]> andersk Git - libfaim.git/blob - aim_misc.c
- Mon Aug 28 03:11:15 GMT 2000
[libfaim.git] / aim_misc.c
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  */
24 u_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  */
60 u_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  */
137 u_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  */
213 u_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 (all classes).
254  *
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.
258  *
259  */
260 u_long aim_bos_setgroupperm(struct aim_session_t *sess,
261                             struct aim_conn_t *conn, 
262                             u_long mask)
263 {
264   return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
265 }
266
267 /*
268  * aim_bos_clientready()
269  * 
270  * Send Client Ready.  
271  *
272  * TODO: Dynamisize.
273  *
274  */
275 u_long aim_bos_clientready(struct aim_session_t *sess,
276                            struct aim_conn_t *conn)
277 {
278   u_char command_2[] = {
279      /* placeholders for dynamic data */
280      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
281      0xff, 0xff, 
282      /* real data */
283      0x00, 0x01,   
284      0x00, 0x03, 
285      0x00, 0x04, 
286      0x06, 0x86,  
287      0x00, 0x02, 
288      0x00, 0x01,  
289      0x00, 0x04, 
290      0x00, 0x01, 
291  
292      0x00, 0x03, 
293      0x00, 0x01,  
294      0x00, 0x04, 
295      0x00, 0x01, 
296      0x00, 0x04, 
297      0x00, 0x01, 
298      0x00, 0x04,
299      0x00, 0x01,
300  
301      0x00, 0x06, 
302      0x00, 0x01, 
303      0x00, 0x04,  
304      0x00, 0x01, 
305      0x00, 0x08, 
306      0x00, 0x01, 
307      0x00, 0x04,
308      0x00, 0x01,
309  
310      0x00, 0x09, 
311      0x00, 0x01, 
312      0x00, 0x04,
313      0x00, 0x01, 
314      0x00, 0x0a, 
315      0x00, 0x01, 
316      0x00, 0x04,
317      0x00, 0x01,
318  
319      0x00, 0x0b,
320      0x00, 0x01, 
321      0x00, 0x04,
322      0x00, 0x01
323   };
324   int command_2_len = 0x52;
325   struct command_tx_struct *newpacket;
326   
327   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, command_2_len)))
328     return -1;
329
330   newpacket->lock = 1;
331
332   memcpy(newpacket->data, command_2, command_2_len);
333   
334   /* This write over the dynamic parts of the byte block */
335   aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
336
337   aim_tx_enqueue(sess, newpacket);
338
339   return (sess->snac_nextid++);
340 }
341
342 /* 
343  *  Request Rate Information.
344  * 
345  */
346 u_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  *  Rate Information Response Acknowledge.
354  *
355  */
356 u_long aim_bos_ackrateresp(struct aim_session_t *sess,
357                            struct aim_conn_t *conn)
358 {
359   struct command_tx_struct *newpacket;
360   int packlen = 18, i=0;
361
362   if (conn->type != AIM_CONN_TYPE_BOS)
363     packlen += 2;
364
365   if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, packlen)));
366   
367   newpacket->lock = 1;
368
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);
374   
375   if (conn->type != AIM_CONN_TYPE_BOS) {
376     i += aimutil_put16(newpacket->data+i, 0x0005);
377   }
378
379   aim_tx_enqueue(sess, newpacket);
380
381   return (sess->snac_nextid++);
382 }
383
384 /* 
385  * aim_bos_setprivacyflags()
386  *
387  * Sets privacy flags. Normally 0x03.
388  *
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.
391  *
392  */
393 u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
394                                struct aim_conn_t *conn, 
395                                u_long flags)
396 {
397   return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
398 }
399
400 /*
401  * aim_bos_reqpersonalinfo()
402  *
403  * Requests the current user's information. Can't go generic on this one
404  * because aparently it uses SNAC flags.
405  *
406  */
407 u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
408                                struct aim_conn_t *conn)
409 {
410   struct command_tx_struct *newpacket;
411   
412   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 12)))
413     return -1;
414
415   newpacket->lock = 1;
416
417   aim_putsnac(newpacket->data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
418   
419   newpacket->data[10] = 0x0d;
420   newpacket->data[11] = 0xda;
421
422   newpacket->lock = 0;
423   aim_tx_enqueue(sess, newpacket);
424
425   return (sess->snac_nextid++);
426 }
427
428 u_long aim_setversions(struct aim_session_t *sess,
429                                struct aim_conn_t *conn)
430 {
431   struct command_tx_struct *newpacket;
432   int i;
433
434   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10 + (4*11))))
435     return -1;
436
437   newpacket->lock = 1;
438
439   i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
440
441   i += aimutil_put16(newpacket->data+i, 0x0001);
442   i += aimutil_put16(newpacket->data+i, 0x0003);
443
444   i += aimutil_put16(newpacket->data+i, 0x0002);
445   i += aimutil_put16(newpacket->data+i, 0x0001);
446
447   i += aimutil_put16(newpacket->data+i, 0x0003);
448   i += aimutil_put16(newpacket->data+i, 0x0001);
449
450   i += aimutil_put16(newpacket->data+i, 0x0004);
451   i += aimutil_put16(newpacket->data+i, 0x0001);
452
453   i += aimutil_put16(newpacket->data+i, 0x0006);
454   i += aimutil_put16(newpacket->data+i, 0x0001);
455
456   i += aimutil_put16(newpacket->data+i, 0x0008);
457   i += aimutil_put16(newpacket->data+i, 0x0001);
458
459   i += aimutil_put16(newpacket->data+i, 0x0009);
460   i += aimutil_put16(newpacket->data+i, 0x0001);
461
462   i += aimutil_put16(newpacket->data+i, 0x000a);
463   i += aimutil_put16(newpacket->data+i, 0x0001);
464
465   i += aimutil_put16(newpacket->data+i, 0x000b);
466   i += aimutil_put16(newpacket->data+i, 0x0002);
467
468   i += aimutil_put16(newpacket->data+i, 0x000c);
469   i += aimutil_put16(newpacket->data+i, 0x0001);
470
471   i += aimutil_put16(newpacket->data+i, 0x0015);
472   i += aimutil_put16(newpacket->data+i, 0x0001);
473
474 #if 0
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 */
478   }
479 #endif
480   newpacket->lock = 0;
481   aim_tx_enqueue(sess, newpacket);
482
483   return (sess->snac_nextid++);
484 }
485
486
487 /*
488  * aim_bos_reqservice(serviceid)
489  *
490  * Service request. 
491  *
492  */
493 u_long aim_bos_reqservice(struct aim_session_t *sess,
494                           struct aim_conn_t *conn, 
495                           u_short serviceid)
496 {
497   return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
498 }
499
500 /*
501  * aim_bos_nop()
502  *
503  * No-op.  WinAIM sends these every 4min or so to keep
504  * the connection alive.  Its not real necessary.
505  *
506  */
507 u_long aim_bos_nop(struct aim_session_t *sess,
508                    struct aim_conn_t *conn)
509 {
510   return aim_genericreq_n(sess, conn, 0x0001, 0x0016);
511 }
512
513 /*
514  * aim_bos_reqrights()
515  *
516  * Request BOS rights.
517  *
518  */
519 u_long aim_bos_reqrights(struct aim_session_t *sess,
520                          struct aim_conn_t *conn)
521 {
522   return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
523 }
524
525 /*
526  * aim_bos_reqbuddyrights()
527  *
528  * Request Buddy List rights.
529  *
530  */
531 u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
532                               struct aim_conn_t *conn)
533 {
534   return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
535 }
536
537 /*
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
543  *
544  * returns -1 on error (couldn't alloc packet), next snacid on success.
545  *
546  */
547 int aim_send_warning(struct aim_session_t *sess, struct aim_conn_t *conn, char *destsn, int anon)
548 {
549   struct command_tx_struct *newpacket;
550   int curbyte;
551
552   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, strlen(destsn)+13)))
553     return -1;
554
555   newpacket->lock = 1;
556
557   curbyte  = 0;
558   curbyte += aim_putsnac(newpacket->data+curbyte,
559                         0x0004, 0x0008, 0x0000, sess->snac_nextid);
560
561   curbyte += aimutil_put16(newpacket->data+curbyte, (anon & AIM_WARN_ANON)?1:0);
562
563   curbyte += aimutil_put8(newpacket->data+curbyte, strlen(destsn));
564
565   curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn));
566
567   newpacket->commandlen = curbyte;
568   newpacket->lock = 0;
569
570   aim_tx_enqueue(sess, newpacket);
571
572   return (sess->snac_nextid++);
573 }
574
575
576
577 /*
578  * aim_debugconn_sendconnect()
579  *
580  * For aimdebugd.  If you don't know what it is, you don't want to.
581  */
582 u_long aim_debugconn_sendconnect(struct aim_session_t *sess,
583                                  struct aim_conn_t *conn)
584 {
585   return aim_genericreq_n(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT);
586 }
587
588 /*
589  * Generic routine for sending commands.
590  *
591  *
592  * I know I can do this in a smarter way...but I'm not thinking straight
593  * right now...
594  *
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.
598  *
599  */
600 u_long aim_genericreq_n(struct aim_session_t *sess,
601                         struct aim_conn_t *conn, 
602                         u_short family, u_short subtype)
603 {
604   struct command_tx_struct *newpacket;
605
606   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10)))
607     return 0;
608
609   newpacket->lock = 1;
610
611   aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
612  
613   aim_tx_enqueue(sess, newpacket);
614   return (sess->snac_nextid++);
615 }
616
617 /*
618  *
619  *
620  */
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)
624 {
625   struct command_tx_struct *newpacket;
626   u_long newlong;
627
628   /* If we don't have data, there's no reason to use this function */
629   if (!longdata)
630     return aim_genericreq_n(sess, conn, family, subtype);
631
632   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_long))))
633     return -1;
634
635   newpacket->lock = 1;
636
637   aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
638
639   /* copy in data */
640   newlong = htonl(*longdata);
641   memcpy(&(newpacket->data[10]), &newlong, sizeof(u_long));
642
643   aim_tx_enqueue(sess, newpacket);
644   return (sess->snac_nextid++);
645 }
646
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)
650 {
651   struct command_tx_struct *newpacket;
652   u_short newshort;
653
654   /* If we don't have data, there's no reason to use this function */
655   if (!shortdata)
656     return aim_genericreq_n(sess, conn, family, subtype);
657
658   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+sizeof(u_short))))
659     return -1;
660
661   newpacket->lock = 1;
662
663   aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
664
665   /* copy in data */
666   newshort = htons(*shortdata);
667   memcpy(&(newpacket->data[10]), &newshort, sizeof(u_short));
668
669   aim_tx_enqueue(sess, newpacket);
670   return (sess->snac_nextid++);
671 }
672
673 /*
674  * aim_bos_reqlocaterights()
675  *
676  * Request Location services rights.
677  *
678  */
679 u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
680                                struct aim_conn_t *conn)
681 {
682   return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
683 }
684
685 /*
686 * aim_bos_reqicbmparaminfo()
687  *
688  * Request ICBM parameter information.
689  *
690  */
691 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
692                                 struct aim_conn_t *conn)
693 {
694   return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
695 }
696
This page took 0.093485 seconds and 5 git commands to generate.