diff --git a/Makefile b/Makefile
index 2ecdeb82..85d8296b 100644
--- a/Makefile
+++ b/Makefile
@@ -64,6 +64,7 @@ LIB_SOURCES = src/libhttp.c \
src/httplib_getreq.c \
src/httplib_handle_file_based_request.c \
src/httplib_handle_form_request.c \
+ src/httplib_handle_propfind.c \
src/httplib_handle_request.c \
src/httplib_handle_websocket_request.c \
src/httplib_initialize_ssl.c \
diff --git a/src/httplib_handle_propfind.c b/src/httplib_handle_propfind.c
new file mode 100644
index 00000000..62068c27
--- /dev/null
+++ b/src/httplib_handle_propfind.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2016 Lammert Bies
+ * Copyright (c) 2013-2016 the Civetweb developers
+ * Copyright (c) 2004-2013 Sergey Lyubka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+
+#include "libhttp-private.h"
+
+
+
+#if !defined(NO_FILES)
+
+/*
+ * static void print_props( struct mg_connection *conn, const char *uri, struct file *filep );
+ *
+ * The function print_props() writes the PROPFIND properties for a collection
+ * event.
+ */
+
+static void print_props( struct mg_connection *conn, const char *uri, struct file *filep ) {
+
+ char mtime[64];
+
+ if ( conn == NULL || uri == NULL || filep == NULL ) return;
+
+ XX_httplib_gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
+ conn->num_bytes_sent +=
+ mg_printf(conn,
+ ""
+ "%s"
+ ""
+ ""
+ "%s"
+ "%" INT64_FMT ""
+ "%s"
+ ""
+ "HTTP/1.1 200 OK"
+ ""
+ "\n",
+ uri,
+ filep->is_directory ? "" : "",
+ filep->size,
+ mtime);
+
+} /* print_props */
+
+
+
+/*
+ * static void print_dav_dir_entry( struct de *de, void *data );
+ *
+ * The function print_dav_dir_entry() is used to send the properties of a
+ * webdav directory to the remote client.
+ */
+
+static void print_dav_dir_entry( struct de *de, void *data ) {
+
+ char href[PATH_MAX];
+ char href_encoded[PATH_MAX * 3 /* worst case */];
+ int truncated;
+
+ struct mg_connection *conn = (struct mg_connection *)data;
+ if (!de || !conn) return;
+
+ XX_httplib_snprintf(conn, &truncated, href, sizeof(href), "%s%s", conn->request_info.local_uri, de->file_name);
+
+ if (!truncated) {
+ mg_url_encode(href, href_encoded, PATH_MAX * 3);
+ print_props(conn, href_encoded, &de->file);
+ }
+
+} /* print_dav_dir_entry */
+
+
+
+/*
+ * void XX_httplib_handle_propfind( struct mg_connection *conn, const char *path, struct file *filep );
+ *
+ * The function XX_httlib_handle_propfind() handles a propfind request.
+ */
+
+void XX_httplib_handle_propfind( struct mg_connection *conn, const char *path, struct file *filep ) {
+
+ const char *depth = mg_get_header(conn, "Depth");
+ char date[64];
+ time_t curtime = time(NULL);
+
+ XX_httplib_gmt_time_string(date, sizeof(date), &curtime);
+
+ if (!conn || !path || !filep || !conn->ctx) return;
+
+ conn->must_close = 1;
+ conn->status_code = 207;
+ mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n" "Date: %s\r\n", date);
+ XX_httplib_send_static_cache_header(conn);
+ mg_printf(conn, "Connection: %s\r\n" "Content-Type: text/xml; charset=utf-8\r\n\r\n", XX_httplib_suggest_connection_header(conn));
+
+ conn->num_bytes_sent += mg_printf(conn, "" "\n");
+
+ /* Print properties for the requested resource itself */
+ print_props(conn, conn->request_info.local_uri, filep);
+
+ /* If it is a directory, print directory entries too if Depth is not 0 */
+ if (filep && filep->is_directory
+ && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
+ && (depth == NULL || strcmp(depth, "0") != 0)) {
+ XX_httplib_scan_directory(conn, path, conn, &print_dav_dir_entry);
+ }
+
+ conn->num_bytes_sent += mg_printf(conn, "%s\n", "");
+
+} /* XX_httplib_handle_propfind */
+
+#endif
diff --git a/src/libhttp-private.h b/src/libhttp-private.h
index d6ce8324..3542fbc7 100644
--- a/src/libhttp-private.h
+++ b/src/libhttp-private.h
@@ -825,6 +825,14 @@ struct vec {
enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
+/* Directory entry */
+struct de {
+ struct mg_connection *conn;
+ char *file_name;
+ struct file file;
+};
+
+
/*
* Functions local to the server. These functions all begin with XX_httplib to
@@ -907,9 +915,11 @@ int XX_httplib_refresh_trust( struct mg_connection *conn );
void XX_httplib_remove_bad_file( const struct mg_connection *conn, const char *path );
void XX_httplib_remove_double_dots_and_double_slashes( char *s );
void XX_httplib_reset_per_request_attributes( struct mg_connection *conn );
+int XX_httplib_scan_directory( struct mg_connection *conn, const char *dir, void *data, void (*cb)(struct de *, void *) );
void XX_httplib_send_authorization_request( struct mg_connection *conn );
void XX_httplib_send_http_error( struct mg_connection *, int, PRINTF_FORMAT_STRING(const char *fmt), ... ) PRINTF_ARGS(3, 4);
void XX_httplib_send_options( struct mg_connection *conn );
+int XX_httplib_send_static_cache_header( struct mg_connection *conn );
int XX_httplib_send_websocket_handshake( struct mg_connection *conn, const char *websock_key );
int XX_httplib_set_acl_option( struct mg_context *ctx );
void XX_httplib_set_close_on_exec( SOCKET sock, struct mg_connection *conn );
diff --git a/src/libhttp.c b/src/libhttp.c
index beeff483..fc0a06be 100644
--- a/src/libhttp.c
+++ b/src/libhttp.c
@@ -613,13 +613,6 @@ int XX_httplib_sTlsInit = 0;
int XX_httplib_thread_idx_max = 0;
-/* Directory entry */
-struct de {
- struct mg_connection *conn;
- char *file_name;
- struct file file;
-};
-
@@ -1500,7 +1493,7 @@ static int send_no_cache_header(struct mg_connection *conn) {
}
-static int send_static_cache_header(struct mg_connection *conn) {
+int XX_httplib_send_static_cache_header(struct mg_connection *conn) {
#if !defined(NO_CACHING)
/* Read the server config to check how long a file may be cached.
@@ -1526,7 +1519,8 @@ static int send_static_cache_header(struct mg_connection *conn) {
#else /* NO_CACHING */
return send_no_cache_header(conn);
#endif /* !NO_CACHING */
-}
+
+} /* XX_httplib_send_static_cache_header */
void XX_httplib_send_http_error( struct mg_connection *conn, int status, const char *fmt, ... ) {
@@ -4565,7 +4559,7 @@ int XX_httplib_must_hide_file( struct mg_connection *conn, const char *path ) {
-static int scan_directory(struct mg_connection *conn, const char *dir, void *data, void (*cb)(struct de *, void *)) {
+int XX_httplib_scan_directory( struct mg_connection *conn, const char *dir, void *data, void (*cb)(struct de *, void *) ) {
char path[PATH_MAX];
struct dirent *dp;
@@ -4605,7 +4599,8 @@ static int scan_directory(struct mg_connection *conn, const char *dir, void *dat
(void)mg_closedir(dirp);
}
return 1;
-}
+
+} /* XX_httplib_scan_directory */
#if !defined(NO_FILES)
@@ -4714,7 +4709,7 @@ void XX_httplib_handle_directory_request( struct mg_connection *conn, const char
char date[64];
time_t curtime = time(NULL);
- if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
+ if (!XX_httplib_scan_directory(conn, dir, &data, dir_scan_callback)) {
XX_httplib_send_http_error(conn, 500, "Error: Cannot open directory\nopendir(%s): %s", dir, strerror(ERRNO));
return;
}
@@ -4727,7 +4722,7 @@ void XX_httplib_handle_directory_request( struct mg_connection *conn, const char
conn->must_close = 1;
mg_printf(conn, "HTTP/1.1 200 OK\r\n");
- send_static_cache_header(conn);
+ XX_httplib_send_static_cache_header(conn);
mg_printf(conn, "Date: %s\r\n" "Connection: close\r\n" "Content-Type: text/html; charset=utf-8\r\n\r\n", date);
conn->num_bytes_sent +=
@@ -4998,9 +4993,9 @@ void XX_httplib_handle_static_file_request( struct mg_connection *conn, const ch
XX_httplib_gmt_time_string(lm, sizeof(lm), &filep->last_modified);
construct_etag(etag, sizeof(etag), filep);
- (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n" "%s%s%s" "Date: %s\r\n", conn->status_code, msg, cors1, cors2, cors3, date);
- send_static_cache_header(conn);
- (void)mg_printf(conn,
+ mg_printf(conn, "HTTP/1.1 %d %s\r\n" "%s%s%s" "Date: %s\r\n", conn->status_code, msg, cors1, cors2, cors3, date);
+ XX_httplib_send_static_cache_header(conn);
+ mg_printf(conn,
"Last-Modified: %s\r\n"
"Etag: %s\r\n"
"Content-Type: %.*s\r\n"
@@ -5048,7 +5043,7 @@ void XX_httplib_handle_not_modified_static_file_request( struct mg_connection *c
construct_etag(etag, sizeof(etag), filep);
mg_printf(conn, "HTTP/1.1 %d %s\r\n" "Date: %s\r\n", conn->status_code, mg_get_response_code_text(conn, conn->status_code), date);
- send_static_cache_header(conn);
+ XX_httplib_send_static_cache_header(conn);
mg_printf(conn, "Last-Modified: %s\r\n" "Etag: %s\r\n" "Connection: %s\r\n" "\r\n", lm, etag, XX_httplib_suggest_connection_header(conn));
} /* XX_httplib_handle_not_modified_static_file_request */
@@ -5996,7 +5991,7 @@ void XX_httplib_mkcol( struct mg_connection *conn, const char *path ) {
conn->status_code = 201;
XX_httplib_gmt_time_string(date, sizeof(date), &curtime);
mg_printf(conn, "HTTP/1.1 %d Created\r\n" "Date: %s\r\n", conn->status_code, date);
- send_static_cache_header(conn);
+ XX_httplib_send_static_cache_header(conn);
mg_printf(conn, "Content-Length: 0\r\n" "Connection: %s\r\n\r\n", XX_httplib_suggest_connection_header(conn));
}
@@ -6404,82 +6399,4 @@ void XX_httplib_send_options( struct mg_connection *conn ) {
} /* XX_httplib_send_options */
-
-/* Writes PROPFIND properties for a collection element */
-static void print_props( struct mg_connection *conn, const char *uri, struct file *filep ) {
-
- char mtime[64];
-
- if ( conn == NULL || uri == NULL || filep == NULL ) return;
-
- XX_httplib_gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
- conn->num_bytes_sent +=
- mg_printf(conn,
- ""
- "%s"
- ""
- ""
- "%s"
- "%" INT64_FMT ""
- "%s"
- ""
- "HTTP/1.1 200 OK"
- ""
- "\n",
- uri,
- filep->is_directory ? "" : "",
- filep->size,
- mtime);
-}
-
-
-static void print_dav_dir_entry(struct de *de, void *data) {
-
- char href[PATH_MAX];
- char href_encoded[PATH_MAX * 3 /* worst case */];
- int truncated;
-
- struct mg_connection *conn = (struct mg_connection *)data;
- if (!de || !conn) return;
-
- XX_httplib_snprintf(conn, &truncated, href, sizeof(href), "%s%s", conn->request_info.local_uri, de->file_name);
-
- if (!truncated) {
- mg_url_encode(href, href_encoded, PATH_MAX * 3);
- print_props(conn, href_encoded, &de->file);
- }
-}
-
-
-void XX_httplib_handle_propfind( struct mg_connection *conn, const char *path, struct file *filep ) {
-
- const char *depth = mg_get_header(conn, "Depth");
- char date[64];
- time_t curtime = time(NULL);
-
- XX_httplib_gmt_time_string(date, sizeof(date), &curtime);
-
- if (!conn || !path || !filep || !conn->ctx) return;
-
- conn->must_close = 1;
- conn->status_code = 207;
- mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n" "Date: %s\r\n", date);
- send_static_cache_header(conn);
- mg_printf(conn, "Connection: %s\r\n" "Content-Type: text/xml; charset=utf-8\r\n\r\n", XX_httplib_suggest_connection_header(conn));
-
- conn->num_bytes_sent += mg_printf(conn, "" "\n");
-
- /* Print properties for the requested resource itself */
- print_props(conn, conn->request_info.local_uri, filep);
-
- /* If it is a directory, print directory entries too if Depth is not 0 */
- if (filep && filep->is_directory
- && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
- && (depth == NULL || strcmp(depth, "0") != 0)) {
- scan_directory(conn, path, conn, &print_dav_dir_entry);
- }
-
- conn->num_bytes_sent += mg_printf(conn, "%s\n", "");
-
-} /* XX_httplib_handle_propfind */
#endif