MIDAS
Loading...
Searching...
No Matches
mongoose v4 web server library

Classes

struct  mg_request_info
 
struct  mg_request_info::mg_header
 
struct  mg_event
 

Macros

#define MG_REQUEST_BEGIN   1
 
#define MG_REQUEST_END   2
 
#define MG_HTTP_ERROR   3
 
#define MG_EVENT_LOG   4
 
#define MG_THREAD_BEGIN   5
 
#define MG_THREAD_END   6
 
#define PRINTF_FORMAT_STRING(s)   s
 
#define PRINTF_ARGS(x, y)
 

Typedefs

typedef int(* mg_event_handler_t) (struct mg_event *event)
 
typedef void *(* mg_thread_func_t) (void *)
 

Enumerations

enum  {
  WEBSOCKET_OPCODE_CONTINUATION = 0x0 , WEBSOCKET_OPCODE_TEXT = 0x1 , WEBSOCKET_OPCODE_BINARY = 0x2 , WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8 ,
  WEBSOCKET_OPCODE_PING = 0x9 , WEBSOCKET_OPCODE_PONG = 0xa
}
 

Functions

struct mg_contextmg_start (const char **configuration_options, mg_event_handler_t func, void *user_data)
 
void mg_stop (struct mg_context *)
 
void mg_websocket_handshake (struct mg_connection *)
 
int mg_websocket_read (struct mg_connection *, int *bits, char **data)
 
int mg_websocket_write (struct mg_connection *conn, int opcode, const char *data, size_t data_len)
 
const charmg_get_option (const struct mg_context *ctx, const char *name)
 
const char ** mg_get_valid_option_names (void)
 
int mg_modify_passwords_file (const char *passwords_file_name, const char *domain, const char *user, const char *password)
 
int mg_write (struct mg_connection *, const void *buf, int len)
 
int mg_printf (struct mg_connection *, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
 
int void mg_send_file (struct mg_connection *conn, const char *path)
 
int mg_read (struct mg_connection *, void *buf, int len)
 
const charmg_get_header (const struct mg_connection *, const char *name)
 
int mg_get_var (const char *data, size_t data_len, const char *var_name, char *dst, size_t dst_len)
 
int mg_get_cookie (const char *cookie, const char *var_name, char *buf, size_t buf_len)
 
struct mg_connectionmg_download (const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, PRINTF_FORMAT_STRING(const char *request_fmt),...) PRINTF_ARGS(6
 
struct mg_connection void mg_close_connection (struct mg_connection *conn)
 
FILEmg_upload (struct mg_connection *conn, const char *destination_dir, char *path, int path_len)
 
int mg_start_thread (mg_thread_func_t f, void *p)
 
const charmg_get_builtin_mime_type (const char *file_name)
 
const charmg_version (void)
 
int mg_url_decode (const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
 
charmg_md5 (char buf[33],...)
 

Variables

const charmg_request_info::request_method
 
const charmg_request_info::uri
 
const charmg_request_info::http_version
 
const charmg_request_info::query_string
 
const charmg_request_info::remote_user
 
long mg_request_info::remote_ip
 
int mg_request_info::remote_port
 
int mg_request_info::is_ssl
 
int mg_request_info::num_headers
 
const charmg_request_info::mg_header::name
 
const charmg_request_info::mg_header::value
 
struct mg_request_info::mg_header mg_request_info::http_headers [64]
 
int mg_event::type
 
voidmg_event::user_data
 
voidmg_event::conn_data
 
voidmg_event::event_param
 
struct mg_connectionmg_event::conn
 
struct mg_request_infomg_event::request_info
 

Detailed Description


Macro Definition Documentation

◆ MG_EVENT_LOG

#define MG_EVENT_LOG   4

Definition at line 58 of file mongoose4.h.

◆ MG_HTTP_ERROR

#define MG_HTTP_ERROR   3

Definition at line 57 of file mongoose4.h.

◆ MG_REQUEST_BEGIN

#define MG_REQUEST_BEGIN   1

Definition at line 55 of file mongoose4.h.

◆ MG_REQUEST_END

#define MG_REQUEST_END   2

Definition at line 56 of file mongoose4.h.

◆ MG_THREAD_BEGIN

#define MG_THREAD_BEGIN   5

Definition at line 59 of file mongoose4.h.

◆ MG_THREAD_END

#define MG_THREAD_END   6

Definition at line 60 of file mongoose4.h.

◆ PRINTF_ARGS

#define PRINTF_ARGS (   x,
 
)

Definition at line 114 of file mongoose4.h.

◆ PRINTF_FORMAT_STRING

#define PRINTF_FORMAT_STRING (   s)    s

Definition at line 108 of file mongoose4.h.

Typedef Documentation

◆ mg_event_handler_t

typedef int(* mg_event_handler_t) (struct mg_event *event)

Definition at line 70 of file mongoose4.h.

◆ mg_thread_func_t

typedef void *(* mg_thread_func_t) (void *)

Definition at line 218 of file mongoose4.h.

Enumeration Type Documentation

◆ anonymous enum

Enumerator
WEBSOCKET_OPCODE_CONTINUATION 
WEBSOCKET_OPCODE_TEXT 
WEBSOCKET_OPCODE_BINARY 
WEBSOCKET_OPCODE_CONNECTION_CLOSE 
WEBSOCKET_OPCODE_PING 
WEBSOCKET_OPCODE_PONG 

Definition at line 81 of file mongoose4.h.

81 {
88};
@ WEBSOCKET_OPCODE_CONNECTION_CLOSE
Definition mongoose4.h:85
@ WEBSOCKET_OPCODE_PONG
Definition mongoose4.h:87
@ WEBSOCKET_OPCODE_TEXT
Definition mongoose4.h:83
@ WEBSOCKET_OPCODE_CONTINUATION
Definition mongoose4.h:82
@ WEBSOCKET_OPCODE_BINARY
Definition mongoose4.h:84
@ WEBSOCKET_OPCODE_PING
Definition mongoose4.h:86

Function Documentation

◆ mg_close_connection()

struct mg_connection void mg_close_connection ( struct mg_connection conn)

Definition at line 5097 of file mongoose4.cxx.

5097 {
5098#ifndef NO_SSL
5099 if (conn->client_ssl_ctx != NULL) {
5101 }
5102#endif
5103 close_connection(conn);
5104 free(conn);
5105}
void * SSL_CTX
Definition mongoose6.h:1175
static void close_connection(struct mg_connection *conn)
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
SSL_CTX * client_ssl_ctx
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mg_download()

struct mg_connection * mg_download ( const char host,
int  port,
int  use_ssl,
char error_buffer,
size_t  error_buffer_size,
PRINTF_FORMAT_STRING(const char *request_fmt ,
  ... 
)

◆ mg_get_builtin_mime_type()

const char * mg_get_builtin_mime_type ( const char file_name)

Definition at line 2895 of file mongoose4.cxx.

2895 {
2896 const char *ext;
2897 size_t i, path_len;
2898
2899 path_len = strlen(path);
2900
2901 for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
2902 ext = path + (path_len - builtin_mime_types[i].ext_len);
2905 return builtin_mime_types[i].mime_type;
2906 }
2907 }
2908
2909 return "text/plain";
2910}
INT i
Definition mdump.cxx:32
static int mg_strcasecmp(const char *s1, const char *s2)
size_t ext_len
const char * extension
static const struct @22 builtin_mime_types[]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mg_get_cookie()

int mg_get_cookie ( const char cookie,
const char var_name,
char buf,
size_t  buf_len 
)

Definition at line 2678 of file mongoose4.cxx.

2679 {
2680 const char *s, *p, *end;
2681 int name_len, len = -1;
2682
2683 if (dst == NULL || dst_size == 0) {
2684 len = -2;
2685 } else if (var_name == NULL || (s = cookie_header) == NULL) {
2686 len = -1;
2687 dst[0] = '\0';
2688 } else {
2689 name_len = (int) strlen(var_name);
2690 end = s + strlen(s);
2691 dst[0] = '\0';
2692
2693 for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
2694 if (s[name_len] == '=') {
2695 s += name_len + 1;
2696 if ((p = strchr(s, ' ')) == NULL)
2697 p = end;
2698 if (p[-1] == ';')
2699 p--;
2700 if (*s == '"' && p[-1] == '"' && p > s + 1) {
2701 s++;
2702 p--;
2703 }
2704 if ((size_t) (p - s) < dst_size) {
2705 len = p - s;
2706 mg_strlcpy(dst, s, (size_t) len + 1);
2707 } else {
2708 len = -3;
2709 }
2710 break;
2711 }
2712 }
2713 }
2714 return len;
2715}
#define end
static void mg_strlcpy(register char *dst, register const char *src, size_t n)
static const char * mg_strcasestr(const char *big_str, const char *small_str)
char var_name[256]
Definition odbhist.cxx:41
Here is the call graph for this function:

◆ mg_get_header()

const char * mg_get_header ( const struct mg_connection conn,
const char name 
)

Definition at line 693 of file mongoose4.cxx.

693 {
694 return get_header(&conn->request_info, name);
695}
#define name(x)
Definition midas_macro.h:24
static const char * get_header(const struct mg_request_info *ri, const char *name)
struct mg_request_info request_info
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mg_get_option()

const char * mg_get_option ( const struct mg_context ctx,
const char name 
)

Definition at line 870 of file mongoose4.cxx.

870 {
871 int i;
872 if ((i = get_option_index(name)) == -1) {
873 return NULL;
874 } else if (ctx->config[i] == NULL) {
875 return "";
876 } else {
877 return ctx->config[i];
878 }
879}
static int get_option_index(const char *name)
char * config[NUM_OPTIONS]
Here is the call graph for this function:

◆ mg_get_valid_option_names()

const char ** mg_get_valid_option_names ( void  )

Definition at line 855 of file mongoose4.cxx.

855 {
856 return config_options;
857}
static const char * config_options[]

◆ mg_get_var()

int mg_get_var ( const char data,
size_t  data_len,
const char var_name,
char dst,
size_t  dst_len 
)

Definition at line 2631 of file mongoose4.cxx.

2632 {
2633 const char *p, *e, *s;
2634 size_t name_len;
2635 int len;
2636
2637 if (dst == NULL || dst_len == 0) {
2638 len = -2;
2639 } else if (data == NULL || name == NULL || data_len == 0) {
2640 len = -1;
2641 dst[0] = '\0';
2642 } else {
2643 name_len = strlen(name);
2644 e = data + data_len;
2645 len = -1;
2646 dst[0] = '\0';
2647
2648 // data is "var1=val1&var2=val2...". Find variable first
2649 for (p = data; p + name_len < e; p++) {
2650 if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
2651 !mg_strncasecmp(name, p, name_len)) {
2652
2653 // Point p to variable value
2654 p += name_len + 1;
2655
2656 // Point s to the end of the value
2657 s = (const char *) memchr(p, '&', (size_t)(e - p));
2658 if (s == NULL) {
2659 s = e;
2660 }
2661 assert(s >= p);
2662
2663 // Decode variable into destination buffer
2664 len = mg_url_decode(p, (size_t)(s - p), dst, dst_len, 1);
2665
2666 // Redirect error code from -1 to -2 (destination buffer too small).
2667 if (len == -1) {
2668 len = -2;
2669 }
2670 break;
2671 }
2672 }
2673 }
2674
2675 return len;
2676}
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
void * data
Definition mana.cxx:268
static int mg_strncasecmp(const char *s1, const char *s2, size_t len)
static double e(void)
Definition tinyexpr.c:136
Here is the call graph for this function:

◆ mg_md5()

char * mg_md5 ( char  buf[33],
  ... 
)

Definition at line 1090 of file mongoose4.cxx.

1090 {
1091 unsigned char hash[16];
1092 const char *p;
1093 va_list ap;
1094 MD5_CTX ctx;
1095
1096 MD5Init(&ctx);
1097
1098 va_start(ap, buf);
1099 while ((p = va_arg(ap, const char *)) != NULL) {
1100 MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p));
1101 }
1102 va_end(ap);
1103
1104 MD5Final(hash, &ctx);
1105 bin2str(buf, hash, sizeof(hash));
1106 return buf;
1107}
static void MD5Final(unsigned char digest[16], MD5_CTX *ctx)
static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len)
static void bin2str(char *to, const unsigned char *p, size_t len)
static void MD5Init(MD5_CTX *ctx)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mg_modify_passwords_file()

int mg_modify_passwords_file ( const char passwords_file_name,
const char domain,
const char user,
const char password 
)

Definition at line 1314 of file mongoose4.cxx.

1315 {
1316 int found;
1317 char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX];
1318 FILE *fp, *fp2;
1319
1320 found = 0;
1321 fp = fp2 = NULL;
1322
1323 // Regard empty password as no password - remove user record.
1324 if (pass != NULL && pass[0] == '\0') {
1325 pass = NULL;
1326 }
1327
1328 (void) snprintf(tmp, sizeof(tmp), "%s.tmp", fname);
1329
1330 // Create the file if does not exist
1331 if ((fp = fopen(fname, "a+")) != NULL) {
1332 fclose(fp);
1333 }
1334
1335 // Open the given file and temporary file
1336 if ((fp = fopen(fname, "r")) == NULL) {
1337 return 0;
1338 } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
1339 fclose(fp);
1340 return 0;
1341 }
1342
1343 // Copy the stuff to temporary file
1344 while (fgets(line, sizeof(line), fp) != NULL) {
1345 if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) {
1346 continue;
1347 }
1348
1349 if (!strcmp(u, user) && !strcmp(d, domain)) {
1350 found++;
1351 if (pass != NULL) {
1352 mg_md5(ha1, user, ":", domain, ":", pass, NULL);
1353 fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
1354 }
1355 } else {
1356 fprintf(fp2, "%s", line);
1357 }
1358 }
1359
1360 // If new user, just add it
1361 if (!found && pass != NULL) {
1362 mg_md5(ha1, user, ":", domain, ":", pass, NULL);
1363 fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
1364 }
1365
1366 // Close files
1367 fclose(fp);
1368 fclose(fp2);
1369
1370 // Put the temp file in place of real file
1371 remove(fname);
1372 rename(tmp, fname);
1373
1374 return 1;
1375}
char * mg_md5(char buf[33],...)
static std::string remove(const std::string s, char c)
Definition mjsonrpc.cxx:253
static FILE * fp
#define PATH_MAX
double d
Definition system.cxx:1311
Here is the call graph for this function:

◆ mg_printf()

int mg_printf ( struct mg_connection ,
PRINTF_FORMAT_STRING(const char *fmt)  ,
  ... 
)
Here is the caller graph for this function:

◆ mg_read()

int mg_read ( struct mg_connection conn,
void buf,
int  len 
)

Definition at line 2529 of file mongoose4.cxx.

2529 {
2530 int n, buffered_len, nread = 0;
2531 int64_t left;
2532
2533 if (conn->content_len <= 0) {
2534 return 0;
2535 }
2536
2537 // conn->buf body
2538 // |=================|==========|===============|
2539 // |<--request_len-->| |
2540 // |<-----------data_len------->| conn->buf + conn->buf_size
2541
2542 // First, check for data buffered in conn->buf by read_request().
2543 if (len > 0 && (buffered_len = conn->data_len - conn->request_len) > 0) {
2544 char *body = conn->buf + conn->request_len;
2545 if (buffered_len > len) buffered_len = len;
2546 if (buffered_len > conn->content_len) buffered_len = (int)conn->content_len;
2547
2548 memcpy(buf, body, (size_t) buffered_len);
2549 memmove(body, body + buffered_len,
2550 &conn->buf[conn->data_len] - &body[buffered_len]);
2551 len -= buffered_len;
2552 conn->data_len -= buffered_len;
2554 }
2555
2556 // Read data from the socket.
2557 if (len > 0 && (left = left_to_read(conn)) > 0) {
2558 if (left < len) {
2559 len = (int) left;
2560 }
2561 n = pull_all(NULL, conn, (char *) buf + nread, (int) len);
2562 nread = n >= 0 ? nread + n : n;
2563 }
2564
2565 return nread;
2566}
DWORD n[4]
Definition mana.cxx:247
static int64_t left_to_read(const struct mg_connection *conn)
static int pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
static int left(const struct frozen *f)
int64_t content_len
Here is the call graph for this function:

◆ mg_send_file()

int void mg_send_file ( struct mg_connection conn,
const char path 
)

Definition at line 3332 of file mongoose4.cxx.

3332 {
3334 if (mg_stat(path, &file)) {
3335 handle_file_request(conn, path, &file);
3336 } else {
3337 send_http_error(conn, 404, "Not Found", "%s", "File not found");
3338 }
3339}
static void send_http_error(struct mg_connection *, int, const char *, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(4
static void handle_file_request(struct mg_connection *conn, const char *path, struct file *filep)
static int mg_stat(const char *path, struct file *filep)
#define STRUCT_FILE_INITIALIZER
Here is the call graph for this function:

◆ mg_start()

struct mg_context * mg_start ( const char **  configuration_options,
mg_event_handler_t  func,
void user_data 
)

Definition at line 5466 of file mongoose4.cxx.

5468 {
5469 struct mg_context *ctx;
5470 const char *name, *value, *default_value;
5471 int i;
5472
5473#if defined(_WIN32) && !defined(__SYMBIAN32__)
5474 WSADATA data;
5475 WSAStartup(MAKEWORD(2,2), &data);
5476#endif // _WIN32
5477
5478 // Allocate context and initialize reasonable general case defaults.
5479 // TODO(lsm): do proper error handling here.
5480 if ((ctx = (struct mg_context *) calloc(1, sizeof(*ctx))) == NULL) {
5481 return NULL;
5482 }
5483 ctx->event_handler = func;
5484 ctx->user_data = user_data;
5485
5486 while (options && (name = *options++) != NULL) {
5487 if ((i = get_option_index(name)) == -1) {
5488 cry(fc(ctx), "Invalid option: %s", name);
5489 free_context(ctx);
5490 return NULL;
5491 } else if ((value = *options++) == NULL) {
5492 cry(fc(ctx), "%s: option value cannot be NULL", name);
5493 free_context(ctx);
5494 return NULL;
5495 }
5496 if (ctx->config[i] != NULL) {
5497 cry(fc(ctx), "warning: %s: duplicate option", name);
5498 free(ctx->config[i]);
5499 }
5500 ctx->config[i] = mg_strdup(value);
5501 DEBUG_TRACE(("[%s] -> [%s]", name, value));
5502 }
5503
5504 // Set default value if needed
5505 for (i = 0; config_options[i * 2] != NULL; i++) {
5506 default_value = config_options[i * 2 + 1];
5507 if (ctx->config[i] == NULL && default_value != NULL) {
5509 }
5510 }
5511
5512 // NOTE(lsm): order is important here. SSL certificates must
5513 // be initialized before listening ports. UID must be set last.
5514 if (!set_gpass_option(ctx) ||
5515#if !defined(NO_SSL)
5516 !set_ssl_option(ctx) ||
5517#endif
5518 !set_ports_option(ctx) ||
5519#if !defined(_WIN32)
5520 !set_uid_option(ctx) ||
5521#endif
5522 !set_acl_option(ctx)) {
5523 free_context(ctx);
5524 return NULL;
5525 }
5526
5527#if !defined(_WIN32) && !defined(__SYMBIAN32__)
5528 // Ignore SIGPIPE signal, so if browser cancels the request, it
5529 // won't kill the whole process.
5531#endif // !_WIN32
5532
5534 (void) pthread_cond_init(&ctx->cond, NULL);
5537
5538 // Start master (listening) thread
5540
5541 // Start worker threads
5542 for (i = 0; i < atoi(ctx->config[NUM_THREADS]); i++) {
5543 if (mg_start_thread(worker_thread, ctx) != 0) {
5544 cry(fc(ctx), "Cannot start worker thread: %ld", (long) ERRNO);
5545 } else {
5546 ctx->num_threads++;
5547 }
5548 }
5549
5550 return ctx;
5551}
int mg_start_thread(mg_thread_func_t func, void *param)
static int set_ports_option(struct mg_context *ctx)
static int set_uid_option(struct mg_context *ctx)
static int set_gpass_option(struct mg_context *ctx)
#define ERRNO
static char * mg_strdup(const char *str)
#define DEBUG_TRACE(x)
static int set_ssl_option(struct mg_context *ctx)
static void * master_thread(void *thread_func_param)
@ NUM_THREADS
static void free_context(struct mg_context *ctx)
static struct mg_connection * fc(struct mg_context *ctx)
static void * worker_thread(void *thread_func_param)
static void static void cry(struct mg_connection *conn, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
static int set_acl_option(struct mg_context *ctx)
double value[100]
Definition odbhist.cxx:42
pthread_cond_t sq_empty
mg_event_handler_t event_handler
void * user_data
volatile int num_threads
pthread_cond_t sq_full
pthread_mutex_t mutex
pthread_cond_t cond
Here is the call graph for this function:

◆ mg_start_thread()

int mg_start_thread ( mg_thread_func_t  f,
void p 
)

Definition at line 1802 of file mongoose4.cxx.

1802 {
1803 pthread_t thread_id;
1805 int result;
1806
1809
1810#if USE_STACK_SIZE > 1
1811 // Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384
1813#endif
1814
1815 result = pthread_create(&thread_id, &attr, func, param);
1817
1818 return result;
1819}
char param[10][256]
Definition mana.cxx:250
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mg_stop()

void mg_stop ( struct mg_context ctx)

Definition at line 5452 of file mongoose4.cxx.

5452 {
5453 ctx->stop_flag = 1;
5454
5455 // Wait until mg_fini() stops
5456 while (ctx->stop_flag != 2) {
5457 (void) mg_sleep(10);
5458 }
5459 free_context(ctx);
5460
5461#if defined(_WIN32) && !defined(__SYMBIAN32__)
5462 (void) WSACleanup();
5463#endif // _WIN32
5464}
#define mg_sleep(x)
volatile int stop_flag
Here is the call graph for this function:

◆ mg_upload()

FILE * mg_upload ( struct mg_connection conn,
const char destination_dir,
char path,
int  path_len 
)

Definition at line 4543 of file mongoose4.cxx.

4544 {
4545 const char *content_type_header, *boundary_start;
4546 char *buf, fname[1024], boundary[100], *s;
4547 int bl, n, i, j, headers_len, boundary_len, eof, buf_len, to_read, len = 0;
4548 FILE *fp;
4549
4550 // Request looks like this:
4551 //
4552 // POST /upload HTTP/1.1
4553 // Host: 127.0.0.1:8080
4554 // Content-Length: 244894
4555 // Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryRVr
4556 //
4557 // ------WebKitFormBoundaryRVr
4558 // Content-Disposition: form-data; name="file"; filename="accum.png"
4559 // Content-Type: image/png
4560 //
4561 // <89>PNG
4562 // <PNG DATA>
4563 // ------WebKitFormBoundaryRVr
4564
4565 // Extract boundary string from the Content-Type header
4566 if ((content_type_header = mg_get_header(conn, "Content-Type")) == NULL ||
4568 "boundary=")) == NULL ||
4569 (sscanf(boundary_start, "boundary=\"%99[^\"]\"", boundary) == 0 &&
4570 sscanf(boundary_start, "boundary=%99s", boundary) == 0) ||
4571 boundary[0] == '\0') {
4572 return NULL;
4573 }
4574
4575 boundary_len = strlen(boundary);
4576 bl = boundary_len + 4; // \r\n--<boundary>
4577
4578 // buf
4579 // conn->buf |<--------- buf_len ------>|
4580 // |=================|==========|===============|
4581 // |<--request_len-->|<--len--->| |
4582 // |<-----------data_len------->| conn->buf + conn->buf_size
4583
4584 buf = conn->buf + conn->request_len;
4585 buf_len = conn->buf_size - conn->request_len;
4586 len = conn->data_len - conn->request_len;
4587
4588 for (;;) {
4589 // Pull in headers
4590 assert(len >= 0 && len <= buf_len);
4591 to_read = buf_len - len;
4592 if (to_read > left_to_read(conn)) {
4593 to_read = (int) left_to_read(conn);
4594 }
4595 while (len < buf_len &&
4596 (n = pull(NULL, conn, buf + len, to_read)) > 0) {
4597 len += n;
4598 }
4599 if ((headers_len = get_request_len(buf, len)) <= 0) {
4600 break;
4601 }
4602
4603 // Fetch file name.
4604 fname[0] = '\0';
4605 for (i = j = 0; i < headers_len; i++) {
4606 if (buf[i] == '\r' && buf[i + 1] == '\n') {
4607 buf[i] = buf[i + 1] = '\0';
4608 // TODO(lsm): don't expect filename to be the 3rd field,
4609 // parse the header properly instead.
4610 sscanf(&buf[j], "Content-Disposition: %*s %*s filename=\"%1023[^\"]",
4611 fname);
4612 j = i + 2;
4613 }
4614 }
4615
4616 // Give up if the headers are not what we expect
4617 if (fname[0] == '\0') {
4618 break;
4619 }
4620
4621 // Move data to the beginning of the buffer
4622 assert(len >= headers_len);
4623 memmove(buf, &buf[headers_len], len - headers_len);
4624 len -= headers_len;
4625 conn->data_len = conn->request_len + len;
4626
4627 // We open the file with exclusive lock held. This guarantee us
4628 // there is no other thread can save into the same file simultaneously.
4629 fp = NULL;
4630
4631 // Construct destination file name. Do not allow paths to have slashes.
4632 if ((s = strrchr(fname, '/')) == NULL &&
4633 (s = strrchr(fname, '\\')) == NULL) {
4634 s = fname;
4635 }
4636
4637 // Open file in binary mode. TODO: set an exclusive lock.
4638 snprintf(path, path_len, "%s/%s", destination_dir, s);
4639 if ((fp = fopen(path, "wb")) == NULL) {
4640 break;
4641 }
4642
4643 // Read POST data, write into file until boundary is found.
4644 eof = n = 0;
4645 do {
4646 len += n;
4647 for (i = 0; i < len - bl; i++) {
4648 if (!memcmp(&buf[i], "\r\n--", 4) &&
4649 !memcmp(&buf[i + 4], boundary, boundary_len)) {
4650 // Found boundary, that's the end of file data.
4651 fwrite(buf, 1, i, fp);
4652 eof = 1;
4653 memmove(buf, &buf[i + bl], len - (i + bl));
4654 len -= i + bl;
4655 break;
4656 }
4657 }
4658 if (!eof && len > bl) {
4659 fwrite(buf, 1, len - bl, fp);
4660 memmove(buf, &buf[len - bl], bl);
4661 len = bl;
4662 }
4663 to_read = buf_len - len;
4664 if (to_read > left_to_read(conn)) {
4665 to_read = (int) left_to_read(conn);
4666 }
4667 } while (!eof && (n = pull(NULL, conn, buf + len, to_read)) > 0);
4668 conn->data_len = conn->request_len + len;
4669
4670 if (eof) {
4671 rewind(fp);
4672 return fp;
4673 } else {
4674 fclose(fp);
4675 }
4676 }
4677
4678 return NULL;
4679}
const char * mg_get_header(const struct mg_connection *conn, const char *name)
INT bl
Definition mdump.cxx:29
static int get_request_len(const char *buf, int buf_len)
static int pull(FILE *fp, struct mg_connection *conn, char *buf, int len)
INT j
Definition odbhist.cxx:40
Here is the call graph for this function:

◆ mg_url_decode()

int mg_url_decode ( const char src,
int  src_len,
char dst,
int  dst_len,
int  is_form_url_encoded 
)

Definition at line 2606 of file mongoose4.cxx.

2607 {
2608 int i, j, a, b;
2609#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
2610
2611 for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
2612 if (src[i] == '%' && i < src_len - 2 &&
2613 isxdigit(* (const unsigned char *) (src + i + 1)) &&
2614 isxdigit(* (const unsigned char *) (src + i + 2))) {
2615 a = tolower(* (const unsigned char *) (src + i + 1));
2616 b = tolower(* (const unsigned char *) (src + i + 2));
2617 dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b));
2618 i += 2;
2619 } else if (is_form_url_encoded && src[i] == '+') {
2620 dst[j] = ' ';
2621 } else {
2622 dst[j] = src[i];
2623 }
2624 }
2625
2626 dst[j] = '\0'; // Null-terminate the destination
2627
2628 return i >= src_len ? j : -1;
2629}
#define HEXTOI(x)
Here is the call graph for this function:

◆ mg_version()

const char * mg_version ( void  )

Definition at line 2396 of file mongoose4.cxx.

2396 {
2397 return MONGOOSE_VERSION;
2398}
#define MONGOOSE_VERSION
Here is the caller graph for this function:

◆ mg_websocket_handshake()

void mg_websocket_handshake ( struct mg_connection )

◆ mg_websocket_read()

int mg_websocket_read ( struct mg_connection ,
int bits,
char **  data 
)

◆ mg_websocket_write()

int mg_websocket_write ( struct mg_connection conn,
int  opcode,
const char data,
size_t  data_len 
)

◆ mg_write()

int mg_write ( struct mg_connection conn,
const void buf,
int  len 
)

Definition at line 2568 of file mongoose4.cxx.

2568 {
2569 time_t now;
2571
2572 if (conn->throttle > 0) {
2573 if ((now = time(NULL)) != conn->last_throttle_time) {
2574 conn->last_throttle_time = now;
2575 conn->last_throttle_bytes = 0;
2576 }
2577 allowed = conn->throttle - conn->last_throttle_bytes;
2578 if (allowed > (int64_t) len) {
2579 allowed = len;
2580 }
2581 if ((total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
2582 (int64_t) allowed)) == allowed) {
2583 buf = (char *) buf + total;
2584 conn->last_throttle_bytes += total;
2585 while (total < (int64_t) len && conn->ctx->stop_flag == 0) {
2586 allowed = conn->throttle > (int64_t) len - total ?
2587 (int64_t) len - total : conn->throttle;
2588 if ((n = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
2589 (int64_t) allowed)) != allowed) {
2590 break;
2591 }
2592 sleep(1);
2594 conn->last_throttle_time = time(NULL);
2595 buf = (char *) buf + n;
2596 total += n;
2597 }
2598 }
2599 } else {
2600 total = push(NULL, conn->client.sock, conn->ssl, (const char *) buf,
2601 (int64_t) len);
2602 }
2603 return (int) total;
2604}
#define sleep(ms)
static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int64_t len)
double total[100]
Definition odbhist.cxx:42
time_t last_throttle_time
struct socket client
int64_t last_throttle_bytes
struct mg_context * ctx
SOCKET sock
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ conn

struct mg_connection* mg_event::conn

Definition at line 66 of file mongoose4.h.

◆ conn_data

void* mg_event::conn_data

Definition at line 63 of file mongoose4.h.

◆ event_param

void* mg_event::event_param

Definition at line 64 of file mongoose4.h.

◆ http_headers

struct mg_request_info::mg_header mg_request_info::http_headers[64]

◆ http_version

const char* mg_request_info::http_version

Definition at line 39 of file mongoose4.h.

◆ is_ssl

int mg_request_info::is_ssl

Definition at line 44 of file mongoose4.h.

◆ name

const char* mg_request_info::mg_header::name

Definition at line 48 of file mongoose4.h.

◆ num_headers

int mg_request_info::num_headers

Definition at line 46 of file mongoose4.h.

◆ query_string

const char* mg_request_info::query_string

Definition at line 40 of file mongoose4.h.

◆ remote_ip

long mg_request_info::remote_ip

Definition at line 42 of file mongoose4.h.

◆ remote_port

int mg_request_info::remote_port

Definition at line 43 of file mongoose4.h.

◆ remote_user

const char* mg_request_info::remote_user

Definition at line 41 of file mongoose4.h.

◆ request_info

struct mg_request_info* mg_event::request_info

Definition at line 67 of file mongoose4.h.

◆ request_method

const char* mg_request_info::request_method

Definition at line 37 of file mongoose4.h.

◆ type

int mg_event::type

Definition at line 54 of file mongoose4.h.

◆ uri

const char* mg_request_info::uri

Definition at line 38 of file mongoose4.h.

◆ user_data

void* mg_event::user_data

Definition at line 62 of file mongoose4.h.

◆ value

const char* mg_request_info::mg_header::value

Definition at line 49 of file mongoose4.h.