bat_xfer.cpp 24.5 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 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
    char	str[129],tmp2[250],done=0,ch;
	char 	tmp[512];
47
	char	keys[32];
48
49
50
51
	uint	i,n,xfrprot,xfrdir;
    ulong	totalcdt,totalsize,totaltime;
    time_t	start,end;
    file_t	f;
52
53
54

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

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

/****************************************************************************/
/* Download files from batch queue                                          */
/****************************************************************************/
341
BOOL sbbs_t::start_batch_download()
342
{
343
344
345
346
347
348
349
350
	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;
351
352
353
354
    int		j;
    uint	i,xfrprot;
    ulong	totalcdt,totalsize,totaltime;
    time_t	start,end,t;
355
	struct	tm tm;
356

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

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

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

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

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

	return(TRUE);
486
}
487
488
489
490
491

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

499
500
501
	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);
502
503
		return(false); 
	}
504
505
	for(i=0;i<batdn_total;i++) {
		if(batdn_dir[i]>=cfg.total_dirs || cfg.dir[batdn_dir[i]]->seqdev)
506
			SAFECOPY(path,cfg.temp_dir);
507
		else
508
			SAFECOPY(path,batdn_alt[i]>0 && batdn_alt[i]<=cfg.altpaths
509
				? cfg.altpath[batdn_alt[i]-1] : cfg.dir[batdn_dir[i]]->path);
510
511

		unpadfname(batdn_name[i],fname);
512
		SAFECAT(path,fname);
513
514
		if(native)
			fexistcase(path);
515
		SAFECAT(path,crlf);
516
		write(file,path,strlen(path)); 
517
	}
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
	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);
536
537
		return(false); 
	}
538
539
540
541
542
543
544
545
546
	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);
547
548
		write(file,str,strlen(str)); 
	}
549
550
551
552
553
554
555
556
557
558
559
	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];
560
	char 	tmp[512];
561
562
563
564
565
566
    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);
567
568
		return(false); 
	}
569
570
571
572
573
574
575
	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);
576
577
		write(file,tmp2,248); 
	}
578
579
580
581
582
583
584
	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);
585
586
		write(file,tmp2,248); 
	}
587
588
589
590
591
592
593
594
595
	close(file);
	return(true);
}

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

	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);
610
		if(fexistcase(str1) && fexistcase(str2)) { /* file's in two places */
611
612
613
			bprintf(text[FileAlreadyThere],batup_name[i]);
			remove(str1);    /* this is the one received */
			i++;
614
615
			continue; 
		}
616
617
618
619
620
621
622
623
624
625
626
627
628
629
		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]);
630
631
632
633
634
				strcpy(batup_desc[j],batup_desc[j+1]); 
			} 
		}
		else i++; 
	}
635
636
	if(cfg.upload_dir==INVALID_DIR)
		return;
637
	dir=opendir(cfg.temp_dir);
638
	while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
639
640
641
642
643
		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;
644
645
646
647
648
649
650

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

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

/****************************************************************************/
/* 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];
688
		if(xfrprot==-1 || checkprotresult(cfg.prot[xfrprot],0,&f)) {
689
690
691
692
693
694
695
696
697
698
699
			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];
700
701
702
703
704
				batdn_offset[j]=batdn_offset[j+1]; 
			} 
		}
		else i++; 
	}
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
}

/****************************************************************************/
/* 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;
726
			truncnl(str);
727
728
			sprintf(f.name,"%.12s",str);
			lncntr=0;
729
			for(i=j=k=0;i<usrlibs;i++) {
730
731
732
733
734
				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))
735
736
						break; 
				}
737
				if(j<usrdirs[i])
738
739
					break; 
			}
740
741
742
743
744
745
746
747
			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
748
749
750
					addtobatdl(&f); 
			} 
		}
751
752
		fclose(stream);
		remove(list);
753
754
		CRLF; 
	}
755
}
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
/****************************************************************************/
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); 
		} 
	}
}
772
773
774
775
776
777

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

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