Annotation of sbbs/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.10 2004/12/29 10:13:08 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 2004 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(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=(uchar*)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: #define SMB_MAX_HASH_COUNT 4
                    232: 
                    233:        if((hashes=(hash_t**)malloc(sizeof(hash_t*)*SMB_MAX_HASH_COUNT))==NULL)
                    234:                return(NULL);
                    235: 
                    236:        memset(hashes, 0, sizeof(hash_t*)*SMB_MAX_HASH_COUNT);
                    237: 
                    238:        if(msg->id!=NULL && 
                    239:                (hash=smb_hashstr(msg->hdr.number, t, SMB_HASH_SOURCE_MSG_ID, flags, msg->id))!=NULL)
                    240:                hashes[h++]=hash;
                    241: 
                    242:        if(msg->ftn_msgid!=NULL && 
                    243:                (hash=smb_hashstr(msg->hdr.number, t, SMB_HASH_SOURCE_FTN_ID, flags, msg->ftn_msgid))!=NULL)
                    244:                hashes[h++]=hash;
                    245: 
                    246:        flags|=SMB_HASH_STRIP_WSP;
                    247:        if(body!=NULL && 
                    248:                (hash=smb_hashstr(msg->hdr.number, t, SMB_HASH_SOURCE_BODY, flags, body))!=NULL)
                    249:                hashes[h++]=hash;
                    250: 
                    251:        return(hashes);
                    252: }
                    253: 
                    254: /* Calculates and stores the hashes for a single message                                       */
                    255: int SMBCALL smb_hashmsg(smb_t* smb, smbmsg_t* msg, const uchar* text, BOOL update)
                    256: {
                    257:        size_t          n;
                    258:        int                     retval=SMB_SUCCESS;
                    259:        hash_t          found;
                    260:        hash_t**        hashes; /* This is a NULL-terminated list of hashes */
                    261: 
                    262:        hashes=smb_msghashes(msg,text);
                    263: 
                    264:        if(smb_findhash(smb, hashes, &found, SMB_HASH_SOURCE_ALL, update)==SMB_SUCCESS && !update) {
                    265:                retval=SMB_DUPE_MSG;
                    266:                safe_snprintf(smb->last_error,sizeof(smb->last_error)
                    267:                        ,"duplicate %s: %s found in message #%lu"
                    268:                        ,smb_hashsourcetype(found.source)
                    269:                        ,smb_hashsource(msg,found.source)
                    270:                        ,found.number);
                    271:        } else
                    272:                if((retval=smb_addhashes(smb,hashes,/* skip_marked? */TRUE))==SMB_SUCCESS)
                    273:                        msg->flags|=MSG_FLAG_HASHED;
                    274: 
                    275:        FREE_LIST(hashes,n);
                    276: 
                    277:        return(retval);
                    278: }
                    279: 
                    280: /* length=0 specifies ASCIIZ data                                                                                      */
                    281: int SMBCALL smb_getmsgidx_by_hash(smb_t* smb, smbmsg_t* msg, unsigned source
                    282:                                                                 ,unsigned flags, const void* data, size_t length)
                    283: {
                    284:        int                     retval;
                    285:        size_t          n;
                    286:        hash_t**        hashes;
                    287:        hash_t          found;
                    288: 
                    289:        if((hashes=(hash_t**)malloc(sizeof(hash_t*)*2))==NULL)
                    290:                return(SMB_ERR_MEM);
                    291: 
                    292:        if(length==0)
                    293:                hashes[0]=smb_hashstr(0,0,source,flags,data);
                    294:        else
                    295:                hashes[0]=smb_hash(0,0,source,flags,data,length);
                    296:        if(hashes[0]==NULL)
                    297:                return(SMB_ERR_MEM);
                    298: 
                    299:        hashes[1]=NULL; /* terminate list */
                    300: 
                    301:        if((retval=smb_findhash(smb, hashes, &found, 1<<source, FALSE))==SMB_SUCCESS) {
                    302:                if(found.number==0)
                    303:                        retval=SMB_FAILURE;     /* use better error value here? */
                    304:                else {
                    305:                        msg->hdr.number=found.number;
                    306:                        retval=smb_getmsgidx(smb, msg);
                    307:                }
                    308:        }
                    309: 
                    310:        FREE_LIST(hashes,n);
                    311: 
                    312:        return(retval);
                    313: }
                    314: 
                    315: int SMBCALL smb_getmsghdr_by_hash(smb_t* smb, smbmsg_t* msg, unsigned source
                    316:                                                                 ,unsigned flags, const void* data, size_t length)
                    317: {
                    318:        int retval;
                    319: 
                    320:        if((retval=smb_getmsgidx_by_hash(smb,msg,source,flags,data,length))!=SMB_SUCCESS)
                    321:                return(retval);
                    322: 
                    323:        if((retval=smb_lockmsghdr(smb,msg))!=SMB_SUCCESS)
                    324:                return(retval);
                    325: 
                    326:        retval=smb_getmsghdr(smb,msg);
                    327: 
                    328:        smb_unlockmsghdr(smb,msg); 
                    329: 
                    330:        return(retval);
                    331: }
                    332: 
                    333: ushort SMBCALL smb_subject_crc(const char* subj)
                    334: {
                    335:        char*   str;
                    336:        ushort  crc;
                    337: 
                    338:        if(subj==NULL)
                    339:                return(0xffff);
                    340: 
                    341:        while(!strnicmp(subj,"RE:",3)) {
                    342:                subj+=3;
                    343:                while(*subj==' ')
                    344:                        subj++; 
                    345:        }
                    346: 
                    347:        if((str=strdup(subj))==NULL)
                    348:                return(0xffff);
                    349: 
                    350:        strlwr(str);
                    351:        crc=crc16(str,0 /* auto-length */);
                    352:        free(str);
                    353: 
                    354:        return(crc);
                    355: }
                    356: 
                    357: ushort SMBCALL smb_name_crc(const char* name)
                    358: {
                    359:        char*   str;
                    360:        ushort  crc;
                    361: 
                    362:        if(name==NULL)
                    363:                return(0xffff);
                    364: 
                    365:        if((str=strdup(name))==NULL)
                    366:                return(0xffff);
                    367: 
                    368:        strlwr(str);
                    369:        crc=crc16(str,0 /* auto-length */);
                    370:        free(str);
                    371: 
                    372:        return(crc);
                    373: }
                    374: 
                    375: int SMBCALL smb_init_idx(smb_t* smb, smbmsg_t* msg)
                    376: {
                    377:        msg->idx.subj=smb_subject_crc(msg->subj);
                    378:        if(smb->status.attr&SMB_EMAIL) {
                    379:                if(msg->to_ext)
                    380:                        msg->idx.to=atoi(msg->to_ext);
                    381:                else
                    382:                        msg->idx.to=0;
                    383:                if(msg->from_ext)
                    384:                        msg->idx.from=atoi(msg->from_ext);
                    385:                else
                    386:                        msg->idx.from=0; 
                    387:        } else {
                    388:                msg->idx.to=smb_name_crc(msg->to);
                    389:                msg->idx.from=smb_name_crc(msg->from);
                    390:        }
                    391: 
                    392:        return(SMB_SUCCESS);
                    393: }

unix.superglobalmegacorp.com

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