Move httpupload into modules

This commit is contained in:
Philipp Hörist 2018-07-07 01:15:48 +02:00
parent 0eeb111a02
commit 4bcdbde2c8
9 changed files with 63 additions and 66 deletions

View File

@ -274,6 +274,7 @@ class ChatControl(ChatControlBase):
def update_actions(self): def update_actions(self):
win = self.parent_win.window win = self.parent_win.window
online = app.account_is_connected(self.account) online = app.account_is_connected(self.account)
con = app.connections[self.account]
# Add to roster # Add to roster
if not isinstance(self.contact, GC_Contact) \ if not isinstance(self.contact, GC_Contact) \
@ -297,7 +298,7 @@ class ChatControl(ChatControlBase):
httpupload = win.lookup_action( httpupload = win.lookup_action(
'send-file-httpupload-' + self.control_id) 'send-file-httpupload-' + self.control_id)
httpupload.set_enabled( httpupload.set_enabled(
online and app.connections[self.account].httpupload) online and con.get_module('HTTPUpload').available)
# Send file (Jingle) # Send file (Jingle)
jingle_conditions = ( jingle_conditions = (

View File

@ -759,19 +759,19 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
# groupchat only supports httpupload on drag and drop # groupchat only supports httpupload on drag and drop
if httpupload.get_enabled(): if httpupload.get_enabled():
# use httpupload # use httpupload
con.check_file_before_transfer( con.get_module('HTTPUpload').check_file_before_transfer(
path, self.encryption, contact, path, self.encryption, contact,
self.session, groupchat=True) self.session, groupchat=True)
else: else:
if httpupload.get_enabled() and jingle.get_enabled(): if httpupload.get_enabled() and jingle.get_enabled():
if ft_pref == 'httpupload': if ft_pref == 'httpupload':
con.check_file_before_transfer( con.get_module('HTTPUpload').check_file_before_transfer(
path, self.encryption, contact, self.session) path, self.encryption, contact, self.session)
else: else:
ft = app.interface.instances['file_transfers'] ft = app.interface.instances['file_transfers']
ft.send_file(self.account, contact, path) ft.send_file(self.account, contact, path)
elif httpupload.get_enabled(): elif httpupload.get_enabled():
con.check_file_before_transfer( con.get_module('HTTPUpload').check_file_before_transfer(
path, self.encryption, contact, self.session) path, self.encryption, contact, self.session)
elif jingle.get_enabled(): elif jingle.get_enabled():
ft = app.interface.instances['file_transfers'] ft = app.interface.instances['file_transfers']

View File

@ -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_mood import UserMood
from gajim.common.modules.user_location import UserLocation from gajim.common.modules.user_location import UserLocation
from gajim.common.modules.user_nickname import UserNickname from gajim.common.modules.user_nickname import UserNickname
from gajim.common.modules.httpupload import HTTPUpload
from gajim.common.connection_handlers import * from gajim.common.connection_handlers import *
from gajim.common.contacts import GC_Contact from gajim.common.contacts import GC_Contact
from gajim.gtkgui_helpers import get_action from gajim.gtkgui_helpers import get_action
@ -681,6 +682,7 @@ class Connection(CommonConnection, ConnectionHandlers):
self.register_module('UserMood', UserMood, self) self.register_module('UserMood', UserMood, self)
self.register_module('UserLocation', UserLocation, self) self.register_module('UserLocation', UserLocation, self)
self.register_module('UserNickname', UserNickname, self) self.register_module('UserNickname', UserNickname, self)
self.register_module('HTTPUpload', HTTPUpload, self)
app.ged.register_event_handler('privacy-list-received', ged.CORE, app.ged.register_event_handler('privacy-list-received', ged.CORE,
self._nec_privacy_list_received) self._nec_privacy_list_received)

View File

@ -53,7 +53,6 @@ from gajim.common.protocol.caps import ConnectionCaps
from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream
from gajim.common.protocol.bytestream import ConnectionIBBytestream from gajim.common.protocol.bytestream import ConnectionIBBytestream
from gajim.common.message_archiving import ConnectionArchive313 from gajim.common.message_archiving import ConnectionArchive313
from gajim.common.httpupload import ConnectionHTTPUpload
from gajim.common.connection_handlers_events import * from gajim.common.connection_handlers_events import *
from gajim.common import ged from gajim.common import ged
@ -754,14 +753,12 @@ class ConnectionHandlersBase:
class ConnectionHandlers(ConnectionArchive313, class ConnectionHandlers(ConnectionArchive313,
ConnectionSocks5Bytestream, ConnectionDisco, ConnectionSocks5Bytestream, ConnectionDisco,
ConnectionCommands, ConnectionCaps, ConnectionCommands, ConnectionCaps,
ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream, ConnectionHandlersBase, ConnectionJingle, ConnectionIBBytestream):
ConnectionHTTPUpload):
def __init__(self): def __init__(self):
ConnectionArchive313.__init__(self) ConnectionArchive313.__init__(self)
ConnectionSocks5Bytestream.__init__(self) ConnectionSocks5Bytestream.__init__(self)
ConnectionIBBytestream.__init__(self) ConnectionIBBytestream.__init__(self)
ConnectionCommands.__init__(self) ConnectionCommands.__init__(self)
ConnectionHTTPUpload.__init__(self)
# Handle presences BEFORE caps # Handle presences BEFORE caps
app.nec.register_incoming_event(PresenceReceivedEvent) app.nec.register_incoming_event(PresenceReceivedEvent)
@ -819,7 +816,6 @@ ConnectionHTTPUpload):
ConnectionHandlersBase.cleanup(self) ConnectionHandlersBase.cleanup(self)
ConnectionCaps.cleanup(self) ConnectionCaps.cleanup(self)
ConnectionArchive313.cleanup(self) ConnectionArchive313.cleanup(self)
ConnectionHTTPUpload.cleanup(self)
app.ged.remove_event_handler('roster-set-received', app.ged.remove_event_handler('roster-set-received',
ged.CORE, self._nec_roster_set_received) ged.CORE, self._nec_roster_set_received)
app.ged.remove_event_handler('roster-received', ged.CORE, app.ged.remove_event_handler('roster-received', ged.CORE,

View File

@ -2545,17 +2545,3 @@ class BlockingEvent(nec.NetworkIncomingEvent):
app.log('blocking').info( app.log('blocking').info(
'Blocking Push - unblocked JIDs: %s', self.unblocked_jids) 'Blocking Push - unblocked JIDs: %s', self.unblocked_jids)
return True 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

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
#
# This file is part of Gajim. # This file is part of Gajim.
# #
# Gajim is free software; you can redistribute it and/or modify # 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 # You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>. # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
# XEP-0363: HTTP File Upload
import os import os
import sys import sys
import threading import threading
import ssl import ssl
import urllib import urllib
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
from urllib.parse import urlparse, quote from urllib.parse import urlparse
import io import io
import mimetypes import mimetypes
import logging import logging
@ -31,26 +32,28 @@ from gi.repository import GLib
from gajim.common import app from gajim.common import app
from gajim.common import ged 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 InformationEvent
from gajim.common.connection_handlers_events import HTTPUploadProgressEvent
from gajim.common.connection_handlers_events import MessageOutgoingEvent from gajim.common.connection_handlers_events import MessageOutgoingEvent
from gajim.common.connection_handlers_events import GcMessageOutgoingEvent from gajim.common.connection_handlers_events import GcMessageOutgoingEvent
if sys.platform in ('win32', 'darwin'): if sys.platform in ('win32', 'darwin'):
import certifi import certifi
log = logging.getLogger('gajim.c.httpupload') log = logging.getLogger('gajim.c.m.httpupload')
NS_HTTPUPLOAD_0 = NS_HTTPUPLOAD + ':0' NS_HTTPUPLOAD_0 = NS_HTTPUPLOAD + ':0'
class ConnectionHTTPUpload:
""" class HTTPUpload:
Implement HTTP File Upload def __init__(self, con):
(XEP-0363, https://xmpp.org/extensions/xep-0363.html) self._con = con
""" self._account = con.name
def __init__(self):
self.httpupload = False self.handlers = []
self.encrypted_upload = False
self.available = False
self.component = None self.component = None
self.httpupload_namespace = None self.httpupload_namespace = None
self._allowed_headers = ['Authorization', 'Cookie', 'Expires'] self._allowed_headers = ['Authorization', 'Cookie', 'Expires']
@ -81,7 +84,7 @@ class ConnectionHTTPUpload:
def handle_agent_info_received(self, event): def handle_agent_info_received(self, event):
account = event.conn.name account = event.conn.name
if account != self.name: if account != self._account:
return return
if not app.jid_is_transport(event.jid): if not app.jid_is_transport(event.jid):
@ -112,14 +115,14 @@ class ConnectionHTTPUpload:
log.warning('%s does not provide maximum file size', account) log.warning('%s does not provide maximum file size', account)
else: else:
log.info('%s has a maximum file size of: %s MiB', 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 self.available = True
for ctrl in app.interface.msg_win_mgr.get_controls(acct=self.name): for ctrl in app.interface.msg_win_mgr.get_controls(acct=self._account):
ctrl.update_actions() ctrl.update_actions()
def handle_outgoing_stanza(self, event): def handle_outgoing_stanza(self, event):
if event.conn.name != self.name: if event.conn.name != self._account:
return return
message = event.msg_iq.getTagData('body') message = event.msg_iq.getTagData('body')
if message and message in self.messages: if message and message in self.messages:
@ -177,9 +180,9 @@ class ConnectionHTTPUpload:
return return
if encryption is not None: if encryption is not None:
app.interface.encrypt_file(file, self.request_slot) app.interface.encrypt_file(file, self._request_slot)
else: else:
self.request_slot(file) self._request_slot(file)
@staticmethod @staticmethod
def raise_progress_event(status, file, seen=None, total=None): def raise_progress_event(status, file, seen=None, total=None):
@ -191,13 +194,13 @@ class ConnectionHTTPUpload:
app.nec.push_incoming_event(InformationEvent( app.nec.push_incoming_event(InformationEvent(
None, dialog_name=dialog_name, args=args)) 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) GLib.idle_add(self.raise_progress_event, 'request', file)
iq = self._build_request(file) iq = self._build_request(file)
log.info("Sending request for slot") log.info("Sending request for slot")
app.connections[self.name].connection.SendAndCallForResponse( self._con.connection.SendAndCallForResponse(
iq, self.received_slot, {'file': file}) iq, self._received_slot, {'file': file})
def _build_request(self, file): def _build_request(self, file):
iq = nbxmpp.Iq(typ='get', to=self.component) iq = nbxmpp.Iq(typ='get', to=self.component)
id_ = app.get_an_id() id_ = app.get_an_id()
@ -230,7 +233,7 @@ class ConnectionHTTPUpload:
return stanza.getErrorMsg() return stanza.getErrorMsg()
def received_slot(self, conn, stanza, file): def _received_slot(self, conn, stanza, file):
log.info("Received slot") log.info("Received slot")
if stanza.getType() == 'error': if stanza.getType() == 'error':
self.raise_progress_event('close', file) self.raise_progress_event('close', file)
@ -279,11 +282,11 @@ class ConnectionHTTPUpload:
log.info('Uploading file to %s', file.put) log.info('Uploading file to %s', file.put)
log.info('Please download from %s', file.get) 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.daemon = True
thread.start() thread.start()
def upload_file(self, file): def _upload_file(self, file):
GLib.idle_add(self.raise_progress_event, 'upload', file) GLib.idle_add(self.raise_progress_event, 'upload', file)
try: try:
file.headers['User-Agent'] = 'Gajim %s' % app.version file.headers['User-Agent'] = 'Gajim %s' % app.version
@ -294,7 +297,7 @@ class ConnectionHTTPUpload:
file.put, data=file.stream, headers=file.headers, method='PUT') file.put, data=file.stream, headers=file.headers, method='PUT')
log.info("Opening Urllib upload request...") 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 = ssl.create_default_context()
context.check_hostname = False context.check_hostname = False
context.verify_mode = ssl.CERT_NONE context.verify_mode = ssl.CERT_NONE
@ -309,7 +312,7 @@ class ConnectionHTTPUpload:
file.stream.close() file.stream.close()
log.info('Urllib upload request done, response code: %s', log.info('Urllib upload request done, response code: %s',
transfer.getcode()) transfer.getcode())
GLib.idle_add(self.upload_complete, transfer.getcode(), file) GLib.idle_add(self._upload_complete, transfer.getcode(), file)
return return
except UploadAbortedException as exc: except UploadAbortedException as exc:
log.info(exc) log.info(exc)
@ -326,9 +329,9 @@ class ConnectionHTTPUpload:
log.exception("Exception during upload") log.exception("Exception during upload")
error_msg = exc error_msg = exc
GLib.idle_add(self.raise_progress_event, 'close', file) 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) self.raise_progress_event('close', file)
if 200 <= response_code < 300: if 200 <= response_code < 300:
log.info("Upload completed successfully") log.info("Upload completed successfully")
@ -341,12 +344,12 @@ class ConnectionHTTPUpload:
if file.groupchat: if file.groupchat:
app.nec.push_outgoing_event(GcMessageOutgoingEvent( 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, message=message, automatic_message=False,
session=file.session)) session=file.session))
else: else:
app.nec.push_outgoing_event(MessageOutgoingEvent( 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', message=message, keyID=file.keyID, type_='chat',
automatic_message=False, session=file.session)) automatic_message=False, session=file.session))
@ -356,7 +359,7 @@ class ConnectionHTTPUpload:
self.raise_information_event('httpupload-response-error', self.raise_information_event('httpupload-response-error',
response_code) response_code)
def on_upload_error(self, file, reason): def _on_upload_error(self, file, reason):
self.raise_progress_event('close', file) self.raise_progress_event('close', file)
self.raise_information_event('httpupload-error', str(reason)) self.raise_information_event('httpupload-error', str(reason))
@ -428,3 +431,8 @@ class StreamFileWithProgress:
class UploadAbortedException(Exception): class UploadAbortedException(Exception):
def __str__(self): def __str__(self):
return "Upload Aborted" return "Upload Aborted"
class HTTPUploadProgressEvent(NetworkIncomingEvent):
name = 'httpupload-progress'
base_network_events = []

View File

@ -574,6 +574,7 @@ class GroupchatControl(ChatControlBase):
contact = app.contacts.get_gc_contact( contact = app.contacts.get_gc_contact(
self.account, self.room_jid, self.nick) self.account, self.room_jid, self.nick)
online = app.gc_connected[self.account][self.room_jid] online = app.gc_connected[self.account][self.room_jid]
con = app.connections[self.account]
# Destroy Room # Destroy Room
win.lookup_action('destroy-' + self.control_id).set_enabled( win.lookup_action('destroy-' + self.control_id).set_enabled(
@ -615,7 +616,7 @@ class GroupchatControl(ChatControlBase):
httpupload = win.lookup_action( httpupload = win.lookup_action(
'send-file-httpupload-' + self.control_id) 'send-file-httpupload-' + self.control_id)
httpupload.set_enabled( 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( win.lookup_action('send-file-' + self.control_id).set_enabled(
httpupload.get_enabled()) httpupload.get_enabled())

View File

@ -93,8 +93,9 @@ from gajim.common import passwords
from gajim.common import logging_helpers from gajim.common import logging_helpers
from gajim.common.connection_handlers_events import ( from gajim.common.connection_handlers_events import (
OurShowEvent, FileRequestErrorEvent, FileTransferCompletedEvent, OurShowEvent, FileRequestErrorEvent, FileTransferCompletedEvent,
UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent, UpdateRosterAvatarEvent, UpdateGCAvatarEvent, UpdateRoomAvatarEvent)
HTTPUploadProgressEvent)
from gajim.common.modules.httpupload import HTTPUploadProgressEvent
from gajim.common.connection import Connection from gajim.common.connection import Connection
from gajim.common.file_props import FilesProp from gajim.common.file_props import FilesProp
from gajim import emoticons from gajim import emoticons
@ -1142,11 +1143,12 @@ class Interface:
con = app.connections[chat_control.account] con = app.connections[chat_control.account]
groupchat = chat_control.type_id == message_control.TYPE_GC groupchat = chat_control.type_id == message_control.TYPE_GC
for path in paths: for path in paths:
con.check_file_before_transfer(path, con.get_module('HTTPUpload').check_file_before_transfer(
chat_control.encryption, path,
chat_control.contact, chat_control.encryption,
chat_control.session, chat_control.contact,
groupchat) chat_control.session,
groupchat)
def encrypt_file(self, file, callback): def encrypt_file(self, file, callback):
app.nec.push_incoming_event(HTTPUploadProgressEvent( app.nec.push_incoming_event(HTTPUploadProgressEvent(

View File

@ -177,7 +177,8 @@ class ServerInfoDialog(Gtk.Dialog):
con.archiving_namespace, con.archiving_namespace, con.archiving_namespace, con.archiving_namespace,
mam_enabled), mam_enabled),
Feature('XEP-0363: HTTP File Upload', 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): def add_info(self, info):
self.info_listbox.add(ServerInfoItem(info)) self.info_listbox.add(ServerInfoItem(info))