comparison src/protocols/oscar/ssi.c @ 3017:f0e8770d786d

[gaim-migrate @ 3030] Better SSI stuff? Thanks, KingAnt. committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Thu, 07 Mar 2002 02:19:38 +0000
parents 6d95285533df
children 25c2f11e92fa
comparison
equal deleted inserted replaced
3016:8863555aacc6 3017:f0e8770d786d
8 * This is entirely too complicated. 8 * This is entirely too complicated.
9 * You don't know the half of it. 9 * You don't know the half of it.
10 * 10 *
11 * XXX - Make sure moving buddies from group to group moves the buddy in the server list also 11 * XXX - Make sure moving buddies from group to group moves the buddy in the server list also
12 * XXX - Test for memory leaks 12 * XXX - Test for memory leaks
13 * XXX - Write a c plugin to manage ssi data
14 * XXX - Better parsing of rights, and use the rights info to limit adds 13 * XXX - Better parsing of rights, and use the rights info to limit adds
15 * 14 *
16 */ 15 */
17 16
18 #define FAIM_INTERNAL 17 #define FAIM_INTERNAL
22 * Checks if the given screen name is anywhere in our buddy list. 21 * Checks if the given screen name is anywhere in our buddy list.
23 */ 22 */
24 faim_export int aim_ssi_inlist(aim_session_t *sess, aim_conn_t *conn, char *name, fu16_t type) 23 faim_export int aim_ssi_inlist(aim_session_t *sess, aim_conn_t *conn, char *name, fu16_t type)
25 { 24 {
26 struct aim_ssi_item *cur; 25 struct aim_ssi_item *cur;
26 if (!sess && !conn && !name)
27 return -EINVAL;
27 for (cur=sess->ssi.items; cur; cur=cur->next) 28 for (cur=sess->ssi.items; cur; cur=cur->next)
28 if ((cur->type==type) && (cur->name) && (!aim_sncmp(cur->name, name))) 29 if ((cur->type==type) && (cur->name) && (!aim_sncmp(cur->name, name)))
29 return 1; 30 return 1;
30 return 0; 31 return 0;
31 } 32 }
32 33
33 /* 34 /*
35 * Return the parent group of a given buddy.
36 */
37 faim_export char *aim_ssi_getparentgroup(aim_session_t *sess, aim_conn_t *conn, char *name)
38 {
39 fu16_t gid;
40 struct aim_ssi_item *cur;
41 if (!sess && !conn && !name)
42 return NULL;
43 for (cur=sess->ssi.items; cur && (cur->type!=AIM_SSI_TYPE_BUDDY || !cur->name || aim_sncmp(cur->name, name)); cur=cur->next)
44 if (!cur)
45 return NULL;
46 gid = cur->gid;
47 for (cur=sess->ssi.items; cur; cur=cur->next)
48 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == gid) && (cur->name))
49 return cur->name;
50 return 0;
51 }
52
53 /*
34 * Returns the permit/deny byte 54 * Returns the permit/deny byte
35 * Should should be removed and the byte should be passed directly to 55 * This should be removed and the byte should be passed directly to
36 * the handler 56 * the handler for x0006, along with all the buddies and other info.
37 */ 57 */
38 faim_export int aim_ssi_getpermdeny(aim_tlvlist_t *tlvlist) 58 faim_export int aim_ssi_getpermdeny(aim_tlvlist_t *tlvlist)
39 { 59 {
40 aim_tlv_t *tlv; 60 aim_tlv_t *tlv;
41 if ((tlv = aim_gettlv(tlvlist, 0x00ca, 1)) && tlv->value) 61 if ((tlv = aim_gettlv(tlvlist, 0x00ca, 1)) && tlv->value)
51 struct aim_ssi_item *cur; 71 struct aim_ssi_item *cur;
52 if (name) { 72 if (name) {
53 for (cur=items; cur; cur=cur->next) 73 for (cur=items; cur; cur=cur->next)
54 if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, name))) 74 if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, name)))
55 return cur; 75 return cur;
56 } else { /* they probably want the master group */ 76 } else { /* return the master group */
57 for (cur=items; cur; cur=cur->next) 77 for (cur=items; cur; cur=cur->next)
58 if ((cur->type == type) && (cur->gid == 0x0000)) 78 if ((cur->type == type) && (cur->gid == 0x0000))
59 return cur; 79 return cur;
60 } 80 }
61 return NULL; 81 return NULL;
127 147
128 /* Find the length for the new additional data */ 148 /* Find the length for the new additional data */
129 newlen = 0; 149 newlen = 0;
130 if (parentgroup->gid == 0x0000) { 150 if (parentgroup->gid == 0x0000) {
131 for (cur=sess->ssi.items; cur; cur=cur->next) 151 for (cur=sess->ssi.items; cur; cur=cur->next)
132 if ((cur->gid != 0x0000) && (cur->type == 0x0001)) 152 if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP))
133 newlen += 2; 153 newlen += 2;
134 } else { 154 } else {
135 for (cur=sess->ssi.items; cur; cur=cur->next) 155 for (cur=sess->ssi.items; cur; cur=cur->next)
136 if ((cur->gid == parentgroup->gid) && (cur->type == 0x0000)) 156 if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
137 newlen += 2; 157 newlen += 2;
138 } 158 }
139 159
140 /* Rebuild the additional data */ 160 /* Rebuild the additional data */
141 if (newlen>0) { 161 if (newlen>0) {
146 return -ENOMEM; 166 return -ENOMEM;
147 aimbs_put16(&tbs, 0x00c8); 167 aimbs_put16(&tbs, 0x00c8);
148 aimbs_put16(&tbs, tbs.len-4); 168 aimbs_put16(&tbs, tbs.len-4);
149 if (parentgroup->gid == 0x0000) { 169 if (parentgroup->gid == 0x0000) {
150 for (cur=sess->ssi.items; cur; cur=cur->next) 170 for (cur=sess->ssi.items; cur; cur=cur->next)
151 if ((cur->gid != 0x0000) && (cur->type == 0x0001)) 171 if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP))
152 aimbs_put16(&tbs, cur->gid); 172 aimbs_put16(&tbs, cur->gid);
153 } else { 173 } else {
154 for (cur=sess->ssi.items; cur; cur=cur->next) 174 for (cur=sess->ssi.items; cur; cur=cur->next)
155 if ((cur->gid == parentgroup->gid) && (cur->type == 0x0000)) 175 if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
156 aimbs_put16(&tbs, cur->bid); 176 aimbs_put16(&tbs, cur->bid);
157 } 177 }
158 tbs.offset = 0; 178 tbs.offset = 0;
159 parentgroup->data = (void *)aim_readtlvchain(&tbs); 179 parentgroup->data = (void *)aim_readtlvchain(&tbs);
160 free(tbs.data); 180 free(tbs.data);
164 if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t)))) 184 if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t))))
165 return -ENOMEM; 185 return -ENOMEM;
166 newlen = 0; 186 newlen = 0;
167 if (parentgroup->gid == 0x0000) { 187 if (parentgroup->gid == 0x0000) {
168 for (cur=sess->ssi.items; cur; cur=cur->next) 188 for (cur=sess->ssi.items; cur; cur=cur->next)
169 if ((cur->gid != 0x0000) && (cur->type == 0x0001)) { 189 if ((cur->gid != 0x0000) && (cur->type == AIM_SSI_TYPE_GROUP)) {
170 memcpy(&newdata[newlen*2], &cur->gid, 2); 190 memcpy(&newdata[newlen*2], &cur->gid, 2);
171 newlen += 2; 191 newlen += 2;
172 } 192 }
173 } else { 193 } else {
174 for (cur=sess->ssi.items; cur; cur=cur->next) 194 for (cur=sess->ssi.items; cur; cur=cur->next)
175 if ((cur->gid == parentgroup->gid) && (cur->type == 0x0000)) { 195 if ((cur->gid == parentgroup->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) {
176 memcpy(newdata+newlen*2, &cur->bid, 2); 196 memcpy(&newdata[newlen*2], &cur->bid, 2);
177 newlen += 2; 197 newlen += 2;
178 } 198 }
179 } 199 }
180 aim_addtlvtochain_raw((aim_tlvlist_t **)&parentgroup->data, 0x00c8, newlen, newdata); 200 aim_addtlvtochain_raw((aim_tlvlist_t **)&parentgroup->data, 0x00c8, newlen, newdata);
181 free(newdata); */ 201 free(newdata); */
218 for (cur=sess->ssi.items, num=0; cur; cur=cur->next) 238 for (cur=sess->ssi.items, num=0; cur; cur=cur->next)
219 num++; 239 num++;
220 240
221 if (!(items = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)))) 241 if (!(items = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *))))
222 return -ENOMEM; 242 return -ENOMEM;
223 bzero(items, num*sizeof(struct aim_ssi_item *)); 243 memset(items, 0, num*sizeof(struct aim_ssi_item *));
224 for (cur=sess->ssi.items, num=0; cur; cur=cur->next) { 244 for (cur=sess->ssi.items, num=0; cur; cur=cur->next) {
225 items[num] = cur; 245 items[num] = cur;
226 num++; 246 num++;
227 } 247 }
228 248
229 aim_ssi_delitems(sess, conn, items, num); 249 aim_ssi_addmoddel(sess, conn, items, num, AIM_CB_SSI_DEL);
230 free(items); 250 free(items);
231 aim_ssi_dispatch(sess, conn); 251 aim_ssi_dispatch(sess, conn);
232 aim_ssi_freelist(sess); 252 aim_ssi_freelist(sess);
233 253
234 return 0; 254 return 0;
246 struct aim_ssi_item *cur, *parentgroup; 266 struct aim_ssi_item *cur, *parentgroup;
247 267
248 /* Make sure we actually need to clean out the list */ 268 /* Make sure we actually need to clean out the list */
249 for (cur=sess->ssi.items, num_to_be_fixed=0; cur; cur=cur->next) { 269 for (cur=sess->ssi.items, num_to_be_fixed=0; cur; cur=cur->next) {
250 /* Any buddies directly in the master group */ 270 /* Any buddies directly in the master group */
251 if ((cur->type == 0x0000) && (cur->gid == 0x0000)) 271 if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->gid == 0x0000))
252 num_to_be_fixed++; 272 num_to_be_fixed++;
253 } 273 }
254 if (!num_to_be_fixed) 274 if (!num_to_be_fixed)
255 return 0; 275 return 0;
256 276
257 /* Remove all the additional data from all groups and buddies */ 277 /* Remove all the additional data from all groups and buddies */
258 for (cur=sess->ssi.items; cur; cur=cur->next) 278 for (cur=sess->ssi.items; cur; cur=cur->next)
259 if (cur->data && ((cur->type == 0x0000) || (cur->type == 0x0001))) { 279 if (cur->data && ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_GROUP))) {
260 aim_freetlvchain((aim_tlvlist_t **)&cur->data); 280 aim_freetlvchain((aim_tlvlist_t **)&cur->data);
261 cur->data = NULL; 281 cur->data = NULL;
262 } 282 }
263 283
264 /* If there are buddies directly in the master group, make sure */ 284 /* If there are buddies directly in the master group, make sure */
265 /* there is a group to put them in. Any group, any group at all. */ 285 /* there is a group to put them in. Any group, any group at all. */
266 for (cur=sess->ssi.items; ((cur) && ((cur->type != 0x0000) || (cur->gid != 0x0000))); cur=cur->next); 286 for (cur=sess->ssi.items; ((cur) && ((cur->type != AIM_SSI_TYPE_BUDDY) || (cur->gid != 0x0000))); cur=cur->next);
267 if (!cur) { 287 if (!cur) {
268 for (parentgroup=sess->ssi.items; ((parentgroup) && ((parentgroup->type!=0x0001) || (parentgroup->gid!=0x0000))); parentgroup=parentgroup->next); 288 for (parentgroup=sess->ssi.items; ((parentgroup) && ((parentgroup->type!=AIM_SSI_TYPE_GROUP) || (parentgroup->gid!=0x0000))); parentgroup=parentgroup->next);
269 if (!parentgroup) { 289 if (!parentgroup) {
270 char *newgroup; 290 char *newgroup;
271 newgroup = (char*)malloc(strlen("Unknown")*sizeof(char)); 291 newgroup = (char*)malloc(strlen("Unknown")*sizeof(char));
272 strcpy(newgroup, "Unknown"); 292 strcpy(newgroup, "Unknown");
273 aim_ssi_addgroups(sess, conn, &newgroup, 1); 293 aim_ssi_addgroups(sess, conn, &newgroup, 1);
274 } 294 }
275 } 295 }
276 296
277 /* Set parentgroup equal to any arbitray group */ 297 /* Set parentgroup equal to any arbitray group */
278 for (parentgroup=sess->ssi.items; parentgroup->gid==0x0000 || parentgroup->type!=0x0001; parentgroup=parentgroup->next); 298 for (parentgroup=sess->ssi.items; parentgroup->gid==0x0000 || parentgroup->type!=AIM_SSI_TYPE_GROUP; parentgroup=parentgroup->next);
279 299
280 /* If there are any buddies directly in the master group, put them in a real group */ 300 /* If there are any buddies directly in the master group, put them in a real group */
281 for (cur=sess->ssi.items; cur; cur=cur->next) 301 for (cur=sess->ssi.items; cur; cur=cur->next)
282 if ((cur->type == 0x0000) && (cur->gid == 0x0000)) { 302 if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->gid == 0x0000)) {
283 aim_ssi_delitems(sess, conn, &cur, 1); 303 aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_DEL);
284 cur->gid = parentgroup->gid; 304 cur->gid = parentgroup->gid;
285 aim_ssi_additems(sess, conn, &cur, 1); 305 aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_ADD);
286 } 306 }
287 307
288 /* Rebuild additional data for all groups */ 308 /* Rebuild additional data for all groups */
289 for (parentgroup=sess->ssi.items; parentgroup; parentgroup=parentgroup->next) 309 for (parentgroup=sess->ssi.items; parentgroup; parentgroup=parentgroup->next)
290 if (parentgroup->type == 0x0001) 310 if (parentgroup->type == AIM_SSI_TYPE_GROUP)
291 aim_ssi_rebuildgroup(sess, conn, parentgroup); 311 aim_ssi_rebuildgroup(sess, conn, parentgroup);
292 312
293 /* Send a mod snac for all groups */ 313 /* Send a mod snac for all groups */
294 for (cur=sess->ssi.items; cur; cur=cur->next) 314 for (cur=sess->ssi.items; cur; cur=cur->next)
295 if (cur->type == 0x0001) 315 if (cur->type == AIM_SSI_TYPE_GROUP)
296 aim_ssi_moditems(sess, conn, &cur, 1); 316 aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_MOD);
297
298 /* Begin sending SSI SNACs */
299 aim_ssi_dispatch(sess, conn);
300
301 return 0;
302 }
303
304 /*
305 * This adds the master group (the group containing all groups) if it doesn't exist.
306 * It's called by aim_ssi_addgroups, if your list is empty.
307 */
308 faim_export int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn) {
309 struct aim_ssi_item *newitem;
310
311 if (!sess || !conn)
312 return -EINVAL;
313
314 /* Allocate an array of pointers to each of the new items */
315 if (!(newitem = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item))))
316 return -ENOMEM;
317 bzero(newitem, sizeof(struct aim_ssi_item));
318
319 /* bzero sets most of the vars to what they should be */
320 newitem->type = 0x0001;
321
322 /* Add the item to our list */
323 newitem->next = sess->ssi.items;
324 sess->ssi.items = newitem;
325
326 /* If there are any existing groups (technically there shouldn't be, but */
327 /* just in case) then add their group ID#'s to the additional data */
328 if (sess->ssi.items)
329 aim_ssi_rebuildgroup(sess, conn, newitem);
330
331 /* Send the add item SNAC */
332 aim_ssi_additems(sess, conn, &newitem, 1);
333 317
334 /* Begin sending SSI SNACs */ 318 /* Begin sending SSI SNACs */
335 aim_ssi_dispatch(sess, conn); 319 aim_ssi_dispatch(sess, conn);
336 320
337 return 0; 321 return 0;
353 337
354 if (!sess || !conn || !gn || !sn || !num) 338 if (!sess || !conn || !gn || !sn || !num)
355 return -EINVAL; 339 return -EINVAL;
356 340
357 /* Look up the parent group */ 341 /* Look up the parent group */
358 if (!(parentgroup = get_ssi_item(sess->ssi.items, gn, 0x0001))) { 342 if (!(parentgroup = get_ssi_item(sess->ssi.items, gn, AIM_SSI_TYPE_GROUP))) {
359 aim_ssi_addgroups(sess, conn, &gn, 1); 343 aim_ssi_addgroups(sess, conn, &gn, 1);
360 if (!(parentgroup = get_ssi_item(sess->ssi.items, gn, 0x0001))) 344 if (!(parentgroup = get_ssi_item(sess->ssi.items, gn, AIM_SSI_TYPE_GROUP)))
361 return -ENOMEM; 345 return -ENOMEM;
362 } 346 }
363 347
364 /* Allocate an array of pointers to each of the new items */ 348 /* Allocate an array of pointers to each of the new items */
365 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)))) 349 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *))))
366 return -ENOMEM; 350 return -ENOMEM;
367 bzero(newitems, num*sizeof(struct aim_ssi_item *)); 351 memset(newitems, 0, num*sizeof(struct aim_ssi_item *));
368 352
369 /* The following for loop iterates once per item that needs to be added. */ 353 /* The following for loop iterates once per item that needs to be added. */
370 /* For each i, create an item and tack it onto the newitems array */ 354 /* For each i, create an item and tack it onto the newitems array */
371 for (i=0; i<num; i++) { 355 for (i=0; i<num; i++) {
372 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) { 356 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) {
390 newitems[i]->gid = parentgroup->gid; 374 newitems[i]->gid = parentgroup->gid;
391 newitems[i]->bid = i ? newitems[i-1]->bid : 0; 375 newitems[i]->bid = i ? newitems[i-1]->bid : 0;
392 do { 376 do {
393 newitems[i]->bid += 0x0001; 377 newitems[i]->bid += 0x0001;
394 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next) 378 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next)
395 if ((cur->bid == newitems[i]->bid) && (cur->gid == newitems[i]->gid) && (cur->type == 0x0000)) 379 if ((cur->bid == newitems[i]->bid) && (cur->gid == newitems[i]->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
396 j=1; 380 j=1;
397 } while (j); 381 } while (j);
398 newitems[i]->type = 0x0000; 382 newitems[i]->type = AIM_SSI_TYPE_BUDDY;
399 newitems[i]->data = NULL; 383 newitems[i]->data = NULL;
400 newitems[i]->next = i ? newitems[i-1] : NULL; 384 newitems[i]->next = i ? newitems[i-1] : NULL;
401 } 385 }
402 386
403 /* Add the items to our list */ 387 /* Add the items to our list */
404 newitems[0]->next = sess->ssi.items; 388 newitems[0]->next = sess->ssi.items;
405 sess->ssi.items = newitems[num-1]; 389 sess->ssi.items = newitems[num-1];
406 390
407 /* Send the add item SNAC */ 391 /* Send the add item SNAC */
408 aim_ssi_additems(sess, conn, newitems, num); 392 aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD);
409 393
410 /* Free the array of pointers to each of the new items */ 394 /* Free the array of pointers to each of the new items */
411 free(newitems); 395 free(newitems);
412 396
413 /* Rebuild the additional data in the parent group */ 397 /* Rebuild the additional data in the parent group */
414 aim_ssi_rebuildgroup(sess, conn, parentgroup); 398 aim_ssi_rebuildgroup(sess, conn, parentgroup);
415 399
416 /* Send the mod item SNAC */ 400 /* Send the mod item SNAC */
417 aim_ssi_moditems(sess, conn, &parentgroup, 1); 401 aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD);
418 402
419 /* Begin sending SSI SNACs */ 403 /* Begin sending SSI SNACs */
420 aim_ssi_dispatch(sess, conn); 404 aim_ssi_dispatch(sess, conn);
421 405
422 return 0; 406 return 0;
423 } 407 }
424 408
409 /*
410 * This adds the master group (the group containing all groups) if it doesn't exist.
411 * It's called by aim_ssi_addgroups, if your list is empty.
412 */
413 faim_export int aim_ssi_addmastergroup(aim_session_t *sess, aim_conn_t *conn) {
414 struct aim_ssi_item *newitem;
415
416 if (!sess || !conn)
417 return -EINVAL;
418
419 /* Allocate an array of pointers to each of the new items */
420 if (!(newitem = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item))))
421 return -ENOMEM;
422 memset(newitem, 0, sizeof(struct aim_ssi_item));
423
424 /* memset to 0 sets most of the vars to what they should be */
425 newitem->type = AIM_SSI_TYPE_GROUP;
426
427 /* Add the item to our list */
428 newitem->next = sess->ssi.items;
429 sess->ssi.items = newitem;
430
431 /* If there are any existing groups (technically there shouldn't be, but */
432 /* just in case) then add their group ID#'s to the additional data */
433 if (sess->ssi.items)
434 aim_ssi_rebuildgroup(sess, conn, newitem);
435
436 /* Send the add item SNAC */
437 aim_ssi_addmoddel(sess, conn, &newitem, 1, AIM_CB_SSI_ADD);
438
439 /* Begin sending SSI SNACs */
440 aim_ssi_dispatch(sess, conn);
441
442 return 0;
443 }
444
425 faim_export int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num) 445 faim_export int aim_ssi_addgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num)
426 { 446 {
427 struct aim_ssi_item *cur, *parentgroup, **newitems; 447 struct aim_ssi_item *cur, *parentgroup, **newitems;
428 fu16_t i, j; 448 fu16_t i, j;
429 449
430 if (!sess || !conn || !gn || !num) 450 if (!sess || !conn || !gn || !num)
431 return -EINVAL; 451 return -EINVAL;
432 452
433 /* Look up the parent group */ 453 /* Look up the parent group */
434 if (!(parentgroup = get_ssi_item(sess->ssi.items, NULL, 0x0001))) { 454 if (!(parentgroup = get_ssi_item(sess->ssi.items, NULL, AIM_SSI_TYPE_GROUP))) {
435 aim_ssi_addmastergroup(sess, conn); 455 aim_ssi_addmastergroup(sess, conn);
436 if (!(parentgroup = get_ssi_item(sess->ssi.items, NULL, 0x0001))) 456 if (!(parentgroup = get_ssi_item(sess->ssi.items, NULL, AIM_SSI_TYPE_GROUP)))
437 return -ENOMEM; 457 return -ENOMEM;
438 } 458 }
439 459
440 /* Allocate an array of pointers to each of the new items */ 460 /* Allocate an array of pointers to each of the new items */
441 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)))) 461 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *))))
442 return -ENOMEM; 462 return -ENOMEM;
443 bzero(newitems, num*sizeof(struct aim_ssi_item *)); 463 memset(newitems, 0, num*sizeof(struct aim_ssi_item *));
444 464
445 /* The following for loop iterates once per item that needs to be added. */ 465 /* The following for loop iterates once per item that needs to be added. */
446 /* For each i, create an item and tack it onto the newitems array */ 466 /* For each i, create an item and tack it onto the newitems array */
447 for (i=0; i<num; i++) { 467 for (i=0; i<num; i++) {
448 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) { 468 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) {
465 strcpy(newitems[i]->name, gn[i]); 485 strcpy(newitems[i]->name, gn[i]);
466 newitems[i]->gid = i ? newitems[i-1]->gid : 0; 486 newitems[i]->gid = i ? newitems[i-1]->gid : 0;
467 do { 487 do {
468 newitems[i]->gid += 0x0001; 488 newitems[i]->gid += 0x0001;
469 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next) 489 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next)
470 if ((cur->gid == newitems[i]->gid) && (cur->type == 0x0001)) 490 if ((cur->gid == newitems[i]->gid) && (cur->type == AIM_SSI_TYPE_GROUP))
471 j=1; 491 j=1;
472 } while (j); 492 } while (j);
473 newitems[i]->bid = 0x0000; 493 newitems[i]->bid = 0x0000;
474 newitems[i]->type = 0x0001; 494 newitems[i]->type = AIM_SSI_TYPE_GROUP;
475 newitems[i]->data = NULL; 495 newitems[i]->data = NULL;
476 newitems[i]->next = i ? newitems[i-1] : NULL; 496 newitems[i]->next = i ? newitems[i-1] : NULL;
477 } 497 }
478 498
479 /* Add the items to our list */ 499 /* Add the items to our list */
480 newitems[0]->next = sess->ssi.items; 500 newitems[0]->next = sess->ssi.items;
481 sess->ssi.items = newitems[num-1]; 501 sess->ssi.items = newitems[num-1];
482 502
483 /* Send the add item SNAC */ 503 /* Send the add item SNAC */
484 aim_ssi_additems(sess, conn, newitems, num); 504 aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD);
485 505
486 /* Free the array of pointers to each of the new items */ 506 /* Free the array of pointers to each of the new items */
487 free(newitems); 507 free(newitems);
488 508
489 /* Rebuild the additional data in the parent group */ 509 /* Rebuild the additional data in the parent group */
490 aim_ssi_rebuildgroup(sess, conn, parentgroup); 510 aim_ssi_rebuildgroup(sess, conn, parentgroup);
491 511
492 /* Send the mod item SNAC */ 512 /* Send the mod item SNAC */
493 aim_ssi_moditems(sess, conn, &parentgroup, 1); 513 aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD);
494 514
495 /* Begin sending SSI SNACs */ 515 /* Begin sending SSI SNACs */
496 aim_ssi_dispatch(sess, conn); 516 aim_ssi_dispatch(sess, conn);
497 517
498 return 0; 518 return 0;
499 } 519 }
500 520
501 faim_export int aim_ssi_addpermits(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num) 521 /*
522 * Add permit or deny buddies to the permit or deny list.
523 * The buddies are passed as an array of pointers to char strings.
524 */
525 faim_export int aim_ssi_addpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, fu16_t type)
502 { 526 {
503 struct aim_ssi_item *cur, **newitems; 527 struct aim_ssi_item *cur, **newitems;
504 fu16_t i, j; 528 fu16_t i, j;
505 529
506 if (!sess || !conn || !sn || !num) 530 if (!sess || !conn || !sn || !num || (type!=AIM_SSI_TYPE_PERMIT && type!=AIM_SSI_TYPE_DENY))
507 return -EINVAL; 531 return -EINVAL;
508 532
509 /* Allocate an array of pointers to each of the new items */ 533 /* Allocate an array of pointers to each of the new items */
510 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)))) 534 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *))))
511 return -ENOMEM; 535 return -ENOMEM;
512 bzero(newitems, num*sizeof(struct aim_ssi_item *)); 536 memset(newitems, 0, num*sizeof(struct aim_ssi_item *));
513 537
514 /* The following for loop iterates once per item that needs to be added. */ 538 /* The following for loop iterates once per item that needs to be added. */
515 /* For each i, create an item and tack it onto the newitems array */ 539 /* For each i, create an item and tack it onto the newitems array */
516 for (i=0; i<num; i++) { 540 for (i=0; i<num; i++) {
517 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) { 541 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) {
535 newitems[i]->gid = 0x0000; 559 newitems[i]->gid = 0x0000;
536 newitems[i]->bid = i ? newitems[i-1]->bid : 0x0000; 560 newitems[i]->bid = i ? newitems[i-1]->bid : 0x0000;
537 do { 561 do {
538 newitems[i]->bid += 0x0001; 562 newitems[i]->bid += 0x0001;
539 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next) 563 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next)
540 if ((cur->bid == newitems[i]->bid) && ((cur->type == 0x0002) || (cur->type == 0x0003))) 564 if ((cur->bid == newitems[i]->bid) && ((cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY)))
541 j=1; 565 j=1;
542 } while (j); 566 } while (j);
543 newitems[i]->type = 0x0002; 567 newitems[i]->type = type;
544 newitems[i]->data = NULL; 568 newitems[i]->data = NULL;
545 newitems[i]->next = i ? newitems[i-1] : NULL; 569 newitems[i]->next = i ? newitems[i-1] : NULL;
546 } 570 }
547 571
548 /* Add the items to our list */ 572 /* Add the items to our list */
549 newitems[0]->next = sess->ssi.items; 573 newitems[0]->next = sess->ssi.items;
550 sess->ssi.items = newitems[num-1]; 574 sess->ssi.items = newitems[num-1];
551 575
552 /* Send the add item SNAC */ 576 /* Send the add item SNAC */
553 aim_ssi_additems(sess, conn, newitems, num); 577 aim_ssi_addmoddel(sess, conn, newitems, num, AIM_CB_SSI_ADD);
554 578
555 /* Free the array of pointers to each of the new items */ 579 /* Free the array of pointers to each of the new items */
556 free(newitems); 580 free(newitems);
557 581
558 /* Begin sending SSI SNACs */ 582 /* Begin sending SSI SNACs */
559 aim_ssi_dispatch(sess, conn); 583 aim_ssi_dispatch(sess, conn);
560 584
561 return 0; 585 return 0;
562 } 586 }
563 587
564 faim_export int aim_ssi_adddenies(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num)
565 {
566 struct aim_ssi_item *cur, **newitems;
567 fu16_t i, j;
568
569 if (!sess || !conn || !sn || !num)
570 return -EINVAL;
571
572 /* Allocate an array of pointers to each of the new items */
573 if (!(newitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *))))
574 return -ENOMEM;
575 bzero(newitems, num*sizeof(struct aim_ssi_item *));
576
577 /* The following for loop iterates once per item that needs to be added. */
578 /* For each i, create an item and tack it onto the newitems array */
579 for (i=0; i<num; i++) {
580 if (!(newitems[i] = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) {
581 for (j=0; j<(i-1); j++) {
582 free(newitems[j]->name);
583 free(newitems[j]);
584 }
585 free(newitems);
586 return -ENOMEM;
587 }
588 if (!(newitems[i]->name = (char *)malloc((strlen(sn[i])+1)*sizeof(char)))) {
589 for (j=0; j<(i-1); j++) {
590 free(newitems[j]->name);
591 free(newitems[j]);
592 }
593 free(newitems[i]);
594 free(newitems);
595 return -ENOMEM;
596 }
597 strcpy(newitems[i]->name, sn[i]);
598 newitems[i]->gid = 0x0000;
599 newitems[i]->bid = i ? newitems[i-1]->bid : 0x0000;
600 do {
601 newitems[i]->bid += 0x0001;
602 for (cur=sess->ssi.items, j=0; ((cur) && (!j)); cur=cur->next)
603 if ((cur->bid == newitems[i]->bid) && ((cur->type == 0x0002) || (cur->type == 0x0003)))
604 j=1;
605 } while (j);
606 newitems[i]->type = 0x0003;
607 newitems[i]->data = NULL;
608 newitems[i]->next = i ? newitems[i-1] : NULL;
609 }
610
611 /* Add the items to our list */
612 newitems[0]->next = sess->ssi.items;
613 sess->ssi.items = newitems[num-1];
614
615 /* Send the add item SNAC */
616 aim_ssi_additems(sess, conn, newitems, num);
617
618 /* Free the array of pointers to each of the new items */
619 free(newitems);
620
621 /* Begin sending SSI SNACs */
622 aim_ssi_dispatch(sess, conn);
623
624 return 0;
625 }
626
627 faim_export int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num) 588 faim_export int aim_ssi_delbuddies(aim_session_t *sess, aim_conn_t *conn, char *gn, char **sn, unsigned int num)
628 { 589 {
629 struct aim_ssi_item *cur, *parentgroup, **delitems; 590 struct aim_ssi_item *cur, *parentgroup, **delitems;
630 int i; 591 int i;
631 592
632 if (!sess || !conn || !gn || !sn || !num) 593 if (!sess || !conn || !gn || !sn || !num)
633 return -EINVAL; 594 return -EINVAL;
634 595
635 /* Look up the parent group */ 596 /* Look up the parent group */
636 if (!(parentgroup = get_ssi_item(sess->ssi.items, gn, 0x0001))) 597 if (!(parentgroup = get_ssi_item(sess->ssi.items, gn, AIM_SSI_TYPE_GROUP)))
637 return -EINVAL; 598 return -EINVAL;
638 599
639 /* Allocate an array of pointers to each of the items to be deleted */ 600 /* Allocate an array of pointers to each of the items to be deleted */
640 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)); 601 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *));
641 bzero(delitems, num*sizeof(struct aim_ssi_item *)); 602 memset(delitems, 0, num*sizeof(struct aim_ssi_item *));
642 603
643 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */ 604 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
644 for (i=0; i<num; i++) { 605 for (i=0; i<num; i++) {
645 if (!(delitems[i] = get_ssi_item(sess->ssi.items, sn[i], 0x0000))) { 606 if (!(delitems[i] = get_ssi_item(sess->ssi.items, sn[i], AIM_SSI_TYPE_BUDDY))) {
646 free(delitems); 607 free(delitems);
647 return -EINVAL; 608 return -EINVAL;
648 } 609 }
649 610
650 /* Remove the delitems from the item list */ 611 /* Remove the delitems from the item list */
656 cur->next = cur->next->next; 617 cur->next = cur->next->next;
657 } 618 }
658 } 619 }
659 620
660 /* Send the del item SNAC */ 621 /* Send the del item SNAC */
661 aim_ssi_delitems(sess, conn, delitems, num); 622 aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL);
662 623
663 /* Free the items */ 624 /* Free the items */
664 for (i=0; i<num; i++) { 625 for (i=0; i<num; i++) {
665 if (delitems[i]->name) 626 if (delitems[i]->name)
666 free(delitems[i]->name); 627 free(delitems[i]->name);
672 633
673 /* Rebuild the additional data in the parent group */ 634 /* Rebuild the additional data in the parent group */
674 aim_ssi_rebuildgroup(sess, conn, parentgroup); 635 aim_ssi_rebuildgroup(sess, conn, parentgroup);
675 636
676 /* Send the mod item SNAC */ 637 /* Send the mod item SNAC */
677 aim_ssi_moditems(sess, conn, &parentgroup, 1); 638 aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD);
678 639
679 /* Delete the group, but only if it's empty */ 640 /* Delete the group, but only if it's empty */
680 if (!parentgroup->data) 641 if (!parentgroup->data)
681 aim_ssi_delgroups(sess, conn, &parentgroup->name, 1); 642 aim_ssi_delgroups(sess, conn, &parentgroup->name, 1);
682 643
684 aim_ssi_dispatch(sess, conn); 645 aim_ssi_dispatch(sess, conn);
685 646
686 return 0; 647 return 0;
687 } 648 }
688 649
650 faim_export int aim_ssi_delmastergroup(aim_session_t *sess, aim_conn_t *conn) {
651 struct aim_ssi_item *cur, *delitem;
652
653 if (!sess || !conn)
654 return -EINVAL;
655
656 /* Make delitem a pointer to the aim_ssi_item to be deleted */
657 if (!(delitem = get_ssi_item(sess->ssi.items, NULL, AIM_SSI_TYPE_GROUP)))
658 return -EINVAL;
659
660 /* Remove delitem from the item list */
661 if (sess->ssi.items == delitem) {
662 sess->ssi.items = sess->ssi.items->next;
663 } else {
664 for (cur=sess->ssi.items; (cur->next && (cur->next!=delitem)); cur=cur->next);
665 if (cur->next)
666 cur->next = cur->next->next;
667 }
668
669 /* Send the del item SNAC */
670 aim_ssi_addmoddel(sess, conn, &delitem, 1, AIM_CB_SSI_DEL);
671
672 /* Free the item */
673 if (delitem->name)
674 free(delitem->name);
675 if (delitem->data)
676 aim_freetlvchain((aim_tlvlist_t **)&delitem->data);
677 free(delitem);
678
679 /* Begin sending SSI SNACs */
680 aim_ssi_dispatch(sess, conn);
681
682 return 0;
683 }
684
689 faim_export int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num) { 685 faim_export int aim_ssi_delgroups(aim_session_t *sess, aim_conn_t *conn, char **gn, unsigned int num) {
690 struct aim_ssi_item *cur, *parentgroup, **delitems; 686 struct aim_ssi_item *cur, *parentgroup, **delitems;
691 int i; 687 int i;
692 688
693 if (!sess || !conn || !gn || !num) 689 if (!sess || !conn || !gn || !num)
694 return -EINVAL; 690 return -EINVAL;
695 691
696 /* Look up the parent group */ 692 /* Look up the parent group */
697 if (!(parentgroup = get_ssi_item(sess->ssi.items, NULL, 0x0001))) 693 if (!(parentgroup = get_ssi_item(sess->ssi.items, NULL, AIM_SSI_TYPE_GROUP)))
698 return -EINVAL; 694 return -EINVAL;
699 695
700 /* Allocate an array of pointers to each of the items to be deleted */ 696 /* Allocate an array of pointers to each of the items to be deleted */
701 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)); 697 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *));
702 bzero(delitems, num*sizeof(struct aim_ssi_item *)); 698 memset(delitems, 0, num*sizeof(struct aim_ssi_item *));
703 699
704 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */ 700 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
705 for (i=0; i<num; i++) { 701 for (i=0; i<num; i++) {
706 if (!(delitems[i] = get_ssi_item(sess->ssi.items, gn[i], 0x0001))) { 702 if (!(delitems[i] = get_ssi_item(sess->ssi.items, gn[i], AIM_SSI_TYPE_GROUP))) {
707 free(delitems); 703 free(delitems);
708 return -EINVAL; 704 return -EINVAL;
709 } 705 }
710 706
711 /* Remove the delitems from the item list */ 707 /* Remove the delitems from the item list */
717 cur->next = cur->next->next; 713 cur->next = cur->next->next;
718 } 714 }
719 } 715 }
720 716
721 /* Send the del item SNAC */ 717 /* Send the del item SNAC */
722 aim_ssi_delitems(sess, conn, delitems, num); 718 aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL);
723 719
724 /* Free the items */ 720 /* Free the items */
725 for (i=0; i<num; i++) { 721 for (i=0; i<num; i++) {
726 if (delitems[i]->name) 722 if (delitems[i]->name)
727 free(delitems[i]->name); 723 free(delitems[i]->name);
733 729
734 /* Rebuild the additional data in the parent group */ 730 /* Rebuild the additional data in the parent group */
735 aim_ssi_rebuildgroup(sess, conn, parentgroup); 731 aim_ssi_rebuildgroup(sess, conn, parentgroup);
736 732
737 /* Send the mod item SNAC */ 733 /* Send the mod item SNAC */
738 aim_ssi_moditems(sess, conn, &parentgroup, 1); 734 aim_ssi_addmoddel(sess, conn, &parentgroup, 1, AIM_CB_SSI_MOD);
739 735
740 /* Delete the group, but only if it's empty */ 736 /* Delete the group, but only if it's empty */
741 if (!parentgroup->data) 737 if (!parentgroup->data)
742 aim_ssi_delgroups(sess, conn, &parentgroup->name, 1); 738 aim_ssi_delmastergroup(sess, conn);
743 739
744 /* Begin sending SSI SNACs */ 740 /* Begin sending SSI SNACs */
745 aim_ssi_dispatch(sess, conn); 741 aim_ssi_dispatch(sess, conn);
746 742
747 return 0; 743 return 0;
748 } 744 }
749 745
750 faim_export int aim_ssi_delpermits(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num) { 746 faim_export int aim_ssi_delpord(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num, fu16_t type) {
751 struct aim_ssi_item *cur, **delitems; 747 struct aim_ssi_item *cur, **delitems;
752 int i; 748 int i;
753 749
754 if (!sess || !conn || !sn || !num) 750 if (!sess || !conn || !sn || !num || (type!=AIM_SSI_TYPE_PERMIT && type!=AIM_SSI_TYPE_DENY))
755 return -EINVAL; 751 return -EINVAL;
756 752
757 /* Allocate an array of pointers to each of the items to be deleted */ 753 /* Allocate an array of pointers to each of the items to be deleted */
758 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *)); 754 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *));
759 bzero(delitems, num*sizeof(struct aim_ssi_item *)); 755 memset(delitems, 0, num*sizeof(struct aim_ssi_item *));
760 756
761 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */ 757 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
762 for (i=0; i<num; i++) { 758 for (i=0; i<num; i++) {
763 if (!(delitems[i] = get_ssi_item(sess->ssi.items, sn[i], 0x0002))) { 759 if (!(delitems[i] = get_ssi_item(sess->ssi.items, sn[i], type))) {
764 free(delitems); 760 free(delitems);
765 return -EINVAL; 761 return -EINVAL;
766 } 762 }
767 763
768 /* Remove the delitems from the item list */ 764 /* Remove the delitems from the item list */
774 cur->next = cur->next->next; 770 cur->next = cur->next->next;
775 } 771 }
776 } 772 }
777 773
778 /* Send the del item SNAC */ 774 /* Send the del item SNAC */
779 aim_ssi_delitems(sess, conn, delitems, num); 775 aim_ssi_addmoddel(sess, conn, delitems, num, AIM_CB_SSI_DEL);
780
781 /* Free the items */
782 for (i=0; i<num; i++) {
783 if (delitems[i]->name)
784 free(delitems[i]->name);
785 if (delitems[i]->data)
786 aim_freetlvchain((aim_tlvlist_t **)&delitems[i]->data);
787 free(delitems[i]);
788 }
789 free(delitems);
790
791 /* Begin sending SSI SNACs */
792 aim_ssi_dispatch(sess, conn);
793
794 return 0;
795 }
796
797 faim_export int aim_ssi_deldenies(aim_session_t *sess, aim_conn_t *conn, char **sn, unsigned int num) {
798 struct aim_ssi_item *cur, **delitems;
799 int i;
800
801 if (!sess || !conn || !sn || !num)
802 return -EINVAL;
803
804 /* Allocate an array of pointers to each of the items to be deleted */
805 delitems = (struct aim_ssi_item **)malloc(num*sizeof(struct aim_ssi_item *));
806 bzero(delitems, num*sizeof(struct aim_ssi_item *));
807
808 /* Make the delitems array a pointer to the aim_ssi_item structs to be deleted */
809 for (i=0; i<num; i++) {
810 if (!(delitems[i] = get_ssi_item(sess->ssi.items, sn[i], 0x0003))) {
811 free(delitems);
812 return -EINVAL;
813 }
814
815 /* Remove the delitems from the item list */
816 if (sess->ssi.items == delitems[i]) {
817 sess->ssi.items = sess->ssi.items->next;
818 } else {
819 for (cur=sess->ssi.items; (cur->next && (cur->next!=delitems[i])); cur=cur->next);
820 if (cur->next)
821 cur->next = cur->next->next;
822 }
823 }
824
825 /* Send the del item SNAC */
826 aim_ssi_delitems(sess, conn, delitems, num);
827 776
828 /* Free the items */ 777 /* Free the items */
829 for (i=0; i<num; i++) { 778 for (i=0; i<num; i++) {
830 if (delitems[i]->name) 779 if (delitems[i]->name)
831 free(delitems[i]->name); 780 free(delitems[i]->name);
858 807
859 if (!sess || !conn) 808 if (!sess || !conn)
860 return -EINVAL; 809 return -EINVAL;
861 810
862 /* Look up the permit/deny settings item */ 811 /* Look up the permit/deny settings item */
863 for (cur=sess->ssi.items; (cur && (cur->type!=0x0004)); cur=cur->next); 812 for (cur=sess->ssi.items; (cur && (cur->type!=AIM_SSI_TYPE_PDINFO)); cur=cur->next);
864 813
865 if (cur) { 814 if (cur) {
866 /* The permit/deny item exists */ 815 /* The permit/deny item exists */
867 if (cur->data && (tlv = aim_gettlv(cur->data, 0x00ca, 1))) { 816 if (cur->data && (tlv = aim_gettlv(cur->data, 0x00ca, 1))) {
868 /* Just change the value of the x00ca TLV */ 817 /* Just change the value of the x00ca TLV */
876 /* Need to add the x00ca TLV to the TLV chain */ 825 /* Need to add the x00ca TLV to the TLV chain */
877 aim_addtlvtochain8((aim_tlvlist_t**)&cur->data, 0x00ca, permdeny); 826 aim_addtlvtochain8((aim_tlvlist_t**)&cur->data, 0x00ca, permdeny);
878 } 827 }
879 828
880 /* Send the mod item SNAC */ 829 /* Send the mod item SNAC */
881 aim_ssi_moditems(sess, conn, &cur, 1); 830 aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_MOD);
882 } else { 831 } else {
883 /* Need to add the permit/deny item */ 832 /* Need to add the permit/deny item */
884 if (!(cur = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) 833 if (!(cur = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item))))
885 return -ENOMEM; 834 return -ENOMEM;
886 cur->name = NULL; 835 cur->name = NULL;
890 cur->bid += 0x0001; 839 cur->bid += 0x0001;
891 for (tmp=sess->ssi.items, j=0; ((tmp) && (!j)); tmp=tmp->next) 840 for (tmp=sess->ssi.items, j=0; ((tmp) && (!j)); tmp=tmp->next)
892 if (tmp->bid == cur->bid) 841 if (tmp->bid == cur->bid)
893 j=1; 842 j=1;
894 } while (j); 843 } while (j);
895 cur->type = 0x0004; 844 cur->type = AIM_SSI_TYPE_PDINFO;
896 cur->data = NULL; 845 cur->data = NULL;
897 aim_addtlvtochain8((aim_tlvlist_t**)&cur->data, 0x00ca, permdeny); 846 aim_addtlvtochain8((aim_tlvlist_t**)&cur->data, 0x00ca, permdeny);
898 aim_addtlvtochain32((aim_tlvlist_t**)&cur->data, 0x00cb, 0xffffffff); 847 aim_addtlvtochain32((aim_tlvlist_t**)&cur->data, 0x00cb, 0xffffffff);
899 848
900 /* Add the item to our list */ 849 /* Add the item to our list */
901 cur->next = sess->ssi.items; 850 cur->next = sess->ssi.items;
902 sess->ssi.items = cur; 851 sess->ssi.items = cur;
903 852
904 /* Send the add item SNAC */ 853 /* Send the add item SNAC */
905 aim_ssi_additems(sess, conn, &cur, 1); 854 aim_ssi_addmoddel(sess, conn, &cur, 1, AIM_CB_SSI_ADD);
906 } 855 }
907 856
908 /* Begin sending SSI SNACs */ 857 /* Begin sending SSI SNACs */
909 aim_ssi_dispatch(sess, conn); 858 aim_ssi_dispatch(sess, conn);
910 859
914 /* 863 /*
915 * Request SSI Rights. 864 * Request SSI Rights.
916 */ 865 */
917 faim_export int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn) 866 faim_export int aim_ssi_reqrights(aim_session_t *sess, aim_conn_t *conn)
918 { 867 {
919 return aim_genericreq_n(sess, conn, 0x0013, 0x0002); 868 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);
920 } 869 }
921 870
922 /* 871 /*
923 * SSI Rights Information. 872 * SSI Rights Information.
924 */ 873 */
951 return -EINVAL; 900 return -EINVAL;
952 901
953 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2))) 902 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))
954 return -ENOMEM; 903 return -ENOMEM;
955 904
956 snacid = aim_cachesnac(sess, 0x0013, 0x0005, 0x0000, NULL, 0); 905 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQLIST, 0x0000, NULL, 0);
957 906
958 aim_putsnac(&fr->data, 0x0013, 0x0005, 0x0000, snacid); 907 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQLIST, 0x0000, snacid);
959 aimbs_put32(&fr->data, localstamp); 908 aimbs_put32(&fr->data, localstamp);
960 aimbs_put16(&fr->data, localrev); 909 aimbs_put16(&fr->data, localrev);
961 910
962 aim_tx_enqueue(sess, fr); 911 aim_tx_enqueue(sess, fr);
963 912
1032 * settings into effect. 981 * settings into effect.
1033 * 982 *
1034 */ 983 */
1035 faim_export int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn) 984 faim_export int aim_ssi_enable(aim_session_t *sess, aim_conn_t *conn)
1036 { 985 {
1037 return aim_genericreq_n(sess, conn, 0x0013, 0x0007); 986 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);
1038 } 987 }
1039 988
1040 /* 989 /*
1041 * SSI Add Item. 990 * SSI Add/Mod/Del Item(s).
1042 * 991 *
1043 * Adds an item to the data stored on the AIM server. An item could 992 * Sends the SNAC to add, modify, or delete an item from the server-stored
1044 * be a group, buddy, or permit or deny buddy. 993 * information. These 3 SNACs all have an identical structure. The only
994 * difference is the subtype that is set for the SNAC.
1045 * 995 *
1046 */ 996 */
1047 faim_export int aim_ssi_additems(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num) 997 faim_export int aim_ssi_addmoddel(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num, fu16_t subtype)
1048 { 998 {
1049 aim_frame_t *fr; 999 aim_frame_t *fr;
1050 aim_snacid_t snacid; 1000 aim_snacid_t snacid;
1051 int i, snaclen; 1001 int i, snaclen;
1052 1002
1063 } 1013 }
1064 1014
1065 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) 1015 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen)))
1066 return -ENOMEM; 1016 return -ENOMEM;
1067 1017
1068 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_ADD, 0x0000, NULL, 0); 1018 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, subtype, 0x0000, NULL, 0);
1069 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_ADD, 0x0000, snacid); 1019 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, subtype, 0x0000, snacid);
1070 1020
1071 for (i=0; i<num; i++) { 1021 for (i=0; i<num; i++) {
1072 aimbs_put16(&fr->data, items[i]->name ? strlen(items[i]->name) : 0); 1022 aimbs_put16(&fr->data, items[i]->name ? strlen(items[i]->name) : 0);
1073 if (items[i]->name) 1023 if (items[i]->name)
1074 aimbs_putraw(&fr->data, items[i]->name, strlen(items[i]->name)); 1024 aimbs_putraw(&fr->data, items[i]->name, strlen(items[i]->name));
1084 1034
1085 return 0; 1035 return 0;
1086 } 1036 }
1087 1037
1088 /* 1038 /*
1089 * SSI Mod Item.
1090 *
1091 * Modifies an item in the data stored on the AIM server. An item could
1092 * be a group, buddy, or permit or deny buddy.
1093 *
1094 */
1095 faim_export int aim_ssi_moditems(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num)
1096 {
1097 aim_frame_t *fr;
1098 aim_snacid_t snacid;
1099 int i, snaclen;
1100
1101 if (!sess || !conn || !items || !num)
1102 return -EINVAL;
1103
1104 snaclen = 10; /* For family, subtype, flags, and SNAC ID */
1105 for (i=0; i<num; i++) {
1106 snaclen += 10; /* For length, GID, BID, type, and length */
1107 if (items[i]->name)
1108 snaclen += strlen(items[i]->name);
1109 if (items[i]->data)
1110 snaclen += aim_sizetlvchain((aim_tlvlist_t **)&items[i]->data);
1111 }
1112
1113 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen)))
1114 return -ENOMEM;
1115
1116 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_MOD, 0x0000, NULL, 0);
1117 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_MOD, 0x0000, snacid);
1118
1119 for (i=0; i<num; i++) {
1120 aimbs_put16(&fr->data, items[i]->name ? strlen(items[i]->name) : 0);
1121 if (items[i]->name)
1122 aimbs_putraw(&fr->data, items[i]->name, strlen(items[i]->name));
1123 aimbs_put16(&fr->data, items[i]->gid);
1124 aimbs_put16(&fr->data, items[i]->bid);
1125 aimbs_put16(&fr->data, items[i]->type);
1126 aimbs_put16(&fr->data, items[i]->data ? aim_sizetlvchain((aim_tlvlist_t **)&items[i]->data) : 0);
1127 if (items[i]->data)
1128 aim_writetlvchain(&fr->data, (aim_tlvlist_t **)&items[i]->data);
1129 }
1130
1131 aim_ssi_enqueue(sess, conn, fr);
1132
1133 return 0;
1134 }
1135
1136 /*
1137 * SSI Del Item.
1138 *
1139 * Deletes an item from the data stored on the AIM server. An item
1140 * could be a group, buddy, or permit or deny buddy.
1141 *
1142 */
1143 faim_export int aim_ssi_delitems(aim_session_t *sess, aim_conn_t *conn, struct aim_ssi_item **items, unsigned int num)
1144 {
1145 aim_frame_t *fr;
1146 aim_snacid_t snacid;
1147 int i, snaclen;
1148
1149 if (!sess || !conn || !items || !num)
1150 return -EINVAL;
1151
1152 snaclen = 10; /* For family, subtype, flags, and SNAC ID */
1153 for (i=0; i<num; i++) {
1154 snaclen += 10; /* For length, GID, BID, type, and length */
1155 if (items[i]->name)
1156 snaclen += strlen(items[i]->name);
1157 if (items[i]->data)
1158 snaclen += aim_sizetlvchain((aim_tlvlist_t **)&items[i]->data);
1159 }
1160
1161 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen)))
1162 return -ENOMEM;
1163
1164 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_DEL, 0x0000, NULL, 0);
1165 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_DEL, 0x0000, snacid);
1166
1167 for (i=0; i<num; i++) {
1168 aimbs_put16(&fr->data, items[i]->name ? strlen(items[i]->name) : 0);
1169 if (items[i]->name)
1170 aimbs_putraw(&fr->data, items[i]->name, strlen(items[i]->name));
1171 aimbs_put16(&fr->data, items[i]->gid);
1172 aimbs_put16(&fr->data, items[i]->bid);
1173 aimbs_put16(&fr->data, items[i]->type);
1174 aimbs_put16(&fr->data, items[i]->data ? aim_sizetlvchain((aim_tlvlist_t **)&items[i]->data) : 0);
1175 if (items[i]->data)
1176 aim_writetlvchain(&fr->data, (aim_tlvlist_t **)&items[i]->data);
1177 }
1178
1179 aim_ssi_enqueue(sess, conn, fr);
1180
1181 return 0;
1182 }
1183
1184 /*
1185 * SSI Add/Mod/Del Ack. 1039 * SSI Add/Mod/Del Ack.
1186 * 1040 *
1187 * Response to aim_ssi_additem(), aim_ssi_moditem(), or aim_ssi_delitem(). 1041 * Response to add, modify, or delete SNAC (sent with aim_ssi_addmoddel).
1188 * 1042 *
1189 */ 1043 */
1190 static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1044 static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
1191 { 1045 {
1192 int ret = 0; 1046 int ret = 0;
1207 * Tells the server you're going to start modifying data. 1061 * Tells the server you're going to start modifying data.
1208 * 1062 *
1209 */ 1063 */
1210 faim_export int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn) 1064 faim_export int aim_ssi_modbegin(aim_session_t *sess, aim_conn_t *conn)
1211 { 1065 {
1212 return aim_genericreq_n(sess, conn, 0x0013, 0x0011); 1066 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);
1213 } 1067 }
1214 1068
1215 /* 1069 /*
1216 * SSI End Data Modification. 1070 * SSI End Data Modification.
1217 * 1071 *
1218 * Tells the server you're done modifying data. 1072 * Tells the server you're done modifying data.
1219 * 1073 *
1220 */ 1074 */
1221 faim_export int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn) 1075 faim_export int aim_ssi_modend(aim_session_t *sess, aim_conn_t *conn)
1222 { 1076 {
1223 return aim_genericreq_n(sess, conn, 0x0013, 0x0012); 1077 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP);
1224 } 1078 }
1225 1079
1226 /* 1080 /*
1227 * SSI Data Unchanged. 1081 * SSI Data Unchanged.
1228 * 1082 *
1244 } 1098 }
1245 1099
1246 static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1100 static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
1247 { 1101 {
1248 1102
1249 if (snac->subtype == 0x0003) 1103 if (snac->subtype == AIM_CB_SSI_RIGHTSINFO)
1250 return parserights(sess, mod, rx, snac, bs); 1104 return parserights(sess, mod, rx, snac, bs);
1251 else if (snac->subtype == 0x006) 1105 else if (snac->subtype == AIM_CB_SSI_LIST)
1252 return parsedata(sess, mod, rx, snac, bs); 1106 return parsedata(sess, mod, rx, snac, bs);
1253 else if (snac->subtype == AIM_CB_SSI_SRVACK) 1107 else if (snac->subtype == AIM_CB_SSI_SRVACK)
1254 return parseack(sess, mod, rx, snac, bs); 1108 return parseack(sess, mod, rx, snac, bs);
1255 else if (snac->subtype == 0x00f) 1109 else if (snac->subtype == AIM_CB_SSI_NOLIST)
1256 return parsedataunchanged(sess, mod, rx, snac, bs); 1110 return parsedataunchanged(sess, mod, rx, snac, bs);
1257 1111
1258 return 0; 1112 return 0;
1259 } 1113 }
1260 1114
1266 } 1120 }
1267 1121
1268 faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod) 1122 faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod)
1269 { 1123 {
1270 1124
1271 mod->family = 0x0013; 1125 mod->family = AIM_CB_FAM_SSI;
1272 mod->version = 0x0001; 1126 mod->version = 0x0001;
1273 mod->toolid = 0x0110; 1127 mod->toolid = 0x0110;
1274 mod->toolversion = 0x047b; 1128 mod->toolversion = 0x047b;
1275 mod->flags = 0; 1129 mod->flags = 0;
1276 strncpy(mod->name, "ssi", sizeof(mod->name)); 1130 strncpy(mod->name, "ssi", sizeof(mod->name));