|
@@ -83,11 +83,16 @@ static char *server_name; /* Set by init_server_name() */
|
|
|
static char *icon_name; /* Set by init_server_name() */
|
|
|
static char config_file[PATH_MAX] = ""; /* Set by process_command_line_arguments() */
|
|
|
static struct mg_context *ctx; /* Set by start_civetweb() */
|
|
|
+static int guard = 0; /* test if any dialog is already open */
|
|
|
|
|
|
#if !defined(CONFIG_FILE)
|
|
|
#define CONFIG_FILE "civetweb.conf"
|
|
|
#endif /* !CONFIG_FILE */
|
|
|
|
|
|
+#if !defined(PASSWORDS_FILE_NAME)
|
|
|
+#define PASSWORDS_FILE_NAME ".htpasswd"
|
|
|
+#endif
|
|
|
+
|
|
|
/* backup config file */
|
|
|
#if !defined(CONFIG_FILE2) && defined(LINUX)
|
|
|
#define CONFIG_FILE2 "/usr/local/etc/civetweb.conf"
|
|
@@ -168,7 +173,7 @@ static void show_usage_and_exit(void)
|
|
|
static const char *config_file_top_comment =
|
|
|
"# Civetweb web server configuration file.\n"
|
|
|
"# For detailed description of every option, visit\n"
|
|
|
- "# https://github.com/sunsetbrew/civetweb/blob/master/docs/UserManual.md\n"
|
|
|
+ "# https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md\n"
|
|
|
"# Lines starting with '#' and empty lines are ignored.\n"
|
|
|
"# To make a change, remove leading '#', modify option's value,\n"
|
|
|
"# save this file and then restart Civetweb.\n\n";
|
|
@@ -575,9 +580,9 @@ static void start_civetweb(int argc, char *argv[])
|
|
|
#ifdef _WIN32
|
|
|
enum {
|
|
|
ID_ICON = 100, ID_QUIT, ID_SETTINGS, ID_SEPARATOR, ID_INSTALL_SERVICE,
|
|
|
- ID_REMOVE_SERVICE, ID_STATIC, ID_GROUP,
|
|
|
+ ID_REMOVE_SERVICE, ID_STATIC, ID_GROUP, ID_PASSWORD,
|
|
|
ID_SAVE, ID_RESET_DEFAULTS, ID_RESET_FILE, ID_RESET_ACTIVE,
|
|
|
- ID_STATUS, ID_CONNECT,
|
|
|
+ ID_STATUS, ID_CONNECT, ID_ADD_USER, ID_ADD_USER_NAME, ID_ADD_USER_REALM,
|
|
|
|
|
|
/* All dynamically created text boxes for options have IDs starting from
|
|
|
ID_CONTROLS, incremented by one. */
|
|
@@ -622,7 +627,6 @@ static void WINAPI ServiceMain(void)
|
|
|
SetServiceStatus(hStatus, &ss);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
static void show_error(void)
|
|
|
{
|
|
|
char buf[256];
|
|
@@ -667,7 +671,8 @@ static void save_config(HWND hDlg, FILE *fp)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|
|
+
|
|
|
+static BOOL CALLBACK SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|
|
{
|
|
|
FILE *fp;
|
|
|
int i, j;
|
|
@@ -740,7 +745,7 @@ static BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|
|
CheckDlgButton(hDlg, ID_CONTROLS + i, !strcmp(value, "yes") ?
|
|
|
BST_CHECKED : BST_UNCHECKED);
|
|
|
} else {
|
|
|
- SetWindowText(GetDlgItem(hDlg, ID_CONTROLS + i), value);
|
|
|
+ SetDlgItemText(hDlg, ID_CONTROLS + i, value == NULL ? "" : value);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
@@ -791,18 +796,73 @@ static BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|
|
free(title);
|
|
|
}
|
|
|
SetFocus(GetDlgItem(hDlg, ID_SAVE));
|
|
|
- for (i = 0; default_options[i].name != NULL; i++) {
|
|
|
- name = default_options[i].name;
|
|
|
- value = mg_get_option(ctx, name);
|
|
|
- if (default_options[i].type == CONFIG_TYPE_BOOLEAN) {
|
|
|
- CheckDlgButton(hDlg, ID_CONTROLS + i, !strcmp(value, "yes") ?
|
|
|
- BST_CHECKED : BST_UNCHECKED);
|
|
|
- } else {
|
|
|
- SetDlgItemText(hDlg, ID_CONTROLS + i, value == NULL ? "" : value);
|
|
|
- }
|
|
|
+
|
|
|
+ /* Init dialog with active settings */
|
|
|
+ SendMessage(hDlg, WM_COMMAND, ID_RESET_ACTIVE, 0);
|
|
|
+ /* alternative: SendMessage(hDlg, WM_COMMAND, ID_RESET_FILE, 0); */
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return FALSE;
|
|
|
+}
|
|
|
+
|
|
|
+static void GetPassword(char * password, unsigned maxlen)
|
|
|
+{
|
|
|
+ assert(maxlen>=255);
|
|
|
+ /* TODO: replace by a proper dialog */
|
|
|
+ strcpy(password, "12345");
|
|
|
+}
|
|
|
+
|
|
|
+static BOOL CALLBACK PasswordDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lP)
|
|
|
+{
|
|
|
+ static const char *passfile = 0;
|
|
|
+ char domain[256], user[256], password[256];
|
|
|
+ WORD ctrlId;
|
|
|
+
|
|
|
+ switch (msg) {
|
|
|
+ case WM_CLOSE:
|
|
|
+ passfile = 0;
|
|
|
+ DestroyWindow(hDlg);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case WM_COMMAND:
|
|
|
+ ctrlId = LOWORD(wParam);
|
|
|
+ if (ctrlId == ID_ADD_USER) {
|
|
|
+ /* Add user */
|
|
|
+ GetWindowText(GetDlgItem(hDlg, ID_ADD_USER_NAME), user, sizeof(user));
|
|
|
+ GetWindowText(GetDlgItem(hDlg, ID_ADD_USER_REALM), domain, sizeof(domain));
|
|
|
+ GetPassword(password, sizeof(password));
|
|
|
+ mg_modify_passwords_file(passfile, domain, user, password);
|
|
|
+ EndDialog(hDlg, IDOK);
|
|
|
+ } else if ((ctrlId>=(ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3)) &&
|
|
|
+ (ctrlId<(ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 4))) {
|
|
|
+ /* Modify password */
|
|
|
+ GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 3), user, sizeof(user));
|
|
|
+ GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 2), domain, sizeof(domain));
|
|
|
+ GetPassword(password, sizeof(password));
|
|
|
+ mg_modify_passwords_file(passfile, domain, user, password);
|
|
|
+ EndDialog(hDlg, IDOK);
|
|
|
+ } else if ((ctrlId>=(ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 2)) &&
|
|
|
+ (ctrlId<(ID_CONTROLS + ID_FILE_BUTTONS_DELTA * 3))) {
|
|
|
+ /* Remove user */
|
|
|
+ GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA * 2), user, sizeof(user));
|
|
|
+ GetWindowText(GetDlgItem(hDlg, ctrlId - ID_FILE_BUTTONS_DELTA), domain, sizeof(domain));
|
|
|
+ mg_modify_passwords_file(passfile, domain, user, NULL);
|
|
|
+ EndDialog(hDlg, IDOK);
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
+ case WM_INITDIALOG:
|
|
|
+ passfile = (const char *)lP;
|
|
|
+ SendMessage(hDlg, WM_SETICON,(WPARAM) ICON_SMALL, (LPARAM) hIcon);
|
|
|
+ SendMessage(hDlg, WM_SETICON,(WPARAM) ICON_BIG, (LPARAM) hIcon);
|
|
|
+ SetWindowText(hDlg, passfile);
|
|
|
+ SetFocus(GetDlgItem(hDlg, ID_ADD_USER_NAME));
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
@@ -855,7 +915,6 @@ static void show_settings_dialog()
|
|
|
DWORD style;
|
|
|
DLGTEMPLATE *dia = (DLGTEMPLATE *) mem;
|
|
|
WORD i, cl, x, y, width, nelems = 0;
|
|
|
- static int guard = 0; /* test if dialog is already open */
|
|
|
|
|
|
static struct {
|
|
|
DLGTEMPLATE template; /* 18 bytes */
|
|
@@ -939,8 +998,139 @@ static void show_settings_dialog()
|
|
|
assert((int)p - (int)mem < sizeof(mem));
|
|
|
|
|
|
dia->cy = ((nelems + 1) / 2 + 1) * HEIGHT + 30;
|
|
|
- DialogBoxIndirectParam(NULL, dia, NULL, DlgProc, (LPARAM) NULL);
|
|
|
+ DialogBoxIndirectParam(NULL, dia, NULL, SettingsDlgProc, (LPARAM) NULL);
|
|
|
guard--;
|
|
|
+
|
|
|
+#undef HEIGHT
|
|
|
+#undef WIDTH
|
|
|
+#undef LABEL_WIDTH
|
|
|
+}
|
|
|
+
|
|
|
+static void change_password_file()
|
|
|
+{
|
|
|
+#define HEIGHT 15
|
|
|
+#define WIDTH 320
|
|
|
+#define LABEL_WIDTH 90
|
|
|
+
|
|
|
+ OPENFILENAME of;
|
|
|
+ char path[PATH_MAX] = PASSWORDS_FILE_NAME;
|
|
|
+ char strbuf[256], u[256], d[256];
|
|
|
+ HWND hDlg = NULL;
|
|
|
+ FILE * f;
|
|
|
+ int y, nelems;
|
|
|
+ unsigned char mem[4096], *p;
|
|
|
+ DLGTEMPLATE *dia = (DLGTEMPLATE *) mem;
|
|
|
+ const char * domain = mg_get_option(ctx, "authentication_domain");
|
|
|
+
|
|
|
+ static struct {
|
|
|
+ DLGTEMPLATE template; /* 18 bytes */
|
|
|
+ WORD menu, class;
|
|
|
+ wchar_t caption[1];
|
|
|
+ WORD fontsiz;
|
|
|
+ wchar_t fontface[7];
|
|
|
+ } dialog_header = {{
|
|
|
+ WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE |
|
|
|
+ DS_SETFONT | WS_DLGFRAME, WS_EX_TOOLWINDOW, 0, 200, 200, WIDTH, 0
|
|
|
+ },
|
|
|
+ 0, 0, L"", 8, L"Tahoma"
|
|
|
+ };
|
|
|
+
|
|
|
+ if (guard == 0) {
|
|
|
+ guard++;
|
|
|
+ } else {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ memset(&of, 0, sizeof(of));
|
|
|
+ of.lStructSize = sizeof(of);
|
|
|
+ of.hwndOwner = (HWND) hDlg;
|
|
|
+ of.lpstrFile = path;
|
|
|
+ of.nMaxFile = sizeof(path);
|
|
|
+ of.lpstrInitialDir = mg_get_option(ctx, "document_root");
|
|
|
+ of.Flags = OFN_CREATEPROMPT | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
|
|
|
+
|
|
|
+ if (IDOK != GetSaveFileName(&of)) {
|
|
|
+ guard--;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ f = fopen(path, "a+");
|
|
|
+ if (f) {
|
|
|
+ fclose(f);
|
|
|
+ } else {
|
|
|
+ MessageBox(NULL, path, "Can not open file", MB_ICONERROR);
|
|
|
+ guard--;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ (void) memset(mem, 0, sizeof(mem));
|
|
|
+ (void) memcpy(mem, &dialog_header, sizeof(dialog_header));
|
|
|
+ p = mem + sizeof(dialog_header);
|
|
|
+
|
|
|
+ f = fopen(path, "r+");
|
|
|
+ if (!f) {
|
|
|
+ MessageBox(NULL, path, "Can not open file", MB_ICONERROR);
|
|
|
+ guard--;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ nelems = 0;
|
|
|
+ while (fgets(strbuf, sizeof(strbuf), f)) {
|
|
|
+ if (sscanf(strbuf, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ u[255]=0;
|
|
|
+ d[255]=0;
|
|
|
+ y = (nelems + 1) * HEIGHT + 5;
|
|
|
+ add_control(&p, dia, 0x80, ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA * 3,
|
|
|
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
|
|
|
+ 10, y, 65, 12, "Modify password");
|
|
|
+ add_control(&p, dia, 0x80, ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA * 2,
|
|
|
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
|
|
|
+ 80, y, 55, 12, "Remove user");
|
|
|
+ add_control(&p, dia, 0x81, ID_CONTROLS + nelems + ID_FILE_BUTTONS_DELTA,
|
|
|
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | WS_DISABLED,
|
|
|
+ 245, y, 60, 12, d);
|
|
|
+ add_control(&p, dia, 0x81, ID_CONTROLS + nelems,
|
|
|
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | WS_DISABLED,
|
|
|
+ 140, y, 100, 12, u);
|
|
|
+
|
|
|
+ nelems++;
|
|
|
+ assert((int)p - (int)mem < sizeof(mem));
|
|
|
+ }
|
|
|
+ fclose(f);
|
|
|
+
|
|
|
+ y = (WORD) ((nelems + 1) * HEIGHT + 10);
|
|
|
+ add_control(&p, dia, 0x80, ID_ADD_USER,
|
|
|
+ WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
|
|
|
+ 80, y, 55, 12, "Add user");
|
|
|
+ add_control(&p, dia, 0x81, ID_ADD_USER_REALM,
|
|
|
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
|
|
|
+ 245, y, 60, 12, domain);
|
|
|
+ add_control(&p, dia, 0x81, ID_ADD_USER_NAME,
|
|
|
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
|
|
|
+ 140, y, 100, 12, "");
|
|
|
+
|
|
|
+ y = (WORD) ((nelems + 2) * HEIGHT + 10);
|
|
|
+ add_control(&p, dia, 0x80, ID_GROUP, WS_CHILD | WS_VISIBLE |
|
|
|
+ BS_GROUPBOX, 5, 5, WIDTH - 10, y, " Users ");
|
|
|
+
|
|
|
+ y += HEIGHT;
|
|
|
+ add_control(&p, dia, 0x82, ID_STATIC,
|
|
|
+ WS_CHILD | WS_VISIBLE | WS_DISABLED,
|
|
|
+ 5, y, 100, 12, server_base_name);
|
|
|
+
|
|
|
+ assert((int)p - (int)mem < sizeof(mem));
|
|
|
+
|
|
|
+ dia->cy = y + 20;
|
|
|
+ } while (IDOK == DialogBoxIndirectParam(NULL, dia, NULL, PasswordDlgProc, (LPARAM) path));
|
|
|
+
|
|
|
+ guard--;
|
|
|
+
|
|
|
+#undef HEIGHT
|
|
|
+#undef WIDTH
|
|
|
+#undef LABEL_WIDTH
|
|
|
}
|
|
|
|
|
|
static int manage_service(int action)
|
|
@@ -1022,6 +1212,9 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
|
|
|
case ID_SETTINGS:
|
|
|
show_settings_dialog();
|
|
|
break;
|
|
|
+ case ID_PASSWORD:
|
|
|
+ change_password_file();
|
|
|
+ break;
|
|
|
case ID_INSTALL_SERVICE:
|
|
|
case ID_REMOVE_SERVICE:
|
|
|
manage_service(LOWORD(wParam));
|
|
@@ -1053,6 +1246,7 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
|
|
|
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
|
|
AppendMenu(hMenu, MF_STRING, ID_CONNECT, "Start browser");
|
|
|
AppendMenu(hMenu, MF_STRING, ID_SETTINGS, "Edit settings");
|
|
|
+ AppendMenu(hMenu, MF_STRING, ID_PASSWORD, "Modify password file");
|
|
|
AppendMenu(hMenu, MF_SEPARATOR, ID_SEPARATOR, "");
|
|
|
AppendMenu(hMenu, MF_STRING, ID_QUIT, "Exit");
|
|
|
GetCursorPos(&pt);
|