]> andersk Git - libfaim.git/blame - src/info.c
- Mon Mar 26 15:57:41 PST 2001
[libfaim.git] / src / info.c
CommitLineData
9de3ca7e 1/*
2 * aim_info.c
3 *
4 * The functions here are responsible for requesting and parsing information-
5 * gathering SNACs.
6 *
7 */
8
37ee990e 9#define FAIM_INTERNAL
dd60ff8b 10#include <aim.h>
9de3ca7e 11
262272cc 12struct aim_priv_inforeq {
1ea867e3 13 char sn[MAXSNLEN+1];
262272cc 14 unsigned short infotype;
15};
16
00ef5271 17faim_export int aim_getinfo(struct aim_session_t *sess,
18 struct aim_conn_t *conn,
19 const char *sn,
20 unsigned short infotype)
9de3ca7e 21{
5b79dc93 22 struct command_tx_struct *newpacket;
1ea867e3 23 struct aim_priv_inforeq privdata;
276495a3 24 int i = 0;
25
26 if (!sess || !conn || !sn)
00ef5271 27 return -1;
28
29 if ((infotype != AIM_GETINFO_GENERALINFO) &&
30 (infotype != AIM_GETINFO_AWAYMESSAGE))
31 return -1;
9de3ca7e 32
646c6b52 33 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 12+1+strlen(sn))))
5b79dc93 34 return -1;
9de3ca7e 35
5b79dc93 36 newpacket->lock = 1;
9de3ca7e 37
5b79dc93 38 i = aim_putsnac(newpacket->data, 0x0002, 0x0005, 0x0000, sess->snac_nextid);
9de3ca7e 39
262272cc 40 i += aimutil_put16(newpacket->data+i, infotype);
5b79dc93 41 i += aimutil_put8(newpacket->data+i, strlen(sn));
42 i += aimutil_putstr(newpacket->data+i, sn, strlen(sn));
9de3ca7e 43
5b79dc93 44 newpacket->lock = 0;
45 aim_tx_enqueue(sess, newpacket);
9de3ca7e 46
1ea867e3 47 strncpy(privdata.sn, sn, sizeof(privdata.sn));
48 privdata.infotype = infotype;
49 aim_cachesnac(sess, 0x0002, 0x0005, 0x0000, &privdata, sizeof(struct aim_priv_inforeq));
9de3ca7e 50
00ef5271 51 return 0;
96f8b1ed 52}
5b79dc93 53
54/*
55 * Capability blocks.
56 */
0589dc54 57u_char aim_caps[8][16] = {
5b79dc93 58
59 /* Buddy icon */
60 {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
61 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
62
63 /* Voice */
64 {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,
65 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
66
67 /* IM image */
68 {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,
69 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
70
71 /* Chat */
72 {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
73 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
74
75 /* Get file */
76 {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
77 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
78
79 /* Send file */
80 {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
0589dc54 81 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
82
83 /* Saves stock portfolios */
84 {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
85 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
86
87 /* Games */
88 {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
2acf2afa 89 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00},
5b79dc93 90};
91
646c6b52 92faim_internal unsigned short aim_getcap(struct aim_session_t *sess, unsigned char *capblock, int buflen)
b69540e3 93{
94 u_short ret = 0;
95 int y;
96 int offset = 0;
0589dc54 97 int identified;
b69540e3 98
99 while (offset < buflen) {
0589dc54 100 identified = 0;
b69540e3 101 for(y=0; y < (sizeof(aim_caps)/0x10); y++) {
102 if (memcmp(&aim_caps[y], capblock+offset, 0x10) == 0) {
103 switch(y) {
0589dc54 104 case 0: ret |= AIM_CAPS_BUDDYICON; identified++; break;
105 case 1: ret |= AIM_CAPS_VOICE; identified++; break;
106 case 2: ret |= AIM_CAPS_IMIMAGE; identified++; break;
107 case 3: ret |= AIM_CAPS_CHAT; identified++; break;
108 case 4: ret |= AIM_CAPS_GETFILE; identified++; break;
109 case 5: ret |= AIM_CAPS_SENDFILE; identified++; break;
110 case 6: ret |= AIM_CAPS_GAMES; identified++; break;
111 case 7: ret |= AIM_CAPS_SAVESTOCKS; identified++; break;
b69540e3 112 }
113 }
114 }
0589dc54 115 if (!identified) {
646c6b52 116 faimdprintf(sess, 0, "unknown capability!\n");
0589dc54 117 ret |= 0xff00;
118 }
119
b69540e3 120 offset += 0x10;
121 }
122 return ret;
123}
124
78b3fb13 125faim_internal int aim_putcap(unsigned char *capblock, int buflen, u_short caps)
b69540e3 126{
127 int offset = 0;
128
129 if (!capblock)
130 return -1;
131
132 if ((caps & AIM_CAPS_BUDDYICON) && (offset < buflen)) {
133 memcpy(capblock+offset, aim_caps[0], sizeof(aim_caps[0]));
134 offset += sizeof(aim_caps[1]);
135 }
136 if ((caps & AIM_CAPS_VOICE) && (offset < buflen)) {
137 memcpy(capblock+offset, aim_caps[1], sizeof(aim_caps[1]));
138 offset += sizeof(aim_caps[1]);
139 }
140 if ((caps & AIM_CAPS_IMIMAGE) && (offset < buflen)) {
141 memcpy(capblock+offset, aim_caps[2], sizeof(aim_caps[2]));
142 offset += sizeof(aim_caps[2]);
143 }
144 if ((caps & AIM_CAPS_CHAT) && (offset < buflen)) {
145 memcpy(capblock+offset, aim_caps[3], sizeof(aim_caps[3]));
146 offset += sizeof(aim_caps[3]);
147 }
148 if ((caps & AIM_CAPS_GETFILE) && (offset < buflen)) {
149 memcpy(capblock+offset, aim_caps[4], sizeof(aim_caps[4]));
150 offset += sizeof(aim_caps[4]);
151 }
152 if ((caps & AIM_CAPS_SENDFILE) && (offset < buflen)) {
153 memcpy(capblock+offset, aim_caps[5], sizeof(aim_caps[5]));
154 offset += sizeof(aim_caps[5]);
155 }
0589dc54 156 if ((caps & AIM_CAPS_GAMES) && (offset < buflen)) {
157 memcpy(capblock+offset, aim_caps[6], sizeof(aim_caps[6]));
158 offset += sizeof(aim_caps[6]);
159 }
160 if ((caps & AIM_CAPS_SAVESTOCKS) && (offset < buflen)) {
161 memcpy(capblock+offset, aim_caps[7], sizeof(aim_caps[7]));
162 offset += sizeof(aim_caps[7]);
163 }
b69540e3 164
165 return offset;
166}
167
9de3ca7e 168/*
169 * AIM is fairly regular about providing user info. This
170 * is a generic routine to extract it in its standard form.
171 */
646c6b52 172faim_internal int aim_extractuserinfo(struct aim_session_t *sess, unsigned char *buf, struct aim_userinfo_s *outinfo)
9de3ca7e 173{
174 int i = 0;
175 int tlvcnt = 0;
176 int curtlv = 0;
177 int tlv1 = 0;
178 u_short curtype;
68ac63c2 179 int lastvalid;
9de3ca7e 180
181
182 if (!buf || !outinfo)
183 return -1;
184
185 /* Clear out old data first */
186 memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
187
188 /*
189 * Screen name. Stored as an unterminated string prepended
190 * with an unsigned byte containing its length.
191 */
68ac63c2 192 if (buf[i] < MAXSNLEN) {
193 memcpy(outinfo->sn, &(buf[i+1]), buf[i]);
194 outinfo->sn[(int)buf[i]] = '\0';
195 } else {
196 memcpy(outinfo->sn, &(buf[i+1]), MAXSNLEN-1);
197 outinfo->sn[MAXSNLEN] = '\0';
198 }
9de3ca7e 199 i = 1 + (int)buf[i];
200
201 /*
202 * Warning Level. Stored as an unsigned short.
203 */
204 outinfo->warnlevel = aimutil_get16(&buf[i]);
205 i += 2;
206
207 /*
208 * TLV Count. Unsigned short representing the number of
209 * Type-Length-Value triples that follow.
210 */
211 tlvcnt = aimutil_get16(&buf[i]);
212 i += 2;
213
214 /*
215 * Parse out the Type-Length-Value triples as they're found.
216 */
68ac63c2 217 while (curtlv < tlvcnt) {
218 lastvalid = 1;
219 curtype = aimutil_get16(&buf[i]);
220 switch (curtype) {
221 /*
222 * Type = 0x0000: Invalid
223 *
224 * AOL has been trying to throw these in just to break us.
225 * They're real nice guys over there at AOL.
226 *
227 * Just skip the two zero bytes and continue on. (This doesn't
228 * count towards tlvcnt!)
229 */
230 case 0x0000:
231 lastvalid = 0;
232 i += 2;
233 break;
0b4acf97 234
68ac63c2 235 /*
a15d82b1 236 * Type = 0x0001: User flags
68ac63c2 237 *
238 * Specified as any of the following bitwise ORed together:
239 * 0x0001 Trial (user less than 60days)
240 * 0x0002 Unknown bit 2
241 * 0x0004 AOL Main Service user
242 * 0x0008 Unknown bit 4
243 * 0x0010 Free (AIM) user
244 * 0x0020 Away
245 *
246 * In some odd cases, we can end up with more
247 * than one of these. We only want the first,
248 * as the others may not be something we want.
249 *
250 */
251 case 0x0001:
252 if (tlv1) /* use only the first */
253 break;
a15d82b1 254 outinfo->flags = aimutil_get16(&buf[i+4]);
68ac63c2 255 tlv1++;
256 break;
257
258 /*
259 * Type = 0x0002: Member-Since date.
260 *
261 * The time/date that the user originally
262 * registered for the service, stored in
263 * time_t format
264 */
265 case 0x0002:
266 outinfo->membersince = aimutil_get32(&buf[i+4]);
267 break;
268
269 /*
270 * Type = 0x0003: On-Since date.
271 *
272 * The time/date that the user started
273 * their current session, stored in time_t
274 * format.
275 */
276 case 0x0003:
277 outinfo->onlinesince = aimutil_get32(&buf[i+4]);
278 break;
279
280 /*
281 * Type = 0x0004: Idle time.
282 *
283 * Number of seconds since the user
284 * actively used the service.
285 */
286 case 0x0004:
287 outinfo->idletime = aimutil_get16(&buf[i+4]);
288 break;
289
f2d214f9 290 /*
291 * Type = 0x0006: ICQ Online Status
292 *
293 * ICQ's Away/DND/etc "enriched" status
294 * Some decoding of values done by Scott <darkagl@pcnet.com>
295 */
296 case 0x0006:
f2d214f9 297 outinfo->icqinfo.status = aimutil_get16(buf+i+2+2+2);
298 break;
299
3b101546 300
301 /*
302 * Type = 0x000a
303 *
304 * ICQ User IP Address.
305 * Ahh, the joy of ICQ security.
306 */
307 case 0x000a:
308 outinfo->icqinfo.ipaddr = aimutil_get32(&buf[i+4]);
309 break;
310
311 /* Type = 0x000c
312 *
313 * random crap containing the IP address,
314 * apparently a port number, and some Other Stuff.
315 *
316 */
317 case 0x000c:
318 memcpy(outinfo->icqinfo.crap, &buf[i+4], 0x25);
319 break;
320
68ac63c2 321 /*
322 * Type = 0x000d
323 *
324 * Capability information. Not real sure of
325 * actual decoding. See comment on aim_bos_setprofile()
326 * in aim_misc.c about the capability block, its the same.
327 *
328 */
329 case 0x000d:
330 {
331 int len;
332 len = aimutil_get16(buf+i+2);
333 if (!len)
9de3ca7e 334 break;
68ac63c2 335
646c6b52 336 outinfo->capabilities = aim_getcap(sess, buf+i+4, len);
68ac63c2 337 }
338 break;
339
340 /*
341 * Type = 0x000e
342 *
343 * Unknown. Always of zero length, and always only
344 * on AOL users.
345 *
346 * Ignore.
347 *
348 */
349 case 0x000e:
350 break;
351
352 /*
353 * Type = 0x000f: Session Length. (AIM)
354 * Type = 0x0010: Session Length. (AOL)
355 *
356 * The duration, in seconds, of the user's
357 * current session.
358 *
359 * Which TLV type this comes in depends
360 * on the service the user is using (AIM or AOL).
361 *
362 */
363 case 0x000f:
364 case 0x0010:
365 outinfo->sessionlen = aimutil_get32(&buf[i+4]);
366 break;
367
368 /*
369 * Reaching here indicates that either AOL has
370 * added yet another TLV for us to deal with,
371 * or the parsing has gone Terribly Wrong.
372 *
373 * Either way, inform the owner and attempt
374 * recovery.
375 *
376 */
377 default:
378 {
379 int len,z = 0, y = 0, x = 0;
646c6b52 380 char tmpstr[160];
381
382 faimdprintf(sess, 0, "userinfo: **warning: unexpected TLV:\n");
383 faimdprintf(sess, 0, "userinfo: sn =%s\n", outinfo->sn);
384 faimdprintf(sess, 0, "userinfo: curtlv=0x%04x\n", curtlv);
385 faimdprintf(sess, 0, "userinfo: type =0x%04x\n",aimutil_get16(&buf[i]));
386 faimdprintf(sess, 0, "userinfo: length=0x%04x\n", len = aimutil_get16(&buf[i+2]));
387 faimdprintf(sess, 0, "userinfo: data: \n");
68ac63c2 388 while (z<len)
9de3ca7e 389 {
646c6b52 390 x = snprintf(tmpstr, sizeof(tmpstr), "userinfo: ");
68ac63c2 391 for (y = 0; y < 8; y++)
9de3ca7e 392 {
68ac63c2 393 if (z<len)
9de3ca7e 394 {
646c6b52 395 snprintf(tmpstr+x, sizeof(tmpstr)-x, "%02x ", buf[i+4+z]);
68ac63c2 396 z++;
397 x += 3;
9de3ca7e 398 }
68ac63c2 399 else
400 break;
9de3ca7e 401 }
646c6b52 402 faimdprintf(sess, 0, "%s\n", tmpstr);
9de3ca7e 403 }
68ac63c2 404 }
405 break;
406 }
407 /*
408 * No matter what, TLV triplets should always look like this:
409 *
410 * u_short type;
411 * u_short length;
412 * u_char data[length];
413 *
414 */
415 if (lastvalid) {
416 i += (2 + 2 + aimutil_get16(&buf[i+2]));
9de3ca7e 417 curtlv++;
418 }
68ac63c2 419 }
9de3ca7e 420
421 return i;
422}
423
50443ea0 424/*
425 * Inverse of aim_extractuserinfo()
426 */
78b3fb13 427faim_internal int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info)
50443ea0 428{
9c38f1a7 429 int i = 0, numtlv = 0;
50443ea0 430 struct aim_tlvlist_t *tlvlist = NULL;
431
432 if (!buf || !info)
433 return 0;
434
435 i += aimutil_put8(buf+i, strlen(info->sn));
436 i += aimutil_putstr(buf+i, info->sn, strlen(info->sn));
437
438 i += aimutil_put16(buf+i, info->warnlevel);
439
9c38f1a7 440
a15d82b1 441 aim_addtlvtochain16(&tlvlist, 0x0001, info->flags);
9c38f1a7 442 numtlv++;
443
50443ea0 444 aim_addtlvtochain32(&tlvlist, 0x0002, info->membersince);
9c38f1a7 445 numtlv++;
446
50443ea0 447 aim_addtlvtochain32(&tlvlist, 0x0003, info->onlinesince);
9c38f1a7 448 numtlv++;
449
50443ea0 450 aim_addtlvtochain16(&tlvlist, 0x0004, info->idletime);
9c38f1a7 451 numtlv++;
3b101546 452
453#if ICQ_OSCAR_SUPPORT
454 if(atoi(info->sn) != 0) {
455 aim_addtlvtochain16(&tlvlist, 0x0006, info->icqinfo.status);
456 aim_addtlvtochain32(&tlvlist, 0x000a, info->icqinfo.ipaddr);
457 }
458#endif
459
460 aim_addtlvtochain_caps(&tlvlist, 0x000d, info->capabilities);
9c38f1a7 461 numtlv++;
3b101546 462
a15d82b1 463 aim_addtlvtochain32(&tlvlist, (unsigned short)((info->flags)&AIM_FLAG_AOL?0x0010:0x000f), info->sessionlen);
9c38f1a7 464 numtlv++;
3b101546 465
9c38f1a7 466 i += aimutil_put16(buf+i, numtlv); /* tlvcount */
467 i += aim_writetlvchain(buf+i, buflen-i, &tlvlist); /* tlvs */
50443ea0 468 aim_freetlvchain(&tlvlist);
3b101546 469
50443ea0 470 return i;
471}
472
78b3fb13 473faim_export int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info)
50443ea0 474{
5b79dc93 475 struct command_tx_struct *tx;
50443ea0 476 int i = 0;
477
478 if (!sess || !conn || !info)
479 return 0;
480
646c6b52 481 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 1152)))
5b79dc93 482 return -1;
50443ea0 483
5b79dc93 484 tx->lock = 1;
50443ea0 485
5b79dc93 486 i += aimutil_put16(tx->data+i, 0x0003);
487 i += aimutil_put16(tx->data+i, 0x000b);
488 i += aimutil_put16(tx->data+i, 0x0000);
489 i += aimutil_put16(tx->data+i, 0x0000);
490 i += aimutil_put16(tx->data+i, 0x0000);
50443ea0 491
5b79dc93 492 i += aim_putuserinfo(tx->data+i, tx->commandlen-i, info);
50443ea0 493
5b79dc93 494 tx->commandlen = i;
495 tx->lock = 0;
496 aim_tx_enqueue(sess, tx);
50443ea0 497
498 return 0;
499}
500
78b3fb13 501faim_export int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn)
50443ea0 502{
5b79dc93 503 struct command_tx_struct *tx;
50443ea0 504 int i = 0;
505
506 if (!sess || !conn || !sn)
507 return 0;
508
646c6b52 509 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+1+strlen(sn))))
5b79dc93 510 return -1;
50443ea0 511
5b79dc93 512 tx->lock = 1;
50443ea0 513
5b79dc93 514 i += aimutil_put16(tx->data+i, 0x0003);
515 i += aimutil_put16(tx->data+i, 0x000c);
516 i += aimutil_put16(tx->data+i, 0x0000);
517 i += aimutil_put16(tx->data+i, 0x0000);
518 i += aimutil_put16(tx->data+i, 0x0000);
50443ea0 519
5b79dc93 520 i += aimutil_put8(tx->data+i, strlen(sn));
521 i += aimutil_putstr(tx->data+i, sn, strlen(sn));
50443ea0 522
5b79dc93 523 tx->lock = 0;
524 aim_tx_enqueue(sess, tx);
50443ea0 525
526 return 0;
527}
262272cc 528
e80a0fa9 529faim_export int aim_0002_000b(struct aim_session_t *sess, struct aim_conn_t *conn, const char *sn)
530{
531 struct command_tx_struct *tx;
532 int i = 0;
533
534 if (!sess || !conn || !sn)
535 return 0;
536
537 if (!(tx = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+1+strlen(sn))))
538 return -1;
539
540 tx->lock = 1;
541
542 i = aim_putsnac(tx->data, 0x0002, 0x000b, 0x0000, sess->snac_nextid);
543 i += aimutil_put8(tx->data+i, strlen(sn));
544 i += aimutil_putstr(tx->data+i, sn, strlen(sn));
545
546 tx->commandlen = i;
547 tx->lock = 0;
548 aim_tx_enqueue(sess, tx);
549
550 return 0;
551}
552
00ef5271 553static int rights(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
554{
555 struct aim_tlvlist_t *tlvlist;
556 rxcallback_t userfunc;
557 int ret = 0;
558
559 tlvlist = aim_readtlvchain(data, datalen);
560
561 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
562 ret = userfunc(sess, rx);
563
564 aim_freetlvchain(&tlvlist);
565
566 return ret;
567}
568
569static int userinfo(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
570{
571 struct aim_userinfo_s userinfo;
572 char *text_encoding = NULL;
573 char *text = NULL;
574 int i = 0;
575 rxcallback_t userfunc;
576 struct aim_tlvlist_t *tlvlist;
577 struct aim_snac_t *origsnac = NULL;
578 struct aim_priv_inforeq *inforeq;
579 int ret = 0;
580
581 origsnac = aim_remsnac(sess, snac->id);
582
583 if (!origsnac || !origsnac->data) {
584 faimdprintf(sess, 0, "parse_userinfo_middle: major problem: no snac stored!\n");
585 return 0;
586 }
587
588 inforeq = (struct aim_priv_inforeq *)origsnac->data;
589
590 if ((inforeq->infotype != AIM_GETINFO_GENERALINFO) &&
591 (inforeq->infotype != AIM_GETINFO_AWAYMESSAGE)) {
592 faimdprintf(sess, 0, "parse_userinfo_middle: unknown infotype in request! (0x%04x)\n", inforeq->infotype);
593 return 0;
594 }
595
596 i = aim_extractuserinfo(sess, data, &userinfo);
597
598 tlvlist = aim_readtlvchain(data+i, datalen-i);
599
600 /*
601 * Depending on what informational text was requested, different
602 * TLVs will appear here.
603 *
604 * Profile will be 1 and 2, away message will be 3 and 4.
605 */
606 if (aim_gettlv(tlvlist, 0x0001, 1)) {
607 text_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
608 text = aim_gettlv_str(tlvlist, 0x0002, 1);
609 } else if (aim_gettlv(tlvlist, 0x0003, 1)) {
610 text_encoding = aim_gettlv_str(tlvlist, 0x0003, 1);
611 text = aim_gettlv_str(tlvlist, 0x0004, 1);
612 }
613
614 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
615 ret = userfunc(sess, rx, &userinfo, text_encoding, text, inforeq->infotype);
616
617 free(text_encoding);
618 free(text);
619
620 aim_freetlvchain(&tlvlist);
621
622 if (origsnac) {
623 if (origsnac->data)
624 free(origsnac->data);
625 free(origsnac);
626 }
627
628 return ret;
629}
630
631static int snachandler(struct aim_session_t *sess, aim_module_t *mod, struct command_rx_struct *rx, aim_modsnac_t *snac, unsigned char *data, int datalen)
632{
633
634 if (snac->subtype == 0x0003)
635 return rights(sess, mod, rx, snac, data, datalen);
636 else if (snac->subtype == 0x0006)
637 return userinfo(sess, mod, rx, snac, data, datalen);
638
639 return 0;
640}
641
642faim_internal int locate_modfirst(struct aim_session_t *sess, aim_module_t *mod)
643{
644
645 mod->family = 0x0002;
646 mod->version = 0x0000;
647 mod->flags = 0;
648 strncpy(mod->name, "locate", sizeof(mod->name));
649 mod->snachandler = snachandler;
650
651 return 0;
652}
This page took 0.191585 seconds and 5 git commands to generate.