|
|
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
109: );
110: }
111:
112: /****************************************************************************/
113: /* Displays a message header to the screen */
114: /****************************************************************************/
115: void show_msghdr(smbmsg_t msg)
116: {
117: char *sender=NULL;
118: int i;
119:
120: attr(LIGHTGRAY);
121: if(useron.misc&CLRSCRN)
122: outchar(FF);
123: else
124: CRLF;
125: bprintf(text[MsgSubj],msg.subj);
126: if(msg.hdr.attr)
127: show_msgattr(msg.hdr.attr);
128:
129: bprintf(text[MsgTo],msg.to);
130: if(msg.to_ext)
131: bprintf(text[MsgToExt],msg.to_ext);
132: if(msg.to_net.addr)
133: bprintf(text[MsgToNet],msg.to_net.type==NET_FIDO
134: ? faddrtoa(*(faddr_t *)msg.to_net.addr) : msg.to_net.addr);
135: if(!(msg.hdr.attr&MSG_ANONYMOUS) || SYSOP) {
136: bprintf(text[MsgFrom],msg.from);
137: if(msg.from_ext)
138: bprintf(text[MsgFromExt],msg.from_ext);
139: if(msg.from_net.addr)
140: bprintf(text[MsgFromNet],msg.from_net.type==NET_FIDO
141: ? faddrtoa(*(faddr_t *)msg.from_net.addr)
142: : msg.from_net.addr); }
143: bprintf(text[MsgDate]
144: ,timestr((time_t *)&msg.hdr.when_written.time)
145: ,zonestr(msg.hdr.when_written.zone));
146:
147: CRLF;
148:
149: for(i=0;i<msg.total_hfields;i++) {
150: if(msg.hfield[i].type==SENDER)
151: sender=msg.hfield_dat[i];
152: if(msg.hfield[i].type==FORWARDED && sender)
153: bprintf(text[ForwardedFrom],sender
154: ,timestr((time_t *)msg.hfield_dat[i])); }
155:
156: /* Debug stuff
157: if(SYSOP) {
158: bprintf("\1n\1c\r\nAux : \1h%08lX",msg.hdr.auxattr);
159: bprintf("\1n\1c\r\nNum : \1h%lu",msg.hdr.number); }
160: */
161:
162: CRLF;
163: }
164:
165: #if !LZH
166:
167: /****************************************************************************/
168: /* Displays message header and text (if not deleted) */
169: /****************************************************************************/
170: void show_msg(smbmsg_t msg, int mode)
171: {
172: ushort xlat;
173: int i;
174:
175: show_msghdr(msg);
176: for(i=0;i<msg.hdr.total_dfields;i++)
177: switch(msg.dfield[i].type) {
178: case TEXT_BODY:
179: case TEXT_TAIL:
180: fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
181: ,SEEK_SET);
182: fread(&xlat,2,1,smb.sdt_fp);
183: if(xlat!=XLAT_NONE) /* no translations supported */
184: continue;
185: putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode);
186: CRLF;
187: break; }
188: }
189:
190: #else
191:
192: /****************************************************************************/
193: /* Displays message header and text (if not deleted) */
194: /****************************************************************************/
195: void show_msg(smbmsg_t msg, int mode)
196: {
197: char *inbuf,*lzhbuf;
198: ushort xlat;
199: int i,lzh;
200: long lzhlen,length;
201:
202: show_msghdr(msg);
203: for(i=0;i<msg.hdr.total_dfields;i++)
204: switch(msg.dfield[i].type) {
205: case TEXT_BODY:
206: case TEXT_TAIL:
207: fseek(smb.sdt_fp,msg.hdr.offset+msg.dfield[i].offset
208: ,SEEK_SET);
209: fread(&xlat,2,1,smb.sdt_fp);
210: lzh=0;
211: if(xlat==XLAT_LZH) {
212: lzh=1;
213: fread(&xlat,2,1,smb.sdt_fp); }
214: if(xlat!=XLAT_NONE) /* no translations supported */
215: continue;
216: if(lzh) {
217: length=msg.dfield[i].length-4;
218: if((inbuf=MALLOC(length))==NULL) {
219: errormsg(WHERE,ERR_ALLOC,nulstr,length);
220: continue; }
221: fread(inbuf,length,1,smb.sdt_fp);
222: lzhlen=*(long *)inbuf;
223: /**
224: if(SYSOP)
225: bprintf("Decoding %lu bytes of LZH into %lu bytes of text "
226: "(%d%% compression)"
227: ,length,lzhlen
228: ,(int)(((float)(lzhlen-length)/lzhlen)*100.0));
229: **/
230: if((lzhbuf=MALLOC(lzhlen+2L))==NULL) {
231: FREE(inbuf);
232: errormsg(WHERE,ERR_ALLOC,nulstr,lzhlen+2L);
233: continue; }
234: lzh_decode(inbuf,length,lzhbuf);
235: lzhbuf[lzhlen]=0;
236: // CRLF;
237: putmsg(lzhbuf,P_NOATCODES);
238: FREE(lzhbuf);
239: FREE(inbuf); }
240: else
241: putmsg_fp(smb.sdt_fp,msg.dfield[i].length-2,mode);
242: CRLF;
243: break; }
244: }
245:
246: #endif
247:
248: void quotemsg(smbmsg_t msg, int tails)
249: {
250: char str[256];
251:
252: sprintf(str,"%sQUOTES.TXT",node_dir);
253: remove(str);
254: msgtotxt(msg,str,0,tails);
255: }
256:
257:
258: /****************************************************************************/
259: /* Writes message header and text data to a text file */
260: /****************************************************************************/
261: void msgtotxt(smbmsg_t msg, char *str, int header, int tails)
262: {
263: uchar HUGE16 *buf;
264: ushort xlat;
265: int i,j,x;
266: ulong l;
267: FILE *out;
268:
269: if((out=fnopen(&i,str,O_WRONLY|O_CREAT|O_APPEND))==NULL) {
270: errormsg(WHERE,ERR_OPEN,str,0);
271: return; }
272: if(header) {
273: fprintf(out,"\r\n");
274: fprintf(out,"Subj : %s\r\n",msg.subj);
275: fprintf(out,"To : %s",msg.to);
276: if(msg.to_ext)
277: fprintf(out," #%s",msg.to_ext);
278: if(msg.to_net.addr)
279: fprintf(out," (%s)",msg.to_net.type==NET_FIDO
280: ? faddrtoa(*(faddr_t *)msg.to_net.addr) : msg.to_net.addr);
281: fprintf(out,"\r\nFrom : %s",msg.from);
282: if(msg.from_ext && !(msg.hdr.attr&MSG_ANONYMOUS))
283: fprintf(out," #%s",msg.from_ext);
284: if(msg.from_net.addr)
285: fprintf(out," (%s)",msg.from_net.type==NET_FIDO
286: ? faddrtoa(*(faddr_t *)msg.from_net.addr)
287: : msg.from_net.addr);
288: fprintf(out,"\r\nDate : %.24s %s"
289: ,timestr((time_t *)&msg.hdr.when_written.time)
290: ,zonestr(msg.hdr.when_written.zone));
291: fprintf(out,"\r\n\r\n"); }
292:
293: buf=smb_getmsgtxt(&smb,&msg,tails);
294: if(buf) {
295: lfputs(buf,out);
296: LFREE(buf); }
297: else if(smb_getmsgdatlen(&msg)>2)
298: errormsg(WHERE,ERR_ALLOC,smb.file,smb_getmsgdatlen(&msg));
299: fclose(out);
300: }
301:
302:
303: /****************************************************************************/
304: /* Returns total number of posts in a sub-board */
305: /****************************************************************************/
306: ulong getposts(uint subnum)
307: {
308: char str[128];
309: ulong l;
310:
311: sprintf(str,"%s%s.SID",sub[subnum]->data_dir,sub[subnum]->code);
312: l=flength(str);
313: if((long)l==-1)
314: return(0);
315: return(l/sizeof(idxrec_t));
316: }
317:
318: /****************************************************************************/
319: /* Returns message number posted at or after time */
320: /****************************************************************************/
321: ulong getmsgnum(uint subnum, time_t t)
322: {
323: int i;
324: ulong l,total,bot,top;
325: smbmsg_t msg;
326:
327: if(!t)
328: return(0);
329:
330: sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
331: smb.retry_time=smb_retry_time;
332: if((i=smb_open(&smb))!=0) {
333: errormsg(WHERE,ERR_OPEN,smb.file,i);
334: return(0); }
335:
336: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
337:
338: if(!total) { /* Empty base */
339: smb_close(&smb);
340: return(0); }
341:
342: if((i=smb_locksmbhdr(&smb))!=0) {
343: smb_close(&smb);
344: errormsg(WHERE,ERR_LOCK,smb.file,i);
345: return(0); }
346:
347: if((i=smb_getlastidx(&smb,&msg.idx))!=0) {
348: smb_close(&smb);
349: errormsg(WHERE,ERR_READ,smb.file,i);
350: return(0); }
351:
352: if(msg.idx.time<=t) {
353: smb_close(&smb);
354: return(msg.idx.number); }
355:
356: bot=0;
357: top=total;
358: l=total/2; /* Start at middle index */
359: clearerr(smb.sid_fp);
360: while(1) {
361: fseek(smb.sid_fp,l*sizeof(idxrec_t),SEEK_SET);
362: if(!fread(&msg.idx,sizeof(idxrec_t),1,smb.sid_fp))
363: break;
364: if(bot==top-1)
365: break;
366: if(msg.idx.time>t) {
367: top=l;
368: l=bot+((top-bot)/2);
369: continue; }
370: if(msg.idx.time<t) {
371: bot=l;
372: l=top-((top-bot)/2);
373: continue; }
374: break; }
375: smb_close(&smb);
376: return(msg.idx.number);
377: }
378:
379: /****************************************************************************/
380: /* Returns the time of the message number pointed to by 'ptr' */
381: /****************************************************************************/
382: time_t getmsgtime(uint subnum, ulong ptr)
383: {
384: char str[128];
385: int i;
386: long l;
387: smbmsg_t msg;
388: idxrec_t lastidx;
389:
390: sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
391: smb.retry_time=smb_retry_time;
392: if((i=smb_open(&smb))!=0) {
393: errormsg(WHERE,ERR_OPEN,smb.file,i);
394: return(0); }
395: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */
396: smb_close(&smb);
397: return(0); }
398: msg.offset=0;
399: msg.hdr.number=0;
400: if(smb_getmsgidx(&smb,&msg)) { /* Get first message index */
401: smb_close(&smb);
402: return(0); }
403: if(!ptr || msg.idx.number>=ptr) { /* ptr is before first message */
404: smb_close(&smb);
405: return(msg.idx.time); } /* so return time of first msg */
406:
407: if(smb_getlastidx(&smb,&lastidx)) { /* Get last message index */
408: smb_close(&smb);
409: return(0); }
410: if(lastidx.number<ptr) { /* ptr is after last message */
411: smb_close(&smb);
412: return(lastidx.time); } /* so return time of last msg */
413:
414: msg.idx.time=0;
415: msg.hdr.number=ptr;
416: if(!smb_getmsgidx(&smb,&msg)) {
417: smb_close(&smb);
418: return(msg.idx.time); }
419:
420: if(ptr-msg.idx.number < lastidx.number-ptr) {
421: msg.offset=0;
422: msg.idx.number=0;
423: while(msg.idx.number<ptr) {
424: msg.hdr.number=0;
425: if(smb_getmsgidx(&smb,&msg) || msg.idx.number>=ptr)
426: break;
427: msg.offset++; }
428: smb_close(&smb);
429: return(msg.idx.time); }
430:
431: ptr--;
432: while(ptr) {
433: msg.hdr.number=ptr;
434: if(!smb_getmsgidx(&smb,&msg))
435: break;
436: ptr--; }
437: smb_close(&smb);
438: return(msg.idx.time);
439: }
440:
441:
442: /****************************************************************************/
443: /* Returns the total number of msgs in the sub-board and sets 'ptr' to the */
444: /* number of the last message in the sub (0) if no messages. */
445: /****************************************************************************/
446: ulong getlastmsg(uint subnum, ulong *ptr, time_t *t)
447: {
448: char str[256];
449: int i;
450: ulong total;
451: idxrec_t idx;
452:
453: if(ptr)
454: (*ptr)=0;
455: if(t)
456: (*t)=0;
457: if(subnum>=total_subs)
458: return(0);
459:
460: sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
461: smb.retry_time=smb_retry_time;
462: if((i=smb_open(&smb))!=0) {
463: errormsg(WHERE,ERR_OPEN,smb.file,i);
464: return(0); }
465:
466: if(!filelength(fileno(smb.sid_fp))) { /* Empty base */
467: smb_close(&smb);
468: return(0); }
469: if((i=smb_locksmbhdr(&smb))!=0) {
470: smb_close(&smb);
471: errormsg(WHERE,ERR_LOCK,smb.file,i);
472: return(0); }
473: if((i=smb_getlastidx(&smb,&idx))!=0) {
474: smb_close(&smb);
475: errormsg(WHERE,ERR_READ,smb.file,i);
476: return(0); }
477: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t);
478: smb_unlocksmbhdr(&smb);
479: smb_close(&smb);
480: if(ptr)
481: (*ptr)=idx.number;
482: if(t)
483: (*t)=idx.time;
484: return(total);
485: }
486:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.