25#if !defined(_CRT_SECURE_NO_WARNINGS)
26#define _CRT_SECURE_NO_WARNINGS
28#if !defined(_CRT_SECURE_NO_DEPRECATE)
29#define _CRT_SECURE_NO_DEPRECATE
31#if defined(WIN32_LEAN_AND_MEAN)
32#undef WIN32_LEAN_AND_MEAN
41#pragma GCC diagnostic push
42#pragma GCC diagnostic ignored "-Wreserved-id-macro"
44#if !defined(_XOPEN_SOURCE)
45#define _XOPEN_SOURCE 600
56#if !defined(IGNORE_UNUSED_RESULT)
57#define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
60#if defined(__cplusplus) && (__cplusplus >= 201103L)
61#define NO_RETURN [[noreturn]]
62#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
63#define NO_RETURN _Noreturn
64#elif defined(__GNUC__)
65#define NO_RETURN __attribute((noreturn))
71#if !defined(_LARGEFILE_SOURCE)
72#define _LARGEFILE_SOURCE
74#if !defined(_FILE_OFFSET_BITS)
75#define _FILE_OFFSET_BITS 64
77#if !defined(__STDC_FORMAT_MACROS)
78#define __STDC_FORMAT_MACROS
80#if !defined(__STDC_LIMIT_MACROS)
81#define __STDC_LIMIT_MACROS
86#pragma GCC diagnostic pop
105 DO_NOT_USE_THIS_FUNCTION__USE_fprintf
108#if !defined(_WIN32_WINNT)
109#define _WIN32_WINNT 0x0501
117#define getcwd(a, b) (_getcwd(a, b))
118#if !defined(__MINGW32__)
119extern char *_getcwd(
char *buf,
size_t size);
122#if !defined(PATH_MAX)
123#define PATH_MAX MAX_PATH
127#define S_ISDIR(x) ((x)&_S_IFDIR)
131#define snprintf _snprintf
132#define vsnprintf _vsnprintf
133#define sleep(x) (Sleep((x)*1000))
134#define WINCDECL __cdecl
135#define abs_path(rel, abs, abs_size) (_fullpath((abs), (rel), (abs_size)))
140#include <sys/utsname.h>
146#define abs_path(rel, abs, abs_size) (realpath((rel), (abs)))
151#if !defined(DEBUG_ASSERT)
156#pragma warning(disable : 4127)
159#define DEBUG_ASSERT(cond) \
162 fprintf(stderr, "ASSERTION FAILED: %s", #cond); \
168#define DEBUG_ASSERT(cond)
172#if !defined(PATH_MAX)
173#define PATH_MAX (1024)
176#define MAX_OPTIONS (100)
177#define MAX_CONF_FILE_LINE_SIZE (8 * 1024)
211#if !defined(CONFIG_FILE)
212#define CONFIG_FILE "civetweb.conf"
215#if !defined(PASSWORDS_FILE_NAME)
216#define PASSWORDS_FILE_NAME ".htpasswd"
220#if !defined(CONFIG_FILE2) && defined(__linux__)
221#define CONFIG_FILE2 "/usr/local/etc/civetweb.conf"
230#if defined(DAEMONIZE)
243#if defined(DAEMONIZE)
264 (void)vsnprintf(msg,
sizeof(msg) - 1, fmt, ap);
265 msg[
sizeof(msg) - 1] = 0;
269 MessageBox(
NULL, msg,
"Error", MB_ICONERROR | MB_OK);
271 fprintf(stderr,
"%s\n", msg);
285 (void)vsnprintf(msg,
sizeof(msg) - 1, fmt, ap);
286 msg[
sizeof(msg) - 1] = 0;
290 MessageBox(
NULL, msg,
"Warning", MB_OK);
292 fprintf(stderr,
"%s\n", msg);
298static int MakeConsole(
void);
305#if defined(BUILD_DATE)
306 const char *bd = BUILD_DATE;
308 const char *bd = __DATE__;
314 fprintf(stderr,
"CivetWeb v%s, built on %s\n",
mg_version(), bd);
324 if (exeName == 0 || *exeName == 0) {
325 exeName =
"civetweb";
330 fprintf(stderr,
"\nUsage:\n");
331 fprintf(stderr,
" Start server with a set of options:\n");
332 fprintf(stderr,
" %s [config_file]\n", exeName);
333 fprintf(stderr,
" %s [-option value ...]\n", exeName);
334 fprintf(stderr,
" Run as client:\n");
335 fprintf(stderr,
" %s -C url\n", exeName);
336 fprintf(stderr,
" Show system information:\n");
337 fprintf(stderr,
" %s -I\n", exeName);
338 fprintf(stderr,
" Add user/change password:\n");
340 " %s -A <htpasswd_file> <realm> <user> <passwd>\n",
342 fprintf(stderr,
" Remove user:\n");
343 fprintf(stderr,
" %s -R <htpasswd_file> <realm> <user>\n", exeName);
344 fprintf(stderr,
"\nOPTIONS:\n");
347 for (i = 0; options[i].
name !=
NULL; i++) {
357 for (i = 0; options[i].
name !=
NULL; i++) {
370#if defined(_WIN32) || defined(USE_COCOA) || defined(MAIN_C_UNIT_TEST)
371static const char *config_file_top_comment =
372 "# CivetWeb web server configuration file.\n"
373 "# For detailed description of every option, visit\n"
374 "# https://github.com/civetweb/civetweb/blob/master/docs/UserManual.md\n"
375 "# Lines starting with '#' and empty lines are ignored.\n"
376 "# To make changes, remove leading '#', modify option values,\n"
377 "# save this file and then restart CivetWeb.\n\n";
380get_url_to_first_open_port(
const struct mg_context *ctx)
382 static char url[128];
384#define MAX_PORT_COUNT (32)
390 memset(url, 0,
sizeof(url));
393 for (i = 0; i < portNum; i++) {
395 && (ports[i].
is_ssl == 0)) {
396 snprintf(url,
sizeof(url),
"http://localhost:%d/", ports[i].
port);
401 for (i = 0; i < portNum; i++) {
403 && (ports[i].
is_ssl == 1)) {
404 snprintf(url,
sizeof(url),
"https://localhost:%d/", ports[i].
port);
412 "%s://localhost:%d/",
413 (ports[0].
is_ssl ?
"https" :
"http"),
423#if defined(ENABLE_CREATE_CONFIG_FILE) || defined(MAIN_C_UNIT_TEST)
425create_config_file(
const struct mg_context *ctx,
const char *path)
433 if ((fp = fopen(path,
"r")) !=
NULL) {
435 }
else if ((fp = fopen(path,
"a+")) !=
NULL) {
436 fprintf(fp,
"%s", config_file_top_comment);
438 for (i = 0; options[i].
name !=
NULL; i++) {
458 len = strlen(str) + 1;
462 die(
"Cannot allocate %u bytes", (
unsigned)len);
474 const char *opt_value =
NULL;
483 while (options[2 * i] !=
NULL) {
484 if (strcmp(options[2 * i], option_name) == 0) {
485 opt_value = options[2 * i + 1];
499 const char *multi_sep =
NULL;
518 if (!strcmp(
value,
"yes")) {
520 }
else if (!strcmp(
value,
"no")) {
531 die(
"Out of memory");
538 die(
"Out of memory");
549 for (i = 0; default_options[i].
name !=
NULL; i++) {
550 if (!strcmp(default_options[i].
name,
name)) {
566 unsigned long num = strtoul(
value, &chk, 10);
568 if ((chk ==
NULL) || (*chk != 0) || (chk ==
value)) {
591 if ((0 != strcmp(
value,
"yes")) && (0 != strcmp(
value,
"no"))) {
599 if ((0 != strcmp(
value,
"yes")) && (0 != strcmp(
value,
"no"))
600 && (0 != strcmp(
value,
"optional"))) {
618 die(
"Unknown option type - option %s",
name);
622 if (options[2 * i] ==
NULL) {
626 options[2 * i + 2] =
NULL;
628 }
else if (!strcmp(options[2 * i],
name)) {
632 (
char *)
malloc(strlen(options[2 * i + 1])
633 + strlen(multi_sep) + strlen(
value) + 1);
635 die(
"Out of memory");
637 sprintf(
s,
"%s%s%s", options[2 * i + 1], multi_sep,
value);
638 free((
char *)options[2 * i + 1]);
639 options[2 * i + 1] =
s;
642 free((
char *)options[2 * i + 1]);
650 die(
"Too many options specified");
653 if (options[2 * i] ==
NULL) {
654 die(
"Out of memory");
656 if (options[2 * i + 1] ==
NULL) {
657 die(
"Illegal escape sequence, or out of memory");
670 size_t i, j, line_no = 0;
673 fp = fopen(config_file,
"r");
680 fprintf(stdout,
"Loading config file %s\n", config_file);
683 while (fgets(line,
sizeof(line), fp) !=
NULL) {
685 if (!line_no && !memcmp(line,
"\xEF\xBB\xBF", 3)) {
694 for (i = 0; isspace((
unsigned char)p[i]);)
696 if (p[i] ==
'#' || p[i] ==
'\0') {
701 for (j = strlen(p); (j > 0)
702 && (isspace((
unsigned char)p[j - 1])
703 || iscntrl((
unsigned char)p[j - 1]));)
707 for (j = i; !isspace((
unsigned char)p[j]) && (p[j] != 0);)
717 while (isspace((
unsigned char)p[j])) {
724 "%s: line %d is invalid, ignoring it:\n %s",
741 size_t i, cmd_line_opts_start = 1;
742#if defined(CONFIG_FILE2)
747 if ((argc > 1) && (argv[1] !=
NULL) && (argv[1][0] !=
'-')
748 && (argv[1][0] != 0)) {
754 cmd_line_opts_start = 2;
755 }
else if ((p = strrchr(argv[0],
DIRSEP)) ==
NULL) {
775#if defined(CONFIG_FILE2)
780 fp = fopen(CONFIG_FILE2,
"r");
792 if (cmd_line_opts_start == 2) {
795 die(
"Cannot open config file %s: %s",
805 if (argv[1] ==
NULL || memcmp(argv[1],
"-psn_", 5) != 0) {
808 for (i = cmd_line_opts_start; argv[i] !=
NULL; i += 2) {
809 if (argv[i][0] !=
'-' || argv[i + 1] ==
NULL) {
812 if (!
set_option(options, &argv[i][1], argv[i + 1])) {
815 "command line option is invalid, ignoring it:\n %s %s\n",
849 g_website =
"http://civetweb.github.io/civetweb/";
867 && ((path[0] ==
'\\' && path[1] ==
'\\') ||
869 (isalpha((
unsigned char)path[0]) && path[1] ==
':'
870 && path[2] ==
'\\'));
872 return path !=
NULL && path[0] ==
'/';
881 const char *path =
get_option(options, option_name);
889 memset(wbuf, 0,
sizeof(wbuf));
890 memset(mbbuf, 0,
sizeof(mbbuf));
891 len = MultiByteToWideChar(
892 CP_UTF8, 0, path, -1, wbuf,
sizeof(wbuf) /
sizeof(wbuf[0]) - 1);
893 wcstombs(mbbuf, wbuf,
sizeof(mbbuf) - 1);
900 && (stat(path, &st) != 0
901 || ((S_ISDIR(st.st_mode) ? 1 : 0) != must_be_dir))) {
902 warn(
"Invalid path for %s: [%s]: (%s). Make sure that path is either "
903 "absolute, or it is relative to civetweb executable.",
915 const char *option_name,
916 const char *path_to_civetweb_exe)
919 const char *option_value;
923 option_value =
get_option(options, option_name);
931 if ((p = strrchr(path_to_civetweb_exe,
DIRSEP)) ==
NULL) {
937 (
int)(p - path_to_civetweb_exe),
938 path_to_civetweb_exe);
939 path[
sizeof(path) - 1] = 0;
942 strncat(path,
"/",
sizeof(path) - strlen(path) - 1);
943 strncat(path, option_value,
sizeof(path) - strlen(path) - 1);
959#if defined(USE_DUKTAPE)
964run_duktape(
const char *file_name)
970 fprintf(stderr,
"Failed to create a Duktape heap.\n");
988#if defined(__MINGW32__) || defined(__MINGW64__)
998 char *url =
sdup(url_arg);
1002 unsigned long port = 0;
1009 char ebuf[1024] = {0};
1014 fprintf(stderr,
"Out of memory\n");
1020 if (!strncmp(url,
"http://", 7)) {
1023 }
else if (!strncmp(url,
"https://", 8)) {
1028 fprintf(stderr,
"URL must start with http:// or https://\n");
1032 if ((host[0] <= 32) || (host[0] > 126) || (host[0] ==
'/')
1033 || (host[0] ==
':')) {
1034 fprintf(stderr,
"Invalid host\n");
1039 sep = strcspn(host,
"/:");
1040 switch (host[sep]) {
1046 resource = host + sep + 1;
1050 port = strtoul(host + sep + 1, &endp, 10);
1051 if (!endp || (*endp !=
'/' && *endp != 0) || (port < 1)
1052 || (port > 0xFFFF)) {
1053 fprintf(stderr,
"Invalid port\n");
1059 resource = endp + 1;
1065 fprintf(stderr,
"Syntax error\n");
1070 fprintf(stdout,
"Protocol: %s\n", is_ssl ?
"https" :
"http");
1071 fprintf(stdout,
"Host: %s\n", host);
1072 fprintf(stdout,
"Port: %lu\n", port);
1073 fprintf(stdout,
"Resource: %s\n", resource);
1086 char buf[1024] = {0};
1089 fprintf(stdout,
"Connected to %s\n", host);
1093 "GET /%s HTTP/1.1\r\n"
1095 "Connection: close\r\n"
1107 "Response info: %i %s\n",
1112 ret =
mg_read(conn, buf,
sizeof(buf));
1114 fwrite(buf, 1, (
unsigned)ret, stdout);
1115 ret =
mg_read(conn, buf,
sizeof(buf));
1118 fprintf(stdout,
"Closing connection to %s\n", host);
1122 fprintf(stderr,
"Got no response from %s:\n%s\n", host, ebuf);
1128 fprintf(stderr,
"Error connecting to %s:\n%s\n", host, ebuf);
1176static void show_settings_dialog(
void);
1187 char error_text[256];
1193 if (argc > 1 && !strcmp(argv[1],
"-I")) {
1196 (void)MakeConsole();
1209 if (argc > 1 && !strcmp(argv[1],
"-A")) {
1219 if (argc > 1 && !strcmp(argv[1],
"-R")) {
1229 if (argc > 1 && !strcmp(argv[1],
"-C")) {
1234 exit(
run_client(argv[2]) ? EXIT_SUCCESS : EXIT_FAILURE);
1239 if (argc > 1 && !strcmp(argv[1],
"-L")) {
1246 (void)MakeConsole();
1251 fprintf(stderr,
"\nError: Lua support not enabled\n");
1257 if (argc > 1 && !strcmp(argv[1],
"-E")) {
1259#if defined(USE_DUKTAPE)
1264 (void)MakeConsole();
1266 exit(run_duktape(argv[2]));
1269 fprintf(stderr,
"\nError: Ecmascript support not enabled\n");
1276 && (!strcmp(argv[1],
"-h") || !strcmp(argv[1],
"-H")
1277 || !strcmp(argv[1],
"--help"))) {
1282 memset((
void *)options, 0,
sizeof(options));
1290 die(
"Invalid options");
1297#if defined(DAEMONIZE)
1299 for (i = 0; options[i] !=
NULL; i++) {
1300 if (strcmp(options[i],
"daemonize") == 0) {
1301 if (options[i + 1] !=
NULL) {
1303 fprintf(stdout,
"daemonize.\n");
1304 if (daemon(0, 0) != 0) {
1305 fprintf(stdout,
"Failed to daemonize main process.\n");
1309 if ((fp = fopen(PID_FILE,
"w")) == 0) {
1310 fprintf(stdout,
"Can not open %s.\n", PID_FILE);
1313 fprintf(fp,
"%d", getpid());
1325 memset(&callbacks, 0,
sizeof(callbacks));
1327 memset(&init, 0,
sizeof(init));
1333 error.text = error_text;
1334 error.text_buffer_size =
sizeof(error_text);
1341 for (i = 0; options[i] !=
NULL; i++) {
1342 free((
char *)options[i]);
1349 char msgboxtxt[1024];
1352 "Failed to start %s with code %u:\n%s\n\nEdit settings?",
1357 MessageBox(
NULL, msgboxtxt,
"Error", MB_ICONERROR | MB_YESNOCANCEL);
1359 show_settings_dialog();
1368 die(
"Failed to start %s with code %u:\n%s",
1375#if defined(MG_EXPERIMENTAL_INTERFACES)
1379 memset(options, 0,
sizeof(options));
1383 die(
"Cannot open config file %s: %s",
1390 die(
"Invalid options");
1397 fprintf(stdout,
"Domain file %s loaded\n",
g_add_domain[i]);
1400 for (j = 0; options[j] !=
NULL; j++) {
1401 free((
void *)options[j]);
1449 ID_FILE_BUTTONS_DELTA = 1000
1454static SERVICE_STATUS ss;
1455static SERVICE_STATUS_HANDLE hStatus;
1456static const char *service_magic_argument =
"--";
1457static NOTIFYICONDATA TrayIcon;
1458static UINT msg_taskbar_created;
1461ControlHandler(DWORD
code)
1463 if (
code == SERVICE_CONTROL_STOP ||
code == SERVICE_CONTROL_SHUTDOWN) {
1464 ss.dwWin32ExitCode = 0;
1465 ss.dwCurrentState = SERVICE_STOPPED;
1467 SetServiceStatus(hStatus, &ss);
1474 ss.dwServiceType = SERVICE_WIN32;
1475 ss.dwCurrentState = SERVICE_RUNNING;
1476 ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
1478 hStatus = RegisterServiceCtrlHandler(
g_server_name, ControlHandler);
1479 SetServiceStatus(hStatus, &ss);
1481 while (ss.dwCurrentState == SERVICE_RUNNING) {
1486 ss.dwCurrentState = SERVICE_STOPPED;
1487 ss.dwWin32ExitCode = (DWORD)-1;
1488 SetServiceStatus(hStatus, &ss);
1496 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1499 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1503 MessageBox(
NULL, buf,
"Error", MB_OK);
1508save_config(HWND hDlg, FILE *fp)
1510 char value[2000] =
"";
1511 const char *default_value;
1515 fprintf(fp,
"%s", config_file_top_comment);
1517 for (i = 0; options[i].
name !=
NULL; i++) {
1518 id = ID_CONTROLS + i;
1523 IsDlgButtonChecked(hDlg,
id) ?
"yes" :
"no");
1526 GetDlgItemText(hDlg,
id,
value,
sizeof(
value));
1532 fprintf(fp,
"%s %s\n", options[i].
name,
value);
1539struct dlg_proc_param {
1546 BOOL (*fRetry)(
struct dlg_proc_param *data);
1549struct dlg_header_param {
1552 DLGTEMPLATE dlg_template;
1553 WORD menu, dlg_class;
1556 wchar_t fontface[7];
1560struct dlg_complete {
1561 struct dlg_header_param header;
1563 BYTE elements[4096 * 2];
1569FillDialogHeader(
struct dlg_complete *dlg,
const short width)
1571 memset(dlg, 0,
sizeof(*dlg));
1573 dlg->header.dlg_template.style = WS_CAPTION | WS_POPUP | WS_SYSMENU
1574 | WS_VISIBLE | DS_SETFONT | DS_CENTER
1576 dlg->header.dlg_template.dwExtendedStyle = WS_EX_TOOLWINDOW;
1577 dlg->header.dlg_template.cdit = 0;
1578 dlg->header.dlg_template.x = 0;
1579 dlg->header.dlg_template.y = 0;
1580 dlg->header.dlg_template.cx = width;
1581 dlg->header.dlg_template.cy =
1583 dlg->header.menu = 0;
1584 dlg->header.dlg_class = 0;
1585 dlg->header.caption[0] = (wchar_t)0;
1586 dlg->header.fontsize = 8;
1587 wcscpy(dlg->header.fontface, L
"Tahoma");
1595static INT_PTR CALLBACK
1596SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
1602 const char *file_options[
MAX_OPTIONS * 2 + 1] = {0};
1604 struct dlg_proc_param *pdlg_proc_param;
1609 DestroyWindow(hDlg);
1613 switch (LOWORD(wParam)) {
1616 EnableWindow(GetDlgItem(hDlg, ID_SAVE),
FALSE);
1618 save_config(hDlg, fp);
1623 EnableWindow(GetDlgItem(hDlg, ID_SAVE),
TRUE);
1626 case ID_RESET_DEFAULTS:
1627 for (i = 0; default_options[i].
name !=
NULL; i++) {
1633 CheckDlgButton(hDlg,
1635 !strcmp(
value,
"yes") ? BST_CHECKED
1638 SetWindowText(GetDlgItem(hDlg, ID_CONTROLS + i),
value);
1645 for (i = 0; default_options[i].
name !=
NULL; i++) {
1648 for (j = 0; file_options[j * 2] !=
NULL; j++) {
1649 if (!strcmp(
name, file_options[j * 2])) {
1650 value = file_options[j * 2 + 1];
1657 CheckDlgButton(hDlg,
1659 !strcmp(
value,
"yes") ? BST_CHECKED
1662 SetWindowText(GetDlgItem(hDlg, ID_CONTROLS + i),
value);
1666 free((
void *)file_options[2 * i]);
1667 free((
void *)file_options[2 * i + 1]);
1671 case ID_RESET_ACTIVE:
1672 for (i = 0; default_options[i].
name !=
NULL; i++) {
1676 CheckDlgButton(hDlg,
1678 !strcmp(
value,
"yes") ? BST_CHECKED
1681 SetDlgItemText(hDlg,
1689 for (i = 0; default_options[i].
name !=
NULL; i++) {
1693 && LOWORD(wParam) == ID_CONTROLS + i + ID_FILE_BUTTONS_DELTA) {
1701 memset(&bi, 0,
sizeof(bi));
1702 bi.hwndOwner = (HWND)hDlg;
1703 bi.ulFlags = BIF_RETURNONLYFSDIRS;
1706 bi.lpszTitle =
name;
1708 SHGetPathFromIDList(SHBrowseForFolder(&bi), path);
1713 memset(&of, 0,
sizeof(of));
1714 of.lStructSize =
sizeof(of);
1715 of.hwndOwner = (HWND)hDlg;
1716 of.lpstrFile = path;
1717 of.nMaxFile =
sizeof(path);
1720 OFN_CREATEPROMPT | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
1723 of.lpstrTitle =
name;
1725 GetOpenFileName(&of);
1728 if (path[0] !=
'\0') {
1730 SetWindowText(GetDlgItem(hDlg, ID_CONTROLS + i), path);
1739 pdlg_proc_param = (
struct dlg_proc_param *)lParam;
1740 pdlg_proc_param->hWnd = hDlg;
1743 SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
1744 SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
1748 strcat(title,
" settings");
1749 SetWindowText(hDlg, title);
1752 SetFocus(GetDlgItem(hDlg, ID_SAVE));
1755 SendMessage(hDlg, WM_COMMAND, ID_RESET_ACTIVE, 0);
1768static INT_PTR CALLBACK
1769InputDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
1771 static struct dlg_proc_param *inBuf = 0;
1778 DestroyWindow(hDlg);
1782 ctrlId = LOWORD(wParam);
1783 if (ctrlId == IDOK) {
1785 hIn = GetDlgItem(hDlg, ID_INPUT_LINE);
1789 GetWindowText(hIn, inBuf->buffer, (
int)inBuf->buflen);
1790 if (inBuf->buffer[0] != 0) {
1792 EndDialog(hDlg, IDOK);
1796 EndDialog(hDlg, IDOK);
1799 }
else if (ctrlId == IDRETRY) {
1802 hIn = GetDlgItem(hDlg, inBuf->idRetry);
1806 GetWindowText(hIn, inBuf->buffer, (
int)inBuf->buflen);
1807 if (inBuf->fRetry) {
1808 if (inBuf->fRetry(inBuf)) {
1809 SetWindowText(hIn, inBuf->buffer);
1814 }
else if (ctrlId == IDCANCEL) {
1815 EndDialog(hDlg, IDCANCEL);
1821 hIn = GetDlgItem(hDlg, ID_INPUT_LINE);
1824 inBuf = (
struct dlg_proc_param *)lParam;
1830 SetWindowText(hDlg, inBuf->name);
1837 SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
1838 SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
1839 SendMessage(hIn, EM_LIMITTEXT, inBuf->buflen - 1, 0);
1840 SetWindowText(hIn, inBuf->buffer);
1855suggest_passwd(
char *passwd)
1865 GetSystemTimeAsFileTime(&num.ft);
1866 num.li.HighPart |= (LONG)GetCurrentProcessId();
1868 while (num.li.QuadPart) {
1869 u = (unsigned)(num.li.QuadPart % 95);
1870 num.li.QuadPart -= u;
1871 num.li.QuadPart /= 95;
1872 *p = (char)(u + 32);
1878static void add_control(
struct dlg_complete *dlg,
1886 const char *caption);
1890get_password(
const char *user,
1893 unsigned passwd_len)
1898 short LABEL_WIDTH = 90;
1901 struct dlg_complete dlg;
1902 static struct dlg_proc_param s_dlg_proc_param;
1909 if (s_dlg_proc_param.guard == 0) {
1910 memset(&s_dlg_proc_param, 0,
sizeof(s_dlg_proc_param));
1911 s_dlg_proc_param.guard = 1;
1913 SetForegroundWindow(s_dlg_proc_param.hWnd);
1917 FillDialogHeader(&dlg, WIDTH);
1921 s_dlg_proc_param.guard = 0;
1926 memset(passwd, 0, passwd_len);
1927 suggest_passwd(passwd);
1930 s_dlg_proc_param.buffer = passwd;
1931 s_dlg_proc_param.buflen = passwd_len;
1938 WS_VISIBLE | WS_CHILD,
1947 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
1951 WIDTH - LABEL_WIDTH - 25,
1959 WS_VISIBLE | WS_CHILD,
1968 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
1972 WIDTH - LABEL_WIDTH - 25,
1980 WS_VISIBLE | WS_CHILD,
1989 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | WS_TABSTOP,
1992 WIDTH - LABEL_WIDTH - 25,
1996 y += (WORD)(HEIGHT * 2);
2000 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2009 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2016 dlg.header.dlg_template.cy = y + (WORD)(HEIGHT * 1.5);
2018 s_dlg_proc_param.name =
"Modify password";
2019 s_dlg_proc_param.fRetry =
NULL;
2022 == DialogBoxIndirectParam(
NULL,
2023 &dlg.header.dlg_template,
2026 (LPARAM)&s_dlg_proc_param));
2028 s_dlg_proc_param.hWnd =
NULL;
2029 s_dlg_proc_param.guard = 0;
2036static INT_PTR CALLBACK
2037PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
2039 static const char *passfile = 0;
2040 char domain[256], user[256], password[256];
2042 struct dlg_proc_param *pdlg_proc_param;
2047 DestroyWindow(hDlg);
2051 ctrlId = LOWORD(wParam);
2052 if (ctrlId == ID_ADD_USER) {
2054 GetWindowText(GetDlgItem(hDlg, ID_ADD_USER_NAME),
2057 GetWindowText(GetDlgItem(hDlg, ID_ADD_USER_REALM),
2060 if (get_password(user, domain, password,
sizeof(password))) {
2062 EndDialog(hDlg, IDOK);
2064 }
else if ((ctrlId >= (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3))
2065 && (ctrlId < (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 4))) {
2067 GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 3),
2070 GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 2),
2073 if (get_password(user, domain, password,
sizeof(password))) {
2075 EndDialog(hDlg, IDOK);
2077 }
else if ((ctrlId >= (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 2))
2078 && (ctrlId < (ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3))) {
2080 GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 2),
2083 GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA),
2087 EndDialog(hDlg, IDOK);
2092 pdlg_proc_param = (
struct dlg_proc_param *)lParam;
2093 pdlg_proc_param->hWnd = hDlg;
2094 passfile = pdlg_proc_param->name;
2095 SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
2096 SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
2097 SetWindowText(hDlg, passfile);
2098 SetFocus(GetDlgItem(hDlg, ID_ADD_USER_NAME));
2110add_control(
struct dlg_complete *dlg,
2118 const char *caption)
2120 DLGITEMTEMPLATE *tp;
2122 WORD cap_len = caption ? (WORD)strlen(caption) : 0;
2124 DWORD expected_size =
sizeof(DLGITEMTEMPLATE) + 4 + (cap_len + 1) * 2 + 2;
2126 if ((dlg->used + expected_size + 16)
2127 >=
sizeof(dlg->elements)) {
2133 dlg->header.dlg_template.cdit++;
2136 while (dlg->used % 4) {
2141 tp = (DLGITEMTEMPLATE *)(dlg->elements + dlg->used);
2144 tp->dwExtendedStyle = 0;
2149 dlg->used +=
sizeof(*tp);
2152 p = (LPWORD)(dlg->elements + dlg->used);
2155 dlg->used += 2 *
sizeof(*p);
2158 p = (LPWORD)(dlg->elements + dlg->used);
2159 for (i = 0; i < cap_len; i++) {
2160 p[i] = (WCHAR)caption[i];
2163 dlg->used += (cap_len + 1) *
sizeof(*p);
2166 while (dlg->used % 2) {
2171 p = (LPWORD)(dlg->elements + dlg->used);
2173 dlg->used +=
sizeof(*p);
2178optioncmp(
const char *o1,
const char *o2)
2181 while (*o1 || *o2) {
2182 int c1 = 256 * (int)*o1;
2183 int c2 = 256 * (int)*o2;
2186 else if (*o1 ==
'_')
2190 else if (*o2 ==
'_')
2204show_settings_dialog(
void)
2208 short BORDER_WIDTH = 10;
2209 short BORDER_HEIGTH = BORDER_WIDTH / 2;
2210 short CELL_WIDTH = 125;
2211 short LABEL_WIDTH = 115;
2212 short FILE_DIALOG_BUTTON_WIDTH = 15;
2213 short NO_OF_COLUMNS = 3;
2214 short NO_OF_OPTIONS = 0;
2215 short NO_OF_OPTION_SPACES = 0;
2216 short NO_OF_ROWS = 0;
2219 short COLUMN_WIDTH = LABEL_WIDTH + CELL_WIDTH + BORDER_WIDTH;
2220 short DIALOG_WIDTH = BORDER_WIDTH + NO_OF_COLUMNS * COLUMN_WIDTH;
2225 WORD i, cl, nelems = 0;
2226 short x, y, next_cell_width, next_cell_height;
2227 static struct dlg_proc_param s_dlg_proc_param;
2228 short *option_index, *option_top, *option_bottom;
2230 struct dlg_complete dlg;
2232 if (s_dlg_proc_param.guard == 0) {
2233 memset(&s_dlg_proc_param, 0,
sizeof(s_dlg_proc_param));
2234 s_dlg_proc_param.guard = 1;
2236 SetForegroundWindow(s_dlg_proc_param.hWnd);
2240 FillDialogHeader(&dlg, DIALOG_WIDTH);
2244 for (i = 0; cv_options[i].
name !=
NULL; i++) {
2248 NO_OF_OPTION_SPACES += 2;
2251 NO_OF_OPTION_SPACES++;
2254 NO_OF_ROWS = (NO_OF_OPTION_SPACES + NO_OF_COLUMNS - 1) / NO_OF_COLUMNS;
2262 option_index = (
short *)
calloc(NO_OF_OPTIONS + 2 * NO_OF_COLUMNS,
2264 if (!option_index) {
2268 option_top = option_index + NO_OF_OPTIONS;
2269 option_bottom = option_top + NO_OF_COLUMNS;
2272 for (i = 0; i < NO_OF_OPTIONS; i++) {
2273 option_index[i] = i;
2278 for (i = 1; i < NO_OF_OPTIONS; i++) {
2279 if (optioncmp(cv_options[option_index[i - 1]].
name,
2280 cv_options[option_index[i]].
name)
2282 short swap = option_index[i];
2283 option_index[i] = option_index[i - 1];
2284 option_index[i - 1] = swap;
2294 for (i = 0; i < NO_OF_OPTIONS; i++) {
2297 const struct mg_option *opt = &cv_options[option_index[i]];
2301 style = WS_CHILD | WS_VISIBLE | WS_TABSTOP;
2310 x = BORDER_WIDTH + COLUMN_WIDTH * (nelems / NO_OF_ROWS);
2311 y = BORDER_HEIGTH + HEIGHT + HEIGHT * (nelems % NO_OF_ROWS);
2312 next_cell_width = CELL_WIDTH;
2313 next_cell_height = HEIGHT - 3;
2316 if ((nelems % NO_OF_ROWS) == 0) {
2318 option_top[nelems / NO_OF_ROWS] = option_index[i];
2321 option_bottom[nelems / NO_OF_ROWS] = option_index[i];
2327 style |= WS_BORDER | ES_AUTOHSCROLL;
2331 style |= BS_AUTOCHECKBOX;
2335 style |= WS_BORDER | ES_AUTOHSCROLL;
2341 ID_CONTROLS + option_index[i] + ID_FILE_BUTTONS_DELTA,
2342 WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
2343 x + LABEL_WIDTH + CELL_WIDTH - FILE_DIALOG_BUTTON_WIDTH,
2345 FILE_DIALOG_BUTTON_WIDTH,
2349 next_cell_width -= FILE_DIALOG_BUTTON_WIDTH + BORDER_WIDTH / 2;
2355 style |= WS_BORDER | ES_AUTOHSCROLL | ES_MULTILINE | ES_WANTRETURN
2356 | WS_VSCROLL | ES_AUTOVSCROLL;
2359 next_cell_height += HEIGHT;
2364 style |= WS_BORDER | ES_AUTOHSCROLL;
2371 WS_VISIBLE | WS_CHILD,
2381 ID_CONTROLS + option_index[i],
2392 y = ((nelems + NO_OF_COLUMNS - 1) / NO_OF_COLUMNS + 1) * HEIGHT;
2393 for (i = 0; i < NO_OF_COLUMNS; i++) {
2395 " Settings %c - %c ",
2396 cv_options[option_top[i]].
name[0],
2397 cv_options[option_bottom[i]].
name[0]);
2401 WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
2403 + i * (DIALOG_WIDTH - BORDER_WIDTH) / NO_OF_COLUMNS,
2405 (DIALOG_WIDTH - BORDER_WIDTH) / NO_OF_COLUMNS,
2415 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2424 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2429 "Reset to defaults");
2433 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2438 "Reload from file");
2442 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2451 WS_CHILD | WS_VISIBLE | WS_DISABLED,
2459 dlg.header.dlg_template.cy = y + HEIGHT;
2461 s_dlg_proc_param.fRetry =
NULL;
2463 DialogBoxIndirectParam(
NULL,
2464 &dlg.header.dlg_template,
2467 (LPARAM)&s_dlg_proc_param);
2471 s_dlg_proc_param.hWnd =
NULL;
2472 s_dlg_proc_param.guard = 0;
2477change_password_file()
2482 short LABEL_WIDTH = 90;
2487 char strbuf[256], u[256], d[256];
2492 static struct dlg_proc_param s_dlg_proc_param;
2493 struct dlg_complete dlg;
2495 if (s_dlg_proc_param.guard == 0) {
2496 memset(&s_dlg_proc_param, 0,
sizeof(s_dlg_proc_param));
2497 s_dlg_proc_param.guard = 1;
2499 SetForegroundWindow(s_dlg_proc_param.hWnd);
2503 memset(&of, 0,
sizeof(of));
2504 of.lStructSize =
sizeof(of);
2505 of.hwndOwner = (HWND)hDlg;
2506 of.lpstrFile = path;
2507 of.nMaxFile =
sizeof(path);
2509 of.Flags = OFN_CREATEPROMPT | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
2511 if (!GetSaveFileName(&of)) {
2513 s_dlg_proc_param.guard = 0;
2517 f = fopen(path,
"a+");
2521 MessageBox(
NULL, path,
"Can not open file", MB_ICONERROR);
2522 s_dlg_proc_param.guard = 0;
2527 s_dlg_proc_param.hWnd =
NULL;
2529 FillDialogHeader(&dlg, WIDTH);
2531 f = fopen(path,
"r+");
2533 MessageBox(
NULL, path,
"Can not open file", MB_ICONERROR);
2534 s_dlg_proc_param.guard = 0;
2539 while (fgets(strbuf,
sizeof(strbuf), f)) {
2540 if (sscanf(strbuf,
"%255[^:]:%255[^:]:%*s", u, d) != 2) {
2545 y = (nelems + 1) * HEIGHT + 5;
2548 ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA * 3,
2549 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2557 ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA * 2,
2558 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2566 ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA,
2567 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
2576 ID_CONTROLS + nelems,
2577 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
2589 y = (nelems + 1) * HEIGHT + 10;
2593 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2602 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
2612 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
2620 y = (nelems + 2) * HEIGHT + 10;
2624 WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
2635 WS_CHILD | WS_VISIBLE | WS_DISABLED,
2642 dlg.header.dlg_template.cy = y + 20;
2644 s_dlg_proc_param.name = path;
2645 s_dlg_proc_param.fRetry =
NULL;
2648 == DialogBoxIndirectParam(
NULL,
2649 &dlg.header.dlg_template,
2652 (LPARAM)&s_dlg_proc_param))
2655 s_dlg_proc_param.hWnd =
NULL;
2656 s_dlg_proc_param.guard = 0;
2661sysinfo_reload(
struct dlg_proc_param *prm)
2663 static char *buf = 0;
2669 buf = (
char *)
malloc(cl + 1);
2671 if ((rl > cl) || (rl <= 0)) {
2673 prm->buffer =
"Server not running";
2674 }
else if (rl <= 0) {
2675 prm->buffer =
"No server statistics available";
2677 prm->buffer =
"Please retry";
2693 short LABEL_WIDTH = 50;
2698 static struct dlg_proc_param s_dlg_proc_param;
2699 struct dlg_complete dlg;
2702 if (s_dlg_proc_param.guard == 0) {
2703 memset(&s_dlg_proc_param, 0,
sizeof(s_dlg_proc_param));
2704 s_dlg_proc_param.guard = 1;
2706 SetForegroundWindow(s_dlg_proc_param.hWnd);
2711 FillDialogHeader(&dlg, WIDTH);
2717 WS_VISIBLE | WS_CHILD,
2722 "System Information:");
2726 WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
2727 | ES_AUTOVSCROLL | ES_MULTILINE | ES_READONLY,
2730 WIDTH - LABEL_WIDTH - 25,
2734 y += (WORD)(HEIGHT * 8);
2739 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2740 WIDTH - 10 - 55 - 10 - 55,
2749 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
2756 dlg.header.dlg_template.cy = y + (WORD)(HEIGHT * 1.5);
2758 s_dlg_proc_param.name =
"System information";
2759 s_dlg_proc_param.fRetry = sysinfo_reload;
2760 s_dlg_proc_param.idRetry = ID_CONTROLS + 1;
2763 == DialogBoxIndirectParam(
NULL,
2764 &dlg.header.dlg_template,
2767 (LPARAM)&s_dlg_proc_param));
2769 s_dlg_proc_param.hWnd =
NULL;
2770 s_dlg_proc_param.guard = 0;
2777manage_service(
int action)
2780 SC_HANDLE hSCM =
NULL, hService =
NULL;
2781 SERVICE_DESCRIPTION descr;
2787 if ((hSCM = OpenSCManager(
NULL,
2789 action == ID_INSTALL_SERVICE ? GENERIC_WRITE
2794 }
else if (action == ID_INSTALL_SERVICE) {
2795 path[
sizeof(path) - 1] = 0;
2796 GetModuleFileName(
NULL, path,
sizeof(path) - 1);
2797 strncat(path,
" ",
sizeof(path) - 1 - strlen(path));
2798 strncat(path, service_magic_argument,
sizeof(path) - 1 - strlen(path));
2799 hService = CreateService(hSCM,
2803 SERVICE_WIN32_OWN_PROCESS,
2805 SERVICE_ERROR_NORMAL,
2813 ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &descr);
2817 }
else if (action == ID_REMOVE_SERVICE) {
2818 if ((hService = OpenService(hSCM, service_name, DELETE)) ==
NULL
2819 || !DeleteService(hService)) {
2822 }
else if ((hService =
2823 OpenService(hSCM, service_name, SERVICE_QUERY_STATUS))
2829 CloseServiceHandle(hService);
2831 CloseServiceHandle(hSCM);
2838add_icon_to_systray(HWND hWnd)
2842 TrayIcon.cbSize =
sizeof(TrayIcon);
2843 TrayIcon.uID = ID_ICON;
2844 TrayIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
2845 TrayIcon.hIcon = hIcon;
2846 TrayIcon.hWnd = hWnd;
2848 TrayIcon.uCallbackMessage = WM_USER;
2849 Shell_NotifyIcon(NIM_ADD, &TrayIcon);
2851 TrayIcon.cbSize = 0;
2857static LRESULT CALLBACK
2858WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2861 int service_installed;
2869 if ((__argv[1] !=
NULL) && !strcmp(__argv[1], service_magic_argument)) {
2870 static SERVICE_TABLE_ENTRY service_table[2];
2871 char *service_argv[2];
2873 service_argv[0] = __argv[0];
2874 service_argv[1] =
NULL;
2878 memset(service_table, 0,
sizeof(service_table));
2880 service_table[0].lpServiceProc =
2881 (LPSERVICE_MAIN_FUNCTION)ServiceMain;
2883 StartServiceCtrlDispatcher(service_table);
2891 switch (LOWORD(wParam)) {
2894 if (TrayIcon.cbSize) {
2895 Shell_NotifyIcon(NIM_DELETE, &TrayIcon);
2901 show_settings_dialog();
2904 change_password_file();
2909 case ID_INSTALL_SERVICE:
2910 case ID_REMOVE_SERVICE:
2911 manage_service(LOWORD(wParam));
2916 const char *url = get_url_to_first_open_port(
g_ctx);
2932 case WM_LBUTTONDBLCLK:
2933 hMenu = CreatePopupMenu();
2935 MF_STRING | MF_GRAYED,
2938 AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR,
"");
2939 service_installed = manage_service(0);
2942 "NT service: %s installed",
2943 service_installed ?
"" :
"not");
2944 buf[
sizeof(buf) - 1] = 0;
2945 AppendMenu(hMenu, MF_STRING | MF_GRAYED, ID_SEPARATOR, buf);
2947 MF_STRING | (service_installed ? MF_GRAYED : 0),
2951 MF_STRING | (!service_installed ? MF_GRAYED : 0),
2953 "Deinstall service");
2954 AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR,
"");
2955 AppendMenu(hMenu, MF_STRING, ID_CONNECT,
"Start browser");
2956 AppendMenu(hMenu, MF_STRING, ID_SETTINGS,
"Edit settings");
2957 AppendMenu(hMenu, MF_STRING, ID_PASSWORD,
"Modify password file");
2958 AppendMenu(hMenu, MF_STRING, ID_SYSINFO,
"Show system info");
2959 AppendMenu(hMenu, MF_STRING, ID_WEBSITE,
"Visit website");
2960 AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR,
"");
2961 AppendMenu(hMenu, MF_STRING, ID_QUIT,
"Exit");
2963 SetForegroundWindow(hWnd);
2964 TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hWnd,
NULL);
2965 PostMessage(hWnd, WM_NULL, 0, 0);
2973 if (TrayIcon.cbSize) {
2974 Shell_NotifyIcon(NIM_DELETE, &TrayIcon);
2981 if (msg == msg_taskbar_created) {
2982 add_icon_to_systray(hWnd);
2987 return DefWindowProc(hWnd, msg, wParam, lParam);
2997 HANDLE hConWnd = GetConsoleWindow();
3000 if (hConWnd ==
NULL) {
3001 if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
3003 if (!AllocConsole()) {
3004 err = GetLastError();
3005 if (err == ERROR_ACCESS_DENIED) {
3008 "Insufficient rights to create a console window",
3013 AttachConsole(GetCurrentProcessId());
3017 hConWnd = GetConsoleWindow();
3019 if (hConWnd ==
NULL) {
3025 if (
NULL == freopen(
"CONIN$",
"r", stdin)) {
3028 if (
NULL == freopen(
"CONOUT$",
"w", stdout)) {
3031 if (
NULL == freopen(
"CONOUT$",
"w", stderr)) {
3037 if (hConWnd ==
NULL) {
3049WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline,
int show)
3056 (void)MakeConsole();
3066 msg_taskbar_created = RegisterWindowMessage(
"TaskbarCreated");
3068 memset(&cls, 0,
sizeof(cls));
3069 cls.lpfnWndProc = WindowProc;
3070 cls.hInstance = GetModuleHandle(
NULL);
3071 cls.hIcon = LoadIcon(
NULL, IDI_APPLICATION);
3074 RegisterClass(&cls);
3075 hWnd = CreateWindow(cls.lpszClassName,
3077 WS_OVERLAPPEDWINDOW,
3086 ShowWindow(hWnd, SW_HIDE);
3093 hIcon = (HICON)LoadImage(GetModuleHandle(
NULL),
3094 MAKEINTRESOURCE(ID_ICON),
3101 add_icon_to_systray(hWnd);
3104 while (GetMessage(&msg, hWnd, 0, 0) > 0) {
3105 TranslateMessage(&msg);
3106 DispatchMessage(&msg);
3112 return (
int)msg.wParam;
3118main(
int argc,
char *argv[])
3123 return WinMain(0, 0, 0, 0);
3127#elif defined(USE_COCOA)
3128#import <Cocoa/Cocoa.h>
3130@interface Civetweb : NSObject <NSApplicationDelegate>
3135@implementation Civetweb
3138 [[NSWorkspace sharedWorkspace]
3139 openURL:[NSURL URLWithString:[NSString stringWithUTF8String:
3140 get_url_to_first_open_port(
3146 NSString *path = [NSString stringWithUTF8String:g_config_file_name];
3147 if (![[NSWorkspace sharedWorkspace] openFile:path
3148 withApplication:
@"TextEdit"]) {
3149 NSAlert *alert = [[[NSAlert alloc] init] autorelease];
3150 [alert setAlertStyle:NSWarningAlertStyle];
3151 [alert setMessageText:NSLocalizedString(@"Unable to open config file.",
3153 [alert setInformativeText:path];
3154 (void)[alert runModal];
3159 [NSApp terminate:nil];
3164main(
int argc,
char *argv[])
3170 [NSAutoreleasePool new];
3171 [NSApplication sharedApplication];
3174 Civetweb *myDelegate = [[Civetweb alloc] autorelease];
3175 [NSApp setDelegate:myDelegate];
3178 ProcessSerialNumber psn = {0, kCurrentProcess};
3179 TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
3180 SetFrontProcess(&psn);
3183 id menu = [[NSMenu new] autorelease];
3187 addItem:[[[NSMenuItem alloc]
3190 initWithTitle:[NSString stringWithUTF8String:g_server_name]
3191 action:@selector(noexist)
3192 keyEquivalent:@""] autorelease]];
3195 [menu addItem:[[[NSMenuItem alloc] initWithTitle:@"Edit configuration"
3196 action:@selector(editConfig)
3197 keyEquivalent:@""] autorelease]];
3201 addItem:[[[NSMenuItem alloc] initWithTitle:@"Open web root in a browser"
3202 action:@selector(openBrowser)
3203 keyEquivalent:@""] autorelease]];
3206 [menu addItem:[NSMenuItem separatorItem]];
3209 [menu addItem:[[[NSMenuItem alloc] initWithTitle:@"Quit"
3210 action:@selector(shutDown)
3211 keyEquivalent:@"q"] autorelease]];
3214 id item = [[[NSStatusBar systemStatusBar]
3215 statusItemWithLength:NSVariableStatusItemLength] retain];
3216 [item setHighlightMode:YES];
3217 [item setImage:[NSImage imageNamed:@"civetweb_22x22.png"]];
3218 [item setMenu:menu];
3221 [NSApp activateIgnoringOtherApps:YES];
3227 return EXIT_SUCCESS;
3241 "%s started on port(s) %s with web root [%s]\n",
3251 "Exiting on signal %d, waiting for all threads to finish...",
3255 fprintf(stdout,
"%s",
" done.\n");
3259 return EXIT_SUCCESS;
CIVETWEB_API int mg_start_domain(struct mg_context *ctx, const char **options)
CIVETWEB_API const char * mg_version(void)
CIVETWEB_API struct mg_context * mg_start2(struct mg_init_data *init, struct mg_error_data *error)
CIVETWEB_API void mg_stop(struct mg_context *ctx)
CIVETWEB_API int mg_get_server_ports(const struct mg_context *ctx, int size, struct mg_server_port *ports)
CIVETWEB_API int mg_strcasecmp(const char *s1, const char *s2)
CIVETWEB_API const struct mg_response_info * mg_get_response_info(const struct mg_connection *conn)
CIVETWEB_API int mg_get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout)
CIVETWEB_API unsigned mg_exit_library(void)
CIVETWEB_API int mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
CIVETWEB_API int mg_modify_passwords_file(const char *fname, const char *domain, const char *user, const char *pass)
CIVETWEB_API const struct mg_option * mg_get_valid_options(void)
CIVETWEB_API unsigned mg_init_library(unsigned features)
CIVETWEB_API int mg_printf(struct mg_connection *conn, const char *fmt,...)
CIVETWEB_API struct mg_connection * mg_connect_client(const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size)
CIVETWEB_API void mg_close_connection(struct mg_connection *conn)
CIVETWEB_API int mg_get_system_info(char *buffer, int buflen)
CIVETWEB_API int mg_read(struct mg_connection *conn, void *buf, size_t len)
@ MG_CONFIG_TYPE_DIRECTORY
@ MG_CONFIG_TYPE_EXT_PATTERN
@ MG_CONFIG_TYPE_STRING_MULTILINE
@ MG_CONFIG_TYPE_STRING_LIST
@ MG_CONFIG_TYPE_YES_NO_OPTIONAL
int run_lua(const char *file_name)
DUK_EXTERNAL void duk_destroy_heap(duk_context *ctx)
DUK_EXTERNAL void duk_pop(duk_context *ctx)
#define duk_safe_to_string(ctx, index)
#define duk_create_heap_default()
#define duk_peval_file(ctx, path)
static void error(LoadState *S, const char *why)
CURL_EXTERN CURLMcode curl_socket_t s
const struct mg_callbacks * callbacks
const char ** configuration_options
const char * default_value
static NO_RETURN void die(const char *fmt,...)
static int read_config_file(const char *config_file, const char **options)
static NO_RETURN void show_usage_and_exit(const char *exeName)
static const char * g_server_name
static void set_absolute_path(const char *options[], const char *option_name, const char *path_to_civetweb_exe)
static const char * g_icon_name
static int run_client(const char *url_arg)
static void free_system_info(void)
static void warn(const char *fmt,...)
static int sanitize_options(const char *options[], const char *arg0)
#define DEBUG_ASSERT(cond)
static void stop_civetweb(void)
static char * g_system_info
static int g_num_add_domains
static char g_server_base_name[40]
static void start_civetweb(int argc, char *argv[])
static char * sdup(const char *str)
static int is_path_absolute(const char *path)
static int set_option(const char **options, const char *name, const char *value)
#define abs_path(rel, abs, abs_size)
static const char ** g_add_domain
static void show_server_name(void)
static const char * get_option(const char **options, const char *option_name)
static void process_command_line_arguments(int argc, char *argv[], const char **options)
static char g_config_file_name[PATH_MAX]
static const char * g_website
static struct tuser_data g_user_data
static struct mg_context * g_ctx
static struct mg_option main_config_options[]
#define IGNORE_UNUSED_RESULT(a)
#define MAX_CONF_FILE_LINE_SIZE
static int verify_existence(const char **options, const char *option_name, int must_be_dir)
static void init_server_name(void)
static void init_system_info(void)
#define PASSWORDS_FILE_NAME
static void WINCDECL signal_handler(int sig_num)