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.
256 u_long aim_bos_setgroupperm(struct aim_session_t *sess,
257 struct aim_conn_t *conn,
260 return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
264 * aim_bos_clientready()
271 u_long aim_bos_clientready(struct aim_session_t *sess,
272 struct aim_conn_t *conn)
274 u_char command_2[] = {
275 /* placeholders for dynamic data */
276 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
320 int command_2_len = 0x52;
321 struct command_tx_struct *newpacket;
323 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, command_2_len)))
328 memcpy(newpacket->data, command_2, command_2_len);
330 /* This write over the dynamic parts of the byte block */
331 aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
333 aim_tx_enqueue(sess, newpacket);
335 return (sess->snac_nextid++);
339 * send_login_phase3(int socket)
341 * Request Rate Information.
343 * TODO: Move to aim_conn.
344 * TODO: Move to SNAC interface.
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 * send_login_phase3b(int socket)
355 * Rate Information Response Acknowledge.
358 u_long aim_bos_ackrateresp(struct aim_session_t *sess,
359 struct aim_conn_t *conn)
361 struct command_tx_struct *newpacket;
362 int packlen = 18, i=0;
364 if (conn->type != AIM_CONN_TYPE_BOS)
367 if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packlen)));
371 i = aim_putsnac(newpacket->data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
372 i += aimutil_put16(newpacket->data+i, 0x0001);
373 i += aimutil_put16(newpacket->data+i, 0x0002);
374 i += aimutil_put16(newpacket->data+i, 0x0003);
375 i += aimutil_put16(newpacket->data+i, 0x0004);
377 if (conn->type != AIM_CONN_TYPE_BOS) {
378 i += aimutil_put16(newpacket->data+i, 0x0005);
381 aim_tx_enqueue(sess, newpacket);
383 return (sess->snac_nextid++);
387 * aim_bos_setprivacyflags()
389 * Sets privacy flags. Normally 0x03.
391 * Bit 1: Allows other AIM users to see how long you've been idle.
395 u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
396 struct aim_conn_t *conn,
399 return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
403 * aim_bos_reqpersonalinfo()
405 * Requests the current user's information. Can't go generic on this one
406 * because aparently it uses SNAC flags.
409 u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
410 struct aim_conn_t *conn)
412 struct command_tx_struct *newpacket;
414 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 12)))
419 aim_putsnac(newpacket->data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
421 newpacket->data[10] = 0x0d;
422 newpacket->data[11] = 0xda;
425 aim_tx_enqueue(sess, newpacket);
427 return (sess->snac_nextid++);
430 u_long aim_setversions(struct aim_session_t *sess,
431 struct aim_conn_t *conn)
433 struct command_tx_struct *newpacket;
436 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10 + (4*11))))
441 i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
443 i += aimutil_put16(newpacket->data+i, 0x0001);
444 i += aimutil_put16(newpacket->data+i, 0x0003);
446 i += aimutil_put16(newpacket->data+i, 0x0002);
447 i += aimutil_put16(newpacket->data+i, 0x0001);
449 i += aimutil_put16(newpacket->data+i, 0x0003);
450 i += aimutil_put16(newpacket->data+i, 0x0001);
452 i += aimutil_put16(newpacket->data+i, 0x0004);
453 i += aimutil_put16(newpacket->data+i, 0x0001);
455 i += aimutil_put16(newpacket->data+i, 0x0006);
456 i += aimutil_put16(newpacket->data+i, 0x0001);
458 i += aimutil_put16(newpacket->data+i, 0x0008);
459 i += aimutil_put16(newpacket->data+i, 0x0001);
461 i += aimutil_put16(newpacket->data+i, 0x0009);
462 i += aimutil_put16(newpacket->data+i, 0x0001);
464 i += aimutil_put16(newpacket->data+i, 0x000a);
465 i += aimutil_put16(newpacket->data+i, 0x0001);
467 i += aimutil_put16(newpacket->data+i, 0x000b);
468 i += aimutil_put16(newpacket->data+i, 0x0002);
470 i += aimutil_put16(newpacket->data+i, 0x000c);
471 i += aimutil_put16(newpacket->data+i, 0x0001);
473 i += aimutil_put16(newpacket->data+i, 0x0015);
474 i += aimutil_put16(newpacket->data+i, 0x0001);
477 for (j = 0; j < 0x10; j++) {
478 i += aimutil_put16(newpacket->data+i, j); /* family */
479 i += aimutil_put16(newpacket->data+i, 0x0003); /* version */
483 aim_tx_enqueue(sess, newpacket);
485 return (sess->snac_nextid++);
490 * aim_bos_reqservice(serviceid)
495 u_long aim_bos_reqservice(struct aim_session_t *sess,
496 struct aim_conn_t *conn,
499 return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
505 * No-op. WinAIM sends these every 4min or so to keep
506 * the connection alive. With the recent changes
507 * in the OSCAR servers, it looks like we must do the
508 * same or be disconnected with a mysterious 'you logged
509 * on from another client' message.
512 u_long aim_bos_nop(struct aim_session_t *sess,
513 struct aim_conn_t *conn)
515 return aim_genericreq_n(sess, conn, 0x0001, 0x0016);
519 * aim_bos_reqrights()
521 * Request BOS rights.
524 u_long aim_bos_reqrights(struct aim_session_t *sess,
525 struct aim_conn_t *conn)
527 return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
531 * aim_bos_reqbuddyrights()
533 * Request Buddy List rights.
536 u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
537 struct aim_conn_t *conn)
539 return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
543 * aim_debugconn_sendconnect()
545 * For aimdebugd. If you don't know what it is, you don't want to.
547 u_long aim_debugconn_sendconnect(struct aim_session_t *sess,
548 struct aim_conn_t *conn)
550 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT);
554 * Generic routine for sending commands.
557 * I know I can do this in a smarter way...but I'm not thinking straight
560 * I had one big function that handled all three cases, but then it broke
561 * and I split it up into three. But then I fixed it. I just never went
562 * back to the single. I don't see any advantage to doing it either way.
565 u_long aim_genericreq_n(struct aim_session_t *sess,
566 struct aim_conn_t *conn,
567 u_short family, u_short subtype)
569 struct command_tx_struct *newpacket;
571 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10)))
576 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
578 aim_tx_enqueue(sess, newpacket);
579 return (sess->snac_nextid++);
586 u_long aim_genericreq_l(struct aim_session_t *sess,
587 struct aim_conn_t *conn,
588 u_short family, u_short subtype, u_long *longdata)
590 struct command_tx_struct *newpacket;
593 /* If we don't have data, there's no reason to use this function */
595 return aim_genericreq_n(sess, conn, family, subtype);
597 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_long))))
602 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
605 newlong = htonl(*longdata);
606 memcpy(&(newpacket->data[10]), &newlong, sizeof(u_long));
608 aim_tx_enqueue(sess, newpacket);
609 return (sess->snac_nextid++);
612 u_long aim_genericreq_s(struct aim_session_t *sess,
613 struct aim_conn_t *conn,
614 u_short family, u_short subtype, u_short *shortdata)
616 struct command_tx_struct *newpacket;
619 /* If we don't have data, there's no reason to use this function */
621 return aim_genericreq_n(sess, conn, family, subtype);
623 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_short))))
628 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
631 newshort = htons(*shortdata);
632 memcpy(&(newpacket->data[10]), &newshort, sizeof(u_short));
634 aim_tx_enqueue(sess, newpacket);
635 return (sess->snac_nextid++);
639 * aim_bos_reqlocaterights()
641 * Request Location services rights.
644 u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
645 struct aim_conn_t *conn)
647 return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
651 * aim_bos_reqicbmparaminfo()
653 * Request ICBM parameter information.
656 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
657 struct aim_conn_t *conn)
659 return aim_genericreq_n(sess, conn, 0x0004, 0x0004);