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 u_long aim_bos_setprofile(struct aim_session_t *sess,
228 struct aim_conn_t *conn,
231 int packet_profile_len = 0;
232 struct command_tx_struct newpacket;
236 packet_profile_len = 10;
237 /* len: T+L (where t(0001)) */
238 packet_profile_len += 2 + 2;
239 /* len: V (where t(0001)) */
240 packet_profile_len += strlen("text/x-aolrtf");
241 /* len: T+L (where t(0002)) */
242 packet_profile_len += 2 + 2;
243 /* len: V (where t(0002)) */
244 packet_profile_len += strlen(profile);
246 newpacket.type = 0x02;
248 newpacket.conn = conn;
250 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
252 newpacket.commandlen = packet_profile_len;
253 newpacket.data = (char *) malloc(packet_profile_len);
257 i += aim_putsnac(newpacket.data, 0x0002, 0x004, 0x0000, sess->snac_nextid);
260 newpacket.data[i++] = 0x00;
261 newpacket.data[i++] = 0x01;
263 newpacket.data[i++] = 0x00;
264 newpacket.data[i++] = 0x0d;
265 /* TLV v(text/x-aolrtf) */
266 memcpy(&(newpacket.data[i]), "text/x-aolrtf", 0x000d);
270 newpacket.data[i++] = 0x00;
271 newpacket.data[i++] = 0x02;
273 newpacket.data[i++] = (strlen(profile) >> 8) & 0xFF;
274 newpacket.data[i++] = (strlen(profile) & 0xFF);
276 memcpy(&(newpacket.data[i]), profile, strlen(profile));
278 aim_tx_enqueue(sess, &newpacket);
280 return (sess->snac_nextid++);
284 * aim_bos_setgroupperm(mask)
286 * Set group permisson mask. Normally 0x1f.
289 u_long aim_bos_setgroupperm(struct aim_session_t *sess,
290 struct aim_conn_t *conn,
293 return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
297 * aim_bos_clientready()
304 u_long aim_bos_clientready(struct aim_session_t *sess,
305 struct aim_conn_t *conn)
307 u_char command_2[] = {
308 /* placeholders for dynamic data */
309 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
353 int command_2_len = 0x52;
354 struct command_tx_struct newpacket;
358 newpacket.conn = conn;
360 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
361 newpacket.type = 0x02;
362 newpacket.commandlen = command_2_len;
363 newpacket.data = (char *) malloc (newpacket.commandlen);
364 memcpy(newpacket.data, command_2, newpacket.commandlen);
366 /* This write over the dynamic parts of the byte block */
367 aim_putsnac(newpacket.data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
369 aim_tx_enqueue(sess, &newpacket);
371 return (sess->snac_nextid++);
375 * send_login_phase3(int socket)
377 * Request Rate Information.
379 * TODO: Move to aim_conn.
380 * TODO: Move to SNAC interface.
382 u_long aim_bos_reqrate(struct aim_session_t *sess,
383 struct aim_conn_t *conn)
385 return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
389 * send_login_phase3b(int socket)
391 * Rate Information Response Acknowledge.
394 u_long aim_bos_ackrateresp(struct aim_session_t *sess,
395 struct aim_conn_t *conn)
397 struct command_tx_struct newpacket;
401 newpacket.conn = conn;
403 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
404 newpacket.type = 0x02;
405 newpacket.commandlen = 18;
407 newpacket.data = (char *) malloc(newpacket.commandlen);
408 aim_putsnac(newpacket.data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
410 newpacket.data[10] = 0x00;
411 newpacket.data[11] = 0x01;
412 newpacket.data[12] = 0x00;
413 newpacket.data[13] = 0x02;
414 newpacket.data[14] = 0x00;
415 newpacket.data[15] = 0x03;
416 newpacket.data[16] = 0x00;
417 newpacket.data[17] = 0x04;
419 aim_tx_enqueue(sess, &newpacket);
421 return (sess->snac_nextid++);
425 * aim_bos_setprivacyflags()
427 * Sets privacy flags. Normally 0x03.
429 * Bit 1: Allows other AIM users to see how long you've been idle.
433 u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
434 struct aim_conn_t *conn,
437 return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
441 * aim_bos_reqpersonalinfo()
443 * Requests the current user's information. Can't go generic on this one
444 * because aparently it uses SNAC flags.
447 u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
448 struct aim_conn_t *conn)
450 struct command_tx_struct newpacket;
454 newpacket.conn = conn;
456 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
457 newpacket.type = 0x02;
458 newpacket.commandlen = 12;
460 newpacket.data = (char *) malloc(newpacket.commandlen);
461 aim_putsnac(newpacket.data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
463 newpacket.data[10] = 0x0d;
464 newpacket.data[11] = 0xda;
467 aim_tx_enqueue(sess, &newpacket);
469 return (sess->snac_nextid++);
472 u_long aim_setversions(struct aim_session_t *sess,
473 struct aim_conn_t *conn)
475 struct command_tx_struct newpacket;
480 newpacket.conn = conn;
482 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
483 newpacket.type = 0x02;
484 newpacket.commandlen = 10 + (4*13);
486 newpacket.data = (char *) malloc(newpacket.commandlen);
487 i = aim_putsnac(newpacket.data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
489 i += aimutil_put16(newpacket.data+i, 0x0001);
490 i += aimutil_put16(newpacket.data+i, 0x0003);
491 i += aimutil_put16(newpacket.data+i, 0x0002);
492 i += aimutil_put16(newpacket.data+i, 0x0001);
493 i += aimutil_put16(newpacket.data+i, 0x0003);
494 i += aimutil_put16(newpacket.data+i, 0x0001);
495 i += aimutil_put16(newpacket.data+i, 0x0004);
496 i += aimutil_put16(newpacket.data+i, 0x0001);
497 i += aimutil_put16(newpacket.data+i, 0x0006);
498 i += aimutil_put16(newpacket.data+i, 0x0001);
499 i += aimutil_put16(newpacket.data+i, 0x0008);
500 i += aimutil_put16(newpacket.data+i, 0x0001);
501 i += aimutil_put16(newpacket.data+i, 0x0009);
502 i += aimutil_put16(newpacket.data+i, 0x0001);
503 i += aimutil_put16(newpacket.data+i, 0x000a);
504 i += aimutil_put16(newpacket.data+i, 0x0001);
505 i += aimutil_put16(newpacket.data+i, 0x000b);
506 i += aimutil_put16(newpacket.data+i, 0x0002);
507 i += aimutil_put16(newpacket.data+i, 0x000c);
508 i += aimutil_put16(newpacket.data+i, 0x0001);
509 i += aimutil_put16(newpacket.data+i, 0x0015);
510 i += aimutil_put16(newpacket.data+i, 0x0003);
511 i += aimutil_put16(newpacket.data+i, 0x000f);
512 i += aimutil_put16(newpacket.data+i, 0x0001);
513 i += aimutil_put16(newpacket.data+i, 0x0005);
514 i += aimutil_put16(newpacket.data+i, 0x0001);
517 for (j = 0; j < 0x10; j++)
520 i += aimutil_put16(newpacket.data+i, j); /* family */
521 i += aimutil_put16(newpacket.data+i, 0x0003); /* version */
525 aim_tx_enqueue(sess, &newpacket);
527 return (sess->snac_nextid++);
532 * aim_bos_reqservice(serviceid)
537 u_long aim_bos_reqservice(struct aim_session_t *sess,
538 struct aim_conn_t *conn,
541 return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
545 * aim_bos_reqrights()
547 * Request BOS rights.
550 u_long aim_bos_reqrights(struct aim_session_t *sess,
551 struct aim_conn_t *conn)
553 return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
557 * aim_bos_reqbuddyrights()
559 * Request Buddy List rights.
562 u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
563 struct aim_conn_t *conn)
565 return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
569 * Generic routine for sending commands.
572 * I know I can do this in a smarter way...but I'm not thinking straight
575 * I had one big function that handled all three cases, but then it broke
576 * and I split it up into three. But then I fixed it. I just never went
577 * back to the single. I don't see any advantage to doing it either way.
580 u_long aim_genericreq_n(struct aim_session_t *sess,
581 struct aim_conn_t *conn,
582 u_short family, u_short subtype)
584 struct command_tx_struct newpacket;
589 newpacket.conn = conn;
591 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
592 newpacket.type = 0x02;
594 newpacket.commandlen = 10;
596 newpacket.data = (char *) malloc(newpacket.commandlen);
597 memset(newpacket.data, 0x00, newpacket.commandlen);
599 aim_putsnac(newpacket.data, family, subtype, 0x0000, sess->snac_nextid);
601 aim_tx_enqueue(sess, &newpacket);
602 return (sess->snac_nextid++);
609 u_long aim_genericreq_l(struct aim_session_t *sess,
610 struct aim_conn_t *conn,
611 u_short family, u_short subtype, u_long *longdata)
613 struct command_tx_struct newpacket;
616 /* If we don't have data, there's no reason to use this function */
618 return aim_genericreq_n(sess, conn, family, subtype);
623 newpacket.conn = conn;
625 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
627 newpacket.type = 0x02;
629 newpacket.commandlen = 10+sizeof(u_long);
631 newpacket.data = (char *) malloc(newpacket.commandlen);
632 memset(newpacket.data, 0x00, newpacket.commandlen);
634 aim_putsnac(newpacket.data, family, subtype, 0x0000, sess->snac_nextid);
637 newlong = htonl(*longdata);
638 memcpy(&(newpacket.data[10]), &newlong, sizeof(u_long));
640 aim_tx_enqueue(sess, &newpacket);
641 return (sess->snac_nextid++);
644 u_long aim_genericreq_s(struct aim_session_t *sess,
645 struct aim_conn_t *conn,
646 u_short family, u_short subtype, u_short *shortdata)
648 struct command_tx_struct newpacket;
651 /* If we don't have data, there's no reason to use this function */
653 return aim_genericreq_n(sess, conn, family, subtype);
658 newpacket.conn = conn;
660 newpacket.conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
662 newpacket.type = 0x02;
664 newpacket.commandlen = 10+sizeof(u_short);
666 newpacket.data = (char *) malloc(newpacket.commandlen);
667 memset(newpacket.data, 0x00, newpacket.commandlen);
669 aim_putsnac(newpacket.data, family, subtype, 0x0000, sess->snac_nextid);
672 newshort = htons(*shortdata);
673 memcpy(&(newpacket.data[10]), &newshort, sizeof(u_short));
675 aim_tx_enqueue(sess, &newpacket);
676 return (sess->snac_nextid++);
680 * aim_bos_reqlocaterights()
682 * Request Location services rights.
685 u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
686 struct aim_conn_t *conn)
688 return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
692 * aim_bos_reqicbmparaminfo()
694 * Request ICBM parameter information.
697 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
698 struct aim_conn_t *conn)
700 return aim_genericreq_n(sess, conn, 0x0004, 0x0004);