/* * Copyright (c) 2022 joshua stein * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include "subtext.h" #include "ansi.h" #include "session.h" #include "user.h" #include "user_settings.h" #include "util.h" void user_settings_password(struct session *s); void user_settings_username(struct session *s); void user_settings_renegotiate(struct session *s) { unsigned short c; short cols, lines; char *tsize; session_printf(s, "Does this terminal support VT100 escape sequences? [Y/n] "); session_flush(s); try_again: c = session_input_char(s); if (s->ending) return; if (c == 0 || c > 255) goto try_again; if (c == 'n' || c == 'N') { session_printf(s, "%c\r\n", c == 'N' ? 'N' : 'n'); session_flush(s); s->vt100 = false; } else if (c == '\r' || c == 'Y' || c == 'y') { session_printf(s, "%c\r\n", c == 'Y' ? 'Y' : 'y'); session_flush(s); s->vt100 = true; } if (!s->vt100) { session_printf(s, "Does this terminal support VT52 escape sequences? [Y/n] "); session_flush(s); try_again2: c = session_input_char(s); if (s->ending) return; if (c == 0 || c > 255) goto try_again2; if (c == 'n' || c == 'N') { session_printf(s, "%c\r\n", c == 'N' ? 'N' : 'n'); session_flush(s); s->vt52 = false; } else if (c == '\r' || c == 'Y' || c == 'y') { session_printf(s, "%c\r\n", c == 'Y' ? 'Y' : 'y'); session_flush(s); s->vt52 = true; } } if (s->vt100) ansi_probe_screen_size(s); get_terminal_size: session_printf(s, "Terminal size (columns x rows) [%dx%d] ", s->terminal_columns, s->terminal_lines); session_flush(s); tsize = session_field_input(s, 10, 10, NULL, false, 0); if (tsize == NULL) return; session_output(s, "\r\n", 2); session_flush(s); if (tsize[0] == '\0') { xfree(&tsize); return; } if (sscanf(tsize, "%d%*[xX]%d", &cols, &lines) != 2) { session_printf(s, "Invalid response, must be in format %dx%d\r\n", s->terminal_columns, s->terminal_lines); session_flush(s); xfree(&tsize); goto get_terminal_size; } if (cols < MIN_TERMINAL_COLUMNS || lines < MIN_TERMINAL_LINES) { session_printf(s, "Terminal too small, must be at least " "%dx%d\r\n", MIN_TERMINAL_COLUMNS, MIN_TERMINAL_LINES); session_flush(s); xfree(&tsize); goto get_terminal_size; } s->terminal_columns = cols; s->terminal_lines = lines; session_logf(s, "Changed terminal size to %dx%d", cols, lines); } void user_settings_username(struct session *s) { char *username = NULL, *error = NULL; if (!s->user) { session_printf(s, "{{B}}Error{{/B}}: Guest accounts " "cannot change username\r\n"); return; } while (!s->ending) { session_printf(s, "{{B}}Username:{{/B}} "); session_flush(s); username = session_field_input(s, DB_USERNAME_LENGTH, DB_USERNAME_LENGTH, s->user->username, false, 0); session_output(s, "\r\n", 2); session_flush(s); if (username == NULL || s->ending) break; if (username[0] == '\0') { session_printf(s, "{{B}}Error:{{/B}} " "Username cannot be blank\r\n"); xfree(&username); username = NULL; continue; } if (strcmp(s->user->username, username) == 0) break; if (user_valid_username(s->user, username, &error) != 1) { session_printf(s, "{{B}}Error:{{/B}} %s\r\n", error); xfree(&error); xfree(&username); username = NULL; continue; } session_logf(s, "User changed username from %s to %s", s->user->username, username); strlcpy(s->user->username, username, sizeof(s->user->username)); user_save(s->user); user_cache_usernames(); session_printf(s, "{{B}}Your username has been " "changed to %s{{/B}}\r\n", s->user->username); break; } if (username != NULL) xfree(&username); } void user_settings_menu(struct session *s) { static const struct session_menu_option opts[] = { { 'r', "Rr", "Renegotiate terminal" }, { 'p', "Pp", "Change password" }, { 'u', "Uu", "Change username" }, { 'q', "QqXx", "Return to main menu" }, { '?', "?", "List menu options" }, }; static const char prompt_help[] = "R:Renegotiate P:Password U:Username Q:Return ?:Help"; char c; bool show_help = true; bool done = false; session_logf(s, "User settings menu"); while (!done) { c = session_menu(s, "Settings", "Settings", (char *)prompt_help, opts, nitems(opts), show_help, NULL, NULL); show_help = false; switch (c) { case 'r': user_settings_renegotiate(s); break; case 'p': user_change_password(s, s->user); break; case 'u': user_settings_username(s); break; case '?': show_help = true; break; default: done = true; break; } } }