Some file plugin structures RAII'ed.
This commit is contained in:
91
dpi/file.cc
91
dpi/file.cc
@ -38,6 +38,11 @@
|
|||||||
#include "dpiutil.hh"
|
#include "dpiutil.hh"
|
||||||
#include "d_size.h"
|
#include "d_size.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <compare>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugging macros
|
* Debugging macros
|
||||||
*/
|
*/
|
||||||
@ -69,18 +74,20 @@ typedef enum {
|
|||||||
st_err
|
st_err
|
||||||
} FileState;
|
} FileState;
|
||||||
|
|
||||||
typedef struct {
|
struct FileInfo {
|
||||||
char *full_path;
|
std::string full_path;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
off_t size;
|
off_t size;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
} FileInfo;
|
|
||||||
|
|
||||||
typedef struct {
|
std::strong_ordering operator <=> ( const FileInfo & ) const;
|
||||||
char *dirname;
|
};
|
||||||
Dlist *flist; /* List of files and subdirectories (for sorting) */
|
|
||||||
} DilloDir;
|
struct DilloDir {
|
||||||
|
std::string dirname;
|
||||||
|
std::vector< std::unique_ptr< FileInfo > > flist; /* List of files and subdirectories (for sorting) */
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Dsh *sh;
|
Dsh *sh;
|
||||||
@ -202,6 +209,17 @@ static int File_comp(const FileInfo *f1, const FileInfo *f2)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::strong_ordering
|
||||||
|
FileInfo::operator <=> ( const FileInfo &rhs ) const
|
||||||
|
{
|
||||||
|
const auto &lhs= *this;
|
||||||
|
const auto result= File_comp( &lhs, &rhs );
|
||||||
|
|
||||||
|
if( result < 0 ) return std::strong_ordering::less;
|
||||||
|
if( result > 0 ) return std::strong_ordering::greater;
|
||||||
|
return std::strong_ordering::equal;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a DilloDir structure, set safe values in it and sort the entries.
|
* Allocate a DilloDir structure, set safe values in it and sort the entries.
|
||||||
*/
|
*/
|
||||||
@ -210,19 +228,17 @@ static DilloDir *File_dillodir_new(char *dirname)
|
|||||||
struct stat sb;
|
struct stat sb;
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
DilloDir *Ddir;
|
std::unique_ptr< FileInfo > fifo;
|
||||||
FileInfo *finfo;
|
std::string fname;
|
||||||
char *fname;
|
|
||||||
int dirname_len;
|
int dirname_len;
|
||||||
|
|
||||||
if (!(dir = opendir(dirname)))
|
if (!(dir = opendir(dirname)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Ddir = dNew(DilloDir, 1);
|
auto Ddir = std::make_unique< DilloDir >();
|
||||||
Ddir->dirname = dStrdup(dirname);
|
Ddir->dirname = dirname;
|
||||||
Ddir->flist = dList_new(512);
|
|
||||||
|
|
||||||
dirname_len = strlen(Ddir->dirname);
|
dirname_len = Ddir->dirname.size();
|
||||||
|
|
||||||
/* Scan every name and sort them */
|
/* Scan every name and sort them */
|
||||||
while ((de = readdir(dir)) != 0) {
|
while ((de = readdir(dir)) != 0) {
|
||||||
@ -238,28 +254,28 @@ static DilloDir *File_dillodir_new(char *dirname)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fname = dStrconcat(Ddir->dirname, de->d_name, NULL);
|
fname = Ddir->dirname + de->d_name;
|
||||||
if (stat(fname, &sb) == -1) {
|
if (stat(fname.c_str(), &sb) == -1) {
|
||||||
dFree(fname);
|
|
||||||
continue; /* ignore files we can't stat */
|
continue; /* ignore files we can't stat */
|
||||||
}
|
}
|
||||||
|
|
||||||
finfo = dNew(FileInfo, 1);
|
auto finfo = std::make_unique< FileInfo >();
|
||||||
finfo->full_path = fname;
|
finfo->full_path = fname;
|
||||||
finfo->filename = fname + dirname_len;
|
finfo->filename = finfo->full_path.c_str() + dirname_len;
|
||||||
finfo->size = sb.st_size;
|
finfo->size = sb.st_size;
|
||||||
finfo->mode = sb.st_mode;
|
finfo->mode = sb.st_mode;
|
||||||
finfo->mtime = sb.st_mtime;
|
finfo->mtime = sb.st_mtime;
|
||||||
|
|
||||||
dList_append(Ddir->flist, finfo);
|
Ddir->flist.push_back( std::move( finfo ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
||||||
/* sort the entries */
|
/* sort the entries */
|
||||||
dList_sort(Ddir->flist, (dCompareFunc)File_comp);
|
std::sort( begin( Ddir->flist ), end( Ddir->flist ),
|
||||||
|
[]( const auto &lhs, const auto &rhs ) { return *lhs < *rhs; } );
|
||||||
|
|
||||||
return Ddir;
|
return Ddir.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -267,20 +283,7 @@ static DilloDir *File_dillodir_new(char *dirname)
|
|||||||
*/
|
*/
|
||||||
static void File_dillodir_free(DilloDir *Ddir)
|
static void File_dillodir_free(DilloDir *Ddir)
|
||||||
{
|
{
|
||||||
int i;
|
delete Ddir;
|
||||||
FileInfo *finfo;
|
|
||||||
|
|
||||||
dReturn_if (Ddir == NULL);
|
|
||||||
|
|
||||||
for (i = 0; i < dList_length(Ddir->flist); ++i) {
|
|
||||||
finfo = reinterpret_cast< FileInfo * >( dList_nth_data(Ddir->flist, i) );
|
|
||||||
dFree(finfo->full_path);
|
|
||||||
dFree(finfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
dList_free(Ddir->flist);
|
|
||||||
dFree(Ddir->dirname);
|
|
||||||
dFree(Ddir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -359,7 +362,7 @@ static void File_info2html(ClientInfo *client, FileInfo *finfo, int n)
|
|||||||
} else if (finfo->mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
|
} else if (finfo->mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
|
||||||
filecont = "Executable";
|
filecont = "Executable";
|
||||||
} else {
|
} else {
|
||||||
filecont = File_content_type(finfo->full_path);
|
filecont = File_content_type(finfo->full_path.c_str());
|
||||||
if (!filecont || !strcmp(filecont, "application/octet-stream"))
|
if (!filecont || !strcmp(filecont, "application/octet-stream"))
|
||||||
filecont = "unknown";
|
filecont = "unknown";
|
||||||
}
|
}
|
||||||
@ -424,9 +427,9 @@ static void File_send_dir(ClientInfo *client)
|
|||||||
/* send HTTP header and HTML top part */
|
/* send HTTP header and HTML top part */
|
||||||
|
|
||||||
/* Send page title */
|
/* Send page title */
|
||||||
auto Udirname = Escape_uri_str(Ddir->dirname, NULL);
|
auto Udirname = Escape_uri_str(Ddir->dirname.c_str(), NULL);
|
||||||
HUdirname = Escape_html_str(Udirname.c_str());
|
HUdirname = Escape_html_str(Udirname.c_str());
|
||||||
Hdirname = Escape_html_str(Ddir->dirname);
|
Hdirname = Escape_html_str(Ddir->dirname.c_str());
|
||||||
|
|
||||||
a_Dpip_dsh_printf(client->sh, 0,
|
a_Dpip_dsh_printf(client->sh, 0,
|
||||||
"HTTP/1.1 200 OK\r\n"
|
"HTTP/1.1 200 OK\r\n"
|
||||||
@ -445,13 +448,13 @@ static void File_send_dir(ClientInfo *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Output the parent directory */
|
/* Output the parent directory */
|
||||||
File_print_parent_dir(client, Ddir->dirname);
|
File_print_parent_dir(client, Ddir->dirname.c_str());
|
||||||
|
|
||||||
/* HTML style toggle */
|
/* HTML style toggle */
|
||||||
a_Dpip_dsh_write_str(client->sh, 0,
|
a_Dpip_dsh_write_str(client->sh, 0,
|
||||||
" <a href='dpi:/file/toggle'>%</a>\n");
|
" <a href='dpi:/file/toggle'>%</a>\n");
|
||||||
|
|
||||||
if (dList_length(Ddir->flist)) {
|
if (not Ddir->flist.empty()) {
|
||||||
if (client->old_style) {
|
if (client->old_style) {
|
||||||
a_Dpip_dsh_write_str(client->sh, 0, "\n\n");
|
a_Dpip_dsh_write_str(client->sh, 0, "\n\n");
|
||||||
} else {
|
} else {
|
||||||
@ -473,13 +476,13 @@ static void File_send_dir(ClientInfo *client)
|
|||||||
|
|
||||||
} else if (client->state == st_http) {
|
} else if (client->state == st_http) {
|
||||||
/* send directories as HTML contents */
|
/* send directories as HTML contents */
|
||||||
for (n = 0; n < dList_length(Ddir->flist); ++n) {
|
for (n = 0; n < Ddir->flist.size(); ++n) {
|
||||||
File_info2html(client, reinterpret_cast< FileInfo * >( dList_nth_data(Ddir->flist,n) ), n+1);
|
File_info2html(client, Ddir->flist.at( n ).get(), n+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->old_style) {
|
if (client->old_style) {
|
||||||
a_Dpip_dsh_write_str(client->sh, 0, "</pre>\n");
|
a_Dpip_dsh_write_str(client->sh, 0, "</pre>\n");
|
||||||
} else if (dList_length(Ddir->flist)) {
|
} else if (not Ddir->flist.empty()) {
|
||||||
a_Dpip_dsh_write_str(client->sh, 0, "</table>\n");
|
a_Dpip_dsh_write_str(client->sh, 0, "</table>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user