4 * The functions here are responsible for requesting and parsing information-
10 #include "aim.h" /* for most everything */
12 u_long aim_getinfo(struct aim_conn_t *conn, const char *sn)
14 struct command_tx_struct newpacket;
17 newpacket.conn = conn;
19 newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS);
22 newpacket.type = 0x0002;
24 newpacket.commandlen = 12 + 1 + strlen(sn);
25 newpacket.data = (char *) malloc(newpacket.commandlen);
27 aim_putsnac(newpacket.data, 0x0002, 0x0005, 0x0000, aim_snac_nextid);
29 aimutil_put16(newpacket.data+10, 0x0001);
30 aimutil_put8(newpacket.data+12, strlen(sn));
31 aimutil_putstr(newpacket.data+13, sn, strlen(sn));
33 aim_tx_enqueue(&newpacket);
36 struct aim_snac_t snac;
38 snac.id = aim_snac_nextid;
43 snac.data = malloc(strlen(sn)+1);
44 memcpy(snac.data, sn, strlen(sn)+1);
49 return (aim_snac_nextid++);
53 * AIM is fairly regular about providing user info. This
54 * is a generic routine to extract it in its standard form.
56 int aim_extractuserinfo(u_char *buf, struct aim_userinfo_s *outinfo)
68 /* Clear out old data first */
69 memset(outinfo, 0x00, sizeof(struct aim_userinfo_s));
72 * Screen name. Stored as an unterminated string prepended
73 * with an unsigned byte containing its length.
75 memcpy(outinfo->sn, &(buf[i+1]), buf[i]);
76 outinfo->sn[(int)buf[i]] = '\0';
80 * Warning Level. Stored as an unsigned short.
82 outinfo->warnlevel = aimutil_get16(&buf[i]);
86 * TLV Count. Unsigned short representing the number of
87 * Type-Length-Value triples that follow.
89 tlvcnt = aimutil_get16(&buf[i]);
93 * Parse out the Type-Length-Value triples as they're found.
95 while (curtlv < tlvcnt)
97 curtype = aimutil_get16(&buf[i]);
101 * Type = 0x0001: Member Class.
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
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.
116 if (tlv1) /* use only the first */
118 outinfo->class = aimutil_get16(&buf[i+4]);
123 * Type = 0x0002: Member-Since date.
125 * The time/date that the user originally
126 * registered for the service, stored in
130 outinfo->membersince = aimutil_get32(&buf[i+4]);
134 * Type = 0x0003: On-Since date.
136 * The time/date that the user started
137 * their current session, stored in time_t
141 outinfo->onlinesince = aimutil_get32(&buf[i+4]);
145 * Type = 0x0004: Idle time.
147 * Number of seconds since the user
148 * actively used the service.
151 outinfo->idletime = aimutil_get16(&buf[i+4]);
155 * Type = 0x000f: Session Length. (AIM)
156 * Type = 0x0010: Session Length. (AOL)
158 * The duration, in seconds, of the user's
161 * Which TLV type this comes in depends
162 * on the service the user is using (AIM or AOL).
167 outinfo->sessionlen = aimutil_get32(&buf[i+4]);
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.
175 * Either way, inform the owner and attempt
181 int len,z = 0, y = 0, x = 0;
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");
191 x = sprintf(tmpstr, "faim: userinfo: ");
192 for (y = 0; y < 8; y++)
196 sprintf(tmpstr+x, "%02x ", buf[i+4+z]);
203 printf("%s\n", tmpstr);
209 * No matter what, TLV triplets should always look like this:
213 * u_char data[length];
216 i += (2 + 2 + aimutil_get16(&buf[i+2]));
225 * Oncoming Buddy notifications contain a subset of the
226 * user information structure. Its close enough to run
227 * through aim_extractuserinfo() however.
230 int aim_parse_oncoming_middle(struct command_rx_struct *command)
232 struct aim_userinfo_s userinfo;
234 rxcallback_t userfunc=NULL;
237 i += aim_extractuserinfo(command->data+i, &userinfo);
239 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING);
241 i = userfunc(command, &userinfo);
248 * This parses the user info stuff out all nice and pretty then calls
249 * the higher-level callback (in the user app).
252 int aim_parse_userinfo_middle(struct command_rx_struct *command)
254 struct aim_userinfo_s userinfo;
255 char *prof_encoding = NULL;
258 rxcallback_t userfunc=NULL;
261 u_long snacid = 0x000000000;
262 struct aim_snac_t *snac = NULL;
264 snacid = aimutil_get32(&command->data[6]);
265 snac = aim_remsnac(snacid);
273 i += aim_extractuserinfo(command->data+i, &userinfo);
275 if (i < command->commandlen)
277 if (aimutil_get16(&command->data[i]) == 0x0001)
281 len = aimutil_get16(&command->data[i+2]);
283 prof_encoding = (char *) malloc(len+1);
284 memcpy(prof_encoding, &(command->data[i+4]), len);
285 prof_encoding[len] = '\0';
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];
296 if (i < command->commandlen)
298 if (aimutil_get16(&command->data[i]) == 0x0002)
301 len = aimutil_get16(&command->data[i+2]);
303 prof = (char *) malloc(len+1);
304 memcpy(prof, &(command->data[i+4]), len);
308 printf("faim:userinfo: **warning: profile not found, but still have data\n");
311 userfunc = aim_callhandler(command->conn, AIM_CB_FAM_LOC, AIM_CB_LOC_USERINFO);
314 i = userfunc(command,