Properly parse search size expressions as off_t, not int.
[doldaconnect.git] / daemon / search.c
index 040ec30..633e07e 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
@@ -17,7 +17,6 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 #include <stdlib.h>
-#include <malloc.h>
 #include <wchar.h>
 #include <wctype.h>
 #include <errno.h>
@@ -32,6 +31,7 @@
 #include "log.h"
 #include "sysevents.h"
 #include "filenet.h"
+#include "client.h"
 #include "search.h"
 
 #define TOK_STR 0
@@ -139,6 +139,19 @@ static struct wcslist *newsl(struct wcslist **list, wchar_t *str)
     return(ln);
 }
 
+static int wcsexists(wchar_t *h, wchar_t *n)
+{
+    size_t hl = wcslen(h), nl = wcslen(n);
+    wchar_t lh[hl + 1], ln[nl + 1];
+    int i;
+    
+    for(i = 0; i <= hl; i++)
+       lh[i] = towlower(h[i]);
+    for(i = 0; i <= nl; i++)
+       ln[i] = towlower(n[i]);
+    return(wcsstr(lh, ln) != NULL);
+}
+
 static void slmerge1(struct wcslist **list, wchar_t *str)
 {
     size_t len;
@@ -395,10 +408,12 @@ static struct reinfo analyzere(wchar_t *re, wchar_t **endret, wchar_t endc)
            if(ret.begstr != NULL)
            {
                for(i = 0; (sinf.begstr[i] != L'\0') && (ret.begstr != L'\0') && (ret.begstr[i] == sinf.begstr[i]); i++);
-               if(i == 0)
+               if(i == 0) {
                    free(ret.begstr);
-               else
+                   ret.begstr = NULL;
+               } else {
                    ret.begstr[i] = L'\0';
+               }
            }
            free(sinf.begstr);
        } else {
@@ -423,10 +438,12 @@ static struct reinfo analyzere(wchar_t *re, wchar_t **endret, wchar_t endc)
                    maxlen = len1;
                }
                for(i = 1; (i <= minlen) && (ret.endstr[len1 - i] == sinf.endstr[len2 - i]); i++);
-               if(i == 1)
+               if(i == 1) {
                    free(ret.endstr);
-               else if(i <= maxlen)
+                   ret.endstr = NULL;
+               } else if(i <= maxlen) {
                    wmemmove(ret.endstr, ret.endstr + (len1 - i) + 1, i);
+               }
            }
            free(sinf.endstr);
        } else {
@@ -514,6 +531,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);
 }
 
@@ -642,12 +664,29 @@ struct sexpr *parsesexpr(int argc, wchar_t **argv)
                    sexpr->op = SOP_SIZEEQ;
                else
                    sexpr->op = SOP_SIZEGT;
-               sexpr->d.n = wcstol(tok2->d.str + 2, NULL, 0);
+               sexpr->d.sz = wcstoll(tok2->d.str + 2, NULL, 0);
                sexpr->cost = 0;
                getsexpr(tok->d.se = sexpr);
                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);
@@ -741,8 +780,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);
@@ -1061,9 +1098,7 @@ static int srisvalid(struct srchres *sr, struct sexpr *sexpr)
        free(buf);
        return(!ret);
     case SOP_LINKRE:
-       p = sr->filename;
-       if(sr->fnet->filebasename != NULL)
-           p = sr->fnet->filebasename(p);
+       p = fnfilebasename(sr->filename);
        if((buf = icwcstombs(p, "UTF-8")) == NULL)
            return(0);
        ret = regexec(&sexpr->d.re.cre, buf, 0, NULL, 0);
@@ -1072,16 +1107,18 @@ static int srisvalid(struct srchres *sr, struct sexpr *sexpr)
     case SOP_NAMESS:
        return(wcsexists(sr->filename, sexpr->d.s));
     case SOP_LINKSS:
-       p = sr->filename;
-       if(sr->fnet->filebasename != NULL)
-           p = sr->fnet->filebasename(p);
+       p = fnfilebasename(sr->filename);
        return(wcsexists(p, sexpr->d.s));
     case SOP_SIZELT:
-       return(sr->size < sexpr->d.n);
+       return(sr->size < sexpr->d.sz);
     case SOP_SIZEEQ:
-       return(sr->size == sexpr->d.n);
+       return(sr->size == sexpr->d.sz);
     case SOP_SIZEGT:
-       return(sr->size > sexpr->d.n);
+       return(sr->size > sexpr->d.sz);
+    case SOP_HASHIS:
+       if(sr->hash == NULL)
+           return(0);
+       return(hashcmp(sr->hash, sexpr->d.hash));
     }
     return(0);
 }
@@ -1112,6 +1149,8 @@ void freesrchres(struct srchres *sr)
            sr->srch->results = sr->next;
        sr->srch->numres--;
     }
+    if(sr->hash != NULL)
+       freehash(sr->hash);
     if(sr->filename != NULL)
        free(sr->filename);
     if(sr->peerid != NULL)
@@ -1140,6 +1179,8 @@ struct srchres *dupsrchres(struct srchres *sr)
        new->filename = swcsdup(sr->filename);
     if(sr->fn != NULL)
        getfnetnode(new->fn = sr->fn);
+    if(sr->hash != NULL)
+       new->hash = duphash(sr->hash);
     return(new);
 }