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