Changeset cf02dd6 for libfaim/ssi.c
- Timestamp:
- Dec 10, 2003, 3:20:45 PM (21 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
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 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 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 246 247 248 249 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 263 264 265 266 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 282 283 284 285 286 287 288 struct aim_ssi_item *curg;289 for (curg=list; curg; curg=curg->next)290 291 292 293 294 295 296 297 return cur;298 299 300 301 302 303 304 return cur;305 306 307 308 309 310 311 312 313 314 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 327 328 329 330 331 332 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 345 346 347 348 349 350 351 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 568 569 570 571 572 573 574 575 aim_freetlvchain(&del->data);576 577 578 579 580 581 582 583 584 aim_freetlvchain(&del->data);585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 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 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 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 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 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 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 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 896 897 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 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 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 1094 1095 1096 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 1107 1108 1109 1110 1111 1112 1113 1114 tlvlist = aim_readtlvchain(bs);1115 1116 1117 if (!(tlv = aim_gettlv(tlvlist, 0x0004, 1))) {1118 aim_freetlvchain(&tlvlist);1119 1120 1121 1122 1123 1124 1125 aim_freetlvchain(&tlvlist);1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 aim_freetlvchain(&tlvlist);1136 1137 1138 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 1149 1150 1151 1152 1153 1154 1155 1156 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 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 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 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 data = aim_readtlvchain_len(bs, aimbs_get16(bs));1220 1221 1222 aim_freetlvchain(&data);1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 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 1255 1256 1257 1258 1259 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 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 data = aim_readtlvchain_len(bs, len);1335 1336 1337 1338 1339 1340 1341 aim_freetlvchain(&data);1342 1343 1344 1345 1346 1347 1348 1349 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 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 data = aim_readtlvchain_len(bs, len);1376 1377 1378 1379 1380 1381 1382 1383 1384 item->name = (char *)malloc((strlen(name)+1)*sizeof(char));1385 strcpy(item->name, name);1386 1387 item->name = NULL;1388 aim_freetlvchain(&item->data);1389 1390 1391 1392 1393 1394 1395 1396 item->name = (char *)malloc((strlen(name)+1)*sizeof(char));1397 strcpy(item->name, name);1398 1399 item->name = NULL;1400 aim_freetlvchain(&item->data);1401 1402 1403 1404 1405 1406 1407 1408 aim_freetlvchain(&data);1409 1410 1411 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 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 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 1593 1594 1595 1596 1597 1598 1599 1600 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 1612 1613 1614 1615 1616 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 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 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 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 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 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 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 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 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 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 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 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 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 1933 1934 1935 1936 1937 1938 1939 1940 1941 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.