Changeset 2ecac24


Ignore:
Timestamp:
Oct 15, 2003, 2:37:23 PM (21 years ago)
Author:
James M. Kretchmar <kretch@mit.edu>
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
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfaim/ssi.c

    re374dee r2ecac24  
    3939static struct aim_ssi_item *aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
    4040{
    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;
     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;
    8989}
    9090
     
    103103static 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)
    104104{
    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);
    167166}
    168167
     
    176175static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
    177176{
    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);
    197194}
    198195
     
    206203static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2)
    207204{
    208         if (!cur1 || !cur2)
    209                 return 1;
    210 
    211         if (cur1->data && !cur2->data)
    212                 return 2;
    213 
    214         if (!cur1->data && cur2->data)
    215                 return 3;
    216 
    217         if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))
    218                         return 4;
    219 
    220         if (cur1->name && !cur2->name)
    221                 return 5;
    222 
    223         if (!cur1->name && cur2->name)
    224                 return 6;
    225 
    226         if (cur1->name && cur2->name && aim_sncmp(cur1->name, cur2->name))
    227                 return 7;
    228 
    229         if (cur1->gid != cur2->gid)
    230                 return 8;
    231 
    232         if (cur1->bid != cur2->bid)
    233                 return 9;
    234 
    235         if (cur1->type != cur2->type)
    236                 return 10;
    237 
    238         return 0;
     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;
    239236}
    240237
    241238faim_export int aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
    242239{
    243         struct aim_ssi_item *cur;
    244         for (cur=list; cur; cur=cur->next)
    245                 if (cur == item)
    246                         return 1;
    247         return 0;
     240  struct aim_ssi_item *cur;
     241  for (cur=list; cur; cur=cur->next)
     242    if (cur == item)
     243      return 1;
     244  return 0;
    248245}
    249246
     
    258255faim_export struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, fu16_t gid, fu16_t bid)
    259256{
    260         struct aim_ssi_item *cur;
    261         for (cur=list; cur; cur=cur->next)
    262                 if ((cur->gid == gid) && (cur->bid == bid))
    263                         return cur;
    264         return NULL;
     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;
    265262}
    266263
     
    277274faim_export struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *sn, fu16_t type)
    278275{
    279         struct aim_ssi_item *cur;
    280         if (!list)
    281                 return NULL;
    282 
    283         if (gn && sn) { /* For finding buddies in groups */
    284                 for (cur=list; cur; cur=cur->next)
    285                         if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
    286                                 struct aim_ssi_item *curg;
    287                                 for (curg=list; curg; curg=curg->next)
    288                                         if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(aim_sncmp(curg->name, gn)))
    289                                                 return cur;
    290                         }
    291 
    292         } else if (gn) { /* For finding groups */
    293                 for (cur=list; cur; cur=cur->next) {
    294                         if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(aim_sncmp(cur->name, gn))) {
    295                                 return cur;
    296                         }
    297                 }
    298 
    299         } else if (sn) { /* For finding permits, denies, and ignores */
    300                 for (cur=list; cur; cur=cur->next) {
    301                         if ((cur->type == type) && (cur->name) && !(aim_sncmp(cur->name, sn))) {
    302                                 return cur;
    303                         }
    304                 }
    305 
    306         /* For stuff without names--permit deny setting, visibility mask, etc. */
    307         } else for (cur=list; cur; cur=cur->next) {
    308                 if ((cur->type == type) && (!cur->name))
    309                         return cur;
    310         }
    311 
    312         return NULL;
     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;
    313310}
    314311
     
    322319faim_export struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *sn)
    323320{
    324         struct aim_ssi_item *cur;
    325         if (!list || !sn)
    326                 return NULL;
    327         for (cur=list; cur; cur=cur->next)
    328                 if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->name) && (!aim_sncmp(cur->name, sn)))
    329                         return cur;
    330         return NULL;
     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;
    331328}
    332329
     
    340337faim_export char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *sn)
    341338{
    342         struct aim_ssi_item *cur, *curg;
    343         if (!list || !sn)
    344                 return NULL;
    345         if (!(cur = aim_ssi_itemlist_exists(list, sn)))
    346                 return NULL;
    347         if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))
    348                 return NULL;
    349         return curg->name;
     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;
    350347}
    351348
     
    358355faim_export int aim_ssi_getpermdeny(struct aim_ssi_item *list)
    359356{
    360         struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
    361         if (cur) {
    362                 aim_tlvlist_t *tlvlist = cur->data;
    363                 if (tlvlist) {
    364                         aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00ca, 1);
    365                         if (tlv && tlv->value)
    366                                 return aimutil_get8(tlv->value);
    367                 }
    368         }
    369         return 0;
     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;
    370367}
    371368
     
    380377faim_export fu32_t aim_ssi_getpresence(struct aim_ssi_item *list)
    381378{
    382         struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
    383         if (cur) {
    384                 aim_tlvlist_t *tlvlist = cur->data;
    385                 if (tlvlist) {
    386                         aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x00c9, 1);
    387                         if (tlv && tlv->length)
    388                                 return aimutil_get32(tlv->value);
    389                 }
    390         }
    391         return 0xFFFFFFFF;
     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;
    392389}
    393390
     
    404401faim_export char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *sn)
    405402{
    406         struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
    407         if (cur) {
    408                 aim_tlvlist_t *tlvlist = cur->data;
    409                 if (tlvlist) {
    410                         aim_tlv_t *tlv = aim_gettlv(tlvlist, 0x0131, 1);
    411                         if (tlv && tlv->length) {
    412                                 char *alias = (char *)malloc((tlv->length+1)*sizeof(char));
    413                                 strncpy(alias, tlv->value, tlv->length);
    414                                 alias[tlv->length] = 0;
    415                                 return alias;
    416                         }
    417                 }
    418         }
    419         return NULL;
     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;
    420417}
    421418
     
    432429faim_export int aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *sn)
    433430{
    434         struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, sn, AIM_SSI_TYPE_BUDDY);
    435         if (cur) {
    436                 aim_tlvlist_t *tlvlist = cur->data;
    437                 if (tlvlist)
    438                         if (aim_gettlv(tlvlist, 0x0066, 1))
    439                                 return 1;
    440         }
    441         return 0;
     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;
    442439}
    443440
     
    451448static int aim_ssi_sync(aim_session_t *sess)
    452449{
    453         struct aim_ssi_item *cur1, *cur2;
    454         struct aim_ssi_tmp *cur, *new;
    455 
    456         if (!sess)
    457                 return -EINVAL;
    458 
    459         /* If we're waiting for an ack, we shouldn't do anything else */
    460         if (sess->ssi.waiting_for_ack)
    461                 return 0;
    462 
    463         /*
    464         * Compare the 2 lists and create an aim_ssi_tmp for each difference. 
    465         * We should only send either additions, modifications, or deletions
    466         * before waiting for an acknowledgement.  So first do deletions, then
    467         * additions, then modifications.  Also, both the official and the local
    468         * list should be in ascending numerical order for the group ID#s and the
    469         * buddy ID#s, which makes things more efficient.  I think.
    470         */
    471 
    472         /* Additions */
    473         if (!sess->ssi.pending) {
    474                 for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
    475                         if (!aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid)) {
    476                                 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
    477                                 new->action = AIM_CB_SSI_ADD;
    478                                 new->ack = 0xffff;
    479                                 new->name = NULL;
    480                                 new->item = cur1;
    481                                 new->next = NULL;
    482                                 if (sess->ssi.pending) {
    483                                         for (cur=sess->ssi.pending; cur->next; cur=cur->next);
    484                                         cur->next = new;
    485                                 } else
    486                                         sess->ssi.pending = new;
    487                         }
    488                 }
    489         }
    490 
    491         /* Deletions */
    492         if (!sess->ssi.pending) {
    493                 for (cur1=sess->ssi.official; cur1; cur1=cur1->next) {
    494                         if (!aim_ssi_itemlist_find(sess->ssi.local, cur1->gid, cur1->bid)) {
    495                                 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
    496                                 new->action = AIM_CB_SSI_DEL;
    497                                 new->ack = 0xffff;
    498                                 new->name = NULL;
    499                                 new->item = cur1;
    500                                 new->next = NULL;
    501                                 if (sess->ssi.pending) {
    502                                         for (cur=sess->ssi.pending; cur->next; cur=cur->next);
    503                                         cur->next = new;
    504                                 } else
    505                                         sess->ssi.pending = new;
    506                         }
    507                 }
    508         }
    509 
    510         /* Modifications */
    511         if (!sess->ssi.pending) {
    512                 for (cur1=sess->ssi.local; cur1; cur1=cur1->next) {
    513                         cur2 = aim_ssi_itemlist_find(sess->ssi.official, cur1->gid, cur1->bid);
    514                         if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
    515                                 new = (struct aim_ssi_tmp *)malloc(sizeof(struct aim_ssi_tmp));
    516                                 new->action = AIM_CB_SSI_MOD;
    517                                 new->ack = 0xffff;
    518                                 new->name = NULL;
    519                                 new->item = cur1;
    520                                 new->next = NULL;
    521                                 if (sess->ssi.pending) {
    522                                         for (cur=sess->ssi.pending; cur->next; cur=cur->next);
    523                                         cur->next = new;
    524                                 } else
    525                                         sess->ssi.pending = new;
    526                         }
    527                 }
    528         }
    529 
    530         /* We're out of stuff to do, so tell the AIM servers we're done and exit */
    531         if (!sess->ssi.pending) {
    532                 aim_ssi_modend(sess);
    533                 return 0;
    534         }
    535 
    536         /* Make sure we don't send anything else between now
    537         * and when we receive the ack for the following operation */
    538         sess->ssi.waiting_for_ack = 1;
    539 
    540         /* Now go mail off our data and wait 4 to 6 weeks */
    541         aim_ssi_addmoddel(sess);
    542 
    543         return 0;
     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;
    544541}
    545542
     
    554551static int aim_ssi_freelist(aim_session_t *sess)
    555552{
    556         struct aim_ssi_item *cur, *del;
    557         struct aim_ssi_tmp *curtmp, *deltmp;
    558 
    559         cur = sess->ssi.official;
    560         while (cur) {
    561                 del = cur;
    562                 cur = cur->next;
    563                 free(del->name);
    564                 aim_freetlvchain(&del->data);
    565                 free(del);
    566         }
    567 
    568         cur = sess->ssi.local;
    569         while (cur) {
    570                 del = cur;
    571                 cur = cur->next;
    572                 free(del->name);
    573                 aim_freetlvchain(&del->data);
    574                 free(del);
    575         }
    576 
    577         curtmp = sess->ssi.pending;
    578         while (curtmp) {
    579                 deltmp = curtmp;
    580                 curtmp = curtmp->next;
    581                 free(deltmp);
    582         }
    583 
    584         sess->ssi.numitems = 0;
    585         sess->ssi.official = NULL;
    586         sess->ssi.local = NULL;
    587         sess->ssi.pending = NULL;
    588         sess->ssi.timestamp = (time_t)0;
    589 
    590         return 0;
     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;
    591588}
    592589
     
    599596faim_export int aim_ssi_deletelist(aim_session_t *sess)
    600597{
    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;
    621617}
    622618
     
    632628faim_export int aim_ssi_cleanlist(aim_session_t *sess)
    633629{
    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;
    678673}
    679674
     
    691686faim_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)
    692687{
    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);
    734727}
    735728
     
    744737{
    745738
    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);
    756748}
    757749
     
    766758{
    767759
    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);
    778769}
    779770
     
    788779faim_export int aim_ssi_delbuddy(aim_session_t *sess, const char *name, const char *group)
    789780{
    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);
    822817}
    823818
     
    831826faim_export int aim_ssi_delpermit(aim_session_t *sess, const char *name)
    832827{
    833         struct aim_ssi_item *del;
    834 
    835         if (!sess)
    836                 return -EINVAL;
    837 
    838         /* Find the item */
    839         if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_PERMIT)))
    840                 return -EINVAL;
    841 
    842         /* Remove the item from the list */
    843         aim_ssi_itemlist_del(&sess->ssi.local, del);
    844 
    845         /* Sync our local list with the server list */
    846         aim_ssi_sync(sess);
    847 
    848         return 0;
     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;
    849844}
    850845
     
    858853faim_export int aim_ssi_deldeny(aim_session_t *sess, const char *name)
    859854{
    860         struct aim_ssi_item *del;
    861 
    862         if (!sess)
    863                 return -EINVAL;
    864 
    865         /* Find the item */
    866         if (!(del = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, name, AIM_SSI_TYPE_DENY)))
    867                 return -EINVAL;
    868 
    869         /* Remove the item from the list */
    870         aim_ssi_itemlist_del(&sess->ssi.local, del);
    871 
    872         /* Sync our local list with the server list */
    873         aim_ssi_sync(sess);
    874 
    875         return 0;
     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;
    876871}
    877872
     
    888883faim_export int aim_ssi_movebuddy(aim_session_t *sess, const char *oldgn, const char *newgn, const char *sn)
    889884{
    890         aim_ssi_addbuddy(sess, sn, newgn, aim_ssi_getalias(sess->ssi.local, oldgn, sn), NULL, NULL, aim_ssi_waitingforauth(sess->ssi.local, oldgn, sn));
    891         aim_ssi_delbuddy(sess, sn, oldgn);
    892         return 0;
     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;
    893888}
    894889
     
    904899faim_export int aim_ssi_aliasbuddy(aim_session_t *sess, const char *gn, const char *sn, const char *alias)
    905900{
    906         struct aim_ssi_item *tmp;
    907         aim_tlvlist_t *data = NULL;
    908 
    909         if (!sess || !gn || !sn)
    910                 return -EINVAL;
    911 
    912         if (!(tmp = aim_ssi_itemlist_finditem(sess->ssi.local, gn, sn, AIM_SSI_TYPE_BUDDY)))
    913                 return -EINVAL;
    914 
    915         if (alias && !strlen(alias))
    916                 alias = NULL;
    917 
    918         /* Need to add the x0131 TLV to the TLV chain */
    919         if (alias)
    920                 aim_addtlvtochain_raw(&data, 0x0131, strlen(alias), alias);
    921 
    922         aim_freetlvchain(&tmp->data);
    923         tmp->data = data;
    924 
    925         /* Sync our local list with the server list */
    926         aim_ssi_sync(sess);
    927 
    928         return 0;
     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;
    929924}
    930925
     
    939934faim_export int aim_ssi_rename_group(aim_session_t *sess, const char *oldgn, const char *newgn)
    940935{
    941         struct aim_ssi_item *group;
    942 
    943         if (!sess || !oldgn || !newgn)
    944                 return -EINVAL;
    945 
    946         if (!(group = aim_ssi_itemlist_finditem(sess->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
    947                 return -EINVAL;
    948 
    949         free(group->name);
    950         group->name = (char *)malloc((strlen(newgn)+1)*sizeof(char));
    951         strcpy(group->name, newgn);
    952 
    953         /* Sync our local list with the server list */
    954         aim_ssi_sync(sess);
    955 
    956         return 0;
     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;
    957952}
    958953
     
    973968faim_export int aim_ssi_setpermdeny(aim_session_t *sess, fu8_t permdeny, fu32_t vismask)
    974969{
    975         struct aim_ssi_item *tmp;
    976         aim_tlvlist_t *data = NULL;
    977 
    978         if (!sess)
    979                 return -EINVAL;
    980 
    981         /* Need to add the x00ca TLV to the TLV chain */
    982         aim_addtlvtochain8(&data, 0x00ca, permdeny);
    983 
    984         /* Need to add the x00cb TLV to the TLV chain */
    985         aim_addtlvtochain32(&data, 0x00cb, vismask);
    986 
    987         if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
    988                 aim_freetlvchain(&tmp->data);
    989                 tmp->data = data;
    990         } else {
    991                 tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, data);
    992                 aim_freetlvchain(&data);
    993         }
    994 
    995         /* Sync our local list with the server list */
    996         aim_ssi_sync(sess);
    997 
    998         return 0;
     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;
    999994}
    1000995
     
    10091004faim_export int aim_ssi_seticon(aim_session_t *sess, fu8_t *iconsum, fu16_t iconsumlen)
    10101005{
    1011         struct aim_ssi_item *tmp;
    1012         aim_tlvlist_t *data = NULL;
    1013         fu8_t *csumdata;
    1014 
    1015         if (!sess || !iconsum || !iconsumlen)
    1016                 return -EINVAL;
    1017 
    1018         if (!(csumdata = (fu8_t *)malloc((iconsumlen+2)*sizeof(fu8_t))))
    1019                 return -ENOMEM;
    1020         csumdata[0] = 0x00;
    1021         csumdata[1] = 0x10;
    1022         memcpy(&csumdata[2], iconsum, iconsumlen);
    1023 
    1024         /* Need to add the x00d5 TLV to the TLV chain */
    1025         aim_addtlvtochain_raw(&data, 0x00d5, (iconsumlen+2) * sizeof(fu8_t), csumdata);
    1026 
    1027         /* This TLV is added to cache the icon. */
    1028         aim_addtlvtochain_noval(&data, 0x0131);
    1029 
    1030         if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
    1031                 /* If the new tlvchain and oldtlvchain are the same, then do nothing */
    1032                 if (!aim_tlvlist_cmp(tmp->data, data)) {
    1033                         /* The new tlvlist is the identical to the old one */
    1034                         aim_freetlvchain(&data);
    1035                         free(csumdata);
    1036                         return 0;
    1037                 }
    1038                 aim_freetlvchain(&tmp->data);
    1039                 tmp->data = data;
    1040         } else {
    1041                 tmp = aim_ssi_itemlist_add(&sess->ssi.local, "1", 0x0000, 0x51F4, AIM_SSI_TYPE_ICONINFO, data);
    1042                 aim_freetlvchain(&data);
    1043         }
    1044 
    1045         /* Sync our local list with the server list */
    1046         aim_ssi_sync(sess);
    1047         free(csumdata);
    1048         return 0;
     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;
    10491044}
    10501045
     
    10581053 */
    10591054faim_export int aim_ssi_setpresence(aim_session_t *sess, fu32_t presence) {
    1060         struct aim_ssi_item *tmp;
    1061         aim_tlvlist_t *data = NULL;
    1062 
    1063         if (!sess)
    1064                 return -EINVAL;
    1065 
    1066         /* Need to add the x00c9 TLV to the TLV chain */
    1067         aim_addtlvtochain32(&data, 0x00c9, presence);
    1068 
    1069         if ((tmp = aim_ssi_itemlist_finditem(sess->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
    1070                 aim_freetlvchain(&tmp->data);
    1071                 tmp->data = data;
    1072         } else {
    1073                 tmp = aim_ssi_itemlist_add(&sess->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, data);
    1074                 aim_freetlvchain(&data);
    1075         }
    1076 
    1077         /* Sync our local list with the server list */
    1078         aim_ssi_sync(sess);
    1079 
    1080         return 0;
     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;
    10811076}
    10821077
     
    10861081faim_export int aim_ssi_reqrights(aim_session_t *sess)
    10871082{
    1088         aim_conn_t *conn;
    1089 
    1090         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1091                 return -EINVAL;
    1092 
    1093         return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQRIGHTS);
     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);
    10941089}
    10951090
     
    10991094static int parserights(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    11001095{
    1101         int ret = 0, i;
    1102         aim_rxcallback_t userfunc;
    1103         aim_tlvlist_t *tlvlist;
    1104         aim_tlv_t *tlv;
    1105         aim_bstream_t bstream;
    1106         fu16_t *maxitems;
    1107 
    1108         /* This SNAC is made up of a bunch of TLVs */
    1109         tlvlist = aim_readtlvchain(bs);
    1110 
    1111         /* TLV 0x0004 contains the maximum number of each item */
    1112         if (!(tlv = aim_gettlv(tlvlist, 0x0004, 1))) {
    1113                 aim_freetlvchain(&tlvlist);
    1114                 return 0;
    1115         }
    1116 
    1117         aim_bstream_init(&bstream, tlv->value, tlv->length);
    1118 
    1119         if (!(maxitems = (fu16_t *)malloc((tlv->length/2)*sizeof(fu16_t)))) {
    1120                 aim_freetlvchain(&tlvlist);
    1121                 return 0;
    1122         }
    1123 
    1124         for (i=0; i<(tlv->length/2); i++)
    1125                 maxitems[i] = aimbs_get16(&bstream);
    1126 
    1127         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1128                 ret = userfunc(sess, rx, tlv->length/2, maxitems);
    1129 
    1130         aim_freetlvchain(&tlvlist);
    1131         free(maxitems);
    1132 
    1133         return ret;
     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;
    11341129}
    11351130
     
    11411136faim_export int aim_ssi_reqdata(aim_session_t *sess)
    11421137{
    1143         aim_conn_t *conn;
    1144 
    1145         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1146                 return -EINVAL;
    1147 
    1148         /* Free any current data, just in case */
    1149         aim_ssi_freelist(sess);
    1150 
    1151         return aim_genericreq_n_snacid(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_REQDATA);
     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);
    11521147}
    11531148
     
    11641159faim_export int aim_ssi_reqifchanged(aim_session_t *sess, time_t timestamp, fu16_t numitems)
    11651160{
    1166         aim_conn_t *conn;
    1167         aim_frame_t *fr;
    1168         aim_snacid_t snacid;
    1169 
    1170         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1171                 return -EINVAL;
    1172 
    1173         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+4+2)))
    1174                 return -ENOMEM;
    1175 
    1176         snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, NULL, 0);
    1177 
    1178         aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_REQIFCHANGED, 0x0000, snacid);
    1179         aimbs_put32(&fr->data, timestamp);
    1180         aimbs_put16(&fr->data, numitems);
    1181 
    1182         aim_tx_enqueue(sess, fr);
    1183 
    1184         /* Free any current data, just in case */
    1185         aim_ssi_freelist(sess);
    1186 
    1187         return 0;
     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;
    11881183}
    11891184
     
    11931188static int parsedata(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    11941189{
    1195         int ret = 0;
    1196         aim_rxcallback_t userfunc;
    1197         fu8_t fmtver; /* guess */
    1198         fu16_t namelen, gid, bid, type;
    1199         char *name;
    1200         aim_tlvlist_t *data;
    1201 
    1202         fmtver = aimbs_get8(bs); /* Version of ssi data.  Should be 0x00 */
    1203         sess->ssi.numitems += aimbs_get16(bs); /* # of items in this SSI SNAC */
    1204 
    1205         /* Read in the list */
    1206         while (aim_bstream_empty(bs) > 4) { /* last four bytes are timestamp */
    1207                 if ((namelen = aimbs_get16(bs)))
    1208                         name = aimbs_getstr(bs, namelen);
    1209                 else
    1210                         name = NULL;
    1211                 gid = aimbs_get16(bs);
    1212                 bid = aimbs_get16(bs);
    1213                 type = aimbs_get16(bs);
    1214                 data = aim_readtlvchain_len(bs, aimbs_get16(bs));
    1215                 aim_ssi_itemlist_add(&sess->ssi.official, name, gid, bid, type, data);
    1216                 free(name);
    1217                 aim_freetlvchain(&data);
    1218         }
    1219 
    1220         /* Read in the timestamp */
    1221         sess->ssi.timestamp = aimbs_get32(bs);
    1222 
    1223         if (!(snac->flags & 0x0001)) {
    1224                 /* Make a copy of the list */
    1225                 struct aim_ssi_item *cur;
    1226                 for (cur=sess->ssi.official; cur; cur=cur->next)
    1227                         aim_ssi_itemlist_add(&sess->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
    1228 
    1229                 sess->ssi.received_data = 1;
    1230 
    1231                 if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1232                         ret = userfunc(sess, rx, fmtver, sess->ssi.numitems, sess->ssi.official, sess->ssi.timestamp);
    1233         }
    1234 
    1235         return ret;
     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;
    12361231}
    12371232
     
    12471242faim_export int aim_ssi_enable(aim_session_t *sess)
    12481243{
    1249         aim_conn_t *conn;
    1250 
    1251         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1252                 return -EINVAL;
    1253 
    1254         return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, 0x0007);
     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);
    12551250}
    12561251
     
    12651260faim_export int aim_ssi_addmoddel(aim_session_t *sess)
    12661261{
    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 */
     1309static 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 */
     1349static 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 */
     1411static 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 */
     1443static 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;
    12841500        }
    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;
    13021533        }
    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;
    15651560}
    15661561
     
    15741569static int parsedataunchanged(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    15751570{
    1576         int ret = 0;
    1577         aim_rxcallback_t userfunc;
    1578 
    1579         sess->ssi.received_data = 1;
    1580 
    1581         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1582                 ret = userfunc(sess, rx);
    1583 
    1584         return ret;
     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;
    15851580}
    15861581
     
    15931588faim_export int aim_ssi_modbegin(aim_session_t *sess)
    15941589{
    1595         aim_conn_t *conn;
    1596 
    1597         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1598                 return -EINVAL;
    1599 
    1600         return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTART);
     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);
    16011596}
    16021597
     
    16091604faim_export int aim_ssi_modend(aim_session_t *sess)
    16101605{
    1611         aim_conn_t *conn;
    1612 
    1613         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)))
    1614                 return -EINVAL;
    1615 
    1616         return aim_genericreq_n(sess, conn, AIM_CB_FAM_SSI, AIM_CB_SSI_EDITSTOP);
     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);
    16171612}
    16181613
     
    16251620faim_export int aim_ssi_sendauth(aim_session_t *sess, char *sn, char *msg)
    16261621{
    1627         aim_conn_t *conn;
    1628         aim_frame_t *fr;
    1629         aim_snacid_t snacid;
    1630 
    1631         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
    1632                 return -EINVAL;
    1633 
    1634         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
    1635                 return -ENOMEM;
    1636 
    1637         snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, NULL, 0);
    1638         aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTH, 0x0000, snacid);
    1639 
    1640         /* Screen name */
    1641         aimbs_put8(&fr->data, strlen(sn));
    1642         aimbs_putraw(&fr->data, sn, strlen(sn));
    1643 
    1644         /* Message (null terminated) */
    1645         aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
    1646         if (msg) {
    1647                 aimbs_putraw(&fr->data, msg, strlen(msg));
    1648                 aimbs_put8(&fr->data, 0x00);
    1649         }
    1650 
    1651         /* Unknown */
    1652         aimbs_put16(&fr->data, 0x0000);
    1653 
    1654         aim_tx_enqueue(sess, fr);
    1655 
    1656         return 0;
     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;
    16571652}
    16581653
     
    16621657static int receiveauthgrant(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    16631658{
    1664         int ret = 0;
    1665         aim_rxcallback_t userfunc;
    1666         fu16_t tmp;
    1667         char *sn, *msg;
    1668 
    1669         /* Read screen name */
    1670         if ((tmp = aimbs_get8(bs)))
    1671                 sn = aimbs_getstr(bs, tmp);
    1672         else
    1673                 sn = NULL;
    1674 
    1675         /* Read message (null terminated) */
    1676         if ((tmp = aimbs_get16(bs)))
    1677                 msg = aimbs_getstr(bs, tmp);
    1678         else
    1679                 msg = NULL;
    1680 
    1681         /* Unknown */
    1682         tmp = aimbs_get16(bs);
    1683 
    1684         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1685                 ret = userfunc(sess, rx, sn, msg);
    1686 
    1687         free(sn);
    1688         free(msg);
    1689 
    1690         return ret;
     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;
    16911686}
    16921687
     
    17001695faim_export int aim_ssi_sendauthrequest(aim_session_t *sess, char *sn, char *msg)
    17011696{
    1702         aim_conn_t *conn;
    1703         aim_frame_t *fr;
    1704         aim_snacid_t snacid;
    1705 
    1706         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
    1707                 return -EINVAL;
    1708 
    1709         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10+1+strlen(sn)+2+(msg ? strlen(msg)+1 : 0)+2)))
    1710                 return -ENOMEM;
    1711 
    1712         snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, NULL, 0);
    1713         aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREQ, 0x0000, snacid);
    1714 
    1715         /* Screen name */
    1716         aimbs_put8(&fr->data, strlen(sn));
    1717         aimbs_putraw(&fr->data, sn, strlen(sn));
    1718 
    1719         /* Message (null terminated) */
    1720         aimbs_put16(&fr->data, msg ? strlen(msg) : 0);
    1721         if (msg) {
    1722                 aimbs_putraw(&fr->data, msg, strlen(msg));
    1723                 aimbs_put8(&fr->data, 0x00);
    1724         }
    1725 
    1726         /* Unknown */
    1727         aimbs_put16(&fr->data, 0x0000);
    1728 
    1729         aim_tx_enqueue(sess, fr);
    1730 
    1731         return 0;
     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;
    17321727}
    17331728
     
    17371732static int receiveauthrequest(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    17381733{
    1739         int ret = 0;
    1740         aim_rxcallback_t userfunc;
    1741         fu16_t tmp;
    1742         char *sn, *msg;
    1743 
    1744         /* Read screen name */
    1745         if ((tmp = aimbs_get8(bs)))
    1746                 sn = aimbs_getstr(bs, tmp);
    1747         else
    1748                 sn = NULL;
    1749 
    1750         /* Read message (null terminated) */
    1751         if ((tmp = aimbs_get16(bs)))
    1752                 msg = aimbs_getstr(bs, tmp);
    1753         else
    1754                 msg = NULL;
    1755 
    1756         /* Unknown */
    1757         tmp = aimbs_get16(bs);
    1758 
    1759         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1760                 ret = userfunc(sess, rx, sn, msg);
    1761 
    1762         free(sn);
    1763         free(msg);
    1764 
    1765         return ret;
     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;
    17661761}
    17671762
     
    17781773faim_export int aim_ssi_sendauthreply(aim_session_t *sess, char *sn, fu8_t reply, char *msg)
    17791774{
    1780         aim_conn_t *conn;
    1781         aim_frame_t *fr;
    1782         aim_snacid_t snacid;
    1783 
    1784         if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_SSI)) || !sn)
    1785                 return -EINVAL;
    1786 
    1787         if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 1+strlen(sn) + 1 + 2+(msg ? strlen(msg)+1 : 0) + 2)))
    1788                 return -ENOMEM;
    1789 
    1790         snacid = aim_cachesnac(sess, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, NULL, 0);
    1791         aim_putsnac(&fr->data, AIM_CB_FAM_SSI, AIM_CB_SSI_SENDAUTHREP, 0x0000, snacid);
    1792 
    1793         /* Screen name */
    1794         aimbs_put8(&fr->data, strlen(sn));
    1795         aimbs_putraw(&fr->data, sn, strlen(sn));
    1796 
    1797         /* Grant or deny */
    1798         aimbs_put8(&fr->data, reply);
    1799 
    1800         /* Message (null terminated) */
    1801         aimbs_put16(&fr->data, msg ? (strlen(msg)+1) : 0);
    1802         if (msg) {
    1803                 aimbs_putraw(&fr->data, msg, strlen(msg));
    1804                 aimbs_put8(&fr->data, 0x00);
    1805         }
    1806 
    1807         /* Unknown */
    1808         aimbs_put16(&fr->data, 0x0000);
    1809 
    1810         aim_tx_enqueue(sess, fr);
    1811 
    1812         return 0;
     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;
    18131808}
    18141809
     
    18201815static int receiveauthreply(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    18211816{
    1822         int ret = 0;
    1823         aim_rxcallback_t userfunc;
    1824         fu16_t tmp;
    1825         fu8_t reply;
    1826         char *sn, *msg;
    1827 
    1828         /* Read screen name */
    1829         if ((tmp = aimbs_get8(bs)))
    1830                 sn = aimbs_getstr(bs, tmp);
    1831         else
    1832                 sn = NULL;
    1833 
    1834         /* Read reply */
    1835         reply = aimbs_get8(bs);
    1836 
    1837         /* Read message (null terminated) */
    1838         if ((tmp = aimbs_get16(bs)))
    1839                 msg = aimbs_getstr(bs, tmp);
    1840         else
    1841                 msg = NULL;
    1842 
    1843         /* Unknown */
    1844         tmp = aimbs_get16(bs);
    1845 
    1846         if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
    1847                 ret = userfunc(sess, rx, sn, reply, msg);
    1848 
    1849         free(sn);
    1850         free(msg);
    1851 
    1852         return ret;
     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;
    18531848}
    18541849
     
    18581853static int receiveadded(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    18591854{
    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);
    18771873}
    18781874
    18791875static int snachandler(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
    18801876{
    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);
    19061901}
    19071902
    19081903static void ssi_shutdown(aim_session_t *sess, aim_module_t *mod)
    19091904{
    1910         aim_ssi_freelist(sess);
    1911 
    1912         return;
     1905  aim_ssi_freelist(sess);
     1906  return;
    19131907}
    19141908
    19151909faim_internal int ssi_modfirst(aim_session_t *sess, aim_module_t *mod)
    19161910{
    1917 
    1918         mod->family = AIM_CB_FAM_SSI;
    1919         mod->version = 0x0004;
    1920         mod->toolid = 0x0110;
    1921         mod->toolversion = 0x0629;
    1922         mod->flags = 0;
    1923         strncpy(mod->name, "ssi", sizeof(mod->name));
    1924         mod->snachandler = snachandler;
    1925         mod->shutdown = ssi_shutdown;
    1926 
    1927         return 0;
    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.