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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/app/assets/javascripts/xmpp/index.js +0 -0
- data/app/assets/javascripts/xmpp/scripts/checkplayer.js +12 -0
- data/app/assets/javascripts/xmpp/scripts/crossdomain.xml +7 -0
- data/app/assets/javascripts/xmpp/scripts/flXHR.js +2 -0
- data/app/assets/javascripts/xmpp/scripts/flXHR.swf +0 -0
- data/app/assets/javascripts/xmpp/scripts/flXHR.vbs +44 -0
- data/app/assets/javascripts/xmpp/scripts/flensed.js +12 -0
- data/app/assets/javascripts/xmpp/scripts/strophe.flxhr.js +31 -0
- data/app/assets/javascripts/xmpp/scripts/strophe.js +3538 -0
- data/app/assets/javascripts/xmpp/scripts/swfobject.js +5 -0
- data/app/assets/javascripts/xmpp/scripts/updateplayer.swf +0 -0
- data/app/assets/javascripts/xmpp/scripts/xmpp.js.coffee +386 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/LICENSE.txt +19 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/README.markdown +95 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/archive/README.markdown +14 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/archive/iso8601_support.js +32 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/archive/strophe.archive.js +88 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/caps/README.markdown +53 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/caps/sha1.js +202 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/caps/strophe.CAPS.coffee +153 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/caps/strophe.CAPS.js +88 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/caps/strophe.caps.jsonly.js +240 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/chatstates/strophe.chatstates.js +80 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/README.markdown +47 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/spec/GetUrlComamndSpec.js +66 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/spec/strophe.cmds.spec.coffee +145 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/spec/support/jasmine.json +16 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/src/strophe.cmds.coffee +265 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/cmds/src/strophe.cmds.js +403 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/README.markdown +82 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/spec/strophe.x.coffee +715 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/src/strophe.x.coffee +443 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/dataforms/src/strophe.x.js +854 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/.gitignore +1 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/README.markdown +0 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/convert.js +13 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/jasmine.json +11 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/lib/strophe.disco.js +137 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/public/javascript/strophe.disco.js +137 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/01_querying_information.xml +6 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/02_result_set_for_information_request.xml +22 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/03_target_entity_does_not_exist.xml +10 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/04_service_unavailable.xml +11 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/09_querying_specific_jid_and_node_combination.xml +7 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/10_jid_and_node_result.xml +12 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/11_requesting_all_items.xml +6 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/12_result_set_for_all_items.xml +23 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/13_empty_result_set.xml +7 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/17_service_returns_nodes.xml +16 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/18_requesting_further_nodes.xml +7 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/24_jid_and_node_error.xml +11 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/DiscoNodeSpec.js +50 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/SpecHelper.js +51 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/Stanzas.js +0 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/strophe.disco.spec.helper.js +54 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/strophe.disco.spec.js +0 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/spec/support/jasmine.json +13 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/disco/strophe.disco.js +232 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/epic/public/javascript/jquery.epic.js +61 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/epic/spec/SpecHelper.js +9 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/epic/spec/jquery.epic.js +39 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/epic/spec/support/jasmine.json +22 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/iexdomain/iexdomain.js +36 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/README.markdown +117 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/buster.js +23 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/jid.coffee +64 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/jid.js +92 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/spec/browserSetup.coffee +1 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/spec/jid.spec.coffee +96 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/spec/strophe.joap.spec.coffee +461 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/strophe.joap.coffee +304 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/joap/strophe.joap.js +522 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/mam/LICENSE.txt +19 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/mam/README.markdown +52 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/mam/strophe.mam.js +62 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/muc/LICENSE.txt +20 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/muc/strophe.muc.js +1003 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/ping/README.markdown +28 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/ping/strophe.ping.js +68 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/private/README.markdown +16 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/private/strophe.private.js +192 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/pubsub/strophe.pubsub.js +555 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/receipts/strophe.receipts.js +155 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/register/README.markdown +44 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/register/strophe.register.js +431 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/roster/public/javascript/strophe.roster.js +40 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/roster/spec/strophe.roster.spec.js +65 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/roster/spec/support/jasmine.json +15 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/roster/strophe.roster.js +438 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/.gitignore +6 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/README.md +113 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/buster.js +11 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/lib/strophe.js +4198 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/spec/strophe.rpc.spec.helper.js +38 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/spec/strophe.rpc.spec.js +262 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rpc/strophe.rpc.js +464 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/rsm/strophe.rsm.js +52 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/serverdate/strophe.serverdate.js +58 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/examples/index.html +17 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/examples/strophevcard.js +0 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/strophe.vcard.coffee +44 -0
- data/app/assets/javascripts/xmpp/strophejs-plugins/vcard/strophe.vcard.js +66 -0
- data/app/assets/stylesheets/xmpp/index.css +0 -0
- data/app/controllers/omniauth_callbacks_controller.rb +15 -0
- data/app/controllers/ruby_bosh.rb +221 -0
- data/app/models/identity.rb +3 -0
- data/app/models/user.rb +40 -0
- data/bin/rails +8 -0
- data/db/migrate/20140329065635_create_users.rb +10 -0
- data/db/migrate/20140329070238_create_identities.rb +11 -0
- data/lib/xmppify/version.rb +3 -0
- data/lib/xmppify.rb +6 -0
- data/xmppify.gemspec +23 -0
- 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
|
+
}
|