|
|
1.1 ! root 1: /* smbadd.c */ ! 2: ! 3: /* Synchronet message base (SMB) high-level "add message" function */ ! 4: ! 5: /* $Id: smbadd.c,v 1.17 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> ! 39: #include <string.h> /* strlen(), memset() */ ! 40: #include "smblib.h" ! 41: #include "genwrap.h" ! 42: #include "crc32.h" ! 43: ! 44: /****************************************************************************/ ! 45: /****************************************************************************/ ! 46: int SMBCALL smb_addmsg(smb_t* smb, smbmsg_t* msg, int storage, long dupechk_hashes ! 47: ,ushort xlat, const uchar* body, const uchar* tail) ! 48: { ! 49: uchar* lzhbuf=NULL; ! 50: long lzhlen; ! 51: int retval; ! 52: size_t n; ! 53: size_t l,length; ! 54: size_t taillen=0; ! 55: size_t bodylen=0; ! 56: size_t chklen=0; ! 57: long offset; ! 58: ulong crc=0xffffffff; ! 59: hash_t found; ! 60: hash_t** hashes=NULL; /* This is a NULL-terminated list of hashes */ ! 61: smbmsg_t remsg; ! 62: ! 63: if(!SMB_IS_OPEN(smb)) { ! 64: safe_snprintf(smb->last_error,sizeof(smb->last_error),"msgbase not open"); ! 65: return(SMB_ERR_NOT_OPEN); ! 66: } ! 67: ! 68: if(filelength(fileno(smb->shd_fp))<1) { /* Create it if it doesn't exist */ ! 69: /* smb->status.max_crcs, max_msgs, max_age, and attr should be pre-initialized */ ! 70: if((retval=smb_create(smb))!=SMB_SUCCESS) ! 71: return(retval); ! 72: } ! 73: ! 74: if(!smb->locked && smb_locksmbhdr(smb)!=SMB_SUCCESS) ! 75: return(SMB_ERR_LOCK); ! 76: ! 77: msg->hdr.total_dfields = 0; ! 78: ! 79: /* try */ ! 80: do { ! 81: ! 82: if((retval=smb_getstatus(smb))!=SMB_SUCCESS) ! 83: break; ! 84: ! 85: msg->hdr.number=smb->status.last_msg+1; ! 86: if(!(smb->status.attr&SMB_EMAIL)) { ! 87: ! 88: hashes=smb_msghashes(msg,body); ! 89: ! 90: if(smb_findhash(smb, hashes, &found, dupechk_hashes, /* mark? */FALSE)==SMB_SUCCESS) { ! 91: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 92: ,"duplicate %s: %s found in message #%lu" ! 93: ,smb_hashsourcetype(found.source) ! 94: ,smb_hashsource(msg,found.source) ! 95: ,found.number); ! 96: retval=SMB_DUPE_MSG; ! 97: break; ! 98: } ! 99: } ! 100: ! 101: if(tail!=NULL && (taillen=strlen(tail))>0) ! 102: taillen+=sizeof(xlat); /* xlat string terminator */ ! 103: ! 104: if(body!=NULL && (bodylen=strlen(body))>0) { ! 105: ! 106: /* Remove white-space from end of message text */ ! 107: chklen=bodylen; ! 108: while(chklen && body[chklen-1]<=' ') ! 109: chklen--; ! 110: ! 111: /* Calculate CRC-32 of message text (before encoding, if any) */ ! 112: if(smb->status.max_crcs && dupechk_hashes&(1<<SMB_HASH_SOURCE_BODY)) { ! 113: for(l=0;l<chklen;l++) ! 114: crc=ucrc32(body[l],crc); ! 115: crc=~crc; ! 116: ! 117: /* Add CRC to CRC history (and check for duplicates) */ ! 118: if((retval=smb_addcrc(smb,crc))!=SMB_SUCCESS) ! 119: break; ! 120: } ! 121: ! 122: bodylen+=sizeof(xlat); /* xlat string terminator */ ! 123: ! 124: /* LZH compress? */ ! 125: if(xlat==XLAT_LZH && bodylen+taillen>=SDT_BLOCK_LEN ! 126: && (lzhbuf=(uchar *)malloc(bodylen*2))!=NULL) { ! 127: lzhlen=lzh_encode((uchar*)body,bodylen-sizeof(xlat),lzhbuf); ! 128: if(lzhlen>1 ! 129: && smb_datblocks(lzhlen+(sizeof(xlat)*2)+taillen) ! 130: < smb_datblocks(bodylen+taillen)) { ! 131: bodylen=lzhlen+(sizeof(xlat)*2); /* Compressible */ ! 132: body=lzhbuf; ! 133: } else ! 134: xlat=XLAT_NONE; ! 135: } else ! 136: xlat=XLAT_NONE; ! 137: } ! 138: ! 139: length=bodylen+taillen; ! 140: ! 141: if(length) { ! 142: ! 143: if(length&0x80000000) { ! 144: sprintf(smb->last_error,"message length: 0x%lX",length); ! 145: retval=SMB_ERR_DAT_LEN; ! 146: break; ! 147: } ! 148: ! 149: /* Allocate Data Blocks */ ! 150: if(smb->status.attr&SMB_HYPERALLOC) { ! 151: offset=smb_hallocdat(smb); ! 152: storage=SMB_HYPERALLOC; ! 153: } else { ! 154: if((retval=smb_open_da(smb))!=SMB_SUCCESS) ! 155: break; ! 156: if(storage==SMB_FASTALLOC) ! 157: offset=smb_fallocdat(smb,length,1); ! 158: else { /* SMB_SELFPACK */ ! 159: offset=smb_allocdat(smb,length,1); ! 160: storage=SMB_SELFPACK; ! 161: } ! 162: smb_close_da(smb); ! 163: } ! 164: ! 165: if(offset<0) { ! 166: retval=offset; ! 167: break; ! 168: } ! 169: msg->hdr.offset=offset; ! 170: ! 171: smb_fseek(smb->sdt_fp,offset,SEEK_SET); ! 172: ! 173: if(bodylen) { ! 174: if((retval=smb_dfield(msg,TEXT_BODY,bodylen))!=SMB_SUCCESS) ! 175: break; ! 176: ! 177: if(xlat!=XLAT_NONE) { /* e.g. XLAT_LZH */ ! 178: if(smb_fwrite(smb,&xlat,sizeof(xlat),smb->sdt_fp)!=sizeof(xlat)) { ! 179: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 180: ,"%d '%s' writing body xlat string" ! 181: ,get_errno(),STRERROR(get_errno())); ! 182: retval=SMB_ERR_WRITE; ! 183: break; ! 184: } ! 185: bodylen-=sizeof(xlat); ! 186: } ! 187: xlat=XLAT_NONE; /* xlat string terminator */ ! 188: if(smb_fwrite(smb,&xlat,sizeof(xlat),smb->sdt_fp)!=sizeof(xlat)) { ! 189: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 190: ,"%d '%s' writing body xlat terminator" ! 191: ,get_errno(),STRERROR(get_errno())); ! 192: retval=SMB_ERR_WRITE; ! 193: break; ! 194: } ! 195: bodylen-=sizeof(xlat); ! 196: ! 197: if(smb_fwrite(smb,body,bodylen,smb->sdt_fp)!=bodylen) { ! 198: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 199: ,"%d '%s' writing body (%ld bytes)" ! 200: ,get_errno(),STRERROR(get_errno()) ! 201: ,bodylen); ! 202: retval=SMB_ERR_WRITE; ! 203: break; ! 204: } ! 205: } ! 206: ! 207: if(taillen) { ! 208: if((retval=smb_dfield(msg,TEXT_TAIL,taillen))!=SMB_SUCCESS) ! 209: break; ! 210: ! 211: xlat=XLAT_NONE; /* xlat string terminator */ ! 212: if(smb_fwrite(smb,&xlat,sizeof(xlat),smb->sdt_fp)!=sizeof(xlat)) { ! 213: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 214: ,"%d '%s' writing tail xlat terminator" ! 215: ,get_errno(),STRERROR(get_errno())); ! 216: retval=SMB_ERR_WRITE; ! 217: break; ! 218: } ! 219: ! 220: if(smb_fwrite(smb,tail,taillen-sizeof(xlat),smb->sdt_fp)!=taillen-sizeof(xlat)) { ! 221: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 222: ,"%d '%s' writing tail (%ld bytes)" ! 223: ,get_errno(),STRERROR(get_errno()) ! 224: ,taillen-sizeof(xlat)); ! 225: retval=SMB_ERR_WRITE; ! 226: break; ! 227: } ! 228: } ! 229: ! 230: for(l=length;l%SDT_BLOCK_LEN;l++) { ! 231: if(smb_fputc(0,smb->sdt_fp)!=0) ! 232: break; ! 233: } ! 234: if(l%SDT_BLOCK_LEN) { ! 235: safe_snprintf(smb->last_error,sizeof(smb->last_error) ! 236: ,"%d '%s' writing data padding" ! 237: ,get_errno(),STRERROR(get_errno())); ! 238: retval=SMB_ERR_WRITE; ! 239: break; ! 240: } ! 241: ! 242: fflush(smb->sdt_fp); ! 243: } ! 244: ! 245: if(msg->hdr.when_imported.time==0) { ! 246: msg->hdr.when_imported.time=time(NULL); ! 247: msg->hdr.when_imported.zone=0; /* how do we detect system TZ? */ ! 248: } ! 249: if(msg->hdr.when_written.time==0) /* Uninitialized */ ! 250: msg->hdr.when_written = msg->hdr.when_imported; ! 251: ! 252: /* Look-up thread_back if RFC822 Reply-ID was specified */ ! 253: if(msg->hdr.thread_back==0 && msg->reply_id!=NULL) { ! 254: if(smb_getmsgidx_by_msgid(smb,&remsg,msg->reply_id)==SMB_SUCCESS) ! 255: msg->hdr.thread_back=remsg.idx.number; /* needed for threading backward */ ! 256: } ! 257: ! 258: /* Look-up thread_back if FTN REPLY was specified */ ! 259: if(msg->hdr.thread_back==0 && msg->ftn_reply!=NULL) { ! 260: if(smb_getmsghdr_by_ftnid(smb,&remsg,msg->ftn_reply)==SMB_SUCCESS) ! 261: msg->hdr.thread_back=remsg.idx.number; /* needed for threading backward */ ! 262: } ! 263: ! 264: /* Auto-thread linkage */ ! 265: if(msg->hdr.thread_back) { ! 266: memset(&remsg,0,sizeof(remsg)); ! 267: remsg.hdr.number=msg->hdr.thread_back; ! 268: if(smb_getmsgidx(smb, &remsg)==SMB_SUCCESS /* valid thread origin */ ! 269: && smb_lockmsghdr(smb,&remsg)==SMB_SUCCESS) { ! 270: ! 271: do { /* try */ ! 272: ! 273: if(smb_getmsghdr(smb, &remsg)!=SMB_SUCCESS) ! 274: break; ! 275: ! 276: /* Add RFC-822 Reply-ID if original message has RFC Message-ID */ ! 277: if(msg->reply_id==NULL && remsg.id!=NULL ! 278: && smb_hfield_str(msg,RFC822REPLYID,remsg.id)!=SMB_SUCCESS) ! 279: break; ! 280: ! 281: /* Add FidoNet Reply if original message has FidoNet MSGID */ ! 282: if(msg->ftn_reply==NULL && remsg.ftn_msgid!=NULL ! 283: && smb_hfield_str(msg,FIDOREPLYID,remsg.ftn_msgid)!=SMB_SUCCESS) ! 284: break; ! 285: ! 286: smb_updatethread(smb, &remsg, msg->hdr.number); ! 287: ! 288: } while(0); /* finally */ ! 289: ! 290: smb_unlockmsghdr(smb, &remsg); ! 291: smb_freemsgmem(&remsg); ! 292: } ! 293: } ! 294: ! 295: if(!(smb->status.attr&SMB_EMAIL) ! 296: && smb_addhashes(smb,hashes,/* skip_marked? */FALSE)==SMB_SUCCESS) ! 297: msg->flags|=MSG_FLAG_HASHED; ! 298: if(msg->to==NULL) /* no recipient, don't add header (required for bulkmail) */ ! 299: break; ! 300: ! 301: retval=smb_addmsghdr(smb,msg,storage); /* calls smb_unlocksmbhdr() */ ! 302: ! 303: } while(0); ! 304: /* finally */ ! 305: ! 306: if(retval!=SMB_SUCCESS) ! 307: smb_freemsg_dfields(smb,msg,1); ! 308: ! 309: if(smb->locked) ! 310: smb_unlocksmbhdr(smb); ! 311: FREE_AND_NULL(lzhbuf); ! 312: FREE_LIST(hashes,n); ! 313: ! 314: return(retval); ! 315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.