]> andersk Git - libfaim.git/blame - aim_info.c
*** empty log message ***
[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;
17
18 if (conn)
19 newpacket.conn = conn;
20 else
a25832e6 21 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
9de3ca7e 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
a25832e6 29 aim_putsnac(newpacket.data, 0x0002, 0x0005, 0x0000, sess->snac_nextid);
9de3ca7e 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
a25832e6 35 aim_tx_enqueue(sess, &newpacket);
9de3ca7e 36
37 {
38 struct aim_snac_t snac;
39
a25832e6 40 snac.id = sess->snac_nextid;
9de3ca7e 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
a25832e6 48 aim_newsnac(sess, &snac);
9de3ca7e 49 }
50
a25832e6 51 return (sess->snac_nextid++);
9de3ca7e 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 */
58int 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 *
112 * In some odd cases, we can end up with more
113 * than one of these. We only want the first,
114 * as the others may not be something we want.
115 *
116 */
117 case 0x0001:
118 if (tlv1) /* use only the first */
119 break;
120 outinfo->class = aimutil_get16(&buf[i+4]);
121 tlv1++;
122 break;
123
124 /*
125 * Type = 0x0002: Member-Since date.
126 *
127 * The time/date that the user originally
128 * registered for the service, stored in
129 * time_t format
130 */
131 case 0x0002:
132 outinfo->membersince = aimutil_get32(&buf[i+4]);
133 break;
134
135 /*
136 * Type = 0x0003: On-Since date.
137 *
138 * The time/date that the user started
139 * their current session, stored in time_t
140 * format.
141 */
142 case 0x0003:
143 outinfo->onlinesince = aimutil_get32(&buf[i+4]);
144 break;
145
146 /*
147 * Type = 0x0004: Idle time.
148 *
149 * Number of seconds since the user
150 * actively used the service.
151 */
152 case 0x0004:
153 outinfo->idletime = aimutil_get16(&buf[i+4]);
154 break;
155
156 /*
157 * Type = 0x000f: Session Length. (AIM)
158 * Type = 0x0010: Session Length. (AOL)
159 *
160 * The duration, in seconds, of the user's
161 * current session.
162 *
163 * Which TLV type this comes in depends
164 * on the service the user is using (AIM or AOL).
165 *
166 */
167 case 0x000f:
168 case 0x0010:
169 outinfo->sessionlen = aimutil_get32(&buf[i+4]);
170 break;
171
172 /*
173 * Reaching here indicates that either AOL has
174 * added yet another TLV for us to deal with,
175 * or the parsing has gone Terribly Wrong.
176 *
177 * Either way, inform the owner and attempt
178 * recovery.
179 *
180 */
181 default:
182 {
183 int len,z = 0, y = 0, x = 0;
184 char tmpstr[80];
185 printf("faim: userinfo: **warning: unexpected TLV:\n");
186 printf("faim: userinfo: sn =%s\n", outinfo->sn);
187 printf("faim: userinfo: curtlv=0x%04x\n", curtlv);
188 printf("faim: userinfo: type =0x%04x\n",aimutil_get16(&buf[i]));
189 printf("faim: userinfo: length=0x%04x\n", len = aimutil_get16(&buf[i+2]));
190 printf("faim: userinfo: data: \n");
191 while (z<len)
192 {
193 x = sprintf(tmpstr, "faim: userinfo: ");
194 for (y = 0; y < 8; y++)
195 {
196 if (z<len)
197 {
198 sprintf(tmpstr+x, "%02x ", buf[i+4+z]);
199 z++;
200 x += 3;
201 }
202 else
203 break;
204 }
205 printf("%s\n", tmpstr);
206 }
207 }
208 break;
209 }
210 /*
211 * No matter what, TLV triplets should always look like this:
212 *
213 * u_short type;
214 * u_short length;
215 * u_char data[length];
216 *
217 */
218 i += (2 + 2 + aimutil_get16(&buf[i+2]));
219
220 curtlv++;
221 }
222
223 return i;
224}
225
226/*
227 * Oncoming Buddy notifications contain a subset of the
228 * user information structure. Its close enough to run
229 * through aim_extractuserinfo() however.
230 *
231 */
a25832e6 232int aim_parse_oncoming_middle(struct aim_session_t *sess,
233 struct command_rx_struct *command)
9de3ca7e 234{
235 struct aim_userinfo_s userinfo;
236 u_int i = 0;
237 rxcallback_t userfunc=NULL;
238
239 i = 10;
240 i += aim_extractuserinfo(command->data+i, &userinfo);
241
242 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
243 if (userfunc)
a25832e6 244 i = userfunc(sess, command, &userinfo);
9de3ca7e 245
246 return 1;
247}
248
a25832e6 249/*
250 * Offgoing Buddy notifications contain no useful
251 * information other than the name it applies to.
252 *
253 */
254int aim_parse_offgoing_middle(struct aim_session_t *sess,
255 struct command_rx_struct *command)
256{
257 char sn[MAXSNLEN+1];
258 u_int i = 0;
259 rxcallback_t userfunc=NULL;
260
261 /* Protect against future SN length extensions */
262 strncpy(sn, command->data+11, (strlen(sn)<=MAXSNLEN)?strlen(sn):MAXSNLEN);
263
264 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING);
265 if (userfunc)
266 i = userfunc(sess, command, sn);
267
268 return 1;
269}
9de3ca7e 270
271/*
272 * This parses the user info stuff out all nice and pretty then calls
273 * the higher-level callback (in the user app).
274 *
275 */
a25832e6 276int aim_parse_userinfo_middle(struct aim_session_t *sess,
277 struct command_rx_struct *command)
9de3ca7e 278{
279 struct aim_userinfo_s userinfo;
280 char *prof_encoding = NULL;
281 char *prof = NULL;
282 u_int i = 0;
283 rxcallback_t userfunc=NULL;
284
285 {
286 u_long snacid = 0x000000000;
287 struct aim_snac_t *snac = NULL;
288
289 snacid = aimutil_get32(&command->data[6]);
a25832e6 290 snac = aim_remsnac(sess, snacid);
9de3ca7e 291
292 free(snac->data);
293 free(snac);
294
295 }
296
297 i = 10;
298 i += aim_extractuserinfo(command->data+i, &userinfo);
299
300 if (i < command->commandlen)
301 {
302 if (aimutil_get16(&command->data[i]) == 0x0001)
303 {
304 int len = 0;
305
306 len = aimutil_get16(&command->data[i+2]);
307
308 prof_encoding = (char *) malloc(len+1);
309 memcpy(prof_encoding, &(command->data[i+4]), len);
310 prof_encoding[len] = '\0';
311
312 i += (2+2+len);
313 }
314 else
315 {
a25832e6 316 printf("faim: userinfo: **warning: unexpected TLV after TLVblock t(%04x) l(%04x)\n", aimutil_get16(command->data+i), aimutil_get16(command->data+i+2));
9de3ca7e 317 i += 2 + 2 + command->data[i+3];
318 }
319 }
320
321 if (i < command->commandlen)
322 {
323 if (aimutil_get16(&command->data[i]) == 0x0002)
324 {
325 int len = 0;
326 len = aimutil_get16(&command->data[i+2]);
327
328 prof = (char *) malloc(len+1);
329 memcpy(prof, &(command->data[i+4]), len);
330 prof[len] = '\0';
331 }
332 else
333 printf("faim:userinfo: **warning: profile not found, but still have data\n");
334 }
335
336 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
337 if (userfunc)
338 {
a25832e6 339 i = userfunc(sess,
340 command,
9de3ca7e 341 &userinfo,
342 prof_encoding,
343 prof);
344 }
345
346 free(prof_encoding);
347 free(prof);
348
349 return 1;
350}
This page took 0.09272 seconds and 5 git commands to generate.