0
|
1 'use strict';
|
|
2
|
2
|
3 /**
|
|
4 Copyright (c) 2011, Sonny Piers <sonny at fastmail dot net>
|
|
5
|
|
6 Permission to use, copy, modify, and/or distribute this software for any
|
|
7 purpose with or without fee is hereby granted, provided that the above
|
|
8 copyright notice and this permission notice appear in all copies.
|
|
9
|
|
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
17 */
|
|
18
|
0
|
19 //
|
|
20 //Roster
|
|
21 //
|
|
22 Lighstring.NS.roster = 'jabber:iq:roster';
|
|
23 Lighstring.stanza.roster = {
|
|
24 'get': function() {
|
2
|
25 return "<iq type='get'><query xmlns='"+Lightstring.NS.roster+"'/></iq>";
|
0
|
26 },
|
|
27 add: function(aAddress, aGroups, aCustomName) {
|
2
|
28 var iq = $iq({type: 'set'}).c('query', {xmlns: Lightstring.NS.roster}).c('item', {jid: aAddress}).tree();
|
0
|
29 if(aCustomName) iq.querySelector('item').setAttribute(aCustomName);
|
|
30 for (var i=0; i<aGroups.length; i++) {
|
|
31 if(i === 0) iq.querySelector('item').appendChild(document.createElement('group'));
|
|
32 iq.querySelector('group').appendChild(document.createElement(aGroups[i]));
|
|
33 }
|
|
34 return iq;
|
|
35 },
|
|
36 remove: function(aAddress) {
|
2
|
37 return $iq({type: 'set'}).c('query', {xmlns: Lightstring.NS.roster}).c('item', {jid: aAddress, subscription: 'remove'}).tree();
|
0
|
38 }
|
|
39 };
|
|
40 Lighstring.getRoster = function(connection, aCallback) {
|
|
41 connection.send(this.stanza.roster.get(), function(answer){
|
|
42 var contacts = [];
|
|
43 answer.querySelectorAll('item').forEach(function(item) {
|
|
44 var jid = item.getAttribute('jid');
|
|
45 var name = item.getAttribute('name');
|
|
46 var groups = item.querySelectorAll('group');
|
|
47 var subscription = item.getAttribute('subscription');
|
|
48 var contact = {};
|
|
49 if(name)
|
|
50 contact.name = name;
|
|
51 if(jid)
|
|
52 contact.jid = jid;
|
|
53 if(subscription)
|
|
54 contact.subscription = subscription;
|
|
55 if(groups.length > 0) {
|
|
56 contact.groups = [];
|
|
57 groups.forEach(function(group) {
|
|
58 contact.groups.push(group.textContent);
|
|
59 });
|
|
60 }
|
|
61
|
|
62 contacts.push(contact);
|
|
63 });
|
|
64 aCallback(contacts);
|
|
65 });
|
|
66 }
|
|
67 //
|
|
68 //vCard
|
|
69 //
|
|
70 Lighstring.NS.vcard = 'vcard-temp';
|
|
71 Lighstring.stanza.vcard = {
|
|
72 'get': function(aTo) {
|
|
73 if(aTo)
|
2
|
74 return "<iq type='get' to='"+aTo+"'><vCard xmlns='"+Lightstring.NS.vcard+"'/></iq>";
|
0
|
75 else
|
2
|
76 return "<iq type='get'><vCard xmlns='"+Lightstring.NS.vcard+"'/></iq>";
|
0
|
77 }
|
|
78 };
|
|
79 //FIXME we should return a proper vcard, not an XMPP one
|
|
80 Lighstring.getVcard = function(aConnection, aTo, aCallback) {
|
2
|
81 aConnection.send(Lightstring.stanza.vcard.get(aTo), function(answer, err){
|
0
|
82 if(answer) {
|
|
83 var vcard = answer.querySelector('vCard');
|
|
84 if(vcard)
|
|
85 aCallback(vcard);
|
|
86 }
|
|
87 else
|
|
88 aCallback(null);
|
|
89 });
|
|
90 }
|
|
91 //
|
|
92 //Disco
|
|
93 //
|
|
94 Lighstring.NS['disco#info'] = "http://jabber.org/protocol/disco#info";
|
|
95 Lighstring.NS['disco#items'] = "http://jabber.org/protocol/disco#items";
|
|
96 Lighstring.stanza.disco = {
|
|
97 items: function(aTo, aNode) {
|
|
98 if(aTo)
|
|
99 var iq = "<iq type='get' to='"+aTo+"'>";
|
|
100 else
|
|
101 var iq = "<iq type='get'>";
|
|
102
|
|
103 if(aNode)
|
2
|
104 var query = "<query xmlns='"+Lightstring.NS['disco#items']+"' node='"+aNode+"'/>";
|
0
|
105 else
|
2
|
106 var query = "<query xmlns='"+Lightstring.NS['disco#items']+"'/>";
|
0
|
107
|
|
108 return iq+query+"</iq>";
|
|
109 },
|
|
110 info: function(aTo, aNode) {
|
|
111 if(aTo)
|
|
112 var iq = "<iq type='get' to='"+aTo+"'>";
|
|
113 else
|
|
114 var iq = "<iq type='get'>";
|
|
115 if(aNode)
|
2
|
116 var query = "<query xmlns='"+Lightstring.NS['disco#info']+"' node='"+aNode+"'/>";
|
0
|
117 else
|
2
|
118 var query = "<query xmlns='"+Lightstring.NS['disco#info']+"'/>";
|
0
|
119
|
|
120 return iq+query+"</iq>";
|
|
121 }
|
|
122 };
|
|
123 Lighstring.discoItems = function(aConnection, aTo, aCallback) {
|
2
|
124 aConnection.send(Lightstring.stanza.disco.items(aTo), function(answer){
|
0
|
125 var items = [];
|
|
126 answer.querySelectorAll('item').forEach(function(node) {
|
|
127 var item = {
|
|
128 jid: node.getAttribute('jid'),
|
|
129 name: node.getAttribute('name'),
|
|
130 node: node.getAttribute('node')
|
|
131 }
|
|
132 items.push(item);
|
|
133 });
|
|
134 if(aCallback)
|
|
135 aCallback(items);
|
|
136 });
|
|
137 };
|
|
138 Lighstring.discoInfo = function(aConnection, aTo, aNode, aCallback) {
|
2
|
139 aConnection.send(Lightstring.stanza.disco.info(aTo, aNode), function(answer){
|
0
|
140 var field = answer.querySelector('field[var="pubsub#creator"] > value');
|
|
141 var creator = field ? field.textContent : '';
|
|
142 //FIXME callback the entire data
|
|
143 aCallback(creator);
|
|
144 });
|
|
145 };
|
|
146 //
|
|
147 //PubSub
|
|
148 //
|
|
149 Lighstring.NS.x = "jabber:x:data";
|
|
150 Lighstring.NS.pubsub = "http://jabber.org/protocol/pubsub";
|
|
151 Lighstring.NS.pubsub_owner = "http://jabber.org/protocol/pubsub#owner";
|
|
152 Lighstring.stanza.pubsub = {
|
|
153 getConfig: function(aTo, aNode) {
|
2
|
154 return "<iq type='get' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub_owner+"'><configure node='"+aNode+"'/></pubsub></iq>";
|
0
|
155 },
|
|
156 items: function(aTo, aNode) {
|
2
|
157 return "<iq type='get' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub+"'><items node='"+aNode+"'/></pubsub></iq>";
|
0
|
158 },
|
|
159 affiliations: function(aTo, aNode) {
|
2
|
160 return "<iq type='get' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub_owner+"'><affiliations node='"+aNode+"'/></pubsub></iq>";
|
0
|
161 },
|
|
162 publish: function(aTo, aNode, aItem, aId) {
|
2
|
163 return "<iq type='set' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub+"'><publish node='"+aNode+"'><item id='"+aId+"'>"+aItem+"</item></publish></pubsub></iq>";
|
0
|
164 },
|
|
165 retract: function(aTo, aNode, aItem) {
|
2
|
166 return "<iq type='set' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub+"'><retract node='"+aNode+"'><item id='"+aItem+"'/></retract></pubsub></iq>";
|
0
|
167 },
|
|
168 'delete': function(aTo, aNode, aURI) {
|
2
|
169 return "<iq type='set' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub_owner+"'><delete node='"+aNode+"'/></pubsub></iq>";
|
0
|
170 },
|
|
171 create: function(aTo, aNode, aFields) {
|
2
|
172 var iq = "<iq type='set' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub+"'><create node='"+aNode+"'/>";
|
0
|
173 if(aFields) {
|
2
|
174 iq += "<configure><x xmlns='"+Lightstring.NS.x+"' type='submit'>"
|
0
|
175 aFields.forEach(function(field) {
|
|
176 iq += field;
|
|
177 });
|
|
178 iq += "</x></configure>";
|
|
179 }
|
|
180 iq += "</pubsub></iq>";
|
|
181 return iq;
|
|
182 },
|
|
183 setAffiliations: function(aTo, aNode, aAffiliations) {
|
2
|
184 var iq = "<iq type='set' to='"+aTo+"'><pubsub xmlns='"+Lightstring.NS.pubsub_owner+"'><affiliations node='"+aNode+"'>";
|
0
|
185 for(var i = 0; i < aAffiliations.length; i++) {
|
|
186 iq += "<affiliation jid='"+aAffiliations[i][0]+"' affiliation='"+aAffiliations[i][1]+"'/>"
|
|
187 }
|
|
188 iq += "</affiliations></pubsub></iq>";
|
|
189 return iq;
|
|
190 },
|
|
191 };
|
|
192 Lighstring.pubsubItems = function(aConnection, aTo, aNode, aCallback) {
|
2
|
193 aConnection.send(Lightstring.stanza.pubsub.items(aTo, aNode), function(answer){
|
0
|
194 var items = [];
|
|
195 answer.querySelectorAll('item').forEach(function(node) {
|
|
196 var item = {
|
|
197 id: node.getAttribute('id'),
|
|
198 name: node.querySelector('title').textContent,
|
|
199 src: node.querySelector('content').getAttribute('src'),
|
|
200 type: node.querySelector('content').getAttribute('type'),
|
|
201 }
|
|
202 var thumbnail = node.querySelector('link');
|
|
203 if(thumbnail)
|
|
204 item.thumbnail = thumbnail.getAttribute('href');
|
|
205 items.push(item);
|
|
206 })
|
|
207 if(aCallback)
|
|
208 aCallback(items);
|
|
209 });
|
|
210 }
|
|
211 Lighstring.pubsubCreate = function(aConnection, aTo, aNode, aFields, aCallback) {
|
2
|
212 aConnection.send(Lightstring.stanza.pubsub.create(aTo, aNode, aFields), function(answer) {
|
0
|
213 if(answer.getAttribute('type') === 'result')
|
|
214 aCallback(null, answer);
|
|
215 else
|
|
216 aCallback(answer, null);
|
|
217 });
|
|
218 };
|
|
219 Lighstring.pubsubConfig = function(aConnection, aTo, aNode, aCallback) {
|
2
|
220 aConnection.send(Lightstring.stanza.pubsub.getConfig(aTo, aNode), function(answer){
|
0
|
221 var accessmodel = answer.querySelector('field[var="pubsub#access_model"]').lastChild.textContent;
|
|
222 if(accessmodel)
|
|
223 aCallback(accessmodel);
|
|
224 else
|
|
225 aCallback(null);
|
|
226 });
|
|
227 }
|
|
228 Lighstring.pubsubRetract = function(aConnection, aTo, aNode, aItem, aCallback) {
|
2
|
229 aConnection.send(Lightstring.stanza.pubsub.retract(aTo, aNode, aItem), function(answer){
|
0
|
230 if(aCallback)
|
|
231 aCallback(answer);
|
|
232 });
|
|
233 }
|
|
234 Lighstring.pubsubPublish = function(aConnection, aTo, aNode, aItem, aId, aCallback) {
|
2
|
235 aConnection.send(Lightstring.stanza.pubsub.publish(aTo, aNode, aItem, aId), function(answer){
|
0
|
236 if(answer.getAttribute('type') === 'result')
|
|
237 aCallback(null, answer);
|
|
238 else
|
|
239 aCallback(answer, null);
|
|
240 });
|
|
241 }
|
|
242 Lighstring.pubsubDelete = function(aConnection, aTo, aNode, aCallback) {
|
2
|
243 aConnection.send(Lightstring.stanza.pubsub.delete(aTo, aNode), function(answer){
|
0
|
244 if(aCallback)
|
|
245 aCallback(answer);
|
|
246 });
|
|
247 }
|
|
248 Lighstring.pubsubGetAffiliations = function(aConnection, aTo, aNode, aCallback) {
|
2
|
249 aConnection.send(Lightstring.stanza.pubsub.affiliations(aTo, aNode), function(answer) {
|
0
|
250 if((answer.getAttribute('type') === 'result') && aCallback) {
|
|
251 var affiliations = {};
|
|
252 answer.querySelectorAll('affiliation').forEach(function(affiliation) {
|
|
253 affiliations[affiliation.getAttribute("jid")] = affiliation.getAttribute("affiliation");
|
|
254 })
|
|
255 aCallback(affiliations);
|
|
256 }
|
|
257 });
|
|
258 };
|
|
259 Lighstring.pubsubSetAffiliations = function(aConnection, aTo, aNode, aAffiliations, aCallback) {
|
2
|
260 aConnection.send(Lightstring.stanza.pubsub.setAffiliations(aTo, aNode, aAffiliations));
|
0
|
261 };
|
|
262 //
|
|
263 //IM
|
|
264 //
|
|
265 Lighstring.stanza.message = {
|
|
266 normal: function(aTo, aSubject, aText) {
|
|
267 return "<message type='normal' to='"+aTo+"'><subject>"+aSubject+"</subject><body>"+aText+"</body></message>";
|
|
268 },
|
|
269 chat: function(aTo, aText) {
|
|
270 return "<message type='chat' to='"+aTo+"'><body>"+aText+"</body></message>";
|
|
271 }
|
|
272 };
|
|
273
|