Annotation of sbbs/sbbs3/download.cpp, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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