upload.cpp 18.5 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
35
36
	char	tmp[MAX_PATH+1];
    uint	i;
    long	length;
	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, 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
			safe_snprintf(sbbsfilename,sizeof(sbbsfilename),"SBBSFILENAME=%s",f->name);
65
			putenv(sbbsfilename);
66
			safe_snprintf(sbbsfiledesc,sizeof(sbbsfiledesc),"SBBSFILEDESC=%s",f->desc);
67
			putenv(sbbsfiledesc);
68
			SAFEPRINTF(str,"%ssbbsfile.nam",cfg.node_dir);
69
			if((stream=fopen(str,"w"))!=NULL) {
70
				fprintf(stream, "%s", f->desc);
71
72
				fclose(stream); 
			}
73
			SAFEPRINTF(str,"%ssbbsfile.des",cfg.node_dir);
74
75
			if((stream=fopen(str,"w"))!=NULL) {
				fwrite(f->desc,1,strlen(f->desc),stream);
76
77
				fclose(stream); 
			}
78
			if(external(cmdstr(cfg.ftest[i]->cmd,path,f->desc,NULL),EX_OFFLINE)) {
79
				safe_snprintf(str,sizeof(str),"attempted to upload %s to %s %s (%s Errors)"
80
					,f->name
81
					,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname,cfg.ftest[i]->ext);
82
				logline(LOG_NOTICE,"U!",str);
83
84
85
86
87
88
89
#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);
90
91
				return(0); 
			} else {
92
#if 0 // NFB-TODO - uploader tester changes filename or description
93
				sprintf(str,"%ssbbsfile.nam",cfg.node_dir);
94
95
96
97
98
99
				if((stream=fopen(str,"r"))!=NULL) {
					if(fgets(str,128,stream)) {
						truncsp(str);
						padfname(str,f->name);
						strcpy(tmp,f->name);
						truncsp(tmp);
100
						sprintf(path,"%s%s", cfg.dir[f->dir]->path
101
102
							,unpadfname(f->name,fname)); 
					}
103
104
					fclose(stream);
					}
105
				sprintf(str,"%ssbbsfile.des",cfg.node_dir);
106
107
108
				if((stream=fopen(str,"r"))!=NULL) {
					if(fgets(str,128,stream)) {
						truncsp(str);
109
110
111
112
						sprintf(f->desc,"%.*s",LEN_FDESC,str); 
					}
					fclose(stream); 
				}
113
114
115
				CRLF;
#endif
			}
116
		}
117

118
	if((length=(long)flength(path))==0L) {
119
120
		bprintf(text[FileZeroLength],f->name);
		remove(path);
121
		safe_snprintf(str,sizeof(str),"attempted to upload %s to %s %s (Zero length)"
122
			,f->name
123
			,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
124
		logline(LOG_NOTICE,"U!",str);
125
		return false; 
126
	}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

	bputs(text[SearchingForDupes]);
	/* Note: Hashes file *after* running upload-testers (which could modify file) */
	if(hashfile(&cfg, f)) {
		bputs(text[SearchedForDupes]);
		for(uint i=0, k=0; i < usrlibs; i++) {
			progress(text[Scanning], i, usrlibs, 1);
			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 */
					}
				}
147
			}
148
149
150
151
152
153
154
155
		}
		progress(text[Done], usrlibs, usrlibs);
	} else
		bputs(text[SearchedForDupes]);

	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))) {
156
			struct sauce_charinfo sauce;
157
158
			lprintf(LOG_DEBUG, "Parsing DIZ: %s", str);

159
			char* lines = read_diz(str, &sauce);
160
			if(lines != NULL)
161
162
163
				format_diz(lines, ext, sizeof(ext), sauce.width, sauce.ice_color);
			free(lines);
			file_sauce_hfields(f, &sauce);
164
165

			if(f->desc == NULL || f->desc[0] == 0) {
166
				char	desc[LEN_FDESC + 1];
167
168
169
170
171
				SAFECOPY(desc, (char*)ext);
				strip_exascii(desc, desc);
				prep_file_desc(desc, desc);
				for(i=0;desc[i];i++)
					if(IS_ALPHANUMERIC(desc[i]))
172
						break;
173
174
				if(desc[i] == '\0')
					i = 0;
175
				smb_new_hfield_str(f, SMB_FILEDESC, desc + i);
176
177
178
179
			}
			remove(str);
		} else
			lprintf(LOG_DEBUG, "DIZ does not exist in: %s", path);
180
	}
181

182
183
184
185
	if(!(cfg.dir[f->dir]->misc&DIR_NOSTAT)) {
		logon_ulb+=length;  /* Update 'this call' stats */
		logon_uls++;
	}
186
	if(cfg.dir[f->dir]->misc&DIR_AONLY)  /* Forced anonymous */
187
188
189
190
		f->hdr.attr |= MSG_ANONYMOUS;
	uint32_t cdt = (uint32_t)length;
	smb_hfield_bin(f, SMB_COST, cdt);
	smb_hfield_str(f, SENDER, useron.alias);
191
	bprintf(text[FileNBytesReceived],f->name,ultoac(length,tmp));
192
	if(!addfile(&cfg, f->dir, f, ext, &client))
193
		return false;
194

195
	safe_snprintf(str,sizeof(str),"uploaded %s to %s %s"
196
		,f->name,cfg.lib[cfg.dir[f->dir]->lib]->sname
197
198
		,cfg.dir[f->dir]->sname);
	if(cfg.dir[f->dir]->upload_sem[0])
199
		ftouch(cmdstr(cfg.dir[f->dir]->upload_sem,nulstr,nulstr,NULL));
200
201
202
203
	logline("U+",str);
	/**************************/
	/* Update Uploader's Info */
	/**************************/
204
	user_uploaded(&cfg, &useron, 1, length);
205
206
207
208
209
210
	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
211
				,(ulong)(f->cost * (cfg.dir[f->dir]->up_pct/100.0))); 
212
213
214
	}

	user_event(EVENT_UPLOAD);
215

216
	return true;
217
218
219
220
221
}

/****************************************************************************/
/* Uploads files                                                            */
/****************************************************************************/
222
bool sbbs_t::upload(uint dirnum)
223
{
224
	char	descbeg[25]={""},descend[25]={""}
225
				,fname[MAX_FILENAME_LEN + 1],keys[256],ch,*p;
226
227
	char	str[MAX_PATH+1];
	char	path[MAX_PATH+1];
228
	char 	tmp[512];
229
    time_t	start,end;
230
    uint	i,j,k;
231
	ulong	space;
232
	file_t	f = {{}};
233
	str_list_t dest_user_list = NULL;
234

235
236
237
238
239
240
241
242
243
	/* Security Checks */
	if(useron.rest&FLAG('U')) {
		bputs(text[R_Upload]);
		return(false); 
	}
	if(dirnum==INVALID_DIR) {
		bputs(text[CantUploadHere]);
		return(false);
	}
244
245
246
247
248
249
250
251
252
253
	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);
		}
254
255
	}

256
257
	if(sys_status&SS_EVENT && online==ON_REMOTE && !dir_op(dirnum))
		bprintf(text[UploadBeforeEvent],timeleft/60);
258
259

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

261
262
	if(!isdir(path)) {
		bprintf(text[DirectoryDoesNotExist], path);
263
		lprintf(LOG_ERR,"File directory does not exist: %s", path);
264
265
		return(false);
	}
266
267

	/* get free disk space */
268
269
	space=getfreediskspace(path,1024);
	if(space<(ulong)cfg.min_dspace) {
270
		bputs(text[LowDiskSpace]);
271
		lprintf(LOG_ERR,"Diskspace is low: %s (%lu kilobytes)",path,space);
272
		if(!dir_op(dirnum))
273
274
			return(false); 
	}
275
276
277
278
	bprintf(text[DiskNBytesFree],ultoac(space,tmp));

	f.dir=curdirnum=dirnum;
	bputs(text[Filename]);
279
	if(getstr(fname, sizeof(fname) - 1, 0) < 1 || strchr(fname,'?') || strchr(fname,'*') || !checkfname(fname)) {
280
		if(fname[0])
281
			bprintf(text[BadFilename], fname);
282
283
		return(false); 
	}
284
	if(dirnum==cfg.sysop_dir)
285
		SAFEPRINTF(str,text[UploadToSysopDirQ],fname);
286
	else if(dirnum==cfg.user_dir)
287
		SAFEPRINTF(str,text[UploadToUserDirQ],fname);
288
	else
289
		SAFEPRINTF3(str,text[UploadToCurDirQ],fname,cfg.lib[cfg.dir[dirnum]->lib]->sname
290
			,cfg.dir[dirnum]->sname);
291
	if(!yesno(str)) return(false);
292
	action=NODE_ULNG;
293
294
295
	SAFECOPY(f.file_idx.name, fname);
	getfilepath(&cfg, &f, path);
	if(fexistcase(path)) {   /* File is on disk */
296
297
		if(!dir_op(dirnum) && online!=ON_LOCAL) {		 /* local users or sysops */
			bprintf(text[FileAlreadyThere],fname);
298
299
			return(false); 
		}
300
		if(!yesno(text[FileOnDiskAddQ]))
301
302
			return(false); 
	}
303
304
	char* ext = getfext(fname);
	SAFECOPY(str,cfg.dir[dirnum]->exts);
305
306
307
308
309
	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;
310
		ch=(char)strlen(str+i);
311
312
		if(ext != NULL && stricmp(ext + 1, str + i) == 0)
			break;
313
	}
314
315
316
317
	if(j && i>=j) {
		bputs(text[TheseFileExtsOnly]);
		bputs(cfg.dir[dirnum]->exts);
		CRLF;
318
319
		if(!dir_op(dirnum)) return(false); 
	}
320
	bputs(text[SearchingForDupes]);
321
322
323
	bool found = findfile(&cfg, dirnum, fname, NULL);
	bputs(text[SearchedForDupes]);
	if(found) {
324
325
326
		bprintf(text[FileAlreadyOnline],fname);
		return(false); 	 /* File is already in database */
	}
327
	for(i=k=0;i<usrlibs;i++) {
328
		progress(text[SearchingForDupes], i, usrlibs, 1);
329
		for(j=0;j<usrdirs[i];j++,k++) {
330
331
332
			if(usrdir[i][j]==dirnum)
				continue;	/* we already checked this dir */
			if(cfg.dir[usrdir[i][j]]->misc&DIR_DUPES
333
				&& findfile(&cfg, usrdir[i][j], fname, NULL)) {
334
				bputs(text[SearchedForDupes]);
335
				bprintf(text[FileAlreadyOnline],fname);
336
				if(!dir_op(dirnum))
337
					return(false); 	 /* File is in database for another dir */
338
339
340
			}
		}
	}
341
342
343
344
345
	bputs(text[SearchedForDupes]);
	if(cfg.dir[dirnum]->misc&DIR_RATE) {
		SYNC;
		bputs(text[RateThisFile]);
		ch=getkey(K_ALPHA);
346
		if(!IS_ALPHA(ch) || sys_status&SS_ABORT)
347
			return(false);
348
		CRLF;
349
		SAFEPRINTF(descbeg,text[Rated],toupper(ch)); 
350
	}
351
352
353
354
	if(cfg.dir[dirnum]->misc&DIR_ULDATE) {
		now=time(NULL);
		if(descbeg[0])
			strcat(descbeg," ");
355
		SAFEPRINTF(str,"%s  ",unixtodstr(&cfg,(time32_t)now,tmp));
356
357
		strcat(descbeg,str); 
	}
358
359
360
361
	if(cfg.dir[dirnum]->misc&DIR_MULT) {
		SYNC;
		if(!noyes(text[MultipleDiskQ])) {
			bputs(text[HowManyDisksTotal]);
362
			if((int)(i=getnum(99))<2)
363
				return(false);
364
			bputs(text[NumberOfFile]);
365
			if((int)(j=getnum(i))<1)
366
				return(false);
367
368
369
			if(j==1)
				upload_lastdesc[0]=0;
			if(i>9)
370
				SAFEPRINTF2(descend,text[FileOneOfTen],j,i);
371
			else
372
				SAFEPRINTF2(descend,text[FileOneOfTwo],j,i); 
373
374
375
		} else
			upload_lastdesc[0]=0; 
	}
376
377
	else
		upload_lastdesc[0]=0;
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
	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;
	}
413
414

	char fdesc[LEN_FDESC + 1] = "";
415
416
	bputs(text[EnterDescNow]);
	i=LEN_FDESC-(strlen(descbeg)+strlen(descend));
417
	getstr(upload_lastdesc,i,K_LINE|K_EDIT|K_AUTODEL|K_TRIM);
418
419
	if(sys_status&SS_ABORT) {
		strListFree(&dest_user_list);
420
		return(false);
421
	}
422
	if(descend[0])      /* end of desc specified, so pad desc with spaces */
423
		safe_snprintf(fdesc,sizeof(fdesc),"%s%-*s%s",descbeg,i,upload_lastdesc,descend);
424
	else                /* no end specified, so string ends at desc end */
425
426
427
428
429
430
431
		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);
	}
432
433
434
435

	if(cfg.dir[dirnum]->misc&DIR_ANON && !(cfg.dir[dirnum]->misc&DIR_AONLY)
		&& (dir_op(dirnum) || useron.exempt&FLAG('A'))) {
		if(!noyes(text[AnonymousQ]))
436
			f.hdr.attr |= MSG_ANONYMOUS;
437
	}
438
439
440
441

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

/****************************************************************************/
/* 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)
{
504
505
    char	str[MAX_PATH+1];
	char	path[MAX_PATH+1];
506
507
508
	char	desc[LEN_FDESC + 1];
	smb_t	smb;
    file_t f;
509
510
	DIR*	dir;
	DIRENT*	dirent;
511

512
	memset(&f,0,sizeof(f));
513
514
	f.dir=dirnum;
	bprintf(text[BulkUpload],cfg.lib[cfg.dir[dirnum]->lib]->sname,cfg.dir[dirnum]->sname);
515
516
517
518
519
520
521
	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;
	}
522
523
	action=NODE_ULNG;
	SYNC;
524
525
	str_list_t list = loadfilenames(&smb, ALLFILES, /* time_t */0, FILE_SORT_NATURAL, NULL);
	smb_close(&smb);
526
	dir=opendir(path);
527
	while(dir!=NULL && (dirent=readdir(dir))!=NULL && !msgabort()) {
528
		char fname[SMB_FILEIDX_NAMELEN + 1];
529
		SAFEPRINTF2(str,"%s%s",path,dirent->d_name);
530
531
		if(isdir(str))
			continue;
532
533
534
535
536
#ifdef _WIN32
		/* Skip hidden/system files on Win32 */
		if(getfattr(str)&(_A_HIDDEN|_A_SYSTEM))
			continue;
#endif
537
538
539
540
541
542
		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);
			uint32_t cdt = (uint32_t)flength(str);
			bprintf(text[BulkUploadDescPrompt], format_filename(f.name, fname, 12, /* pad: */FALSE), cdt/1024);
543
544
545
546
547
			if(strcmp(f.name, fname) != 0)
				SAFECOPY(desc, f.name);
			else
				desc[0] = 0;
			getstr(desc, LEN_FDESC, K_LINE|K_EDIT|K_AUTODEL);
548
549
			if(sys_status&SS_ABORT)
				break;
550
			if(strcmp(desc,"-")==0)	/* don't add this file */
551
				continue;
552
553
			smb_hfield_str(&f, SMB_FILEDESC, desc);
			uploadfile(&f);
554
555
		}
	}
556
557
	if(dir!=NULL)
		closedir(dir);
558
559
	strListFree(&list);
	smb_freemsgmem(&f);
560
561
	if(sys_status&SS_ABORT)
		return(true);
562
563
564
	return(false);
}

565
bool sbbs_t::recvfile(char *fname, char prot, bool autohang)
566
567
568
569
570
571
{
	char	keys[32];
	char	ch;
	size_t	i;
	bool	result=false;

572
573
574
575
576
	if(prot)
		ch=toupper(prot);
	else {
		xfer_prot_menu(XFER_UPLOAD);
		mnemonics(text[ProtocolOrQuit]);
577
		SAFEPRINTF(keys,"%c",text[YNQP][2]);
578
		for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
579
			if(cfg.prot[i]->ulcmd[0] && chk_ar(cfg.prot[i]->ar,&useron,&client))
580
				sprintf(keys+strlen(keys),"%c",cfg.prot[i]->mnemonic);
581

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

584
		if(ch==text[YNQP][2] || sys_status&SS_ABORT)
585
586
			return(false); 
	}
587
	for(i=0;i<cfg.total_prots;i++)
rswindell's avatar
rswindell committed
588
		if(cfg.prot[i]->mnemonic==ch && chk_ar(cfg.prot[i]->ar,&useron,&client))
589
590
			break;
	if(i<cfg.total_prots) {
591
		if(protocol(cfg.prot[i], XFER_UPLOAD, fname, fname, true, autohang)==0)
592
593
594
595
596
597
			result=true;
		autohangup(); 
	}

	return(result);
}