18 #ifdef NOEMBED_NET_SKELETON 38 #ifndef NS_SKELETON_HEADER_INCLUDED 39 #define NS_SKELETON_HEADER_INCLUDED 41 #define NS_SKELETON_VERSION "2.1.0" 43 #undef UNICODE // Use ANSI WinAPI functions 44 #undef _UNICODE // Use multibyte encoding on Windows 45 #define _MBCS // Use multibyte encoding on Windows 46 #define _INTEGRAL_MAX_BITS 64 // Enable _stati64() on Windows 47 #ifndef _CRT_SECURE_NO_WARNINGS 48 #define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005+ 50 #undef WIN32_LEAN_AND_MEAN // Let windows.h always include winsock2.h 52 #define _XOPEN_SOURCE 600 // For flockfile() on Linux 54 #define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++ 55 #define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX 56 #ifndef _LARGEFILE_SOURCE 57 #define _LARGEFILE_SOURCE // Enable fseeko() and ftello() functions 59 #define _FILE_OFFSET_BITS 64 // Enable 64-bit file offsets 62 #pragma warning (disable : 4127) // FD_SET() emits warning, disable it 63 #pragma warning (disable : 4204) // missing c99 support 66 #if defined(_WIN32) && !defined(MONGOOSE_NO_CGI) 67 #define MONGOOSE_ENABLE_THREADS 70 #ifndef MONGOOSE_ENABLE_THREADS 71 #define NS_DISABLE_THREADS 75 #define _MMAP_DECLARED // Prevent dummy mmap() declaration in stdio.h 78 #include <sys/types.h> 94 #pragma comment(lib, "ws2_32.lib") // Linking with winsock library 103 #define EINPROGRESS WSAEINPROGRESS 106 #define EWOULDBLOCK WSAEWOULDBLOCK 110 #define STR(x) STRX(x) 111 #define __func__ __FILE__ ":" STR(__LINE__) 114 #define va_copy(x,y) x = y 115 #endif // MINGW #defines va_copy 116 #define snprintf _snprintf 117 #define vsnprintf _vsnprintf 118 #define sleep(x) Sleep((x) * 1000) 119 #define to64(x) _atoi64(x) 120 typedef int socklen_t;
121 typedef unsigned char uint8_t;
122 typedef unsigned int uint32_t;
123 typedef unsigned short uint16_t;
124 typedef unsigned __int64 uint64_t;
125 typedef __int64 int64_t;
129 #define S_ISDIR(x) ((x) & _S_IFDIR) 138 #include <arpa/inet.h> 139 #include <netinet/in.h> 140 #include <sys/socket.h> 141 #include <sys/select.h> 142 #define closesocket(x) close(x) 146 #include <sys/time.h> 147 typedef int socklen_t;
149 #define INVALID_SOCKET (-1) 150 #define to64(x) strtoll(x, NULL, 10) 155 #ifdef NS_ENABLE_DEBUG 156 #define DBG(x) do { printf("%-20s ", __func__); printf x; putchar('\n'); \ 157 fflush(stdout); } while(0) 163 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) 168 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 170 #include <openssl/ssl.h> 178 #endif // __cplusplus 182 struct sockaddr_in sin;
183 #ifdef NS_ENABLE_IPV6 184 struct sockaddr_in6 sin6;
186 struct sockaddr sin6;
215 #define NS_POLL 0 // Sent to each connection on each call to ns_mgr_poll() 216 #define NS_ACCEPT 1 // New connection accept()-ed. union socket_address *addr 217 #define NS_CONNECT 2 // connect() succeeded or failed. int *success_status 218 #define NS_RECV 3 // Data has benn received. int *num_bytes 219 #define NS_SEND 4 // Data has been written to a socket. int *num_bytes 220 #define NS_CLOSE 5 // Connection is closed. NULL 225 const char *hexdump_file;
238 struct iobuf recv_iobuf;
239 struct iobuf send_iobuf;
248 #define NSF_FINISHED_SENDING_DATA (1 << 0) 249 #define NSF_BUFFER_BUT_DONT_SEND (1 << 1) 250 #define NSF_SSL_HANDSHAKE_DONE (1 << 2) 251 #define NSF_CONNECTING (1 << 3) 252 #define NSF_CLOSE_IMMEDIATELY (1 << 4) 253 #define NSF_WANT_READ (1 << 5) 254 #define NSF_WANT_WRITE (1 << 6) 255 #define NSF_LISTENING (1 << 7) 256 #define NSF_UDP (1 << 8) 258 #define NSF_USER_1 (1 << 20) 259 #define NSF_USER_2 (1 << 21) 260 #define NSF_USER_3 (1 << 22) 261 #define NSF_USER_4 (1 << 23) 262 #define NSF_USER_5 (1 << 24) 263 #define NSF_USER_6 (1 << 25) 291 int ns_resolve(
const char *domain_name,
char *ip_addr_buf,
size_t buf_len);
295 #endif // __cplusplus 297 #endif // NS_SKELETON_HEADER_INCLUDED 318 #define NS_MALLOC malloc 322 #define NS_REALLOC realloc 330 #define NS_CALLOC calloc 333 #define NS_CTL_MSG_MESSAGE_SIZE (8 * 1024) 334 #define NS_READ_BUFFER_SIZE 2048 335 #define NS_UDP_RECEIVE_BUFFER_SIZE 2000 336 #define NS_VPRINTF_BUFFER_SIZE 500 345 if ((new_size > io->
size || (new_size < io->
size && new_size >= io->
len)) &&
372 if (len > ~(
size_t)0 - (
size_t)(io->
buf + io->
len)) {
377 }
else if (io->
len + len <= io->
size) {
393 if (n > 0 && n <= io->
len) {
394 memmove(io->
buf, io->
buf + n, io->
len - n);
403 DBG((
"%p %d send %ld (%d %s)", nc, nc->
sock, n, errno, strerror(errno)));
404 return n < 0 ? 0 : n;
410 #ifndef NS_DISABLE_THREADS 413 return (
void *) _beginthread((
void (
__cdecl *)(
void *))
f, 0, p);
418 (void) pthread_attr_init(&attr);
419 (void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
421 #if defined(NS_STACK_SIZE) && NS_STACK_SIZE > 1 422 (void) pthread_attr_setstacksize(&attr, NS_STACK_SIZE);
425 pthread_create(&thread_id, &attr,
f, p);
426 pthread_attr_destroy(&attr);
431 #endif // NS_DISABLE_THREADS 453 va_copy(ap_copy, ap);
454 len =
vsnprintf(*buf, size, fmt, ap_copy);
465 if ((*buf = (
char *)
NS_MALLOC(size)) == NULL)
break;
466 va_copy(ap_copy, ap);
467 len =
vsnprintf(*buf, size, fmt, ap_copy);
470 }
else if (len > (
int) size) {
472 if ((*buf = (
char *)
NS_MALLOC(len + 1)) == NULL) {
475 va_copy(ap_copy, ap);
476 len =
vsnprintf(*buf, len + 1, fmt, ap_copy);
488 if ((len =
ns_avprintf(&buf,
sizeof(mem), fmt, ap)) > 0) {
491 if (buf != mem && buf != NULL) {
508 int num_bytes,
int ev) {
511 char *
buf, src[60], dst[60];
512 int buf_size = num_bytes * 5 + 100;
514 if ((fp = fopen(path,
"a")) != NULL) {
517 fprintf(fp,
"%lu %p %s %s %s %d\n", (
unsigned long) time(NULL),
522 if (num_bytes > 0 && (buf = (
char *)
NS_MALLOC(buf_size)) != NULL) {
524 (ev ==
NS_SEND ? 0 : num_bytes), num_bytes, buf, buf_size);
546 if (conn->
ssl != NULL) {
565 (void) SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
567 fcntl(sock, F_SETFD, FD_CLOEXEC);
573 unsigned long on = 1;
574 ioctlsocket(sock, FIONBIO, &on);
576 int flags = fcntl(sock, F_GETFL, 0);
577 fcntl(sock, F_SETFL, flags | O_NONBLOCK);
581 #ifndef NS_DISABLE_SOCKETPAIR 585 socklen_t
len =
sizeof(sa.
sin);
590 (void) memset(&sa, 0,
sizeof(sa));
591 sa.
sin.sin_family = AF_INET;
592 sa.
sin.sin_port = htons(0);
593 sa.
sin.sin_addr.s_addr = htonl(0x7f000001);
596 !
bind(sock, &sa.
sa, len) &&
597 (sock_type == SOCK_DGRAM || !listen(sock, 1)) &&
598 !getsockname(sock, &sa.
sa, &len) &&
601 (sock_type == SOCK_STREAM ||
602 (!getsockname(sp[0], &sa.
sa, &len) && !
connect(sock, &sa.
sa, len))) &&
603 (sp[1] = (sock_type == SOCK_DGRAM ? sock :
621 #endif // NS_DISABLE_SOCKETPAIR 625 #ifdef NS_ENABLE_GETADDRINFO 627 struct addrinfo hints, *servinfo, *
p;
628 struct sockaddr_in *h = NULL;
630 memset(&hints, 0,
sizeof hints);
631 hints.ai_family = AF_INET;
632 hints.ai_socktype = SOCK_STREAM;
634 if((rv =
getaddrinfo(host, NULL , NULL, &servinfo)) != 0) {
635 DBG((
"getaddrinfo(%s) failed: %s", host, strerror(errno)));
639 for(p = servinfo; p != NULL; p = p->ai_next) {
640 memcpy(&h, &p->ai_addr,
sizeof(
struct sockaddr_in *));
641 memcpy(ina, &h->sin_addr,
sizeof(ina));
644 freeaddrinfo(servinfo);
648 if ((he = gethostbyname(host)) == NULL) {
649 DBG((
"gethostbyname(%s) failed: %s", host, strerror(errno)));
651 memcpy(ina, he->h_addr_list[0],
sizeof(*ina));
667 int *proto,
int *use_ssl,
char *cert,
char *ca) {
668 unsigned int a, b, c,
d,
port;
671 #ifdef NS_ENABLE_IPV6 678 memset(sa, 0,
sizeof(*sa));
679 sa->
sin.sin_family = AF_INET;
681 *proto = SOCK_STREAM;
683 cert[0] = ca[0] =
'\0';
685 if (memcmp(str,
"ssl://", 6) == 0) {
688 }
else if (memcmp(str,
"udp://", 6) == 0) {
691 }
else if (memcmp(str,
"tcp://", 6) == 0) {
695 if (sscanf(str,
"%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &
len) == 5) {
697 sa->
sin.sin_addr.s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
698 sa->
sin.sin_port = htons((uint16_t) port);
699 #ifdef NS_ENABLE_IPV6 700 }
else if (sscanf(str,
"[%99[^]]]:%u%n", buf, &port, &
len) == 2 &&
701 inet_pton(AF_INET6, buf, &sa->
sin6.sin6_addr)) {
703 sa->
sin6.sin6_family = AF_INET6;
704 sa->
sin6.sin6_port = htons((uint16_t) port);
706 }
else if (sscanf(str,
"%199[^ :]:%u%n", host, &port, &
len) == 2) {
707 sa->
sin.sin_port = htons((uint16_t) port);
709 }
else if (sscanf(str,
"%u%n", &port, &
len) == 1) {
711 sa->
sin.sin_port = htons((uint16_t) port);
714 if (*use_ssl && (sscanf(str +
len,
":%99[^:,]:%99[^:,]%n", cert, ca, &n) == 2 ||
715 sscanf(str +
len,
":%99[^:,]%n", cert, &n) == 1)) {
719 return port < 0xffff && str[
len] ==
'\0' ?
len : 0;
724 socklen_t sa_len = (sa->
sa.sa_family == AF_INET) ?
725 sizeof(sa->
sin) :
sizeof(sa->
sin6);
739 !setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
void *) &on,
sizeof(on)) &&
741 !
bind(sock, &sa->
sa, sa_len) &&
742 (proto == SOCK_DGRAM || listen(sock, SOMAXCONN) == 0)) {
745 (void) getsockname(sock, &sa->
sa, &sa_len);
758 static int ns_use_ca_cert(
SSL_CTX *ctx,
const char *cert) {
761 }
else if (cert == NULL || cert[0] ==
'\0') {
768 static int ns_use_cert(
SSL_CTX *ctx,
const char *pem_file) {
771 }
else if (pem_file == NULL || pem_file[0] ==
'\0') {
777 SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
778 SSL_CTX_use_certificate_chain_file(ctx, pem_file);
782 #endif // NS_ENABLE_SSL 789 char cert[100], ca_cert[100];
793 if (use_ssl && cert[0] ==
'\0')
return NULL;
796 }
else if ((nc =
ns_add_sock(srv, sock, callback, NULL)) == NULL) {
804 if (proto == SOCK_DGRAM) {
811 if (ns_use_cert(nc->
ssl_ctx, cert) != 0 ||
812 ns_use_ca_cert(nc->
ssl_ctx, ca_cert) != 0) {
819 DBG((
"%p sock %d/%d ssl %p %p", nc, sock, proto, nc->
ssl_ctx, nc->
ssl));
828 socklen_t
len =
sizeof(
sa);
837 }
else if (ls->
ssl_ctx != NULL &&
856 (n < 0 && errno != EINTR && errno != EINPROGRESS &&
857 errno !=
EAGAIN && errno != EWOULDBLOCK
859 && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK
866 socklen_t slen =
sizeof(
sa);
868 if (buf != NULL && len > 0) {
870 memset(&sa, 0,
sizeof(sa));
872 getpeername(sock, &sa.
sa, &slen);
874 getsockname(sock, &sa.
sa, &slen);
877 #if defined(NS_ENABLE_IPV6) 878 inet_ntop(sa.
sa.sa_family, sa.
sa.sa_family == AF_INET ?
879 (
void *) &sa.
sin.sin_addr :
880 (
void *) &sa.
sin6.sin6_addr, buf, len);
881 #elif defined(_WIN32) 883 strncpy(buf, inet_ntoa(sa.
sin.sin_addr), len);
885 inet_ntop(sa.
sa.sa_family, (
void *) &sa.
sin.sin_addr, buf,(socklen_t)len);
889 snprintf(buf + strlen(buf), len - (strlen(buf) + 1),
"%s%d",
890 flags & 1 ?
":" :
"", (
int) ntohs(sa.
sin.sin_port));
896 const unsigned char *p = (
const unsigned char *) buf;
900 for (i = 0; i <
len; i++) {
903 if (i > 0) n +=
snprintf(dst + n, dst_len - n,
" %s\n", ascii);
904 n +=
snprintf(dst + n, dst_len - n,
"%04x ", i);
906 n +=
snprintf(dst + n, dst_len - n,
" %02x", p[i]);
907 ascii[idx] = p[
i] < 0x20 || p[
i] > 0x7e ?
'.' : p[
i];
908 ascii[idx + 1] =
'\0';
911 while (i++ % 16) n +=
snprintf(dst + n, dst_len - n,
"%s",
" ");
912 n +=
snprintf(dst + n, dst_len - n,
" %s\n\n", ascii);
932 socklen_t
len =
sizeof(ok);
934 ret = getsockopt(conn->
sock, SOL_SOCKET, SO_ERROR, (
char *) &ok, &len);
937 if (ret == 0 && ok == 0 && conn->
ssl != NULL) {
939 int ssl_err = ns_ssl_err(conn, res);
942 }
else if (ssl_err == SSL_ERROR_WANT_READ ||
943 ssl_err == SSL_ERROR_WANT_WRITE) {
952 DBG((
"%p ok=%d", conn, ok));
961 if (conn->
ssl != NULL) {
966 while ((n =
SSL_read(conn->
ssl, buf,
sizeof(buf))) > 0) {
967 DBG((
"%p %d <- %d bytes (SSL)", conn, conn->
flags, n));
973 int res = SSL_accept(conn->
ssl);
974 int ssl_err = ns_ssl_err(conn, res);
978 }
else if (ssl_err == SSL_ERROR_WANT_READ ||
979 ssl_err == SSL_ERROR_WANT_WRITE) {
989 while ((n = (
int) recv(conn->
sock, buf,
sizeof(buf), 0)) > 0) {
990 DBG((
"%p %d <- %d bytes (PLAIN)", conn, conn->
flags, n));
1005 #ifdef NS_ENABLE_SSL 1006 if (conn->
ssl != NULL) {
1009 int ssl_err = ns_ssl_err(conn, n);
1010 if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
1020 { n = (int) send(conn->
sock, io->
buf, io->
len, 0); }
1022 DBG((
"%p %d -> %d bytes", conn, conn->
flags, n));
1033 return (
int)
ns_out(conn, buf, len);
1040 socklen_t s_len =
sizeof(nc.
sa);
1042 memset(&nc, 0,
sizeof(nc));
1045 DBG((
"%p recvfrom: %s", ls, strerror(errno)));
1057 DBG((
"%p %d bytes received", ls, n));
1074 fd_set read_set, write_set;
1076 time_t current_time = time(NULL);
1079 FD_ZERO(&write_set);
1083 tmp_conn = conn->
next;
1103 tv.
tv_sec = milli / 1000;
1104 tv.
tv_usec = (milli % 1000) * 1000;
1106 if (select((
int) max_fd + 1, &read_set, &write_set, NULL, &tv) > 0) {
1109 current_time = time(NULL);
1113 FD_ISSET(mgr->
ctl[1], &read_set)) {
1115 int len = (int) recv(mgr->
ctl[1], (
char *) &ctl_msg,
sizeof(ctl_msg), 0);
1126 tmp_conn = conn->
next;
1127 if (FD_ISSET(conn->
sock, &read_set)) {
1143 if (FD_ISSET(conn->
sock, &write_set)) {
1155 tmp_conn = conn->
next;
1163 return current_time;
1171 char cert[100], ca_cert[100];
1172 int rc, use_ssl, proto;
1179 rc = (proto == SOCK_DGRAM) ? 0 :
connect(sock, &sa.
sa,
sizeof(sa.
sin));
1184 }
else if ((nc =
ns_add_sock(mgr, sock, callback, user_data)) == NULL) {
1192 #ifdef NS_ENABLE_SSL 1195 ns_use_cert(nc->
ssl_ctx, cert) != 0 ||
1196 ns_use_ca_cert(nc->
ssl_ctx, ca_cert) != 0 ||
1213 memset(conn, 0,
sizeof(*conn));
1222 DBG((
"%p %d", conn, sock));
1234 len <
sizeof(ctl_msg.
message)) {
1237 send(mgr->
ctl[0], (
char *) &ctl_msg,
1238 offsetof(
struct ctl_msg,
message) + len, 0);
1239 recv(mgr->
ctl[0], (
char *) &len, 1, 0);
1244 memset(s, 0,
sizeof(*s));
1249 { WSADATA
data; WSAStartup(MAKEWORD(2, 2), &data); }
1253 signal(SIGPIPE, SIG_IGN);
1256 #ifndef NS_DISABLE_SOCKETPAIR 1262 #ifdef NS_ENABLE_SSL 1263 {
static int init_done;
if (!init_done) {
SSL_library_init(); init_done++; }}
1271 if (s == NULL)
return;
1280 tmp_conn = conn->
next;
1285 #endif // NOEMBED_NET_SKELETON 1290 #include <io.h> // For _lseeki64 1293 #define S_ISDIR(x) ((x) & _S_IFDIR) 1307 #define stat(x, y) mg_stat((x), (y)) 1308 #define fopen(x, y) mg_fopen((x), (y)) 1309 #define open(x, y, z) mg_open((x), (y), (z)) 1310 #define close(x) _close(x) 1311 #define fileno(x) _fileno(x) 1312 #define lseek(x, y, z) _lseeki64((x), (y), (z)) 1313 #define read(x, y, z) _read((x), (y), (z)) 1314 #define write(x, y, z) _write((x), (y), (z)) 1315 #define popen(x, y) _popen((x), (y)) 1316 #define pclose(x) _pclose(x) 1317 #define mkdir(x, y) _mkdir(x) 1318 #define rmdir(x) _rmdir(x) 1319 #define strdup(x) _strdup(x) 1322 #define STR(x) STRX(x) 1323 #define __func__ __FILE__ ":" STR(__LINE__) 1325 #define INT64_FMT "I64d" 1326 #define flockfile(x) ((void) (x)) 1327 #define funlockfile(x) ((void) (x)) 1328 typedef struct _stati64 file_stat_t;
1333 #if !defined(MONGOOSE_NO_FILESYSTEM) &&\ 1334 (!defined(MONGOOSE_NO_DAV) || !defined(MONGOOSE_NO_DIRECTORY_LISTING)) 1337 #if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_DL) 1340 #include <inttypes.h> 1342 #if !defined(O_BINARY) 1345 #define INT64_FMT PRId64 1352 #define MAX_REQUEST_SIZE 16384 1353 #define IOBUF_SIZE 8192 1354 #define MAX_PATH_SIZE 8192 1355 #define DEFAULT_CGI_PATTERN "**.cgi$|**.pl$|**.php$" 1356 #define CGI_ENVIRONMENT_SIZE 8192 1357 #define MAX_CGI_ENVIR_VARS 64 1358 #define ENV_EXPORT_TO_CGI "MONGOOSE_CGI" 1359 #define PASSWORDS_FILE_NAME ".htpasswd" 1361 #ifndef MONGOOSE_USE_WEBSOCKET_PING_INTERVAL 1362 #define MONGOOSE_USE_WEBSOCKET_PING_INTERVAL 5 1366 #if !defined(MONGOOSE_USE_EXTRA_HTTP_HEADERS) 1367 #define MONGOOSE_USE_EXTRA_HTTP_HEADERS "" 1370 #ifndef MONGOOSE_POST_SIZE_LIMIT 1371 #define MONGOOSE_POST_SIZE_LIMIT 0 1374 #ifndef MONGOOSE_IDLE_TIMEOUT_SECONDS 1375 #define MONGOOSE_IDLE_TIMEOUT_SECONDS 300 1378 #if defined(NS_DISABLE_SOCKETPAIR) && !defined(MONGOOSE_NO_CGI) 1379 #define MONGOOSE_NO_CGI 1382 #ifdef MONGOOSE_NO_FILESYSTEM 1383 #define MONGOOSE_NO_AUTH 1384 #if !defined(MONGOOSE_NO_CGI) 1385 #define MONGOOSE_NO_CGI 1387 #define MONGOOSE_NO_DAV 1388 #define MONGOOSE_NO_DIRECTORY_LISTING 1389 #define MONGOOSE_NO_LOGGING 1390 #define MONGOOSE_NO_SSI 1391 #define MONGOOSE_NO_DL 1409 #ifndef MONGOOSE_NO_FILESYSTEM 1411 #ifndef MONGOOSE_NO_AUTH 1414 #ifndef MONGOOSE_NO_CGI 1421 #ifndef MONGOOSE_NO_DIRECTORY_LISTING 1427 #if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_AUTH) 1430 #ifndef MONGOOSE_NO_FILESYSTEM 1439 #ifndef MONGOOSE_NO_SSI 1447 "access_control_list", NULL,
1448 #ifndef MONGOOSE_NO_FILESYSTEM 1449 "access_log_file", NULL,
1450 #ifndef MONGOOSE_NO_AUTH 1451 "auth_domain",
"mydomain.com",
1453 #ifndef MONGOOSE_NO_CGI 1454 "cgi_interpreter", NULL,
1457 "dav_auth_file", NULL,
1459 "document_root", NULL,
1460 #ifndef MONGOOSE_NO_DIRECTORY_LISTING 1461 "enable_directory_listing",
"yes",
1464 "enable_proxy", NULL,
1465 "extra_mime_types", NULL,
1466 #if !defined(MONGOOSE_NO_FILESYSTEM) && !defined(MONGOOSE_NO_AUTH) 1467 "global_auth_file", NULL,
1469 #ifndef MONGOOSE_NO_FILESYSTEM 1470 "hide_files_patterns", NULL,
1471 "hexdump_file", NULL,
1472 "index_files",
"index.html,index.htm,index.shtml,index.cgi,index.php",
1474 "listening_port", NULL,
1476 "run_as_user", NULL,
1478 #ifndef MONGOOSE_NO_SSI 1479 "ssi_pattern",
"**.shtml$|**.shtm$",
1481 "url_rewrites", NULL,
1502 #define MG_HEADERS_SENT NSF_USER_1 1503 #define MG_USING_CHUNKED_API NSF_USER_2 1504 #define MG_CGI_CONN NSF_USER_3 1505 #define MG_PROXY_CONN NSF_USER_4 1506 #define MG_PROXY_DONT_PARSE NSF_USER_5 1521 #define MG_CONN_2_CONN(c) ((struct connection *) ((char *) (c) - \ 1522 offsetof(struct connection, mg_conn))) 1528 static const struct {
1533 {
".html", 5,
"text/html"},
1534 {
".htm", 4,
"text/html"},
1535 {
".shtm", 5,
"text/html"},
1536 {
".shtml", 6,
"text/html"},
1537 {
".css", 4,
"text/css"},
1538 {
".js", 3,
"application/javascript"},
1539 {
".ico", 4,
"image/x-icon"},
1540 {
".gif", 4,
"image/gif"},
1541 {
".jpg", 4,
"image/jpeg"},
1542 {
".jpeg", 5,
"image/jpeg"},
1543 {
".png", 4,
"image/png"},
1544 {
".svg", 4,
"image/svg+xml"},
1545 {
".txt", 4,
"text/plain"},
1546 {
".torrent", 8,
"application/x-bittorrent"},
1547 {
".wav", 4,
"audio/x-wav"},
1548 {
".mp3", 4,
"audio/x-mp3"},
1549 {
".mid", 4,
"audio/mid"},
1550 {
".m3u", 4,
"audio/x-mpegurl"},
1551 {
".ogg", 4,
"application/ogg"},
1552 {
".ram", 4,
"audio/x-pn-realaudio"},
1553 {
".xml", 4,
"text/xml"},
1554 {
".json", 5,
"application/json"},
1555 {
".xslt", 5,
"application/xml"},
1556 {
".xsl", 4,
"application/xml"},
1557 {
".ra", 3,
"audio/x-pn-realaudio"},
1558 {
".doc", 4,
"application/msword"},
1559 {
".exe", 4,
"application/octet-stream"},
1560 {
".zip", 4,
"application/x-zip-compressed"},
1561 {
".xls", 4,
"application/excel"},
1562 {
".tgz", 4,
"application/x-tar-gz"},
1563 {
".tar", 4,
"application/x-tar"},
1564 {
".gz", 3,
"application/x-gunzip"},
1565 {
".arj", 4,
"application/x-arj-compressed"},
1566 {
".rar", 4,
"application/x-rar-compressed"},
1567 {
".rtf", 4,
"application/rtf"},
1568 {
".pdf", 4,
"application/pdf"},
1569 {
".swf", 4,
"application/x-shockwave-flash"},
1570 {
".mpg", 4,
"video/mpeg"},
1571 {
".webm", 5,
"video/webm"},
1572 {
".mpeg", 5,
"video/mpeg"},
1573 {
".mov", 4,
"video/quicktime"},
1574 {
".mp4", 4,
"video/mp4"},
1575 {
".m4v", 4,
"video/x-m4v"},
1576 {
".asf", 4,
"video/x-ms-asf"},
1577 {
".avi", 4,
"video/x-msvideo"},
1578 {
".bmp", 4,
"image/bmp"},
1579 {
".ttf", 4,
"application/x-font-ttf"},
1583 #ifdef MONGOOSE_ENABLE_THREADS 1587 #endif // MONGOOSE_ENABLE_THREADS 1589 #ifndef MONGOOSE_NO_MMAP 1591 static void *mmap(
void *addr, int64_t
len,
int prot,
int flags,
int fd,
1593 HANDLE fh = (HANDLE) _get_osfhandle(fd);
1594 HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0);
1595 void *p = MapViewOfFile(mh, FILE_MAP_READ, 0, 0, (
size_t) len);
1599 #define munmap(x, y) UnmapViewOfFile(x) 1600 #define MAP_FAILED NULL 1601 #define MAP_PRIVATE 0 1603 #elif defined(__OS2__) 1604 static void *mmap(
void *addr, int64_t len,
int prot,
int flags,
int fd,
1608 int pos = lseek( fd, 0, SEEK_CUR );
1614 if (lseek( fd, offset, SEEK_SET) == -1)
1620 if (!p || read(fd, p, len) == -1) {
1626 lseek(fd, pos, SEEK_SET);
1630 #define munmap(x, y) free(x) 1631 #define MAP_FAILED NULL 1632 #define MAP_PRIVATE 0 1635 #include <sys/mman.h> 1639 void *p = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
fileno(fp), 0);
1640 return p == MAP_FAILED ? NULL :
p;
1646 #endif // MONGOOSE_NO_MMAP 1648 #if defined(_WIN32) && !defined(MONGOOSE_NO_FILESYSTEM) 1651 static void to_wchar(
const char *
path,
wchar_t *wbuf,
size_t wbuf_len) {
1654 strncpy(buf, path,
sizeof(buf));
1655 buf[
sizeof(
buf) - 1] =
'\0';
1658 p = buf + strlen(buf) - 1;
1659 while (p > buf && p[-1] !=
':' && (p[0] ==
'\\' || p[0] ==
'/')) *p-- =
'\0';
1663 memset(wbuf, 0, wbuf_len *
sizeof(
wchar_t));
1664 MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (
int) wbuf_len);
1665 WideCharToMultiByte(CP_UTF8, 0, wbuf, (
int) wbuf_len, buf2,
sizeof(buf2),
1667 if (strcmp(buf, buf2) != 0) {
1672 static int mg_stat(
const char *path, file_stat_t *st) {
1675 DBG((
"[%ls] -> %d", wpath, _wstati64(wpath, st)));
1676 return _wstati64(wpath, st);
1679 static FILE *mg_fopen(
const char *path,
const char *mode) {
1683 return _wfopen(wpath, wmode);
1686 static int mg_open(
const char *path,
int flag,
int mode) {
1689 return _wopen(wpath, flag, mode);
1691 #endif // _WIN32 && !MONGOOSE_NO_FILESYSTEM 1700 struct vec *eq_val) {
1701 if (list == NULL || *list ==
'\0') {
1706 if ((list = strchr(val->
ptr,
',')) != NULL) {
1708 val->
len = list - val->
ptr;
1712 list = val->
ptr + strlen(val->
ptr);
1713 val->
len = list - val->
ptr;
1716 if (eq_val != NULL) {
1720 eq_val->
ptr = (
const char *) memchr(val->
ptr,
'=', val->
len);
1721 if (eq_val->
ptr != NULL) {
1724 val->
len = (eq_val->
ptr - val->
ptr) - 1;
1736 if (buflen < 1)
return 0;
1740 }
else if (n >= (
int) buflen) {
1741 n = (int) buflen - 1;
1761 const unsigned char *
buf = (
unsigned char *) s;
1764 for (i = 0; i < buf_len; i++) {
1767 if (!isprint(buf[i]) && buf[
i] !=
'\r' && buf[
i] !=
'\n' && buf[
i] < 128) {
1769 }
else if (buf[i] ==
'\n' && i + 1 < buf_len && buf[i + 1] ==
'\n') {
1771 }
else if (buf[i] ==
'\n' && i + 2 < buf_len && buf[i + 1] ==
'\r' &&
1772 buf[i + 2] ==
'\n') {
1783 static char *
skip(
char **
buf,
const char *delimiters) {
1784 char *
p, *begin_word, *end_word, *end_delimiters;
1787 end_word = begin_word + strcspn(begin_word, delimiters);
1788 end_delimiters = end_word + strspn(end_word, delimiters);
1790 for (p = end_word; p < end_delimiters; p++) {
1794 *buf = end_delimiters;
1814 switch (status_code) {
1816 case 100:
return "Continue";
1817 case 101:
return "Switching Protocols";
1818 case 102:
return "Processing";
1820 case 200:
return "OK";
1821 case 201:
return "Created";
1822 case 202:
return "Accepted";
1823 case 203:
return "Non-Authoritative Information";
1824 case 204:
return "No Content";
1825 case 205:
return "Reset Content";
1826 case 206:
return "Partial Content";
1827 case 207:
return "Multi-Status";
1828 case 208:
return "Already Reported";
1829 case 226:
return "IM Used";
1831 case 300:
return "Multiple Choices";
1832 case 301:
return "Moved Permanently";
1833 case 302:
return "Found";
1834 case 303:
return "See Other";
1835 case 304:
return "Not Modified";
1836 case 305:
return "Use Proxy";
1837 case 306:
return "Switch Proxy";
1838 case 307:
return "Temporary Redirect";
1839 case 308:
return "Permanent Redirect";
1841 case 400:
return "Bad Request";
1842 case 401:
return "Unauthorized";
1843 case 402:
return "Payment Required";
1844 case 403:
return "Forbidden";
1845 case 404:
return "Not Found";
1846 case 405:
return "Method Not Allowed";
1847 case 406:
return "Not Acceptable";
1848 case 407:
return "Proxy Authentication Required";
1849 case 408:
return "Request Timeout";
1850 case 409:
return "Conflict";
1851 case 410:
return "Gone";
1852 case 411:
return "Length Required";
1853 case 412:
return "Precondition Failed";
1854 case 413:
return "Payload Too Large";
1855 case 414:
return "URI Too Long";
1856 case 415:
return "Unsupported Media Type";
1857 case 416:
return "Requested Range Not Satisfiable";
1858 case 417:
return "Expectation Failed";
1859 case 418:
return "I\'m a teapot";
1860 case 422:
return "Unprocessable Entity";
1861 case 423:
return "Locked";
1862 case 424:
return "Failed Dependency";
1863 case 426:
return "Upgrade Required";
1864 case 428:
return "Precondition Required";
1865 case 429:
return "Too Many Requests";
1866 case 431:
return "Request Header Fields Too Large";
1867 case 451:
return "Unavailable For Legal Reasons";
1869 case 500:
return "Internal Server Error";
1870 case 501:
return "Not Implemented";
1871 case 502:
return "Bad Gateway";
1872 case 503:
return "Service Unavailable";
1873 case 504:
return "Gateway Timeout";
1874 case 505:
return "HTTP Version Not Supported";
1875 case 506:
return "Variant Also Negotiates";
1876 case 507:
return "Insufficient Storage";
1877 case 508:
return "Loop Detected";
1878 case 510:
return "Not Extended";
1879 case 511:
return "Network Authentication Required";
1881 default:
return "Server Error";
1886 return conn != NULL && conn->
server != NULL &&
1892 const char *fmt, ...) {
1895 char headers[200],
body[200];
1898 int body_len, headers_len, match_code;
1909 while ((rewrites =
next_option(rewrites, &a, &b)) != NULL) {
1910 if ((match_code = atoi(a.
ptr)) > 0 && match_code == code) {
1914 "Location: %.*s?code=%d&orig_uri=%s&query_string=%s\r\n\r\n",
1922 body_len =
mg_snprintf(body,
sizeof(body),
"%d %s\n", code, message);
1925 body_len +=
mg_vsnprintf(body + body_len,
sizeof(body) - body_len, fmt, ap);
1928 if ((code >= 300 && code <= 399) || code == 204) {
1932 headers_len =
mg_snprintf(headers,
sizeof(headers),
1933 "HTTP/1.1 %d %s\r\nContent-Length: %d\r\n" 1934 "Content-Type: text/plain\r\n\r\n",
1935 code, message, body_len);
1942 char chunk_size[50];
1943 int n =
mg_snprintf(chunk_size,
sizeof(chunk_size),
"%X\r\n", len);
1961 DBG((
"%p -> %p %lu bytes", from, to, (
unsigned long)from->
recv_iobuf.
len));
1966 #ifndef MONGOOSE_NO_CGI 1968 struct threadparam {
1973 static int wait_until_ready(
sock_t sock,
int for_read) {
1977 select(sock + 1, for_read ? &
set : 0, for_read ? 0 : &
set, 0, 0);
1981 static void *push_to_stdin(
void *arg) {
1982 struct threadparam *tp = (
struct threadparam *)arg;
1983 int n, sent, stop = 0;
1987 while (!stop && wait_until_ready(tp->s, 1) &&
1988 (n = recv(tp->s, buf,
sizeof(buf), 0)) > 0) {
1989 if (n == -1 && GetLastError() == WSAEWOULDBLOCK)
continue;
1990 for (sent = 0; !stop && sent < n; sent += k) {
1991 if (!WriteFile(tp->hPipe, buf + sent, n - sent, &k, 0)) stop = 1;
1994 DBG((
"%s",
"FORWARED EVERYTHING TO CGI"));
1995 CloseHandle(tp->hPipe);
2001 static void *pull_from_stdout(
void *arg) {
2002 struct threadparam *tp = (
struct threadparam *)arg;
2003 int k = 0, stop = 0;
2007 while (!stop && ReadFile(tp->hPipe, buf,
sizeof(buf), &n, NULL)) {
2008 for (sent = 0; !stop && sent < n; sent += k) {
2009 if (wait_until_ready(tp->s, 0) &&
2010 (k = send(tp->s, buf + sent, n - sent, 0)) <= 0) stop = 1;
2013 DBG((
"%s",
"EOF FROM CGI"));
2014 CloseHandle(tp->hPipe);
2022 static void spawn_stdio_thread(
sock_t sock, HANDLE hPipe,
2023 void *(*func)(
void *)) {
2024 struct threadparam *tp = (
struct threadparam *)
NS_MALLOC(
sizeof(*tp));
2035 GetFullPathNameW(buf,
ARRAY_SIZE(buf2), buf2, NULL);
2036 WideCharToMultiByte(CP_UTF8, 0, buf2, wcslen(buf2) + 1, abs_path, len, 0, 0);
2039 static process_id_t
start_process(
char *interp,
const char *cmd,
2040 const char *env,
const char *envp[],
2041 const char *dir,
sock_t sock) {
2043 PROCESS_INFORMATION pi;
2044 HANDLE
a[2], b[2], me = GetCurrentProcess();
2048 DWORD flags = DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS;
2051 memset(&si, 0,
sizeof(si));
2052 memset(&pi, 0,
sizeof(pi));
2055 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
2056 si.wShowWindow = SW_HIDE;
2057 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
2059 CreatePipe(&a[0], &a[1], NULL, 0);
2060 CreatePipe(&b[0], &b[1], NULL, 0);
2061 DuplicateHandle(me, a[0], me, &si.hStdInput, 0,
TRUE, flags);
2062 DuplicateHandle(me, b[1], me, &si.hStdOutput, 0,
TRUE, flags);
2064 if (interp == NULL && (fp = fopen(cmd,
"r")) != NULL) {
2065 buf[0] = buf[1] =
'\0';
2066 fgets(buf,
sizeof(buf), fp);
2067 buf[
sizeof(
buf) - 1] =
'\0';
2068 if (buf[0] ==
'#' && buf[1] ==
'!') {
2070 for (p = interp + strlen(interp) - 1;
2071 isspace(* (uint8_t *) p) && p > interp; p--) *p =
'\0';
2076 if (interp != NULL) {
2081 to_wchar(dir, full_dir,
ARRAY_SIZE(full_dir));
2082 mg_snprintf(cmdline,
sizeof(cmdline),
"%s%s\"%s\"",
2083 interp ? interp :
"", interp ?
" " :
"", cmd);
2086 if (CreateProcessW(NULL, wcmd, NULL, NULL,
TRUE, CREATE_NEW_PROCESS_GROUP,
2087 (
void *) env, full_dir, &si, &pi) != 0) {
2088 spawn_stdio_thread(sock, a[1], push_to_stdin);
2089 spawn_stdio_thread(sock, b[0], pull_from_stdout);
2095 DBG((
"CGI command: [%ls] -> %p", wcmd, pi.hProcess));
2098 CloseHandle(si.hStdOutput);
2099 CloseHandle(si.hStdInput);
2107 const char *env,
const char *envp[],
2108 const char *dir,
sock_t sock) {
2110 process_id_t pid = fork();
2115 (void) dup2(sock, 0);
2116 (void) dup2(sock, 1);
2123 signal(SIGCHLD, SIG_DFL);
2125 if (interp == NULL) {
2126 execle(cmd, cmd, (
char *) 0, envp);
2128 execle(interp, interp, cmd, (
char *) 0, envp);
2130 snprintf(buf,
sizeof(buf),
"Status: 500\r\n\r\n" 2131 "500 Server Error: %s%s%s: %s", interp == NULL ?
"" : interp,
2132 interp == NULL ?
"" :
" ", cmd, strerror(errno));
2133 send(1, buf, strlen(buf), 0);
2165 space =
sizeof(block->
buf) - block->
len - 2;
2169 added = block->
buf + block->
len;
2177 if (n > 0 && n + 1 < space &&
2182 block->
len += n + 1;
2190 if ((s =
getenv(name)) != NULL)
addenv(blk,
"%s=%s", name, s);
2197 const char *
s, *slash;
2204 if ((s =
getenv(
"SERVER_NAME")) != NULL) {
2205 addenv(blk,
"SERVER_NAME=%s", s);
2210 addenv(blk,
"DOCUMENT_ROOT=%s", opts[DOCUMENT_ROOT]);
2214 addenv(blk,
"%s",
"GATEWAY_INTERFACE=CGI/1.1");
2215 addenv(blk,
"%s",
"SERVER_PROTOCOL=HTTP/1.1");
2216 addenv(blk,
"%s",
"REDIRECT_STATUS=200");
2224 addenv(blk,
"REQUEST_URI=%s%s%s", ri->
uri,
2230 addenv(blk,
"SCRIPT_NAME=%.*s",
2234 s = strrchr(prog,
'/');
2235 slash = strrchr(ri->
uri,
'/');
2236 addenv(blk,
"SCRIPT_NAME=%.*s%s",
2237 slash == NULL ? 0 : (
int) (slash - ri->
uri), ri->
uri,
2238 s == NULL ? prog : s);
2241 addenv(blk,
"SCRIPT_FILENAME=%s", prog);
2242 addenv(blk,
"PATH_TRANSLATED=%s", prog);
2246 addenv(blk,
"CONTENT_TYPE=%s", s);
2252 addenv(blk,
"CONTENT_LENGTH=%s", s);
2266 addenv2(blk,
"ProgramFiles(x86)");
2267 addenv2(blk,
"CommonProgramFiles(x86)");
2269 addenv2(blk,
"LD_LIBRARY_PATH");
2274 p =
addenv(blk,
"HTTP_%s=%s",
2278 for (; *p !=
'=' && *p !=
'\0'; p++) {
2281 *p = (char) toupper(* (
unsigned char *)
p);
2286 blk->
buf[blk->
len++] =
'\0';
2289 assert(blk->
len > 0);
2290 assert(blk->
len < (
int)
sizeof(blk->
buf));
2305 if ((p = strrchr(prog,
'/')) == NULL) {
2308 mg_snprintf(dir,
sizeof(dir),
"%.*s", (
int) (p - prog), prog);
2319 prog, blk.
buf, blk.
vars, dir, fds[1]) != 0) {
2342 const char *status =
"500";
2357 if (len == 0)
return;
2359 if (len < 0 || len > (
int)
sizeof(buf)) {
2362 send_http_error(conn, 500,
"CGI program sent malformed headers: [%.*s]",
2365 memset(&c, 0,
sizeof(c));
2367 buf[len - 1] =
'\0';
2371 }
else if ((status = (
char *)
mg_get_header(&c,
"Status")) == NULL) {
2380 #endif // !MONGOOSE_NO_CGI 2383 char *copy = (
char *)
NS_MALLOC(strlen(str) + 1);
2391 return n >= 0 && n <= 255;
2394 static int parse_net(
const char *spec, uint32_t *net, uint32_t *mask) {
2395 int n,
a, b, c,
d, slash = 32, len = 0;
2397 if ((sscanf(spec,
"%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
2398 sscanf(spec,
"%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
2400 slash >= 0 && slash < 33) {
2402 *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | d;
2403 *mask = slash ? 0xffffffffU << (32 - slash) : 0;
2417 allowed = acl == NULL ?
'+' :
'-';
2419 while ((acl =
next_option(acl, &vec, NULL)) != NULL) {
2421 if ((flag !=
'+' && flag !=
'-') ||
2426 if (net == (remote_ip & mask)) {
2431 return allowed ==
'+';
2439 while (*s !=
'\0') {
2441 if (s[-1] ==
'/' || s[-1] ==
'\\') {
2443 while (s[0] !=
'\0') {
2444 if (s[0] ==
'/' || s[0] ==
'\\') { s++; }
2445 else if (s[0] ==
'.' && (s[1] ==
'/' || s[1] ==
'\\')) { s += 2; }
2446 else if (s[0] ==
'.' && s[1] ==
'.' && s[2] ==
'\0') { s += 2; }
2447 else if (s[0] ==
'.' && s[1] ==
'.' && (s[2] ==
'/' || s[2] ==
'\\')) { s += 3; }
2456 size_t dst_len,
int is_form_url_encoded) {
2459 #define HEXTOI(x) (isdigit(x) ? (x) - '0' : (x) - 'W') 2461 for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
2462 if (src[i] ==
'%' && i + 2 < src_len &&
2463 isxdigit(* (
const unsigned char *) (src + i + 1)) &&
2464 isxdigit(* (
const unsigned char *) (src + i + 2))) {
2465 a = tolower(* (
const unsigned char *) (src + i + 1));
2466 b = tolower(* (
const unsigned char *) (src + i + 2));
2469 }
else if (is_form_url_encoded && src[i] ==
'+') {
2478 return i >= src_len ? j : -1;
2482 return !strcmp(s,
"GET") || !strcmp(s,
"POST") || !strcmp(s,
"HEAD") ||
2483 !strcmp(s,
"CONNECT") || !strcmp(s,
"PUT") || !strcmp(s,
"DELETE") ||
2484 !strcmp(s,
"OPTIONS") || !strcmp(s,
"PROPFIND") || !strcmp(s,
"MKCOL") ||
2485 !strcmp(s,
"PATCH");
2501 if (len < 1)
return ~0;
2503 buf[len - 1] =
'\0';
2506 while (*buf !=
'\0' && isspace(* (
unsigned char *) buf)) {
2516 if ((is_request && memcmp(ri->
http_version,
"HTTP/", 5) != 0) ||
2530 n = (int) strlen(ri->
uri);
2532 if (*ri->
uri ==
'/' || *ri->
uri ==
'.') {
2541 return tolower(* (
const unsigned char *) s);
2549 }
while (diff == 0 && s1[-1] !=
'\0');
2560 }
while (diff == 0 && s1[-1] !=
'\0' && --len > 0);
2581 if ((or_str = (
const char *) memchr(pattern,
'|', pattern_len)) != NULL) {
2584 (pattern + pattern_len) - (or_str + 1), str);
2587 for (; i < pattern_len; i++,
j++) {
2588 if (pattern[i] ==
'?' && str[
j] !=
'\0') {
2590 }
else if (pattern[i] ==
'$') {
2591 return str[
j] ==
'\0' ?
j : -1;
2592 }
else if (pattern[i] ==
'*') {
2594 if (pattern[i] ==
'*') {
2596 len = (int) strlen(str +
j);
2598 len = (int) strcspn(str +
j,
"/");
2600 if (i == pattern_len) {
2605 }
while (res == -1 && len-- > 0);
2606 return res == -1 ? -1 :
j + res +
len;
2620 int i,
j, pos = 0, inside_marker = 0;
2622 for (i = 0; s[
i] !=
'\0'; i++) {
2623 if (inside_marker == 0 && !memcmp(&s[i],
"{{", 2)) {
2630 if (inside_marker == 1 && !memcmp(&s[i],
"}}", 2)) {
2631 for (j = 0; expansions[
j].
keyword != NULL; j++) {
2632 const char *kw = expansions[
j].
keyword;
2633 if ((
int) strlen(kw) == i - (pos + 2) &&
2634 memcmp(kw, &s[pos + 2], i - (pos + 2)) == 0) {
2648 #ifndef MONGOOSE_NO_FILESYSTEM 2651 return !strcmp(s,
"PUT") || !strcmp(s,
"DELETE") ||
2652 !strcmp(s,
"MKCOL") || !strcmp(s,
"PROPFIND");
2659 (pattern != NULL &&
mg_match_prefix(pattern, strlen(pattern), path) > 0);
2664 size_t buf_len, file_stat_t *st) {
2668 #ifndef MONGOOSE_NO_DAV 2673 #ifndef MONGOOSE_NO_CGI 2679 size_t match_len, root_len = root == NULL ? 0 : strlen(root);
2682 if (rewrites != NULL && domain != NULL) {
2683 const char *colon = strchr(domain,
':');
2684 size_t domain_len = colon == NULL ? strlen(domain) : colon - domain;
2686 while ((rewrites =
next_option(rewrites, &a, &b)) != NULL) {
2687 if (a.
len > 1 && a.
ptr[0] ==
'@' && a.
len == domain_len + 1 &&
2697 if (root == NULL || root_len == 0)
return 0;
2700 mg_snprintf(buf, buf_len,
"%.*s%s", root_len, root, uri);
2702 while ((rewrites =
next_option(rewrites, &a, &b)) != NULL) {
2709 if (
stat(buf, st) == 0)
return 1;
2711 #ifndef MONGOOSE_NO_CGI 2713 for (p = buf + strlen(root) + 2; *p !=
'\0'; p++) {
2718 DBG((
"!!!! [%s]", buf));
2731 #endif // MONGOOSE_NO_FILESYSTEM 2738 return method != NULL &&
2740 ((header != NULL && !
mg_strcasecmp(header,
"keep-alive")) ||
2741 (header == NULL && http_version && !strcmp(http_version,
"1.1")));
2800 if (buf != mem && buf != NULL) {
2806 #if !defined(MONGOOSE_NO_WEBSOCKET) || !defined(MONGOOSE_NO_AUTH) 2808 static const int n = 1;
2809 return ((
char *) &n)[0] == 0;
2813 #ifndef MONGOOSE_NO_WEBSOCKET 2816 #define SHA1HANDSOFF 2818 #include "solarisfixes.h" 2823 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 2828 block->
l[
i] = (
rol(block->
l[i], 24) & 0xFF00FF00) |
2829 (
rol(block->
l[i], 8) & 0x00FF00FF);
2842 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 2843 ^block->l[(i+2)&15]^block->l[i&15],1)) 2844 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(block, i)+0x5A827999+rol(v,5);w=rol(w,30); 2845 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 2846 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 2847 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 2848 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 2857 uint32_t
a, b, c,
d, e;
2860 memcpy(block, buffer, 64);
2866 R0(a,b,c,d,e, 0);
R0(e,a,b,c,d, 1);
R0(d,e,a,b,c, 2);
R0(c,d,e,a,b, 3);
2867 R0(b,c,d,e,a, 4);
R0(a,b,c,d,e, 5);
R0(e,a,b,c,d, 6);
R0(d,e,a,b,c, 7);
2868 R0(c,d,e,a,b, 8);
R0(b,c,d,e,a, 9);
R0(a,b,c,d,e,10);
R0(e,a,b,c,d,11);
2869 R0(d,e,a,b,c,12);
R0(c,d,e,a,b,13);
R0(b,c,d,e,a,14);
R0(a,b,c,d,e,15);
2870 R1(e,a,b,c,d,16);
R1(d,e,a,b,c,17);
R1(c,d,e,a,b,18);
R1(b,c,d,e,a,19);
2871 R2(a,b,c,d,e,20);
R2(e,a,b,c,d,21);
R2(d,e,a,b,c,22);
R2(c,d,e,a,b,23);
2872 R2(b,c,d,e,a,24);
R2(a,b,c,d,e,25);
R2(e,a,b,c,d,26);
R2(d,e,a,b,c,27);
2873 R2(c,d,e,a,b,28);
R2(b,c,d,e,a,29);
R2(a,b,c,d,e,30);
R2(e,a,b,c,d,31);
2874 R2(d,e,a,b,c,32);
R2(c,d,e,a,b,33);
R2(b,c,d,e,a,34);
R2(a,b,c,d,e,35);
2875 R2(e,a,b,c,d,36);
R2(d,e,a,b,c,37);
R2(c,d,e,a,b,38);
R2(b,c,d,e,a,39);
2876 R3(a,b,c,d,e,40);
R3(e,a,b,c,d,41);
R3(d,e,a,b,c,42);
R3(c,d,e,a,b,43);
2877 R3(b,c,d,e,a,44);
R3(a,b,c,d,e,45);
R3(e,a,b,c,d,46);
R3(d,e,a,b,c,47);
2878 R3(c,d,e,a,b,48);
R3(b,c,d,e,a,49);
R3(a,b,c,d,e,50);
R3(e,a,b,c,d,51);
2879 R3(d,e,a,b,c,52);
R3(c,d,e,a,b,53);
R3(b,c,d,e,a,54);
R3(a,b,c,d,e,55);
2880 R3(e,a,b,c,d,56);
R3(d,e,a,b,c,57);
R3(c,d,e,a,b,58);
R3(b,c,d,e,a,59);
2881 R4(a,b,c,d,e,60);
R4(e,a,b,c,d,61);
R4(d,e,a,b,c,62);
R4(c,d,e,a,b,63);
2882 R4(b,c,d,e,a,64);
R4(a,b,c,d,e,65);
R4(e,a,b,c,d,66);
R4(d,e,a,b,c,67);
2883 R4(c,d,e,a,b,68);
R4(b,c,d,e,a,69);
R4(a,b,c,d,e,70);
R4(e,a,b,c,d,71);
2884 R4(d,e,a,b,c,72);
R4(c,d,e,a,b,73);
R4(b,c,d,e,a,74);
R4(a,b,c,d,e,75);
2885 R4(e,a,b,c,d,76);
R4(d,e,a,b,c,77);
R4(c,d,e,a,b,78);
R4(b,c,d,e,a,79);
2893 memset(block, 0,
sizeof(block));
2894 a = b = c = d = e = 0;
2895 (void) a; (void) b; (void) c; (void) d; (void) e;
2899 context->
state[0] = 0x67452301;
2900 context->
state[1] = 0xEFCDAB89;
2901 context->
state[2] = 0x98BADCFE;
2902 context->
state[3] = 0x10325476;
2903 context->
state[4] = 0xC3D2E1F0;
2911 j = context->
count[0];
2912 if ((context->
count[0] += len << 3) < j)
2913 context->
count[1]++;
2914 context->
count[1] += (len>>29);
2916 if ((j + len) > 63) {
2919 for ( ; i + 63 <
len; i += 64) {
2930 unsigned char finalcount[8],
c;
2932 for (i = 0; i < 8; i++) {
2933 finalcount[
i] = (
unsigned char)((context->
count[(i >= 4 ? 0 : 1)]
2934 >> ((3-(i & 3)) * 8) ) & 255);
2938 while ((context->
count[0] & 504) != 448) {
2943 for (i = 0; i < 20; i++) {
2944 digest[
i] = (
unsigned char)
2945 ((context->
state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
2947 memset(context,
'\0',
sizeof(*context));
2948 memset(&finalcount,
'\0',
sizeof(finalcount));
2953 static const char *b64 =
2954 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2957 for (i = j = 0; i < src_len; i += 3) {
2959 b = i + 1 >= src_len ? 0 : src[i + 1];
2960 c = i + 2 >= src_len ? 0 : src[i + 2];
2962 dst[j++] = b64[a >> 2];
2963 dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
2964 if (i + 1 < src_len) {
2965 dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
2967 if (i + 2 < src_len) {
2968 dst[j++] = b64[c & 63];
2971 while (j % 4 != 0) {
2979 static const char *magic =
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
2980 char buf[500], sha[20], b64_sha[
sizeof(sha) * 2];
2983 mg_snprintf(buf,
sizeof(buf),
"%s%s", key, magic);
2985 SHA1Update(&sha_ctx, (
unsigned char *) buf, strlen(buf));
2986 SHA1Final((
unsigned char *) sha, &sha_ctx);
2989 "HTTP/1.1 101 Switching Protocols\r\n" 2990 "Upgrade: websocket\r\n" 2991 "Connection: Upgrade\r\n" 2992 "Sec-WebSocket-Accept: ", b64_sha,
"\r\n\r\n");
3001 mask_len = 0, header_len = 0, data_len = 0, buffered = 0;
3005 mask_len = buf[1] & 128 ? 4 : 0;
3006 if (len < 126 && buf_len >= mask_len) {
3008 header_len = 2 + mask_len;
3009 }
else if (len == 126 && buf_len >= 4 + mask_len) {
3010 header_len = 4 + mask_len;
3011 data_len = ((((
size_t) buf[2]) << 8) + buf[3]);
3012 }
else if (buf_len >= 10 + mask_len) {
3013 header_len = 10 + mask_len;
3014 data_len = (
size_t) (((uint64_t) htonl(* (uint32_t *) &buf[2])) << 32) +
3015 htonl(* (uint32_t *) &buf[6]);
3019 frame_len = header_len + data_len;
3020 buffered = frame_len > 0 && frame_len <= buf_len;
3029 for (i = 0; i < data_len; i++) {
3030 buf[i + header_len] ^= (buf + header_len - mask_len)[i % 4];
3046 const char *data,
size_t data_len) {
3047 unsigned char mem[4192], *copy = mem;
3048 size_t copy_len = 0;
3051 if (data_len > ~(
size_t)0 - (
size_t)10) {
3055 if (data_len + 10 >
sizeof(mem) &&
3056 (copy = (
unsigned char *)
NS_MALLOC(data_len + 10)) == NULL) {
3060 copy[0] = 0x80 + (opcode & 0x0f);
3063 if (data_len < 126) {
3066 memcpy(copy + 2, data, data_len);
3067 copy_len = 2 + data_len;
3068 }
else if (data_len <= 0xFFFF) {
3071 * (uint16_t *) (copy + 2) = (uint16_t) htons((uint16_t) data_len);
3072 memcpy(copy + 4, data, data_len);
3073 copy_len = 4 + data_len;
3076 const uint32_t hi = htonl((uint32_t) ((uint64_t) data_len >> 32));
3077 const uint32_t lo = htonl(data_len & 0xffffffff);
3079 memcpy(copy+2,&hi,
sizeof(hi));
3080 memcpy(copy+6,&lo,
sizeof(lo));
3081 memcpy(copy + 10, data, data_len);
3082 copy_len = 10 + data_len;
3102 const char *fmt, ...) {
3103 char mem[4192], *
buf = mem;
3108 if ((len =
ns_avprintf(&buf,
sizeof(mem), fmt, ap)) > 0) {
3113 if (buf != mem && buf != NULL) {
3121 const char *ver =
mg_get_header(conn,
"Sec-WebSocket-Version"),
3123 if (ver != NULL &&
key != NULL) {
3138 #define ping_idle_websocket_connection(conn, t) 3139 #endif // !MONGOOSE_NO_WEBSOCKET 3162 path_len = strlen(path);
3172 return default_mime_type;
3175 #ifndef MONGOOSE_NO_FILESYSTEM 3178 static const char *month_names[] = {
3179 "Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
3180 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" 3184 for (i = 0; i < (int)
ARRAY_SIZE(month_names); i++)
3185 if (!strcmp(s, month_names[i]))
3192 return year / 4 - year / 100 + year / 400;
3197 static const unsigned short days_before_month[] = {
3198 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
3201 int second, minute, hour, day, month, year, leap_days, days;
3202 time_t
result = (time_t) 0;
3204 if (((sscanf(datetime,
"%d/%3s/%d %d:%d:%d",
3205 &day, month_str, &year, &hour, &minute, &second) == 6) ||
3206 (sscanf(datetime,
"%d %3s %d %d:%d:%d",
3207 &day, month_str, &year, &hour, &minute, &second) == 6) ||
3208 (sscanf(datetime,
"%*3s, %d %3s %d %d:%d:%d",
3209 &day, month_str, &year, &hour, &minute, &second) == 6) ||
3210 (sscanf(datetime,
"%d-%3s-%d %d:%d:%d",
3211 &day, month_str, &year, &hour, &minute, &second) == 6)) &&
3216 days = year * 365 + days_before_month[month] + (day - 1) + leap_days;
3217 result = days * 24 * 3600 + hour * 3600 + minute * 60 + second;
3227 struct vec ext_vec, mime_vec;
3228 const char *list, *ext;
3231 path_len = strlen(path);
3236 while ((list =
next_option(list, &ext_vec, &mime_vec)) != NULL) {
3238 ext = path + path_len - ext_vec.
len;
3246 vec->
len = strlen(vec->
ptr);
3255 (
unsigned long) st->st_mtime, (int64_t) st->st_size);
3260 const file_stat_t *stp) {
3273 size_t path_len, file_stat_t *stp) {
3276 struct vec filename_vec;
3277 size_t n = strlen(path);
3283 while (n > 0 && path[n - 1] ==
'/') {
3290 while ((list =
next_option(list, &filename_vec, NULL)) != NULL) {
3292 if (path_len <= n + 2) {
3297 if (filename_vec.
len > (path_len - (n + 2)))
3301 strncpy(path + n + 1, filename_vec.
ptr, filename_vec.
len);
3302 path[n + 1 + filename_vec.
len] =
'\0';
3307 if (!
stat(path, &st)) {
3328 strftime(buf, buf_len,
"%a, %d %b %Y %H:%M:%S GMT", gmtime(t));
3332 file_stat_t *st,
const char *extra_headers) {
3333 char date[64], lm[64], etag[64], range[64], headers[1000];
3334 const char *msg =
"OK", *hdr;
3335 time_t
t, curtime = time(NULL);
3337 struct vec mime_vec;
3345 conn->
cl = st->st_size;
3352 r1 >= 0 && r2 >= 0) {
3354 conn->
cl = n == 2 ? (r2 > conn->
cl ? conn->
cl : r2) - r1 + 1: conn->
cl - r1;
3355 mg_snprintf(range,
sizeof(range),
"Content-Range: bytes " 3357 r1, r1 + conn->
cl - 1, (int64_t) st->st_size);
3358 msg =
"Partial Content";
3370 "HTTP/1.1 %d %s\r\n" 3372 "Last-Modified: %s\r\n" 3374 "Content-Type: %.*s\r\n" 3376 "Connection: %s\r\n" 3377 "Accept-Ranges: bytes\r\n" 3380 (
int) mime_vec.
len, mime_vec.
ptr, conn->
cl,
3382 range, extra_headers == NULL ?
"" : extra_headers,
3399 #endif // MONGOOSE_NO_FILESYSTEM 3402 #ifndef MONGOOSE_NO_WEBSOCKET 3413 #if !defined(MONGOOSE_NO_DIRECTORY_LISTING) || !defined(MONGOOSE_NO_DAV) 3420 typedef struct DIR {
3422 WIN32_FIND_DATAW info;
3423 struct dirent result;
3427 static DIR *opendir(
const char *
name) {
3433 SetLastError(ERROR_BAD_ARGUMENTS);
3434 }
else if ((dir = (DIR *)
NS_MALLOC(
sizeof(*dir))) == NULL) {
3435 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3438 attrs = GetFileAttributesW(wpath);
3439 if (attrs != 0xFFFFFFFF &&
3440 ((attrs & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)) {
3441 (void) wcscat(wpath, L
"\\*");
3442 dir->handle = FindFirstFileW(wpath, &dir->info);
3443 dir->result.d_name[0] =
'\0';
3453 static int closedir(DIR *dir) {
3457 if (dir->handle != INVALID_HANDLE_VALUE)
3458 result = FindClose(dir->handle) ? 0 : -1;
3463 SetLastError(ERROR_BAD_ARGUMENTS);
3469 static struct dirent *readdir(DIR *dir) {
3470 struct dirent *
result = 0;
3473 if (dir->handle != INVALID_HANDLE_VALUE) {
3474 result = &dir->result;
3475 (void) WideCharToMultiByte(CP_UTF8, 0,
3476 dir->info.cFileName, -1, result->d_name,
3477 sizeof(result->d_name), NULL, NULL);
3479 if (!FindNextFileW(dir->handle, &dir->info)) {
3480 (void) FindClose(dir->handle);
3481 dir->handle = INVALID_HANDLE_VALUE;
3485 SetLastError(ERROR_FILE_NOT_FOUND);
3488 SetLastError(ERROR_BAD_ARGUMENTS);
3493 #endif // _WIN32 POSIX opendir/closedir/readdir implementation 3500 int arr_size = 0, arr_ind = 0, inc = 100;
3504 if ((dirp = (opendir(dir))) == NULL)
return 0;
3506 while ((dp = readdir(dirp)) != NULL) {
3508 if (!strcmp(dp->d_name,
".") ||
3509 !strcmp(dp->d_name,
"..") ||
3513 mg_snprintf(path,
sizeof(path),
"%s%c%s", dir,
'/', dp->d_name);
3516 if (arr_ind >= arr_size) {
3518 NS_REALLOC(*arr, (inc + arr_size) *
sizeof(**arr))) != NULL) {
3522 memset(p + arr_size, 0,
sizeof(**arr) * inc);
3529 if (arr_ind < arr_size) {
3530 (*arr)[arr_ind].conn = conn;
3531 (*arr)[arr_ind].file_name =
strdup(dp->d_name);
3532 stat(path, &(*arr)[arr_ind].st);
3541 size_t mg_url_encode(
const char *src,
size_t s_len,
char *dst,
size_t dst_len) {
3542 static const char *dont_escape =
"._-$,;~()";
3543 static const char *hex =
"0123456789abcdef";
3544 size_t i = 0,
j = 0;
3546 for (i =
j = 0; dst_len > 0 && i < s_len &&
j + 2 < dst_len - 1; i++,
j++) {
3547 if (isalnum(* (
const unsigned char *) (src + i)) ||
3548 strchr(dont_escape, * (
const unsigned char *) (src + i)) != NULL) {
3550 }
else if (
j + 3 < dst_len) {
3552 dst[
j + 1] = hex[(* (
const unsigned char *) (src + i)) >> 4];
3553 dst[
j + 2] = hex[(* (
const unsigned char *) (src + i)) & 0xf];
3561 #endif // !NO_DIRECTORY_LISTING || !MONGOOSE_NO_DAV 3563 #ifndef MONGOOSE_NO_DIRECTORY_LISTING 3567 int64_t fsize = de->
st.st_size;
3568 int is_dir = S_ISDIR(de->
st.st_mode);
3569 const char *slash = is_dir ?
"/" :
"";
3573 mg_snprintf(size,
sizeof(size),
"%s",
"[DIRECTORY]");
3578 mg_snprintf(size,
sizeof(size),
"%d", (
int) fsize);
3579 }
else if (fsize < 0x100000) {
3580 mg_snprintf(size,
sizeof(size),
"%.1fk", (
double) fsize / 1024.0);
3581 }
else if (fsize < 0x40000000) {
3582 mg_snprintf(size,
sizeof(size),
"%.1fM", (
double) fsize / 1048576);
3584 mg_snprintf(size,
sizeof(size),
"%.1fG", (
double) fsize / 1073741824);
3587 t = de->
st.st_mtime;
3588 strftime(mod,
sizeof(mod),
"%d-%b-%Y %H:%M", localtime(&t));
3591 "<tr><td><a href=\"%s%s\">%s%s</a></td>" 3592 "<td> %s</td><td> %s</td></tr>\n",
3593 href, slash, de->
file_name, slash, mod, size);
3606 if (S_ISDIR(a->
st.st_mode) && !S_ISDIR(b->st.st_mode)) {
3608 }
else if (!S_ISDIR(a->
st.st_mode) && S_ISDIR(b->st.st_mode)) {
3610 }
else if (*qs ==
'n') {
3611 cmp_result = strcmp(a->
file_name, b->file_name);
3612 }
else if (*qs ==
's') {
3613 cmp_result = a->
st.st_size == b->st.st_size ? 0 :
3614 a->
st.st_size > b->st.st_size ? 1 : -1;
3615 }
else if (*qs ==
'd') {
3616 cmp_result = a->
st.st_mtime == b->st.st_mtime ? 0 :
3617 a->
st.st_mtime > b->st.st_mtime ? 1 : -1;
3620 return qs[1] ==
'd' ? -cmp_result : cmp_result;
3632 "<html><head><title>Index of %s</title>" 3633 "<style>th {text-align: left;}</style></head>" 3634 "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">" 3635 "<tr><th><a href=\"?n%c\">Name</a></th>" 3636 "<th><a href=\"?d%c\">Modified</a></th>" 3637 "<th><a href=\"?s%c\">Size</a></th></tr>" 3638 "<tr><td colspan=\"3\"><hr></td></tr>",
3640 sort_direction, sort_direction, sort_direction);
3645 for (i = 0; i < num_entries; i++) {
3655 #endif // MONGOOSE_NO_DIRECTORY_LISTING 3657 #ifndef MONGOOSE_NO_DAV 3661 time_t
t = stp->st_mtime;
3665 "<d:href>%s</d:href>" 3668 "<d:resourcetype>%s</d:resourcetype>" 3669 "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>" 3670 "<d:getlastmodified>%s</d:getlastmodified>" 3672 "<d:status>HTTP/1.1 200 OK</d:status>" 3675 uri, S_ISDIR(stp->st_mode) ?
"<d:collection/>" :
"",
3676 (int64_t) stp->st_size, mtime);
3680 file_stat_t *stp,
int exists) {
3681 static const char header[] =
"HTTP/1.1 207 Multi-Status\r\n" 3682 "Connection: close\r\n" 3683 "Content-Type: text/xml; charset=utf-8\r\n\r\n" 3684 "<?xml version=\"1.0\" encoding=\"utf-8\"?>" 3685 "<d:multistatus xmlns:d='DAV:'>\n";
3686 static const char footer[] =
"</d:multistatus>";
3688 #ifdef MONGOOSE_NO_DIRECTORY_LISTING 3689 const char *list_dir =
"no";
3700 }
else if (S_ISDIR(stp->st_mode) &&
mg_strcasecmp(list_dir,
"yes") != 0) {
3703 "HTTP/1.1 403 Directory Listing Denied\r\n\r\n");
3708 if (S_ISDIR(stp->st_mode) &&
3709 (depth == NULL || strcmp(depth,
"0") != 0)) {
3713 for (i = 0; i < num_entries; i++) {
3729 int status_code = 500;
3733 }
else if (!mkdir(path, 0755)) {
3735 }
else if (errno == EEXIST) {
3737 }
else if (errno == EACCES) {
3739 }
else if (errno == ENOENT) {
3751 if ((dirp = opendir(dir)) == NULL)
return 0;
3753 while ((dp = readdir(dirp)) != NULL) {
3754 if (!strcmp(dp->d_name,
".") || !strcmp(dp->d_name,
".."))
continue;
3755 mg_snprintf(path,
sizeof(path),
"%s%c%s", dir,
'/', dp->d_name);
3757 if (S_ISDIR(st.st_mode)) {
3772 if (
stat(path, &st) != 0) {
3774 }
else if (S_ISDIR(st.st_mode)) {
3777 }
else if (
remove(path) == 0) {
3793 for (s = p = path + 1; (p = strchr(s,
'/')) != NULL; s = ++
p) {
3794 if (p - path >= (
int)
sizeof(
buf))
return -1;
3795 memcpy(buf, path, p - path);
3796 buf[p -
path] =
'\0';
3797 if (
stat(buf, &st) != 0 && mkdir(buf, 0755) != 0)
return -1;
3798 if (p[1] ==
'\0')
return 0;
3811 if ((rc =
put_dir(path)) == 0) {
3815 }
else if (rc == -1) {
3817 }
else if (cl_hdr == NULL) {
3820 open(path, O_RDWR | O_CREAT | O_TRUNC |
O_BINARY, 0644)) < 0) {
3832 conn->
cl = r2 > r1 ? r2 - r1 + 1: conn->
cl - r1;
3841 size_t k = conn->
cl < (int64_t) io->
len ? conn->
cl : (int64_t) io->
len;
3847 if (conn->
cl <= 0) {
3851 #endif // MONGOOSE_NO_DAV 3856 "HTTP/1.1 200 OK\r\nAllow: GET, POST, HEAD, CONNECT, PUT, " 3857 "DELETE, OPTIONS, PROPFIND, MKCOL\r\nDAV: 1\r\n\r\n");
3861 #ifndef MONGOOSE_NO_AUTH 3866 "HTTP/1.1 401 Unauthorized\r\n" 3867 "Content-Length: 0\r\n" 3868 "WWW-Authenticate: Digest qop=\"auth\", " 3869 "realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
3871 (
unsigned long) time(NULL));
3883 if (gpass != NULL) {
3885 fp = fopen(gpass,
"r");
3886 }
else if (is_directory) {
3888 fp = fopen(name,
"r");
3891 if ((p = strrchr(path,
'/')) == NULL) p =
path;
3894 fp = fopen(name,
"r");
3900 #if !defined(HAVE_MD5) && !defined(MONGOOSE_NO_AUTH) 3921 unsigned char in[64];
3930 t = (uint32_t) ((
unsigned) buf[3] << 8 | buf[2]) << 16 |
3931 ((
unsigned) buf[1] << 8 | buf[0]);
3932 * (uint32_t *) buf = t;
3938 #define F1(x, y, z) (z ^ (x & (y ^ z))) 3939 #define F2(x, y, z) F1(z, x, y) 3940 #define F3(x, y, z) (x ^ y ^ z) 3941 #define F4(x, y, z) (y ^ (x | ~z)) 3943 #define MD5STEP(f, w, x, y, z, data, s) \ 3944 ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) 3949 ctx->buf[0] = 0x67452301;
3950 ctx->buf[1] = 0xefcdab89;
3951 ctx->buf[2] = 0x98badcfe;
3952 ctx->buf[3] = 0x10325476;
3959 register uint32_t
a, b, c,
d;
3966 MD5STEP(
F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3967 MD5STEP(
F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3968 MD5STEP(
F1, c, d, a, b, in[2] + 0x242070db, 17);
3969 MD5STEP(
F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3970 MD5STEP(
F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3971 MD5STEP(
F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3972 MD5STEP(
F1, c, d, a, b, in[6] + 0xa8304613, 17);
3973 MD5STEP(
F1, b, c, d, a, in[7] + 0xfd469501, 22);
3974 MD5STEP(
F1, a, b, c, d, in[8] + 0x698098d8, 7);
3975 MD5STEP(
F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3976 MD5STEP(
F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3977 MD5STEP(
F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3978 MD5STEP(
F1, a, b, c, d, in[12] + 0x6b901122, 7);
3979 MD5STEP(
F1, d, a, b, c, in[13] + 0xfd987193, 12);
3980 MD5STEP(
F1, c, d, a, b, in[14] + 0xa679438e, 17);
3981 MD5STEP(
F1, b, c, d, a, in[15] + 0x49b40821, 22);
3983 MD5STEP(
F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3984 MD5STEP(
F2, d, a, b, c, in[6] + 0xc040b340, 9);
3985 MD5STEP(
F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3986 MD5STEP(
F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3987 MD5STEP(
F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3988 MD5STEP(
F2, d, a, b, c, in[10] + 0x02441453, 9);
3989 MD5STEP(
F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3990 MD5STEP(
F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3991 MD5STEP(
F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3992 MD5STEP(
F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3993 MD5STEP(
F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3994 MD5STEP(
F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3995 MD5STEP(
F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3996 MD5STEP(
F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3997 MD5STEP(
F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3998 MD5STEP(
F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
4000 MD5STEP(
F3, a, b, c, d, in[5] + 0xfffa3942, 4);
4001 MD5STEP(
F3, d, a, b, c, in[8] + 0x8771f681, 11);
4002 MD5STEP(
F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
4003 MD5STEP(
F3, b, c, d, a, in[14] + 0xfde5380c, 23);
4004 MD5STEP(
F3, a, b, c, d, in[1] + 0xa4beea44, 4);
4005 MD5STEP(
F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
4006 MD5STEP(
F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
4007 MD5STEP(
F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
4008 MD5STEP(
F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
4009 MD5STEP(
F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
4010 MD5STEP(
F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
4011 MD5STEP(
F3, b, c, d, a, in[6] + 0x04881d05, 23);
4012 MD5STEP(
F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
4013 MD5STEP(
F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
4014 MD5STEP(
F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
4015 MD5STEP(
F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
4017 MD5STEP(
F4, a, b, c, d, in[0] + 0xf4292244, 6);
4018 MD5STEP(
F4, d, a, b, c, in[7] + 0x432aff97, 10);
4019 MD5STEP(
F4, c, d, a, b, in[14] + 0xab9423a7, 15);
4020 MD5STEP(
F4, b, c, d, a, in[5] + 0xfc93a039, 21);
4021 MD5STEP(
F4, a, b, c, d, in[12] + 0x655b59c3, 6);
4022 MD5STEP(
F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
4023 MD5STEP(
F4, c, d, a, b, in[10] + 0xffeff47d, 15);
4024 MD5STEP(
F4, b, c, d, a, in[1] + 0x85845dd1, 21);
4025 MD5STEP(
F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
4026 MD5STEP(
F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
4027 MD5STEP(
F4, c, d, a, b, in[6] + 0xa3014314, 15);
4028 MD5STEP(
F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
4029 MD5STEP(
F4, a, b, c, d, in[4] + 0xf7537e82, 6);
4030 MD5STEP(
F4, d, a, b, c, in[11] + 0xbd3af235, 10);
4031 MD5STEP(
F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
4032 MD5STEP(
F4, b, c, d, a, in[9] + 0xeb86d391, 21);
4044 if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
4046 ctx->bits[1] += len >> 29;
4048 t = (t >> 3) & 0x3f;
4051 unsigned char *p = (
unsigned char *) ctx->in + t;
4066 memcpy(ctx->in, buf, 64);
4073 memcpy(ctx->in, buf, len);
4081 count = (ctx->bits[0] >> 3) & 0x3F;
4083 p = ctx->in + count;
4085 count = 64 - 1 - count;
4087 memset(p, 0, count);
4090 memset(ctx->in, 0, 56);
4092 memset(p, 0, count - 8);
4096 a = (uint32_t *)ctx->in;
4097 a[14] = ctx->bits[0];
4098 a[15] = ctx->bits[1];
4102 memcpy(digest, ctx->buf, 16);
4103 memset((
char *) ctx, 0,
sizeof(*ctx));
4111 static void bin2str(
char *to,
const unsigned char *p,
size_t len) {
4112 static const char *hex =
"0123456789abcdef";
4114 for (; len--; p++) {
4115 *to++ = hex[p[0] >> 4];
4116 *to++ = hex[p[0] & 0x0f];
4123 unsigned char hash[16];
4131 while ((p = va_arg(ap,
const char *)) != NULL) {
4132 MD5Update(&ctx, (
const unsigned char *) p, (
unsigned) strlen(p));
4137 bin2str(buf, hash,
sizeof(hash));
4143 const char *nonce,
const char *nc,
const char *cnonce,
4144 const char *qop,
const char *response) {
4145 char ha2[32 + 1], expected_response[32 + 1];
4149 if ((
unsigned long) time(NULL) - (
unsigned long)
to64(nonce) > 3600 * 2) {
4154 mg_md5(ha2, method,
":", uri, NULL);
4155 mg_md5(expected_response, ha1,
":", nonce,
":", nc,
4156 ":", cnonce,
":", qop,
":", ha2, NULL);
4166 char line[256], f_user[256], ha1[256], f_domain[256], user[100], nonce[100],
4169 if (c == NULL || fp == NULL)
return 0;
4173 if (!
mg_parse_header(hdr,
"cnonce", cnonce,
sizeof(cnonce)))
return 0;
4180 while (fgets(line,
sizeof(line), fp) != NULL) {
4181 if (sscanf(line,
"%[^:]:%[^:]:%s", f_user, f_domain, ha1) == 3 &&
4182 !strcmp(user, f_user) &&
4186 nonce, nc, cnonce, qop, resp);
4213 if (method != NULL && !strcmp(method,
"PROPFIND") && auth_file == NULL) {
4215 }
else if (auth_file != NULL && (fp = fopen(auth_file,
"r")) != NULL) {
4222 #endif // MONGOOSE_NO_AUTH 4225 char *
buf,
size_t buf_size) {
4226 int ch =
' ', ch1 =
',', len = 0;
4227 size_t n = strlen(var_name);
4228 const char *
p, *end = str + str_len, *
s = NULL;
4230 if (buf != NULL && buf_size > 0) buf[0] =
'\0';
4233 for (s = str; s != NULL && s + n < end; s++) {
4234 if ((s == str || s[-1] == ch || s[-1] == ch1) && s[n] ==
'=' &&
4235 !memcmp(s, var_name, n))
break;
4238 if (s != NULL && &s[n + 1] < end) {
4240 if (*s ==
'"' || *s ==
'\'') ch = ch1 = *s++;
4242 while (p < end && p[0] != ch && p[0] != ch1 && len < (
int) buf_size) {
4243 if (ch == ch1 && p[0] ==
'\\' && p[1] == ch) p++;
4246 if (len >= (
int) buf_size || (ch !=
' ' && *p != ch)) {
4249 if (len > 0 && s[len - 1] ==
',') len--;
4250 if (len > 0 && s[len - 1] ==
';') len--;
4260 return parse_header(s, s == NULL ? 0 : strlen(s), var_name, buf, buf_size);
4263 #ifndef MONGOOSE_NO_SSI 4269 while ((n =
fread(buf, 1,
sizeof(buf), fp)) > 0) {
4275 char *tag,
int include_level) {
4282 if (sscanf(tag,
" virtual=\"%[^\"]\"", file_name) == 1) {
4286 }
else if (sscanf(tag,
" abspath=\"%[^\"]\"", file_name) == 1) {
4290 }
else if (sscanf(tag,
" file=\"%[^\"]\"", file_name) == 1 ||
4291 sscanf(tag,
" \"%[^\"]\"", file_name) == 1) {
4294 if ((p = strrchr(path,
'/')) != NULL) {
4297 mg_snprintf(path + strlen(path),
sizeof(path) - strlen(path),
"%s",
4300 mg_printf(conn,
"Bad SSI #include: [%s]", tag);
4304 if ((fp = fopen(path,
"rb")) == NULL) {
4305 mg_printf(conn,
"Cannot open SSI #include: [%s]: fopen(%s): %s",
4306 tag, path, strerror(errno));
4319 #ifndef MONGOOSE_NO_POPEN 4324 if (sscanf(tag,
" \"%[^\"]\"", cmd) != 1) {
4325 mg_printf(conn,
"Bad SSI #exec: [%s]", tag);
4326 }
else if ((fp = popen(cmd,
"r")) == NULL) {
4327 mg_printf(conn,
"Cannot SSI #exec: [%s]: %s", cmd, strerror(errno));
4333 #endif // !MONGOOSE_NO_POPEN 4336 FILE *fp,
int include_level) {
4338 int ch, offset,
len, in_ssi_tag;
4340 if (include_level > 10) {
4341 mg_printf(conn,
"SSI #include level is too deep (%s)", path);
4345 in_ssi_tag = len = offset = 0;
4346 while ((ch = fgetc(fp)) != EOF) {
4347 if (in_ssi_tag && ch ==
'>') {
4349 buf[len++] = (char) ch;
4351 assert(len <= (
int)
sizeof(buf));
4352 if (len < 6 || memcmp(buf,
"<!--#", 5) != 0) {
4356 if (!memcmp(buf + 5,
"include", 7)) {
4358 #if !defined(MONGOOSE_NO_POPEN) 4359 }
else if (!memcmp(buf + 5,
"exec", 4)) {
4363 mg_printf(conn,
"%s: unknown SSI " "command: \"%s\"", path, buf);
4367 }
else if (in_ssi_tag) {
4368 if (len == 5 && memcmp(buf,
"<!--#", 5) != 0) {
4371 }
else if (len == (
int)
sizeof(buf) - 2) {
4372 mg_printf(conn,
"%s: SSI tag is too large", path);
4375 buf[len++] = ch & 0xff;
4376 }
else if (ch ==
'<') {
4382 buf[len++] = ch & 0xff;
4384 buf[len++] = ch & 0xff;
4385 if (len == (
int)
sizeof(buf)) {
4400 struct vec mime_vec;
4402 if ((fp = fopen(path,
"rb")) == NULL) {
4409 "HTTP/1.1 %d OK\r\n" 4410 "Content-Type: %.*s\r\n" 4411 "Connection: close\r\n\r\n",
4421 int i, sent_close_header = 0;
4431 ns_printf(pc,
"%s: %s\r\n",
"Connection",
"close");
4432 sent_close_header = 1;
4438 if (!sent_close_header) {
4439 ns_printf(pc,
"%s: %s\r\n",
"Connection",
"close");
4446 #ifdef NS_ENABLE_SSL 4448 static const char ok[] =
"HTTP/1.0 200 OK\r\n\r\n";
4452 DBG((
"%p MITM", conn));
4453 if ((ctx =
SSL_CTX_new(SSLv23_server_method())) == NULL)
return 0;
4457 SSL_CTX_use_certificate_chain_file(ctx, cert);
4475 static const char ok[] =
"HTTP/1.1 200 OK\r\n\r\n";
4489 DBG((
"%p [%s] [%s] -> %p %p", conn, c->
uri, addr, pc, conn->
ns_conn->
ssl));
4494 (void) send(conn->
ns_conn->
sock, ok,
sizeof(ok) - 1, 0);
4497 if (memcmp(c->
uri,
"http://", 7) == 0) c->
uri += 7;
4498 while (*c->
uri !=
'\0' && *c->
uri !=
'/') c->
uri++;
4505 char proto[10], host[500], cert[500], addr[1000];
4506 unsigned short port = 80;
4509 const char *url = c->
uri;
4511 proto[0] = host[0] = cert[0] =
'\0';
4512 if (sscanf(url,
"%499[^: ]:%hu%n", host, &port, &n) != 2 &&
4513 sscanf(url,
"%9[a-z]://%499[^: ]:%hu%n", proto, host, &port, &n) != 3 &&
4514 sscanf(url,
"%9[a-z]://%499[^/ ]%n", proto, host, &n) != 2) {
4518 snprintf(addr,
sizeof(addr),
"%s://%s:%hu",
4519 conn->
ns_conn->
ssl != NULL ?
"ssl" :
"tcp", host, port);
4525 #ifndef MONGOOSE_NO_FILESYSTEM 4527 file_stat_t *st,
int exists,
4528 const char *extra_headers) {
4531 const int is_directory = S_ISDIR(st->st_mode);
4532 #ifndef MONGOOSE_NO_CGI 4537 #ifndef MONGOOSE_NO_DIRECTORY_LISTING 4540 const char *dir_lst =
"yes";
4547 }
else if (is_directory &&
4553 }
else if (is_directory && !
find_index_file(conn, path,
sizeof(path), st)) {
4555 #ifndef MONGOOSE_NO_DIRECTORY_LISTING 4564 #if !defined(MONGOOSE_NO_CGI) 4568 #endif // !MONGOOSE_NO_CGI 4569 #ifndef MONGOOSE_NO_SSI 4586 const char *extra_headers) {
4588 const int exists =
stat(file_name, &st) == 0;
4591 #endif // !MONGOOSE_NO_FILESYSTEM 4594 #ifndef MONGOOSE_NO_FILESYSTEM 4603 #ifndef MONGOOSE_NO_AUTH 4613 #if MONGOOSE_POST_SIZE_LIMIT > 1 4630 if (enp == NULL || strcmp(enp,
"yes") != 0) {
4643 #ifdef MONGOOSE_NO_FILESYSTEM 4652 #ifndef MONGOOSE_NO_AUTH 4654 exists && S_ISDIR(st.st_mode))) ||
4659 #ifndef MONGOOSE_NO_DAV 4674 #endif // MONGOOSE_NO_FILESYSTEM 4678 static const char expect_response[] =
"HTTP/1.1 100 Continue\r\n\r\n";
4681 if (expect_hdr != NULL && !
mg_strcasecmp(expect_hdr,
"100-continue")) {
4682 ns_send(conn->
ns_conn, expect_response,
sizeof(expect_response) - 1);
4689 return uri[0] ==
'/' ||
4690 strcmp(uri,
"*") == 0 ||
4692 sscanf(uri,
"%*[^ :]:%hu", &n) > 0;
4715 conn->
cl = cl_hdr == NULL ? 0 :
to64(cl_hdr);
4731 DBG((
"%p forwarding", conn));
4758 #ifndef MONGOOSE_NO_WEBSOCKET 4765 #ifndef MONGOOSE_NO_CGI 4776 }
else if ((
size_t) n <= io->len) {
4781 #ifndef MONGOOSE_NO_DAV 4791 if (conn->
cl == 0) {
4813 }
else if ((int64_t) io->
len >= conn->
cl) {
4823 if (nsconn == NULL)
return 0;
4843 #ifndef MONGOOSE_NO_LOGGING 4846 const char *header_value;
4849 (void)
fprintf(fp,
"%s",
" -");
4851 (void)
fprintf(fp,
" \"%s\"", header_value);
4857 FILE *fp = (path == NULL) ? NULL : fopen(path,
"a+");
4858 char date[64], user[100];
4861 if (fp == NULL)
return;
4863 strftime(date,
sizeof(date),
"%d/%b/%Y:%H:%M:%S %z", localtime(&now));
4867 user,
sizeof(user));
4868 fprintf(fp,
"%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d 0",
4869 c->
remote_ip, user[0] ==
'\0' ?
"-" : user, date,
4908 #ifndef MONGOOSE_NO_LOGGING 4951 n = read(conn->
endpoint.
fd, buf, conn->
cl < (int64_t)
sizeof(buf) ?
4952 (
int) conn->
cl : (
int)
sizeof(buf));
4959 if (conn->
cl <= 0) {
4970 if (server != NULL && *server != NULL) {
4986 if (nc != NULL && nc->
user_data != NULL) {
4993 static int get_var(
const char *data,
size_t data_len,
const char *name,
4994 char *dst,
size_t dst_len) {
4995 const char *
p, *e, *
s;
4999 if (dst == NULL || dst_len == 0) {
5001 }
else if (data == NULL || name == NULL || data_len == 0) {
5005 name_len = strlen(name);
5006 e = data + data_len;
5011 for (p = data; p + name_len < e; p++) {
5012 if ((p == data || p[-1] ==
'&') && p[name_len] ==
'=' &&
5019 s = (
const char *) memchr(p,
'&', (
size_t)(e -
p));
5041 char *dst,
size_t dst_len) {
5052 while (len < buf_len && buf[len] !=
'\n') len++;
5053 return buf[
len] ==
'\n' ? len + 1: -1;
5057 char *var_name,
int var_name_len,
5058 char *file_name,
int file_name_len,
5059 const char **data,
int *data_len) {
5060 static const char cd[] =
"Content-Disposition: ";
5062 int hl, bl, n, ll, pos, cdl =
sizeof(cd) - 1;
5065 if (buf == NULL || buf_len <= 0)
return 0;
5067 if (buf[0] !=
'-' || buf[1] !=
'-' || buf[2] ==
'\n')
return 0;
5073 var_name[0] = file_name[0] =
'\0';
5074 for (n = bl; (ll =
get_line_len(buf + n, hl - n)) > 0; n += ll) {
5077 var_name, var_name_len);
5078 parse_header(buf + n + cdl, ll - (cdl + 2),
"filename",
5079 file_name, file_name_len);
5084 for (pos = hl; pos + (bl - 2) < buf_len; pos++) {
5085 if (buf[pos] ==
'-' && !memcmp(buf, &buf[pos], bl - 2)) {
5086 if (data_len != NULL) *data_len = (pos - 2) - hl;
5087 if (data != NULL) *data = buf + hl;
5105 memcpy(tmp, c,
sizeof(*tmp));
5107 #if defined(NS_ENABLE_SSL) && defined(HEADER_SSL_H) 5123 for (i = 0; static_config_options[i * 2] != NULL; i++) {
5124 if (strcmp(static_config_options[i * 2], name) == 0) {
5135 for (i = 0; all_opts[i * 2] != NULL; i++) {
5136 value = all_opts[i * 2 + 1];
5137 if (opts[i] == NULL && value != NULL) {
5144 const char *
value) {
5146 const char *error_msg = NULL;
5149 if (ind < 0)
return "No such option";
5153 if ((*v == NULL && value == NULL) ||
5154 (value != NULL && *v != NULL && !strcmp(value, *v))) {
5163 if (value == NULL || value[0] ==
'\0')
return NULL;
5166 DBG((
"%s [%s]", name, *v));
5178 while ((value =
next_option(value, &vec, NULL)) != NULL) {
5182 error_msg =
"Cannot bind to port";
5185 char buf2[50], cert[100], ca[100];
5191 memchr(vec.
ptr,
':', vec.
len) == NULL ? 2 : 3);
5193 n +=
snprintf(buf + n,
sizeof(buf) - n,
"%s%s%s%s%s%s%s",
5195 use_ssl ?
"ssl://" :
"",
5196 buf2, cert[0] ?
":" :
"", cert, ca[0] ?
":" :
"", ca);
5199 buf[
sizeof(
buf) - 1] =
'\0';
5202 #ifndef MONGOOSE_NO_FILESYSTEM 5206 #if !defined(_WIN32) && !defined(MONGOOSE_NO_USER) 5209 if ((pw = getpwnam(value)) == NULL) {
5210 error_msg =
"Unknown user";
5211 }
else if (setgid(pw->pw_gid) != 0) {
5212 error_msg =
"setgid() failed";
5213 }
else if (setuid(pw->pw_uid) != 0) {
5214 error_msg =
"setuid() failed";
5228 sscanf(
buf,
"%47[^:]:%hu",
5239 ntohl(* (uint32_t *) &sa->
sin.sin_addr)) ||
5259 memset(&conn, 0,
sizeof(conn));
5272 #ifdef MONGOOSE_SEND_NS_EVENTS
5275 void *
param[2] = { nc, p };
5284 #ifdef MONGOOSE_SEND_NS_EVENTS 5287 void *
param[2] = { nc, p };
5288 if (conn != NULL) conn->mg_conn.callback_param =
param;
5295 if (nc->user_data != NULL) {
5299 conn->mg_conn.status_code = * (
int *) p;
5300 if (conn->mg_conn.status_code != 0 ||
5309 conn->num_bytes_recv += * (
int *) p;
5314 }
else if (nc->listener != NULL) {
5316 #ifndef MONGOOSE_NO_CGI 5333 nc->user_data = NULL;
5335 DBG((
"%p %p closing cgi/proxy conn", conn, nc));
5336 if (conn && conn->ns_conn) {
5340 conn->endpoint.nc = NULL;
5342 }
else if (conn != NULL) {
5343 DBG((
"%p %p %d closing", conn, nc, conn->endpoint_type));
5345 if (conn->endpoint_type ==
EP_CLIENT && nc->recv_iobuf.len > 0) {
5351 conn->ns_conn = NULL;
5365 if (conn->endpoint_type ==
EP_FILE) {
5372 time_t current_time = * (time_t *) p;
5374 if (conn != NULL && conn->mg_conn.is_websocket) {
5378 if (nc->listener != NULL &&
5394 const char *msg = (
const char *) param;
5399 if (sscanf(msg,
"%p %n", &func, &n) && func != NULL && conn != NULL) {
5406 const char *fmt, ...) {
5412 len =
snprintf(buf,
sizeof(buf),
"%p ", cb);
5414 len +=
vsnprintf(buf + len,
sizeof(buf) - len, fmt, ap);
5428 return i == -1 ? NULL : opts[
i] == NULL ?
"" : opts[
i];
static void ns_remove_conn(struct ns_connection *conn)
size_t iobuf_append(struct iobuf *, const void *data, size_t data_size)
static void write_terminating_chunk(struct connection *conn)
static int scan_directory(struct connection *conn, const char *dir, struct dir_entry **arr)
struct mg_server * server
static const char cgi_status[]
static int is_authorized(struct connection *conn, const char *path, int is_directory)
#define R3(v, w, x, y, z, i)
struct mg_connection::mg_header http_headers[30]
static const struct @51 static_builtin_mime_types[]
static void handle_propfind(struct connection *conn, const char *path, file_stat_t *stp, int exists)
int mg_get_var(const struct mg_connection *conn, const char *name, char *dst, size_t dst_len)
void mg_send_header(struct mg_connection *c, const char *name, const char *v)
static void send_directory_listing(struct connection *conn, const char *dir)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val)
#define ENV_EXPORT_TO_CGI
struct ns_connection * ns_add_sock(struct ns_mgr *, sock_t, ns_callback_t, void *)
static FILE * open_auth_file(struct connection *conn, const char *path, int is_directory)
#define MG_USING_CHUNKED_API
static int is_big_endian(void)
struct mg_connection * mg_next(struct mg_server *s, struct mg_connection *c)
int mg_terminate_ssl(struct mg_connection *c, const char *cert)
char buf[CGI_ENVIRONMENT_SIZE]
#define MAX_CGI_ENVIR_VARS
static char * addenv(struct cgi_env_block *block, const char *fmt,...)
static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
static void handle_delete(struct connection *conn, const char *path)
static int get_option_index(const char *name)
int ns_vprintf(struct ns_connection *, const char *fmt, va_list ap)
static void handle_mkcol(struct connection *conn, const char *path)
static void base64_encode(const unsigned char *src, int src_len, char *dst)
static void do_proxy(struct connection *conn)
static void close_local_endpoint(struct connection *conn)
static void log_header(const struct mg_connection *conn, const char *header, FILE *fp)
#define CGI_ENVIRONMENT_SIZE
void * mg_start_thread(void *(*func)(void *), void *param)
static void remove_double_dots_and_double_slashes(char *s)
static void print_props(struct connection *conn, const char *uri, file_stat_t *stp)
static void send_websocket_handshake(struct mg_connection *conn, const char *key)
static int lowercase(const char *s)
int stat(const char *path, struct stat *buffer)
static void send_options(struct connection *conn)
int(* mg_handler_t)(struct mg_connection *, enum mg_event)
struct ns_connection * ns_bind(struct ns_mgr *, const char *, ns_callback_t, void *)
static int mg_strncasecmp(const char *s1, const char *s2, size_t len)
#define NSF_FINISHED_SENDING_DATA
static void forward_put_data(struct connection *conn)
static struct ns_connection * accept_conn(struct ns_connection *ls)
static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
static size_t ns_out(struct ns_connection *nc, const void *buf, size_t len)
void ns_set_close_on_exec(sock_t)
static process_id_t start_process(const char *interp, const char *cmd, const char *env, const char *envp[], const char *dir, sock_t sock)
const char * mg_get_header(const struct mg_connection *ri, const char *s)
size_t mg_websocket_write(struct mg_connection *conn, int opcode, const char *data, size_t data_len)
static void ns_handle_udp(struct ns_connection *ls)
struct ns_connection * active_connections
static void send_file_data(struct mg_connection *conn, FILE *fp)
static void on_accept(struct ns_connection *nc, union socket_address *sa)
const char * vars[MAX_CGI_ENVIR_VARS]
size_t mg_websocket_printf(struct mg_connection *conn, int opcode, const char *fmt,...)
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
static int num_leap_years(int year)
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
void iobuf_free(struct iobuf *)
const char * mg_get_mime_type(const char *path, const char *default_mime_type)
static void transfer_file_data(struct connection *conn)
char * mg_md5(char buf[33],...)
#define NSF_CLOSE_IMMEDIATELY
static int convert_uri_to_file_name(struct connection *conn, char *buf, size_t buf_len, file_stat_t *st)
const char * hexdump_file
struct mg_server * mg_create_server(void *server_data, mg_handler_t handler)
static int mg_strcasecmp(const char *s1, const char *s2)
static int call_user(struct connection *conn, enum mg_event ev)
struct mg_connection mg_conn
const char * mg_get_option(const struct mg_server *server, const char *name)
#define MONGOOSE_POST_SIZE_LIMIT
#define SSL_CTX_use_PrivateKey_file
if(strcmp(arg,"1305")!=0)
const char ** mg_get_valid_option_names(void)
static void byteReverse(unsigned char *buf, unsigned longs)
void mg_send_status(struct mg_connection *c, int status)
static void SHA1Update(SHA1_CTX *context, const unsigned char *data, size_t len)
static void ns_write_to_socket(struct ns_connection *conn)
static void log_access(const struct connection *conn, const char *path)
#define NS_UDP_RECEIVE_BUFFER_SIZE
#define SSL_CTX_load_verify_locations
void iobuf_resize(struct iobuf *, size_t new_size)
geometry_msgs::TransformStamped t
static void ping_idle_websocket_connection(struct connection *conn, time_t t)
static void MD5Init(MD5_CTX *ctx)
static void ns_set_non_blocking_mode(sock_t sock)
UNITTEST_START int result
size_t mg_write(struct mg_connection *c, const void *buf, size_t len)
static int check_password(const char *method, const char *ha1, const char *uri, const char *nonce, const char *nc, const char *cnonce, const char *qop, const char *response)
#define DEFAULT_CGI_PATTERN
void mg_copy_listeners(struct mg_server *s, struct mg_server *to)
int ns_send(struct ns_connection *, const void *buf, size_t len)
static void ns_add_conn(struct ns_mgr *mgr, struct ns_connection *c)
static int call_request_handler(struct connection *conn)
static void get_mime_type(const struct mg_server *server, const char *path, struct vec *vec)
static srvr_sockaddr_union_t from
static void ns_destroy_conn(struct ns_connection *conn)
static int get_request_len(const char *s, size_t buf_len)
void ns_mgr_init(struct ns_mgr *, void *user_data)
static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
#define MONGOOSE_USE_EXTRA_HTTP_HEADERS
static int is_valid_http_method(const char *s)
static int should_keep_alive(const struct mg_connection *conn)
static int must_hide_file(struct connection *conn, const char *path)
int ns_socketpair(sock_t[2])
static void ns_add_to_set(sock_t sock, fd_set *set, sock_t *max_fd)
void iobuf_remove(struct iobuf *, size_t data_size)
time_t mg_poll_server(struct mg_server *server, int milliseconds)
static uint32_t blk0(union char64long16 *block, int i)
int mg_parse_header(const char *s, const char *var_name, char *buf, size_t buf_size)
void ns_broadcast(struct ns_mgr *, ns_callback_t, void *, size_t)
struct ns_connection * listener
static int find_index_file(struct connection *conn, char *path, size_t path_len, file_stat_t *stp)
size_t mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len)
mg_handler_t event_handler
static void handle_ssi_request(struct connection *conn, const char *path)
memcpy(filename, filename1, strlen(filename1))
#define NS_READ_BUFFER_SIZE
#define R0(v, w, x, y, z, i)
void(* ns_callback_t)(struct ns_connection *, int event_num, void *evp)
static int get_line_len(const char *buf, int buf_len)
static char * mg_strdup(const char *str)
#define SSL_CTX_use_certificate_file
struct ns_connection * prev
static void open_cgi_endpoint(struct connection *conn, const char *prog)
static const char * status_code_to_str(int status_code)
#define MD5STEP(f, w, x, y, z, data, s)
static void SHA1Init(SHA1_CTX *context)
curl_easy_setopt expects a curl_off_t argument for this option curl_easy_setopt expects a curl_write_callback argument for this option curl_easy_setopt expects a curl_ioctl_callback argument for this option curl_easy_setopt expects a curl_opensocket_callback argument for this option curl_easy_setopt expects a curl_debug_callback argument for this option curl_easy_setopt expects a curl_conv_callback argument for this option curl_easy_setopt expects a private data pointer as argument for this option curl_easy_setopt expects a FILE *argument for this option curl_easy_setopt expects a struct curl_httppost *argument for this option curl_easy_setopt expects a struct curl_slist *argument for this option curl_easy_getinfo expects a pointer to char *for this info curl_easy_getinfo expects a pointer to double for this info curl_easy_getinfo expects a pointer to struct curl_tlssessioninfo *for this info curl_easy_getinfo expects a pointer to curl_socket_t for this info size_t
static int ns_is_error(int n)
static void ns_call(struct ns_connection *nc, int ev, void *p)
static void handle_put(struct connection *conn, const char *path)
void mg_template(struct mg_connection *conn, const char *s, struct mg_expansion *expansions)
size_t mg_printf_data(struct mg_connection *c, const char *fmt,...)
static void SHA1Final(unsigned char digest[20], SHA1_CTX *context)
static void send_continue_if_expected(struct connection *conn)
static int is_authorized_for_dav(struct connection *conn)
static const char * next_option(const char *list, struct vec *val, struct vec *eq_val)
int ns_avprintf(char **buf, size_t size, const char *fmt, va_list ap)
static void hexdump(struct ns_connection *nc, const char *path, int num_bytes, int ev)
static int check_acl(const char *acl, uint32_t remote_ip)
const char * query_string
static int get_month_index(const char *s)
struct ns_connection * ns_connect(struct ns_mgr *, const char *, ns_callback_t, void *)
#define R1(v, w, x, y, z, i)
UNITTEST_START struct Curl_easy data
static int remove_directory(const char *dir)
enum endpoint_type endpoint_type
static struct mg_server * server
static void on_cgi_data(struct ns_connection *nc)
void * ns_start_thread(void *(*f)(void *), void *p)
#define R4(v, w, x, y, z, i)
static int mg_snprintf(char *buf, size_t buflen, const char *fmt,...)
static void ns_forward(struct ns_connection *from, struct ns_connection *to)
#define MONGOOSE_USE_WEBSOCKET_PING_INTERVAL
#define SSL_CTX_set_verify
int ns_printf(struct ns_connection *, const char *fmt,...)
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
static int ns_resolve2(const char *host, struct in_addr *ina)
struct ns_connection * ns_next(struct ns_mgr *, struct ns_connection *)
static int mg_vsnprintf(char *buf, size_t buflen, const char *fmt, va_list ap)
struct ns_connection * ns_conn
static void ns_read_from_socket(struct ns_connection *conn)
struct mg_connection * conn
static void try_parse(struct connection *conn)
static void proxify_connection(struct connection *conn)
static void open_local_endpoint(struct connection *conn, int skip_user)
int ns_resolve(const char *domain_name, char *ip_addr_buf, size_t buf_len)
static void open_file_endpoint(struct connection *conn, const char *path, file_stat_t *st, const char *extra_headers)
char * config_options[NUM_OPTIONS]
static unsigned short port
static int parse_range_header(const char *header, int64_t *a, int64_t *b)
static void terminate_headers(struct mg_connection *c)
char message[NS_CTL_MSG_MESSAGE_SIZE]
static void call_request_handler_if_data_is_buffered(struct connection *conn)
struct mg_connection * mg_connect(struct mg_server *server, const char *addr)
static void bin2str(char *to, const unsigned char *p, size_t len)
#define R2(v, w, x, y, z, i)
static int __cdecl compare_dir_entries(const void *p1, const void *p2)
unsigned short local_port
void ns_sock_to_str(sock_t sock, char *buf, size_t len, int flags)
static void proxy_request(struct ns_connection *pc, struct mg_connection *c)
static void process_response(struct connection *conn)
#define ARRAY_SIZE(array)
int mg_authorize_digest(struct mg_connection *c, FILE *fp)
static void prepare_cgi_environment(struct connection *conn, const char *prog, struct cgi_env_block *blk)
static void process_udp(struct ns_connection *nc)
static int is_dav_request(const struct connection *conn)
#define NSF_BUFFER_BUT_DONT_SEND
static size_t parse_http_message(char *buf, size_t len, struct mg_connection *ri)
#define NS_VPRINTF_BUFFER_SIZE
void ns_mgr_free(struct ns_mgr *)
#define abs_path(rel, abs, abs_size)
void * mg_mmap(FILE *fp, size_t size)
static char * skip(char **buf, const char *delimiters)
#define PASSWORDS_FILE_NAME
int ns_socketpair2(sock_t[2], int sock_type)
static size_t cb(char *d, size_t n, size_t l, void *p)
void mg_munmap(void *p, size_t size)
static void do_ssi_include(struct mg_connection *conn, const char *ssi, char *tag, int include_level)
int mg_forward(struct mg_connection *c, const char *addr)
static void parse_http_headers(char **buf, struct mg_connection *ri)
const char * mg_set_option(struct mg_server *server, const char *name, const char *value)
struct ns_connection * nc
void(* handler)(struct mg_connection *)
void mg_send_file(struct mg_connection *c, const char *file_name, const char *extra_headers)
static void addenv2(struct cgi_env_block *blk, const char *name)
unsigned short remote_port
static int ns_parse_address(const char *str, union socket_address *sa, int *proto, int *use_ssl, char *cert, char *ca)
static sock_t ns_open_listening_socket(union socket_address *sa, int proto)
void mg_send_file_data(struct mg_connection *c, int fd)
UNITTEST_START int * value
static void send_http_error(struct connection *conn, int code, const char *fmt,...)
size_t mg_printf(struct mg_connection *conn, const char *fmt,...)
static void mg_ev_handler(struct ns_connection *nc, int ev, void *p)
const char * http_version
void mg_send_digest_auth_request(struct mg_connection *c)
struct ns_connection * next
ROSCPP_DECL bool exists(const std::string &service_name, bool print_failure_reason)
static void set_ips(struct ns_connection *nc, int is_rem)
int mg_match_prefix(const char *pattern, ssize_t pattern_len, const char *str)
static time_t parse_date_string(const char *datetime)
static size_t deliver_websocket_frame(struct connection *conn)
time_t ns_mgr_poll(struct ns_mgr *, int milli)
static int is_valid_uri(const char *uri)
static void set_default_option_values(char **opts)
static void send_websocket_handshake_if_requested(struct mg_connection *conn)
static void ns_close_conn(struct ns_connection *conn)
static void do_ssi_exec(struct mg_connection *conn, char *tag)
static void call_http_client_handler(struct connection *conn)
#define MONGOOSE_IDLE_TIMEOUT_SECONDS
static int parse_header(const char *str, size_t str_len, const char *var_name, char *buf, size_t buf_size)
static int get_var(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len)
#define SSLv23_client_method
static void MD5Final(unsigned char digest[16], MD5_CTX *ctx)
const char * request_method
struct MD5Context MD5_CTX
static void print_dir_entry(const struct dir_entry *de)
#define NS_CTL_MSG_MESSAGE_SIZE
void mg_send_file_internal(struct mg_connection *c, const char *file_name, file_stat_t *st, int exists, const char *extra_headers)
static unsigned long thread_id(void)
int mg_parse_multipart(const char *buf, int buf_len, char *var_name, int var_name_len, char *file_name, int file_name_len, const char **data, int *data_len)
static int put_dir(const char *path)
void mg_destroy_server(struct mg_server **server)
#define MG_CONN_2_CONN(c)
void mg_wakeup_server(struct mg_server *server)
static void send_ssi_file(struct mg_connection *, const char *, FILE *, int)
static void iter2(struct ns_connection *nc, int ev, void *param)
static const char * suggest_connection_header(const struct mg_connection *conn)
void mg_wakeup_server_ex(struct mg_server *server, mg_handler_t cb, const char *fmt,...)
#define NSF_SSL_HANDSHAKE_DONE
void iobuf_init(struct iobuf *, size_t initial_size)
static void on_recv_data(struct connection *conn)
static void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len)
int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len, int is_form_url_encoded)
int ns_hexdump(const void *buf, int len, char *dst, int dst_len)
static void construct_etag(char *buf, size_t buf_len, const file_stat_t *st)
static void write_chunk(struct connection *conn, const char *buf, int len)
static size_t callback(char *ptr, size_t size, size_t nmemb, void *data)
size_t mg_send_data(struct mg_connection *c, const void *data, int data_len)
static const char * static_config_options[]
static int is_not_modified(const struct connection *conn, const file_stat_t *stp)