فهرست منبع

Initial work on XEP-0363: HTTP File Upload

JC Brand 7 سال پیش
والد
کامیت
77a51cc2a6
7فایلهای تغییر یافته به همراه173 افزوده شده و 2 حذف شده
  1. 1 0
      spec/disco.js
  2. 152 0
      spec/http-file-upload.js
  3. 1 0
      src/config.js
  4. 1 0
      src/converse-core.js
  5. 16 0
      src/converse-http-file-upload.js
  6. 0 1
      src/converse-otr.js
  7. 2 1
      tests/runner.js

+ 1 - 0
spec/disco.js

@@ -14,6 +14,7 @@
     describe("Service Discovery", function () {
 
         describe("Whenever converse.js queries a server for its features", function () {
+
             it("stores the features it receives", mock.initConverseWithAsync(function (done, _converse) {
                 var IQ_stanzas = _converse.connection.IQ_stanzas;
                 var IQ_ids =  _converse.connection.IQ_ids;

+ 152 - 0
spec/http-file-upload.js

@@ -0,0 +1,152 @@
+(function (root, factory) {
+    define([
+        "jasmine",
+        "jquery",
+        "converse-core",
+        "mock",
+        "test-utils"], factory);
+} (this, function (jasmine, $, converse, mock, test_utils) {
+    "use strict";
+    var Strophe = converse.env.Strophe;
+    var $iq = converse.env.$iq;
+    var _ = converse.env._;
+
+    describe("XEP-0363: HTTP File Upload", function () {
+
+        describe("Discovering support", function () {
+
+            it("is done automatically", mock.initConverseWithAsync(function (done, _converse) {
+                var IQ_stanzas = _converse.connection.IQ_stanzas;
+                var IQ_ids =  _converse.connection.IQ_ids;
+                test_utils.waitUntil(function () {
+                    return _.filter(IQ_stanzas, function (iq) {
+                        return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#info"]');
+                    }).length > 0;
+                }, 300).then(function () {
+                    /* <iq type='result'
+                     *      from='plays.shakespeare.lit'
+                     *      to='romeo@montague.net/orchard'
+                     *      id='info1'>
+                     *  <query xmlns='http://jabber.org/protocol/disco#info'>
+                     *      <identity
+                     *          category='server'
+                     *          type='im'/>
+                     *      <feature var='http://jabber.org/protocol/disco#info'/>
+                     *      <feature var='http://jabber.org/protocol/disco#items'/>
+                     *  </query>
+                     *  </iq>
+                     */
+                    var info_IQ_id = IQ_ids[0];
+                    var stanza = $iq({
+                        'type': 'result',
+                        'from': 'localhost',
+                        'to': 'dummy@localhost/resource',
+                        'id': info_IQ_id
+                    }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
+                        .c('identity', {
+                            'category': 'server',
+                            'type': 'im'}).up()
+                        .c('feature', {
+                            'var': 'http://jabber.org/protocol/disco#info'}).up()
+                        .c('feature', {
+                            'var': 'http://jabber.org/protocol/disco#items'});
+                    _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+                    var entities = _converse.disco_entities;
+                    expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
+                    expect(entities.get(_converse.domain).features.length).toBe(2);
+                    expect(entities.get(_converse.domain).identities.length).toBe(1);
+
+                    return test_utils.waitUntil(function () {
+                        // Converse.js sees that the entity has a disco#items feature,
+                        // so it will make a query for it.
+                        return _.filter(IQ_stanzas, function (iq) {
+                            return iq.nodeTree.querySelector('query[xmlns="http://jabber.org/protocol/disco#items"]');
+                        }).length > 0;
+                    }, 300);
+                }).then(function () {
+                    /* <iq from='montague.tld'
+                     *      id='step_01'
+                     *      to='romeo@montague.tld/garden'
+                     *      type='result'>
+                     *  <query xmlns='http://jabber.org/protocol/disco#items'>
+                     *      <item jid='upload.montague.tld' name='HTTP File Upload' />
+                     *      <item jid='conference.montague.tld' name='Chatroom Service' />
+                     *  </query>
+                     *  </iq>
+                     */
+                   var items_IQ_id = IQ_ids[IQ_ids.length-1];
+                   var stanza = $iq({
+                       'type': 'result',
+                       'from': 'localhost',
+                       'to': 'dummy@localhost/resource',
+                       'id': items_IQ_id
+                   }).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
+                       .c('item', {
+                           'jid': 'upload.localhost',
+                           'name': 'HTTP File Upload'}).up()
+                       .c('item', {
+                           'jid': 'conference.localhost',
+                           'name': 'Chatrooms Service'});
+                    _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+                    var entities = _converse.disco_entities;
+                    expect(entities.length).toBe(4); // We have an extra entity, which is the user's JID
+
+                    return test_utils.waitUntil(function () {
+                        // Converse.js sees that the entity has a disco#items feature,
+                        // so it will make a query for it.
+                        return _.filter(IQ_stanzas, function (iq) {
+                            return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
+                        }).length > 0;
+                    }, 300);
+                }).then(function () {
+                    var stanza = _.filter(IQ_stanzas, function (iq) {
+                        return iq.nodeTree.querySelector('iq[to="upload.localhost"] query[xmlns="http://jabber.org/protocol/disco#info"]');
+                    })[0];
+                    var IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
+                    expect(stanza.toLocaleString()).toBe(
+                        "<iq from='dummy@localhost/resource' to='upload.localhost' type='get' xmlns='jabber:client' id='"+IQ_id+"'>"+
+                            "<query xmlns='http://jabber.org/protocol/disco#info'/>"+
+                        "</iq>");
+
+                    // Upload service responds and reports a maximum file size of 5MiB
+                    /* <iq from='upload.montague.tld'
+                     *     id='step_02'
+                     *     to='romeo@montague.tld/garden'
+                     *     type='result'>
+                     * <query xmlns='http://jabber.org/protocol/disco#info'>
+                     *     <identity category='store'
+                     *             type='file'
+                     *             name='HTTP File Upload' />
+                     *     <feature var='urn:xmpp:http:upload:0' />
+                     *     <x type='result' xmlns='jabber:x:data'>
+                     *     <field var='FORM_TYPE' type='hidden'>
+                     *         <value>urn:xmpp:http:upload:0</value>
+                     *     </field>
+                     *     <field var='max-file-size'>
+                     *         <value>5242880</value>
+                     *     </field>
+                     *     </x>
+                     * </query>
+                     * </iq>
+                     */
+                    stanza = $iq({'type': 'result', 'to': 'dummy@localhost/resource', 'id': IQ_id, 'from': 'upload.localhost'})
+                        .c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
+                            .c('identity', {'category':'store', 'type':'file', 'name':'HTTP File Upload'}).up()
+                            .c('feature', {'var':'urn:xmpp:http:upload:0'}).up()
+                            .c('x', {'type':'result', 'xmlns':'jabber:x:data'})
+                                .c('field', {'var':'FORM_TYPE', 'type':'hidden'})
+                                    .c('value').t('urn:xmpp:http:upload:0').up().up()
+                                .c('field', {'var':'max-file-size'})
+                                    .c('value').t('5242880');
+                    _converse.connection._dataRecv(test_utils.createRequest(stanza));
+
+                    var entities = _converse.disco_entities;
+                    expect(entities.get('upload.localhost').identities.where({'category': 'store'}).length).toBe(1);
+                    done();
+                })
+            }));
+        });
+    });
+}));

+ 1 - 0
src/config.js

@@ -74,6 +74,7 @@ require.config({
         "converse-dragresize":      "src/converse-dragresize",
         "converse-fullscreen":      "src/converse-fullscreen",
         "converse-headline":        "src/converse-headline",
+        "converse-http-file-upload":"src/converse-http-file-upload",
         "converse-mam":             "src/converse-mam",
         "converse-minimize":        "src/converse-minimize",
         "converse-modal":           "src/converse-modal",

+ 1 - 0
src/converse-core.js

@@ -78,6 +78,7 @@
         'converse-dropdown',
         'converse-fullscreen',
         'converse-headline',
+        'converse-http-file-upload',
         'converse-mam',
         'converse-minimize',
         'converse-modal',

+ 16 - 0
src/converse-http-file-upload.js

@@ -0,0 +1,16 @@
+(function (root, factory) {
+    define(["converse-http-file-upload"], factory);
+}(this, function (converse) {
+    "use strict";
+
+    converse.plugins.add('converse-http-file-upload', {
+
+        initialize () {
+            /* The initialize function gets called as soon as the plugin is
+             * loaded by converse.js's plugin machinery.
+             */
+            const { _converse } = this;
+
+        }
+    });
+}));

+ 0 - 1
src/converse-otr.js

@@ -10,7 +10,6 @@
  * encryption of one-on-one chat messages.
  */
 (function (root, factory) {
-
     define([ "converse-chatview",
             "bootstrap",
             "tpl!toolbar_otr",

+ 2 - 1
tests/runner.js

@@ -54,7 +54,8 @@ var specs = [
     "spec/chatroom",
     "spec/minchats",
     "spec/notification",
-    "spec/register"
+    "spec/register",
+    "spec/http-file-upload"
 ];
 
 require(['console-reporter', 'mock', 'sinon', 'wait-until-promise', 'pluggable'],