Use proper e-mail address format everywhere.
[doldaconnect.git] / daemon / fnet-dc.c
index f7d976e..880b1e3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Dolda Connect - Modular multiuser Direct Connect-style client
- *  Copyright (C) 2004 Fredrik Tolf (fredrik@dolda2000.com)
+ *  Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
  *  
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@
 #include <string.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <alloca.h>
 #include <wctype.h>
 #include <time.h>
 #include <errno.h>
@@ -109,6 +108,7 @@ struct dchub
     char *charset;
     char *nativename;
     char *nativenick;
+    char **supports;
 };
 
 struct dcexppeer
@@ -244,6 +244,24 @@ static int isdchash(struct hash *hash)
     return(1);
 }
 
+/*
+ * Uncomment when used!
+static int hubsupports(struct dchub *hub, char *cap)
+{
+    char **p;
+    
+    if(hub->supports == NULL)
+       return(0);
+    for(p = hub->supports; *p != NULL; p++)
+    {
+       if(!strcasecmp(*p, cap))
+           return(1);
+    }
+    return(0);
+}
+*/
+
 static int supports(struct dcpeer *peer, char *cap)
 {
     char **p;
@@ -727,7 +745,7 @@ static void requestfile(struct dcpeer *peer)
            freedcpeer(peer);
            return;
        }
-       qstrf(peer->sk, "$UGetBlock %i %i %s|", peer->transfer->curpos, peer->transfer->size - peer->transfer->curpos, buf);
+       qstrf(peer->sk, "$UGetBlock %zi %zi %s|", peer->transfer->curpos, peer->transfer->size - peer->transfer->curpos, buf);
     } else {
        /* Use DCCHARSET for $Get paths until further researched... */
        if((buf = icswcstombs(peer->transfer->path, DCCHARSET, NULL)) == NULL)
@@ -736,7 +754,7 @@ static void requestfile(struct dcpeer *peer)
            freedcpeer(peer);
            return;
        }
-       qstrf(peer->sk, "$Get %s$%i|", buf, peer->transfer->curpos + 1);
+       qstrf(peer->sk, "$Get %s$%zi|", buf, peer->transfer->curpos + 1);
     }
 }
 
@@ -1230,10 +1248,10 @@ static void cmd_search(struct socket *sk, struct fnetnode *fn, char *cmd, char *
                if(node->f.b.hastth)
                {
                    buf2 = base32encode(node->hashtth, 24);
-                   qstrf(dsk, "%s%s\005%i%sTTH:%.39s%s", prefix, buf, node->size, infix, buf2, postfix);
+                   qstrf(dsk, "%s%s\005%zi%sTTH:%.39s%s", prefix, buf, node->size, infix, buf2, postfix);
                    free(buf2);
                } else {
-                   qstrf(dsk, "%s%s\005%i%s%s%s", prefix, buf, node->size, infix, hub->nativename, postfix);
+                   qstrf(dsk, "%s%s\005%zi%s%s%s", prefix, buf, node->size, infix, hub->nativename, postfix);
                }
                free(buf);
            }
@@ -1480,6 +1498,36 @@ static void cmd_logedin(struct socket *sk, struct fnetnode *fn, char *cmd, char
     hubhandleaction(sk, fn, cmd, args);
 }
 
+static void cmd_hubsupports(struct socket *sk, struct fnetnode *fn, char *cmd, char *args)
+{
+    struct dchub *hub;
+    int i;
+    char *p, *p2;
+    char **arr;
+    size_t arrsize, arrdata;
+    
+    hub = fn->data;
+    if(hub->supports != NULL)
+    {
+       for(i = 0; hub->supports[i] != NULL; i++)
+           free(hub->supports[i]);
+       free(hub->supports);
+    }
+    arr = NULL;
+    arrsize = arrdata = 0;
+    p = args;
+    do
+    {
+       if((p2 = strchr(p, ' ')) != NULL)
+           *(p2++) = 0;
+       if(*p == 0)
+           continue;
+       addtobuf(arr, sstrdup(p));
+    } while((p = p2) != NULL);
+    addtobuf(arr, NULL);
+    hub->supports = arr;
+}
+
 static void cmd_mynick(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
 {
     struct dcexppeer *expect;
@@ -1860,7 +1908,7 @@ static void cmd_get(struct socket *sk, struct dcpeer *peer, char *cmd, char *arg
     lesk = wrapsock(fd);
     transferprepul(peer->transfer, sb.st_size, offset, -1, lesk);
     putsock(lesk);
-    qstrf(sk, "$FileLength %i|", peer->transfer->size);
+    qstrf(sk, "$FileLength %zi|", peer->transfer->size);
 }
 
 static void cmd_send(struct socket *sk, struct dcpeer *peer, char *cmd, char *args)
@@ -2573,6 +2621,7 @@ static struct command hubcmds[] =
     {"$UserCommand", cc(cmd_usercommand)},
     {"$GetPass", cc(cmd_getpass)},
     {"$LogedIn", cc(cmd_logedin)}, /* sic */
+    {"$Supports", cc(cmd_hubsupports)},
     {NULL, NULL}
 };
 
@@ -3086,6 +3135,7 @@ static void hubconnect(struct fnetnode *fn)
 
 static void hubdestroy(struct fnetnode *fn)
 {
+    int i;
     struct dchub *hub;
     struct qcommand *qcmd;
     
@@ -3101,6 +3151,12 @@ static void hubdestroy(struct fnetnode *fn)
        return;
     while((qcmd = ulqcmd(&hub->queue)) != NULL)
        freeqcmd(qcmd);
+    if(hub->supports != NULL)
+    {
+       for(i = 0; hub->supports[i] != NULL; i++)
+           free(hub->supports[i]);
+       free(hub->supports);
+    }
     if(hub->nativename != NULL)
        free(hub->nativename);
     if(hub->nativenick != NULL)
@@ -3246,7 +3302,7 @@ static void updatehmlist(void)
            if(node->f.b.type == FILE_REG)
            {
                addtobuf(buf, '|');
-               sprintf(numbuf, "%i", node->size);
+               sprintf(numbuf, "%zi", node->size);
                bufcat(buf, numbuf, strlen(numbuf));
            }
            addtobuf(buf, 13);
@@ -3421,7 +3477,7 @@ static void updatexmllist(void)
                lev++;
                continue;
            } else {
-               fprintf(fs, "<File Name=\"%s\" Size=\"%i\"", namebuf, node->size);
+               fprintf(fs, "<File Name=\"%s\" Size=\"%zi\"", namebuf, node->size);
                if(node->f.b.hastth)
                {
                    hashbuf = base32encode(node->hashtth, 24);
@@ -3531,7 +3587,7 @@ static void updatelists(int now)
     if(!now)
     {
        if(listwritetimer == NULL)
-           listwritetimer = timercallback(ntime() + 300, listtimercb, NULL);
+           listwritetimer = timercallback(ntime() + confgetint("cli", "hashwritedelay"), listtimercb, NULL);
        return;
     }
     if(listwritetimer != NULL)
@@ -3547,6 +3603,78 @@ static int shareupdate(unsigned long long uusharesize, void *data)
     return(0);
 }
 
+static char *quotestr(char *str)
+{
+    unsigned char *buf;
+    unsigned char *p;
+    size_t bufsize, bufdata;
+    wchar_t *wbuf;
+    static char *enc = NULL;
+    size_t encsize, encdata;
+    
+    buf = NULL;
+    bufsize = bufdata = 0;
+    for(p = (unsigned char *)str; *p; p++)
+    {
+       if(*p == '\b')
+           bufcat(buf, "\\b", 2);
+       else if(*p == '\t')
+           bufcat(buf, "\\t", 2);
+       else if(*p == '\n')
+           bufcat(buf, "\\n", 2);
+       else if(*p == '\r')
+           bufcat(buf, "\\r", 2);
+       else if(*p == '\\')
+           bufcat(buf, "\\\\", 2);
+       else if(*p >= 32)
+           addtobuf(buf, *p);
+       else
+           bprintf(buf, "\\x%02x", *p);
+    }
+    addtobuf(buf, 0);
+    if(enc != NULL)
+       free(enc);
+    enc = NULL;
+    if((wbuf = icmbstowcs((char *)buf, DCCHARSET)) != NULL)
+    {
+       enc = icwcstombs(wbuf, NULL);
+       free(wbuf);
+    }
+    if(enc == NULL)
+    {
+       encsize = encdata = 0;
+       for(p = buf; *p; p++) {
+           if(*p < 128)
+               addtobuf(enc, *p);
+           else
+               bprintf(buf, "\\x%x", *p);
+       }
+    }
+    free(buf);
+    return(enc);
+}
+
+static void logunimpl(char *list, char *cmd, char *args)
+{
+    FILE *log;
+    
+    if((log = fopen("/tmp/dc-unimpl", "a")) == NULL)
+    {
+       flog(LOG_WARNING, "could not open unimpl log: %s", strerror(errno));
+       return;
+    }
+    fputs(list, log);
+    fputc('\t', log);
+    fputs(quotestr(cmd), log);
+    if(args != NULL)
+    {
+       fputc('\t', log);
+       fputs(quotestr(args), log);
+    }
+    fputc('\n', log);
+    fclose(log);
+}
+
 static void dispatchcommand(struct qcommand *qcmd, struct command *cmdlist, struct socket *sk, void *data)
 {
     char *p;
@@ -3560,11 +3688,16 @@ static void dispatchcommand(struct qcommand *qcmd, struct command *cmdlist, stru
            break;
     }
     if(cmd->handler != NULL)
+    {
        cmd->handler(sk, data, qcmd->string, p);
-/*
-    else
-       flog(LOG_DEBUG, "Unimplemented DC command: %s \"%s\"", qcmd->string, p?p:"noargs");
-*/
+    } else if(confgetint("dc", "logunimpl")) {
+       if(cmdlist == hubcmds)
+           logunimpl("hub", qcmd->string, p);
+       else if(cmdlist == peercmds)
+           logunimpl("peer", qcmd->string, p);
+       else
+           logunimpl("other?!", qcmd->string, p);
+    }
 }
 
 static int run(void)
@@ -3736,6 +3869,10 @@ static struct configvar myvars[] =
      * hub owners, though. Note that DC++ emulation can also be turned
      * on or off for individual hubs, overriding this setting. */
     {CONF_VAR_BOOL, "dcppemu", {.num = 0}},
+    /** Use for debugging. If set to true, doldacond will log all
+     * unknown commands it receives, and their arguments, to
+     * /tmp/dc-unimpl. */
+    {CONF_VAR_BOOL, "logunimpl", {.num = 0}},
     {CONF_VAR_END}
 };