Commit c0b3f36b authored by Philipp Hörist's avatar Philipp Hörist

[plugin_installer] Port recent plugin_installer

This inlcudes slight refactoring and switch to https instead of ftps
parent 3347951d
......@@ -394,24 +394,6 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="check_update_periodically">
<property name="label" translatable="yes">Check update every 24 hours</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="receives_default">False</property>
<property name="focus_on_click">False</property>
<property name="xalign">0.5</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_check_update_periodically_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
......
......@@ -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'])
con.login()
con.prot_p()
return con
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
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()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment