source: protocols/oscar/misc.c @ 4c225f0

Last change on this file since 4c225f0 was b7d3cc34, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-11-06T18:23:18Z

Initial repository (0.99 release tree)

  • Property mode set to 100644
File size: 9.9 KB
Line 
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 <aim.h> 
15
16/*
17 * aim_bos_setbuddylist(buddylist)
18 *
19 * This just builds the "set buddy list" command then queues it.
20 *
21 * buddy_list = "Screen Name One&ScreenNameTwo&";
22 *
23 * TODO: Clean this up. 
24 *
25 * XXX: I can't stress the TODO enough.
26 *
27 */
28int aim_bos_setbuddylist(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list)
29{
30        aim_frame_t *fr;
31        aim_snacid_t snacid;
32        int len = 0;
33        char *localcpy = NULL;
34        char *tmpptr = NULL;
35
36        if (!buddy_list || !(localcpy = g_strdup(buddy_list))) 
37                return -EINVAL;
38
39        for (tmpptr = strtok(localcpy, "&"); tmpptr; ) {
40                len += 1 + strlen(tmpptr);
41                tmpptr = strtok(NULL, "&");
42        }
43
44        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len)))
45                return -ENOMEM;
46
47        snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0);
48        aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);
49
50        strncpy(localcpy, buddy_list, strlen(buddy_list) + 1);
51
52        for (tmpptr = strtok(localcpy, "&"); tmpptr; ) {
53
54                aimbs_put8(&fr->data, strlen(tmpptr));
55                aimbs_putraw(&fr->data, (guint8 *)tmpptr, strlen(tmpptr));
56                tmpptr = strtok(NULL, "&");
57        }
58
59        aim_tx_enqueue(sess, fr);
60
61        g_free(localcpy);
62
63        return 0;
64}
65
66/*
67 * aim_bos_setprofile(profile)
68 *
69 * Gives BOS your profile.
70 *
71 */
72int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, guint32 caps)
73{
74        static const char defencoding[] = {"text/aolrtf; charset=\"utf-8\""};
75        aim_frame_t *fr;
76        aim_tlvlist_t *tl = NULL;
77        aim_snacid_t snacid;
78
79        /* Build to packet first to get real length */
80        if (profile) {
81                aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), (guint8 *)defencoding);
82                aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), (guint8 *)profile);
83        }
84
85        /*
86         * So here's how this works:
87         *   - You are away when you have a non-zero-length type 4 TLV stored.
88         *   - You become unaway when you clear the TLV with a zero-length
89         *       type 4 TLV.
90         *   - If you do not send the type 4 TLV, your status does not change
91         *       (that is, if you were away, you'll remain away).
92         */
93        if (awaymsg) {
94                if (strlen(awaymsg)) {
95                        aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), (guint8 *)defencoding);
96                        aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), (guint8 *)awaymsg);
97                } else
98                        aim_addtlvtochain_noval(&tl, 0x0004);
99        }
100
101        aim_addtlvtochain_caps(&tl, 0x0005, caps);
102
103        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl))))
104                return -ENOMEM;
105
106        snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0);
107       
108        aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid);
109        aim_writetlvchain(&fr->data, &tl);
110        aim_freetlvchain(&tl);
111
112        aim_tx_enqueue(sess, fr);
113
114        return 0;
115}
116
117/*
118 * aim_bos_reqbuddyrights()
119 *
120 * Request Buddy List rights.
121 *
122 */
123int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn)
124{
125        return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
126}
127
128/*
129 * Send a warning to destsn.
130 *
131 * Flags:
132 *  AIM_WARN_ANON  Send as an anonymous (doesn't count as much)
133 *
134 * returns -1 on error (couldn't alloc packet), 0 on success.
135 *
136 */
137int aim_send_warning(aim_session_t *sess, aim_conn_t *conn, const char *destsn, guint32 flags)
138{
139        aim_frame_t *fr;
140        aim_snacid_t snacid;
141        guint16 outflags = 0x0000;
142
143        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, strlen(destsn)+13)))
144                return -ENOMEM;
145
146        snacid = aim_cachesnac(sess, 0x0004, 0x0008, 0x0000, destsn, strlen(destsn)+1);
147
148        aim_putsnac(&fr->data, 0x0004, 0x0008, 0x0000, snacid);
149
150        if (flags & AIM_WARN_ANON)
151                outflags |= 0x0001;
152
153        aimbs_put16(&fr->data, outflags); 
154        aimbs_put8(&fr->data, strlen(destsn));
155        aimbs_putraw(&fr->data, (guint8 *)destsn, strlen(destsn));
156
157        aim_tx_enqueue(sess, fr);
158
159        return 0;
160}
161
162/*
163 * Generic routine for sending commands.
164 *
165 *
166 * I know I can do this in a smarter way...but I'm not thinking straight
167 * right now...
168 *
169 * I had one big function that handled all three cases, but then it broke
170 * and I split it up into three.  But then I fixed it.  I just never went
171 * back to the single.  I don't see any advantage to doing it either way.
172 *
173 */
174int aim_genericreq_n(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype)
175{
176        aim_frame_t *fr;
177        aim_snacid_t snacid = 0x00000000;
178
179        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10)))
180                return -ENOMEM;
181
182        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
183
184        aim_tx_enqueue(sess, fr);
185
186        return 0;
187}
188
189int aim_genericreq_n_snacid(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype)
190{
191        aim_frame_t *fr;
192        aim_snacid_t snacid;
193
194        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10)))
195                return -ENOMEM;
196
197        snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
198        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
199
200        aim_tx_enqueue(sess, fr);
201
202        return 0;
203}
204
205int aim_genericreq_l(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype, guint32 *longdata)
206{
207        aim_frame_t *fr;
208        aim_snacid_t snacid;
209
210        if (!longdata)
211                return aim_genericreq_n(sess, conn, family, subtype);
212
213        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4)))
214                return -ENOMEM; 
215
216        snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
217
218        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
219        aimbs_put32(&fr->data, *longdata);
220
221        aim_tx_enqueue(sess, fr);
222
223        return 0;
224}
225
226int aim_genericreq_s(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype, guint16 *shortdata)
227{
228        aim_frame_t *fr;
229        aim_snacid_t snacid;
230
231        if (!shortdata)
232                return aim_genericreq_n(sess, conn, family, subtype);
233
234        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+2)))
235                return -ENOMEM; 
236
237        snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
238
239        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
240        aimbs_put16(&fr->data, *shortdata);
241
242        aim_tx_enqueue(sess, fr);
243
244        return 0;
245}
246
247/*
248 * aim_bos_reqlocaterights()
249 *
250 * Request Location services rights.
251 *
252 */
253int aim_bos_reqlocaterights(aim_session_t *sess, aim_conn_t *conn)
254{
255        return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
256}
257
258/*
259 * Set directory profile data (not the same as aim_bos_setprofile!)
260 *
261 * privacy: 1 to allow searching, 0 to disallow.
262 */
263int 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, guint16 privacy) 
264{
265        aim_frame_t *fr;
266        aim_snacid_t snacid;
267        aim_tlvlist_t *tl = NULL;
268
269
270        aim_addtlvtochain16(&tl, 0x000a, privacy);
271
272        if (first)
273                aim_addtlvtochain_raw(&tl, 0x0001, strlen(first), (guint8 *)first);
274        if (last)
275                aim_addtlvtochain_raw(&tl, 0x0002, strlen(last), (guint8 *)last);
276        if (middle)
277                aim_addtlvtochain_raw(&tl, 0x0003, strlen(middle), (guint8 *)middle);
278        if (maiden)
279                aim_addtlvtochain_raw(&tl, 0x0004, strlen(maiden), (guint8 *)maiden);
280
281        if (state)
282                aim_addtlvtochain_raw(&tl, 0x0007, strlen(state), (guint8 *)state);
283        if (city)
284                aim_addtlvtochain_raw(&tl, 0x0008, strlen(city), (guint8 *)city);
285
286        if (nickname)
287                aim_addtlvtochain_raw(&tl, 0x000c, strlen(nickname), (guint8 *)nickname);
288        if (zip)
289                aim_addtlvtochain_raw(&tl, 0x000d, strlen(zip), (guint8 *)zip);
290
291        if (street)
292                aim_addtlvtochain_raw(&tl, 0x0021, strlen(street), (guint8 *)street);
293
294        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
295                return -ENOMEM;
296
297        snacid = aim_cachesnac(sess, 0x0002, 0x0009, 0x0000, NULL, 0);
298       
299        aim_putsnac(&fr->data, 0x0002, 0x0009, 0x0000, snacid);
300        aim_writetlvchain(&fr->data, &tl);
301        aim_freetlvchain(&tl);
302
303        aim_tx_enqueue(sess, fr);
304
305        return 0;
306}
307
308/* XXX pass these in better */
309int 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, guint16 privacy)
310{
311        aim_frame_t *fr;
312        aim_snacid_t snacid;
313        aim_tlvlist_t *tl = NULL;
314
315        /* ?? privacy ?? */
316        aim_addtlvtochain16(&tl, 0x000a, privacy);
317
318        if (interest1)
319                aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest1), (guint8 *)interest1);
320        if (interest2)
321                aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest2), (guint8 *)interest2);
322        if (interest3)
323                aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest3), (guint8 *)interest3);
324        if (interest4)
325                aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest4), (guint8 *)interest4);
326        if (interest5)
327                aim_addtlvtochain_raw(&tl, 0x0000b, strlen(interest5), (guint8 *)interest5);
328
329        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+aim_sizetlvchain(&tl))))
330                return -ENOMEM;
331
332        snacid = aim_cachesnac(sess, 0x0002, 0x000f, 0x0000, NULL, 0);
333
334        aim_putsnac(&fr->data, 0x0002, 0x000f, 0x0000, 0);
335        aim_writetlvchain(&fr->data, &tl);
336        aim_freetlvchain(&tl);
337
338        aim_tx_enqueue(sess, fr);
339
340        return 0;
341}
342
343/*
344 * Should be generic enough to handle the errors for all groups.
345 *
346 */
347static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
348{
349        int ret = 0;
350        int error = 0;
351        aim_rxcallback_t userfunc;
352        aim_snac_t *snac2;
353
354        snac2 = aim_remsnac(sess, snac->id);
355
356        if (aim_bstream_empty(bs))
357                error = aimbs_get16(bs);
358
359        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
360                ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL);
361
362        if (snac2)
363                g_free(snac2->data);
364        g_free(snac2);
365
366        return ret;
367}
368
369static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
370{
371
372        if (snac->subtype == 0x0001)
373                return generror(sess, mod, rx, snac, bs);
374        else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
375                aim_rxcallback_t userfunc;
376
377                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
378                        return userfunc(sess, rx);
379        }
380
381        return 0;
382}
383
384int misc_modfirst(aim_session_t *sess, aim_module_t *mod)
385{
386
387        mod->family = 0xffff;
388        mod->version = 0x0000;
389        mod->flags = AIM_MODFLAG_MULTIFAMILY;
390        strncpy(mod->name, "misc", sizeof(mod->name));
391        mod->snachandler = snachandler;
392
393        return 0;
394}
395
396
Note: See TracBrowser for help on using the repository browser.