|
|
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.