Make libdcui build against the same utils as the rest of the tree.
[doldaconnect.git] / lib / uimisc.c
index 6c799df..249f8f8 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include <unistd.h>
+#include <stdlib.h>
 /* I'm very unsure about this, but for now it defines wcstoll (which
  * should be defined anyway) and doesn't break anything... let's keep
  * two eyes wide open, though. */
@@ -26,7 +27,6 @@
 #include <wctype.h>
 #include <pwd.h>
 #include <string.h>
-#include <malloc.h>
 #include <stdio.h>
 
 #ifdef HAVE_CONFIG_H
@@ -34,7 +34,7 @@
 #endif
 #include <doldaconnect/uilib.h>
 #include <doldaconnect/uimisc.h>
-#include <doldaconnect/utils.h>
+#include <utils.h>
 
 #ifdef HAVE_KRB5
 #include <krb5.h>
@@ -205,77 +205,6 @@ struct krb5data
     int valid, fwd, fwded;
 };
 
-static char *hexencode(char *data, size_t datalen)
-{
-    char *buf, this;
-    size_t bufsize, bufdata;
-    int dig;
-    
-    buf = NULL;
-    bufsize = bufdata = 0;
-    for(; datalen > 0; datalen--, data++)
-    {
-       dig = (*data & 0xF0) >> 4;
-       if(dig > 9)
-           this = 'A' + dig - 10;
-       else
-           this = dig + '0';
-       addtobuf(buf, this);
-       dig = *data & 0x0F;
-       if(dig > 9)
-           this = 'A' + dig - 10;
-       else
-           this = dig + '0';
-       addtobuf(buf, this);
-    }
-    addtobuf(buf, 0);
-    return(buf);
-}
-
-static char *hexdecode(char *data, size_t *len)
-{
-    char *buf, this;
-    size_t bufsize, bufdata;
-    
-    buf = NULL;
-    bufsize = bufdata = 0;
-    for(; *data; data++)
-    {
-       if((*data >= 'A') && (*data <= 'F'))
-       {
-           this = (this & 0x0F) | ((*data - 'A' + 10) << 4);
-       } else if((*data >= '0') && (*data <= '9')) {
-           this = (this & 0x0F) | ((*data - '0') << 4);
-       } else {
-           if(buf != NULL)
-               free(buf);
-           return(NULL);
-       }
-       data++;
-       if(!*data)
-       {
-           if(buf != NULL)
-               free(buf);
-           return(NULL);
-       }
-       if((*data >= 'A') && (*data <= 'F'))
-       {
-           this = (this & 0xF0) | (*data - 'A' + 10);
-       } else if((*data >= '0') && (*data <= '9')) {
-           this = (this & 0xF0) | (*data - '0');
-       } else {
-           if(buf != NULL)
-               free(buf);
-           return(NULL);
-       }
-       addtobuf(buf, this);
-    }
-    addtobuf(buf, 0);
-    if(len != NULL)
-       *len = bufdata - 1;
-    return(buf);
-}
-
 static void process_krb5(struct dc_response *resp, struct logindata *data)
 {
     int ret;
@@ -869,6 +798,9 @@ static int getfnlistcallback(struct dc_response *resp)
                fn->name = swcsdup(ires->argv[2].val.str);
                fn->numusers = ires->argv[3].val.num;
                fn->state = ires->argv[4].val.num;
+               if(fn->pubid != NULL)
+                   free(fn->pubid);
+               fn->pubid = swcsdup(ires->argv[5].val.str);
            } else {
                fn = newfn();
                fn->id = ires->argv[0].val.num;
@@ -876,6 +808,7 @@ static int getfnlistcallback(struct dc_response *resp)
                fn->name = swcsdup(ires->argv[2].val.str);
                fn->numusers = ires->argv[3].val.num;
                fn->state = ires->argv[4].val.num;
+               fn->pubid = swcsdup(ires->argv[5].val.str);
                fn->found = 1;
            }
            dc_freeires(ires);
@@ -985,13 +918,49 @@ static int gettrlistcallback(struct dc_response *resp)
     return(1);
 }
 
+static int sortlist1(const struct dc_respline *l1, const struct dc_respline *l2)
+{
+    return(wcscmp(l1->argv[1], l2->argv[1]));
+}
+
+static int sortlist2(const struct dc_fnetpeer **p1, const struct dc_fnetpeer **p2)
+{
+    return(wcscmp((*p1)->id, (*p2)->id));
+}
+
+static void fillpeer(struct dc_fnetpeer *peer, struct dc_respline *r)
+{
+    int i;
+    struct dc_fnetpeerdatum *datum;
+    
+    for(i = 3; i < r->argc; i += 2)
+    {
+       if((datum = finddatum(peer->fn, r->argv[i])) != NULL)
+       {
+           switch(datum->dt)
+           {
+           case DC_FNPD_INT:
+               peersetnum(peer, datum->id, wcstol(r->argv[i + 1], NULL, 10));
+               break;
+           case DC_FNPD_LL:
+               peersetlnum(peer, datum->id, wcstoll(r->argv[i + 1], NULL, 10));
+               break;
+           case DC_FNPD_STR:
+               peersetstr(peer, datum->id, r->argv[i + 1]);
+               break;
+           }
+       }
+    }
+}
+
 static int getpeerlistcallback(struct dc_response *resp)
 {
-    int i, o;
+    int i, o, c;
     struct dc_fnetnode *fn;
     struct fnetcbdata *data;
-    struct dc_fnetpeer *peer, *next;
-    struct dc_fnetpeerdatum *datum;
+    struct dc_fnetpeer *peer;
+    struct dc_fnetpeer **plist;
+    size_t plistsize, plistdata;
     
     data = resp->data;
     if((fn = dc_findfnetnode(data->fnid)) == NULL)
@@ -1002,43 +971,46 @@ static int getpeerlistcallback(struct dc_response *resp)
     }
     if(resp->code == 200)
     {
-       for(peer = fn->peers; peer != NULL; peer = peer->next)
-           peer->found = 0;
-       for(i = 0; i < resp->numlines; i++)
+       qsort(resp->rlines, resp->numlines, sizeof(*resp->rlines), (int (*)(const void *, const void *))sortlist1);
+       plist = NULL;
+       plistsize = plistdata = 0;
+       for(i = 0, peer = fn->peers; peer != NULL; peer = peer->next)
+           addtobuf(plist, peer);
+       qsort(plist, plistdata, sizeof(*plist), (int (*)(const void *, const void *))sortlist2);
+       i = o = 0;
+       while(1)
        {
-           if((peer = dc_fnetfindpeer(fn, resp->rlines[i].argv[1])) == NULL)
-               peer = addpeer(fn, resp->rlines[i].argv[1], resp->rlines[i].argv[2]);
-           peer->found = 1;
-           for(o = 3; o < resp->rlines[i].argc; o += 2)
+           if((i < resp->numlines) && (o < plistdata))
            {
-               if((datum = finddatum(fn, resp->rlines[i].argv[o])) != NULL)
+               c = wcscmp(resp->rlines[i].argv[1], plist[o]->id);
+               if(c < 0)
                {
-                   switch(datum->dt)
-                   {
-                   case DC_FNPD_INT:
-                       peersetnum(peer, datum->id, wcstol(resp->rlines[i].argv[o + 1], NULL, 10));
-                       break;
-                   case DC_FNPD_LL:
-                       peersetlnum(peer, datum->id, wcstoll(resp->rlines[i].argv[o + 1], NULL, 10));
-                       break;
-                   case DC_FNPD_STR:
-                       peersetstr(peer, datum->id, resp->rlines[i].argv[o + 1]);
-                       break;
-                   }
+                   peer = addpeer(fn, resp->rlines[i].argv[1], resp->rlines[i].argv[2]);
+                   fillpeer(peer, resp->rlines + i);
+                   i++;
+               } else if(c > 0) {
+                   delpeer(plist[o]);
+                   o++;
+               } else {
+                   fillpeer(plist[o], resp->rlines + i);
+                   i++;
+                   o++;
                }
+           } else if(i < resp->numlines) {
+               peer = addpeer(fn, resp->rlines[i].argv[1], resp->rlines[i].argv[2]);
+               fillpeer(peer, resp->rlines + i);
+               i++;
+           } else if(o < plistdata) {
+               delpeer(plist[o]);
+               o++;
+           } else {
+               break;
            }
        }
-       for(peer = fn->peers; peer != NULL; peer = next)
-       {
-           next = peer->next;
-           if(!peer->found)
-               delpeer(peer);
-       }
-       fn->trackpeers = 1;
+       free(plist);
     } else if(resp->code == 201) {
        while(fn->peers != NULL)
            delpeer(fn->peers);
-       fn->trackpeers = 1;
     }
     data->callback(fn, resp->code, data->data);
     free(data);
@@ -1217,21 +1189,29 @@ void dc_uimisc_handlenotify(struct dc_response *resp)
        }
        break;
     case 630:
-       if(((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL) && fn->trackpeers)
+       if((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL)
        {
            if((peer = dc_fnetfindpeer(fn, ires->argv[1].val.str)) == NULL)
-               addpeer(fn, ires->argv[1].val.str, ires->argv[2].val.str);
+           {
+               peer = addpeer(fn, ires->argv[1].val.str, ires->argv[2].val.str);
+               if(fn->newpeercb != NULL)
+                   fn->newpeercb(peer);
+           }
        }
        break;
     case 631:
-       if(((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL) && fn->trackpeers)
+       if((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL)
        {
            if((peer = dc_fnetfindpeer(fn, ires->argv[1].val.str)) != NULL)
+           {
+               if(fn->delpeercb != NULL)
+                   fn->delpeercb(peer);
                delpeer(peer);
+           }
        }
        break;
     case 632:
-       if(((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL) && fn->trackpeers)
+       if((fn = dc_findfnetnode(ires->argv[0].val.num)) != NULL)
        {
            if((peer = dc_fnetfindpeer(fn, ires->argv[1].val.str)) != NULL)
            {
@@ -1240,7 +1220,7 @@ void dc_uimisc_handlenotify(struct dc_response *resp)
                    free(peer->nick);
                    peer->nick = swcsdup(ires->argv[2].val.str);
                }
-               for(i = 3; i < resp->rlines[0].argc; i += 3)
+               for(i = 4; i < resp->rlines[0].argc; i += 3)
                {
                    switch(wcstol(resp->rlines[0].argv[i + 1], NULL, 10))
                    {
@@ -1255,6 +1235,8 @@ void dc_uimisc_handlenotify(struct dc_response *resp)
                        break;
                    }
                }
+               if(fn->chpeercb != NULL)
+                   fn->chpeercb(peer);
            }
        }
        break;