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