691 lines
15 KiB
C++
691 lines
15 KiB
C++
#define Use_LinkedList
|
|
|
|
#include <dir.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <dos.h>
|
|
#include <io.h>
|
|
#include <ctype.h>
|
|
#include "proboard.hpp"
|
|
|
|
static void MoveFailedFile(FileName full_fn);
|
|
|
|
static bool file_in_index(FileName fn);
|
|
bool check_dszlog(protocol& p , LinkedList<String>& downloads , LinkedList<String>& uploads);
|
|
|
|
void process_uploads(protocol& p , char *dir , LinkedList<String>& uploads , bool pvt , bool ask_desc , bool no_log , bool quiet_dl , String extra_log );
|
|
|
|
static char oldpath[70]="";
|
|
|
|
static char env_buf[80];
|
|
|
|
static void
|
|
pushdir(char *p)
|
|
{
|
|
char path[65];
|
|
unsigned disk;
|
|
|
|
strcpy(path,p);
|
|
getcwd(oldpath,69);
|
|
disk=toupper(path[0])-'A'+1;
|
|
|
|
_dos_setdrive(disk,&disk);
|
|
|
|
if(path[strlen(path)-1]=='\\')
|
|
path[strlen(path)-1]=0;
|
|
|
|
chdir(&path[2]);
|
|
}
|
|
|
|
static void
|
|
popdir()
|
|
{
|
|
unsigned disk = toupper(oldpath[0])-'A'+1;
|
|
_dos_setdrive(disk,&disk);
|
|
chdir(&oldpath[2]);
|
|
}
|
|
|
|
|
|
void
|
|
upload(char *data)
|
|
{
|
|
bool private_download = FALSE;
|
|
bool no_input = FALSE;
|
|
bool quiet_download = FALSE;
|
|
bool no_log = FALSE;
|
|
bool ask_description = TRUE;
|
|
char protocol_key = '\0';
|
|
char filename[13] = "";
|
|
FileName extra_log;
|
|
protocol p;
|
|
int i,npara;
|
|
String param[20];
|
|
char uploadpath[80];
|
|
|
|
adjust_limits();
|
|
|
|
strcpy(uploadpath , cfg.uploadpath);
|
|
|
|
npara = parse_data(data,param); // Parse command line
|
|
|
|
for(i=0 ; i<npara ; i++)
|
|
{
|
|
if(param[i][0]=='/')
|
|
switch(toupper(param[i][1]))
|
|
{
|
|
case 'F': strncpy(filename,¶m[i][3],12);
|
|
filename[12] = '\0';
|
|
no_input = TRUE;
|
|
break;
|
|
case 'P': private_download = TRUE;
|
|
no_input = TRUE;
|
|
strcpy(uploadpath , cfg.pvtuploadpath);
|
|
break;
|
|
case 'K': protocol_key = param[i][3];
|
|
break;
|
|
case 'Q': quiet_download = TRUE;
|
|
ask_description = FALSE;
|
|
break;
|
|
case 'N': no_log = TRUE;
|
|
break;
|
|
case 'L': extra_log = ¶m[i][3];
|
|
break;
|
|
case 'D': ask_description = FALSE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
strcpy(uploadpath , param[i]);
|
|
}
|
|
}
|
|
|
|
append_backspace(uploadpath);
|
|
strupr(uploadpath);
|
|
|
|
if(!no_log)
|
|
LOG(2,"Upload menu");
|
|
|
|
if(!quiet_download)
|
|
io << "\n\f" << S_UPLOAD_TITLE << "\n\n";
|
|
|
|
if(dos_getdiskfreespace(uploadpath[0]-'A'+1)<(1024L*cfg.uploadspace))
|
|
{
|
|
io << "\n\n" << S_NOT_ENOUGH_FREE_DISK_SPACE << "\n\n"
|
|
<< S_PRESS_ENTER_TO_CONTINUE;
|
|
|
|
return;
|
|
}
|
|
|
|
if(timer.left()<10 && time_removed>0 && !quiet_download)
|
|
{
|
|
io << S_NO_UPLOAD_DUE_TO_EVENT << "\n\n"
|
|
<< S_PRESS_ENTER_TO_CONTINUE;
|
|
|
|
return;
|
|
}
|
|
|
|
if(!select_protocol(p,protocol_key)) return;
|
|
|
|
if(!(p.flags&PROT_BATCH) && !no_input)
|
|
{
|
|
io << "\n\n" << S_FILE_TO_UPLOAD;
|
|
|
|
io.read(filename,12,READMODE_UPALL);
|
|
|
|
if(!*filename || strchr(filename,':') || strchr(filename,'\\'))
|
|
return;
|
|
|
|
io << '\n';
|
|
}
|
|
|
|
String command;
|
|
|
|
if(p.ulcom[0] != '@')
|
|
command << "*N*Q";
|
|
|
|
for(i=0;i<strlen(p.ulcom);i++)
|
|
if(p.ulcom[i] != '#')
|
|
{
|
|
command << p.ulcom[i];
|
|
}
|
|
else
|
|
{
|
|
command << uploadpath;
|
|
|
|
if(!(p.flags&PROT_BATCH)) command << filename;
|
|
}
|
|
|
|
if(!quiet_download)
|
|
{
|
|
io << '\n' << S_UPLOAD_START_PROMPT;
|
|
|
|
char k = wait_language_hotkeys(K_UPLOAD_START_PROMPT);
|
|
|
|
if(k==1) return;
|
|
|
|
io << "\n\n" << S_READY_TO_UPLOAD_FILES << '\xFF';
|
|
}
|
|
|
|
sprintf(env_buf,"DSZLOG=%s%s",mypath,p.logfile);
|
|
|
|
putenv(env_buf);
|
|
|
|
timer.suspend();
|
|
|
|
pushdir(uploadpath);
|
|
|
|
if(command[0]=='@')
|
|
{
|
|
run_sdkfile(replace_stringvars(&command[1]));
|
|
}
|
|
else
|
|
{
|
|
shell(replace_stringvars(command));
|
|
}
|
|
|
|
popdir();
|
|
|
|
timer.restart();
|
|
|
|
LinkedList<String> downloads , uploads;
|
|
|
|
check_dszlog(p , downloads , uploads);
|
|
|
|
if(!uploads.count())
|
|
{
|
|
if(!quiet_download)
|
|
{
|
|
io << "\n\n" << S_NO_FILES_RECEIVED << "\n\n"
|
|
<< S_PRESS_ENTER_TO_CONTINUE;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
process_uploads(p,uploadpath,uploads,private_download,ask_description,no_log,quiet_download,extra_log);
|
|
|
|
if(!quiet_download)
|
|
io << '\n' << S_PRESS_ENTER_TO_CONTINUE;
|
|
}
|
|
|
|
|
|
void
|
|
process_uploads(protocol& p , char *dir , LinkedList<String>& uploads , bool pvt ,
|
|
bool ask_desc ,
|
|
bool no_log ,
|
|
bool quiet_dl ,
|
|
String extra_log
|
|
)
|
|
{
|
|
long total_bytes = 0;
|
|
int total_files = 0;
|
|
String uploadpath(dir);
|
|
|
|
bool dupes_found = FALSE;
|
|
|
|
if(!quiet_dl)
|
|
io << "\n\n" << S_CHECKING_UPLOADS << "\n\xFF";
|
|
|
|
for( uploads.rewind() ; !uploads.eol() ; )
|
|
{
|
|
FileName fn( uploadpath , uploads.get() );
|
|
|
|
fn.upperCase();
|
|
|
|
FileName fullfn(fn);
|
|
|
|
DirScan scan(fullfn);
|
|
|
|
if(!int(scan))
|
|
{
|
|
uploads.remove();
|
|
|
|
continue;
|
|
}
|
|
|
|
fn.stripPath();
|
|
|
|
if(!quiet_dl)
|
|
io << '\n' << S_FILE_RECEIVED((char *)fn) << '\xFF';
|
|
|
|
Date date(TODAY);
|
|
Time time(NOW);
|
|
|
|
File ul_log;
|
|
|
|
if(!no_log)
|
|
{
|
|
ul_log.open(FileName(syspath,"UPLOAD.LOG"),fmode_text | fmode_append | fmode_write | fmode_copen);
|
|
|
|
ul_log.printf("%02d-%s-%02d %02d:%02d:%02d Upload of %-13s by %s\n",date[0],
|
|
months_short[date[1]],
|
|
date[2],
|
|
time[0],time[1],time[2],
|
|
(char *)fn,user.name);
|
|
ul_log.close();
|
|
}
|
|
|
|
if(extra_log.len())
|
|
{
|
|
ul_log.open(extra_log,fmode_text | fmode_append | fmode_write | fmode_copen);
|
|
ul_log.printf("U 0 %s %ld NO\n",(char *)fullfn,scan.size());
|
|
ul_log.close();
|
|
}
|
|
|
|
if(!pvt && cfg.checkdupes && file_in_index(fn) && !quiet_dl)
|
|
{
|
|
dupes_found = TRUE;
|
|
|
|
if(cfg.killdupes)
|
|
{
|
|
unlink(fullfn);
|
|
|
|
io << S_DUPLICATE_UPLOAD_REMOVED;
|
|
}
|
|
else
|
|
{
|
|
io << S_DUPLICATE_UPLOAD;
|
|
}
|
|
|
|
LOG(1,"Upload-%c %s (DUPE)",p.key,(char *)fn);
|
|
|
|
uploads.remove();
|
|
}
|
|
else
|
|
{
|
|
if(!no_log)
|
|
{
|
|
if(pvt)
|
|
LOG(1,"Upload-%c %s (Personal)",p.key,(char *)fn);
|
|
else
|
|
LOG(1,"Upload-%c %s",p.key,(char *)fn);
|
|
}
|
|
|
|
total_files++;
|
|
total_bytes += scan.size();
|
|
|
|
uploads++;
|
|
}
|
|
}
|
|
|
|
if(cfg.virScanCommand[0])
|
|
{
|
|
LinkedList<FileName> failed_files;
|
|
|
|
io << "\n\n" << S_SCANNING_UPLOADS;
|
|
|
|
for(uploads.rewind() ; !uploads.eol(); )
|
|
{
|
|
FileName curfile(uploadpath,uploads.get());
|
|
|
|
DirScan scan(curfile);
|
|
|
|
String cmd = String("*Q*N") + cfg.virScanCommand;
|
|
|
|
cmd.replace("@<FILE>@",curfile);
|
|
|
|
shell(replace_stringvars(cmd));
|
|
|
|
if( (cfg.virScanType && !access(cfg.virScanSemaphore,0))
|
|
|| (!cfg.virScanType && returnvalue)
|
|
)
|
|
{
|
|
LOG(1,"File '%s' rejected by upload scanner",(char *)curfile);
|
|
|
|
if(cfg.virScanFailedAction == VIRSCAN_ACTION_DELETE)
|
|
{
|
|
unlink(curfile);
|
|
}
|
|
|
|
if(cfg.virScanFailedAction == VIRSCAN_ACTION_MOVE)
|
|
{
|
|
MoveFailedFile(curfile);
|
|
}
|
|
|
|
uploads.remove();
|
|
|
|
failed_files.add(curfile);
|
|
|
|
total_files--;
|
|
total_bytes -= scan.size();
|
|
}
|
|
else
|
|
{
|
|
uploads++;
|
|
}
|
|
}
|
|
|
|
if(failed_files.count())
|
|
{
|
|
io << "\n\n" << S_FOLLOWING_FILES_REJECTED << "\n\n";
|
|
|
|
for(failed_files.rewind() ; !failed_files.eol() ; failed_files++)
|
|
{
|
|
FileName fn = failed_files.get();
|
|
|
|
fn.stripPath();
|
|
|
|
io << " " << (char *)fn << '\n';
|
|
}
|
|
|
|
io << '\n' << S_PRESS_ENTER_TO_CONTINUE;
|
|
}
|
|
}
|
|
|
|
|
|
if(total_files)
|
|
{
|
|
if(!pvt)
|
|
{
|
|
user.numUploads += total_files;
|
|
user.kbUploaded += int(total_bytes/1024L);
|
|
|
|
if(!quiet_dl)
|
|
io << "\n\n" << S_X_FILES_UPLOADED(form("%d",total_files),form("%ld",total_bytes/1024L)) << '\n';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!quiet_dl)
|
|
io << "\n\n" << S_NO_FILES_UPLOADED << '\n';
|
|
|
|
return;
|
|
}
|
|
|
|
if(!ask_desc) return;
|
|
|
|
if(dupes_found && !quiet_dl) showansascrip("DUPESFND");
|
|
|
|
if(!pvt && uploads.count())
|
|
io << '\n'
|
|
<< S_PLEASE_ENTER_UPLOAD_DESCRIPTIONS
|
|
<< "\n\n";
|
|
|
|
for(uploads.rewind() ; !uploads.eol(); uploads++)
|
|
{
|
|
io.clearinput();
|
|
|
|
if(pvt)
|
|
{
|
|
User tmpuser;
|
|
char username[36];
|
|
|
|
for(;;)
|
|
{
|
|
io << '\n' << S_ENTER_USERNAME_FOR_PERSONAL_FILE((char *)uploads.get());
|
|
io.read(username,35,READMODE_UPFIRST);
|
|
|
|
if(!strcmpl(username,"Sysop")) strcpy(username,cfg.sysopname);
|
|
if(tmpuser.search(username)) break;
|
|
io << "\n\n" << S_USER_NOT_LOCATED << '\n';
|
|
}
|
|
|
|
File f(FN_PVTFILES_PB,fmode_rw | fmode_copen);
|
|
if(!f.opened())
|
|
{
|
|
LOG("Unable to create PVTFILES.PB");
|
|
continue;
|
|
}
|
|
|
|
_PrivateFile pvt;
|
|
|
|
for(int rec=0;;rec++)
|
|
{
|
|
if(f.read(&pvt,sizeof(pvt))!=sizeof(pvt)) break;
|
|
|
|
if(!pvt.fname[0]) break;
|
|
}
|
|
strcpy(pvt.fname,uploads.get());
|
|
strcpy(pvt.to,username);
|
|
strcpy(pvt.from,user.name);
|
|
pvt.date.today();
|
|
f.seek(long(rec)*sizeof(pvt));
|
|
f.write(&pvt,sizeof(pvt));
|
|
}
|
|
else
|
|
{
|
|
FileName fbbs;
|
|
char descr[41];
|
|
|
|
io << '\n' << S_ENTER_DESCRIPTION_LINE_1((char *)uploads.get());
|
|
|
|
io.clearinput();
|
|
io.read(descr,40);
|
|
|
|
if(descr[0]!='/')
|
|
fbbs(uploadpath,"FILES.BBS");
|
|
else
|
|
fbbs(uploadpath,"FILES.PVT");
|
|
|
|
File tf(fbbs,fmode_write | fmode_append | fmode_text | fmode_copen);
|
|
tf << form("%-12s %s\n",(char *)uploads.get(),((descr[0]=='/') ? (&descr[1]) : descr));
|
|
while(descr[0])
|
|
{
|
|
io << '\n' << S_ENTER_DESCRIPTION_LINE_X;
|
|
io.read(descr,40);
|
|
if(descr[0]) tf << '+' << ((descr[0]=='/') ? (&descr[1]) : descr) << '\n';
|
|
}
|
|
|
|
if(cfg.addUploaderName)
|
|
tf << '+' << "[Uploader: " << user.name << ']\n';
|
|
}
|
|
}
|
|
|
|
io << '\n';
|
|
}
|
|
|
|
|
|
bool
|
|
file_in_index(FileName fn)
|
|
{
|
|
if(cfg.ignore_ext) fn.stripExt();
|
|
|
|
File idx;
|
|
|
|
if(idx.open(FileName(syspath,"FILESIDX.PB") , fmode_read , cfg.fastmode ? 8192:2048))
|
|
{
|
|
FilesIdx fidx;
|
|
|
|
for(;;)
|
|
{
|
|
if(idx.read(&fidx,sizeof(fidx)) != sizeof(fidx)) break;
|
|
|
|
if(cfg.ignore_ext)
|
|
if(strchr(fidx.name,'.'))
|
|
*strchr(fidx.name,'.') = '\0';
|
|
|
|
if(!stricmp(fidx.name,fn)) return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
bool
|
|
check_dszlog(protocol& p , LinkedList<String>& downloads , LinkedList<String>& uploads)
|
|
{
|
|
File dszlog;
|
|
int i;
|
|
char s[200];
|
|
|
|
if(dszlog.open(p.logfile,fmode_read | fmode_text))
|
|
{
|
|
|
|
while(dszlog.readLine(s,199))
|
|
{
|
|
bool found_upload = FALSE;
|
|
bool found_download = FALSE;
|
|
|
|
strip_linefeed(s);
|
|
|
|
char *ptr=strtok(s," ");
|
|
|
|
while(ptr)
|
|
{
|
|
if(!strcmp(ptr,p.dlkeyword))
|
|
{
|
|
found_download = TRUE;
|
|
break;
|
|
}
|
|
if(!strcmp(ptr,p.ulkeyword))
|
|
{
|
|
found_upload = TRUE;
|
|
break;
|
|
}
|
|
|
|
ptr = strtok(NULL," ");
|
|
}
|
|
|
|
if(ptr == NULL) continue;
|
|
|
|
for(i=0;i<p.wordnr && ptr!=NULL;i++) ptr = strtok(NULL," ");
|
|
|
|
if(ptr==NULL) continue;
|
|
|
|
strip_path(ptr);
|
|
strupr(ptr);
|
|
|
|
if(found_download)
|
|
downloads.add( String(ptr) );
|
|
|
|
if(found_upload)
|
|
uploads.add( String(ptr) );
|
|
}
|
|
|
|
dszlog.close();
|
|
|
|
unlink(p.ctlfile);
|
|
unlink(p.logfile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
unlink(p.ctlfile);
|
|
unlink(p.logfile);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
bool
|
|
create_dszctl(protocol& p , LinkedList<DownloadFile>& files)
|
|
{
|
|
File tf;
|
|
|
|
if(!tf.open(p.ctlfile,fmode_create | fmode_text))
|
|
return FALSE;
|
|
|
|
for(files.rewind() ; !files.eol() ; files++)
|
|
{
|
|
if(p.flags&PROT_BIM)
|
|
{
|
|
tf << form("U %-80s%-160s",(char *) files.get().name,EMPTY_STRING);
|
|
}
|
|
else
|
|
{
|
|
for(int j=0;j<strlen(p.dlstring);j++)
|
|
if(p.dlstring[j]=='#')
|
|
tf << (char *)files.get().name;
|
|
else
|
|
tf << p.dlstring[j];
|
|
|
|
tf << '\n';
|
|
}
|
|
}
|
|
|
|
files.rewind();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool
|
|
send_files( protocol& p , LinkedList<DownloadFile>& files , LinkedList<String>& downloads , LinkedList<String>& uploads )
|
|
{
|
|
if(!strchr(p.dlcom,'#'))
|
|
if(!create_dszctl(p , files)) return FALSE;
|
|
|
|
String command;
|
|
|
|
if(p.dlcom[0] != '@')
|
|
command << "*N*Q";
|
|
|
|
files.rewind();
|
|
|
|
for(int i=0;i<strlen(p.dlcom);i++)
|
|
if(p.dlcom[i] != '#')
|
|
command << p.dlcom[i];
|
|
else
|
|
command << files.get().name;
|
|
|
|
sprintf(env_buf,"DSZLOG=%s%s",mypath,p.logfile);
|
|
|
|
putenv(env_buf);
|
|
|
|
if(command[0]=='@')
|
|
run_sdkfile(replace_stringvars(&command[1]));
|
|
else
|
|
shell(replace_stringvars(command));
|
|
|
|
return check_dszlog(p , downloads , uploads);
|
|
}
|
|
|
|
void
|
|
create_dirlist(int area,char *firstdir,LinkedList<String>& dirlist)
|
|
{
|
|
File f(FileName(syspath,form("FA_%d.CTL",area)),fmode_read | fmode_text);
|
|
|
|
dirlist.rewind();
|
|
|
|
dirlist.add(String(firstdir));
|
|
|
|
for(;;)
|
|
{
|
|
char str[128];
|
|
|
|
if(!f.readLine(str,127)) break;
|
|
|
|
append_backspace(str);
|
|
|
|
dirlist.add(String(str));
|
|
}
|
|
}
|
|
|
|
bool
|
|
is_freefile(char *fname)
|
|
{
|
|
File fp(FileName(syspath,"FREEFILE.CTL"),fmode_read | fmode_text);
|
|
|
|
if(!fp.opened()) return FALSE;
|
|
|
|
for(;;)
|
|
{
|
|
char s[100];
|
|
|
|
if(!fp.readLine(s,99)) return FALSE;
|
|
|
|
strip_linefeed(s);
|
|
strip_leading(s);
|
|
strip_trailing(s);
|
|
|
|
if(matchfile(s,fname)) return TRUE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
MoveFailedFile(FileName full_fn)
|
|
{
|
|
FileArea fa;
|
|
FileName fn = full_fn;
|
|
|
|
fn.stripPath();
|
|
|
|
if(fa.read(cfg.virScanFailedArea))
|
|
{
|
|
ts_CopyFile(full_fn,fa.filepath,4096);
|
|
unlink(full_fn);
|
|
|
|
File f(fa.listpath,fmode_rw|fmode_append|fmode_copen);
|
|
f.printf("%-12s <FAILED> Uploaded by %s\n",(char *)fn,user.name);
|
|
}
|
|
}
|