Annotation of sbbs/src/sbbs3/un_qwk.cpp, revision 1.1.1.2

1.1       root        1: /* un_qwk.cpp */
                      2: 
                      3: /* Synchronet QWK unpacking routine */
                      4: 
1.1.1.2 ! root        5: /* $Id: un_qwk.cpp,v 1.42 2011/09/21 03:10:53 rswindell Exp $ */
1.1       root        6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
1.1.1.2 ! root       11:  * Copyright 2010 Rob Swindell - http://www.synchro.net/copyright.html         *
1.1       root       12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include "sbbs.h"
                     39: #include "qwk.h"
                     40: 
                     41: /****************************************************************************/
                     42: /* Unpacks .QWK packet, hubnum is the number of the QWK net hub                        */
                     43: /****************************************************************************/
                     44: bool sbbs_t::unpack_qwk(char *packet,uint hubnum)
                     45: {
                     46:        char    str[MAX_PATH+1],fname[MAX_PATH+1];
                     47:        char    tmp[512];
                     48:        char    inbox[MAX_PATH+1];
                     49:        uchar   block[QWK_BLOCK_LEN];
                     50:        int     k,file;
                     51:        uint    i,j,n,lastsub=INVALID_SUB;
1.1.1.2 ! root       52:        uint    usernum;
1.1       root       53:        uint    blocks;
                     54:        long    l,size,misc;
                     55:        ulong   t;
                     56:        ulong   msgs=0;
                     57:        ulong   tmsgs=0;
                     58:        time_t  start;
                     59:        time_t  startsub;
                     60:        DIR*    dir;
                     61:        DIRENT* dirent;
                     62:        FILE*   qwk;
1.1.1.2 ! root       63:        FILE*   fp;
        !            64:        smbmsg_t        msg;
        !            65:        str_list_t      headers=NULL;
        !            66:        str_list_t      ip_can=NULL;
        !            67:        str_list_t      host_can=NULL;
        !            68:        str_list_t      subject_can=NULL;
        !            69:        str_list_t      twit_list=NULL;
        !            70:        const char* hostname;
1.1       root       71: 
1.1.1.2 ! root       72:        memset(&msg,0,sizeof(msg));
1.1       root       73: 
                     74:        start=time(NULL);
1.1.1.2 ! root       75:        if((l=(long)flength(packet))<1) {
1.1       root       76:                errormsg(WHERE,ERR_LEN,packet,l);
                     77:                return(false);
                     78:        }
1.1.1.2 ! root       79:        delfiles(cfg.temp_dir,ALLFILES);
1.1       root       80:        i=external(cmdstr(cfg.qhub[hubnum]->unpack,packet,ALLFILES,NULL),EX_OFFLINE);
                     81:        if(i) {
                     82:                errormsg(WHERE,ERR_EXEC,cmdstr(cfg.qhub[hubnum]->unpack,packet,ALLFILES,NULL),i);
                     83:                return(false); 
                     84:        }
1.1.1.2 ! root       85:        SAFEPRINTF(str,"%sMESSAGES.DAT",cfg.temp_dir);
1.1       root       86:        if(!fexistcase(str)) {
1.1.1.2 ! root       87:                lprintf(LOG_WARNING,"%s doesn't contain MESSAGES.DAT (%s)",packet,str);
1.1       root       88:                return(false); 
                     89:        }
                     90:        if((qwk=fnopen(&file,str,O_RDONLY))==NULL) {
                     91:                errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
                     92:                return(false); 
                     93:        }
1.1.1.2 ! root       94:        size=(long)filelength(file);
        !            95: 
        !            96:        SAFEPRINTF(str,"%sHEADERS.DAT",cfg.temp_dir);
        !            97:        if(fexistcase(str)) {
        !            98:                if((fp=fopen(str,"r")) == NULL)
        !            99:                        errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
        !           100:                else {
        !           101:                        headers=iniReadFile(fp);
        !           102:                        fclose(fp);
        !           103:                }
        !           104:                remove(str);
        !           105:        }
        !           106: 
1.1       root      107:        /********************/
                    108:        /* Process messages */
                    109:        /********************/
                    110:        eprintf(LOG_INFO,"Importing QWK Network Packet: %s",packet);
                    111: 
1.1.1.2 ! root      112:        ip_can=trashcan_list(&cfg,"ip");
        !           113:        host_can=trashcan_list(&cfg,"host");
        !           114:        subject_can=trashcan_list(&cfg,"subject");
        !           115: 
        !           116:        SAFEPRINTF(fname,"%stwitlist.cfg",cfg.ctrl_dir);
        !           117:        if((fp=fopen(fname,"r"))!=NULL) {
        !           118:                twit_list=strListReadFile(fp,NULL,128);
        !           119:                fclose(fp);
        !           120:        }
        !           121: 
1.1       root      122:        for(l=QWK_BLOCK_LEN;l<size;l+=blocks*QWK_BLOCK_LEN) {
                    123:                if(terminated) {
                    124:                        eprintf(LOG_NOTICE,"!Terminated");
                    125:                        break;
                    126:                }
                    127:                fseek(qwk,l,SEEK_SET);
                    128:                fread(block,QWK_BLOCK_LEN,1,qwk);
                    129:                if(block[0]<' ' || block[0]&0x80) {
1.1.1.2 ! root      130:                        eprintf(LOG_NOTICE,"!Invalid QWK message status (%02X) at offset %lu in %s"
1.1       root      131:                                ,block[0], l, packet);
                    132:                        blocks=1;
                    133:                        continue;
                    134:                }
                    135:                sprintf(tmp,"%.6s",block+116);
                    136:                blocks=atoi(tmp);  /* i = number of blocks */
                    137:                if(blocks<2) {
1.1.1.2 ! root      138:                        eprintf(LOG_NOTICE,"!Invalid number of QWK blocks (%d) at offset %lu in %s"
1.1       root      139:                                ,blocks, l+116, packet);
                    140:                        blocks=1;
                    141:                        continue; 
                    142:                }
                    143:                /*********************************/
                    144:                /* public message on a sub-board */
                    145:                /*********************************/
                    146:                n=(uint)block[123]|(((uint)block[124])<<8);  /* conference number */
                    147: 
1.1.1.2 ! root      148:                qwk_new_msg(&msg,(char*)block,/* offset: */l,headers,/* parse_sender_hfields: */true);
        !           149: 
        !           150:                if(cfg.max_qwkmsgage && msg.hdr.when_written.time < (uint32_t)now
        !           151:                        && (now-msg.hdr.when_written.time)/(24*60*60) > cfg.max_qwkmsgage) {
        !           152:                        eprintf(LOG_NOTICE,"!Filtering QWK message from %s due to age: %u days"
        !           153:                                ,msg.from
        !           154:                                ,(now-msg.hdr.when_written.time)/(24*60*60)); 
        !           155:                        logline(LOG_NOTICE,"P!",str);
        !           156:                        continue;
        !           157:                }
        !           158: 
        !           159:                if(findstr_in_list(msg.from_ip,ip_can)) {
        !           160:                        eprintf(LOG_NOTICE,"!Filtering QWK message from %s due to blocked IP: %s"
        !           161:                                ,msg.from
        !           162:                                ,msg.from_ip); 
        !           163:                        continue;
        !           164:                }
        !           165: 
        !           166:                hostname=getHostNameByAddr(msg.from_host);
        !           167:                if(findstr_in_list(hostname,host_can)) {
        !           168:                        eprintf(LOG_NOTICE,"!Filtering QWK message from %s due to blocked hostname: %s"
        !           169:                                ,msg.from
        !           170:                                ,hostname); 
        !           171:                        continue;
        !           172:                }
        !           173: 
        !           174:                if(findstr_in_list(msg.subj,subject_can)) {
        !           175:                        eprintf(LOG_NOTICE,"!Filtering QWK message from %s due to filtered subject: %s"
        !           176:                                ,msg.from
        !           177:                                ,msg.subj); 
        !           178:                        continue;
        !           179:                }
        !           180: 
1.1       root      181:                if(!n) {                /* NETMAIL */
1.1.1.2 ! root      182:                        eprintf(LOG_INFO,"QWK NetMail from %s to %s", cfg.qhub[hubnum]->id, msg.to);
        !           183:                        if(!stricmp(msg.to,"NETMAIL")) {  /* QWK to FidoNet NetMail */
1.1       root      184:                                qwktonetmail(qwk,(char *)block,NULL,hubnum+1);
                    185:                                continue; 
                    186:                        }
1.1.1.2 ! root      187:                        if(strchr(msg.to,'@')) {
        !           188:                                qwktonetmail(qwk,(char *)block,msg.to,hubnum+1);
1.1       root      189:                                continue; 
                    190:                        }
1.1.1.2 ! root      191:                        usernum=atoi(msg.to);
        !           192:                        if(usernum && usernum>lastuser(&cfg))
        !           193:                                usernum=0;
        !           194:                        if(!usernum)
        !           195:                                usernum=matchuser(&cfg,msg.to,TRUE /* sysop_alias */);
        !           196:                        if(!usernum) {
        !           197:                                eprintf(LOG_NOTICE,"!QWK NetMail from %s to UNKNOWN USER: %s", cfg.qhub[hubnum]->id, msg.to);
1.1       root      198:                                continue; 
                    199:                        }
                    200: 
1.1.1.2 ! root      201:                        getuserrec(&cfg,usernum,U_MISC,8,str);
1.1       root      202:                        misc=ahtoul(str);
                    203:                        if(misc&NETMAIL && cfg.sys_misc&SM_FWDTONET) {
1.1.1.2 ! root      204:                                getuserrec(&cfg,usernum,U_NETMAIL,LEN_NETMAIL,str);
1.1       root      205:                                qwktonetmail(qwk,(char*)block,str,hubnum+1);
                    206:                                continue; 
                    207:                        }
                    208: 
                    209:                        smb_stack(&smb,SMB_STACK_PUSH);
                    210:                        sprintf(smb.file,"%smail",cfg.data_dir);
                    211:                        smb.retry_time=cfg.smb_retry_time;
                    212:                        smb.subnum=INVALID_SUB;
                    213:                        if((k=smb_open(&smb))!=0) {
                    214:                                errormsg(WHERE,ERR_OPEN,smb.file,k,smb.last_error);
                    215:                                smb_stack(&smb,SMB_STACK_POP);
                    216:                                continue; 
                    217:                        }
                    218:                        if(!filelength(fileno(smb.shd_fp))) {
                    219:                                smb.status.max_crcs=cfg.mail_maxcrcs;
                    220:                                smb.status.max_msgs=0;
                    221:                                smb.status.max_age=cfg.mail_maxage;
                    222:                                smb.status.attr=SMB_EMAIL;
                    223:                                if((k=smb_create(&smb))!=0) {
                    224:                                        smb_close(&smb);
1.1.1.2 ! root      225:                                        errormsg(WHERE,ERR_CREATE,smb.file,k,smb.last_error);
1.1       root      226:                                        smb_stack(&smb,SMB_STACK_POP);
                    227:                                        continue; 
                    228:                                } 
                    229:                        }
                    230:                        if((k=smb_locksmbhdr(&smb))!=0) {
                    231:                                smb_close(&smb);
1.1.1.2 ! root      232:                                errormsg(WHERE,ERR_LOCK,smb.file,k,smb.last_error);
1.1       root      233:                                smb_stack(&smb,SMB_STACK_POP);
                    234:                                continue; 
                    235:                        }
                    236:                        if((k=smb_getstatus(&smb))!=0) {
                    237:                                smb_close(&smb);
1.1.1.2 ! root      238:                                errormsg(WHERE,ERR_READ,smb.file,k,smb.last_error);
1.1       root      239:                                smb_stack(&smb,SMB_STACK_POP);
                    240:                                continue; 
                    241:                        }
                    242:                        smb_unlocksmbhdr(&smb);
1.1.1.2 ! root      243:                        if(qwk_import_msg(qwk,(char *)block,blocks,hubnum+1,INVALID_SUB,usernum,&msg)) {
        !           244:                                SAFEPRINTF(str,text[UserSentYouMail],msg.from);
        !           245:                                putsmsg(&cfg,usernum,str);
1.1       root      246:                                tmsgs++;
                    247:                        }
                    248:                        smb_close(&smb);
                    249:                        smb_stack(&smb,SMB_STACK_POP);
                    250:                        continue;
                    251:                }
                    252: 
                    253:                for(j=0;j<cfg.qhub[hubnum]->subs;j++)
                    254:                        if(cfg.qhub[hubnum]->conf[j]==n)
                    255:                                break;
                    256:                if(j>=cfg.qhub[hubnum]->subs) { /* ignore messages for subs not in config */
1.1.1.2 ! root      257:                        eprintf(LOG_NOTICE,"!Message from %s on UNKNOWN QWK CONFERENCE NUMBER: %u"
1.1       root      258:                                ,cfg.qhub[hubnum]->id, n);
                    259:                        continue;
                    260:                }
                    261: 
                    262:                j=cfg.qhub[hubnum]->sub[j];
                    263: 
                    264:                /* TWIT FILTER */
1.1.1.2 ! root      265:                if(findstr_in_list(msg.from,twit_list) || findstr_in_list(msg.to,twit_list)) {
        !           266:                        eprintf(LOG_NOTICE,"!Filtering QWK post from %s to %s on %s %s"
        !           267:                                ,msg.from
        !           268:                                ,msg.to
        !           269:                                ,cfg.grp[cfg.sub[j]->grp]->sname,cfg.sub[j]->lname); 
        !           270:                        continue; 
1.1       root      271:                }
                    272: 
                    273:                if(j!=lastsub) {
                    274: 
                    275:                        if(msgs) {
                    276:                                t=time(NULL)-startsub;
                    277:                                if(t<1)
                    278:                                        t=1;
1.1.1.2 ! root      279:                                eprintf(LOG_INFO,"Imported %lu QWK msgs in %lu seconds (%lu msgs/sec)", msgs,t,msgs/t);
1.1       root      280:                        }
                    281:                        msgs=0;
                    282:                        startsub=time(NULL);
                    283: 
1.1.1.2 ! root      284:                        eprintf(LOG_INFO,"Importing QWK messages from %s into %s %s"
1.1       root      285:                                ,cfg.qhub[hubnum]->id, cfg.grp[cfg.sub[j]->grp]->sname,cfg.sub[j]->lname);
                    286: 
                    287:                        if(lastsub!=INVALID_SUB)
                    288:                                smb_close(&smb);
                    289:                        lastsub=INVALID_SUB;
                    290:                        sprintf(smb.file,"%s%s",cfg.sub[j]->data_dir,cfg.sub[j]->code);
                    291:                        smb.retry_time=cfg.smb_retry_time;
                    292:                        smb.subnum=j;
                    293:                        if((k=smb_open(&smb))!=0) {
                    294:                                errormsg(WHERE,ERR_OPEN,smb.file,k,smb.last_error);
                    295:                                continue; 
                    296:                        }
                    297:                        if(!filelength(fileno(smb.shd_fp))) {
                    298:                                smb.status.max_crcs=cfg.sub[j]->maxcrcs;
                    299:                                smb.status.max_msgs=cfg.sub[j]->maxmsgs;
                    300:                                smb.status.max_age=cfg.sub[j]->maxage;
                    301:                                smb.status.attr=cfg.sub[j]->misc&SUB_HYPER ? SMB_HYPERALLOC :0;
                    302:                                if((k=smb_create(&smb))!=0) {
                    303:                                        smb_close(&smb);
1.1.1.2 ! root      304:                                        errormsg(WHERE,ERR_CREATE,smb.file,k,smb.last_error);
1.1       root      305:                                        continue; 
                    306:                                } 
                    307:                        }
                    308:                        if((k=smb_locksmbhdr(&smb))!=0) {
                    309:                                smb_close(&smb);
1.1.1.2 ! root      310:                                errormsg(WHERE,ERR_LOCK,smb.file,k,smb.last_error);
1.1       root      311:                                continue; 
                    312:                        }
                    313:                        if((k=smb_getstatus(&smb))!=0) {
                    314:                                smb_close(&smb);
1.1.1.2 ! root      315:                                errormsg(WHERE,ERR_READ,smb.file,k,smb.last_error);
1.1       root      316:                                continue; 
                    317:                        }
                    318:                        smb_unlocksmbhdr(&smb);
                    319:                        lastsub=j; 
                    320:                }
                    321: 
1.1.1.2 ! root      322:                if(qwk_import_msg(qwk,(char *)block,blocks,hubnum+1,/*subnum: */j,/*touser: */0,&msg)) {
        !           323:                        signal_sub_sem(&cfg,j);
        !           324:                        msgs++;
        !           325:                        tmsgs++;
1.1       root      326:                }
                    327:        }
                    328: 
                    329:        update_qwkroute(NULL);          /* Write ROUTE.DAT */
                    330: 
1.1.1.2 ! root      331:        smb_freemsgmem(&msg);
1.1       root      332:        fclose(qwk);
1.1.1.2 ! root      333: 
        !           334:        iniFreeStringList(headers);
        !           335: 
        !           336:        strListFree(&ip_can);
        !           337:        strListFree(&host_can);
        !           338:        strListFree(&subject_can);
        !           339:        strListFree(&twit_list);
        !           340: 
1.1       root      341:        if(lastsub!=INVALID_SUB)
                    342:                smb_close(&smb);
                    343: 
                    344:        delfiles(cfg.temp_dir,"*.NDX");
1.1.1.2 ! root      345:        SAFEPRINTF(str,"%sMESSAGES.DAT",cfg.temp_dir);
1.1       root      346:        remove(str);
1.1.1.2 ! root      347:        SAFEPRINTF(str,"%sDOOR.ID",cfg.temp_dir);
1.1       root      348:        remove(str);
1.1.1.2 ! root      349:        SAFEPRINTF(str,"%sCONTROL.DAT",cfg.temp_dir);
1.1       root      350:        remove(str);
1.1.1.2 ! root      351:        SAFEPRINTF(str,"%sNETFLAGS.DAT",cfg.temp_dir);
1.1       root      352:        remove(str);
                    353: 
                    354:        dir=opendir(cfg.temp_dir);
                    355:        while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
                    356:                sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name);
                    357:                if(isdir(str))  /* sub-dir */
                    358:                        continue;
                    359: 
                    360:                // Create directory if necessary
                    361:                sprintf(inbox,"%sqnet/%s.in",cfg.data_dir,cfg.qhub[hubnum]->id);
                    362:                MKDIR(inbox);
                    363: 
                    364:                // Copy files
                    365:                sprintf(fname,"%s/%s",inbox,dirent->d_name);
                    366:                mv(str,fname,1 /* overwrite */);
                    367:                sprintf(str,text[ReceivedFileViaQWK],dirent->d_name,cfg.qhub[hubnum]->id);
                    368:                putsmsg(&cfg,1,str);
                    369:                eprintf(LOG_INFO,"Received %s from %s", dirent->d_name, cfg.qhub[hubnum]->id);
                    370:        }
                    371:        if(dir!=NULL)
                    372:                closedir(dir);
                    373: 
                    374:        t=time(NULL)-start;
                    375:        if(tmsgs) {
                    376:                if(t<1)
                    377:                        t=1;
                    378:                eprintf(LOG_INFO,"Finished Importing QWK Network Packet from %s: "
                    379:                        "(%lu msgs) in %lu seconds (%lu msgs/sec)"
                    380:                        ,cfg.qhub[hubnum]->id, tmsgs, t, tmsgs/t);
1.1.1.2 ! root      381:                /* trigger timed event with internal code of 'qnet-qwk' to run */
        !           382:                sprintf(str,"%sqnet-qwk.now",cfg.data_dir);
        !           383:                ftouch(str);
1.1       root      384:        }
                    385:        delfiles(cfg.temp_dir,ALLFILES);
                    386:        return(true);
                    387: }

unix.superglobalmegacorp.com

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