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