xmppify 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
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
+ }