]> andersk Git - libfaim.git/blame - aim_info.c
- Fixed a robustness problem in aim_handleredirect_middle()
[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{
16 struct command_tx_struct newpacket;
276495a3 17 int i = 0;
18
19 if (!sess || !conn || !sn)
20 return 0;
9de3ca7e 21
22 if (conn)
23 newpacket.conn = conn;
24 else
a25832e6 25 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
9de3ca7e 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
276495a3 33 i = aim_putsnac(newpacket.data, 0x0002, 0x0005, 0x0000, sess->snac_nextid);
9de3ca7e 34
276495a3 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));
9de3ca7e 38
276495a3 39 newpacket.lock = 0;
a25832e6 40 aim_tx_enqueue(sess, &newpacket);
9de3ca7e 41
42 {
43 struct aim_snac_t snac;
44
a25832e6 45 snac.id = sess->snac_nextid;
9de3ca7e 46 snac.family = 0x0002;
47 snac.type = 0x0005;
48 snac.flags = 0x0000;
49
50 snac.data = malloc(strlen(sn)+1);
276495a3 51 strcpy(snac.data, sn);
9de3ca7e 52
a25832e6 53 aim_newsnac(sess, &snac);
9de3ca7e 54 }
55
a25832e6 56 return (sess->snac_nextid++);
9de3ca7e 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 */
63int 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
0c20631f 116 * 0x0020 Away
9de3ca7e 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;
0b4acf97 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;
9de3ca7e 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 */
a25832e6 263int aim_parse_oncoming_middle(struct aim_session_t *sess,
264 struct command_rx_struct *command)
9de3ca7e 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)
a25832e6 275 i = userfunc(sess, command, &userinfo);
9de3ca7e 276
277 return 1;
278}
279
a25832e6 280/*
281 * Offgoing Buddy notifications contain no useful
282 * information other than the name it applies to.
283 *
284 */
285int 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
1a7c2214 292 strncpy(sn, command->data+11, (int)command->data[10]);
293 sn[(int)command->data[10]] = '\0';
a25832e6 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}
9de3ca7e 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 */
a25832e6 307int aim_parse_userinfo_middle(struct aim_session_t *sess,
308 struct command_rx_struct *command)
9de3ca7e 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;
0c20631f 315 struct aim_tlvlist_t *tlvlist;
9de3ca7e 316
317 {
318 u_long snacid = 0x000000000;
319 struct aim_snac_t *snac = NULL;
320
321 snacid = aimutil_get32(&command->data[6]);
a25832e6 322 snac = aim_remsnac(sess, snacid);
9de3ca7e 323
276495a3 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);
9de3ca7e 334
335 }
336
337 i = 10;
9de3ca7e 338
0c20631f 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);
9de3ca7e 350
351 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
352 if (userfunc)
353 {
a25832e6 354 i = userfunc(sess,
355 command,
9de3ca7e 356 &userinfo,
357 prof_encoding,
358 prof);
359 }
0c20631f 360
9de3ca7e 361 free(prof_encoding);
362 free(prof);
0c20631f 363 aim_freetlvchain(&tlvlist);
9de3ca7e 364
365 return 1;
366}
This page took 0.163107 seconds and 5 git commands to generate.