|
|
1.1 ! root 1: /* getmsg.cpp */ ! 2: ! 3: /* Synchronet message retrieval functions */ ! 4: ! 5: /* $Id: getmsg.cpp,v 1.30 2005/09/30 09:12:37 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 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: /****************************************************************************/ ! 45: /* Loads an SMB message from the open msg base the fastest way possible */ ! 46: /* first by offset, and if that's the wrong message, then by number. */ ! 47: /* Returns 1 if the message was loaded and left locked, otherwise */ ! 48: /* !WARNING!: If you're going to write the msg index back to disk, you must */ ! 49: /* Call this function with a msg->idx.offset of 0 (so msg->offset will be */ ! 50: /* initialized correctly) */ ! 51: /****************************************************************************/ ! 52: int sbbs_t::loadmsg(smbmsg_t *msg, ulong number) ! 53: { ! 54: char str[128]; ! 55: int i; ! 56: ! 57: if(msg->idx.offset) { /* Load by offset if specified */ ! 58: ! 59: if((i=smb_lockmsghdr(&smb,msg))!=0) { ! 60: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 61: return(0); ! 62: } ! 63: ! 64: i=smb_getmsghdr(&smb,msg); ! 65: if(i==SMB_SUCCESS) { ! 66: if(msg->hdr.number==number) ! 67: return(1); ! 68: /* Wrong offset */ ! 69: smb_freemsgmem(msg); ! 70: } ! 71: ! 72: smb_unlockmsghdr(&smb,msg); ! 73: } ! 74: ! 75: msg->hdr.number=number; ! 76: if((i=smb_getmsgidx(&smb,msg))!=SMB_SUCCESS) /* Message is deleted */ ! 77: return(0); ! 78: if((i=smb_lockmsghdr(&smb,msg))!=SMB_SUCCESS) { ! 79: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 80: return(0); ! 81: } ! 82: if((i=smb_getmsghdr(&smb,msg))!=SMB_SUCCESS) { ! 83: sprintf(str,"(%06lX) #%lu/%lu %s",msg->idx.offset,msg->idx.number ! 84: ,number,smb.file); ! 85: smb_unlockmsghdr(&smb,msg); ! 86: errormsg(WHERE,ERR_READ,str,i,smb.last_error); ! 87: return(0); ! 88: } ! 89: return(msg->total_hfields); ! 90: } ! 91: ! 92: ! 93: void sbbs_t::show_msgattr(ushort attr) ! 94: { ! 95: ! 96: bprintf(text[MsgAttr] ! 97: ,attr&MSG_PRIVATE ? "Private " :nulstr ! 98: ,attr&MSG_READ ? "Read " :nulstr ! 99: ,attr&MSG_DELETE ? "Deleted " :nulstr ! 100: ,attr&MSG_KILLREAD ? "Kill " :nulstr ! 101: ,attr&MSG_ANONYMOUS ? "Anonymous " :nulstr ! 102: ,attr&MSG_LOCKED ? "Locked " :nulstr ! 103: ,attr&MSG_PERMANENT ? "Permanent " :nulstr ! 104: ,attr&MSG_MODERATED ? "Moderated " :nulstr ! 105: ,attr&MSG_VALIDATED ? "Validated " :nulstr ! 106: ,attr&MSG_REPLIED ? "Replied " :nulstr ! 107: ,nulstr ! 108: ,nulstr ! 109: ,nulstr ! 110: ,nulstr ! 111: ,nulstr ! 112: ,nulstr ! 113: ); ! 114: } ! 115: ! 116: /****************************************************************************/ ! 117: /* Displays a message header to the screen */ ! 118: /****************************************************************************/ ! 119: void sbbs_t::show_msghdr(smbmsg_t* msg) ! 120: { ! 121: char str[MAX_PATH+1]; ! 122: char *sender=NULL; ! 123: int i; ! 124: ! 125: current_msg=msg; ! 126: attr(LIGHTGRAY); ! 127: if(useron.misc&CLRSCRN) ! 128: outchar(FF); ! 129: else ! 130: CRLF; ! 131: ! 132: sprintf(str,"%smenu/msghdr.*", cfg.text_dir); ! 133: if(fexist(str)) { ! 134: menu("msghdr"); ! 135: current_msg=NULL; ! 136: return; ! 137: } ! 138: ! 139: bprintf(text[MsgSubj],msg->subj); ! 140: if(msg->hdr.attr) ! 141: show_msgattr(msg->hdr.attr); ! 142: ! 143: bprintf(text[MsgTo],msg->to); ! 144: if(msg->to_ext) ! 145: bprintf(text[MsgToExt],msg->to_ext); ! 146: if(msg->to_net.addr) ! 147: bprintf(text[MsgToNet],smb_netaddr(&msg->to_net)); ! 148: if(!(msg->hdr.attr&MSG_ANONYMOUS) || SYSOP) { ! 149: bprintf(text[MsgFrom],msg->from); ! 150: if(msg->from_ext) ! 151: bprintf(text[MsgFromExt],msg->from_ext); ! 152: if(msg->from_net.addr && !strchr(msg->from,'@')) ! 153: bprintf(text[MsgFromNet],smb_netaddr(&msg->from_net)); ! 154: } ! 155: bprintf(text[MsgDate] ! 156: ,timestr((time_t *)&msg->hdr.when_written.time) ! 157: ,smb_zonestr(msg->hdr.when_written.zone,NULL)); ! 158: ! 159: CRLF; ! 160: ! 161: for(i=0;i<msg->total_hfields;i++) { ! 162: if(msg->hfield[i].type==SENDER) ! 163: sender=(char *)msg->hfield_dat[i]; ! 164: if(msg->hfield[i].type==FORWARDED && sender) ! 165: bprintf(text[ForwardedFrom],sender ! 166: ,timestr((time_t *)msg->hfield_dat[i])); } ! 167: ! 168: /* Debug stuff ! 169: if(SYSOP) { ! 170: bprintf("\1n\1c\r\nAux : \1h%08lX",msg->hdr.auxattr); ! 171: bprintf("\1n\1c\r\nNum : \1h%lu",msg->hdr.number); } ! 172: */ ! 173: ! 174: CRLF; ! 175: current_msg=NULL; ! 176: } ! 177: ! 178: /****************************************************************************/ ! 179: /* Displays message header and text (if not deleted) */ ! 180: /****************************************************************************/ ! 181: void sbbs_t::show_msg(smbmsg_t* msg, long mode) ! 182: { ! 183: char* text; ! 184: ! 185: show_msghdr(msg); ! 186: ! 187: if((text=smb_getmsgtxt(&smb,msg,GETMSGTXT_ALL))!=NULL) { ! 188: truncsp_lines(text); ! 189: putmsg(text, mode); ! 190: smb_freemsgtxt(text); ! 191: } ! 192: } ! 193: ! 194: void sbbs_t::quotemsg(smbmsg_t* msg, int tails) ! 195: { ! 196: char str[256]; ! 197: char tmp[13]; ! 198: ! 199: strcpy(tmp,"QUOTES.TXT"); ! 200: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE) ! 201: strlwr(tmp); ! 202: sprintf(str,"%s%s",cfg.node_dir,tmp); ! 203: remove(str); ! 204: msgtotxt(msg,str,0,tails); ! 205: } ! 206: ! 207: ! 208: /****************************************************************************/ ! 209: /* Writes message header and text data to a text file */ ! 210: /****************************************************************************/ ! 211: void sbbs_t::msgtotxt(smbmsg_t* msg, char *str, int header, int tails) ! 212: { ! 213: char *buf; ! 214: int i; ! 215: FILE *out; ! 216: ! 217: if((out=fnopen(&i,str,O_WRONLY|O_CREAT|O_APPEND))==NULL) { ! 218: errormsg(WHERE,ERR_OPEN,str,0); ! 219: return; } ! 220: if(header) { ! 221: fprintf(out,"\r\n"); ! 222: fprintf(out,"Subj : %s\r\n",msg->subj); ! 223: fprintf(out,"To : %s",msg->to); ! 224: if(msg->to_ext) ! 225: fprintf(out," #%s",msg->to_ext); ! 226: if(msg->to_net.addr) ! 227: fprintf(out," (%s)",smb_netaddr(&msg->to_net)); ! 228: fprintf(out,"\r\nFrom : %s",msg->from); ! 229: if(msg->from_ext && !(msg->hdr.attr&MSG_ANONYMOUS)) ! 230: fprintf(out," #%s",msg->from_ext); ! 231: if(msg->from_net.addr) ! 232: fprintf(out," (%s)",smb_netaddr(&msg->from_net)); ! 233: fprintf(out,"\r\nDate : %.24s %s" ! 234: ,timestr((time_t *)&msg->hdr.when_written.time) ! 235: ,smb_zonestr(msg->hdr.when_written.zone,NULL)); ! 236: fprintf(out,"\r\n\r\n"); } ! 237: ! 238: buf=smb_getmsgtxt(&smb,msg,tails); ! 239: if(buf!=NULL) { ! 240: fputs(buf,out); ! 241: smb_freemsgtxt(buf); ! 242: } else if(smb_getmsgdatlen(msg)>2) ! 243: errormsg(WHERE,ERR_READ,smb.file,smb_getmsgdatlen(msg)); ! 244: fclose(out); ! 245: } ! 246: ! 247: /****************************************************************************/ ! 248: /* Returns message number posted at or after time */ ! 249: /****************************************************************************/ ! 250: ulong sbbs_t::getmsgnum(uint subnum, time_t t) ! 251: { ! 252: int i; ! 253: ulong l,total,bot,top; ! 254: smbmsg_t msg; ! 255: ! 256: if(!t) ! 257: return(0); ! 258: ! 259: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 260: smb.retry_time=cfg.smb_retry_time; ! 261: smb.subnum=subnum; ! 262: if((i=smb_open(&smb))!=0) { ! 263: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); ! 264: return(0); } ! 265: ! 266: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t); ! 267: ! 268: if(!total) { /* Empty base */ ! 269: smb_close(&smb); ! 270: return(0); } ! 271: ! 272: if((i=smb_locksmbhdr(&smb))!=0) { ! 273: smb_close(&smb); ! 274: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 275: return(0); } ! 276: ! 277: if((i=smb_getlastidx(&smb,&msg.idx))!=0) { ! 278: smb_close(&smb); ! 279: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); ! 280: return(0); } ! 281: ! 282: if((time_t)msg.idx.time<=t) { ! 283: smb_close(&smb); ! 284: return(msg.idx.number); } ! 285: ! 286: bot=0; ! 287: top=total; ! 288: l=total/2; /* Start at middle index */ ! 289: clearerr(smb.sid_fp); ! 290: while(1) { ! 291: fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET); ! 292: if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp)) ! 293: break; ! 294: if(bot==top-1) ! 295: break; ! 296: if((time_t)msg.idx.time>t) { ! 297: top=l; ! 298: l=bot+((top-bot)/2); ! 299: continue; } ! 300: if((time_t)msg.idx.time<t) { ! 301: bot=l; ! 302: l=top-((top-bot)/2); ! 303: continue; } ! 304: break; } ! 305: smb_close(&smb); ! 306: return(msg.idx.number); ! 307: } ! 308: ! 309: /****************************************************************************/ ! 310: /* Returns the time of the message number pointed to by 'ptr' */ ! 311: /****************************************************************************/ ! 312: time_t sbbs_t::getmsgtime(uint subnum, ulong ptr) ! 313: { ! 314: int i; ! 315: smbmsg_t msg; ! 316: idxrec_t lastidx; ! 317: ! 318: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 319: smb.retry_time=cfg.smb_retry_time; ! 320: smb.subnum=subnum; ! 321: if((i=smb_open(&smb))!=0) { ! 322: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); ! 323: return(0); } ! 324: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */ ! 325: smb_close(&smb); ! 326: return(0); } ! 327: msg.offset=0; ! 328: msg.hdr.number=0; ! 329: if(smb_getmsgidx(&smb,&msg)) { /* Get first message index */ ! 330: smb_close(&smb); ! 331: return(0); } ! 332: if(!ptr || msg.idx.number>=ptr) { /* ptr is before first message */ ! 333: smb_close(&smb); ! 334: return(msg.idx.time); } /* so return time of first msg */ ! 335: ! 336: if(smb_getlastidx(&smb,&lastidx)) { /* Get last message index */ ! 337: smb_close(&smb); ! 338: return(0); } ! 339: if(lastidx.number<ptr) { /* ptr is after last message */ ! 340: smb_close(&smb); ! 341: return(lastidx.time); } /* so return time of last msg */ ! 342: ! 343: msg.idx.time=0; ! 344: msg.hdr.number=ptr; ! 345: if(!smb_getmsgidx(&smb,&msg)) { ! 346: smb_close(&smb); ! 347: return(msg.idx.time); } ! 348: ! 349: if(ptr-msg.idx.number < lastidx.number-ptr) { ! 350: msg.offset=0; ! 351: msg.idx.number=0; ! 352: while(msg.idx.number<ptr) { ! 353: msg.hdr.number=0; ! 354: if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr) ! 355: break; ! 356: msg.offset++; } ! 357: smb_close(&smb); ! 358: return(msg.idx.time); } ! 359: ! 360: ptr--; ! 361: while(ptr) { ! 362: msg.hdr.number=ptr; ! 363: if(!smb_getmsgidx(&smb,&msg)) ! 364: break; ! 365: ptr--; } ! 366: smb_close(&smb); ! 367: return(msg.idx.time); ! 368: } ! 369: ! 370: ! 371: /****************************************************************************/ ! 372: /* Returns the total number of msgs in the sub-board and sets 'ptr' to the */ ! 373: /* number of the last message in the sub (0) if no messages. */ ! 374: /****************************************************************************/ ! 375: ulong sbbs_t::getlastmsg(uint subnum, ulong *ptr, time_t *t) ! 376: { ! 377: int i; ! 378: ulong total; ! 379: idxrec_t idx; ! 380: ! 381: if(ptr) ! 382: (*ptr)=0; ! 383: if(t) ! 384: (*t)=0; ! 385: if(subnum>=cfg.total_subs) ! 386: return(0); ! 387: ! 388: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code); ! 389: smb.retry_time=cfg.smb_retry_time; ! 390: smb.subnum=subnum; ! 391: if((i=smb_open(&smb))!=0) { ! 392: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error); ! 393: return(0); } ! 394: ! 395: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */ ! 396: smb_close(&smb); ! 397: return(0); } ! 398: if((i=smb_locksmbhdr(&smb))!=0) { ! 399: smb_close(&smb); ! 400: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error); ! 401: return(0); } ! 402: if((i=smb_getlastidx(&smb,&idx))!=0) { ! 403: smb_close(&smb); ! 404: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error); ! 405: return(0); } ! 406: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t); ! 407: smb_unlocksmbhdr(&smb); ! 408: smb_close(&smb); ! 409: if(ptr) ! 410: (*ptr)=idx.number; ! 411: if(t) ! 412: (*t)=idx.time; ! 413: return(total); ! 414: } ! 415:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.