Newer
Older
if (!isdir(path)) {
sockprintf(sock,sess, "501 Not a directory");
continue;
}
sockprintf(sock,sess, "150 Directory of %s", path);
backslash(path);
strcat(path, "*");
}
lprintf(LOG_INFO,"%04d %s MLSx listing: %s in %s mode", sock, user.alias, path, mode);
now=time(NULL);
if(localtime_r(&now,&cur_tm)==NULL)
memset(&cur_tm,0,sizeof(cur_tm));
if (cmd[3] == 'T') {
write_local_mlsx(NULL, sock, sess, mlsx_feats, path, TRUE);
sockprintf(sock, sess, "250 End");
}
else {
glob(path,0,NULL,&g);
for(i=0;i<(int)g.gl_pathc;i++)
write_local_mlsx(fp, INVALID_SOCKET, -1, mlsx_feats, g.gl_pathv[i], FALSE);
globfree(&g);
fclose(fp);
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,0L
,&transfer_inprogress,&transfer_aborted
,TRUE /* delfile */
,TRUE /* tmpfile */
,&lastactive,&user,&client,-1,FALSE,FALSE,FALSE,NULL,protection);
}
}
if(!strnicmp(cmd, "LIST", 4) || !strnicmp(cmd, "NLST", 4)) {
if(!strnicmp(cmd, "LIST", 4))
detail=TRUE;
else
detail=FALSE;
if((fp=fopen(ftp_tmpfname(fname,"lst",sock),"w+b"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d (%s) line %d opening %s (useron=%s)"
,sock, errno, strerror(errno), __LINE__, fname, user.alias);
sockprintf(sock,sess, "451 Insufficient system storage");
continue;
}
SKIP_WHITESPACE(p);
if(*p=='-') { /* -Letc */
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
filespec=p;
if(*filespec==0)
filespec="*";
SAFEPRINTF2(path,"%s%s",local_dir, filespec);
lprintf(LOG_INFO,"%04d %s listing: %s in %s mode", sock, user.alias, path, mode);
sockprintf(sock,sess, "150 Directory of %s%s", local_dir, filespec);
now=time(NULL);
if(localtime_r(&now,&cur_tm)==NULL)
memset(&cur_tm,0,sizeof(cur_tm));

rswindell
committed
glob(path,0,NULL,&g);
for(i=0;i<(int)g.gl_pathc;i++) {

rswindell
committed
f.size=flength(g.gl_pathv[i]);
t=fdate(g.gl_pathv[i]);
if(localtime_r(&t,&tm)==NULL)
fprintf(fp,"%crw-r--r-- 1 %-8s local %9"PRId32" %s %2d "

rswindell
committed
,isdir(g.gl_pathv[i]) ? 'd':'-'
,ftp_mon[tm.tm_mon],tm.tm_mday);
if(tm.tm_year==cur_tm.tm_year)
fprintf(fp,"%02d:%02d %s\r\n"
,tm.tm_hour,tm.tm_min

rswindell
committed
,getfname(g.gl_pathv[i]));
else
fprintf(fp,"%5d %s\r\n"
,1900+tm.tm_year

rswindell
committed
,getfname(g.gl_pathv[i]));

rswindell
committed
fprintf(fp,"%s\r\n",getfname(g.gl_pathv[i]));

rswindell
committed
globfree(&g);
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,0L
,&transfer_inprogress,&transfer_aborted
,TRUE /* delfile */
,TRUE /* tmpfile */
,&lastactive,&user,&client,-1,FALSE,FALSE,FALSE,NULL,protection);
continue;
} /* Local LIST/NLST */
if(!strnicmp(cmd, "CWD ", 4) || !strnicmp(cmd,"XCWD ",5)) {
if(!strnicmp(cmd,"CWD ",4))
p=cmd+4;
else
p=cmd+5;
SKIP_WHITESPACE(p);
tp=p;
if(*tp=='/' || *tp=='\\') /* /local: and /bbs: are valid */
tp++;
if(!strnicmp(tp,BBS_FSYS_DIR,strlen(BBS_FSYS_DIR))) {
local_fsys=FALSE;
sockprintf(sock,sess,"250 CWD command successful (BBS file system mounted).");
lprintf(LOG_INFO,"%04d %s mounted BBS file system", sock, user.alias);
continue;
}
if(!strnicmp(tp,LOCAL_FSYS_DIR,strlen(LOCAL_FSYS_DIR))) {
tp+=strlen(LOCAL_FSYS_DIR); /* already mounted */
p=tp;
}
if(p[1]==':' || !strncmp(p,"\\\\",2))
else if(*p=='/' || *p=='\\') {
SAFEPRINTF2(path,"%s%s",root_dir(local_dir),p+1);
p = FULLPATH(NULL, path, 0);
SAFECOPY(path, p);
free(p);
}
SAFEPRINTF2(fname,"%s%s",local_dir,p);
}
if(!direxist(path)) {
sockprintf(sock,sess,"550 Directory does not exist (%s).",path);
lprintf(LOG_WARNING,"%04d !%s attempted to change to an invalid directory: %s"
,sock, user.alias, path);
} else {
sockprintf(sock,sess,"250 CWD command successful (%s).", local_dir);
}
continue;
} /* Local CWD */
if(!stricmp(cmd,"CDUP") || !stricmp(cmd,"XCUP")) {
SAFEPRINTF(path,"%s..",local_dir);
if(FULLPATH(local_dir,path,sizeof(local_dir))==NULL)
continue;
}
if(!stricmp(cmd, "PWD") || !stricmp(cmd,"XPWD")) {
if(strlen(local_dir)>3)
local_dir[strlen(local_dir)-1]=0; /* truncate '/' */
,local_dir);
continue;
} /* Local PWD */
if(!strnicmp(cmd, "MKD ", 4) || !strnicmp(cmd,"XMKD",4)) {
p=cmd+4;
SKIP_WHITESPACE(p);
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_NOTICE,"%04d %s created directory: %s",sock,user.alias,fname);
sockprintf(sock,sess,"521 Error %d creating directory: %s",i,fname);
lprintf(LOG_WARNING,"%04d !%s attempted to create directory: %s (Error %d)"
,sock,user.alias,fname,i);
}
continue;
}
if(!strnicmp(cmd, "RMD ", 4) || !strnicmp(cmd,"XRMD",4)) {
p=cmd+4;
SKIP_WHITESPACE(p);
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_NOTICE,"%04d %s removed directory: %s",sock,user.alias,fname);
sockprintf(sock,sess,"450 Error %d removing directory: %s",i,fname);
lprintf(LOG_WARNING,"%04d !%s attempted to remove directory: %s (Error %d)"
,sock,user.alias,fname,i);
}
continue;
}
if(!strnicmp(cmd, "RNFR ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
SAFEPRINTF2(ren_from,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(ren_from,"%s%s",local_dir,p);
lprintf(LOG_WARNING,"%04d !%s attempted to rename %s (not found)"
,sock,user.alias,ren_from);
} else
sockprintf(sock,sess,"350 File exists, ready for destination name");
continue;
}
if(!strnicmp(cmd, "RNTO ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
if((i=rename(ren_from, fname))==0) {
sockprintf(sock,sess,"250 \"%s\" renamed to \"%s\"",ren_from,fname);
lprintf(LOG_NOTICE,"%04d %s renamed %s to %s",sock,user.alias,ren_from,fname);
sockprintf(sock,sess,"450 Error %d renaming file: %s",i,ren_from);
lprintf(LOG_WARNING,"%04d !%s attempted to rename file: %s (Error %d)"
,sock,user.alias,ren_from,i);
}
continue;
}
if(!strnicmp(cmd, "RETR ", 5) || !strnicmp(cmd,"SIZE ",5)
|| !strnicmp(cmd, "MDTM ",5) || !strnicmp(cmd, "DELE ",5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
if(!strnicmp(p,LOCAL_FSYS_DIR,strlen(LOCAL_FSYS_DIR)))
p+=strlen(LOCAL_FSYS_DIR); /* already mounted */
if(p[1]==':') /* drive specified */
else if(*p=='/') /* absolute, current drive */
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_WARNING,"%04d !%s file not found: %s",sock,user.alias,fname);
continue;
}
if(!strnicmp(cmd,"SIZE ",5)) {
continue;
}
if(!strnicmp(cmd,"MDTM ",5)) {
t=fdate(fname);
if(gmtime_r(&t,&tm)==NULL) /* specifically use GMT/UTC representation */
,1900+tm.tm_year,tm.tm_mon+1,tm.tm_mday
,tm.tm_hour,tm.tm_min,tm.tm_sec);
continue;
}
if(!strnicmp(cmd,"DELE ",5)) {
if((i=ftp_remove(sock, __LINE__, fname))==0) {
sockprintf(sock,sess,"250 \"%s\" removed successfully.",fname);
lprintf(LOG_NOTICE,"%04d %s deleted file: %s",sock,user.alias,fname);
sockprintf(sock,sess,"450 Error %d removing file: %s",i,fname);
lprintf(LOG_WARNING,"%04d !%s attempted to delete file: %s (Error %d)"
,sock,user.alias,fname,i);
}
continue;
}
/* RETR */
lprintf(LOG_INFO,"%04d %s downloading: %s (%"PRIuOFF" bytes) in %s mode"
,sock,user.alias,fname,flength(fname)
,mode);
sockprintf(sock,sess,"150 Opening BINARY mode data connection for file transfer.");
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,filepos
,&transfer_inprogress,&transfer_aborted,FALSE,FALSE
,&lastactive,&user,&client,-1,FALSE,FALSE,FALSE,NULL,protection);
continue;
} /* Local RETR/SIZE/MDTM */
if(!strnicmp(cmd, "STOR ", 5) || !strnicmp(cmd, "APPE ", 5)) {
p=cmd+5;
SKIP_WHITESPACE(p);
if(!strnicmp(p,LOCAL_FSYS_DIR,strlen(LOCAL_FSYS_DIR)))
p+=strlen(LOCAL_FSYS_DIR); /* already mounted */
if(p[1]==':') /* drive specified */
else if(*p=='/') /* absolute, current drive */
SAFEPRINTF2(fname,"%s%s",root_dir(local_dir),p+1);
SAFEPRINTF2(fname,"%s%s",local_dir,p);
lprintf(LOG_INFO,"%04d %s uploading: %s in %s mode", sock,user.alias,fname
,mode);
sockprintf(sock,sess,"150 Opening BINARY mode data connection for file transfer.");
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,filepos
,&transfer_inprogress,&transfer_aborted,FALSE,FALSE
,&lastactive
,&user
,-1 /* dir */
,TRUE /* uploading */
,FALSE /* credits */
,!strnicmp(cmd,"APPE",4) ? TRUE : FALSE /* append */
,NULL /* desc */
);
filepos=0;
continue;
} /* Local STOR */
}
if (!strnicmp(cmd, "MLS", 3)) {
if (cmd[3] == 'D' || cmd[3] == 'T') {
dir=curdir;
lib=curlib;
l = 0;
if(cmd[4]!=0)
lprintf(LOG_DEBUG,"%04d MLSx: %s",sock,cmd);
/* path specified? */
p=cmd+4;
if (*p == ' ')
p++;
if (parsepath(&p,&user,&client,&lib,&dir) == -1) {
sockprintf(sock,sess, "550 No such path");
continue;
}
if (strchr(p, '/')) {
sockprintf(sock,sess, "550 No such path");
continue;
}
if (cmd[3] == 'T') {
if (cmd[4])
strcpy(mls_path, cmd+5);
else
strcpy(mls_path, p);
}
else {
if (*p) {
sockprintf(sock,sess, "501 Not a directory");
continue;
}
strcpy(mls_path, p);
}
fp = NULL;
if (cmd[3] == 'D') {
if((fp=fopen(ftp_tmpfname(fname,"lst",sock),"w+b"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d (%s) line %d opening %s (useron=%s)"
,sock, errno, strerror(errno), __LINE__, fname, user.alias);
sockprintf(sock,sess, "451 Insufficient system storage");
continue;
}
sockprintf(sock,sess,"150 Opening ASCII mode data connection for MLSD.");
}
now=time(NULL);
if(localtime_r(&now,&cur_tm)==NULL)
memset(&cur_tm,0,sizeof(cur_tm));
/* ASCII Index File */
if(startup->options&FTP_OPT_INDEX_FILE && startup->index_file_name[0]
&& (cmd[3] == 'D' || strcmp(startup->index_file_name, mls_fname) == 0)) {
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", startup->index_file_name);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "file", "r", UINT64_MAX, 0, str, NULL, 0, cmd[3] == 'T' ? mls_path : startup->index_file_name);
l++;
}
/* HTML Index File */
if(startup->options&FTP_OPT_INDEX_FILE && startup->html_index_file[0]
&& (cmd[3] == 'D' || strcmp(startup->html_index_file, mls_fname) == 0)) {
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", startup->html_index_file);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "file", "r", UINT64_MAX, 0, str, NULL, 0, cmd[3] == 'T' ? mls_path : startup->html_index_file);
l++;
}
if(lib<0) { /* Root dir */
if (cmd[3] == 'T' && !*mls_fname) {
sockprintf(sock,sess, "250- Listing root");
strcpy(aliaspath, "/");
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", (startup->options&FTP_OPT_ALLOW_QWK) ? "elc" : "el", UINT64_MAX, 0, str, NULL, 0, aliaspath);
l++;
}
else {
send_mlsx_entry(fp, sock, sess, mlsx_feats, "cdir", (startup->options&FTP_OPT_ALLOW_QWK) ? "elc" : "el", UINT64_MAX, 0, str, NULL, 0, "/");
}
lprintf(LOG_INFO,"%04d %s listing: root in %s mode",sock,user.alias, mode);
/* QWK Packet */
if(startup->options&FTP_OPT_ALLOW_QWK) {
SAFEPRINTF(str,"%s.qwk",scfg.sys_id);
if (cmd[3] == 'D' || strcmp(str, mls_fname) == 0) {
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", str);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "file", "r", UINT64_MAX, 0, str, NULL, 0, cmd[3] == 'T' ? mls_path : str);
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
l++;
}
}
/* File Aliases */
sprintf(aliasfile,"%sftpalias.cfg",scfg.ctrl_dir);
if((alias_fp=fopen(aliasfile,"r"))!=NULL) {
while(!feof(alias_fp)) {
if(!fgets(aliasline,sizeof(aliasline),alias_fp))
break;
alias_dir=FALSE;
p=aliasline; /* alias pointer */
SKIP_WHITESPACE(p);
if(*p==';') /* comment */
continue;
tp=p; /* terminator pointer */
FIND_WHITESPACE(tp);
if(*tp) *tp=0;
np=tp+1; /* filename pointer */
SKIP_WHITESPACE(np);
tp=np; /* terminator pointer */
FIND_WHITESPACE(tp);
if(*tp) *tp=0;
dp=tp+1; /* description pointer */
SKIP_WHITESPACE(dp);
truncsp(dp);
if(stricmp(dp,BBS_HIDDEN_ALIAS)==0)
continue;
/* Virtual Path? */
aliaspath[0]=0;
if(!strnicmp(np,BBS_VIRTUAL_PATH,strlen(BBS_VIRTUAL_PATH))) {
if((dir=getdir(np+strlen(BBS_VIRTUAL_PATH),&user,&client))<0) {
lprintf(LOG_WARNING,"0000 !Invalid virtual path (%s) for %s",np,user.alias);
continue; /* No access or invalid virtual path */
}
tp=strrchr(np,'/');
if(tp==NULL)
continue;
tp++;
if(*tp) {
SAFEPRINTF2(aliasfile,"%s%s",scfg.dir[dir]->path,tp);
np=aliasfile;
SAFEPRINTF3(aliaspath,"/%s/%s/%s", scfg.lib[scfg.dir[dir]->lib]->sname, scfg.dir[dir]->code_suffix, tp);
alias_dir=TRUE;
SAFEPRINTF2(aliaspath,"/%s/%s", scfg.lib[scfg.dir[dir]->lib]->sname, scfg.dir[dir]->code_suffix);
}
}
if(!alias_dir && !fexist(np)) {
lprintf(LOG_WARNING,"0000 !Missing aliased file (%s) for %s",np,user.alias);
continue;
}
if(cmd[3] == 'D' || strcmp(startup->html_index_file, mls_fname) == 0) {
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", p);
get_unique(aliaspath, uniq);
if (cmd[3] == 'D') {
if (alias_dir==TRUE)
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", "el", UINT64_MAX, 0, NULL, uniq, 0, p);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "file", "r", (uint64_t)flength(np), fdate(np), NULL, uniq, 0, p);
if (alias_dir==TRUE)
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", "el", UINT64_MAX, 0, NULL, uniq, 0, aliaspath[0] ? aliaspath : mls_path);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "file", "r", (uint64_t)flength(np), fdate(np), NULL, uniq, 0, mls_path);
l++;
}
}
fclose(alias_fp);
}
/* Library folders */
for(i=0;i<scfg.total_libs;i++) {
if(!chk_ar(&scfg,scfg.lib[i]->ar,&user,&client))
continue;
if (cmd[3] != 'D' && strcmp(scfg.lib[i]->sname, mls_fname) != 0)
continue;
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", scfg.lib[i]->sname);
get_libperm(scfg.lib[i], &user, &client, permstr);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", permstr, UINT64_MAX, 0, str, NULL, 0, cmd[3] == 'T' ? mls_path : scfg.lib[i]->sname);
l++;
}
} else if(dir<0) {
if (cmd[3] == 'T' && !*mls_fname) {
sockprintf(sock,sess, "250- Listing %s", scfg.lib[lib]->sname);
SAFEPRINTF(aliaspath, "/%s", scfg.lib[lib]->sname);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", "el", UINT64_MAX, 0, str, NULL, 0, aliaspath);
l++;
}
if (cmd[3] == 'D') {
get_owner_name(NULL, str);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "pdir", (startup->options&FTP_OPT_ALLOW_QWK) ? "elc" : "el", UINT64_MAX, 0, str, NULL, 0, "/");
SAFEPRINTF(aliaspath, "/%s", scfg.lib[lib]->sname);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "cdir", (startup->options&FTP_OPT_ALLOW_QWK) ? "elc" : "el", UINT64_MAX, 0, str, NULL, 0, aliaspath);
lprintf(LOG_INFO,"%04d %s listing: %s library in %s mode"
,sock,user.alias,scfg.lib[lib]->sname,mode);
for(i=0;i<scfg.total_dirs;i++) {
if(scfg.dir[i]->lib!=lib)
continue;
if(i!=(int)scfg.sysop_dir && i!=(int)scfg.upload_dir
&& !chk_ar(&scfg,scfg.dir[i]->ar,&user,&client))
continue;
if (cmd[3] != 'D' && strcmp(scfg.dir[i]->code_suffix, mls_fname) != 0)
continue;
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", scfg.dir[i]->code_suffix);
get_dirperm(scfg.lib[lib], scfg.dir[i], &user, &client, permstr);
SAFEPRINTF2(aliaspath, "/%s/%s", scfg.lib[lib]->sname, scfg.dir[i]->code_suffix);
get_unique(aliaspath, uniq);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", permstr, UINT64_MAX, 0, str, uniq, 0, cmd[3] == 'T' ? mls_path : scfg.dir[i]->code_suffix);
l++;
}
} else if(chk_ar(&scfg,scfg.dir[dir]->ar,&user,&client)) {
lprintf(LOG_INFO,"%04d %s listing: %s/%s directory in %s mode"
,sock,user.alias,scfg.lib[lib]->sname,scfg.dir[dir]->code_suffix,mode);
if (cmd[3] == 'T' && !*mls_fname) {
sockprintf(sock,sess, "250- Listing %s/%s",scfg.lib[lib]->sname,scfg.dir[dir]->code_suffix);
SAFEPRINTF2(aliaspath, "/%s/%s", scfg.lib[lib]->sname, scfg.dir[dir]->code_suffix);
get_unique(aliaspath, uniq);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "dir", (startup->options&FTP_OPT_ALLOW_QWK) ? "elc" : "el", UINT64_MAX, 0, str, uniq, 0, aliaspath);
l++;
}
if (cmd[3] == 'D') {
get_libperm(scfg.lib[lib], &user, &client, permstr);
get_owner_name(NULL, str);
SAFEPRINTF(aliaspath, "/%s", scfg.lib[lib]->sname);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "pdir", permstr, UINT64_MAX, 0, str, NULL, 0, aliaspath);
SAFEPRINTF2(aliaspath, "/%s/%s", scfg.lib[lib]->sname, scfg.dir[dir]->code_suffix);
get_unique(aliaspath, uniq);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "cdir", permstr, UINT64_MAX, 0, str, NULL, 0, aliaspath);
SAFEPRINTF2(path,"%s%s",scfg.dir[dir]->path,"*");
glob(path,0,NULL,&g);
for(i=0;i<(int)g.gl_pathc;i++) {
if(isdir(g.gl_pathv[i]))
continue;
#ifdef _WIN32
GetShortPathName(g.gl_pathv[i], str, sizeof(str));
#else
SAFECOPY(str,g.gl_pathv[i]);
#endif
padfname(getfname(str),f.name);
f.dir=dir;
if((filedat=getfileixb(&scfg,&f))==FALSE
&& !(startup->options&FTP_OPT_DIR_FILES)
&& !(scfg.dir[dir]->misc&DIR_FILES))
continue;
if (cmd[3] != 'D' && strcmp(getfname(g.gl_pathv[i]), mls_fname) != 0)
continue;
if (cmd[3] == 'T')
sockprintf(sock,sess, "250- Listing %s", p);
get_fileperm(scfg.lib[lib], scfg.dir[dir], &user, &client, &f, permstr);
SAFEPRINTF3(aliaspath, "/%s/%s/%s", scfg.lib[lib]->sname, scfg.dir[dir]->code_suffix, getfname(g.gl_pathv[i]));
get_unique(aliaspath, uniq);
send_mlsx_entry(fp, sock, sess, mlsx_feats, "file", permstr, (uint64_t)flength(g.gl_pathv[i]), fdate(g.gl_pathv[i]), str, uniq, f.dateuled, cmd[3] == 'T' ? mls_path : getfname(g.gl_pathv[i]));
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
l++;
}
globfree(&g);
} else
lprintf(LOG_INFO,"%04d %s listing: %s/%s directory in %s mode (empty - no access)"
,sock,user.alias,scfg.lib[lib]->sname,scfg.dir[dir]->code_suffix,mode);
if (cmd[3] == 'D') {
fclose(fp);
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,0L
,&transfer_inprogress,&transfer_aborted
,TRUE /* delfile */
,TRUE /* tmpfile */
,&lastactive,&user,&client,dir,FALSE,FALSE,FALSE,NULL,protection);
}
else {
if (l==0)
sockprintf(sock,sess, "550 No such path");
else
sockprintf(sock, sess, "250 End");
}
continue;
}
}
if(!strnicmp(cmd, "LIST", 4) || !strnicmp(cmd, "NLST", 4)) {
dir=curdir;
lib=curlib;
if(cmd[4]!=0)
lprintf(LOG_DEBUG,"%04d LIST/NLST: %s",sock,cmd);
/* path specified? */
p=cmd+4;
SKIP_WHITESPACE(p);
if(*p=='-') { /* -Letc */
FIND_WHITESPACE(p);
SKIP_WHITESPACE(p);
if((fp=fopen(ftp_tmpfname(fname,"lst",sock),"w+b"))==NULL) {
lprintf(LOG_ERR,"%04d !ERROR %d (%s) line %d opening %s (useron=%s)"
,sock, errno, strerror(errno), __LINE__, fname, user.alias);
sockprintf(sock,sess,"150 Opening ASCII mode data connection for /bin/ls.");
if (parsepath(&p,&user,&client,&lib,&dir) == -1) {
/* Empty list */
fclose(fp);
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,0L
,&transfer_inprogress,&transfer_aborted
,TRUE /* delfile */
,TRUE /* tmpfile */
,&lastactive,&user,&client,dir,FALSE,FALSE,FALSE,NULL,protection);
continue;
}
filespec=p;
if(*filespec==0)
filespec="*";
if(!strnicmp(cmd, "LIST", 4))
detail=TRUE;
else
detail=FALSE;
now=time(NULL);
if(localtime_r(&now,&cur_tm)==NULL)
memset(&cur_tm,0,sizeof(cur_tm));
if(startup->options&FTP_OPT_INDEX_FILE && startup->index_file_name[0]
&& wildmatchi(startup->index_file_name, filespec, FALSE)) {
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,lib<0 ? scfg.sys_id : dir<0
? scfg.lib[lib]->sname : scfg.dir[dir]->code_suffix
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,startup->index_file_name);
else
fprintf(fp,"%s\r\n",startup->index_file_name);
}
/* HTML Index File */
if(startup->options&FTP_OPT_HTML_INDEX_FILE && startup->html_index_file[0]
&& wildmatchi(startup->html_index_file, filespec, FALSE)) {
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,lib<0 ? scfg.sys_id : dir<0
? scfg.lib[lib]->sname : scfg.dir[dir]->code_suffix
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,startup->html_index_file);
else
fprintf(fp,"%s\r\n",startup->html_index_file);
}
lprintf(LOG_INFO,"%04d %s listing: root in %s mode",sock,user.alias, mode);
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
if(startup->options&FTP_OPT_ALLOW_QWK) {
SAFEPRINTF(str,"%s.qwk",scfg.sys_id);
if(wildmatchi(str, filespec, FALSE)) {
if(detail) {
if(fexistcase(qwkfile)) {
t=fdate(qwkfile);
l=flength(qwkfile);
} else {
t=time(NULL);
l=10240;
};
if(localtime_r(&t,&tm)==NULL)
memset(&tm,0,sizeof(tm));
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.sys_id
,l
,ftp_mon[tm.tm_mon],tm.tm_mday,tm.tm_hour,tm.tm_min
,str);
} else
fprintf(fp,"%s\r\n",str);
}
}
/* File Aliases */

rswindell
committed
sprintf(aliasfile,"%sftpalias.cfg",scfg.ctrl_dir);
if((alias_fp=fopen(aliasfile,"r"))!=NULL) {
while(!feof(alias_fp)) {
if(!fgets(aliasline,sizeof(aliasline),alias_fp))
break;
alias_dir=FALSE;
p=aliasline; /* alias pointer */
SKIP_WHITESPACE(p);
if(*p==';') /* comment */
continue;
tp=p; /* terminator pointer */
FIND_WHITESPACE(tp);
if(*tp) *tp=0;
np=tp+1; /* filename pointer */
SKIP_WHITESPACE(np);
tp=np; /* terminator pointer */
FIND_WHITESPACE(tp);
dp=tp+1; /* description pointer */
SKIP_WHITESPACE(dp);
truncsp(dp);
if(stricmp(dp,BBS_HIDDEN_ALIAS)==0)
continue;
if(!wildmatchi(p, filespec, FALSE))
continue;
/* Virtual Path? */
if(!strnicmp(np,BBS_VIRTUAL_PATH,strlen(BBS_VIRTUAL_PATH))) {
if((dir=getdir(np+strlen(BBS_VIRTUAL_PATH),&user,&client))<0) {
lprintf(LOG_WARNING,"0000 !Invalid virtual path (%s) for %s",np,user.alias);
continue; /* No access or invalid virtual path */
tp=strrchr(np,'/');
if(tp==NULL)
continue;
tp++;
if(*tp) {
SAFEPRINTF2(aliasfile,"%s%s",scfg.dir[dir]->path,tp);
np=aliasfile;
}
else
alias_dir=TRUE;
}
if(!alias_dir && !fexist(np)) {
lprintf(LOG_WARNING,"0000 !Missing aliased file (%s) for %s",np,user.alias);
if(detail) {
if(alias_dir==TRUE) {
fprintf(fp,"drwxrwxrwx 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.lib[scfg.dir[dir]->lib]->sname
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,p);
}
else {
t=fdate(np);
if(localtime_r(&t,&tm)==NULL)
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9"PRIdOFF" %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.sys_id
,flength(np)
,ftp_mon[tm.tm_mon],tm.tm_mday,tm.tm_hour,tm.tm_min
,p);
}
} else
fprintf(fp,"%s\r\n",p);
}
fclose(alias_fp);
}
/* Library folders */
for(i=0;i<scfg.total_libs;i++) {
if(!wildmatchi(scfg.lib[i]->sname, filespec, FALSE))
continue;
fprintf(fp,"dr-xr-xr-x 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.sys_id
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,scfg.lib[i]->sname);
else
fprintf(fp,"%s\r\n",scfg.lib[i]->sname);
}
} else if(dir<0) {
lprintf(LOG_INFO,"%04d %s listing: %s library in %s mode"
,sock,user.alias,scfg.lib[lib]->sname,mode);
for(i=0;i<scfg.total_dirs;i++) {
if(scfg.dir[i]->lib!=lib)
continue;
if(i!=(int)scfg.sysop_dir && i!=(int)scfg.upload_dir
if(!wildmatchi(scfg.dir[i]->code_suffix, filespec, FALSE))
continue;
fprintf(fp,"drwxrwxrwx 1 %-*s %-8s %9ld %s %2d %02d:%02d %s\r\n"
,NAME_LEN
,scfg.sys_id
,scfg.lib[lib]->sname
,ftp_mon[cur_tm.tm_mon],cur_tm.tm_mday,cur_tm.tm_hour,cur_tm.tm_min
,scfg.dir[i]->code_suffix);
fprintf(fp,"%s\r\n",scfg.dir[i]->code_suffix);
} else if(chk_ar(&scfg,scfg.dir[dir]->ar,&user,&client)) {
lprintf(LOG_INFO,"%04d %s listing: %s/%s directory in %s mode"
,sock,user.alias,scfg.lib[lib]->sname,scfg.dir[dir]->code_suffix,mode);
SAFEPRINTF2(path,"%s%s",scfg.dir[dir]->path,filespec);

rswindell
committed
glob(path,0,NULL,&g);
for(i=0;i<(int)g.gl_pathc;i++) {
if(isdir(g.gl_pathv[i]))
continue;
#ifdef _WIN32
GetShortPathName(g.gl_pathv[i], str, sizeof(str));
#else
SAFECOPY(str,g.gl_pathv[i]);

rswindell
committed
#endif
padfname(getfname(str),f.name);

rswindell
committed
if((filedat=getfileixb(&scfg,&f))==FALSE
&& !(startup->options&FTP_OPT_DIR_FILES)
&& !(scfg.dir[dir]->misc&DIR_FILES))

rswindell
committed
continue;
if(detail) {
f.size=flength(g.gl_pathv[i]);
getfiledat(&scfg,&f);
t=fdate(g.gl_pathv[i]);
if(localtime_r(&t,&tm)==NULL)

rswindell
committed
memset(&tm,0,sizeof(tm));
if(filedat) {
if(f.misc&FM_ANON)
else
dotname(f.uler,str);
} else
fprintf(fp,"-r--r--r-- 1 %-*s %-8s %9"PRId32" %s %2d "

rswindell
committed
,NAME_LEN
,scfg.dir[dir]->code_suffix

rswindell
committed
,f.size
,ftp_mon[tm.tm_mon],tm.tm_mday);

rswindell
committed
if(tm.tm_year==cur_tm.tm_year)
fprintf(fp,"%02d:%02d %s\r\n"
,tm.tm_hour,tm.tm_min
,getfname(g.gl_pathv[i]));
else
fprintf(fp,"%5d %s\r\n"
,1900+tm.tm_year
,getfname(g.gl_pathv[i]));
} else
fprintf(fp,"%s\r\n",getfname(g.gl_pathv[i]));

rswindell
committed
globfree(&g);
lprintf(LOG_INFO,"%04d %s listing: %s/%s directory in %s mode (empty - no access)"
,sock,user.alias,scfg.lib[lib]->sname,scfg.dir[dir]->code_suffix,mode);
filexfer(&data_addr,sock,sess,pasv_sock,pasv_sess,&data_sock,&data_sess,fname,0L
,&transfer_inprogress,&transfer_aborted
,TRUE /* delfile */
,TRUE /* tmpfile */
,&lastactive,&user,&client,dir,FALSE,FALSE,FALSE,NULL,protection);

rswindell
committed
if(!strnicmp(cmd, "RETR ", 5)
|| !strnicmp(cmd, "SIZE ",5)
|| !strnicmp(cmd, "MDTM ",5)
|| !strnicmp(cmd, "DELE ",5)) {
getdate=FALSE;
getsize=FALSE;

rswindell
committed
delecmd=FALSE;
file_date=0;
if(!strnicmp(cmd,"SIZE ",5))
getsize=TRUE;
else if(!strnicmp(cmd,"MDTM ",5))
getdate=TRUE;

rswindell
committed
else if(!strnicmp(cmd,"DELE ",5))
delecmd=TRUE;
if(!getsize && !getdate && user.rest&FLAG('D')) {
filepos=0;
continue;
}
credits=TRUE;
success=FALSE;
delfile=FALSE;
tmpfile=FALSE;
lib=curlib;
dir=curdir;
p=cmd+5;
SKIP_WHITESPACE(p);
if(!strnicmp(p,BBS_FSYS_DIR,strlen(BBS_FSYS_DIR)))
p+=strlen(BBS_FSYS_DIR); /* already mounted */
if(*p=='/') {
lib=-1;
p++;
}
else if(!strncmp(p,"./",2))
p+=2;
if(lib<0 && ftpalias(p, fname, &user, &client, &dir)==TRUE) {
success=TRUE;
credits=TRUE; /* include in d/l stats */
tmpfile=FALSE;
delfile=FALSE;
lprintf(LOG_INFO,"%04d %s %.4s by alias: %s"
if(dir>=0)
lib=scfg.dir[dir]->lib;
}
if(!success && lib<0 && (tp=strchr(p,'/'))!=NULL) {
dir=-1;
*tp=0;
for(i=0;i<scfg.total_libs;i++) {
continue;
if(!stricmp(scfg.lib[i]->sname,p))
break;
}
if(i<scfg.total_libs)
lib=i;
p=tp+1;
}
if(!success && dir<0 && (tp=strchr(p,'/'))!=NULL) {
*tp=0;
for(i=0;i<scfg.total_dirs;i++) {
if(scfg.dir[i]->lib!=lib)
continue;
if(!stricmp(scfg.dir[i]->code_suffix,p))