mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-05 02:49:00 +08:00
commit
4a88ad5ca9
120
mongoose.c
120
mongoose.c
@ -2695,6 +2695,50 @@ static int scan_directory(struct mg_connection *conn, const char *dir,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int remove_directory(struct mg_connection *conn, const char *dir) {
|
||||||
|
char path[PATH_MAX];
|
||||||
|
struct dirent *dp;
|
||||||
|
DIR *dirp;
|
||||||
|
struct de de;
|
||||||
|
|
||||||
|
if ((dirp = opendir(dir)) == NULL) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
de.conn = conn;
|
||||||
|
|
||||||
|
while ((dp = readdir(dirp)) != NULL) {
|
||||||
|
// Do not show current dir (but show hidden files as they will also be removed)
|
||||||
|
if (!strcmp(dp->d_name, ".") ||
|
||||||
|
!strcmp(dp->d_name, "..")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, '/', dp->d_name);
|
||||||
|
|
||||||
|
// If we don't memset stat structure to zero, mtime will have
|
||||||
|
// garbage and strftime() will segfault later on in
|
||||||
|
// print_dir_entry(). memset is required only if mg_stat()
|
||||||
|
// fails. For more details, see
|
||||||
|
// http://code.google.com/p/mongoose/issues/detail?id=79
|
||||||
|
memset(&de.file, 0, sizeof(de.file));
|
||||||
|
mg_stat(conn, path, &de.file);
|
||||||
|
if(de.file.modification_time) {
|
||||||
|
if(de.file.is_directory) {
|
||||||
|
remove_directory(conn, path);
|
||||||
|
} else {
|
||||||
|
mg_remove(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
(void) closedir(dirp);
|
||||||
|
|
||||||
|
rmdir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct dir_scan_data {
|
struct dir_scan_data {
|
||||||
struct de *entries;
|
struct de *entries;
|
||||||
int num_entries;
|
int num_entries;
|
||||||
@ -2948,7 +2992,9 @@ 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, "PROPFIND");
|
!strcmp(method, "OPTIONS") || !strcmp(method, "PROPFIND")
|
||||||
|
|| !strcmp(method, "MKCOL")
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse HTTP request, fill in mg_request_info structure.
|
// Parse HTTP request, fill in mg_request_info structure.
|
||||||
@ -3466,6 +3512,46 @@ static int put_dir(struct mg_connection *conn, const char *path) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mkcol(struct mg_connection *conn, const char *path) {
|
||||||
|
int rc, body_len;
|
||||||
|
struct de de;
|
||||||
|
memset(&de.file, 0, sizeof(de.file));
|
||||||
|
mg_stat(conn, path, &de.file);
|
||||||
|
|
||||||
|
if(de.file.modification_time) {
|
||||||
|
send_http_error(conn, 405, "Method Not Allowed",
|
||||||
|
"mkcol(%s): %s", path, strerror(ERRNO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
body_len = conn->data_len - conn->request_len;
|
||||||
|
if(body_len > 0) {
|
||||||
|
send_http_error(conn, 415, "Unsupported media type",
|
||||||
|
"mkcol(%s): %s", path, strerror(ERRNO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = mg_mkdir(path, 0755);
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
conn->status_code = 201;
|
||||||
|
mg_printf(conn, "HTTP/1.1 %d Created\r\n\r\n", conn->status_code);
|
||||||
|
} else if (rc == -1) {
|
||||||
|
if(errno == EEXIST)
|
||||||
|
send_http_error(conn, 405, "Method Not Allowed",
|
||||||
|
"mkcol(%s): %s", path, strerror(ERRNO));
|
||||||
|
else if(errno == EACCES)
|
||||||
|
send_http_error(conn, 403, "Forbidden",
|
||||||
|
"mkcol(%s): %s", path, strerror(ERRNO));
|
||||||
|
else if(errno == ENOENT)
|
||||||
|
send_http_error(conn, 409, "Conflict",
|
||||||
|
"mkcol(%s): %s", path, strerror(ERRNO));
|
||||||
|
else
|
||||||
|
send_http_error(conn, 500, http_500_error,
|
||||||
|
"fopen(%s): %s", path, strerror(ERRNO));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void put_file(struct mg_connection *conn, const char *path) {
|
static void put_file(struct mg_connection *conn, const char *path) {
|
||||||
struct file file = STRUCT_FILE_INITIALIZER;
|
struct file file = STRUCT_FILE_INITIALIZER;
|
||||||
const char *range;
|
const char *range;
|
||||||
@ -3655,7 +3741,7 @@ static void send_options(struct mg_connection *conn) {
|
|||||||
conn->status_code = 200;
|
conn->status_code = 200;
|
||||||
|
|
||||||
mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n"
|
mg_printf(conn, "%s", "HTTP/1.1 200 OK\r\n"
|
||||||
"Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS\r\n"
|
"Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL\r\n"
|
||||||
"DAV: 1\r\n\r\n");
|
"DAV: 1\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3684,10 +3770,12 @@ static void print_props(struct mg_connection *conn, const char* uri,
|
|||||||
|
|
||||||
static void print_dav_dir_entry(struct de *de, void *data) {
|
static void print_dav_dir_entry(struct de *de, void *data) {
|
||||||
char href[PATH_MAX];
|
char href[PATH_MAX];
|
||||||
|
char href_encoded[PATH_MAX];
|
||||||
struct mg_connection *conn = (struct mg_connection *) data;
|
struct mg_connection *conn = (struct mg_connection *) data;
|
||||||
mg_snprintf(conn, href, sizeof(href), "%s%s",
|
mg_snprintf(conn, href, sizeof(href), "%s%s",
|
||||||
conn->request_info.uri, de->file_name);
|
conn->request_info.uri, de->file_name);
|
||||||
print_props(conn, href, &de->file);
|
mg_url_encode(href, href_encoded, PATH_MAX-1);
|
||||||
|
print_props(conn, href_encoded, &de->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_propfind(struct mg_connection *conn, const char *path,
|
static void handle_propfind(struct mg_connection *conn, const char *path,
|
||||||
@ -4182,7 +4270,7 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir) {
|
|||||||
|
|
||||||
static int is_put_or_delete_request(const struct mg_connection *conn) {
|
static int is_put_or_delete_request(const struct mg_connection *conn) {
|
||||||
const char *s = conn->request_info.request_method;
|
const char *s = conn->request_info.request_method;
|
||||||
return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE"));
|
return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE") || !strcmp(s, "MKCOL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_first_ssl_listener_index(const struct mg_context *ctx) {
|
static int get_first_ssl_listener_index(const struct mg_context *ctx) {
|
||||||
@ -4249,18 +4337,34 @@ static void handle_request(struct mg_connection *conn) {
|
|||||||
} else if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
|
} else if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
|
||||||
send_http_error(conn, 404, "Not Found", "Not Found");
|
send_http_error(conn, 404, "Not Found", "Not Found");
|
||||||
} else if (is_put_or_delete_request(conn) &&
|
} else if (is_put_or_delete_request(conn) &&
|
||||||
(conn->ctx->config[PUT_DELETE_PASSWORDS_FILE] == NULL ||
|
(is_authorized_for_put(conn) != 1)) {
|
||||||
is_authorized_for_put(conn) != 1)) {
|
|
||||||
send_authorization_request(conn);
|
send_authorization_request(conn);
|
||||||
} else if (!strcmp(ri->request_method, "PUT")) {
|
} else if (!strcmp(ri->request_method, "PUT")) {
|
||||||
put_file(conn, path);
|
put_file(conn, path);
|
||||||
|
} else if (!strcmp(ri->request_method, "MKCOL")) {
|
||||||
|
mkcol(conn, path);
|
||||||
} else if (!strcmp(ri->request_method, "DELETE")) {
|
} else if (!strcmp(ri->request_method, "DELETE")) {
|
||||||
if (mg_remove(path) == 0) {
|
struct de de;
|
||||||
send_http_error(conn, 200, "OK", "%s", "");
|
memset(&de.file, 0, sizeof(de.file));
|
||||||
|
if(!mg_stat(conn, path, &de.file)) {
|
||||||
|
send_http_error(conn, 404, "Not Found", "%s", "File not found");
|
||||||
} else {
|
} else {
|
||||||
|
if(de.file.modification_time) {
|
||||||
|
if(de.file.is_directory) {
|
||||||
|
remove_directory(conn, path);
|
||||||
|
send_http_error(conn, 204, "No Content", "%s", "");
|
||||||
|
} else if (mg_remove(path) == 0) {
|
||||||
|
send_http_error(conn, 204, "No Content", "%s", "");
|
||||||
|
} else {
|
||||||
|
send_http_error(conn, 423, "Locked", "remove(%s): %s", path,
|
||||||
|
strerror(ERRNO));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
send_http_error(conn, 500, http_500_error, "remove(%s): %s", path,
|
send_http_error(conn, 500, http_500_error, "remove(%s): %s", path,
|
||||||
strerror(ERRNO));
|
strerror(ERRNO));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if ((file.membuf == NULL && file.modification_time == (time_t) 0) ||
|
} else if ((file.membuf == NULL && file.modification_time == (time_t) 0) ||
|
||||||
must_hide_file(conn, path)) {
|
must_hide_file(conn, path)) {
|
||||||
send_http_error(conn, 404, "Not Found", "%s", "File not found");
|
send_http_error(conn, 404, "Not Found", "%s", "File not found");
|
||||||
|
Loading…
Reference in New Issue
Block a user