|
|
1.1 root 1: /* tmp_xfer.cpp */
2:
3: /* Synchronet temp directory file transfer routines */
4:
5: /* $Id: tmp_xfer.cpp,v 1.38 2005/10/02 23:52:26 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 2005 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: /* Temp directory section. Files must be extracted here and both temp_uler */
42: /* and temp_uler fields should be filled before entrance. */
43: /*****************************************************************************/
44: void sbbs_t::temp_xfer()
45: {
46: char str[256],tmp2[256],done=0,ch;
47: char tmp[512];
48: int error;
49: uint i,dirnum=cfg.total_dirs,files;
50: ulong bytes;
51: ulong space;
52: time_t start,end,t;
53: file_t f;
54: glob_t g;
55: struct tm tm;
56:
57: if(!usrlibs)
58: return;
59: if(useron.rest&FLAG('D')) {
60: bputs(text[R_Download]);
61: return; }
62: /*************************************/
63: /* Create TEMP directory information */
64: /*************************************/
65: if((cfg.dir[dirnum]=(dir_t *)malloc(sizeof(dir_t)))==0) {
66: errormsg(WHERE,ERR_ALLOC,"temp_dir",sizeof(dir_t));
67: return; }
68: memset(cfg.dir[dirnum],0,sizeof(dir_t));
69: SAFECOPY(cfg.dir[dirnum]->lname,"Temporary");
70: SAFECOPY(cfg.dir[dirnum]->sname,"Temp");
71: SAFECOPY(cfg.dir[dirnum]->code,"TEMP");
72: SAFECOPY(cfg.dir[dirnum]->path,cfg.temp_dir);
73: SAFECOPY(cfg.dir[dirnum]->data_dir,cfg.dir[0]->data_dir);
74: cfg.dir[dirnum]->maxfiles=MAX_FILES;
75: cfg.dir[dirnum]->op_ar=(uchar *)nulstr;
76: cfg.dir[dirnum]->ex_ar=(uchar *)nulstr;
77: temp_dirnum=curdirnum=usrdir[curlib][curdir[curlib]];
78: cfg.total_dirs++;
79:
80: /****************************/
81: /* Fill filedat information */
82: /****************************/
83: memset(&f,0,sizeof(f));
84: SAFEPRINTF2(f.name,"temp_%3.3d.%s",cfg.node_num,useron.tmpext);
85: SAFECOPY(f.desc,"Temp File");
86: f.dir=dirnum;
87:
88: if(useron.misc&(RIP|WIP|HTML) && !(useron.misc&EXPERT))
89: menu("tempxfer");
90: lncntr=0;
91: while(online && !done) {
92: if(!(useron.misc&(EXPERT|RIP|WIP|HTML))) {
93: sys_status&=~SS_ABORT;
94: if(lncntr) {
95: SYNC;
96: CRLF;
97: if(lncntr) /* CRLF or SYNC can cause pause */
98: pause(); }
99: menu("tempxfer"); }
100: ASYNC;
101: bputs(text[TempDirPrompt]);
102: SAFECOPY(f.uler,temp_uler);
103: ch=(char)getkeys("ADEFNILQRVX?\r",0);
104: if(ch>' ')
105: logch(ch,0);
106: switch(ch) {
107: case 'A': /* add to temp file */
108: /* free disk space */
109: space=getfreediskspace(cfg.temp_dir,1024);
110: if(space<(ulong)cfg.min_dspace) {
111: bputs(text[LowDiskSpace]);
112: sprintf(str,"Diskspace is low: %s (%lu kilobytes)"
113: ,cfg.temp_dir,space);
114: errorlog(str);
115: if(!dir_op(dirnum))
116: break; }
117: bprintf(text[DiskNBytesFree],ultoac(space,tmp));
118: if(!getfilespec(str))
119: break;
120: if(!checkfname(str))
121: break;
122: sprintf(tmp2,"%s added %s to %s"
123: ,useron.alias,str,f.name);
124: logline(nulstr,tmp2);
125: sprintf(tmp2,"%s%s",cfg.temp_dir,str);
126: sprintf(str,"%s%s",cfg.temp_dir,f.name);
127: external(cmdstr(temp_cmd(),str,tmp2,NULL),EX_WILDCARD|EX_OUTL|EX_OUTR);
128: break;
129: case 'D': /* download from temp dir */
130: sprintf(str,"%s%s",cfg.temp_dir,f.name);
131: if(!fexist(str)) {
132: bprintf(text[TempFileNotCreatedYet],f.name);
133: break; }
134: f.size=f.cdt=flength(str);
135: f.opencount=0;
136: if(temp_cdt) /* if file was not free */
137: f.cdt=f.size;
138: else
139: f.cdt=0;
140: if(!(useron.exempt&FLAG('D'))
141: && f.cdt>useron.cdt+useron.freecdt) {
142: bprintf(text[YouOnlyHaveNCredits]
143: ,ultoac(useron.cdt+useron.freecdt,tmp));
144: break; } /* f.cdt must equal size here */
145: if(!(useron.exempt&FLAG('T')) && !dir_op(dirnum)
146: && !(cfg.dir[temp_dirnum]->misc&DIR_TFREE) && cur_cps
147: && f.size/(ulong)cur_cps>timeleft) {
148: bputs(text[NotEnoughTimeToDl]);
149: break; }
150: if(!chk_ar(cfg.dir[temp_dirnum]->dl_ar,&useron)) {
151: bputs(text[CantDownloadFromDir]);
152: break; }
153: addfiledat(&cfg,&f);
154: xfer_prot_menu(XFER_DOWNLOAD);
155: SYNC;
156: mnemonics(text[ProtocolOrQuit]);
157: SAFECOPY(tmp2,"Q");
158: for(i=0;i<cfg.total_prots;i++)
159: if(cfg.prot[i]->dlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron)) {
160: sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
161: strcat(tmp2,tmp); }
162: ungetkey(useron.prot);
163: ch=(char)getkeys(tmp2,0);
164: for(i=0;i<cfg.total_prots;i++)
165: if(cfg.prot[i]->dlcmd[0] && cfg.prot[i]->mnemonic==ch
166: && chk_ar(cfg.prot[i]->ar,&useron))
167: break;
168: if(i<cfg.total_prots) {
169: getnodedat(cfg.node_num,&thisnode,1);
170: action=NODE_DLNG;
171: t=now;
172: if(cur_cps)
173: t+=(f.size/(ulong)cur_cps);
174: if(localtime_r(&t,&tm)==NULL)
175: break;
176: thisnode.aux=(tm.tm_hour*60)+tm.tm_min;
177:
178: putnodedat(cfg.node_num,&thisnode); /* calculate ETA */
179: start=time(NULL);
180: error=protocol(cfg.prot[i],XFER_DOWNLOAD,str,nulstr,false);
181: end=time(NULL);
182: if(cfg.dir[temp_dirnum]->misc&DIR_TFREE)
183: starttime+=end-start;
184: if(checkprotresult(cfg.prot[i],error,&f))
185: downloadfile(&f);
186: else
187: notdownloaded(f.size,start,end);
188: autohangup();
189: }
190: removefiledat(&cfg,&f);
191: break;
192: case 'E':
193: extract(usrdir[curlib][curdir[curlib]]);
194: sys_status&=~SS_ABORT;
195: break;
196: case 'F': /* Create a file list */
197: delfiles(cfg.temp_dir,ALLFILES);
198: create_filelist("FILELIST.TXT",0);
199: if(!(sys_status&SS_ABORT))
200: logline(nulstr,"Created list of all files");
201: CRLF;
202: sys_status&=~SS_ABORT;
203: break;
204: case 'I': /* information on what's here */
205: bprintf(text[TempFileInfo],f.uler,temp_file);
206: break;
207: case 'L': /* list files in dir */
208: if(!getfilespec(str))
209: break;
210: if(!checkfname(str))
211: break;
212: bytes=files=0L;
213: CRLF;
214: sprintf(tmp2,"%s%s",cfg.temp_dir,str);
215: glob(tmp2,0,NULL,&g);
216: for(i=0;i<(uint)g.gl_pathc && !msgabort();i++) {
217: if(isdir(g.gl_pathv[i]))
218: continue;
219: t=fdate(g.gl_pathv[i]);
220: bprintf("%-25s %15s %s\r\n",getfname(g.gl_pathv[i])
221: ,ultoac(flength(g.gl_pathv[i]),tmp)
222: ,timestr(&t));
223: files++;
224: bytes+=flength(g.gl_pathv[i]);
225: }
226: globfree(&g);
227: if(!files)
228: bputs(text[EmptyDir]);
229: else if(files>1)
230: bprintf(text[TempDirTotal],ultoac(bytes,tmp),files);
231: break;
232: case 'N': /* Create a list of new files */
233: delfiles(cfg.temp_dir,ALLFILES);
234: create_filelist("NEWFILES.TXT",FL_ULTIME);
235: if(!(sys_status&SS_ABORT))
236: logline(nulstr,"Created list of new files");
237: CRLF;
238: sys_status&=~SS_ABORT;
239: break;
240: case 'R': /* Remove files from dir */
241: if(!getfilespec(str) || !checkfname(str))
242: break;
243: bprintf(text[NFilesRemoved],delfiles(cfg.temp_dir,str));
244: break;
245: case 'V': /* view files in dir */
246: bputs(text[FileSpec]);
247: if(!getstr(str,64,K_NONE) || !checkfname(str))
248: break;
249: viewfiles(dirnum,str);
250: break;
251: case CR:
252: case 'Q': /* quit */
253: done=1;
254: break;
255: case 'X': /* extract from archive in temp dir */
256: extract(dirnum);
257: sys_status&=~SS_ABORT;
258: break;
259: case '?': /* menu */
260: if(useron.misc&(EXPERT|RIP|WIP|HTML))
261: menu("tempxfer");
262: break; }
263: if(sys_status&SS_ABORT)
264: break; }
265: free(cfg.dir[dirnum]);
266: cfg.total_dirs--;
267: }
268:
269: /*****************************************************************************/
270: /* Handles extraction from a normal transfer file to the temp directory */
271: /*****************************************************************************/
272: void sbbs_t::extract(uint dirnum)
273: {
274: char fname[13],str[256],excmd[256],path[256],done
275: ,tmp[256],intmp=0;
276: uint i,j;
277: ulong space;
278: file_t f;
279: DIR* dir;
280: DIRENT* dirent;
281:
282: temp_dirnum=curdirnum=dirnum;
283: if(!strcmp(cfg.dir[dirnum]->code,"TEMP"))
284: intmp=1;
285:
286: /* get free disk space */
287: space=getfreediskspace(cfg.temp_dir,1024);
288: if(space<(ulong)cfg.min_dspace) {
289: bputs(text[LowDiskSpace]);
290: sprintf(str,"Diskspace is low: %s (%lu kilobytes)",cfg.temp_dir,space);
291: errorlog(str);
292: if(!dir_op(dirnum))
293: return; }
294: else if(!intmp) { /* not in temp dir */
295: CRLF; }
296: bprintf(text[DiskNBytesFree],ultoac(space,tmp));
297:
298: if(!intmp) { /* not extracting FROM temp directory */
299: sprintf(str,"%s%s",cfg.temp_dir,ALLFILES);
300: if(fexist(str)) {
301: bputs(text[RemovingTempFiles]);
302: dir=opendir(cfg.temp_dir);
303: while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
304: sprintf(str,"%s%s",cfg.temp_dir,dirent->d_name);
305: if(!isdir(str))
306: remove(str);
307: }
308: if(dir!=NULL)
309: closedir(dir);
310: CRLF;
311: }
312: }
313: bputs(text[ExtractFrom]);
314: if(!getstr(fname,64,K_NONE) || !checkfname(fname) || strchr(fname,'*')
315: || strchr(fname,'?'))
316: return;
317: padfname(fname,f.name);
318: SAFECOPY(str,f.name);
319: truncsp(str);
320: for(i=0;i<cfg.total_fextrs;i++)
321: if(!stricmp(str+9,cfg.fextr[i]->ext) && chk_ar(cfg.fextr[i]->ar,&useron)) {
322: SAFECOPY(excmd,cfg.fextr[i]->cmd);
323: break; }
324: if(i==cfg.total_fextrs) {
325: bputs(text[UnextractableFile]);
326: return; }
327: if(!intmp && !findfile(&cfg,dirnum,f.name)) { /* not temp dir */
328: bputs(text[SearchingAllDirs]);
329: for(i=0;i<usrdirs[curlib] && !msgabort();i++) {
330: if(i==dirnum) continue;
331: if(findfile(&cfg,usrdir[curlib][i],f.name))
332: break; }
333: if(i==usrdirs[curlib]) { /* not found in cur lib */
334: bputs(text[SearchingAllLibs]);
335: for(i=j=0;i<usrlibs;i++) {
336: if(i==curlib) continue;
337: for(j=0;j<usrdirs[i] && !msgabort();j++)
338: if(findfile(&cfg,usrdir[i][j],f.name))
339: break;
340: if(j<usrdirs[i])
341: break; }
342: if(i==usrlibs) {
343: bputs(text[FileNotFound]); /* not in database */
344: return; }
345: dirnum=usrdir[i][j]; }
346: else
347: dirnum=usrdir[curlib][i]; }
348: if(sys_status&SS_ABORT)
349: return;
350: sprintf(path,"%s%s",cfg.dir[dirnum]->path,fname);
351: if(!intmp) { /* not temp dir, so get temp_file info */
352: f.datoffset=f.dateuled=f.datedled=0L;
353: f.dir=dirnum;
354: getfileixb(&cfg,&f);
355: if(!f.datoffset && !f.dateuled && !f.datedled) /* error reading ixb */
356: return;
357: f.size=0;
358: getfiledat(&cfg,&f);
359: fileinfo(&f);
360: if(f.altpath>0 && f.altpath<=cfg.altpaths)
361: sprintf(path,"%s%s",cfg.altpath[f.altpath-1],fname);
362: temp_dirnum=dirnum;
363: if(cfg.dir[f.dir]->misc&DIR_FREE)
364: temp_cdt=0L;
365: else
366: temp_cdt=f.cdt;
367: SAFECOPY(temp_uler,f.uler);
368: SAFECOPY(temp_file,f.name); } /* padded filename */
369: if(!fexistcase(path)) {
370: bputs(text[FileNotThere]); /* not on disk */
371: return; }
372: done=0;
373: while(online && !done) {
374: mnemonics(text[ExtractFilesPrompt]);
375: switch(getkeys("EVQ",0)) {
376: case 'E':
377: if(!getfilespec(str))
378: break;
379: if(!checkfname(str))
380: break;
381: if((i=external(cmdstr(excmd,path,str,NULL)
382: ,EX_INR|EX_OUTL|EX_OUTR))!=0) {
383: errormsg(WHERE,ERR_EXEC,cmdstr(excmd,path,str,NULL),i);
384: return; }
385: sprintf(tmp,"%s extracted %s from %s",useron.alias,str,path);
386: logline(nulstr,tmp);
387: CRLF;
388: break;
389: case 'V':
390: viewfiles(dirnum,fname);
391: break;
392: default:
393: done=1;
394: break; } }
395: }
396:
397: /****************************************************************************/
398: /* Creates a text file named NEWFILES.DAT in the temp directory that */
399: /* all new files since p-date. Returns number of files in list. */
400: /****************************************************************************/
401: ulong sbbs_t::create_filelist(char *name, long mode)
402: {
403: char str[256];
404: int file;
405: uint i,j,d;
406: ulong l,k;
407:
408: bprintf(text[CreatingFileList],name);
409: sprintf(str,"%s%s",cfg.temp_dir,name);
410: if((file=nopen(str,O_CREAT|O_WRONLY|O_APPEND))==-1) {
411: errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_APPEND);
412: return(0); }
413: k=0;
414: if(mode&FL_ULTIME) {
415: sprintf(str,"New files since: %s\r\n",timestr(&ns_time));
416: write(file,str,strlen(str)); }
417: for(i=j=d=0;i<usrlibs;i++) {
418: for(j=0;j<usrdirs[i];j++,d++) {
419: outchar('.');
420: if(d && !(d%5))
421: bputs("\b\b\b\b\b \b\b\b\b\b");
422: if(mode&FL_ULTIME /* New-scan */
423: && (cfg.lib[usrlib[i]]->offline_dir==usrdir[i][j]
424: || cfg.dir[usrdir[i][j]]->misc&DIR_NOSCAN))
425: continue;
426: l=listfiles(usrdir[i][j],nulstr,file,mode);
427: if((long)l==-1)
428: break;
429: k+=l; }
430: if(j<usrdirs[i])
431: break; }
432: if(k>1) {
433: sprintf(str,"\r\n%ld Files Listed.\r\n",k);
434: write(file,str,strlen(str)); }
435: close(file);
436: if(k)
437: bprintf(text[CreatedFileList],name);
438: else {
439: bputs(text[NoFiles]);
440: sprintf(str,"%s%s",cfg.temp_dir,name);
441: remove(str); }
442: SAFECOPY(temp_file,name);
443: SAFECOPY(temp_uler,"File List");
444: return(k);
445: }
446:
447: /****************************************************************************/
448: /* This function returns the command line for the temp file extension for */
449: /* current user online. */
450: /****************************************************************************/
451: char * sbbs_t::temp_cmd(void)
452: {
453: int i;
454:
455: if(!cfg.total_fcomps) {
456: errormsg(WHERE,ERR_CHK,"compressible file types",0);
457: return(nulstr); }
458: for(i=0;i<cfg.total_fcomps;i++)
459: if(!stricmp(useron.tmpext,cfg.fcomp[i]->ext)
460: && chk_ar(cfg.fcomp[i]->ar,&useron))
461: return(cfg.fcomp[i]->cmd);
462: return(cfg.fcomp[0]->cmd);
463: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.