upload.cpp 18.1 KB
Newer Older
1
2
3
4
5
6
/* Synchronet file upload-related routines */

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

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

/****************************************************************************/
/****************************************************************************/
28
bool sbbs_t::uploadfile(file_t* f)
29
{
30
	char	path[MAX_PATH+1];
31
32
	char	str[MAX_PATH+1] = "";
	char	ext[LEN_EXTDESC + 1] = "";
33
34
	char	tmp[MAX_PATH+1];
    uint	i;
35
    off_t	length;
36
	FILE*	stream;
37
38

	curdirnum=f->dir;
39
40
41
	if(findfile(&cfg, f->dir, f->name, NULL)) {
		errormsg(WHERE, ERR_CHK, f->name, f->dir);
		return false;
42
	}
43
44
	getfilepath(&cfg, f, path);
	SAFEPRINTF2(tmp, "%s%s", cfg.temp_dir, getfname(path));
45
	if(!fexistcase(path) && fexistcase(tmp))
46
		mv(tmp,path,0);
47
	if(!fexistcase(path)) {
48
		bprintf(text[FileNotReceived],f->name);
49
		safe_snprintf(str,sizeof(str),"attempted to upload %s to %s %s (Not received)"
50
			,f->name
51
			,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
52
		logline(LOG_NOTICE,"U!",str);
53
		return false;
54
	}
55
56
	f->hdr.when_written.time = (uint32_t)fdate(path);
	char* fext = getfext(f->name);
57
	for(i=0;i<cfg.total_ftests;i++)
58
		if(cfg.ftest[i]->ext[0]=='*' || (fext != NULL && stricmp(fext + 1, cfg.ftest[i]->ext) == 0)) {
rswindell's avatar
rswindell committed
59
			if(!chk_ar(cfg.ftest[i]->ar,&useron,&client))
60
61
62
63
				continue;
			attr(LIGHTGRAY);
			bputs(cfg.ftest[i]->workstr);

64
			SAFEPRINTF(str,"%ssbbsfile.nam",cfg.node_dir);
65
			if((stream=fopen(str,"w"))!=NULL) {
66
				fprintf(stream, "%s", f->name);
67
68
				fclose(stream); 
			}
69
			SAFEPRINTF(str,"%ssbbsfile.des",cfg.node_dir);
70
			if((stream=fopen(str,"w"))!=NULL) {
71
72
				if(f->desc != NULL)
					fprintf(stream, "%s", f->desc);
73
74
				fclose(stream); 
			}
75
76
			// Note: str (%s) is path/to/sbbsfile.des (used to be the description itself)
			int result = external(cmdstr(cfg.ftest[i]->cmd, path, str, NULL), EX_OFFLINE);
77
78
79
			clearline();
			if(result != 0) {
				safe_snprintf(str,sizeof(str),"attempted to upload %s to %s %s (%s error code %d)"
80
					,f->name
81
82
					,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname,cfg.ftest[i]->ext
					,result);
83
				logline(LOG_NOTICE,"U!",str);
84
85
86
				bprintf(text[FileHadErrors],f->name,cfg.ftest[i]->ext);
				if(!SYSOP || yesno(text[DeleteFileQ]))
					remove(path);
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
				return false;
			}
			SAFEPRINTF(str,"%ssbbsfile.nam",cfg.node_dir);
			if((stream=fopen(str,"r"))!=NULL) {
				if(fgets(str, sizeof(str), stream)) {
					truncsp(str);
					smb_new_hfield_str(f, SMB_FILENAME, str);
					getfilepath(&cfg, f, path);
				}
				fclose(stream);
			}
			SAFEPRINTF(str,"%ssbbsfile.des",cfg.node_dir);
			if((stream=fopen(str,"r"))!=NULL) {
				if(fgets(str, sizeof(str), stream)) {
					truncsp(str);
102
103
					if(*str)
						smb_new_hfield_str(f, SMB_FILEDESC, str);
104
				}
105
				fclose(stream); 
106
			}
107
		}
108

109
	if((length = flength(path))==0L) {
110
111
		bprintf(text[FileZeroLength],f->name);
		remove(path);
112
		safe_snprintf(str,sizeof(str),"attempted to upload %s to %s %s (Zero length)"
113
			,f->name
114
			,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
115
		logline(LOG_NOTICE,"U!",str);
116
		return false; 
117
	}
118

119
	bputs(text[HashingFile]);
120
	/* Note: Hashes file *after* running upload-testers (which could modify file) */
121
122
123
	bool hashed = hashfile(&cfg, f);
	bputs(text[HashedFile]);
	if(hashed) {
124
		for(uint i=0, k=0; i < usrlibs; i++) {
125
			progress(text[Scanning], i, usrlibs);
126
127
128
129
130
131
132
133
134
135
136
137
138
			for(uint j=0; j < usrdirs[i]; j++,k++) {
				if(cfg.dir[usrdir[i][j]]->misc&DIR_DUPES
					&& findfile(&cfg, usrdir[i][j], /* filename: */NULL, f)) {
					bprintf(text[FileAlreadyOnline], f->name);
					if(!dir_op(f->dir)) {
						remove(path);
						safe_snprintf(str, sizeof(str), "attempted to upload %s to %s %s (duplicate hash)"
							,f->name
							,cfg.lib[cfg.dir[f->dir]->lib]->sname, cfg.dir[f->dir]->sname);
						logline(LOG_NOTICE, "U!", str);
						return(false); 	 /* File is in database for another dir */
					}
				}
139
			}
140
141
		}
		progress(text[Done], usrlibs, usrlibs);
142
	}
143
144
145
146

	if(cfg.dir[f->dir]->misc&DIR_DIZ) {
		lprintf(LOG_DEBUG, "Extracting DIZ from: %s", path);
		if(extract_diz(&cfg, f, /* diz_fnames: */NULL, str, sizeof(str))) {
147
			struct sauce_charinfo sauce;
148
149
			lprintf(LOG_DEBUG, "Parsing DIZ: %s", str);

150
			char* lines = read_diz(str, &sauce);
151
			if(lines != NULL)
152
153
154
				format_diz(lines, ext, sizeof(ext), sauce.width, sauce.ice_color);
			free(lines);
			file_sauce_hfields(f, &sauce);
155
156

			if(f->desc == NULL || f->desc[0] == 0) {
157
				char desc[LEN_EXTDESC + 1];
158
159
				SAFECOPY(desc, (char*)ext);
				prep_file_desc(desc, desc);
160
				smb_new_hfield_str(f, SMB_FILEDESC, desc);
161
162
163
164
			}
			remove(str);
		} else
			lprintf(LOG_DEBUG, "DIZ does not exist in: %s", path);
165
	}
166

167
168
169
170
	if(!(cfg.dir[f->dir]->misc&DIR_NOSTAT)) {
		logon_ulb+=length;  /* Update 'this call' stats */
		logon_uls++;
	}
171
	if(cfg.dir[f->dir]->misc&DIR_AONLY)  /* Forced anonymous */
172
		f->hdr.attr |= MSG_ANONYMOUS;
173
	smb_hfield_bin(f, SMB_COST, length);
174
	smb_hfield_str(f, SENDER, useron.alias);
175
	bprintf(text[FileNBytesReceived],f->name, u64toac(length,tmp));
176
	if(!addfile(&cfg, f->dir, f, ext, /* metadata: */NULL, &client))
177
		return false;
178

179
	safe_snprintf(str,sizeof(str),"uploaded %s to %s %s"
180
		,f->name,cfg.lib[cfg.dir[f->dir]->lib]->sname
181
182
		,cfg.dir[f->dir]->sname);
	if(cfg.dir[f->dir]->upload_sem[0])
183
		ftouch(cmdstr(cfg.dir[f->dir]->upload_sem,nulstr,nulstr,NULL));
184
185
186
187
	logline("U+",str);
	/**************************/
	/* Update Uploader's Info */
	/**************************/
188
	user_uploaded(&cfg, &useron, 1, length);
189
190
	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 */
191
			useron.min=(uint32_t)adjustuserrec(&cfg,useron.number,U_MIN
192
193
				,((ulong)(length*(cfg.dir[f->dir]->up_pct/100.0))/cur_cps)/60);
		else
194
195
			useron.cdt=adjustuserrec(&cfg,useron.number,U_CDT
				,(int64_t)(f->cost * (cfg.dir[f->dir]->up_pct/100.0))); 
196
197
198
	}

	user_event(EVENT_UPLOAD);
199

200
	return true;
201
202
203
204
205
}

/****************************************************************************/
/* Uploads files                                                            */
/****************************************************************************/
206
bool sbbs_t::upload(uint dirnum)
207
{
208
	char	descbeg[25]={""},descend[25]={""}
209
				,fname[MAX_FILENAME_LEN + 1],keys[256],ch,*p;
210
211
	char	str[MAX_PATH+1];
	char	path[MAX_PATH+1];
212
	char 	tmp[512];
213
    time_t	start,end;
214
    uint	i,j,k;
215
	ulong	space;
216
	file_t	f = {{}};
217
	str_list_t dest_user_list = NULL;
218

219
220
221
222
223
224
225
226
227
	/* Security Checks */
	if(useron.rest&FLAG('U')) {
		bputs(text[R_Upload]);
		return(false); 
	}
	if(dirnum==INVALID_DIR) {
		bputs(text[CantUploadHere]);
		return(false);
	}
228
229
230
231
232
233
234
235
236
237
	if(!(useron.exempt&FLAG('U')) && !dir_op(dirnum)) {
		if(!chk_ar(cfg.dir[dirnum]->ul_ar,&useron,&client)) {
			bputs(dirnum==cfg.user_dir ? text[CantUploadToUser] : 
				dirnum==cfg.sysop_dir ? text[CantUploadToSysop] : text[CantUploadHere]);
			return(false); 
		}
		if(cfg.dir[dirnum]->maxfiles && getfiles(&cfg,dirnum)>=cfg.dir[dirnum]->maxfiles) {
			bputs(dirnum==cfg.user_dir ? text[UserDirFull] : text[DirFull]);
			return(false);
		}
238
239
	}

240
241
	if(sys_status&SS_EVENT && online==ON_REMOTE && !dir_op(dirnum))
		bprintf(text[UploadBeforeEvent],timeleft/60);
242
243

	SAFECOPY(path,cfg.dir[dirnum]->path);
244

245
246
	if(!isdir(path)) {
		bprintf(text[DirectoryDoesNotExist], path);
247
		lprintf(LOG_ERR,"File directory does not exist: %s", path);
248
249
		return(false);
	}
250
251

	/* get free disk space */
252
253
	space=getfreediskspace(path,1024);
	if(space<(ulong)cfg.min_dspace) {
254
		bputs(text[LowDiskSpace]);
255
		lprintf(LOG_ERR,"Diskspace is low: %s (%lu kilobytes)",path,space);
256
		if(!dir_op(dirnum))
257
258
			return(false); 
	}
259
260
261
262
	bprintf(text[DiskNBytesFree],ultoac(space,tmp));

	f.dir=curdirnum=dirnum;
	bputs(text[Filename]);
263
	if(getstr(fname, sizeof(fname) - 1, K_TRIM) < 1 || !checkfname(fname)) {
264
		if(fname[0])
265
			bprintf(text[BadFilename], fname);
266
267
		return(false); 
	}
268
	if(dirnum==cfg.sysop_dir)
269
		SAFEPRINTF(str,text[UploadToSysopDirQ],fname);
270
	else if(dirnum==cfg.user_dir)
271
		SAFEPRINTF(str,text[UploadToUserDirQ],fname);
272
	else
273
		SAFEPRINTF3(str,text[UploadToCurDirQ],fname,cfg.lib[cfg.dir[dirnum]->lib]->sname
274
			,cfg.dir[dirnum]->sname);
275
	if(!yesno(str)) return(false);
276
	action=NODE_ULNG;
277
278
279
	SAFECOPY(f.file_idx.name, fname);
	getfilepath(&cfg, &f, path);
	if(fexistcase(path)) {   /* File is on disk */
280
281
		if(!dir_op(dirnum) && online!=ON_LOCAL) {		 /* local users or sysops */
			bprintf(text[FileAlreadyThere],fname);
282
283
			return(false); 
		}
284
		if(!yesno(text[FileOnDiskAddQ]))
285
286
			return(false); 
	}
287
288
	char* ext = getfext(fname);
	SAFECOPY(str,cfg.dir[dirnum]->exts);
289
290
291
292
293
	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;
294
		ch=(char)strlen(str+i);
295
296
		if(ext != NULL && stricmp(ext + 1, str + i) == 0)
			break;
297
	}
298
299
300
301
	if(j && i>=j) {
		bputs(text[TheseFileExtsOnly]);
		bputs(cfg.dir[dirnum]->exts);
		CRLF;
302
303
		if(!dir_op(dirnum)) return(false); 
	}
304
	bputs(text[SearchingForDupes]);
305
306
307
	bool found = findfile(&cfg, dirnum, fname, NULL);
	bputs(text[SearchedForDupes]);
	if(found) {
308
309
310
		bprintf(text[FileAlreadyOnline],fname);
		return(false); 	 /* File is already in database */
	}
311
	for(i=k=0;i<usrlibs;i++) {
312
		progress(text[SearchingForDupes], i, usrlibs);
313
		for(j=0;j<usrdirs[i];j++,k++) {
314
315
316
			if(usrdir[i][j]==dirnum)
				continue;	/* we already checked this dir */
			if(cfg.dir[usrdir[i][j]]->misc&DIR_DUPES
317
				&& findfile(&cfg, usrdir[i][j], fname, NULL)) {
318
				bputs(text[SearchedForDupes]);
319
				bprintf(text[FileAlreadyOnline],fname);
320
				if(!dir_op(dirnum))
321
					return(false); 	 /* File is in database for another dir */
322
			}
323
324
325
326
			if(msgabort(true)) {
				bputs(text[SearchedForDupes]);
				return false;
			}
327
328
		}
	}
329
330
331
332
333
	bputs(text[SearchedForDupes]);
	if(cfg.dir[dirnum]->misc&DIR_RATE) {
		SYNC;
		bputs(text[RateThisFile]);
		ch=getkey(K_ALPHA);
334
		if(!IS_ALPHA(ch) || sys_status&SS_ABORT)
335
			return(false);
336
		CRLF;
337
		SAFEPRINTF(descbeg,text[Rated],toupper(ch)); 
338
	}
339
340
341
342
	if(cfg.dir[dirnum]->misc&DIR_ULDATE) {
		now=time(NULL);
		if(descbeg[0])
			strcat(descbeg," ");
343
		SAFEPRINTF(str,"%s  ",unixtodstr(&cfg,(time32_t)now,tmp));
344
345
		strcat(descbeg,str); 
	}
346
347
348
349
	if(cfg.dir[dirnum]->misc&DIR_MULT) {
		SYNC;
		if(!noyes(text[MultipleDiskQ])) {
			bputs(text[HowManyDisksTotal]);
350
			if((int)(i=getnum(99))<2)
351
				return(false);
352
			bputs(text[NumberOfFile]);
353
			if((int)(j=getnum(i))<1)
354
				return(false);
355
356
357
			if(j==1)
				upload_lastdesc[0]=0;
			if(i>9)
358
				SAFEPRINTF2(descend,text[FileOneOfTen],j,i);
359
			else
360
				SAFEPRINTF2(descend,text[FileOneOfTwo],j,i); 
361
362
363
		} else
			upload_lastdesc[0]=0; 
	}
364
365
	else
		upload_lastdesc[0]=0;
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
	if(dirnum == cfg.user_dir) {  /* User to User transfer */
		bputs(text[EnterAfterLastDestUser]);
		while(dir_op(dirnum) || strListCount(dest_user_list) < cfg.max_userxfer) {
			bputs(text[SendFileToUser]);
			if(!getstr(str,LEN_ALIAS,cfg.uq&UQ_NOUPRLWR ? K_NONE:K_UPRLWR))
				break;
			user_t user;
			if((user.number=finduser(str))!=0) {
				if(!dir_op(dirnum) && user.number==useron.number) {
					bputs(text[CantSendYourselfFiles]);
					continue; 
				}
				char usernum[16];
				SAFEPRINTF(usernum, "%u", user.number);
				if(strListFind(dest_user_list, usernum, /* case-sensitive: */true) >= 0) {
					bputs(text[DuplicateUser]);
					continue; 
				}
				getuserdat(&cfg,&user);
				if((user.rest&(FLAG('T')|FLAG('D')))
					|| !chk_ar(cfg.lib[cfg.dir[cfg.user_dir]->lib]->ar,&user,/* client: */NULL)
					|| !chk_ar(cfg.dir[cfg.user_dir]->dl_ar,&user,/* client: */NULL)) {
					bprintf(text[UserWontBeAbleToDl],user.alias); 
				} else {
					bprintf(text[UserAddedToDestList],user.alias,usernum);
					strListPush(&dest_user_list, usernum);
				} 
			}
			else {
				CRLF;
			}
		}
		if(strListCount(dest_user_list) < 1)
			return false;
	}
401
402

	char fdesc[LEN_FDESC + 1] = "";
403
404
	bputs(text[EnterDescNow]);
	i=LEN_FDESC-(strlen(descbeg)+strlen(descend));
405
	getstr(upload_lastdesc,i,K_LINE|K_EDIT|K_AUTODEL|K_TRIM);
406
407
	if(sys_status&SS_ABORT) {
		strListFree(&dest_user_list);
408
		return(false);
409
	}
410
	if(descend[0])      /* end of desc specified, so pad desc with spaces */
411
		safe_snprintf(fdesc,sizeof(fdesc),"%s%-*s%s",descbeg,i,upload_lastdesc,descend);
412
	else                /* no end specified, so string ends at desc end */
413
414
415
416
417
418
419
		safe_snprintf(fdesc,sizeof(fdesc),"%s%s",descbeg,upload_lastdesc);

	char tags[64] = "";
	if((cfg.dir[dirnum]->misc&DIR_FILETAGS) && (text[TagFileQ][0] == 0 || !noyes(text[TagFileQ]))) {
		bputs(text[TagFilePrompt]);
		getstr(tags, sizeof(tags)-1, K_EDIT|K_LINE|K_TRIM);
	}
420
421
422
423

	if(cfg.dir[dirnum]->misc&DIR_ANON && !(cfg.dir[dirnum]->misc&DIR_AONLY)
		&& (dir_op(dirnum) || useron.exempt&FLAG('A'))) {
		if(!noyes(text[AnonymousQ]))
424
			f.hdr.attr |= MSG_ANONYMOUS;
425
	}
426
427
428
429

	bool result = false;
	smb_hfield_str(&f, SMB_FILENAME, fname);
	smb_hfield_str(&f, SMB_FILEDESC, fdesc);
430
431
	if(strListCount(dest_user_list) > 0)
		smb_hfield_str(&f, RECIPIENTLIST, strListCombine(dest_user_list, tmp, sizeof(tmp), ","));
432
433
434
435
	if(tags[0])
		smb_hfield_str(&f, SMB_TAGS, tags);
	if(fexistcase(path)) {   /* File is on disk */
		result = uploadfile(&f);
436
	} else {
437
		xfer_prot_menu(XFER_UPLOAD);
438
		SYNC;
439
		SAFEPRINTF(keys,"%c",quit_key());
440
441
442
443
		if(dirnum==cfg.user_dir || !cfg.max_batup)  /* no batch user to user xfers */
			mnemonics(text[ProtocolOrQuit]);
		else {
			mnemonics(text[ProtocolBatchOrQuit]);
444
445
			strcat(keys,"B"); 
		}
446
		for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
447
			if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client)) {
448
				SAFEPRINTF(tmp,"%c",cfg.prot[i]->mnemonic);
449
450
				strcat(keys,tmp); 
			}
451
		ch=(char)getkeys(keys,0);
452
		if(ch==quit_key() || (sys_status&SS_ABORT))
453
454
455
			result = false;
		else if(ch=='B') {
			if(batup_total() >= cfg.max_batup)
456
				bputs(text[BatchUlQueueIsFull]);
457
458
459
			else if(batch_file_exists(&cfg, useron.number, XFER_BATCH_UPLOAD, f.name))
				bprintf(text[FileAlreadyInQueue],fname);
			else if(batch_file_add(&cfg, useron.number, XFER_BATCH_UPLOAD, &f)) {
460
				bprintf(text[FileAddedToUlQueue]
461
462
463
					,fname, batup_total(), cfg.max_batup);
				result = true;
			}
464
		} else {
465
466
			for(i=0;i<cfg.total_prots;i++)
				if(cfg.prot[i]->ulcmd[0] && cfg.prot[i]->mnemonic==ch
rswindell's avatar
rswindell committed
467
					&& chk_ar(cfg.prot[i]->ar,&useron,&client))
468
469
470
					break;
			if(i<cfg.total_prots) {
				start=time(NULL);
471
				protocol(cfg.prot[i],XFER_UPLOAD,path,nulstr,true);
472
473
474
				end=time(NULL);
				if(!(cfg.dir[dirnum]->misc&DIR_ULTIME)) /* Don't deduct upload time */
					starttime+=end-start;
475
				result = uploadfile(&f);
476
				autohangup();
477
478
479
			} 
		} 
	}
480
	smb_freefilemem(&f);
481
	strListFree(&dest_user_list);
482
	return result;
483
484
485
486
487
488
489
490
491
}

/****************************************************************************/
/* 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)
{
492
493
    char	str[MAX_PATH+1];
	char	path[MAX_PATH+1];
494
495
496
	char	desc[LEN_FDESC + 1];
	smb_t	smb;
    file_t f;
497
498
	DIR*	dir;
	DIRENT*	dirent;
499

500
	memset(&f,0,sizeof(f));
501
502
	f.dir=dirnum;
	bprintf(text[BulkUpload],cfg.lib[cfg.dir[dirnum]->lib]->sname,cfg.dir[dirnum]->sname);
503
504
505
506
507
508
509
	SAFECOPY(path, cfg.dir[dirnum]->path);

	int result = smb_open_dir(&cfg, &smb, dirnum);
	if(result != SMB_SUCCESS) {
		errormsg(WHERE, ERR_OPEN, smb.file, result, smb.last_error);
		return false;
	}
510
511
	action=NODE_ULNG;
	SYNC;
512
513
	str_list_t list = loadfilenames(&smb, ALLFILES, /* time_t */0, FILE_SORT_NATURAL, NULL);
	smb_close(&smb);
514
	dir=opendir(path);
515
	while(dir!=NULL && (dirent=readdir(dir))!=NULL && !msgabort()) {
516
		char fname[SMB_FILEIDX_NAMELEN + 1];
517
		SAFEPRINTF2(str,"%s%s",path,dirent->d_name);
518
519
		if(isdir(str))
			continue;
520
521
522
523
524
#ifdef _WIN32
		/* Skip hidden/system files on Win32 */
		if(getfattr(str)&(_A_HIDDEN|_A_SYSTEM))
			continue;
#endif
525
526
527
528
		smb_fileidxname(dirent->d_name, fname, sizeof(fname));
		if(strListFind(list, fname, /* case-sensitive: */FALSE) < 0) {
			smb_freemsgmem(&f);
			smb_hfield_str(&f, SMB_FILENAME, dirent->d_name);
529
530
			off_t flen = flength(str);
			bprintf(text[BulkUploadDescPrompt], format_filename(f.name, fname, 12, /* pad: */FALSE), flen/1024);
531
532
533
534
535
			if(strcmp(f.name, fname) != 0)
				SAFECOPY(desc, f.name);
			else
				desc[0] = 0;
			getstr(desc, LEN_FDESC, K_LINE|K_EDIT|K_AUTODEL);
536
537
			if(sys_status&SS_ABORT)
				break;
538
			if(strcmp(desc,"-")==0)	/* don't add this file */
539
				continue;
540
541
			smb_hfield_str(&f, SMB_FILEDESC, desc);
			uploadfile(&f);
542
543
		}
	}
544
545
	if(dir!=NULL)
		closedir(dir);
546
547
	strListFree(&list);
	smb_freemsgmem(&f);
548
549
	if(sys_status&SS_ABORT)
		return(true);
550
551
552
	return(false);
}

553
bool sbbs_t::recvfile(char *fname, char prot, bool autohang)
554
555
556
557
558
559
{
	char	keys[32];
	char	ch;
	size_t	i;
	bool	result=false;

560
561
562
563
564
	if(prot)
		ch=toupper(prot);
	else {
		xfer_prot_menu(XFER_UPLOAD);
		mnemonics(text[ProtocolOrQuit]);
565
		SAFEPRINTF(keys,"%c",quit_key());
566
		for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
567
			if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client))
568
				sprintf(keys+strlen(keys),"%c",cfg.prot[i]->mnemonic);
569

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

572
		if(ch==quit_key() || sys_status&SS_ABORT)
573
574
			return(false); 
	}
575
	for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
576
		if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
577
578
			break;
	if(i<cfg.total_prots) {
579
		if(protocol(cfg.prot[i], XFER_UPLOAD, fname, fname, true, autohang)==0)
580
581
582
583
584
585
			result=true;
		autohangup(); 
	}

	return(result);
}