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