Changeset cf02dd6 for libfaim/ssi.c
- Timestamp:
- Dec 10, 2003, 3:20:45 PM (22 years ago)
- Branches:
- master, barnowl_perlaim, debian, owl, release-1.10, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
- Children:
- b1fe407
- Parents:
- 8c46404
- File:
-
- 1 edited
-
libfaim/ssi.c (modified) (49 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libfaim/ssi.c
ra0a5179 rcf02dd6 22 22 * You don't know the half of it. 23 23 * 24 * XXX - Preserve unknown data in TLV lists25 *26 24 */ 27 25 … … 39 37 static struct aim_ssi_item *aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name) 40 38 { 41 int newlen; 42 struct aim_ssi_item *cur, *group; 43 44 owl_function_debugmsg("aim_ssi_itemlist_rebuildgroup: in for group %s", name?name:"NULL"); 45 46 if (!list) return(NULL); 47 48 /* Find the group */ 49 if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP))) return(NULL); 50 51 /* Free the old data */ 52 aim_freetlvchain(&group->data); 53 group->data = NULL; 54 55 /* Find the length for the new additional data */ 56 newlen = 0; 57 if (group->gid == 0x0000) { 58 for (cur=list; cur; cur=cur->next) 59 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000)) 60 newlen += 2; 61 } else { 62 for (cur=list; cur; cur=cur->next) 63 if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) 64 newlen += 2; 65 } 66 owl_function_debugmsg("aim_ssi_itemlist_rebuildgroup: newlen is %i", newlen); 67 68 /* Build the new TLV list */ 69 if (newlen > 0) { 70 fu8_t *newdata; 71 72 if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t)))) return NULL; 73 newlen = 0; 74 if (group->gid == 0x0000) { 75 for (cur=list; cur; cur=cur->next) 76 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000)) 77 newlen += aimutil_put16(newdata+newlen, cur->gid); 78 } else { 79 for (cur=list; cur; cur=cur->next) 80 if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) 81 newlen += aimutil_put16(newdata+newlen, cur->bid); 82 } 83 aim_addtlvtochain_raw(&group->data, 0x00c8, newlen, newdata); 84 85 free(newdata); 86 } 87 88 owl_function_debugmsg("aim_ssi_itemlist_rebuildgroup: exiting"); 89 return group; 39 int newlen; 40 struct aim_ssi_item *cur, *group; 41 42 if (!list) 43 return NULL; 44 45 /* Find the group */ 46 if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP))) 47 return NULL; 48 49 /* Find the length for the new additional data */ 50 newlen = 0; 51 if (group->gid == 0x0000) { 52 for (cur=list; cur; cur=cur->next) 53 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000)) 54 newlen += 2; 55 } else { 56 for (cur=list; cur; cur=cur->next) 57 if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) 58 newlen += 2; 59 } 60 61 /* Build the new TLV list */ 62 if (newlen > 0) { 63 fu8_t *newdata; 64 65 if (!(newdata = (fu8_t *)malloc((newlen)*sizeof(fu8_t)))) 66 return NULL; 67 newlen = 0; 68 if (group->gid == 0x0000) { 69 for (cur=list; cur; cur=cur->next) 70 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000)) 71 newlen += aimutil_put16(newdata+newlen, cur->gid); 72 } else { 73 for (cur=list; cur; cur=cur->next) 74 if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY)) 75 newlen += aimutil_put16(newdata+newlen, cur->bid); 76 } 77 aim_tlvlist_replace_raw(&group->data, 0x00c8, newlen, newdata); 78 79 free(newdata); 80 } 81 82 return group; 90 83 } 91 84 … … 104 97 static struct aim_ssi_item *aim_ssi_itemlist_add(struct aim_ssi_item **list, const char *name, fu16_t gid, fu16_t bid, fu16_t type, aim_tlvlist_t *data) 105 98 { 106 int i; 107 struct aim_ssi_item *cur, *new; 108 109 if (!list) return(NULL); 110 111 if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) return(NULL); 112 113 /* Set the name */ 114 if (name) { 115 new->name = (char *)malloc((strlen(name)+1)*sizeof(char)); 116 strcpy(new->name, name); 117 } else { 118 new->name = NULL; 119 } 120 121 /* Set the group ID# and buddy ID# */ 122 new->gid = gid; 123 new->bid = bid; 124 if (type == AIM_SSI_TYPE_GROUP) { 125 if ((new->gid == 0xFFFF) && name) { 126 do { 127 new->gid += 0x0001; 128 for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next) 129 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) 130 i=1; 131 } while (i); 132 } 133 } else { 134 if (new->bid == 0xFFFF) { 135 do { 136 new->bid += 0x0001; 137 for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next) 138 if ((cur->bid == new->bid) && (cur->gid == new->gid)) 139 i=1; 140 } while (i); 141 } 142 } 143 144 /* Set the type */ 145 new->type = type; 146 147 /* Set the TLV list */ 148 new->data = aim_tlvlist_copy(data); 149 150 /* Add the item to the list in the correct numerical position. Fancy, eh? */ 151 if (*list) { 152 if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) { 153 new->next = *list; 154 *list = new; 155 } else { 156 struct aim_ssi_item *prev; 157 for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next); 158 new->next = prev->next; 159 prev->next = new; 160 } 161 } else { 162 new->next = *list; 163 *list = new; 164 } 165 166 return(new); 99 int i; 100 struct aim_ssi_item *cur, *new; 101 102 if (!list) 103 return NULL; 104 105 if (!(new = (struct aim_ssi_item *)malloc(sizeof(struct aim_ssi_item)))) 106 return NULL; 107 108 /* Set the name */ 109 if (name) { 110 new->name = (char *)malloc((strlen(name)+1)*sizeof(char)); 111 strcpy(new->name, name); 112 } else 113 new->name = NULL; 114 115 /* Set the group ID# and buddy ID# */ 116 new->gid = gid; 117 new->bid = bid; 118 if (type == AIM_SSI_TYPE_GROUP) { 119 if ((new->gid == 0xFFFF) && name) { 120 do { 121 new->gid += 0x0001; 122 for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next) 123 if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) 124 i=1; 125 } while (i); 126 } 127 } else { 128 if (new->bid == 0xFFFF) { 129 do { 130 new->bid += 0x0001; 131 for (cur=*list, i=0; ((cur) && (!i)); cur=cur->next) 132 if ((cur->bid == new->bid) && (cur->gid == new->gid)) 133 i=1; 134 } while (i); 135 } 136 } 137 138 /* Set the type */ 139 new->type = type; 140 141 /* Set the TLV list */ 142 new->data = aim_tlvlist_copy(data); 143 144 /* Add the item to the list in the correct numerical position. Fancy, eh? */ 145 if (*list) { 146 if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) { 147 new->next = *list; 148 *list = new; 149 } else { 150 struct aim_ssi_item *prev; 151 for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next); 152 new->next = prev->next; 153 prev->next = new; 154 } 155 } else { 156 new->next = *list; 157 *list = new; 158 } 159 160 return new; 167 161 } 168 162 … … 176 170 static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del) 177 171 { 178 if (!list || !(*list) || !del) return -EINVAL; 179 180 owl_function_debugmsg("aim_ssi_itemlist_del: in"); 181 /* Remove the item from the list */ 182 if (*list == del) { 183 *list = (*list)->next; 184 owl_function_debugmsg("aim_ssi_itemlist_del: deleted %s from beginning of list", del->name); 185 } else { 186 struct aim_ssi_item *cur; 187 for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next); 188 if (cur->next) cur->next=cur->next->next; 189 owl_function_debugmsg("aim_ssi_itemlist_del: deleted %s from middle of list", del->name); 190 } 191 192 /* Free the deleted item */ 193 owl_function_debugmsg("aim_ssi_itemlist_del: freeing"); 194 free(del->name); 195 aim_freetlvchain(&del->data); 196 free(del); 197 198 return(0); 172 if (!list || !(*list) || !del) 173 return -EINVAL; 174 175 /* Remove the item from the list */ 176 if (*list == del) { 177 *list = (*list)->next; 178 } else { 179 struct aim_ssi_item *cur; 180 for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next); 181 if (cur->next) 182 cur->next = del->next; 183 } 184 185 /* Free the removed item */ 186 free(del->name); 187 aim_tlvlist_free(&del->data); 188 free(del); 189 190 return 0; 199 191 } 200 192 … … 208 200 static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2) 209 201 { 210 if (!cur1 || !cur2)211 return 1;212 213 if (cur1->data && !cur2->data)214 return 2;215 216 if (!cur1->data && cur2->data)217 return 3;218 219 if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))220 return 4;221 222 if (cur1->name && !cur2->name)223 return 5;224 225 if (!cur1->name && cur2->name)226 return 6;227 228 if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name))229 return 7;230 231 if (cur1->gid != cur2->gid)232 return 8;233 234 if (cur1->bid != cur2->bid)235 return 9;236 237 if (cur1->type != cur2->type)238 return 10;239 240 return 0;202 if (!cur1 || !cur2) 203 return 1; 204 205 if (cur1->data && !cur2->data) 206 return 2; 207 208 if (!cur1->data && cur2->data) 209 return 3; 210 211 if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data))) 212 return 4; 213 214 if (cur1->name && !cur2->name) 215 return 5; 216 217 if (!cur1->name && cur2->name) 218 return 6; 219 220 if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name)) 221 return 7; 222 223 if (cur1->gid != cur2->gid) 224 return 8; 225 226 if (cur1->bid != cur2->bid) 227 return 9; 228 229 if (cur1->type != cur2->type) 230 return 10; 231 232 return 0; 241 233 } 242 234 243 235 faim_export int aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item) 244 236 { 245 struct aim_ssi_item *cur;246 for (cur=list; cur; cur=cur->next)247 if (cur == item)248 return 1;249 return 0;237 struct aim_ssi_item *cur; 238 for (cur=list; cur; cur=cur->next) 239 if (cur == item) 240 return 1; 241 return 0; 250 242 } 251 243 … … 260 252 faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid) 261 253 { 262 struct aim_ssi_item *cur;263 for (cur=list; cur; cur=cur->next)264 if ((cur->gid == gid) && (cur->bid == bid))265 return cur;266 return NULL;254 struct aim_ssi_item *cur; 255 for (cur=list; cur; cur=cur->next) 256 if ((cur->gid == gid) && (cur->bid == bid)) 257 return cur; 258 return NULL; 267 259 } 268 260 … … 279 271 faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t type) 280 272 { 281 struct aim_ssi_item *cur;282 if (!list)283 return NULL;284 285 if (gn && sn) { /* For finding buddies in groups */286 for (cur=list; cur; cur=cur->next)287 if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {288 struct aim_ssi_item *curg;289 for (curg=list; curg; curg=curg->next)290 if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn)))291 return cur;292 }293 294 } else if (gn) { /* For finding groups */295 for (cur=list; cur; cur=cur->next) {296 if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) {297 return cur;298 }299 }300 301 } else if (sn) { /* For finding permits, denies, and ignores */302 for (cur=list; cur; cur=cur->next) {303 if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {304 return cur;305 }306 }307 308 /* For stuff without names--permit deny setting, visibility mask, etc. */309 } else for (cur=list; cur; cur=cur->next) {310 if ((cur->type == type) && (!cur->name))311 return cur;312 }313 314 return NULL;273 struct aim_ssi_item *cur; 274 if (!list) 275 return NULL; 276 277 if (gn && sn) { /* For finding buddies in groups */ 278 for (cur=list; cur; cur=cur->next) 279 if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) { 280 struct aim_ssi_item *curg; 281 for (curg=list; curg; curg=curg->next) 282 if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn))) 283 return cur; 284 } 285 286 } else if (gn) { /* For finding groups */ 287 for (cur=list; cur; cur=cur->next) { 288 if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) { 289 return cur; 290 } 291 } 292 293 } else if (sn) { /* For finding permits, denies, and ignores */ 294 for (cur=list; cur; cur=cur->next) { 295 if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) { 296 return cur; 297 } 298 } 299 300 /* For stuff without names--permit deny setting, visibility mask, etc. */ 301 } else for (cur=list; cur; cur=cur->next) { 302 if ((cur->type == type) && (!cur->name)) 303 return cur; 304 } 305 306 return NULL; 315 307 } 316 308 … … 324 316 faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn) 325 317 { 326 struct aim_ssi_item *cur;327 if (!list || !sn)328 return NULL;329 for (cur=list; cur; cur=cur->next)330 if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn)))331 return cur;332 return NULL;318 struct aim_ssi_item *cur; 319 if (!list || !sn) 320 return NULL; 321 for (cur=list; cur; cur=cur->next) 322 if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn))) 323 return cur; 324 return NULL; 333 325 } 334 326 … … 342 334 faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn) 343 335 { 344 struct aim_ssi_item *cur, *curg;345 if (!list || !sn)346 return NULL;347 if (!(cur = aim_ssi_itemlist_exists(list, sn)))348 return NULL;349 if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))350 return NULL;351 return curg->name;336 struct aim_ssi_item *cur, *curg; 337 if (!list || !sn) 338 return NULL; 339 if (!(cur = aim_ssi_itemlist_exists(list, sn))) 340 return NULL; 341 if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000))) 342 return NULL; 343 return curg->name; 352 344 } 353 345 … … 360 352 faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list) 361 353 { 362 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO); 363 if (cur) { 364 aim_tlvlist_t *tlvlist = cur->data; 365 if (tlvlist) { 366 aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00ca, 1); 367 if (tlv && tlv->value) 368 return aimutil_get8(tlv->value); 369 } 370 } 371 return 0; 354 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO); 355 if (cur) { 356 aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00ca, 1); 357 if (tlv && tlv->value) 358 return aimutil_get8(tlv->value); 359 } 360 return 0; 372 361 } 373 362 … … 382 371 faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list) 383 372 { 384 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS); 385 if (cur) { 386 aim_tlvlist_t *tlvlist = cur->data; 387 if (tlvlist) { 388 aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00c9, 1); 389 if (tlv && tlv->length) 390 return aimutil_get32(tlv->value); 391 } 392 } 393 return 0xFFFFFFFF; 373 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS); 374 if (cur) { 375 aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c9, 1); 376 if (tlv && tlv->length) 377 return aimutil_get32(tlv->value); 378 } 379 return 0xFFFFFFFF; 394 380 } 395 381 396 382 /** 397 383 * Locally find the alias of the given buddy. 384 * 385 * @param list A pointer to the current list of items. 386 * @param gn The group of the buddy. 387 * @param sn The name of the buddy. 388 * @return A pointer to a NULL terminated string that is the buddy's 389 * alias, or NULL if the buddy has no alias. You should free 390 * this returned value! 391 */ 392 faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn) 393 { 394 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); 395 if (cur) { 396 aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1); 397 if (tlv && tlv->length) { 398 char *alias = (char *)malloc((tlv->length+1)*sizeof(char)); 399 strncpy(alias, tlv->value, tlv->length); 400 alias[tlv->length] = 0; 401 return alias; 402 } 403 } 404 return NULL; 405 } 406 407 /** 408 * Locally find the comment of the given buddy. 409 * 410 * @param list A pointer to the current list of items. 411 * @param gn The group of the buddy. 412 * @param sn The name of the buddy. 413 * @return A pointer to a NULL terminated string that is the buddy's 414 * comment, or NULL if the buddy has no comment. You should free 415 * this returned value! 416 */ 417 faim_export char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *sn) 418 { 419 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); 420 if (cur) { 421 aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x013c, 1); 422 if (tlv && tlv->length) { 423 char *alias = (char *)malloc((tlv->length+1)*sizeof(char)); 424 strncpy(alias, tlv->value, tlv->length); 425 alias[tlv->length] = 0; 426 return alias; 427 } 428 } 429 return NULL; 430 } 431 432 /** 433 * Locally find if you are waiting for authorization for a buddy. 398 434 * 399 435 * @param list A pointer to the current list of items. … … 404 440 * this returned value! 405 441 */ 406 faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn)407 {408 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);409 if (cur) {410 aim_tlvlist_t *tlvlist = cur->data;411 if (tlvlist) {412 aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x0131, 1);413 if (tlv && tlv->length) {414 char *alias = (char *)malloc((tlv->length+1)*sizeof(char));415 strncpy(alias, tlv->value, tlv->length);416 alias[tlv->length] = 0;417 return alias;418 }419 }420 }421 return NULL;422 }423 424 /**425 * Locally find if you are waiting for authorization for a buddy.426 *427 * @param list A pointer to the current list of items.428 * @param gn The group of the buddy.429 * @param sn The name of the buddy.430 * @return A pointer to a NULL terminated string that is the buddies431 * alias, or NULL if the buddy has no alias. You should free432 * this returned value!433 */434 442 faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn) 435 443 { 436 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); 437 if (cur) { 438 aim_tlvlist_t *tlvlist = cur->data; 439 if (tlvlist) 440 if (aim_gettlv(tlvlist, 0x0066, 1)) 441 return 1; 442 } 443 return 0; 444 struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY); 445 if (cur) { 446 if (aim_tlv_gettlv(cur->data, 0x0066, 1)) 447 return 1; 448 } 449 return 0; 444 450 } 445 451 … … 453 459 static int aim_ssi_sync(aim_session_t *sess) 454 460 { 455 struct aim_ssi_item *cur1, *cur2; 456 struct aim_ssi_tmp *cur, *new; 457 458 owl_function_debugmsg("aim_ssi_sync: beginning"); 459 460 if (!sess) return (-EINVAL); 461 462 /* If we're waiting for an ack, we shouldn't do anything else */ 463 if (sess->ssi.waiting_for_ack) { 464 owl_function_debugmsg("Aborting aim_ssi_sync, waiting for ack"); 465 return 0; 466 } 467 468 /* 469 * Compare the 2 lists and create an aim_ssi_tmp for each difference. 470 * We should only send either additions, modifications, or deletions 471 * before waiting for an acknowledgement. So first do deletions, then 472 * additions, then modifications. Also, both the official and the local 473 * list should be in ascending numerical order for the group ID#s and the 474 * buddy ID#s, which makes things more efficient. I think. 475 */ 476 477 /* Additions */ 478 if (!sess->ssi.pending) { 479 for (cur1=sess->ssi.local; cur1; cur1=cur1->next) { 480 if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) { 481 owl_function_debugmsg("aim_ssi_sync: doing addition"); 482 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); 483 new->action = AIM_CB_SSI_ADD; 484 new->ack = 0xffff; 485 new->name = NULL; 486 new->item = cur1; 487 new->next = NULL; 488 if (sess->ssi.pending) { 489 for (cur=sess->ssi.pending; cur->next; cur=cur->next); 490 cur->next = new; 491 } else 492 sess->ssi.pending = new; 493 } 494 } 495 } 496 497 /* Deletions */ 498 if (!sess->ssi.pending) { 499 for (cur1=sess->ssi.official; cur1; cur1=cur1->next) { 500 if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) { 501 owl_function_debugmsg("aim_ssi_sync: doing deletion"); 502 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); 503 new->action = AIM_CB_SSI_DEL; 504 new->ack = 0xffff; 505 new->name = NULL; 506 new->item = cur1; 507 new->next = NULL; 508 if (sess->ssi.pending) { 509 for (cur=sess->ssi.pending; cur->next; cur=cur->next); 510 cur->next = new; 511 } else 512 sess->ssi.pending = new; 513 } 514 } 515 } 516 517 /* Modifications */ 518 if (!sess->ssi.pending) { 519 for (cur1=sess->ssi.local; cur1; cur1=cur1->next) { 520 cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid); 521 if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) { 522 owl_function_debugmsg("aim_ssi_sync: doing modification"); 523 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); 524 new->action = AIM_CB_SSI_MOD; 525 new->ack = 0xffff; 526 new->name = NULL; 527 new->item = cur1; 528 new->next = NULL; 529 if (sess->ssi.pending) { 530 for (cur=sess->ssi.pending; cur->next; cur=cur->next); 531 cur->next = new; 532 } else 533 sess->ssi.pending = new; 534 } 535 } 536 } 537 538 /* We're out of stuff to do, so tell the AIM servers we're done and exit */ 539 if (!sess->ssi.pending) { 540 owl_function_debugmsg("aim_ssi_sync: telling server we're done modifying SSI data."); 541 aim_ssi_modend(sess); 542 return 0; 543 } 544 545 /* Make sure we don't send anything else between now 546 * and when we receive the ack for the following operation */ 547 owl_function_debugmsg("aim_ssi_sync: setting SSI waiting_for_ack"); 548 sess->ssi.waiting_for_ack = 1; 549 550 /* Now go mail off our data and wait 4 to 6 weeks */ 551 owl_function_debugmsg("aim_ssi_sync: about to call addmoddel to send SNACs to server"); 552 aim_ssi_addmoddel(sess); 553 554 return 0; 461 struct aim_ssi_item *cur1, *cur2; 462 struct aim_ssi_tmp *cur, *new; 463 464 if (!sess) 465 return -EINVAL; 466 467 /* If we're waiting for an ack, we shouldn't do anything else */ 468 if (sess->ssi.waiting_for_ack) 469 return 0; 470 471 /* 472 * Compare the 2 lists and create an aim_ssi_tmp for each difference. 473 * We should only send either additions, modifications, or deletions 474 * before waiting for an acknowledgement. So first do deletions, then 475 * additions, then modifications. Also, both the official and the local 476 * list should be in ascending numerical order for the group ID#s and the 477 * buddy ID#s, which makes things more efficient. I think. 478 */ 479 480 /* Additions */ 481 if (!sess->ssi.pending) { 482 for (cur1=sess->ssi.local; cur1; cur1=cur1->next) { 483 if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) { 484 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); 485 new->action = AIM_CB_SSI_ADD; 486 new->ack = 0xffff; 487 new->name = NULL; 488 new->item = cur1; 489 new->next = NULL; 490 if (sess->ssi.pending) { 491 for (cur=sess->ssi.pending; cur->next; cur=cur->next); 492 cur->next = new; 493 } else 494 sess->ssi.pending = new; 495 } 496 } 497 } 498 499 /* Deletions */ 500 if (!sess->ssi.pending) { 501 for (cur1=sess->ssi.official; cur1; cur1=cur1->next) { 502 if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) { 503 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); 504 new->action = AIM_CB_SSI_DEL; 505 new->ack = 0xffff; 506 new->name = NULL; 507 new->item = cur1; 508 new->next = NULL; 509 if (sess->ssi.pending) { 510 for (cur=sess->ssi.pending; cur->next; cur=cur->next); 511 cur->next = new; 512 } else 513 sess->ssi.pending = new; 514 } 515 } 516 } 517 518 /* Modifications */ 519 if (!sess->ssi.pending) { 520 for (cur1=sess->ssi.local; cur1; cur1=cur1->next) { 521 cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid); 522 if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) { 523 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp)); 524 new->action = AIM_CB_SSI_MOD; 525 new->ack = 0xffff; 526 new->name = NULL; 527 new->item = cur1; 528 new->next = NULL; 529 if (sess->ssi.pending) { 530 for (cur=sess->ssi.pending; cur->next; cur=cur->next); 531 cur->next = new; 532 } else 533 sess->ssi.pending = new; 534 } 535 } 536 } 537 538 /* We're out of stuff to do, so tell the AIM servers we're done and exit */ 539 if (!sess->ssi.pending) { 540 aim_ssi_modend(sess); 541 return 0; 542 } 543 544 /* Make sure we don't send anything else between now 545 * and when we receive the ack for the following operation */ 546 sess->ssi.waiting_for_ack = 1; 547 548 /* Now go mail off our data and wait 4 to 6 weeks */ 549 aim_ssi_addmoddel(sess); 550 551 return 0; 555 552 } 556 553 … … 565 562 static int aim_ssi_freelist(aim_session_t *sess) 566 563 { 567 struct aim_ssi_item *cur, *del;568 struct aim_ssi_tmp *curtmp, *deltmp;569 570 cur = sess->ssi.official;571 while (cur) {572 del = cur;573 cur = cur->next;574 free(del->name);575 aim_freetlvchain(&del->data);576 free(del);577 }578 579 cur = sess->ssi.local;580 while (cur) {581 del = cur;582 cur = cur->next;583 free(del->name);584 aim_freetlvchain(&del->data);585 free(del);586 }587 588 curtmp = sess->ssi.pending;589 while (curtmp) {590 deltmp = curtmp;591 curtmp = curtmp->next;592 free(deltmp);593 }594 595 sess->ssi.numitems = 0;596 sess->ssi.official = NULL;597 sess->ssi.local = NULL;598 sess->ssi.pending = NULL;599 sess->ssi.timestamp = (time_t)0;600 601 return 0;564 struct aim_ssi_item *cur, *del; 565 struct aim_ssi_tmp *curtmp, *deltmp; 566 567 cur = sess->ssi.official; 568 while (cur) { 569 del = cur; 570 cur = cur->next; 571 free(del->name); 572 aim_tlvlist_free(&del->data); 573 free(del); 574 } 575 576 cur = sess->ssi.local; 577 while (cur) { 578 del = cur; 579 cur = cur->next; 580 free(del->name); 581 aim_tlvlist_free(&del->data); 582 free(del); 583 } 584 585 curtmp = sess->ssi.pending; 586 while (curtmp) { 587 deltmp = curtmp; 588 curtmp = curtmp->next; 589 free(deltmp); 590 } 591 592 sess->ssi.numitems = 0; 593 sess->ssi.official = NULL; 594 sess->ssi.local = NULL; 595 sess->ssi.pending = NULL; 596 sess->ssi.timestamp = (time_t)0; 597 598 return 0; 602 599 } 603 600 … … 610 607 faim_export int aim_ssi_deletelist(aim_session_t *sess) 611 608 { 612 struct aim_ssi_item *cur, *del; 613 614 if (!sess) return (-EINVAL); 615 616 /* Free the local list */ 617 cur = sess->ssi.local; 618 while (cur) { 619 del = cur; 620 cur = cur->next; 621 free(del->name); 622 aim_freetlvchain(&del->data); 623 free(del); 624 } 625 sess->ssi.local = NULL; 626 627 /* Sync our local list with the server list */ 628 aim_ssi_sync(sess); 629 630 return 0; 609 struct aim_ssi_item *cur, *del; 610 611 if (!sess) 612 return -EINVAL; 613 614 /* Free the local list */ 615 cur = sess->ssi.local; 616 while (cur) { 617 del = cur; 618 cur = cur->next; 619 free(del->name); 620 aim_tlvlist_free(&del->data); 621 free(del); 622 } 623 sess->ssi.local = NULL; 624 625 /* Sync our local list with the server list */ 626 aim_ssi_sync(sess); 627 628 return 0; 631 629 } 632 630 … … 642 640 faim_export int aim_ssi_cleanlist(aim_session_t *sess) 643 641 { 644 struct aim_ssi_item *cur, *next; 645 646 if (!sess) return -EINVAL; 647 648 /* Delete any buddies, permits, or denies with empty names. */ 649 /* If there are any buddies directly in the master group, add them to a real group. */ 650 /* DESTROY any buddies that are directly in the master group. */ 651 /* Do the same for buddies that are in a non-existant group. */ 652 /* This will kind of mess up if you hit the item limit, but this function isn't too critical */ 653 cur = sess->ssi.local; 654 while (cur) { 655 next = cur->next; 656 if (!cur->name) { 657 if (cur->type == AIM_SSI_TYPE_BUDDY) 658 aim_ssi_delbuddy(sess, NULL, NULL); 659 else if (cur->type == AIM_SSI_TYPE_PERMIT) 660 aim_ssi_delpermit(sess, NULL); 661 else if (cur->type == AIM_SSI_TYPE_DENY) 662 aim_ssi_deldeny(sess, NULL); 663 } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(sess->ssi.local, cur->gid, 0x0000)))) { 664 aim_ssi_addbuddy(sess, cur->name, "orphans", NULL, NULL, NULL, 0); 665 aim_ssi_delbuddy(sess, cur->name, NULL); 666 } 667 cur = next; 668 } 669 670 /* Check if there are empty groups and delete them */ 671 cur = sess->ssi.local; 672 while (cur) { 673 next = cur->next; 674 if (cur->type == AIM_SSI_TYPE_GROUP) { 675 aim_tlv_t *tlv = aim_gettlv(cur->data, 0x00c8, 1); 676 if (!tlv || !tlv->length) 677 aim_ssi_itemlist_del(&sess->ssi.local, cur); 678 } 679 cur = next; 680 } 681 682 /* Check if the master group is empty */ 683 if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data)) 684 aim_ssi_itemlist_del(&sess->ssi.local, cur); 685 686 return 0; 642 struct aim_ssi_item *cur, *next; 643 644 if (!sess) 645 return -EINVAL; 646 647 /* Delete any buddies, permits, or denies with empty names. */ 648 /* If there are any buddies directly in the master group, add them to a real group. */ 649 /* DESTROY any buddies that are directly in the master group. */ 650 /* Do the same for buddies that are in a non-existant group. */ 651 /* This will kind of mess up if you hit the item limit, but this function isn't too critical */ 652 cur = sess->ssi.local; 653 while (cur) { 654 next = cur->next; 655 if (!cur->name) { 656 if (cur->type == AIM_SSI_TYPE_BUDDY) 657 aim_ssi_delbuddy(sess, NULL, NULL); 658 else if (cur->type == AIM_SSI_TYPE_PERMIT) 659 aim_ssi_delpermit(sess, NULL); 660 else if (cur->type == AIM_SSI_TYPE_DENY) 661 aim_ssi_deldeny(sess, NULL); 662 } else if ((cur->type == AIM_SSI_TYPE_BUDDY) && ((cur->gid == 0x0000) || (!aim_ssi_itemlist_find(sess->ssi.local, cur->gid, 0x0000)))) { 663 aim_ssi_addbuddy(sess, cur->name, "orphans", NULL, NULL, NULL, 0); 664 aim_ssi_delbuddy(sess, cur->name, NULL); 665 } 666 cur = next; 667 } 668 669 /* Check if there are empty groups and delete them */ 670 cur = sess->ssi.local; 671 while (cur) { 672 next = cur->next; 673 if (cur->type == AIM_SSI_TYPE_GROUP) { 674 aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c8, 1); 675 if (!tlv || !tlv->length) 676 aim_ssi_itemlist_del(&sess->ssi.local, cur); 677 } 678 cur = next; 679 } 680 681 /* Check if the master group is empty */ 682 if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data)) 683 aim_ssi_itemlist_del(&sess->ssi.local, cur); 684 685 return 0; 687 686 } 688 687 … … 700 699 faim_export int aim_ssi_addbuddy(aim_session_t *sess, const char *name, const char *group, const char *alias, const char *comment, const char *smsnum, int needauth) 701 700 { 702 struct aim_ssi_item *parent; 703 aim_tlvlist_t *data = NULL; 704 705 if (!sess || !name || !group) return (-EINVAL); 706 707 /* Find the parent */ 708 if (!(parent = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) { 709 /* Find the parent's parent (the master group) */ 710 if (!(parent = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000))) { 711 if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) { 712 return -ENOMEM; 713 } 714 } 715 /* Add the parent */ 716 if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) { 717 return -ENOMEM; 718 } 719 720 /* Modify the parent's parent (the master group) */ 721 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL); 722 } 723 724 /* Create a TLV list for the new buddy */ 725 if (needauth) aim_addtlvtochain_noval(&data, 0x0066); 726 if (alias) aim_addtlvtochain_raw(&data, 0x0131, strlen(alias), alias); 727 if (smsnum) aim_addtlvtochain_raw(&data, 0x013a, strlen(smsnum), smsnum); 728 if (comment) aim_addtlvtochain_raw(&data, 0x013c, strlen(comment), comment); 729 730 /* Add that bad boy */ 731 aim_ssi_itemlist_add(&sess->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data); 732 aim_freetlvchain(&data); 733 734 /* Modify the parent group */ 735 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group); 736 737 /* Sync our local list with the server list */ 738 aim_ssi_sync(sess); 739 740 return(0); 701 struct aim_ssi_item *parent; 702 aim_tlvlist_t *data = NULL; 703 704 if (!sess || !name || !group) 705 return -EINVAL; 706 707 /* Find the parent */ 708 if (!(parent = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) { 709 /* Find the parent's parent (the master group) */ 710 if (!(parent = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000))) 711 if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) 712 return -ENOMEM; 713 /* Add the parent */ 714 if (!(parent = aim_ssi_itemlist_add(&sess->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL))) 715 return -ENOMEM; 716 717 /* Modify the parent's parent (the master group) */ 718 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL); 719 } 720 721 /* Create a TLV list for the new buddy */ 722 if (needauth) 723 aim_tlvlist_add_noval(&data, 0x0066); 724 if (alias) 725 aim_tlvlist_add_raw(&data, 0x0131, strlen(alias), alias); 726 if (smsnum) 727 aim_tlvlist_add_raw(&data, 0x013a, strlen(smsnum), smsnum); 728 if (comment) 729 aim_tlvlist_add_raw(&data, 0x013c, strlen(comment), comment); 730 731 /* Add that bad boy */ 732 aim_ssi_itemlist_add(&sess->ssi.local, name, parent->gid, 0xFFFF, AIM_SSI_TYPE_BUDDY, data); 733 aim_tlvlist_free(&data); 734 735 /* Modify the parent group */ 736 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group); 737 738 /* Sync our local list with the server list */ 739 aim_ssi_sync(sess); 740 741 return 0; 741 742 } 742 743 … … 751 752 { 752 753 753 if (!sess || !name) return -EINVAL; 754 755 /* Add that bad boy */ 756 aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL); 757 758 /* Sync our local list with the server list */ 759 aim_ssi_sync(sess); 760 761 return(0); 754 if (!sess || !name) 755 return -EINVAL; 756 757 /* Add that bad boy */ 758 aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_PERMIT, NULL); 759 760 /* Sync our local list with the server list */ 761 aim_ssi_sync(sess); 762 763 return 0; 762 764 } 763 765 … … 772 774 { 773 775 774 if (!sess || !name) return (-EINVAL); 775 776 /* Add that bad boy */ 777 aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL); 778 779 /* Sync our local list with the server list */ 780 aim_ssi_sync(sess); 781 782 return(0); 776 if (!sess || !name) 777 return -EINVAL; 778 779 /* Add that bad boy */ 780 aim_ssi_itemlist_add(&sess->ssi.local, name, 0x0000, 0xFFFF, AIM_SSI_TYPE_DENY, NULL); 781 782 /* Sync our local list with the server list */ 783 aim_ssi_sync(sess); 784 785 return 0; 783 786 } 784 787 … … 793 796 faim_export int aim_ssi_delbuddy(aim_session_t *sess, const char *name, const char *group) 794 797 { 795 struct aim_ssi_item *del;796 797 if (!sess) return -EINVAL; 798 799 /* Find the buddy */ 800 del=aim_ssi_itemlist_finditem(sess->ssi.local, group, name, AIM_SSI_TYPE_BUDDY); 801 if (!del) return(-EINVAL); 802 803 /* Remove the item from the list */ 804 aim_ssi_itemlist_del(&sess->ssi.local, del); 805 806 /* Modify the parent group */ 807 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group); 808 809 /* Check if we should delete the parent group */ 810 if ((del = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) { 811 aim_ssi_itemlist_del(&sess->ssi.local, del); 812 813 /* Modify the parent group */ 814 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL); 815 816 /* Check if we should delete the parent's parent (the master group) */ 817 if ((del = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!del->data)) { 818 aim_ssi_itemlist_del(&sess->ssi.local, del); 819 } 820 }821 822 /* Sync our local list with the server list */ 823 owl_function_debugmsg("aim_ssi_delbuddy: about to sync"); 824 aim_ssi_sync(sess);825 826 return(0);798 struct aim_ssi_item *del; 799 800 if (!sess) 801 return -EINVAL; 802 803 /* Find the buddy */ 804 if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, group, name, AIM_SSI_TYPE_BUDDY))) 805 return -EINVAL; 806 807 /* Remove the item from the list */ 808 aim_ssi_itemlist_del(&sess->ssi.local, del); 809 810 /* Modify the parent group */ 811 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, group); 812 813 /* Check if we should delete the parent group */ 814 if ((del = aim_ssi_itemlist_finditem(sess->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)) && (!del->data)) { 815 aim_ssi_itemlist_del(&sess->ssi.local, del); 816 817 /* Modify the parent group */ 818 aim_ssi_itemlist_rebuildgroup(sess->ssi.local, NULL); 819 820 /* Check if we should delete the parent's parent (the master group) */ 821 if ((del = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!del->data)) { 822 aim_ssi_itemlist_del(&sess->ssi.local, del); 823 } 824 } 825 826 /* Sync our local list with the server list */ 827 aim_ssi_sync(sess); 828 829 return 0; 827 830 } 828 831 … … 836 839 faim_export int aim_ssi_delpermit(aim_session_t *sess, const char *name) 837 840 { 838 struct aim_ssi_item *del;839 840 if (!sess)841 return -EINVAL;842 843 /* Find the item */844 if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT)))845 return -EINVAL;846 847 /* Remove the item from the list */848 aim_ssi_itemlist_del(&sess->ssi.local, del);849 850 /* Sync our local list with the server list */851 aim_ssi_sync(sess);852 853 return 0;841 struct aim_ssi_item *del; 842 843 if (!sess) 844 return -EINVAL; 845 846 /* Find the item */ 847 if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT))) 848 return -EINVAL; 849 850 /* Remove the item from the list */ 851 aim_ssi_itemlist_del(&sess->ssi.local, del); 852 853 /* Sync our local list with the server list */ 854 aim_ssi_sync(sess); 855 856 return 0; 854 857 } 855 858 … … 863 866 faim_export int aim_ssi_deldeny(aim_session_t *sess, const char *name) 864 867 { 865 struct aim_ssi_item *del;866 867 if (!sess)868 return -EINVAL;869 870 /* Find the item */871 if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY)))872 return -EINVAL;873 874 /* Remove the item from the list */875 aim_ssi_itemlist_del(&sess->ssi.local, del);876 877 /* Sync our local list with the server list */878 aim_ssi_sync(sess);879 880 return 0;868 struct aim_ssi_item *del; 869 870 if (!sess) 871 return -EINVAL; 872 873 /* Find the item */ 874 if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY))) 875 return -EINVAL; 876 877 /* Remove the item from the list */ 878 aim_ssi_itemlist_del(&sess->ssi.local, del); 879 880 /* Sync our local list with the server list */ 881 aim_ssi_sync(sess); 882 883 return 0; 881 884 } 882 885 … … 893 896 faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn) 894 897 { 895 aim_ssi_addbuddy(sess, sn, newgn, aim_ssi_getalias(sess->ssi.local, oldgn, sn), NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn));896 aim_ssi_delbuddy(sess, sn, oldgn);897 return 0;898 aim_ssi_addbuddy(sess, sn, newgn, aim_ssi_getalias(sess->ssi.local, oldgn, sn), NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn)); 899 aim_ssi_delbuddy(sess, sn, oldgn); 900 return 0; 898 901 } 899 902 … … 904 907 * @param gn The group that the buddy is currently in. 905 908 * @param sn The screen name of the buddy. 906 * @param alias The new alias for the buddy. 909 * @param alias The new alias for the buddy, or NULL if you want to remove 910 * a buddy's comment. 907 911 * @return Return 0 if no errors, otherwise return the error number. 908 912 */ 909 913 faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias) 910 914 { 911 struct aim_ssi_item *tmp; 912 aim_tlvlist_t *data = NULL; 913 914 if (!sess || !gn || !sn) 915 return -EINVAL; 916 917 if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) 918 return -EINVAL; 919 920 if (alias && !strlen(alias)) 921 alias = NULL; 922 923 /* Need to add the x0131 TLV to the TLV chain */ 924 if (alias) 925 aim_addtlvtochain_raw(&data, 0x0131, strlen(alias), alias); 926 927 aim_freetlvchain(&tmp->data); 928 tmp->data = data; 929 930 /* Sync our local list with the server list */ 931 aim_ssi_sync(sess); 932 933 return 0; 915 struct aim_ssi_item *tmp; 916 917 if (!sess || !gn || !sn) 918 return -EINVAL; 919 920 if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) 921 return -EINVAL; 922 923 /* Either add or remove the 0x0131 TLV from the TLV chain */ 924 if ((alias != NULL) && (strlen(alias) > 0)) 925 aim_tlvlist_replace_raw(&tmp->data, 0x0131, strlen(alias), alias); 926 else 927 aim_tlvlist_remove(&tmp->data, 0x0131); 928 929 /* Sync our local list with the server list */ 930 aim_ssi_sync(sess); 931 932 return 0; 933 } 934 935 /** 936 * Change the comment stored on the server for a given buddy. 937 * 938 * @param sess The oscar session. 939 * @param gn The group that the buddy is currently in. 940 * @param sn The screen name of the buddy. 941 * @param alias The new comment for the buddy, or NULL if you want to remove 942 * a buddy's comment. 943 * @return Return 0 if no errors, otherwise return the error number. 944 */ 945 faim_export int aim_ssi_editcomment(aim_session_t *sess, const char *gn, const char *sn, const char *comment) 946 { 947 struct aim_ssi_item *tmp; 948 949 if (!sess || !gn || !sn) 950 return -EINVAL; 951 952 if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY))) 953 return -EINVAL; 954 955 /* Either add or remove the 0x0131 TLV from the TLV chain */ 956 if ((comment != NULL) && (strlen(comment) > 0)) 957 aim_tlvlist_replace_raw(&tmp->data, 0x013c, strlen(comment), comment); 958 else 959 aim_tlvlist_remove(&tmp->data, 0x013c); 960 961 /* Sync our local list with the server list */ 962 aim_ssi_sync(sess); 963 964 return 0; 934 965 } 935 966 … … 944 975 faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn) 945 976 { 946 struct aim_ssi_item *group;947 948 if (!sess || !oldgn || !newgn)949 return -EINVAL;950 951 if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))952 return -EINVAL;953 954 free(group->name);955 group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char));956 strcpy(group->name, newgn);957 958 /* Sync our local list with the server list */959 aim_ssi_sync(sess);960 961 return 0;977 struct aim_ssi_item *group; 978 979 if (!sess || !oldgn || !newgn) 980 return -EINVAL; 981 982 if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP))) 983 return -EINVAL; 984 985 free(group->name); 986 group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char)); 987 strcpy(group->name, newgn); 988 989 /* Sync our local list with the server list */ 990 aim_ssi_sync(sess); 991 992 return 0; 962 993 } 963 994 … … 978 1009 faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask) 979 1010 { 980 struct aim_ssi_item *tmp; 981 aim_tlvlist_t *data = NULL; 982 983 if (!sess) 984 return -EINVAL; 985 986 /* Need to add the x00ca TLV to the TLV chain */ 987 aim_addtlvtochain8(&data, 0x00ca, permdeny); 988 989 /* Need to add the x00cb TLV to the TLV chain */ 990 aim_addtlvtochain32(&data, 0x00cb, vismask); 991 992 if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) { 993 aim_freetlvchain(&tmp->data); 994 tmp->data = data; 995 } else { 996 tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, data); 997 aim_freetlvchain(&data); 998 } 999 1000 /* Sync our local list with the server list */ 1001 aim_ssi_sync(sess); 1002 1003 return 0; 1011 struct aim_ssi_item *tmp; 1012 1013 if (!sess) 1014 return -EINVAL; 1015 1016 /* Find the PDINFO item, or add it if it does not exist */ 1017 if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) 1018 tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL); 1019 1020 /* Need to add the 0x00ca TLV to the TLV chain */ 1021 aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny); 1022 1023 /* Need to add the 0x00cb TLV to the TLV chain */ 1024 aim_tlvlist_replace_32(&tmp->data, 0x00cb, vismask); 1025 1026 /* Sync our local list with the server list */ 1027 aim_ssi_sync(sess); 1028 1029 return 0; 1004 1030 } 1005 1031 … … 1014 1040 faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen) 1015 1041 { 1016 struct aim_ssi_item *tmp; 1017 aim_tlvlist_t *data = NULL; 1018 fu8_t *csumdata; 1019 1020 if (!sess || !iconsum || !iconsumlen) 1021 return -EINVAL; 1022 1023 if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t)))) 1024 return -ENOMEM; 1025 csumdata[0] = 0x00; 1026 csumdata[1] = 0x10; 1027 memcpy(&csumdata[2], iconsum, iconsumlen); 1028 1029 /* Need to add the x00d5 TLV to the TLV chain */ 1030 aim_addtlvtochain_raw(&data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata); 1031 1032 /* This TLV is added to cache the icon. */ 1033 aim_addtlvtochain_noval(&data, 0x0131); 1034 1035 if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { 1036 /* If the new tlvchain and oldtlvchain are the same, then do nothing */ 1037 if (!aim_tlvlist_cmp(tmp->data, data)) { 1038 /* The new tlvlist is the identical to the old one */ 1039 aim_freetlvchain(&data); 1040 free(csumdata); 1041 return 0; 1042 } 1043 aim_freetlvchain(&tmp->data); 1044 tmp->data = data; 1045 } else { 1046 tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, data); 1047 aim_freetlvchain(&data); 1048 } 1049 1050 /* Sync our local list with the server list */ 1051 aim_ssi_sync(sess); 1052 free(csumdata); 1053 return 0; 1042 struct aim_ssi_item *tmp; 1043 fu8_t *csumdata; 1044 1045 if (!sess || !iconsum || !iconsumlen) 1046 return -EINVAL; 1047 1048 /* Find the ICONINFO item, or add it if it does not exist */ 1049 if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) { 1050 tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, NULL); 1051 } 1052 1053 /* Need to add the 0x00d5 TLV to the TLV chain */ 1054 if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t)))) 1055 return -ENOMEM; 1056 csumdata[0] = 0x00; 1057 csumdata[1] = 0x10; 1058 memcpy(&csumdata[2], iconsum, iconsumlen); 1059 aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata); 1060 free(csumdata); 1061 1062 /* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */ 1063 aim_tlvlist_replace_noval(&tmp->data, 0x0131); 1064 1065 /* Sync our local list with the server list */ 1066 aim_ssi_sync(sess); 1067 return 0; 1068 } 1069 1070 /** 1071 * Remove a reference to a server stored buddy icon. This will make your 1072 * icon stop showing up to other people. 1073 * 1074 * @param sess The oscar session. 1075 * @return Return 0 if no errors, otherwise return the error number. 1076 */ 1077 faim_export int aim_ssi_delicon(aim_session_t *sess) 1078 { 1079 struct aim_ssi_item *tmp; 1080 1081 if (!sess) 1082 return -EINVAL; 1083 1084 /* Find the ICONINFO item and delete it if it exists*/ 1085 if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) 1086 aim_ssi_itemlist_del(&sess->ssi.local, tmp); 1087 1088 /* Sync our local list with the server list */ 1089 aim_ssi_sync(sess); 1090 return 0; 1054 1091 } 1055 1092 … … 1059 1096 * @param sess The oscar session. 1060 1097 * @param presence I think it's a bitmask, but I only know what one of the bits is: 1098 * 0x00000002 - Hide wireless? 1061 1099 * 0x00000400 - Allow others to see your idle time 1062 1100 * @return Return 0 if no errors, otherwise return the error number. 1063 1101 */ 1064 1102 faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence) { 1065 struct aim_ssi_item *tmp; 1066 aim_tlvlist_t *data = NULL; 1067 1068 if (!sess) 1069 return -EINVAL; 1070 1071 /* Need to add the x00c9 TLV to the TLV chain */ 1072 aim_addtlvtochain32(&data, 0x00c9, presence); 1073 1074 if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) { 1075 aim_freetlvchain(&tmp->data); 1076 tmp->data = data; 1077 } else { 1078 tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, data); 1079 aim_freetlvchain(&data); 1080 } 1081 1082 /* Sync our local list with the server list */ 1083 aim_ssi_sync(sess); 1084 1085 return 0; 1103 struct aim_ssi_item *tmp; 1104 1105 if (!sess) 1106 return -EINVAL; 1107 1108 /* Find the PRESENCEPREFS item, or add it if it does not exist */ 1109 if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) 1110 tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL); 1111 1112 /* Need to add the x00c9 TLV to the TLV chain */ 1113 aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence); 1114 1115 /* Sync our local list with the server list */ 1116 aim_ssi_sync(sess); 1117 1118 return 0; 1086 1119 } 1087 1120 … … 1091 1124 faim_export int aim_ssi_reqrights(aim_session_t *sess) 1092 1125 { 1093 aim_conn_t *conn;1094 1095 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))1096 return -EINVAL;1097 1098 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);1126 aim_conn_t *conn; 1127 1128 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) 1129 return -EINVAL; 1130 1131 return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS); 1099 1132 } 1100 1133 … … 1104 1137 static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1105 1138 { 1106 int ret = 0, i;1107 aim_rxcallback_t userfunc;1108 aim_tlvlist_t *tlvlist;1109 aim_tlv_t *tlv;1110 aim_bstream_t bstream;1111 fu16_t *maxitems;1112 1113 /* This SNAC is made up of a bunch of TLVs */1114 tlvlist = aim_readtlvchain(bs);1115 1116 /* TLV 0x0004 contains the maximum number of each item */1117 if (!(tlv = aim_gettlv(tlvlist, 0x0004, 1))) {1118 aim_freetlvchain(&tlvlist);1119 return 0;1120 }1121 1122 aim_bstream_init(&bstream, tlv->value, tlv->length);1123 1124 if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) {1125 aim_freetlvchain(&tlvlist);1126 return 0;1127 }1128 1129 for (i=0; i<(tlv->length/2); i++)1130 maxitems[i] = aimbs_get16(&bstream);1131 1132 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1133 ret = userfunc(sess, rx, tlv->length/2, maxitems);1134 1135 aim_freetlvchain(&tlvlist);1136 free(maxitems);1137 1138 return ret;1139 int ret = 0, i; 1140 aim_rxcallback_t userfunc; 1141 aim_tlvlist_t *tlvlist; 1142 aim_tlv_t *tlv; 1143 aim_bstream_t bstream; 1144 fu16_t *maxitems; 1145 1146 /* This SNAC is made up of a bunch of TLVs */ 1147 tlvlist = aim_tlvlist_read(bs); 1148 1149 /* TLV 0x0004 contains the maximum number of each item */ 1150 if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) { 1151 aim_tlvlist_free(&tlvlist); 1152 return 0; 1153 } 1154 1155 aim_bstream_init(&bstream, tlv->value, tlv->length); 1156 1157 if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) { 1158 aim_tlvlist_free(&tlvlist); 1159 return 0; 1160 } 1161 1162 for (i=0; i<(tlv->length/2); i++) 1163 maxitems[i] = aimbs_get16(&bstream); 1164 1165 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1166 ret = userfunc(sess, rx, tlv->length/2, maxitems); 1167 1168 aim_tlvlist_free(&tlvlist); 1169 free(maxitems); 1170 1171 return ret; 1139 1172 } 1140 1173 … … 1146 1179 faim_export int aim_ssi_reqdata(aim_session_t *sess) 1147 1180 { 1148 aim_conn_t *conn;1149 1150 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))1151 return -EINVAL;1152 1153 /* Free any current data, just in case */1154 aim_ssi_freelist(sess);1155 1156 return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);1181 aim_conn_t *conn; 1182 1183 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) 1184 return -EINVAL; 1185 1186 /* Free any current data, just in case */ 1187 aim_ssi_freelist(sess); 1188 1189 return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA); 1157 1190 } 1158 1191 … … 1169 1202 faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t timestamp, fu16_t numitems) 1170 1203 { 1171 aim_conn_t *conn;1172 aim_frame_t *fr;1173 aim_snacid_t snacid;1174 1175 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))1176 return -EINVAL;1177 1178 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))1179 return -ENOMEM;1180 1181 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0);1182 1183 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid);1184 aimbs_put32(&fr->data, timestamp);1185 aimbs_put16(&fr->data, numitems);1186 1187 aim_tx_enqueue(sess, fr);1188 1189 /* Free any current data, just in case */1190 aim_ssi_freelist(sess);1191 1192 return 0;1204 aim_conn_t *conn; 1205 aim_frame_t *fr; 1206 aim_snacid_t snacid; 1207 1208 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) 1209 return -EINVAL; 1210 1211 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2))) 1212 return -ENOMEM; 1213 1214 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0); 1215 1216 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid); 1217 aimbs_put32(&fr->data, timestamp); 1218 aimbs_put16(&fr->data, numitems); 1219 1220 aim_tx_enqueue(sess, fr); 1221 1222 /* Free any current data, just in case */ 1223 aim_ssi_freelist(sess); 1224 1225 return 0; 1193 1226 } 1194 1227 … … 1198 1231 static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1199 1232 { 1200 int ret = 0;1201 aim_rxcallback_t userfunc;1202 fu8_t fmtver; /* guess */1203 fu16_t namelen, gid, bid, type;1204 char *name;1205 aim_tlvlist_t *data;1206 1207 fmtver = aimbs_get8(bs); /* Version of ssi data. Should be 0x00 */1208 sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */1209 1210 /* Read in the list */1211 while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */1212 if ((namelen = aimbs_get16(bs)))1213 name = aimbs_getstr(bs, namelen);1214 else1215 name = NULL;1216 gid = aimbs_get16(bs);1217 bid = aimbs_get16(bs);1218 type = aimbs_get16(bs);1219 data = aim_readtlvchain_len(bs, aimbs_get16(bs));1220 aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);1221 free(name);1222 aim_freetlvchain(&data);1223 }1224 1225 /* Read in the timestamp */1226 sess->ssi.timestamp = aimbs_get32(bs);1227 1228 if (!(snac->flags & 0x0001)) {1229 /* Make a copy of the list */1230 struct aim_ssi_item *cur;1231 for (cur=sess->ssi.official; cur; cur=cur->next)1232 aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);1233 1234 sess->ssi.received_data = 1;1235 1236 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1237 ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp);1238 }1239 1240 return ret;1233 int ret = 0; 1234 aim_rxcallback_t userfunc; 1235 fu8_t fmtver; /* guess */ 1236 fu16_t namelen, gid, bid, type; 1237 char *name; 1238 aim_tlvlist_t *data; 1239 1240 fmtver = aimbs_get8(bs); /* Version of ssi data. Should be 0x00 */ 1241 sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */ 1242 1243 /* Read in the list */ 1244 while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */ 1245 if ((namelen = aimbs_get16(bs))) 1246 name = aimbs_getstr(bs, namelen); 1247 else 1248 name = NULL; 1249 gid = aimbs_get16(bs); 1250 bid = aimbs_get16(bs); 1251 type = aimbs_get16(bs); 1252 data = aim_tlvlist_readlen(bs, aimbs_get16(bs)); 1253 aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data); 1254 free(name); 1255 aim_tlvlist_free(&data); 1256 } 1257 1258 /* Read in the timestamp */ 1259 sess->ssi.timestamp = aimbs_get32(bs); 1260 1261 if (!(snac->flags & 0x0001)) { 1262 /* Make a copy of the list */ 1263 struct aim_ssi_item *cur; 1264 for (cur=sess->ssi.official; cur; cur=cur->next) 1265 aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data); 1266 1267 sess->ssi.received_data = 1; 1268 1269 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1270 ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp); 1271 } 1272 1273 return ret; 1241 1274 } 1242 1275 … … 1252 1285 faim_export int aim_ssi_enable(aim_session_t *sess) 1253 1286 { 1254 aim_conn_t *conn;1255 1256 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))1257 return -EINVAL;1258 1259 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);1287 aim_conn_t *conn; 1288 1289 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) 1290 return -EINVAL; 1291 1292 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007); 1260 1293 } 1261 1294 … … 1270 1303 faim_export int aim_ssi_addmoddel(aim_session_t *sess) 1271 1304 { 1272 aim_conn_t *conn; 1273 aim_frame_t *fr; 1274 aim_snacid_t snacid; 1275 int snaclen; 1276 struct aim_ssi_tmp *cur; 1277 1278 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item) { 1279 owl_function_debugmsg("aim_ssi_addmoddel: aborting early"); 1280 return -EINVAL; 1281 } 1282 1283 /* Calculate total SNAC size */ 1284 snaclen = 10; /* For family, subtype, flags, and SNAC ID */ 1285 for (cur=sess->ssi.pending; cur; cur=cur->next) { 1286 snaclen += 10; /* For length, GID, BID, type, and length */ 1287 if (cur->item->name) snaclen += strlen(cur->item->name); 1288 if (cur->item->data) snaclen += aim_sizetlvchain(&cur->item->data); 1289 } 1290 1291 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) return (-ENOMEM); 1292 1293 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0); 1294 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid); 1295 1296 for (cur=sess->ssi.pending; cur; cur=cur->next) { 1297 aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0); 1298 if (cur->item->name) aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name)); 1299 aimbs_put16(&fr->data, cur->item->gid); 1300 aimbs_put16(&fr->data, cur->item->bid); 1301 aimbs_put16(&fr->data, cur->item->type); 1302 aimbs_put16(&fr->data, cur->item->data ? aim_sizetlvchain(&cur->item->data) : 0); 1303 if (cur->item->data) aim_writetlvchain(&fr->data, &cur->item->data); 1304 } 1305 1306 aim_tx_enqueue(sess, fr); 1307 1308 owl_function_debugmsg("aim_ssi_addmoddel: exiting normally"); 1309 return 0; 1305 aim_conn_t *conn; 1306 aim_frame_t *fr; 1307 aim_snacid_t snacid; 1308 int snaclen; 1309 struct aim_ssi_tmp *cur; 1310 1311 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sess->ssi.pending || !sess->ssi.pending->item) 1312 return -EINVAL; 1313 1314 /* Calculate total SNAC size */ 1315 snaclen = 10; /* For family, subtype, flags, and SNAC ID */ 1316 for (cur=sess->ssi.pending; cur; cur=cur->next) { 1317 snaclen += 10; /* For length, GID, BID, type, and length */ 1318 if (cur->item->name) 1319 snaclen += strlen(cur->item->name); 1320 if (cur->item->data) 1321 snaclen += aim_tlvlist_size(&cur->item->data); 1322 } 1323 1324 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, snaclen))) 1325 return -ENOMEM; 1326 1327 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, NULL, 0); 1328 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, sess->ssi.pending->action, 0x0000, snacid); 1329 1330 for (cur=sess->ssi.pending; cur; cur=cur->next) { 1331 aimbs_put16(&fr->data, cur->item->name ? strlen(cur->item->name) : 0); 1332 if (cur->item->name) 1333 aimbs_putraw(&fr->data, cur->item->name, strlen(cur->item->name)); 1334 aimbs_put16(&fr->data, cur->item->gid); 1335 aimbs_put16(&fr->data, cur->item->bid); 1336 aimbs_put16(&fr->data, cur->item->type); 1337 aimbs_put16(&fr->data, cur->item->data ? aim_tlvlist_size(&cur->item->data) : 0); 1338 if (cur->item->data) 1339 aim_tlvlist_write(&fr->data, &cur->item->data); 1340 } 1341 1342 aim_tx_enqueue(sess, fr); 1343 1344 return 0; 1310 1345 } 1311 1346 … … 1317 1352 static int parseadd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1318 1353 { 1319 int ret = 0;1320 aim_rxcallback_t userfunc;1321 char *name;1322 fu16_t len, gid, bid, type;1323 aim_tlvlist_t *data;1324 1325 while (aim_bstream_empty(bs)) {1326 if ((len = aimbs_get16(bs)))1327 name = aimbs_getstr(bs, len);1328 else1329 name = NULL;1330 gid = aimbs_get16(bs);1331 bid = aimbs_get16(bs);1332 type = aimbs_get16(bs);1333 if ((len = aimbs_get16(bs)))1334 data = aim_readtlvchain_len(bs, len);1335 else1336 data = NULL;1337 1338 aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data);1339 aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);1340 free(name);1341 aim_freetlvchain(&data);1342 1343 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1344 ret = userfunc(sess, rx);1345 1346 free(name);1347 }1348 1349 return ret;1354 int ret = 0; 1355 aim_rxcallback_t userfunc; 1356 char *name; 1357 fu16_t len, gid, bid, type; 1358 aim_tlvlist_t *data; 1359 1360 while (aim_bstream_empty(bs)) { 1361 if ((len = aimbs_get16(bs))) 1362 name = aimbs_getstr(bs, len); 1363 else 1364 name = NULL; 1365 gid = aimbs_get16(bs); 1366 bid = aimbs_get16(bs); 1367 type = aimbs_get16(bs); 1368 if ((len = aimbs_get16(bs))) 1369 data = aim_tlvlist_readlen(bs, len); 1370 else 1371 data = NULL; 1372 1373 aim_ssi_itemlist_add(&sess->ssi.local, name, gid, bid, type, data); 1374 aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data); 1375 free(name); 1376 aim_tlvlist_free(&data); 1377 1378 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1379 ret = userfunc(sess, rx); 1380 1381 free(name); 1382 } 1383 1384 return ret; 1350 1385 } 1351 1386 … … 1357 1392 static int parsemod(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1358 1393 { 1359 int ret = 0;1360 aim_rxcallback_t userfunc;1361 char *name;1362 fu16_t len, gid, bid, type;1363 aim_tlvlist_t *data;1364 struct aim_ssi_item *item;1365 1366 while (aim_bstream_empty(bs)) {1367 if ((len = aimbs_get16(bs)))1368 name = aimbs_getstr(bs, len);1369 else1370 name = NULL;1371 gid = aimbs_get16(bs);1372 bid = aimbs_get16(bs);1373 type = aimbs_get16(bs);1374 if ((len = aimbs_get16(bs)))1375 data = aim_readtlvchain_len(bs, len);1376 else1377 data = NULL;1378 1379 /* Replace the 2 local items with the given one */1380 if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) {1381 item->type = type;1382 free(item->name);1383 if (name) {1384 item->name = (char *)malloc((strlen(name)+1)*sizeof(char));1385 strcpy(item->name, name);1386 } else1387 item->name = NULL;1388 aim_freetlvchain(&item->data);1389 item->data = aim_tlvlist_copy(data);1390 }1391 1392 if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) {1393 item->type = type;1394 free(item->name);1395 if (name) {1396 item->name = (char *)malloc((strlen(name)+1)*sizeof(char));1397 strcpy(item->name, name);1398 } else1399 item->name = NULL;1400 aim_freetlvchain(&item->data);1401 item->data = aim_tlvlist_copy(data);1402 }1403 1404 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1405 ret = userfunc(sess, rx);1406 1407 free(name);1408 aim_freetlvchain(&data);1409 }1410 1411 return ret;1394 int ret = 0; 1395 aim_rxcallback_t userfunc; 1396 char *name; 1397 fu16_t len, gid, bid, type; 1398 aim_tlvlist_t *data; 1399 struct aim_ssi_item *item; 1400 1401 while (aim_bstream_empty(bs)) { 1402 if ((len = aimbs_get16(bs))) 1403 name = aimbs_getstr(bs, len); 1404 else 1405 name = NULL; 1406 gid = aimbs_get16(bs); 1407 bid = aimbs_get16(bs); 1408 type = aimbs_get16(bs); 1409 if ((len = aimbs_get16(bs))) 1410 data = aim_tlvlist_readlen(bs, len); 1411 else 1412 data = NULL; 1413 1414 /* Replace the 2 local items with the given one */ 1415 if ((item = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) { 1416 item->type = type; 1417 free(item->name); 1418 if (name) { 1419 item->name = (char *)malloc((strlen(name)+1)*sizeof(char)); 1420 strcpy(item->name, name); 1421 } else 1422 item->name = NULL; 1423 aim_tlvlist_free(&item->data); 1424 item->data = aim_tlvlist_copy(data); 1425 } 1426 1427 if ((item = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) { 1428 item->type = type; 1429 free(item->name); 1430 if (name) { 1431 item->name = (char *)malloc((strlen(name)+1)*sizeof(char)); 1432 strcpy(item->name, name); 1433 } else 1434 item->name = NULL; 1435 aim_tlvlist_free(&item->data); 1436 item->data = aim_tlvlist_copy(data); 1437 } 1438 1439 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1440 ret = userfunc(sess, rx); 1441 1442 free(name); 1443 aim_tlvlist_free(&data); 1444 } 1445 1446 return ret; 1412 1447 } 1413 1448 … … 1419 1454 static int parsedel(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1420 1455 { 1421 int ret = 0;1422 aim_rxcallback_t userfunc;1423 fu16_t gid, bid;1424 struct aim_ssi_item *del;1425 1426 while (aim_bstream_empty(bs)) {1427 aim_bstream_advance(bs, aimbs_get16(bs));1428 gid = aimbs_get16(bs);1429 bid = aimbs_get16(bs);1430 aimbs_get16(bs);1431 aim_bstream_advance(bs, aimbs_get16(bs));1432 1433 if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid)))1434 aim_ssi_itemlist_del(&sess->ssi.local, del);1435 if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid)))1436 aim_ssi_itemlist_del(&sess->ssi.official, del);1437 1438 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1439 ret = userfunc(sess, rx);1440 }1441 1442 return ret;1456 int ret = 0; 1457 aim_rxcallback_t userfunc; 1458 fu16_t gid, bid; 1459 struct aim_ssi_item *del; 1460 1461 while (aim_bstream_empty(bs)) { 1462 aim_bstream_advance(bs, aimbs_get16(bs)); 1463 gid = aimbs_get16(bs); 1464 bid = aimbs_get16(bs); 1465 aimbs_get16(bs); 1466 aim_bstream_advance(bs, aimbs_get16(bs)); 1467 1468 if ((del = aim_ssi_itemlist_find(sess->ssi.local, gid, bid))) 1469 aim_ssi_itemlist_del(&sess->ssi.local, del); 1470 if ((del = aim_ssi_itemlist_find(sess->ssi.official, gid, bid))) 1471 aim_ssi_itemlist_del(&sess->ssi.official, del); 1472 1473 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1474 ret = userfunc(sess, rx); 1475 } 1476 1477 return ret; 1443 1478 } 1444 1479 … … 1451 1486 static int parseack(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1452 1487 { 1453 int ret = 0; 1454 aim_rxcallback_t userfunc; 1455 struct aim_ssi_tmp *cur, *del; 1456 1457 owl_function_debugmsg("Handling SNAC SSI ACK"); 1458 1459 /* Read in the success/failure flags from the ack SNAC */ 1460 cur = sess->ssi.pending; 1461 while (cur && (aim_bstream_empty(bs)>0)) { 1462 cur->ack = aimbs_get16(bs); 1463 cur = cur->next; 1464 } 1465 1466 /* 1467 * If outcome is 0, then add the item to the item list, or replace the other item, 1468 * or remove the old item. If outcome is non-zero, then remove the item from the 1469 * local list, or unmodify it, or add it. 1470 */ 1471 for (cur=sess->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) { 1472 owl_function_debugmsg("parseack: processing a change"); 1473 if (cur->item) { 1474 if (cur->ack) { 1475 /* Our action was unsuccessful, so change the local list back to how it was */ 1476 if (cur->action == AIM_CB_SSI_ADD) { 1477 owl_function_debugmsg("parseack: unsuccesful add, reverting"); 1478 /* Remove the item from the local list */ 1479 /* Make sure cur->item is still valid memory */ 1480 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1481 if (cur->item->name) { 1482 cur->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char)); 1483 strcpy(cur->name, cur->item->name); 1484 } 1485 aim_ssi_itemlist_del(&sess->ssi.local, cur->item); 1486 } 1487 cur->item = NULL; 1488 1489 } else if (cur->action == AIM_CB_SSI_MOD) { 1490 /* Replace the local item with the item from the official list */ 1491 owl_function_debugmsg("parseack: unsuccesful modify, reverting"); 1492 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1493 struct aim_ssi_item *cur1; 1494 if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) { 1495 free(cur->item->name); 1496 if (cur1->name) { 1497 cur->item->name = (char *)malloc((strlen(cur1->name)+1)*sizeof(char)); 1498 strcpy(cur->item->name, cur1->name); 1499 } else 1500 cur->item->name = NULL; 1501 aim_freetlvchain(&cur->item->data); 1502 cur->item->data = aim_tlvlist_copy(cur1->data); 1503 } 1504 } else 1505 cur->item = NULL; 1506 1507 } else if (cur->action == AIM_CB_SSI_DEL) { 1508 /* Add the item back into the local list */ 1509 owl_function_debugmsg("parseack: unsuccesful delete, reverting"); 1510 if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) { 1511 aim_ssi_itemlist_add(&sess->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); 1512 } else 1513 cur->item = NULL; 1514 } 1515 1516 } else { 1517 /* Do the exact opposite */ 1518 if (cur->action == AIM_CB_SSI_ADD) { 1519 /* Add the local item to the official list */ 1520 owl_function_debugmsg("parseack: succesful add"); 1521 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1522 aim_ssi_itemlist_add(&sess->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); 1523 } else 1524 cur->item = NULL; 1525 1526 } else if (cur->action == AIM_CB_SSI_MOD) { 1527 /* Replace the official item with the item from the local list */ 1528 owl_function_debugmsg("parseack: succesful modify"); 1529 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1530 struct aim_ssi_item *cur1; 1531 if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) { 1532 free(cur1->name); 1533 if (cur->item->name) { 1534 cur1->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char)); 1535 strcpy(cur1->name, cur->item->name); 1536 } else 1537 cur1->name = NULL; 1538 aim_freetlvchain(&cur1->data); 1539 cur1->data = aim_tlvlist_copy(cur->item->data); 1540 } 1541 } else 1542 cur->item = NULL; 1543 1544 } else if (cur->action == AIM_CB_SSI_DEL) { 1545 /* Remove the item from the official list */ 1546 owl_function_debugmsg("parseack: succesful delete"); 1547 if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) 1548 aim_ssi_itemlist_del(&sess->ssi.official, cur->item); 1549 cur->item = NULL; 1550 } 1551 1552 } 1553 } /* End if (cur->item) */ 1554 } /* End for loop */ 1555 1556 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1557 ret = userfunc(sess, rx, sess->ssi.pending); 1558 1559 /* Free all aim_ssi_tmp's with an outcome */ 1560 cur = sess->ssi.pending; 1561 while (cur && (cur->ack != 0xffff)) { 1562 del = cur; 1563 cur = cur->next; 1564 free(del->name); 1565 free(del); 1566 } 1567 sess->ssi.pending = cur; 1568 1569 /* If we're not waiting for any more acks, then send more SNACs */ 1570 1571 if (!sess->ssi.pending) { 1572 sess->ssi.pending = NULL; 1573 sess->ssi.waiting_for_ack = 0; 1574 owl_function_debugmsg("parseack: Clearing SSI waiting_for_ack"); 1575 aim_ssi_sync(sess); 1576 } 1577 1578 owl_function_debugmsg("parseack: returning with %i", ret); 1579 1580 return ret; 1488 int ret = 0; 1489 aim_rxcallback_t userfunc; 1490 struct aim_ssi_tmp *cur, *del; 1491 1492 /* Read in the success/failure flags from the ack SNAC */ 1493 cur = sess->ssi.pending; 1494 while (cur && (aim_bstream_empty(bs)>0)) { 1495 cur->ack = aimbs_get16(bs); 1496 cur = cur->next; 1497 } 1498 1499 /* 1500 * If outcome is 0, then add the item to the item list, or replace the other item, 1501 * or remove the old item. If outcome is non-zero, then remove the item from the 1502 * local list, or unmodify it, or add it. 1503 */ 1504 for (cur=sess->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) { 1505 if (cur->item) { 1506 if (cur->ack) { 1507 /* Our action was unsuccessful, so change the local list back to how it was */ 1508 if (cur->action == AIM_CB_SSI_ADD) { 1509 /* Remove the item from the local list */ 1510 /* Make sure cur->item is still valid memory */ 1511 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1512 if (cur->item->name) { 1513 cur->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char)); 1514 strcpy(cur->name, cur->item->name); 1515 } 1516 aim_ssi_itemlist_del(&sess->ssi.local, cur->item); 1517 } 1518 cur->item = NULL; 1519 1520 } else if (cur->action == AIM_CB_SSI_MOD) { 1521 /* Replace the local item with the item from the official list */ 1522 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1523 struct aim_ssi_item *cur1; 1524 if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) { 1525 free(cur->item->name); 1526 if (cur1->name) { 1527 cur->item->name = (char *)malloc((strlen(cur1->name)+1)*sizeof(char)); 1528 strcpy(cur->item->name, cur1->name); 1529 } else 1530 cur->item->name = NULL; 1531 aim_tlvlist_free(&cur->item->data); 1532 cur->item->data = aim_tlvlist_copy(cur1->data); 1533 } 1534 } else 1535 cur->item = NULL; 1536 1537 } else if (cur->action == AIM_CB_SSI_DEL) { 1538 /* Add the item back into the local list */ 1539 if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) { 1540 aim_ssi_itemlist_add(&sess->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); 1541 } else 1542 cur->item = NULL; 1543 } 1544 1545 } else { 1546 /* Do the exact opposite */ 1547 if (cur->action == AIM_CB_SSI_ADD) { 1548 /* Add the local item to the official list */ 1549 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1550 aim_ssi_itemlist_add(&sess->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data); 1551 } else 1552 cur->item = NULL; 1553 1554 } else if (cur->action == AIM_CB_SSI_MOD) { 1555 /* Replace the official item with the item from the local list */ 1556 if (aim_ssi_itemlist_valid(sess->ssi.local, cur->item)) { 1557 struct aim_ssi_item *cur1; 1558 if ((cur1 = aim_ssi_itemlist_find(sess->ssi.official, cur->item->gid, cur->item->bid))) { 1559 free(cur1->name); 1560 if (cur->item->name) { 1561 cur1->name = (char *)malloc((strlen(cur->item->name)+1)*sizeof(char)); 1562 strcpy(cur1->name, cur->item->name); 1563 } else 1564 cur1->name = NULL; 1565 aim_tlvlist_free(&cur1->data); 1566 cur1->data = aim_tlvlist_copy(cur->item->data); 1567 } 1568 } else 1569 cur->item = NULL; 1570 1571 } else if (cur->action == AIM_CB_SSI_DEL) { 1572 /* Remove the item from the official list */ 1573 if (aim_ssi_itemlist_valid(sess->ssi.official, cur->item)) 1574 aim_ssi_itemlist_del(&sess->ssi.official, cur->item); 1575 cur->item = NULL; 1576 } 1577 1578 } 1579 } /* End if (cur->item) */ 1580 } /* End for loop */ 1581 1582 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1583 ret = userfunc(sess, rx, sess->ssi.pending); 1584 1585 /* Free all aim_ssi_tmp's with an outcome */ 1586 cur = sess->ssi.pending; 1587 while (cur && (cur->ack != 0xffff)) { 1588 del = cur; 1589 cur = cur->next; 1590 free(del->name); 1591 free(del); 1592 } 1593 sess->ssi.pending = cur; 1594 1595 /* If we're not waiting for any more acks, then send more SNACs */ 1596 if (!sess->ssi.pending) { 1597 sess->ssi.pending = NULL; 1598 sess->ssi.waiting_for_ack = 0; 1599 aim_ssi_sync(sess); 1600 } 1601 1602 return ret; 1581 1603 } 1582 1604 … … 1590 1612 static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1591 1613 { 1592 int ret = 0;1593 aim_rxcallback_t userfunc;1594 1595 sess->ssi.received_data = 1;1596 1597 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1598 ret = userfunc(sess, rx);1599 1600 return ret;1614 int ret = 0; 1615 aim_rxcallback_t userfunc; 1616 1617 sess->ssi.received_data = 1; 1618 1619 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1620 ret = userfunc(sess, rx); 1621 1622 return ret; 1601 1623 } 1602 1624 … … 1609 1631 faim_export int aim_ssi_modbegin(aim_session_t *sess) 1610 1632 { 1611 aim_conn_t *conn;1612 1613 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))1614 return -EINVAL;1615 1616 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);1633 aim_conn_t *conn; 1634 1635 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) 1636 return -EINVAL; 1637 1638 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART); 1617 1639 } 1618 1640 … … 1625 1647 faim_export int aim_ssi_modend(aim_session_t *sess) 1626 1648 { 1627 aim_conn_t *conn; 1628 1629 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) return -EINVAL; 1630 1631 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP); 1649 aim_conn_t *conn; 1650 1651 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI))) 1652 return -EINVAL; 1653 1654 return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP); 1632 1655 } 1633 1656 … … 1640 1663 faim_export int aim_ssi_sendauth(aim_session_t *sess, char *sn, char *msg) 1641 1664 { 1642 aim_conn_t *conn;1643 aim_frame_t *fr;1644 aim_snacid_t snacid;1645 1646 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)1647 return -EINVAL;1648 1649 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))1650 return -ENOMEM;1651 1652 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, NULL, 0);1653 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, snacid);1654 1655 /* Screen name */1656 aimbs_put8(&fr->data, strlen(sn));1657 aimbs_putraw(&fr->data, sn, strlen(sn));1658 1659 /* Message (null terminated) */1660 aimbs_put16(&fr->data, msg ? strlen(msg) : 0);1661 if (msg) {1662 aimbs_putraw(&fr->data, msg, strlen(msg));1663 aimbs_put8(&fr->data, 0x00);1664 }1665 1666 /* Unknown */1667 aimbs_put16(&fr->data, 0x0000);1668 1669 aim_tx_enqueue(sess, fr);1670 1671 return 0;1665 aim_conn_t *conn; 1666 aim_frame_t *fr; 1667 aim_snacid_t snacid; 1668 1669 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn) 1670 return -EINVAL; 1671 1672 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2))) 1673 return -ENOMEM; 1674 1675 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, NULL, 0); 1676 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, snacid); 1677 1678 /* Screen name */ 1679 aimbs_put8(&fr->data, strlen(sn)); 1680 aimbs_putraw(&fr->data, sn, strlen(sn)); 1681 1682 /* Message (null terminated) */ 1683 aimbs_put16(&fr->data, msg ? strlen(msg) : 0); 1684 if (msg) { 1685 aimbs_putraw(&fr->data, msg, strlen(msg)); 1686 aimbs_put8(&fr->data, 0x00); 1687 } 1688 1689 /* Unknown */ 1690 aimbs_put16(&fr->data, 0x0000); 1691 1692 aim_tx_enqueue(sess, fr); 1693 1694 return 0; 1672 1695 } 1673 1696 … … 1677 1700 static int receiveauthgrant(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1678 1701 { 1679 int ret = 0;1680 aim_rxcallback_t userfunc;1681 fu16_t tmp;1682 char *sn, *msg;1683 1684 /* Read screen name */1685 if ((tmp = aimbs_get8(bs)))1686 sn = aimbs_getstr(bs, tmp);1687 else1688 sn = NULL;1689 1690 /* Read message (null terminated) */1691 if ((tmp = aimbs_get16(bs)))1692 msg = aimbs_getstr(bs, tmp);1693 else1694 msg = NULL;1695 1696 /* Unknown */1697 tmp = aimbs_get16(bs);1698 1699 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1700 ret = userfunc(sess, rx, sn, msg);1701 1702 free(sn);1703 free(msg);1704 1705 return ret;1702 int ret = 0; 1703 aim_rxcallback_t userfunc; 1704 fu16_t tmp; 1705 char *sn, *msg; 1706 1707 /* Read screen name */ 1708 if ((tmp = aimbs_get8(bs))) 1709 sn = aimbs_getstr(bs, tmp); 1710 else 1711 sn = NULL; 1712 1713 /* Read message (null terminated) */ 1714 if ((tmp = aimbs_get16(bs))) 1715 msg = aimbs_getstr(bs, tmp); 1716 else 1717 msg = NULL; 1718 1719 /* Unknown */ 1720 tmp = aimbs_get16(bs); 1721 1722 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1723 ret = userfunc(sess, rx, sn, msg); 1724 1725 free(sn); 1726 free(msg); 1727 1728 return ret; 1706 1729 } 1707 1730 … … 1715 1738 faim_export int aim_ssi_sendauthrequest(aim_session_t *sess, char *sn, char *msg) 1716 1739 { 1717 aim_conn_t *conn;1718 aim_frame_t *fr;1719 aim_snacid_t snacid;1720 1721 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)1722 return -EINVAL;1723 1724 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))1725 return -ENOMEM;1726 1727 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0);1728 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid);1729 1730 /* Screen name */1731 aimbs_put8(&fr->data, strlen(sn));1732 aimbs_putraw(&fr->data, sn, strlen(sn));1733 1734 /* Message (null terminated) */1735 aimbs_put16(&fr->data, msg ? strlen(msg) : 0);1736 if (msg) {1737 aimbs_putraw(&fr->data, msg, strlen(msg));1738 aimbs_put8(&fr->data, 0x00);1739 }1740 1741 /* Unknown */1742 aimbs_put16(&fr->data, 0x0000);1743 1744 aim_tx_enqueue(sess, fr);1745 1746 return 0;1740 aim_conn_t *conn; 1741 aim_frame_t *fr; 1742 aim_snacid_t snacid; 1743 1744 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn) 1745 return -EINVAL; 1746 1747 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2))) 1748 return -ENOMEM; 1749 1750 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0); 1751 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid); 1752 1753 /* Screen name */ 1754 aimbs_put8(&fr->data, strlen(sn)); 1755 aimbs_putraw(&fr->data, sn, strlen(sn)); 1756 1757 /* Message (null terminated) */ 1758 aimbs_put16(&fr->data, msg ? strlen(msg) : 0); 1759 if (msg) { 1760 aimbs_putraw(&fr->data, msg, strlen(msg)); 1761 aimbs_put8(&fr->data, 0x00); 1762 } 1763 1764 /* Unknown */ 1765 aimbs_put16(&fr->data, 0x0000); 1766 1767 aim_tx_enqueue(sess, fr); 1768 1769 return 0; 1747 1770 } 1748 1771 … … 1752 1775 static int receiveauthrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1753 1776 { 1754 int ret = 0;1755 aim_rxcallback_t userfunc;1756 fu16_t tmp;1757 char *sn, *msg;1758 1759 /* Read screen name */1760 if ((tmp = aimbs_get8(bs)))1761 sn = aimbs_getstr(bs, tmp);1762 else1763 sn = NULL;1764 1765 /* Read message (null terminated) */1766 if ((tmp = aimbs_get16(bs)))1767 msg = aimbs_getstr(bs, tmp);1768 else1769 msg = NULL;1770 1771 /* Unknown */1772 tmp = aimbs_get16(bs);1773 1774 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1775 ret = userfunc(sess, rx, sn, msg);1776 1777 free(sn);1778 free(msg);1779 1780 return ret;1777 int ret = 0; 1778 aim_rxcallback_t userfunc; 1779 fu16_t tmp; 1780 char *sn, *msg; 1781 1782 /* Read screen name */ 1783 if ((tmp = aimbs_get8(bs))) 1784 sn = aimbs_getstr(bs, tmp); 1785 else 1786 sn = NULL; 1787 1788 /* Read message (null terminated) */ 1789 if ((tmp = aimbs_get16(bs))) 1790 msg = aimbs_getstr(bs, tmp); 1791 else 1792 msg = NULL; 1793 1794 /* Unknown */ 1795 tmp = aimbs_get16(bs); 1796 1797 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1798 ret = userfunc(sess, rx, sn, msg); 1799 1800 free(sn); 1801 free(msg); 1802 1803 return ret; 1781 1804 } 1782 1805 … … 1793 1816 faim_export int aim_ssi_sendauthreply(aim_session_t *sess, char *sn, fu8_t reply, char *msg) 1794 1817 { 1795 aim_conn_t *conn;1796 aim_frame_t *fr;1797 aim_snacid_t snacid;1798 1799 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)1800 return -EINVAL;1801 1802 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2)))1803 return -ENOMEM;1804 1805 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0);1806 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid);1807 1808 /* Screen name */1809 aimbs_put8(&fr->data, strlen(sn));1810 aimbs_putraw(&fr->data, sn, strlen(sn));1811 1812 /* Grant or deny */1813 aimbs_put8(&fr->data, reply);1814 1815 /* Message (null terminated) */1816 aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0);1817 if (msg) {1818 aimbs_putraw(&fr->data, msg, strlen(msg));1819 aimbs_put8(&fr->data, 0x00);1820 }1821 1822 /* Unknown */1823 aimbs_put16(&fr->data, 0x0000);1824 1825 aim_tx_enqueue(sess, fr);1826 1827 return 0;1818 aim_conn_t *conn; 1819 aim_frame_t *fr; 1820 aim_snacid_t snacid; 1821 1822 if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn) 1823 return -EINVAL; 1824 1825 if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2))) 1826 return -ENOMEM; 1827 1828 snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0); 1829 aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid); 1830 1831 /* Screen name */ 1832 aimbs_put8(&fr->data, strlen(sn)); 1833 aimbs_putraw(&fr->data, sn, strlen(sn)); 1834 1835 /* Grant or deny */ 1836 aimbs_put8(&fr->data, reply); 1837 1838 /* Message (null terminated) */ 1839 aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0); 1840 if (msg) { 1841 aimbs_putraw(&fr->data, msg, strlen(msg)); 1842 aimbs_put8(&fr->data, 0x00); 1843 } 1844 1845 /* Unknown */ 1846 aimbs_put16(&fr->data, 0x0000); 1847 1848 aim_tx_enqueue(sess, fr); 1849 1850 return 0; 1828 1851 } 1829 1852 … … 1835 1858 static int receiveauthreply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1836 1859 { 1837 int ret = 0;1838 aim_rxcallback_t userfunc;1839 fu16_t tmp;1840 fu8_t reply;1841 char *sn, *msg;1842 1843 /* Read screen name */1844 if ((tmp = aimbs_get8(bs)))1845 sn = aimbs_getstr(bs, tmp);1846 else1847 sn = NULL;1848 1849 /* Read reply */1850 reply = aimbs_get8(bs);1851 1852 /* Read message (null terminated) */1853 if ((tmp = aimbs_get16(bs)))1854 msg = aimbs_getstr(bs, tmp);1855 else1856 msg = NULL;1857 1858 /* Unknown */1859 tmp = aimbs_get16(bs);1860 1861 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))1862 ret = userfunc(sess, rx, sn, reply, msg);1863 1864 free(sn);1865 free(msg);1866 1867 return ret;1860 int ret = 0; 1861 aim_rxcallback_t userfunc; 1862 fu16_t tmp; 1863 fu8_t reply; 1864 char *sn, *msg; 1865 1866 /* Read screen name */ 1867 if ((tmp = aimbs_get8(bs))) 1868 sn = aimbs_getstr(bs, tmp); 1869 else 1870 sn = NULL; 1871 1872 /* Read reply */ 1873 reply = aimbs_get8(bs); 1874 1875 /* Read message (null terminated) */ 1876 if ((tmp = aimbs_get16(bs))) 1877 msg = aimbs_getstr(bs, tmp); 1878 else 1879 msg = NULL; 1880 1881 /* Unknown */ 1882 tmp = aimbs_get16(bs); 1883 1884 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1885 ret = userfunc(sess, rx, sn, reply, msg); 1886 1887 free(sn); 1888 free(msg); 1889 1890 return ret; 1868 1891 } 1869 1892 … … 1873 1896 static int receiveadded(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1874 1897 { 1875 int ret = 0; 1876 aim_rxcallback_t userfunc; 1877 fu16_t tmp; 1878 char *sn; 1879 1880 /* Read screen name */ 1881 if ((tmp = aimbs_get8(bs))) { 1882 sn = aimbs_getstr(bs, tmp); 1883 } else { 1884 sn = NULL; 1885 } 1886 1887 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) { 1888 ret = userfunc(sess, rx, sn); 1889 } 1890 1891 free(sn); 1892 return(ret); 1898 int ret = 0; 1899 aim_rxcallback_t userfunc; 1900 fu16_t tmp; 1901 char *sn; 1902 1903 /* Read screen name */ 1904 if ((tmp = aimbs_get8(bs))) 1905 sn = aimbs_getstr(bs, tmp); 1906 else 1907 sn = NULL; 1908 1909 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) 1910 ret = userfunc(sess, rx, sn); 1911 1912 free(sn); 1913 1914 return ret; 1893 1915 } 1894 1916 1895 1917 static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs) 1896 1918 { 1897 if (snac->subtype == AIM_CB_SSI_RIGHTSINFO) { 1898 return parserights(sess, mod, rx, snac, bs); 1899 } else if (snac->subtype == AIM_CB_SSI_LIST) { 1900 return parsedata(sess, mod, rx, snac, bs); 1901 } else if (snac->subtype == AIM_CB_SSI_ADD) { 1902 return parseadd(sess, mod, rx, snac, bs); 1903 } else if (snac->subtype == AIM_CB_SSI_MOD) { 1904 return parsemod(sess, mod, rx, snac, bs); 1905 } else if (snac->subtype == AIM_CB_SSI_DEL) { 1906 return parsedel(sess, mod, rx, snac, bs); 1907 } else if (snac->subtype == AIM_CB_SSI_SRVACK) { 1908 return parseack(sess, mod, rx, snac, bs); 1909 } else if (snac->subtype == AIM_CB_SSI_NOLIST) { 1910 return parsedataunchanged(sess, mod, rx, snac, bs); 1911 } else if (snac->subtype == AIM_CB_SSI_RECVAUTH) { 1912 return receiveauthgrant(sess, mod, rx, snac, bs); 1913 } else if (snac->subtype == AIM_CB_SSI_RECVAUTHREQ) { 1914 return receiveauthrequest(sess, mod, rx, snac, bs); 1915 } else if (snac->subtype == AIM_CB_SSI_RECVAUTHREP) { 1916 return receiveauthreply(sess, mod, rx, snac, bs); 1917 } else if (snac->subtype == AIM_CB_SSI_ADDED) { 1918 return receiveadded(sess, mod, rx, snac, bs); 1919 } 1920 return(0); 1919 1920 if (snac->subtype == AIM_CB_SSI_RIGHTSINFO) 1921 return parserights(sess, mod, rx, snac, bs); 1922 else if (snac->subtype == AIM_CB_SSI_LIST) 1923 return parsedata(sess, mod, rx, snac, bs); 1924 else if (snac->subtype == AIM_CB_SSI_ADD) 1925 return parseadd(sess, mod, rx, snac, bs); 1926 else if (snac->subtype == AIM_CB_SSI_MOD) 1927 return parsemod(sess, mod, rx, snac, bs); 1928 else if (snac->subtype == AIM_CB_SSI_DEL) 1929 return parsedel(sess, mod, rx, snac, bs); 1930 else if (snac->subtype == AIM_CB_SSI_SRVACK) 1931 return parseack(sess, mod, rx, snac, bs); 1932 else if (snac->subtype == AIM_CB_SSI_NOLIST) 1933 return parsedataunchanged(sess, mod, rx, snac, bs); 1934 else if (snac->subtype == AIM_CB_SSI_RECVAUTH) 1935 return receiveauthgrant(sess, mod, rx, snac, bs); 1936 else if (snac->subtype == AIM_CB_SSI_RECVAUTHREQ) 1937 return receiveauthrequest(sess, mod, rx, snac, bs); 1938 else if (snac->subtype == AIM_CB_SSI_RECVAUTHREP) 1939 return receiveauthreply(sess, mod, rx, snac, bs); 1940 else if (snac->subtype == AIM_CB_SSI_ADDED) 1941 return receiveadded(sess, mod, rx, snac, bs); 1942 1943 return 0; 1921 1944 } 1922 1945 1923 1946 static void ssi_shutdown(aim_session_t *sess, aim_module_t *mod) 1924 1947 { 1925 aim_ssi_freelist(sess); 1926 return; 1948 aim_ssi_freelist(sess); 1927 1949 } 1928 1950 1929 1951 faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod) 1930 1952 { 1931 1932 mod->family = AIM_CB_FAM_SSI;1933 mod->version = 0x0004;1934 mod->toolid = 0x0110;1935 mod->toolversion = 0x0629;1936 mod->flags = 0;1937 strncpy(mod->name, "ssi", sizeof(mod->name));1938 mod->snachandler = snachandler;1939 mod->shutdown = ssi_shutdown;1940 1941 return 0;1942 } 1953 1954 mod->family = AIM_CB_FAM_SSI; 1955 mod->version = 0x0004; 1956 mod->toolid = 0x0110; 1957 mod->toolversion = 0x0629; 1958 mod->flags = 0; 1959 strncpy(mod->name, "ssi", sizeof(mod->name)); 1960 mod->snachandler = snachandler; 1961 mod->shutdown = ssi_shutdown; 1962 1963 return 0; 1964 }
Note: See TracChangeset
for help on using the changeset viewer.
