|
|
1.1 ! root 1: /* getmsg.cpp */ ! 2: ! 3: /* Synchronet message retrieval functions */ ! 4: ! 5: /* $Id: getmsg.cpp,v 1.3 2000/12/11 23:03:16 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 2000 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This program is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU 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 General Public License for more details: gpl.txt or * ! 18: * http://www.fsf.org/copyleft/gpl.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: /***********************************************************************/ ! 39: /* Functions that do i/o with messages (posts/mail/auto) or their data */ ! 40: /***********************************************************************/ ! 41: ! 42: #include "sbbs.h" ! 43: ! 44: #define LZH TRUE ! 45: ! 46: void lfputs(char HUGE16 *buf, FILE *fp) ! 47: { ! 48: while(*buf) { ! 49: fputc(*buf,fp); ! 50: buf++; } ! 51: } ! 52: ! 53: /****************************************************************************/ ! 54: /* Loads an SMB message from the open msg base the fastest way possible */ ! 55: /* first by offset, and if that's the wrong message, then by number. */ ! 56: /* Returns 1 if the message was loaded and left locked, otherwise */ ! 57: /****************************************************************************/ ! 58: int sbbs_t::loadmsg(smbmsg_t *msg, ulong number) ! 59: { ! 60: char str[128]; ! 61: int i; ! 62: ! 63: if(msg->idx.offset) { /* Load by offset if specified */ ! 64: ! 65: if((i=smb_lockmsghdr(&smb,msg))!=0) { ! 66: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 67: return(0); } ! 68: ! 69: i=smb_getmsghdr(&smb,msg); ! 70: if(!i && msg->hdr.number==number) ! 71: return(1); ! 72: ! 73: /* Wrong offset */ ! 74: ! 75: if(!i) { ! 76: smb_freemsgmem(msg); ! 77: msg->total_hfields=0; } ! 78: ! 79: smb_unlockmsghdr(&smb,msg); } ! 80: ! 81: msg->hdr.number=number; ! 82: if((i=smb_getmsgidx(&smb,msg))!=0) /* Message is deleted */ ! 83: return(0); ! 84: if((i=smb_lockmsghdr(&smb,msg))!=0) { ! 85: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 86: return(0); } ! 87: if((i=smb_getmsghdr(&smb,msg))!=0) { ! 88: sprintf(str,"(%06lX) #%lu/%lu %s",msg->idx.offset,msg->idx.number ! 89: ,number,smb.file); ! 90: smb_unlockmsghdr(&smb,msg); ! 91: errormsg(WHERE,ERR_READ,str,i,smb.last_error); ! 92: return(0); } ! 93: return(msg->total_hfields); ! 94: } ! 95: ! 96: ! 97: void sbbs_t::show_msgattr(ushort attr) ! 98: { ! 99: ! 100: bprintf(text[MsgAttr] ! 101: ,attr&MSG_PRIVATE ? "Private " :nulstr ! 102: ,attr&MSG_READ ? "Read " :nulstr ! 103: ,attr&MSG_DELETE ? "Deleted " :nulstr ! 104: ,attr&MSG_KILLREAD ? "Kill " :nulstr ! 105: ,attr&MSG_ANONYMOUS ? "Anonymous " :nulstr ! 106: ,attr&MSG_LOCKED ? "Locked " :nulstr ! 107: ,attr&MSG_PERMANENT ? "Permanent " :nulstr ! 108: ,attr&MSG_MODERATED ? "Moderated " :nulstr ! 109: ,attr&MSG_VALIDATED ? "Validated " :nulstr ! 110: ,attr&MSG_REPLIED ? "Replied " :nulstr ! 111: ,nulstr ! 112: ,nulstr ! 113: ,nulstr ! 114: ,nulstr ! 115: ,nulstr ! 116: ,nulstr ! 117: ); ! 118: } ! 119: ! 120: /****************************************************************************/ ! 121: /* Displays a message header to the screen */ ! 122: /****************************************************************************/ ! 123: void sbbs_t::show_msghdr(smbmsg_t* msg) ! 124: { ! 125: char *sender=NULL; ! 126: int i; ! 127: ! 128: attr(LIGHTGRAY); ! 129: if(useron.misc&CLRSCRN) ! 130: outchar(FF); ! 131: else ! 132: CRLF; ! 133: bprintf(text[MsgSubj],msg->subj); ! 134: if(msg->hdr.attr) ! 135: show_msgattr(msg->hdr.attr); ! 136: ! 137: bprintf(text[MsgTo],msg->to); ! 138: if(msg->to_ext) ! 139: bprintf(text[MsgToExt],msg->to_ext); ! 140: if(msg->to_net.addr) ! 141: bprintf(text[MsgToNet],msg->to_net.type==NET_FIDO ! 142: ? faddrtoa(*(faddr_t *)msg->to_net.addr) : msg->to_net.addr); ! 143: if(!(msg->hdr.attr&MSG_ANONYMOUS) || SYSOP) { ! 144: bprintf(text[MsgFrom],msg->from); ! 145: if(msg->from_ext) ! 146: bprintf(text[MsgFromExt],msg->from_ext); ! 147: if(msg->from_net.addr && !strchr(msg->from,'@')) ! 148: bprintf(text[MsgFromNet],msg->from_net.type==NET_FIDO ! 149: ? faddrtoa(*(faddr_t *)msg->from_net.addr) ! 150: : msg->from_net.addr); } ! 151: bprintf(text[MsgDate] ! 152: ,timestr((time_t *)&msg->hdr.when_written.time) ! 153: ,zonestr(msg->hdr.when_written.zone)); ! 154: ! 155: CRLF; ! 156: ! 157: for(i=0;i<msg->total_hfields;i++) { ! 158: if(msg->hfield[i].type==SENDER) ! 159: sender=(char *)msg->hfield_dat[i]; ! 160: if(msg->hfield[i].type==FORWARDED && sender) ! 161: bprintf(text[ForwardedFrom],sender ! 162: ,timestr((time_t *)msg->hfield_dat[i])); } ! 163: ! 164: /* Debug stuff ! 165: if(SYSOP) { ! 166: bprintf("\1n\1c\r\nAux : \1h%08lX",msg->hdr.auxattr); ! 167: bprintf("\1n\1c\r\nNum : \1h%lu",msg->hdr.number); } ! 168: */ ! 169: ! 170: CRLF; ! 171: } ! 172: ! 173: #if !LZH ! 174: ! 175: /****************************************************************************/ ! 176: /* Displays message header and text (if not deleted) */ ! 177: /****************************************************************************/ ! 178: void sbbs_t::show_msg(smbmsg_t msg, long mode) ! 179: { ! 180: ushort xlat; ! 181: int i; ! 182: ! 183: show_msghdr(msg); ! 184: for(i=0;i<msg.hdr.total_dfields;i++) ! 185: switch(msg.dfield[i].type) { ! 186: case TEXT_BODY: ! 187: case TEXT_TAIL: ! 188: smb_fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset ! 189: ,SEEK_SET); ! 190: smb_fread(&xlat,2,1,smb.sdt_fp); ! 191: if(xlat!=XLAT_NONE) /* no translations supported */ ! 192: continue; ! 193: putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode); ! 194: CRLF; ! 195: break; } ! 196: } ! 197: ! 198: #else ! 199: ! 200: /****************************************************************************/ ! 201: /* Displays message header and text (if not deleted) */ ! 202: /****************************************************************************/ ! 203: void sbbs_t::show_msg(smbmsg_t* msg, long mode) ! 204: { ! 205: uchar *inbuf,*lzhbuf; ! 206: ushort xlat; ! 207: int i,lzh; ! 208: long lzhlen,length; ! 209: ! 210: show_msghdr(msg); ! 211: for(i=0;i<msg->hdr.total_dfields;i++) ! 212: switch(msg->dfield[i].type) { ! 213: case TEXT_BODY: ! 214: case TEXT_TAIL: ! 215: fseek(smb.sdt_fp,msg->hdr.offset+msg->dfield[i].offset ! 216: ,SEEK_SET); ! 217: fread(&xlat,2,1,smb.sdt_fp); ! 218: lzh=0; ! 219: if(xlat==XLAT_LZH) { ! 220: lzh=1; ! 221: fread(&xlat,2,1,smb.sdt_fp); } ! 222: if(xlat!=XLAT_NONE) /* no translations supported */ ! 223: continue; ! 224: if(lzh) { ! 225: length=msg->dfield[i].length-4; ! 226: if((inbuf=(uchar *)MALLOC(length))==NULL) { ! 227: errormsg(WHERE,ERR_ALLOC,nulstr,length); ! 228: continue; } ! 229: fread(inbuf,length,1,smb.sdt_fp); ! 230: lzhlen=*(long *)inbuf; ! 231: /** ! 232: if(SYSOP) ! 233: bprintf("Decoding %lu bytes of LZH into %lu bytes of text " ! 234: "(%d%% compression)" ! 235: ,length,lzhlen ! 236: ,(int)(((float)(lzhlen-length)/lzhlen)*100.0)); ! 237: **/ ! 238: if((lzhbuf=(uchar *)MALLOC(lzhlen+2L))==NULL) { ! 239: FREE(inbuf); ! 240: errormsg(WHERE,ERR_ALLOC,nulstr,lzhlen+2L); ! 241: continue; } ! 242: lzh_decode(inbuf,length,lzhbuf); ! 243: lzhbuf[lzhlen]=0; ! 244: // CRLF; ! 245: putmsg((char *)lzhbuf,P_NOATCODES); ! 246: FREE(lzhbuf); ! 247: FREE(inbuf); } ! 248: else ! 249: putmsg_fp(smb.sdt_fp,msg->dfield[i].length-2,mode); ! 250: CRLF; ! 251: break; } ! 252: } ! 253: ! 254: #endif ! 255: ! 256: void sbbs_t::quotemsg(smbmsg_t* msg, int tails) ! 257: { ! 258: char str[256]; ! 259: ! 260: sprintf(str,"%sQUOTES.TXT",cfg.node_dir); ! 261: remove(str); ! 262: msgtotxt(msg,str,0,tails); ! 263: } ! 264: ! 265: ! 266: /****************************************************************************/ ! 267: /* Writes message header and text data to a text file */ ! 268: /****************************************************************************/ ! 269: void sbbs_t::msgtotxt(smbmsg_t* msg, char *str, int header, int tails) ! 270: { ! 271: char HUGE16 *buf; ! 272: int i; ! 273: FILE *out; ! 274: ! 275: if((out=fnopen(&i,str,O_WRONLY|O_CREAT|O_APPEND))==NULL) { ! 276: errormsg(WHERE,ERR_OPEN,str,0); ! 277: return; } ! 278: if(header) { ! 279: fprintf(out,"\r\n"); ! 280: fprintf(out,"Subj : %s\r\n",msg->subj); ! 281: fprintf(out,"To : %s",msg->to); ! 282: if(msg->to_ext) ! 283: fprintf(out," #%s",msg->to_ext); ! 284: if(msg->to_net.addr) ! 285: fprintf(out," (%s)",msg->to_net.type==NET_FIDO ! 286: ? faddrtoa(*(faddr_t *)msg->to_net.addr) : msg->to_net.addr); ! 287: fprintf(out,"\r\nFrom : %s",msg->from); ! 288: if(msg->from_ext && !(msg->hdr.attr&MSG_ANONYMOUS)) ! 289: fprintf(out," #%s",msg->from_ext); ! 290: if(msg->from_net.addr) ! 291: fprintf(out," (%s)",msg->from_net.type==NET_FIDO ! 292: ? faddrtoa(*(faddr_t *)msg->from_net.addr) ! 293: : msg->from_net.addr); ! 294: fprintf(out,"\r\nDate : %.24s %s" ! 295: ,timestr((time_t *)&msg->hdr.when_written.time) ! 296: ,zonestr(msg->hdr.when_written.zone)); ! 297: fprintf(out,"\r\n\r\n"); } ! 298: ! 299: buf=smb_getmsgtxt(&smb,msg,tails); ! 300: if(buf!=NULL) { ! 301: lfputs(buf,out); ! 302: LFREE(buf); ! 303: } else if(smb_getmsgdatlen(msg)>2) ! 304: errormsg(WHERE,ERR_READ,smb.file,smb_getmsgdatlen(msg)); ! 305: fclose(out); ! 306: } ! 307: ! 308: ! 309: /****************************************************************************/ ! 310: /* Returns total number of posts in a sub-board */ ! 311: /****************************************************************************/ ! 312: ulong sbbs_t::getposts(uint subnum) ! 313: { ! 314: char str[128]; ! 315: ulong l; ! 316: ! 317: sprintf(str,"%s%s.sid",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 318: l=flength(str); ! 319: if((long)l==-1) ! 320: return(0); ! 321: return(l/sizeof(idxrec_t)); ! 322: } ! 323: ! 324: /****************************************************************************/ ! 325: /* Returns message number posted at or after time */ ! 326: /****************************************************************************/ ! 327: ulong sbbs_t::getmsgnum(uint subnum, time_t t) ! 328: { ! 329: int i; ! 330: ulong l,total,bot,top; ! 331: smbmsg_t msg; ! 332: ! 333: if(!t) ! 334: return(0); ! 335: ! 336: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 337: smb.retry_time=cfg.smb_retry_time; ! 338: if((i=smb_open(&smb))!=0) { ! 339: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); ! 340: return(0); } ! 341: ! 342: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t); ! 343: ! 344: if(!total) { /* Empty base */ ! 345: smb_close(&smb); ! 346: return(0); } ! 347: ! 348: if((i=smb_locksmbhdr(&smb))!=0) { ! 349: smb_close(&smb); ! 350: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 351: return(0); } ! 352: ! 353: if((i=smb_getlastidx(&smb,&msg.idx))!=0) { ! 354: smb_close(&smb); ! 355: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); ! 356: return(0); } ! 357: ! 358: if((time_t)msg.idx.time<=t) { ! 359: smb_close(&smb); ! 360: return(msg.idx.number); } ! 361: ! 362: bot=0; ! 363: top=total; ! 364: l=total/2; /* Start at middle index */ ! 365: clearerr(smb.sid_fp); ! 366: while(1) { ! 367: fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET); ! 368: if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp)) ! 369: break; ! 370: if(bot==top-1) ! 371: break; ! 372: if((time_t)msg.idx.time>t) { ! 373: top=l; ! 374: l=bot+((top-bot)/2); ! 375: continue; } ! 376: if((time_t)msg.idx.time<t) { ! 377: bot=l; ! 378: l=top-((top-bot)/2); ! 379: continue; } ! 380: break; } ! 381: smb_close(&smb); ! 382: return(msg.idx.number); ! 383: } ! 384: ! 385: /****************************************************************************/ ! 386: /* Returns the time of the message number pointed to by 'ptr' */ ! 387: /****************************************************************************/ ! 388: time_t sbbs_t::getmsgtime(uint subnum, ulong ptr) ! 389: { ! 390: int i; ! 391: smbmsg_t msg; ! 392: idxrec_t lastidx; ! 393: ! 394: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 395: smb.retry_time=cfg.smb_retry_time; ! 396: if((i=smb_open(&smb))!=0) { ! 397: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); ! 398: return(0); } ! 399: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */ ! 400: smb_close(&smb); ! 401: return(0); } ! 402: msg.offset=0; ! 403: msg.hdr.number=0; ! 404: if(smb_getmsgidx(&smb,&msg)) { /* Get first message index */ ! 405: smb_close(&smb); ! 406: return(0); } ! 407: if(!ptr || msg.idx.number>=ptr) { /* ptr is before first message */ ! 408: smb_close(&smb); ! 409: return(msg.idx.time); } /* so return time of first msg */ ! 410: ! 411: if(smb_getlastidx(&smb,&lastidx)) { /* Get last message index */ ! 412: smb_close(&smb); ! 413: return(0); } ! 414: if(lastidx.number<ptr) { /* ptr is after last message */ ! 415: smb_close(&smb); ! 416: return(lastidx.time); } /* so return time of last msg */ ! 417: ! 418: msg.idx.time=0; ! 419: msg.hdr.number=ptr; ! 420: if(!smb_getmsgidx(&smb,&msg)) { ! 421: smb_close(&smb); ! 422: return(msg.idx.time); } ! 423: ! 424: if(ptr-msg.idx.number < lastidx.number-ptr) { ! 425: msg.offset=0; ! 426: msg.idx.number=0; ! 427: while(msg.idx.number<ptr) { ! 428: msg.hdr.number=0; ! 429: if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr) ! 430: break; ! 431: msg.offset++; } ! 432: smb_close(&smb); ! 433: return(msg.idx.time); } ! 434: ! 435: ptr--; ! 436: while(ptr) { ! 437: msg.hdr.number=ptr; ! 438: if(!smb_getmsgidx(&smb,&msg)) ! 439: break; ! 440: ptr--; } ! 441: smb_close(&smb); ! 442: return(msg.idx.time); ! 443: } ! 444: ! 445: ! 446: /****************************************************************************/ ! 447: /* Returns the total number of msgs in the sub-board and sets 'ptr' to the */ ! 448: /* number of the last message in the sub (0) if no messages. */ ! 449: /****************************************************************************/ ! 450: ulong sbbs_t::getlastmsg(uint subnum, ulong *ptr, time_t *t) ! 451: { ! 452: int i; ! 453: ulong total; ! 454: idxrec_t idx; ! 455: ! 456: if(ptr) ! 457: (*ptr)=0; ! 458: if(t) ! 459: (*t)=0; ! 460: if(subnum>=cfg.total_subs) ! 461: return(0); ! 462: ! 463: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 464: smb.retry_time=cfg.smb_retry_time; ! 465: if((i=smb_open(&smb))!=0) { ! 466: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); ! 467: return(0); } ! 468: ! 469: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */ ! 470: smb_close(&smb); ! 471: return(0); } ! 472: if((i=smb_locksmbhdr(&smb))!=0) { ! 473: smb_close(&smb); ! 474: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 475: return(0); } ! 476: if((i=smb_getlastidx(&smb,&idx))!=0) { ! 477: smb_close(&smb); ! 478: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); ! 479: return(0); } ! 480: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t); ! 481: smb_unlocksmbhdr(&smb); ! 482: smb_close(&smb); ! 483: if(ptr) ! 484: (*ptr)=idx.number; ! 485: if(t) ! 486: (*t)=idx.time; ! 487: return(total); ! 488: } ! 489:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.