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

filespagehandler.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/handlers/filespagehandler.h"
00024 #include "backends/networking/sdl_net/handlerutils.h"
00025 #include "backends/networking/sdl_net/localwebserver.h"
00026 #include "common/config-manager.h"
00027 #include "common/translation.h"
00028 
00029 namespace Networking {
00030 
00031 #define INDEX_PAGE_NAME ".index.html"
00032 #define FILES_PAGE_NAME ".files.html"
00033 
00034 FilesPageHandler::FilesPageHandler() {}
00035 
00036 FilesPageHandler::~FilesPageHandler() {}
00037 
00038 namespace {
00039 Common::String encodeDoubleQuotes(Common::String s) {
00040     Common::String result = "";
00041     for (uint32 i = 0; i < s.size(); ++i)
00042         if (s[i] == '"') {
00043             result += "\\\"";
00044         } else {
00045             result += s[i];
00046         }
00047     return result;
00048 }
00049 
00050 Common::String encodeHtmlEntities(Common::String s) {
00051     Common::String result = "";
00052     for (uint32 i = 0; i < s.size(); ++i)
00053         if (s[i] == '<')
00054             result += "&lt;";
00055         else if (s[i] == '>')
00056             result += "&gt;";
00057         else if (s[i] == '&')
00058             result += "&amp;";
00059         else if (s[i] > (byte)0x7F)
00060             result += Common::String::format("&#%d;", (int)s[i]);
00061         else result += s[i];
00062     return result;
00063 }
00064 
00065 Common::String getDisplayPath(Common::String s) {
00066     Common::String result = "";
00067     for (uint32 i = 0; i < s.size(); ++i)
00068         if (s[i] == '\\')
00069             result += '/';
00070         else
00071             result += s[i];
00072     if (result == "")
00073         return "/";
00074     return result;
00075 }
00076 }
00077 
00078 bool FilesPageHandler::listDirectory(Common::String path, Common::String &content, const Common::String &itemTemplate) {
00079     if (path == "" || path == "/") {
00080         if (ConfMan.hasKey("rootpath", "cloud"))
00081             addItem(content, itemTemplate, IT_DIRECTORY, "/root/", _("File system root"));
00082         addItem(content, itemTemplate, IT_DIRECTORY, "/saves/", _("Saved games"));
00083         return true;
00084     }
00085 
00086     if (HandlerUtils::hasForbiddenCombinations(path))
00087         return false;
00088 
00089     Common::String prefixToRemove = "", prefixToAdd = "";
00090     if (!transformPath(path, prefixToRemove, prefixToAdd))
00091         return false;
00092 
00093     Common::FSNode node = Common::FSNode(path);
00094     if (path == "/")
00095         node = node.getParent(); // absolute root
00096 
00097     if (!HandlerUtils::permittedPath(node.getPath()))
00098         return false;
00099 
00100     if (!node.isDirectory())
00101         return false;
00102 
00103     // list directory
00104     Common::FSList _nodeContent;
00105     if (!node.getChildren(_nodeContent, Common::FSNode::kListAll, false)) // do not show hidden files
00106         _nodeContent.clear();
00107     else
00108         Common::sort(_nodeContent.begin(), _nodeContent.end());
00109 
00110     // add parent directory link
00111     {
00112         Common::String filePath = path;
00113         if (filePath.hasPrefix(prefixToRemove))
00114             filePath.erase(0, prefixToRemove.size());
00115         if (filePath == "" || filePath == "/" || filePath == "\\")
00116             filePath = "/";
00117         else
00118             filePath = parentPath(prefixToAdd + filePath);
00119         addItem(content, itemTemplate, IT_PARENT_DIRECTORY, filePath, _("Parent directory"));
00120     }
00121 
00122     // fill the content
00123     for (Common::FSList::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) {
00124         Common::String name = i->getDisplayName();
00125         if (i->isDirectory())
00126             name += "/";
00127 
00128         Common::String filePath = i->getPath();
00129         if (filePath.hasPrefix(prefixToRemove))
00130             filePath.erase(0, prefixToRemove.size());
00131         filePath = prefixToAdd + filePath;
00132 
00133         addItem(content, itemTemplate, detectType(i->isDirectory(), name), filePath, name);
00134     }
00135 
00136     return true;
00137 }
00138 
00139 FilesPageHandler::ItemType FilesPageHandler::detectType(bool isDirectory, const Common::String &name) {
00140     if (isDirectory)
00141         return IT_DIRECTORY;
00142     if (name.hasSuffix(".txt"))
00143         return IT_TXT;
00144     if (name.hasSuffix(".zip"))
00145         return IT_ZIP;
00146     if (name.hasSuffix(".7z"))
00147         return IT_7Z;
00148     return IT_UNKNOWN;
00149 }
00150 
00151 void FilesPageHandler::addItem(Common::String &content, const Common::String &itemTemplate, ItemType itemType, Common::String path, Common::String name, Common::String size) const {
00152     Common::String item = itemTemplate, icon;
00153     bool isDirectory = (itemType == IT_DIRECTORY || itemType == IT_PARENT_DIRECTORY);
00154     switch (itemType) {
00155     case IT_DIRECTORY:
00156         icon = "dir.png";
00157         break;
00158     case IT_PARENT_DIRECTORY:
00159         icon = "up.png";
00160         break;
00161     case IT_TXT:
00162         icon = "txt.png";
00163         break;
00164     case IT_ZIP:
00165         icon = "zip.png";
00166         break;
00167     case IT_7Z:
00168         icon = "7z.png";
00169         break;
00170     default:
00171         icon = "unk.png";
00172     }
00173     replace(item, "{icon}", icon);
00174     replace(item, "{link}", (isDirectory ? "files?path=" : "download?path=") + LocalWebserver::urlEncodeQueryParameterValue(path));
00175     replace(item, "{name}", encodeHtmlEntities(name));
00176     replace(item, "{size}", size);
00177     content += item;
00178 }
00179 
00181 
00182 void FilesPageHandler::handle(Client &client) {
00183     Common::String response =
00184         "<html>" \
00185         "<head><title>ScummVM</title></head>" \
00186         "<body>" \
00187         "<p>{create_directory_desc}</p>" \
00188         "<form action=\"create\">" \
00189         "<input type=\"hidden\" name=\"path\" value=\"{path}\"/>" \
00190         "<input type=\"text\" name=\"directory_name\" value=\"\"/>" \
00191         "<input type=\"submit\" value=\"{create_directory_button}\"/>" \
00192         "</form>" \
00193         "<hr/>" \
00194         "<p>{upload_file_desc}</p>" \
00195         "<form action=\"upload?path={path}\" method=\"post\" enctype=\"multipart/form-data\">" \
00196         "<input type=\"file\" name=\"upload_file-f\" allowdirs multiple/>" \
00197         "<span>{or_upload_directory_desc}</span>" \
00198         "<input type=\"file\" name=\"upload_file-d\" directory webkitdirectory multiple/>" \
00199         "<input type=\"submit\" value=\"{upload_file_button}\"/>" \
00200         "</form>"
00201         "<hr/>" \
00202         "<h1>{index_of_directory}</h1>" \
00203         "<table>{content}</table>" \
00204         "</body>" \
00205         "</html>";
00206     Common::String itemTemplate = "<tr><td><img src=\"icons/{icon}\"/></td><td><a href=\"{link}\">{name}</a></td><td>{size}</td></tr>\n"; //TODO: load this template too?
00207 
00208                                                                                                                                           // load stylish response page from the archive
00209     Common::SeekableReadStream *const stream = HandlerUtils::getArchiveFile(FILES_PAGE_NAME);
00210     if (stream)
00211         response = HandlerUtils::readEverythingFromStream(stream);
00212 
00213     Common::String path = client.queryParameter("path");
00214     Common::String content = "";
00215 
00216     // show an error message if failed to list directory
00217     if (!listDirectory(path, content, itemTemplate)) {
00218         HandlerUtils::setFilesManagerErrorMessageHandler(client, _("ScummVM couldn't list the directory you specified."));
00219         return;
00220     }
00221 
00222     //these occur twice:
00223     replace(response, "{create_directory_button}", _("Create directory"));
00224     replace(response, "{create_directory_button}", _("Create directory"));
00225     replace(response, "{path}", encodeDoubleQuotes(client.queryParameter("path")));
00226     replace(response, "{path}", encodeDoubleQuotes(client.queryParameter("path")));
00227     replace(response, "{upload_files_button}", _("Upload files")); //tab
00228     replace(response, "{upload_file_button}", _("Upload files")); //button in the tab
00229     replace(response, "{create_directory_desc}", _("Type new directory name:"));
00230     replace(response, "{upload_file_desc}", _("Select a file to upload:"));
00231     replace(response, "{or_upload_directory_desc}", _("Or select a directory (works in Chrome only):"));
00232     replace(response, "{index_of_directory}", Common::String::format(_("Index of %s"), encodeHtmlEntities(getDisplayPath(client.queryParameter("path"))).c_str()));
00233     replace(response, "{content}", content);
00234     LocalWebserver::setClientGetHandler(client, response);
00235 }
00236 
00237 } // End of namespace Networking


Generated on Sat Mar 16 2019 05:01:31 for ResidualVM by doxygen 1.7.1
curved edge   curved edge