Annotation of sbbs/src/smblib/smbhash.c, revision 1.1.1.1

1.1       root        1: /* smbhash.c */
                      2: 
                      3: /* Synchronet message base (SMB) hash-related functions */
                      4: 
                      5: /* $Id: smbhash.c,v 1.15 2005/10/02 23:28:57 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2005 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This library is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU Lesser General Public License          *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU Lesser General Public License for more details: lgpl.txt or     *
                     18:  * http://www.fsf.org/copyleft/lesser.html                                                                     *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include <time.h>              /* time()       */
                     39: #include <string.h>            /* strdup() */
                     40: #include "smblib.h"
                     41: #include "md5.h"
                     42: #include "crc16.h"
                     43: #include "crc32.h"
                     44: #include "genwrap.h"
                     45: 
                     46: /* If return value is SMB_ERROR_NOT_FOUND, hash file is left open */
                     47: int SMBCALL smb_findhash(smb_t* smb, hash_t** compare, hash_t* found_hash, 
                     48:                                                 long source_mask, BOOL mark)
                     49: {
                     50:        int             retval;
                     51:        BOOL    found=FALSE;
                     52:        size_t  c,count;
                     53:        hash_t  hash;
                     54: 
                     55:        if(found_hash!=NULL)
                     56:                memset(found_hash,0,sizeof(hash_t));
                     57: 
                     58:        if((retval=smb_open_hash(smb))!=SMB_SUCCESS)
                     59:                return(retval);
                     60: 
                     61:        COUNT_LIST_ITEMS(compare, count);
                     62: 
                     63:        if(count) {
                     64: 
                     65:                rewind(smb->hash_fp);
                     66:                while(!feof(smb->hash_fp)) {
                     67:                        if(smb_fread(smb,&hash,sizeof(hash),smb->hash_fp)!=sizeof(hash))
                     68:                                break;
                     69: 
                     70:                        if(hash.flags==0)
                     71:                                continue;               /* invalid hash record (!?) */
                     72: 
                     73:                        if((source_mask&(1<<hash.source))==0)   /* not checking this source type */
                     74:                                continue;
                     75: 
                     76:                        for(c=0;compare[c]!=NULL;c++) {
                     77: 
                     78:                                if(compare[c]->source!=hash.source)
                     79:                                        continue;       /* wrong source */
                     80:                                if(compare[c]->length!=hash.length)
                     81:                                        continue;       /* wrong source length */
                     82:                                if(compare[c]->flags&SMB_HASH_MARKED)
                     83:                                        continue;       /* already marked */
                     84:                                if((compare[c]->flags&SMB_HASH_PROC_MASK)!=(hash.flags&SMB_HASH_PROC_MASK))
                     85:                                        continue;       /* wrong pre-process flags */
                     86:                                if((compare[c]->flags&hash.flags&SMB_HASH_MASK)==0)     
                     87:                                        continue;       /* no matching hashes */
                     88:                                if(compare[c]->flags&hash.flags&SMB_HASH_CRC16 
                     89:                                        && compare[c]->crc16!=hash.crc16)
                     90:                                        continue;       /* wrong crc-16 */
                     91:                                if(compare[c]->flags&hash.flags&SMB_HASH_CRC32
                     92:                                        && compare[c]->crc32!=hash.crc32)
                     93:                                        continue;       /* wrong crc-32 */
                     94:                                if(compare[c]->flags&hash.flags&SMB_HASH_MD5 
                     95:                                        && memcmp(compare[c]->md5,hash.md5,sizeof(hash.md5)))
                     96:                                        continue;       /* wrong crc-16 */
                     97:                                
                     98:                                /* successful match! */
                     99:                                break;  /* can't match more than one, so stop comparing */
                    100:                        }
                    101: 
                    102:                        if(compare[c]==NULL)
                    103:                                continue;       /* no match */
                    104: 
                    105:                        found=TRUE;
                    106: 
                    107:                        if(found_hash!=NULL)
                    108:                                memcpy(found_hash,&hash,sizeof(hash));
                    109: 
                    110:                        if(!mark)
                    111:                                break;
                    112: 
                    113:                        compare[c]->flags|=SMB_HASH_MARKED;
                    114:                }
                    115:                if(found) {
                    116:                        smb_close_hash(smb);
                    117:                        return(SMB_SUCCESS);
                    118:                }
                    119:        }
                    120: 
                    121:        /* hash file left open */
                    122:        return(SMB_ERR_NOT_FOUND);
                    123: }
                    124: 
                    125: int SMBCALL smb_addhashes(smb_t* smb, hash_t** hashes, BOOL skip_marked)
                    126: {
                    127:        int             retval;
                    128:        size_t  h;
                    129: 
                    130:        COUNT_LIST_ITEMS(hashes, h);
                    131:        if(!h)  /* nothing to add */
                    132:                return(SMB_SUCCESS);
                    133: 
                    134:        if((retval=smb_open_hash(smb))!=SMB_SUCCESS)
                    135:                return(retval);
                    136: 
                    137:        fseek(smb->hash_fp,0,SEEK_END);
                    138: 
                    139:        for(h=0;hashes[h]!=NULL;h++) {
                    140: 
                    141:                /* skip hashes marked by smb_findhash() */
                    142:                if(skip_marked && hashes[h]->flags&SMB_HASH_MARKED)     
                    143:                        continue;       
                    144:        
                    145:                /* can't think of any reason to strip SMB_HASH_MARKED flag right now */
                    146:                if(smb_fwrite(smb,hashes[h],sizeof(hash_t),smb->hash_fp)!=sizeof(hash_t)) {
                    147:                        retval=SMB_ERR_WRITE;
                    148:                        break;
                    149:                }
                    150:        }
                    151: 
                    152:        smb_close_hash(smb);
                    153: 
                    154:        return(retval);
                    155: }
                    156: 
                    157: static char* strip_chars(uchar* dst, const uchar* src, uchar* set)
                    158: {
                    159:        while(*src) {
                    160:                if(strchr(set,*src)==NULL)
                    161:                        *(dst++)=*src;
                    162:                src++;
                    163:        }
                    164:        *dst=0;
                    165: 
                    166:        return((char *)dst);
                    167: }
                    168: 
                    169: /* Allocates and calculates hashes of data (based on flags)                                    */
                    170: /* Returns NULL on failure                                                                                                     */
                    171: hash_t* SMBCALL smb_hash(ulong msgnum, ulong t, unsigned source, unsigned flags
                    172:                                                 ,const void* data, size_t length)
                    173: {
                    174:        hash_t* hash;
                    175: 
                    176:        if((hash=(hash_t*)malloc(sizeof(hash_t)))==NULL)
                    177:                return(NULL);
                    178: 
                    179:        memset(hash,0,sizeof(hash_t));
                    180:        hash->number=msgnum;
                    181:        hash->time=t;
                    182:        hash->length=length;
                    183:        hash->source=source;
                    184:        hash->flags=flags;
                    185:        if(flags&SMB_HASH_CRC16)
                    186:                hash->crc16=crc16((char*)data,length);
                    187:        if(flags&SMB_HASH_CRC32)
                    188:                hash->crc32=crc32((char*)data,length);
                    189:        if(flags&SMB_HASH_MD5)
                    190:                MD5_calc(hash->md5,data,length);
                    191: 
                    192:        return(hash);
                    193: }
                    194: 
                    195: /* Allocates and calculates hashes of data (based on flags)                                    */
                    196: /* Supports string hash "pre-processing" (e.g. lowercase, strip whitespace)    */
                    197: /* Returns NULL on failure                                                                                                     */
                    198: hash_t* SMBCALL smb_hashstr(ulong msgnum, ulong t, unsigned source, unsigned flags
                    199:                                                        ,const char* str)
                    200: {
                    201:        char*   p=(char *)str;
                    202:        hash_t* hash;
                    203: 
                    204:        if(flags&SMB_HASH_PROC_MASK) {  /* string pre-processing */
                    205:                if((p=strdup(str))==NULL)
                    206:                        return(NULL);
                    207:                if(flags&SMB_HASH_STRIP_WSP)
                    208:                        strip_chars(p,str," \t\r\n");
                    209:                if(flags&SMB_HASH_LOWERCASE)
                    210:                        strlwr(p);
                    211:        }
                    212:        
                    213:        hash=smb_hash(msgnum, t, source, flags, p, strlen(p));
                    214: 
                    215:        if(p!=str)      /* duped string */
                    216:                free(p);
                    217: 
                    218:        return(hash);
                    219: }
                    220: 
                    221: /* Allocatese and calculates all hashes for a single message                           */
                    222: /* Returns NULL on failure                                                                                                     */
                    223: hash_t** SMBCALL smb_msghashes(smbmsg_t* msg, const uchar* body)
                    224: {
                    225:        size_t          h=0;
                    226:        uchar           flags=SMB_HASH_CRC16|SMB_HASH_CRC32|SMB_HASH_MD5;
                    227:        hash_t**        hashes; /* This is a NULL-terminated list of hashes */
                    228:        hash_t*         hash;
                    229:        time_t          t=time(NULL);
                    230: 
                    231:        if((hashes=(hash_t**)malloc(sizeof(hash_t*)*(SMB_HASH_SOURCE_TYPES+1)))==NULL)
                    232:                return(NULL);
                    233: 
                    234:        memset(hashes, 0, sizeof(hash_t*)*(SMB_HASH_SOURCE_TYPES+1));
                    235: 
                    236:        if(msg->id!=NULL && 
                    237:                (hash=smb_hashstr(msg->hdr.number, t, SMB_HASH_SOURCE_MSG_ID, flags, msg->id))!=NULL)
                    238:                hashes[h++]=hash;
                    239: 
                    240:        if(msg->ftn_msgid!=NULL && 
                    241:                (hash=smb_hashstr(msg->hdr.number, t, SMB_HASH_SOURCE_FTN_ID, flags, msg->ftn_msgid))!=NULL)
                    242:                hashes[h++]=hash;
                    243: 
                    244:        flags|=SMB_HASH_STRIP_WSP;
                    245:        if(body!=NULL && 
                    246:                (hash=smb_hashstr(msg->hdr.number, t, SMB_HASH_SOURCE_BODY, flags, body))!=NULL)
                    247:                hashes[h++]=hash;
                    248: 
                    249:        return(hashes);
                    250: }
                    251: 
                    252: /* Calculates and stores the hashes for a single message                                       */
                    253: int SMBCALL smb_hashmsg(smb_t* smb, smbmsg_t* msg, const uchar* text, BOOL update)
                    254: {
                    255:        size_t          n;
                    256:        int                     retval=SMB_SUCCESS;
                    257:        hash_t          found;
                    258:        hash_t**        hashes; /* This is a NULL-terminated list of hashes */
                    259: 
                    260:        if(smb->status.attr&SMB_EMAIL)
                    261:                return(SMB_SUCCESS);
                    262: 
                    263:        hashes=smb_msghashes(msg,text);
                    264: 
                    265:        if(smb_findhash(smb, hashes, &found, SMB_HASH_SOURCE_ALL, update)==SMB_SUCCESS && !update) {
                    266:                retval=SMB_DUPE_MSG;
                    267:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
                    268:                        ,"duplicate %s: %s found in message #%lu"
                    269:                        ,smb_hashsourcetype(found.source)
                    270:                        ,smb_hashsource(msg,found.source)
                    271:                        ,found.number);
                    272:        } else
                    273:                if((retval=smb_addhashes(smb,hashes,/* skip_marked? */TRUE))==SMB_SUCCESS)
                    274:                        msg->flags|=MSG_FLAG_HASHED;
                    275: 
                    276:        FREE_LIST(hashes,n);
                    277: 
                    278:        return(retval);
                    279: }
                    280: 
                    281: /* length=0 specifies ASCIIZ data                                                                                      */
                    282: int SMBCALL smb_getmsgidx_by_hash(smb_t* smb, smbmsg_t* msg, unsigned source
                    283:                                                                 ,unsigned flags, const void* data, size_t length)
                    284: {
                    285:        int                     retval;
                    286:        size_t          n;
                    287:        hash_t**        hashes;
                    288:        hash_t          found;
                    289: 
                    290:        if((hashes=(hash_t**)malloc(sizeof(hash_t*)*2))==NULL)
                    291:                return(SMB_ERR_MEM);
                    292: 
                    293:        if(length==0)
                    294:                hashes[0]=smb_hashstr(0,0,source,flags,data);
                    295:        else
                    296:                hashes[0]=smb_hash(0,0,source,flags,data,length);
                    297:        if(hashes[0]==NULL)
                    298:                return(SMB_ERR_MEM);
                    299: 
                    300:        hashes[1]=NULL; /* terminate list */
                    301: 
                    302:        if((retval=smb_findhash(smb, hashes, &found, 1<<source, FALSE))==SMB_SUCCESS) {
                    303:                if(found.number==0)
                    304:                        retval=SMB_FAILURE;     /* use better error value here? */
                    305:                else {
                    306:                        msg->hdr.number=found.number;
                    307:                        retval=smb_getmsgidx(smb, msg);
                    308:                }
                    309:        }
                    310: 
                    311:        FREE_LIST(hashes,n);
                    312: 
                    313:        return(retval);
                    314: }
                    315: 
                    316: int SMBCALL smb_getmsghdr_by_hash(smb_t* smb, smbmsg_t* msg, unsigned source
                    317:                                                                 ,unsigned flags, const void* data, size_t length)
                    318: {
                    319:        int retval;
                    320: 
                    321:        if((retval=smb_getmsgidx_by_hash(smb,msg,source,flags,data,length))!=SMB_SUCCESS)
                    322:                return(retval);
                    323: 
                    324:        if((retval=smb_lockmsghdr(smb,msg))!=SMB_SUCCESS)
                    325:                return(retval);
                    326: 
                    327:        retval=smb_getmsghdr(smb,msg);
                    328: 
                    329:        smb_unlockmsghdr(smb,msg); 
                    330: 
                    331:        return(retval);
                    332: }
                    333: 
                    334: ushort SMBCALL smb_subject_crc(const char* subj)
                    335: {
                    336:        char*   str;
                    337:        ushort  crc;
                    338: 
                    339:        if(subj==NULL)
                    340:                return(0xffff);
                    341: 
                    342:        while(!strnicmp(subj,"RE:",3)) {
                    343:                subj+=3;
                    344:                while(*subj==' ')
                    345:                        subj++; 
                    346:        }
                    347: 
                    348:        if((str=strdup(subj))==NULL)
                    349:                return(0xffff);
                    350: 
                    351:        strlwr(str);
                    352:        crc=crc16(str,0 /* auto-length */);
                    353:        free(str);
                    354: 
                    355:        return(crc);
                    356: }
                    357: 
                    358: ushort SMBCALL smb_name_crc(const char* name)
                    359: {
                    360:        char*   str;
                    361:        ushort  crc;
                    362: 
                    363:        if(name==NULL)
                    364:                return(0xffff);
                    365: 
                    366:        if((str=strdup(name))==NULL)
                    367:                return(0xffff);
                    368: 
                    369:        strlwr(str);
                    370:        crc=crc16(str,0 /* auto-length */);
                    371:        free(str);
                    372: 
                    373:        return(crc);
                    374: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.