Add the ability to search for hashes.
authorfredrik <fredrik@959494ce-11ee-0310-bf91-de5d638817bd>
Wed, 19 Oct 2005 01:14:34 +0000 (01:14 +0000)
committerfredrik <fredrik@959494ce-11ee-0310-bf91-de5d638817bd>
Wed, 19 Oct 2005 01:14:34 +0000 (01:14 +0000)
git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/doldaconnect@384 959494ce-11ee-0310-bf91-de5d638817bd

daemon/fnet-dc.c
daemon/search.c
daemon/search.h

index 056c3d1..48b34ff 100644 (file)
@@ -1158,7 +1158,7 @@ static void cmd_search(struct socket *sk, struct fnetnode *fn, char *cmd, char *
        goto out;
     if(*p == 0)
        goto out;
-    if(*(p++) == 'T')
+    if((*(p++) == 'T') && (minsize == 0))
     {
        maxsize = 0;
        minsize = -1;
@@ -2172,6 +2172,33 @@ static void findsizelimit(struct sexpr *sexpr, int *min, int *max)
        *max = retmax;
 }
 
+static struct hash *findsehash(struct sexpr *sexpr)
+{
+    struct hash *h1, *h2;
+    
+    switch(sexpr->op)
+    {
+    case SOP_AND:
+       if((h1 = findsehash(sexpr->l)) != NULL)
+           return(h1);
+       if((h1 = findsehash(sexpr->r)) != NULL)
+           return(h1);
+       break;
+    case SOP_OR:
+       h1 = findsehash(sexpr->l);
+       h2 = findsehash(sexpr->r);
+       if(hashcmp(h1, h2))
+           return(h1);
+       break;
+    case SOP_HASHIS:
+       if(!wcscmp(sexpr->d.hash->algo, L"TTH"))
+           return(sexpr->d.hash);
+    default:
+       break;
+    }
+    return(NULL);
+}
+
 static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlist *ln)
 {
     struct dchub *hub;
@@ -2181,13 +2208,14 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis
     struct sockaddr *name;
     socklen_t namelen;
     int minsize, maxsize;
-    char sizedesc[32];
+    struct hash *hash;
     
     hub = fn->data;
     if((fn->state != FNN_EST) || (fn->sk == NULL) || (fn->sk->state != SOCK_EST))
        return(1);
     list = findsexprstrs(srch->sexpr);
     findsizelimit(srch->sexpr, &minsize, &maxsize);
+    hash = findsehash(srch->sexpr);
     if((minsize != 0) && (maxsize != -1))
     {
        /* Choose either minsize or maxsize by trying to determine
@@ -2198,52 +2226,64 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis
        else
            maxsize = -1;
     }
-    if(minsize != 0)
-    {
-       snprintf(sizedesc, sizeof(sizedesc), "T?F?%i", minsize);
-    } else if(maxsize != -1) {
-       snprintf(sizedesc, sizeof(sizedesc), "T?T?%i", maxsize);
-    } else {
-       strcpy(sizedesc, "F?F?0");
-    }
     sstr = NULL;
     sstrsize = sstrdata = 0;
-    if(list != NULL)
+    if((hash != NULL) && (hash->len == 24))
     {
-       for(cur = list; cur != NULL; cur = cur->next)
+       /* Prioritize hash searches above all else */
+       bufcat(sstr, "F?T?0?9?TTH:", 12);
+       buf = base32encode(hash->buf, hash->len);
+       
+       bufcat(sstr, buf, 39);
+       free(buf);
+    } else {
+       if(minsize != 0)
        {
-           if((buf = icwcstombs(cur->str, DCCHARSET)) == NULL)
-           {
-               /* Can't find anything anyway if the search expression
-                * requires characters outside DC's charset. There's
-                * nothing technically wrong with the search itself,
-                * however, so return success. This should be
-                * considered as an optimization. */
-               freesl(&list);
-               if(sstr != NULL)
-                   free(sstr);
-               return(0);
-           }
-           if(cur != list)
-               addtobuf(sstr, '$');
-           /*
-            * It probably doesn't hurt if buf contains any extra
-            * dollar signs - it will just result in extra search
-            * terms, and the extraneous results will be filtered by
-            * the search layer anyway. It hurts if it contains any
-            * pipes, though, so let's sell them for money.
-            */
-           for(p = buf; *p; p++)
+           sizebuf2(sstr, sstrdata + 32, 1);
+           snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?F?%i?1?", minsize);
+       } else if(maxsize != -1) {
+           sizebuf2(sstr, sstrdata + 32, 1);
+           snprintf(sstr + sstrdata, sstrsize - sstrdata, "T?T?%i?1?", maxsize);
+       } else {
+           bufcat(sstr, "F?F?0?1?", 8);
+       }
+       if(list != NULL)
+       {
+           for(cur = list; cur != NULL; cur = cur->next)
            {
-               if(*p == '|')
-                   *p = '$';
+               if((buf = icwcstombs(cur->str, DCCHARSET)) == NULL)
+               {
+                   /* Can't find anything anyway if the search expression
+                    * requires characters outside DC's charset. There's
+                    * nothing technically wrong with the search itself,
+                    * however, so return success. This should be
+                    * considered as an optimization. */
+                   freesl(&list);
+                   if(sstr != NULL)
+                       free(sstr);
+                   return(0);
+               }
+               if(cur != list)
+                   addtobuf(sstr, '$');
+               /*
+                * It probably doesn't hurt if buf contains any extra
+                * dollar signs - it will just result in extra search
+                * terms, and the extraneous results will be filtered by
+                * the search layer anyway. It hurts if it contains any
+                * pipes, though, so let's sell them for money.
+                */
+               for(p = buf; *p; p++)
+               {
+                   if(*p == '|')
+                       *p = '$';
+               }
+               bufcat(sstr, buf, strlen(buf));
+               free(buf);
            }
-           bufcat(sstr, buf, strlen(buf));
-           free(buf);
+       } else {
+           /* Will match all files... :-/ */
+           addtobuf(sstr, '.');
        }
-    } else {
-       /* Will match all files... :-/ */
-       addtobuf(sstr, '.');
     }
     addtobuf(sstr, 0);
     if(tcpsock != NULL)
@@ -2252,11 +2292,11 @@ static int hubsearch(struct fnetnode *fn, struct search *srch, struct srchfnnlis
        {
            flog(LOG_WARNING, "cannot get address of UDP socket");
        } else {
-           qstrf(fn->sk, "$Search %s %s?1?%s|", formataddress(name, namelen), sizedesc, sstr);
+           qstrf(fn->sk, "$Search %s %s|", formataddress(name, namelen), sstr);
            free(name);
        }
     } else {
-       qstrf(fn->sk, "$Search Hub:%s %s?1?%s|", hub->nativenick, sizedesc, sstr);
+       qstrf(fn->sk, "$Search Hub:%s %s|", hub->nativenick, sstr);
     }
     free(sstr);
     freesl(&list);
index b319685..d16e5a0 100644 (file)
@@ -515,6 +515,11 @@ void putsexpr(struct sexpr *sexpr)
        if(sexpr->d.s != NULL)
            free(sexpr->d.s);
     }
+    if(sexpr->op == SOP_HASHIS)
+    {
+       if(sexpr->d.hash != NULL)
+           freehash(sexpr->d.hash);
+    }
     free(sexpr);
 }
 
@@ -649,6 +654,23 @@ struct sexpr *parsesexpr(int argc, wchar_t **argv)
                freetok(tok2);
                putsexpr(sexpr);
                done = 0;
+           } else if((st->type == TOK_STR) && !wcsncmp(st->d.str, L"H=", 2)) {
+               tok2 = poptok(&st);
+               pushtok(tok = newtok(), &st);
+               tok->type = TOK_SE;
+               sexpr = newsexpr();
+               sexpr->op = SOP_HASHIS;
+               if((sexpr->d.hash = parsehash(tok2->d.str + 2)) == NULL)
+               {
+                   freetok(tok2);
+                   putsexpr(sexpr);
+                   goto out_err;
+               }
+               sexpr->cost = 2;
+               getsexpr(tok->d.se = sexpr);
+               freetok(tok2);
+               putsexpr(sexpr);
+               done = 0;
            } else if((std >= 3) && (st->type == TOK_CP) && (st->next->type == TOK_SE) && (st->next->next->type == TOK_OP)) {
                freetok(poptok(&st));
                tok = poptok(&st);
@@ -742,8 +764,6 @@ struct wcslist *findsexprstrs(struct sexpr *sexpr)
        freesl(&l1);
        freesl(&l2);
        break;
-    case SOP_NOT:
-       break;
     case SOP_NAMERE:
     case SOP_LINKRE:
        list = regexfindstrings(sexpr->d.re.sre);
@@ -1083,6 +1103,10 @@ static int srisvalid(struct srchres *sr, struct sexpr *sexpr)
        return(sr->size == sexpr->d.n);
     case SOP_SIZEGT:
        return(sr->size > sexpr->d.n);
+    case SOP_HASHIS:
+       if(sr->hash == NULL)
+           return(0);
+       return(hashcmp(sr->hash, sexpr->d.hash));
     }
     return(0);
 }
index 35d0230..67501eb 100644 (file)
@@ -37,6 +37,7 @@
 #define SOP_SIZEGT 9
 #define SOP_SIZELT 10
 #define SOP_SIZEEQ 11
+#define SOP_HASHIS 12
 
 #define SRCH_WAIT 0
 #define SRCH_RUN 1
@@ -64,6 +65,7 @@ struct sexpr
        } re;
        wchar_t *s;
        int n;
+       struct hash *hash;
     } d;
 };