瀏覽代碼

WebServer: Show icons in directory listings :^)

Just adding some basic folder/file icon makes a big difference here.
Andreas Kling 5 年之前
父節點
當前提交
33d2ecdd79
共有 2 個文件被更改,包括 50 次插入10 次删除
  1. 44 10
      Services/WebServer/Client.cpp
  2. 6 0
      Services/WebServer/main.cpp

+ 44 - 10
Services/WebServer/Client.cpp

@@ -25,7 +25,9 @@
  */
 
 #include "Client.h"
+#include <AK/Base64.h>
 #include <AK/LexicalPath.h>
+#include <AK/MappedFile.h>
 #include <AK/StringBuilder.h>
 #include <AK/URLParser.h>
 #include <LibCore/DateTime.h>
@@ -156,6 +158,26 @@ void Client::send_redirect(StringView redirect_path, const HTTP::HttpRequest& re
     log_response(301, request);
 }
 
+static String folder_image_data()
+{
+    static String cache;
+    if (cache.is_empty()) {
+        MappedFile image("/res/icons/16x16/filetype-folder.png");
+        cache = encode_base64({ image.data(), image.size() });
+    }
+    return cache;
+}
+
+static String file_image_data()
+{
+    static String cache;
+    if (cache.is_empty()) {
+        MappedFile image("/res/icons/16x16/filetype-unknown.png");
+        cache = encode_base64({ image.data(), image.size() });
+    }
+    return cache;
+}
+
 void Client::handle_directory_listing(const String& requested_path, const String& real_path, const HTTP::HttpRequest& request)
 {
     StringBuilder builder;
@@ -164,22 +186,23 @@ void Client::handle_directory_listing(const String& requested_path, const String
     builder.append("<html>\n");
     builder.append("<head><title>Index of ");
     builder.append(escape_html_entities(requested_path));
-    builder.append("</title></head>\n");
-    builder.append("<body>\n");
+    builder.append("</title><style>\n");
+    builder.append(".folder { width: 16px; height: 16px; background-image: url('data:image/png;base64,");
+    builder.append(folder_image_data());
+    builder.append("'); }\n");
+    builder.append(".file { width: 16px; height: 16px; background-image: url('data:image/png;base64,");
+    builder.append(file_image_data());
+    builder.append("'); }\n");
+    builder.append("</style></head><body>\n");
     builder.append("<h1>Index of ");
     builder.append(escape_html_entities(requested_path));
     builder.append("</h1>\n");
     builder.append("<hr>\n");
-    builder.append("<table>\n");
+    builder.append("<code><table>\n");
 
     Core::DirIterator dt(real_path);
     while (dt.has_next()) {
         auto name = dt.next_path();
-        builder.append("<tr><td><a href=\"");
-        builder.append(urlencode(name));
-        builder.append("\">");
-        builder.append(escape_html_entities(name));
-        builder.append("</a></td>");
 
         StringBuilder path_builder;
         path_builder.append(real_path);
@@ -191,14 +214,25 @@ void Client::handle_directory_listing(const String& requested_path, const String
         if (rc < 0) {
             perror("stat");
         }
-        builder.appendf("<td>%10d</td>", st.st_size);
+
+        bool is_directory = S_ISDIR(st.st_mode) || name.is_one_of(".", "..");
+
+        builder.append("<tr>");
+        builder.appendf("<td><div class=\"%s\"></div></td>", is_directory ? "folder" : "file");
+        builder.append("<td><a href=\"");
+        builder.append(urlencode(name));
+        builder.append("\">");
+        builder.append(escape_html_entities(name));
+        builder.append("</a></td><td>&nbsp;</td>");
+
+        builder.appendf("<td>%10d</td><td>&nbsp;</td>", st.st_size);
         builder.append("<td>");
         builder.append(Core::DateTime::from_timestamp(st.st_mtime).to_string());
         builder.append("</td>");
         builder.append("</tr>\n");
     }
 
-    builder.append("</table>\n");
+    builder.append("</table></code>\n");
     builder.append("<hr>\n");
     builder.append("<i>Generated by WebServer (SerenityOS)</i>\n");
     builder.append("</body>\n");

+ 6 - 0
Services/WebServer/main.cpp

@@ -25,6 +25,7 @@
  */
 
 #include "Client.h"
+#include <AK/MappedFile.h>
 #include <LibCore/ArgsParser.h>
 #include <LibCore/EventLoop.h>
 #include <LibCore/File.h>
@@ -75,6 +76,11 @@ int main(int argc, char** argv)
     server->listen({}, port);
     printf("Listening on 0.0.0.0:%d\n", port);
 
+    if (unveil("/res/icons", "r") < 0) {
+        perror("unveil");
+        return 1;
+    }
+
     if (unveil(real_root_path.characters(), "r") < 0) {
         perror("unveil");
         return 1;