Commit f51ca8d5 authored by Sergey Lyubka's avatar Sergey Lyubka

Added mg_send_file(). Changed sending function to return send_iobuf length.

parent 7b37e0cb
...@@ -1602,16 +1602,15 @@ static void write_chunk(struct connection *conn, const char *buf, int len) { ...@@ -1602,16 +1602,15 @@ static void write_chunk(struct connection *conn, const char *buf, int len) {
ns_send(conn->ns_conn, "\r\n", 2); ns_send(conn->ns_conn, "\r\n", 2);
} }
int mg_printf(struct mg_connection *conn, const char *fmt, ...) { size_t mg_printf(struct mg_connection *conn, const char *fmt, ...) {
struct connection *c = MG_CONN_2_CONN(conn); struct connection *c = MG_CONN_2_CONN(conn);
int len;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
len = ns_vprintf(c->ns_conn, fmt, ap); ns_vprintf(c->ns_conn, fmt, ap);
va_end(ap); va_end(ap);
return len; return c->ns_conn->send_iobuf.len;
} }
static void ns_forward(struct ns_connection *from, struct ns_connection *to) { static void ns_forward(struct ns_connection *from, struct ns_connection *to) {
...@@ -2176,7 +2175,7 @@ static int parse_http_message(char *buf, int len, struct mg_connection *ri) { ...@@ -2176,7 +2175,7 @@ static int parse_http_message(char *buf, int len, struct mg_connection *ri) {
n = (int) strlen(ri->uri); n = (int) strlen(ri->uri);
mg_url_decode(ri->uri, n, (char *) ri->uri, n + 1, 0); mg_url_decode(ri->uri, n, (char *) ri->uri, n + 1, 0);
if (*ri->uri == '/' || *ri->uri == '.') { if (*ri->uri == '/' || *ri->uri == '.') {
remove_double_dots_and_double_slashes((char *) ri->uri); remove_double_dots_and_double_slashes((char *) ri->uri);
} }
} }
...@@ -2376,9 +2375,10 @@ static int should_keep_alive(const struct mg_connection *conn) { ...@@ -2376,9 +2375,10 @@ static int should_keep_alive(const struct mg_connection *conn) {
(header == NULL && http_version && !strcmp(http_version, "1.1"))); (header == NULL && http_version && !strcmp(http_version, "1.1")));
} }
int mg_write(struct mg_connection *c, const void *buf, int len) { size_t mg_write(struct mg_connection *c, const void *buf, int len) {
struct connection *conn = MG_CONN_2_CONN(c); struct connection *conn = MG_CONN_2_CONN(c);
return ns_send(conn->ns_conn, buf, len); ns_send(conn->ns_conn, buf, len);
return conn->ns_conn->send_iobuf.len;
} }
void mg_send_status(struct mg_connection *c, int status) { void mg_send_status(struct mg_connection *c, int status) {
...@@ -2405,12 +2405,14 @@ static void terminate_headers(struct mg_connection *c) { ...@@ -2405,12 +2405,14 @@ static void terminate_headers(struct mg_connection *c) {
} }
} }
void mg_send_data(struct mg_connection *c, const void *data, int data_len) { size_t mg_send_data(struct mg_connection *c, const void *data, int data_len) {
struct connection *conn = MG_CONN_2_CONN(c);
terminate_headers(c); terminate_headers(c);
write_chunk(MG_CONN_2_CONN(c), (const char *) data, data_len); write_chunk(MG_CONN_2_CONN(c), (const char *) data, data_len);
return conn->ns_conn->send_iobuf.len;
} }
void mg_printf_data(struct mg_connection *c, const char *fmt, ...) { size_t mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
struct connection *conn = MG_CONN_2_CONN(c); struct connection *conn = MG_CONN_2_CONN(c);
va_list ap; va_list ap;
int len; int len;
...@@ -2428,6 +2430,7 @@ void mg_printf_data(struct mg_connection *c, const char *fmt, ...) { ...@@ -2428,6 +2430,7 @@ void mg_printf_data(struct mg_connection *c, const char *fmt, ...) {
if (buf != mem && buf != NULL) { if (buf != mem && buf != NULL) {
free(buf); free(buf);
} }
return conn->ns_conn->send_iobuf.len;
} }
#if !defined(MONGOOSE_NO_WEBSOCKET) || !defined(MONGOOSE_NO_AUTH) #if !defined(MONGOOSE_NO_WEBSOCKET) || !defined(MONGOOSE_NO_AUTH)
...@@ -2660,15 +2663,14 @@ static int deliver_websocket_frame(struct connection *conn) { ...@@ -2660,15 +2663,14 @@ static int deliver_websocket_frame(struct connection *conn) {
return buffered; return buffered;
} }
int mg_websocket_write(struct mg_connection* conn, int opcode, size_t mg_websocket_write(struct mg_connection* conn, int opcode,
const char *data, size_t data_len) { const char *data, size_t data_len) {
unsigned char mem[4192], *copy = mem; unsigned char mem[4192], *copy = mem;
size_t copy_len = 0; size_t copy_len = 0;
int retval = -1;
if (data_len + 10 > sizeof(mem) && if (data_len + 10 > sizeof(mem) &&
(copy = (unsigned char *) malloc(data_len + 10)) == NULL) { (copy = (unsigned char *) malloc(data_len + 10)) == NULL) {
return -1; return 0;
} }
copy[0] = 0x80 + (opcode & 0x0f); copy[0] = 0x80 + (opcode & 0x0f);
...@@ -2696,17 +2698,17 @@ int mg_websocket_write(struct mg_connection* conn, int opcode, ...@@ -2696,17 +2698,17 @@ int mg_websocket_write(struct mg_connection* conn, int opcode,
} }
if (copy_len > 0) { if (copy_len > 0) {
retval = mg_write(conn, copy, copy_len); mg_write(conn, copy, copy_len);
} }
if (copy != mem) { if (copy != mem) {
free(copy); free(copy);
} }
return retval; return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len;
} }
int mg_websocket_printf(struct mg_connection* conn, int opcode, size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
const char *fmt, ...) { const char *fmt, ...) {
char mem[4192], *buf = mem; char mem[4192], *buf = mem;
va_list ap; va_list ap;
int len; int len;
...@@ -2721,7 +2723,7 @@ int mg_websocket_printf(struct mg_connection* conn, int opcode, ...@@ -2721,7 +2723,7 @@ int mg_websocket_printf(struct mg_connection* conn, int opcode,
free(buf); free(buf);
} }
return len; return MG_CONN_2_CONN(conn)->ns_conn->send_iobuf.len;
} }
static void send_websocket_handshake_if_requested(struct mg_connection *conn) { static void send_websocket_handshake_if_requested(struct mg_connection *conn) {
...@@ -4121,8 +4123,9 @@ static void proxify_connection(struct connection *conn) { ...@@ -4121,8 +4123,9 @@ static void proxify_connection(struct connection *conn) {
} }
} }
static void open_local_endpoint(struct connection *conn, int skip_user) {
#ifndef MONGOOSE_NO_FILESYSTEM #ifndef MONGOOSE_NO_FILESYSTEM
void mg_send_file(struct mg_connection *c, const char *file_name) {
struct connection *conn = MG_CONN_2_CONN(c);
file_stat_t st; file_stat_t st;
char path[MAX_PATH_SIZE]; char path[MAX_PATH_SIZE];
int exists = 0, is_directory = 0; int exists = 0, is_directory = 0;
...@@ -4136,7 +4139,57 @@ static void open_local_endpoint(struct connection *conn, int skip_user) { ...@@ -4136,7 +4139,57 @@ static void open_local_endpoint(struct connection *conn, int skip_user) {
#else #else
const char *dir_lst = "yes"; const char *dir_lst = "yes";
#endif #endif
mg_snprintf(path, sizeof(path), "%s", file_name);
exists = stat(path, &st) == 0;
is_directory = S_ISDIR(st.st_mode);
if (!exists || must_hide_file(conn, path)) {
send_http_error(conn, 404, NULL);
} else if (is_directory &&
conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') {
conn->mg_conn.status_code = 301;
mg_printf(&conn->mg_conn, "HTTP/1.1 301 Moved Permanently\r\n"
"Location: %s/\r\n\r\n", conn->mg_conn.uri);
close_local_endpoint(conn);
} else if (is_directory && !find_index_file(conn, path, sizeof(path), &st)) {
if (!mg_strcasecmp(dir_lst, "yes")) {
#ifndef MONGOOSE_NO_DIRECTORY_LISTING
send_directory_listing(conn, path);
#else
send_http_error(conn, 501, NULL);
#endif
} else {
send_http_error(conn, 403, NULL);
}
} else if (mg_match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) {
#if !defined(MONGOOSE_NO_CGI)
open_cgi_endpoint(conn, path);
#else
send_http_error(conn, 501, NULL);
#endif // !MONGOOSE_NO_CGI
#ifndef MONGOOSE_NO_SSI
} else if (mg_match_prefix(conn->server->config_options[SSI_PATTERN],
strlen(conn->server->config_options[SSI_PATTERN]),
path) > 0) {
handle_ssi_request(conn, path);
#endif #endif
} else if (is_not_modified(conn, &st)) {
send_http_error(conn, 304, NULL);
} else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) {
// O_BINARY is required for Windows, otherwise in default text mode
// two bytes \r\n will be read as one.
open_file_endpoint(conn, path, &st);
} else {
send_http_error(conn, 404, NULL);
}
}
#endif // !MONGOOSE_NO_FILESYSTEM
static void open_local_endpoint(struct connection *conn, int skip_user) {
char path[MAX_PATH_SIZE];
file_stat_t st;
int exists = 0;
// If EP_USER was set in a prev call, reset it // If EP_USER was set in a prev call, reset it
conn->endpoint_type = EP_NONE; conn->endpoint_type = EP_NONE;
...@@ -4170,16 +4223,16 @@ static void open_local_endpoint(struct connection *conn, int skip_user) { ...@@ -4170,16 +4223,16 @@ static void open_local_endpoint(struct connection *conn, int skip_user) {
proxify_connection(conn); proxify_connection(conn);
return; return;
} }
#ifdef MONGOOSE_NO_FILESYSTEM
if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) { if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
send_options(conn); send_options(conn);
} else { return;
send_http_error(conn, 404, NULL);
} }
#ifdef MONGOOSE_NO_FILESYSTEM
send_http_error(conn, 404, NULL);
#else #else
exists = convert_uri_to_file_name(conn, path, sizeof(path), &st); exists = convert_uri_to_file_name(conn, path, sizeof(path), &st);
is_directory = S_ISDIR(st.st_mode);
if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) { if (!strcmp(conn->mg_conn.request_method, "OPTIONS")) {
send_options(conn); send_options(conn);
...@@ -4201,44 +4254,8 @@ static void open_local_endpoint(struct connection *conn, int skip_user) { ...@@ -4201,44 +4254,8 @@ static void open_local_endpoint(struct connection *conn, int skip_user) {
} else if (!strcmp(conn->mg_conn.request_method, "PUT")) { } else if (!strcmp(conn->mg_conn.request_method, "PUT")) {
handle_put(conn, path); handle_put(conn, path);
#endif #endif
} else if (!exists || must_hide_file(conn, path)) {
send_http_error(conn, 404, NULL);
} else if (is_directory &&
conn->mg_conn.uri[strlen(conn->mg_conn.uri) - 1] != '/') {
conn->mg_conn.status_code = 301;
mg_printf(&conn->mg_conn, "HTTP/1.1 301 Moved Permanently\r\n"
"Location: %s/\r\n\r\n", conn->mg_conn.uri);
close_local_endpoint(conn);
} else if (is_directory && !find_index_file(conn, path, sizeof(path), &st)) {
if (!mg_strcasecmp(dir_lst, "yes")) {
#ifndef MONGOOSE_NO_DIRECTORY_LISTING
send_directory_listing(conn, path);
#else
send_http_error(conn, 501, NULL);
#endif
} else {
send_http_error(conn, 403, NULL);
}
} else if (mg_match_prefix(cgi_pat, strlen(cgi_pat), path) > 0) {
#if !defined(MONGOOSE_NO_CGI)
open_cgi_endpoint(conn, path);
#else
send_http_error(conn, 501, NULL);
#endif // !MONGOOSE_NO_CGI
#ifndef MONGOOSE_NO_SSI
} else if (mg_match_prefix(conn->server->config_options[SSI_PATTERN],
strlen(conn->server->config_options[SSI_PATTERN]),
path) > 0) {
handle_ssi_request(conn, path);
#endif
} else if (is_not_modified(conn, &st)) {
send_http_error(conn, 304, NULL);
} else if ((conn->endpoint.fd = open(path, O_RDONLY | O_BINARY)) != -1) {
// O_BINARY is required for Windows, otherwise in default text mode
// two bytes \r\n will be read as one.
open_file_endpoint(conn, path, &st);
} else { } else {
send_http_error(conn, 404, NULL); mg_send_file(&conn->mg_conn, path);
} }
#endif // MONGOOSE_NO_FILESYSTEM #endif // MONGOOSE_NO_FILESYSTEM
} }
......
...@@ -99,17 +99,15 @@ struct mg_connection *mg_connect(struct mg_server *, const char *, int, int); ...@@ -99,17 +99,15 @@ struct mg_connection *mg_connect(struct mg_server *, const char *, int, int);
// Connection management functions // Connection management functions
void mg_send_status(struct mg_connection *, int status_code); void mg_send_status(struct mg_connection *, int status_code);
void mg_send_header(struct mg_connection *, const char *name, const char *val); void mg_send_header(struct mg_connection *, const char *name, const char *val);
void mg_send_data(struct mg_connection *, const void *data, int data_len); size_t mg_send_data(struct mg_connection *, const void *data, int data_len);
void mg_printf_data(struct mg_connection *, const char *format, ...); size_t mg_printf_data(struct mg_connection *, const char *format, ...);
size_t mg_write(struct mg_connection *, const void *buf, int len);
size_t mg_printf(struct mg_connection *conn, const char *fmt, ...);
int mg_websocket_write(struct mg_connection *, int opcode, size_t mg_websocket_write(struct mg_connection *, int opcode,
const char *data, size_t data_len); const char *data, size_t data_len);
int mg_websocket_printf(struct mg_connection* conn, int opcode, size_t mg_websocket_printf(struct mg_connection* conn, int opcode,
const char *fmt, ...); const char *fmt, ...);
// Deprecated in favor of mg_send_* interface
int mg_write(struct mg_connection *, const void *buf, int len);
int mg_printf(struct mg_connection *conn, const char *fmt, ...);
const char *mg_get_header(const struct mg_connection *, const char *name); const char *mg_get_header(const struct mg_connection *, const char *name);
const char *mg_get_mime_type(const char *name, const char *default_mime_type); const char *mg_get_mime_type(const char *name, const char *default_mime_type);
...@@ -122,6 +120,7 @@ int mg_parse_multipart(const char *buf, int buf_len, ...@@ -122,6 +120,7 @@ int mg_parse_multipart(const char *buf, int buf_len,
const char **data, int *data_len); const char **data, int *data_len);
// Utility functions // Utility functions
void mg_send_file(struct mg_connection *, const char *path);
void *mg_start_thread(void *(*func)(void *), void *param); void *mg_start_thread(void *(*func)(void *), void *param);
char *mg_md5(char buf[33], ...); char *mg_md5(char buf[33], ...);
int mg_authorize_digest(struct mg_connection *c, FILE *fp); int mg_authorize_digest(struct mg_connection *c, FILE *fp);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment