diff --git a/client/HTTPServer.cpp b/client/HTTPServer.cpp index fc045760..cff6256c 100644 --- a/client/HTTPServer.cpp +++ b/client/HTTPServer.cpp @@ -94,26 +94,41 @@ void HTTPConnection::HandleWriteReply(const boost::system::error_code& e) } } -void HTTPConnection::HandleRequest() +void HTTPConnection::Send404Reply() +{ + try { + const std::string error_page = "404.html"; + m_Reply = i2p::util::http::Response(404, GetFileContents(error_page, true)); + m_Reply.setHeader("Content-Type", i2p::util::http::getMimeType(error_page)); + } catch(const std::runtime_error&) { + // Failed to load 404.html, assume the webui is incorrectly installed + m_Reply = i2p::util::http::Response(404, + "<!DOCTYPE HTML><html>" + "<head><title>Error: 404 - webui not installed</title></head><body>" + "<p>It looks like your webui installation is broken.</p>" + "<p>Run the following command to (re)install it:</p>" + "<pre>./i2pd --install /path/to/webui</pre>" + "<p>The webui folder should come with the binaries.</p>" + "</body></html>" + ); + } + SendReply(); +} + +std::string HTTPConnection::GetFileContents(const std::string& filename, bool preprocess) const { boost::system::error_code e; - std::string uri = m_Request.getUri(); - if(uri == "/") - uri = "index.html"; - - // Use canonical to avoid .. or . in path + // Use canonical to avoid .. or . in path const boost::filesystem::path address = boost::filesystem::canonical( - i2p::util::filesystem::GetWebuiDataDir() / uri, e + i2p::util::filesystem::GetWebuiDataDir() / filename, e ); const std::string address_str = address.string(); std::ifstream ifs(address_str); - if(e || !ifs || !isAllowed(address_str)) { - m_Reply = i2p::util::http::Response(404, ""); - return SendReply(); - } + if(e || !ifs || !isAllowed(address_str)) + throw std::runtime_error("Cannot load " + address_str + "."); std::string str; ifs.seekg(0, ifs.end); @@ -122,11 +137,27 @@ void HTTPConnection::HandleRequest() ifs.read(&str[0], str.size()); ifs.close(); - str = i2p::util::http::preprocessContent(str, address.parent_path().string()); - m_Reply = i2p::util::http::Response(200, str); + if(preprocess) + return i2p::util::http::preprocessContent(str, address.parent_path().string()); + else + return str; +} - m_Reply.setHeader("Content-Type", i2p::util::http::getMimeType(address_str)); - SendReply(); +void HTTPConnection::HandleRequest() +{ + + std::string uri = m_Request.getUri(); + if(uri == "/") + uri = "index.html"; + + try { + m_Reply = i2p::util::http::Response(200, GetFileContents(uri, true)); + m_Reply.setHeader("Content-Type", i2p::util::http::getMimeType(uri)); + SendReply(); + } catch(const std::runtime_error&) { + // Cannot open the file for some reason, send 404 + Send404Reply(); + } } void HTTPConnection::HandleI2PControlRequest() @@ -138,7 +169,7 @@ void HTTPConnection::HandleI2PControlRequest() SendReply(); } -bool HTTPConnection::isAllowed(const std::string& address) +bool HTTPConnection::isAllowed(const std::string& address) const { const std::size_t pos_dot = address.find_last_of('.'); const std::size_t pos_slash = address.find_last_of('/'); diff --git a/client/HTTPServer.h b/client/HTTPServer.h index d47cd700..a4209e2d 100644 --- a/client/HTTPServer.h +++ b/client/HTTPServer.h @@ -32,11 +32,18 @@ private: void HandleWriteReply(const boost::system::error_code& ecode); void SendReply(); + void Send404Reply(); + + /* + * @throw std::runtime_error when the file is not accessible + */ + std::string GetFileContents(const std::string& filename, bool preprocess) const; + void HandleRequest(); void HandleI2PControlRequest(); void ExtractParams(const std::string& str, std::map<std::string, std::string>& params); - bool isAllowed(const std::string& address); + bool isAllowed(const std::string& address) const; private: boost::asio::ip::tcp::socket* m_Socket; char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1]; diff --git a/webui/404.html b/webui/404.html new file mode 100644 index 00000000..41174fe6 --- /dev/null +++ b/webui/404.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<title>404 - Page not found</title> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<link rel="stylesheet" href="css/main.css"> +</head> + + +<body> +<div class="header"> + <h1>404 - Page not found</h1> +</div> + +<div class="content"> + <h2 class="content-subhead">The page you were looking for could not be found.</h2> +</div> + +<!--#include virtual="menu.html" --> +<!--#include virtual="footer.html" --> + +</body> +</html> diff --git a/webui/help.html b/webui/help.html index d626ec16..09f519b2 100644 --- a/webui/help.html +++ b/webui/help.html @@ -5,7 +5,6 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="css/main.css"> -<script type="text/javascript" src="javascript/I2PControl.js"></script> </head> <body> diff --git a/webui/menu.html b/webui/menu.html index 47c7e8b0..d73089e3 100644 --- a/webui/menu.html +++ b/webui/menu.html @@ -8,7 +8,7 @@ <a href="netdb.html" class="menu-link">Network Database</a> </li> <li class="menu-item"> - <a href="#/config" class="menu-link">Configure</a> + <a href="config.html" class="menu-link">Configure</a> </li> <li class="menu-item"> <a href="help.html" class="menu-link">Help</a> diff --git a/webui/netdb.html b/webui/netdb.html index 2ac2147a..321c3751 100644 --- a/webui/netdb.html +++ b/webui/netdb.html @@ -19,7 +19,7 @@ function updateNetDbInfo(result, session) { "leasesets" : result["i2p.router.netdb.leasesets"], }); - window.setTimeout(function() { requestNetDbInfo(session); }, 5000); + window.setTimeout(function() { requestNetDbInfo(session); }, 10000); } function requestNetDbInfo(session) {