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
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.
118 if (tlv1) /* use only the first */
120 outinfo->class = aimutil_get16(&buf[i+4]);
125 * Type = 0x0002: Member-Since date.
127 * The time/date that the user originally
128 * registered for the service, stored in
132 outinfo->membersince = aimutil_get32(&buf[i+4]);
136 * Type = 0x0003: On-Since date.
138 * The time/date that the user started
139 * their current session, stored in time_t
143 outinfo->onlinesince = aimutil_get32(&buf[i+4]);
147 * Type = 0x0004: Idle time.
149 * Number of seconds since the user
150 * actively used the service.
153 outinfo->idletime = aimutil_get16(&buf[i+4]);
157 * Type = 0x000f: Session Length. (AIM)
158 * Type = 0x0010: Session Length. (AOL)
160 * The duration, in seconds, of the user's
163 * Which TLV type this comes in depends
164 * on the service the user is using (AIM or AOL).
169 outinfo->sessionlen = aimutil_get32(&buf[i+4]);
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.
177 * Either way, inform the owner and attempt
183 int len,z = 0, y = 0, x = 0;
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");
193 x = sprintf(tmpstr, "faim: userinfo: ");
194 for (y = 0; y < 8; y++)
198 sprintf(tmpstr+x, "%02x ", buf[i+4+z]);
205 printf("%s\n", tmpstr);
211 * No matter what, TLV triplets should always look like this:
215 * u_char data[length];
218 i += (2 + 2 + aimutil_get16(&buf[i+2]));
227 * Oncoming Buddy notifications contain a subset of the
228 * user information structure. Its close enough to run
229 * through aim_extractuserinfo() however.
232 int aim_parse_oncoming_middle(struct aim_session_t *sess,
233 struct command_rx_struct *command)
235 struct aim_userinfo_s userinfo;
237 rxcallback_t userfunc=NULL;
240 i += aim_extractuserinfo(command->data+i, &userinfo);
242 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
244 i = userfunc(sess, command, &userinfo);
250 * Offgoing Buddy notifications contain no useful
251 * information other than the name it applies to.
254 int aim_parse_offgoing_middle(struct aim_session_t *sess,
255 struct command_rx_struct *command)
259 rxcallback_t userfunc=NULL;
261 /* Protect against future SN length extensions */
262 strncpy(sn, command->data+11, (((int)(command->data+10))<=MAXSNLEN)?(int)command->data+10:MAXSNLEN);
264 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING);
266 i = userfunc(sess, command, sn);
272 * This parses the user info stuff out all nice and pretty then calls
273 * the higher-level callback (in the user app).
276 int aim_parse_userinfo_middle(struct aim_session_t *sess,
277 struct command_rx_struct *command)
279 struct aim_userinfo_s userinfo;
280 char *prof_encoding = NULL;
283 rxcallback_t userfunc=NULL;
286 u_long snacid = 0x000000000;
287 struct aim_snac_t *snac = NULL;
289 snacid = aimutil_get32(&command->data[6]);
290 snac = aim_remsnac(sess, snacid);
298 i += aim_extractuserinfo(command->data+i, &userinfo);
300 if (i < command->commandlen)
302 if (aimutil_get16(&command->data[i]) == 0x0001)
306 len = aimutil_get16(&command->data[i+2]);
308 prof_encoding = (char *) malloc(len+1);
309 memcpy(prof_encoding, &(command->data[i+4]), len);
310 prof_encoding[len] = '\0';
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));
317 i += 2 + 2 + command->data[i+3];
321 if (i < command->commandlen)
323 if (aimutil_get16(&command->data[i]) == 0x0002)
326 len = aimutil_get16(&command->data[i+2]);
328 prof = (char *) malloc(len+1);
329 memcpy(prof, &(command->data[i+4]), len);
333 printf("faim:userinfo: **warning: profile not found, but still have data\n");
336 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);