|
|
1.1 ! root 1: /* download.cpp */ ! 2: ! 3: /* Synchronet file download routines */ ! 4: ! 5: /* $Id: download.cpp,v 1.7 2000/12/11 23:21:11 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 2000 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: /****************************************************************************/ ! 41: /* Updates downloader, uploader and downloaded file data */ ! 42: /* Must have offset, dir and name fields filled prior to call. */ ! 43: /****************************************************************************/ ! 44: void sbbs_t::downloadfile(file_t* f) ! 45: { ! 46: char str[256],fname[13]; ! 47: char tmp[512]; ! 48: int i,file; ! 49: long length,mod; ! 50: ulong l; ! 51: user_t uploader; ! 52: ! 53: getfiledat(&cfg,f); /* Get current data - right after download */ ! 54: if((length=f->size)<0L) ! 55: length=0L; ! 56: logon_dlb+=length; /* Update 'this call' stats */ ! 57: logon_dls++; ! 58: bprintf(text[FileNBytesSent],f->name,ultoac(length,tmp)); ! 59: sprintf(str,"Downloaded %s from %s %s",f->name,cfg.lib[cfg.dir[f->dir]->lib]->sname ! 60: ,cfg.dir[f->dir]->sname); ! 61: logline("D-",str); ! 62: /****************************/ ! 63: /* Update Downloader's Info */ ! 64: /****************************/ ! 65: useron.dls=(ushort)adjustuserrec(&cfg,useron.number,U_DLS,5,1); ! 66: useron.dlb=adjustuserrec(&cfg,useron.number,U_DLB,10,length); ! 67: if(!(cfg.dir[f->dir]->misc&DIR_FREE) && !(useron.exempt&FLAG('D'))) ! 68: subtract_cdt(&cfg,&useron,f->cdt); ! 69: /**************************/ ! 70: /* Update Uploader's Info */ ! 71: /**************************/ ! 72: i=matchuser(&cfg,f->uler); ! 73: uploader.number=i; ! 74: getuserdat(&cfg,&uploader); ! 75: if(i && i!=useron.number && uploader.firston<f->dateuled) { ! 76: l=f->cdt; ! 77: if(!(cfg.dir[f->dir]->misc&DIR_CDTDL)) /* Don't give credits on d/l */ ! 78: l=0; ! 79: if(cfg.dir[f->dir]->misc&DIR_CDTMIN && cur_cps) { /* Give min instead of cdt */ ! 80: mod=((ulong)(l*(cfg.dir[f->dir]->dn_pct/100.0))/cur_cps)/60; ! 81: adjustuserrec(&cfg,i,U_MIN,10,mod); ! 82: sprintf(tmp,"%lu minute",mod); ! 83: sprintf(str,text[DownloadUserMsg] ! 84: ,!strcmp(cfg.dir[f->dir]->code,"TEMP") ? temp_file : f->name ! 85: ,!strcmp(cfg.dir[f->dir]->code,"TEMP") ? text[Partially] : nulstr ! 86: ,useron.alias,tmp); } ! 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: sprintf(str,text[DownloadUserMsg] ! 92: ,!strcmp(cfg.dir[f->dir]->code,"TEMP") ? temp_file : f->name ! 93: ,!strcmp(cfg.dir[f->dir]->code,"TEMP") ? text[Partially] : nulstr ! 94: ,useron.alias,tmp); } ! 95: putsmsg(&cfg,i,str); } ! 96: /*******************/ ! 97: /* Update IXB File */ ! 98: /*******************/ ! 99: f->datedled=time(NULL); ! 100: sprintf(str,"%s%s.ixb",cfg.dir[f->dir]->data_dir,cfg.dir[f->dir]->code); ! 101: if((file=nopen(str,O_RDWR))==-1) { ! 102: errormsg(WHERE,ERR_OPEN,str,O_RDWR); ! 103: return; } ! 104: length=filelength(file); ! 105: if(length%F_IXBSIZE) { ! 106: close(file); ! 107: errormsg(WHERE,ERR_LEN,str,length); ! 108: return; } ! 109: strcpy(fname,f->name); ! 110: for(i=8;i<12;i++) /* Turn FILENAME.EXT into FILENAMEEXT */ ! 111: fname[i]=fname[i+1]; ! 112: for(l=0;l<(ulong)length;l+=F_IXBSIZE) { ! 113: read(file,str,F_IXBSIZE); /* Look for the filename in the IXB file */ ! 114: str[11]=0; ! 115: if(!strcmp(fname,str)) break; } ! 116: if(l>=(ulong)length) { ! 117: close(file); ! 118: errormsg(WHERE,ERR_CHK,f->name,0); ! 119: return; } ! 120: lseek(file,l+18,SEEK_SET); ! 121: write(file,&f->datedled,4); /* Write the current time stamp for datedled */ ! 122: close(file); ! 123: /*******************/ ! 124: /* Update DAT File */ ! 125: /*******************/ ! 126: f->timesdled++; ! 127: putfiledat(&cfg,f); ! 128: /******************************************/ ! 129: /* Update User to User index if necessary */ ! 130: /******************************************/ ! 131: if(f->dir==cfg.user_dir) { ! 132: rmuserxfers(&cfg,0,useron.number,f->name); ! 133: if(!getuserxfers(0,0,f->name)) { /* check if any ixt entries left */ ! 134: sprintf(str,"%s%s",f->altpath>0 && f->altpath<=cfg.altpaths ? ! 135: cfg.altpath[f->altpath-1] : cfg.dir[f->dir]->path,unpadfname(f->name,tmp)); ! 136: remove(str); ! 137: removefiledat(&cfg,f); ! 138: } ! 139: } ! 140: } ! 141: ! 142: /****************************************************************************/ ! 143: /* This function is called when a file is unsuccessfully downloaded. */ ! 144: /* It logs the tranfer time and checks for possible leech protocol use. */ ! 145: /****************************************************************************/ ! 146: void sbbs_t::notdownloaded(ulong size, time_t start, time_t end) ! 147: { ! 148: char str[256],tmp2[256]; ! 149: char tmp[512]; ! 150: ! 151: sprintf(str,"Estimated Time: %s Transfer Time: %s" ! 152: ,sectostr(cur_cps ? size/cur_cps : 0,tmp) ! 153: ,sectostr((uint)end-start,tmp2)); ! 154: logline(nulstr,str); ! 155: if(cfg.leech_pct && cur_cps /* leech detection */ ! 156: && end-start>=cfg.leech_sec ! 157: && end-start>=(double)(size/cur_cps)*(double)cfg.leech_pct/100.0) { ! 158: sprintf(str,"Possible use of leech protocol (leech=%u downloads=%u)" ! 159: ,useron.leech+1,useron.dls); ! 160: errorlog(str); ! 161: useron.leech=(uchar)adjustuserrec(&cfg,useron.number,U_LEECH,2,1); } ! 162: } ! 163: ! 164: ! 165: /****************************************************************************/ ! 166: /* Handles start and stop routines for transfer protocols */ ! 167: /****************************************************************************/ ! 168: int sbbs_t::protocol(char *cmdline, int cd) ! 169: { ! 170: char protlog[256],*p=NULL; ! 171: char msg[256]; ! 172: int i; ! 173: FILE* stream; ! 174: ! 175: sprintf(protlog,"%sPROTOCOL.LOG",cfg.node_dir); ! 176: remove(protlog); /* Deletes the protocol log */ ! 177: if(useron.misc&AUTOHANG) ! 178: autohang=1; ! 179: else ! 180: autohang=yesno(text[HangUpAfterXferQ]); ! 181: if(sys_status&SS_ABORT) { /* if ctrl-c */ ! 182: autohang=0; ! 183: return(-1); } ! 184: bputs(text[StartXferNow]); ! 185: RIOSYNC(0); ! 186: //lprintf("%s",cmdline); ! 187: if(cd) ! 188: p=cfg.temp_dir; ! 189: sprintf(msg,"Transferring %s",cmdline); ! 190: spymsg(msg); ! 191: sys_status|=SS_FILEXFER; ! 192: i=external(cmdline,EX_OUTL,p); ! 193: sys_status&=~SS_FILEXFER; ! 194: if(online==ON_REMOTE) ! 195: rioctl(IOFB); ! 196: ! 197: // Save DSZLOG to logfile ! 198: if((stream=fnopen(NULL,protlog,O_RDONLY))!=NULL) { ! 199: while(!feof(stream) && !ferror(stream)) { ! 200: if(!fgets(protlog,sizeof(protlog)-1,stream)) ! 201: break; ! 202: truncsp(protlog); ! 203: logline(nulstr,protlog); ! 204: } ! 205: fclose(stream); ! 206: } ! 207: ! 208: CRLF; ! 209: if(autohang) sys_status|=SS_PAUSEOFF; /* Pause off after download */ ! 210: return(i); ! 211: } ! 212: ! 213: /****************************************************************************/ ! 214: /* Invokes the timed auto-hangup after transfer routine */ ! 215: /****************************************************************************/ ! 216: void sbbs_t::autohangup() ! 217: { ! 218: char a,c,k; ! 219: char tmp[512]; ! 220: ! 221: if(online!=ON_REMOTE) ! 222: return; ! 223: SYNC; ! 224: sys_status&=~SS_PAUSEOFF; /* turn pause back on */ ! 225: rioctl(IOFI); ! 226: if(!autohang) return; ! 227: lncntr=0; ! 228: bputs(text[Disconnecting]); ! 229: attr(GREEN); ! 230: outchar('['); ! 231: for(c=9,a=0;c>-1 && online && !a;c--) { ! 232: checkline(); ! 233: attr(LIGHTGRAY|HIGH); ! 234: bputs(ultoa(c,tmp,10)); ! 235: attr(GREEN); ! 236: outchar(']'); ! 237: while((k=inkey(0))!=0 && online) { ! 238: if(toupper(k)=='H') { ! 239: c=0; ! 240: break; } ! 241: if(toupper(k)=='A') { ! 242: a=1; ! 243: break; } } ! 244: mswait(DELAY_AUTOHG); ! 245: if(!a) { ! 246: outchar(BS); ! 247: outchar(BS); } } ! 248: if(c==-1) { ! 249: bputs(text[Disconnected]); ! 250: hangup(); } ! 251: else ! 252: CRLF; ! 253: } ! 254: ! 255: /****************************************************************************/ ! 256: /* Checks dsz compatible log file for errors in transfer */ ! 257: /* Returns 1 if the file in the struct file_t was successfuly transfered */ ! 258: /****************************************************************************/ ! 259: bool sbbs_t::checkprotlog(file_t* f) ! 260: { ! 261: char str[256],size[128]; ! 262: char tmp[512]; ! 263: int file; ! 264: FILE * stream; ! 265: ! 266: sprintf(str,"%sPROTOCOL.LOG",cfg.node_dir); ! 267: if((stream=fnopen(&file,str,O_RDONLY))==NULL) { ! 268: bprintf(text[FileNotSent],f->name); ! 269: if(f->dir<cfg.total_dirs) ! 270: sprintf(str,"Attempted to download %s (%s) from %s %s" ! 271: ,f->name,ultoac(f->size,size) ! 272: ,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname); ! 273: else if(f->dir==cfg.total_dirs) ! 274: strcpy(str,"Attempted to download QWK packet"); ! 275: else if(f->dir==cfg.total_dirs+1) ! 276: sprintf(str,"Attempted to download attached file: %s",f->name); ! 277: logline("D!",str); ! 278: return(0); } ! 279: unpadfname(f->name,tmp); ! 280: if(tmp[strlen(tmp)-1]=='.') /* DSZ log uses FILE instead of FILE. */ ! 281: tmp[strlen(tmp)-1]=0; /* when there isn't an extension. */ ! 282: strupr(tmp); ! 283: while(!ferror(stream)) { ! 284: if(!fgets(str,256,stream)) ! 285: break; ! 286: if(str[strlen(str)-2]==CR) ! 287: str[strlen(str)-2]=0; /* chop off CRLF */ ! 288: strupr(str); ! 289: if(strstr(str,tmp)) { /* Only check for name, Bimodem doesn't put path */ ! 290: // logline(nulstr,str); now handled by protocol() ! 291: if(str[0]=='E' || str[0]=='L' || (str[6]==SP && str[7]=='0')) ! 292: break; /* E for Error or L for Lost Carrier */ ! 293: fclose(stream); /* or only sent 0 bytes! */ ! 294: return(true); } } ! 295: fclose(stream); ! 296: bprintf(text[FileNotSent],f->name); ! 297: if(f->dir<cfg.total_dirs) ! 298: sprintf(str,"Attempted to download %s (%s) from %s %s",f->name ! 299: ,ultoac(f->size,tmp),cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname); ! 300: else ! 301: strcpy(str,"Attempted to download QWK packet"); ! 302: logline("D!",str); ! 303: return(false); ! 304: } ! 305: ! 306: ! 307: ! 308: /************************************************************************/ ! 309: /* Wait (for a limited period of time) for sequential dev to become */ ! 310: /* available for file retrieval */ ! 311: /************************************************************************/ ! 312: void sbbs_t::seqwait(uint devnum) ! 313: { ! 314: char loop=0; ! 315: int i; ! 316: time_t start; ! 317: node_t node; ! 318: ! 319: if(!devnum) ! 320: return; ! 321: for(start=now=time(NULL);online && now-start<90;now=time(NULL)) { ! 322: if(msgabort()) /* max wait ^^^^ sec */ ! 323: break; ! 324: getnodedat(cfg.node_num,&thisnode,1); /* open and lock this record */ ! 325: for(i=1;i<=cfg.sys_nodes;i++) { ! 326: if(i==cfg.node_num) continue; ! 327: getnodedat(i,&node,1); ! 328: if((node.status==NODE_INUSE || node.status==NODE_QUIET) ! 329: && node.action==NODE_RFSD && node.aux==devnum) { ! 330: putnodedat(i,&node); ! 331: break; } ! 332: putnodedat(i,&node); } ! 333: if(i>cfg.sys_nodes) { ! 334: thisnode.action=NODE_RFSD; ! 335: thisnode.aux=devnum; ! 336: putnodedat(cfg.node_num,&thisnode); /* write devnum, unlock, and ret */ ! 337: return; } ! 338: putnodedat(cfg.node_num,&thisnode); ! 339: if(!loop) ! 340: bprintf(text[WaitingForDeviceN],devnum); ! 341: loop=1; ! 342: mswait(100); } ! 343: ! 344: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.