|
|
1.1 root 1: #line 1 "READMSGS.C"
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: #include "sbbs.h"
6: #include "post.h"
7:
8: char movemsg(smbmsg_t msg, uint subnum);
9: void editmsg(smbmsg_t *msg, uint subnum);
10:
11: int sub_op(uint subnum)
12: {
13: return(SYSOP || (sub[subnum]->op_ar[0] && chk_ar(sub[subnum]->op_ar,useron)));
14: }
15:
16:
17: void listmsgs(int subnum, post_t HUGE16 *post, long i, long posts)
18: {
19: char ch;
20: int j;
21: smbmsg_t msg;
22:
23:
24: bputs(text[MailOnSystemLstHdr]);
25: msg.total_hfields=0;
26: while(i<posts && !msgabort()) {
27: if(msg.total_hfields)
28: smb_freemsgmem(&msg);
29: msg.total_hfields=0;
30: msg.idx.offset=post[i].offset;
31: if(!loadmsg(&msg,post[i].number))
32: break;
33: smb_unlockmsghdr(&smb,&msg);
34: if(msg.hdr.attr&MSG_DELETE)
35: ch='-';
36: else if((!stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name))
37: && !(msg.hdr.attr&MSG_READ))
38: ch='!';
39: else if(msg.hdr.number>sub[subnum]->ptr)
40: ch='*';
41: else
42: ch=' ';
43: bprintf(text[SubMsgLstFmt],(long)i+1
44: ,msg.hdr.attr&MSG_ANONYMOUS && !sub_op(subnum)
45: ? text[Anonymous] : msg.from
46: ,msg.to
47: ,ch
48: ,msg.subj);
49: smb_freemsgmem(&msg);
50: msg.total_hfields=0;
51: i++; }
52: }
53:
54: char *binstr(uchar *buf, ushort length)
55: {
56: static char str[128];
57: char tmp[128];
58: int i;
59:
60: str[0]=0;
61: for(i=0;i<length;i++)
62: if(buf[i] && (buf[i]<SP || buf[i]>=0x7f))
63: break;
64: if(i==length) /* not binary */
65: return(buf);
66: for(i=0;i<length;i++) {
67: sprintf(tmp,"%02X ",buf[i]);
68: strcat(str,tmp); }
69: return(str);
70: }
71:
72:
73: void msghdr(smbmsg_t msg)
74: {
75: int i;
76:
77: for(i=0;i<msg.total_hfields;i++)
78: bprintf("hfield[%u].type %02Xh\r\n"
79: "hfield[%u].length %d\r\n"
80: "hfield[%u]_dat %s\r\n"
81: ,i,msg.hfield[i].type
82: ,i,msg.hfield[i].length
83: ,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
84: }
85:
86: /****************************************************************************/
87: /****************************************************************************/
88: post_t HUGE16 *loadposts(ulong *posts, uint subnum, ulong ptr, uint mode)
89: {
90: char name[128];
91: ushort aliascrc,namecrc,sysop;
92: int i,file,skip;
93: ulong l=0,total,alloc_len;
94: smbmsg_t msg;
95: idxrec_t idx;
96: post_t HUGE16 *post;
97:
98: if(posts==NULL)
99: return(NULL);
100:
101: (*posts)=0;
102:
103: if((i=smb_locksmbhdr(&smb))!=0) { /* Be sure noone deletes or */
104: errormsg(WHERE,ERR_LOCK,smb.file,i); /* adds while we're reading */
105: return(NULL); }
106:
107: total=filelength(fileno(smb.sid_fp))/sizeof(idxrec_t); /* total msgs in sub */
108:
109: if(!total) { /* empty */
110: smb_unlocksmbhdr(&smb);
111: return(NULL); }
112:
113: strcpy(name,useron.name);
114: strlwr(name);
115: namecrc=crc16(name);
116: strcpy(name,useron.alias);
117: strlwr(name);
118: aliascrc=crc16(name);
119: sysop=crc16("sysop");
120:
121: rewind(smb.sid_fp);
122:
123: alloc_len=sizeof(post_t)*total;
124: #ifdef __OS2__
125: while(alloc_len%4096)
126: alloc_len++;
127: #endif
128: if((post=(post_t HUGE16 *)LMALLOC(alloc_len))==NULL) { /* alloc for max */
129: smb_unlocksmbhdr(&smb);
130: errormsg(WHERE,ERR_ALLOC,smb.file,sizeof(post_t *)*sub[subnum]->maxmsgs);
131: return(NULL); }
132: while(!feof(smb.sid_fp)) {
133: skip=0;
134: if(!fread(&idx,sizeof(idxrec_t),1,smb.sid_fp))
135: break;
136:
137: if(idx.number<=ptr)
138: continue;
139:
140: if(idx.attr&MSG_READ && mode&LP_UNREAD) /* Skip read messages */
141: continue;
142:
143: if(idx.attr&MSG_DELETE) { /* Pre-flagged */
144: if(mode&LP_REP) /* Don't include deleted msgs in REP pkt */
145: continue;
146: if(!(sys_misc&SM_SYSVDELM)) /* Noone can view deleted msgs */
147: continue;
148: if(!(sys_misc&SM_USRVDELM) /* Users can't view deleted msgs */
149: && !sub_op(subnum)) /* not sub-op */
150: continue;
151: if(!sub_op(subnum) /* not sub-op */
152: && idx.from!=namecrc && idx.from!=aliascrc) /* not for you */
153: continue; }
154:
155: if(idx.attr&MSG_MODERATED && !(idx.attr&MSG_VALIDATED)
156: && (mode&LP_REP || !sub_op(subnum)))
157: break;
158:
159: if(idx.attr&MSG_PRIVATE && !(mode&LP_PRIVATE)
160: && !sub_op(subnum) && !(useron.rest&FLAG('Q'))) {
161: if(idx.to!=namecrc && idx.from!=namecrc
162: && idx.to!=aliascrc && idx.from!=aliascrc
163: && (useron.number!=1 || idx.to!=sysop))
164: continue;
165: if(!smb_lockmsghdr(&smb,&msg)) {
166: if(!smb_getmsghdr(&smb,&msg)) {
167: if(stricmp(msg.to,useron.alias)
168: && stricmp(msg.from,useron.alias)
169: && stricmp(msg.to,useron.name)
170: && stricmp(msg.from,useron.name)
171: && (useron.number!=1 || stricmp(msg.to,"sysop")
172: || msg.from_net.type))
173: skip=1;
174: smb_freemsgmem(&msg); }
175: smb_unlockmsghdr(&smb,&msg); }
176: if(skip)
177: continue; }
178:
179:
180: if(!(mode&LP_BYSELF) && (idx.from==namecrc || idx.from==aliascrc)) {
181: msg.idx=idx;
182: if(!smb_lockmsghdr(&smb,&msg)) {
183: if(!smb_getmsghdr(&smb,&msg)) {
184: if(!stricmp(msg.from,useron.alias)
185: || !stricmp(msg.from,useron.name))
186: skip=1;
187: smb_freemsgmem(&msg); }
188: smb_unlockmsghdr(&smb,&msg); }
189: if(skip)
190: continue; }
191:
192: if(!(mode&LP_OTHERS)) {
193: if(idx.to!=namecrc && idx.to!=aliascrc
194: && (useron.number!=1 || idx.to!=sysop))
195: continue;
196: msg.idx=idx;
197: if(!smb_lockmsghdr(&smb,&msg)) {
198: if(!smb_getmsghdr(&smb,&msg)) {
199: if(stricmp(msg.to,useron.alias) && stricmp(msg.to,useron.name)
200: && (useron.number!=1 || stricmp(msg.to,"sysop")
201: || msg.from_net.type))
202: skip=1;
203: smb_freemsgmem(&msg); }
204: smb_unlockmsghdr(&smb,&msg); }
205: if(skip)
206: continue; }
207:
208: post[l].offset=idx.offset;
209: post[l].number=idx.number;
210: post[l].to=idx.to;
211: post[l].from=idx.from;
212: post[l].subj=idx.subj;
213: l++; }
214: smb_unlocksmbhdr(&smb);
215: if(!l) {
216: LFREE(post);
217: post=NULL; }
218: (*posts)=l;
219: return(post);
220: }
221:
222:
223: /****************************************************************************/
224: /* Reads posts on subboard sub. 'mode' determines new-posts only, browse, */
225: /* or continuous read. */
226: /* Returns 0 if normal completion, 1 if aborted. */
227: /* Called from function main_sec */
228: /****************************************************************************/
229: char scanposts(uint subnum, char mode, char *find)
230: {
231: char str[256],str2[256],str3[256],reread=0,mismatches=0
232: ,done=0,domsg=1,HUGE16 *buf,*p;
233: int file,i,j,usub,ugrp,reads=0;
234: uint lp=0;
235: long curpost;
236: ulong msgs,last,posts,l;
237: post_t HUGE16 *post;
238: smbmsg_t msg;
239:
240: cursubnum=subnum; /* for ARS */
241: if(!chk_ar(sub[subnum]->read_ar,useron)) {
242: bprintf("\1n\r\nYou can't read messages on %s %s\r\n"
243: ,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
244: return(0); }
245: msg.total_hfields=0; /* init to NULL, specify not-allocated */
246: if(!(mode&SCAN_CONST))
247: lncntr=0;
248: if((msgs=getlastmsg(subnum,&last,0))==0) {
249: if(mode&(SCAN_NEW|SCAN_TOYOU))
250: bprintf(text[NScanStatusFmt]
251: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,0L,0L);
252: else
253: bprintf(text[NoMsgsOnSub]
254: ,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
255: return(0); }
256: if(mode&SCAN_NEW && sub[subnum]->ptr>=last && !(mode&SCAN_BACK)) {
257: if(sub[subnum]->ptr>last)
258: sub[subnum]->ptr=sub[subnum]->last=last;
259: bprintf(text[NScanStatusFmt]
260: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,0L,msgs);
261: return(0); }
262:
263: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
264: errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
265: return(0); }
266: sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
267: smb.retry_time=smb_retry_time;
268: if((i=smb_open(&smb))!=0) {
269: smb_stack(&smb,SMB_STACK_POP);
270: errormsg(WHERE,ERR_OPEN,smb.file,i);
271: return(0); }
272:
273: if(!(mode&SCAN_TOYOU)
274: && (!mode || mode&SCAN_FIND || !(sub[subnum]->misc&SUB_YSCAN)))
275: lp=LP_BYSELF|LP_OTHERS;
276: if(mode&SCAN_TOYOU)
277: lp|=LP_UNREAD;
278: post=loadposts(&posts,subnum,0,lp);
279: if(mode&SCAN_NEW) { /* Scanning for new messages */
280: for(curpost=0;curpost<posts;curpost++)
281: if(sub[subnum]->ptr<post[curpost].number)
282: break;
283: bprintf(text[NScanStatusFmt]
284: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts-curpost,msgs);
285: if(!posts) { /* no messages at all */
286: smb_close(&smb);
287: smb_stack(&smb,SMB_STACK_POP);
288: return(0); }
289: if(curpost==posts) { /* no new messages */
290: if(!(mode&SCAN_BACK)) {
291: if(post)
292: LFREE(post);
293: smb_close(&smb);
294: smb_stack(&smb,SMB_STACK_POP);
295: return(0); }
296: curpost=posts-1; } }
297: else {
298: if(mode&SCAN_TOYOU)
299: bprintf(text[NScanStatusFmt]
300: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts,msgs);
301: if(!posts) {
302: if(!(mode&SCAN_TOYOU))
303: bprintf(text[NoMsgsOnSub]
304: ,grp[sub[subnum]->grp]->sname,sub[subnum]->sname);
305: smb_close(&smb);
306: smb_stack(&smb,SMB_STACK_POP);
307: return(0); }
308: if(mode&SCAN_FIND) {
309: bprintf(text[SearchSubFmt]
310: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts);
311: domsg=1;
312: curpost=0; }
313: else if(mode&SCAN_TOYOU)
314: curpost=0;
315: else {
316: for(curpost=0;curpost<posts;curpost++)
317: if(post[curpost].number>=sub[subnum]->last)
318: break;
319: if(curpost==posts)
320: curpost=posts-1;
321:
322: domsg=1; } }
323:
324: if(useron.misc&RIP)
325: menu("MSGSCAN");
326:
327: if((i=smb_locksmbhdr(&smb))!=0) {
328: smb_close(&smb);
329: smb_stack(&smb,SMB_STACK_POP);
330: errormsg(WHERE,ERR_LOCK,smb.file,i);
331: return(0); }
332: if((i=smb_getstatus(&smb))!=0) {
333: smb_close(&smb);
334: smb_stack(&smb,SMB_STACK_POP);
335: errormsg(WHERE,ERR_READ,smb.file,i);
336: return(0); }
337: smb_unlocksmbhdr(&smb);
338: last=smb.status.last_msg;
339:
340: action=NODE_RMSG;
341: if(mode&SCAN_CONST) { /* update action */
342: getnodedat(node_num,&thisnode,1);
343: thisnode.action=NODE_RMSG;
344: putnodedat(node_num,thisnode); }
345: while(online && !done) {
346:
347: action=NODE_RMSG;
348: if((i=heapcheck())!=_HEAPOK) {
349: errormsg(WHERE,ERR_CHK,"heap",i);
350: break; }
351:
352: if(mode&(SCAN_CONST|SCAN_FIND) && sys_status&SS_ABORT)
353: break;
354:
355: if(post==NULL) /* Been unloaded */
356: post=loadposts(&posts,subnum,0,lp); /* So re-load */
357:
358: if(!posts) {
359: done=1;
360: continue; }
361:
362: while(curpost>=posts) curpost--;
363:
364: for(ugrp=0;ugrp<usrgrps;ugrp++)
365: if(usrgrp[ugrp]==sub[subnum]->grp)
366: break;
367: for(usub=0;usub<usrsubs[ugrp];usub++)
368: if(usrsub[ugrp][usub]==subnum)
369: break;
370: usub++;
371: ugrp++;
372:
373: msg.idx.offset=post[curpost].offset;
374: msg.idx.number=post[curpost].number;
375: msg.idx.to=post[curpost].to;
376: msg.idx.from=post[curpost].from;
377: msg.idx.subj=post[curpost].subj;
378:
379: if((i=smb_locksmbhdr(&smb))!=0) {
380: errormsg(WHERE,ERR_LOCK,smb.file,i);
381: break; }
382: if((i=smb_getstatus(&smb))!=0) {
383: smb_unlocksmbhdr(&smb);
384: errormsg(WHERE,ERR_READ,smb.file,i);
385: break; }
386: smb_unlocksmbhdr(&smb);
387:
388: if(smb.status.last_msg!=last) { /* New messages */
389: last=smb.status.last_msg;
390: if(post) {
391: LFREE((void *)post); }
392: post=loadposts(&posts,subnum,0,lp); /* So re-load */
393: if(!posts)
394: break;
395: for(curpost=0;curpost<posts;curpost++)
396: if(post[curpost].number==msg.idx.number)
397: break;
398: if(curpost>(posts-1))
399: curpost=(posts-1);
400: continue; }
401:
402: if(msg.total_hfields)
403: smb_freemsgmem(&msg);
404: msg.total_hfields=0;
405:
406: if(!loadmsg(&msg,post[curpost].number)) {
407: if(mismatches>5) { /* We can't do this too many times in a row */
408: errormsg(WHERE,ERR_CHK,smb.file,post[curpost].number);
409: break; }
410: if(post)
411: LFREE(post);
412: post=loadposts(&posts,subnum,0,lp);
413: if(!posts)
414: break;
415: if(curpost>(posts-1))
416: curpost=(posts-1);
417: mismatches++;
418: continue; }
419: smb_unlockmsghdr(&smb,&msg);
420:
421: mismatches=0;
422:
423: if(domsg) {
424:
425: if(!reread && mode&SCAN_FIND) { /* Find text in messages */
426: buf=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS);
427: if(!buf) {
428: if(curpost<posts-1) curpost++;
429: else done=1;
430: continue; }
431: strupr((char *)buf);
432: if(!strstr((char *)buf,find) && !strstr(msg.subj,find)) {
433: FREE(buf);
434: if(curpost<posts-1) curpost++;
435: else done=1;
436: continue; }
437: FREE(buf); }
438:
439: if(mode&SCAN_CONST)
440: bprintf(text[ZScanPostHdr],ugrp,usub,curpost+1,posts);
441:
442: if(!reads && mode)
443: CRLF;
444:
445: show_msg(msg
446: ,msg.from_ext && !strcmp(msg.from_ext,"1") && !msg.from_net.type
447: ? 0:P_NOATCODES);
448:
449: reads++; /* number of messages actually read during this sub-scan */
450:
451: /* Message is to this user and hasn't been read, so flag as read */
452: if((!stricmp(msg.to,useron.name) || !stricmp(msg.to,useron.alias)
453: || (useron.number==1 && !stricmp(msg.to,"sysop")
454: && !msg.from_net.type))
455: && !(msg.hdr.attr&MSG_READ)) {
456: if(msg.total_hfields)
457: smb_freemsgmem(&msg);
458: msg.total_hfields=0;
459: msg.idx.offset=0;
460: if(!smb_locksmbhdr(&smb)) { /* Lock the entire base */
461: if(loadmsg(&msg,msg.idx.number)) {
462: msg.hdr.attr|=MSG_READ;
463: msg.idx.attr=msg.hdr.attr;
464: if((i=smb_putmsg(&smb,&msg))!=0)
465: errormsg(WHERE,ERR_WRITE,smb.file,i);
466: smb_unlockmsghdr(&smb,&msg); }
467: smb_unlocksmbhdr(&smb); }
468: if(!msg.total_hfields) { /* unsuccessful reload */
469: domsg=0;
470: continue; } }
471:
472: sub[subnum]->last=post[curpost].number;
473:
474: if(sub[subnum]->ptr<post[curpost].number && !(mode&SCAN_TOYOU)) {
475: posts_read++;
476: sub[subnum]->ptr=post[curpost].number; } }
477: else domsg=1;
478: if(mode&SCAN_CONST) {
479: if(curpost<posts-1) curpost++;
480: else done=1;
481: continue; }
482: if(useron.misc&WIP)
483: menu("MSGSCAN");
484: ASYNC;
485: bprintf(text[ReadingSub],ugrp,grp[sub[subnum]->grp]->sname
486: ,usub,sub[subnum]->sname,curpost+1,posts);
487: sprintf(str,"ABCDFILMPQRTY?<>[]{}-+.,");
488: if(sub_op(subnum))
489: strcat(str,"O");
490: reread=0;
491: l=getkeys(str,posts);
492: if(l&0x80000000L) {
493: if((long)l==-1) { /* ctrl-c */
494: if(msg.total_hfields)
495: smb_freemsgmem(&msg);
496: if(post)
497: LFREE(post);
498: smb_close(&smb);
499: smb_stack(&smb,SMB_STACK_POP);
500: return(1); }
501: curpost=(l&~0x80000000L)-1;
502: reread=1;
503: continue; }
504: switch(l) {
505: case 'A': /* Reply to last message */
506: domsg=0;
507: if(!chk_ar(sub[subnum]->post_ar,useron)) {
508: bputs(text[CantPostOnSub]);
509: break; }
510: quotemsg(msg,0);
511: if(post)
512: LFREE(post);
513: post=NULL;
514: postmsg(subnum,&msg,WM_QUOTE);
515: // post=loadposts(&posts,subnum,0,lp);
516: if(mode&SCAN_TOYOU)
517: domsg=1;
518: break;
519: case 'B': /* Skip sub-board */
520: if(mode&SCAN_NEW && !noyes(text[RemoveFromNewScanQ]))
521: sub[subnum]->misc&=~SUB_NSCAN;
522: if(msg.total_hfields)
523: smb_freemsgmem(&msg);
524: if(post)
525: LFREE(post);
526: smb_close(&smb);
527: smb_stack(&smb,SMB_STACK_POP);
528: return(0);
529: case 'C': /* Continuous */
530: mode|=SCAN_CONST;
531: if(curpost<posts-1) curpost++;
532: else done=1;
533: break;
534: case 'D': /* Delete message on sub-board */
535: domsg=0;
536: if(!sub_op(subnum) && !(sub[subnum]->misc&SUB_DEL)) {
537: bputs(text[CantDeletePosts]);
538: break; }
539: if(!sub_op(subnum)) {
540: if(stricmp(sub[subnum]->misc&SUB_NAME
541: ? useron.name : useron.alias, msg.from)
542: && stricmp(sub[subnum]->misc&SUB_NAME
543: ? useron.name : useron.alias, msg.to)) {
544: bprintf(text[YouDidntPostMsgN],curpost+1);
545: break; } }
546: if(msg.hdr.attr&MSG_PERMANENT) {
547: bputs("\1n\r\nMessage is marked permanent.\r\n");
548: domsg=0;
549: break; }
550: if(post)
551: LFREE(post);
552: post=NULL;
553:
554: if(msg.total_hfields)
555: smb_freemsgmem(&msg);
556: msg.total_hfields=0;
557: msg.idx.offset=0;
558: if(loadmsg(&msg,msg.idx.number)) {
559: msg.idx.attr^=MSG_DELETE;
560: msg.hdr.attr=msg.idx.attr;
561: if((i=smb_putmsg(&smb,&msg))!=0)
562: errormsg(WHERE,ERR_WRITE,smb.file,i);
563: smb_unlockmsghdr(&smb,&msg);
564: if(i==0 && msg.idx.attr&MSG_DELETE) {
565: sprintf(str,"Removed post from %s %s"
566: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname);
567: logline("P-",str);
568: if(!stricmp(sub[subnum]->misc&SUB_NAME
569: ? useron.name : useron.alias, msg.from))
570: useron.posts=adjustuserrec(useron.number
571: ,U_POSTS,5,-1); } }
572: domsg=1;
573: if((sys_misc&SM_SYSVDELM // anyone can view delete msgs
574: || (sys_misc&SM_USRVDELM // sys/subops can view deleted msgs
575: && sub_op(subnum)))
576: && curpost<posts-1)
577: curpost++;
578: if(curpost>=posts-1)
579: done=1;
580: break;
581:
582: case 'F': /* find text in messages */
583: domsg=0;
584: bprintf(text[StartWithN],curpost+2);
585: if((i=getnum(posts))<0)
586: break;
587: if(i)
588: i--;
589: else
590: i=curpost+1;
591: bputs(text[SearchStringPrompt]);
592: if(!getstr(str,40,K_LINE|K_UPPER))
593: break;
594: searchposts(subnum,post,(long)i,posts,str);
595: break;
596: case 'I': /* Sub-board information */
597: domsg=0;
598: subinfo(subnum);
599: break;
600: case 'L': /* List messages */
601: domsg=0;
602: bprintf(text[StartWithN],curpost+1);
603: if((i=getnum(posts))<0)
604: break;
605: if(i) i--;
606: else i=curpost;
607: listmsgs(subnum,post,i,posts);
608: break;
609: case 'M': /* Reply to last post in mail */
610: domsg=0;
611: if(msg.hdr.attr&MSG_ANONYMOUS && !sub_op(subnum)) {
612: bputs(text[CantReplyToAnonMsg]);
613: break; }
614: if(!sub_op(subnum) && msg.hdr.attr&MSG_PRIVATE
615: && stricmp(msg.to,useron.name)
616: && stricmp(msg.to,useron.alias))
617: break;
618: sprintf(str2,text[Regarding]
619: ,msg.subj
620: ,timestr((time_t *)&msg.hdr.when_written.time));
621: if(msg.from_net.type==NET_FIDO)
622: sprintf(str,"%s @%s",msg.from
623: ,faddrtoa(*(faddr_t *)msg.from_net.addr));
624: else if(msg.from_net.type==NET_INTERNET)
625: strcpy(str,msg.from_net.addr);
626: else if(msg.from_net.type)
627: sprintf(str,"%s@%s",msg.from,msg.from_net.addr);
628: else
629: strcpy(str,msg.from);
630: bputs(text[Email]);
631: if(!getstr(str,60,K_EDIT|K_AUTODEL))
632: break;
633: if(post)
634: LFREE(post);
635: post=NULL;
636: quotemsg(msg,1);
637: if(msg.from_net.type==NET_INTERNET
638: && (!strcmp(str,msg.from_net.addr) || strchr(str,'@')))
639: inetmail(str,msg.subj,WM_QUOTE|WM_NETMAIL);
640: else {
641: p=strrchr(str,'@');
642: if(p) /* FidoNet or QWKnet */
643: netmail(str,msg.subj,WM_QUOTE);
644: else {
645: i=atoi(str);
646: if(!i) {
647: if(sub[subnum]->misc&SUB_NAME)
648: i=userdatdupe(0,U_NAME,LEN_NAME,str,0);
649: else
650: i=matchuser(str); }
651: email(i,str2,msg.subj,WM_EMAIL|WM_QUOTE); } }
652: // post=loadposts(&posts,subnum,0,lp);
653: break;
654: case 'P': /* Post message on sub-board */
655: domsg=0;
656: if(!chk_ar(sub[subnum]->post_ar,useron))
657: bputs(text[CantPostOnSub]);
658: else {
659: if(post)
660: LFREE(post);
661: post=NULL;
662: postmsg(subnum,0,0);
663: // post=loadposts(&posts,subnum,0,lp);
664: }
665: break;
666: case 'Q': /* Quit */
667: if(msg.total_hfields)
668: smb_freemsgmem(&msg);
669: if(post)
670: LFREE(post);
671: smb_close(&smb);
672: smb_stack(&smb,SMB_STACK_POP);
673: return(1);
674: case 'R': /* re-read last message */
675: reread=1;
676: break;
677: case 'T': /* List titles of next ten messages */
678: domsg=0;
679: if(!posts)
680: break;
681: if(curpost>=posts-1) {
682: done=1;
683: break; }
684: i=curpost+11;
685: if(i>posts)
686: i=posts;
687: listmsgs(subnum,post,curpost+1,i);
688: curpost=i-1;
689: if(sub[subnum]->ptr<post[curpost].number)
690: sub[subnum]->ptr=post[curpost].number;
691: break;
692: case 'Y': /* Your messages */
693: domsg=0;
694: showposts_toyou(post,0,posts);
695: break;
696: case '-':
697: if(curpost>0) curpost--;
698: reread=1;
699: break;
700: case 'O': /* Operator commands */
701: while(online) {
702: if(!(useron.misc&EXPERT))
703: menu("SYSMSCAN");
704: bprintf("\r\n\1y\1hOperator: \1w");
705: strcpy(str,"?CEHMPQUV");
706: if(SYSOP)
707: strcat(str,"S");
708: switch(getkeys(str,0)) {
709: case '?':
710: if(useron.misc&EXPERT)
711: menu("SYSMSCAN");
712: continue;
713: case 'P': /* Purge user */
714: purgeuser(sub[subnum]->misc&SUB_NAME
715: ? userdatdupe(0,U_NAME,LEN_NAME,msg.from,0)
716: : matchuser(msg.from));
717: break;
718: case 'C': /* Change message attributes */
719: i=chmsgattr(msg.hdr.attr);
720: if(msg.hdr.attr==i)
721: break;
722: if(msg.total_hfields)
723: smb_freemsgmem(&msg);
724: msg.total_hfields=0;
725: msg.idx.offset=0;
726: if(loadmsg(&msg,msg.idx.number)) {
727: msg.hdr.attr=msg.idx.attr=i;
728: if((i=smb_putmsg(&smb,&msg))!=0)
729: errormsg(WHERE,ERR_WRITE,smb.file,i);
730: smb_unlockmsghdr(&smb,&msg); }
731: break;
732: case 'E': /* edit last post */
733: if(post)
734: LFREE(post);
735: post=NULL;
736: editmsg(&msg,subnum);
737: // post=loadposts(&posts,subnum,0,lp);
738: break;
739: case 'H': /* View message header */
740: msghdr(msg);
741: domsg=0;
742: break;
743: case 'M': /* Move message */
744: domsg=0;
745: if(post)
746: LFREE(post);
747: post=NULL;
748: if(msg.total_hfields)
749: smb_freemsgmem(&msg);
750: msg.total_hfields=0;
751: msg.idx.offset=0;
752: if(!loadmsg(&msg,msg.idx.number)) {
753: errormsg(WHERE,ERR_READ,smb.file,msg.idx.number);
754: break; }
755: sprintf(str,text[DeletePostQ],msg.hdr.number,msg.subj);
756: if(movemsg(msg,subnum) && yesno(str)) {
757: msg.idx.attr|=MSG_DELETE;
758: msg.hdr.attr=msg.idx.attr;
759: if((i=smb_putmsg(&smb,&msg))!=0)
760: errormsg(WHERE,ERR_WRITE,smb.file,i); }
761: smb_unlockmsghdr(&smb,&msg);
762: // post=loadposts(&posts,subnum,0,lp);
763: break;
764:
765: case 'Q':
766: break;
767: case 'S': /* Save/Append message to another file */
768: /* 05/26/95
769: if(!yesno(text[SaveMsgToFile]))
770: break;
771: */
772: bputs(text[FileToWriteTo]);
773: if(getstr(str,40,K_LINE|K_UPPER))
774: msgtotxt(msg,str,1,1);
775: break;
776: case 'U': /* User edit */
777: useredit(sub[subnum]->misc&SUB_NAME
778: ? userdatdupe(0,U_NAME,LEN_NAME,msg.from,0)
779: : matchuser(msg.from),0);
780: break;
781: case 'V': /* Validate message */
782: if(msg.total_hfields)
783: smb_freemsgmem(&msg);
784: msg.total_hfields=0;
785: msg.idx.offset=0;
786: if(loadmsg(&msg,msg.idx.number)) {
787: msg.idx.attr|=MSG_VALIDATED;
788: msg.hdr.attr=msg.idx.attr;
789: if((i=smb_putmsg(&smb,&msg))!=0)
790: errormsg(WHERE,ERR_WRITE,smb.file,i);
791: smb_unlockmsghdr(&smb,&msg); }
792: break;
793: default:
794: continue; }
795: break; }
796: break;
797: case '.': /* Thread forward */
798: l=msg.hdr.thread_first;
799: if(!l) l=msg.hdr.thread_next;
800: if(!l) {
801: domsg=0;
802: break; }
803: for(i=0;i<posts;i++)
804: if(l==post[i].number)
805: break;
806: if(i<posts)
807: curpost=i;
808: break;
809: case ',': /* Thread backwards */
810: if(!msg.hdr.thread_orig) {
811: domsg=0;
812: break; }
813: for(i=0;i<posts;i++)
814: if(msg.hdr.thread_orig==post[i].number)
815: break;
816: if(i<posts)
817: curpost=i;
818: break;
819: case '>': /* Search Title forward */
820: for(i=curpost+1;i<posts;i++)
821: if(post[i].subj==msg.idx.subj)
822: break;
823: if(i<posts)
824: curpost=i;
825: else
826: domsg=0;
827: break;
828: case '<': /* Search Title backward */
829: for(i=curpost-1;i>-1;i--)
830: if(post[i].subj==msg.idx.subj)
831: break;
832: if(i>-1)
833: curpost=i;
834: else
835: domsg=0;
836: break;
837: case '}': /* Search Author forward */
838: strcpy(str,msg.from);
839: for(i=curpost+1;i<posts;i++)
840: if(post[i].from==msg.idx.from)
841: break;
842: if(i<posts)
843: curpost=i;
844: else
845: domsg=0;
846: break;
847: case '{': /* Search Author backward */
848: strcpy(str,msg.from);
849: for(i=curpost-1;i>-1;i--)
850: if(post[i].from==msg.idx.from)
851: break;
852: if(i>-1)
853: curpost=i;
854: else
855: domsg=0;
856: break;
857: case ']': /* Search To User forward */
858: strcpy(str,msg.to);
859: for(i=curpost+1;i<posts;i++)
860: if(post[i].to==msg.idx.to)
861: break;
862: if(i<posts)
863: curpost=i;
864: else
865: domsg=0;
866: break;
867: case '[': /* Search To User backward */
868: strcpy(str,msg.to);
869: for(i=curpost-1;i>-1;i--)
870: if(post[i].to==msg.idx.to)
871: break;
872: if(i>-1)
873: curpost=i;
874: else
875: domsg=0;
876: break;
877: case 0: /* Carriage return - Next Message */
878: case '+':
879: if(curpost<posts-1) curpost++;
880: else done=1;
881: break;
882: case '?':
883: menu("MSGSCAN");
884: domsg=0;
885: break; } }
886: if(msg.total_hfields)
887: smb_freemsgmem(&msg);
888: if(post)
889: LFREE(post);
890: if(!(mode&(SCAN_CONST|SCAN_TOYOU|SCAN_FIND)) && !(sub[subnum]->misc&SUB_PONLY)
891: && reads && chk_ar(sub[subnum]->post_ar,useron)
892: && !(useron.rest&FLAG('P'))) {
893: sprintf(str,text[Post],grp[sub[subnum]->grp]->sname
894: ,sub[subnum]->lname);
895: if(!noyes(str))
896: postmsg(subnum,0,0); }
897: smb_close(&smb);
898: smb_stack(&smb,SMB_STACK_POP);
899: return(0);
900: }
901:
902: /****************************************************************************/
903: /* This function will search the specified sub-board for messages that */
904: /* contain the string 'search'. */
905: /* Returns number of messages found. */
906: /****************************************************************************/
907: int searchsub(uint subnum,char *search)
908: {
909: int i,found;
910: ulong l,posts,total;
911: post_t HUGE16 *post;
912:
913: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
914: errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
915: return(0); }
916: total=getposts(subnum);
917: sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
918: smb.retry_time=smb_retry_time;
919: if((i=smb_open(&smb))!=0) {
920: smb_stack(&smb,SMB_STACK_POP);
921: errormsg(WHERE,ERR_OPEN,smb.file,i);
922: return(0); }
923: post=loadposts(&posts,subnum,0,LP_BYSELF|LP_OTHERS);
924: bprintf(text[SearchSubFmt]
925: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,posts,total);
926: found=searchposts(subnum,post,0,posts,search);
927: if(posts)
928: LFREE(post);
929: smb_close(&smb);
930: smb_stack(&smb,SMB_STACK_POP);
931: return(found);
932: }
933:
934: /****************************************************************************/
935: /* Will search the messages pointed to by 'msg' for the occurance of the */
936: /* string 'search' and display any messages (number of message, author and */
937: /* title). 'msgs' is the total number of valid messages. */
938: /* Returns number of messages found. */
939: /****************************************************************************/
940: int searchposts(uint subnum, post_t HUGE16 *post, long start, long posts
941: , char *search)
942: {
943: char HUGE16 *buf,ch;
944: ushort xlat;
945: int i,j;
946: long l,length,found=0;
947: smbmsg_t msg;
948:
949: msg.total_hfields=0;
950: for(l=start;l<posts && !msgabort();l++) {
951: msg.idx.offset=post[l].offset;
952: if(!loadmsg(&msg,post[l].number))
953: continue;
954: smb_unlockmsghdr(&smb,&msg);
955: buf=smb_getmsgtxt(&smb,&msg,1);
956: if(!buf) {
957: smb_freemsgmem(&msg);
958: continue; }
959: strupr((char *)buf);
960: if(strstr((char *)buf,search) || strstr(msg.subj,search)) {
961: if(!found)
962: CRLF;
963: if(msg.hdr.attr&MSG_DELETE)
964: ch='-';
965: else if((!stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name))
966: && !(msg.hdr.attr&MSG_READ))
967: ch='!';
968: else if(msg.hdr.number>sub[subnum]->ptr)
969: ch='*';
970: else
971: ch=' ';
972: bprintf(text[SubMsgLstFmt],l+1
973: ,(msg.hdr.attr&MSG_ANONYMOUS) && !sub_op(subnum) ? text[Anonymous]
974: : msg.from
975: ,msg.to
976: ,ch
977: ,msg.subj);
978: found++; }
979: FREE(buf);
980: smb_freemsgmem(&msg); }
981:
982: return(found);
983: }
984:
985: /****************************************************************************/
986: /* Will search the messages pointed to by 'msg' for message to the user on */
987: /* Returns number of messages found. */
988: /****************************************************************************/
989: void showposts_toyou(post_t HUGE16 *post, ulong start, ulong posts)
990: {
991: char str[128];
992: ushort namecrc,aliascrc,sysop;
993: int i;
994: ulong l,found;
995: smbmsg_t msg;
996:
997: strcpy(str,useron.alias);
998: strlwr(str);
999: aliascrc=crc16(str);
1000: strcpy(str,useron.name);
1001: strlwr(str);
1002: namecrc=crc16(str);
1003: sysop=crc16("sysop");
1004: msg.total_hfields=0;
1005: for(l=start,found=0;l<posts && !msgabort();l++) {
1006:
1007: if((useron.number!=1 || post[l].to!=sysop)
1008: && post[l].to!=aliascrc && post[l].to!=namecrc)
1009: continue;
1010:
1011: if(msg.total_hfields)
1012: smb_freemsgmem(&msg);
1013: msg.total_hfields=0;
1014: msg.idx.offset=post[l].offset;
1015: if(!loadmsg(&msg,post[l].number))
1016: continue;
1017: smb_unlockmsghdr(&smb,&msg);
1018: if((useron.number==1 && !stricmp(msg.to,"sysop") && !msg.from_net.type)
1019: || !stricmp(msg.to,useron.alias) || !stricmp(msg.to,useron.name)) {
1020: if(!found)
1021: CRLF;
1022: found++;
1023: bprintf(text[SubMsgLstFmt],l+1
1024: ,(msg.hdr.attr&MSG_ANONYMOUS) && !SYSOP
1025: ? text[Anonymous] : msg.from
1026: ,msg.to
1027: ,msg.hdr.attr&MSG_DELETE ? '-' : msg.hdr.attr&MSG_READ ? ' ' : '*'
1028: ,msg.subj); } }
1029:
1030: if(msg.total_hfields)
1031: smb_freemsgmem(&msg);
1032: }
1033:
1034: /****************************************************************************/
1035: /* This function will search the specified sub-board for messages that */
1036: /* are sent to the currrent user. */
1037: /* returns number of messages found */
1038: /****************************************************************************/
1039: int searchsub_toyou(uint subnum)
1040: {
1041: int i;
1042: ulong l,posts,total;
1043: post_t HUGE16 *post;
1044:
1045: if((i=smb_stack(&smb,SMB_STACK_PUSH))!=0) {
1046: errormsg(WHERE,ERR_OPEN,sub[subnum]->code,i);
1047: return(0); }
1048: total=getposts(subnum);
1049: sprintf(smb.file,"%s%s",sub[subnum]->data_dir,sub[subnum]->code);
1050: smb.retry_time=smb_retry_time;
1051: if((i=smb_open(&smb))!=0) {
1052: smb_stack(&smb,SMB_STACK_POP);
1053: errormsg(WHERE,ERR_OPEN,smb.file,i);
1054: return(0); }
1055: post=loadposts(&posts,subnum,0,0);
1056: bprintf(text[SearchSubFmt]
1057: ,grp[sub[subnum]->grp]->sname,sub[subnum]->lname,total);
1058: if(posts) {
1059: if(post)
1060: LFREE(post);
1061: post=loadposts(&posts,subnum,0,LP_BYSELF|LP_OTHERS);
1062: showposts_toyou(post,0,posts); }
1063: if(post)
1064: LFREE(post);
1065: smb_close(&smb);
1066: smb_stack(&smb,SMB_STACK_POP);
1067: return(posts);
1068: }
1069:
1070:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.