13234
|
1 /*
|
|
2 * Gaim's oscar protocol plugin
|
|
3 * This file is the legal property of its developers.
|
|
4 * Please see the AUTHORS file distributed alongside this file.
|
|
5 *
|
|
6 * This library is free software; you can redistribute it and/or
|
|
7 * modify it under the terms of the GNU Lesser General Public
|
|
8 * License as published by the Free Software Foundation; either
|
|
9 * version 2 of the License, or (at your option) any later version.
|
|
10 *
|
|
11 * This library is distributed in the hope that it will be useful,
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14 * Lesser General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU Lesser General Public
|
|
17 * License along with this library; if not, write to the Free Software
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19 */
|
|
20
|
|
21 /*
|
|
22 * Family 0x0001 - This is a very special group. All connections support
|
|
23 * this group, as it does some particularly good things (like rate limiting).
|
|
24 */
|
|
25
|
|
26 #include "oscar.h"
|
|
27
|
|
28 #include "cipher.h"
|
|
29
|
|
30 /* Subtype 0x0002 - Client Online */
|
13592
|
31 int
|
|
32 aim_clientready(OscarData *od, FlapConnection *conn)
|
13234
|
33 {
|
|
34 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
|
|
35 struct snacgroup *sg;
|
13592
|
36 FlapFrame *frame;
|
13234
|
37 aim_snacid_t snacid;
|
|
38
|
|
39 if (!ins)
|
|
40 return -EINVAL;
|
|
41
|
13592
|
42 frame = flap_frame_new(od, 0x02, 1152);
|
13234
|
43
|
13592
|
44 snacid = aim_cachesnac(od, 0x0001, 0x0002, 0x0000, NULL, 0);
|
|
45 aim_putsnac(&frame->data, 0x0001, 0x0002, 0x0000, snacid);
|
13234
|
46
|
|
47 /*
|
|
48 * Send only the tool versions that the server cares about (that it
|
|
49 * marked as supporting in the server ready SNAC).
|
|
50 */
|
|
51 for (sg = ins->groups; sg; sg = sg->next) {
|
|
52 aim_module_t *mod;
|
|
53
|
13592
|
54 if ((mod = aim__findmodulebygroup(od, sg->group))) {
|
|
55 byte_stream_put16(&frame->data, mod->family);
|
|
56 byte_stream_put16(&frame->data, mod->version);
|
|
57 byte_stream_put16(&frame->data, mod->toolid);
|
|
58 byte_stream_put16(&frame->data, mod->toolversion);
|
13234
|
59 } else
|
|
60 gaim_debug_misc("oscar", "aim_clientready: server supports group 0x%04x but we don't!\n", sg->group);
|
|
61 }
|
|
62
|
13592
|
63 flap_connection_send(conn, frame);
|
13234
|
64
|
|
65 return 0;
|
|
66 }
|
|
67
|
|
68 /*
|
|
69 * Subtype 0x0003 - Host Online
|
|
70 *
|
|
71 * See comments in conn.c about how the group associations are supposed
|
|
72 * to work, and how they really work.
|
|
73 *
|
|
74 * This info probably doesn't even need to make it to the client.
|
|
75 *
|
|
76 * We don't actually call the client here. This starts off the connection
|
|
77 * initialization routine required by all AIM connections. The next time
|
|
78 * the client is called is the CONNINITDONE callback, which should be
|
|
79 * shortly after the rate information is acknowledged.
|
|
80 *
|
|
81 */
|
13592
|
82 static int
|
|
83 hostonline(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
84 {
|
|
85 guint16 *families;
|
|
86 int famcount;
|
|
87
|
|
88
|
13592
|
89 families = malloc(byte_stream_empty(bs));
|
13234
|
90
|
13592
|
91 for (famcount = 0; byte_stream_empty(bs); famcount++) {
|
|
92 families[famcount] = byte_stream_get16(bs);
|
|
93 flap_connection_addgroup(conn, families[famcount]);
|
13234
|
94 }
|
|
95
|
|
96 free(families);
|
|
97
|
|
98
|
|
99 /*
|
|
100 * Next step is in the Host Versions handler.
|
|
101 *
|
|
102 * Note that we must send this before we request rates, since
|
|
103 * the format of the rate information depends on the versions we
|
|
104 * give it.
|
|
105 *
|
|
106 */
|
13592
|
107 aim_setversions(od, conn);
|
13234
|
108
|
|
109 return 1;
|
|
110 }
|
|
111
|
|
112 /* Subtype 0x0004 - Service request */
|
13592
|
113 int aim_reqservice(OscarData *od, guint16 serviceid)
|
13234
|
114 {
|
13592
|
115 FlapConnection *conn;
|
|
116
|
|
117 conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
|
|
118
|
|
119 return aim_genericreq_s(od, conn, 0x0001, 0x0004, &serviceid);
|
13234
|
120 }
|
|
121
|
|
122 /*
|
13592
|
123 * Join a room of name roomname. This is the first step to joining an
|
|
124 * already created room. It's basically a Service Request for
|
|
125 * family 0x000e, with a little added on to specify the exchange and room
|
13234
|
126 * name.
|
|
127 */
|
13592
|
128 int
|
|
129 aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance)
|
13234
|
130 {
|
13592
|
131 FlapConnection *conn;
|
|
132 FlapFrame *frame;
|
13234
|
133 aim_snacid_t snacid;
|
|
134 aim_tlvlist_t *tl = NULL;
|
|
135 struct chatsnacinfo csi;
|
|
136
|
13592
|
137 conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
|
|
138 if (!od || !conn || !roomname || !strlen(roomname))
|
13234
|
139 return -EINVAL;
|
|
140
|
13592
|
141 frame = flap_frame_new(od, 0x02, 512);
|
13234
|
142
|
|
143 memset(&csi, 0, sizeof(csi));
|
|
144 csi.exchange = exchange;
|
|
145 strncpy(csi.name, roomname, sizeof(csi.name));
|
|
146 csi.instance = instance;
|
|
147
|
13592
|
148 snacid = aim_cachesnac(od, 0x0001, 0x0004, 0x0000, &csi, sizeof(csi));
|
|
149 aim_putsnac(&frame->data, 0x0001, 0x0004, 0x0000, snacid);
|
13234
|
150
|
|
151 /*
|
|
152 * Requesting service chat (0x000e)
|
|
153 */
|
13592
|
154 byte_stream_put16(&frame->data, 0x000e);
|
13234
|
155
|
|
156 aim_tlvlist_add_chatroom(&tl, 0x0001, exchange, roomname, instance);
|
13592
|
157 aim_tlvlist_write(&frame->data, &tl);
|
13234
|
158 aim_tlvlist_free(&tl);
|
|
159
|
13592
|
160 flap_connection_send(conn, frame);
|
13234
|
161
|
|
162 return 0;
|
|
163 }
|
|
164
|
|
165 /* Subtype 0x0005 - Redirect */
|
13592
|
166 static int
|
|
167 redirect(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
168 {
|
|
169 struct aim_redirect_data redir;
|
|
170 aim_rxcallback_t userfunc;
|
|
171 aim_tlvlist_t *tlvlist;
|
|
172 aim_snac_t *origsnac = NULL;
|
|
173 int ret = 0;
|
|
174
|
|
175 memset(&redir, 0, sizeof(redir));
|
|
176
|
|
177 tlvlist = aim_tlvlist_read(bs);
|
|
178
|
|
179 if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
|
|
180 !aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
|
|
181 !aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
|
|
182 aim_tlvlist_free(&tlvlist);
|
|
183 return 0;
|
|
184 }
|
|
185
|
|
186 redir.group = aim_tlv_get16(tlvlist, 0x000d, 1);
|
|
187 redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
|
|
188 redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length;
|
|
189 redir.cookie = (guchar *)aim_tlv_getstr(tlvlist, 0x0006, 1);
|
|
190
|
|
191 /* Fetch original SNAC so we can get csi if needed */
|
13592
|
192 origsnac = aim_remsnac(od, snac->id);
|
13234
|
193
|
13592
|
194 if ((redir.group == SNAC_FAMILY_CHAT) && origsnac) {
|
13234
|
195 struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data;
|
|
196
|
|
197 redir.chat.exchange = csi->exchange;
|
|
198 redir.chat.room = csi->name;
|
|
199 redir.chat.instance = csi->instance;
|
|
200 }
|
|
201
|
13592
|
202 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
203 ret = userfunc(od, conn, frame, &redir);
|
13234
|
204
|
|
205 free((void *)redir.ip);
|
|
206 free((void *)redir.cookie);
|
|
207
|
|
208 if (origsnac)
|
|
209 free(origsnac->data);
|
|
210 free(origsnac);
|
|
211
|
|
212 aim_tlvlist_free(&tlvlist);
|
|
213
|
|
214 return ret;
|
|
215 }
|
|
216
|
|
217 /* Subtype 0x0006 - Request Rate Information. */
|
13592
|
218 int
|
|
219 aim_reqrates(OscarData *od, FlapConnection *conn)
|
13234
|
220 {
|
13592
|
221 return aim_genericreq_n_snacid(od, conn, 0x0001, 0x0006);
|
13234
|
222 }
|
|
223
|
|
224 /*
|
|
225 * OSCAR defines several 'rate classes'. Each class has separate
|
|
226 * rate limiting properties (limit level, alert level, disconnect
|
|
227 * level, etc), and a set of SNAC family/type pairs associated with
|
|
228 * it. The rate classes, their limiting properties, and the definitions
|
|
229 * of which SNACs are belong to which class, are defined in the
|
13592
|
230 * Rate Response packet at login to each host.
|
13234
|
231 *
|
|
232 * Logically, all rate offenses within one class count against further
|
|
233 * offenses for other SNACs in the same class (ie, sending messages
|
|
234 * too fast will limit the number of user info requests you can send,
|
|
235 * since those two SNACs are in the same rate class).
|
|
236 *
|
|
237 * Since the rate classes are defined dynamically at login, the values
|
|
238 * below may change. But they seem to be fairly constant.
|
|
239 *
|
|
240 * Currently, BOS defines five rate classes, with the commonly used
|
|
241 * members as follows...
|
|
242 *
|
|
243 * Rate class 0x0001:
|
13592
|
244 * - Everything thats not in any of the other classes
|
13234
|
245 *
|
|
246 * Rate class 0x0002:
|
13592
|
247 * - Buddy list add/remove
|
13234
|
248 * - Permit list add/remove
|
|
249 * - Deny list add/remove
|
|
250 *
|
|
251 * Rate class 0x0003:
|
|
252 * - User information requests
|
|
253 * - Outgoing ICBMs
|
|
254 *
|
|
255 * Rate class 0x0004:
|
|
256 * - A few unknowns: 2/9, 2/b, and f/2
|
|
257 *
|
|
258 * Rate class 0x0005:
|
|
259 * - Chat room create
|
|
260 * - Outgoing chat ICBMs
|
|
261 *
|
|
262 * The only other thing of note is that class 5 (chat) has slightly looser
|
13592
|
263 * limiting properties than class 3 (normal messages). But thats just a
|
13234
|
264 * small bit of trivia for you.
|
|
265 *
|
|
266 * The last thing that needs to be learned about the rate limiting
|
|
267 * system is how the actual numbers relate to the passing of time. This
|
|
268 * seems to be a big mystery.
|
13592
|
269 *
|
13234
|
270 */
|
|
271
|
13592
|
272 static void
|
|
273 rc_addclass(struct rateclass **head, struct rateclass *inrc)
|
13234
|
274 {
|
|
275 struct rateclass *rc, *rc2;
|
|
276
|
13592
|
277 rc = g_memdup(inrc, sizeof(struct rateclass));
|
13234
|
278 rc->next = NULL;
|
|
279
|
|
280 for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next)
|
|
281 ;
|
|
282
|
|
283 if (!rc2)
|
|
284 *head = rc;
|
|
285 else
|
|
286 rc2->next = rc;
|
|
287
|
|
288 return;
|
|
289 }
|
|
290
|
13592
|
291 static struct rateclass *
|
|
292 rc_findclass(struct rateclass **head, guint16 id)
|
13234
|
293 {
|
|
294 struct rateclass *rc;
|
|
295
|
|
296 for (rc = *head; rc; rc = rc->next) {
|
|
297 if (rc->classid == id)
|
|
298 return rc;
|
|
299 }
|
|
300
|
|
301 return NULL;
|
|
302 }
|
|
303
|
13592
|
304 static void
|
|
305 rc_addpair(struct rateclass *rc, guint16 group, guint16 type)
|
13234
|
306 {
|
|
307 struct snacpair *sp, *sp2;
|
|
308
|
13592
|
309 sp = g_new0(struct snacpair, 1);
|
13234
|
310 sp->group = group;
|
|
311 sp->subtype = type;
|
|
312 sp->next = NULL;
|
|
313
|
|
314 for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next)
|
|
315 ;
|
|
316
|
|
317 if (!sp2)
|
|
318 rc->members = sp;
|
|
319 else
|
|
320 sp2->next = sp;
|
|
321
|
|
322 return;
|
|
323 }
|
|
324
|
|
325 /* Subtype 0x0007 - Rate Parameters */
|
13592
|
326 static int
|
|
327 rateresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
328 {
|
13592
|
329 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
|
13234
|
330 guint16 numclasses, i;
|
|
331 aim_rxcallback_t userfunc;
|
|
332
|
|
333
|
|
334 /*
|
|
335 * First are the parameters for each rate class.
|
|
336 */
|
13592
|
337 numclasses = byte_stream_get16(bs);
|
13234
|
338 for (i = 0; i < numclasses; i++) {
|
|
339 struct rateclass rc;
|
|
340
|
|
341 memset(&rc, 0, sizeof(struct rateclass));
|
|
342
|
13592
|
343 rc.classid = byte_stream_get16(bs);
|
|
344 rc.windowsize = byte_stream_get32(bs);
|
|
345 rc.clear = byte_stream_get32(bs);
|
|
346 rc.alert = byte_stream_get32(bs);
|
|
347 rc.limit = byte_stream_get32(bs);
|
|
348 rc.disconnect = byte_stream_get32(bs);
|
|
349 rc.current = byte_stream_get32(bs);
|
|
350 rc.max = byte_stream_get32(bs);
|
13234
|
351
|
|
352 /*
|
|
353 * The server will send an extra five bytes of parameters
|
|
354 * depending on the version we advertised in 1/17. If we
|
|
355 * didn't send 1/17 (evil!), then this will crash and you
|
13592
|
356 * die, as it will default to the old version but we have
|
|
357 * the new version hardcoded here.
|
13234
|
358 */
|
|
359 if (mod->version >= 3)
|
13592
|
360 byte_stream_getrawbuf(bs, rc.unknown, sizeof(rc.unknown));
|
13234
|
361
|
|
362 rc_addclass(&ins->rates, &rc);
|
|
363 }
|
|
364
|
|
365 /*
|
|
366 * Then the members of each class.
|
|
367 */
|
|
368 for (i = 0; i < numclasses; i++) {
|
|
369 guint16 classid, count;
|
|
370 struct rateclass *rc;
|
|
371 int j;
|
|
372
|
13592
|
373 classid = byte_stream_get16(bs);
|
|
374 count = byte_stream_get16(bs);
|
13234
|
375
|
|
376 rc = rc_findclass(&ins->rates, classid);
|
|
377
|
|
378 for (j = 0; j < count; j++) {
|
|
379 guint16 group, subtype;
|
|
380
|
13592
|
381 group = byte_stream_get16(bs);
|
|
382 subtype = byte_stream_get16(bs);
|
13234
|
383
|
|
384 if (rc)
|
|
385 rc_addpair(rc, group, subtype);
|
|
386 }
|
|
387 }
|
|
388
|
|
389 /*
|
|
390 * We don't pass the rate information up to the client, as it really
|
|
391 * doesn't care. The information is stored in the connection, however
|
|
392 * so that we can do more fun stuff later (not really).
|
|
393 */
|
|
394
|
|
395 /*
|
|
396 * Last step in the conn init procedure is to acknowledge that we
|
|
397 * agree to these draconian limitations.
|
|
398 */
|
13592
|
399 aim_rates_addparam(od, conn);
|
13234
|
400
|
|
401 /*
|
|
402 * Finally, tell the client it's ready to go...
|
|
403 */
|
13592
|
404 if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE)))
|
|
405 userfunc(od, conn, frame);
|
13234
|
406
|
|
407
|
|
408 return 1;
|
|
409 }
|
|
410
|
|
411 /* Subtype 0x0008 - Add Rate Parameter */
|
13592
|
412 int
|
|
413 aim_rates_addparam(OscarData *od, FlapConnection *conn)
|
13234
|
414 {
|
|
415 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
|
13592
|
416 FlapFrame *frame;
|
13234
|
417 aim_snacid_t snacid;
|
|
418 struct rateclass *rc;
|
|
419
|
13592
|
420 frame = flap_frame_new(od, 0x02, 512);
|
13234
|
421
|
13592
|
422 snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0);
|
|
423 aim_putsnac(&frame->data, 0x0001, 0x0008, 0x0000, snacid);
|
13234
|
424
|
|
425 for (rc = ins->rates; rc; rc = rc->next)
|
13592
|
426 byte_stream_put16(&frame->data, rc->classid);
|
13234
|
427
|
13592
|
428 flap_connection_send(conn, frame);
|
13234
|
429
|
|
430 return 0;
|
|
431 }
|
|
432
|
|
433 /* Subtype 0x0009 - Delete Rate Parameter */
|
13592
|
434 int
|
|
435 aim_rates_delparam(OscarData *od, FlapConnection *conn)
|
13234
|
436 {
|
|
437 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
|
13592
|
438 FlapFrame *frame;
|
13234
|
439 aim_snacid_t snacid;
|
|
440 struct rateclass *rc;
|
|
441
|
13592
|
442 frame = flap_frame_new(od, 0x02, 512);
|
13234
|
443
|
13592
|
444 snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0);
|
|
445 aim_putsnac(&frame->data, 0x0001, 0x0009, 0x0000, snacid);
|
13234
|
446
|
|
447 for (rc = ins->rates; rc; rc = rc->next)
|
13592
|
448 byte_stream_put16(&frame->data, rc->classid);
|
13234
|
449
|
13592
|
450 flap_connection_send(conn, frame);
|
13234
|
451
|
|
452 return 0;
|
|
453 }
|
|
454
|
|
455 /* Subtype 0x000a - Rate Change */
|
13592
|
456 static int
|
|
457 ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
458 {
|
|
459 int ret = 0;
|
|
460 aim_rxcallback_t userfunc;
|
|
461 guint16 code, rateclass;
|
|
462 guint32 currentavg, maxavg, windowsize, clear, alert, limit, disconnect;
|
|
463
|
13592
|
464 code = byte_stream_get16(bs);
|
|
465 rateclass = byte_stream_get16(bs);
|
13234
|
466
|
13592
|
467 windowsize = byte_stream_get32(bs);
|
|
468 clear = byte_stream_get32(bs);
|
|
469 alert = byte_stream_get32(bs);
|
|
470 limit = byte_stream_get32(bs);
|
|
471 disconnect = byte_stream_get32(bs);
|
|
472 currentavg = byte_stream_get32(bs);
|
|
473 maxavg = byte_stream_get32(bs);
|
13234
|
474
|
13592
|
475 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
476 ret = userfunc(od, conn, frame, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg);
|
13234
|
477
|
|
478 return ret;
|
|
479 }
|
|
480
|
|
481 /*
|
|
482 * How Migrations work.
|
|
483 *
|
13592
|
484 * The server sends a Server Pause message, which the client should respond to
|
|
485 * with a Server Pause Ack, which contains the families it needs on this
|
|
486 * connection. The server will send a Migration Notice with an IP address, and
|
|
487 * then disconnect. Next the client should open the connection and send the
|
13234
|
488 * cookie. Repeat the normal login process and pretend this never happened.
|
|
489 *
|
|
490 * The Server Pause contains no data.
|
|
491 *
|
|
492 */
|
|
493
|
|
494 /* Subtype 0x000b - Service Pause */
|
13592
|
495 static int
|
|
496 serverpause(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
497 {
|
|
498 int ret = 0;
|
|
499 aim_rxcallback_t userfunc;
|
|
500
|
13592
|
501 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
502 ret = userfunc(od, conn, frame);
|
13234
|
503
|
|
504 return ret;
|
|
505 }
|
|
506
|
|
507 /*
|
|
508 * Subtype 0x000c - Service Pause Acknowledgement
|
|
509 *
|
|
510 * It is rather important that aim_sendpauseack() gets called for the exact
|
|
511 * same connection that the Server Pause callback was called for, since
|
|
512 * libfaim extracts the data for the SNAC from the connection structure.
|
|
513 *
|
|
514 * Of course, if you don't do that, more bad things happen than just what
|
|
515 * libfaim can cause.
|
|
516 *
|
|
517 */
|
13592
|
518 int
|
|
519 aim_sendpauseack(OscarData *od, FlapConnection *conn)
|
13234
|
520 {
|
13592
|
521 FlapFrame *frame;
|
13234
|
522 aim_snacid_t snacid;
|
|
523 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
|
|
524 struct snacgroup *sg;
|
|
525
|
13592
|
526 frame = flap_frame_new(od, 0x02, 1024);
|
13234
|
527
|
13592
|
528 snacid = aim_cachesnac(od, 0x0001, 0x000c, 0x0000, NULL, 0);
|
|
529 aim_putsnac(&frame->data, 0x0001, 0x000c, 0x0000, snacid);
|
13234
|
530
|
|
531 /*
|
13592
|
532 * This list should have all the groups that the original
|
|
533 * Host Online / Server Ready said this host supports. And
|
13234
|
534 * we want them all back after the migration.
|
|
535 */
|
|
536 for (sg = ins->groups; sg; sg = sg->next)
|
13592
|
537 byte_stream_put16(&frame->data, sg->group);
|
13234
|
538
|
13592
|
539 flap_connection_send(conn, frame);
|
13234
|
540
|
|
541 return 0;
|
|
542 }
|
|
543
|
|
544 /* Subtype 0x000d - Service Resume */
|
13592
|
545 static int
|
|
546 serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
547 {
|
|
548 int ret = 0;
|
|
549 aim_rxcallback_t userfunc;
|
|
550
|
13592
|
551 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
552 ret = userfunc(od, conn, frame);
|
13234
|
553
|
|
554 return ret;
|
|
555 }
|
|
556
|
|
557 /* Subtype 0x000e - Request self-info */
|
13592
|
558 int
|
|
559 aim_reqpersonalinfo(OscarData *od, FlapConnection *conn)
|
13234
|
560 {
|
13592
|
561 return aim_genericreq_n_snacid(od, conn, 0x0001, 0x000e);
|
13234
|
562 }
|
|
563
|
|
564 /* Subtype 0x000f - Self User Info */
|
13592
|
565 static int
|
|
566 selfinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
567 {
|
|
568 int ret = 0;
|
|
569 aim_rxcallback_t userfunc;
|
|
570 aim_userinfo_t userinfo;
|
|
571
|
13592
|
572 aim_info_extract(od, bs, &userinfo);
|
13234
|
573
|
13592
|
574 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
575 ret = userfunc(od, conn, frame, &userinfo);
|
13234
|
576
|
|
577 aim_info_free(&userinfo);
|
|
578
|
|
579 return ret;
|
|
580 }
|
|
581
|
|
582 /* Subtype 0x0010 - Evil Notification */
|
13592
|
583 static int
|
|
584 evilnotify(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
585 {
|
|
586 int ret = 0;
|
|
587 aim_rxcallback_t userfunc;
|
|
588 guint16 newevil;
|
|
589 aim_userinfo_t userinfo;
|
|
590
|
|
591 memset(&userinfo, 0, sizeof(aim_userinfo_t));
|
|
592
|
13592
|
593 newevil = byte_stream_get16(bs);
|
13234
|
594
|
13592
|
595 if (byte_stream_empty(bs))
|
|
596 aim_info_extract(od, bs, &userinfo);
|
13234
|
597
|
13592
|
598 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
599 ret = userfunc(od, conn, frame, newevil, &userinfo);
|
13234
|
600
|
|
601 aim_info_free(&userinfo);
|
|
602
|
|
603 return ret;
|
|
604 }
|
|
605
|
|
606 /*
|
|
607 * Subtype 0x0011 - Idle Notification
|
|
608 *
|
|
609 * Should set your current idle time in seconds. Note that this should
|
|
610 * never be called consecutively with a non-zero idle time. That makes
|
|
611 * OSCAR do funny things. Instead, just set it once you go idle, and then
|
|
612 * call it again with zero when you're back.
|
|
613 *
|
|
614 */
|
13592
|
615 int
|
|
616 aim_srv_setidle(OscarData *od, guint32 idletime)
|
13234
|
617 {
|
13592
|
618 FlapConnection *conn;
|
13234
|
619
|
13592
|
620 if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS)))
|
13234
|
621 return -EINVAL;
|
|
622
|
13592
|
623 return aim_genericreq_l(od, conn, 0x0001, 0x0011, &idletime);
|
13234
|
624 }
|
|
625
|
|
626 /*
|
|
627 * Subtype 0x0012 - Service Migrate
|
|
628 *
|
|
629 * This is the final SNAC sent on the original connection during a migration.
|
13592
|
630 * It contains the IP and cookie used to connect to the new server, and
|
13234
|
631 * optionally a list of the SNAC groups being migrated.
|
|
632 *
|
|
633 */
|
13592
|
634 static int
|
|
635 migrate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
636 {
|
|
637 aim_rxcallback_t userfunc;
|
|
638 int ret = 0;
|
|
639 guint16 groupcount, i;
|
|
640 aim_tlvlist_t *tl;
|
|
641 char *ip = NULL;
|
|
642 aim_tlv_t *cktlv;
|
|
643
|
|
644 /*
|
|
645 * Apparently there's some fun stuff that can happen right here. The
|
|
646 * migration can actually be quite selective about what groups it
|
|
647 * moves to the new server. When not all the groups for a connection
|
|
648 * are migrated, or they are all migrated but some groups are moved
|
13592
|
649 * to a different server than others, it is called a bifurcated
|
13234
|
650 * migration.
|
|
651 *
|
|
652 * Let's play dumb and not support that.
|
|
653 *
|
|
654 */
|
13592
|
655 groupcount = byte_stream_get16(bs);
|
13234
|
656 for (i = 0; i < groupcount; i++) {
|
|
657 guint16 group;
|
|
658
|
13592
|
659 group = byte_stream_get16(bs);
|
13234
|
660
|
|
661 gaim_debug_misc("oscar", "bifurcated migration unsupported -- group 0x%04x\n", group);
|
|
662 }
|
|
663
|
|
664 tl = aim_tlvlist_read(bs);
|
|
665
|
|
666 if (aim_tlv_gettlv(tl, 0x0005, 1))
|
|
667 ip = aim_tlv_getstr(tl, 0x0005, 1);
|
|
668
|
|
669 cktlv = aim_tlv_gettlv(tl, 0x0006, 1);
|
|
670
|
13592
|
671 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
672 ret = userfunc(od, conn, frame, ip, cktlv ? cktlv->value : NULL);
|
13234
|
673
|
|
674 aim_tlvlist_free(&tl);
|
|
675 free(ip);
|
|
676
|
|
677 return ret;
|
|
678 }
|
|
679
|
|
680 /* Subtype 0x0013 - Message of the Day */
|
13592
|
681 static int
|
|
682 motd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
683 {
|
|
684 aim_rxcallback_t userfunc;
|
|
685 char *msg = NULL;
|
|
686 int ret = 0;
|
|
687 aim_tlvlist_t *tlvlist;
|
|
688 guint16 id;
|
|
689
|
|
690 /*
|
|
691 * Code.
|
|
692 *
|
|
693 * Valid values:
|
|
694 * 1 Mandatory upgrade
|
|
695 * 2 Advisory upgrade
|
|
696 * 3 System bulletin
|
|
697 * 4 Nothing's wrong ("top o the world" -- normal)
|
13592
|
698 * 5 Lets-break-something.
|
13234
|
699 *
|
|
700 */
|
13592
|
701 id = byte_stream_get16(bs);
|
13234
|
702
|
13592
|
703 /*
|
|
704 * TLVs follow
|
13234
|
705 */
|
|
706 tlvlist = aim_tlvlist_read(bs);
|
|
707
|
|
708 msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
|
|
709
|
13592
|
710 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
711 ret = userfunc(od, conn, frame, id, msg);
|
13234
|
712
|
|
713 free(msg);
|
|
714
|
|
715 aim_tlvlist_free(&tlvlist);
|
|
716
|
|
717 return ret;
|
|
718 }
|
|
719
|
13592
|
720 /*
|
13234
|
721 * Subtype 0x0014 - Set privacy flags
|
|
722 *
|
|
723 * Normally 0x03.
|
|
724 *
|
|
725 * Bit 1: Allows other AIM users to see how long you've been idle.
|
|
726 * Bit 2: Allows other AIM users to see how long you've been a member.
|
|
727 *
|
|
728 */
|
13592
|
729 int
|
|
730 aim_bos_setprivacyflags(OscarData *od, FlapConnection *conn, guint32 flags)
|
13234
|
731 {
|
13592
|
732 return aim_genericreq_l(od, conn, 0x0001, 0x0014, &flags);
|
13234
|
733 }
|
|
734
|
|
735 /*
|
|
736 * Subtype 0x0016 - No-op
|
|
737 *
|
13592
|
738 * WinAIM sends these every 4min or so to keep the connection alive. Its not
|
13234
|
739 * really necessary.
|
|
740 *
|
13592
|
741 * Wha? No? Since when? I think WinAIM sends an empty channel 5
|
|
742 * FLAP as a no-op...
|
13234
|
743 */
|
13592
|
744 int
|
|
745 aim_nop(OscarData *od, FlapConnection *conn)
|
13234
|
746 {
|
13592
|
747 return aim_genericreq_n(od, conn, 0x0001, 0x0016);
|
13234
|
748 }
|
|
749
|
13592
|
750 /*
|
13234
|
751 * Subtype 0x0017 - Set client versions
|
|
752 *
|
13592
|
753 * If you've seen the clientonline/clientready SNAC you're probably
|
13234
|
754 * wondering what the point of this one is. And that point seems to be
|
|
755 * that the versions in the client online SNAC are sent too late for the
|
|
756 * server to be able to use them to change the protocol for the earlier
|
13592
|
757 * login packets (client versions are sent right after Host Online is
|
13234
|
758 * received, but client online versions aren't sent until quite a bit later).
|
|
759 * We can see them already making use of this by changing the format of
|
|
760 * the rate information based on what version of group 1 we advertise here.
|
|
761 *
|
|
762 */
|
13592
|
763 int
|
|
764 aim_setversions(OscarData *od, FlapConnection *conn)
|
13234
|
765 {
|
|
766 aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside;
|
|
767 struct snacgroup *sg;
|
13592
|
768 FlapFrame *frame;
|
13234
|
769 aim_snacid_t snacid;
|
|
770
|
|
771 if (!ins)
|
|
772 return -EINVAL;
|
|
773
|
13592
|
774 frame = flap_frame_new(od, 0x02, 1152);
|
13234
|
775
|
13592
|
776 snacid = aim_cachesnac(od, 0x0001, 0x0017, 0x0000, NULL, 0);
|
|
777 aim_putsnac(&frame->data, 0x0001, 0x0017, 0x0000, snacid);
|
13234
|
778
|
|
779 /*
|
|
780 * Send only the versions that the server cares about (that it
|
13592
|
781 * marked as supporting in the server ready SNAC).
|
13234
|
782 */
|
|
783 for (sg = ins->groups; sg; sg = sg->next) {
|
|
784 aim_module_t *mod;
|
|
785
|
13592
|
786 if ((mod = aim__findmodulebygroup(od, sg->group))) {
|
|
787 byte_stream_put16(&frame->data, mod->family);
|
|
788 byte_stream_put16(&frame->data, mod->version);
|
13234
|
789 } else
|
|
790 gaim_debug_misc("oscar", "aim_setversions: server supports group 0x%04x but we don't!\n", sg->group);
|
|
791 }
|
|
792
|
13592
|
793 flap_connection_send(conn, frame);
|
13234
|
794
|
|
795 return 0;
|
|
796 }
|
|
797
|
|
798 /* Subtype 0x0018 - Host versions */
|
13592
|
799 static int
|
|
800 hostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
801 {
|
|
802 int vercount;
|
|
803 guint8 *versions;
|
|
804
|
|
805 /* This is frivolous. (Thank you SmarterChild.) */
|
13592
|
806 vercount = byte_stream_empty(bs)/4;
|
|
807 versions = byte_stream_getraw(bs, byte_stream_empty(bs));
|
13234
|
808 free(versions);
|
|
809
|
|
810 /*
|
|
811 * Now request rates.
|
|
812 */
|
13592
|
813 aim_reqrates(od, conn);
|
13234
|
814
|
|
815 return 1;
|
|
816 }
|
|
817
|
13592
|
818 /*
|
13234
|
819 * Subtype 0x001e - Set various account settings (mostly ICQ related).
|
|
820 *
|
|
821 * These settings are transient, not server-stored (i.e. they only
|
|
822 * apply to this session, and must be re-set the next time you sign
|
|
823 * on).
|
|
824 *
|
|
825 * You can set your ICQ status (available, away, do not disturb,
|
|
826 * etc.), or whether your IP address should be hidden or not, or
|
|
827 * if your status is visible on ICQ web sites, and you can set
|
|
828 * your IP address info and what not.
|
|
829 *
|
|
830 * These are the same TLVs seen in user info. You can
|
|
831 * also set 0x0008 and 0x000c.
|
|
832 */
|
13592
|
833 int
|
|
834 aim_setextstatus(OscarData *od, guint32 status)
|
13234
|
835 {
|
13592
|
836 FlapConnection *conn;
|
|
837 FlapFrame *frame;
|
13234
|
838 aim_snacid_t snacid;
|
|
839 aim_tlvlist_t *tl = NULL;
|
|
840 guint32 data;
|
|
841
|
13592
|
842 if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
|
13234
|
843 return -EINVAL;
|
|
844
|
|
845 data = AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH | status;
|
|
846
|
13592
|
847 frame = flap_frame_new(od, 0x02, 10 + 8);
|
13234
|
848
|
13592
|
849 snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
|
|
850 aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid);
|
13234
|
851
|
|
852 aim_tlvlist_add_32(&tl, 0x0006, data);
|
|
853 #if 0
|
|
854 aim_tlvlist_add_raw(&tl, 0x000c, 0x0025, chunk_of_x25_bytes_with_ip_address_etc);
|
|
855 aim_tlvlist_add_raw(&tl, 0x0011, 0x0005, unknown 0x01 61 10 f6 41);
|
|
856 aim_tlvlist_add_16(&tl, 0x0012, unknown 0x00 00);
|
|
857 #endif
|
13592
|
858 aim_tlvlist_write(&frame->data, &tl);
|
13234
|
859 aim_tlvlist_free(&tl);
|
|
860
|
13592
|
861 flap_connection_send(conn, frame);
|
13234
|
862
|
|
863 return 0;
|
|
864 }
|
|
865
|
|
866 /*
|
|
867 * Subtype 0x001e - Extended Status.
|
|
868 *
|
|
869 * Sets your "available" message. This is currently only supported by iChat
|
|
870 * and Gaim.
|
|
871 *
|
|
872 * These are the same TLVs seen in user info. You can
|
|
873 * also set 0x0008 and 0x000c.
|
|
874 */
|
13592
|
875 int
|
|
876 aim_srv_setstatusmsg(OscarData *od, const char *msg)
|
13234
|
877 {
|
13592
|
878 FlapConnection *conn;
|
|
879 FlapFrame *frame;
|
13234
|
880 aim_snacid_t snacid;
|
|
881
|
13592
|
882 if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
|
13234
|
883 return -EINVAL;
|
|
884
|
|
885 if ((msg != NULL) && *msg != '\0') {
|
13592
|
886 frame = flap_frame_new(od, 0x02, 10 + 4 + strlen(msg) + 8);
|
13234
|
887
|
13592
|
888 snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
|
|
889 aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid);
|
13234
|
890
|
13592
|
891 byte_stream_put16(&frame->data, 0x001d); /* userinfo TLV type */
|
|
892 byte_stream_put16(&frame->data, strlen(msg)+8); /* total length of userinfo TLV data */
|
|
893 byte_stream_put16(&frame->data, 0x0002);
|
|
894 byte_stream_put8(&frame->data, 0x04);
|
|
895 byte_stream_put8(&frame->data, strlen(msg)+4);
|
|
896 byte_stream_put16(&frame->data, strlen(msg));
|
|
897 byte_stream_putstr(&frame->data, msg);
|
|
898 byte_stream_put16(&frame->data, 0x0000);
|
13234
|
899 } else {
|
13592
|
900 frame = flap_frame_new(od, 0x02, 10 + 4 + 8);
|
13234
|
901
|
13592
|
902 snacid = aim_cachesnac(od, 0x0001, 0x001e, 0x0000, NULL, 0);
|
|
903 aim_putsnac(&frame->data, 0x0001, 0x001e, 0x0000, snacid);
|
13234
|
904
|
13592
|
905 byte_stream_put16(&frame->data, 0x001d);
|
|
906 byte_stream_put16(&frame->data, 0x0008);
|
|
907 byte_stream_put16(&frame->data, 0x0002);
|
|
908 byte_stream_put16(&frame->data, 0x0404);
|
|
909 byte_stream_put16(&frame->data, 0x0000);
|
|
910 byte_stream_put16(&frame->data, 0x0000);
|
13234
|
911 }
|
|
912
|
13592
|
913 flap_connection_send(conn, frame);
|
13234
|
914
|
|
915 return 0;
|
|
916 }
|
|
917
|
|
918 /*
|
|
919 * Starting this past week (26 Mar 2001, say), AOL has started sending
|
|
920 * this nice little extra SNAC. AFAIK, it has never been used until now.
|
|
921 *
|
|
922 * The request contains eight bytes. The first four are an offset, the
|
|
923 * second four are a length.
|
|
924 *
|
|
925 * The offset is an offset into aim.exe when it is mapped during execution
|
|
926 * on Win32. So far, AOL has only been requesting bytes in static regions
|
|
927 * of memory. (I won't put it past them to start requesting data in
|
|
928 * less static regions -- regions that are initialized at run time, but still
|
|
929 * before the client receives this request.)
|
|
930 *
|
|
931 * When the client receives the request, it adds it to the current ds
|
|
932 * (0x00400000) and dereferences it, copying the data into a buffer which
|
|
933 * it then runs directly through the MD5 hasher. The 16 byte output of
|
|
934 * the hash is then sent back to the server.
|
|
935 *
|
|
936 * If the client does not send any data back, or the data does not match
|
|
937 * the data that the specific client should have, the client will get the
|
|
938 * following message from "AOL Instant Messenger":
|
13592
|
939 * "You have been disconnected from the AOL Instant Message Service (SM)
|
13234
|
940 * for accessing the AOL network using unauthorized software. You can
|
13592
|
941 * download a FREE, fully featured, and authorized client, here
|
13234
|
942 * http://www.aol.com/aim/download2.html"
|
|
943 * The connection is then closed, receiving disconnect code 1, URL
|
13592
|
944 * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.
|
13234
|
945 *
|
13592
|
946 * Note, however, that numerous inconsistencies can cause the above error,
|
13234
|
947 * not just sending back a bad hash. Do not immediatly suspect this code
|
|
948 * if you get disconnected. AOL and the open/free software community have
|
|
949 * played this game for a couple years now, generating the above message
|
|
950 * on numerous ocassions.
|
|
951 *
|
|
952 * Anyway, neener. We win again.
|
|
953 *
|
|
954 */
|
|
955 /* Subtype 0x001f - Client verification */
|
13592
|
956 static int
|
|
957 memrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
958 {
|
|
959 int ret = 0;
|
|
960 aim_rxcallback_t userfunc;
|
|
961 guint32 offset, len;
|
|
962 aim_tlvlist_t *list;
|
|
963 char *modname;
|
|
964
|
13592
|
965 offset = byte_stream_get32(bs);
|
|
966 len = byte_stream_get32(bs);
|
13234
|
967 list = aim_tlvlist_read(bs);
|
|
968
|
|
969 modname = aim_tlv_getstr(list, 0x0001, 1);
|
|
970
|
|
971 gaim_debug_info("oscar", "Got memory request for data at 0x%08lx (%d bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe");
|
|
972
|
13592
|
973 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
|
|
974 ret = userfunc(od, conn, frame, offset, len, modname);
|
13234
|
975
|
|
976 free(modname);
|
|
977 aim_tlvlist_free(&list);
|
|
978
|
|
979 return ret;
|
|
980 }
|
|
981
|
|
982 /* Subtype 0x0020 - Client verification reply */
|
13592
|
983 int
|
|
984 aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag)
|
13234
|
985 {
|
13592
|
986 FlapFrame *frame;
|
13234
|
987 aim_snacid_t snacid;
|
|
988
|
13592
|
989 if (!od || !conn)
|
13234
|
990 return -EINVAL;
|
|
991
|
13592
|
992 frame = flap_frame_new(od, 0x02, 10+2+16);
|
13234
|
993
|
13592
|
994 snacid = aim_cachesnac(od, 0x0001, 0x0020, 0x0000, NULL, 0);
|
13234
|
995
|
13592
|
996 aim_putsnac(&frame->data, 0x0001, 0x0020, 0x0000, snacid);
|
|
997 byte_stream_put16(&frame->data, 0x0010); /* md5 is always 16 bytes */
|
13234
|
998
|
|
999 if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */
|
|
1000
|
13592
|
1001 byte_stream_putraw(&frame->data, buf, 0x10);
|
13234
|
1002
|
|
1003 } else if (buf && (len > 0)) { /* use input buffer */
|
|
1004 GaimCipher *cipher;
|
|
1005 GaimCipherContext *context;
|
|
1006 guchar digest[16];
|
|
1007
|
|
1008 cipher = gaim_ciphers_find_cipher("md5");
|
|
1009
|
|
1010 context = gaim_cipher_context_new(cipher, NULL);
|
|
1011 gaim_cipher_context_append(context, buf, len);
|
|
1012 gaim_cipher_context_digest(context, 16, digest, NULL);
|
|
1013 gaim_cipher_context_destroy(context);
|
|
1014
|
13592
|
1015 byte_stream_putraw(&frame->data, digest, 0x10);
|
13234
|
1016
|
|
1017 } else if (len == 0) { /* no length, just hash NULL (buf is optional) */
|
|
1018 GaimCipher *cipher;
|
|
1019 GaimCipherContext *context;
|
|
1020 guchar digest[16];
|
|
1021 guint8 nil = '\0';
|
|
1022
|
|
1023 /*
|
|
1024 * I'm not sure if we really need the empty append with the
|
|
1025 * new MD5 functions, so I'll leave it in, just in case.
|
|
1026 */
|
|
1027 cipher = gaim_ciphers_find_cipher("md5");
|
|
1028
|
|
1029 context = gaim_cipher_context_new(cipher, NULL);
|
|
1030 gaim_cipher_context_append(context, &nil, 0);
|
|
1031 gaim_cipher_context_digest(context, 16, digest, NULL);
|
|
1032 gaim_cipher_context_destroy(context);
|
|
1033
|
13592
|
1034 byte_stream_putraw(&frame->data, digest, 0x10);
|
13234
|
1035
|
|
1036 } else {
|
|
1037
|
|
1038 /*
|
|
1039 * This data is correct for AIM 3.5.1670.
|
|
1040 *
|
|
1041 * Using these blocks is as close to "legal" as you can get
|
|
1042 * without using an AIM binary.
|
|
1043 *
|
|
1044 */
|
|
1045 if ((offset == 0x03ffffff) && (len == 0x03ffffff)) {
|
|
1046
|
|
1047 #if 1 /* with "AnrbnrAqhfzcd" */
|
13592
|
1048 byte_stream_put32(&frame->data, 0x44a95d26);
|
|
1049 byte_stream_put32(&frame->data, 0xd2490423);
|
|
1050 byte_stream_put32(&frame->data, 0x93b8821f);
|
|
1051 byte_stream_put32(&frame->data, 0x51c54b01);
|
13234
|
1052 #else /* no filename */
|
13592
|
1053 byte_stream_put32(&frame->data, 0x1df8cbae);
|
|
1054 byte_stream_put32(&frame->data, 0x5523b839);
|
|
1055 byte_stream_put32(&frame->data, 0xa0e10db3);
|
|
1056 byte_stream_put32(&frame->data, 0xa46d3b39);
|
13234
|
1057 #endif
|
|
1058
|
|
1059 } else if ((offset == 0x00001000) && (len == 0x00000000)) {
|
|
1060
|
13592
|
1061 byte_stream_put32(&frame->data, 0xd41d8cd9);
|
|
1062 byte_stream_put32(&frame->data, 0x8f00b204);
|
|
1063 byte_stream_put32(&frame->data, 0xe9800998);
|
|
1064 byte_stream_put32(&frame->data, 0xecf8427e);
|
13234
|
1065
|
|
1066 } else
|
|
1067 gaim_debug_warning("oscar", "sendmemblock: unknown hash request\n");
|
|
1068
|
|
1069 }
|
|
1070
|
13592
|
1071 flap_connection_send(conn, frame);
|
13234
|
1072
|
|
1073 return 0;
|
|
1074 }
|
|
1075
|
|
1076 /*
|
|
1077 * Subtype 0x0021 - Receive our extended status
|
|
1078 *
|
|
1079 * This is used for iChat's "available" messages, and maybe ICQ extended
|
|
1080 * status messages? It's also used to tell the client whether or not it
|
|
1081 * needs to upload an SSI buddy icon... who engineers this stuff, anyway?
|
|
1082 */
|
13592
|
1083 static int
|
|
1084 aim_parse_extstatus(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
1085 {
|
|
1086 int ret = 0;
|
|
1087 aim_rxcallback_t userfunc;
|
|
1088 guint16 type;
|
|
1089 guint8 flags, length;
|
|
1090
|
13592
|
1091 type = byte_stream_get16(bs);
|
|
1092 flags = byte_stream_get8(bs);
|
|
1093 length = byte_stream_get8(bs);
|
13234
|
1094
|
13592
|
1095 if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) {
|
13234
|
1096 switch (type) {
|
|
1097 case 0x0000:
|
|
1098 case 0x0001: { /* buddy icon checksum */
|
|
1099 /* not sure what the difference between 1 and 0 is */
|
13592
|
1100 guint8 *md5 = byte_stream_getraw(bs, length);
|
|
1101 ret = userfunc(od, conn, frame, type, flags, length, md5);
|
13234
|
1102 free(md5);
|
|
1103 } break;
|
|
1104 case 0x0002: { /* available message */
|
|
1105 /* there is a second length that is just for the message */
|
13592
|
1106 char *msg = byte_stream_getstr(bs, byte_stream_get16(bs));
|
|
1107 ret = userfunc(od, conn, frame, msg);
|
13234
|
1108 free(msg);
|
|
1109 } break;
|
|
1110 }
|
|
1111 }
|
|
1112
|
|
1113 return ret;
|
|
1114 }
|
|
1115
|
13592
|
1116 static int
|
|
1117 snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
|
13234
|
1118 {
|
|
1119 if (snac->subtype == 0x0003)
|
13592
|
1120 return hostonline(od, conn, mod, frame, snac, bs);
|
13234
|
1121 else if (snac->subtype == 0x0005)
|
13592
|
1122 return redirect(od, conn, mod, frame, snac, bs);
|
13234
|
1123 else if (snac->subtype == 0x0007)
|
13592
|
1124 return rateresp(od, conn, mod, frame, snac, bs);
|
13234
|
1125 else if (snac->subtype == 0x000a)
|
13592
|
1126 return ratechange(od, conn, mod, frame, snac, bs);
|
13234
|
1127 else if (snac->subtype == 0x000b)
|
13592
|
1128 return serverpause(od, conn, mod, frame, snac, bs);
|
13234
|
1129 else if (snac->subtype == 0x000d)
|
13592
|
1130 return serverresume(od, conn, mod, frame, snac, bs);
|
13234
|
1131 else if (snac->subtype == 0x000f)
|
13592
|
1132 return selfinfo(od, conn, mod, frame, snac, bs);
|
13234
|
1133 else if (snac->subtype == 0x0010)
|
13592
|
1134 return evilnotify(od, conn, mod, frame, snac, bs);
|
13234
|
1135 else if (snac->subtype == 0x0012)
|
13592
|
1136 return migrate(od, conn, mod, frame, snac, bs);
|
13234
|
1137 else if (snac->subtype == 0x0013)
|
13592
|
1138 return motd(od, conn, mod, frame, snac, bs);
|
13234
|
1139 else if (snac->subtype == 0x0018)
|
13592
|
1140 return hostversions(od, conn, mod, frame, snac, bs);
|
13234
|
1141 else if (snac->subtype == 0x001f)
|
13592
|
1142 return memrequest(od, conn, mod, frame, snac, bs);
|
13234
|
1143 else if (snac->subtype == 0x0021)
|
13592
|
1144 return aim_parse_extstatus(od, conn, mod, frame, snac, bs);
|
13234
|
1145
|
|
1146 return 0;
|
|
1147 }
|
|
1148
|
13592
|
1149 int service_modfirst(OscarData *od, aim_module_t *mod)
|
13234
|
1150 {
|
|
1151 mod->family = 0x0001;
|
|
1152 mod->version = 0x0003;
|
|
1153 mod->toolid = 0x0110;
|
|
1154 mod->toolversion = 0x0629;
|
|
1155 mod->flags = 0;
|
|
1156 strncpy(mod->name, "oservice", sizeof(mod->name));
|
|
1157 mod->snachandler = snachandler;
|
|
1158
|
|
1159 return 0;
|
|
1160 }
|