bat_xfer.cpp 24.8 KB
Newer Older
1
2
3
4
/* bat_xfer.cpp */

/* Synchronet batch file transfer functions */

5
/* $Id: bat_xfer.cpp,v 1.41 2020/05/13 23:56:08 rswindell Exp $ */
6
7
8
9
10

/****************************************************************************
 * @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
		SAFEPRINTF(keys,"BCDLRU?\r%c", text[YNQP][2]);
75
		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
				SAFEPRINTF(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
					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);
154
							SAFEPRINTF2(tmp2,"%s%s",cfg.temp_dir,tmp);
155
							if(!fexistcase(tmp2)) {
156
157
								seqwait(cfg.dir[batdn_dir[i]]->seqdev);
								bprintf(text[RetrievingFile],tmp);
158
								SAFEPRINTF2(str,"%s%s"
159
160
161
162
163
									,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
					SAFEPRINTF(str,"%sBATCHDN.LST",cfg.node_dir);
					SAFEPRINTF(tmp2,"%sBATCHUP.LST",cfg.node_dir);
173
					start=time(NULL);
174
					protocol(cfg.prot[xfrprot],XFER_BIDIR,str,tmp2,true);
175
176
177
178
					end=time(NULL);
					for(i=0;i<batdn_total;i++)
						if(cfg.dir[batdn_dir[i]]->seqdev) {
							unpadfname(batdn_name[i],tmp);
179
							SAFEPRINTF2(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
						for(i=0;i<batdn_total;i++) {
							f.dir=batdn_dir[i];
							f.datoffset=batdn_offset[i];
							f.size=batdn_size[i];
202
							SAFECOPY(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
						n--;
						f.dir=batdn_dir[n];
263
						SAFECOPY(f.name,batdn_name[n]);
264
265
266
267
268
269
270
271
272
273
274
						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
				SAFEPRINTF(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
						break;
				if(i<cfg.total_prots) {
312
					SAFEPRINTF(str,"%sBATCHUP.LST",cfg.node_dir);
313
314
315
316
317
318
319
320
					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
	SAFEPRINTF(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
	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;
415
			SAFEPRINTF2(path,"%s%s",cfg.temp_dir,fname);
416
			if(!fexistcase(path)) {
417
418
				seqwait(cfg.dir[batdn_dir[i]]->seqdev);
				bprintf(text[RetrievingFile],fname);
419
				SAFEPRINTF2(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
		else
433
			SAFEPRINTF2(path,"%s%s"
434
435
436
437
438
439
440
441
				,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
443
444
		char* np;
		if((np=(char*)realloc(list,list_len+strlen(path)+1	/* add one for '\0'*/))==NULL) {
			free(list);
445
			errormsg(WHERE,ERR_ALLOC,"list",list_len+strlen(path));
446
			return(FALSE);
447
		}
448
		list = np;
449
450
451
452
453
454
455
456
457
		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
458
			if(!chk_ar(cfg.dlevent[j]->ar,&useron,&client))
459
460
461
462
463
				continue;
			bputs(cfg.dlevent[j]->workstr);
			external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr,NULL),EX_OUTL);
			CRLF; 
		}
464
	}
465

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

	return(TRUE);
489
}
490
491
492
493
494

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

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

		unpadfname(batdn_name[i],fname);
515
		SAFECAT(path,fname);
516
517
		if(native)
			fexistcase(path);
518
		SAFECAT(path,crlf);
519
		write(file,path,strlen(path)); 
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;

536
	SAFEPRINTF(str,"%sBATCHUP.LST",cfg.node_dir);
537
538
	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
539
540
		return(false); 
	}
541
542
	for(i=0;i<batup_total;i++) {
		if(batup_dir[i]>=cfg.total_dirs)
543
			SAFECOPY(str,cfg.temp_dir);
544
		else
545
			SAFECOPY(str,batup_alt[i]>0 && batup_alt[i]<=cfg.altpaths
546
547
548
549
				? 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);
550
551
		write(file,str,strlen(str)); 
	}
552
553
554
555
556
557
558
559
560
561
562
	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];
563
	char 	tmp[512];
564
565
566
    int		file;
	uint	i;

567
	SAFEPRINTF(str,"%sBIMODEM.PTH",cfg.node_dir);  /* Create bimodem file */
568
569
	if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
		errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
570
571
		return(false); 
	}
572
	for(i=0;i<batup_total;i++) {
573
		SAFEPRINTF2(str,"%s%s",batup_dir[i]>=cfg.total_dirs ? cfg.temp_dir
574
575
576
			: 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));
577
		SAFEPRINTF2(tmp2,"D       %-80.80s%-160.160s"
578
			,unpadfname(batup_name[i],tmp),str);
579
580
		write(file,tmp2,248); 
	}
581
	for(i=0;i<batdn_total;i++) {
582
		SAFEPRINTF2(str,"%s%s"
583
584
585
586
			,(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));
587
		SAFEPRINTF(tmp2,"U       %-240.240s",str);
588
589
		write(file,tmp2,248); 
	}
590
591
592
593
594
595
596
597
598
	close(file);
	return(true);
}

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

	for(i=0;i<batup_total;) {
		curdirnum=batup_dir[i]; 			/* for ARS */
		lncntr=0;                               /* defeat pause */
		unpadfname(batup_name[i],tmp);
611
612
		SAFEPRINTF2(str1,"%s%s",cfg.temp_dir,tmp);
		SAFEPRINTF2(str2,"%s%s",cfg.dir[batup_dir[i]]->path,tmp);
613
		if(fexistcase(str1) && fexistcase(str2)) { /* file's in two places */
614
615
616
			bprintf(text[FileAlreadyThere],batup_name[i]);
			remove(str1);    /* this is the one received */
			i++;
617
618
			continue; 
		}
619
620
		if(fexist(str1))
			mv(str1,str2,0);
621
622
		SAFECOPY(f.name,batup_name[i]);
		SAFECOPY(f.desc,batup_desc[i]);
623
624
625
626
627
628
629
630
631
632
		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]);
633
634
635
636
637
				strcpy(batup_desc[j],batup_desc[j+1]); 
			} 
		}
		else i++; 
	}
638
639
	if(cfg.upload_dir==INVALID_DIR)
		return;
640
	dir=opendir(cfg.temp_dir);
641
	while(dir!=NULL && (dirent=readdir(dir))!=NULL) {
rswindell's avatar
rswindell committed
642
643
644
		SAFEPRINTF2(tmp,"%s%s",cfg.temp_dir,dirent->d_name);
		if(isdir(tmp))
			continue;
645
646
		memset(&f,0,sizeof(file_t));
		f.dir=cfg.upload_dir;
rswindell's avatar
rswindell committed
647
648
649
650
651
652
		SAFEPRINTF2(path,"%s%s",cfg.dir[f.dir]->path,dirent->d_name);
		if(fexistcase(path)) {
			bprintf(text[FileAlreadyOnline], dirent->d_name);
			continue;
		}
		if(mv(tmp, path, /* copy: */false))
653
			continue;
654
655

#ifdef _WIN32
rswindell's avatar
rswindell committed
656
		GetShortPathName(path, tmp, sizeof(tmp));
657
#endif
rswindell's avatar
rswindell committed
658
		padfname(getfname(tmp),f.name);
659

660
661
662
663
664
665
666
		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; 
667
		}
rswindell's avatar
rswindell committed
668
		if(x<usrlibs) {
669
670
671
672
673
			bprintf(text[FileAlreadyOnline],f.name);
		} else {
			uploadfile(&f); 
		}
	}
674
675
	if(dir!=NULL)
		closedir(dir);
676
677
678
679
680
681
682
683
684
685
686
687
688
689
}

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

/****************************************************************************/
/* 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;
732
			truncnl(str);
733
734
			sprintf(f.name,"%.12s",str);
			lncntr=0;
735
			for(i=j=k=0;i<usrlibs;i++) {
736
737
738
739
740
				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))
741
742
						break; 
				}
743
				if(j<usrdirs[i])
744
745
					break; 
			}
746
747
748
749
750
751
752
753
			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
754
755
756
					addtobatdl(&f); 
			} 
		}
757
758
		fclose(stream);
		remove(list);
759
760
		CRLF; 
	}
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) {
770
		SAFEPRINTF2(str,"%sfile/%04u.dwn",cfg.data_dir,useron.number);
771
772
773
774
775
776
777
		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); 
		} 
	}
}
778
779
780
781
782
783

/**************************************************************************/
/* Add file 'f' to batch download queue. Return 1 if successful, 0 if not */
/**************************************************************************/
bool sbbs_t::addtobatdl(file_t* f)
{
784
785
786
787
    char	str[256],tmp2[256];
	char 	tmp[512];
    uint	i;
	ulong	totalcdt, totalsize, totaltime;
788
789
790

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