Commit 9f1679e9 authored by Sergey Lyubka's avatar Sergey Lyubka

Merge branch 'master' of ssh://github.com/valenok/mongoose

parents d553ae99 c0af018e
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key> <string>Mongoose</string>
<key>CFBundlePackageType</key> <string>APPL</string>
<key>CFBundleTypeRole</key> <string>None</string>
<key>CFBundleIconFile</key> <string>mongoose.icns</string>
<key>LSUIElement</key> <true/>
<key>RunAtLoad</key> <true/>
<key>Label</key> <string>com.kolkin.mongoose</string>
<key>ProgramArguments</key> <array> </array>
<key>KeepAlive</key> <true/>
</dict>
</plist>
# This Makefile is part of Mongoose web server project,
# https://github.com/valenok/mongoose
#
# This Makefile is GNU make compatible. You can get GNU Make from
# http://gnuwin32.sourceforge.net/packages/make.htm
PROG = mongoose
EXE_SUFFIX =
CFLAGS = -std=c99 -O2 -W -Wall -pedantic -pthread -pipe -I. -I.. $(CFLAGS_EXTRA)
VERSION = $(shell perl -lne \
'print $$1 if /define\s+MONGOOSE_VERSION\s+"(\S+)"/' ../mongoose.h)
WP = wordpress-private-1.3
RM = rm -rf
VDIR = mongoose-$(VERSION)
# Stock windows binary builds with Lua and YASSL library.
YASSL = ../../cyassl-2.4.6
YASSL_FLAGS = -I $(YASSL) -I $(YASSL)/cyassl \
-D _LIB -D OPENSSL_EXTRA -D HAVE_ERRNO_H \
-D HAVE_GETHOSTBYNAME -D HAVE_INET_NTOA -D HAVE_LIMITS_H \
-D HAVE_MEMSET -D HAVE_SOCKET -D HAVE_STDDEF_H -D HAVE_STDLIB_H \
-D HAVE_STRING_H -D HAVE_SYS_STAT_H -D HAVE_SYS_TYPES_H
YASSL_SOURCES = \
$(YASSL)/src/internal.c $(YASSL)/src/io.c $(YASSL)/src/keys.c \
$(YASSL)/src/ssl.c $(YASSL)/src/tls.c $(YASSL)/ctaocrypt/src/hmac.c \
$(YASSL)/ctaocrypt/src/random.c $(YASSL)/ctaocrypt/src/sha.c \
$(YASSL)/ctaocrypt/src/sha256.c $(YASSL)/ctaocrypt/src/logging.c \
$(YASSL)/ctaocrypt/src/error.c $(YASSL)/ctaocrypt/src/rsa.c \
$(YASSL)/ctaocrypt/src/des3.c $(YASSL)/ctaocrypt/src/asn.c \
$(YASSL)/ctaocrypt/src/coding.c $(YASSL)/ctaocrypt/src/arc4.c \
$(YASSL)/ctaocrypt/src/md4.c $(YASSL)/ctaocrypt/src/md5.c \
$(YASSL)/ctaocrypt/src/dh.c $(YASSL)/ctaocrypt/src/dsa.c \
$(YASSL)/ctaocrypt/src/pwdbased.c $(YASSL)/ctaocrypt/src/aes.c \
$(YASSL)/ctaocrypt/src/md2.c $(YASSL)/ctaocrypt/src/ripemd.c \
$(YASSL)/ctaocrypt/src/sha512.c $(YASSL)/src/sniffer.c \
$(YASSL)/ctaocrypt/src/rabbit.c $(YASSL)/ctaocrypt/src/misc.c \
$(YASSL)/ctaocrypt/src/tfm.c $(YASSL)/ctaocrypt/src/integer.c \
$(YASSL)/ctaocrypt/src/ecc.c $(YASSL)/src/ocsp.c $(YASSL)/src/crl.c \
$(YASSL)/ctaocrypt/src/hc128.c $(YASSL)/ctaocrypt/src/memory.c
TINY_SOURCES = ../mongoose.c main.c
LUA_SOURCES = $(TINY_SOURCES) lua_5.2.1.c
LUA_SQLITE_SOURCES = $(LUA_SOURCES) sqlite3.c lsqlite3.c
BIG_SOURCES = $(TINY_SOURCES) lua_5.2.1.c sqlite3.c lsqlite3.c $(YASSL_SOURCES)
SQLITE_FLAGS = -DTHREADSAFE=1 -DSQLITE_ENABLE_FTS3 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS
LUA_FLAGS = -DUSE_LUA
LUA_SQLITE_FLAGS = $(SQLITE_FLAGS) $(LUA_FLAGS) -DUSE_LUA_SQLITE3
BIG_FLAGS = -DTHREADSAFE=1 -DSQLITE_ENABLE_FTS3 \
-DSQLITE_ENABLE_FTS3_PARENTHESIS \
-DUSE_LUA -DUSE_LUA_SQLITE3 -DUSE_SSL -DUSE_CYASSL $(YASSL_FLAGS)
# Using Visual Studio 6.0. To build Mongoose:
# Set MSVC variable below to where VS 6.0 is installed on your system
# Run "PATH_TO_VC6\bin\nmake windows"
MSVC = ../../vc6
#DBG = /Zi /Od
DBG = /DNDEBUG /O1 $(CFLAGS_EXTRA)
CL = $(MSVC)/bin/cl /MD /TC /nologo $(DBG) /W3 /I$(MSVC)/include /I.. /I.
LINK_FLAGS = /incremental:no /libpath:$(MSVC)/lib /machine:IX86 \
user32.lib shell32.lib comdlg32.lib ws2_32.lib advapi32.lib
LINK = $(MSVC)/bin/link $(LINK_FLAGS)
ifeq ($(OS), Windows_NT)
EXE_SUFFIX = .exe
RM = del
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S), Linux)
CFLAGS += -ldl -lm
endif
endif
all: mongoose$(EXE_SUFFIX)
# Make sure that the compiler flags come last in the compilation string.
# If not so, this can break some on some Linux distros which use
# "-Wl,--as-needed" turned on by default in cc command.
# Also, this is turned in many other distros in static linkage builds.
$(PROG): $(TINY_SOURCES)
$(CC) $(TINY_SOURCES) -o $@ $(CFLAGS)
$(PROG)-lua: $(TINY_SOURCES) $(LUA_SOURCES)
$(CC) $(LUA_SOURCES) -o $@ $(LUA_FLAGS) $(CFLAGS)
$(PROG)-lua-sqlite: $(LUA_SQLITE_SOURCES)
$(CC) $(LUA_SQLITE_SOURCES) -o $@ $(LUA_SQLITE_FLAGS) $(CFLAGS)
$(PROG)-lua-sqlite-ssl: $(BIG_SOURCES)
$(CC) $(BIG_SOURCES) -o $@ $(BIG_FLAGS) $(CFLAGS)
$(PROG)-big: $(BIG_SOURCES)
$(CC) $(BIG_SOURCES) -o $@ $(CFLAGS) $(BIG_FLAGS)
unix_unit_test: $(LUA_SOURCES) Makefile ./test/unit_test.c
$(CC) ./test/unit_test.c lua_5.2.1.c $(CFLAGS) -g -O0 -o t && ./t
# Windows build
$(PROG)-lua-sqlite.exe: $(LUA_SQLITE_SOURCES)
$(MSVC)/bin/rc res.rc
$(CL) $(LUA_SQLITE_SOURCES) $(LUA_SQLITE_FLAGS) /link $(LINK_FLAGS) res.res /out:$@
$(PROG)-lua-sqlite-ssl.exe: $(BIG_SOURCES)
$(MSVC)/bin/rc res.rc
$(CL) $(BIG_SOURCES) $(BIG_FLAGS) /link $(LINK_FLAGS) res.res /out:$@
$(PROG)-lua.exe: $(LUA_SOURCES)
$(MSVC)/bin/rc res.rc
$(CL) $(LUA_SOURCES) $(LUA_FLAGS) /link $(LINK_FLAGS) res.res /out:$@
$(PROG).exe: $(TINY_SOURCES)
$(MSVC)/bin/rc res.rc
$(CL) $(TINY_SOURCES) /link $(LINK_FLAGS) res.res /out:$@
$(PROG).dll: $(TINY_SOURCES) Makefile
$(CL) ../mongoose.c /Gz /link $(LINK_FLAGS) /DLL /DEF:dll.def /out:$@
# This is broken now due to SSL exclusion
windows_unit_test.exe: ../mongoose.c Makefile
$(CL) ./test/unit_test.c lua_5.2.1.c \
/link /libpath:$(MSVC)/lib advapi32.lib /out:$@
./$@
# MacOS build with Cocoa GUI
# For codesign to work in non-interactive mode, unlock login keychain:
# security unlock ~/Library/Keychains/login.keychain
# See e.g. http://lists.apple.com/archives/apple-cdsa/2008/Jan/msg00027.html
macos: $(BIG_SOURCES)
DIR=dmg/Mongoose.app
rm -rf dmg
mkdir -p dmg/Mongoose.app/Contents/{MacOS,Resources}
install -m 644 *.icns *.png dmg/Mongoose.app/Contents/Resources/
install -m 644 Info.plist dmg/Mongoose.app/Contents/
$(CC) $(BIG_SOURCES) \
-DUSE_COCOA $(CFLAGS) $(BIG_FLAGS) -mmacosx-version-min=10.4 \
-framework Cocoa -ObjC -arch i386 -arch x86_64 \
-o dmg/Mongoose.app/Contents/MacOS/Mongoose
ln -fs /Applications dmg/
hdiutil create Mongoose-$(VERSION).dmg -volname "Mongoose $(VERSION)" \
-srcfolder dmg -ov
#rm -rf dmg
tests:
perl ./test/test.pl $(TEST)
tarball: clean
rm -rf $(VDIR)
install -d $(VDIR) $(VDIR)/docs $(VDIR)/examples
install -m 644 ../{LICENSE,README.md,mongoose.[ch]} $(VDIR)
install -m 644 ../docs/*.md $(VDIR)/docs
install -m 644 ../examples/{Makefile,*.c} $(VDIR)/examples
tar -czf $(VDIR).tgz $(VDIR)
release: tarball macos
wine make mongoose.exe mongoose-lua-sqlite-ssl.exe
upx mongoose.exe
upx mongoose-lua-sqlite-ssl.exe
cp mongoose.exe mongoose-$(VERSION).exe
cp mongoose-lua-sqlite-ssl.exe mongoose-lua-sqlite-ssl-$(VERSION).exe
cp mongoose-lua-sqlite-ssl.exe mongoose_php_bundle/mongoose.exe
zip -r mongoose-php-$(VERSION).zip mongoose_php_bundle/
wp: mongoose.exe
upx mongoose.exe
cp mongoose.exe $(WP)/
zip -r $(WP).zip $(WP)
clean:
@cd ../examples && $(MAKE) clean
@$(RM) *.o *.core $(PROG) *.obj *.so $(PROG).txt *.dSYM *.tgz \
$(PROG).exe *.dll *.lib res.o res.RES *.dSYM *.zip *.pdb \
*.exe *dmg* $(PROG)-* unix_unit_test
LIBRARY
EXPORTS
mg_start
mg_stop
mg_read
mg_write
mg_printf
mg_get_header
mg_get_var
mg_get_cookie
mg_get_option
mg_get_valid_option_names
mg_version
mg_modify_passwords_file
mg_md5
mg_upload
mg_download
mg_send_file
mg_get_builtin_mime_type
LOCAL_PATH := $(call my-dir)/../..
include $(CLEAR_VARS)
# To build with lua support, uncomment two lines below:
#LUA_SOURCES := build/lua_5.2.1.c build/sqlite3.c build/lsqlite3.c
#LUA_FLAGS := -I$(LOCAL_PATH)/build -DTHREADSAFE=1 -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DUSE_LUA -DUSE_LUA_SQLITE3 -DLUA_COMPAT_ALL -D"getlocaledecpoint() ='.'"
LOCAL_CFLAGS := -std=c99 -O2 -W -Wall -pthread -pipe $(LUA_FLAGS) $(COPT)
LOCAL_MODULE := mongoose
LOCAL_SRC_FILES := build/main.c mongoose.c $(LUA_SOURCES)
include $(BUILD_EXECUTABLE)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
100 ICON DISCARDABLE "systray.ico"
This diff is collapsed.
This diff is collapsed.
#include "internal.h"
// Stringify binary data. Output buffer must be twice as big as input,
// because each byte takes 2 bytes in string representation
static void bin2str(char *to, const unsigned char *p, size_t len) {
static const char *hex = "0123456789abcdef";
for (; len--; p++) {
*to++ = hex[p[0] >> 4];
*to++ = hex[p[0] & 0x0f];
}
*to = '\0';
}
// Return stringified MD5 hash for list of strings. Buffer must be 33 bytes.
char *mg_md5(char buf[33], ...) {
unsigned char hash[16];
const char *p;
va_list ap;
MD5_CTX ctx;
MD5Init(&ctx);
va_start(ap, buf);
while ((p = va_arg(ap, const char *)) != NULL) {
MD5Update(&ctx, (const unsigned char *) p, (unsigned) strlen(p));
}
va_end(ap);
MD5Final(hash, &ctx);
bin2str(buf, hash, sizeof(hash));
return buf;
}
// Check the user's password, return 1 if OK
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) {
char ha2[32 + 1], expected_response[32 + 1];
// Some of the parameters may be NULL
if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL ||
qop == NULL || response == NULL) {
return 0;
}
// NOTE(lsm): due to a bug in MSIE, we do not compare the URI
// TODO(lsm): check for authentication timeout
if (// strcmp(dig->uri, c->ouri) != 0 ||
strlen(response) != 32
// || now - strtoul(dig->nonce, NULL, 10) > 3600
) {
return 0;
}
mg_md5(ha2, method, ":", uri, NULL);
mg_md5(expected_response, ha1, ":", nonce, ":", nc,
":", cnonce, ":", qop, ":", ha2, NULL);
return mg_strcasecmp(response, expected_response) == 0;
}
// Use the global passwords file, if specified by auth_gpass option,
// or search for .htpasswd in the requested directory.
static FILE *open_auth_file(struct mg_connection *conn, const char *path) {
char name[PATH_MAX];
const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
struct file file = STRUCT_FILE_INITIALIZER;
FILE *fp = NULL;
if (gpass != NULL) {
// Use global passwords file
fp = mg_fopen(gpass, "r");
// Important: using local struct file to test path for is_directory flag.
// If filep is used, mg_stat() makes it appear as if auth file was opened.
} else if (mg_stat(path, &file) && file.is_directory) {
mg_snprintf(name, sizeof(name), "%s%c%s",
path, '/', PASSWORDS_FILE_NAME);
fp = mg_fopen(name, "r");
} else {
// Try to find .htpasswd in requested directory.
for (p = path, e = p + strlen(p) - 1; e > p; e--)
if (e[0] == '/')
break;
mg_snprintf(name, sizeof(name), "%.*s%c%s",
(int) (e - p), p, '/', PASSWORDS_FILE_NAME);
fp = mg_fopen(name, "r");
}
return fp;
}
// Parsed Authorization header
struct ah {
char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
};
// Return 1 on success. Always initializes the ah structure.
static int parse_auth_header(struct mg_connection *conn, char *buf,
size_t buf_size, struct ah *ah) {
char *name, *value, *s;
const char *auth_header;
(void) memset(ah, 0, sizeof(*ah));
if ((auth_header = mg_get_header(conn, "Authorization")) == NULL ||
mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
return 0;
}
// Make modifiable copy of the auth header
(void) mg_strlcpy(buf, auth_header + 7, buf_size);
s = buf;
// Parse authorization header
for (;;) {
// Gobble initial spaces
while (isspace(* (unsigned char *) s)) {
s++;
}
name = skip_quoted(&s, "=", " ", 0);
// Value is either quote-delimited, or ends at first comma or space.
if (s[0] == '\"') {
s++;
value = skip_quoted(&s, "\"", " ", '\\');
if (s[0] == ',') {
s++;
}
} else {
value = skip_quoted(&s, ", ", " ", 0); // IE uses commas, FF uses spaces
}
if (*name == '\0') {
break;
}
if (!strcmp(name, "username")) {
ah->user = value;
} else if (!strcmp(name, "cnonce")) {
ah->cnonce = value;
} else if (!strcmp(name, "response")) {
ah->response = value;
} else if (!strcmp(name, "uri")) {
ah->uri = value;
} else if (!strcmp(name, "qop")) {
ah->qop = value;
} else if (!strcmp(name, "nc")) {
ah->nc = value;
} else if (!strcmp(name, "nonce")) {
ah->nonce = value;
}
}
// CGI needs it as REMOTE_USER
if (ah->user != NULL) {
conn->request_info.remote_user = mg_strdup(ah->user);
} else {
return 0;
}
return 1;
}
// Authorize against the opened passwords file. Return 1 if authorized.
static int authorize(struct mg_connection *conn, FILE *fp) {
struct ah ah;
char line[256], f_user[256], ha1[256], f_domain[256], buf[MG_BUF_LEN];
if (!parse_auth_header(conn, buf, sizeof(buf), &ah)) {
return 0;
}
// Loop over passwords file
while (fgets(line, sizeof(line), fp) != NULL) {
if (sscanf(line, "%[^:]:%[^:]:%s", f_user, f_domain, ha1) != 3) {
continue;
}
if (!strcmp(ah.user, f_user) &&
!strcmp(conn->ctx->config[AUTHENTICATION_DOMAIN], f_domain))
return check_password(conn->request_info.request_method, ha1, ah.uri,
ah.nonce, ah.nc, ah.cnonce, ah.qop, ah.response);
}
return 0;
}
// Return 1 if request is authorised, 0 otherwise.
static int check_authorization(struct mg_connection *conn, const char *path) {
char fname[PATH_MAX];
struct vec uri_vec, filename_vec;
const char *list;
FILE *fp = NULL;
int authorized = 1;
list = conn->ctx->config[PROTECT_URI];
while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
if (!memcmp(conn->request_info.uri, uri_vec.ptr, uri_vec.len)) {
mg_snprintf(fname, sizeof(fname), "%.*s",
(int) filename_vec.len, filename_vec.ptr);
fp = mg_fopen(fname, "r");
break;
}
}
if (fp == NULL) {
fp = open_auth_file(conn, path);
}
if (fp != NULL) {
authorized = authorize(conn, fp);
fclose(fp);
}
return authorized;
}
static void send_authorization_request(struct mg_connection *conn) {
conn->status_code = 401;
mg_printf(conn,
"HTTP/1.1 401 Unauthorized\r\n"
"Content-Length: 0\r\n"
"WWW-Authenticate: Digest qop=\"auth\", "
"realm=\"%s\", nonce=\"%lu\"\r\n\r\n",
conn->ctx->config[AUTHENTICATION_DOMAIN],
(unsigned long) time(NULL));
}
static int is_authorized_for_put(struct mg_connection *conn) {
const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
FILE *fp;
int ret = 0;
if (passfile != NULL && (fp = mg_fopen(passfile, "r")) != NULL) {
ret = authorize(conn, fp);
fclose(fp);
}
return ret;
}
int mg_modify_passwords_file(const char *fname, const char *domain,
const char *user, const char *pass) {
int found;
char line[512], u[512], d[512], ha1[33], tmp[PATH_MAX];
FILE *fp, *fp2;
found = 0;
fp = fp2 = NULL;
// Regard empty password as no password - remove user record.
if (pass != NULL && pass[0] == '\0') {
pass = NULL;
}
(void) snprintf(tmp, sizeof(tmp), "%s.tmp", fname);
// Create the file if does not exist
if ((fp = fopen(fname, "a+")) != NULL) {
fclose(fp);
}
// Open the given file and temporary file
if ((fp = fopen(fname, "r")) == NULL) {
return 0;
} else if ((fp2 = fopen(tmp, "w+")) == NULL) {
fclose(fp);
return 0;
}
// Copy the stuff to temporary file
while (fgets(line, sizeof(line), fp) != NULL) {
if (sscanf(line, "%[^:]:%[^:]:%*s", u, d) != 2) {
continue;
}
if (!strcmp(u, user) && !strcmp(d, domain)) {
found++;
if (pass != NULL) {
mg_md5(ha1, user, ":", domain, ":", pass, NULL);
fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
}
} else {
fprintf(fp2, "%s", line);
}
}
// If new user, just add it
if (!found && pass != NULL) {
mg_md5(ha1, user, ":", domain, ":", pass, NULL);
fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
}
// Close files
fclose(fp);
fclose(fp2);
// Put the temp file in place of real file
remove(fname);
rename(tmp, fname);
return 1;
}
This diff is collapsed.
This diff is collapsed.
// Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
// Copyright (c) 2013 Cesanta Software Limited
// All rights reserved
//
// This library is dual-licensed: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation. For the terms of this
// license, see <http://www.gnu.org/licenses/>.
//
// You are free to use this library under the terms of the GNU General
// Public License, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// Alternatively, you can license this library under a commercial
// license, as set out in <http://cesanta.com/products.html>.
//
// NOTE: Detailed API documentation is at http://cesanta.com/docs.html
#ifndef MONGOOSE_HEADER_INCLUDED
#define MONGOOSE_HEADER_INCLUDED
#include <stdio.h> // required for FILE
#include <stddef.h> // required for size_t
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// This structure contains information about HTTP request.
struct mg_connection {
const char *request_method; // "GET", "POST", etc
const char *uri; // URL-decoded URI
const char *http_version; // E.g. "1.0", "1.1"
const char *query_string; // URL part after '?', not including '?', or NULL
char remote_ip[48]; // Max IPv6 string length is 45 characters
int remote_port; // Client's port
int num_headers; // Number of HTTP headers
struct mg_header {
const char *name; // HTTP header name
const char *value; // HTTP header value
} http_headers[30];
char *content; // POST (or websocket message) data, or NULL
int content_len; // content length
int is_websocket; // Connection is a websocket connection
int status_code; // HTTP status code for HTTP error handler
unsigned char wsbits; // First byte of the websocket frame
void *server_param; // Parameter passed to mg_add_uri_handler()
void *connection_param; // Placeholder for connection-specific data
};
struct mg_server; // Opaque structure describing server instance
typedef int (*mg_handler_t)(struct mg_connection *);
// Server management functions
struct mg_server *mg_create_server(void *server_param);
void mg_destroy_server(struct mg_server **);
const char *mg_set_option(struct mg_server *, const char *opt, const char *val);
void mg_poll_server(struct mg_server *, int milliseconds);
void mg_add_uri_handler(struct mg_server *, const char *uri, mg_handler_t);
void mg_set_error_handler(struct mg_server *, mg_handler_t);
void mg_set_log_handler(struct mg_server*, mg_handler_t);
const char **mg_get_valid_option_names(void);
const char *mg_get_option(const struct mg_server *server, const char *name);
int mg_iterate_over_connections(struct mg_server *,
void (*func)(struct mg_connection *, void *),
void *param);
// Connection management functions
int mg_write(struct mg_connection *, const void *buf, int len);
int mg_websocket_write(struct mg_connection *, int opcode,
const char *data, size_t data_len);
const char *mg_get_header(const struct mg_connection *, const char *name);
const char *mg_get_mime_type(const char *file_name);
int mg_get_var(const struct mg_connection *conn, const char *var_name,
char *buf, size_t buf_len);
int mg_parse_header(const char *hdr, const char *var_name, char *buf, size_t);
// Utility functions
int mg_start_thread(void *(*func)(void *), void *param);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // MONGOOSE_HEADER_INCLUDED
This diff is collapsed.
This diff is collapsed.
#include "internal.h"
static SOCKET conn2(const char *host, int port, int use_ssl,
char *ebuf, size_t ebuf_len) {
struct sockaddr_in sin;
struct hostent *he = NULL;
SOCKET sock = INVALID_SOCKET;
(void) use_ssl; // Prevent warning for -DNO_SSL case
if (host == NULL) {
snprintf(ebuf, ebuf_len, "%s", "NULL host");
#ifndef NO_SSL
} else if (use_ssl && SSLv23_client_method == NULL) {
snprintf(ebuf, ebuf_len, "%s", "SSL is not initialized");
// TODO(lsm): use something threadsafe instead of gethostbyname()
#endif
} else if ((he = gethostbyname(host)) == NULL) {
snprintf(ebuf, ebuf_len, "gethostbyname(%s): %s", host, strerror(ERRNO));
} else if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
snprintf(ebuf, ebuf_len, "socket(): %s", strerror(ERRNO));
} else {
set_close_on_exec(sock);
sin.sin_family = AF_INET;
sin.sin_port = htons((uint16_t) port);
sin.sin_addr = * (struct in_addr *) he->h_addr_list[0];
if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
snprintf(ebuf, ebuf_len, "connect(%s:%d): %s",
host, port, strerror(ERRNO));
closesocket(sock);
sock = INVALID_SOCKET;
}
}
return sock;
}
struct mg_connection *mg_connect(const char *host, int port, int use_ssl,
char *ebuf, size_t ebuf_len) {
static struct mg_context fake_ctx;
struct mg_connection *conn = NULL;
SOCKET sock;
if ((sock = conn2(host, port, use_ssl, ebuf, ebuf_len)) == INVALID_SOCKET) {
} else if ((conn = (struct mg_connection *)
calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
snprintf(ebuf, ebuf_len, "calloc(): %s", strerror(ERRNO));
closesocket(sock);
#ifndef NO_SSL
} else if (use_ssl && (conn->client_ssl_ctx =
SSL_CTX_new(SSLv23_client_method())) == NULL) {
snprintf(ebuf, ebuf_len, "SSL_CTX_new error");
closesocket(sock);
free(conn);
conn = NULL;
#endif // NO_SSL
} else {
socklen_t len = sizeof(struct sockaddr);
conn->buf_size = MAX_REQUEST_SIZE;
conn->buf = (char *) (conn + 1);
conn->ctx = &fake_ctx;
conn->client.sock = sock;
getsockname(sock, &conn->client.rsa.sa, &len);
conn->client.is_ssl = use_ssl;
#ifndef NO_SSL
if (use_ssl) {
// SSL_CTX_set_verify call is needed to switch off server certificate
// checking, which is off by default in OpenSSL and on in yaSSL.
SSL_CTX_set_verify(conn->client_ssl_ctx, 0, 0);
sslize(conn, conn->client_ssl_ctx, SSL_connect);
}
#endif
}
return conn;
}
struct mg_connection *mg_download(const char *host, int port, int use_ssl,
char *ebuf, size_t ebuf_len,
const char *fmt, ...) {
struct mg_connection *conn;
const char *msg = NULL;
va_list ap;
va_start(ap, fmt);
if ((conn = mg_connect(host, port, use_ssl, ebuf, ebuf_len)) == NULL) {
} else if (mg_vprintf(conn, fmt, ap) <= 0) {
snprintf(ebuf, ebuf_len, "%s", "Error sending request");
} else {
msg = getreq(conn);
}
if (msg != NULL && conn != NULL) {
mg_close_connection(conn);
conn = NULL;
}
return conn;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/bin/sh
echo "echoing bad headers: server must report status 500"
exec 1>&2
echo shit!!!
#!/usr/bin/env perl
print "Status: 302 Please pass me to the client\r\n\r\n";
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment