Philipp Hörist pushed to branch master at gajim / gajim
Commits: 4bcdbde2 by Philipp Hörist at 2018-07-07T01:49:50+02:00 Move httpupload into modules
- - - - - 09aead3e by Philipp Hörist at 2018-07-07T01:49:50+02:00 Remove unused imports
- - - - - 3a3b3224 by Philipp Hörist at 2018-07-07T01:49:50+02:00 Fix requesting pubsub node config
Regression from refactoring
- - - - -
11 changed files:
- gajim/chat_control.py - gajim/chat_control_base.py - gajim/common/connection.py - gajim/common/connection_handlers.py - gajim/common/connection_handlers_events.py - gajim/common/httpupload.py → gajim/common/modules/httpupload.py - gajim/common/modules/pubsub.py - gajim/config.py - gajim/groupchat_control.py - gajim/gui_interface.py - gajim/server_info.py
Changes:
===================================== gajim/chat_control.py ===================================== --- 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 = (
===================================== gajim/chat_control_base.py ===================================== --- 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']
===================================== gajim/common/connection.py ===================================== --- a/gajim/common/connection.py +++ b/gajim/common/connection.py @@ -32,14 +32,12 @@ ## along with Gajim. If not, see http://www.gnu.org/licenses/. ##
-import os import sys import random import socket import operator import string import time -import locale import hmac import hashlib import json @@ -83,6 +81,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 +680,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)
===================================== gajim/common/connection_handlers.py ===================================== --- a/gajim/common/connection_handlers.py +++ b/gajim/common/connection_handlers.py @@ -28,14 +28,9 @@ ## along with Gajim. If not, see http://www.gnu.org/licenses/. ##
-import os -import base64 -import binascii import operator -import hashlib
-from time import (altzone, daylight, gmtime, localtime, strftime, - time as time_time, timezone, tzname) +from time import time as time_time
from gi.repository import GLib
@@ -44,20 +39,16 @@ from gajim.common import caps_cache as capscache
from gajim.common import helpers from gajim.common import app -from gajim.common import dataforms from gajim.common import jingle_xtls -from gajim.common import configpaths from gajim.common.caps_cache import muc_caps_cache from gajim.common.commands import ConnectionCommands 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 -from gajim.common import nec from gajim.common.nec import NetworkEvent from gajim.common.const import KindConstant
@@ -72,7 +63,6 @@ METACONTACTS_ARRIVED = 'metacontacts_arrived' ROSTER_ARRIVED = 'roster_arrived' DELIMITER_ARRIVED = 'delimiter_arrived' PRIVACY_ARRIVED = 'privacy_arrived' -PEP_CONFIG = 'pep_config'
class ConnectionDisco: @@ -754,14 +744,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 +807,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, @@ -944,21 +931,6 @@ ConnectionHTTPUpload): # connection process, we don't take the risk self.privacy_rules_supported = False self._continue_connection_request_privacy() - elif self.awaiting_answers[id_][0] == PEP_CONFIG: - del self.awaiting_answers[id_] - if iq_obj.getType() == 'error': - return - if not iq_obj.getTag('pubsub'): - return - conf = iq_obj.getTag('pubsub').getTag('configure') - if not conf: - return - node = conf.getAttr('node') - form_tag = conf.getTag('x', namespace=nbxmpp.NS_DATA) - if form_tag: - form = dataforms.ExtendForm(node=form_tag) - app.nec.push_incoming_event(PEPConfigReceivedEvent(None, - conn=self, node=node, form=form))
def _nec_iq_error_received(self, obj): if obj.conn.name != self.name:
===================================== gajim/common/connection_handlers_events.py ===================================== --- a/gajim/common/connection_handlers_events.py +++ b/gajim/common/connection_handlers_events.py @@ -1822,10 +1822,6 @@ class UpdateRoomAvatarEvent(nec.NetworkIncomingEvent): def generate(self): return True
-class PEPConfigReceivedEvent(nec.NetworkIncomingEvent): - name = 'pep-config-received' - base_network_events = [] - class MetacontactsReceivedEvent(nec.NetworkIncomingEvent): name = 'metacontacts-received' base_network_events = [] @@ -2545,17 +2541,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
===================================== gajim/common/httpupload.py → gajim/common/modules/httpupload.py ===================================== --- 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 http://www.gnu.org/licenses/.
+# 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 = []
===================================== gajim/common/modules/pubsub.py ===================================== --- a/gajim/common/modules/pubsub.py +++ b/gajim/common/modules/pubsub.py @@ -25,6 +25,8 @@ import logging import nbxmpp
from gajim.common import app +from gajim.common import dataforms +from gajim.common.nec import NetworkIncomingEvent
log = logging.getLogger('gajim.c.m.pubsub')
@@ -185,7 +187,7 @@ class PubSub:
self._con.connection.SendAndCallForResponse(query, cb)
- def send_pb_configure(self, jid, node, form, cb=None): + def send_pb_configure(self, jid, node, form, cb=None, **kwargs): if not app.account_is_connected(self._account): return
@@ -197,21 +199,58 @@ class PubSub: c = c.addChild('configure', {'node': node}) c.addChild(node=form)
- self._con.connection.SendAndCallForResponse(query, cb) + log.info('Send node config for %s', node) + self._con.connection.SendAndCallForResponse(query, cb, kwargs)
- def request_pb_configuration(self, jid, node, cb=None): + def request_pb_configuration(self, jid, node): if not app.account_is_connected(self._account): return
- if cb is None: - cb = self._default_callback - query = nbxmpp.Iq('get', to=jid) e = query.addChild('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) e = e.addChild('configure', {'node': node})
- self._con.connection.SendAndCallForResponse(query, cb) + log.info('Request node config for %s', node) + self._con.connection.SendAndCallForResponse( + query, self._received_pb_configuration, {'node': node}) + + def _received_pb_configuration(self, conn, stanza, node): + if not nbxmpp.isResultNode(stanza): + log.warning('Error: %s', stanza.getError()) + return + + pubsub = stanza.getTag('pubsub', namespace=nbxmpp.NS_PUBSUB_OWNER) + if pubsub is None: + log.warning('Malformed PubSub configure ' + 'stanza (no pubsub node): %s', stanza) + return + + configure = pubsub.getTag('configure') + if configure is None: + log.warning('Malformed PubSub configure ' + 'stanza (no configure node): %s', stanza) + return + + if configure.getAttr('node') != node: + log.warning('Malformed PubSub configure ' + 'stanza (wrong node): %s', stanza) + return + + form = configure.getTag('x', namespace=nbxmpp.NS_DATA) + if form is None: + log.warning('Malformed PubSub configure ' + 'stanza (no form): %s', stanza) + return + + app.nec.push_incoming_event(PubSubConfigReceivedEvent( + None, conn=self._con, node=node, + form=dataforms.ExtendForm(node=form)))
def _default_callback(self, conn, stanza, *args, **kwargs): if not nbxmpp.isResultNode(stanza): log.warning('Error: %s', stanza.getError()) + + +class PubSubConfigReceivedEvent(NetworkIncomingEvent): + name = 'pubsub-config-received' + base_network_events = []
===================================== gajim/config.py ===================================== --- a/gajim/config.py +++ b/gajim/config.py @@ -2839,7 +2839,7 @@ class ManagePEPServicesWindow: self.xml.get_object('services_treeview').get_selection().connect( 'changed', self.on_services_selection_changed)
- app.ged.register_event_handler('pep-config-received', ged.GUI1, + app.ged.register_event_handler('pubsub-config-received', ged.GUI1, self._nec_pep_config_received) app.ged.register_event_handler('agent-items-received', ged.GUI1, self._nec_agent_items_received) @@ -2849,7 +2849,7 @@ class ManagePEPServicesWindow: def on_manage_pep_services_window_destroy(self, widget): '''close window''' del app.interface.instances[self.account]['pep_services'] - app.ged.remove_event_handler('pep-config-received', ged.GUI1, + app.ged.remove_event_handler('pubsub-config-received', ged.GUI1, self._nec_pep_config_received) app.ged.remove_event_handler('agent-items-received', ged.GUI1, self._nec_agent_items_received)
===================================== gajim/groupchat_control.py ===================================== --- 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())
===================================== gajim/gui_interface.py ===================================== --- 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(
===================================== gajim/server_info.py ===================================== --- 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))
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/0eeb111a02d23fd3dfc39f7e40620fb76e...