diff --git a/Makefile b/Makefile index 200484a4..faef3550 100644 --- a/Makefile +++ b/Makefile @@ -14,13 +14,15 @@ all: # -DNO_SSL - disable SSL functionality (-2kb) # -DCONFIG_FILE=\"file\" - use `file' as the default config file # -DHAVE_STRTOUI64 - use system strtoui64() function for strtoull() +# -DSSL_LIB=\"libssl.so.\" - use system versioned SSL shared object +# -DCRYPTO_LIB=\"libcrypto.so.\" - use system versioned CRYPTO so ########################################################################## ### UNIX build: linux, bsd, mac, rtems ########################################################################## -CFLAGS= -W -Wall -std=c99 -pedantic -O2 -fomit-frame-pointer $(COPT) +CFLAGS= -W -Wall -std=c99 -pedantic -O2 $(COPT) MAC_SHARED= -flat_namespace -bundle -undefined suppress LINFLAGS= -ldl -pthread $(CFLAGS) LIB= _$(PROG).so @@ -126,7 +128,7 @@ do_test: perl test/test.pl $(TEST) release: clean - F=mongoose-`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' mongoose.c`.tgz ; cd .. && tar --exclude \*.hg --exclude \*.svn --exclude \*.swp --exclude \*.nfs\* --exclude win32 -czf x mongoose && mv x mongoose/$$F + F=mongoose-`perl -lne '/define\s+MONGOOSE_VERSION\s+"(\S+)"/ and print $$1' mongoose.c`.tgz ; cd .. && tar --exclude \*.hg --exclude \*.svn --exclude \*.swp --exclude \*.nfs\* -czf x mongoose && mv x mongoose/$$F clean: rm -rf *.o *.core $(PROG) *.obj $(PROG).txt *.dSYM *.tgz diff --git a/examples/chat.c b/examples/chat.c index 7aa81453..8ce6833d 100644 --- a/examples/chat.c +++ b/examples/chat.c @@ -374,7 +374,7 @@ int main(void) { srand((unsigned) time(0)); // Setup and start Mongoose - ctx = mg_start(&event_handler, options); + ctx = mg_start(&event_handler, NULL, options); assert(ctx != NULL); // Wait until enter is pressed, then exit diff --git a/mongoose.c b/mongoose.c index 950c0a8c..dd21977e 100644 --- a/mongoose.c +++ b/mongoose.c @@ -163,7 +163,6 @@ typedef struct DIR { #include #include #include -#include #include #include #include @@ -174,15 +173,21 @@ typedef struct DIR { #include #include #include +#if !defined(NO_SSL_DL) && !defined(NO_SSL) #include +#endif #include #if defined(__MACH__) #define SSL_LIB "libssl.dylib" #define CRYPTO_LIB "libcrypto.dylib" #else +#if !defined(SSL_LIB) #define SSL_LIB "libssl.so" +#endif +#if !defined(CRYPTO_LIB) #define CRYPTO_LIB "libcrypto.so" #endif +#endif #define DIRSEP '/' #define IS_DIRSEP_CHAR(c) ((c) == '/') #define O_BINARY 0 @@ -557,7 +562,7 @@ static void mg_strlcpy(register char *dst, register const char *src, size_t n) { } static int lowercase(const char *s) { - return tolower(* (unsigned char *) s); + return tolower(* (const unsigned char *) s); } static int mg_strncasecmp(const char *s1, const char *s2, size_t len) { @@ -1280,11 +1285,11 @@ static int64_t push(FILE *fp, SOCKET sock, SSL *ssl, const char *buf, if (ssl != NULL) { n = SSL_write(ssl, buf + sent, k); } else if (fp != NULL) { - n = fwrite(buf + sent, 1, k, fp); + n = fwrite(buf + sent, 1, (size_t)k, fp); if (ferror(fp)) n = -1; } else { - n = send(sock, buf + sent, k, 0); + n = send(sock, buf + sent, (size_t)k, 0); } if (n < 0) @@ -1304,7 +1309,10 @@ static int pull(FILE *fp, SOCKET sock, SSL *ssl, char *buf, int len) { if (ssl != NULL) { nread = SSL_read(ssl, buf, len); } else if (fp != NULL) { - nread = fread(buf, 1, (size_t) len, fp); + // Use read() instead of fread(), because if we're reading from the CGI + // pipe, fread() may block until IO buffer is filled up. We cannot afford + // to block and must pass all read bytes immediately to the client. + nread = read(fileno(fp), buf, (size_t) len); if (ferror(fp)) nread = -1; } else { @@ -1331,7 +1339,7 @@ int mg_read(struct mg_connection *conn, void *buf, size_t len) { } // How many bytes of data we have buffered in the request buffer? - buffered = conn->buf + conn->request_len; + buffered = conn->buf + conn->request_len + conn->consumed_content; buffered_len = conn->data_len - conn->request_len; assert(buffered_len >= 0); @@ -1341,7 +1349,7 @@ int mg_read(struct mg_connection *conn, void *buf, size_t len) { if (len < (size_t) buffered_len) { buffered_len = len; } - memcpy(buf, buffered, buffered_len); + memcpy(buf, buffered, (size_t)buffered_len); len -= buffered_len; buf = (char *) buf + buffered_len; conn->consumed_content += buffered_len; @@ -1377,7 +1385,7 @@ int mg_printf(struct mg_connection *conn, const char *fmt, ...) { len = mg_vsnprintf(conn, buf, sizeof(buf), fmt, ap); va_end(ap); - return mg_write(conn, buf, len); + return mg_write(conn, buf, (size_t)len); } // URL-decode input buffer into destination buffer. @@ -1393,10 +1401,10 @@ static size_t url_decode(const char *src, size_t src_len, char *dst, for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) { if (src[i] == '%' && - isxdigit(* (unsigned char *) (src + i + 1)) && - isxdigit(* (unsigned char *) (src + i + 2))) { - a = tolower(* (unsigned char *) (src + i + 1)); - b = tolower(* (unsigned char *) (src + i + 2)); + isxdigit(* (const unsigned char *) (src + i + 1)) && + isxdigit(* (const unsigned char *) (src + i + 2))) { + a = tolower(* (const unsigned char *) (src + i + 1)); + b = tolower(* (const unsigned char *) (src + i + 2)); dst[j] = (char) ((HEXTOI(a) << 4) | HEXTOI(b)); i += 2; } else if (is_form_url_encoded && src[i] == '+') { @@ -1434,7 +1442,7 @@ int mg_get_var(const char *buf, size_t buf_len, const char *name, p += name_len + 1; // Point s to the end of the value - s = (const char *) memchr(p, '&', e - p); + s = (const char *) memchr(p, '&', (size_t)(e - p)); if (s == NULL) { s = e; } @@ -1442,7 +1450,7 @@ int mg_get_var(const char *buf, size_t buf_len, const char *name, // Decode variable into destination buffer if ((size_t) (s - p) < dst_len) { - len = url_decode(p, s - p, dst, dst_len, 1); + len = url_decode(p, (size_t)(s - p), dst, dst_len, 1); } break; } @@ -1477,7 +1485,7 @@ int mg_get_cookie(const struct mg_connection *conn, const char *cookie_name, } if ((size_t) (p - s) < dst_size) { len = (p - s) + 1; - mg_strlcpy(dst, s, len); + mg_strlcpy(dst, s, (size_t)len); } break; } @@ -1531,7 +1539,7 @@ static int sslize(struct mg_connection *conn, int (*func)(SSL *)) { func(conn->ssl) == 1; } -struct mg_connection *mg_connect(struct mg_connection *conn, +static struct mg_connection *mg_connect(struct mg_connection *conn, const char *host, int port, int use_ssl) { struct mg_connection *newconn = NULL; struct sockaddr_in sin; @@ -1578,8 +1586,8 @@ static int get_request_len(const char *buf, int buflen) { DEBUG_TRACE(("buf: %p, len: %d", buf, buflen)); for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++) // Control characters are not allowed but >=128 is. - if (!isprint(* (unsigned char *) s) && *s != '\r' && - *s != '\n' && * (unsigned char *) s < 128) { + if (!isprint(* (const unsigned char *) s) && *s != '\r' && + *s != '\n' && * (const unsigned char *) s < 128) { len = -1; } else if (s[0] == '\n' && s[1] == '\n') { len = (int) (s - buf) + 2; @@ -1757,7 +1765,7 @@ typedef struct MD5Context { unsigned char in[64]; } MD5_CTX; -#if __BYTE_ORDER == 1234 +#if defined(__BYTE_ORDER) && (__BYTE_ORDER == 1234) #define byteReverse(buf, len) // Do nothing #else static void byteReverse(unsigned char *buf, unsigned longs) { @@ -1961,7 +1969,7 @@ void mg_md5(char *buf, ...) { va_start(ap, buf); while ((p = va_arg(ap, const char *)) != NULL) { - MD5Update(&ctx, (unsigned char *) p, (int) strlen(p)); + MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p)); } va_end(ap); @@ -2052,7 +2060,7 @@ static int parse_auth_header(struct mg_connection *conn, char *buf, // Parse authorization header for (;;) { name = skip(&s, "="); - value = skip(&s, " "); + value = skip(&s, ", "); // IE uses commas, FF uses spaces // Handle commas: Digest username="a", realm="b", ... if (value[strlen(value) - 1] == ',') { @@ -2256,13 +2264,13 @@ static void url_encode(const char *src, char *dst, size_t dst_len) { const char *end = dst + dst_len - 1; for (; *src != '\0' && dst < end; src++, dst++) { - if (isalnum(*(unsigned char *) src) || - strchr(dont_escape, * (unsigned char *) src) != NULL) { + if (isalnum(*(const unsigned char *) src) || + strchr(dont_escape, * (const unsigned char *) src) != NULL) { *dst = *src; } else if (dst + 2 < end) { dst[0] = '%'; - dst[1] = hex[(* (unsigned char *) src) >> 4]; - dst[2] = hex[(* (unsigned char *) src) & 0xf]; + dst[1] = hex[(* (const unsigned char *) src) >> 4]; + dst[2] = hex[(* (const unsigned char *) src) & 0xf]; dst += 2; } } @@ -2306,7 +2314,7 @@ static void print_dir_entry(struct de *de) { // On windows, __cdecl specification is needed in case if project is built // with __stdcall convention. qsort always requires __cdels callback. static int WINCDECL compare_dir_entries(const void *p1, const void *p2) { - const struct de *a = (struct de *) p1, *b = (struct de *) p2; + const struct de *a = (const struct de *) p1, *b = (const struct de *) p2; const char *query_string = a->conn->request_info.query_string; int cmp_result = 0; @@ -2408,7 +2416,7 @@ static void handle_directory_request(struct mg_connection *conn, conn->request_info.uri, "..", "Parent directory", "-", "-"); // Sort and print directory entries - qsort(entries, num_entries, sizeof(entries[0]), compare_dir_entries); + qsort(entries, (size_t)num_entries, sizeof(entries[0]), compare_dir_entries); for (i = 0; i < num_entries; i++) { print_dir_entry(&entries[i]); free(entries[i].file_name); @@ -2431,11 +2439,11 @@ static void send_file_data(struct mg_connection *conn, FILE *fp, int64_t len) { to_read = (int) len; // Read from file, exit the loop on error - if ((num_read = fread(buf, 1, to_read, fp)) == 0) + if ((num_read = fread(buf, 1, (size_t)to_read, fp)) == 0) break; // Send read bytes to the client, exit the loop on error - if ((num_written = mg_write(conn, buf, num_read)) != num_read) + if ((num_written = mg_write(conn, buf, (size_t)num_read)) != num_read) break; // Both read and were successful, adjust counters @@ -2918,7 +2926,7 @@ static void handle_cgi_request(struct mg_connection *conn, const char *prog) { // Send chunk of data that may be read after the headers conn->num_bytes_sent += mg_write(conn, buf + headers_len, - data_len - headers_len); + (size_t)(data_len - headers_len)); // Read the rest of CGI output and send to the client send_file_data(conn, out, INT64_MAX); @@ -3062,6 +3070,7 @@ static void do_ssi_include(struct mg_connection *conn, const char *ssi, } } +#if !defined(NO_POPEN) static void do_ssi_exec(struct mg_connection *conn, char *tag) { char cmd[BUFSIZ]; FILE *fp; @@ -3075,6 +3084,7 @@ static void do_ssi_exec(struct mg_connection *conn, char *tag) { (void) pclose(fp); } } +#endif // !NO_POPEN static void send_ssi_file(struct mg_connection *conn, const char *path, FILE *fp, int include_level) { @@ -3097,12 +3107,14 @@ static void send_ssi_file(struct mg_connection *conn, const char *path, assert(len <= (int) sizeof(buf)); if (len < 6 || memcmp(buf, "