From bf3daa15e9e744d9481d9e6d1e250b77d1f7b256 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 15 Jun 2013 16:45:12 +0200 Subject: add directory listing to the webserver Git-Dch: Ignore --- test/interactive-helper/aptwebserver.cc | 121 ++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/test/interactive-helper/aptwebserver.cc b/test/interactive-helper/aptwebserver.cc index 98bbde21b..d25f50624 100644 --- a/test/interactive-helper/aptwebserver.cc +++ b/test/interactive-helper/aptwebserver.cc @@ -13,12 +13,14 @@ #include #include +#include #include #include #include #include #include #include +#include #include char const * const httpcodeToStr(int const httpcode) /*{{{*/ @@ -164,6 +166,118 @@ void sendError(int const client, int const httpcode, std::string const &request, sendData(client, response); } /*}}}*/ +void sendRedirect(int const client, int const httpcode, std::string const &uri,/*{{{*/ + std::string const &request, bool content) +{ + std::list headers; + std::string response(""); + response.append(httpcodeToStr(httpcode)).append(""); + response.append("

").append(httpcodeToStr(httpcode)).append("You should be redirected to ").append(uri).append("

"); + response.append("This page is a result of the request:
");
+   response.append(request).append("
"); + addDataHeaders(headers, response); + std::string location("Location: "); + if (strncmp(uri.c_str(), "http://", 7) != 0) + location.append("http://").append(LookupTag(request, "Host")).append("/").append(uri); + else + location.append(uri); + headers.push_back(location); + sendHead(client, httpcode, headers); + if (content == true) + sendData(client, response); +} + /*}}}*/ +int filter_hidden_files(const struct dirent *a) /*{{{*/ +{ + if (a->d_name[0] == '.') + return 0; +#ifdef _DIRENT_HAVE_D_TYPE + // if we have the d_type check that only files and dirs will be included + if (a->d_type != DT_UNKNOWN && + a->d_type != DT_REG && + a->d_type != DT_LNK && // this includes links to regular files + a->d_type != DT_DIR) + return 0; +#endif + return 1; +} +int grouped_alpha_case_sort(const struct dirent **a, const struct dirent **b) { +#ifdef _DIRENT_HAVE_D_TYPE + if ((*a)->d_type == DT_DIR && (*b)->d_type == DT_DIR); + else if ((*a)->d_type == DT_DIR && (*b)->d_type == DT_REG) + return -1; + else if ((*b)->d_type == DT_DIR && (*a)->d_type == DT_REG) + return 1; + else +#endif + { + struct stat f_prop; //File's property + stat((*a)->d_name, &f_prop); + int const amode = f_prop.st_mode; + stat((*b)->d_name, &f_prop); + int const bmode = f_prop.st_mode; + if (S_ISDIR(amode) && S_ISDIR(bmode)); + else if (S_ISDIR(amode)) + return -1; + else if (S_ISDIR(bmode)) + return 1; + } + return strcasecmp((*a)->d_name, (*b)->d_name); +} + /*}}}*/ +void sendDirectoryListing(int const client, std::string const &dir, /*{{{*/ + std::string const &request, bool content) +{ + std::list headers; + std::ostringstream listing; + + struct dirent **namelist; + int const counter = scandir(dir.c_str(), &namelist, filter_hidden_files, grouped_alpha_case_sort); + if (counter == -1) + { + sendError(client, 500, request, content); + return; + } + + listing << "Index of " << dir << "" + << "" + << "" << std::endl + << "

Index of " << dir << "

" << std::endl + << "" << std::endl; + if (dir != ".") + listing << ""; + for (int i = 0; i < counter; ++i) { + struct stat fs; + std::string filename(dir); + filename.append("/").append(namelist[i]->d_name); + stat(filename.c_str(), &fs); + if (S_ISDIR(fs.st_mode)) + { + listing << "" + << "" + << ""; + } + else + { + listing << "" + << "" + << ""; + } + listing << "" << std::endl; + } + listing << "
#NameSizeLast-Modified
dParent Directory--
dd_name << "/\">" << namelist[i]->d_name << "-
fd_name << "\">" << namelist[i]->d_name << "" << SizeToStr(fs.st_size) << "B" << TimeRFC1123(fs.st_mtime) << "
" << std::endl; + + std::string response(listing.str()); + addDataHeaders(headers, response); + sendHead(client, 200, headers); + if (content == true) + sendData(client, response); +} + /*}}}*/ bool parseFirstLine(int const client, std::string const &request, /*{{{*/ std::string &filename, bool &sendContent, bool &closeConnection) @@ -326,6 +440,13 @@ int main(int const argc, const char * argv[]) if (sendContent == true) sendFile(client, data); } + else if (DirectoryExists(filename) == true) + { + if (filename == "." || filename[filename.length()-1] == '/') + sendDirectoryListing(client, filename, *m, sendContent); + else + sendRedirect(client, 301, filename.append("/"), *m, sendContent); + } else sendError(client, 404, *m, sendContent); } -- cgit v1.2.3