Skip to content
Permalink
Browse files

Add support for HTTP File Upload (XEP-0363)

This change adds JXT types and client methods for requesting HTTP upload
slots.

Closes #296.
  • Loading branch information...
wiktor-k committed Jan 30, 2019
1 parent 6964cb8 commit c0b3905d5246c8fa99bba9b3a01d112ca7237d2b
Showing with 122 additions and 0 deletions.
  1. +16 −0 docs/Reference.md
  2. +2 −0 src/plugins/index.js
  3. +44 −0 src/plugins/upload.js
  4. +2 −0 src/protocol/index.js
  5. +58 −0 src/protocol/stanzas/upload.js
@@ -81,6 +81,9 @@
- [Chat Markers](#chat-markers)
- [`client.markDisplayed(msg)`](#clientmarkdisplayed)
- [`client.markAcknowledged(msg)`](#clientmarkacknowledged)
- [HTTP File Upload](#http-upload)
- [`client.getUploadService()`](#clientgetuploadservice)
- [`client.getUploadSlot(jid, request, [cb])`](#clientgetuploadslot)
- [Other](#other)
- [`client.deleteAccount([jid, cb])`](#clientdeleteaccountjid-cb)
- [`client.getAccountInfo([jid, cb])`](#clientgetaccountinfojid-cb)
@@ -554,6 +557,19 @@ Marks a message as displayed by using [Chat Markers](http://xmpp.org/extensions/
Marks a message as acknowledged by using [Chat Markers](http://xmpp.org/extensions/xep-0333.html).
#### HTTP File Upload
[HTTP File Upload](https://xmpp.org/extensions/xep-0363.html) allows requesting upload slots for sharing files via HTTP.
##### `client.getUploadService()`
Returns upload service information including maximum file size and upload service JID.
##### `client.getUploadSlot(jid, request, [cb]))`
Requests a new upload slot from upload service given as `jid`. The `request` is an object
that contains `filename`, `type`, and `size` properties.
#### Avatars
##### `client.getAvatar(jid, id, [cb])`
@@ -34,6 +34,7 @@ import Register from './register';
import Roster from './roster';
import RTT from './rtt';
import Time from './time';
import Upload from './upload';
import VCard from './vcard';
import Version from './version';

@@ -75,6 +76,7 @@ export default function(client) {
client.use(Roster);
client.use(RTT);
client.use(Time);
client.use(Upload);
client.use(VCard);
client.use(Version);
}
@@ -0,0 +1,44 @@
export default function(client) {
async function getUploadParameters(jid) {
const { discoInfo } = await client.getDiscoInfo(jid);
if (discoInfo.features.includes('urn:xmpp:http:upload:0')) {
const fields = discoInfo.form.fields;
let maxSize = null;
if (
fields.some(
field =>
field.name === 'FORM_TYPE' && field.value.includes('urn:xmpp:http:upload:0')
)
) {
maxSize = parseInt(fields.find(field => field.name === 'max-file-size').value, 10);
}
return { maxSize, jid };
}
}

client.getUploadService = async function(domain = client.jid.domain) {
const domainParameters = await getUploadParameters(domain);
if (domainParameters) {
return domainParameters;
}
const { discoItems } = await client.getDiscoItems(domain);
for (const item of discoItems.items) {
const itemParameters = await getUploadParameters(item.jid);
if (itemParameters) {
return itemParameters;
}
}
throw new Error('No upload service discovered on: ' + domain);
};

client.getUploadSlot = function(uploadService, uploadRequest, cb) {
return client.sendIq(
{
to: uploadService,
type: 'get',
uploadRequest
},
cb
);
};
}
@@ -62,6 +62,7 @@ import StreamError from './stanzas/streamError';
import StreamFeatures from './stanzas/streamFeatures';
import Time from './stanzas/time';
import Tune from './stanzas/tune';
import Upload from './stanzas/upload';
import VCardTemp from './stanzas/vcard';
import Version from './stanzas/version';
import Visibility from './stanzas/visibility';
@@ -144,6 +145,7 @@ export default function(JXT) {
JXT.use(StreamFeatures);
JXT.use(Time);
JXT.use(Tune);
JXT.use(Upload);
JXT.use(VCardTemp);
JXT.use(Version);
JXT.use(Visibility);
@@ -0,0 +1,58 @@
import * as NS from '../namespaces';

export default function(JXT) {
const Utils = JXT.utils;

const Request = JXT.define({
element: 'request',
fields: {
filename: Utils.attribute('filename'),
size: Utils.numberAttribute('size'),
type: Utils.attribute('content-type')
},
name: 'uploadRequest',
namespace: NS.HTTP_UPLOAD_0
});

const Slot = JXT.define({
element: 'slot',
name: 'uploadSlots',
namespace: NS.HTTP_UPLOAD_0
});

const Put = JXT.define({
element: 'put',
fields: {
url: Utils.attribute('url')
},
name: 'put',
namespace: NS.HTTP_UPLOAD_0
});

const Header = JXT.define({
element: 'header',
fields: {
name: Utils.attribute('name'),
value: Utils.text()
},
name: '_header',
namespace: NS.HTTP_UPLOAD_0
});

const Get = JXT.define({
element: 'get',
fields: {
url: Utils.attribute('url')
},
name: 'get',
namespace: NS.HTTP_UPLOAD_0
});

JXT.extend(Put, Header, 'headers');

JXT.extend(Slot, Put);
JXT.extend(Slot, Get);

JXT.extendIQ(Slot);
JXT.extendIQ(Request);
}

0 comments on commit c0b3905

Please sign in to comment.
You can’t perform that action at this time.