5 * TODO: Seperate a lot of this into an aim_bos.c.
19 * Should set your current idle time in seconds. Idealy, OSCAR should
20 * do this for us. But, it doesn't. The client must call this to set idle
24 u_long aim_bos_setidle(struct aim_session_t *sess,
25 struct aim_conn_t *conn,
28 return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime);
33 * aim_bos_changevisibility(conn, changtype, namelist)
35 * Changes your visibility depending on changetype:
37 * AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you
38 * AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list
39 * AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names
40 * AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again
42 * list should be a list of
43 * screen names in the form "Screen Name One&ScreenNameTwo&" etc.
45 * Equivelents to options in WinAIM:
46 * - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD
47 * with only your name on it.
48 * - Allow only users on my Buddy List: Send an
49 * AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your
51 * - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD
52 * with everyone listed that you want to see you.
53 * - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only
54 * yourself in the list
55 * - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with
56 * the list of users to be blocked
60 u_long aim_bos_changevisibility(struct aim_session_t *sess,
61 struct aim_conn_t *conn,
62 int changetype, char *denylist)
64 struct command_tx_struct newpacket;
67 char *localcpy = NULL;
78 newpacket.conn = conn;
80 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
82 newpacket.type = 0x02;
84 localcpy = (char *) malloc(strlen(denylist)+1);
85 memcpy(localcpy, denylist, strlen(denylist)+1);
87 listcount = aimutil_itemcnt(localcpy, '&');
88 newpacket.commandlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9;
91 newpacket.data = (char *) malloc(newpacket.commandlen);
92 memset(newpacket.data, 0x00, newpacket.commandlen);
96 case AIM_VISIBILITYCHANGE_PERMITADD: subtype = 0x05; break;
97 case AIM_VISIBILITYCHANGE_PERMITREMOVE: subtype = 0x06; break;
98 case AIM_VISIBILITYCHANGE_DENYADD: subtype = 0x07; break;
99 case AIM_VISIBILITYCHANGE_DENYREMOVE: subtype = 0x08; break;
101 free(newpacket.data);
105 /* We actually DO NOT send a SNAC ID with this one! */
106 aim_putsnac(newpacket.data, 0x0009, subtype, 0x00, 0);
108 j = 10; /* the next byte */
110 for (i=0; (i < (listcount - 1)) && (i < 99); i++)
112 tmpptr = aimutil_itemidx(localcpy, i, '&');
114 newpacket.data[j] = strlen(tmpptr);
115 memcpy(&(newpacket.data[j+1]), tmpptr, strlen(tmpptr));
116 j += strlen(tmpptr)+1;
123 aim_tx_enqueue(sess, &newpacket);
125 return (sess->snac_nextid); /* dont increment */
132 * aim_bos_setbuddylist(buddylist)
134 * This just builds the "set buddy list" command then queues it.
136 * buddy_list = "Screen Name One&ScreenNameTwo&";
138 * TODO: Clean this up.
141 u_long aim_bos_setbuddylist(struct aim_session_t *sess,
142 struct aim_conn_t *conn,
147 struct command_tx_struct newpacket;
149 int packet_login_phase3c_hi_b_len = 0;
151 char *localcpy = NULL;
154 packet_login_phase3c_hi_b_len = 16; /* 16b for FLAP and SNAC headers */
156 /* bail out if we can't make the packet */
157 if (buddy_list == NULL)
159 printf("\nNO BUDDIES! ARE YOU THAT LONELY???\n");
163 printf("****buddy list: %s\n", buddy_list);
164 printf("****buddy list len: %d (%x)\n", strlen(buddy_list), strlen(buddy_list));
167 localcpy = (char *) malloc(strlen(buddy_list)+1);
168 memcpy(localcpy, buddy_list, strlen(buddy_list)+1);
171 tmpptr = strtok(localcpy, "&");
172 while ((tmpptr != NULL) && (i < 100))
175 printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
177 packet_login_phase3c_hi_b_len += strlen(tmpptr)+1;
179 tmpptr = strtok(NULL, "&");
182 printf("*** send buddy list len: %d (%x)\n", packet_login_phase3c_hi_b_len, packet_login_phase3c_hi_b_len);
186 newpacket.type = 0x02;
188 newpacket.conn = conn;
190 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
191 newpacket.commandlen = packet_login_phase3c_hi_b_len - 6;
194 newpacket.data = (char *) malloc(newpacket.commandlen);
196 aim_putsnac(newpacket.data, 0x0003, 0x0004, 0x0000, sess->snac_nextid);
198 j = 10; /* the next byte */
201 tmpptr = strtok(buddy_list, "&");
202 while ((tmpptr != NULL) & (i < 100))
205 printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
207 newpacket.data[j] = strlen(tmpptr);
208 memcpy(&(newpacket.data[j+1]), tmpptr, strlen(tmpptr));
209 j += strlen(tmpptr)+1;
211 tmpptr = strtok(NULL, "&");
216 aim_tx_enqueue(sess, &newpacket);
218 return (sess->snac_nextid++);
222 * aim_bos_setprofile(profile)
224 * Gives BOS your profile.
227 * The large data chunk given here is of unknown decoding.
228 * What I do know is that each 0x20 byte repetition
229 * represents a capability. People with only the
230 * first two reptitions can support normal messaging
231 * and chat (client version 2.0 or 3.0). People with
232 * the third as well can also support voice chat (client
233 * version 3.5 or higher). IOW, if we don't send this,
234 * we won't get chat invitations (get "software doesn't
235 * support chat" error).
237 * This data is broadcast along with your oncoming
238 * buddy command to everyone who has you on their
239 * buddy list, as a type 0x0002 TLV.
242 u_long aim_bos_setprofile(struct aim_session_t *sess,
243 struct aim_conn_t *conn,
246 struct command_tx_struct newpacket;
248 u_char funkydata[] = {
249 0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
250 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
251 0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,
252 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
254 0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,
255 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
256 0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
257 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
259 0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
260 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00,
261 0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
262 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
265 newpacket.type = 0x02;
267 newpacket.conn = conn;
269 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
271 newpacket.commandlen = 1152+strlen(profile)+1; /*arbitrarily large */
272 newpacket.data = (char *) malloc(newpacket.commandlen);
274 i += aim_putsnac(newpacket.data, 0x0002, 0x004, 0x0000, sess->snac_nextid);
275 i += aim_puttlv_str(newpacket.data+i, 0x0001, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
276 i += aim_puttlv_str(newpacket.data+i, 0x0002, strlen(profile), profile);
277 /* why do we send this twice? */
278 i += aim_puttlv_str(newpacket.data+i, 0x0003, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
280 /* a blank TLV 0x0004 --- not sure what this is either */
281 i += aimutil_put16(newpacket.data+i, 0x0004);
282 i += aimutil_put16(newpacket.data+i, 0x0000);
284 /* Capability information. */
285 i += aim_puttlv_str(newpacket.data+i, 0x0005, 0x0060, funkydata);
287 newpacket.commandlen = i;
288 aim_tx_enqueue(sess, &newpacket);
290 return (sess->snac_nextid++);
294 * aim_bos_setgroupperm(mask)
296 * Set group permisson mask. Normally 0x1f.
299 u_long aim_bos_setgroupperm(struct aim_session_t *sess,
300 struct aim_conn_t *conn,
303 return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
307 * aim_bos_clientready()
314 u_long aim_bos_clientready(struct aim_session_t *sess,
315 struct aim_conn_t *conn)
317 u_char command_2[] = {
318 /* placeholders for dynamic data */
319 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
363 int command_2_len = 0x52;
364 struct command_tx_struct newpacket;
368 newpacket.conn = conn;
370 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
371 newpacket.type = 0x02;
372 newpacket.commandlen = command_2_len;
373 newpacket.data = (char *) malloc (newpacket.commandlen);
374 memcpy(newpacket.data, command_2, newpacket.commandlen);
376 /* This write over the dynamic parts of the byte block */
377 aim_putsnac(newpacket.data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
379 aim_tx_enqueue(sess, &newpacket);
381 return (sess->snac_nextid++);
385 * send_login_phase3(int socket)
387 * Request Rate Information.
389 * TODO: Move to aim_conn.
390 * TODO: Move to SNAC interface.
392 u_long aim_bos_reqrate(struct aim_session_t *sess,
393 struct aim_conn_t *conn)
395 return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
399 * send_login_phase3b(int socket)
401 * Rate Information Response Acknowledge.
404 u_long aim_bos_ackrateresp(struct aim_session_t *sess,
405 struct aim_conn_t *conn)
407 struct command_tx_struct newpacket;
411 newpacket.conn = conn;
413 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
414 newpacket.type = 0x02;
415 newpacket.commandlen = 18;
417 newpacket.data = (char *) malloc(newpacket.commandlen);
418 aim_putsnac(newpacket.data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
420 newpacket.data[10] = 0x00;
421 newpacket.data[11] = 0x01;
422 newpacket.data[12] = 0x00;
423 newpacket.data[13] = 0x02;
424 newpacket.data[14] = 0x00;
425 newpacket.data[15] = 0x03;
426 newpacket.data[16] = 0x00;
427 newpacket.data[17] = 0x04;
429 aim_tx_enqueue(sess, &newpacket);
431 return (sess->snac_nextid++);
435 * aim_bos_setprivacyflags()
437 * Sets privacy flags. Normally 0x03.
439 * Bit 1: Allows other AIM users to see how long you've been idle.
443 u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
444 struct aim_conn_t *conn,
447 return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
451 * aim_bos_reqpersonalinfo()
453 * Requests the current user's information. Can't go generic on this one
454 * because aparently it uses SNAC flags.
457 u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
458 struct aim_conn_t *conn)
460 struct command_tx_struct newpacket;
464 newpacket.conn = conn;
466 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
467 newpacket.type = 0x02;
468 newpacket.commandlen = 12;
470 newpacket.data = (char *) malloc(newpacket.commandlen);
471 aim_putsnac(newpacket.data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
473 newpacket.data[10] = 0x0d;
474 newpacket.data[11] = 0xda;
477 aim_tx_enqueue(sess, &newpacket);
479 return (sess->snac_nextid++);
482 u_long aim_setversions(struct aim_session_t *sess,
483 struct aim_conn_t *conn)
485 struct command_tx_struct newpacket;
490 newpacket.conn = conn;
492 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
493 newpacket.type = 0x02;
494 newpacket.commandlen = 10 + (4*11);
496 newpacket.data = (char *) malloc(newpacket.commandlen);
497 i = aim_putsnac(newpacket.data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
499 i += aimutil_put16(newpacket.data+i, 0x0001);
500 i += aimutil_put16(newpacket.data+i, 0x0003);
502 i += aimutil_put16(newpacket.data+i, 0x0002);
503 i += aimutil_put16(newpacket.data+i, 0x0001);
505 i += aimutil_put16(newpacket.data+i, 0x0003);
506 i += aimutil_put16(newpacket.data+i, 0x0001);
508 i += aimutil_put16(newpacket.data+i, 0x0004);
509 i += aimutil_put16(newpacket.data+i, 0x0001);
511 i += aimutil_put16(newpacket.data+i, 0x0006);
512 i += aimutil_put16(newpacket.data+i, 0x0001);
514 i += aimutil_put16(newpacket.data+i, 0x0008);
515 i += aimutil_put16(newpacket.data+i, 0x0001);
517 i += aimutil_put16(newpacket.data+i, 0x0009);
518 i += aimutil_put16(newpacket.data+i, 0x0001);
520 i += aimutil_put16(newpacket.data+i, 0x000a);
521 i += aimutil_put16(newpacket.data+i, 0x0001);
523 i += aimutil_put16(newpacket.data+i, 0x000b);
524 i += aimutil_put16(newpacket.data+i, 0x0002);
526 i += aimutil_put16(newpacket.data+i, 0x000c);
527 i += aimutil_put16(newpacket.data+i, 0x0001);
529 i += aimutil_put16(newpacket.data+i, 0x0015);
530 i += aimutil_put16(newpacket.data+i, 0x0001);
533 for (j = 0; j < 0x10; j++)
536 i += aimutil_put16(newpacket.data+i, j); /* family */
537 i += aimutil_put16(newpacket.data+i, 0x0003); /* version */
541 aim_tx_enqueue(sess, &newpacket);
543 return (sess->snac_nextid++);
548 * aim_bos_reqservice(serviceid)
553 u_long aim_bos_reqservice(struct aim_session_t *sess,
554 struct aim_conn_t *conn,
557 return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
561 * aim_bos_reqrights()
563 * Request BOS rights.
566 u_long aim_bos_reqrights(struct aim_session_t *sess,
567 struct aim_conn_t *conn)
569 return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
573 * aim_bos_reqbuddyrights()
575 * Request Buddy List rights.
578 u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
579 struct aim_conn_t *conn)
581 return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
585 * Generic routine for sending commands.
588 * I know I can do this in a smarter way...but I'm not thinking straight
591 * I had one big function that handled all three cases, but then it broke
592 * and I split it up into three. But then I fixed it. I just never went
593 * back to the single. I don't see any advantage to doing it either way.
596 u_long aim_genericreq_n(struct aim_session_t *sess,
597 struct aim_conn_t *conn,
598 u_short family, u_short subtype)
600 struct command_tx_struct newpacket;
605 newpacket.conn = conn;
607 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
608 newpacket.type = 0x02;
610 newpacket.commandlen = 10;
612 newpacket.data = (char *) malloc(newpacket.commandlen);
613 memset(newpacket.data, 0x00, newpacket.commandlen);
615 aim_putsnac(newpacket.data, family, subtype, 0x0000, sess->snac_nextid);
617 aim_tx_enqueue(sess, &newpacket);
618 return (sess->snac_nextid++);
625 u_long aim_genericreq_l(struct aim_session_t *sess,
626 struct aim_conn_t *conn,
627 u_short family, u_short subtype, u_long *longdata)
629 struct command_tx_struct newpacket;
632 /* If we don't have data, there's no reason to use this function */
634 return aim_genericreq_n(sess, conn, family, subtype);
639 newpacket.conn = conn;
641 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
643 newpacket.type = 0x02;
645 newpacket.commandlen = 10+sizeof(u_long);
647 newpacket.data = (char *) malloc(newpacket.commandlen);
648 memset(newpacket.data, 0x00, newpacket.commandlen);
650 aim_putsnac(newpacket.data, family, subtype, 0x0000, sess->snac_nextid);
653 newlong = htonl(*longdata);
654 memcpy(&(newpacket.data[10]), &newlong, sizeof(u_long));
656 aim_tx_enqueue(sess, &newpacket);
657 return (sess->snac_nextid++);
660 u_long aim_genericreq_s(struct aim_session_t *sess,
661 struct aim_conn_t *conn,
662 u_short family, u_short subtype, u_short *shortdata)
664 struct command_tx_struct newpacket;
667 /* If we don't have data, there's no reason to use this function */
669 return aim_genericreq_n(sess, conn, family, subtype);
674 newpacket.conn = conn;
676 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
678 newpacket.type = 0x02;
680 newpacket.commandlen = 10+sizeof(u_short);
682 newpacket.data = (char *) malloc(newpacket.commandlen);
683 memset(newpacket.data, 0x00, newpacket.commandlen);
685 aim_putsnac(newpacket.data, family, subtype, 0x0000, sess->snac_nextid);
688 newshort = htons(*shortdata);
689 memcpy(&(newpacket.data[10]), &newshort, sizeof(u_short));
691 aim_tx_enqueue(sess, &newpacket);
692 return (sess->snac_nextid++);
696 * aim_bos_reqlocaterights()
698 * Request Location services rights.
701 u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
702 struct aim_conn_t *conn)
704 return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
708 * aim_bos_reqicbmparaminfo()
710 * Request ICBM parameter information.
713 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
714 struct aim_conn_t *conn)
716 return aim_genericreq_n(sess, conn, 0x0004, 0x0004);