From 9d8cf7438740ac21033158d8ba039e40e1f3abc2 Mon Sep 17 00:00:00 2001 From: fredrik Date: Wed, 19 Oct 2005 01:14:34 +0000 Subject: [PATCH] Add the ability to search for hashes. git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/doldaconnect@384 959494ce-11ee-0310-bf91-de5d638817bd --- daemon/fnet-dc.c | 126 ++++++++++++++++++++++++++++++++++++------------------- daemon/search.c | 28 ++++++++++++- daemon/search.h | 2 + 3 files changed, 111 insertions(+), 45 deletions(-) diff --git a/daemon/fnet-dc.c b/daemon/fnet-dc.c index 056c3d1..48b34ff 100644 --- a/daemon/fnet-dc.c +++ b/daemon/fnet-dc.c @@ -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); diff --git a/daemon/search.c b/daemon/search.c index b319685..d16e5a0 100644 --- a/daemon/search.c +++ b/daemon/search.c @@ -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); } diff --git a/daemon/search.h b/daemon/search.h index 35d0230..67501eb 100644 --- a/daemon/search.h +++ b/daemon/search.h @@ -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; }; -- 2.11.0