Annotation of sbbs/src/sbbs3/download.cpp, revision 1.1

1.1     ! root        1: /* download.cpp */
        !             2: 
        !             3: /* Synchronet file download routines */
        !             4: 
        !             5: /* $Id: download.cpp,v 1.36 2006/06/18 05:08:13 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: #include "telnet.h"
        !            40: 
        !            41: /****************************************************************************/
        !            42: /* Updates downloader, uploader and downloaded file data                    */
        !            43: /* Must have offset, dir and name fields filled prior to call.              */
        !            44: /****************************************************************************/
        !            45: void sbbs_t::downloadfile(file_t* f)
        !            46: {
        !            47:     char       str[256],fname[13];
        !            48:        char    tmp[512];
        !            49:     int                i,file;
        !            50:        long    length,mod;
        !            51:     ulong      l;
        !            52:        user_t  uploader;
        !            53: 
        !            54:        getfiledat(&cfg,f); /* Get current data - right after download */
        !            55:        if((length=f->size)<0L)
        !            56:                length=0L;
        !            57:        if(!(cfg.dir[f->dir]->misc&DIR_NOSTAT)) {
        !            58:                logon_dlb+=length;  /* Update 'this call' stats */
        !            59:                logon_dls++;
        !            60:        }
        !            61:        bprintf(text[FileNBytesSent],f->name,ultoac(length,tmp));
        !            62:        sprintf(str,"%s downloaded %s from %s %s"
        !            63:                ,useron.alias
        !            64:                ,f->name,cfg.lib[cfg.dir[f->dir]->lib]->sname
        !            65:                ,cfg.dir[f->dir]->sname);
        !            66:        logline("D-",str);
        !            67:        /****************************/
        !            68:        /* Update Downloader's Info */
        !            69:        /****************************/
        !            70:        user_downloaded(&cfg, &useron, 1, length);
        !            71:        if(!is_download_free(&cfg,f->dir,&useron))
        !            72:                subtract_cdt(&cfg,&useron,f->cdt);
        !            73:        /**************************/
        !            74:        /* Update Uploader's Info */
        !            75:        /**************************/
        !            76:        i=matchuser(&cfg,f->uler,TRUE /*sysop_alias*/);
        !            77:        uploader.number=i;
        !            78:        getuserdat(&cfg,&uploader);
        !            79:        if(i && i!=useron.number && uploader.firston<f->dateuled) {
        !            80:                l=f->cdt;
        !            81:                if(!(cfg.dir[f->dir]->misc&DIR_CDTDL))  /* Don't give credits on d/l */
        !            82:                        l=0;
        !            83:                if(cfg.dir[f->dir]->misc&DIR_CDTMIN && cur_cps) { /* Give min instead of cdt */
        !            84:                        mod=((ulong)(l*(cfg.dir[f->dir]->dn_pct/100.0))/cur_cps)/60;
        !            85:                        adjustuserrec(&cfg,i,U_MIN,10,mod);
        !            86:                        sprintf(tmp,"%lu minute",mod);
        !            87:                } else {
        !            88:                        mod=(ulong)(l*(cfg.dir[f->dir]->dn_pct/100.0));
        !            89:                        adjustuserrec(&cfg,i,U_CDT,10,mod);
        !            90:                        ultoac(mod,tmp);
        !            91:                }
        !            92:                if(!(cfg.dir[f->dir]->misc&DIR_QUIET)) {
        !            93:                        sprintf(str,text[DownloadUserMsg]
        !            94:                                ,!strcmp(cfg.dir[f->dir]->code,"TEMP") ? temp_file : f->name
        !            95:                                ,!strcmp(cfg.dir[f->dir]->code,"TEMP") ? text[Partially] : nulstr
        !            96:                                ,useron.alias,tmp); 
        !            97:                        putsmsg(&cfg,i,str); 
        !            98:                }
        !            99:        }
        !           100:        /*******************/
        !           101:        /* Update IXB File */
        !           102:        /*******************/
        !           103:        f->datedled=time(NULL);
        !           104:        sprintf(str,"%s%s.ixb",cfg.dir[f->dir]->data_dir,cfg.dir[f->dir]->code);
        !           105:        if((file=nopen(str,O_RDWR))==-1) {
        !           106:                errormsg(WHERE,ERR_OPEN,str,O_RDWR);
        !           107:                return; 
        !           108:        }
        !           109:        length=filelength(file);
        !           110:        if(length%F_IXBSIZE) {
        !           111:                close(file);
        !           112:                errormsg(WHERE,ERR_LEN,str,length);
        !           113:                return; 
        !           114:        }
        !           115:        strcpy(fname,f->name);
        !           116:        for(i=8;i<12;i++)   /* Turn FILENAME.EXT into FILENAMEEXT */
        !           117:                fname[i]=fname[i+1];
        !           118:        for(l=0;l<(ulong)length;l+=F_IXBSIZE) {
        !           119:                read(file,str,F_IXBSIZE);      /* Look for the filename in the IXB file */
        !           120:                str[11]=0;
        !           121:                if(!strcmp(fname,str)) 
        !           122:                        break; 
        !           123:        }
        !           124:        if(l>=(ulong)length) {
        !           125:                close(file);
        !           126:                errormsg(WHERE,ERR_CHK,f->name,0);
        !           127:                return; 
        !           128:        }
        !           129:        lseek(file,l+18,SEEK_SET);
        !           130:        write(file,&f->datedled,4);  /* Write the current time stamp for datedled */
        !           131:        close(file);
        !           132:        /*******************/
        !           133:        /* Update DAT File */
        !           134:        /*******************/
        !           135:        f->timesdled++;
        !           136:        putfiledat(&cfg,f);
        !           137:        /******************************************/
        !           138:        /* Update User to User index if necessary */
        !           139:        /******************************************/
        !           140:        if(f->dir==cfg.user_dir) {
        !           141:                rmuserxfers(&cfg,0,useron.number,f->name);
        !           142:                if(!getuserxfers(0,0,f->name)) { /* check if any ixt entries left */
        !           143:                        remove(getfilepath(&cfg,f,str));
        !           144:                        removefiledat(&cfg,f); 
        !           145:                } 
        !           146:        }
        !           147: 
        !           148:        user_event(EVENT_DOWNLOAD);
        !           149: }
        !           150: 
        !           151: /****************************************************************************/
        !           152: /* This function is called when a file is unsuccessfully downloaded.        */
        !           153: /* It logs the tranfer time and checks for possible leech protocol use.     */
        !           154: /****************************************************************************/
        !           155: void sbbs_t::notdownloaded(ulong size, time_t start, time_t end)
        !           156: {
        !           157:     char       str[256],tmp2[256];
        !           158:        char    tmp[512];
        !           159: 
        !           160:        sprintf(str,"Estimated Time: %s  Transfer Time: %s"
        !           161:                ,sectostr(cur_cps ? size/cur_cps : 0,tmp)
        !           162:                ,sectostr((uint)end-start,tmp2));
        !           163:        logline(nulstr,str);
        !           164:        if(cfg.leech_pct && cur_cps                 /* leech detection */
        !           165:                && end-start>=cfg.leech_sec
        !           166:                && end-start>=(double)(size/cur_cps)*(double)cfg.leech_pct/100.0) {
        !           167:                sprintf(str,"Possible use of leech protocol (leech=%u  downloads=%u)"
        !           168:                        ,useron.leech+1,useron.dls);
        !           169:                errorlog(str);
        !           170:                useron.leech=(uchar)adjustuserrec(&cfg,useron.number,U_LEECH,2,1); 
        !           171:        }
        !           172: }
        !           173: 
        !           174: char* sbbs_t::protcmdline(prot_t* prot, enum XFER_TYPE type)
        !           175: {
        !           176:        switch(type) {
        !           177:                case XFER_UPLOAD:
        !           178:                        return(prot->ulcmd);
        !           179:                case XFER_DOWNLOAD:
        !           180:                        return(prot->dlcmd);
        !           181:                case XFER_BATCH_UPLOAD:
        !           182:                        return(prot->batulcmd);
        !           183:                case XFER_BATCH_DOWNLOAD:
        !           184:                        return(prot->batdlcmd);
        !           185:                case XFER_BIDIR:
        !           186:                        return(prot->bicmd);
        !           187:        }
        !           188: 
        !           189:        return("invalid transfer type");
        !           190: }
        !           191: 
        !           192: /****************************************************************************/
        !           193: /* Handles start and stop routines for transfer protocols                   */
        !           194: /****************************************************************************/
        !           195: int sbbs_t::protocol(prot_t* prot, enum XFER_TYPE type
        !           196:                                         ,char *fpath, char *fspec, bool cd)
        !           197: {
        !           198:        char    protlog[256],*p;
        !           199:        char*   cmdline;
        !           200:        char    msg[256];
        !           201:     int                i;
        !           202:        long    ex_mode;
        !           203:        FILE*   stream;
        !           204: 
        !           205:        sprintf(protlog,"%sPROTOCOL.LOG",cfg.node_dir);
        !           206:        remove(protlog);                        /* Deletes the protocol log */
        !           207:        if(useron.misc&AUTOHANG)
        !           208:                autohang=1;
        !           209:        else
        !           210:                autohang=yesno(text[HangUpAfterXferQ]);
        !           211:        if(sys_status&SS_ABORT || !online) {    /* if ctrl-c or hangup */
        !           212:                autohang=0;
        !           213:                return(-1); 
        !           214:        }
        !           215:        bputs(text[StartXferNow]);
        !           216:        if(cd) 
        !           217:                p=cfg.temp_dir;
        !           218:        else
        !           219:                p=NULL;
        !           220:        cmdline=cmdstr(protcmdline(prot,type),fpath,fspec,NULL);
        !           221:        sprintf(msg,"Transferring %s",cmdline);
        !           222:        spymsg(msg);
        !           223:        sys_status|=SS_FILEXFER;        /* disable spy during file xfer */
        !           224:        /* enable telnet binary transmission in both directions */
        !           225:        request_telnet_opt(TELNET_DO,TELNET_BINARY_TX);
        !           226:        request_telnet_opt(TELNET_WILL,TELNET_BINARY_TX);
        !           227:        ex_mode=0;
        !           228:        if(prot->misc&PROT_NATIVE)
        !           229:                ex_mode|=EX_NATIVE;
        !           230: #ifdef __unix__                /* file xfer progs must use stdio on Unix */
        !           231:        if(!(prot->misc&PROT_SOCKET))
        !           232:                ex_mode|=(EX_INR|EX_OUTR|EX_BIN);
        !           233: #endif
        !           234: 
        !           235:        i=external(cmdline,ex_mode,p);
        !           236:        /* Got back to Text/NVT mode */
        !           237:        request_telnet_opt(TELNET_DONT,TELNET_BINARY_TX);
        !           238:        request_telnet_opt(TELNET_WONT,TELNET_BINARY_TX);
        !           239: 
        !           240:        sys_status&=~SS_FILEXFER;
        !           241:        if(online==ON_REMOTE)
        !           242:                rioctl(IOFB);
        !           243: 
        !           244:        // Save DSZLOG to logfile
        !           245:        if((stream=fnopen(NULL,protlog,O_RDONLY))!=NULL) {
        !           246:                while(!feof(stream) && !ferror(stream)) {
        !           247:                        if(!fgets(protlog,sizeof(protlog),stream))
        !           248:                                break;
        !           249:                        truncsp(protlog);
        !           250:                        logline(nulstr,protlog);
        !           251:                }
        !           252:                fclose(stream);
        !           253:        }
        !           254: 
        !           255:        CRLF;
        !           256:        if(autohang) sys_status|=SS_PAUSEOFF;   /* Pause off after download */
        !           257:        return(i);
        !           258: }
        !           259: 
        !           260: /****************************************************************************/
        !           261: /* Invokes the timed auto-hangup after transfer routine                     */
        !           262: /****************************************************************************/
        !           263: void sbbs_t::autohangup()
        !           264: {
        !           265:     char       a,c,k;
        !           266:        char    tmp[512];
        !           267: 
        !           268:        if(online!=ON_REMOTE)
        !           269:                return;
        !           270:        SYNC;
        !           271:        sys_status&=~SS_PAUSEOFF;               /* turn pause back on */
        !           272:        rioctl(IOFI);
        !           273:        if(!autohang) return;
        !           274:        lncntr=0;
        !           275:        bputs(text[Disconnecting]);
        !           276:        attr(GREEN);
        !           277:        outchar('[');
        !           278:        for(c=9,a=0;c>-1 && online && !a;c--) {
        !           279:                checkline();
        !           280:                attr(LIGHTGRAY|HIGH);
        !           281:                bputs(ultoa(c,tmp,10));
        !           282:                attr(GREEN);
        !           283:                outchar(']');
        !           284:                while((k=inkey(K_NONE,DELAY_AUTOHG))!=0 && online) {
        !           285:                        if(toupper(k)=='H') {
        !           286:                                c=0;
        !           287:                                break; 
        !           288:                        }
        !           289:                        if(toupper(k)=='A') {
        !           290:                                a=1;
        !           291:                                break; 
        !           292:                        } 
        !           293:                }
        !           294:                if(!a) {
        !           295:                        outchar(BS);
        !           296:                        outchar(BS); 
        !           297:                } 
        !           298:        }
        !           299:        if(c==-1) {
        !           300:                bputs(text[Disconnected]);
        !           301:                hangup(); 
        !           302:        }
        !           303:        else
        !           304:                CRLF;
        !           305: }
        !           306: 
        !           307: bool sbbs_t::checkdszlog(file_t* f)
        !           308: {
        !           309:        char    path[MAX_PATH+1];
        !           310:        char    str[MAX_PATH+128];
        !           311:        char    fname[MAX_PATH+1];
        !           312:        char    rpath[MAX_PATH+1];
        !           313:        char*   p;
        !           314:        char*   rname;
        !           315:        char    code;
        !           316:        ulong   bytes;
        !           317:        FILE*   fp;
        !           318:        bool    success=false;
        !           319: 
        !           320:        sprintf(path,"%sPROTOCOL.LOG",cfg.node_dir);
        !           321:        if((fp=fopen(path,"r"))==NULL)
        !           322:                return(false);
        !           323: 
        !           324:        unpadfname(f->name,fname);
        !           325: 
        !           326:        getfilepath(&cfg,f,rpath);
        !           327:        fexistcase(rpath);      /* incase of long filename */
        !           328:        rname=getfname(rpath);
        !           329: 
        !           330:        while(!ferror(fp)) {
        !           331:                if(!fgets(str,sizeof(str),fp))
        !           332:                        break;
        !           333:                if((p=strrchr(str,' '))!=NULL)
        !           334:                        *p=0;   /* we don't care about no stinking serial number */
        !           335:                p=str;
        !           336:                code=*p;
        !           337:                FIND_WHITESPACE(p);     // Skip code
        !           338:                SKIP_WHITESPACE(p);
        !           339:                bytes=strtoul(p,NULL,10);
        !           340:                FIND_WHITESPACE(p);     // Skip bytes
        !           341:                SKIP_WHITESPACE(p);
        !           342:                FIND_WHITESPACE(p);     // Skip DTE rate
        !           343:                SKIP_WHITESPACE(p);
        !           344:                FIND_WHITESPACE(p);     // Skip "bps" rate
        !           345:                SKIP_WHITESPACE(p);
        !           346:                FIND_WHITESPACE(p);     // Skip CPS
        !           347:                SKIP_WHITESPACE(p);
        !           348:                FIND_WHITESPACE(p);     // Skip "cps"
        !           349:                SKIP_WHITESPACE(p);
        !           350:                FIND_WHITESPACE(p);     // Skip errors
        !           351:                SKIP_WHITESPACE(p);
        !           352:                FIND_WHITESPACE(p);     // Skip "errors"
        !           353:                SKIP_WHITESPACE(p);
        !           354:                FIND_WHITESPACE(p);     // Skip flows
        !           355:                SKIP_WHITESPACE(p);
        !           356:                FIND_WHITESPACE(p);     // Skip block size
        !           357:                SKIP_WHITESPACE(p);
        !           358:                p=getfname(p);  /* DSZ stores fullpath, BiModem doesn't */
        !           359:                if(stricmp(p,fname)==0 || stricmp(p,rname)==0) {
        !           360:                        /* E for Error or L for Lost Carrier or s for Skipped */
        !           361:                        /* or only sent 0 bytes! */
        !           362:                        if(code!='E' && code!='L' && code!='s' && bytes!=0)
        !           363:                                success=true;
        !           364:                        break;
        !           365:                }
        !           366:        }
        !           367:        fclose(fp);
        !           368:        return(success);
        !           369: }
        !           370: 
        !           371: 
        !           372: /****************************************************************************/
        !           373: /* Checks dsz compatible log file for errors in transfer                    */
        !           374: /* Returns 1 if the file in the struct file_t was successfuly transfered    */
        !           375: /****************************************************************************/
        !           376: bool sbbs_t::checkprotresult(prot_t* prot, int error, file_t* f)
        !           377: {
        !           378:        char str[512];
        !           379:        char tmp[128];
        !           380:        bool success;
        !           381: 
        !           382:        if(prot->misc&PROT_DSZLOG)
        !           383:                success=checkdszlog(f);
        !           384:        else
        !           385:                success=(error==0);
        !           386: 
        !           387:        if(!success) {
        !           388:                bprintf(text[FileNotSent],f->name);
        !           389:                if(f->dir<cfg.total_dirs)
        !           390:                        sprintf(str,"%s attempted to download %s (%s) from %s %s"
        !           391:                                ,useron.alias
        !           392:                                ,f->name,ultoac(f->size,tmp)
        !           393:                                ,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
        !           394:                else if(f->dir==cfg.total_dirs)
        !           395:                        sprintf(str,"%s attempted to download QWK packet"
        !           396:                                ,useron.alias);
        !           397:                else if(f->dir==cfg.total_dirs+1)
        !           398:                        sprintf(str,"%s attempted to download attached file: %s"
        !           399:                                ,useron.alias,f->name);
        !           400:                logline("D!",str);
        !           401:                return(false); 
        !           402:        }
        !           403:        return(true);
        !           404: }
        !           405: 
        !           406: 
        !           407: 
        !           408: /************************************************************************/
        !           409: /* Wait (for a limited period of time) for sequential dev to become    */
        !           410: /* available for file retrieval                                                                                */
        !           411: /************************************************************************/
        !           412: void sbbs_t::seqwait(uint devnum)
        !           413: {
        !           414:        char loop=0;
        !           415:        int i;
        !           416:        time_t start;
        !           417:        node_t node;
        !           418: 
        !           419:        if(!devnum)
        !           420:                return;
        !           421:        for(start=now=time(NULL);online && now-start<90;now=time(NULL)) {
        !           422:                if(msgabort())                          /* max wait ^^^^ sec */
        !           423:                        break;
        !           424:                getnodedat(cfg.node_num,&thisnode,true);        /* open and lock this record */
        !           425:                for(i=1;i<=cfg.sys_nodes;i++) {
        !           426:                        if(i==cfg.node_num) continue;
        !           427:                        if(getnodedat(i,&node,true)==0) {
        !           428:                                if((node.status==NODE_INUSE || node.status==NODE_QUIET)
        !           429:                                        && node.action==NODE_RFSD && node.aux==devnum) {
        !           430:                                        putnodedat(i,&node);
        !           431:                                        break; 
        !           432:                                }
        !           433:                                putnodedat(i,&node); 
        !           434:                        }
        !           435:                }
        !           436:                if(i>cfg.sys_nodes) {
        !           437:                        thisnode.action=NODE_RFSD;
        !           438:                        thisnode.aux=devnum;
        !           439:                        putnodedat(cfg.node_num,&thisnode);     /* write devnum, unlock, and ret */
        !           440:                        return; 
        !           441:                }
        !           442:                putnodedat(cfg.node_num,&thisnode);
        !           443:                if(!loop)
        !           444:                        bprintf(text[WaitingForDeviceN],devnum);
        !           445:                loop=1;
        !           446:                mswait(100); 
        !           447:        }
        !           448: 
        !           449: }
        !           450: 
        !           451: bool sbbs_t::sendfile(char* fname, char prot)
        !           452: {
        !           453:        char    keys[128];
        !           454:        char    ch;
        !           455:        size_t  i;
        !           456:        bool    result=false;
        !           457: 
        !           458:        if(prot)
        !           459:                ch=toupper(prot);
        !           460:        else {
        !           461:                xfer_prot_menu(XFER_DOWNLOAD);
        !           462:                mnemonics(text[ProtocolOrQuit]);
        !           463:                strcpy(keys,"Q");
        !           464:                for(i=0;i<cfg.total_prots;i++)
        !           465:                        if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron))
        !           466:                                sprintf(keys+strlen(keys),"%c",cfg.prot[i]->mnemonic);
        !           467: 
        !           468:                ch=(char)getkeys(keys,0);
        !           469: 
        !           470:                if(ch=='Q' || sys_status&SS_ABORT)
        !           471:                        return(false); 
        !           472:        }
        !           473:        for(i=0;i<cfg.total_prots;i++)
        !           474:                if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron))
        !           475:                        break;
        !           476:        if(i<cfg.total_prots) {
        !           477:                if(protocol(cfg.prot[i],XFER_DOWNLOAD,fname,fname,false)==0)
        !           478:                        result=true;
        !           479:                autohangup(); 
        !           480:        }
        !           481: 
        !           482:        return(result);
        !           483: }

unix.superglobalmegacorp.com

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