|
|
1.1 root 1: /* writemsg.cpp */
2:
3: /* Synchronet message creation routines */
4:
1.1.1.2 ! root 5: /* $Id: writemsg.cpp,v 1.58 2004/10/21 08:14:28 rswindell Exp $ */
1.1 root 6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
1.1.1.2 ! root 11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39:
40: #define MAX_LINE_LEN 82L
41:
42: const char *qstr=" > %.76s\r\n";
43: void quotestr(char *str);
44:
45: /****************************************************************************/
46: /* Creates a message (post or mail) using standard line editor. 'fname' is */
47: /* is name of file to create, 'top' is a buffer to place at beginning of */
48: /* message and 'title' is the title (70chars max) for the message. */
49: /* 'dest' contains a text description of where the message is going. */
50: /****************************************************************************/
51: bool sbbs_t::writemsg(char *fname, char *top, char *title, long mode, int subnum
52: ,char *dest)
53: {
1.1.1.2 ! root 54: char str[256],quote[128],c,*buf,*p,*tp
1.1 root 55: ,useron_level;
1.1.1.2 ! root 56: char msgtmp[MAX_PATH+1];
1.1 root 57: char tmp[512];
58: int i,j,file,linesquoted=0;
1.1.1.2 ! root 59: long length,qlen=0,qtime=0,ex_mode=0;
1.1 root 60: ulong l;
61: FILE * stream;
62:
63: useron_level=useron.level;
64:
1.1.1.2 ! root 65: if((buf=(char*)malloc(cfg.level_linespermsg[useron_level]*MAX_LINE_LEN))
1.1 root 66: ==NULL) {
67: errormsg(WHERE,ERR_ALLOC,fname
68: ,cfg.level_linespermsg[useron_level]*MAX_LINE_LEN);
1.1.1.2 ! root 69: return(false);
! 70: }
1.1 root 71:
72: if(mode&WM_NETMAIL ||
73: (!(mode&(WM_EMAIL|WM_NETMAIL)) && cfg.sub[subnum]->misc&SUB_PNET))
74: mode|=WM_NOTOP;
75:
76: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&QUICKBBS)
1.1.1.2 ! root 77: sprintf(msgtmp,"%sMSGTMP",cfg.node_dir); /* QuickBBS editors are dumb */
1.1 root 78: else
1.1.1.2 ! root 79: sprintf(msgtmp,"%sINPUT.MSG",cfg.temp_dir);
! 80: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE)
! 81: strlwr(msgtmp);
1.1 root 82:
83: if(mode&WM_QUOTE && !(useron.rest&FLAG('J'))
84: && ((mode&(WM_EMAIL|WM_NETMAIL) && cfg.sys_misc&SM_QUOTE_EM)
85: || (!(mode&(WM_EMAIL|WM_NETMAIL)) && (uint)subnum!=INVALID_SUB
86: && cfg.sub[subnum]->misc&SUB_QUOTE))) {
87:
88: /* Quote entire message to MSGTMP or INPUT.MSG */
89:
90: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc"EALL) {
1.1.1.2 ! root 91: strcpy(tmp,"QUOTES.TXT");
! 92: if(cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE)
! 93: strlwr(tmp);
! 94: sprintf(str,"%s%s",cfg.node_dir,tmp);
1.1 root 95: if((stream=fnopen(NULL,str,O_RDONLY))==NULL) {
96: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
1.1.1.2 ! root 97: free(buf);
1.1 root 98: return(false);
99: }
100:
1.1.1.2 ! root 101: if((file=nopen(msgtmp,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
! 102: errormsg(WHERE,ERR_OPEN,msgtmp,O_WRONLY|O_CREAT|O_TRUNC);
! 103: free(buf);
1.1 root 104: fclose(stream);
105: return(false);
106: }
107:
108: while(!feof(stream) && !ferror(stream)) {
109: if(!fgets(str,255,stream))
110: break;
111: quotestr(str);
112: sprintf(tmp,qstr,str);
113: write(file,tmp,strlen(tmp));
114: linesquoted++;
115: }
116: fclose(stream);
117: close(file);
118: }
119:
120: /* Quote nothing to MSGTMP or INPUT.MSG automatically */
121:
122: else if(useron.xedit && cfg.xedit[useron.xedit-1]->misc"ENONE)
123: ;
124:
125: else if(yesno(text[QuoteMessageQ])) {
1.1.1.2 ! root 126: strcpy(tmp,"QUOTES.TXT");
! 127: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE)
! 128: strlwr(tmp);
! 129: sprintf(str,"%s%s",cfg.node_dir,tmp);
1.1 root 130: if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
131: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
1.1.1.2 ! root 132: free(buf);
! 133: return(false);
! 134: }
1.1 root 135:
1.1.1.2 ! root 136: if((file=nopen(msgtmp,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
! 137: errormsg(WHERE,ERR_OPEN,msgtmp,O_WRONLY|O_CREAT|O_TRUNC);
! 138: free(buf);
1.1 root 139: fclose(stream);
1.1.1.2 ! root 140: return(false);
! 141: }
1.1 root 142:
143: l=ftell(stream); /* l now points to start of message */
144:
145: while(online) {
146: sprintf(str,text[QuoteLinesPrompt],linesquoted ? "Done":"All");
147: mnemonics(str);
148: i=getstr(quote,10,K_UPPER);
149: if(sys_status&SS_ABORT) {
150: fclose(stream);
151: close(file);
1.1.1.2 ! root 152: free(buf);
! 153: return(false);
! 154: }
1.1 root 155: if(!i && linesquoted)
156: break;
157: if(!i || quote[0]=='A') { /* Quote all */
158: fseek(stream,l,SEEK_SET);
159: while(!feof(stream) && !ferror(stream)) {
160: if(!fgets(str,255,stream))
161: break;
162: quotestr(str);
163: sprintf(tmp,qstr,str);
164: write(file,tmp,strlen(tmp));
1.1.1.2 ! root 165: linesquoted++;
! 166: }
! 167: break;
! 168: }
1.1 root 169: if(quote[0]=='L') {
170: fseek(stream,l,SEEK_SET);
171: i=1;
172: CRLF;
173: attr(LIGHTGRAY);
174: while(!feof(stream) && !ferror(stream) && !msgabort()) {
175: if(!fgets(str,255,stream))
176: break;
177: quotestr(str);
178: bprintf("%3d: %.74s\r\n",i,str);
1.1.1.2 ! root 179: i++;
! 180: }
! 181: continue;
! 182: }
1.1 root 183:
184: if(!isdigit(quote[0]))
185: break;
186: p=quote;
187: while(p) {
1.1.1.2 ! root 188: if(*p==',' || *p==' ')
1.1 root 189: p++;
190: i=atoi(p);
191: if(!i)
192: break;
193: fseek(stream,l,SEEK_SET);
194: j=1;
195: while(!feof(stream) && !ferror(stream) && j<i) {
196: if(!fgets(tmp,255,stream))
197: break;
1.1.1.2 ! root 198: j++; /* skip beginning */
! 199: }
1.1 root 200: tp=strchr(p,'-'); /* tp for temp pointer */
201: if(tp) { /* range */
202: i=atoi(tp+1);
203: while(!feof(stream) && !ferror(stream) && j<=i) {
204: if(!fgets(str,255,stream))
205: break;
206: quotestr(str);
207: sprintf(tmp,qstr,str);
208: write(file,tmp,strlen(tmp));
209: linesquoted++;
1.1.1.2 ! root 210: j++;
! 211: }
! 212: }
1.1 root 213: else { /* one line */
214: if(fgets(str,255,stream)) {
215: quotestr(str);
216: sprintf(tmp,qstr,str);
217: write(file,tmp,strlen(tmp));
1.1.1.2 ! root 218: linesquoted++;
! 219: }
! 220: }
1.1 root 221: p=strchr(p,',');
1.1.1.2 ! root 222: // if(!p) p=strchr(p,' '); 02/05/96 huh?
! 223: }
! 224: }
1.1 root 225:
226: fclose(stream);
1.1.1.2 ! root 227: close(file);
! 228: }
! 229: }
1.1 root 230: else {
1.1.1.2 ! root 231: strcpy(tmp,"QUOTES.TXT");
! 232: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE)
! 233: strlwr(tmp);
! 234: sprintf(str,"%s%s",cfg.node_dir,tmp);
! 235: remove(str);
! 236: }
1.1 root 237:
238: if(!online || sys_status&SS_ABORT) {
1.1.1.2 ! root 239: free(buf);
! 240: return(false);
! 241: }
1.1 root 242:
243: if(!(mode&WM_EXTDESC)) {
244: if(mode&WM_FILE) {
245: c=12;
246: CRLF;
1.1.1.2 ! root 247: bputs(text[Filename]);
! 248: }
1.1 root 249: else {
250: c=LEN_TITLE;
1.1.1.2 ! root 251: if(mode&WM_QWKNET
! 252: || (subnum!=INVALID_SUB
! 253: && (cfg.sub[subnum]->misc&(SUB_QNET|SUB_INET|SUB_FIDO))==SUB_QNET))
! 254: c=25;
! 255: bputs(text[SubjectPrompt]);
! 256: }
1.1 root 257: if(!getstr(title,c,mode&WM_FILE ? K_LINE|K_UPPER : K_LINE|K_EDIT|K_AUTODEL)
258: && useron_level && useron.logons) {
1.1.1.2 ! root 259: free(buf);
! 260: return(false);
! 261: }
1.1 root 262: if(!(mode&(WM_EMAIL|WM_NETMAIL)) && cfg.sub[subnum]->misc&SUB_QNET
263: && !SYSOP
264: && (!stricmp(title,"DROP") || !stricmp(title,"ADD")
265: || !strnicmp(dest,"SBBS",4))) {
1.1.1.2 ! root 266: free(buf); /* Users can't post DROP or ADD in QWK netted subs */
! 267: return(false); /* or messages to "SBBS" */
! 268: }
! 269: }
1.1 root 270:
271: if(!online || sys_status&SS_ABORT) {
1.1.1.2 ! root 272: free(buf);
! 273: return(false);
! 274: }
1.1 root 275:
276: /* Create WWIV compatible EDITOR.INF file */
277:
278: if(useron.xedit) {
279: editor_inf(useron.xedit,dest,title,mode,subnum);
280: if(cfg.xedit[useron.xedit-1]->type) {
281: gettimeleft();
282: xtrndat(useron.alias,cfg.node_dir,cfg.xedit[useron.xedit-1]->type
1.1.1.2 ! root 283: ,timeleft,cfg.xedit[useron.xedit-1]->misc);
1.1 root 284: }
1.1.1.2 ! root 285: }
1.1 root 286:
287: if(console&CON_RAW_IN) {
288: bprintf(text[EnterMsgNowRaw]
289: ,(ulong)cfg.level_linespermsg[useron_level]*MAX_LINE_LEN);
290: if(top[0] && !(mode&WM_NOTOP)) {
291: strcpy((char *)buf,top);
292: strcat((char *)buf,crlf);
1.1.1.2 ! root 293: l=strlen((char *)buf);
! 294: }
1.1 root 295: else
296: l=0;
297: while(l<(ulong)(cfg.level_linespermsg[useron_level]*MAX_LINE_LEN)) {
298: c=getkey(0);
299: if(sys_status&SS_ABORT) { /* Ctrl-C */
1.1.1.2 ! root 300: free(buf);
! 301: return(false);
! 302: }
! 303: if((c==ESC || c==CTRL_A) && useron.rest&FLAG('A')) /* ANSI restriction */
1.1 root 304: continue;
305: if(c==BEL && useron.rest&FLAG('B')) /* Beep restriction */
306: continue;
307: if(!(console&CON_RAW_IN)) /* Ctrl-Z was hit */
308: break;
309: outchar(c);
1.1.1.2 ! root 310: buf[l++]=c;
! 311: }
1.1 root 312: buf[l]=0;
313: if(l==(ulong)cfg.level_linespermsg[useron_level]*MAX_LINE_LEN)
1.1.1.2 ! root 314: bputs(text[OutOfBytes]);
! 315: }
1.1 root 316:
317:
1.1.1.2 ! root 318: else if(useron.xedit) {
1.1 root 319:
320: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&IO_INTS) {
1.1.1.2 ! root 321: ex_mode|=(EX_OUTR|EX_INR);
1.1 root 322: if(cfg.xedit[useron.xedit-1]->misc&WWIVCOLOR)
1.1.1.2 ! root 323: ex_mode|=EX_WWIV;
! 324: }
! 325: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_NATIVE)
! 326: ex_mode|=EX_NATIVE;
! 327: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_SH)
! 328: ex_mode|=EX_SH;
1.1 root 329:
1.1.1.2 ! root 330: if(!linesquoted && fexistcase(msgtmp))
! 331: remove(msgtmp);
1.1 root 332: if(linesquoted) {
1.1.1.2 ! root 333: qlen=flength(msgtmp);
! 334: qtime=fdate(msgtmp);
! 335: }
! 336:
! 337: CLS;
! 338: rioctl(IOCM|PAUSE|ABORT);
! 339: external(cmdstr(cfg.xedit[useron.xedit-1]->rcmd,msgtmp,nulstr,NULL),ex_mode,cfg.node_dir);
! 340: rioctl(IOSM|PAUSE|ABORT);
1.1 root 341:
342: checkline();
1.1.1.2 ! root 343: if(!fexistcase(msgtmp) || !online
! 344: || (linesquoted && qlen==flength(msgtmp) && qtime==fdate(msgtmp))) {
! 345: free(buf);
! 346: return(false);
! 347: }
1.1 root 348: buf[0]=0;
349: if(!(mode&WM_NOTOP))
350: strcpy((char *)buf,top);
1.1.1.2 ! root 351: if((file=nopen(msgtmp,O_RDONLY))==-1) {
! 352: errormsg(WHERE,ERR_OPEN,msgtmp,O_RDONLY);
! 353: free(buf);
! 354: return(false);
! 355: }
1.1 root 356: length=filelength(file);
357: l=strlen((char *)buf); /* reserve space for top and terminating null */
358: /* truncate if too big */
359: if(length>(long)((cfg.level_linespermsg[useron_level]*MAX_LINE_LEN)-(l+1))) {
360: length=(cfg.level_linespermsg[useron_level]*MAX_LINE_LEN)-(l+1);
1.1.1.2 ! root 361: bputs(text[OutOfBytes]);
! 362: }
1.1 root 363: lread(file,buf+l,length);
364: close(file);
1.1.1.2 ! root 365: // remove(msgtmp); /* no need to save the temp input file */
! 366: buf[l+length]=0;
! 367: }
1.1 root 368: else {
369: buf[0]=0;
370: if(linesquoted) {
1.1.1.2 ! root 371: if((file=nopen(msgtmp,O_RDONLY))!=-1) {
1.1 root 372: length=filelength(file);
1.1.1.2 ! root 373: l=length>(cfg.level_linespermsg[useron_level]*MAX_LINE_LEN)-1
! 374: ? (cfg.level_linespermsg[useron_level]*MAX_LINE_LEN)-1 : length;
1.1 root 375: lread(file,buf,l);
376: buf[l]=0;
377: close(file);
1.1.1.2 ! root 378: // remove(msgtmp);
! 379: }
! 380: }
1.1 root 381: if(!(msgeditor((char *)buf,mode&WM_NOTOP ? nulstr : top,title))) {
1.1.1.2 ! root 382: free(buf); /* Assertion here Dec-17-2003, think I fixed in block above (rev 1.52) */
! 383: return(false);
! 384: }
! 385: }
1.1 root 386:
387: now=time(NULL);
388: bputs(text[Saving]);
389: if((stream=fnopen(&file,fname,O_WRONLY|O_CREAT|O_TRUNC))==NULL) {
390: errormsg(WHERE,ERR_OPEN,fname,O_WRONLY|O_CREAT|O_TRUNC);
1.1.1.2 ! root 391: free(buf);
! 392: return(false);
! 393: }
1.1 root 394: for(l=i=0;buf[l] && i<cfg.level_linespermsg[useron_level];l++) {
395: if((uchar)buf[l]==141 && useron.xedit
396: && cfg.xedit[useron.xedit-1]->misc&QUICKBBS) {
397: fwrite(crlf,2,1,stream);
398: i++;
1.1.1.2 ! root 399: continue;
! 400: }
! 401: /* Expand LF to CRLF? */
1.1 root 402: if(buf[l]==LF && (!l || buf[l-1]!=CR) && useron.xedit
403: && cfg.xedit[useron.xedit-1]->misc&EXPANDLF) {
404: fwrite(crlf,2,1,stream);
405: i++;
1.1.1.2 ! root 406: continue;
! 407: }
! 408: /* Strip FidoNet Kludge Lines? */
! 409: if(buf[l]==1 && useron.xedit
! 410: && cfg.xedit[useron.xedit-1]->misc&STRIPKLUDGE) {
! 411: while(buf[l] && buf[l]!=LF)
! 412: l++;
! 413: if(buf[l]==0)
! 414: break;
! 415: continue;
! 416: }
1.1 root 417: if(!(mode&(WM_EMAIL|WM_NETMAIL))
418: && (!l || buf[l-1]==LF)
419: && buf[l]=='-' && buf[l+1]=='-' && buf[l+2]=='-'
1.1.1.2 ! root 420: && (buf[l+3]==' ' || buf[l+3]==TAB || buf[l+3]==CR))
1.1 root 421: buf[l+1]='+';
422: if(buf[l]==LF)
423: i++;
1.1.1.2 ! root 424: fputc(buf[l],stream);
! 425: }
1.1 root 426:
427: if(buf[l])
428: bputs(text[NoMoreLines]);
1.1.1.2 ! root 429:
! 430: /* Signature file */
! 431: if(subnum==INVALID_SUB || !(cfg.sub[subnum]->misc&SUB_NOUSERSIG)) {
! 432: sprintf(str,"%suser/%04u.sig",cfg.data_dir,useron.number);
! 433: FILE* sig;
! 434: if(fexist(str) && (sig=fopen(str,"rb"))!=NULL) {
! 435: while(!feof(sig)) {
! 436: if(!fgets(str,sizeof(str),sig))
! 437: break;
! 438: fputs(str,stream);
! 439: l+=strlen(str); /* byte counter */
! 440: i++; /* line counter */
! 441: }
! 442: fclose(sig);
! 443: }
! 444: }
! 445:
1.1 root 446: fclose(stream);
1.1.1.2 ! root 447: free((char *)buf);
1.1 root 448: bprintf(text[SavedNBytes],l,i);
449: return(true);
450: }
451:
452: /****************************************************************************/
453: /* Modify 'str' to for quoted format. Remove ^A codes, etc. */
454: /****************************************************************************/
455: void quotestr(char *str)
456: {
457: int j;
458:
459: j=strlen(str);
1.1.1.2 ! root 460: while(j && (str[j-1]==' ' || str[j-1]==LF || str[j-1]==CR)) j--;
1.1 root 461: str[j]=0;
1.1.1.2 ! root 462: remove_ctrl_a(str,NULL);
1.1 root 463: }
464:
465: void sbbs_t::editor_inf(int xeditnum,char *dest, char *title, long mode
466: ,uint subnum)
467: {
468: char str[512];
469: int file;
1.1.1.2 ! root 470: char tmp[13];
1.1 root 471:
472: xeditnum--;
473:
474: if(cfg.xedit[xeditnum]->misc&QUICKBBS) {
475: sprintf(str,"%sMSGINF",cfg.node_dir);
476: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
477: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
1.1.1.2 ! root 478: return;
! 479: }
1.1 root 480: sprintf(str,"%s\r\n%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n"
481: ,(subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_NAME) ? useron.name
482: : useron.alias
483: ,dest,title,1
484: ,mode&WM_NETMAIL ? "NetMail"
485: :mode&WM_EMAIL ? "Electronic Mail"
486: :subnum==INVALID_SUB ? nulstr
487: :cfg.sub[subnum]->sname
488: ,mode&WM_PRIVATE ? "YES":"NO");
489: write(file,str,strlen(str));
1.1.1.2 ! root 490: close(file);
! 491: }
1.1 root 492: else {
1.1.1.2 ! root 493: strcpy(tmp,"EDITOR.INF");
! 494: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE)
! 495: strlwr(tmp);
! 496: sprintf(str,"%s%s",cfg.node_dir,tmp);
1.1 root 497: if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
498: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
1.1.1.2 ! root 499: return;
! 500: }
1.1 root 501: sprintf(str,"%s\r\n%s\r\n%u\r\n%s\r\n%s\r\n%u\r\n"
502: ,title,dest,useron.number
503: ,(subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_NAME) ? useron.name
504: : useron.alias
505: ,useron.name,useron.level);
506: write(file,str,strlen(str));
1.1.1.2 ! root 507: close(file);
! 508: }
1.1 root 509: }
510:
511:
512:
513: /****************************************************************************/
514: /* Removes from file 'str' every LF terminated line that starts with 'str2' */
515: /* That is divisable by num. Function skips first 'skip' number of lines */
516: /****************************************************************************/
517: void sbbs_t::removeline(char *str, char *str2, char num, char skip)
518: {
1.1.1.2 ! root 519: char* buf;
1.1 root 520: char slen;
521: int i,file;
522: long l=0,flen;
523: FILE *stream;
524:
525: if((file=nopen(str,O_RDONLY))==-1) {
526: errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
1.1.1.2 ! root 527: return;
! 528: }
1.1 root 529: flen=filelength(file);
530: slen=strlen(str2);
531: if((buf=(char *)MALLOC(flen))==NULL) {
532: close(file);
533: errormsg(WHERE,ERR_ALLOC,str,flen);
1.1.1.2 ! root 534: return;
! 535: }
1.1 root 536: if(lread(file,buf,flen)!=flen) {
537: close(file);
538: errormsg(WHERE,ERR_READ,str,flen);
1.1.1.2 ! root 539: free(buf);
! 540: return;
! 541: }
1.1 root 542: close(file);
543: if((stream=fnopen(&file,str,O_WRONLY|O_TRUNC))==NULL) {
544: close(file);
545: errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_TRUNC);
1.1.1.2 ! root 546: free(buf);
! 547: return;
! 548: }
1.1 root 549: for(i=0;l<flen && i<skip;l++) {
550: fputc(buf[l],stream);
551: if(buf[l]==LF)
1.1.1.2 ! root 552: i++;
! 553: }
1.1 root 554: while(l<flen) {
555: if(!strncmp((char *)buf+l,str2,slen)) {
556: for(i=0;i<num && l<flen;i++) {
557: while(l<flen && buf[l]!=LF) l++;
1.1.1.2 ! root 558: l++;
! 559: }
! 560: }
1.1 root 561: else {
562: for(i=0;i<num && l<flen;i++) {
563: while(l<flen && buf[l]!=LF) fputc(buf[l++],stream);
1.1.1.2 ! root 564: fputc(buf[l++],stream);
! 565: }
! 566: }
! 567: }
1.1 root 568: fclose(stream);
1.1.1.2 ! root 569: free((char *)buf);
1.1 root 570: }
571:
572: /*****************************************************************************/
573: /* The Synchronet editor. */
574: /* Returns the number of lines edited. */
575: /*****************************************************************************/
576: ulong sbbs_t::msgeditor(char *buf, char *top, char *title)
577: {
578: int i,j,line,lines=0,maxlines;
579: char strin[256],**str,done=0;
580: char tmp[512];
1.1.1.2 ! root 581: char path[MAX_PATH+1];
1.1 root 582: ulong l,m;
583:
1.1.1.2 ! root 584: rioctl(IOCM|ABORT);
! 585: rioctl(IOCS|ABORT);
1.1 root 586:
587: maxlines=cfg.level_linespermsg[useron.level];
588:
589: if((str=(char **)MALLOC(sizeof(char *)*(maxlines+1)))==NULL) {
590: errormsg(WHERE,ERR_ALLOC,"msgeditor",sizeof(char *)*(maxlines+1));
1.1.1.2 ! root 591: return(0);
! 592: }
1.1 root 593: m=strlen(buf);
594: l=0;
595: while(l<m && lines<maxlines) {
596: msgabort(); /* to allow pausing */
597: if((str[lines]=(char *)MALLOC(MAX_LINE_LEN))==NULL) {
598: errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
599: for(i=0;i<lines;i++)
1.1.1.2 ! root 600: free(str[i]);
! 601: free(str);
! 602: rioctl(IOSM|ABORT);
! 603: return(0);
! 604: }
1.1 root 605: for(i=0;i<79 && l<m;i++,l++) {
606: if(buf[l]==CR) {
607: l+=2;
1.1.1.2 ! root 608: break;
! 609: }
1.1 root 610: if(buf[l]==TAB) {
611: if(!(i%8)) /* hard-coded tabstop of 8 */
1.1.1.2 ! root 612: str[lines][i++]=' '; /* for expansion */
1.1 root 613: while(i%8 && i<79)
1.1.1.2 ! root 614: str[lines][i++]=' ';
1.1 root 615: i--;
616: /***
617: bprintf("\r\nMessage editor: Expanded tab on line #%d",lines+1);
618: ***/ }
1.1.1.2 ! root 619: else str[lines][i]=buf[l];
! 620: }
1.1 root 621: if(i==79) {
622: if(buf[l]==CR)
623: l+=2;
624: else
1.1.1.2 ! root 625: bprintf("\r\nMessage editor: Split line #%d",lines+1);
! 626: }
1.1 root 627: str[lines][i]=0;
1.1.1.2 ! root 628: lines++;
! 629: }
1.1 root 630: if(lines)
631: bprintf("\r\nMessage editor: Read in %d lines\r\n",lines);
632: bprintf(text[EnterMsgNow],maxlines);
1.1.1.2 ! root 633:
! 634: sprintf(path,"%smenu/msgtabs.*", cfg.text_dir);
! 635: if(fexist(path))
! 636: menu("msgtabs");
! 637: else {
! 638: for(i=0;i<79;i++) {
! 639: if(i%EDIT_TABSIZE || !i)
! 640: outchar('-');
! 641: else
! 642: outchar('+');
! 643: }
! 644: CRLF;
! 645: }
1.1 root 646: putmsg(top,P_SAVEATR|P_NOATCODES);
647: for(line=0;line<lines && !msgabort();line++) { /* display lines in buf */
648: putmsg(str[line],P_SAVEATR|P_NOATCODES);
1.1.1.2 ! root 649: cleartoeol(); /* delete to end of line */
! 650: CRLF;
! 651: }
1.1 root 652: SYNC;
1.1.1.2 ! root 653: rioctl(IOSM|ABORT);
1.1 root 654: while(online && !done) {
655: checkline();
656: if(line==lines) {
657: if((str[line]=(char *)MALLOC(MAX_LINE_LEN))==NULL) {
658: errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
659: for(i=0;i<lines;i++)
1.1.1.2 ! root 660: free(str[i]);
! 661: free(str);
! 662: return(0);
! 663: }
! 664: str[line][0]=0;
! 665: }
1.1 root 666: if(line>(maxlines-10)) {
667: if(line==maxlines)
668: bputs(text[NoMoreLines]);
669: else
1.1.1.2 ! root 670: bprintf(text[OnlyNLinesLeft],maxlines-line);
! 671: }
1.1 root 672: strcpy(strin,str[line]);
673: do {
674: if(!line)
675: outchar(CR);
676: getstr(strin,79,K_WRAP|K_MSG|K_EDIT);
677: } while(console&CON_UPARROW && !line);
678:
679: if(sys_status&SS_ABORT) {
680: if(line==lines)
1.1.1.2 ! root 681: free(str[line]);
! 682: continue;
! 683: }
1.1 root 684: if(strin[0]=='/' && strlen(strin)<8) {
685: if(!stricmp(strin,"/DEBUG") && SYSOP) {
686: if(line==lines)
1.1.1.2 ! root 687: free(str[line]);
1.1 root 688: bprintf("\r\nline=%d lines=%d rows=%d\r\n",line,lines,rows);
1.1.1.2 ! root 689: continue;
! 690: }
1.1 root 691: else if(!stricmp(strin,"/ABT")) {
692: if(line==lines) /* delete a line */
1.1.1.2 ! root 693: free(str[line]);
1.1 root 694: for(i=0;i<lines;i++)
1.1.1.2 ! root 695: free(str[i]);
! 696: free(str);
! 697: return(0);
! 698: }
1.1 root 699: else if(toupper(strin[1])=='D') {
700: if(line==lines) /* delete a line */
1.1.1.2 ! root 701: free(str[line]);
1.1 root 702: if(!lines)
703: continue;
704: i=atoi(strin+2)-1;
705: if(i==-1) /* /D means delete last line */
706: i=lines-1;
707: if(i>=lines || i<0)
708: bputs(text[InvalidLineNumber]);
709: else {
1.1.1.2 ! root 710: free(str[i]);
1.1 root 711: lines--;
712: while(i<lines) {
713: str[i]=str[i+1];
1.1.1.2 ! root 714: i++;
! 715: }
1.1 root 716: if(line>lines)
1.1.1.2 ! root 717: line=lines;
! 718: }
! 719: continue;
! 720: }
1.1 root 721: else if(toupper(strin[1])=='I') {
722: if(line==lines) /* insert a line before number x */
1.1.1.2 ! root 723: free(str[line]);
1.1 root 724: if(line==maxlines || !lines)
725: continue;
726: i=atoi(strin+2)-1;
727: if(i==-1)
728: i=lines-1;
729: if(i>=lines || i<0)
730: bputs(text[InvalidLineNumber]);
731: else {
732: for(line=lines;line>i;line--) /* move the pointers */
733: str[line]=str[line-1];
734: if((str[i]=(char *)MALLOC(MAX_LINE_LEN))==NULL) {
735: errormsg(WHERE,ERR_ALLOC,nulstr,MAX_LINE_LEN);
736: for(i=0;i<lines;i++)
1.1.1.2 ! root 737: free(str[i]);
! 738: free(str);
! 739: return(0);
! 740: }
1.1 root 741: str[i][0]=0;
1.1.1.2 ! root 742: line=++lines;
! 743: }
! 744: continue;
! 745: }
1.1 root 746: else if(toupper(strin[1])=='E') {
747: if(line==lines) /* edit a line */
1.1.1.2 ! root 748: free(str[line]);
1.1 root 749: if(!lines)
750: continue;
751: i=atoi(strin+2)-1;
752: j=K_MSG|K_EDIT; /* use j for the getstr mode */
753: if(i==-1) { /* /E means edit last line */
754: i=lines-1;
1.1.1.2 ! root 755: j|=K_WRAP; /* wrap when editing last line */
! 756: }
1.1 root 757: if(i>=lines || i<0)
758: bputs(text[InvalidLineNumber]);
759: else
760: getstr(str[i],79,j);
1.1.1.2 ! root 761: continue;
! 762: }
1.1 root 763: else if(!stricmp(strin,"/CLR")) {
764: bputs(text[MsgCleared]);
765: if(line!=lines)
766: lines--;
767: for(i=0;i<=lines;i++)
1.1.1.2 ! root 768: free(str[i]);
1.1 root 769: line=0;
770: lines=0;
771: putmsg(top,P_SAVEATR|P_NOATCODES);
1.1.1.2 ! root 772: continue;
! 773: }
1.1 root 774: else if(toupper(strin[1])=='L') { /* list message */
775: if(line==lines)
1.1.1.2 ! root 776: free(str[line]);
1.1 root 777: if(lines)
778: i=!noyes(text[WithLineNumbersQ]);
1.1.1.2 ! root 779: else
! 780: i=0;
1.1 root 781: CRLF;
782: attr(LIGHTGRAY);
783: putmsg(top,P_SAVEATR|P_NOATCODES);
784: if(!lines) {
1.1.1.2 ! root 785: continue;
! 786: }
1.1 root 787: j=atoi(strin+2);
788: if(j) j--; /* start from line j */
789: while(j<lines && !msgabort()) {
790: if(i) { /* line numbers */
791: sprintf(tmp,"%3d: %-.74s",j+1,str[j]);
1.1.1.2 ! root 792: putmsg(tmp,P_SAVEATR|P_NOATCODES);
! 793: }
1.1 root 794: else
795: putmsg(str[j],P_SAVEATR|P_NOATCODES);
1.1.1.2 ! root 796: cleartoeol(); /* delete to end of line */
1.1 root 797: CRLF;
1.1.1.2 ! root 798: j++;
! 799: }
1.1 root 800: SYNC;
1.1.1.2 ! root 801: continue;
! 802: }
1.1 root 803: else if(!stricmp(strin,"/S")) { /* Save */
804: if(line==lines)
1.1.1.2 ! root 805: free(str[line]);
1.1 root 806: done=1;
807: continue;}
1.1.1.2 ! root 808: else if(!stricmp(strin,"/T")) { /* Edit title/subject */
1.1 root 809: if(line==lines)
1.1.1.2 ! root 810: free(str[line]);
1.1 root 811: if(title[0]) {
1.1.1.2 ! root 812: bputs(text[SubjectPrompt]);
1.1 root 813: getstr(title,LEN_TITLE,K_LINE|K_EDIT|K_AUTODEL);
814: SYNC;
1.1.1.2 ! root 815: CRLF;
! 816: }
! 817: continue;
! 818: }
1.1 root 819: else if(!stricmp(strin,"/?")) {
820: if(line==lines)
1.1.1.2 ! root 821: free(str[line]);
1.1 root 822: menu("editor"); /* User Editor Commands */
823: SYNC;
1.1.1.2 ! root 824: continue;
! 825: }
1.1 root 826: else if(!stricmp(strin,"/ATTR")) {
827: if(line==lines)
1.1.1.2 ! root 828: free(str[line]);
1.1 root 829: menu("attr"); /* User ANSI Commands */
830: SYNC;
1.1.1.2 ! root 831: continue;
! 832: }
! 833: }
1.1 root 834: strcpy(str[line],strin);
835: if(line<maxlines)
836: line++;
837: else
1.1.1.2 ! root 838: free(str[line]);
1.1 root 839: if(line>lines)
840: lines++;
841: if(console&CON_UPARROW) {
842: outchar(CR);
1.1.1.2 ! root 843: cursor_up();
! 844: cleartoeol();
! 845: line-=2;
! 846: }
1.1 root 847: }
848: if(!online) {
849: for(i=0;i<lines;i++)
1.1.1.2 ! root 850: free(str[i]);
! 851: free(str);
! 852: return(0);
! 853: }
1.1 root 854: strcpy(buf,top);
855: for(i=0;i<lines;i++) {
856: strcat(buf,str[i]);
857: strcat(buf,crlf);
1.1.1.2 ! root 858: free(str[i]);
! 859: }
! 860: free(str);
1.1 root 861: return(lines);
862: }
863:
864:
865: /****************************************************************************/
866: /* Edits an existing file or creates a new one in MSG format */
867: /****************************************************************************/
868: void sbbs_t::editfile(char *str)
869: {
1.1.1.2 ! root 870: char *buf,str2[128];
1.1 root 871: int file;
1.1.1.2 ! root 872: long length,maxlines,lines,l,mode=0;
1.1 root 873:
874: maxlines=cfg.level_linespermsg[useron.level];
875: sprintf(str2,"%sQUOTES.TXT",cfg.node_dir);
1.1.1.2 ! root 876: fexistcase(str2);
1.1 root 877: remove(str2);
878: if(cfg.node_editor[0] && online==ON_LOCAL) {
879: external(cmdstr(cfg.node_editor,str,nulstr,NULL),0,cfg.node_dir);
1.1.1.2 ! root 880: return;
! 881: }
1.1 root 882: if(useron.xedit) {
883: editor_inf(useron.xedit,nulstr,nulstr,0,INVALID_SUB);
1.1.1.2 ! root 884: if(cfg.xedit[useron.xedit-1]->misc&XTRN_NATIVE)
! 885: mode|=EX_NATIVE;
! 886: if(cfg.xedit[useron.xedit-1]->misc&XTRN_SH)
! 887: mode|=EX_SH;
1.1 root 888: if(cfg.xedit[useron.xedit-1]->misc&IO_INTS) {
1.1.1.2 ! root 889: mode|=(EX_OUTR|EX_INR);
1.1 root 890: if(cfg.xedit[useron.xedit-1]->misc&WWIVCOLOR)
1.1.1.2 ! root 891: mode|=EX_WWIV;
! 892: }
1.1 root 893: if(online==ON_LOCAL)
894: external(cmdstr(cfg.xedit[useron.xedit-1]->lcmd,str,nulstr,NULL),mode,cfg.node_dir);
895: else {
1.1.1.2 ! root 896: CLS;
1.1 root 897: rioctl(IOCM|PAUSE|ABORT);
898: external(cmdstr(cfg.xedit[useron.xedit-1]->rcmd,str,nulstr,NULL),mode,cfg.node_dir);
1.1.1.2 ! root 899: rioctl(IOSM|PAUSE|ABORT);
! 900: }
! 901: return;
! 902: }
1.1 root 903: if((buf=(char *)MALLOC(maxlines*MAX_LINE_LEN))==NULL) {
904: errormsg(WHERE,ERR_ALLOC,nulstr,maxlines*MAX_LINE_LEN);
1.1.1.2 ! root 905: return;
! 906: }
1.1 root 907: if((file=nopen(str,O_RDONLY))!=-1) {
908: length=filelength(file);
909: if(length>(long)maxlines*MAX_LINE_LEN) {
910: close(file);
1.1.1.2 ! root 911: free(buf);
! 912: attr(cfg.color[clr_err]);
! 913: bprintf("\7\r\nFile size (%lu bytes) is larger than %lu (maxlines: %lu).\r\n"
! 914: ,length, (ulong)maxlines*MAX_LINE_LEN, maxlines);
! 915: return;
! 916: }
1.1 root 917: if(read(file,buf,length)!=length) {
918: close(file);
1.1.1.2 ! root 919: free(buf);
1.1 root 920: errormsg(WHERE,ERR_READ,str,length);
1.1.1.2 ! root 921: return;
! 922: }
1.1 root 923: buf[length]=0;
1.1.1.2 ! root 924: close(file);
! 925: }
1.1 root 926: else {
927: buf[0]=0;
1.1.1.2 ! root 928: bputs(text[NewFile]);
! 929: }
1.1 root 930: if(!msgeditor(buf,nulstr,nulstr)) {
1.1.1.2 ! root 931: free(buf);
! 932: return;
! 933: }
1.1 root 934: bputs(text[Saving]);
935: if((file=nopen(str,O_CREAT|O_WRONLY|O_TRUNC))==-1) {
936: errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_TRUNC);
1.1.1.2 ! root 937: free(buf);
! 938: return;
! 939: }
1.1 root 940: if((size_t)write(file,buf,strlen(buf))!=strlen(buf)) {
941: close(file);
942: errormsg(WHERE,ERR_WRITE,str,strlen(buf));
1.1.1.2 ! root 943: free(buf);
! 944: return;
! 945: }
1.1 root 946: for(l=lines=0;buf[l];l++)
947: if(buf[l]==LF)
948: lines++;
949: bprintf(text[SavedNBytes],l,lines);
950: close(file);
1.1.1.2 ! root 951: free(buf);
1.1 root 952: return;
953: }
954:
955: /*************************/
956: /* Copy file attachments */
957: /*************************/
958: void sbbs_t::copyfattach(uint to, uint from, char *title)
959: {
960: char str[128],str2[128],str3[128],*tp,*sp,*p;
961:
962: strcpy(str,title);
963: tp=str;
964: while(1) {
1.1.1.2 ! root 965: p=strchr(tp,' ');
1.1 root 966: if(p) *p=0;
967: sp=strrchr(tp,'/'); /* sp is slash pointer */
968: if(!sp) sp=strrchr(tp,'\\');
969: if(sp) tp=sp+1;
970: sprintf(str2,"%sfile/%04u.in/%s" /* str2 is path/fname */
971: ,cfg.data_dir,to,tp);
972: sprintf(str3,"%sfile/%04u.in/%s" /* str2 is path/fname */
973: ,cfg.data_dir,from,tp);
974: if(strcmp(str2,str3))
975: mv(str3,str2,1);
976: if(!p)
977: break;
1.1.1.2 ! root 978: tp=p+1;
! 979: }
1.1 root 980: }
981:
982:
983: /****************************************************************************/
984: /* Forwards mail (fname) to usernumber */
985: /* Called from function readmail */
986: /****************************************************************************/
987: void sbbs_t::forwardmail(smbmsg_t *msg, int usernumber)
988: {
989: char str[256],touser[128];
990: char tmp[512];
991: int i;
992: node_t node;
993: msghdr_t hdr=msg->hdr;
994: idxrec_t idx=msg->idx;
995:
996: if(useron.etoday>=cfg.level_emailperday[useron.level] && !SYSOP) {
997: bputs(text[TooManyEmailsToday]);
1.1.1.2 ! root 998: return;
! 999: }
1.1 root 1000: if(useron.rest&FLAG('F')) {
1001: bputs(text[R_Forward]);
1.1.1.2 ! root 1002: return;
! 1003: }
1.1 root 1004: if(usernumber==1 && useron.rest&FLAG('S')) {
1005: bprintf(text[R_Feedback],cfg.sys_op);
1.1.1.2 ! root 1006: return;
! 1007: }
1.1 root 1008: if(usernumber!=1 && useron.rest&FLAG('E')) {
1009: bputs(text[R_Email]);
1.1.1.2 ! root 1010: return;
! 1011: }
1.1 root 1012:
1013: msg->idx.attr&=~(MSG_READ|MSG_DELETE);
1014: msg->hdr.attr=msg->idx.attr;
1015:
1016:
1.1.1.2 ! root 1017: smb_hfield_str(msg,SENDER,useron.alias);
1.1 root 1018: sprintf(str,"%u",useron.number);
1.1.1.2 ! root 1019: smb_hfield_str(msg,SENDEREXT,str);
1.1 root 1020:
1021: username(&cfg,usernumber,touser);
1.1.1.2 ! root 1022: smb_hfield_str(msg,RECIPIENT,touser);
1.1 root 1023: sprintf(str,"%u",usernumber);
1024: smb_hfield(msg,RECIPIENTEXT,sizeof(str),str);
1025: msg->idx.to=usernumber;
1026:
1027: now=time(NULL);
1028: smb_hfield(msg,FORWARDED,sizeof(time_t),&now);
1029:
1030:
1.1.1.2 ! root 1031: if((i=smb_open_da(&smb))!=SMB_SUCCESS) {
1.1 root 1032: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 1033: return;
! 1034: }
! 1035: if((i=smb_incmsg_dfields(&smb,msg,1))!=SMB_SUCCESS) {
1.1 root 1036: errormsg(WHERE,ERR_WRITE,smb.file,i);
1.1.1.2 ! root 1037: return;
! 1038: }
1.1 root 1039: smb_close_da(&smb);
1040:
1041:
1.1.1.2 ! root 1042: if((i=smb_addmsghdr(&smb,msg,SMB_SELFPACK))!=SMB_SUCCESS) {
1.1 root 1043: errormsg(WHERE,ERR_WRITE,smb.file,i);
1.1.1.2 ! root 1044: smb_freemsg_dfields(&smb,msg,1);
! 1045: return;
! 1046: }
1.1 root 1047:
1048: if(msg->hdr.auxattr&MSG_FILEATTACH)
1049: copyfattach(usernumber,useron.number,msg->subj);
1050:
1051: bprintf(text[Forwarded],username(&cfg,usernumber,str),usernumber);
1.1.1.2 ! root 1052: sprintf(str,"%s forwarded mail to %s #%d"
! 1053: ,useron.alias
! 1054: ,username(&cfg,usernumber,tmp)
1.1 root 1055: ,usernumber);
1056: logline("E",str);
1057: msg->idx=idx;
1058: msg->hdr=hdr;
1059:
1060:
1061: if(usernumber==1) {
1062: useron.fbacks++;
1063: logon_fbacks++;
1.1.1.2 ! root 1064: putuserrec(&cfg,useron.number,U_FBACKS,5,ultoa(useron.fbacks,tmp,10));
! 1065: }
1.1 root 1066: else {
1067: useron.emails++;
1068: logon_emails++;
1.1.1.2 ! root 1069: putuserrec(&cfg,useron.number,U_EMAILS,5,ultoa(useron.emails,tmp,10));
! 1070: }
1.1 root 1071: useron.etoday++;
1072: putuserrec(&cfg,useron.number,U_ETODAY,5,ultoa(useron.etoday,tmp,10));
1073:
1074: for(i=1;i<=cfg.sys_nodes;i++) { /* Tell user, if online */
1075: getnodedat(i,&node,0);
1076: if(node.useron==usernumber && !(node.misc&NODE_POFF)
1077: && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
1078: sprintf(str,text[EmailNodeMsg],cfg.node_num,useron.alias);
1.1.1.2 ! root 1079: putnmsg(&cfg,i,str);
! 1080: break;
! 1081: }
! 1082: }
1.1 root 1083: if(i>cfg.sys_nodes) { /* User wasn't online, so leave short msg */
1084: sprintf(str,text[UserSentYouMail],useron.alias);
1.1.1.2 ! root 1085: putsmsg(&cfg,usernumber,str);
! 1086: }
1.1 root 1087: }
1088:
1089: /****************************************************************************/
1090: /* Auto-Message Routine ('A' from the main menu) */
1091: /****************************************************************************/
1092: void sbbs_t::automsg()
1093: {
1094: char str[256],buf[300],anon=0;
1095: char tmp[512];
1.1.1.2 ! root 1096: char automsg[MAX_PATH+1];
1.1 root 1097: int file;
1.1.1.2 ! root 1098: time_t now=time(NULL);
1.1 root 1099:
1100: sprintf(automsg,"%smsgs/auto.msg",cfg.data_dir);
1101: while(online) {
1102: SYNC;
1103: mnemonics(text[AutoMsg]);
1104: switch(getkeys("RWQ",0)) {
1105: case 'R':
1106: printfile(automsg,P_NOABORT|P_NOATCODES);
1107: break;
1108: case 'W':
1109: if(useron.rest&FLAG('W')) {
1110: bputs(text[R_AutoMsg]);
1.1.1.2 ! root 1111: break;
! 1112: }
1.1 root 1113: action=NODE_AMSG;
1114: SYNC;
1115: bputs("\r\n3 lines:\r\n");
1116: if(!getstr(str,68,K_WRAP|K_MSG))
1117: break;
1118: strcpy(buf,str);
1119: strcat(buf,"\r\n ");
1120: getstr(str,68,K_WRAP|K_MSG);
1121: strcat(buf,str);
1122: strcat(buf,"\r\n ");
1123: getstr(str,68,K_MSG);
1124: strcat(str,crlf);
1125: strcat(buf,str);
1126: if(yesno(text[OK])) {
1127: if(useron.exempt&FLAG('A')) {
1128: if(!noyes(text[AnonymousQ]))
1.1.1.2 ! root 1129: anon=1;
! 1130: }
1.1 root 1131: if((file=nopen(automsg,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
1132: errormsg(WHERE,ERR_OPEN,automsg,O_WRONLY|O_CREAT|O_TRUNC);
1.1.1.2 ! root 1133: return;
! 1134: }
1.1 root 1135: if(anon)
1136: sprintf(tmp,"%.80s",text[Anonymous]);
1137: else
1138: sprintf(tmp,"%s #%d",useron.alias,useron.number);
1.1.1.2 ! root 1139: sprintf(str,text[AutoMsgBy],tmp,timestr(&now));
1.1 root 1140: strcat(str," ");
1141: write(file,str,strlen(str));
1142: write(file,buf,strlen(buf));
1.1.1.2 ! root 1143: close(file);
! 1144: }
1.1 root 1145: break;
1146: case 'Q':
1.1.1.2 ! root 1147: return;
! 1148: }
! 1149: }
1.1 root 1150: }
1151:
1152: /****************************************************************************/
1153: /* Edits messages */
1154: /****************************************************************************/
1155: void sbbs_t::editmsg(smbmsg_t *msg, uint subnum)
1156: {
1.1.1.2 ! root 1157: char buf[SDT_BLOCK_LEN];
! 1158: char msgtmp[MAX_PATH+1];
1.1 root 1159: ushort xlat;
1160: int file,i,j,x;
1.1.1.2 ! root 1161: long length,offset;
1.1 root 1162: FILE *instream;
1163:
1164: if(!msg->hdr.total_dfields)
1165: return;
1.1.1.2 ! root 1166: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&QUICKBBS)
! 1167: sprintf(msgtmp,"%sMSGTMP",cfg.node_dir); /* QuickBBS editors are dumb */
! 1168: else
! 1169: sprintf(msgtmp,"%sINPUT.MSG",cfg.temp_dir);
! 1170: if(useron.xedit && cfg.xedit[useron.xedit-1]->misc&XTRN_LWRCASE)
! 1171: strlwr(msgtmp);
! 1172:
! 1173: remove(msgtmp);
! 1174: msgtotxt(msg,msgtmp,0,1);
! 1175: editfile(msgtmp);
! 1176: length=flength(msgtmp);
1.1 root 1177: if(length<1L)
1178: return;
1179:
1.1.1.2 ! root 1180: length+=2; /* +2 for translation string */
! 1181:
! 1182: if((i=smb_locksmbhdr(&smb))!=SMB_SUCCESS) {
1.1 root 1183: errormsg(WHERE,ERR_LOCK,smb.file,i);
1.1.1.2 ! root 1184: return;
! 1185: }
1.1 root 1186:
1.1.1.2 ! root 1187: if((i=smb_getstatus(&smb))!=SMB_SUCCESS) {
1.1 root 1188: errormsg(WHERE,ERR_READ,smb.file,i);
1.1.1.2 ! root 1189: return;
! 1190: }
1.1 root 1191:
1192: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1.1.1.2 ! root 1193: if((i=smb_open_da(&smb))!=SMB_SUCCESS) {
1.1 root 1194: errormsg(WHERE,ERR_OPEN,smb.file,i,smb.last_error);
1.1.1.2 ! root 1195: return;
! 1196: }
! 1197: if((i=smb_freemsg_dfields(&smb,msg,1))!=SMB_SUCCESS)
! 1198: errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error);
! 1199: }
1.1 root 1200:
1201: msg->dfield[0].type=TEXT_BODY; /* Make one single data field */
1202: msg->dfield[0].length=length;
1203: msg->dfield[0].offset=0;
1204: for(x=1;x<msg->hdr.total_dfields;x++) { /* Clear the other data fields */
1205: msg->dfield[x].type=UNUSED; /* so we leave the header length */
1206: msg->dfield[x].length=0; /* unchanged */
1.1.1.2 ! root 1207: msg->dfield[x].offset=0;
! 1208: }
1.1 root 1209:
1210:
1.1.1.2 ! root 1211: if(smb.status.attr&SMB_HYPERALLOC)
! 1212: offset=smb_hallocdat(&smb);
1.1 root 1213: else {
1214: if((subnum!=INVALID_SUB && cfg.sub[subnum]->misc&SUB_FAST)
1215: || (subnum==INVALID_SUB && cfg.sys_misc&SM_FASTMAIL))
1216: offset=smb_fallocdat(&smb,length,1);
1217: else
1218: offset=smb_allocdat(&smb,length,1);
1.1.1.2 ! root 1219: smb_close_da(&smb);
! 1220: }
1.1 root 1221:
1222: msg->hdr.offset=offset;
1.1.1.2 ! root 1223: if((file=open(msgtmp,O_RDONLY|O_BINARY))==-1
1.1 root 1224: || (instream=fdopen(file,"rb"))==NULL) {
1225: smb_unlocksmbhdr(&smb);
1226: smb_freemsgdat(&smb,offset,length,1);
1.1.1.2 ! root 1227: errormsg(WHERE,ERR_OPEN,msgtmp,O_RDONLY|O_BINARY);
! 1228: return;
! 1229: }
1.1 root 1230:
1231: setvbuf(instream,NULL,_IOFBF,2*1024);
1232: fseek(smb.sdt_fp,offset,SEEK_SET);
1233: xlat=XLAT_NONE;
1234: fwrite(&xlat,2,1,smb.sdt_fp);
1235: x=SDT_BLOCK_LEN-2; /* Don't read/write more than 255 */
1236: while(!feof(instream)) {
1237: memset(buf,0,x);
1238: j=fread(buf,1,x,instream);
1.1.1.2 ! root 1239: if(j<1)
! 1240: break;
! 1241: if(j>1 && (j!=x || feof(instream)) && buf[j-1]==LF && buf[j-2]==CR)
1.1 root 1242: buf[j-1]=buf[j-2]=0; /* Convert to NULL */
1243: fwrite(buf,j,1,smb.sdt_fp);
1.1.1.2 ! root 1244: x=SDT_BLOCK_LEN;
! 1245: }
1.1 root 1246: fflush(smb.sdt_fp);
1247: fclose(instream);
1248:
1249: smb_unlocksmbhdr(&smb);
1.1.1.2 ! root 1250: msg->hdr.length=(ushort)smb_getmsghdrlen(msg);
! 1251: if((i=smb_putmsghdr(&smb,msg))!=SMB_SUCCESS)
1.1 root 1252: errormsg(WHERE,ERR_WRITE,smb.file,i);
1253: }
1254:
1255: /****************************************************************************/
1256: /* Moves a message from one message base to another */
1257: /****************************************************************************/
1258: bool sbbs_t::movemsg(smbmsg_t* msg, uint subnum)
1259: {
1260: char str[256],*buf;
1261: uint i;
1.1.1.2 ! root 1262: int newgrp,newsub,storage;
1.1 root 1263: ulong offset,length;
1.1.1.2 ! root 1264: smbmsg_t newmsg=*msg;
! 1265: smb_t newsmb;
1.1 root 1266:
1267: for(i=0;i<usrgrps;i++) /* Select New Group */
1268: uselect(1,i,"Message Group",cfg.grp[usrgrp[i]]->lname,0);
1269: if((newgrp=uselect(0,0,0,0,0))<0)
1270: return(false);
1271:
1272: for(i=0;i<usrsubs[newgrp];i++) /* Select New Sub-Board */
1273: uselect(1,i,"Sub-Board",cfg.sub[usrsub[newgrp][i]]->lname,0);
1274: if((newsub=uselect(0,0,0,0,0))<0)
1275: return(false);
1276: newsub=usrsub[newgrp][newsub];
1277:
1278: length=smb_getmsgdatlen(msg);
1279: if((buf=(char *)MALLOC(length))==NULL) {
1280: errormsg(WHERE,ERR_ALLOC,smb.file,length);
1.1.1.2 ! root 1281: return(false);
! 1282: }
1.1 root 1283:
1284: fseek(smb.sdt_fp,msg->hdr.offset,SEEK_SET);
1285: fread(buf,length,1,smb.sdt_fp);
1286:
1.1.1.2 ! root 1287: sprintf(newsmb.file,"%s%s",cfg.sub[newsub]->data_dir,cfg.sub[newsub]->code);
! 1288: newsmb.retry_time=cfg.smb_retry_time;
! 1289: newsmb.subnum=newsub;
! 1290: if((i=smb_open(&newsmb))!=SMB_SUCCESS) {
! 1291: free(buf);
! 1292: errormsg(WHERE,ERR_OPEN,newsmb.file,i,newsmb.last_error);
! 1293: return(false);
! 1294: }
! 1295:
! 1296: if(filelength(fileno(newsmb.shd_fp))<1) { /* Create it if it doesn't exist */
! 1297: newsmb.status.max_crcs=cfg.sub[newsub]->maxcrcs;
! 1298: newsmb.status.max_msgs=cfg.sub[newsub]->maxmsgs;
! 1299: newsmb.status.max_age=cfg.sub[newsub]->maxage;
! 1300: newsmb.status.attr=cfg.sub[newsub]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
! 1301: if((i=smb_create(&newsmb))!=SMB_SUCCESS) {
! 1302: free(buf);
! 1303: smb_close(&newsmb);
! 1304: errormsg(WHERE,ERR_CREATE,newsmb.file,i,newsmb.last_error);
! 1305: return(false);
! 1306: }
! 1307: }
! 1308:
! 1309: if((i=smb_locksmbhdr(&newsmb))!=SMB_SUCCESS) {
! 1310: free(buf);
! 1311: smb_close(&newsmb);
! 1312: errormsg(WHERE,ERR_LOCK,newsmb.file,i,newsmb.last_error);
! 1313: return(false);
! 1314: }
! 1315:
! 1316: if((i=smb_getstatus(&newsmb))!=SMB_SUCCESS) {
! 1317: free(buf);
! 1318: smb_close(&newsmb);
! 1319: errormsg(WHERE,ERR_READ,newsmb.file,i,newsmb.last_error);
! 1320: return(false);
! 1321: }
! 1322:
! 1323: if(newsmb.status.attr&SMB_HYPERALLOC) {
! 1324: offset=smb_hallocdat(&newsmb);
! 1325: storage=SMB_HYPERALLOC;
! 1326: }
1.1 root 1327: else {
1.1.1.2 ! root 1328: if((i=smb_open_da(&newsmb))!=SMB_SUCCESS) {
! 1329: free(buf);
! 1330: smb_close(&newsmb);
! 1331: errormsg(WHERE,ERR_OPEN,newsmb.file,i,newsmb.last_error);
! 1332: return(false);
! 1333: }
1.1 root 1334: if(cfg.sub[newsub]->misc&SUB_FAST) {
1.1.1.2 ! root 1335: offset=smb_fallocdat(&newsmb,length,1);
! 1336: storage=SMB_FASTALLOC;
! 1337: }
1.1 root 1338: else {
1.1.1.2 ! root 1339: offset=smb_allocdat(&newsmb,length,1);
! 1340: storage=SMB_SELFPACK;
! 1341: }
! 1342: smb_close_da(&newsmb);
! 1343: }
1.1 root 1344:
1.1.1.2 ! root 1345: newmsg.hdr.offset=offset;
! 1346: newmsg.hdr.version=smb_ver();
1.1 root 1347:
1.1.1.2 ! root 1348: fseek(newsmb.sdt_fp,offset,SEEK_SET);
! 1349: fwrite(buf,length,1,newsmb.sdt_fp);
! 1350: fflush(newsmb.sdt_fp);
! 1351: free(buf);
1.1 root 1352:
1.1.1.2 ! root 1353: i=smb_addmsghdr(&newsmb,&newmsg,storage); // calls smb_unlocksmbhdr()
! 1354: smb_close(&newsmb);
1.1 root 1355:
1356: if(i) {
1.1.1.2 ! root 1357: errormsg(WHERE,ERR_WRITE,newsmb.file,i,newsmb.last_error);
! 1358: smb_freemsg_dfields(&newsmb,&newmsg,1);
! 1359: return(false);
! 1360: }
1.1 root 1361:
1362: bprintf("\r\nMoved to %s %s\r\n\r\n"
1363: ,cfg.grp[usrgrp[newgrp]]->sname,cfg.sub[newsub]->lname);
1.1.1.2 ! root 1364: sprintf(str,"%s moved message from %s %s to %s %s"
! 1365: ,useron.alias
1.1 root 1366: ,cfg.grp[newgrp]->sname,cfg.sub[newsub]->sname
1367: ,cfg.grp[cfg.sub[subnum]->grp]->sname,cfg.sub[subnum]->sname);
1368: logline("M+",str);
1.1.1.2 ! root 1369: signal_sub_sem(&cfg,newsub);
! 1370:
1.1 root 1371: return(true);
1372: }
1373:
1374: ushort sbbs_t::chmsgattr(ushort attr)
1375: {
1376: int ch;
1377:
1378: while(online && !(sys_status&SS_ABORT)) {
1379: CRLF;
1380: show_msgattr(attr);
1381: menu("msgattr");
1382: ch=getkey(K_UPPER);
1383: if(ch)
1384: bprintf("%c\r\n",ch);
1385: switch(ch) {
1386: case 'P':
1387: attr^=MSG_PRIVATE;
1388: break;
1389: case 'R':
1390: attr^=MSG_READ;
1391: break;
1392: case 'K':
1393: attr^=MSG_KILLREAD;
1394: break;
1395: case 'A':
1396: attr^=MSG_ANONYMOUS;
1397: break;
1398: case 'N': /* Non-purgeable */
1399: attr^=MSG_PERMANENT;
1400: break;
1401: case 'M':
1402: attr^=MSG_MODERATED;
1403: break;
1404: case 'V':
1405: attr^=MSG_VALIDATED;
1406: break;
1407: case 'D':
1408: attr^=MSG_DELETE;
1409: break;
1410: case 'L':
1411: attr^=MSG_LOCKED;
1412: break;
1413: default:
1.1.1.2 ! root 1414: return(attr);
! 1415: }
! 1416: }
1.1 root 1417: return(attr);
1418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.