4 * The functions here are responsible for requesting and parsing information-
12 u_long aim_getinfo(struct aim_session_t *sess,
13 struct aim_conn_t *conn,
16 struct command_tx_struct newpacket;
19 newpacket.conn = conn;
21 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
24 newpacket.type = 0x0002;
26 newpacket.commandlen = 12 + 1 + strlen(sn);
27 newpacket.data = (char *) malloc(newpacket.commandlen);
29 aim_putsnac(newpacket.data, 0x0002, 0x0005, 0x0000, sess->snac_nextid);
31 aimutil_put16(newpacket.data+10, 0x0001);
32 aimutil_put8(newpacket.data+12, strlen(sn));
33 aimutil_putstr(newpacket.data+13, sn, strlen(sn));
35 aim_tx_enqueue(sess, &newpacket);
38 struct aim_snac_t snac;
40 snac.id = sess->snac_nextid;
45 snac.data = malloc(strlen(sn)+1);
46 memcpy(snac.data, sn, strlen(sn)+1);
48 aim_newsnac(sess, &snac);
51 return (sess->snac_nextid++);
55 * AIM is fairly regular about providing user info. This
56 * is a generic routine to extract it in its standard form.
58 int aim_extractuserinfo(u_char *buf, struct aim_userinfo_s *outinfo)
70 /* Clear out old data first */
71 memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
74 * Screen name. Stored as an unterminated string prepended
75 * with an unsigned byte containing its length.
77 memcpy(outinfo->sn, &(buf[i+1]), buf[i]);
78 outinfo->sn[(int)buf[i]] = '\0';
82 * Warning Level. Stored as an unsigned short.
84 outinfo->warnlevel = aimutil_get16(&buf[i]);
88 * TLV Count. Unsigned short representing the number of
89 * Type-Length-Value triples that follow.
91 tlvcnt = aimutil_get16(&buf[i]);
95 * Parse out the Type-Length-Value triples as they're found.
97 while (curtlv < tlvcnt)
99 curtype = aimutil_get16(&buf[i]);
103 * Type = 0x0001: Member Class.
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
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.
119 if (tlv1) /* use only the first */
121 outinfo->class = aimutil_get16(&buf[i+4]);
126 * Type = 0x0002: Member-Since date.
128 * The time/date that the user originally
129 * registered for the service, stored in
133 outinfo->membersince = aimutil_get32(&buf[i+4]);
137 * Type = 0x0003: On-Since date.
139 * The time/date that the user started
140 * their current session, stored in time_t
144 outinfo->onlinesince = aimutil_get32(&buf[i+4]);
148 * Type = 0x0004: Idle time.
150 * Number of seconds since the user
151 * actively used the service.
154 outinfo->idletime = aimutil_get16(&buf[i+4]);
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.
173 * Unknown. Always of zero length, and always only
183 * Type = 0x000f: Session Length. (AIM)
184 * Type = 0x0010: Session Length. (AOL)
186 * The duration, in seconds, of the user's
189 * Which TLV type this comes in depends
190 * on the service the user is using (AIM or AOL).
195 outinfo->sessionlen = aimutil_get32(&buf[i+4]);
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.
203 * Either way, inform the owner and attempt
209 int len,z = 0, y = 0, x = 0;
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");
219 x = sprintf(tmpstr, "faim: userinfo: ");
220 for (y = 0; y < 8; y++)
224 sprintf(tmpstr+x, "%02x ", buf[i+4+z]);
231 printf("%s\n", tmpstr);
237 * No matter what, TLV triplets should always look like this:
241 * u_char data[length];
244 i += (2 + 2 + aimutil_get16(&buf[i+2]));
253 * Oncoming Buddy notifications contain a subset of the
254 * user information structure. Its close enough to run
255 * through aim_extractuserinfo() however.
258 int aim_parse_oncoming_middle(struct aim_session_t *sess,
259 struct command_rx_struct *command)
261 struct aim_userinfo_s userinfo;
263 rxcallback_t userfunc=NULL;
266 i += aim_extractuserinfo(command->data+i, &userinfo);
268 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
270 i = userfunc(sess, command, &userinfo);
276 * Offgoing Buddy notifications contain no useful
277 * information other than the name it applies to.
280 int aim_parse_offgoing_middle(struct aim_session_t *sess,
281 struct command_rx_struct *command)
285 rxcallback_t userfunc=NULL;
287 /* Protect against future SN length extensions */
288 strncpy(sn, command->data+11, (((int)(command->data+10))<=MAXSNLEN)?(int)command->data+10:MAXSNLEN);
290 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING);
292 i = userfunc(sess, command, sn);
298 * This parses the user info stuff out all nice and pretty then calls
299 * the higher-level callback (in the user app).
302 int aim_parse_userinfo_middle(struct aim_session_t *sess,
303 struct command_rx_struct *command)
305 struct aim_userinfo_s userinfo;
306 char *prof_encoding = NULL;
309 rxcallback_t userfunc=NULL;
310 struct aim_tlvlist_t *tlvlist;
313 u_long snacid = 0x000000000;
314 struct aim_snac_t *snac = NULL;
316 snacid = aimutil_get32(&command->data[6]);
317 snac = aim_remsnac(sess, snacid);
327 * extractuserinfo will give us the basic metaTLV information
329 i += aim_extractuserinfo(command->data+i, &userinfo);
332 * However, in this command, there's usually more TLVs following...
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);
338 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
350 aim_freetlvchain(&tlvlist);