From bf3daa15e9e744d9481d9e6d1e250b77d1f7b256 Mon Sep 17 00:00:00 2001
From: David Kalnischkies
Date: Sat, 15 Jun 2013 16:45:12 +0200
Subject: [PATCH] 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
+ << "# | Name | Size | Last-Modified |
" << std::endl;
+ if (dir != ".")
+ listing << "d | Parent Directory | - | - |
";
+ 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 << "d | "
+ << "d_name << "/\">" << namelist[i]->d_name << " | "
+ << "- | ";
+ }
+ else
+ {
+ listing << "
f | "
+ << "d_name << "\">" << namelist[i]->d_name << " | "
+ << "" << SizeToStr(fs.st_size) << "B | ";
+ }
+ listing << "" << TimeRFC1123(fs.st_mtime) << " |
" << std::endl;
+ }
+ listing << "
" << 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);
}
--
2.45.2