bat_xfer.cpp 21.4 KB
Newer Older
1
2
3
4
5
6
/* Synchronet batch file transfer functions */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"
23
#include "filedat.h"
24
25
26
27
28
29

/****************************************************************************/
/* This is the batch menu section                                           */
/****************************************************************************/
void sbbs_t::batchmenu()
{
30
31
    char	str[129],tmp2[250],done=0,ch;
	char 	tmp[512];
32
	char	keys[32];
33
	uint	i,n,xfrprot,xfrdir;
34
    int64_t	totalcdt,totalsize;
35
    time_t	start,end;
36
37
	str_list_t ini;
	str_list_t filenames;
38

39
	if(batdn_total() < 1 && batup_total() < 1 && cfg.upload_dir==INVALID_DIR) {
40
		bputs(text[NoFilesInBatchQueue]);
41
42
		return; 
	}
43
	if(useron.misc&(RIP|WIP|HTML) && !(useron.misc&EXPERT))
44
		menu("batchxfer");
45
	lncntr=0;
46
	while(online && !done && (cfg.upload_dir!=INVALID_DIR || batdn_total() || batup_total())) {
47
		if(!(useron.misc&(EXPERT|RIP|WIP|HTML))) {
48
49
50
51
52
			sys_status&=~SS_ABORT;
			if(lncntr) {
				SYNC;
				CRLF;
				if(lncntr)          /* CRLF or SYNC can cause pause */
53
54
55
56
					pause(); 
			}
			menu("batchxfr"); 
		}
57
58
		ASYNC;
		bputs(text[BatchMenuPrompt]);
59
		SAFEPRINTF(keys,"CDLRU?\r%c", text[YNQP][2]);
60
		ch=(char)getkeys(keys,0);
61
		if(ch>' ')
62
			logch(ch,0);
63
64
65
66
67
		if(ch==text[YNQP][2] || ch=='\r') {	/* Quit */
			lncntr=0;
			done=1;
			break;
		}
68
69
		switch(ch) {
			case '?':
70
				if(useron.misc&(EXPERT|RIP|WIP|HTML))
71
					menu("batchxfr");
72
73
				break;
			case 'C':
74
75
76
				if(batup_total() < 1) {
					bputs(text[UploadQueueIsEmpty]);
				} else {
77
					if(text[ClearUploadQueueQ][0]==0 || !noyes(text[ClearUploadQueueQ])) {
78
79
						if(clearbatul())
							bputs(text[UploadQueueCleared]);
80
81
					} 
				}
82
83
84
				if(batdn_total() <1 ) {
					bputs(text[DownloadQueueIsEmpty]);
				} else {
85
					if(text[ClearDownloadQueueQ][0]==0 || !noyes(text[ClearDownloadQueueQ])) {
86
87
						if(clearbatdl())
							bputs(text[DownloadQueueCleared]); 
88
89
					} 
				}
90
91
92
93
94
				break;
			case 'D':
				start_batch_download();
				break;
			case 'L':
95
96
97
				ini = batch_list_read(&cfg, useron.number, XFER_BATCH_UPLOAD);
				filenames = iniGetSectionList(ini, NULL);
				if(strListCount(filenames)) {
98
					bputs(text[UploadQueueLstHdr]);
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
					for(size_t i = 0; filenames[i]; ++i) {
						const char* filename = filenames[i];
						char value[INI_MAX_VALUE_LEN];
						bprintf(text[UploadQueueLstFmt]
							,i+1, filename
							,iniGetString(ini, filename, "desc", text[NoDescription], value));
					}
				} else
					bputs(text[UploadQueueIsEmpty]);

				iniFreeStringList(filenames);
				iniFreeStringList(ini);

				totalsize = 0;
				totalcdt = 0;
				ini = batch_list_read(&cfg, useron.number, XFER_BATCH_DOWNLOAD);
				filenames = iniGetSectionList(ini, NULL);
				if(strListCount(filenames)) {
117
					bputs(text[DownloadQueueLstHdr]);
118
119
120
121
122
123
124
					for(size_t i = 0; filenames[i]; ++i) {
						const char* filename = filenames[i];
						file_t f = {{}};
						if(!batch_file_load(&cfg, ini, filename, &f))
							continue;
						getfilesize(&cfg, &f);
						getfiletime(&cfg, &f);
125
						bprintf(text[DownloadQueueLstFmt],i+1
126
127
128
							,filename
							,ultoac(f.cost, tmp)
							,ultoac((ulong)f.size, str)
129
							,cur_cps
130
131
132
133
134
135
								? sectostr((uint)(f.size/(ulong)cur_cps),tmp2)
								: "??:??:??"
							,datestr(f.time)
						);
						totalsize += f.size;
						totalcdt += f.cost;
136
						smb_freefilemem(&f);
137
					}
138
					bprintf(text[DownloadQueueTotals]
139
140
						,ultoac((ulong)totalcdt,tmp),ultoac((ulong)totalsize,str),cur_cps
						? sectostr((ulong)totalsize/(ulong)cur_cps,tmp2)
141
						: "??:??:??"); 
142
143
144
145
146
				} else
					bputs(text[DownloadQueueIsEmpty]);
				iniFreeStringList(filenames);
				iniFreeStringList(ini);
				break;
147
			case 'R':
148
149
150
151
				if((n = batup_total()) > 0) {
					bprintf(text[RemoveWhichFromUlQueue], n);
					if(getstr(str, MAX_FILENAME_LEN, K_NONE) > 0)
						batch_file_remove(&cfg, useron.number, XFER_BATCH_UPLOAD, str);
152
				}
153
154
155
156
				if((n = batdn_total()) > 0) {
					bprintf(text[RemoveWhichFromDlQueue], n);
					if(getstr(str, MAX_FILENAME_LEN, K_NONE) > 0)
						batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, str);
157
				}
158
159
160
161
				break;
		   case 'U':
				if(useron.rest&FLAG('U')) {
					bputs(text[R_Upload]);
162
163
					break; 
				}
164
				if(batup_total() < 1 && cfg.upload_dir==INVALID_DIR) {
165
					bputs(text[UploadQueueIsEmpty]);
166
167
					break; 
				}
168
				xfer_prot_menu(XFER_BATCH_UPLOAD);
169
170
171
172
				if(!create_batchup_lst())
					break;
				ASYNC;
				mnemonics(text[ProtocolOrQuit]);
173
				SAFEPRINTF(str,"%c",text[YNQP][2]);
174
				for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
175
					if(cfg.prot[i]->batulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
176
						sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
177
						SAFECAT(str,tmp); 
178
					}
179
				ch=(char)getkeys(str,0);
180
				if(ch==text[YNQP][2])
181
182
183
					break;
				for(i=0;i<cfg.total_prots;i++)
					if(cfg.prot[i]->batulcmd[0] && cfg.prot[i]->mnemonic==ch
rswindell's avatar
rswindell committed
184
						&& chk_ar(cfg.prot[i]->ar,&useron,&client))
185
186
						break;
				if(i<cfg.total_prots) {
187
					SAFEPRINTF(str,"%sBATCHUP.LST",cfg.node_dir);
188
					xfrprot=i;
189
					xfrdir=cfg.upload_dir;
190
191
192
					action=NODE_ULNG;
					SYNC;
					if(online==ON_REMOTE) {
193
						delfiles(cfg.temp_dir,ALLFILES);
194
						start=time(NULL);
195
						protocol(cfg.prot[xfrprot],XFER_BATCH_UPLOAD,str,nulstr,true);
196
197
						end=time(NULL);
						if(!(cfg.dir[xfrdir]->misc&DIR_ULTIME))
198
199
							starttime+=end-start; 
					}
200
					batch_upload();
201
					delfiles(cfg.temp_dir,ALLFILES);
202
203
204
205
206
					autohangup(); 
				}
				break; 
		} 
	}
207
	delfiles(cfg.temp_dir,ALLFILES);
208
209
210
211
212
}

/****************************************************************************/
/* Download files from batch queue                                          */
/****************************************************************************/
213
BOOL sbbs_t::start_batch_download()
214
{
215
216
217
218
	char	ch;
	char	tmp[32];
	char	str[MAX_PATH+1];
	char 	path[MAX_PATH+1];
219
	char	list[1024] = "";
220
	int		error;
221
222
    uint	i,xfrprot;
    time_t	start,end,t;
223
	struct	tm tm;
224
225
226

	if(useron.rest&FLAG('D')) {     /* Download restriction */
		bputs(text[R_Download]);
227
228
		return(FALSE); 
	}
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262

	str_list_t ini = batch_list_read(&cfg, useron.number, XFER_BATCH_DOWNLOAD);

	size_t file_count = iniGetSectionCount(ini, NULL);
	if(file_count < 1) {
		bputs(text[DownloadQueueIsEmpty]);
		iniFreeStringList(ini);
		return(FALSE);
	}
	str_list_t filenames = iniGetSectionList(ini, NULL);

	if(file_count == 1) {	// Only one file in the queue? Perform a non-batch (e.g. XMODEM) download
		file_t f = {{}};
		BOOL result = FALSE;
		if(batch_file_get(&cfg, ini, filenames[0], &f)) {
			result = sendfile(&f, /* prot: */' ', /* autohang: */true);
			if(result == TRUE)
				batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, f.name);
		}
		iniFreeStringList(ini);
		iniFreeStringList(filenames);
		smb_freefilemem(&f);
		return result;
	}

	int64_t totalcdt = 0;
	for(size_t i=0; filenames[i] != NULL; ++i) {
		file_t f = {{}};
		if(batch_file_load(&cfg, ini, filenames[i], &f)) {
			totalcdt += f.cost;
			smb_freefilemem(&f);
		}
	}
	if(totalcdt > (int64_t)(useron.cdt+useron.freecdt)) {
263
264
		bprintf(text[YouOnlyHaveNCredits]
			,ultoac(useron.cdt+useron.freecdt,tmp));
265
266
		iniFreeStringList(ini);
		iniFreeStringList(filenames);
267
		return(FALSE); 
268
	}
269

270
271
272
273
274
275
276
277
278
279
280
	int64_t totalsize = 0;
	int64_t totaltime = 0;
	for(size_t i=0; filenames[i] != NULL; ++i) {
		file_t f = {{}};
		if(!batch_file_get(&cfg, ini, filenames[i], &f))
			continue;
		if(!(cfg.dir[f.dir]->misc&DIR_TFREE) && cur_cps)
			totaltime += getfilesize(&cfg, &f) / (ulong)cur_cps;
		SAFECAT(list, getfilepath(&cfg, &f, path));
		SAFECAT(list, " ");
		smb_freefilemem(&f);
281
	}
282
283
284
285
	iniFreeStringList(ini);
	iniFreeStringList(filenames);

	if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime > (int64_t)timeleft) {
286
		bputs(text[NotEnoughTimeToDl]);
287
		return(FALSE); 
288
	}
289
	xfer_prot_menu(XFER_BATCH_DOWNLOAD);
290
291
	ASYNC;
	mnemonics(text[ProtocolOrQuit]);
292
	SAFEPRINTF(str,"%c",text[YNQP][2]);
293
	for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
294
		if(cfg.prot[i]->batdlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
295
			sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
296
			SAFECAT(str,tmp); 
297
		}
298
	ungetkey(useron.prot);
299
	ch=(char)getkeys(str,0);
300
	if(ch==text[YNQP][2] || sys_status&SS_ABORT)
301
		return(FALSE);
302
303
	for(i=0;i<cfg.total_prots;i++)
		if(cfg.prot[i]->batdlcmd[0] && cfg.prot[i]->mnemonic==ch
rswindell's avatar
rswindell committed
304
			&& chk_ar(cfg.prot[i]->ar,&useron,&client))
305
			break;
306
	if(i>=cfg.total_prots || !create_batchdn_lst((cfg.prot[i]->misc&PROT_NATIVE) ? true:false)) {
307
		return(FALSE);
308
	}
309
	xfrprot=i;
310
#if 0 // NFB-TODO: Download events
311
312
313
314
315
316
	list=NULL;
	for(i=0;i<batdn_total;i++) {
		curdirnum=batdn_dir[i]; 		/* for ARS */
		unpadfname(batdn_name[i],fname);
		if(cfg.dir[batdn_dir[i]]->seqdev) {
			lncntr=0;
317
			SAFEPRINTF2(path,"%s%s",cfg.temp_dir,fname);
318
			if(!fexistcase(path)) {
319
320
				seqwait(cfg.dir[batdn_dir[i]]->seqdev);
				bprintf(text[RetrievingFile],fname);
321
				SAFEPRINTF2(str,"%s%s"
322
					,cfg.dir[batdn_dir[i]]->path
323
					,fname);
324
				mv(str,path,1); /* copy the file to temp dir */
325
326
327
328
				if(getnodedat(cfg.node_num,&thisnode,true)==0) {
					thisnode.aux=40; /* clear the seq dev # */
					putnodedat(cfg.node_num,&thisnode);
				}
329
				CRLF; 
330
			} 
331
		}
332
		else
333
			SAFEPRINTF2(path,"%s%s"
334
335
336
337
338
339
340
341
				,batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths
				? cfg.altpath[batdn_alt[i]-1]
				: cfg.dir[batdn_dir[i]]->path
				,fname);
		if(list==NULL)
			list_len=0;
		else
			list_len=strlen(list)+1;	/* add one for ' ' */
342
343
344
		char* np;
		if((np=(char*)realloc(list,list_len+strlen(path)+1	/* add one for '\0'*/))==NULL) {
			free(list);
345
			errormsg(WHERE,ERR_ALLOC,"list",list_len+strlen(path));
346
			return(FALSE);
347
		}
348
		list = np;
349
350
351
352
353
354
355
356
357
		if(!list_len)
			strcpy(list,path);
		else {
			strcat(list," ");
			strcat(list,path);
		}
		for(j=0;j<cfg.total_dlevents;j++) {
			if(stricmp(cfg.dlevent[j]->ext,batdn_name[i]+9))
				continue;
rswindell's avatar
rswindell committed
358
			if(!chk_ar(cfg.dlevent[j]->ar,&useron,&client))
359
360
361
362
363
				continue;
			bputs(cfg.dlevent[j]->workstr);
			external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr,NULL),EX_OUTL);
			CRLF; 
		}
364
	}
365
#endif
366

367
	SAFEPRINTF(str,"%sBATCHDN.LST",cfg.node_dir);
368
369
370
371
	action=NODE_DLNG;
	t=now;
	if(cur_cps) 
		t+=(totalsize/(ulong)cur_cps);
372
	localtime_r(&t,&tm);
373
374
375
376
377
	if(getnodedat(cfg.node_num,&thisnode,true)==0) {
		thisnode.aux=(tm.tm_hour*60)+tm.tm_min;
		thisnode.action=action;
		putnodedat(cfg.node_num,&thisnode); /* calculate ETA */
	}
378
	start=time(NULL);
379
	error=protocol(cfg.prot[xfrprot],XFER_BATCH_DOWNLOAD,str,list,false);
380
381
382
	end=time(NULL);
	if(cfg.prot[xfrprot]->misc&PROT_DSZLOG || !error)
		batch_download(xfrprot);
383
384
385
	if(batdn_total())
		notdownloaded((ulong)totalsize,start,end);
	autohangup();
386

387
	return TRUE;
388
}
389
390
391
392
393

/****************************************************************************/
/* Creates the file BATCHDN.LST in the node directory. Returns true if      */
/* everything goes okay, false if not.                                      */
/****************************************************************************/
394
bool sbbs_t::create_batchdn_lst(bool native)
395
{
396
	char	path[MAX_PATH+1];
397

398
399
400
401
402
	SAFEPRINTF(path, "%sBATCHDN.LST", cfg.node_dir);
	FILE* fp = fopen(path, "wb");
	if(fp == NULL) {
		errormsg(WHERE, ERR_OPEN, path);
		return false;
403
	}
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
	str_list_t ini = batch_list_read(&cfg, useron.number, XFER_BATCH_DOWNLOAD);
	str_list_t filenames = iniGetSectionList(ini, /* prefix: */NULL);
	for(size_t i = 0; filenames[i] != NULL; ++i) {
		const char* filename = filenames[i];
		file_t f = {};
		f.dir = batch_file_dir(&cfg, ini, filename);
		if(!loadfile(&cfg, f.dir, filename, &f, file_detail_index)) {
			errormsg(WHERE, "loading file", filename, i);
			batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, filename);
			continue;
		}
		getfilepath(&cfg, &f, path);
		if(!fexistcase(path)) {
			bprintf(text[FileDoesNotExist], path);
			batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, filename);
		}
		else {
#ifdef _WIN32
			if(!native) {
				char tmp[MAX_PATH + 1];
				GetShortPathName(path, tmp, sizeof(tmp));
				SAFECOPY(path, tmp);
			}
#endif
			fprintf(fp, "%s\r\n", path);
		}
		smb_freefilemem(&f);
431
	}
432
433
434
435
	fclose(fp);
	iniFreeStringList(ini);
	iniFreeStringList(filenames);
	return true;
436
437
438
439
440
441
442
443
444
}

/****************************************************************************/
/* Creates the file BATCHUP.LST in the node directory. Returns true if      */
/* everything goes okay, false if not.                                      */
/* This list is not used by any protocols to date.                          */
/****************************************************************************/
bool sbbs_t::create_batchup_lst()
{
445
    char	path[MAX_PATH + 1];
446

447
448
449
450
451
	SAFEPRINTF(path,"%sBATCHUP.LST",cfg.node_dir);
	FILE* fp = fopen(path, "wb");
	if(fp == NULL) {
		errormsg(WHERE, ERR_OPEN, path);
		return false;
452
	}
453
454
455
456
457
458
459
460
	str_list_t ini = batch_list_read(&cfg, useron.number, XFER_BATCH_UPLOAD);
	str_list_t filenames = iniGetSectionList(ini, /* prefix: */NULL);
	for(size_t i = 0; filenames[i] != NULL; ++i) {
		const char* filename = filenames[i];
		file_t f = {{}};
		if(!batch_file_get(&cfg, ini, filename, &f))
			continue;
		fprintf(fp, "%s%s\r\n", cfg.dir[f.dir]->path, filename);
461
		smb_freefilemem(&f);
462
	}
463
464
465
466
	fclose(fp);
	iniFreeStringList(ini);
	iniFreeStringList(filenames);
	return true;
467
468
469
470
471
472
473
}

/****************************************************************************/
/* Processes files that were supposed to be received in the batch queue     */
/****************************************************************************/
void sbbs_t::batch_upload()
{
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
	char src[MAX_PATH + 1];
	char dest[MAX_PATH + 1];

	str_list_t ini = batch_list_read(&cfg, useron.number, XFER_BATCH_UPLOAD);
	str_list_t filenames = iniGetSectionList(ini, /* prefix: */NULL);
	for(size_t i = 0; filenames[i] != NULL; ++i) {
		const char* filename = filenames[i];
		int dir = batch_file_dir(&cfg, ini, filename);
		curdirnum = dir; /* for ARS */
		lncntr = 0; /* defeat pause */

		SAFEPRINTF2(src, "%s%s", cfg.temp_dir, filename);
		SAFEPRINTF2(dest, "%s%s", cfg.dir[dir]->path, filename);
		if(fexistcase(src) && fexistcase(dest)) { /* file's in two places */
			bprintf(text[FileAlreadyThere], filename);
			remove(src);    /* this is the one received */
			continue;
491
		}
492
493
494
495
496
497
498
499
500

		if(fexist(src))
			mv(src, dest, /* copy: */FALSE);

		file_t f = {{}};
		if(!batch_file_get(&cfg, ini, filename, &f))
			continue;
		if(uploadfile(&f))
			batch_file_remove(&cfg, useron.number, XFER_BATCH_DOWNLOAD, filename);
501
		smb_freefilemem(&f);
502
	}
503
504
505
506
	iniFreeStringList(filenames);
	iniFreeStringList(ini);

	if(cfg.upload_dir == INVALID_DIR) // no blind upload dir specified
507
		return;
508
509
510

	DIR* dir = opendir(cfg.temp_dir);
	DIRENT* dirent;
511
	while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
512
513
		SAFEPRINTF2(src, "%s%s", cfg.temp_dir,dirent->d_name);
		if(isdir(src))
rswindell's avatar
rswindell committed
514
			continue;
515
516
517
518
		if(!checkfname(dirent->d_name)) {
			bprintf(text[BadFilename], dirent->d_name);
			continue;
		}
519
520
		SAFEPRINTF2(dest, "%s%s", cfg.dir[cfg.upload_dir]->path, dirent->d_name);
		if(fexistcase(dest)) {
rswindell's avatar
rswindell committed
521
522
523
			bprintf(text[FileAlreadyOnline], dirent->d_name);
			continue;
		}
524
		if(mv(src, dest, /* copy: */false))
525
			continue;
526

527
		uint x,y;
528
		for(x=0;x<usrlibs;x++) {
529
			progress(text[SearchingForDupes], x, usrlibs, 1);
530
531
			for(y=0;y<usrdirs[x];y++)
				if(cfg.dir[usrdir[x][y]]->misc&DIR_DUPES
532
					&& findfile(&cfg,usrdir[x][y], dirent->d_name, NULL))
533
534
535
					break;
			if(y<usrdirs[x])
				break; 
536
		}
537
		bputs(text[SearchedForDupes]);
rswindell's avatar
rswindell committed
538
		if(x<usrlibs) {
539
			bprintf(text[FileAlreadyOnline], dirent->d_name);
540
		} else {
541
542
543
544
545
			file_t f = {{}};
			f.dir = cfg.upload_dir;
			smb_hfield_str(&f, SMB_FILENAME, dirent->d_name);
			uploadfile(&f);
			smb_freefilemem(&f);
546
547
		}
	}
548
549
	if(dir!=NULL)
		closedir(dir);
550
551
552
553
554
555
556
557
}

/****************************************************************************/
/* Processes files that were supposed to be sent from the batch queue       */
/* xfrprot is -1 if downloading files from within QWK (no DSZLOG)           */
/****************************************************************************/
void sbbs_t::batch_download(int xfrprot)
{
558
559
560
561
562
	FILE* fp = batch_list_open(&cfg, useron.number, XFER_BATCH_DOWNLOAD, /* create: */FALSE);
	if(fp == NULL)
		return;
	str_list_t ini = iniReadFile(fp);
	str_list_t filenames = iniGetSectionList(ini, /* prefix: */NULL);
563

564
565
	for(size_t i = 0; filenames[i] != NULL; ++i) {
		char* filename = filenames[i];
566
		lncntr=0;                               /* defeat pause */
567
568
569
570
571
572
573
		if(xfrprot==-1 || checkprotresult(cfg.prot[xfrprot], 0, filename)) {
			file_t f = {{}};
			if(!batch_file_load(&cfg, ini, filename, &f)) {
				errormsg(WHERE, "loading file", filename, i);
				continue;
			}
			iniRemoveSection(&ini, filename);
574
575
			if(cfg.dir[f.dir]->misc&DIR_TFREE && cur_cps)
				starttime+=f.size/(ulong)cur_cps;
576
577
			downloadedfile(&f);
			smb_freefilemem(&f);
578
579
		}
	}
580
581
582
583
	iniWriteFile(fp, ini);
	iniCloseFile(fp);
	iniFreeStringList(ini);
	iniFreeStringList(filenames);
584
585
586
587
588
589
590
}

/****************************************************************************/
/* Adds a list of files to the batch download queue 						*/
/****************************************************************************/
void sbbs_t::batch_add_list(char *list)
{
591
592
    char	str[1024];
	char	path[MAX_PATH + 1];
593
594
595
596
597
598
599
600
601
602
603
	int		file;
	uint	i,j,k;
    FILE *	stream;
	file_t	f;

	if((stream=fnopen(&file,list,O_RDONLY))!=NULL) {
		bputs(text[SearchingAllLibs]);
		while(!feof(stream)) {
			checkline();
			if(!online)
				break;
604
			if(!fgets(str, sizeof(str) - 1,stream))
605
				break;
606
			truncnl(str);
607
			lncntr=0;
608
			for(i=j=k=0;i<usrlibs;i++) {
609
610
611
612
				for(j=0;j<usrdirs[i];j++,k++) {
					outchar('.');
					if(k && !(k%5))
						bputs("\b\b\b\b\b     \b\b\b\b\b");
613
614
615
616
617
618
619
620
					if(loadfile(&cfg, usrdir[i][j], str, &f, file_detail_normal)) {
						if(fexist(getfilepath(&cfg, &f, path)))
							addtobatdl(&f);
						else
							bprintf(text[FileIsNotOnline],f.name);
						smb_freefilemem(&f);
						break;
					}
621
				}
622
				if(j<usrdirs[i])
623
624
625
					break; 
			}
		}
626
627
		fclose(stream);
		remove(list);
628
		CRLF;
629
630
	}
}
631
632
633
634
635
636

/**************************************************************************/
/* Add file 'f' to batch download queue. Return 1 if successful, 0 if not */
/**************************************************************************/
bool sbbs_t::addtobatdl(file_t* f)
{
637
638
639
    char	str[256],tmp2[256];
	char 	tmp[512];
    uint	i;
640
641
	uint64_t	totalcost, totalsize;
	uint64_t	totaltime;
642
643
644

	if(useron.rest&FLAG('D')) {
		bputs(text[R_Download]);
645
		return false;
646
	}
rswindell's avatar
rswindell committed
647
	if(!chk_ar(cfg.dir[f->dir]->dl_ar,&useron,&client)) {
648
649
		bprintf(text[CantAddToQueue],f->name);
		bputs(text[CantDownloadFromDir]);
650
		return false;
651
	}
652
653
654
655
	if(getfilesize(&cfg, f) < 1) {
		bprintf(text[CantAddToQueue], f->name);
		bprintf(text[FileIsNotOnline], f->name);
		return false;
656
	}
657
658
659
660
661
662

	str_list_t ini = batch_list_read(&cfg, useron.number, XFER_BATCH_DOWNLOAD);
	if(iniSectionExists(ini, f->name)) {
		bprintf(text[FileAlreadyInQueue], f->name);
		iniFreeStringList(ini);
		return false;
663
	}
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732

	bool result = false;
	str_list_t filenames = iniGetSectionList(ini, /* prefix: */NULL);
	if(strListCount(filenames) >= cfg.max_batdn) {
		bprintf(text[CantAddToQueue] ,f->name);
		bputs(text[BatchDlQueueIsFull]);
	} else {
		totalcost = 0;
		totaltime = 0;
		totalsize = 0;
		for(i=0; filenames[i] != NULL; ++i) {
			const char* filename = filenames[i];
			file_t bf = {{}};
			if(!batch_file_load(&cfg, ini, filename, &bf))
				continue;
			totalcost += bf.cost;
			totalsize += getfilesize(&cfg, &bf);
			if(!(cfg.dir[bf.dir]->misc&DIR_TFREE) && cur_cps)
				totaltime += bf.size/(ulong)cur_cps;
			smb_freefilemem(&bf);
		}
		if(cfg.dir[f->dir]->misc&DIR_FREE)
			f->cost=0L;
		if(!is_download_free(&cfg,f->dir,&useron,&client))
			totalcost += f->cost;
		if(totalcost > useron.cdt+useron.freecdt) {
			bprintf(text[CantAddToQueue],f->name);
			bprintf(text[YouOnlyHaveNCredits],ultoac(useron.cdt+useron.freecdt,tmp));
		} else {
			totalsize += f->size;
			if(!(cfg.dir[f->dir]->misc&DIR_TFREE) && cur_cps)
				totaltime += f->size/(ulong)cur_cps;
			if(!(useron.exempt&FLAG('T')) && totaltime > timeleft) {
				bprintf(text[CantAddToQueue],f->name);
				bputs(text[NotEnoughTimeToDl]);
			} else {
				if(batch_file_add(&cfg, useron.number, XFER_BATCH_DOWNLOAD, f)) {
					bprintf(text[FileAddedToBatDlQueue]
						,f->name, strListCount(filenames) + 1, cfg.max_batdn, ultoac((ulong)totalcost,tmp)
						,ultoac((ulong)totalsize,tmp2)
						,sectostr((ulong)totalsize/(ulong)cur_cps,str));
					result = true;
				}
			}
		}
	}
	iniFreeStringList(ini);
	iniFreeStringList(filenames);
	return result;
}

bool sbbs_t::clearbatdl(void)
{
	return batch_list_clear(&cfg, useron.number, XFER_BATCH_DOWNLOAD);
}

bool sbbs_t::clearbatul(void)
{
	return batch_list_clear(&cfg, useron.number, XFER_BATCH_UPLOAD);
}

size_t sbbs_t::batdn_total(void)
{
	return batch_file_count(&cfg, useron.number, XFER_BATCH_DOWNLOAD);
}

size_t sbbs_t::batup_total(void)
{
	return batch_file_count(&cfg, useron.number, XFER_BATCH_UPLOAD);
733
}