source: protocols/oscar/misc.c @ 1c7b646

Last change on this file since 1c7b646 was e88fe7da, checked in by Veres Lajos <vlajos@…>, at 2015-08-07T21:53:25Z

typofix - https://github.com/vlajos/misspell_fixer

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[b7d3cc34]1
2/*
3 * aim_misc.c
4 *
[e88fe7da]5 * TODO: Separate a lot of this into an aim_bos.c.
[b7d3cc34]6 *
7 * Other things...
8 *
[5ebff60]9 *   - Idle setting
10 *
[b7d3cc34]11 *
12 */
13
[5ebff60]14#include <aim.h>
[b7d3cc34]15
[5ebff60]16/*
[b7d3cc34]17 * aim_bos_setprofile(profile)
18 *
19 * Gives BOS your profile.
[5ebff60]20 *
[b7d3cc34]21 */
22int aim_bos_setprofile(aim_session_t *sess, aim_conn_t *conn, const char *profile, const char *awaymsg, guint32 caps)
23{
[5ebff60]24        static const char defencoding[] = { "text/aolrtf; charset=\"utf-8\"" };
[b7d3cc34]25        aim_frame_t *fr;
26        aim_tlvlist_t *tl = NULL;
27        aim_snacid_t snacid;
28
29        /* Build to packet first to get real length */
30        if (profile) {
[5ebff60]31                aim_addtlvtochain_raw(&tl, 0x0001, strlen(defencoding), (guint8 *) defencoding);
32                aim_addtlvtochain_raw(&tl, 0x0002, strlen(profile), (guint8 *) profile);
[b7d3cc34]33        }
34
35        /*
36         * So here's how this works:
37         *   - You are away when you have a non-zero-length type 4 TLV stored.
38         *   - You become unaway when you clear the TLV with a zero-length
39         *       type 4 TLV.
40         *   - If you do not send the type 4 TLV, your status does not change
41         *       (that is, if you were away, you'll remain away).
42         */
43        if (awaymsg) {
44                if (strlen(awaymsg)) {
[5ebff60]45                        aim_addtlvtochain_raw(&tl, 0x0003, strlen(defencoding), (guint8 *) defencoding);
46                        aim_addtlvtochain_raw(&tl, 0x0004, strlen(awaymsg), (guint8 *) awaymsg);
47                } else {
[b7d3cc34]48                        aim_addtlvtochain_noval(&tl, 0x0004);
[5ebff60]49                }
[b7d3cc34]50        }
51
52        aim_addtlvtochain_caps(&tl, 0x0005, caps);
53
[5ebff60]54        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + aim_sizetlvchain(&tl)))) {
[b7d3cc34]55                return -ENOMEM;
[5ebff60]56        }
[b7d3cc34]57
58        snacid = aim_cachesnac(sess, 0x0002, 0x0004, 0x0000, NULL, 0);
[5ebff60]59
[b7d3cc34]60        aim_putsnac(&fr->data, 0x0002, 0x004, 0x0000, snacid);
61        aim_writetlvchain(&fr->data, &tl);
62        aim_freetlvchain(&tl);
63
64        aim_tx_enqueue(sess, fr);
65
66        return 0;
67}
68
69/*
70 * aim_bos_reqbuddyrights()
71 *
72 * Request Buddy List rights.
73 *
74 */
75int aim_bos_reqbuddyrights(aim_session_t *sess, aim_conn_t *conn)
76{
77        return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
78}
79
80/*
81 * Generic routine for sending commands.
82 *
83 *
84 * I know I can do this in a smarter way...but I'm not thinking straight
85 * right now...
86 *
87 * I had one big function that handled all three cases, but then it broke
88 * and I split it up into three.  But then I fixed it.  I just never went
89 * back to the single.  I don't see any advantage to doing it either way.
90 *
91 */
92int aim_genericreq_n(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype)
93{
94        aim_frame_t *fr;
95        aim_snacid_t snacid = 0x00000000;
96
[5ebff60]97        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) {
[b7d3cc34]98                return -ENOMEM;
[5ebff60]99        }
[b7d3cc34]100
101        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
102
103        aim_tx_enqueue(sess, fr);
104
105        return 0;
106}
107
108int aim_genericreq_n_snacid(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype)
109{
110        aim_frame_t *fr;
111        aim_snacid_t snacid;
112
[5ebff60]113        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10))) {
[b7d3cc34]114                return -ENOMEM;
[5ebff60]115        }
[b7d3cc34]116
117        snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
118        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
119
120        aim_tx_enqueue(sess, fr);
121
122        return 0;
123}
124
125int aim_genericreq_l(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype, guint32 *longdata)
126{
127        aim_frame_t *fr;
128        aim_snacid_t snacid;
129
[5ebff60]130        if (!longdata) {
[b7d3cc34]131                return aim_genericreq_n(sess, conn, family, subtype);
[5ebff60]132        }
[b7d3cc34]133
[5ebff60]134        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 4))) {
135                return -ENOMEM;
136        }
[b7d3cc34]137
138        snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
139
140        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
141        aimbs_put32(&fr->data, *longdata);
142
143        aim_tx_enqueue(sess, fr);
144
145        return 0;
146}
147
148int aim_genericreq_s(aim_session_t *sess, aim_conn_t *conn, guint16 family, guint16 subtype, guint16 *shortdata)
149{
150        aim_frame_t *fr;
151        aim_snacid_t snacid;
152
[5ebff60]153        if (!shortdata) {
[b7d3cc34]154                return aim_genericreq_n(sess, conn, family, subtype);
[5ebff60]155        }
[b7d3cc34]156
[5ebff60]157        if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 2))) {
158                return -ENOMEM;
159        }
[b7d3cc34]160
161        snacid = aim_cachesnac(sess, family, subtype, 0x0000, NULL, 0);
162
163        aim_putsnac(&fr->data, family, subtype, 0x0000, snacid);
164        aimbs_put16(&fr->data, *shortdata);
165
166        aim_tx_enqueue(sess, fr);
167
168        return 0;
169}
170
171/*
172 * aim_bos_reqlocaterights()
173 *
174 * Request Location services rights.
175 *
176 */
177int aim_bos_reqlocaterights(aim_session_t *sess, aim_conn_t *conn)
178{
179        return aim_genericreq_n(sess, conn, 0x0002, 0x0002);
180}
181
182/*
183 * Should be generic enough to handle the errors for all groups.
184 *
185 */
186static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
187{
188        int ret = 0;
189        int error = 0;
190        aim_rxcallback_t userfunc;
191        aim_snac_t *snac2;
192
193        snac2 = aim_remsnac(sess, snac->id);
194
[5ebff60]195        if (aim_bstream_empty(bs)) {
[b7d3cc34]196                error = aimbs_get16(bs);
[5ebff60]197        }
[b7d3cc34]198
[5ebff60]199        if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
[b7d3cc34]200                ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL);
[5ebff60]201        }
[b7d3cc34]202
[5ebff60]203        if (snac2) {
[b7d3cc34]204                g_free(snac2->data);
[5ebff60]205        }
[b7d3cc34]206        g_free(snac2);
207
208        return ret;
209}
210
211static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
212{
213
[5ebff60]214        if (snac->subtype == 0x0001) {
[b7d3cc34]215                return generror(sess, mod, rx, snac, bs);
[5ebff60]216        } else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
[b7d3cc34]217                aim_rxcallback_t userfunc;
218
[5ebff60]219                if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
[b7d3cc34]220                        return userfunc(sess, rx);
[5ebff60]221                }
[b7d3cc34]222        }
223
224        return 0;
225}
226
227int misc_modfirst(aim_session_t *sess, aim_module_t *mod)
228{
229
230        mod->family = 0xffff;
231        mod->version = 0x0000;
232        mod->flags = AIM_MODFLAG_MULTIFAMILY;
233        strncpy(mod->name, "misc", sizeof(mod->name));
234        mod->snachandler = snachandler;
235
236        return 0;
237}
238
239
Note: See TracBrowser for help on using the repository browser.