src/protocols/oscar/buddylist.c

branch
gaim
changeset 20470
77693555855f
parent 13071
b98e72d4089a
parent 20469
b2836a24d81e
child 20471
1966704b3e42
equal deleted inserted replaced
13071:b98e72d4089a 20470:77693555855f
1 /*
2 * Family 0x0003 - Old-style Buddylist Management (non-SSI).
3 *
4 */
5
6 #define FAIM_INTERNAL
7 #include <aim.h>
8
9 #include <string.h>
10
11 /*
12 * Subtype 0x0002 - Request rights.
13 *
14 * Request Buddy List rights.
15 *
16 */
17 faim_export int aim_buddylist_reqrights(aim_session_t *sess, aim_conn_t *conn)
18 {
19 return aim_genericreq_n_snacid(sess, conn, 0x0003, 0x0002);
20 }
21
22 /*
23 * Subtype 0x0003 - Rights.
24 *
25 */
26 static int rights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
27 {
28 aim_rxcallback_t userfunc;
29 aim_tlvlist_t *tlvlist;
30 fu16_t maxbuddies = 0, maxwatchers = 0;
31 int ret = 0;
32
33 /*
34 * TLVs follow
35 */
36 tlvlist = aim_tlvlist_read(bs);
37
38 /*
39 * TLV type 0x0001: Maximum number of buddies.
40 */
41 if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
42 maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);
43
44 /*
45 * TLV type 0x0002: Maximum number of watchers.
46 *
47 * Watchers are other users who have you on their buddy
48 * list. (This is called the "reverse list" by a certain
49 * other IM protocol.)
50 *
51 */
52 if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
53 maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);
54
55 /*
56 * TLV type 0x0003: Unknown.
57 *
58 * ICQ only?
59 */
60
61 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
62 ret = userfunc(sess, rx, maxbuddies, maxwatchers);
63
64 aim_tlvlist_free(&tlvlist);
65
66 return ret;
67 }
68
69 /*
70 * Subtype 0x0004 - Add buddy to list.
71 *
72 * Adds a single buddy to your buddy list after login.
73 * XXX This should just be an extension of setbuddylist()
74 *
75 */
76 faim_export int aim_buddylist_addbuddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
77 {
78 aim_frame_t *fr;
79 aim_snacid_t snacid;
80
81 if (!sn || !strlen(sn))
82 return -EINVAL;
83
84 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
85 return -ENOMEM;
86
87 snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, sn, strlen(sn)+1);
88 aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);
89
90 aimbs_put8(&fr->data, strlen(sn));
91 aimbs_putstr(&fr->data, sn);
92
93 aim_tx_enqueue(sess, fr);
94
95 return 0;
96 }
97
98 /*
99 * Subtype 0x0004 - Add multiple buddies to your buddy list.
100 *
101 * This just builds the "set buddy list" command then queues it.
102 *
103 * buddy_list = "Screen Name One&ScreenNameTwo&";
104 *
105 * XXX Clean this up.
106 *
107 */
108 faim_export int aim_buddylist_set(aim_session_t *sess, aim_conn_t *conn, const char *buddy_list)
109 {
110 aim_frame_t *fr;
111 aim_snacid_t snacid;
112 int len = 0;
113 char *localcpy = NULL;
114 char *tmpptr = NULL;
115
116 if (!buddy_list || !(localcpy = strdup(buddy_list)))
117 return -EINVAL;
118
119 for (tmpptr = strtok(localcpy, "&"); tmpptr; ) {
120 gaim_debug_misc("oscar", "---adding: %s (%d)\n", tmpptr, strlen(tmpptr));
121 len += 1 + strlen(tmpptr);
122 tmpptr = strtok(NULL, "&");
123 }
124
125 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+len)))
126 return -ENOMEM;
127
128 snacid = aim_cachesnac(sess, 0x0003, 0x0004, 0x0000, NULL, 0);
129 aim_putsnac(&fr->data, 0x0003, 0x0004, 0x0000, snacid);
130
131 strncpy(localcpy, buddy_list, strlen(buddy_list) + 1);
132
133 for (tmpptr = strtok(localcpy, "&"); tmpptr; ) {
134
135 gaim_debug_misc("oscar", "---adding: %s (%d)\n", tmpptr, strlen(tmpptr));
136
137 aimbs_put8(&fr->data, strlen(tmpptr));
138 aimbs_putstr(&fr->data, tmpptr);
139 tmpptr = strtok(NULL, "&");
140 }
141
142 aim_tx_enqueue(sess, fr);
143
144 free(localcpy);
145
146 return 0;
147 }
148
149 /*
150 * Subtype 0x0005 - Remove buddy from list.
151 *
152 * XXX generalise to support removing multiple buddies (basically, its
153 * the same as setbuddylist() but with a different snac subtype).
154 *
155 */
156 faim_export int aim_buddylist_removebuddy(aim_session_t *sess, aim_conn_t *conn, const char *sn)
157 {
158 aim_frame_t *fr;
159 aim_snacid_t snacid;
160
161 if (!sn || !strlen(sn))
162 return -EINVAL;
163
164 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
165 return -ENOMEM;
166
167 snacid = aim_cachesnac(sess, 0x0003, 0x0005, 0x0000, sn, strlen(sn)+1);
168 aim_putsnac(&fr->data, 0x0003, 0x0005, 0x0000, snacid);
169
170 aimbs_put8(&fr->data, strlen(sn));
171 aimbs_putstr(&fr->data, sn);
172
173 aim_tx_enqueue(sess, fr);
174
175 return 0;
176 }
177
178 /*
179 * Subtype 0x000b
180 *
181 * XXX Why would we send this?
182 *
183 */
184 faim_export int aim_buddylist_oncoming(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_t *info)
185 {
186 aim_frame_t *fr;
187 aim_snacid_t snacid;
188
189 if (!sess || !conn || !info)
190 return -EINVAL;
191
192 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152)))
193 return -ENOMEM;
194
195 snacid = aim_cachesnac(sess, 0x0003, 0x000b, 0x0000, NULL, 0);
196
197 aim_putsnac(&fr->data, 0x0003, 0x000b, 0x0000, snacid);
198 aim_putuserinfo(&fr->data, info);
199
200 aim_tx_enqueue(sess, fr);
201
202 return 0;
203 }
204
205 /*
206 * Subtype 0x000c
207 *
208 * XXX Why would we send this?
209 *
210 */
211 faim_export int aim_buddylist_offgoing(aim_session_t *sess, aim_conn_t *conn, const char *sn)
212 {
213 aim_frame_t *fr;
214 aim_snacid_t snacid;
215
216 if (!sess || !conn || !sn)
217 return -EINVAL;
218
219 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn))))
220 return -ENOMEM;
221
222 snacid = aim_cachesnac(sess, 0x0003, 0x000c, 0x0000, NULL, 0);
223
224 aim_putsnac(&fr->data, 0x0003, 0x000c, 0x0000, snacid);
225 aimbs_put8(&fr->data, strlen(sn));
226 aimbs_putstr(&fr->data, sn);
227
228 aim_tx_enqueue(sess, fr);
229
230 return 0;
231 }
232
233 /*
234 * Subtypes 0x000b and 0x000c - Change in buddy status
235 *
236 * Oncoming Buddy notifications contain a subset of the
237 * user information structure. It's close enough to run
238 * through aim_info_extract() however.
239 *
240 * Although the offgoing notification contains no information,
241 * it is still in a format parsable by aim_info_extract().
242 *
243 */
244 static int buddychange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
245 {
246 int ret = 0;
247 aim_userinfo_t userinfo;
248 aim_rxcallback_t userfunc;
249
250 aim_info_extract(sess, bs, &userinfo);
251
252 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
253 ret = userfunc(sess, rx, &userinfo);
254
255 if (snac->subtype == 0x000b)
256 aim_locate_requestuserinfo(sess, userinfo.sn);
257 aim_info_free(&userinfo);
258
259 return ret;
260 }
261
262 static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
263 {
264
265 if (snac->subtype == 0x0003)
266 return rights(sess, mod, rx, snac, bs);
267 else if ((snac->subtype == 0x000b) || (snac->subtype == 0x000c))
268 return buddychange(sess, mod, rx, snac, bs);
269
270 return 0;
271 }
272
273 faim_internal int buddylist_modfirst(aim_session_t *sess, aim_module_t *mod)
274 {
275
276 mod->family = 0x0003;
277 mod->version = 0x0001;
278 mod->toolid = 0x0110;
279 mod->toolversion = 0x0629;
280 mod->flags = 0;
281 strncpy(mod->name, "buddylist", sizeof(mod->name));
282 mod->snachandler = snachandler;
283
284 return 0;
285 }

mercurial