diff --git a/memo.txt b/memo.txt index 28280f6..dd03cec 100644 --- a/memo.txt +++ b/memo.txt @@ -1,4 +1,5 @@ +- do correct handling of special character in url (/rfc2119_files/errata.js.t%C3%A9l%C3%A9chargement -> /rfc2119_files/errata.js.téléchargement) - handle redirection - maybe add a "last_action_time" in Client for timeout handling little global timeout on epoll, like 100ms, then find client that actualy need to timeout diff --git a/srcs/Client.cpp b/srcs/Client.cpp index 8de09f4..471da4e 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -1,6 +1,8 @@ #include "Client.hpp" +char Client::buf[MAX_FILESIZE+1]; + /********************************************* * COPLIENS *********************************************/ @@ -54,6 +56,7 @@ void Client::clear() clear_request(); raw_request.clear(); response.clear(); + body_size = 0; status = 0; } diff --git a/srcs/Client.hpp b/srcs/Client.hpp index 38fcd33..c23a7de 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -17,6 +17,7 @@ struct Request std::string body; }; +# define MAX_FILESIZE 1000000 // (1Mo) class Client { public: @@ -28,6 +29,8 @@ class Client int fd; std::string raw_request; std::string response; + static char buf[MAX_FILESIZE+1]; + size_t body_size; unsigned int status; // const functions ? diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 585feac..67e2c13 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -62,6 +62,7 @@ class Webserv std::vector _servers; std::vector _clients; std::map _http_status; + std::map _mime_types; // accept.cpp void _accept_connection(int fd); @@ -77,7 +78,7 @@ class Webserv void _process_method(Client *client, ServerConfig &server, LocationConfig &location); void _insert_status_line(Client *client); void _error_html_response(Client *client, ServerConfig &server); - void _append_body(Client *client, const char *body, size_t body_size); + void _append_body(Client *client, const char *body, size_t body_size, const std::string &file_extension = ""); void _get(Client *client, ServerConfig &server, LocationConfig &location); void _get_file(Client *client, const std::string &path); @@ -109,6 +110,7 @@ class Webserv void _bind(int socket_fd, in_port_t port, std::string host); void _listen(int socket_fd, unsigned int max_connections); void _init_http_status_map(); + void _init_mime_types_map(); }; #endif diff --git a/srcs/webserv/base.cpp b/srcs/webserv/base.cpp index 30fa868..3392619 100644 --- a/srcs/webserv/base.cpp +++ b/srcs/webserv/base.cpp @@ -13,6 +13,7 @@ Webserv::Webserv() } _init_http_status_map(); + _init_mime_types_map(); std::signal(SIGPIPE, signal_handler); std::signal(SIGINT, signal_handler); diff --git a/srcs/webserv/init.cpp b/srcs/webserv/init.cpp index db0c4be..ddd0edc 100644 --- a/srcs/webserv/init.cpp +++ b/srcs/webserv/init.cpp @@ -91,3 +91,119 @@ void Webserv::_init_http_status_map() _http_status[500] = S500; } + +void Webserv::_init_mime_types_map() +{ + _mime_types[""] = "application/octet-stream"; + + _mime_types["html"] = "text/html"; + _mime_types["htm"] = "text/html"; + _mime_types["shtml"] = "text/html"; + _mime_types["css"] = "text/css"; + _mime_types["xml"] = "text/xml"; + _mime_types["gif"] = "image/gif"; + _mime_types["jpeg"] = "image/jpeg"; + _mime_types["jpg"] = "image/jpeg"; + _mime_types["js"] = "application/javascript"; + _mime_types["atom"] = "application/atom+xml"; + _mime_types["rss"] = "application/rss+xml"; + + _mime_types["mml"] = "text/mathml"; + _mime_types["txt"] = "text/plain"; + _mime_types["jad"] = "text/vnd.sun.j2me.app-descriptor"; + _mime_types["wml"] = "text/vnd.wap.wml"; + _mime_types["htc"] = "text/x-component"; + + _mime_types["png"] = "image/png"; + _mime_types["tif"] = "image/tiff"; + _mime_types["tiff"] = "image/tiff"; + _mime_types["wbmp"] = "image/vnd.wap.wbmp"; + _mime_types["ico"] = "image/x-icon"; + _mime_types["jng"] = "image/x-jng"; + _mime_types["bmp"] = "image/x-ms-bmp"; + _mime_types["svg"] = "image/svg+xml"; + _mime_types["svgz"] = "image/svg+xml"; + _mime_types["webp"] = "image/webp"; + + _mime_types["woff"] = "application/font-woff"; + _mime_types["jar"] = "application/java-archive"; + _mime_types["war"] = "application/java-archive"; + _mime_types["ear"] = "application/java-archive"; + _mime_types["json"] = "application/json"; + _mime_types["hqx"] = "application/mac-binhex40"; + _mime_types["doc"] = "application/msword"; + _mime_types["pdf"] = "application/pdf"; + _mime_types["ps"] = "application/postscript"; + _mime_types["eps"] = "application/postscript"; + _mime_types["ai"] = "application/postscript"; + _mime_types["rtf"] = "application/rtf"; + _mime_types["m3u8"] = "application/vnd.apple.mpegurl"; + _mime_types["xls"] = "application/vnd.ms-excel"; + _mime_types["eot"] = "application/vnd.ms-fontobject"; + _mime_types["ppt"] = "application/vnd.ms-powerpoint"; + _mime_types["wmlc"] = "application/vnd.wap.wmlc"; + _mime_types["kml"] = "application/vnd.google-earth.kml+xml"; + _mime_types["kmz"] = "application/vnd.google-earth.kmz"; + _mime_types["7z"] = "application/x-7z-compressed"; + _mime_types["cco"] = "application/x-cocoa"; + _mime_types["jardiff"] = "application/x-java-archive-diff"; + _mime_types["jnlp"] = "application/x-java-jnlp-file"; + _mime_types["run"] = "application/x-makeself"; + _mime_types["pl"] = "application/x-perl"; + _mime_types["pm"] = "application/x-perl"; + _mime_types["prc"] = "application/x-pilot"; + _mime_types["pdb"] = "application/x-pilot"; + _mime_types["rar"] = "application/x-rar-compressed"; + _mime_types["rpm"] = "application/x-redhat-package-manager"; + _mime_types["sea"] = "application/x-sea"; + _mime_types["swf"] = "application/x-shockwave-flash"; + _mime_types["sit"] = "application/x-stuffit"; + _mime_types["tcl"] = "application/x-tcl"; + _mime_types["tk"] = "application/x-tcl"; + _mime_types["der"] = "application/x-x509-ca-cert"; + _mime_types["pem"] = "application/x-x509-ca-cert"; + _mime_types["crt"] = "application/x-x509-ca-cert"; + _mime_types["xpi"] = "application/x-xpinstall"; + _mime_types["xhtml"] = "application/xhtml+xml"; + _mime_types["xspf"] = "application/xspf+xml"; + _mime_types["zip"] = "application/zip"; + + _mime_types["bin"] = "application/octet-stream"; + _mime_types["exe"] = "application/octet-stream"; + _mime_types["dll"] = "application/octet-stream"; + _mime_types["deb"] = "application/octet-stream"; + _mime_types["dmg"] = "application/octet-stream"; + _mime_types["iso"] = "application/octet-stream"; + _mime_types["img"] = "application/octet-stream"; + _mime_types["msi"] = "application/octet-stream"; + _mime_types["msp"] = "application/octet-stream"; + _mime_types["msm"] = "application/octet-stream"; + + _mime_types["docx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + _mime_types["xlsx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + _mime_types["pptx"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; + + _mime_types["mid"] = "audio/midi"; + _mime_types["midi"] = "audio/midi"; + _mime_types["kar"] = "audio/midi"; + _mime_types["mp3"] = "audio/mpeg"; + _mime_types["ogg"] = "audio/ogg"; + _mime_types["m4a"] = "audio/x-m4a"; + _mime_types["ra"] = "audio/x-realaudio"; + + _mime_types["3gpp"] = "video/3gpp"; + _mime_types["3gp"] = "video/3gpp"; + _mime_types["ts"] = "video/mp2t"; + _mime_types["mp4"] = "video/mp4"; + _mime_types["mpeg"] = "video/mpeg"; + _mime_types["mpg"] = "video/mpeg"; + _mime_types["mov"] = "video/quicktime"; + _mime_types["webm"] = "video/webm"; + _mime_types["flv"] = "video/x-flv"; + _mime_types["m4v"] = "video/x-m4v"; + _mime_types["mng"] = "video/x-mng"; + _mime_types["asx"] = "video/x-ms-asf"; + _mime_types["asf"] = "video/x-ms-asf"; + _mime_types["wmv"] = "video/x-ms-wmv"; + _mime_types["avi"] = "video/x-msvideo"; +} diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 705f77d..0b6f3fa 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -32,6 +32,19 @@ void Webserv::_send_response(Client *client, ServerConfig &server) return ; } + // Body send (WIP for working binary files) + if (client->body_size) + { + ret = ::send(client->fd, client->buf, client->body_size, 0); + if (ret == -1) + { + std::perror("err send()"); + std::cerr << "client.fd =" << client->fd << "\n"; // DEBUG + _close_client(client->fd); + return ; + } + } + if (client->get_headers("Connection") == "close") _close_client(client->fd); else @@ -114,7 +127,7 @@ void Webserv::_error_html_response(Client *client, ServerConfig &server) { std::string html_page = HTML_ERROR; ::replace_all_substr(html_page, STATUS_PLACEHOLDER, _http_status[client->status]); - _append_body(client, html_page.c_str(), html_page.size()); + _append_body(client, html_page.c_str(), html_page.size(), "html"); } else _get_file(client, server.error_pages[client->status]); @@ -145,11 +158,10 @@ void Webserv::_get(Client *client, ServerConfig &server, LocationConfig &locatio _get_file(client, path); } -#define MAX_FILESIZE 1000000 // (1Mo) void Webserv::_get_file(Client *client, const std::string &path) { std::ifstream ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ? - char buf[MAX_FILESIZE+1]; + // char buf[MAX_FILESIZE+1]; if (access(path.c_str(), F_OK) == -1) { @@ -186,7 +198,7 @@ void Webserv::_get_file(Client *client, const std::string &path) } ifd.seekg(0, std::ios::beg); - ifd.read(buf, size); + ifd.read(client->buf, size); if (!ifd) { std::cerr << path << ": ifd.read fail" << '\n'; @@ -195,15 +207,25 @@ void Webserv::_get_file(Client *client, const std::string &path) else { client->status = 200; - buf[ifd.gcount()] = '\0'; - _append_body(client, buf, ifd.gcount()); + client->buf[ifd.gcount()] = '\0'; + + std::string file_ext = ""; + size_t dot_pos = path.rfind("."); + std::cerr << "dot_pos = " << dot_pos << "\n"; + if (dot_pos != std::string::npos && dot_pos + 1 < path.size()) + file_ext = path.substr(dot_pos + 1); + std::cerr << "file_ext = " << file_ext << "\n"; + + client->body_size = ifd.gcount(); + // WIP, pass empty body argument because append to string mess up binary file + _append_body(client, "", client->body_size, file_ext); } ifd.close(); } } -void Webserv::_append_body(Client *client, const char *body, size_t body_size) +void Webserv::_append_body(Client *client, const char *body, size_t body_size, const std::string &file_extension) { /* TODO : determine Content-Type @@ -212,7 +234,12 @@ void Webserv::_append_body(Client *client, const char *body, size_t body_size) http://nginx.org/en/docs/http/ngx_http_core_module.html#types Need to look "conf/mime.types" of nginx. Maybe make a map<> based on that. */ - client->response.append("Content-Type: text/html; charset=UTF-8" CRLF); + const std::string &mime_type = _mime_types[file_extension]; + client->response.append("Content-Type: "); + client->response.append(mime_type); + if (mime_type.find("text/") != std::string::npos) + client->response.append("; charset=UTF-8"); + client->response.append(CRLF); client->response.append("Content-Length: "); std::string tmp = ::itos(body_size); @@ -220,7 +247,7 @@ void Webserv::_append_body(Client *client, const char *body, size_t body_size) client->response.append(CRLF); client->response.append(CRLF); - client->response.append(body); + client->response.append(body); } void Webserv::_post(Client *client, ServerConfig &server, LocationConfig &location) diff --git a/www/drill.jpg b/www/drill.jpg new file mode 100644 index 0000000..1812dbd Binary files /dev/null and b/www/drill.jpg differ diff --git a/www/favicon.ico b/www/favicon.ico new file mode 100644 index 0000000..8be776b Binary files /dev/null and b/www/favicon.ico differ diff --git a/www/kermit.ico b/www/kermit.ico new file mode 100644 index 0000000..8be776b Binary files /dev/null and b/www/kermit.ico differ diff --git a/www/rfc2119.html b/www/rfc2119.html index b8b389b..42168fa 100644 --- a/www/rfc2119.html +++ b/www/rfc2119.html @@ -13,7 +13,7 @@ - +
@@ -309,4 +309,4 @@ Full stop should appear outside the parentheses in the last sentence. - + \ No newline at end of file diff --git a/www/rfc2119_files/errata-base.css b/www/rfc2119_files/errata-base.css new file mode 100644 index 0000000..c34a536 --- /dev/null +++ b/www/rfc2119_files/errata-base.css @@ -0,0 +1,139 @@ + diff --git a/www/rfc2119_files/errata-color.css b/www/rfc2119_files/errata-color.css new file mode 100644 index 0000000..74428de --- /dev/null +++ b/www/rfc2119_files/errata-color.css @@ -0,0 +1,43 @@ + diff --git a/www/rfc2119_files/errata-monochrome.css b/www/rfc2119_files/errata-monochrome.css new file mode 100644 index 0000000..be74384 --- /dev/null +++ b/www/rfc2119_files/errata-monochrome.css @@ -0,0 +1,34 @@ + diff --git a/www/rfc2119_files/errata-printer.css b/www/rfc2119_files/errata-printer.css new file mode 100644 index 0000000..4a3dab3 --- /dev/null +++ b/www/rfc2119_files/errata-printer.css @@ -0,0 +1,43 @@ + diff --git a/www/rfc2119_files/errata.js b/www/rfc2119_files/errata.js new file mode 100644 index 0000000..4e29587 --- /dev/null +++ b/www/rfc2119_files/errata.js @@ -0,0 +1,4 @@ +function hideFunction(nodeId) { + var ul = document.getElementById(nodeId) + ul.className = (ul.className=="nodeOpenClass") ? "nodeCloseClass" : "nodeOpenClass" +} diff --git a/www/rfc2119_files/errata.js.téléchargement b/www/rfc2119_files/errata.js.téléchargement new file mode 100644 index 0000000..4e29587 --- /dev/null +++ b/www/rfc2119_files/errata.js.téléchargement @@ -0,0 +1,4 @@ +function hideFunction(nodeId) { + var ul = document.getElementById(nodeId) + ul.className = (ul.className=="nodeOpenClass") ? "nodeCloseClass" : "nodeOpenClass" +} diff --git a/www/rfc2119_no_link.html b/www/rfc2119_no_link.html deleted file mode 100644 index eec8fe5..0000000 --- a/www/rfc2119_no_link.html +++ /dev/null @@ -1,300 +0,0 @@ - - - - rfc2119 - - -
-This is a purely informative rendering of an RFC that includes verified errata. This rendering may not be used as a reference. -
-
-The following 'Verified' errata have been incorporated in this document: - EID 493, EID 494, EID 495, EID 496, EID 498, EID 499, EID 500, EID 5101 -
- -
Network Working Group                                         S. Bradner
-Request for Comments: 2119                            Harvard University
-BCP: 14                                                       March 1997
-Category: Best Current Practice
-
-
-        Key words for use in RFCs to Indicate Requirement Levels
-
-Status of this Memo
-
-   This document specifies an Internet Best Current Practices for the
-   Internet Community, and requests discussion and suggestions for
-   improvements.  Distribution of this memo is unlimited.
-
-Abstract
-
-   In many standards track documents several words are used to signify
-   the requirements in the specification.  These words are often
-   capitalized.  This document defines these words as they should be
-   interpreted in IETF documents.  Authors who follow these guidelines
-   should incorporate this phrase near the beginning of their document:
-
-             The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL 
-       NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT 
-       RECOMMENDED",  "MAY", and "OPTIONAL" in this document are to 
-       be interpreted as described in RFC 2119.
-
-
EID 499 (Verified) is as follows:
-
-Section: Abstract
-
-Original Text:
-
-       The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
-       NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
-       "OPTIONAL" in this document are to be interpreted as described in
-       RFC 2119.
-
-Corrected Text:
-
-       The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
-       NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT 
-       RECOMMENDED",  "MAY", and "OPTIONAL" in this document are to 
-       be interpreted as described in RFC 2119.
-
-Notes:
-The phrase "NOT RECOMMENDED" is missing from this sentence. -
-
- Note that the force of these words is modified by the requirement - level of the document in which they are used. - -1. MUST This word, or the terms "REQUIRED" or "SHALL", means that the - definition is an absolute requirement of the specification. -
-
EID 493 (Verified) is as follows:
-
-Section: 1
-
-Original Text:
-
-2. MUST NOT   This phrase, or the phrase "SHALL NOT", mean that the
-   definition is an absolute prohibition of the specification.
-
-Corrected Text:
-
-2. MUST NOT   This phrase, or the phrase "SHALL NOT", means that the
-   definition is an absolute prohibition of the specification.
-
-Notes:
- -
-
-
EID 498 (Verified) is as follows:
-
-Section: 1
-
-Original Text:
-
-4. SHOULD NOT   This phrase, or the phrase "NOT RECOMMENDED" mean that
-   there may exist valid reasons in particular circumstances when the
-   particular behavior is acceptable or even useful, but the full
-   implications should be understood and the case carefully weighed
-   before implementing any behavior described with this label.
-
-Corrected Text:
-
-4. SHOULD NOT   This phrase, or the phrase "NOT RECOMMENDED", means that
-   there may exist valid reasons in particular circumstances when the
-   particular behavior is acceptable or even useful, but the full
-   implications should be understood and the case carefully weighed
-   before implementing any behavior described with this label.
-
-Notes:
- -
-
-
EID 500 (Verified) is as follows:
-
-Section: 1
-
-Original Text:
-
-3. SHOULD   This word, or the adjective "RECOMMENDED", mean that there
-   may exist valid reasons in particular circumstances to ignore a
-   particular item, but the full implications must be understood and
-   carefully weighed before choosing a different course.
-
-Corrected Text:
-
-3. SHOULD   This word, or the adjective "RECOMMENDED", means that there
-   may exist valid reasons in particular circumstances to ignore a
-   particular item, but the full implications must be understood and
-   carefully weighed before choosing a different course.
-
-Notes:
- -
-
-
-
EID 495 (Verified) is as follows:
-
-Section: 1
-
-Original Text:
-
-1. MUST   This word, or the terms "REQUIRED" or "SHALL", mean that the
-   definition is an absolute requirement of the specification.
-
-
-Corrected Text:
-
-1. MUST   This word, or the terms "REQUIRED" or "SHALL", means that the
-   definition is an absolute requirement of the specification.
-
-Notes:
- -
-
-2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the - definition is an absolute prohibition of the specification. - -3. SHOULD This word, or the adjective "RECOMMENDED", mean that there - may exist valid reasons in particular circumstances to ignore a - particular item, but the full implications must be understood and - carefully weighed before choosing a different course. - -4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that - there may exist valid reasons in particular circumstances when the - particular behavior is acceptable or even useful, but the full - implications should be understood and the case carefully weighed - before implementing any behavior described with this label. - -5. MAY This word, or the adjective "OPTIONAL", mean that an item is - truly optional. One vendor may choose to include the item because a - particular marketplace requires it or because the vendor feels that - it enhances the product while another vendor may omit the same item. - An implementation which does not include a particular option MUST be - prepared to interoperate with another implementation which does - include the option, though perhaps with reduced functionality. In the - same vein an implementation which does include a particular option - MUST be prepared to interoperate with another implementation which - does not include the option (except, of course, for the feature the - option provides). -
-
EID 5101 (Verified) is as follows:
-
-Section: 5
-
-Original Text:
-
-5. MAY   This word, or the adjective "OPTIONAL", mean that an item is
-   truly optional.  One vendor may choose to include the item because a
-   particular marketplace requires it or because the vendor feels that
-   it enhances the product while another vendor may omit the same item.
-   An implementation which does not include a particular option MUST be
-   prepared to interoperate with another implementation which does
-   include the option, though perhaps with reduced functionality. In the
-   same vein an implementation which does include a particular option
-   MUST be prepared to interoperate with another implementation which
-   does not include the option (except, of course, for the feature the
-   option provides.)
-
-Corrected Text:
-
-5. MAY   This word, or the adjective "OPTIONAL", mean that an item is
-   truly optional.  One vendor may choose to include the item because a
-   particular marketplace requires it or because the vendor feels that
-   it enhances the product while another vendor may omit the same item.
-   An implementation which does not include a particular option MUST be
-   prepared to interoperate with another implementation which does
-   include the option, though perhaps with reduced functionality. In the
-   same vein an implementation which does include a particular option
-   MUST be prepared to interoperate with another implementation which
-   does not include the option (except, of course, for the feature the
-   option provides).
-
-Notes:
-Full stop should appear outside the parentheses in the last sentence. -
-
-6. Guidance in the use of these Imperatives - - Imperatives of the type defined in this memo must be used with care - and sparingly. In particular, they MUST only be used where it is - actually required for interoperation or to limit behavior which has - potential for causing harm (e.g., limiting retransmissions) For -
-
EID 494 (Verified) is as follows:
-
-Section: 6
-
-Original Text:
-
-(e.g., limiting retransmisssions)
-
-Corrected Text:
-
-(e.g., limiting retransmissions)
-
-Notes:
- -
-
-
EID 496 (Verified) is as follows:
-
-Section: 6
-
-Original Text:
-
-   In particular, they MUST only be used where it is actually required
-   for interoperation or to limit behavior which has potential for
-   causing harm (e.g., limiting retransmisssions)  For example, they
-   must not be used to try to impose a particular method on
-   implementors where the method is not required for interoperability.   
-
-Corrected Text:
-
-   In particular, they MUST only be used where it is actually required
-   for interoperation or to limit behavior which has potential for
-   causing harm (e.g., limiting retransmissions).  For example, they
-   must not be used to try to impose a particular method on
-   implementors where the method is not required for interoperability.
-
-Notes:
- -
-
example, they must not be used to try to impose a particular method - on implementors where the method is not required for - interoperability. - -7. Security Considerations - - These terms are frequently used to specify behavior with security - implications. The effects on security of not implementing a MUST or - SHOULD, or doing something the specification says MUST NOT or SHOULD - NOT be done may be very subtle. Document authors should take the time - to elaborate the security implications of not following - recommendations or requirements as most implementors will not have - had the benefit of the experience and discussion that produced the - specification. - -8. Acknowledgments - - The definitions of these terms are an amalgam of definitions taken - from a number of RFCs. In addition, suggestions have been - incorporated from a number of people including Robert Ullmann, Thomas - Narten, Neal McBurnett, and Robert Elz. - -9. Author's Address - - Scott Bradner - Harvard University - 1350 Mass. Ave. - Cambridge, MA 02138 - - phone - +1 617 495 3864 - - email - sob@harvard.edu - - - - - - -
\ No newline at end of file diff --git a/www/root.png b/www/root.png new file mode 100644 index 0000000..ebd1548 Binary files /dev/null and b/www/root.png differ