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