Annotation of sbbs/src/sbbs3/writemsg.cpp, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.