0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
1 #!/usr/bin/env node
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
2
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
3 /*
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
4 * Copyright (C) 2011 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
5 *
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
6 * This file is the source code of an XMPP avatar retriever.
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
7 *
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
8 * This program is free software: you can redistribute it and/or modify
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
9 * it under the terms of the GNU Affero General Public License as
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
10 * published by the Free Software Foundation, version 3 of the License.
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
11 *
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
12 * This program is distributed in the hope that it will be useful,
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
15 * GNU Affero General Public License for more details.
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
16 *
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
17 * You should have received a copy of the GNU Affero General Public License
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
19 */
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
20
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
21 'use strict';
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
22
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
23 var config = require('./configuration');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
24
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
25 try {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
26 var xmpp = require('node-xmpp');
|
4
|
27 var conn = new xmpp.Component(config);
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
28
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
29 conn.on('stanza', function (stanza) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
30 if (stanza.is('iq'))
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
31 onIq(stanza);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
32 else
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
33 onError(stanza);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
34 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
35
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
36 conn._uniqueId = 42;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
37 conn.getUniqueId = function(suffix) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
38 return ++this._uniqueId + (suffix?(":"+suffix):"");
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
39 };
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
40
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
41 var Element = require('ltx').Element;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
42 } catch (e) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
43 var xmpp = require('xmpp');
|
4
|
44 var conn = new xmpp.Connection(config.host, config.port);
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
45
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
46 conn.log = function (_, m) { console.log(m); };
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
47
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
48 conn.connect(config.jid, config.password, function (status, condition) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
49 if(status == xmpp.Status.CONNECTED) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
50 conn.addHandler(onIq, null, 'iq', null, null, null);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
51 conn.addHandler(onError, null, 'message', null, null, null);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
52 conn.addHandler(onError, null, 'presence', null, null, null);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
53 } else
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
54 conn.log(xmpp.LogLevel.DEBUG, "New connection status: " + status + (condition?(" ("+condition+")"):""));
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
55 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
56
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
57 xmpp.StanzaBuilder.prototype.cnode = function (stanza)
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
58 {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
59 var parent = this.last_node[this.last_node.length-1];
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
60 parent.tags.push(stanza);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
61 parent.children.push(stanza);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
62 this.last_node.push(stanza);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
63 return this;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
64 };
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
65
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
66 var Element = xmpp.StanzaBuilder;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
67 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
68
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
69 var fs = require('fs');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
70 var http = require('http');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
71
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
72 process.addListener('uncaughtException', function (err) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
73 console.log('\x1b[41;1mUncaught exception (' + err + '), this should never happen:\x1b[0m\n' + err.stack);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
74 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
75
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
76 var extensions = {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
77 png: 'image/png',
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
78 svg: 'image/svg+xml',
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
79 jpg: 'image/jpeg',
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
80 gif: 'image/gif'
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
81 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
82
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
83 var jids = {};
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
84
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
85 var sent = {};
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
86
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
87 var svgError = function(res, message) {
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
88 res.writeHead(500, {'Content-Type': 'image/svg+xml'});
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
89 res.write('<?xml version="1.0" encoding="UTF-8"?>\n');
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
90 res.write('<svg xmlns="http://www.w3.org/2000/svg" viewBox="-256 -20 512 32">\n');
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
91 res.write('\t<rect x="-256" y="-20" width="512" height="32" fill="white"/>\n');
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
92 res.write('\t<text text-anchor="middle">'+message+'</text>\n');
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
93 res.end('</svg>\n');
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
94 }
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
95
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
96 var makeError = function(response) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
97 response.attr.type = 'error';
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
98
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
99 var error = new Element('error', {type: 'cancel'});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
100 error.c('feature-not-implemented', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up();
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
101 response.cnode(error);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
102
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
103 return response;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
104 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
105
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
106 function onIq(stanza) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
107 var type = stanza.getAttribute('type');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
108 var from = stanza.getAttribute('to');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
109 var to = stanza.getAttribute('from');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
110 var id = stanza.getAttribute('id');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
111
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
112 var response;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
113 if (id)
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
114 response = new Element('iq', {to: to, from: from, type: 'result', id: id});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
115 else
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
116 response = new Element('iq', {to: to, from: from, type: 'result'});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
117
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
118 if (!sent[id]) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
119 conn.send(makeError(response));
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
120 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
121 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
122
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
123 var res = sent[id];
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
124 delete sent[id];
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
125
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
126 if (type == 'error') {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
127 try {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
128 var err = stanza.getChild('error').getChild().name;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
129 } catch (e) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
130 var err = 'none';
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
131 }
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
132 svgError(res, 'Error during query of this user’s vCard: “'+err+'”.');
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
133 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
134 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
135
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
136 var vCard = stanza.getChild('vCard', 'vcard-temp');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
137 if (!vCard) {
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
138 svgError(res, 'Error: this user doesn’t have a vCard.');
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
139 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
140 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
141
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
142 try {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
143 var photo = vCard.getChild('PHOTO', 'vcard-temp');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
144 var base64 = photo.getChild('BINVAL', 'vcard-temp').getText();
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
145
|
1
0c19fadfc12d
Serve the right error message when the TYPE of the PHOTO is missing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
146 try {
|
0c19fadfc12d
Serve the right error message when the TYPE of the PHOTO is missing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
147 var type = photo.getChild('TYPE', 'vcard-temp').getText();
|
0c19fadfc12d
Serve the right error message when the TYPE of the PHOTO is missing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
148 } catch (e) {
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
149 svgError(res, 'Error: this user’s vCard doesn’t specify the MIME type of its avatar.');
|
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
150 return;
|
1
0c19fadfc12d
Serve the right error message when the TYPE of the PHOTO is missing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
151 }
|
0c19fadfc12d
Serve the right error message when the TYPE of the PHOTO is missing.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
152
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
153 var ext;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
154 for (var i in extensions)
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
155 if (type == extensions[i])
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
156 ext = i;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
157
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
158 if (ext === undefined) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
159 console.log('Type MIME inconnu : '+type);
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
160 svgError(res, 'Error: this user’s avatar is in an unknown format.');
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
161 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
162 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
163
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
164 var binval = new Buffer(base64.replace(/\n/g, ''), 'base64');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
165
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
166 fs.writeFile(config.directory+'/'+to+'.'+ext, binval, function() {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
167 jids[to] = ext;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
168 showImage(to, res);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
169 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
170 } catch (e) {
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
171 svgError(res, 'Error: this user doesn’t have an avatar in his/her vCard.');
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
172 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
173 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
174
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
175 function onError(stanza) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
176 if (stanza.getAttribute('type') == 'error')
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
177 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
178
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
179 var from = stanza.getAttribute('to');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
180 var to = stanza.getAttribute('from');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
181 var id = stanza.getAttribute('id');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
182
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
183 var response;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
184 if (id)
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
185 response = new Element(stanza.name, {to: to, from: from, id: id});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
186 else
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
187 response = new Element(stanza.name, {to: to, from: from});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
188
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
189 conn.send(makeError(response));
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
190 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
191
|
3
|
192 var getVCard = function(jid, res) {
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
193 var id = conn.getUniqueId();
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
194
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
195 var toSend = new Element('iq', {to: jid, from: config.jid, type: 'get', id: id})
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
196 .c('vCard', {xmlns: 'vcard-temp'});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
197
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
198 conn.send(toSend);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
199
|
3
|
200 sent[id] = res;
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
201 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
202
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
203 var showImage = function(jid, res) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
204 var extension = jids[jid];
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
205 var file = config.directory+'/'+jid+'.'+extension;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
206 res.writeHead(200, {'Content-Type': extensions[extension]});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
207 fs.readFile(file, function(err, data) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
208 res.end(data);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
209 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
210 fs.stat(file, function(err, stats) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
211 if (err) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
212 console.log('Error when stat on “'+file+'”.');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
213 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
214 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
215
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
216 var last = new Date(stats.mtime);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
217 var now = new Date();
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
218
|
3
|
219 if (now - last > 24*60*60*1000)
|
|
220 getVCard(jid, res);
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
221 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
222 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
223 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
224
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
225 fs.readdir('data', function(err, files) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
226 if (err)
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
227 process.exit('1');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
228
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
229 for (var i in files) {
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
230 var tab = /(.*)\.([a-z]{3})/.exec(files[i]);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
231 jids[tab[1]] = tab[2];
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
232 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
233 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
234
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
235 http.createServer(function (req, res) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
236 console.log('Connection from '+req.client.remoteAddress+' ('+req.headers['user-agent']+') to get “'+req.url+'”.');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
237
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
238 var easterEggs = {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
239 source: {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
240 re: /^\/avatar\/source\/code$/,
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
241 file: process.argv[1],
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
242 mime: 'application/ecmascript',
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
243 error: 'source code unavailable! oO'
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
244 },
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
245 README: {},
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
246 COPYING: {},
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
247 };
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
248
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
249 req.setEncoding('utf-8');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
250
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
251 for (var i in easterEggs) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
252 var ee = easterEggs[i];
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
253 var file = ee.file || i;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
254 var re = ee.re || new RegExp('^/avatar/'+file+'$');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
255 if (re.test(req.url)) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
256 fs.readFile(file, function(err, content) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
257 if (err) {
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
258 svgError(res, 'Error: ' + (ee.error || file + ' unavailable.'));
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
259 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
260 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
261 res.writeHead(200, {'Content-Type': ee.mime || 'text/plain'});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
262 res.end(content);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
263 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
264 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
265 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
266 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
267
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
268 var jid = unescape(req.url.replace(/^\/avatar\//, ''));
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
269
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
270 if (jid === '') {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
271 res.writeHead(200, {'Content-Type': 'application/xhtml+xml'});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
272 res.write('<?xml version="1.0" encoding="utf-8"?>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
273 res.write('<!DOCTYPE html>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
274 res.write('<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
275 res.write('\t<head>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
276 res.write('\t\t<title>JavaScript XMPP Avatar Retriever</title>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
277 res.write('\t</head>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
278 res.write('\t<body>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
279 res.write('\t\t<header><h1>JavaScript XMPP Avatar Retriever</h1></header>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
280 res.write('\t\t<p>Put any JID and get its avatar. :)</p>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
281 res.write('\t\t<form action="redirect" method="post">\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
282 res.write('\t\t\t<p>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
283 res.write('\t\t\t\t<input name="jid" type="text" placeholder="you@yourserver.tld"/>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
284 res.write('\t\t\t\t<input type="submit"/>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
285 res.write('\t\t\t</p>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
286 res.write('\t\t</form>\n');
|
2
ad496e8a5e66
Use an image for errors instead of text (unusable in <img/>).
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
diff
changeset
|
287 res.write('\t\t<footer><p>(<a href="README">README</a>, <a href="source/code">source code</a>, <a href="http://hg.linkmauve.fr/avatar">Mercurial repository</a>)</p></footer>\n');
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
288 res.write('\t</body>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
289 res.end('</html>\n');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
290 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
291 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
292
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
293 if (jid === 'redirect') {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
294 if (req.method !== 'POST') {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
295 res.writeHead(404, {'Content-Type': 'text/plain'});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
296 res.end('Error: redirect unavailable.');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
297 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
298 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
299
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
300 req.on('data', function(content) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
301 console.log(content);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
302 var jid = unescape(content.toString()).replace(/^jid=/, '');
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
303 res.writeHead(301, {'Location': jid});
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
304 res.end();
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
305 });
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
306 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
307 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
308
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
309 if (jid in jids) {
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
310 showImage(jid, res);
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
311 return;
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
312 }
|
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
313
|
3
|
314 getVCard(jid, res);
|
0
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
diff
changeset
|
315 }).listen(8032);
|