Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit bc883458 authored by Rob Swindell's avatar Rob Swindell 💬

Restore the user-to-user file transfer feature

I forget who it was that said they were still using this feature in v3.18, but here you go, it's working again (the /D and /U commands). I'm not migrating any file sender/recipient info from v3.18, so only files added after upgrading to this will be downloadable from the "user" directory (if you have one).

Something that I never implemented before but noticed is missing is the removal (or dereferencing) of user-to-user files that were sent from/to a user that is then deleted. So that's still a TODO item.
parent edd76adb
......@@ -330,7 +330,18 @@ int sbbs_t::exec_file(csi_t *csi)
return(0);
case CS_FILE_DOWNLOAD_USER: /* Download from user dir */
csi->logic=LOGIC_FALSE;
bputs(text[NoUserDir]);
if(cfg.user_dir==INVALID_DIR) {
bputs(text[NoUserDir]);
return(0);
}
if(useron.rest&FLAG('D')) {
bputs(text[R_Download]);
return(0);
}
if(!listfileinfo(cfg.user_dir,nulstr,FI_USERXFER))
bputs(text[NoFilesForYou]);
else
csi->logic=LOGIC_TRUE;
return(0);
case CS_FILE_DOWNLOAD_BATCH:
if(batdn_total() > 0
......
......@@ -480,6 +480,42 @@ bool removefile(scfg_t* cfg, uint dirnum, const char* filename)
return result == SMB_SUCCESS;
}
ulong getuserxfers(scfg_t* cfg, const char* from, uint to)
{
smb_t smb;
ulong found = 0;
if(cfg == NULL)
return 0;
if(cfg->user_dir >= cfg->total_dirs)
return 0;
if(smb_open_dir(cfg, &smb, cfg->user_dir) != SMB_SUCCESS)
return 0;
char usernum[16];
SAFEPRINTF(usernum, "%u", to);
size_t count = 0;
file_t* list = loadfiles(&smb, /* filespec */ NULL, /* since: */0, file_detail_normal, FILE_SORT_NATURAL, &count);
for(size_t i = 0; i < count; i++) {
file_t* f = &list[i];
if(from != NULL && (f->from == NULL || stricmp(f->from, from) != 0))
continue;
if(to != 0) {
str_list_t dest_user_list = strListSplitCopy(NULL, f->to_list, ",");
int dest_user = strListFind(dest_user_list, usernum, /* case-sensitive: */true);
strListFree(&dest_user_list);
if(dest_user < 0)
continue;
}
found++;
}
smb_close(&smb);
freefiles(list, count);
return found;
}
/****************************************************************************/
/* Returns full (case-corrected) path to specified file */
/* 'path' should be MAX_PATH + 1 chars in size */
......
......@@ -40,7 +40,7 @@ DLLEXPORT time_t lastfiletime(smb_t*); // Reads the last index record
DLLEXPORT bool findfile(scfg_t* cfg, uint dirnum, const char *filename, file_t*);
DLLEXPORT bool loadfile(scfg_t*, uint dirnum, const char* filename, file_t*, enum file_detail);
DLLEXPORT file_t* loadfiles(smb_t*, const char* filespec, time_t, enum file_detail, enum file_sort, size_t* count);
DLLEXPORT file_t* loadfiles(smb_t*, const char* filespec, time_t, enum file_detail, enum file_sort, size_t* count);
DLLEXPORT void sortfiles(file_t*, size_t count, enum file_sort);
DLLEXPORT void freefiles(file_t*, size_t count);
DLLEXPORT str_list_t loadfilenames(smb_t*, const char* filespec, time_t t, enum file_sort, size_t* count);
......@@ -50,6 +50,7 @@ DLLEXPORT char* getfilepath(scfg_t*, file_t*, char* path);
DLLEXPORT off_t getfilesize(scfg_t*, file_t*);
DLLEXPORT time_t getfiletime(scfg_t*, file_t*);
DLLEXPORT ulong gettimetodl(scfg_t*, file_t*, uint rate_cps);
DLLEXPORT ulong getuserxfers(scfg_t*, const char* from, uint to);
DLLEXPORT bool hashfile(scfg_t*, file_t*);
DLLEXPORT bool addfile(scfg_t*, uint dirnum, file_t*, const char* extdesc);
DLLEXPORT bool removefile(scfg_t*, uint dirnum, const char* filename);
......
......@@ -185,6 +185,11 @@ set_file_properties(JSContext *cx, JSObject* obj, file_t* f, enum file_detail de
|| !JS_DefineProperty(cx, obj, "from", STRING_TO_JSVAL(js_str), NULL, NULL, flags)))
return false;
if(((f->to_list != NULL && *f->to_list != '\0') || detail > file_detail_extdesc)
&& ((js_str = JS_NewStringCopyZ(cx, f->to_list)) == NULL
|| !JS_DefineProperty(cx, obj, "to_list", STRING_TO_JSVAL(js_str), NULL, NULL, flags)))
return false;
val = BOOLEAN_TO_JSVAL(f->idx.attr & FILE_ANONYMOUS);
if((val == JSVAL_TRUE || detail > file_detail_extdesc)
&& !JS_DefineProperty(cx, obj, "anon", val, NULL, NULL, flags))
......@@ -349,6 +354,21 @@ parse_file_properties(JSContext *cx, JSObject* obj, file_t* file, char** extdesc
}
}
prop_name = "to_list";
if(JS_GetProperty(cx, obj, prop_name, &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid '%s' string in file object", prop_name);
return SMB_FAILURE;
}
if((file->to_list != NULL || *cp != '\0') && (result = smb_new_hfield_str(file, RECIPIENTLIST, cp)) != SMB_SUCCESS) {
free(cp);
JS_ReportError(cx, "Error %d adding '%s' property to file object", result, prop_name);
return result;
}
}
prop_name = "from";
if(JS_GetProperty(cx, obj, prop_name, &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
......
......@@ -779,6 +779,15 @@ int sbbs_t::listfileinfo(uint dirnum, const char *filespec, long mode)
curdirnum = dirnum;
if(mode==FI_OFFLINE && getfilesize(&cfg, f) >= 0)
continue;
if(mode==FI_USERXFER) {
str_list_t dest_user_list = strListSplitCopy(NULL, f->to_list, ",");
char usernum[16];
SAFEPRINTF(usernum, "%u", useron.number);
int dest_user = strListFind(dest_user_list, usernum, /* case-sensitive: */true);
strListFree(&dest_user_list);
if(dest_user < 0)
continue;
}
SAFECOPY(dirpath, cfg.dir[f->dir]->path);
if((mode==FI_REMOVE) && (!dir_op(dirnum) && stricmp(f->from
,useron.alias) && !(useron.exempt&FLAG('R'))))
......@@ -995,7 +1004,7 @@ int sbbs_t::listfileinfo(uint dirnum, const char *filespec, long mode)
break;
}
}
else if(mode==FI_DOWNLOAD) {
else if(mode==FI_DOWNLOAD || mode==FI_USERXFER) {
getfilepath(&cfg, f, path);
if(getfilesize(&cfg, f) < 1L) { /* getfilesize will set this to -1 if non-existant */
SYNC; /* and 0 byte files shouldn't be d/led */
......
......@@ -550,6 +550,10 @@ bool sbbs_t::logon()
if(criterrs && SYSOP)
bprintf(text[CriticalErrors],criterrs);
if((i=getuserxfers(&cfg, /* from: */NULL, useron.number)) != 0)
bprintf(text[UserXferForYou],i,i>1 ? "s" : nulstr);
if((i=getuserxfers(&cfg, useron.alias, /* to: */0)) != 0)
bprintf(text[UnreceivedUserXfer],i,i>1 ? "s" : nulstr);
SYNC;
sys_status&=~SS_PAUSEON; /* Turn off the pause override flag */
if(online==ON_REMOTE)
......
......@@ -863,6 +863,7 @@ enum { /* Values for 'mode' in listfileinfo */
,FI_OLD /* Search/Remove files not downloaded since */
,FI_OLDUL /* Search/Remove files uploaded before */
,FI_OFFLINE /* Search/Remove files not online */
,FI_USERXFER /* User-to-user transfer Download */
};
enum XFER_TYPE { /* Values for type in xfer_prot_select() */
......
......@@ -57,6 +57,8 @@ void xfer_opts()
,cfg.max_batup);
sprintf(opt[i++],"%-33.33s%u","Max Files in Batch DL Queue"
,cfg.max_batdn);
sprintf(opt[i++],"%-33.33s%u","Max Users in User Transfers"
,cfg.max_userxfer);
sprintf(opt[i++],"%-33.33s%u%%","Default Credit on Upload"
,cfg.cdt_up_pct);
sprintf(opt[i++],"%-33.33s%u%%","Default Credit on Download"
......@@ -126,6 +128,18 @@ void xfer_opts()
cfg.max_batdn=atoi(tmp);
break;
case __COUNTER__:
uifc.helpbuf=
"`Maximum Destination Users in User to User Transfers:`\n"
"\n"
"This is the maximum number of users allowed in the destination user list\n"
"of a user to user file upload.\n"
;
uifc.input(WIN_MID,0,0
,"Maximum Destination Users in User to User Transfers"
,ultoa(cfg.max_userxfer,tmp,10),5,K_EDIT|K_NUMBER);
cfg.max_userxfer=atoi(tmp);
break;
case __COUNTER__:
uifc.helpbuf=
"`Default Percentage of Credits to Credit Uploader on Upload:`\n"
"\n"
......
......@@ -335,10 +335,8 @@ BOOL read_file_cfg(scfg_t* cfg, char* error, size_t maxerrlen)
if(!stricmp(cfg->dir[i]->sname,"SYSOP")) /* Sysop upload directory */
cfg->sysop_dir=i;
#if 0 // TODO: Remove or re-implement
else if(!stricmp(cfg->dir[i]->sname,"USER")) /* User to User xfer dir */
cfg->user_dir=i;
#endif
else if(!stricmp(cfg->dir[i]->sname,"UPLOADS")) /* Upload directory */
cfg->upload_dir=i;
else if(!stricmp(cfg->dir[i]->sname,"OFFLINE")) /* Offline files dir */
......
......@@ -201,8 +201,8 @@ const char * const text_defaults[TOTAL_TEXT]={
,"\x01\x6e\x01\x3f\x01\x6d\x53\x65\x6e\x64\x69\x6e\x67\x20\x6d\x65\x73\x73\x61\x67\x65\x20\x74\x6f\x20\x01\x68\x25\x73\x0d\x0a" // 121 SendingMessageToUser
,"\x0d\x0a\x01\x72\x01\x68\x4e\x6f\x20\x6f\x74\x68\x65\x72\x20\x61\x63\x74\x69\x76\x65\x20\x6e\x6f\x64\x65\x73\x2e\x01\x6e\x0d\x0a"
"" // 122 NoOtherActiveNodes
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x73\x65\x20\x74\x68\x65\x20\x65\x78\x74\x65\x72\x6e\x61\x6c\x20\x70"
"\x72\x6f\x67\x72\x61\x6d\x73\x2e\x0d\x0a" // 123 R_ExternalPrograms
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x73\x65\x20\x74\x68\x65\x20\x65\x78\x74\x65\x72\x6e\x61\x6c\x20\x70\x72\x6f"
"\x67\x72\x61\x6d\x73\x2e\x0d\x0a" // 123 R_ExternalPrograms
,"\x0d\x0a\x01\x2d\x01\x67\x55\x73\x61\x67\x65\x20\x53\x74\x61\x74\x69\x73\x74\x69\x63\x73\x20\x66\x6f\x72\x20\x01\x68\x25\x73\x20"
"\x23\x25\x64\x01\x6e\x0d\x0a\x0d\x0a" // 124 UserStats
,"\x01\x2d\x01\x67\x53\x75\x62\x2d\x62\x6f\x61\x72\x64\x73\x20\x6f\x66\x20\x01\x68\x25\x2d\x34\x30\x73\x20\x20\x20\x20\x20\x20\x20"
......@@ -269,25 +269,25 @@ const char * const text_defaults[TOTAL_TEXT]={
,"\x44\x65\x6c\x65\x74\x65\x20\x47\x75\x72\x75\x20\x66\x69\x6c\x65" // 163 DeleteGuruLogQ
,"\x01\x6e\x01\x67\x07\x54\x65\x6c\x65\x67\x72\x61\x6d\x20\x66\x72\x6f\x6d\x20\x01\x6e\x01\x68\x25\x73\x01\x6e\x01\x67\x20\x6f\x6e"
"\x20\x25\x73\x3a\x0d\x0a\x01\x68" // 164 TelegramFmt
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x2e\x0d\x0a" // 165 R_Download
,"\x0d\x0a\x01\x77\x01\x68\x53\x65\x61\x72\x63\x68\x69\x6e\x67\x20\x63\x75\x72\x72\x65\x6e\x74\x20\x6c\x69\x62\x72\x61\x72\x79\x20"
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x2e\x0d\x0a" // 165 R_Download
,"\x01\x2f\x01\x77\x01\x68\x53\x65\x61\x72\x63\x68\x69\x6e\x67\x20\x63\x75\x72\x72\x65\x6e\x74\x20\x6c\x69\x62\x72\x61\x72\x79\x20"
"\x40\x45\x4c\x4c\x49\x50\x53\x49\x53\x40\x0d\x0a\x01\x71" // 166 SearchingAllDirs
,"\x01\x77\x01\x68\x53\x65\x61\x72\x63\x68\x69\x6e\x67\x20\x61\x6c\x6c\x20\x6c\x69\x62\x72\x61\x72\x69\x65\x73\x20\x40\x45\x4c\x4c"
"\x49\x50\x53\x49\x53\x40\x0d\x0a\x01\x71" // 167 SearchingAllLibs
,"\x0d\x0a\x01\x77\x01\x68\x25\x75\x20\x46\x69\x6c\x65\x73\x20\x4c\x69\x73\x74\x65\x64\x2e\x0d\x0a" // 168 NFilesListed
,"\x0d\x0a\x01\x77\x01\x68\x45\x6d\x70\x74\x79\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x2e\x0d\x0a" // 169 EmptyDir
,"\x0d\x0a\x01\x6e\x01\x63\x53\x65\x61\x72\x63\x68\x69\x6e\x67\x20\x66\x6f\x72\x20\x66\x69\x6c\x65\x73\x20\x75\x70\x6c\x6f\x61\x64"
"\x65\x64\x20\x61\x66\x74\x65\x72\x01\x5c\x20\x01\x68\x25\x73\x01\x6e\x0d\x0a" // 170 NScanHdr
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x72\x65\x6d\x6f\x76\x65\x20\x66\x69\x6c\x65\x73\x2e\x0d\x0a" // 171 R_RemoveFiles
,"\x0d\x0a\x0d\x0a\x54\x68\x69\x73\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x69\x73\x20\x66\x75\x6c\x6c\x2e\x0d\x0a" // 172 DirFull
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x70\x6c\x6f\x61\x64\x2e\x0d\x0a" // 173 R_Upload
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x70\x6c\x6f\x61\x64\x20\x68\x65\x72\x65\x2e\x0d\x0a" // 174 CantUploadHere
,"\x01\x5f\x0d\x0a\x0d\x0a\x01\x79\x01\x68\x46\x69\x6c\x65\x73\x70\x65\x63\x3a\x20\x01\x6e\x01\x7e" // 175 FileSpec
,"\x01\x3f\x01\x63\x53\x65\x61\x72\x63\x68\x69\x6e\x67\x20\x66\x6f\x72\x20\x66\x69\x6c\x65\x73\x20\x75\x70\x6c\x6f\x61\x64\x65\x64"
"\x20\x61\x66\x74\x65\x72\x01\x5c\x20\x01\x68\x25\x73\x01\x6e\x0d\x0a" // 170 NScanHdr
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x72\x65\x6d\x6f\x76\x65\x20\x66\x69\x6c\x65\x73\x2e\x0d\x0a" // 171 R_RemoveFiles
,"\x01\x3f\x54\x68\x69\x73\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x69\x73\x20\x66\x75\x6c\x6c\x2e\x0d\x0a" // 172 DirFull
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x70\x6c\x6f\x61\x64\x2e\x0d\x0a" // 173 R_Upload
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x70\x6c\x6f\x61\x64\x20\x68\x65\x72\x65\x2e\x0d\x0a" // 174 CantUploadHere
,"\x01\x5f\x01\x3f\x01\x79\x01\x68\x46\x69\x6c\x65\x73\x70\x65\x63\x3a\x20\x01\x6e\x01\x7e" // 175 FileSpec
,"\x53\x59\x3a\x20" // 176 SystemPassword
,"\x0d\x0a\x0d\x0a\x4e\x6f\x20\x73\x79\x73\x6f\x70\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64"
"\x2e\x0d\x0a" // 177 NoSysopDir
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x70\x6c\x6f\x61\x64\x20\x74\x6f\x20\x73\x79\x73\x6f\x70\x2e\x0d\x0a"
"" // 178 CantUploadToSysop
,"\x01\x3f\x4e\x6f\x20\x73\x79\x73\x6f\x70\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x69\x73\x20\x63\x6f\x6e\x66\x69\x67\x75\x72"
"\x65\x64\x2e\x0d\x0a" // 177 NoSysopDir
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x75\x70\x6c\x6f\x61\x64\x20\x74\x6f\x20\x74\x68\x65\x20\x73\x79\x73\x6f\x70\x2e"
"\x0d\x0a" // 178 CantUploadToSysop
,"\x01\x2d\x01\x67\x44\x69\x72\x65\x63\x74\x6f\x72\x69\x65\x73\x20\x6f\x66\x20\x01\x68\x25\x2d\x34\x30\x2e\x34\x30\x73\x20\x20\x20"
"\x20\x20\x01\x6e\x01\x67\x46\x69\x6c\x65\x73\x0d\x0a\x0d\x0a\x01\x68" // 179 DirLstHdr
,"\x01\x6e\x01\x67\x28\x01\x68\x25\x75\x01\x6e\x01\x67\x29\x20\x25\x2d\x34\x30\x2e\x34\x30\x73\x20\x25\x31\x32\x2e\x31\x32\x73\x20"
......@@ -306,13 +306,13 @@ const char * const text_defaults[TOTAL_TEXT]={
"\x68\x20\x25\x64\x25\x25\x20\x6f\x66\x20\x74\x68\x65\x20\x63\x72\x65\x64\x69\x74\x20\x76\x61\x6c\x75\x65\x0d\x0a" // 186 TpUpload
,"\x41\x6c\x6c\x20\x64\x6f\x77\x6e\x6c\x6f\x61\x64\x73\x20\x61\x72\x65\x20\x72\x65\x77\x61\x72\x64\x65\x64\x20\x77\x69\x74\x68\x20"
"\x25\x64\x25\x25\x20\x6f\x66\x20\x74\x68\x65\x20\x63\x72\x65\x64\x69\x74\x20\x76\x61\x6c\x75\x65\x0d\x0a" // 187 TpDownload
,"\x0d\x0a\x0d\x0a\x4e\x6f\x20\x75\x73\x65\x72\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x2e"
"\x0d\x0a" // 188 NoUserDir
,"\x01\x3f\x4e\x6f\x20\x75\x73\x65\x72\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x69\x73\x20\x63\x6f\x6e\x66\x69\x67\x75\x72\x65"
"\x64\x2e\x0d\x0a" // 188 NoUserDir
,"\x0d\x0a\x54\x68\x65\x72\x65\x20\x61\x72\x65\x20\x6e\x6f\x20\x66\x69\x6c\x65\x73\x20\x66\x6f\x72\x20\x79\x6f\x75\x2e\x0d\x0a" // 189 NoFilesForYou
,"\x0d\x0a\x0d\x0a\x55\x73\x65\x72\x20\x74\x72\x61\x6e\x73\x66\x65\x72\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x69\x73\x20\x66"
"\x75\x6c\x6c\x2e\x0d\x0a" // 190 UserDirFull
,"\x0d\x0a\x0d\x0a\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x73\x65\x6e\x64\x20\x66\x69\x6c\x65\x73\x20\x74\x6f\x20\x75\x73\x65\x72"
"\x73\x2e\x0d\x0a" // 191 CantUploadToUser
,"\x01\x3f\x55\x73\x65\x72\x20\x74\x72\x61\x6e\x73\x66\x65\x72\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x69\x73\x20\x66\x75\x6c"
"\x6c\x2e\x0d\x0a" // 190 UserDirFull
,"\x01\x3f\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x73\x65\x6e\x64\x20\x66\x69\x6c\x65\x73\x20\x74\x6f\x20\x75\x73\x65\x72\x73\x2e"
"\x0d\x0a" // 191 CantUploadToUser
,"\x01\x6e\x01\x63\x4c\x69\x62\x72\x61\x72\x79\x20\x20\x20\x3a\x20\x28\x25\x75\x29\x20\x25\x73\x01\x79\x01\x68" // 192 BoxHdrLib
,"\x01\x6e\x01\x63\x44\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x3a\x20\x28\x25\x75\x29\x20\x25\x73\x01\x79\x01\x68" // 193 BoxHdrDir
,"\x01\x6e\x01\x63\x46\x69\x6c\x65\x73\x20\x20\x20\x20\x20\x3a\x20\x25\x75\x01\x79\x01\x68" // 194 BoxHdrFiles
......@@ -354,7 +354,7 @@ const char * const text_defaults[TOTAL_TEXT]={
,"\x07\x0d\x0a\x01\x72\x01\x68\x01\x69\x59\x6f\x75\x20\x63\x61\x6e\x27\x74\x20\x73\x65\x6e\x64\x20\x79\x6f\x75\x72\x73\x65\x6c\x66"
"\x20\x66\x69\x6c\x65\x73\x2e\x01\x6e\x0d\x0a\x0d\x0a" // 216 CantSendYourselfFiles
,"\x0d\x0a\x01\x2d\x01\x67\x41\x64\x64\x65\x64\x20\x74\x6f\x20\x64\x65\x73\x74\x69\x6e\x61\x74\x69\x6f\x6e\x20\x75\x73\x65\x72\x20"
"\x6c\x69\x73\x74\x3a\x20\x01\x77\x01\x68\x25\x73\x0d\x0a\x0d\x0a\x01\x6e" // 217 UserAddedToDestList
"\x6c\x69\x73\x74\x3a\x20\x01\x77\x01\x68\x25\x73\x20\x23\x25\x73\x0d\x0a\x0d\x0a\x01\x6e" // 217 UserAddedToDestList
,"\x0d\x0a\x01\x2d\x01\x67\x48\x6f\x77\x20\x64\x6f\x20\x79\x6f\x75\x20\x72\x61\x74\x65\x20\x74\x68\x65\x20\x63\x6f\x6e\x74\x65\x6e"
"\x74\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x66\x69\x6c\x65\x20\x28\x01\x68\x01\x77\x47\x01\x6e\x01\x67\x2c\x20\x01\x68\x01\x77\x52"
"\x01\x6e\x01\x67\x2c\x20\x6f\x72\x20\x01\x68\x01\x77\x58\x01\x6e\x01\x67\x29\x3a\x20\x01\x6e" // 218 RateThisFile
......@@ -581,8 +581,12 @@ const char * const text_defaults[TOTAL_TEXT]={
,"\x07\x01\x72\x01\x68\x01\x69\x25\x64\x20\x63\x72\x69\x74\x69\x63\x61\x6c\x20\x65\x72\x72\x6f\x72\x73\x20\x68\x61\x76\x65\x20\x6f"
"\x63\x63\x75\x72\x72\x65\x64\x2e\x20\x54\x79\x70\x65\x20\x3b\x45\x52\x52\x20\x61\x74\x20\x6d\x61\x69\x6e\x20\x6d\x65\x6e\x75\x2e"
"\x01\x6e\x0d\x0a" // 359 CriticalErrors
,"\x55\x6e\x75\x73\x65\x64\x33\x36\x30" // 360 UserXferForYou
,"\x55\x6e\x75\x73\x65\x64\x33\x36\x31" // 361 UnreceivedUserXfer
,"\x01\x5f\x01\x77\x01\x68\x59\x6f\x75\x20\x68\x61\x76\x65\x20\x25\x64\x20\x55\x73\x65\x72\x20\x74\x6f\x20\x55\x73\x65\x72\x20\x46"
"\x69\x6c\x65\x20\x54\x72\x61\x6e\x73\x66\x65\x72\x25\x73\x20\x77\x61\x69\x74\x69\x6e\x67\x20\x66\x6f\x72\x20\x79\x6f\x75\x0d\x0a"
"" // 360 UserXferForYou
,"\x01\x5f\x01\x77\x01\x68\x59\x6f\x75\x20\x68\x61\x76\x65\x20\x73\x65\x6e\x74\x20\x25\x64\x20\x75\x6e\x72\x65\x63\x65\x69\x76\x65"
"\x64\x20\x55\x73\x65\x72\x20\x74\x6f\x20\x55\x73\x65\x72\x20\x46\x69\x6c\x65\x20\x54\x72\x61\x6e\x73\x66\x65\x72\x25\x73\x0d\x0a"
"" // 361 UnreceivedUserXfer
,"\x52\x65\x61\x64\x20\x79\x6f\x75\x72\x20\x6d\x61\x69\x6c\x20\x6e\x6f\x77" // 362 ReadYourMailNowQ
,"\x53\x6f\x72\x72\x79\x2c\x20\x74\x68\x65\x20\x73\x79\x73\x74\x65\x6d\x20\x69\x73\x20\x63\x6c\x6f\x73\x65\x64\x20\x74\x6f\x20\x6e"
"\x65\x77\x20\x75\x73\x65\x72\x73\x2e\x0d\x0a" // 363 NoNewUsers
......
......@@ -227,6 +227,7 @@ bool sbbs_t::upload(uint dirnum)
uint i,j,k;
ulong space;
file_t f = {{}};
str_list_t dest_user_list = NULL;
/* Security Checks */
if(useron.rest&FLAG('U')) {
......@@ -372,13 +373,50 @@ bool sbbs_t::upload(uint dirnum)
}
else
upload_lastdesc[0]=0;
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;
}
char fdesc[LEN_FDESC + 1] = "";
bputs(text[EnterDescNow]);
i=LEN_FDESC-(strlen(descbeg)+strlen(descend));
getstr(upload_lastdesc,i,K_LINE|K_EDIT|K_AUTODEL|K_TRIM);
if(sys_status&SS_ABORT)
if(sys_status&SS_ABORT) {
strListFree(&dest_user_list);
return(false);
}
if(descend[0]) /* end of desc specified, so pad desc with spaces */
safe_snprintf(fdesc,sizeof(fdesc),"%s%-*s%s",descbeg,i,upload_lastdesc,descend);
else /* no end specified, so string ends at desc end */
......@@ -399,6 +437,8 @@ bool sbbs_t::upload(uint dirnum)
bool result = false;
smb_hfield_str(&f, SMB_FILENAME, fname);
smb_hfield_str(&f, SMB_FILEDESC, fdesc);
if(strListCount(dest_user_list) > 0)
smb_hfield_str(&f, RECIPIENTLIST, strListCombine(dest_user_list, tmp, sizeof(tmp), ","));
if(tags[0])
smb_hfield_str(&f, SMB_TAGS, tags);
if(fexistcase(path)) { /* File is on disk */
......@@ -448,6 +488,7 @@ bool sbbs_t::upload(uint dirnum)
}
}
smb_freefilemem(&f);
strListFree(&dest_user_list);
return result;
}
......@@ -498,7 +539,11 @@ bool sbbs_t::bulkupload(uint dirnum)
uint32_t cdt = (uint32_t)flength(str);
smb_hfield_bin(&f, SMB_COST, cdt);
bprintf(text[BulkUploadDescPrompt], format_filename(f.name, fname, 12, /* pad: */FALSE), cdt/1024);
getstr(desc, LEN_FDESC, K_LINE);
if(strcmp(f.name, fname) != 0)
SAFECOPY(desc, f.name);
else
desc[0] = 0;
getstr(desc, LEN_FDESC, K_LINE|K_EDIT|K_AUTODEL);
if(sys_status&SS_ABORT)
break;
if(strcmp(desc,"-")==0) /* don't add this file */
......
......@@ -2439,6 +2439,7 @@ BOOL user_downloaded_file(scfg_t* cfg, user_t* user, client_t* client,
uint dirnum, const char* filename, off_t bytes)
{
file_t f;
bool removed = false;
if(!loadfile(cfg, dirnum, filename, &f, file_detail_normal))
return FALSE;
......@@ -2446,9 +2447,28 @@ BOOL user_downloaded_file(scfg_t* cfg, user_t* user, client_t* client,
if(!bytes)
bytes = getfilesize(cfg, &f);
if(dirnum == cfg->user_dir) {
str_list_t dest_user_list = strListSplitCopy(NULL, f.to_list, ",");
char usernum[16];
SAFEPRINTF(usernum, "%u", user->number);
int i = strListFind(dest_user_list, usernum, /* case-sensitive: */true);
if(i >= 0) {
strListFastDelete(dest_user_list, i);
char tmp[512];
smb_hfield_replace_str(&f, RECIPIENTLIST, strListCombine(dest_user_list, tmp, sizeof(tmp), ","));
}
if(strListCount(dest_user_list) < 1) {
char path[MAX_PATH + 1];
if(remove(getfilepath(cfg, &f, path)) == 0)
removed = removefile(cfg, dirnum, f.name);
}
strListFree(&dest_user_list);
}
f.hdr.times_downloaded++;
f.hdr.last_downloaded = time32(NULL);
if(!updatefile(cfg, &f)) {
if(!removed && !updatefile(cfg, &f)) {
smb_freefilemem(&f);
return FALSE;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment