]> andersk Git - libfaim.git/blame - aim_info.c
- Sun Apr 2 07:29:11 UTC 2000
[libfaim.git] / aim_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
9
a25832e6 10#include <faim/aim.h>
9de3ca7e 11
a25832e6 12u_long aim_getinfo(struct aim_session_t *sess,
13 struct aim_conn_t *conn,
14 const char *sn)
9de3ca7e 15{
5b79dc93 16 struct command_tx_struct *newpacket;
276495a3 17 int i = 0;
18
19 if (!sess || !conn || !sn)
20 return 0;
9de3ca7e 21
5b79dc93 22 if (!(newpacket = aim_tx_new(0x0002, conn, 12+1+strlen(sn))))
23 return -1;
9de3ca7e 24
5b79dc93 25 newpacket->lock = 1;
9de3ca7e 26
5b79dc93 27 i = aim_putsnac(newpacket->data, 0x0002, 0x0005, 0x0000, sess->snac_nextid);
9de3ca7e 28
5b79dc93 29 i += aimutil_put16(newpacket->data+i, 0x0001);
30 i += aimutil_put8(newpacket->data+i, strlen(sn));
31 i += aimutil_putstr(newpacket->data+i, sn, strlen(sn));
9de3ca7e 32
5b79dc93 33 newpacket->lock = 0;
34 aim_tx_enqueue(sess, newpacket);
9de3ca7e 35
36 {
37 struct aim_snac_t snac;
38
a25832e6 39 snac.id = sess->snac_nextid;
9de3ca7e 40 snac.family = 0x0002;
41 snac.type = 0x0005;
42 snac.flags = 0x0000;
43
44 snac.data = malloc(strlen(sn)+1);
276495a3 45 strcpy(snac.data, sn);
9de3ca7e 46
a25832e6 47 aim_newsnac(sess, &snac);
9de3ca7e 48 }
49
a25832e6 50 return (sess->snac_nextid++);
9de3ca7e 51}
52
5b79dc93 53
54/*
55 * Capability blocks.
56 */
57u_char aim_caps[6][16] = {
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,
81 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}
82};
83
9de3ca7e 84/*
85 * AIM is fairly regular about providing user info. This
86 * is a generic routine to extract it in its standard form.
87 */
88int aim_extractuserinfo(u_char *buf, struct aim_userinfo_s *outinfo)
89{
90 int i = 0;
91 int tlvcnt = 0;
92 int curtlv = 0;
93 int tlv1 = 0;
94 u_short curtype;
95
96
97 if (!buf || !outinfo)
98 return -1;
99
100 /* Clear out old data first */
101 memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
102
103 /*
104 * Screen name. Stored as an unterminated string prepended
105 * with an unsigned byte containing its length.
106 */
107 memcpy(outinfo->sn, &(buf[i+1]), buf[i]);
108 outinfo->sn[(int)buf[i]] = '\0';
109 i = 1 + (int)buf[i];
110
111 /*
112 * Warning Level. Stored as an unsigned short.
113 */
114 outinfo->warnlevel = aimutil_get16(&buf[i]);
115 i += 2;
116
117 /*
118 * TLV Count. Unsigned short representing the number of
119 * Type-Length-Value triples that follow.
120 */
121 tlvcnt = aimutil_get16(&buf[i]);
122 i += 2;
123
124 /*
125 * Parse out the Type-Length-Value triples as they're found.
126 */
127 while (curtlv < tlvcnt)
128 {
129 curtype = aimutil_get16(&buf[i]);
130 switch (curtype)
131 {
132 /*
133 * Type = 0x0001: Member Class.
134 *
135 * Specified as any of the following bitwise ORed together:
136 * 0x0001 Trial (user less than 60days)
137 * 0x0002 Unknown bit 2
138 * 0x0004 AOL Main Service user
139 * 0x0008 Unknown bit 4
140 * 0x0010 Free (AIM) user
0c20631f 141 * 0x0020 Away
9de3ca7e 142 *
143 * In some odd cases, we can end up with more
144 * than one of these. We only want the first,
145 * as the others may not be something we want.
146 *
147 */
148 case 0x0001:
149 if (tlv1) /* use only the first */
150 break;
151 outinfo->class = aimutil_get16(&buf[i+4]);
152 tlv1++;
153 break;
154
155 /*
156 * Type = 0x0002: Member-Since date.
157 *
158 * The time/date that the user originally
159 * registered for the service, stored in
160 * time_t format
161 */
162 case 0x0002:
163 outinfo->membersince = aimutil_get32(&buf[i+4]);
164 break;
165
166 /*
167 * Type = 0x0003: On-Since date.
168 *
169 * The time/date that the user started
170 * their current session, stored in time_t
171 * format.
172 */
173 case 0x0003:
174 outinfo->onlinesince = aimutil_get32(&buf[i+4]);
175 break;
176
177 /*
178 * Type = 0x0004: Idle time.
179 *
180 * Number of seconds since the user
181 * actively used the service.
182 */
183 case 0x0004:
184 outinfo->idletime = aimutil_get16(&buf[i+4]);
185 break;
0b4acf97 186
187 /*
188 * Type = 0x000d
189 *
190 * Capability information. Not real sure of
191 * actual decoding. See comment on aim_bos_setprofile()
192 * in aim_misc.c about the capability block, its the same.
193 *
194 * Ignore.
195 *
196 */
197 case 0x000d:
5b79dc93 198 {
199 int z,y;
200 int len;
201 len = aimutil_get16(buf+i+2);
202 if (!len)
203 break;
204
205 for (z = 0; z < len; z+=0x10) {
206 for(y=0; y < 6; y++) {
207 if (memcmp(&aim_caps[y], buf+i+4+z, 0x10) == 0) {
208 switch(y) {
209 case 0: outinfo->capabilities |= AIM_CAPS_BUDDYICON; break;
210 case 1: outinfo->capabilities |= AIM_CAPS_VOICE; break;
211 case 2: outinfo->capabilities |= AIM_CAPS_IMIMAGE; break;
212 case 3: outinfo->capabilities |= AIM_CAPS_CHAT; break;
213 case 4: outinfo->capabilities |= AIM_CAPS_GETFILE; break;
214 case 5: outinfo->capabilities |= AIM_CAPS_SENDFILE; break;
215 default: outinfo->capabilities |= 0xff00; break;
216 }
217 }
218 }
219 }
220 }
0b4acf97 221 break;
222
223 /*
224 * Type = 0x000e
225 *
226 * Unknown. Always of zero length, and always only
227 * on AOL users.
228 *
229 * Ignore.
230 *
231 */
232 case 0x000e:
233 break;
9de3ca7e 234
235 /*
236 * Type = 0x000f: Session Length. (AIM)
237 * Type = 0x0010: Session Length. (AOL)
238 *
239 * The duration, in seconds, of the user's
240 * current session.
241 *
242 * Which TLV type this comes in depends
243 * on the service the user is using (AIM or AOL).
244 *
245 */
246 case 0x000f:
247 case 0x0010:
248 outinfo->sessionlen = aimutil_get32(&buf[i+4]);
249 break;
250
251 /*
252 * Reaching here indicates that either AOL has
253 * added yet another TLV for us to deal with,
254 * or the parsing has gone Terribly Wrong.
255 *
256 * Either way, inform the owner and attempt
257 * recovery.
258 *
259 */
260 default:
261 {
262 int len,z = 0, y = 0, x = 0;
263 char tmpstr[80];
264 printf("faim: userinfo: **warning: unexpected TLV:\n");
265 printf("faim: userinfo: sn =%s\n", outinfo->sn);
266 printf("faim: userinfo: curtlv=0x%04x\n", curtlv);
267 printf("faim: userinfo: type =0x%04x\n",aimutil_get16(&buf[i]));
268 printf("faim: userinfo: length=0x%04x\n", len = aimutil_get16(&buf[i+2]));
269 printf("faim: userinfo: data: \n");
270 while (z<len)
271 {
272 x = sprintf(tmpstr, "faim: userinfo: ");
273 for (y = 0; y < 8; y++)
274 {
275 if (z<len)
276 {
277 sprintf(tmpstr+x, "%02x ", buf[i+4+z]);
278 z++;
279 x += 3;
280 }
281 else
282 break;
283 }
284 printf("%s\n", tmpstr);
285 }
286 }
287 break;
288 }
289 /*
290 * No matter what, TLV triplets should always look like this:
291 *
292 * u_short type;
293 * u_short length;
294 * u_char data[length];
295 *
296 */
297 i += (2 + 2 + aimutil_get16(&buf[i+2]));
298
299 curtlv++;
300 }
301
302 return i;
303}
304
305/*
306 * Oncoming Buddy notifications contain a subset of the
307 * user information structure. Its close enough to run
308 * through aim_extractuserinfo() however.
309 *
310 */
a25832e6 311int aim_parse_oncoming_middle(struct aim_session_t *sess,
312 struct command_rx_struct *command)
9de3ca7e 313{
314 struct aim_userinfo_s userinfo;
315 u_int i = 0;
316 rxcallback_t userfunc=NULL;
317
318 i = 10;
319 i += aim_extractuserinfo(command->data+i, &userinfo);
320
321 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
322 if (userfunc)
a25832e6 323 i = userfunc(sess, command, &userinfo);
9de3ca7e 324
325 return 1;
326}
327
a25832e6 328/*
329 * Offgoing Buddy notifications contain no useful
330 * information other than the name it applies to.
331 *
332 */
333int aim_parse_offgoing_middle(struct aim_session_t *sess,
334 struct command_rx_struct *command)
335{
336 char sn[MAXSNLEN+1];
337 u_int i = 0;
338 rxcallback_t userfunc=NULL;
339
1a7c2214 340 strncpy(sn, command->data+11, (int)command->data[10]);
341 sn[(int)command->data[10]] = '\0';
a25832e6 342
343 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING);
344 if (userfunc)
345 i = userfunc(sess, command, sn);
346
347 return 1;
348}
9de3ca7e 349
350/*
351 * This parses the user info stuff out all nice and pretty then calls
352 * the higher-level callback (in the user app).
353 *
354 */
a25832e6 355int aim_parse_userinfo_middle(struct aim_session_t *sess,
356 struct command_rx_struct *command)
9de3ca7e 357{
358 struct aim_userinfo_s userinfo;
359 char *prof_encoding = NULL;
360 char *prof = NULL;
361 u_int i = 0;
362 rxcallback_t userfunc=NULL;
0c20631f 363 struct aim_tlvlist_t *tlvlist;
9de3ca7e 364
365 {
366 u_long snacid = 0x000000000;
367 struct aim_snac_t *snac = NULL;
368
369 snacid = aimutil_get32(&command->data[6]);
a25832e6 370 snac = aim_remsnac(sess, snacid);
9de3ca7e 371
276495a3 372 if (snac)
373 {
374 if (snac->data)
375 free(snac->data);
376 else
377 printf("faim: parse_userinfo_middle: warning: no ->data in cached SNAC\n");
378 free(snac);
379 }
380 else
381 printf("faim: parseuserinfo_middle: warning: no SNAC cached with for this response (%08lx)\n", snacid);
9de3ca7e 382
383 }
384
385 i = 10;
9de3ca7e 386
0c20631f 387 /*
388 * extractuserinfo will give us the basic metaTLV information
389 */
390 i += aim_extractuserinfo(command->data+i, &userinfo);
391
392 /*
393 * However, in this command, there's usually more TLVs following...
394 */
395 tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
396 prof_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
397 prof = aim_gettlv_str(tlvlist, 0x0002, 1);
9de3ca7e 398
399 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
400 if (userfunc)
401 {
a25832e6 402 i = userfunc(sess,
403 command,
9de3ca7e 404 &userinfo,
405 prof_encoding,
406 prof);
407 }
0c20631f 408
9de3ca7e 409 free(prof_encoding);
410 free(prof);
0c20631f 411 aim_freetlvchain(&tlvlist);
9de3ca7e 412
413 return 1;
414}
50443ea0 415
416/*
417 * Inverse of aim_extractuserinfo()
418 */
419int aim_putuserinfo(u_char *buf, int buflen, struct aim_userinfo_s *info)
420{
421 int i = 0;
422 struct aim_tlvlist_t *tlvlist = NULL;
423
424 if (!buf || !info)
425 return 0;
426
427 i += aimutil_put8(buf+i, strlen(info->sn));
428 i += aimutil_putstr(buf+i, info->sn, strlen(info->sn));
429
430 i += aimutil_put16(buf+i, info->warnlevel);
431
432 /* XXX: we only put down five */
433 i += aimutil_put16(buf+i, 5);
434 aim_addtlvtochain16(&tlvlist, 0x0001, info->class);
435 aim_addtlvtochain32(&tlvlist, 0x0002, info->membersince);
436 aim_addtlvtochain32(&tlvlist, 0x0003, info->onlinesince);
437 aim_addtlvtochain16(&tlvlist, 0x0004, info->idletime);
438 /* XXX: should put caps here */
439 aim_addtlvtochain32(&tlvlist, (info->class)&AIM_CLASS_AOL?0x0010:0x000f, info->sessionlen);
440
441 i += aim_writetlvchain(buf+i, buflen-i, &tlvlist);
442 aim_freetlvchain(&tlvlist);
443
444 return i;
445}
446
447int aim_sendbuddyoncoming(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_userinfo_s *info)
448{
5b79dc93 449 struct command_tx_struct *tx;
50443ea0 450 int i = 0;
451
452 if (!sess || !conn || !info)
453 return 0;
454
5b79dc93 455 if (!(tx = aim_tx_new(0x0002, conn, 1152)))
456 return -1;
50443ea0 457
5b79dc93 458 tx->lock = 1;
50443ea0 459
5b79dc93 460 i += aimutil_put16(tx->data+i, 0x0003);
461 i += aimutil_put16(tx->data+i, 0x000b);
462 i += aimutil_put16(tx->data+i, 0x0000);
463 i += aimutil_put16(tx->data+i, 0x0000);
464 i += aimutil_put16(tx->data+i, 0x0000);
50443ea0 465
5b79dc93 466 i += aim_putuserinfo(tx->data+i, tx->commandlen-i, info);
50443ea0 467
5b79dc93 468 tx->commandlen = i;
469 tx->lock = 0;
470 aim_tx_enqueue(sess, tx);
50443ea0 471
472 return 0;
473}
474
475int aim_sendbuddyoffgoing(struct aim_session_t *sess, struct aim_conn_t *conn, char *sn)
476{
5b79dc93 477 struct command_tx_struct *tx;
50443ea0 478 int i = 0;
479
480 if (!sess || !conn || !sn)
481 return 0;
482
5b79dc93 483 if (!(tx = aim_tx_new(0x0002, conn, 10+1+strlen(sn))))
484 return -1;
50443ea0 485
5b79dc93 486 tx->lock = 1;
50443ea0 487
5b79dc93 488 i += aimutil_put16(tx->data+i, 0x0003);
489 i += aimutil_put16(tx->data+i, 0x000c);
490 i += aimutil_put16(tx->data+i, 0x0000);
491 i += aimutil_put16(tx->data+i, 0x0000);
492 i += aimutil_put16(tx->data+i, 0x0000);
50443ea0 493
5b79dc93 494 i += aimutil_put8(tx->data+i, strlen(sn));
495 i += aimutil_putstr(tx->data+i, sn, strlen(sn));
50443ea0 496
5b79dc93 497 tx->lock = 0;
498 aim_tx_enqueue(sess, tx);
50443ea0 499
500 return 0;
501}
This page took 0.118612 seconds and 5 git commands to generate.