summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2018-01-10 20:49:03 +0100
committerRoland Stigge <stigge@antcom.de>2018-01-10 20:49:03 +0100
commit188a87d1a66f09dc7b224b89e6c1c16d77681423 (patch)
treea5e6c104af5af0548cb1e591b11b42f484c51b5a
parent97c8b7f21b8aeeda56f68deee8349f381d60eb96 (diff)
Handle errors from HTTP, separated out commands as classes
-rw-r--r--TODO11
-rw-r--r--html/webbox.js49
-rw-r--r--src/Makefile4
-rw-r--r--src/webbox.cpp879
4 files changed, 565 insertions, 378 deletions
diff --git a/TODO b/TODO
index 03d1a79..e803457 100644
--- a/TODO
+++ b/TODO
@@ -1,20 +1,19 @@
Prio 1 (for next version)
======
+handle writability
+rename function
+gallery
+scroll in dialog/menu / handle too small popup window
Prio 2 (for future versions)
======
-scroll in dialog/menu / handle too small popup window
+links in path line, to dirs
google pagespeed insights https://developers.google.com/speed/pagespeed/insights/?url=http%3A%2F%2Fwww.kneipenband.com%2Fwebbox%2F&tab=mobile
-rename function
-handle errors from http
-gallery
chromecast
player
-handle writability
-register GET/POST functions
sandclock during operations
i18n
forward/back button
diff --git a/html/webbox.js b/html/webbox.js
index 8612062..01738be 100644
--- a/html/webbox.js
+++ b/html/webbox.js
@@ -354,11 +354,14 @@ function createDir() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
- if (this.readyState != 4 || this.status != 200) {
+ if (this.readyState != 4) {
return;
}
-
- document.getElementById("dialog").innerHTML = xhr.responseText;
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
document.getElementById("okbutton").onclick = hideDialog;
document.getElementById("okbutton").focus();
loadContents(currentDir); // load new file list with new dir
@@ -396,18 +399,22 @@ function onUploadFile() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
- if (this.readyState != 4 || this.status != 200) {
+ if (this.readyState != 4) {
return;
}
showDialog();
var message = "";
- if (xhr.responseText == "OK") {
- message = "Upload successful.";
- loadContents(currentDir); // load new file list with uploaded file
+ if (this.status != 200) {
+ message = "HTTP error";
} else {
- message = "Error: " + xhr.responseText;
+ if (xhr.responseText == "OK") {
+ message = "Upload successful.";
+ loadContents(currentDir); // load new file list with uploaded file
+ } else {
+ message = "Error: " + xhr.responseText;
+ }
}
document.getElementById("dialog").innerHTML = message;
@@ -450,11 +457,14 @@ function deleteItems() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
- if (this.readyState != 4 || this.status != 200) {
+ if (this.readyState != 4) {
return;
}
-
- document.getElementById("dialog").innerHTML = xhr.responseText;
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
document.getElementById("okbutton").onclick = hideDialog;
loadContents(currentDir); // load new file list with deleted items
}
@@ -505,11 +515,15 @@ function move() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
- if (this.readyState != 4 || this.status != 200) {
+ if (this.readyState != 4) {
return;
}
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
- document.getElementById("dialog").innerHTML = xhr.responseText;
document.getElementById("okbutton").onclick = hideDialog;
document.getElementById("okbutton").focus();
loadContents(currentDir); // load new file list with deleted items
@@ -556,11 +570,14 @@ function info() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
- if (this.readyState != 4 || this.status != 200) {
+ if (this.readyState != 4) {
return;
}
-
- document.getElementById("dialog").innerHTML = xhr.responseText;
+ if (this.status != 200) {
+ document.getElementById("dialog").innerHTML = "HTTP error";
+ } else {
+ document.getElementById("dialog").innerHTML = xhr.responseText;
+ }
}
var parser = new DOMParser();
diff --git a/src/Makefile b/src/Makefile
index d7f3847..0a8ab19 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,7 @@
ARCH=$(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
TARGET=query
-CPPFLAGS=-Wall -O2 -fPIC -I/usr/include/$(ARCH)/qt5 -I/usr/include/$(ARCH)/qt5/QtCore
-LDFLAGS=-Wall -O2 -fPIC -lstdc++ -lfcgi -lQt5Core
+CPPFLAGS=-Wall -O2 -fPIC -std=gnu++17 -I/usr/include/$(ARCH)/qt5 -I/usr/include/$(ARCH)/qt5/QtCore
+LDFLAGS=-Wall -O2 -fPIC -std=gnu++17 -lstdc++ -lfcgi -lQt5Core
OBJS=webbox.o
all: $(TARGET)
diff --git a/src/webbox.cpp b/src/webbox.cpp
index e991266..c3f03e2 100644
--- a/src/webbox.cpp
+++ b/src/webbox.cpp
@@ -10,8 +10,10 @@
#include <QDateTime>
#include <QProcess>
#include <QTemporaryFile>
+#include <QUrlQuery>
+#include <QPair>
-#define PROGRAMVERSION "1.0"
+#define PROGRAMVERSION "1.1"
#define BUFSIZE 1000000
// XML special characters:
@@ -63,89 +65,154 @@ QString httpError(int httpStatusCode, QString message) {
return QString("Status: %1 %2\r\nContent-Type: text/html\r\n\r\n<html><body><h1>%1 %2</h1><p>%3</p></body></html>\r\n").arg(httpStatusCode).arg(description).arg(message);
}
-void initlocale() {
- if (setenv("LC_ALL", "UTF-8", 1)) {
- exit(1);
- }
-}
+struct CommandParameters {
+ FCGX_Request request; // the request
-int main(int argc, char* argv[]) {
- initlocale();
+ QUrlQuery urlQuery; // derived from request
+ QHash<QString, QString> paramHash; // derived from urlQuery
- int result = FCGX_Init();
- if (result != 0) {
- return 1; // error on init
- }
+ int count; // request count for this instance
+};
- FCGX_Request request;
+class Command {
+ public:
+ // call interface
+ void execute(CommandParameters& p) {
+ QString requestMethod(FCGX_GetParam("REQUEST_METHOD", p.request.envp));
+ if (requestMethod != m_requestMethod) {
+ printHttpError(403, QString("Bad request method"), p);
+ return;
+ }
- if (FCGX_InitRequest(&request, 0, 0) != 0) {
- return 1; // error on init
- }
+ // process environment
+ QString webboxPath(getenv("WEBBOX_PATH"));
- int count = 0;
+ // FastCGI request environment
+ m_pathInfo = FCGX_GetParam("PATH_INFO", p.request.envp);
+ if (m_pathInfo == "") {
+ m_pathInfo = "/";
+ }
+ if (m_pathInfo.contains("..")) {
+ printHttpError(403, QString("Bad path: %1"), p);
+ return;
+ }
- while (FCGX_Accept_r(&request) == 0) {
+ m_path = webboxPath + m_pathInfo;
- count++;
+ this->start(p);
+ }
- QString queryString(FCGX_GetParam("QUERY_STRING", request.envp));
+ QString getCommandName() {
+ return m_commandName;
+ }
- // URL parameters
- QStringList paramList = queryString.split("&");
- QHash<QString, QString> paramHash;
-
- foreach(QString keyValue, paramList) {
- QStringList keyValueList = keyValue.split("=");
- if (keyValueList.size() == 2) {
- QString key = keyValueList[0];
- QString value = keyValueList[1];
- paramHash[key] = value;
- }
+ protected:
+ // helper function for writing http error
+ void printHttpError(int httpStatusCode, QString message, CommandParameters& p) {
+ FCGX_PutS(httpError(httpStatusCode, message).toUtf8().data(), p.request.out);
+ }
+
+ // implemented in implementation classes
+ virtual void start(CommandParameters& p) = 0;
+
+ // Implementation class constants
+ QString m_commandName;
+ QString m_requestMethod;
+
+ // calculated during start of execute()
+ QString m_pathInfo; // path inside webbox, derived from request
+ QString m_path; // complete path
+};
+
+class GetCommand: public Command {
+ public:
+ GetCommand() {
+ m_requestMethod = "GET";
}
+};
- QString command = paramHash["command"];
+class PostCommand: public Command {
+ public:
+ PostCommand() {
+ m_requestMethod = "POST";
+ }
- // process environment
- QString webboxPath(getenv("WEBBOX_PATH"));
+ protected:
+ // prepare POST handler implementation: read m_contentLength and m_content
+ // needs to be called at beginning of post implementations start()
+ // returns true on success
+ bool readContent(CommandParameters& p) {
+ QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", p.request.envp));
+ bool ok;
+ m_contentLength = contentLengthString.toInt(&ok);
- // FastCGI request environment
- QString pathInfo(FCGX_GetParam("PATH_INFO", request.envp));
- if (pathInfo == "") {
- pathInfo = "/";
+ if (!ok) {
+ printHttpError(400, QString("Bad content length"), p);
+ return false;
+ } else {
+ m_content.resize(m_contentLength);
+
+ int result = FCGX_GetStr(m_content.data(), m_content.size(), p.request.in);
+ if (result != m_content.size()) {
+ printHttpError(400, QString("Read error (%1/%2)").arg(result).arg(m_content.size()), p);
+ return false;
+ }
+ }
+ return true;
}
- if (pathInfo.contains("..")) {
- FCGX_PutS(httpError(403, QString("Bad path: %1").arg(pathInfo)).toUtf8().data(), request.out);
- continue;
+
+ int m_contentLength;
+ QByteArray m_content;
+};
+
+class DiagCommand: public GetCommand {
+ public:
+ DiagCommand() {
+ m_commandName = "diag";
}
- QString path = webboxPath + pathInfo;
+ protected:
+ virtual void start(CommandParameters& p) {
+ QString serverName(FCGX_GetParam("SERVER_NAME", p.request.envp));
+ // provide diag only on "localhost"
+ if (serverName != "localhost") {
+ printHttpError(403, QString("Command not available"), p);
+ return;
+ }
-#if 0
- // only for debugging
- if (command == "diag") {
- FCGX_PutS("Content-Type: text/html\r\n\r\n", request.out);
+ FCGX_PutS("Content-Type: text/html\r\n\r\n", p.request.out);
- FCGX_PutS("<html><head><title>Params</title></head><body>\r\n", request.out);
+ FCGX_PutS("<html><head><title>Params</title></head><body>\r\n", p.request.out);
- FCGX_PutS(QString("Request no. %1<br/><br/>\r\n").arg(count).toUtf8().data(), request.out);
+ FCGX_PutS(QString("Request no. %1<br/><br/>\r\n").arg(p.count).toUtf8().data(), p.request.out);
- char** tmp = request.envp;
+ char** tmp = p.request.envp;
while (*tmp) {
- FCGX_PutS(QString("%1<br/>\r\n").arg(*tmp).toUtf8().data(), request.out);
+ FCGX_PutS(QString("%1<br/>\r\n").arg(*tmp).toUtf8().data(), p.request.out);
tmp++;
}
- FCGX_PutS(QString("<br/>WEBBOX_PATH=%1<br/>\r\n").arg(getenv("WEBBOX_PATH")).toUtf8().data(), request.out);
+ FCGX_PutS(QString("<br/>WEBBOX_PATH=%1<br/>\r\n").arg(getenv("WEBBOX_PATH")).toUtf8().data(), p.request.out);
+
+ FCGX_PutS(QString("<br/>URL Query=%1<br/>\r\n").arg(p.urlQuery.toString()).toUtf8().data(), p.request.out);
+
- FCGX_PutS("</body></html>\r\n", request.out);
- } else
-#endif
- if (command == "list") {
- FCGX_PutS("Content-Type: text/xml\r\n\r\n", request.out);
+ FCGX_PutS("</body></html>\r\n", p.request.out);
+ }
+};
- QDir dir(path);
+class ListCommand: public GetCommand {
+ public:
+ ListCommand() {
+ m_commandName = "list";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ FCGX_PutS("Content-Type: text/xml\r\n\r\n", p.request.out);
+
+ QDir dir(m_path);
QFileInfoList dirEntryList = dir.entryInfoList(QDir::NoDot | QDir::AllEntries, QDir::DirsFirst | QDir::Name | QDir::IgnoreCase);
QByteArray xmlData;
@@ -153,7 +220,7 @@ int main(int argc, char* argv[]) {
xmlWriter.writeStartDocument();
xmlWriter.writeStartElement("list");
foreach(QFileInfo i, dirEntryList) {
- if (pathInfo != "/" || i.fileName() != "..") { // skip on ".." in "/"
+ if (m_pathInfo != "/" || i.fileName() != "..") { // skip on ".." in "/"
xmlWriter.writeStartElement("listentry");
xmlWriter.writeAttribute("type", i.isDir() ? "dir" : "file");
xmlWriter.writeCharacters(i.fileName());
@@ -162,351 +229,352 @@ int main(int argc, char* argv[]) {
}
xmlWriter.writeEndElement(); // list
xmlWriter.writeEndDocument();
- FCGX_PutS(xmlData.data(), request.out);
- } else if (command == "title") {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(getenv("WEBBOX_NAME"), request.out);
- } else if (command == "version") {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("webbox %1<br/>(C) 2017 <a href=\"https://www.reichwein.it/\">Reichwein.IT</a>\r\n").arg(PROGRAMVERSION).toUtf8().data(), request.out);
- } else if (command == "newdir") { // POST!
- QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
- bool ok;
- int contentLength = contentLengthString.toInt(&ok);
+ FCGX_PutS(xmlData.data(), p.request.out);
+ }
+};
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- if (!ok) {
- FCGX_PutS(QString("Bad content length").toUtf8().data(), request.out);
- } else {
- QByteArray content(contentLength, 0);
-
- int result = FCGX_GetStr(content.data(), content.size(), request.in);
- if (result != content.size()) {
- FCGX_PutS(QString("Read error (%1/%2)").arg(result).arg(content.size()).toUtf8().data(), request.out);
- } else {
- QXmlStreamReader xml(content);
+class TitleCommand: public GetCommand {
+ public:
+ TitleCommand() {
+ m_commandName = "title";
+ }
- while (!xml.atEnd()) {
- while (xml.readNextStartElement()) {
- if (xml.name() == "dirname") {
- QString dirname = xml.readElementText();
- QDir dir(path);
- if (dir.mkdir(dirname)) {
- FCGX_PutS("Successfully created directory", request.out);
- } else {
- FCGX_PutS("Error creating directory", request.out);
- }
- }
+ protected:
+ virtual void start(CommandParameters& p) {
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ FCGX_PutS(getenv("WEBBOX_NAME"), p.request.out);
+ }
+};
+
+class VersionCommand: public GetCommand {
+ public:
+ VersionCommand() {
+ m_commandName = "version";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ FCGX_PutS(QString("webbox %1<br/>(C) 2017 <a href=\"https://www.reichwein.it/\">Reichwein.IT</a>\r\n").arg(PROGRAMVERSION).toUtf8().data(), p.request.out);
+ }
+};
+
+class NewDirCommand: public PostCommand {
+ public:
+ NewDirCommand() {
+ m_commandName = "newdir";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ if (!readContent(p))
+ return;
+
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ QXmlStreamReader xml(m_content);
+
+ while (!xml.atEnd()) {
+ while (xml.readNextStartElement()) {
+ if (xml.name() == "dirname") {
+ QString dirname = xml.readElementText();
+ QDir dir(m_path);
+ if (dir.mkdir(dirname)) {
+ FCGX_PutS("Successfully created directory", p.request.out);
+ } else {
+ FCGX_PutS("Error creating directory", p.request.out);
}
}
}
}
- } else if (command == "info") { // POST!
- QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
- bool ok;
- int contentLength = contentLengthString.toInt(&ok);
+ }
+};
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- if (!ok) {
- FCGX_PutS(QString("Bad content length").toUtf8().data(), request.out);
- } else {
- QByteArray content(contentLength, 0);
-
- int result = FCGX_GetStr(content.data(), content.size(), request.in);
- if (result != content.size()) {
- FCGX_PutS(QString("Read error (%1/%2)").arg(result).arg(content.size()).toUtf8().data(), request.out);
- } else {
- QXmlStreamReader xml(content);
+class InfoCommand: public PostCommand {
+ public:
+ InfoCommand() {
+ m_commandName = "info";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ if (!readContent(p))
+ return;
- while (!xml.atEnd()) {
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ QXmlStreamReader xml(m_content);
+
+ while (!xml.atEnd()) {
+ while (xml.readNextStartElement()) {
+ if (xml.name() == "files") {
while (xml.readNextStartElement()) {
- if (xml.name() == "files") {
- while (xml.readNextStartElement()) {
- if (xml.name() == "file") {
- QString filename = xml.readElementText();
- QFileInfo fileInfo(path + "/" + filename);
- qint64 size = fileInfo.size();
- QString date = fileInfo.lastModified().toString();
- QString type = fileInfo.isDir() ? "directory" : "file";
- FCGX_PutS(QString("%1, %2 bytes, %3 (%4)<br>")
- .arg(filename)
- .arg(size)
- .arg(date)
- .arg(type).toUtf8().data(), request.out);
- }
- }
+ if (xml.name() == "file") {
+ QString filename = xml.readElementText();
+ QFileInfo fileInfo(m_path + "/" + filename);
+ qint64 size = fileInfo.size();
+ QString date = fileInfo.lastModified().toString();
+ QString type = fileInfo.isDir() ? "directory" : "file";
+ FCGX_PutS(QString("%1, %2 bytes, %3 (%4)<br>")
+ .arg(filename)
+ .arg(size)
+ .arg(date)
+ .arg(type).toUtf8().data(), p.request.out);
}
}
}
}
}
- } else if (command == "download-zip") { // POST!
- QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
- bool ok;
- int contentLength = contentLengthString.toInt(&ok);
+ }
+};
- if (!ok) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Bad content length").toUtf8().data(), request.out);
- } else {
- QByteArray content(contentLength, 0);
-
- int result = FCGX_GetStr(content.data(), content.size(), request.in);
- if (result != content.size()) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Read error (%1/%2)").arg(result).arg(content.size()).toUtf8().data(), request.out);
- } else {
- QXmlStreamReader xml(content);
-
- QByteArray zipData;
- QStringList argumentList;
- QTemporaryFile tempfile(QDir::tempPath() + "/webboxXXXXXX.zip");
- tempfile.open();
- QFileInfo fileInfo(tempfile);
- QString tempfilePath = fileInfo.absolutePath();
- QString tempfileName = fileInfo.fileName();
- tempfile.close();
- tempfile.remove();
-
- argumentList << "-r"; // recursive packing
- argumentList << tempfilePath + "/" + tempfileName; // zip filename
-
- while (!xml.atEnd()) {
+class DownloadZipCommand: public PostCommand {
+ public:
+ DownloadZipCommand() {
+ m_commandName = "download-zip";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ if (!readContent(p))
+ return;
+
+ QXmlStreamReader xml(m_content);
+
+ QByteArray zipData;
+ QStringList argumentList;
+ QTemporaryFile tempfile(QDir::tempPath() + "/webboxXXXXXX.zip");
+ tempfile.open();
+ QFileInfo fileInfo(tempfile);
+ QString tempfilePath = fileInfo.absolutePath();
+ QString tempfileName = fileInfo.fileName();
+ tempfile.close();
+ tempfile.remove();
+
+ argumentList << "-r"; // recursive packing
+ argumentList << tempfilePath + "/" + tempfileName; // zip filename
+
+ while (!xml.atEnd()) {
+ while (xml.readNextStartElement()) {
+ if (xml.name() == "files") {
while (xml.readNextStartElement()) {
- if (xml.name() == "files") {
- while (xml.readNextStartElement()) {
- if (xml.name() == "file") {
- QString filename = xml.readElementText();
+ if (xml.name() == "file") {
+ QString filename = xml.readElementText();
- argumentList.append(filename); // add parts
- }
- }
+ argumentList.append(filename); // add parts
}
}
}
-
- QProcess process;
- process.setWorkingDirectory(path);
- process.setProgram("/usr/bin/zip");
- process.setArguments(argumentList);
- process.start();
- process.waitForFinished();
-
- QString debugText = process.readAll();
- process.setReadChannel(QProcess::StandardError);
- debugText += process.readAll();
-
- if (process.state() != QProcess::NotRunning ||
- process.exitCode() != 0 ||
- process.exitStatus() != QProcess::NormalExit)
- {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Error running process: %1 %2 %3 %4 %5 %6 %7").
- arg(process.state()).
- arg(process.exitCode()).
- arg(process.exitStatus()).
- arg(tempfilePath).
- arg(tempfileName).
- arg(argumentList[0]).
- arg(debugText).toUtf8().data(), request.out);
- } else {
-
- QFile tempfile(tempfilePath + "/" + tempfileName);
- if (!tempfile.open(QIODevice::ReadOnly)) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Error reading file").toUtf8().data(), request.out);
- } else {
- zipData = tempfile.readAll();
-
- FCGX_PutS(QString("Content-Disposition: attachment; filename=\"%1\"\r\n").arg("webbox-download.zip").toUtf8().data(), request.out);
- FCGX_PutS("Content-Type: application/octet-stream\r\n\r\n", request.out);
-
- FCGX_PutStr(zipData.data(), zipData.size(), request.out);
- }
-
- tempfile.close();
- tempfile.remove();
- }
}
}
- } else if (command == "delete") { // POST!
- QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
- bool ok;
- int contentLength = contentLengthString.toInt(&ok);
- if (!ok) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Bad content length").toUtf8().data(), request.out);
+ QProcess process;
+ process.setWorkingDirectory(m_path);
+ process.setProgram("/usr/bin/zip");
+ process.setArguments(argumentList);
+ process.start();
+ process.waitForFinished();
+
+ QString debugText = process.readAll();
+ process.setReadChannel(QProcess::StandardError);
+ debugText += process.readAll();
+
+ if (process.state() != QProcess::NotRunning ||
+ process.exitCode() != 0 ||
+ process.exitStatus() != QProcess::NormalExit)
+ {
+ printHttpError(500, QString("Error running process: %1 %2 %3 %4 %5 %6 %7").
+ arg(process.state()).
+ arg(process.exitCode()).
+ arg(process.exitStatus()).
+ arg(tempfilePath).
+ arg(tempfileName).
+ arg(argumentList[0]).
+ arg(debugText), p);
} else {
- QByteArray content(contentLength, 0);
-
- int result = FCGX_GetStr(content.data(), content.size(), request.in);
- if (result != content.size()) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Read error (%1/%2)").arg(result).arg(content.size()).toUtf8().data(), request.out);
+
+ QFile tempfile(tempfilePath + "/" + tempfileName);
+ if (!tempfile.open(QIODevice::ReadOnly)) {
+ printHttpError(500, QString("Error reading file"), p);
} else {
- QXmlStreamReader xml(content);
+ zipData = tempfile.readAll();
+
+ FCGX_PutS(QString("Content-Disposition: attachment; filename=\"%1\"\r\n").arg("webbox-download.zip").toUtf8().data(), p.request.out);
+ FCGX_PutS("Content-Type: application/octet-stream\r\n\r\n", p.request.out);
- QString response = "";
+ FCGX_PutStr(zipData.data(), zipData.size(), p.request.out);
+ }
+
+ tempfile.close();
+ tempfile.remove();
+ }
+ }
+};
- while (!xml.atEnd()) {
+class DeleteCommand: public PostCommand {
+ public:
+ DeleteCommand() {
+ m_commandName = "delete";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ if (!readContent(p))
+ return;
+
+ QXmlStreamReader xml(m_content);
+
+ QString response = "";
+
+ while (!xml.atEnd()) {
+ while (xml.readNextStartElement()) {
+ if (xml.name() == "files") {
while (xml.readNextStartElement()) {
- if (xml.name() == "files") {
- while (xml.readNextStartElement()) {
- if (xml.name() == "file") {
- QString filename = xml.readElementText();
-
- QFileInfo fileInfo(path + "/" + filename);
- if (fileInfo.isDir()) {
- QDir dir(path);
- if (!dir.rmdir(filename)) {
- response += QString("Error on removing directory %1<br/>").arg(filename);
- }
- } else if (fileInfo.isFile()) {
- QFile file(path + "/" + filename);
- if (!file.remove()) {
- response += QString("Error on removing file %1<br/>").arg(filename);
- }
- } else {
- response += QString("Error: %1 is neither file nor directory.<br/>").arg(filename);
- }
+ if (xml.name() == "file") {
+ QString filename = xml.readElementText();
+
+ QFileInfo fileInfo(m_path + "/" + filename);
+ if (fileInfo.isDir()) {
+ QDir dir(m_path);
+ if (!dir.rmdir(filename)) {
+ response += QString("Error on removing directory %1<br/>").arg(filename);
}
+ } else if (fileInfo.isFile()) {
+ QFile file(m_path + "/" + filename);
+ if (!file.remove()) {
+ response += QString("Error on removing file %1<br/>").arg(filename);
+ }
+ } else {
+ response += QString("Error: %1 is neither file nor directory.<br/>").arg(filename);
}
}
}
}
-
- if (response == "") {
- response = "OK";
- }
-
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(response.toUtf8().data(), request.out);
}
}
- } else if (command == "move") { // POST!
- QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
- bool ok;
- int contentLength = contentLengthString.toInt(&ok);
- if (!ok) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Bad content length").toUtf8().data(), request.out);
- } else {
- QByteArray content(contentLength, 0);
-
- int result = FCGX_GetStr(content.data(), content.size(), request.in);
- if (result != content.size()) {
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(QString("Read error (%1/%2)").arg(result).arg(content.size()).toUtf8().data(), request.out);
- } else {
- QXmlStreamReader xml(content);
-
- QString response = "";
- QString targetDir;
+ if (response == "") {
+ response = "OK";
+ }
+
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ FCGX_PutS(response.toUtf8().data(), p.request.out);
+ }
+};
+
+class MoveCommand: public PostCommand {
+ public:
+ MoveCommand() {
+ m_commandName = "move";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ if (!readContent(p))
+ return;
- while (!xml.atEnd()) {
+ QXmlStreamReader xml(m_content);
+
+ QString response = "";
+ QString targetDir;
+
+ while (!xml.atEnd()) {
+ while (xml.readNextStartElement()) {
+ if (xml.name() == "request") {
while (xml.readNextStartElement()) {
- if (xml.name() == "request") {
- while (xml.readNextStartElement()) {
- if (xml.name() == "target") {
- targetDir = xml.readElementText();
- } else if (xml.name() == "file") {
- QString filename = xml.readElementText();
-
- QFileInfo fileInfo(path + "/" + filename);
- if (fileInfo.isDir()) {
- QDir dir(path);
- if (!dir.rename(filename, targetDir + "/" + filename)) {
- response += QString("Error moving directory %1<br/>").arg(filename);
- }
- } else if (fileInfo.isFile()) {
- QFile file(path + "/" + filename);
- if (!file.rename(path + "/" + targetDir + "/" + filename)) {
- response += QString("Error on moving file %1<br/>").arg(filename);
- }
- } else {
- response += QString("Error: %1 is neither file nor directory.<br/>").arg(filename);
- }
+ if (xml.name() == "target") {
+ targetDir = xml.readElementText();
+ } else if (xml.name() == "file") {
+ QString filename = xml.readElementText();
+
+ QFileInfo fileInfo(m_path + "/" + filename);
+ if (fileInfo.isDir()) {
+ QDir dir(m_path);
+ if (!dir.rename(filename, targetDir + "/" + filename)) {
+ response += QString("Error moving directory %1<br/>").arg(filename);
}
+ } else if (fileInfo.isFile()) {
+ QFile file(m_path + "/" + filename);
+ if (!file.rename(m_path + "/" + targetDir + "/" + filename)) {
+ response += QString("Error on moving file %1<br/>").arg(filename);
+ }
+ } else {
+ response += QString("Error: %1 is neither file nor directory.<br/>").arg(filename);
}
}
}
}
-
- if (response == "") {
- response = "OK";
- }
-
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- FCGX_PutS(response.toUtf8().data(), request.out);
}
}
- } else if (command == "upload") { // POST!
- QString contentLengthString(FCGX_GetParam("CONTENT_LENGTH", request.envp));
- bool ok;
- int contentLength = contentLengthString.toInt(&ok);
- FCGX_PutS("Content-Type: text/plain\r\n\r\n", request.out);
- if (!ok) {
- FCGX_PutS(QString("Bad content length").toUtf8().data(), request.out);
+
+ if (response == "") {
+ response = "OK";
+ }
+
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ FCGX_PutS(response.toUtf8().data(), p.request.out);
+ }
+};
+
+class UploadCommand: public PostCommand {
+ public:
+ UploadCommand() {
+ m_commandName = "upload";
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ if (!readContent(p))
+ return;
+
+ FCGX_PutS("Content-Type: text/plain\r\n\r\n", p.request.out);
+ QString contentType(FCGX_GetParam("CONTENT_TYPE", p.request.envp));
+
+ QString separator("boundary=");
+ if (!contentType.contains(separator)) {
+ FCGX_PutS(QString("No boundary defined").toUtf8().data(), p.request.out);
} else {
- QByteArray content(contentLength, 0);
-
- int result = FCGX_GetStr(content.data(), content.size(), request.in);
- if (result != content.size()) {
- FCGX_PutS(QString("Read error (%1/%2)").arg(result).arg(content.size()).toUtf8().data(), request.out);
+ QByteArray boundary = QByteArray("--") + contentType.split(separator)[1].toUtf8();
+ int boundaryCount = m_content.count(boundary);
+ if (boundaryCount != 2) {
+ FCGX_PutS(QString("Bad boundary number found: %1").arg(boundaryCount).toUtf8().data(), p.request.out);
} else {
- QString contentType(FCGX_GetParam("CONTENT_TYPE", request.envp));
+ int start = m_content.indexOf(boundary) + boundary.size();
+ int end = m_content.indexOf(QByteArray("\r\n") + boundary, start);
+
+ m_content = m_content.mid(start, end - start);
- QString separator("boundary=");
- if (!contentType.contains(separator)) {
- FCGX_PutS(QString("No boundary defined").toUtf8().data(), request.out);
+ // Read filename
+ start = m_content.indexOf("filename=\"");
+ if (start == -1) {
+ FCGX_PutS(QString("Error reading filename / start").toUtf8().data(), p.request.out);
} else {
- QByteArray boundary = QByteArray("--") + contentType.split(separator)[1].toUtf8();
- int boundaryCount = content.count(boundary);
- if (boundaryCount != 2) {
- FCGX_PutS(QString("Bad boundary number found: %1").arg(boundaryCount).toUtf8().data(), request.out);
- } else {
- int start = content.indexOf(boundary) + boundary.size();
- int end = content.indexOf(QByteArray("\r\n") + boundary, start);
+ start += QByteArray("filename=\"").size();
- content = content.mid(start, end - start);
+ end = m_content.indexOf(QByteArray("\""), start);
+ if (end == -1) {
+ FCGX_PutS(QString("Error reading filename / end").toUtf8().data(), p.request.out);
+ } else {
+ QString filename = QString::fromUtf8(m_content.mid(start, end - start));
- // Read filename
- start = content.indexOf("filename=\"");
- if (start == -1) {
- FCGX_PutS(QString("Error reading filename / start").toUtf8().data(), request.out);
+ if (filename.size() < 1) {
+ FCGX_PutS(QString("Bad filename").toUtf8().data(), p.request.out);
} else {
- start += QByteArray("filename=\"").size();
-
- end = content.indexOf(QByteArray("\""), start);
- if (end == -1) {
- FCGX_PutS(QString("Error reading filename / end").toUtf8().data(), request.out);
+ // Remove header
+ start = m_content.indexOf(QByteArray("\r\n\r\n"));
+ if (start == -1) {
+ FCGX_PutS(QString("Error removing upload header").toUtf8().data(), p.request.out);
} else {
- QString filename = QString::fromUtf8(content.mid(start, end - start));
- if (filename.size() < 1) {
- FCGX_PutS(QString("Bad filename").toUtf8().data(), request.out);
+ m_content = m_content.mid(start + QString("\r\n\r\n").toUtf8().size());
+
+ QFile file(m_path + "/" + filename);
+ if (!file.open(QIODevice::WriteOnly)) {
+ FCGX_PutS(QString("Error opening file").toUtf8().data(), p.request.out);
} else {
- // Remove header
- start = content.indexOf(QByteArray("\r\n\r\n"));
- if (start == -1) {
- FCGX_PutS(QString("Error removing upload header").toUtf8().data(), request.out);
+ qint64 written = file.write(m_content);
+ if (written != m_content.size()) {
+ FCGX_PutS(QString("Error writing file").toUtf8().data(), p.request.out);
} else {
-
- content = content.mid(start + QString("\r\n\r\n").toUtf8().size());
-
- QFile file(path + "/" + filename);
- if (!file.open(QIODevice::WriteOnly)) {
- FCGX_PutS(QString("Error opening file").toUtf8().data(), request.out);
- } else {
- qint64 written = file.write(content);
- if (written != content.size()) {
- FCGX_PutS(QString("Error writing file").toUtf8().data(), request.out);
- } else {
- FCGX_PutS("OK", request.out);
- }
- }
+ FCGX_PutS("OK", p.request.out);
}
}
}
@@ -515,21 +583,124 @@ int main(int argc, char* argv[]) {
}
}
}
- } else { // default: download
- QFile file(path);
+ }
+};
+
+class DownloadCommand: public GetCommand {
+ public:
+ DownloadCommand() {
+ m_commandName = ""; // default command w/o explict "command=" query argument
+ }
+
+ protected:
+ virtual void start(CommandParameters& p) {
+ QFile file(m_path);
if (file.open(QIODevice::ReadOnly)) {
- QFileInfo fileInfo(path);
- FCGX_PutS(QString("Content-Disposition: attachment; filename=\"%1\"\r\n").arg(fileInfo.fileName()).toUtf8().data(), request.out);
- FCGX_PutS("Content-Type: application/octet-stream\r\n\r\n", request.out);
+ QFileInfo fileInfo(m_path);
+ FCGX_PutS(QString("Content-Disposition: attachment; filename=\"%1\"\r\n").arg(fileInfo.fileName()).toUtf8().data(), p.request.out);
+ FCGX_PutS("Content-Type: application/octet-stream\r\n\r\n", p.request.out);
while (!file.atEnd()) {
QByteArray ba = file.read(BUFSIZE);
- FCGX_PutStr(ba.data(), ba.size(), request.out);
+ FCGX_PutStr(ba.data(), ba.size(), p.request.out);
}
} else {
- FCGX_PutS(httpError(500, QString("Bad file: %1").arg(pathInfo)).toUtf8().data(), request.out);
+ FCGX_PutS(httpError(500, QString("Bad file: %1").arg(m_pathInfo)).toUtf8().data(), p.request.out);
}
}
+};
+
+// Hash of commands for fast access
+class Commands: public QHash<QString, Command*> {
+ public:
+ void registerCommand(Command& command) {
+ (*this)[command.getCommandName()] = &command;
+ }
+};
+
+void initlocale() {
+ if (setenv("LC_ALL", "UTF-8", 1)) {
+ exit(1);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ initlocale();
+
+ int result = FCGX_Init();
+ if (result != 0) {
+ return 1; // error on init
+ }
+
+ CommandParameters commandParameters;
+
+ FCGX_Request& request = commandParameters.request;
+
+ if (FCGX_InitRequest(&request, 0, 0) != 0) {
+ return 1; // error on init
+ }
+
+ commandParameters.count = 0;
+
+ Commands commands;
+
+ DiagCommand diagCommand;
+ commands.registerCommand(diagCommand);
+
+ ListCommand listCommand;
+ commands.registerCommand(listCommand);
+
+ TitleCommand titleCommand;
+ commands.registerCommand(titleCommand);
+
+ VersionCommand versionCommand;
+ commands.registerCommand(versionCommand);
+
+ NewDirCommand newDirCommand;
+ commands.registerCommand(newDirCommand);
+
+ InfoCommand infoCommand;
+ commands.registerCommand(infoCommand);
+
+ DownloadZipCommand downloadZipCommand;
+ commands.registerCommand(downloadZipCommand);
+
+ DeleteCommand deleteCommand;
+ commands.registerCommand(deleteCommand);
+
+ MoveCommand moveCommand;
+ commands.registerCommand(moveCommand);
+
+ UploadCommand uploadCommand;
+ commands.registerCommand(uploadCommand);
+
+ DownloadCommand downloadCommand;
+ commands.registerCommand(downloadCommand);
+
+ while (FCGX_Accept_r(&request) == 0) {
+
+ commandParameters.count++;
+
+ QString queryString(FCGX_GetParam("QUERY_STRING", request.envp));
+
+ // URL parameters
+ commandParameters.urlQuery.setQuery(queryString);
+
+ QList<QPair<QString, QString> > items = commandParameters.urlQuery.queryItems();
+ commandParameters.paramHash.clear();
+
+ for (int i = 0; i < items.size(); i++) {
+ commandParameters.paramHash[items[i].first] = items[i].second;
+ }
+
+ QString commandName = commandParameters.paramHash["command"];
+ if (commands.contains(commandName)) {
+ Command* command = commands[commandName];
+
+ command->execute(commandParameters);
+ } else {
+ FCGX_PutS(httpError(400, QString("Bad command: %1").arg(commandName)).toUtf8().data(), request.out);
+ }
}
return 0;