Sfoglia il codice sorgente

Basic PROPFIND support. Not capable of listing a directory yet.

Colin Leitner 14 anni fa
parent
commit
015ddf8ac1
1 ha cambiato i file con 44 aggiunte e 2 eliminazioni
  1. 44 2
      mongoose.c

+ 44 - 2
mongoose.c

@@ -2602,7 +2602,7 @@ static int is_valid_http_method(const char *method) {
   return !strcmp(method, "GET") || !strcmp(method, "POST") ||
   return !strcmp(method, "GET") || !strcmp(method, "POST") ||
     !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") ||
     !strcmp(method, "HEAD") || !strcmp(method, "CONNECT") ||
     !strcmp(method, "PUT") || !strcmp(method, "DELETE") ||
     !strcmp(method, "PUT") || !strcmp(method, "DELETE") ||
-    !strcmp(method, "OPTIONS");
+    !strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND");
 }
 }
 
 
 // Parse HTTP request, fill in mg_request_info structure.
 // Parse HTTP request, fill in mg_request_info structure.
@@ -3242,9 +3242,49 @@ static void send_options(struct mg_connection *conn) {
 
 
   (void) mg_printf(conn,
   (void) mg_printf(conn,
       "HTTP/1.1 200 OK\r\n"
       "HTTP/1.1 200 OK\r\n"
-      "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS\r\n\r\n");
+      "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS\r\n"
+      "DAV: 1\r\n\r\n");
 }
 }
 
 
+// Writes PROPFIND properties for a collection element
+static void print_props(struct mg_connection *conn, const char* uri, struct mgstat* st) {
+  char mod[64];
+
+  (void) strftime(mod, sizeof(mod), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&st->mtime));
+
+  conn->num_bytes_sent += mg_printf(conn,
+      "<d:response>"
+       "<d:href>%s</d:href>"
+       "<d:propstat>"
+        "<d:prop>"
+         "<d:resourcetype>%s</d:resourcetype>"
+         "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
+         "<d:getlastmodified>%s</d:getlastmodified>"
+        "</d:prop>"
+        "<d:status>HTTP/1.1 200 OK</d:status>"
+       "</d:propstat>"
+      "</d:response>",
+      uri,
+      st->is_directory ? "<d:collection/>" : "",
+      st->size,
+      mod);
+}
+
+static void handle_propfind(struct mg_connection *conn, const char* path, struct mgstat* st) {
+  conn->request_info.status_code = 200;
+  (void) mg_printf(conn,
+       "HTTP/1.1 207 Multi-Status\r\n"
+       "Connection: close\r\n"
+       "Content-Type: text/xml; charset=utf-8\r\n\r\n");
+
+  conn->num_bytes_sent += mg_printf(conn,
+      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+      "<d:multistatus xmlns:d='DAV:'>");
+
+  print_props(conn, conn->request_info.uri, st);
+
+  conn->num_bytes_sent += mg_printf(conn, "</d:multistatus>");
+}
 
 
 // This is the heart of the Mongoose's logic.
 // This is the heart of the Mongoose's logic.
 // This function is called when the request is read, parsed and validated,
 // This function is called when the request is read, parsed and validated,
@@ -3296,6 +3336,8 @@ static void handle_request(struct mg_connection *conn) {
     (void) mg_printf(conn,
     (void) mg_printf(conn,
         "HTTP/1.1 301 Moved Permanently\r\n"
         "HTTP/1.1 301 Moved Permanently\r\n"
         "Location: %s/\r\n\r\n", ri->uri);
         "Location: %s/\r\n\r\n", ri->uri);
+  } else if (!strcmp(ri->request_method, "PROPFIND")) {
+    handle_propfind(conn, path, &st);
   } else if (st.is_directory &&
   } else if (st.is_directory &&
              !substitute_index_file(conn, path, sizeof(path), &st)) {
              !substitute_index_file(conn, path, sizeof(path), &st)) {
     if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {
     if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")) {