mirror of
https://github.com/lammertb/libhttp.git
synced 2026-01-27 08:02:47 +03:00
Moved handle_propfind to own file
This commit is contained in:
1
Makefile
1
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 \
|
||||
|
||||
134
src/httplib_handle_propfind.c
Normal file
134
src/httplib_handle_propfind.c
Normal file
@@ -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,
|
||||
"<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>\n",
|
||||
uri,
|
||||
filep->is_directory ? "<d:collection/>" : "",
|
||||
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, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<d:multistatus xmlns:d='DAV:'>\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", "</d:multistatus>");
|
||||
|
||||
} /* XX_httplib_handle_propfind */
|
||||
|
||||
#endif
|
||||
@@ -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 );
|
||||
|
||||
109
src/libhttp.c
109
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,
|
||||
"<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>\n",
|
||||
uri,
|
||||
filep->is_directory ? "<d:collection/>" : "",
|
||||
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, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<d:multistatus xmlns:d='DAV:'>\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", "</d:multistatus>");
|
||||
|
||||
} /* XX_httplib_handle_propfind */
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user