|
|
1.1 root 1: /* getmsg.cpp */
2:
3: /* Synchronet message retrieval functions */
4:
1.1.1.2 ! root 5: /* $Id: getmsg.cpp,v 1.39 2011/08/25 19:22:44 rswindell Exp $ */
1.1 root 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: * *
1.1.1.2 ! root 11: * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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
1.1.1.2 ! root 107: ,attr&MSG_NOREPLY ? "NoReply " :nulstr
1.1 root 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)
1.1.1.2 ! root 147: bprintf(text[MsgToNet],smb_netaddrstr(&msg->to_net,str));
1.1 root 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,'@'))
1.1.1.2 ! root 153: bprintf(text[MsgFromNet],smb_netaddrstr(&msg->from_net,str));
1.1 root 154: }
155: bprintf(text[MsgDate]
1.1.1.2 ! root 156: ,timestr(msg->hdr.when_written.time)
1.1 root 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
1.1.1.2 ! root 166: ,timestr(*(time32_t *)msg->hfield_dat[i]));
! 167: }
1.1 root 168:
169: /* Debug stuff
170: if(SYSOP) {
171: bprintf("\1n\1c\r\nAux : \1h%08lX",msg->hdr.auxattr);
1.1.1.2 ! root 172: bprintf("\1n\1c\r\nNum : \1h%lu",msg->hdr.number);
! 173: }
1.1 root 174: */
175:
176: CRLF;
177: current_msg=NULL;
178: }
179:
180: /****************************************************************************/
181: /* Displays message header and text (if not deleted) */
182: /****************************************************************************/
183: void sbbs_t::show_msg(smbmsg_t* msg, long mode)
184: {
185: char* text;
186:
187: show_msghdr(msg);
188:
189: if((text=smb_getmsgtxt(&smb,msg,GETMSGTXT_ALL))!=NULL) {
190: truncsp_lines(text);
191: putmsg(text, mode);
192: smb_freemsgtxt(text);
193: }
194: }
195:
196: /****************************************************************************/
197: /* Writes message header and text data to a text file */
198: /****************************************************************************/
199: void sbbs_t::msgtotxt(smbmsg_t* msg, char *str, int header, int tails)
200: {
201: char *buf;
1.1.1.2 ! root 202: char tmp[128];
1.1 root 203: int i;
204: FILE *out;
205:
206: if((out=fnopen(&i,str,O_WRONLY|O_CREAT|O_APPEND))==NULL) {
207: errormsg(WHERE,ERR_OPEN,str,0);
1.1.1.2 ! root 208: return;
! 209: }
1.1 root 210: if(header) {
211: fprintf(out,"\r\n");
212: fprintf(out,"Subj : %s\r\n",msg->subj);
213: fprintf(out,"To : %s",msg->to);
214: if(msg->to_ext)
215: fprintf(out," #%s",msg->to_ext);
216: if(msg->to_net.addr)
1.1.1.2 ! root 217: fprintf(out," (%s)",smb_netaddrstr(&msg->to_net,tmp));
1.1 root 218: fprintf(out,"\r\nFrom : %s",msg->from);
219: if(msg->from_ext && !(msg->hdr.attr&MSG_ANONYMOUS))
220: fprintf(out," #%s",msg->from_ext);
221: if(msg->from_net.addr)
1.1.1.2 ! root 222: fprintf(out," (%s)",smb_netaddrstr(&msg->from_net,tmp));
1.1 root 223: fprintf(out,"\r\nDate : %.24s %s"
1.1.1.2 ! root 224: ,timestr(msg->hdr.when_written.time)
1.1 root 225: ,smb_zonestr(msg->hdr.when_written.zone,NULL));
1.1.1.2 ! root 226: fprintf(out,"\r\n\r\n");
! 227: }
1.1 root 228:
229: buf=smb_getmsgtxt(&smb,msg,tails);
230: if(buf!=NULL) {
1.1.1.2 ! root 231: strip_invalid_attr(buf);
1.1 root 232: fputs(buf,out);
233: smb_freemsgtxt(buf);
234: } else if(smb_getmsgdatlen(msg)>2)
235: errormsg(WHERE,ERR_READ,smb.file,smb_getmsgdatlen(msg));
236: fclose(out);
237: }
238:
239: /****************************************************************************/
240: /* Returns message number posted at or after time */
241: /****************************************************************************/
242: ulong sbbs_t::getmsgnum(uint subnum, time_t t)
243: {
244: int i;
245: ulong l,total,bot,top;
246: smbmsg_t msg;
247:
248: if(!t)
249: return(0);
250:
251: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
252: smb.retry_time=cfg.smb_retry_time;
253: smb.subnum=subnum;
254: if((i=smb_open(&smb))!=0) {
255: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 256: return(0);
! 257: }
1.1 root 258:
1.1.1.2 ! root 259: total=(long)filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
1.1 root 260:
261: if(!total) { /* Empty base */
262: smb_close(&smb);
1.1.1.2 ! root 263: return(0);
! 264: }
1.1 root 265:
266: if((i=smb_locksmbhdr(&smb))!=0) {
267: smb_close(&smb);
268: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
1.1.1.2 ! root 269: return(0);
! 270: }
1.1 root 271:
272: if((i=smb_getlastidx(&smb,&msg.idx))!=0) {
273: smb_close(&smb);
274: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error);
1.1.1.2 ! root 275: return(0);
! 276: }
1.1 root 277:
278: if((time_t)msg.idx.time<=t) {
279: smb_close(&smb);
1.1.1.2 ! root 280: return(msg.idx.number);
! 281: }
1.1 root 282:
283: bot=0;
284: top=total;
285: l=total/2; /* Start at middle index */
286: clearerr(smb.sid_fp);
287: while(1) {
288: fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET);
289: if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
290: break;
291: if(bot==top-1)
292: break;
293: if((time_t)msg.idx.time>t) {
294: top=l;
295: l=bot+((top-bot)/2);
1.1.1.2 ! root 296: continue;
! 297: }
1.1 root 298: if((time_t)msg.idx.time<t) {
299: bot=l;
300: l=top-((top-bot)/2);
1.1.1.2 ! root 301: continue;
! 302: }
! 303: break;
! 304: }
1.1 root 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);
1.1.1.2 ! root 323: return(0);
! 324: }
1.1 root 325: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */
326: smb_close(&smb);
1.1.1.2 ! root 327: return(0);
! 328: }
1.1 root 329: msg.offset=0;
330: msg.hdr.number=0;
331: if(smb_getmsgidx(&smb,&msg)) { /* Get first message index */
332: smb_close(&smb);
1.1.1.2 ! root 333: return(0);
! 334: }
1.1 root 335: if(!ptr || msg.idx.number>=ptr) { /* ptr is before first message */
336: smb_close(&smb);
1.1.1.2 ! root 337: return(msg.idx.time); /* so return time of first msg */
! 338: }
1.1 root 339:
340: if(smb_getlastidx(&smb,&lastidx)) { /* Get last message index */
341: smb_close(&smb);
1.1.1.2 ! root 342: return(0);
! 343: }
1.1 root 344: if(lastidx.number<ptr) { /* ptr is after last message */
345: smb_close(&smb);
1.1.1.2 ! root 346: return(lastidx.time); /* so return time of last msg */
! 347: }
1.1 root 348:
349: msg.idx.time=0;
350: msg.hdr.number=ptr;
351: if(!smb_getmsgidx(&smb,&msg)) {
352: smb_close(&smb);
1.1.1.2 ! root 353: return(msg.idx.time);
! 354: }
1.1 root 355:
356: if(ptr-msg.idx.number < lastidx.number-ptr) {
357: msg.offset=0;
358: msg.idx.number=0;
359: while(msg.idx.number<ptr) {
360: msg.hdr.number=0;
361: if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr)
362: break;
1.1.1.2 ! root 363: msg.offset++;
! 364: }
1.1 root 365: smb_close(&smb);
1.1.1.2 ! root 366: return(msg.idx.time);
! 367: }
1.1 root 368:
369: ptr--;
370: while(ptr) {
371: msg.hdr.number=ptr;
372: if(!smb_getmsgidx(&smb,&msg))
373: break;
1.1.1.2 ! root 374: ptr--;
! 375: }
1.1 root 376: smb_close(&smb);
377: return(msg.idx.time);
378: }
379:
380:
381: /****************************************************************************/
382: /* Returns the total number of msgs in the sub-board and sets 'ptr' to the */
383: /* number of the last message in the sub (0) if no messages. */
384: /****************************************************************************/
1.1.1.2 ! root 385: ulong sbbs_t::getlastmsg(uint subnum, uint32_t *ptr, time_t *t)
1.1 root 386: {
387: int i;
388: ulong total;
389: idxrec_t idx;
390:
391: if(ptr)
392: (*ptr)=0;
393: if(t)
394: (*t)=0;
395: if(subnum>=cfg.total_subs)
396: return(0);
397:
398: sprintf(smb.file,"%s%s",cfg.sub[subnum]->data_dir,cfg.sub[subnum]->code);
399: smb.retry_time=cfg.smb_retry_time;
400: smb.subnum=subnum;
401: if((i=smb_open(&smb))!=0) {
402: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 403: return(0);
! 404: }
1.1 root 405:
406: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */
407: smb_close(&smb);
1.1.1.2 ! root 408: return(0);
! 409: }
1.1 root 410: if((i=smb_locksmbhdr(&smb))!=0) {
411: smb_close(&smb);
412: errormsg(WHERE,ERR_LOCK,smb.file,i,smb.last_error);
1.1.1.2 ! root 413: return(0);
! 414: }
1.1 root 415: if((i=smb_getlastidx(&smb,&idx))!=0) {
416: smb_close(&smb);
417: errormsg(WHERE,ERR_READ,smb.file,i,smb.last_error);
1.1.1.2 ! root 418: return(0);
! 419: }
! 420: total=(long)filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
1.1 root 421: smb_unlocksmbhdr(&smb);
422: smb_close(&smb);
423: if(ptr)
424: (*ptr)=idx.number;
425: if(t)
426: (*t)=idx.time;
427: return(total);
428: }
429:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.