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