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

/* Synchronet file upload-related routines */

/* $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 2006 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
45
46
47
 *																			*
 * 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"

/****************************************************************************/
/* Adds file data in 'f' to DIR#.DAT and DIR#.IXB   and updates user        */
/* info for uploader. Must have .name, .desc and .dir fields filled prior   */
/* to a call to this function.                                              */
/* Returns 1 if file uploaded sucessfully, 0 if not.                        */
/****************************************************************************/
bool sbbs_t::uploadfile(file_t *f)
{
48
49
50
51
52
53
54
55
56
	char	path[MAX_PATH+1];
	char	str[MAX_PATH+1],fname[25];
	char	ext[F_EXBSIZE+1];
	char	desc[F_EXBSIZE+1];
	char	tmp[MAX_PATH+1];
	int		file;
    uint	i;
    long	length;
	FILE*	stream;
57

58
	// f->misc=0; Removed AUG-22-2001 - broken anonymous uploads
59
60
61
	curdirnum=f->dir;
	if(findfile(&cfg,f->dir,f->name)) {
		errormsg(WHERE,ERR_CHK,f->name,f->dir);
62
63
		return(0); 
	}
64
65
66
	sprintf(path,"%s%s",f->altpath>0 && f->altpath<=cfg.altpaths
		? cfg.altpath[f->altpath-1]
		: cfg.dir[f->dir]->path,unpadfname(f->name,fname));
67
	sprintf(tmp,"%s%s",cfg.temp_dir,fname);
68
	if(!fexistcase(path) && fexistcase(tmp))
69
		mv(tmp,path,0);
70
	if(!fexistcase(path)) {
71
		bprintf(text[FileNotReceived],f->name);
72
73
74
		sprintf(str,"%s attempted to upload %s to %s %s (Not received)"
			,useron.alias
			,f->name
75
76
			,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
		logline("U!",str);
77
78
		return(0); 
	}
79
80
81
	strcpy(tmp,f->name);
	truncsp(tmp);
	for(i=0;i<cfg.total_ftests;i++)
82
		if(cfg.ftest[i]->ext[0]=='*' || !stricmp(tmp+9,cfg.ftest[i]->ext)) {
83
84
85
86
87
			if(!chk_ar(cfg.ftest[i]->ar,&useron))
				continue;
			attr(LIGHTGRAY);
			bputs(cfg.ftest[i]->workstr);

88
			sprintf(sbbsfilename,"SBBSFILENAME=%.64s",unpadfname(f->name,fname));
89
90
91
			putenv(sbbsfilename);
			sprintf(sbbsfiledesc,"SBBSFILEDESC=%.*s",LEN_FDESC,f->desc);
			putenv(sbbsfiledesc);
92
			sprintf(str,"%ssbbsfile.nam",cfg.node_dir);
93
94
			if((stream=fopen(str,"w"))!=NULL) {
				fwrite(fname,1,strlen(fname),stream);
95
96
				fclose(stream); 
			}
97
			sprintf(str,"%ssbbsfile.des",cfg.node_dir);
98
99
			if((stream=fopen(str,"w"))!=NULL) {
				fwrite(f->desc,1,strlen(f->desc),stream);
100
101
				fclose(stream); 
			}
102
			if(external(cmdstr(cfg.ftest[i]->cmd,path,f->desc,NULL),EX_OFFLINE)) {
103
104
105
				sprintf(str,"%s attempted to upload %s to %s %s (%s Errors)"
					,useron.alias
					,f->name
106
107
					,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname,cfg.ftest[i]->ext);
				logline("U!",str);
108
109
110
111
112
113
114
#if 0
				sprintf(str,"Failed test: %s", cmdstr(cfg.ftest[i]->cmd,path,f->desc,NULL));
				logline("  ",str);
#endif
				bprintf(text[FileHadErrors],f->name,cfg.ftest[i]->ext);
				if(!SYSOP || yesno(text[DeleteFileQ]))
					remove(path);
115
116
				return(0); 
			} else {
117
				sprintf(str,"%ssbbsfile.nam",cfg.node_dir);
118
119
120
121
122
123
124
125
				if((stream=fopen(str,"r"))!=NULL) {
					if(fgets(str,128,stream)) {
						truncsp(str);
						padfname(str,f->name);
						strcpy(tmp,f->name);
						truncsp(tmp);
						sprintf(path,"%s%s",f->altpath>0 && f->altpath<=cfg.altpaths
							? cfg.altpath[f->altpath-1] : cfg.dir[f->dir]->path
126
127
							,unpadfname(f->name,fname)); 
					}
128
129
					fclose(stream);
					}
130
				sprintf(str,"%ssbbsfile.des",cfg.node_dir);
131
132
133
				if((stream=fopen(str,"r"))!=NULL) {
					if(fgets(str,128,stream)) {
						truncsp(str);
134
135
136
137
138
139
140
						sprintf(f->desc,"%.*s",LEN_FDESC,str); 
					}
					fclose(stream); 
				}
				CRLF; 
			} 
		}
141
142
143
144

	if((length=flength(path))<=0L) {
		bprintf(text[FileZeroLength],f->name);
		remove(path);
145
146
147
		sprintf(str,"%s attempted to upload %s to %s %s (Zero length)"
			,useron.alias
			,f->name
148
149
			,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
		logline("U!",str);
150
151
		return(0); 
	}
152
153
154
155
156
157
	if(cfg.dir[f->dir]->misc&DIR_DIZ) {
		for(i=0;i<cfg.total_fextrs;i++)
			if(!stricmp(cfg.fextr[i]->ext,tmp+9) && chk_ar(cfg.fextr[i]->ar,&useron))
				break;
		if(i<cfg.total_fextrs) {
			sprintf(str,"%sFILE_ID.DIZ",cfg.temp_dir);
158
159
			if(fexistcase(str))
				remove(str);
160
			external(cmdstr(cfg.fextr[i]->cmd,path,"FILE_ID.DIZ",NULL),EX_OFFLINE);
161
			if(!fexistcase(str)) {
162
				sprintf(str,"%sDESC.SDI",cfg.temp_dir);
163
164
				if(fexistcase(str))
					remove(str);
165
				external(cmdstr(cfg.fextr[i]->cmd,path,"DESC.SDI",NULL),EX_OFFLINE); 
166
167
				fexistcase(str);
			}
168
			if((file=nopen(str,O_RDONLY))!=-1) {
169
170
171
				memset(ext,0,F_EXBSIZE+1);
				read(file,ext,F_EXBSIZE);
				for(i=F_EXBSIZE;i;i--)
172
					if(ext[i-1]>' ')
173
174
175
176
177
						break;
				ext[i]=0;
				if(!f->desc[0]) {
					strcpy(desc,ext);
					strip_exascii(desc);
178
					prep_file_desc(desc);
179
180
181
					for(i=0;desc[i];i++)
						if(isalnum(desc[i]))
							break;
182
183
					sprintf(f->desc,"%.*s",LEN_FDESC,desc+i); 
				}
184
185
				close(file);
				remove(str);
186
187
188
189
				f->misc|=FM_EXTDESC; 
			} 
		} 
	}
190

191
192
193
194
	if(!(cfg.dir[f->dir]->misc&DIR_NOSTAT)) {
		logon_ulb+=length;  /* Update 'this call' stats */
		logon_uls++;
	}
195
196
197
198
199
200
201
202
203
	if(cfg.dir[f->dir]->misc&DIR_AONLY)  /* Forced anonymous */
		f->misc|=FM_ANON;
	f->cdt=length;
	f->dateuled=time(NULL);
	f->timesdled=0;
	f->datedled=0L;
	f->opencount=0;
	strcpy(f->uler,useron.alias);
	bprintf(text[FileNBytesReceived],f->name,ultoac(length,tmp));
204
205
206
207
208
209
	if(!f->desc[0]) {
		if(stricmp(f->name,getfname(path)))
			SAFECOPY(f->desc,getfname(path));
		else
			sprintf(f->desc,"%.*s",LEN_FDESC,text[NoDescription]);
	}
210
211
212
213
	if(!addfiledat(&cfg,f))
		return(0);

	if(f->misc&FM_EXTDESC)
214
		putextdesc(&cfg,f->dir,f->datoffset,ext);
215

216
217
218
	sprintf(str,"%s uploaded %s to %s %s"
		,useron.alias
		,f->name,cfg.lib[cfg.dir[f->dir]->lib]->sname
219
220
		,cfg.dir[f->dir]->sname);
	if(cfg.dir[f->dir]->upload_sem[0])
221
		ftouch(cmdstr(cfg.dir[f->dir]->upload_sem,nulstr,nulstr,NULL));
222
223
224
225
	logline("U+",str);
	/**************************/
	/* Update Uploader's Info */
	/**************************/
226
	user_uploaded(&cfg, &useron, 1, length);
227
228
229
230
231
232
	if(cfg.dir[f->dir]->up_pct && cfg.dir[f->dir]->misc&DIR_CDTUL) { /* credit for upload */
		if(cfg.dir[f->dir]->misc&DIR_CDTMIN && cur_cps)    /* Give min instead of cdt */
			useron.min=adjustuserrec(&cfg,useron.number,U_MIN,10
				,((ulong)(length*(cfg.dir[f->dir]->up_pct/100.0))/cur_cps)/60);
		else
			useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT,10
233
234
235
236
				,(ulong)(f->cdt*(cfg.dir[f->dir]->up_pct/100.0))); 
	}

	user_event(EVENT_UPLOAD);
237
238
239
240
241
242
243

	return(true);
}

/****************************************************************************/
/* Uploads files                                                            */
/****************************************************************************/
244
bool sbbs_t::upload(uint dirnum)
245
{
246
	char	descbeg[25]={""},descend[25]={""}
247
				,fname[13],keys[256],ch,*p;
248
249
250
	char	str[MAX_PATH+1];
	char	path[MAX_PATH+1];
	char	spath[MAX_PATH+1];
251
	char 	tmp[512];
252
253
254
255
256
257
258
259
    time_t	start,end;
    uint	i,j,k,destuser[MAX_USERXFER],destusers=0;
	int		file;
	ulong	space;
    file_t	f;
    user_t	user;
    node_t	node;

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
	/* Security Checks */
	if(useron.rest&FLAG('U')) {
		bputs(text[R_Upload]);
		return(false); 
	}
	if(dirnum==INVALID_DIR) {
		bputs(text[CantUploadHere]);
		return(false);
	}
	if(!chk_ar(cfg.dir[dirnum]->ul_ar,&useron)) {
		bputs(dirnum==cfg.user_dir ? text[CantUploadToUser] : 
			dirnum==cfg.sysop_dir ? text[CantUploadToSysop] : text[CantUploadHere]);
		return(false); 
	}
	if(getfiles(&cfg,dirnum)>=cfg.dir[dirnum]->maxfiles) {
		bputs(dirnum==cfg.user_dir ? text[UserDirFull] : text[DirFull]);
		return(false);
	}

279
280
281
282
283
284
285
286
287
	if(sys_status&SS_EVENT && online==ON_REMOTE && !dir_op(dirnum))
		bprintf(text[UploadBeforeEvent],timeleft/60);
	if(altul)
		strcpy(path,cfg.altpath[altul-1]);
	else
		strcpy(path,cfg.dir[dirnum]->path);


	/* get free disk space */
288
289
	space=getfreediskspace(path,1024);
	if(space<(ulong)cfg.min_dspace) {
290
		bputs(text[LowDiskSpace]);
291
		sprintf(str,"Diskspace is low: %s (%lu kilobytes)",path,space);
292
293
		errorlog(str);
		if(!dir_op(dirnum))
294
295
			return(false); 
	}
296
297
298
299
300
301
	bprintf(text[DiskNBytesFree],ultoac(space,tmp));

	f.dir=curdirnum=dirnum;
	f.misc=0;
	f.altpath=altul;
	bputs(text[Filename]);
302
	if(!getstr(fname,12,0) || strchr(fname,'?') || strchr(fname,'*')
303
		|| !checkfname(fname) || (trashcan(fname,"file") && !dir_op(dirnum))) {
304
305
		if(fname[0])
			bputs(text[BadFilename]);
306
307
		return(false); 
	}
308
309
310
311
312
313
314
	if(dirnum==cfg.sysop_dir)
		sprintf(str,text[UploadToSysopDirQ],fname);
	else if(dirnum==cfg.user_dir)
		sprintf(str,text[UploadToUserDirQ],fname);
	else
		sprintf(str,text[UploadToCurDirQ],fname,cfg.lib[cfg.dir[dirnum]->lib]->sname
			,cfg.dir[dirnum]->sname);
315
	if(!yesno(str)) return(false);
316
317
	action=NODE_ULNG;
	sprintf(str,"%s%s",path,fname);
318
	if(fexistcase(str)) {   /* File is on disk */
319
320
321
322
323
324
#ifdef _WIN32
		GetShortPathName(str, spath, sizeof(spath));
#else
		SAFECOPY(spath,str);
#endif
		SAFECOPY(fname,getfname(spath));
325
326
		if(!dir_op(dirnum) && online!=ON_LOCAL) {		 /* local users or sysops */
			bprintf(text[FileAlreadyThere],fname);
327
328
			return(false); 
		}
329
		if(!yesno(text[FileOnDiskAddQ]))
330
331
			return(false); 
	}
332
	padfname(fname,f.name);
333
334
335
336
337
338
339
340
341
	strcpy(str,cfg.dir[dirnum]->exts);
	strcpy(tmp,f.name);
	truncsp(tmp);
	j=strlen(str);
	for(i=0;i<j;i+=ch+1) { /* Check extension of upload with allowable exts */
		p=strchr(str+i,',');
		if(p!=NULL)
			*p=0;
		ch=strlen(str+i);
342
		if(!stricmp(tmp+9,str+i))
343
344
			break; 
	}
345
346
347
348
	if(j && i>=j) {
		bputs(text[TheseFileExtsOnly]);
		bputs(cfg.dir[dirnum]->exts);
		CRLF;
349
350
		if(!dir_op(dirnum)) return(false); 
	}
351
	bputs(text[SearchingForDupes]);
352
353
354
355
356
	if(findfile(&cfg,dirnum,f.name)) {
		bputs(text[SearchedForDupes]);
		bprintf(text[FileAlreadyOnline],fname);
		return(false); 	 /* File is already in database */
	}
357
	for(i=k=0;i<usrlibs;i++) {
358
359
360
361
		for(j=0;j<usrdirs[i];j++,k++) {
			outchar('.');
			if(k && !(k%5))
				bputs("\b\b\b\b\b     \b\b\b\b\b");
362
363
364
			if(usrdir[i][j]==dirnum)
				continue;	/* we already checked this dir */
			if(cfg.dir[usrdir[i][j]]->misc&DIR_DUPES
365
366
				&& findfile(&cfg,usrdir[i][j],f.name)) {
				bputs(text[SearchedForDupes]);
367
				bprintf(text[FileAlreadyOnline],fname);
368
				if(!dir_op(dirnum))
369
					return(false); 	 /* File is in database for another dir */
370
371
372
			}
		}
	}
373
374
375
376
377
	bputs(text[SearchedForDupes]);
	if(dirnum==cfg.user_dir) {  /* User to User transfer */
		bputs(text[EnterAfterLastDestUser]);
		while((!dir_op(dirnum) && destusers<cfg.max_userxfer) || destusers<MAX_USERXFER) {
			bputs(text[SendFileToUser]);
378
			if(!getstr(str,LEN_ALIAS,cfg.uq&UQ_NOUPRLWR ? K_NONE:K_UPRLWR))
379
380
381
382
				break;
			if((user.number=finduser(str))!=0) {
				if(!dir_op(dirnum) && user.number==useron.number) {
					bputs(text[CantSendYourselfFiles]);
383
384
					continue; 
				}
385
386
387
388
389
				for(i=0;i<destusers;i++)
					if(user.number==destuser[i])
						break;
				if(i<destusers) {
					bputs(text[DuplicateUser]);
390
391
					continue; 
				}
392
393
394
395
				getuserdat(&cfg,&user);
				if((user.rest&(FLAG('T')|FLAG('D')))
					|| !chk_ar(cfg.lib[cfg.dir[cfg.user_dir]->lib]->ar,&user)
					|| !chk_ar(cfg.dir[cfg.user_dir]->dl_ar,&user)) {
396
397
					bprintf(text[UserWontBeAbleToDl],user.alias); 
				} else {
398
					bprintf(text[UserAddedToDestList],user.alias);
399
400
401
					destuser[destusers++]=user.number; 
				} 
			}
402
			else {
403
404
405
				CRLF; 
			} 
		}
406
		if(!destusers)
407
408
			return(false); 
	}
409
410
411
412
413
	if(cfg.dir[dirnum]->misc&DIR_RATE) {
		SYNC;
		bputs(text[RateThisFile]);
		ch=getkey(K_ALPHA);
		if(!isalpha(ch) || sys_status&SS_ABORT)
414
			return(false);
415
		CRLF;
416
417
		sprintf(descbeg,text[Rated],toupper(ch)); 
	}
418
419
420
421
422
	if(cfg.dir[dirnum]->misc&DIR_ULDATE) {
		now=time(NULL);
		if(descbeg[0])
			strcat(descbeg," ");
		sprintf(str,"%s  ",unixtodstr(&cfg,now,tmp));
423
424
		strcat(descbeg,str); 
	}
425
426
427
428
	if(cfg.dir[dirnum]->misc&DIR_MULT) {
		SYNC;
		if(!noyes(text[MultipleDiskQ])) {
			bputs(text[HowManyDisksTotal]);
429
			if((int)(i=getnum(99))<2)
430
				return(false);
431
			bputs(text[NumberOfFile]);
432
			if((int)(j=getnum(i))<1)
433
				return(false);
434
435
436
437
438
			if(j==1)
				upload_lastdesc[0]=0;
			if(i>9)
				sprintf(descend,text[FileOneOfTen],j,i);
			else
439
440
441
442
				sprintf(descend,text[FileOneOfTwo],j,i); 
		} else
			upload_lastdesc[0]=0; 
	}
443
444
445
446
447
448
	else
		upload_lastdesc[0]=0;
	bputs(text[EnterDescNow]);
	i=LEN_FDESC-(strlen(descbeg)+strlen(descend));
	getstr(upload_lastdesc,i,K_LINE|K_EDIT|K_AUTODEL);
	if(sys_status&SS_ABORT)
449
		return(false);
450
451
452
453
454
455
456
457
	if(descend[0])      /* end of desc specified, so pad desc with spaces */
		sprintf(f.desc,"%s%-*s%s",descbeg,i,upload_lastdesc,descend);
	else                /* no end specified, so string ends at desc end */
		sprintf(f.desc,"%s%s",descbeg,upload_lastdesc);

	if(cfg.dir[dirnum]->misc&DIR_ANON && !(cfg.dir[dirnum]->misc&DIR_AONLY)
		&& (dir_op(dirnum) || useron.exempt&FLAG('A'))) {
		if(!noyes(text[AnonymousQ]))
458
459
			f.misc|=FM_ANON; 
	}
460
	sprintf(str,"%s%s",path,fname);
461
	if(fexistcase(str)) {   /* File is on disk */
462
		if(!uploadfile(&f))
463
464
			return(false); 
	} else {
465
		xfer_prot_menu(XFER_UPLOAD);
466
467
468
469
470
471
		SYNC;
		strcpy(keys,"Q");
		if(dirnum==cfg.user_dir || !cfg.max_batup)  /* no batch user to user xfers */
			mnemonics(text[ProtocolOrQuit]);
		else {
			mnemonics(text[ProtocolBatchOrQuit]);
472
473
			strcat(keys,"B"); 
		}
474
475
476
		for(i=0;i<cfg.total_prots;i++)
			if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron)) {
				sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
477
478
				strcat(keys,tmp); 
			}
479
480
		ch=(char)getkeys(keys,0);
		if(ch=='Q')
481
			return(false);
482
483
484
485
486
487
		if(ch=='B') {
			if(batup_total>=cfg.max_batup)
				bputs(text[BatchUlQueueIsFull]);
			else {
				for(i=0;i<batup_total;i++)
					if(!strcmp(batup_name[i],f.name)) {
488
						bprintf(text[FileAlreadyInQueue],fname);
489
490
						return(false); 
					}
491
492
493
494
495
496
497
				strcpy(batup_name[batup_total],f.name);
				strcpy(batup_desc[batup_total],f.desc);
				batup_dir[batup_total]=dirnum;
				batup_misc[batup_total]=f.misc;
				batup_alt[batup_total]=altul;
				batup_total++;
				bprintf(text[FileAddedToUlQueue]
498
					,fname,batup_total,cfg.max_batup); 
499
500
			} 
		} else {
501
502
503
504
505
506
			for(i=0;i<cfg.total_prots;i++)
				if(cfg.prot[i]->ulcmd[0] && cfg.prot[i]->mnemonic==ch
					&& chk_ar(cfg.prot[i]->ar,&useron))
					break;
			if(i<cfg.total_prots) {
				start=time(NULL);
507
				protocol(cfg.prot[i],XFER_UPLOAD,str,nulstr,true);
508
509
510
511
512
513
				end=time(NULL);
				if(!(cfg.dir[dirnum]->misc&DIR_ULTIME)) /* Don't deduct upload time */
					starttime+=end-start;
				ch=uploadfile(&f);
				autohangup();
				if(!ch)  /* upload failed, don't process user to user xfer */
514
515
516
517
					return(false); 
			} 
		} 
	}
518
	if(dirnum==cfg.user_dir) {  /* Add files to XFER.IXT in INDX dir */
519
		sprintf(str,"%sxfer.ixt",cfg.data_dir);
520
521
		if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
			errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
522
523
			return(false); 
		}
524
525
526
527
528
529
		for(j=0;j<destusers;j++) {
			for(i=1;i<=cfg.sys_nodes;i++) { /* Tell user, if online */
				getnodedat(i,&node,0);
				if(node.useron==destuser[j] && !(node.misc&NODE_POFF)
					&& (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
					sprintf(str,text[UserToUserXferNodeMsg],cfg.node_num,useron.alias);
530
					putnmsg(&cfg,i,str);
531
532
533
					break; 
				} 
			}
534
535
			if(i>cfg.sys_nodes) {   /* User not online */
				sprintf(str,text[UserSentYouFile],useron.alias);
536
537
				putsmsg(&cfg,destuser[j],str); 
			}
538
539
			sprintf(str,"%4.4u %12.12s %4.4u\r\n"
				,destuser[j],f.name,useron.number);
540
541
			write(file,str,strlen(str)); 
		}
542
543
		close(file); 
	}
544
	return(true);
545
546
547
548
549
550
551
552
553
}

/****************************************************************************/
/* Checks directory for 'dir' and prompts user to enter description for     */
/* the files that aren't in the database.                                   */
/* Returns 1 if the user aborted, 0 if not.                                 */
/****************************************************************************/
bool sbbs_t::bulkupload(uint dirnum)
{
554
555
556
    char	str[MAX_PATH+1];
	char	path[MAX_PATH+1];
	char	spath[MAX_PATH+1];
557
    file_t	f;
558
559
	DIR*	dir;
	DIRENT*	dirent;
560
561
562
563
564
565
566
567
568

	memset(&f,0,sizeof(file_t));
	f.dir=dirnum;
	f.altpath=altul;
	bprintf(text[BulkUpload],cfg.lib[cfg.dir[dirnum]->lib]->sname,cfg.dir[dirnum]->sname);
	strcpy(path,altul>0 && altul<=cfg.altpaths ? cfg.altpath[altul-1]
		: cfg.dir[dirnum]->path);
	action=NODE_ULNG;
	SYNC;
569
	dir=opendir(path);
570
	while(dir!=NULL && (dirent=readdir(dir))!=NULL && !msgabort()) {
571
		if(getfiles(&cfg,dirnum)>=cfg.dir[dirnum]->maxfiles) {
572
573
			bputs(text[DirFull]);
			break; 
574
		}
575
576
577
578
579
580
581
582
583
		sprintf(str,"%s%s",path,dirent->d_name);
		if(isdir(str))
			continue;
#ifdef _WIN32
		GetShortPathName(str,spath,sizeof(spath));
#else
		strcpy(spath,str);
#endif
		padfname(getfname(spath),str);
584

585
586
587
		if(findfile(&cfg,f.dir,str)==0) {
			strcpy(f.name,str);
			f.cdt=flength(spath);
588
			bprintf(text[BulkUploadDescPrompt],f.name,f.cdt/1024);
589
590
591
592
593
594
			getstr(f.desc,LEN_FDESC,K_LINE);
			if(sys_status&SS_ABORT)
				break;
			uploadfile(&f); 
		}
	}
595
596
	if(dir!=NULL)
		closedir(dir);
597
598
	if(sys_status&SS_ABORT)
		return(true);
599
600
601
	return(false);
}

602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
bool sbbs_t::recvfile(char *fname)
{
	char	keys[32];
	char	ch;
	size_t	i;
	bool	result=false;

	xfer_prot_menu(XFER_UPLOAD);
	mnemonics(text[ProtocolOrQuit]);
	strcpy(keys,"Q");
	for(i=0;i<cfg.total_prots;i++)
		if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron))
			sprintf(keys+strlen(keys),"%c",cfg.prot[i]->mnemonic);

	ch=(char)getkeys(keys,0);

	if(ch=='Q' || sys_status&SS_ABORT)
		return(false); 

	for(i=0;i<cfg.total_prots;i++)
		if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron))
			break;
	if(i<cfg.total_prots) {
		if(protocol(cfg.prot[i],XFER_UPLOAD,fname,fname,true)==0)
			result=true;
		autohangup(); 
	}

	return(result);
}