]> andersk Git - libfaim.git/blob - src/misc.c
- Sun Oct 14 19:45:54 PDT 2001
[libfaim.git] / src / 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 #define FAIM_INTERNAL
15 #include <aim.h> 
16
17 /*
18  * aim_bos_setidle()
19  *
20  *  Should set your current idle time in seconds.  Idealy, OSCAR should
21  *  do this for us.  But, it doesn't.  The client must call this to set idle
22  *  time.  
23  *
24  */
25 faim_export int aim_bos_setidle(aim_session_t *sess, aim_conn_t *conn, fu32_t idletime)
26 {
27         return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime);
28 }
29
30
31 /*
32  * aim_bos_changevisibility(conn, changtype, namelist)
33  *
34  * Changes your visibility depending on changetype:
35  *
36  *  AIM_VISIBILITYCHANGE_PERMITADD: Lets provided list of names see you
37  *  AIM_VISIBILITYCHANGE_PERMIDREMOVE: Removes listed names from permit list
38  *  AIM_VISIBILITYCHANGE_DENYADD: Hides you from provided list of names
39  *  AIM_VISIBILITYCHANGE_DENYREMOVE: Lets list see you again
40  *
41  * list should be a list of 
42  * screen names in the form "Screen Name One&ScreenNameTwo&" etc.
43  *
44  * Equivelents to options in WinAIM:
45  *   - Allow all users to contact me: Send an AIM_VISIBILITYCHANGE_DENYADD
46  *      with only your name on it.
47  *   - Allow only users on my Buddy List: Send an 
48  *      AIM_VISIBILITYCHANGE_PERMITADD with the list the same as your
49  *      buddy list
50  *   - Allow only the uesrs below: Send an AIM_VISIBILITYCHANGE_PERMITADD 
51  *      with everyone listed that you want to see you.
52  *   - Block all users: Send an AIM_VISIBILITYCHANGE_PERMITADD with only 
53  *      yourself in the list
54  *   - Block the users below: Send an AIM_VISIBILITYCHANGE_DENYADD with
55  *      the list of users to be blocked
56  *
57  * XXX ye gods.
58  */
59 faim_export int aim_bos_changevisibility(aim_session_t *sess, aim_conn_t *conn, int changetype, const char *denylist)
60 {
61         aim_frame_t *fr;
62         int packlen = 0;
63         fu16_t subtype;
64         char *localcpy = NULL, *tmpptr = NULL;
65         int i;
66         int listcount;
67         aim_snacid_t snacid;
68
69         if (!denylist)
70                 return -EINVAL;
71
72         if (changetype == AIM_VISIBILITYCHANGE_PERMITADD)
73                 subtype = 0x05;
74         else if (changetype == AIM_VISIBILITYCHANGE_PERMITREMOVE)
75                 subtype = 0x06;
76         else if (changetype == AIM_VISIBILITYCHANGE_DENYADD)
77                 subtype = 0x07;
78         else if (changetype == AIM_VISIBILITYCHANGE_DENYREMOVE)
79                 subtype = 0x08;
80         else
81                 return -EINVAL;
82
83         localcpy = strdup(denylist);
84
85         listcount = aimutil_itemcnt(localcpy, '&');
86         packlen = aimutil_tokslen(localcpy, 99, '&') + listcount + 9;
87
88         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, packlen))) {
89                 free(localcpy);
90                 return -ENOMEM;
91         }
92
93         snacid = aim_cachesnac(sess, 0x0009, subtype, 0x0000, NULL, 0);
94         aim_putsnac(&fr->data, 0x0009, subtype, 0x00, snacid);
95
96         for (i = 0; (i < (listcount - 1)) && (i < 99); i++) {
97                 tmpptr = aimutil_itemidx(localcpy, i, '&');
98
99                 aimbs_put8(&fr->data, strlen(tmpptr));
100                 aimbs_putraw(&fr->data, tmpptr, strlen(tmpptr));
101
102                 free(tmpptr);
103         }
104         free(localcpy);
105
106         aim_tx_enqueue(sess, fr);
107
108         return 0;
109 }
110
111
112
113 /*
114  * aim_bos_setbuddylist(buddylist)
115  *
116  * This just builds the "set buddy list" command then queues it.
117  *
118  * buddy_list = "Screen Name One&ScreenNameTwo&";
119  *
120  * TODO: Clean this up.  
121  *
122  * XXX: I can't stress the TODO enough.
123  *
124  */
125 faim_export int aim_bos_setbuddylist(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list)
126 {
127         aim_frame_t *fr;
128         aim_snacid_t snacid;
129         int i, len = 0;
130         char *localcpy = NULL;
131         char *tmpptr = NULL;
132
133         if (!buddy_list || !(localcpy = strdup(buddy_list))) 
134                 return -EINVAL;
135
136         i = 0;
137         tmpptr = strtok(localcpy, "&");
138         while ((tmpptr != NULL) && (i < 150)) {
139                 faimdprintf(sess, 2, "---adding %d: %s (%d)\n", i, tmpptr, strlen(tmpptr));
140                 len += 1+strlen(tmpptr);
141                 i++;
142                 tmpptr = strtok(NULL, "&");
143         }
144
145         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len)))
146                 return -ENOMEM;
147
148         snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0);
149         
150         aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);
151
152         strncpy(localcpy, buddy_list, strlen(buddy_list)+1);
153         i = 0;
154         tmpptr = strtok(localcpy, "&");
155         while ((tmpptr != NULL) & (i < 150)) {
156                 faimdprintf(sess, 2, "---adding %d: %s (%d)\n", i, tmpptr, strlen(tmpptr));
157                 
158                 aimbs_put8(&fr->data, strlen(tmpptr));
159                 aimbs_putraw(&fr->data, tmpptr, strlen(tmpptr));
160                 i++;
161                 tmpptr = strtok(NULL, "&");
162         }
163
164         aim_tx_enqueue(sess, fr);
165
166         free(localcpy);
167
168         return 0;
169 }
170
171 /* 
172  * aim_bos_setprofile(profile)
173  *
174  * Gives BOS your profile.
175  *
176  * 
177  */
178 faim_export int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, fu16_t caps)
179 {
180         static const char defencoding[] = {"text/aolrtf; charset=\"us-ascii\""};
181         aim_frame_t *fr;
182         aim_tlvlist_t *tl = NULL;
183         aim_snacid_t snacid;
184
185         /* Build to packet first to get real length */
186         if (profile) {
187                 aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), defencoding);
188                 aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), profile);
189         }
190         
191         if (awaymsg) {
192                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), defencoding);
193                 aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), awaymsg);
194         }
195
196         aim_addtlvtochain_caps(&tl, 0x0005, caps);
197
198         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl))))
199                 return -ENOMEM;
200
201         snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0);
202         
203         aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid);
204         aim_writetlvchain(&fr->data, &tl);
205         aim_freetlvchain(&tl);
206
207         aim_tx_enqueue(sess, fr);
208
209         return 0;
210 }
211
212 /*
213  * aim_bos_clientready()
214  * 
215  * Send Client Ready.  
216  *
217  */
218 faim_export int aim_bos_clientready(aim_session_t *sess, aim_conn_t *conn)
219 {
220         struct aim_tool_version tools[] = {
221                 {0x0001, 0x0003,    AIM_TOOL_WIN32, 0x0686},
222                 {0x0002, 0x0001,    AIM_TOOL_WIN32, 0x0001}, 
223                 {0x0003, 0x0001,    AIM_TOOL_WIN32, 0x0001},
224                 {0x0004, 0x0001,    AIM_TOOL_WIN32, 0x0001},
225                 {0x0006, 0x0001,    AIM_TOOL_WIN32, 0x0001}, 
226                 {0x0008, 0x0001,    AIM_TOOL_WIN32, 0x0001},
227                 {0x0009, 0x0001,    AIM_TOOL_WIN32, 0x0001}, 
228                 {0x000a, 0x0001,    AIM_TOOL_WIN32, 0x0001},
229                 {0x000b, 0x0001,    AIM_TOOL_WIN32, 0x0001}
230         };
231         int j;
232         aim_frame_t *fr;
233         aim_snacid_t snacid;
234         int toolcount = sizeof(tools)/sizeof(struct aim_tool_version);
235
236         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
237                 return -ENOMEM;
238
239         snacid = aim_cachesnac(sess, 0x0001, 0x0002, 0x0000, NULL, 0);
240         aim_putsnac(&fr->data, 0x0001, 0x0002, 0x0000, snacid);
241
242         for (j = 0; j < toolcount; j++) {
243                 aimbs_put16(&fr->data, tools[j].group);
244                 aimbs_put16(&fr->data, tools[j].version);
245                 aimbs_put16(&fr->data, tools[j].tool);
246                 aimbs_put16(&fr->data, tools[j].toolversion);
247         }
248
249         aim_tx_enqueue(sess, fr);
250
251         return 0;
252 }
253
254 /* 
255  *  Request Rate Information.
256  * 
257  */
258 faim_export int aim_bos_reqrate(aim_session_t *sess, aim_conn_t *conn)
259 {
260         return aim_genericreq_n(sess, conn, 0x0001, 0x0006);
261 }
262
263 /* 
264  *  Rate Information Response Acknowledge.
265  *
266  */
267 faim_export int aim_bos_ackrateresp(aim_session_t *sess, aim_conn_t *conn)
268 {
269         aim_frame_t *fr;        
270         aim_snacid_t snacid;
271
272         if(!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+10)))
273                 return -ENOMEM; 
274
275         snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0);
276         
277         aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid);
278         aimbs_put16(&fr->data, 0x0001); 
279         aimbs_put16(&fr->data, 0x0002);
280         aimbs_put16(&fr->data, 0x0003);
281         aimbs_put16(&fr->data, 0x0004);
282         aimbs_put16(&fr->data, 0x0005);
283
284         aim_tx_enqueue(sess, fr);
285
286         return 0;
287 }
288
289 /* 
290  * aim_bos_setprivacyflags()
291  *
292  * Sets privacy flags. Normally 0x03.
293  *
294  *  Bit 1:  Allows other AIM users to see how long you've been idle.
295  *  Bit 2:  Allows other AIM users to see how long you've been a member.
296  *
297  */
298 faim_export int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, fu32_t flags)
299 {
300         return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);
301 }
302
303 /*
304  * aim_bos_reqpersonalinfo()
305  *
306  */
307 faim_export int aim_bos_reqpersonalinfo(aim_session_t *sess, aim_conn_t *conn)
308 {
309         return aim_genericreq_n(sess, conn, 0x0001, 0x000e);
310 }
311
312 faim_export int aim_setversions(aim_session_t *sess, aim_conn_t *conn)
313 {
314         aim_frame_t *fr;
315         aim_snacid_t snacid;
316         static const struct version {
317                 fu16_t group;
318                 fu16_t version;
319         } versions[] = {
320                 {0x0001, 0x0003},
321                 {0x0002, 0x0001},
322                 {0x0003, 0x0001},
323                 {0x0004, 0x0001},
324                 {0x0006, 0x0001},
325                 {0x0008, 0x0001},
326                 {0x0009, 0x0001},
327                 {0x000a, 0x0001},
328                 {0x000b, 0x0002},
329                 {0x000c, 0x0001},
330                 {0x0013, 0x0001},
331                 {0x0015, 0x0001},
332         };
333         int numversions = sizeof(versions) / sizeof(struct version);
334         int i;
335
336         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + (4*numversions))))
337                 return -ENOMEM;
338
339         snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0);
340
341         aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid);
342         for (i = 0; i < numversions; i++) {
343                 aimbs_put16(&fr->data, versions[i].group);
344                 aimbs_put16(&fr->data, versions[i].version);
345         }
346
347         aim_tx_enqueue(sess, fr);
348
349         return 0;
350 }
351
352
353 /*
354  * aim_bos_reqservice(serviceid)
355  *
356  * Service request. 
357  *
358  */
359 faim_export int aim_bos_reqservice(aim_session_t *sess, aim_conn_t *conn, fu16_t serviceid)
360 {
361         return aim_genericreq_s(sess, conn, 0x0001, 0x0004, &serviceid);
362 }
363
364 /*
365  * aim_bos_nop()
366  *
367  * No-op.  WinAIM sends these every 4min or so to keep
368  * the connection alive.  Its not real necessary.
369  *
370  */
371 faim_export int aim_bos_nop(aim_session_t *sess, aim_conn_t *conn)
372 {
373         return aim_genericreq_n(sess, conn, 0x0001, 0x0016);
374 }
375
376 /*
377  * aim_flap_nop()
378  *
379  * No-op.  WinAIM 4.x sends these _every minute_ to keep
380  * the connection alive.  
381  */
382 faim_export int aim_flap_nop(aim_session_t *sess, aim_conn_t *conn)
383 {
384         aim_frame_t *fr;
385
386         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x05, 0)))
387                 return -ENOMEM;
388
389         aim_tx_enqueue(sess, fr);
390
391         return 0;
392 }
393
394 /*
395  * aim_bos_reqrights()
396  *
397  * Request BOS rights.
398  *
399  */
400 faim_export int aim_bos_reqrights(aim_session_t *sess, aim_conn_t *conn)
401 {
402         return aim_genericreq_n(sess, conn, 0x0009, 0x0002);
403 }
404
405 /*
406  * aim_bos_reqbuddyrights()
407  *
408  * Request Buddy List rights.
409  *
410  */
411 faim_export int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn)
412 {
413         return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
414 }
415
416 /*
417  * Send a warning to destsn.
418  * 
419  * Flags:
420  *  AIM_WARN_ANON  Send as an anonymous (doesn't count as much)
421  *
422  * returns -1 on error (couldn't alloc packet), 0 on success. 
423  *
424  */
425 faim_export int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags)
426 {
427         aim_frame_t *fr;
428         aim_snacid_t snacid;
429         fu16_t outflags = 0x0000;
430
431         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13)))
432                 return -ENOMEM;
433
434         snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1);
435
436         aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid);
437
438         if (flags & AIM_WARN_ANON)
439                 outflags |= 0x0001;
440
441         aimbs_put16(&fr->data, outflags); 
442         aimbs_put8(&fr->data, strlen(destsn));
443         aimbs_putraw(&fr->data, destsn, strlen(destsn));
444
445         aim_tx_enqueue(sess, fr);
446
447         return 0;
448 }
449
450 /*
451  * aim_debugconn_sendconnect()
452  *
453  * For aimdebugd.  If you don't know what it is, you don't want to.
454  */
455 faim_export int aim_debugconn_sendconnect(aim_session_t *sess, aim_conn_t *conn)
456 {
457         return aim_genericreq_n(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT);
458 }
459
460 /*
461  * Generic routine for sending commands.
462  *
463  *
464  * I know I can do this in a smarter way...but I'm not thinking straight
465  * right now...
466  *
467  * I had one big function that handled all three cases, but then it broke
468  * and I split it up into three.  But then I fixed it.  I just never went
469  * back to the single.  I don't see any advantage to doing it either way.
470  *
471  */
472 faim_internal int aim_genericreq_n(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype)
473 {
474         aim_frame_t *fr;
475         aim_snacid_t snacid = 0x00000000;
476
477         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10)))
478                 return -ENOMEM;
479
480         aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
481
482         aim_tx_enqueue(sess, fr);
483
484         return 0;
485 }
486
487 faim_internal int aim_genericreq_n_snacid(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype)
488 {
489         aim_frame_t *fr;
490         aim_snacid_t snacid;
491
492         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10)))
493                 return -ENOMEM;
494
495         snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
496         aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
497
498         aim_tx_enqueue(sess, fr);
499
500         return 0;
501 }
502
503 /*
504  *
505  *
506  */
507 faim_internal int aim_genericreq_l(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype, fu32_t *longdata)
508 {
509         aim_frame_t *fr;
510         aim_snacid_t snacid;
511
512         if (!longdata)
513                 return aim_genericreq_n(sess, conn, family, subtype);
514
515         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4)))
516                 return -ENOMEM; 
517
518         snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
519
520         aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
521         aimbs_put32(&fr->data, *longdata);
522
523         aim_tx_enqueue(sess, fr);
524
525         return 0;
526 }
527
528 faim_internal int aim_genericreq_s(aim_session_t *sess, aim_conn_t *conn, fu16_t family, fu16_t subtype, fu16_t *shortdata)
529 {
530         aim_frame_t *fr;
531         aim_snacid_t snacid;
532
533         if (!shortdata)
534                 return aim_genericreq_n(sess, conn, family, subtype);
535
536         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2)))
537                 return -ENOMEM; 
538
539         snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
540
541         aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
542         aimbs_put16(&fr->data, *shortdata);
543
544         aim_tx_enqueue(sess, fr);
545
546         return 0;
547 }
548
549 /*
550  * aim_bos_reqlocaterights()
551  *
552  * Request Location services rights.
553  *
554  */
555 faim_export int aim_bos_reqlocaterights(aim_session_t *sess, aim_conn_t *conn)
556 {
557         return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
558 }
559
560 /* 
561  * Set directory profile data (not the same as aim_bos_setprofile!)
562  *
563  * privacy: 1 to allow searching, 0 to disallow.
564  */
565 faim_export int aim_setdirectoryinfo(aim_session_t *sess, aim_conn_t *conn, const char *first, const char *middle, const char *last, const char *maiden, const char *nickname, const char *street, const char *city, const char *state, const char *zip, int country, fu16_t privacy) 
566 {
567         aim_frame_t *fr;
568         aim_snacid_t snacid;
569         aim_tlvlist_t *tl = NULL;
570
571
572         aim_addtlvtochain16(&tl, 0x000a, privacy);
573
574         if (first)
575                 aim_addtlvtochain_raw(&tl, 0x0001, strlen(first), first);
576         if (last)
577                 aim_addtlvtochain_raw(&tl, 0x0002, strlen(last), last);
578         if (middle)
579                 aim_addtlvtochain_raw(&tl, 0x0003, strlen(middle), middle);
580         if (maiden)
581                 aim_addtlvtochain_raw(&tl, 0x0004, strlen(maiden), maiden);
582
583         if (state)
584                 aim_addtlvtochain_raw(&tl, 0x0007, strlen(state), state);
585         if (city)
586                 aim_addtlvtochain_raw(&tl, 0x0008, strlen(city), city);
587
588         if (nickname)
589                 aim_addtlvtochain_raw(&tl, 0x000c, strlen(nickname), nickname);
590         if (zip)
591                 aim_addtlvtochain_raw(&tl, 0x000d, strlen(zip), zip);
592
593         if (street)
594                 aim_addtlvtochain_raw(&tl, 0x0021, strlen(street), street);
595
596         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
597                 return -ENOMEM;
598
599         snacid = aim_cachesnac(sess, 0x0002, 0x0009, 0x0000, NULL, 0);
600         
601         aim_putsnac(&fr->data, 0x0002, 0x0009, 0x0000, snacid);
602         aim_writetlvchain(&fr->data, &tl);
603         aim_freetlvchain(&tl);
604
605         aim_tx_enqueue(sess, fr);
606
607         return 0;
608 }
609
610 /* XXX pass these in better */
611 faim_export int aim_setuserinterests(aim_session_t *sess, aim_conn_t *conn, const char *interest1, const char *interest2, const char *interest3, const char *interest4, const char *interest5, fu16_t privacy)
612 {
613         aim_frame_t *fr;
614         aim_snacid_t snacid;
615         aim_tlvlist_t *tl = NULL;
616
617         /* ?? privacy ?? */
618         aim_addtlvtochain16(&tl, 0x000a, privacy);
619
620         if (interest1)
621                 aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest1), interest1);
622         if (interest2)
623                 aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest2), interest2);
624         if (interest3)
625                 aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest3), interest3);
626         if (interest4)
627                 aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest4), interest4);
628         if (interest5)
629                 aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest5), interest5);
630
631         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
632                 return -ENOMEM;
633
634         snacid = aim_cachesnac(sess, 0x0002, 0x000f, 0x0000, NULL, 0);
635
636         aim_putsnac(&fr->data, 0x0002, 0x000f, 0x0000, 0);
637         aim_writetlvchain(&fr->data, &tl);
638         aim_freetlvchain(&tl);
639
640         aim_tx_enqueue(sess, fr);
641
642         return 0;
643 }
644
645 faim_export int aim_icq_setstatus(aim_session_t *sess, aim_conn_t *conn, fu16_t status)
646 {
647         aim_frame_t *fr;
648         aim_snacid_t snacid;
649         aim_tlvlist_t *tl = NULL;
650         fu32_t data;
651
652         data = 0x00030000 | status; /* yay for error checking ;^) */
653
654         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 8)))
655                 return -ENOMEM;
656
657         snacid = aim_cachesnac(sess, 0x0001, 0x001e, 0x0000, NULL, 0);
658         aim_putsnac(&fr->data, 0x0001, 0x001e, 0x0000, snacid);
659         
660         aim_addtlvtochain32(&tl, 0x0006, data);
661         aim_writetlvchain(&fr->data, &tl);
662         aim_freetlvchain(&tl);
663         
664         aim_tx_enqueue(sess, fr);
665
666         return 0;
667 }
668
669 /*
670  * Should be generic enough to handle the errors for all families...
671  *
672  */
673 static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
674 {
675         int ret = 0;
676         int error = 0;
677         aim_rxcallback_t userfunc;
678         aim_snac_t *snac2;
679
680         snac2 = aim_remsnac(sess, snac->id);
681
682         if (aim_bstream_empty(bs))
683                 error = aimbs_get16(bs);
684
685         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
686                 ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL);
687
688         if (snac2)
689                 free(snac2->data);
690         free(snac2);
691
692         return ret;
693 }
694
695 static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
696 {
697
698         if (snac->subtype == 0x0001)
699                 return generror(sess, mod, rx, snac, bs);
700         else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
701                 aim_rxcallback_t userfunc;
702
703                 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
704                         return userfunc(sess, rx);
705         }
706
707         return 0;
708 }
709
710 faim_internal int misc_modfirst(aim_session_t *sess, aim_module_t *mod)
711 {
712
713         mod->family = 0xffff;
714         mod->version = 0x0000;
715         mod->flags = AIM_MODFLAG_MULTIFAMILY;
716         strncpy(mod->name, "misc", sizeof(mod->name));
717         mod->snachandler = snachandler;
718
719         return 0;
720 }
This page took 0.0970490000000001 seconds and 5 git commands to generate.