[httpupload] Refactor upload methods

This commit is contained in:
Philipp Hörist
2017-02-27 21:08:40 +01:00
parent d7fa0de8aa
commit 54eeb183e6

View File

@@ -19,12 +19,14 @@ from gi.repository import GObject, Gtk, GLib
import os import os
import sys import sys
import time import time
import threading
from urllib.request import Request, urlopen from urllib.request import Request, urlopen
import mimetypes # better use the magic packet, but that's not a standard lib import mimetypes # better use the magic packet, but that's not a standard lib
import gtkgui_helpers import gtkgui_helpers
import logging import logging
from queue import Queue from queue import Queue
import binascii import binascii
import certifi
from common import gajim from common import gajim
from common import ged from common import ged
@@ -210,7 +212,7 @@ class Base(object):
mime = mimetypes.MimeTypes().guess_type(path)[0] mime = mimetypes.MimeTypes().guess_type(path)[0]
if not mime: if not mime:
mime = 'application/octet-stream' # fallback mime type mime = 'application/octet-stream' # fallback mime type
log.info("Detected MIME type of file: ", mime) log.info("Detected MIME type of file: %s", mime)
progress_messages = Queue(8) progress_messages = Queue(8)
progress_window = ProgressWindow(_('HTTP Upload'), _('Requesting HTTP Upload Slot...'), progress_window = ProgressWindow(_('HTTP Upload'), _('Requesting HTTP Upload Slot...'),
@@ -221,65 +223,6 @@ class Base(object):
progress=progress_window) progress=progress_window)
self.request_slot(file) self.request_slot(file)
def upload_file(stanza):
def upload_complete(response_code):
if response_code == 0:
return # Upload was aborted
if 200 <= response_code < 300:
log.info("Upload completed successfully")
xhtml = None
is_image = mime_type.split('/', 1)[0] == 'image'
progress_window.close_dialog()
id_ = gajim.get_an_id()
def add_oob_tag():
pass
if self.encrypted_upload:
keyAndIv = '#' + binascii.hexlify(iv) + binascii.hexlify(key)
self.chat_control.send_message(message=get.getData() + keyAndIv, xhtml=None)
else:
self.chat_control.send_message(message=get.getData(), xhtml=xhtml)
self.chat_control.msg_textview.grab_focus()
else:
progress_window.close_dialog()
log.error("got unexpected http upload response code: " + str(response_code))
ErrorDialog(_('Could not upload file'),
_('Got unexpected http response code from server: ') + str(response_code),
transient_for=self.chat_control.parent_win.window)
def on_upload_error():
progress_window.close_dialog()
ErrorDialog(_('Could not upload file'),
_('Got unexpected exception while uploading file'
' (see error log for more information)'),
transient_for=self.chat_control.parent_win.window)
return 0
def uploader():
progress_messages.put(_('Uploading file via HTTP...'))
try:
headers = {'User-Agent': 'Gajim %s' % gajim.version,
'Content-Type': mime_type}
request = Request(put.getData(), data=data, headers=headers, method='PUT')
log.debug("opening urllib upload request...")
transfer = urlopen(request, timeout=30)
data.close()
log.debug("urllib upload request done, response code: " + str(transfer.getcode()))
return transfer.getcode()
except UploadAbortedException:
log.info("Upload aborted")
except:
log.error("Exception during upload", exc_info=sys.exc_info())
GLib.idle_add(on_upload_error)
return 0
log.info("Uploading file to '%s'..." % str(put.getData()))
log.info("Please download from '%s' later..." % str(get.getData()))
gajim.thread_interface(uploader, [], upload_complete)
self.chat_control.msg_textview.grab_focus()
def on_file_button_clicked(self, widget, jid, chat_control): def on_file_button_clicked(self, widget, jid, chat_control):
FileChooserDialog( FileChooserDialog(
on_response_ok=lambda widget: self.on_file_dialog_ok(widget, jid, on_response_ok=lambda widget: self.on_file_dialog_ok(widget, jid,
@@ -314,8 +257,8 @@ class Base(object):
return return
try: try:
file.put = stanza.getTag("slot").getTag("put") file.put = stanza.getTag("slot").getTag("put").getData()
file.get = stanza.getTag("slot").getTag("get") file.get = stanza.getTag("slot").getTag("get").getData()
except Exception as exc: except Exception as exc:
file.progress.close_dialog() file.progress.close_dialog()
log.error("Got unexpected stanza: ", stanza) log.error("Got unexpected stanza: ", stanza)
@@ -335,6 +278,60 @@ class Base(object):
transient_for=file.control.parent_win.window) transient_for=file.control.parent_win.window)
return return
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.daemon = True
thread.start()
def upload_file(self, file):
# progress_messages.put(_('Uploading file via HTTP...'))
try:
headers = {'User-Agent': 'Gajim %s' % gajim.version,
'Content-Type': file.mime}
request = Request(file.put, data=file.stream, headers=headers, method='PUT')
log.debug("opening urllib upload request...")
if os.name == 'nt':
transfer = urlopen(request, cafile=certifi.where(), timeout=30)
else:
transfer = urlopen(request, timeout=30)
file.stream.close()
log.debug('urllib upload request done, response code: ', transfer.getcode())
GLib.idle_add(self.upload_complete, transfer.getcode(), file)
except:
log.error("Exception during upload", exc_info=sys.exc_info())
GLib.idle_add(file.progress.close_dialog)
GLib.idle_add(self.on_upload_error, file)
def upload_complete(self, response_code, file):
if response_code == 0:
return # Upload was aborted
if 200 <= response_code < 300:
log.info("Upload completed successfully")
file.progress.close_dialog()
message = file.get
if file.encrypted:
message += '#' + binascii.hexlify(file.iv + file.key)
file.control.send_message(message=message)
file.control.msg_textview.grab_focus()
else:
file.progress.close_dialog()
log.error('Got unexpected http upload response code: ',
response_code)
ErrorDialog(
_('Could not upload file'),
_('HTTP response code from server: %s') % response_code,
transient_for=file.control.parent_win.window)
def on_upload_error(self, file):
file.progress.close_dialog()
ErrorDialog(_('Could not upload file'),
_('Got unexpected exception while uploading file'
' (see log)'),
transient_for=file.control.parent_win.window)
class File: class File:
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -381,13 +378,15 @@ class StreamFileWithProgress:
data += self.encryptor.tag data += self.encryptor.tag
self._seen += TAGSIZE self._seen += TAGSIZE
if self._callback: if self._callback:
self._callback(self._seen, self._total, *self._args) GLib.idle_add(
self._callback, self._seen, self._total, *self._args)
return data return data
else: else:
data = self.backing.read(size) data = self.backing.read(size)
self._seen += len(data) self._seen += len(data)
if self._callback: if self._callback:
self._callback(self._seen, self._total, *self._args) GLib.idle_add(
self._callback, self._seen, self._total, *self._args)
return data return data
def close(self): def close(self):
@@ -445,7 +444,7 @@ class ProgressWindow:
def update_progress(self, seen, total): def update_progress(self, seen, total):
if self.stopped == True: if self.stopped == True:
raise UploadAbortedException raise
if self.pulse_progressbar_timeout_id: if self.pulse_progressbar_timeout_id:
GLib.source_remove(self.pulse_progressbar_timeout_id) GLib.source_remove(self.pulse_progressbar_timeout_id)
self.pulse_progressbar_timeout_id = None self.pulse_progressbar_timeout_id = None
@@ -457,6 +456,7 @@ class ProgressWindow:
def close_dialog(self): def close_dialog(self):
self.on_cancel(None) self.on_cancel(None)
class UploadAbortedException(Exception): class UploadAbortedException(Exception):
def __str__(self): def __str__(self):
return "Upload Aborted" return "Upload Aborted"