xmppify 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/app/assets/javascripts/xmpp/index.js +0 -0
  8. data/app/assets/javascripts/xmpp/scripts/checkplayer.js +12 -0
  9. data/app/assets/javascripts/xmpp/scripts/crossdomain.xml +7 -0
  10. data/app/assets/javascripts/xmpp/scripts/flXHR.js +2 -0
  11. data/app/assets/javascripts/xmpp/scripts/flXHR.swf +0 -0
  12. data/app/assets/javascripts/xmpp/scripts/flXHR.vbs +44 -0
  13. data/app/assets/javascripts/xmpp/scripts/flensed.js +12 -0
  14. data/app/assets/javascripts/xmpp/scripts/strophe.flxhr.js +31 -0
  15. data/app/assets/javascripts/xmpp/scripts/strophe.js +3538 -0
  16. data/app/assets/javascripts/xmpp/scripts/swfobject.js +5 -0
  17. data/app/assets/javascripts/xmpp/scripts/updateplayer.swf +0 -0
  18. data/app/assets/javascripts/xmpp/scripts/xmpp.js.coffee +386 -0
  19. data/app/assets/javascripts/xmpp/strophejs-plugins/LICENSE.txt +19 -0
  20. data/app/assets/javascripts/xmpp/strophejs-plugins/README.markdown +95 -0
  21. data/app/assets/javascripts/xmpp/strophejs-plugins/archive/README.markdown +14 -0
  22. data/app/assets/javascripts/xmpp/strophejs-plugins/archive/iso8601_support.js +32 -0
  23. data/app/assets/javascripts/xmpp/strophejs-plugins/archive/strophe.archive.js +88 -0
  24. data/app/assets/javascripts/xmpp/strophejs-plugins/caps/README.markdown +53 -0
  25. data/app/assets/javascripts/xmpp/strophejs-plugins/caps/sha1.js +202 -0
  26. data/app/assets/javascripts/xmpp/strophejs-plugins/caps/strophe.CAPS.coffee +153 -0
  27. data/app/assets/javascripts/xmpp/strophejs-plugins/caps/strophe.CAPS.js +88 -0
  28. data/app/assets/javascripts/xmpp/strophejs-plugins/caps/strophe.caps.jsonly.js +240 -0
  29. data/app/assets/javascripts/xmpp/strophejs-plugins/chatstates/strophe.chatstates.js +80 -0
  30. data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/README.markdown +47 -0
  31. data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/spec/GetUrlComamndSpec.js +66 -0
  32. data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/spec/strophe.cmds.spec.coffee +145 -0
  33. data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/spec/support/jasmine.json +16 -0
  34. data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/src/strophe.cmds.coffee +265 -0
  35. data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/src/strophe.cmds.js +403 -0
  36. data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/README.markdown +82 -0
  37. data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/spec/strophe.x.coffee +715 -0
  38. data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/src/strophe.x.coffee +443 -0
  39. data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/src/strophe.x.js +854 -0
  40. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/.gitignore +1 -0
  41. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/README.markdown +0 -0
  42. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/convert.js +13 -0
  43. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/jasmine.json +11 -0
  44. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/lib/strophe.disco.js +137 -0
  45. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/public/javascript/strophe.disco.js +137 -0
  46. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/01_querying_information.xml +6 -0
  47. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/02_result_set_for_information_request.xml +22 -0
  48. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/03_target_entity_does_not_exist.xml +10 -0
  49. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/04_service_unavailable.xml +11 -0
  50. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/09_querying_specific_jid_and_node_combination.xml +7 -0
  51. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/10_jid_and_node_result.xml +12 -0
  52. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/11_requesting_all_items.xml +6 -0
  53. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/12_result_set_for_all_items.xml +23 -0
  54. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/13_empty_result_set.xml +7 -0
  55. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/17_service_returns_nodes.xml +16 -0
  56. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/18_requesting_further_nodes.xml +7 -0
  57. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/24_jid_and_node_error.xml +11 -0
  58. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/DiscoNodeSpec.js +50 -0
  59. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/SpecHelper.js +51 -0
  60. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/Stanzas.js +0 -0
  61. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/strophe.disco.spec.helper.js +54 -0
  62. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/strophe.disco.spec.js +0 -0
  63. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/support/jasmine.json +13 -0
  64. data/app/assets/javascripts/xmpp/strophejs-plugins/disco/strophe.disco.js +232 -0
  65. data/app/assets/javascripts/xmpp/strophejs-plugins/epic/public/javascript/jquery.epic.js +61 -0
  66. data/app/assets/javascripts/xmpp/strophejs-plugins/epic/spec/SpecHelper.js +9 -0
  67. data/app/assets/javascripts/xmpp/strophejs-plugins/epic/spec/jquery.epic.js +39 -0
  68. data/app/assets/javascripts/xmpp/strophejs-plugins/epic/spec/support/jasmine.json +22 -0
  69. data/app/assets/javascripts/xmpp/strophejs-plugins/iexdomain/iexdomain.js +36 -0
  70. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/README.markdown +117 -0
  71. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/buster.js +23 -0
  72. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/jid.coffee +64 -0
  73. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/jid.js +92 -0
  74. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/spec/browserSetup.coffee +1 -0
  75. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/spec/jid.spec.coffee +96 -0
  76. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/spec/strophe.joap.spec.coffee +461 -0
  77. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/strophe.joap.coffee +304 -0
  78. data/app/assets/javascripts/xmpp/strophejs-plugins/joap/strophe.joap.js +522 -0
  79. data/app/assets/javascripts/xmpp/strophejs-plugins/mam/LICENSE.txt +19 -0
  80. data/app/assets/javascripts/xmpp/strophejs-plugins/mam/README.markdown +52 -0
  81. data/app/assets/javascripts/xmpp/strophejs-plugins/mam/strophe.mam.js +62 -0
  82. data/app/assets/javascripts/xmpp/strophejs-plugins/muc/LICENSE.txt +20 -0
  83. data/app/assets/javascripts/xmpp/strophejs-plugins/muc/strophe.muc.js +1003 -0
  84. data/app/assets/javascripts/xmpp/strophejs-plugins/ping/README.markdown +28 -0
  85. data/app/assets/javascripts/xmpp/strophejs-plugins/ping/strophe.ping.js +68 -0
  86. data/app/assets/javascripts/xmpp/strophejs-plugins/private/README.markdown +16 -0
  87. data/app/assets/javascripts/xmpp/strophejs-plugins/private/strophe.private.js +192 -0
  88. data/app/assets/javascripts/xmpp/strophejs-plugins/pubsub/strophe.pubsub.js +555 -0
  89. data/app/assets/javascripts/xmpp/strophejs-plugins/receipts/strophe.receipts.js +155 -0
  90. data/app/assets/javascripts/xmpp/strophejs-plugins/register/README.markdown +44 -0
  91. data/app/assets/javascripts/xmpp/strophejs-plugins/register/strophe.register.js +431 -0
  92. data/app/assets/javascripts/xmpp/strophejs-plugins/roster/public/javascript/strophe.roster.js +40 -0
  93. data/app/assets/javascripts/xmpp/strophejs-plugins/roster/spec/strophe.roster.spec.js +65 -0
  94. data/app/assets/javascripts/xmpp/strophejs-plugins/roster/spec/support/jasmine.json +15 -0
  95. data/app/assets/javascripts/xmpp/strophejs-plugins/roster/strophe.roster.js +438 -0
  96. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/.gitignore +6 -0
  97. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/README.md +113 -0
  98. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/buster.js +11 -0
  99. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/lib/strophe.js +4198 -0
  100. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/spec/strophe.rpc.spec.helper.js +38 -0
  101. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/spec/strophe.rpc.spec.js +262 -0
  102. data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/strophe.rpc.js +464 -0
  103. data/app/assets/javascripts/xmpp/strophejs-plugins/rsm/strophe.rsm.js +52 -0
  104. data/app/assets/javascripts/xmpp/strophejs-plugins/serverdate/strophe.serverdate.js +58 -0
  105. data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/examples/index.html +17 -0
  106. data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/examples/strophevcard.js +0 -0
  107. data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/strophe.vcard.coffee +44 -0
  108. data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/strophe.vcard.js +66 -0
  109. data/app/assets/stylesheets/xmpp/index.css +0 -0
  110. data/app/controllers/omniauth_callbacks_controller.rb +15 -0
  111. data/app/controllers/ruby_bosh.rb +221 -0
  112. data/app/models/identity.rb +3 -0
  113. data/app/models/user.rb +40 -0
  114. data/bin/rails +8 -0
  115. data/db/migrate/20140329065635_create_users.rb +10 -0
  116. data/db/migrate/20140329070238_create_identities.rb +11 -0
  117. data/lib/xmppify/version.rb +3 -0
  118. data/lib/xmppify.rb +6 -0
  119. data/xmppify.gemspec +23 -0
  120. metadata +197 -0
@@ -0,0 +1,44 @@
1
+ # strophe.register.js
2
+
3
+ A Strophe Plugin for In-Band Registration.
4
+ ( [XEP 0077](http://xmpp.org/extensions/xep-0077.html) )
5
+
6
+ ## Usage
7
+
8
+ Just link the register plugin below the strophe library in your HTML head
9
+ section:
10
+
11
+ ``` html
12
+ <head>
13
+ <!-- ... -->
14
+ <script type="text/javascript" src="strophe.min.js"></script>
15
+ <script type="text/javascript" src="strophe.register.js"></script>
16
+ <!-- ... -->
17
+ </head>
18
+ ```
19
+
20
+ Before you connect:
21
+
22
+ ``` javascript
23
+ var callback = function (status) {
24
+ if (status === Strophe.Status.REGISTER) {
25
+ connection.register.fields.username = "juliet";
26
+ connection.register.fields.password = "R0m30";
27
+ connection.register.submit();
28
+ } else if (status === Strophe.Status.REGISTERED) {
29
+ console.log("registered!");
30
+ connection.authenticate();
31
+ } else if (status === Strophe.Status.CONNECTED) {
32
+ console.log("logged in!");
33
+ } else {
34
+ // every other status a connection.connect would receive
35
+ }
36
+ };
37
+ connection.register.connect("example.com", callback, wait, hold);
38
+ ```
39
+
40
+ After that you're logged in with a fresh smelling jid.
41
+
42
+ ## ToDo
43
+
44
+ - write specs
@@ -0,0 +1,431 @@
1
+ /*
2
+ This library is free software; you can redistribute it and/or modify it
3
+ under the terms of the GNU Lesser General Public License as published
4
+ by the Free Software Foundation; either version 2.1 of the License, or
5
+ (at your option) any later version.
6
+ .
7
+ This library is distributed in the hope that it will be useful, but
8
+ WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
10
+ General Public License for more details.
11
+
12
+ Copyright (c) dodo <dodo@blacksec.org>, 2011
13
+
14
+ */
15
+
16
+ /**
17
+ * File: strophe.register.js
18
+ * A Strophe plugin for XMPP In-Band Registration.
19
+ */
20
+ Strophe.addConnectionPlugin('register', {
21
+ _connection: null,
22
+
23
+ //The plugin must have the init function.
24
+ init: function(conn) {
25
+ this._connection = conn;
26
+
27
+ // compute free emun index number
28
+ var i = 0;
29
+ Object.keys(Strophe.Status).forEach(function (key) {
30
+ i = Math.max(i, Strophe.Status[key]);
31
+ });
32
+
33
+ /* extend name space
34
+ * NS.REGISTER - In-Band Registration
35
+ * from XEP 77.
36
+ */
37
+ Strophe.addNamespace('REGISTER', 'jabber:iq:register');
38
+ Strophe.Status.REGISTERING = i + 1;
39
+ Strophe.Status.REGIFAIL = i + 2;
40
+ Strophe.Status.REGISTER = i + 3;
41
+ Strophe.Status.SUBMITTING = i + 4;
42
+ Strophe.Status.SBMTFAIL = i + 5;
43
+ Strophe.Status.REGISTERED = i + 6;
44
+
45
+ if (conn.disco)
46
+ conn.disco.addFeature(Strophe.NS.REGISTER);
47
+
48
+ // hooking strophe's connection.reset
49
+ var self = this, reset = conn.reset;
50
+ conn.reset = function () {
51
+ reset();
52
+ self.instructions = "";
53
+ self.fields = {};
54
+ self.authentication = {};
55
+ self.registered = false;
56
+ self.enabled = null;
57
+ };
58
+ },
59
+
60
+ /** Function: connect
61
+ * Starts the registration process.
62
+ *
63
+ * As the registration process proceeds, the user supplied callback will
64
+ * be triggered multiple times with status updates. The callback
65
+ * should take two arguments - the status code and the error condition.
66
+ *
67
+ * The status code will be one of the values in the Strophe.Status
68
+ * constants. The error condition will be one of the conditions
69
+ * defined in RFC 3920 or the condition 'strophe-parsererror'.
70
+ *
71
+ * Please see XEP 77 for a more detailed explanation of the optional
72
+ * parameters below.
73
+ *
74
+ * Parameters:
75
+ * (String) domain - The xmpp server's Domain. This will be the server,
76
+ * which will be contacted to register a new JID.
77
+ * The server has to provide and allow In-Band Registration (XEP-0077).
78
+ * (Function) callback The connect callback function.
79
+ * (Integer) wait - The optional HTTPBIND wait value. This is the
80
+ * time the server will wait before returning an empty result for
81
+ * a request. The default setting of 60 seconds is recommended.
82
+ * Other settings will require tweaks to the Strophe.TIMEOUT value.
83
+ * (Integer) hold - The optional HTTPBIND hold value. This is the
84
+ * number of connections the server will hold at one time. This
85
+ * should almost always be set to 1 (the default).
86
+ */
87
+ connect: function (domain, callback, wait, hold) {
88
+
89
+ var that = this._connection;
90
+
91
+ this.instructions = "";
92
+ this.fields = {};
93
+ this.authentication = {};
94
+ this.registered = false;
95
+ this.enabled = false;
96
+
97
+ that.connect_callback = callback;
98
+ that.connected = false;
99
+ that.authenticated = false;
100
+ that.disconnecting = false;
101
+ that.errors = 0;
102
+
103
+ that.domain = domain || that.domain;
104
+ that.wait = wait || that.wait;
105
+ that.hold = hold || that.hold;
106
+
107
+ // build the body tag
108
+ var body = that._buildBody().attrs({
109
+ to: that.domain,
110
+ "xml:lang": "en",
111
+ wait: that.wait,
112
+ hold: that.hold,
113
+ content: "text/xml; charset=utf-8",
114
+ ver: "1.6",
115
+ "xmpp:version": "1.0",
116
+ "xmlns:xmpp": Strophe.NS.BOSH
117
+ });
118
+
119
+ that._changeConnectStatus(Strophe.Status.CONNECTING, null);
120
+
121
+ that._requests.push(
122
+ new Strophe.Request(body.tree(),
123
+ that._onRequestStateChange.bind(
124
+ that, this._register_cb.bind(this)),
125
+ body.tree().getAttribute("rid")));
126
+ that._throttledRequestHandler();
127
+ },
128
+
129
+ /** PrivateFunction: _register_cb
130
+ * _Private_ handler for initial registration request.
131
+ *
132
+ * This handler is used to process the initial registration request
133
+ * response from the BOSH server. It is used to set up a bosh session
134
+ * and requesting registration fields from host.
135
+ *
136
+ * Parameters:
137
+ * (Strophe.Request) req - The current request.
138
+ */
139
+ _register_cb: function (req) {
140
+ var that = this._connection;
141
+
142
+ Strophe.info("_register_cb was called");
143
+ that.connected = true;
144
+
145
+ var bodyWrap = req.getResponse();
146
+ if (!bodyWrap) { return; }
147
+
148
+ if (that.xmlInput !== Strophe.Connection.prototype.xmlInput) {
149
+ that.xmlInput(bodyWrap);
150
+ }
151
+ if (that.rawInput !== Strophe.Connection.prototype.rawInput) {
152
+ that.rawInput(Strophe.serialize(bodyWrap));
153
+ }
154
+
155
+ var typ = bodyWrap.getAttribute("type");
156
+ var cond, conflict;
157
+ if (typ !== null && typ == "terminate") {
158
+ // an error occurred
159
+ cond = bodyWrap.getAttribute("condition");
160
+ conflict = bodyWrap.getElementsByTagName("conflict");
161
+ if (cond !== null) {
162
+ if (cond == "remote-stream-error" && conflict.length > 0) {
163
+ cond = "conflict";
164
+ }
165
+ that._changeConnectStatus(Strophe.Status.CONNFAIL, cond);
166
+ } else {
167
+ that._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown");
168
+ }
169
+ return;
170
+ }
171
+
172
+ // check to make sure we don't overwrite these if _connect_cb is
173
+ // called multiple times in the case of missing stream:features
174
+ if (!that.sid) {
175
+ that.sid = bodyWrap.getAttribute("sid");
176
+ }
177
+ if (!that.stream_id) {
178
+ that.stream_id = bodyWrap.getAttribute("authid");
179
+ }
180
+
181
+ var wind = bodyWrap.getAttribute('requests');
182
+ if (wind) { that.window = parseInt(wind, 10); }
183
+ var hold = bodyWrap.getAttribute('hold');
184
+ if (hold) { that.hold = parseInt(hold, 10); }
185
+ var wait = bodyWrap.getAttribute('wait');
186
+ if (wait) { that.wait = parseInt(wait, 10); }
187
+
188
+
189
+ var register, mechanisms;
190
+ register = bodyWrap.getElementsByTagName("register");
191
+ mechanisms = bodyWrap.getElementsByTagName("mechanism");
192
+ if (register.length === 0 && mechanisms.length === 0) {
193
+ // we didn't get stream:features yet, so we need wait for it
194
+ // by sending a blank poll request
195
+ var body = that._buildBody();
196
+ that._requests.push(
197
+ new Strophe.Request(body.tree(),
198
+ that._onRequestStateChange.bind(
199
+ that, this._register_cb.bind(this)),
200
+ body.tree().getAttribute("rid")));
201
+ that._throttledRequestHandler();
202
+ return;
203
+ }
204
+
205
+ var i, mech;
206
+ for (i = 0; i < mechanisms.length; i++) {
207
+ mech = Strophe.getText(mechanisms[i]);
208
+ if (mech == 'DIGEST-MD5') {
209
+ this.authentication.sasl_digest_md5 = true;
210
+ } else if (mech == 'PLAIN') {
211
+ this.authentication.sasl_plain = true;
212
+ } else if (mech == 'ANONYMOUS') {
213
+ this.authentication.sasl_anonymous = true;
214
+ }
215
+ }
216
+
217
+ if (register.length === 0) {
218
+ that._changeConnectStatus(Strophe.Status.REGIFAIL, null);
219
+ return;
220
+ } else this.enabled = true;
221
+
222
+ // send a get request for registration, to get all required data fields
223
+ that._changeConnectStatus(Strophe.Status.REGISTERING, null);
224
+ that._addSysHandler(this._get_register_cb.bind(this),
225
+ null, "iq", null, null);
226
+ that.send($iq({type: "get"}).c("query",
227
+ {xmlns: Strophe.NS.REGISTER}).tree());
228
+ },
229
+
230
+ /** PrivateFunction: _get_register_cb
231
+ * _Private_ handler for Registration Fields Request.
232
+ *
233
+ * Parameters:
234
+ * (XMLElement) elem - The query stanza.
235
+ *
236
+ * Returns:
237
+ * false to remove the handler.
238
+ */
239
+ _get_register_cb: function (stanza) {
240
+ var i, query, field, that = this._connection;
241
+ query = stanza.getElementsByTagName("query");
242
+
243
+ if (query.length !== 1) {
244
+ that._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
245
+ return false;
246
+ }
247
+ query = query[0];
248
+ // get required fields
249
+ for (i = 0; i < query.childNodes.length; i++) {
250
+ field = query.childNodes[i];
251
+ if (field.tagName.toLowerCase() === 'instructions') {
252
+ // this is a special element
253
+ // it provides info about given data fields in a textual way.
254
+ this.instructions = Strophe.getText(field);
255
+ continue;
256
+ } else if (field.tagName.toLowerCase() === 'x') {
257
+ // ignore x for now
258
+ continue;
259
+ }
260
+ this.fields[field.tagName.toLowerCase()] = Strophe.getText(field);
261
+ }
262
+ that._changeConnectStatus(Strophe.Status.REGISTER, null);
263
+ return false;
264
+ },
265
+
266
+ /** Function: submit
267
+ * Submits Registration data.
268
+ *
269
+ * As the registration process proceeds, the user supplied callback will
270
+ * be triggered with status code Strophe.Status.REGISTER. At this point
271
+ * the user should fill all required fields in connection.register.fields
272
+ * and invoke this function to procceed in the registration process.
273
+ */
274
+ submit: function () {
275
+ var i, name, query, fields, that = this._connection;
276
+ query = $iq({type: "set"}).c("query", {xmlns:Strophe.NS.REGISTER});
277
+
278
+ // set required fields
279
+ fields = Object.keys(this.fields);
280
+ for (i = 0; i < fields.length; i++) {
281
+ name = fields[i];
282
+ query.c(name).t(this.fields[name]).up();
283
+ }
284
+
285
+ // providing required information
286
+ that._changeConnectStatus(Strophe.Status.SUBMITTING, null);
287
+ that._addSysHandler(this._submit_cb.bind(this),
288
+ null, "iq", null, null);
289
+ that.send(query);
290
+ },
291
+
292
+ /** PrivateFunction: _submit_cb
293
+ * _Private_ handler for submitted registration information.
294
+ *
295
+ * Parameters:
296
+ * (XMLElement) elem - The query stanza.
297
+ *
298
+ * Returns:
299
+ * false to remove the handler.
300
+ */
301
+ _submit_cb: function (stanza) {
302
+ var i, query, field, error = null, that = this._connection;
303
+
304
+ query = stanza.getElementsByTagName("query");
305
+ if (query.length > 0) {
306
+ query = query[0];
307
+ // update fields
308
+ for (i = 0; i < query.childNodes.length; i++) {
309
+ field = query.childNodes[i];
310
+ if (field.tagName.toLowerCase() === 'instructions') {
311
+ // this is a special element
312
+ // it provides info about given data fields in a textual way
313
+ this.instructions = Strophe.getText(field);
314
+ continue;
315
+ }
316
+ this.fields[field.tagName.toLowerCase()]=Strophe.getText(field);
317
+ }
318
+ }
319
+ console.log(stanza);
320
+ if (stanza.getAttribute("type") === "error") {
321
+ error = stanza.getElementsByTagName("error");
322
+ if (error.length !== 1) {
323
+ that._changeConnectStatus(Strophe.Status.SBMTFAIL, "unknown");
324
+ return false;
325
+ }
326
+ // this is either 'conflict' or 'not-acceptable'
327
+ error = error[0].firstChild.tagName.toLowerCase();
328
+ if (error === 'conflict')
329
+ // already registered
330
+ this.registered = true;
331
+ } else
332
+ this.registered = true;
333
+
334
+ if (this.registered) {
335
+ that.jid = this.fields.username + "@" + that.domain;
336
+ that.pass = this.fields.password;
337
+ }
338
+
339
+ if (error === null) {
340
+ console.log("Registered successful.");
341
+ that._changeConnectStatus(Strophe.Status.REGISTERED, null);
342
+ } else {
343
+ console.log("Registration failed.");
344
+ that._changeConnectStatus(Strophe.Status.SBMTFAIL, error);
345
+ }
346
+ return false;
347
+ },
348
+
349
+ /** Function: authenticate
350
+ * Login with newly registered account.
351
+ *
352
+ * This is just a helper function to authenticate with the new account of
353
+ * the successful registration. This is recommended to do in the
354
+ * user supplied callback when receiving Strophe.Status.REGISTERED.
355
+ * It is also possible to do it on Strophe.Status.SBMTFAIL when
356
+ * connection.register.registered is true under the circumstances that an
357
+ * already existing account with the appendant password was supplied.
358
+ */
359
+ authenticate: function () {
360
+ var auth_str, hashed_auth_str, that = this._connection;
361
+
362
+ if (Strophe.getNodeFromJid(that.jid) === null &&
363
+ this.authentication.sasl_anonymous) {
364
+ that._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
365
+ that._sasl_success_handler = that._addSysHandler(
366
+ that._sasl_success_cb.bind(that), null,
367
+ "success", null, null);
368
+ that._sasl_failure_handler = that._addSysHandler(
369
+ that._sasl_failure_cb.bind(that), null,
370
+ "failure", null, null);
371
+
372
+ that.send($build("auth", {
373
+ xmlns: Strophe.NS.SASL,
374
+ mechanism: "ANONYMOUS"
375
+ }).tree());
376
+ } else if (Strophe.getNodeFromJid(that.jid) === null) {
377
+ // we don't have a node, which is required for non-anonymous
378
+ // client connections
379
+ that._changeConnectStatus(Strophe.Status.CONNFAIL,
380
+ 'x-strophe-bad-non-anon-jid');
381
+ that.disconnect();
382
+ } else if (this.authentication.sasl_digest_md5) {
383
+ that._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
384
+ that._sasl_challenge_handler = that._addSysHandler(
385
+ that._sasl_challenge1_cb.bind(that), null,
386
+ "challenge", null, null);
387
+ that._sasl_failure_handler = that._addSysHandler(
388
+ that._sasl_failure_cb.bind(that), null,
389
+ "failure", null, null);
390
+
391
+ that.send($build("auth", {
392
+ xmlns: Strophe.NS.SASL,
393
+ mechanism: "DIGEST-MD5"
394
+ }).tree());
395
+ } else if (this.authentication.sasl_plain) {
396
+ // Build the plain auth string (barejid null
397
+ // username null password) and base 64 encoded.
398
+ auth_str = Strophe.getBareJidFromJid(that.jid);
399
+ auth_str = auth_str + "\u0000";
400
+ auth_str = auth_str + Strophe.getNodeFromJid(that.jid);
401
+ auth_str = auth_str + "\u0000";
402
+ auth_str = auth_str + that.pass;
403
+
404
+ that._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
405
+ that._sasl_success_handler = that._addSysHandler(
406
+ that._sasl_success_cb.bind(that), null,
407
+ "success", null, null);
408
+ that._sasl_failure_handler = that._addSysHandler(
409
+ that._sasl_failure_cb.bind(that), null,
410
+ "failure", null, null);
411
+
412
+ hashed_auth_str = Base64.encode(auth_str);
413
+ that.send($build("auth", {
414
+ xmlns: Strophe.NS.SASL,
415
+ mechanism: "PLAIN"
416
+ }).t(hashed_auth_str).tree());
417
+ } else {
418
+ that._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
419
+ that._addSysHandler(that._auth1_cb.bind(that), null, null,
420
+ null, "_auth_1");
421
+
422
+ that.send($iq({
423
+ type: "get",
424
+ to: that.domain,
425
+ id: "_auth_1"
426
+ }).c("query", {
427
+ xmlns: Strophe.NS.AUTH
428
+ }).c("username", {}).t(Strophe.getNodeFromJid(that.jid)).tree());
429
+ }
430
+ },
431
+ });
@@ -0,0 +1,40 @@
1
+ (function(Strophe) {
2
+
3
+ // only presence based, add roster later if needed, see chapter14
4
+ function log(msg) {
5
+ if (window.console) {
6
+ console.log('roster.' + msg);
7
+ }
8
+ }
9
+
10
+ var roster = {
11
+ init: function (conn) {
12
+ this._conn = conn;
13
+ this.contacts = {};
14
+ Strophe.addNamespace('ROSTER', 'jabber:iq:roster');
15
+ },
16
+ statusChanged: function (status) {
17
+ if (status === Strophe.Status.CONNECTED) {
18
+ this._conn.send($pres());
19
+ this._conn.addHandler(this.presenceChanged.bind(this),
20
+ null, "presence");
21
+ }
22
+ },
23
+ presenceChanged: function(pres) {
24
+ var from = pres.getAttribute('from');
25
+ var type = pres.getAttribute('type') || "available";
26
+ if (from !== this._conn.jid) {
27
+ this.contacts[from] = type;
28
+ if (type === "unavailable") {
29
+ delete this.contacts[from];
30
+ }
31
+ this.onPresenceChanged(from,type);
32
+ }
33
+ return true;
34
+ },
35
+ onPresenceChanged: function(from,type) {
36
+ log('onPresenceChanged: ' + from + " => " + type);
37
+ }
38
+ };
39
+ Strophe.addConnectionPlugin('roster', roster);
40
+ })(Strophe);
@@ -0,0 +1,65 @@
1
+ describe("Roster", function() {
2
+ var conn, roster;
3
+ beforeEach(function() {
4
+ conn = new Strophe.Connection();
5
+ roster = conn.roster;
6
+ conn._changeConnectStatus(Strophe.Status.CONNECTED);
7
+ conn.authenticated = true;
8
+ });
9
+
10
+
11
+ it("adds contacts on presence stanza", function() {
12
+ var pres = $pres({from: 'n@d/r'});
13
+ conn._dataRecv(createRequest(pres));
14
+ expect(conn.roster.contacts).toEqual({'n@d/r': 'available'});
15
+ });
16
+
17
+ it("removes contacts on presence stanza where type is unavailable", function() {
18
+ var pres = $pres({from: 'n@d/r', type: 'unavailable'});
19
+ conn.roster.contacts = { 'n@d/r': 'available'};
20
+ conn._dataRecv(createRequest(pres));
21
+ expect(conn.roster.contacts).toEqual({});
22
+ });
23
+
24
+ it("calls callback on presence stanza", function() {
25
+ spyOn(roster,'onPresenceChanged').andCallThrough();
26
+ var pres = $pres({from: 'n@d/r'});
27
+ conn._dataRecv(createRequest(pres));
28
+ expect(conn.roster.contacts).toEqual({'n@d/r': 'available'});
29
+ expect(roster.onPresenceChanged).toHaveBeenCalledWith('n@d/r','available');
30
+
31
+ pres = $pres({from: 'n@d/r', type: 'unavailable'});
32
+ conn._dataRecv(createRequest(pres));
33
+ expect(conn.roster.contacts).toEqual({});
34
+ expect(roster.onPresenceChanged).toHaveBeenCalledWith('n@d/r','unavailable');
35
+ });
36
+ describe("state and callback", function() {
37
+ var c1, c2;
38
+ beforeEach(function() {
39
+ c1 = new Strophe.Connection();
40
+ c2 = new Strophe.Connection();
41
+ c1._changeConnectStatus(Strophe.Status.CONNECTED);
42
+ c2._changeConnectStatus(Strophe.Status.CONNECTED);
43
+ c1.authenticated = c2.authenticated = true;
44
+ });
45
+
46
+ it("allows per connection contacts", function() {
47
+ var pres = $pres({from: 'n@d/r'});
48
+ c1._dataRecv(createRequest(pres));
49
+ expect(c2.roster.contacts).toEqual({});
50
+ expect(c1.roster.contacts).toEqual({'n@d/r': 'available'});
51
+ });
52
+ it("allows per connection callbacks", function() {
53
+ var pres = $pres({from: 'n@d/r'});
54
+ var cb = jasmine.createSpy();
55
+ spyOn(c1.roster,'onPresenceChanged').andCallThrough();
56
+ c2.roster.onPresenceChanged = cb;
57
+ c1._dataRecv(createRequest(pres));
58
+ c2._dataRecv(createRequest(pres));
59
+ expect(cb).toHaveBeenCalled();
60
+ expect(cb.callCount).toEqual(1);
61
+ expect(c1.roster.onPresenceChanged.callCount).toEqual(1);
62
+ });
63
+ });
64
+ });
65
+
@@ -0,0 +1,15 @@
1
+ {
2
+ "src_dir" : "/public/javascript/",
3
+ "spec_dir" : "/spec/",
4
+
5
+ "server":{
6
+ "port":8124
7
+ },
8
+ "externals":[
9
+ "https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js",
10
+ "https://github.com/velesin/jasmine-jquery/raw/master/lib/jasmine-jquery.js",
11
+ "http://localhost/strophe.js",
12
+ "http://localhost/Stanzas.js"
13
+ ]
14
+
15
+ }