Support http:upload:0
This commit is contained in:
parent
dadc85bb52
commit
8e9c040acf
|
@ -40,6 +40,7 @@ if os.name == 'nt':
|
||||||
|
|
||||||
log = logging.getLogger('gajim.c.httpupload')
|
log = logging.getLogger('gajim.c.httpupload')
|
||||||
|
|
||||||
|
NS_HTTPUPLOAD_0 = NS_HTTPUPLOAD + ':0'
|
||||||
|
|
||||||
class ConnectionHTTPUpload:
|
class ConnectionHTTPUpload:
|
||||||
"""
|
"""
|
||||||
|
@ -50,6 +51,8 @@ class ConnectionHTTPUpload:
|
||||||
self.httpupload = False
|
self.httpupload = False
|
||||||
self.encrypted_upload = False
|
self.encrypted_upload = False
|
||||||
self.component = None
|
self.component = None
|
||||||
|
self.httpupload_namespace = None
|
||||||
|
self._allowed_headers = ['Authorization', 'Cookie', 'Expires']
|
||||||
self.max_file_size = None # maximum file size in bytes
|
self.max_file_size = None # maximum file size in bytes
|
||||||
|
|
||||||
app.ged.register_event_handler('agent-info-received',
|
app.ged.register_event_handler('agent-info-received',
|
||||||
|
@ -76,22 +79,28 @@ class ConnectionHTTPUpload:
|
||||||
self.handle_outgoing_stanza)
|
self.handle_outgoing_stanza)
|
||||||
|
|
||||||
def handle_agent_info_received(self, event):
|
def handle_agent_info_received(self, event):
|
||||||
if (NS_HTTPUPLOAD not in event.features or not
|
account = event.conn.name
|
||||||
app.jid_is_transport(event.jid)):
|
if account != self.name:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not app.jid_is_transport(event.jid):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not event.id_.startswith('Gajim_'):
|
if not event.id_.startswith('Gajim_'):
|
||||||
return
|
return
|
||||||
|
|
||||||
account = event.conn.name
|
if NS_HTTPUPLOAD_0 in event.features:
|
||||||
if account != self.name:
|
self.httpupload_namespace = NS_HTTPUPLOAD_0
|
||||||
|
elif NS_HTTPUPLOAD in event.features:
|
||||||
|
self.httpupload_namespace = NS_HTTPUPLOAD
|
||||||
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.component = event.jid
|
self.component = event.jid
|
||||||
|
|
||||||
for form in event.data:
|
for form in event.data:
|
||||||
form_dict = form.asDict()
|
form_dict = form.asDict()
|
||||||
if form_dict.get('FORM_TYPE', None) != NS_HTTPUPLOAD:
|
if form_dict.get('FORM_TYPE', None) != self.httpupload_namespace:
|
||||||
continue
|
continue
|
||||||
size = form_dict.get('max-file-size', None)
|
size = form_dict.get('max-file-size', None)
|
||||||
if size is not None:
|
if size is not None:
|
||||||
|
@ -183,17 +192,30 @@ class ConnectionHTTPUpload:
|
||||||
|
|
||||||
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 = nbxmpp.Iq(typ='get', to=self.component)
|
iq = self._build_request(file)
|
||||||
id_ = app.get_an_id()
|
|
||||||
iq.setID(id_)
|
|
||||||
request = iq.setTag(name="request", namespace=NS_HTTPUPLOAD)
|
|
||||||
request.addChild('filename', payload=quote(os.path.basename(file.path)))
|
|
||||||
request.addChild('size', payload=file.size)
|
|
||||||
request.addChild('content-type', payload=file.mime)
|
|
||||||
|
|
||||||
log.info("Sending request for slot")
|
log.info("Sending request for slot")
|
||||||
app.connections[self.name].connection.SendAndCallForResponse(
|
app.connections[self.name].connection.SendAndCallForResponse(
|
||||||
iq, self.received_slot, {'file': file})
|
iq, self.received_slot, {'file': file})
|
||||||
|
|
||||||
|
def _build_request(self, file):
|
||||||
|
iq = nbxmpp.Iq(typ='get', to=self.component)
|
||||||
|
id_ = app.get_an_id()
|
||||||
|
iq.setID(id_)
|
||||||
|
if self.httpupload_namespace == NS_HTTPUPLOAD:
|
||||||
|
# experimental namespace
|
||||||
|
request = iq.setTag(name="request",
|
||||||
|
namespace=self.httpupload_namespace)
|
||||||
|
request.addChild('filename', payload=os.path.basename(file.path))
|
||||||
|
request.addChild('size', payload=file.size)
|
||||||
|
request.addChild('content-type', payload=file.mime)
|
||||||
|
else:
|
||||||
|
attr = {'filename': os.path.basename(file.path),
|
||||||
|
'size': file.size,
|
||||||
|
'content-type': file.mime}
|
||||||
|
iq.setTag(name="request",
|
||||||
|
namespace=self.httpupload_namespace,
|
||||||
|
attrs=attr)
|
||||||
|
return iq
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_slot_error_message(stanza):
|
def get_slot_error_message(stanza):
|
||||||
|
@ -217,10 +239,23 @@ class ConnectionHTTPUpload:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
file.put = stanza.getTag("slot").getTag("put").getData()
|
if self.httpupload_namespace == NS_HTTPUPLOAD:
|
||||||
file.get = stanza.getTag("slot").getTag("get").getData()
|
file.put = stanza.getTag('slot').getTag('put').getData()
|
||||||
|
file.get = stanza.getTag('slot').getTag('get').getData()
|
||||||
|
else:
|
||||||
|
slot = stanza.getTag('slot')
|
||||||
|
file.put = slot.getTagAttr('put', 'url')
|
||||||
|
file.get = slot.getTagAttr('get', 'url')
|
||||||
|
for header in slot.getTag('put').getTags('header'):
|
||||||
|
name = header.getAttr('name')
|
||||||
|
if name not in self._allowed_headers:
|
||||||
|
raise ValueError('Not allowed header')
|
||||||
|
data = header.getData()
|
||||||
|
if '\n' in data:
|
||||||
|
raise ValueError('Newline in header data')
|
||||||
|
file.headers[name] = data
|
||||||
except Exception:
|
except Exception:
|
||||||
log.error("Got unexpected stanza: %s", stanza)
|
log.error("Got invalid stanza: %s", stanza)
|
||||||
log.exception('Error')
|
log.exception('Error')
|
||||||
self.raise_progress_event('close', file)
|
self.raise_progress_event('close', file)
|
||||||
self.raise_information_event('request-upload-slot-error2')
|
self.raise_information_event('request-upload-slot-error2')
|
||||||
|
@ -250,12 +285,12 @@ class ConnectionHTTPUpload:
|
||||||
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:
|
||||||
headers = {'User-Agent': 'Gajim %s' % app.version,
|
file.headers['User-Agent'] = 'Gajim %s' % app.version
|
||||||
'Content-Type': file.mime,
|
file.headers['Content-Type'] = file.mime
|
||||||
'Content-Length': file.size}
|
file.headers['Content-Length'] = file.size
|
||||||
|
|
||||||
request = Request(
|
request = Request(
|
||||||
file.put, data=file.stream, headers=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.name, 'httpupload_verify'):
|
||||||
|
@ -345,6 +380,7 @@ class File:
|
||||||
self.data = None
|
self.data = None
|
||||||
self.user_data = None
|
self.user_data = None
|
||||||
self.size = None
|
self.size = None
|
||||||
|
self.headers = {}
|
||||||
self.event = threading.Event()
|
self.event = threading.Event()
|
||||||
self.load_data()
|
self.load_data()
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ 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, nbxmpp.NS_HTTPUPLOAD, None)]
|
con.httpupload, con.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))
|
||||||
|
|
Loading…
Reference in New Issue