bat_xfer.cpp 24.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/* bat_xfer.cpp */

/* Synchronet batch file transfer functions */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html		*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 *																			*
 * 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										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

#include "sbbs.h"

/****************************************************************************/
/* This is the batch menu section                                           */
/****************************************************************************/
void sbbs_t::batchmenu()
{
45
46
47
48
49
50
    char	str[129],tmp2[250],done=0,ch;
	char 	tmp[512];
	uint	i,n,xfrprot,xfrdir;
    ulong	totalcdt,totalsize,totaltime;
    time_t	start,end;
    file_t	f;
51
52
53

	if(!batdn_total && !batup_total && cfg.upload_dir==INVALID_DIR) {
		bputs(text[NoFilesInBatchQueue]);
54
55
		return; 
	}
56
	if(useron.misc&(RIP|WIP|HTML) && !(useron.misc&EXPERT))
57
		menu("batchxfer");
58
59
60
	lncntr=0;
	while(online && !done && (batdn_total || batup_total
		|| cfg.upload_dir!=INVALID_DIR)) {
61
		if(!(useron.misc&(EXPERT|RIP|WIP|HTML))) {
62
63
64
65
66
			sys_status&=~SS_ABORT;
			if(lncntr) {
				SYNC;
				CRLF;
				if(lncntr)          /* CRLF or SYNC can cause pause */
67
68
69
70
					pause(); 
			}
			menu("batchxfr"); 
		}
71
72
73
		ASYNC;
		bputs(text[BatchMenuPrompt]);
		ch=(char)getkeys("BCDLQRU?\r",0);
74
		if(ch>' ')
75
76
77
			logch(ch,0);
		switch(ch) {
			case '?':
78
				if(useron.misc&(EXPERT|RIP|WIP|HTML))
79
					menu("batchxfr");
80
81
82
83
84
85
86
87
88
				break;
			case CR:
			case 'Q':
				lncntr=0;
				done=1;
				break;
			case 'B':   /* Bi-directional transfers */
				if(useron.rest&FLAG('D')) {
					bputs(text[R_Download]);
89
90
					break; 
				}
91
92
				if(useron.rest&FLAG('U')) {
					bputs(text[R_Upload]);
93
94
					break; 
				}
95
96
				if(!batdn_total) {
					bputs(text[DownloadQueueIsEmpty]);
97
98
					break; 
				}
99
100
				if(!batup_total && cfg.upload_dir==INVALID_DIR) {
					bputs(text[UploadQueueIsEmpty]);
101
102
					break; 
				}
103
				for(i=0,totalcdt=0;i<batdn_total;i++)
rswindell's avatar
rswindell committed
104
					if(!is_download_free(&cfg,batdn_dir[i],&useron,&client))
105
						totalcdt+=batdn_cdt[i];
106
				if(totalcdt>useron.cdt+useron.freecdt) {
107
108
					bprintf(text[YouOnlyHaveNCredits]
						,ultoac(useron.cdt+useron.freecdt,tmp));
109
110
					break; 
				}
111
112
113
				for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
					totalsize+=batdn_size[i];
					if(!(cfg.dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
114
115
						totaltime+=batdn_size[i]/(ulong)cur_cps; 
				}
116
117
				if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) {
					bputs(text[NotEnoughTimeToDl]);
118
119
					break; 
				}
120
				xfer_prot_menu(XFER_BIDIR);
121
122
123
124
				SYNC;
				mnemonics(text[ProtocolOrQuit]);
				strcpy(tmp2,"Q");
				for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
125
					if(cfg.prot[i]->bicmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
126
						sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
127
128
						strcat(tmp2,tmp); 
					}
129
130
131
132
133
134
				ungetkey(useron.prot);
				ch=(char)getkeys(tmp2,0);
				if(ch=='Q')
					break;
				for(i=0;i<cfg.total_prots;i++)
					if(cfg.prot[i]->bicmd[0] && cfg.prot[i]->mnemonic==ch
rswindell's avatar
rswindell committed
135
						&& chk_ar(cfg.prot[i]->ar,&useron,&client))
136
137
						break;
				if(i<cfg.total_prots) {
138
139
140
141
142
143
144
					if(!create_batchdn_lst((cfg.prot[i]->misc&PROT_NATIVE) ? true:false))
						break;
					if(!create_batchup_lst())
						break;
					if(!create_bimodem_pth())
						break;

145
146
147
148
149
150
151
152
					xfrprot=i;
					action=NODE_BXFR;
					SYNC;
					for(i=0;i<batdn_total;i++)
						if(cfg.dir[batdn_dir[i]]->seqdev) {
							lncntr=0;
							unpadfname(batdn_name[i],tmp);
							sprintf(tmp2,"%s%s",cfg.temp_dir,tmp);
153
							if(!fexistcase(tmp2)) {
154
155
156
157
158
159
160
161
								seqwait(cfg.dir[batdn_dir[i]]->seqdev);
								bprintf(text[RetrievingFile],tmp);
								sprintf(str,"%s%s"
									,batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths
									? cfg.altpath[batdn_alt[i]-1]
									: cfg.dir[batdn_dir[i]]->path
									,tmp);
								mv(str,tmp2,1); /* copy the file to temp dir */
162
163
164
165
								if(getnodedat(cfg.node_num,&thisnode,true)==0) {
									thisnode.aux=0xff;
									putnodedat(cfg.node_num,&thisnode);
								}
166
167
168
								CRLF; 
							} 
						}
169
170
171
					sprintf(str,"%sBATCHDN.LST",cfg.node_dir);
					sprintf(tmp2,"%sBATCHUP.LST",cfg.node_dir);
					start=time(NULL);
172
					protocol(cfg.prot[xfrprot],XFER_BIDIR,str,tmp2,true);
173
174
175
176
177
					end=time(NULL);
					for(i=0;i<batdn_total;i++)
						if(cfg.dir[batdn_dir[i]]->seqdev) {
							unpadfname(batdn_name[i],tmp);
							sprintf(tmp2,"%s%s",cfg.temp_dir,tmp);
178
179
							remove(tmp2); 
						}
180
181
182
183
					batch_upload();
					batch_download(xfrprot);
					if(batdn_total)     /* files still in queue, not xfered */
						notdownloaded(totalsize,start,end);
184
185
					autohangup(); 
				}
186
187
188
				break;
			case 'C':
				if(batup_total) {
189
					if(text[ClearUploadQueueQ][0]==0 || !noyes(text[ClearUploadQueueQ])) {
190
						batup_total=0;
191
192
193
						bputs(text[UploadQueueCleared]); 
					} 
				}
194
				if(batdn_total) {
195
					if(text[ClearDownloadQueueQ][0]==0 || !noyes(text[ClearDownloadQueueQ])) {
196
197
198
199
200
						for(i=0;i<batdn_total;i++) {
							f.dir=batdn_dir[i];
							f.datoffset=batdn_offset[i];
							f.size=batdn_size[i];
							strcpy(f.name,batdn_name[i]);
201
202
							closefile(&f); 
						}
203
						batdn_total=0;
204
205
206
						bputs(text[DownloadQueueCleared]); 
					} 
				}
207
208
209
210
211
212
213
214
215
				break;
			case 'D':
				start_batch_download();
				break;
			case 'L':
				if(batup_total) {
					bputs(text[UploadQueueLstHdr]);
					for(i=0;i<batup_total;i++)
						bprintf(text[UploadQueueLstFmt],i+1,batup_name[i]
216
217
							,batup_desc[i]); 
				}
218
219
220
221
222
223
224
225
226
227
				if(batdn_total) {
					bputs(text[DownloadQueueLstHdr]);
					for(i=0,totalcdt=0,totalsize=0;i<batdn_total;i++) {
						bprintf(text[DownloadQueueLstFmt],i+1
							,batdn_name[i],ultoac(batdn_cdt[i],tmp)
							,ultoac(batdn_size[i],str)
							,cur_cps
							? sectostr(batdn_size[i]/(ulong)cur_cps,tmp2)
							: "??:??:??");
						totalsize+=batdn_size[i];
228
229
						totalcdt+=batdn_cdt[i]; 
					}
230
231
232
					bprintf(text[DownloadQueueTotals]
						,ultoac(totalcdt,tmp),ultoac(totalsize,str),cur_cps
						? sectostr(totalsize/(ulong)cur_cps,tmp2)
233
234
						: "??:??:??"); 
				}
235
236
237
238
239
				break;  /* Questionable line ^^^, see note above function */
			case 'R':
				if(batup_total) {
					bprintf(text[RemoveWhichFromUlQueue],batup_total);
					n=getnum(batup_total);
240
					if((int)n>=1) {
241
242
243
244
245
246
247
248
						n--;
						batup_total--;
						while(n<batup_total) {
							batup_dir[n]=batup_dir[n+1];
							batup_misc[n]=batup_misc[n+1];
							batup_alt[n]=batup_alt[n+1];
							strcpy(batup_name[n],batup_name[n+1]);
							strcpy(batup_desc[n],batup_desc[n+1]);
249
250
							n++; 
						}
251
						if(!batup_total)
252
253
254
255
							bputs(text[UploadQueueCleared]); 
					} 
				}
				if(batdn_total) {
256
257
					bprintf(text[RemoveWhichFromDlQueue],batdn_total);
					n=getnum(batdn_total);
258
					if((int)n>=1) {
259
260
261
262
263
264
265
266
267
268
269
270
271
272
						n--;
						f.dir=batdn_dir[n];
						strcpy(f.name,batdn_name[n]);
						f.datoffset=batdn_offset[n];
						f.size=batdn_size[n];
						closefile(&f);
						batdn_total--;
						while(n<batdn_total) {
							strcpy(batdn_name[n],batdn_name[n+1]);
							batdn_dir[n]=batdn_dir[n+1];
							batdn_cdt[n]=batdn_cdt[n+1];
							batdn_alt[n]=batdn_alt[n+1];
							batdn_size[n]=batdn_size[n+1];
							batdn_offset[n]=batdn_offset[n+1];
273
274
							n++; 
						}
275
						if(!batdn_total)
276
277
278
							bputs(text[DownloadQueueCleared]); 
					} 
				}
279
280
281
282
				break;
		   case 'U':
				if(useron.rest&FLAG('U')) {
					bputs(text[R_Upload]);
283
284
					break; 
				}
285
286
				if(!batup_total && cfg.upload_dir==INVALID_DIR) {
					bputs(text[UploadQueueIsEmpty]);
287
288
					break; 
				}
289
				xfer_prot_menu(XFER_BATCH_UPLOAD);
290
291
292
293
294
295
296
297
				if(!create_batchup_lst())
					break;
				if(!create_bimodem_pth())
					break;
				ASYNC;
				mnemonics(text[ProtocolOrQuit]);
				strcpy(str,"Q");
				for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
298
					if(cfg.prot[i]->batulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
299
						sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
300
301
						strcat(str,tmp); 
					}
302
303
304
305
306
				ch=(char)getkeys(str,0);
				if(ch=='Q')
					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
307
						&& chk_ar(cfg.prot[i]->ar,&useron,&client))
308
309
310
311
312
313
314
315
316
317
318
						break;
				if(i<cfg.total_prots) {
					sprintf(str,"%sBATCHUP.LST",cfg.node_dir);
					xfrprot=i;
					if(batup_total)
						xfrdir=batup_dir[0];
					else
						xfrdir=cfg.upload_dir;
					action=NODE_ULNG;
					SYNC;
					if(online==ON_REMOTE) {
319
						delfiles(cfg.temp_dir,ALLFILES);
320
						start=time(NULL);
321
						protocol(cfg.prot[xfrprot],XFER_BATCH_UPLOAD,str,nulstr,true);
322
323
						end=time(NULL);
						if(!(cfg.dir[xfrdir]->misc&DIR_ULTIME))
324
325
							starttime+=end-start; 
					}
326
					batch_upload();
327
					delfiles(cfg.temp_dir,ALLFILES);
328
329
330
331
332
					autohangup(); 
				}
				break; 
		} 
	}
333
	delfiles(cfg.temp_dir,ALLFILES);
334
335
336
337
338
}

/****************************************************************************/
/* Download files from batch queue                                          */
/****************************************************************************/
339
BOOL sbbs_t::start_batch_download()
340
{
341
342
343
344
345
346
347
348
	char	ch;
	char	tmp[32];
	char	fname[64];
	char	str[MAX_PATH+1];
	char 	path[MAX_PATH+1];
	char*	list;
	size_t	list_len;
	int		error;
349
350
351
352
    int		j;
    uint	i,xfrprot;
    ulong	totalcdt,totalsize,totaltime;
    time_t	start,end,t;
353
	struct	tm tm;
354

355
356
357
358
	if(batdn_total==0) {
		bputs(text[DownloadQueueIsEmpty]);
		return(FALSE);
	}
359
360
	if(useron.rest&FLAG('D')) {     /* Download restriction */
		bputs(text[R_Download]);
361
362
		return(FALSE); 
	}
363
	for(i=0,totalcdt=0;i<batdn_total;i++)
rswindell's avatar
rswindell committed
364
		if(is_download_free(&cfg,batdn_dir[i],&useron,&client))
365
366
			totalcdt+=batdn_cdt[i];
	if(totalcdt>useron.cdt+useron.freecdt) {
367
368
		bprintf(text[YouOnlyHaveNCredits]
			,ultoac(useron.cdt+useron.freecdt,tmp));
369
		return(FALSE); 
370
	}
371
372
373
374

	for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
		totalsize+=batdn_size[i];
		if(!(cfg.dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
375
376
			totaltime+=batdn_size[i]/(ulong)cur_cps; 
	}
377
378
	if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) {
		bputs(text[NotEnoughTimeToDl]);
379
		return(FALSE); 
380
	}
381
	xfer_prot_menu(XFER_BATCH_DOWNLOAD);
382
383
	ASYNC;
	mnemonics(text[ProtocolOrQuit]);
384
	strcpy(str,"Q");
385
	for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
386
		if(cfg.prot[i]->batdlcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
387
			sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
388
			strcat(str,tmp); 
389
		}
390
	ungetkey(useron.prot);
391
	ch=(char)getkeys(str,0);
392
	if(ch=='Q' || sys_status&SS_ABORT)
393
		return(FALSE);
394
395
	for(i=0;i<cfg.total_prots;i++)
		if(cfg.prot[i]->batdlcmd[0] && cfg.prot[i]->mnemonic==ch
rswindell's avatar
rswindell committed
396
			&& chk_ar(cfg.prot[i]->ar,&useron,&client))
397
			break;
398
	if(i>=cfg.total_prots)
399
		return(FALSE);	/* no protocol selected */
400

401
402
403
404
405
	if(!create_batchdn_lst((cfg.prot[i]->misc&PROT_NATIVE) ? true:false))
		return(FALSE);
	if(!create_bimodem_pth())
		return(FALSE);

406
407
408
409
410
411
412
413
	xfrprot=i;
	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;
			sprintf(path,"%s%s",cfg.temp_dir,fname);
414
			if(!fexistcase(path)) {
415
416
417
				seqwait(cfg.dir[batdn_dir[i]]->seqdev);
				bprintf(text[RetrievingFile],fname);
				sprintf(str,"%s%s"
418
419
420
421
					,batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths
					? cfg.altpath[batdn_alt[i]-1]
					: cfg.dir[batdn_dir[i]]->path
					,fname);
422
				mv(str,path,1); /* copy the file to temp dir */
423
424
425
426
				if(getnodedat(cfg.node_num,&thisnode,true)==0) {
					thisnode.aux=40; /* clear the seq dev # */
					putnodedat(cfg.node_num,&thisnode);
				}
427
				CRLF; 
428
			} 
429
		}
430
431
432
433
434
435
436
437
438
439
		else
			sprintf(path,"%s%s"
				,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 ' ' */
440
		if((list=(char*)realloc(list,list_len+strlen(path)+1	/* add one for '\0'*/))==NULL) {
441
			errormsg(WHERE,ERR_ALLOC,"list",list_len+strlen(path));
442
			return(FALSE);
443
444
445
446
447
448
449
450
451
452
		}
		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
453
			if(!chk_ar(cfg.dlevent[j]->ar,&useron,&client))
454
455
456
457
458
				continue;
			bputs(cfg.dlevent[j]->workstr);
			external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr,NULL),EX_OUTL);
			CRLF; 
		}
459
	}
460
461
462
463
464
465

	sprintf(str,"%sBATCHDN.LST",cfg.node_dir);
	action=NODE_DLNG;
	t=now;
	if(cur_cps) 
		t+=(totalsize/(ulong)cur_cps);
466
	localtime_r(&t,&tm);
467
468
469
470
471
	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 */
	}
472
	start=time(NULL);
473
	error=protocol(cfg.prot[xfrprot],XFER_BATCH_DOWNLOAD,str,list,false);
474
475
476
477
478
479
480
481
	end=time(NULL);
	if(cfg.prot[xfrprot]->misc&PROT_DSZLOG || !error)
		batch_download(xfrprot);
	if(batdn_total)
		notdownloaded(totalsize,start,end);
	autohangup(); 
	if(list!=NULL)
		free(list);
482
483

	return(TRUE);
484
}
485
486
487
488
489

/****************************************************************************/
/* Creates the file BATCHDN.LST in the node directory. Returns true if      */
/* everything goes okay, false if not.                                      */
/****************************************************************************/
490
bool sbbs_t::create_batchdn_lst(bool native)
491
{
492
493
	char	path[MAX_PATH+1];
	char	fname[MAX_PATH+1];
494
495
496
	int		file;
	uint	i;

497
498
499
	sprintf(path,"%sBATCHDN.LST",cfg.node_dir);
	if((file=nopen(path,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
		errormsg(WHERE,ERR_OPEN,path,O_WRONLY|O_CREAT|O_TRUNC);
500
501
		return(false); 
	}
502
503
	for(i=0;i<batdn_total;i++) {
		if(batdn_dir[i]>=cfg.total_dirs || cfg.dir[batdn_dir[i]]->seqdev)
504
			SAFECOPY(path,cfg.temp_dir);
505
		else
506
			SAFECOPY(path,batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths
507
				? cfg.altpath[batdn_alt[i]-1] : cfg.dir[batdn_dir[i]]->path);
508
509
510
511
512
513
514

		unpadfname(batdn_name[i],fname);
		strcat(path,fname);
		if(native)
			fexistcase(path);
		strcat(path,crlf);
		write(file,path,strlen(path)); 
515
	}
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
	close(file);
	return(true);
}

/****************************************************************************/
/* 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()
{
    char	str[256];
    int		file;
	uint	i;

	sprintf(str,"%sBATCHUP.LST",cfg.node_dir);
	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
534
535
		return(false); 
	}
536
537
538
539
540
541
542
543
544
	for(i=0;i<batup_total;i++) {
		if(batup_dir[i]>=cfg.total_dirs)
			strcpy(str,cfg.temp_dir);
		else
			strcpy(str,batup_alt[i]>0 && batup_alt[i]<=cfg.altpaths
				? cfg.altpath[batup_alt[i]-1] : cfg.dir[batup_dir[i]]->path);
		write(file,str,strlen(str));
		unpadfname(batup_name[i],str);
		strcat(str,crlf);
545
546
		write(file,str,strlen(str)); 
	}
547
548
549
550
551
552
553
554
555
556
557
	close(file);
	return(true);
}

/****************************************************************************/
/* Creates the file BIMODEM.PTH in the node directory. Returns true if      */
/* everything goes okay, false if not.                                      */
/****************************************************************************/
bool sbbs_t::create_bimodem_pth()
{
    char	str[256],tmp2[512];
558
	char 	tmp[512];
559
560
561
562
563
564
    int		file;
	uint	i;

	sprintf(str,"%sBIMODEM.PTH",cfg.node_dir);  /* Create bimodem file */
	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
565
566
		return(false); 
	}
567
568
569
570
571
572
573
	for(i=0;i<batup_total;i++) {
		sprintf(str,"%s%s",batup_dir[i]>=cfg.total_dirs ? cfg.temp_dir
			: batup_alt[i]>0 && batup_alt[i]<=cfg.altpaths
			? cfg.altpath[batup_alt[i]-1] : cfg.dir[batup_dir[i]]->path
			,unpadfname(batup_name[i],tmp));
		sprintf(tmp2,"D       %-80.80s%-160.160s"
			,unpadfname(batup_name[i],tmp),str);
574
575
		write(file,tmp2,248); 
	}
576
577
578
579
580
581
582
	for(i=0;i<batdn_total;i++) {
		sprintf(str,"%s%s"
			,(batdn_dir[i]>=cfg.total_dirs || cfg.dir[batdn_dir[i]]->seqdev)
			? cfg.temp_dir : batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths
				? cfg.altpath[batdn_alt[i]-1] : cfg.dir[batdn_dir[i]]->path
				,unpadfname(batdn_name[i],tmp));
		sprintf(tmp2,"U       %-240.240s",str);
583
584
		write(file,tmp2,248); 
	}
585
586
587
588
589
590
591
592
593
	close(file);
	return(true);
}

/****************************************************************************/
/* Processes files that were supposed to be received in the batch queue     */
/****************************************************************************/
void sbbs_t::batch_upload()
{
594
595
596
    char	str1[MAX_PATH+1],str2[MAX_PATH+1];
	char	path[MAX_PATH+1];
	char 	tmp[MAX_PATH+1];
597
598
	uint	i,j,x,y;
    file_t	f;
599
600
	DIR*	dir;
	DIRENT*	dirent;
601
602
603
604
605
606
607

	for(i=0;i<batup_total;) {
		curdirnum=batup_dir[i]; 			/* for ARS */
		lncntr=0;                               /* defeat pause */
		unpadfname(batup_name[i],tmp);
		sprintf(str1,"%s%s",cfg.temp_dir,tmp);
		sprintf(str2,"%s%s",cfg.dir[batup_dir[i]]->path,tmp);
608
		if(fexistcase(str1) && fexistcase(str2)) { /* file's in two places */
609
610
611
			bprintf(text[FileAlreadyThere],batup_name[i]);
			remove(str1);    /* this is the one received */
			i++;
612
613
			continue; 
		}
614
615
616
617
618
619
620
621
622
623
624
625
626
627
		if(fexist(str1))
			mv(str1,str2,0);
		strcpy(f.name,batup_name[i]);
		strcpy(f.desc,batup_desc[i]);
		f.dir=batup_dir[i];
		f.misc=batup_misc[i];
		f.altpath=batup_alt[i];
		if(uploadfile(&f)) {
			batup_total--;
			for(j=i;j<batup_total;j++) {
				batup_dir[j]=batup_dir[j+1];
				batup_alt[j]=batup_alt[j+1];
				batup_misc[j]=batup_misc[j+1];
				strcpy(batup_name[j],batup_name[j+1]);
628
629
630
631
632
				strcpy(batup_desc[j],batup_desc[j+1]); 
			} 
		}
		else i++; 
	}
633
634
	if(cfg.upload_dir==INVALID_DIR)
		return;
635
	dir=opendir(cfg.temp_dir);
636
	while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
637
638
639
640
641
		sprintf(str1,"%s%s",cfg.temp_dir,dirent->d_name);
		if(isdir(str1))
			continue;
		memset(&f,0,sizeof(file_t));
		f.dir=cfg.upload_dir;
642
643
644
645
646
647
648

		SAFECOPY(path,str1);
#ifdef _WIN32
		GetShortPathName(str1, path, sizeof(path));
#endif
		padfname(getfname(path),f.name);

649
650
651
652
653
654
655
		for(x=0;x<usrlibs;x++) {
			for(y=0;y<usrdirs[x];y++)
				if(cfg.dir[usrdir[x][y]]->misc&DIR_DUPES
					&& findfile(&cfg,usrdir[x][y],f.name))
					break;
			if(y<usrdirs[x])
				break; 
656
		}
657
		sprintf(str2,"%s%s",cfg.dir[f.dir]->path,dirent->d_name);
658
		if(x<usrlibs || fexistcase(str2)) {
659
660
661
662
663
664
665
			bprintf(text[FileAlreadyOnline],f.name);
			remove(str1); 
		} else {
			mv(str1,str2,0);
			uploadfile(&f); 
		}
	}
666
667
	if(dir!=NULL)
		closedir(dir);
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
}

/****************************************************************************/
/* 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)
{
    uint	i,j;
    file_t	f;

	for(i=0;i<batdn_total;) {
		lncntr=0;                               /* defeat pause */
		f.dir=curdirnum=batdn_dir[i];
		strcpy(f.name,batdn_name[i]);
		f.datoffset=batdn_offset[i];
		f.size=batdn_size[i];
		f.altpath=batdn_alt[i];
686
		if(xfrprot==-1 || checkprotresult(cfg.prot[xfrprot],0,&f)) {
687
688
689
690
691
692
693
694
695
696
697
			if(cfg.dir[f.dir]->misc&DIR_TFREE && cur_cps)
				starttime+=f.size/(ulong)cur_cps;
			downloadfile(&f);
			closefile(&f);
			batdn_total--;
			for(j=i;j<batdn_total;j++) {
				strcpy(batdn_name[j],batdn_name[j+1]);
				batdn_dir[j]=batdn_dir[j+1];
				batdn_cdt[j]=batdn_cdt[j+1];
				batdn_alt[j]=batdn_alt[j+1];
				batdn_size[j]=batdn_size[j+1];
698
699
700
701
702
				batdn_offset[j]=batdn_offset[j+1]; 
			} 
		}
		else i++; 
	}
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
}

/****************************************************************************/
/* Adds a list of files to the batch download queue 						*/
/****************************************************************************/
void sbbs_t::batch_add_list(char *list)
{
    char	str[128];
	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;
			if(!fgets(str,127,stream))
				break;
			truncsp(str);
			sprintf(f.name,"%.12s",str);
			lncntr=0;
727
			for(i=j=k=0;i<usrlibs;i++) {
728
729
730
731
732
				for(j=0;j<usrdirs[i];j++,k++) {
					outchar('.');
					if(k && !(k%5))
						bputs("\b\b\b\b\b     \b\b\b\b\b");
					if(findfile(&cfg,usrdir[i][j],f.name))
733
734
						break; 
				}
735
				if(j<usrdirs[i])
736
737
					break; 
			}
738
739
740
741
742
743
744
745
			if(i<usrlibs) {
				f.dir=usrdir[i][j];
				getfileixb(&cfg,&f);
				f.size=0;
				getfiledat(&cfg,&f);
				if(f.size==-1L)
					bprintf(text[FileIsNotOnline],f.name);
				else
746
747
748
					addtobatdl(&f); 
			} 
		}
749
750
		fclose(stream);
		remove(list);
751
752
		CRLF; 
	}
753
}
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
/****************************************************************************/
void sbbs_t::batch_create_list()
{
	char	str[MAX_PATH+1];
	int		i;
	FILE*	stream;

	if(batdn_total) {
		sprintf(str,"%sfile/%04u.dwn",cfg.data_dir,useron.number);
		if((stream=fnopen(NULL,str,O_WRONLY|O_TRUNC|O_CREAT))!=NULL) {
			for(i=0;i<(int)batdn_total;i++)
				fprintf(stream,"%s\r\n",batdn_name[i]);
			fclose(stream); 
		} 
	}
}
770
771
772
773
774
775

/**************************************************************************/
/* Add file 'f' to batch download queue. Return 1 if successful, 0 if not */
/**************************************************************************/
bool sbbs_t::addtobatdl(file_t* f)
{
776
777
778
779
    char	str[256],tmp2[256];
	char 	tmp[512];
    uint	i;
	ulong	totalcdt, totalsize, totaltime;
780
781
782

	if(useron.rest&FLAG('D')) {
		bputs(text[R_Download]);
783
784
		return(false); 
	}
785
786
787
	for(i=0;i<batdn_total;i++) {
		if(!strcmp(batdn_name[i],f->name) && f->dir==batdn_dir[i]) {
			bprintf(text[FileAlreadyInQueue],f->name);
788
789
790
			return(false); 
		} 
	}
791
792
	if(f->size<=0 /* !fexist(str) */) {
		bprintf(text[CantAddToQueue],f->name);
793
		bprintf(text[FileIsNotOnline],f->name);
794
795
		return(false); 
	}
796
797
798
	if(batdn_total>=cfg.max_batdn) {
		bprintf(text[CantAddToQueue],f->name);
		bputs(text[BatchDlQueueIsFull]);
799
800
		return(false); 
	}
801
	for(i=0,totalcdt=0;i<batdn_total;i++)
rswindell's avatar
rswindell committed
802
		if(!is_download_free(&cfg,batdn_dir[i],&useron,&client))
803
			totalcdt+=batdn_cdt[i];
804
	if(cfg.dir[f->dir]->misc&DIR_FREE) f->cdt=0L;
rswindell's avatar
rswindell committed
805
	if(!is_download_free(&cfg,f->dir,&useron,&client))
806
807
		totalcdt+=f->cdt;
	if(totalcdt>useron.cdt+useron.freecdt) {
808
809
		bprintf(text[CantAddToQueue],f->name);
		bprintf(text[YouOnlyHaveNCredits],ultoac(useron.cdt+useron.freecdt,tmp));
810
811
		return(false); 
	}
rswindell's avatar
rswindell committed
812
	if(!chk_ar(cfg.dir[f->dir]->dl_ar,&useron,&client)) {
813
814
		bprintf(text[CantAddToQueue],f->name);
		bputs(text[CantDownloadFromDir]);
815
816
		return(false); 
	}
817
818
819
	for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
		totalsize+=batdn_size[i];
		if(!(cfg.dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
820
821
			totaltime+=batdn_size[i]/(ulong)cur_cps; 
	}
822
823
824
825
826
827
	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]);
828
829
		return(false); 
	}
830
831
832
833
834
835
836
837
838
839
840
841
842
843
	strcpy(batdn_name[batdn_total],f->name);
	batdn_dir[batdn_total]=f->dir;
	batdn_cdt[batdn_total]=f->cdt;
	batdn_offset[batdn_total]=f->datoffset;
	batdn_size[batdn_total]=f->size;
	batdn_alt[batdn_total]=f->altpath;
	batdn_total++;
	openfile(f);
	bprintf(text[FileAddedToBatDlQueue]
		,f->name,batdn_total,cfg.max_batdn,ultoac(totalcdt,tmp)
		,ultoac(totalsize,tmp2)
		,sectostr(totalsize/(ulong)cur_cps,str));
	return(true);
}