]> andersk Git - libfaim.git/blame_incremental - aim_misc.c
Forgot this.
[libfaim.git] / aim_misc.c
... / ...
CommitLineData
1
2/*
3 * aim_misc.c
4 *
5 * TODO: Seperate a lot of this into an aim_bos.c.
6 *
7 * Other things...
8 *
9 * - Idle setting
10 *
11 *
12 */
13
14#include <faim/aim.h>
15
16/*
17 * aim_bos_setidle()
18 *
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
21 * time.
22 *
23 */
24u_long aim_bos_setidle(struct aim_session_t *sess,
25 struct aim_conn_t *conn,
26 u_long idletime)
27{
28 return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime);
29}
30
31
32/*
33 * aim_bos_changevisibility(conn, changtype, namelist)
34 *
35 * Changes your visibility depending on changetype:
36 *
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
41 *
42 * list should be a list of
43 * screen names in the form "Screen Name One&ScreenNameTwo&" etc.
44 *
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
50 * buddy list
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
57 *
58 *
59 */
60u_long aim_bos_changevisibility(struct aim_session_t *sess,
61 struct aim_conn_t *conn,
62 int changetype, char *denylist)
63{
64 struct command_tx_struct *newpacket;
65 int packlen = 0;
66 u_short subtype;
67
68 char *localcpy = NULL;
69 char *tmpptr = NULL;
70 int i,j;
71 int listcount;
72
73 if (!denylist)
74 return 0;
75
76 localcpy = (char *) malloc(strlen(denylist)+1);
77 memcpy(localcpy, denylist, strlen(denylist)+1);
78
79 listcount = aimutil_itemcnt(localcpy, '&');
80 packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9;
81
82 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packlen)))
83 return -1;
84
85 newpacket->lock = 1;
86
87 switch(changetype)
88 {
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;
93 default:
94 free(newpacket->data);
95 free(newpacket);
96 return 0;
97 }
98
99 /* We actually DO NOT send a SNAC ID with this one! */
100 aim_putsnac(newpacket->data, 0x0009, subtype, 0x00, 0);
101
102 j = 10; /* the next byte */
103
104 for (i=0; (i < (listcount - 1)) && (i < 99); i++)
105 {
106 tmpptr = aimutil_itemidx(localcpy, i, '&');
107
108 newpacket->data[j] = strlen(tmpptr);
109 memcpy(&(newpacket->data[j+1]), tmpptr, strlen(tmpptr));
110 j += strlen(tmpptr)+1;
111 free(tmpptr);
112 }
113 free(localcpy);
114
115 newpacket->lock = 0;
116
117 aim_tx_enqueue(sess, newpacket);
118
119 return (sess->snac_nextid); /* dont increment */
120
121}
122
123
124
125/*
126 * aim_bos_setbuddylist(buddylist)
127 *
128 * This just builds the "set buddy list" command then queues it.
129 *
130 * buddy_list = "Screen Name One&ScreenNameTwo&";
131 *
132 * TODO: Clean this up.
133 *
134 * XXX: I can't stress the TODO enough.
135 *
136 */
137u_long aim_bos_setbuddylist(struct aim_session_t *sess,
138 struct aim_conn_t *conn,
139 char *buddy_list)
140{
141 int i, j;
142
143 struct command_tx_struct *newpacket;
144
145 int packet_login_phase3c_hi_b_len = 0;
146
147 char *localcpy = NULL;
148 char *tmpptr = NULL;
149
150 packet_login_phase3c_hi_b_len = 16; /* 16b for FLAP and SNAC headers */
151
152 /* bail out if we can't make the packet */
153 if (!buddy_list) {
154 return -1;
155 }
156
157 localcpy = (char *) malloc(strlen(buddy_list)+1);
158 memcpy(localcpy, buddy_list, strlen(buddy_list)+1);
159
160 i = 0;
161 tmpptr = strtok(localcpy, "&");
162 while ((tmpptr != NULL) && (i < 100))
163 {
164#if debug > 0
165 printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
166#endif
167 packet_login_phase3c_hi_b_len += strlen(tmpptr)+1;
168 i++;
169 tmpptr = strtok(NULL, "&");
170 }
171#if debug > 0
172 printf("*** send buddy list len: %d (%x)\n", packet_login_phase3c_hi_b_len, packet_login_phase3c_hi_b_len);
173#endif
174 free(localcpy);
175
176 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packet_login_phase3c_hi_b_len - 6)))
177 return -1;
178
179 newpacket->lock = 1;
180
181 aim_putsnac(newpacket->data, 0x0003, 0x0004, 0x0000, sess->snac_nextid);
182
183 j = 10; /* the next byte */
184
185 i = 0;
186 tmpptr = strtok(buddy_list, "&");
187 while ((tmpptr != NULL) & (i < 100))
188 {
189#if debug > 0
190 printf("---adding %s (%d)\n", tmpptr, strlen(tmpptr));
191#endif
192 newpacket->data[j] = strlen(tmpptr);
193 memcpy(&(newpacket->data[j+1]), tmpptr, strlen(tmpptr));
194 j += strlen(tmpptr)+1;
195 i++;
196 tmpptr = strtok(NULL, "&");
197 }
198
199 newpacket->lock = 0;
200
201 aim_tx_enqueue(sess, newpacket);
202
203 return (sess->snac_nextid++);
204}
205
206/*
207 * aim_bos_setprofile(profile)
208 *
209 * Gives BOS your profile.
210 *
211 *
212 */
213u_long aim_bos_setprofile(struct aim_session_t *sess,
214 struct aim_conn_t *conn,
215 char *profile,
216 char *awaymsg,
217 unsigned int caps)
218{
219 struct command_tx_struct *newpacket;
220 int i = 0, tmp, caplen;
221
222 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 1152+strlen(profile)+1+(awaymsg?strlen(awaymsg):0))))
223 return -1;
224
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\"");
230
231 /* Away message -- we send this no matter what, even if its blank */
232 if (awaymsg)
233 i += aim_puttlv_str(newpacket->data+i, 0x0004, strlen(awaymsg), awaymsg);
234 else
235 i += aim_puttlv_str(newpacket->data+i, 0x0004, 0x0000, NULL);
236
237 /* Capability information. */
238
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 */
243
244 newpacket->commandlen = i;
245 aim_tx_enqueue(sess, newpacket);
246
247 return (sess->snac_nextid++);
248}
249
250/*
251 * aim_bos_setgroupperm(mask)
252 *
253 * Set group permisson mask. Normally 0x1f.
254 *
255 */
256u_long aim_bos_setgroupperm(struct aim_session_t *sess,
257 struct aim_conn_t *conn,
258 u_long mask)
259{
260 return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
261}
262
263/*
264 * aim_bos_clientready()
265 *
266 * Send Client Ready.
267 *
268 * TODO: Dynamisize.
269 *
270 */
271u_long aim_bos_clientready(struct aim_session_t *sess,
272 struct aim_conn_t *conn)
273{
274 u_char command_2[] = {
275 /* placeholders for dynamic data */
276 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
277 0xff, 0xff,
278 /* real data */
279 0x00, 0x01,
280 0x00, 0x03,
281 0x00, 0x04,
282 0x06, 0x86,
283 0x00, 0x02,
284 0x00, 0x01,
285 0x00, 0x04,
286 0x00, 0x01,
287
288 0x00, 0x03,
289 0x00, 0x01,
290 0x00, 0x04,
291 0x00, 0x01,
292 0x00, 0x04,
293 0x00, 0x01,
294 0x00, 0x04,
295 0x00, 0x01,
296
297 0x00, 0x06,
298 0x00, 0x01,
299 0x00, 0x04,
300 0x00, 0x01,
301 0x00, 0x08,
302 0x00, 0x01,
303 0x00, 0x04,
304 0x00, 0x01,
305
306 0x00, 0x09,
307 0x00, 0x01,
308 0x00, 0x04,
309 0x00, 0x01,
310 0x00, 0x0a,
311 0x00, 0x01,
312 0x00, 0x04,
313 0x00, 0x01,
314
315 0x00, 0x0b,
316 0x00, 0x01,
317 0x00, 0x04,
318 0x00, 0x01
319 };
320 int command_2_len = 0x52;
321 struct command_tx_struct *newpacket;
322
323 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, command_2_len)))
324 return -1;
325
326 newpacket->lock = 1;
327
328 memcpy(newpacket->data, command_2, command_2_len);
329
330 /* This write over the dynamic parts of the byte block */
331 aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
332
333 aim_tx_enqueue(sess, newpacket);
334
335 return (sess->snac_nextid++);
336}
337
338/*
339 * send_login_phase3(int socket)
340 *
341 * Request Rate Information.
342 *
343 * TODO: Move to aim_conn.
344 * TODO: Move to SNAC interface.
345 */
346u_long aim_bos_reqrate(struct aim_session_t *sess,
347 struct aim_conn_t *conn)
348{
349 return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
350}
351
352/*
353 * send_login_phase3b(int socket)
354 *
355 * Rate Information Response Acknowledge.
356 *
357 */
358u_long aim_bos_ackrateresp(struct aim_session_t *sess,
359 struct aim_conn_t *conn)
360{
361 struct command_tx_struct *newpacket;
362 int packlen = 18, i=0;
363
364 if (conn->type != AIM_CONN_TYPE_BOS)
365 packlen += 2;
366
367 if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packlen)));
368
369 newpacket->lock = 1;
370
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);
376
377 if (conn->type != AIM_CONN_TYPE_BOS) {
378 i += aimutil_put16(newpacket->data+i, 0x0005);
379 }
380
381 aim_tx_enqueue(sess, newpacket);
382
383 return (sess->snac_nextid++);
384}
385
386/*
387 * aim_bos_setprivacyflags()
388 *
389 * Sets privacy flags. Normally 0x03.
390 *
391 * Bit 1: Allows other AIM users to see how long you've been idle.
392 *
393 *
394 */
395u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
396 struct aim_conn_t *conn,
397 u_long flags)
398{
399 return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
400}
401
402/*
403 * aim_bos_reqpersonalinfo()
404 *
405 * Requests the current user's information. Can't go generic on this one
406 * because aparently it uses SNAC flags.
407 *
408 */
409u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
410 struct aim_conn_t *conn)
411{
412 struct command_tx_struct *newpacket;
413
414 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 12)))
415 return -1;
416
417 newpacket->lock = 1;
418
419 aim_putsnac(newpacket->data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
420
421 newpacket->data[10] = 0x0d;
422 newpacket->data[11] = 0xda;
423
424 newpacket->lock = 0;
425 aim_tx_enqueue(sess, newpacket);
426
427 return (sess->snac_nextid++);
428}
429
430u_long aim_setversions(struct aim_session_t *sess,
431 struct aim_conn_t *conn)
432{
433 struct command_tx_struct *newpacket;
434 int i;
435
436 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10 + (4*11))))
437 return -1;
438
439 newpacket->lock = 1;
440
441 i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
442
443 i += aimutil_put16(newpacket->data+i, 0x0001);
444 i += aimutil_put16(newpacket->data+i, 0x0003);
445
446 i += aimutil_put16(newpacket->data+i, 0x0002);
447 i += aimutil_put16(newpacket->data+i, 0x0001);
448
449 i += aimutil_put16(newpacket->data+i, 0x0003);
450 i += aimutil_put16(newpacket->data+i, 0x0001);
451
452 i += aimutil_put16(newpacket->data+i, 0x0004);
453 i += aimutil_put16(newpacket->data+i, 0x0001);
454
455 i += aimutil_put16(newpacket->data+i, 0x0006);
456 i += aimutil_put16(newpacket->data+i, 0x0001);
457
458 i += aimutil_put16(newpacket->data+i, 0x0008);
459 i += aimutil_put16(newpacket->data+i, 0x0001);
460
461 i += aimutil_put16(newpacket->data+i, 0x0009);
462 i += aimutil_put16(newpacket->data+i, 0x0001);
463
464 i += aimutil_put16(newpacket->data+i, 0x000a);
465 i += aimutil_put16(newpacket->data+i, 0x0001);
466
467 i += aimutil_put16(newpacket->data+i, 0x000b);
468 i += aimutil_put16(newpacket->data+i, 0x0002);
469
470 i += aimutil_put16(newpacket->data+i, 0x000c);
471 i += aimutil_put16(newpacket->data+i, 0x0001);
472
473 i += aimutil_put16(newpacket->data+i, 0x0015);
474 i += aimutil_put16(newpacket->data+i, 0x0001);
475
476#if 0
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 */
480 }
481#endif
482 newpacket->lock = 0;
483 aim_tx_enqueue(sess, newpacket);
484
485 return (sess->snac_nextid++);
486}
487
488
489/*
490 * aim_bos_reqservice(serviceid)
491 *
492 * Service request.
493 *
494 */
495u_long aim_bos_reqservice(struct aim_session_t *sess,
496 struct aim_conn_t *conn,
497 u_short serviceid)
498{
499 return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
500}
501
502/*
503 * aim_bos_nop()
504 *
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.
510 *
511 */
512u_long aim_bos_nop(struct aim_session_t *sess,
513 struct aim_conn_t *conn)
514{
515 return aim_genericreq_n(sess, conn, 0x0001, 0x0016);
516}
517
518/*
519 * aim_bos_reqrights()
520 *
521 * Request BOS rights.
522 *
523 */
524u_long aim_bos_reqrights(struct aim_session_t *sess,
525 struct aim_conn_t *conn)
526{
527 return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
528}
529
530/*
531 * aim_bos_reqbuddyrights()
532 *
533 * Request Buddy List rights.
534 *
535 */
536u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
537 struct aim_conn_t *conn)
538{
539 return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
540}
541
542/*
543 * Generic routine for sending commands.
544 *
545 *
546 * I know I can do this in a smarter way...but I'm not thinking straight
547 * right now...
548 *
549 * I had one big function that handled all three cases, but then it broke
550 * and I split it up into three. But then I fixed it. I just never went
551 * back to the single. I don't see any advantage to doing it either way.
552 *
553 */
554u_long aim_genericreq_n(struct aim_session_t *sess,
555 struct aim_conn_t *conn,
556 u_short family, u_short subtype)
557{
558 struct command_tx_struct *newpacket;
559
560 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10)))
561 return 0;
562
563 newpacket->lock = 1;
564
565 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
566
567 aim_tx_enqueue(sess, newpacket);
568 return (sess->snac_nextid++);
569}
570
571/*
572 *
573 *
574 */
575u_long aim_genericreq_l(struct aim_session_t *sess,
576 struct aim_conn_t *conn,
577 u_short family, u_short subtype, u_long *longdata)
578{
579 struct command_tx_struct *newpacket;
580 u_long newlong;
581
582 /* If we don't have data, there's no reason to use this function */
583 if (!longdata)
584 return aim_genericreq_n(sess, conn, family, subtype);
585
586 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_long))))
587 return -1;
588
589 newpacket->lock = 1;
590
591 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
592
593 /* copy in data */
594 newlong = htonl(*longdata);
595 memcpy(&(newpacket->data[10]), &newlong, sizeof(u_long));
596
597 aim_tx_enqueue(sess, newpacket);
598 return (sess->snac_nextid++);
599}
600
601u_long aim_genericreq_s(struct aim_session_t *sess,
602 struct aim_conn_t *conn,
603 u_short family, u_short subtype, u_short *shortdata)
604{
605 struct command_tx_struct *newpacket;
606 u_short newshort;
607
608 /* If we don't have data, there's no reason to use this function */
609 if (!shortdata)
610 return aim_genericreq_n(sess, conn, family, subtype);
611
612 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_short))))
613 return -1;
614
615 newpacket->lock = 1;
616
617 aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
618
619 /* copy in data */
620 newshort = htons(*shortdata);
621 memcpy(&(newpacket->data[10]), &newshort, sizeof(u_short));
622
623 aim_tx_enqueue(sess, newpacket);
624 return (sess->snac_nextid++);
625}
626
627/*
628 * aim_bos_reqlocaterights()
629 *
630 * Request Location services rights.
631 *
632 */
633u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
634 struct aim_conn_t *conn)
635{
636 return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
637}
638
639/*
640* aim_bos_reqicbmparaminfo()
641 *
642 * Request ICBM parameter information.
643 *
644 */
645u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
646 struct aim_conn_t *conn)
647{
648 return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
649}
650
This page took 0.161888 seconds and 5 git commands to generate.