diff --git a/plugin_installer/config_dialog.ui b/plugin_installer/config_dialog.ui
index fe7764c..01a796c 100644
--- a/plugin_installer/config_dialog.ui
+++ b/plugin_installer/config_dialog.ui
@@ -394,24 +394,6 @@
1
-
-
-
- False
- True
- 2
-
-
diff --git a/plugin_installer/plugin_installer.py b/plugin_installer/plugin_installer.py
index e0197fb..bca7a5e 100644
--- a/plugin_installer/plugin_installer.py
+++ b/plugin_installer/plugin_installer.py
@@ -25,7 +25,6 @@ from gi.repository import Pango
from gi.repository import GLib
from gi.repository import GObject
-import ftplib
import io
import threading
import configparser
@@ -33,9 +32,11 @@ import os
import fnmatch
import sys
import zipfile
-import ssl
import logging
+import posixpath
+from urllib.request import urlopen
+from urllib.parse import urlparse, urljoin
from common import gajim
from plugins import GajimPlugin
from plugins.helpers import log_calls, log
@@ -68,11 +69,11 @@ class PluginInstaller(GajimPlugin):
@log_calls('PluginInstallerPlugin')
def init(self):
- self.description = _('Install and upgrade plugins from ftp')
+ self.description = _('Install and Upgrade Plugins')
self.config_dialog = PluginInstallerPluginConfigDialog(self)
- self.config_default_values = {'ftp_server': ('ftp.gajim.org', ''),
+ self.config_default_values = {'http_server': ('https://ftp.gajim.org', ''),
'check_update': (True, ''),
- 'check_update_periodically': (True, '')}
+ }
self.window = None
self.progressbar = None
self.available_plugins_model = None
@@ -82,20 +83,10 @@ class PluginInstaller(GajimPlugin):
icon = Gtk.Image()
self.def_icon = icon.render_icon(Gtk.STOCK_PREFERENCES,
Gtk.IconSize.MENU)
- if gajim.version.startswith('0.15'):
- self.server_folder = 'plugins_0.15'
- elif gajim.version.startswith('0.16.10'):
- self.server_folder = 'plugins_1'
- else:
- self.server_folder = 'plugins_0.16'
+ self.server_folder = 'plugins_1'
@log_calls('PluginInstallerPlugin')
def activate(self):
- self.pl_menuitem = gajim.interface.roster.xml.get_object(
- 'plugins_menuitem')
- self.id_ = self.pl_menuitem.connect_after('activate', self.on_activate)
- if 'plugins' in gajim.interface.instances:
- self.on_activate(None)
if self.config['check_update']:
self.timeout_id = GLib.timeout_add_seconds(30, self.check_update)
@@ -113,34 +104,53 @@ class PluginInstaller(GajimPlugin):
' your installer plugins. Do you want to update those plugins:'
'\n%s') % plugins_str, on_response_yes=open_update)
- def ftp_connect(self):
- if os.name == 'nt':
- ctx = ssl.create_default_context()
- con = ftplib.FTP_TLS(self.config['ftp_server'], context=ctx)
- else:
- con = ftplib.FTP_TLS(self.config['ftp_server'])
+ def parse_manifest(self, buf):
+ '''
+ given the buffer of the zipfile, returns the list of plugin manifests
+ '''
+ zip_file = zipfile.ZipFile(buf)
+ manifest_list = zip_file.namelist()
+ plugins = []
+ for filename in manifest_list:
+ config = configparser.ConfigParser()
+ conf_file = zip_file.open(filename)
+ config.read_file(io.TextIOWrapper(conf_file, encoding='utf-8'))
+ conf_file.close()
+ if not config.has_section('info'):
+ continue
+ plugins.append(config)
+ return plugins
- con.login()
- con.prot_p()
- return con
+ def retrieve_path(self, directory, fname):
+ print('retrive path')
+ server = self.config['http_server']
+ if not server:
+ server = self.config_default_values['http_server'][0]
+ if not urlparse(server).scheme:
+ server = 'https://' + server
+ if urlparse(server).scheme != 'https':
+ log.warn('Warning: not using HTTPS is a '
+ 'very serious security issue!')
+ location = posixpath.join(directory, fname)
+ uri = urljoin(server, location)
+ log.debug('Fetching {}'.format(uri))
+ request = urlopen(uri)
+
+ manifest_buffer = io.BytesIO(request.read())
+
+ return manifest_buffer
+
+ def retrieve_manifest(self):
+ return self.retrieve_path(self.server_folder, 'manifests.zip')
@log_calls('PluginInstallerPlugin')
def check_update(self):
def _run():
try:
to_update = []
- con = self.ftp_connect()
- con.cwd(self.server_folder)
- con.retrbinary('RETR manifests.zip', ftp.handleDownload)
- zip_file = zipfile.ZipFile(ftp.buffer_)
- manifest_list = zip_file.namelist()
- for filename in manifest_list:
- config = configparser.ConfigParser()
- conf_file = zip_file.open(filename)
- config.read_file(io.TextIOWrapper(conf_file, encoding='utf-8'))
- conf_file.close()
- if not config.has_section('info'):
- continue
+ zipbuf = self.retrieve_manifest()
+ plugin_manifests = self.parse_manifest(zipbuf)
+ for config in plugin_manifests:
opts = config.options('info')
if 'name' not in opts or 'version' not in opts or \
'description' not in opts or 'authors' not in opts or \
@@ -154,13 +164,9 @@ class PluginInstaller(GajimPlugin):
'version'))
if remote > local:
to_update.append(config.get('info', 'name'))
- con.quit()
GLib.idle_add(self.warn_update, to_update)
- # check for updates at least once every 24 hours
- if self.config['check_update_periodically']:
- self.timeout_id = GLib.timeout_add_seconds(24*3600, self.check_update)
except Exception as e:
- log.debug('Ftp error when check updates: %s' % str(e))
+ log.error('Ftp error when check updates: %s' % str(e), exc_info=True)
ftp = Ftp(self)
ftp.run = _run
ftp.start()
@@ -181,18 +187,15 @@ class PluginInstaller(GajimPlugin):
GLib.source_remove(self.timeout_id)
self.timeout_id = 0
- def on_activate(self, widget):
- if 'plugins' not in gajim.interface.instances:
- return
+ def on_activate(self, plugin_win):
if hasattr(self, 'page_num'):
# 'Available' tab exists
return
- self.installed_plugins_model = gajim.interface.instances[
- 'plugins'].installed_plugins_model
- self.notebook = gajim.interface.instances['plugins'].plugins_notebook
+ self.installed_plugins_model = plugin_win.installed_plugins_model
+ self.notebook = plugin_win.plugins_notebook
id_ = self.notebook.connect('switch-page', self.on_notebook_switch_page)
self.connected_ids[id_] = self.notebook
- self.window = gajim.interface.instances['plugins'].window
+ self.window = plugin_win.window
id_ = self.window.connect('destroy', self.on_win_destroy)
self.connected_ids[id_] = self.window
self.Gtk_BUILDER_FILE_PATH = self.local_file_path('config_dialog.ui')
@@ -461,11 +464,10 @@ class PluginInstaller(GajimPlugin):
file_path))
# read metadata from manifest.ini
- with open(manifest_path) as _file:
- conf.read_file(_file)
+ conf.readfp(open(manifest_path, 'r'))
for option in fields:
if conf.get('info', option) is '':
- raise configparser.NoOptionError('field empty')
+ raise configparser.NoOptionError
setattr(module_attr, option, conf.get('info', option))
conf.remove_section('info')
plugins_found.append(module_attr)
@@ -496,13 +498,12 @@ class Ftp(threading.Thread):
self.window = plugin.window
self.progressbar = plugin.progressbar
self.model = plugin.available_plugins_model
- self.buffer_ = io.BytesIO()
self.remote_dirs = None
self.append_to_model = True
self.upgrading = False
icon = Gtk.Image()
- self.def_icon = icon.render_icon(Gtk.STOCK_PREFERENCES,
- Gtk.IconSize.MENU)
+ self.def_icon = icon.render_icon(
+ Gtk.STOCK_PREFERENCES, Gtk.IconSize.MENU)
def model_append(self, row):
self.model.append(row)
@@ -521,14 +522,15 @@ class Ftp(threading.Thread):
try:
GLib.idle_add(self.progressbar.set_text,
_('Connecting to server'))
- self.ftp = self.plugin.ftp_connect()
- self.ftp.cwd(self.plugin.server_folder)
- self.progressbar.set_show_text(True)
if not self.remote_dirs:
GLib.idle_add(self.progressbar.set_text,
- _('Scan files on the server'))
- self.ftp.retrbinary('RETR manifests_images.zip', self.handleDownload)
- zip_file = zipfile.ZipFile(self.buffer_)
+ _('Scan files on the server'))
+ try:
+ buf = self.plugin.retrieve_path(self.plugin.server_folder, 'manifests_images.zip')
+ except:
+ log.exception("Error fetching plugin list")
+ return
+ zip_file = zipfile.ZipFile(buf)
manifest_list = zip_file.namelist()
progress_step = 1.0 / len(manifest_list)
for filename in manifest_list:
@@ -593,9 +595,6 @@ class Ftp(threading.Thread):
except Exception as e:
self.window.emit('error_signal', str(e))
- def handleDownload(self, block):
- self.buffer_.write(block)
-
def download_plugin(self):
GLib.idle_add(self.progressbar.show)
self.pulse = GLib.timeout_add(150, self.progressbar_pulse)
@@ -605,24 +604,22 @@ class Ftp(threading.Thread):
base_dir, user_dir = gajim.PLUGINS_DIRS
if not os.path.isdir(user_dir):
os.mkdir(user_dir)
- local_dir = ld = os.path.join(user_dir, remote_dir)
+ local_dir = os.path.join(user_dir, remote_dir)
if not os.path.isdir(local_dir):
os.mkdir(local_dir)
local_dir = os.path.split(user_dir)[0]
# downloading zip file
GLib.idle_add(self.progressbar.set_text,
- _('Downloading "%s"') % filename)
- full_filename = os.path.join(user_dir, filename)
- self.buffer_ = io.BytesIO()
+ _('Downloading "%s"') % filename)
try:
- self.ftp.retrbinary('RETR %s' % filename, self.handleDownload)
- except ftplib.all_errors as e:
- print (str(e))
-
- with zipfile.ZipFile(self.buffer_) as zip_file:
- zip_file.extractall(os.path.join(user_dir))
-
+ buf = self.plugin.retrieve_path(self.plugin.server_folder,
+ filename)
+ except:
+ log.exception("Error downloading plugin %s" % filename)
+ continue
+ with zipfile.ZipFile(buf) as zip_file:
+ zip_file.extractall(os.path.join(local_dir, 'plugins'))
self.ftp.quit()
GLib.idle_add(self.window.emit, 'plugin_downloaded', self.remote_dirs)
GLib.source_remove(self.pulse)
@@ -642,12 +639,10 @@ class PluginInstallerPluginConfigDialog(GajimPluginConfigDialog):
self.connect('hide', self.on_hide)
def on_run(self):
- widget = self.xml.get_object('ftp_server')
- widget.set_text(str(self.plugin.config['ftp_server']))
+ widget = self.xml.get_object('http_server')
+ widget.set_text(str(self.plugin.config['http_server']))
self.xml.get_object('check_update').set_active(
self.plugin.config['check_update'])
- self.xml.get_object('check_update_periodically').set_active(
- self.plugin.config['check_update_periodically'])
def on_hide(self, widget):
widget = self.xml.get_object('ftp_server')
@@ -655,6 +650,3 @@ class PluginInstallerPluginConfigDialog(GajimPluginConfigDialog):
def on_check_update_toggled(self, widget):
self.plugin.config['check_update'] = widget.get_active()
-
- def on_check_update_periodically_toggled(self, widget):
- self.plugin.config['check_update_periodically'] = widget.get_active()