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;
68 char *localcpy = NULL;
76 localcpy = (char *) malloc(strlen(denylist)+1);
77 memcpy(localcpy, denylist, strlen(denylist)+1);
79 listcount = aimutil_itemcnt(localcpy, '&');
80 packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9;
82 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packlen)))
89 case AIM_VISIBILITYCHANGE_PERMITADD: subtype = 0x05; break;
90 case AIM_VISIBILITYCHANGE_PERMITREMOVE: subtype = 0x06; break;
91 case AIM_VISIBILITYCHANGE_DENYADD: subtype = 0x07; break;
92 case AIM_VISIBILITYCHANGE_DENYREMOVE: subtype = 0x08; break;
94 free(newpacket->data);
99 /* We actually DO NOT send a SNAC ID with this one! */
100 aim_putsnac(newpacket->data, 0x0009, subtype, 0x00, 0);
102 j = 10; /* the next byte */
104 for (i=0; (i < (listcount - 1)) && (i < 99); i++)
106 tmpptr = aimutil_itemidx(localcpy, i, '&');
108 newpacket->data[j] = strlen(tmpptr);
109 memcpy(&(newpacket->data[j+1]), tmpptr, strlen(tmpptr));
110 j += strlen(tmpptr)+1;
117 aim_tx_enqueue(sess, newpacket);
119 return (sess->snac_nextid); /* dont increment */
126 * aim_bos_setbuddylist(buddylist)
128 * This just builds the "set buddy list" command then queues it.
130 * buddy_list = "Screen Name One&ScreenNameTwo&";
132 * TODO: Clean this up.
134 * XXX: I can't stress the TODO enough.
137 u_long aim_bos_setbuddylist(struct aim_session_t *sess,
138 struct aim_conn_t *conn,
143 struct command_tx_struct *newpacket;
145 int packet_login_phase3c_hi_b_len = 0;
147 char *localcpy = NULL;
150 packet_login_phase3c_hi_b_len = 16; /* 16b for FLAP and SNAC headers */
152 /* bail out if we can't make the packet */
157 localcpy = (char *) malloc(strlen(buddy_list)+1);
158 memcpy(localcpy, buddy_list, strlen(buddy_list)+1);
161 tmpptr = strtok(localcpy, "&");
162 while ((tmpptr != NULL) && (i < 100))
165 printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
167 packet_login_phase3c_hi_b_len += strlen(tmpptr)+1;
169 tmpptr = strtok(NULL, "&");
172 printf("*** send buddy list len: %d (%x)\n", packet_login_phase3c_hi_b_len, packet_login_phase3c_hi_b_len);
176 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packet_login_phase3c_hi_b_len - 6)))
181 aim_putsnac(newpacket->data, 0x0003, 0x0004, 0x0000, sess->snac_nextid);
183 j = 10; /* the next byte */
186 tmpptr = strtok(buddy_list, "&");
187 while ((tmpptr != NULL) & (i < 100))
190 printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
192 newpacket->data[j] = strlen(tmpptr);
193 memcpy(&(newpacket->data[j+1]), tmpptr, strlen(tmpptr));
194 j += strlen(tmpptr)+1;
196 tmpptr = strtok(NULL, "&");
201 aim_tx_enqueue(sess, newpacket);
203 return (sess->snac_nextid++);
207 * aim_bos_setprofile(profile)
209 * Gives BOS your profile.
213 u_long aim_bos_setprofile(struct aim_session_t *sess,
214 struct aim_conn_t *conn,
219 struct command_tx_struct *newpacket;
220 int i = 0, tmp, caplen;
222 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152+strlen(profile)+1+(awaymsg?strlen(awaymsg):0))))
225 i += aim_putsnac(newpacket->data, 0x0002, 0x004, 0x0000, sess->snac_nextid);
226 i += aim_puttlv_str(newpacket->data+i, 0x0001, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
227 i += aim_puttlv_str(newpacket->data+i, 0x0002, strlen(profile), profile);
228 /* why do we send this twice? */
229 i += aim_puttlv_str(newpacket->data+i, 0x0003, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
231 /* Away message -- we send this no matter what, even if its blank */
233 i += aim_puttlv_str(newpacket->data+i, 0x0004, strlen(awaymsg), awaymsg);
235 i += aim_puttlv_str(newpacket->data+i, 0x0004, 0x0000, NULL);
237 /* Capability information. */
239 tmp = (i += aimutil_put16(newpacket->data+i, 0x0005));
240 i += aimutil_put16(newpacket->data+i, 0x0000); /* rewritten later */
241 i += (caplen = aim_putcap(newpacket->data+i, 512, caps));
242 aimutil_put16(newpacket->data+tmp, caplen); /* rewrite TLV size */
244 newpacket->commandlen = i;
245 aim_tx_enqueue(sess, newpacket);
247 return (sess->snac_nextid++);
251 * aim_bos_setgroupperm(mask)
253 * Set group permisson mask. Normally 0x1f (all classes).
255 * The group permission mask allows you to keep users of a certain
256 * class or classes from talking to you. The mask should be
257 * a bitwise OR of all the user classes you want to see you.
260 u_long aim_bos_setgroupperm(struct aim_session_t *sess,
261 struct aim_conn_t *conn,
264 return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
268 * aim_bos_clientready()
275 u_long aim_bos_clientready(struct aim_session_t *sess,
276 struct aim_conn_t *conn)
278 u_char command_2[] = {
279 /* placeholders for dynamic data */
280 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
324 int command_2_len = 0x52;
325 struct command_tx_struct *newpacket;
327 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, command_2_len)))
332 memcpy(newpacket->data, command_2, command_2_len);
334 /* This write over the dynamic parts of the byte block */
335 aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
337 aim_tx_enqueue(sess, newpacket);
339 return (sess->snac_nextid++);
343 * Request Rate Information.
346 u_long aim_bos_reqrate(struct aim_session_t *sess,
347 struct aim_conn_t *conn)
349 return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
353 * Rate Information Response Acknowledge.
356 u_long aim_bos_ackrateresp(struct aim_session_t *sess,
357 struct aim_conn_t *conn)
359 struct command_tx_struct *newpacket;
360 int packlen = 18, i=0;
362 if (conn->type != AIM_CONN_TYPE_BOS)
365 if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packlen)));
369 i = aim_putsnac(newpacket->data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
370 i += aimutil_put16(newpacket->data+i, 0x0001);
371 i += aimutil_put16(newpacket->data+i, 0x0002);
372 i += aimutil_put16(newpacket->data+i, 0x0003);
373 i += aimutil_put16(newpacket->data+i, 0x0004);
375 if (conn->type != AIM_CONN_TYPE_BOS) {
376 i += aimutil_put16(newpacket->data+i, 0x0005);
379 aim_tx_enqueue(sess, newpacket);
381 return (sess->snac_nextid++);
385 * aim_bos_setprivacyflags()
387 * Sets privacy flags. Normally 0x03.
389 * Bit 1: Allows other AIM users to see how long you've been idle.
390 * Bit 2: Allows other AIM users to see how long you've been a member.
393 u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
394 struct aim_conn_t *conn,
397 return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
401 * aim_bos_reqpersonalinfo()
403 * Requests the current user's information. Can't go generic on this one
404 * because aparently it uses SNAC flags.
407 u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
408 struct aim_conn_t *conn)
410 struct command_tx_struct *newpacket;
412 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 12)))
417 aim_putsnac(newpacket->data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
419 newpacket->data[10] = 0x0d;
420 newpacket->data[11] = 0xda;
423 aim_tx_enqueue(sess, newpacket);
425 return (sess->snac_nextid++);
428 u_long aim_setversions(struct aim_session_t *sess,
429 struct aim_conn_t *conn)
431 struct command_tx_struct *newpacket;
434 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10 + (4*11))))
439 i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
441 i += aimutil_put16(newpacket->data+i, 0x0001);
442 i += aimutil_put16(newpacket->data+i, 0x0003);
444 i += aimutil_put16(newpacket->data+i, 0x0002);
445 i += aimutil_put16(newpacket->data+i, 0x0001);
447 i += aimutil_put16(newpacket->data+i, 0x0003);
448 i += aimutil_put16(newpacket->data+i, 0x0001);
450 i += aimutil_put16(newpacket->data+i, 0x0004);
451 i += aimutil_put16(newpacket->data+i, 0x0001);
453 i += aimutil_put16(newpacket->data+i, 0x0006);
454 i += aimutil_put16(newpacket->data+i, 0x0001);
456 i += aimutil_put16(newpacket->data+i, 0x0008);
457 i += aimutil_put16(newpacket->data+i, 0x0001);
459 i += aimutil_put16(newpacket->data+i, 0x0009);
460 i += aimutil_put16(newpacket->data+i, 0x0001);
462 i += aimutil_put16(newpacket->data+i, 0x000a);
463 i += aimutil_put16(newpacket->data+i, 0x0001);
465 i += aimutil_put16(newpacket->data+i, 0x000b);
466 i += aimutil_put16(newpacket->data+i, 0x0002);
468 i += aimutil_put16(newpacket->data+i, 0x000c);
469 i += aimutil_put16(newpacket->data+i, 0x0001);
471 i += aimutil_put16(newpacket->data+i, 0x0015);
472 i += aimutil_put16(newpacket->data+i, 0x0001);
475 for (j = 0; j < 0x10; j++) {
476 i += aimutil_put16(newpacket->data+i, j); /* family */
477 i += aimutil_put16(newpacket->data+i, 0x0003); /* version */
481 aim_tx_enqueue(sess, newpacket);
483 return (sess->snac_nextid++);
488 * aim_bos_reqservice(serviceid)
493 u_long aim_bos_reqservice(struct aim_session_t *sess,
494 struct aim_conn_t *conn,
497 return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
503 * No-op. WinAIM sends these every 4min or so to keep
504 * the connection alive. Its not real necessary.
507 u_long aim_bos_nop(struct aim_session_t *sess,
508 struct aim_conn_t *conn)
510 return aim_genericreq_n(sess, conn, 0x0001, 0x0016);
514 * aim_bos_reqrights()
516 * Request BOS rights.
519 u_long aim_bos_reqrights(struct aim_session_t *sess,
520 struct aim_conn_t *conn)
522 return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
526 * aim_bos_reqbuddyrights()
528 * Request Buddy List rights.
531 u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
532 struct aim_conn_t *conn)
534 return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
538 * aim_send_warning(struct aim_session_t *sess,
539 * struct aim_conn_t *conn, char *destsn, int anon)
540 * send a warning to destsn.
541 * anon is anonymous or not;
542 * AIM_WARN_ANON anonymous
544 * returns -1 on error (couldn't alloc packet), next snacid on success.
547 int aim_send_warning(struct aim_session_t *sess, struct aim_conn_t *conn, char *destsn, int anon)
549 struct command_tx_struct *newpacket;
552 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, strlen(destsn)+13)))
558 curbyte += aim_putsnac(newpacket->data+curbyte,
559 0x0004, 0x0008, 0x0000, sess->snac_nextid);
561 curbyte += aimutil_put16(newpacket->data+curbyte, (anon & AIM_WARN_ANON)?1:0);
563 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(destsn));
565 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn));
567 newpacket->commandlen = curbyte;
570 aim_tx_enqueue(sess, newpacket);
572 return (sess->snac_nextid++);
578 * aim_debugconn_sendconnect()
580 * For aimdebugd. If you don't know what it is, you don't want to.
582 u_long aim_debugconn_sendconnect(struct aim_session_t *sess,
583 struct aim_conn_t *conn)
585 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT);
589 * Generic routine for sending commands.
592 * I know I can do this in a smarter way...but I'm not thinking straight
595 * I had one big function that handled all three cases, but then it broke
596 * and I split it up into three. But then I fixed it. I just never went
597 * back to the single. I don't see any advantage to doing it either way.
600 u_long aim_genericreq_n(struct aim_session_t *sess,
601 struct aim_conn_t *conn,
602 u_short family, u_short subtype)
604 struct command_tx_struct *newpacket;
606 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10)))
611 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
613 aim_tx_enqueue(sess, newpacket);
614 return (sess->snac_nextid++);
621 u_long aim_genericreq_l(struct aim_session_t *sess,
622 struct aim_conn_t *conn,
623 u_short family, u_short subtype, u_long *longdata)
625 struct command_tx_struct *newpacket;
628 /* If we don't have data, there's no reason to use this function */
630 return aim_genericreq_n(sess, conn, family, subtype);
632 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_long))))
637 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
640 newlong = htonl(*longdata);
641 memcpy(&(newpacket->data[10]), &newlong, sizeof(u_long));
643 aim_tx_enqueue(sess, newpacket);
644 return (sess->snac_nextid++);
647 u_long aim_genericreq_s(struct aim_session_t *sess,
648 struct aim_conn_t *conn,
649 u_short family, u_short subtype, u_short *shortdata)
651 struct command_tx_struct *newpacket;
654 /* If we don't have data, there's no reason to use this function */
656 return aim_genericreq_n(sess, conn, family, subtype);
658 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_short))))
663 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
666 newshort = htons(*shortdata);
667 memcpy(&(newpacket->data[10]), &newshort, sizeof(u_short));
669 aim_tx_enqueue(sess, newpacket);
670 return (sess->snac_nextid++);
674 * aim_bos_reqlocaterights()
676 * Request Location services rights.
679 u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
680 struct aim_conn_t *conn)
682 return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
686 * aim_bos_reqicbmparaminfo()
688 * Request ICBM parameter information.
691 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
692 struct aim_conn_t *conn)
694 return aim_genericreq_n(sess, conn, 0x0004, 0x0004);