]> andersk Git - libfaim.git/blob - aim_info.c
42b7bdf97e04bac050bc53ec8f37a708921dfb44
[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     printf("faim: getuserinfo: caching snac %08lx\n", snac.id);
47     snac.family = 0x0002;
48     snac.type = 0x0005;
49     snac.flags = 0x0000;
50
51     snac.data = malloc(strlen(sn)+1);
52     strcpy(snac.data, sn);
53
54     aim_newsnac(sess, &snac);
55   }
56
57   return (sess->snac_nextid++);
58 }
59
60 /*
61  * AIM is fairly regular about providing user info.  This
62  * is a generic routine to extract it in its standard form.
63  */
64 int aim_extractuserinfo(u_char *buf, struct aim_userinfo_s *outinfo)
65 {
66   int i = 0;
67   int tlvcnt = 0;
68   int curtlv = 0;
69   int tlv1 = 0;
70   u_short curtype;
71
72
73   if (!buf || !outinfo)
74     return -1;
75
76   /* Clear out old data first */
77   memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
78
79   /*
80    * Screen name.    Stored as an unterminated string prepended
81    *                 with an unsigned byte containing its length.
82    */
83   memcpy(outinfo->sn, &(buf[i+1]), buf[i]);
84   outinfo->sn[(int)buf[i]] = '\0';
85   i = 1 + (int)buf[i];
86
87   /*
88    * Warning Level.  Stored as an unsigned short.
89    */
90   outinfo->warnlevel = aimutil_get16(&buf[i]);
91   i += 2;
92
93   /*
94    * TLV Count.      Unsigned short representing the number of 
95    *                 Type-Length-Value triples that follow.
96    */
97   tlvcnt = aimutil_get16(&buf[i]);
98   i += 2;
99
100   /* 
101    * Parse out the Type-Length-Value triples as they're found.
102    */
103   while (curtlv < tlvcnt)
104     {
105       curtype = aimutil_get16(&buf[i]);
106       switch (curtype)
107         {
108           /*
109            * Type = 0x0001: Member Class.   
110            * 
111            * Specified as any of the following bitwise ORed together:
112            *      0x0001  Trial (user less than 60days)
113            *      0x0002  Unknown bit 2
114            *      0x0004  AOL Main Service user
115            *      0x0008  Unknown bit 4
116            *      0x0010  Free (AIM) user 
117            *      0x0020  Away
118            *
119            * In some odd cases, we can end up with more
120            * than one of these.  We only want the first,
121            * as the others may not be something we want.
122            *
123            */
124         case 0x0001:
125           if (tlv1) /* use only the first */
126             break;
127           outinfo->class = aimutil_get16(&buf[i+4]);
128           tlv1++;
129           break;
130           
131           /*
132            * Type = 0x0002: Member-Since date. 
133            *
134            * The time/date that the user originally
135            * registered for the service, stored in 
136            * time_t format
137            */
138         case 0x0002: 
139           outinfo->membersince = aimutil_get32(&buf[i+4]);
140           break;
141           
142           /*
143            * Type = 0x0003: On-Since date.
144            *
145            * The time/date that the user started 
146            * their current session, stored in time_t
147            * format.
148            */
149         case 0x0003:
150           outinfo->onlinesince = aimutil_get32(&buf[i+4]);
151           break;
152
153           /*
154            * Type = 0x0004: Idle time.
155            *
156            * Number of seconds since the user
157            * actively used the service.
158            */
159         case 0x0004:
160           outinfo->idletime = aimutil_get16(&buf[i+4]);
161           break;
162
163           /*
164            * Type = 0x000d
165            *
166            * Capability information.  Not real sure of
167            * actual decoding.  See comment on aim_bos_setprofile()
168            * in aim_misc.c about the capability block, its the same.
169            *
170            * Ignore.
171            *
172            */
173         case 0x000d:
174           break;
175
176           /*
177            * Type = 0x000e
178            *
179            * Unknown.  Always of zero length, and always only
180            * on AOL users.
181            *
182            * Ignore.
183            *
184            */
185         case 0x000e:
186           break;
187           
188           /*
189            * Type = 0x000f: Session Length. (AIM)
190            * Type = 0x0010: Session Length. (AOL)
191            *
192            * The duration, in seconds, of the user's
193            * current session.
194            *
195            * Which TLV type this comes in depends
196            * on the service the user is using (AIM or AOL).
197            *
198            */
199         case 0x000f:
200         case 0x0010:
201           outinfo->sessionlen = aimutil_get32(&buf[i+4]);
202           break;
203
204           /*
205            * Reaching here indicates that either AOL has
206            * added yet another TLV for us to deal with, 
207            * or the parsing has gone Terribly Wrong.
208            *
209            * Either way, inform the owner and attempt
210            * recovery.
211            *
212            */
213         default:
214           {
215             int len,z = 0, y = 0, x = 0;
216             char tmpstr[80];
217             printf("faim: userinfo: **warning: unexpected TLV:\n");
218             printf("faim: userinfo:   sn    =%s\n", outinfo->sn);
219             printf("faim: userinfo:   curtlv=0x%04x\n", curtlv);
220             printf("faim: userinfo:   type  =0x%04x\n",aimutil_get16(&buf[i]));
221             printf("faim: userinfo:   length=0x%04x\n", len = aimutil_get16(&buf[i+2]));
222             printf("faim: userinfo:   data: \n");
223             while (z<len)
224               {
225                 x = sprintf(tmpstr, "faim: userinfo:      ");
226                 for (y = 0; y < 8; y++)
227                   {
228                     if (z<len)
229                       {
230                         sprintf(tmpstr+x, "%02x ", buf[i+4+z]);
231                         z++;
232                         x += 3;
233                       }
234                     else
235                       break;
236                   }
237                 printf("%s\n", tmpstr);
238               }
239           }
240           break;
241         }  
242       /*
243        * No matter what, TLV triplets should always look like this:
244        *
245        *   u_short type;
246        *   u_short length;
247        *   u_char  data[length];
248        *
249        */
250       i += (2 + 2 + aimutil_get16(&buf[i+2]));
251       
252       curtlv++;
253     }
254   
255   return i;
256 }
257
258 /*
259  * Oncoming Buddy notifications contain a subset of the
260  * user information structure.  Its close enough to run
261  * through aim_extractuserinfo() however.
262  *
263  */
264 int aim_parse_oncoming_middle(struct aim_session_t *sess,
265                               struct command_rx_struct *command)
266 {
267   struct aim_userinfo_s userinfo;
268   u_int i = 0;
269   rxcallback_t userfunc=NULL;
270
271   i = 10;
272   i += aim_extractuserinfo(command->data+i, &userinfo);
273
274   userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
275   if (userfunc)
276     i = userfunc(sess, command, &userinfo);
277
278   return 1;
279 }
280
281 /*
282  * Offgoing Buddy notifications contain no useful
283  * information other than the name it applies to.
284  *
285  */
286 int aim_parse_offgoing_middle(struct aim_session_t *sess,
287                               struct command_rx_struct *command)
288 {
289   char sn[MAXSNLEN+1];
290   u_int i = 0;
291   rxcallback_t userfunc=NULL;
292
293   strncpy(sn, command->data+11, (int)command->data[10]);
294   sn[(int)command->data[10]] = '\0';
295
296   userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING);
297   if (userfunc)
298     i = userfunc(sess, command, sn);
299
300   return 1;
301 }
302
303 /*
304  * This parses the user info stuff out all nice and pretty then calls 
305  * the higher-level callback (in the user app).
306  *
307  */
308 int aim_parse_userinfo_middle(struct aim_session_t *sess,
309                               struct command_rx_struct *command)
310 {
311   struct aim_userinfo_s userinfo;
312   char *prof_encoding = NULL;
313   char *prof = NULL;
314   u_int i = 0;
315   rxcallback_t userfunc=NULL;
316   struct aim_tlvlist_t *tlvlist;
317
318   {
319     u_long snacid = 0x000000000;
320     struct aim_snac_t *snac = NULL;
321
322     snacid = aimutil_get32(&command->data[6]);
323     snac = aim_remsnac(sess, snacid);
324
325     if (snac)
326       {
327         if (snac->data)
328           free(snac->data);
329         else
330           printf("faim: parse_userinfo_middle: warning: no ->data in cached SNAC\n");
331         free(snac);
332       }
333     else
334       printf("faim: parseuserinfo_middle: warning: no SNAC cached with for this response (%08lx)\n", snacid);
335
336   }
337   
338   i = 10;
339
340   /*
341    * extractuserinfo will give us the basic metaTLV information
342    */
343   i += aim_extractuserinfo(command->data+i, &userinfo);
344   
345   /*
346    * However, in this command, there's usually more TLVs following...
347    */ 
348   tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
349   prof_encoding = aim_gettlv_str(tlvlist, 0x0001, 1);
350   prof = aim_gettlv_str(tlvlist, 0x0002, 1);
351
352   userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
353   if (userfunc)
354     {
355       i = userfunc(sess,
356                    command, 
357                    &userinfo, 
358                    prof_encoding, 
359                    prof); 
360     }
361   
362   free(prof_encoding);
363   free(prof);
364   aim_freetlvchain(&tlvlist);
365
366   return 1;
367 }
This page took 0.052749 seconds and 3 git commands to generate.