From 4bcdbde2c89303f8b009ffba3f6344bae60688f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philipp=20H=C3=B6rist?= Date: Sat, 7 Jul 2018 01:15:48 +0200 Subject: [PATCH] Move httpupload into modules --- gajim/chat_control.py | 3 +- gajim/chat_control_base.py | 6 +- gajim/common/connection.py | 2 + gajim/common/connection_handlers.py | 6 +- gajim/common/connection_handlers_events.py | 14 ---- gajim/common/{ => modules}/httpupload.py | 76 ++++++++++++---------- gajim/groupchat_control.py | 3 +- gajim/gui_interface.py | 16 +++-- gajim/server_info.py | 3 +- 9 files changed, 63 insertions(+), 66 deletions(-) rename gajim/common/{ => modules}/httpupload.py (90%) diff --git a/gajim/chat_control.py b/gajim/chat_control.py index c4c56521d..d4d21fce9 100644 --- a/gajim/chat_control.py +++ b/gajim/chat_control.py @@ -274,6 +274,7 @@ class ChatControl(ChatControlBase): def update_actions(self): win = self.parent_win.window online = app.account_is_connected(self.account) + con = app.connections[self.account] # Add to roster if not isinstance(self.contact, GC_Contact) \ @@ -297,7 +298,7 @@ class ChatControl(ChatControlBase): httpupload = win.lookup_action( 'send-file-httpupload-' + self.control_id) httpupload.set_enabled( - online and app.connections[self.account].httpupload) + online and con.get_module('HTTPUpload').available) # Send file (Jingle) jingle_conditions = ( diff --git a/gajim/chat_control_base.py b/gajim/chat_control_base.py index 155607eb8..61bb51ac0 100644 --- a/gajim/chat_control_base.py +++ b/gajim/chat_control_base.py @@ -759,19 +759,19 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # groupchat only supports httpupload on drag and drop if httpupload.get_enabled(): # use httpupload - con.check_file_before_transfer( + con.get_module('HTTPUpload').check_file_before_transfer( path, self.encryption, contact, self.session, groupchat=True) else: if httpupload.get_enabled() and jingle.get_enabled(): if ft_pref == 'httpupload': - con.check_file_before_transfer( + con.get_module('HTTPUpload').check_file_before_transfer( path, self.encryption, contact, self.session) else: ft = app.interface.instances['file_transfers'] ft.send_file(self.account, contact, path) elif httpupload.get_enabled(): - con.check_file_before_transfer( + con.get_module('HTTPUpload').check_file_before_transfer( path, self.encryption, contact, self.session) elif jingle.get_enabled(): ft = app.interface.instances['file_transfers'] diff --git a/gajim/common/connection.py b/gajim/common/connection.py index 21e3152a1..9c2dc6613 100644 --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -83,6 +83,7 @@ from gajim.common.modules.user_tune import UserTune from gajim.common.modules.user_mood import UserMood from gajim.common.modules.user_location import UserLocation from gajim.common.modules.user_nickname import UserNickname +from gajim.common.modules.httpupload import HTTPUpload from gajim.common.connection_handlers import * from gajim.common.contacts import GC_Contact from gajim.gtkgui_helpers import get_action @@ -681,6 +682,7 @@ class Connection(CommonConnection, ConnectionHandlers): self.register_module('UserMood', UserMood, self) self.register_module('UserLocation', UserLocation, self) self.register_module('UserNickname', UserNickname, self) + self.register_module('HTTPUpload', HTTPUpload, self) app.ged.register_event_handler('privacy-list-received', ged.CORE, self._nec_privacy_list_received) diff --git a/gajim/common/connection_handlers.py b/gajim/common/connection_handlers.py index cf5b6c528..08de5c6e8 100644 --- a/gajim/common/connection_handlers.py +++ b/gajim/common/connection_handlers.py @@ -53,7 +53,6 @@ from gajim.common.protocol.caps import ConnectionCaps from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream from gajim.common.protocol.bytestream import ConnectionIBBytestream from gajim.common.message_archiving import ConnectionArchive313 -from gajim.common.httpupload import ConnectionHTTPUpload from gajim.common.connection_handlers_events import * from gajim.common import ged @@ -754,14 +753,12 @@ class ConnectionHandlersBase: class ConnectionHandlers(ConnectionArchive313, ConnectionSocks5Bytestream, ConnectionDisco, ConnectionCommands, ConnectionCaps, -ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream, -ConnectionHTTPUpload): +ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream): def __init__(self): ConnectionArchive313.__init__(self) ConnectionSocks5Bytestream.__init__(self) ConnectionIBBytestream.__init__(self) ConnectionCommands.__init__(self) - ConnectionHTTPUpload.__init__(self) # Handle presences BEFORE caps app.nec.register_incoming_event(PresenceReceivedEvent) @@ -819,7 +816,6 @@ ConnectionHTTPUpload): ConnectionHandlersBase.cleanup(self) ConnectionCaps.cleanup(self) ConnectionArchive313.cleanup(self) - ConnectionHTTPUpload.cleanup(self) app.ged.remove_event_handler('roster-set-received', ged.CORE, self._nec_roster_set_received) app.ged.remove_event_handler('roster-received', ged.CORE, diff --git a/gajim/common/connection_handlers_events.py b/gajim/common/connection_handlers_events.py index 0258de1d9..799a09d6f 100644 --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -2545,17 +2545,3 @@ class BlockingEvent(nec.NetworkIncomingEvent): app.log('blocking').info( 'Blocking Push - unblocked JIDs: %s', self.unblocked_jids) return True - -class HTTPUploadStartEvent(nec.NetworkIncomingEvent): - name = 'httpupload-start' - base_network_events = [] - - def generate(self): - return True - -class HTTPUploadProgressEvent(nec.NetworkIncomingEvent): - name = 'httpupload-progress' - base_network_events = [] - - def generate(self): - return True \ No newline at end of file diff --git a/gajim/common/httpupload.py b/gajim/common/modules/httpupload.py similarity index 90% rename from gajim/common/httpupload.py rename to gajim/common/modules/httpupload.py index 369fb0d91..1f2afd504 100644 --- a/gajim/common/httpupload.py +++ b/gajim/common/modules/httpupload.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # This file is part of Gajim. # # Gajim is free software; you can redistribute it and/or modify @@ -14,13 +12,16 @@ # You should have received a copy of the GNU General Public License # along with Gajim. If not, see . +# XEP-0363: HTTP File Upload + + import os import sys import threading import ssl import urllib from urllib.request import Request, urlopen -from urllib.parse import urlparse, quote +from urllib.parse import urlparse import io import mimetypes import logging @@ -31,26 +32,28 @@ from gi.repository import GLib from gajim.common import app from gajim.common import ged +from gajim.common.nec import NetworkIncomingEvent from gajim.common.connection_handlers_events import InformationEvent -from gajim.common.connection_handlers_events import HTTPUploadProgressEvent from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.common.connection_handlers_events import GcMessageOutgoingEvent if sys.platform in ('win32', 'darwin'): import certifi -log = logging.getLogger('gajim.c.httpupload') +log = logging.getLogger('gajim.c.m.httpupload') + NS_HTTPUPLOAD_0 = NS_HTTPUPLOAD + ':0' -class ConnectionHTTPUpload: - """ - Implement HTTP File Upload - (XEP-0363, https://xmpp.org/extensions/xep-0363.html) - """ - def __init__(self): - self.httpupload = False - self.encrypted_upload = False + +class HTTPUpload: + def __init__(self, con): + self._con = con + self._account = con.name + + self.handlers = [] + + self.available = False self.component = None self.httpupload_namespace = None self._allowed_headers = ['Authorization', 'Cookie', 'Expires'] @@ -81,7 +84,7 @@ class ConnectionHTTPUpload: def handle_agent_info_received(self, event): account = event.conn.name - if account != self.name: + if account != self._account: return if not app.jid_is_transport(event.jid): @@ -112,14 +115,14 @@ class ConnectionHTTPUpload: log.warning('%s does not provide maximum file size', account) else: log.info('%s has a maximum file size of: %s MiB', - account, self.max_file_size/(1024*1024)) + account, self.max_file_size / (1024 * 1024)) - self.httpupload = True - for ctrl in app.interface.msg_win_mgr.get_controls(acct=self.name): + self.available = True + for ctrl in app.interface.msg_win_mgr.get_controls(acct=self._account): ctrl.update_actions() def handle_outgoing_stanza(self, event): - if event.conn.name != self.name: + if event.conn.name != self._account: return message = event.msg_iq.getTagData('body') if message and message in self.messages: @@ -177,9 +180,9 @@ class ConnectionHTTPUpload: return if encryption is not None: - app.interface.encrypt_file(file, self.request_slot) + app.interface.encrypt_file(file, self._request_slot) else: - self.request_slot(file) + self._request_slot(file) @staticmethod def raise_progress_event(status, file, seen=None, total=None): @@ -191,13 +194,13 @@ class ConnectionHTTPUpload: app.nec.push_incoming_event(InformationEvent( None, dialog_name=dialog_name, args=args)) - def request_slot(self, file): + def _request_slot(self, file): GLib.idle_add(self.raise_progress_event, 'request', file) iq = self._build_request(file) log.info("Sending request for slot") - app.connections[self.name].connection.SendAndCallForResponse( - iq, self.received_slot, {'file': file}) - + self._con.connection.SendAndCallForResponse( + iq, self._received_slot, {'file': file}) + def _build_request(self, file): iq = nbxmpp.Iq(typ='get', to=self.component) id_ = app.get_an_id() @@ -230,7 +233,7 @@ class ConnectionHTTPUpload: return stanza.getErrorMsg() - def received_slot(self, conn, stanza, file): + def _received_slot(self, conn, stanza, file): log.info("Received slot") if stanza.getType() == 'error': self.raise_progress_event('close', file) @@ -279,11 +282,11 @@ class ConnectionHTTPUpload: log.info('Uploading file to %s', file.put) log.info('Please download from %s', file.get) - thread = threading.Thread(target=self.upload_file, args=(file,)) + thread = threading.Thread(target=self._upload_file, args=(file,)) thread.daemon = True thread.start() - def upload_file(self, file): + def _upload_file(self, file): GLib.idle_add(self.raise_progress_event, 'upload', file) try: file.headers['User-Agent'] = 'Gajim %s' % app.version @@ -294,7 +297,7 @@ class ConnectionHTTPUpload: file.put, data=file.stream, headers=file.headers, method='PUT') log.info("Opening Urllib upload request...") - if not app.config.get_per('accounts', self.name, 'httpupload_verify'): + if not app.config.get_per('accounts', self._account, 'httpupload_verify'): context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE @@ -309,7 +312,7 @@ class ConnectionHTTPUpload: file.stream.close() log.info('Urllib upload request done, response code: %s', transfer.getcode()) - GLib.idle_add(self.upload_complete, transfer.getcode(), file) + GLib.idle_add(self._upload_complete, transfer.getcode(), file) return except UploadAbortedException as exc: log.info(exc) @@ -326,9 +329,9 @@ class ConnectionHTTPUpload: log.exception("Exception during upload") error_msg = exc GLib.idle_add(self.raise_progress_event, 'close', file) - GLib.idle_add(self.on_upload_error, file, error_msg) + GLib.idle_add(self._on_upload_error, file, error_msg) - def upload_complete(self, response_code, file): + def _upload_complete(self, response_code, file): self.raise_progress_event('close', file) if 200 <= response_code < 300: log.info("Upload completed successfully") @@ -341,12 +344,12 @@ class ConnectionHTTPUpload: if file.groupchat: app.nec.push_outgoing_event(GcMessageOutgoingEvent( - None, account=self.name, jid=file.contact.jid, + None, account=self._account, jid=file.contact.jid, message=message, automatic_message=False, session=file.session)) else: app.nec.push_outgoing_event(MessageOutgoingEvent( - None, account=self.name, jid=file.contact.jid, + None, account=self._account, jid=file.contact.jid, message=message, keyID=file.keyID, type_='chat', automatic_message=False, session=file.session)) @@ -356,7 +359,7 @@ class ConnectionHTTPUpload: self.raise_information_event('httpupload-response-error', response_code) - def on_upload_error(self, file, reason): + def _on_upload_error(self, file, reason): self.raise_progress_event('close', file) self.raise_information_event('httpupload-error', str(reason)) @@ -428,3 +431,8 @@ class StreamFileWithProgress: class UploadAbortedException(Exception): def __str__(self): return "Upload Aborted" + + +class HTTPUploadProgressEvent(NetworkIncomingEvent): + name = 'httpupload-progress' + base_network_events = [] diff --git a/gajim/groupchat_control.py b/gajim/groupchat_control.py index 741e1f5b7..89a5e0fd3 100644 --- a/gajim/groupchat_control.py +++ b/gajim/groupchat_control.py @@ -574,6 +574,7 @@ class GroupchatControl(ChatControlBase): contact = app.contacts.get_gc_contact( self.account, self.room_jid, self.nick) online = app.gc_connected[self.account][self.room_jid] + con = app.connections[self.account] # Destroy Room win.lookup_action('destroy-' + self.control_id).set_enabled( @@ -615,7 +616,7 @@ class GroupchatControl(ChatControlBase): httpupload = win.lookup_action( 'send-file-httpupload-' + self.control_id) httpupload.set_enabled( - online and app.connections[self.account].httpupload) + online and con.get_module('HTTPUpload').available) win.lookup_action('send-file-' + self.control_id).set_enabled( httpupload.get_enabled()) diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py index 2cb9baa26..5578aa32f 100644 --- a/gajim/gui_interface.py +++ b/gajim/gui_interface.py @@ -93,8 +93,9 @@ from gajim.common import passwords from gajim.common import logging_helpers from gajim.common.connection_handlers_events import ( OurShowEvent, FileRequestErrorEvent, FileTransferCompletedEvent, - UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent, - HTTPUploadProgressEvent) + UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent) + +from gajim.common.modules.httpupload import HTTPUploadProgressEvent from gajim.common.connection import Connection from gajim.common.file_props import FilesProp from gajim import emoticons @@ -1142,11 +1143,12 @@ class Interface: con = app.connections[chat_control.account] groupchat = chat_control.type_id == message_control.TYPE_GC for path in paths: - con.check_file_before_transfer(path, - chat_control.encryption, - chat_control.contact, - chat_control.session, - groupchat) + con.get_module('HTTPUpload').check_file_before_transfer( + path, + chat_control.encryption, + chat_control.contact, + chat_control.session, + groupchat) def encrypt_file(self, file, callback): app.nec.push_incoming_event(HTTPUploadProgressEvent( diff --git a/gajim/server_info.py b/gajim/server_info.py index 26fe5c284..423001003 100644 --- a/gajim/server_info.py +++ b/gajim/server_info.py @@ -177,7 +177,8 @@ class ServerInfoDialog(Gtk.Dialog): con.archiving_namespace, con.archiving_namespace, mam_enabled), Feature('XEP-0363: HTTP File Upload', - con.httpupload, con.httpupload_namespace, None)] + con.get_module('HTTPUpload').available, + con.get_module('HTTPUpload').httpupload_namespace, None)] def add_info(self, info): self.info_listbox.add(ServerInfoItem(info))