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