ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

uploadfileclienthandler.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "backends/networking/sdl_net/uploadfileclienthandler.h"
00024 #include "backends/fs/fs-factory.h"
00025 #include "backends/networking/sdl_net/handlerutils.h"
00026 #include "backends/networking/sdl_net/localwebserver.h"
00027 #include "backends/networking/sdl_net/reader.h"
00028 #include "common/file.h"
00029 #include "common/memstream.h"
00030 #include "common/translation.h"
00031 
00032 namespace Networking {
00033 
00034 UploadFileClientHandler::UploadFileClientHandler(Common::String parentDirectoryPath):
00035     _state(UFH_READING_CONTENT), _headersStream(nullptr), _contentStream(nullptr),
00036     _parentDirectoryPath(parentDirectoryPath), _uploadedFiles(0) {}
00037 
00038 UploadFileClientHandler::~UploadFileClientHandler() {
00039     delete _headersStream;
00040     delete _contentStream;
00041 }
00042 
00043 void UploadFileClientHandler::handle(Client *client) {
00044     if (client == nullptr) {
00045         warning("UploadFileClientHandler::handle(): empty client pointer");
00046         return;
00047     }
00048 
00049     while (true) {
00050         switch (_state) {
00051         case UFH_READING_CONTENT:
00052             if (client->readContent(nullptr)) {
00053                 _state = UFH_READING_BLOCK_HEADERS;
00054                 continue;
00055             }
00056             break;
00057 
00058         case UFH_READING_BLOCK_HEADERS:
00059             if (_headersStream == nullptr)
00060                 _headersStream = new Common::MemoryReadWriteStream(DisposeAfterUse::YES);
00061 
00062             if (client->readBlockHeaders(_headersStream)) {
00063                 handleBlockHeaders(client);
00064                 continue;
00065             }
00066 
00067             // fail on suspicious headers
00068             if (_headersStream->size() > Reader::SUSPICIOUS_HEADERS_SIZE) {
00069                 setErrorMessageHandler(*client, _("Invalid request: headers are too long!"));
00070             }
00071             break;
00072 
00073         case UFH_READING_BLOCK_CONTENT:
00074             // _contentStream is created by handleBlockHeaders() if needed
00075 
00076             if (client->readBlockContent(_contentStream)) {
00077                 handleBlockContent(client);
00078                 continue;
00079             }
00080             break;
00081 
00082         case UFH_ERROR:
00083         case UFH_STOP:
00084             return;
00085         }
00086 
00087         break;
00088     }
00089 }
00090 
00091 namespace {
00092 void readFromThatUntilDoubleQuote(const char *cstr, Common::String needle, Common::String &result) {
00093     const char *position = strstr(cstr, needle.c_str());
00094 
00095     if (position) {
00096         char c;
00097         for (const char *i = position + needle.size(); c = *i, c != 0; ++i) {
00098             if (c == '"')
00099                 break;
00100             result += c;
00101         }
00102     }
00103 }
00104 }
00105 
00106 void UploadFileClientHandler::handleBlockHeaders(Client *client) {
00107     _state = UFH_READING_BLOCK_CONTENT;
00108 
00109     // fail on suspicious headers
00110     if (_headersStream->size() > Reader::SUSPICIOUS_HEADERS_SIZE) {
00111         setErrorMessageHandler(*client, _("Invalid request: headers are too long!"));
00112     }
00113 
00114     // search for "upload_file" field
00115     Common::String headers = Reader::readEverythingFromMemoryStream(_headersStream);
00116     Common::String fieldName = "";
00117     readFromThatUntilDoubleQuote(headers.c_str(), "name=\"", fieldName);
00118     if (!fieldName.hasPrefix("upload_file"))
00119         return;
00120 
00121     Common::String filename = "";
00122     readFromThatUntilDoubleQuote(headers.c_str(), "filename=\"", filename);
00123 
00124     // skip block if <filename> is empty
00125     if (filename.empty())
00126         return;
00127 
00128     if (HandlerUtils::hasForbiddenCombinations(filename))
00129         return;
00130 
00131     // check that <path>/<filename> doesn't exist
00132     Common::String path = _parentDirectoryPath;
00133     if (path.lastChar() != '/' && path.lastChar() != '\\')
00134         path += '/';
00135     AbstractFSNode *originalNode = g_system->getFilesystemFactory()->makeFileNodePath(path + filename);
00136     if (!HandlerUtils::permittedPath(originalNode->getPath())) {
00137         setErrorMessageHandler(*client, _("Invalid path!"));
00138         return;
00139     }
00140     if (originalNode->exists()) {
00141         setErrorMessageHandler(*client, _("There is a file with that name in the parent directory!"));
00142         return;
00143     }
00144 
00145     // remove previous stream (if there is one)
00146     if (_contentStream) {
00147         delete _contentStream;
00148         _contentStream = nullptr;
00149     }
00150 
00151     // create file stream (and necessary subdirectories)
00152     Common::DumpFile *f = new Common::DumpFile();
00153     if (!f->open(originalNode->getPath(), true)) {
00154         delete f;
00155         setErrorMessageHandler(*client, _("Failed to upload the file!"));
00156         return;
00157     }
00158 
00159     _contentStream = f;
00160 }
00161 
00162 void UploadFileClientHandler::handleBlockContent(Client *client) {
00163     _state = UFH_READING_BLOCK_HEADERS;
00164 
00165     // if previous block headers were file-related and created a stream
00166     if (_contentStream) {
00167         _contentStream->flush();
00168         ++_uploadedFiles;
00169 
00170         delete _contentStream;
00171         _contentStream = nullptr;
00172 
00173         if (client->noMoreContent()) {
00174             // success - redirect back to directory listing
00175             setSuccessHandler(*client);
00176             return;
00177         }
00178     }
00179 
00180     // no more content avaiable
00181     if (client->noMoreContent()) {
00182         // if no file field was found - failure
00183         if (_uploadedFiles == 0) {
00184             setErrorMessageHandler(*client, _("No file was passed!"));
00185         } else {
00186             setSuccessHandler(*client);
00187         }
00188     }
00189 }
00190 
00191 void UploadFileClientHandler::setErrorMessageHandler(Client &client, Common::String message) {
00192     HandlerUtils::setFilesManagerErrorMessageHandler(client, message);
00193     _state = UFH_ERROR;
00194 }
00195 
00196 void UploadFileClientHandler::setSuccessHandler(Client &client) {
00197     // success - redirect back to directory listing
00198     HandlerUtils::setMessageHandler(
00199         client,
00200         Common::String::format(
00201             "%s<br/><a href=\"files?path=%s\">%s</a>",
00202             _("Uploaded successfully!"),
00203             client.queryParameter("path").c_str(),
00204             _("Back to parent directory")
00205             ),
00206         (client.queryParameter("ajax") == "true" ? "/filesAJAX?path=" : "/files?path=") +
00207         LocalWebserver::urlEncodeQueryParameterValue(client.queryParameter("path"))
00208     );
00209     _state = UFH_STOP;
00210 }
00211 
00212 } // End of namespace Networking


Generated on Sat Feb 16 2019 05:01:10 for ResidualVM by doxygen 1.7.1
curved edge   curved edge