]> andersk Git - libfaim.git/blob - aim_misc.c
- Tue Jun 6 01:36:48 UTC 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(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(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  * The large data chunk given here is of unknown decoding.
213  * What I do know is that each 0x20 byte repetition 
214  * represents a capability.  People with only the 
215  * first two reptitions can support normal messaging
216  * and chat (client version 2.0 or 3.0).  People with 
217  * the third as well can also support voice chat (client
218  * version 3.5 or higher).  IOW, if we don't send this,
219  * we won't get chat invitations (get "software doesn't
220  * support chat" error).
221  *
222  * This data is broadcast along with your oncoming
223  * buddy command to everyone who has you on their
224  * buddy list, as a type 0x0002 TLV.
225  * 
226  */
227 u_long aim_bos_setprofile(struct aim_session_t *sess,
228                           struct aim_conn_t *conn, 
229                           char *profile,
230                           char *awaymsg,
231                           unsigned int caps)
232 {
233   struct command_tx_struct *newpacket;
234   int i = 0;
235
236   if (!(newpacket = aim_tx_new(0x0002, conn, 1152+strlen(profile)+1+(awaymsg?strlen(awaymsg):0))))
237     return -1;
238
239   i += aim_putsnac(newpacket->data, 0x0002, 0x004, 0x0000, sess->snac_nextid);
240   i += aim_puttlv_str(newpacket->data+i, 0x0001, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
241   i += aim_puttlv_str(newpacket->data+i, 0x0002, strlen(profile), profile);
242   /* why do we send this twice?  */
243   i += aim_puttlv_str(newpacket->data+i, 0x0003, strlen("text/x-aolrtf; charset=\"us-ascii\""), "text/x-aolrtf; charset=\"us-ascii\"");
244   
245   /* Away message -- we send this no matter what, even if its blank */
246   if (awaymsg)
247     i += aim_puttlv_str(newpacket->data+i, 0x0004, strlen(awaymsg), awaymsg);
248   else
249     i += aim_puttlv_str(newpacket->data+i, 0x0004, 0x0000, NULL);
250
251   /* Capability information. */
252   {
253     int isave;
254     i += aimutil_put16(newpacket->data+i, 0x0005);
255     isave = i;
256     i += aimutil_put16(newpacket->data+i, 0);
257     if (caps & AIM_CAPS_BUDDYICON)
258       i += aimutil_putstr(newpacket->data+i, aim_caps[0], 0x10);
259     if (caps & AIM_CAPS_VOICE)
260       i += aimutil_putstr(newpacket->data+i, aim_caps[1], 0x10);
261     if (caps & AIM_CAPS_IMIMAGE)
262       i += aimutil_putstr(newpacket->data+i, aim_caps[2], 0x10);
263     if (caps & AIM_CAPS_CHAT)
264       i += aimutil_putstr(newpacket->data+i, aim_caps[3], 0x10);
265     if (caps & AIM_CAPS_GETFILE)
266       i += aimutil_putstr(newpacket->data+i, aim_caps[4], 0x10);
267     if (caps & AIM_CAPS_SENDFILE)
268       i += aimutil_putstr(newpacket->data+i, aim_caps[5], 0x10);
269     aimutil_put16(newpacket->data+isave, i-isave-2);
270   }
271   newpacket->commandlen = i;
272   aim_tx_enqueue(sess, newpacket);
273   
274   return (sess->snac_nextid++);
275 }
276
277 /* 
278  * aim_bos_setgroupperm(mask)
279  * 
280  * Set group permisson mask.  Normally 0x1f.
281  *
282  */
283 u_long aim_bos_setgroupperm(struct aim_session_t *sess,
284                             struct aim_conn_t *conn, 
285                             u_long mask)
286 {
287   return aim_genericreq_l(sess, conn, 0x0009, 0x0004, &mask);
288 }
289
290 /*
291  * aim_bos_clientready()
292  * 
293  * Send Client Ready.  
294  *
295  * TODO: Dynamisize.
296  *
297  */
298 u_long aim_bos_clientready(struct aim_session_t *sess,
299                            struct aim_conn_t *conn)
300 {
301   u_char command_2[] = {
302      /* placeholders for dynamic data */
303      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
304      0xff, 0xff, 
305      /* real data */
306      0x00, 0x01,   
307      0x00, 0x03, 
308      0x00, 0x04, 
309      0x06, 0x86,  
310      0x00, 0x02, 
311      0x00, 0x01,  
312      0x00, 0x04, 
313      0x00, 0x01, 
314  
315      0x00, 0x03, 
316      0x00, 0x01,  
317      0x00, 0x04, 
318      0x00, 0x01, 
319      0x00, 0x04, 
320      0x00, 0x01, 
321      0x00, 0x04,
322      0x00, 0x01,
323  
324      0x00, 0x06, 
325      0x00, 0x01, 
326      0x00, 0x04,  
327      0x00, 0x01, 
328      0x00, 0x08, 
329      0x00, 0x01, 
330      0x00, 0x04,
331      0x00, 0x01,
332  
333      0x00, 0x09, 
334      0x00, 0x01, 
335      0x00, 0x04,
336      0x00, 0x01, 
337      0x00, 0x0a, 
338      0x00, 0x01, 
339      0x00, 0x04,
340      0x00, 0x01,
341  
342      0x00, 0x0b,
343      0x00, 0x01, 
344      0x00, 0x04,
345      0x00, 0x01
346   };
347   int command_2_len = 0x52;
348   struct command_tx_struct *newpacket;
349   
350   if (!(newpacket = aim_tx_new(0x0002, conn, command_2_len)))
351     return -1;
352
353   newpacket->lock = 1;
354
355   memcpy(newpacket->data, command_2, command_2_len);
356   
357   /* This write over the dynamic parts of the byte block */
358   aim_putsnac(newpacket->data, 0x0001, 0x0002, 0x0000, sess->snac_nextid);
359
360   aim_tx_enqueue(sess, newpacket);
361
362   return (sess->snac_nextid++);
363 }
364
365 /* 
366  *  send_login_phase3(int socket)   
367  *
368  *  Request Rate Information.
369  * 
370  *  TODO: Move to aim_conn.
371  *  TODO: Move to SNAC interface.
372  */
373 u_long aim_bos_reqrate(struct aim_session_t *sess,
374                        struct aim_conn_t *conn)
375 {
376   return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
377 }
378
379 /* 
380  *  send_login_phase3b(int socket)   
381  *
382  *  Rate Information Response Acknowledge.
383  *
384  */
385 u_long aim_bos_ackrateresp(struct aim_session_t *sess,
386                            struct aim_conn_t *conn)
387 {
388   struct command_tx_struct *newpacket;
389   int packlen = 18, i=0;
390
391   if (conn->type != AIM_CONN_TYPE_BOS)
392     packlen += 2;
393
394   if(!(newpacket = aim_tx_new(0x0002, conn, packlen)));
395   
396   newpacket->lock = 1;
397
398   i = aim_putsnac(newpacket->data, 0x0001, 0x0008, 0x0000, sess->snac_nextid);
399   i += aimutil_put16(newpacket->data+i, 0x0001); 
400   i += aimutil_put16(newpacket->data+i, 0x0002);
401   i += aimutil_put16(newpacket->data+i, 0x0003);
402   i += aimutil_put16(newpacket->data+i, 0x0004);
403   
404   if (conn->type != AIM_CONN_TYPE_BOS) {
405     i += aimutil_put16(newpacket->data+i, 0x0005);
406   }
407
408   aim_tx_enqueue(sess, newpacket);
409
410   return (sess->snac_nextid++);
411 }
412
413 /* 
414  * aim_bos_setprivacyflags()
415  *
416  * Sets privacy flags. Normally 0x03.
417  *
418  *  Bit 1:  Allows other AIM users to see how long you've been idle.
419  *
420  *
421  */
422 u_long aim_bos_setprivacyflags(struct aim_session_t *sess,
423                                struct aim_conn_t *conn, 
424                                u_long flags)
425 {
426   return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
427 }
428
429 /*
430  * aim_bos_reqpersonalinfo()
431  *
432  * Requests the current user's information. Can't go generic on this one
433  * because aparently it uses SNAC flags.
434  *
435  */
436 u_long aim_bos_reqpersonalinfo(struct aim_session_t *sess,
437                                struct aim_conn_t *conn)
438 {
439   struct command_tx_struct *newpacket;
440   
441   if (!(newpacket = aim_tx_new(0x0002, conn, 12)))
442     return -1;
443
444   newpacket->lock = 1;
445
446   aim_putsnac(newpacket->data, 0x000a, 0x0001, 0x000e /* huh? */, sess->snac_nextid);
447   
448   newpacket->data[10] = 0x0d;
449   newpacket->data[11] = 0xda;
450
451   newpacket->lock = 0;
452   aim_tx_enqueue(sess, newpacket);
453
454   return (sess->snac_nextid++);
455 }
456
457 u_long aim_setversions(struct aim_session_t *sess,
458                                struct aim_conn_t *conn)
459 {
460   struct command_tx_struct *newpacket;
461   int i;
462
463   if (!(newpacket = aim_tx_new(0x0002, conn, 10 + (4*11))))
464     return -1;
465
466   newpacket->lock = 1;
467
468   i = aim_putsnac(newpacket->data, 0x0001, 0x0017, 0x0000, sess->snac_nextid);
469
470   i += aimutil_put16(newpacket->data+i, 0x0001);
471   i += aimutil_put16(newpacket->data+i, 0x0003);
472
473   i += aimutil_put16(newpacket->data+i, 0x0002);
474   i += aimutil_put16(newpacket->data+i, 0x0001);
475
476   i += aimutil_put16(newpacket->data+i, 0x0003);
477   i += aimutil_put16(newpacket->data+i, 0x0001);
478
479   i += aimutil_put16(newpacket->data+i, 0x0004);
480   i += aimutil_put16(newpacket->data+i, 0x0001);
481
482   i += aimutil_put16(newpacket->data+i, 0x0006);
483   i += aimutil_put16(newpacket->data+i, 0x0001);
484
485   i += aimutil_put16(newpacket->data+i, 0x0008);
486   i += aimutil_put16(newpacket->data+i, 0x0001);
487
488   i += aimutil_put16(newpacket->data+i, 0x0009);
489   i += aimutil_put16(newpacket->data+i, 0x0001);
490
491   i += aimutil_put16(newpacket->data+i, 0x000a);
492   i += aimutil_put16(newpacket->data+i, 0x0001);
493
494   i += aimutil_put16(newpacket->data+i, 0x000b);
495   i += aimutil_put16(newpacket->data+i, 0x0002);
496
497   i += aimutil_put16(newpacket->data+i, 0x000c);
498   i += aimutil_put16(newpacket->data+i, 0x0001);
499
500   i += aimutil_put16(newpacket->data+i, 0x0015);
501   i += aimutil_put16(newpacket->data+i, 0x0001);
502
503 #if 0
504   for (j = 0; j < 0x10; j++) {
505     i += aimutil_put16(newpacket->data+i, j); /* family */
506     i += aimutil_put16(newpacket->data+i, 0x0003); /* version */
507   }
508 #endif
509   newpacket->lock = 0;
510   aim_tx_enqueue(sess, newpacket);
511
512   return (sess->snac_nextid++);
513 }
514
515
516 /*
517  * aim_bos_reqservice(serviceid)
518  *
519  * Service request. 
520  *
521  */
522 u_long aim_bos_reqservice(struct aim_session_t *sess,
523                           struct aim_conn_t *conn, 
524                           u_short serviceid)
525 {
526   return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
527 }
528
529 /*
530  * aim_bos_reqrights()
531  *
532  * Request BOS rights.
533  *
534  */
535 u_long aim_bos_reqrights(struct aim_session_t *sess,
536                          struct aim_conn_t *conn)
537 {
538   return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
539 }
540
541 /*
542  * aim_bos_reqbuddyrights()
543  *
544  * Request Buddy List rights.
545  *
546  */
547 u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
548                               struct aim_conn_t *conn)
549 {
550   return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
551 }
552
553 /*
554  * Generic routine for sending commands.
555  *
556  *
557  * I know I can do this in a smarter way...but I'm not thinking straight
558  * right now...
559  *
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.
563  *
564  */
565 u_long aim_genericreq_n(struct aim_session_t *sess,
566                         struct aim_conn_t *conn, 
567                         u_short family, u_short subtype)
568 {
569   struct command_tx_struct *newpacket;
570
571   if (!(newpacket = aim_tx_new(0x0002, conn, 10)))
572     return 0;
573
574   newpacket->lock = 1;
575
576   aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
577  
578   aim_tx_enqueue(sess, newpacket);
579   return (sess->snac_nextid++);
580 }
581
582 /*
583  *
584  *
585  */
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)
589 {
590   struct command_tx_struct *newpacket;
591   u_long newlong;
592
593   /* If we don't have data, there's no reason to use this function */
594   if (!longdata)
595     return aim_genericreq_n(sess, conn, family, subtype);
596
597   if (!(newpacket = aim_tx_new(0x0002, conn, 10+sizeof(u_long))))
598     return -1;
599
600   newpacket->lock = 1;
601
602   aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
603
604   /* copy in data */
605   newlong = htonl(*longdata);
606   memcpy(&(newpacket->data[10]), &newlong, sizeof(u_long));
607
608   aim_tx_enqueue(sess, newpacket);
609   return (sess->snac_nextid++);
610 }
611
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)
615 {
616   struct command_tx_struct *newpacket;
617   u_short newshort;
618
619   /* If we don't have data, there's no reason to use this function */
620   if (!shortdata)
621     return aim_genericreq_n(sess, conn, family, subtype);
622
623   if (!(newpacket = aim_tx_new(0x0002, conn, 10+sizeof(u_short))))
624     return -1;
625
626   newpacket->lock = 1;
627
628   aim_putsnac(newpacket->data, family, subtype, 0x0000, sess->snac_nextid);
629
630   /* copy in data */
631   newshort = htons(*shortdata);
632   memcpy(&(newpacket->data[10]), &newshort, sizeof(u_short));
633
634   aim_tx_enqueue(sess, newpacket);
635   return (sess->snac_nextid++);
636 }
637
638 /*
639  * aim_bos_reqlocaterights()
640  *
641  * Request Location services rights.
642  *
643  */
644 u_long aim_bos_reqlocaterights(struct aim_session_t *sess,
645                                struct aim_conn_t *conn)
646 {
647   return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
648 }
649
650 /*
651 * aim_bos_reqicbmparaminfo()
652  *
653  * Request ICBM parameter information.
654  *
655  */
656 u_long aim_bos_reqicbmparaminfo(struct aim_session_t *sess,
657                                 struct aim_conn_t *conn)
658 {
659   return aim_genericreq_n(sess, conn, 0x0004, 0x0004);
660 }
661
This page took 0.104033 seconds and 5 git commands to generate.