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