diff --git a/server/menuitem.c b/server/menuitem.c index bb19f6a..1b420a7 100644 --- a/server/menuitem.c +++ b/server/menuitem.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "shared/report.h" @@ -71,15 +72,15 @@ typedef struct { int limit; // upper limit of each numeric string int posValue[5]; // digit-value of the digits at the approp. position in the numeric string char format[5]; // printf-format string to print a numeric string - int (*verify)(const char *); // verify function + int (*verify)(const char *); // verify function: returns 1 = OK, 0 = error char dummy[16]; // dummy value (if provided value is no IP address) } IpSstringProperties; const IpSstringProperties IPinfo[] = { - // IPv4: 15 char long ':'-separated sequence of 4-digit hex strings + // IPv4: 15 char long '.'-separated sequence of 3-digit decimal strings in range 000 - 255 { 15, '.', 10, 3, 255, { 100, 10, 1, 0, 0 }, "%03d", verify_ipv4, "0.0.0.0" }, - // IPv6: 39 char long ':'-separated sequence of 4-digit hex strings + // IPv6: 39 char long ':'-separated sequence of 4-digit hex strings in range 0000 - ffff { 39, ':', 16, 4, 65535, { 4096, 256, 16, 1, 0 }, "%04x", verify_ipv6, "0:0:0:0:0:0:0:0" } }; @@ -455,6 +456,7 @@ void menuitem_reset_numeric (MenuItem *item) if (item != NULL) { item->data.numeric.edit_pos = 0; + item->data.numeric.edit_offs = 0; memset (item->data.numeric.edit_str, '\0', MAX_NUMERIC_LEN); if (item->data.numeric.minvalue < 0) { snprintf (item->data.numeric.edit_str, MAX_NUMERIC_LEN, @@ -473,6 +475,7 @@ void menuitem_reset_alpha (MenuItem *item) if (item != NULL) { item->data.alpha.edit_pos = 0; + item->data.alpha.edit_offs = 0; memset (item->data.alpha.edit_str, '\0', item->data.alpha.maxlength+1); strcpy (item->data.alpha.edit_str, item->data.alpha.value); } @@ -487,9 +490,10 @@ void menuitem_reset_ip (MenuItem *item) ((item != NULL) ? item->id : "(null)")); item->data.ip.edit_pos = 0; + item->data.ip.edit_offs = 0; memset (item->data.ip.edit_str, '\0', item->data.ip.maxlength+1); - // normalize IP address string to 010.002.250.002 / 00:01:02:04:05:06:07:08:09:0a:0b:0c:0e:0f + // normalize IP address string to e.g. 010.002.250.002 / 00:01:02:04:05:06:07:08:09:0a:0b:0c:0e:0f while (start != NULL) { char *end; @@ -794,10 +798,10 @@ void menuitem_update_screen_numeric (MenuItem *item, Screen *s) return; w = screen_find_widget (s, "value"); - strcpy (w->text, item->data.numeric.edit_str); + strcpy (w->text, item->data.numeric.edit_str + item->data.numeric.edit_offs); s->cursor = CURSOR_DEFAULT_ON; - s->cursor_x = w->x + item->data.numeric.edit_pos; + s->cursor_x = w->x + item->data.numeric.edit_pos - item->data.numeric.edit_offs; s->cursor_y = w->y; /* Only display error string if enough space... */ @@ -821,14 +825,16 @@ void menuitem_update_screen_alpha (MenuItem *item, Screen *s) w = screen_find_widget (s, "value"); if (item->data.alpha.password_char == '\0') { - strcpy (w->text, item->data.alpha.edit_str); + strcpy (w->text, item->data.alpha.edit_str + item->data.alpha.edit_offs); } else { - memset (w->text, item->data.alpha.password_char, strlen (item->data.alpha.edit_str)); - w->text[ strlen (item->data.alpha.edit_str) ] = '\0'; + int len = strlen(item->data.alpha.edit_str) - item->data.alpha.edit_offs; + + memset (w->text, item->data.alpha.password_char, len); + w->text[len] = '\0'; } s->cursor = CURSOR_DEFAULT_ON; - s->cursor_x = w->x + item->data.alpha.edit_pos; + s->cursor_x = w->x + item->data.alpha.edit_pos - item->data.alpha.edit_offs; s->cursor_y = w->y; /* Only display error string if enough space... */ @@ -852,10 +858,10 @@ void menuitem_update_screen_ip (MenuItem *item, Screen *s) w = screen_find_widget (s, "value"); if (w != NULL) - strcpy (w->text, item->data.ip.edit_str); + strcpy (w->text, item->data.ip.edit_str + item->data.ip.edit_offs); s->cursor = CURSOR_DEFAULT_ON; - s->cursor_x = w->x + item->data.ip.edit_pos; + s->cursor_x = w->x + item->data.ip.edit_pos - item->data.ip.edit_offs; s->cursor_y = w->y; /* Only display error string if enough space... */ @@ -954,9 +960,7 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char } else { /* Reset data */ - item->data.numeric.edit_pos = 0; - memset (str, '\0', MAX_NUMERIC_LEN); - snprintf (str, MAX_NUMERIC_LEN, format_str, item->data.numeric.value); + menuitem_reset_numeric(item); } return MENURESULT_NONE; case MENUTOKEN_ENTER: @@ -976,6 +980,7 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char */ item->data.numeric.error_code = 1; item->data.numeric.edit_pos = 0; + item->data.numeric.edit_offs = 0; return MENURESULT_NONE; } @@ -991,7 +996,9 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char else { /* The user wants to go to next digit */ if (pos < max_len) { - item->data.numeric.edit_pos ++; + item->data.numeric.edit_pos++; + if (pos >= display_props->width - 2) + item->data.numeric.edit_offs++; } } return MENURESULT_NONE; @@ -1000,6 +1007,7 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char /* We're not allowed to add anything anymore */ item->data.numeric.error_code = 2; item->data.numeric.edit_pos = 0; + item->data.numeric.edit_offs = 0; return MENURESULT_NONE; } if (allow_signed && pos == 0) { @@ -1021,6 +1029,7 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char /* We're not allowed to add anything anymore */ item->data.numeric.error_code = 2; item->data.numeric.edit_pos = 0; + item->data.numeric.edit_offs = 0; return MENURESULT_NONE; } if (allow_signed && pos == 0) { @@ -1040,13 +1049,17 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char case MENUTOKEN_RIGHT: /* The user wants to go to next digit */ if (str[pos] != '\0' && pos < max_len) { - item->data.numeric.edit_pos ++; + item->data.numeric.edit_pos++; + if (pos >= display_props->width - 2) + item->data.numeric.edit_offs++; } return MENURESULT_NONE; case MENUTOKEN_LEFT: /* The user wants to go to back a digit */ if (pos > 0) { - item->data.numeric.edit_pos --; + item->data.numeric.edit_pos--; + if (item->data.numeric.edit_offs > item->data.numeric.edit_pos) + item->data.numeric.edit_offs = item->data.numeric.edit_pos; } return MENURESULT_NONE; case MENUTOKEN_OTHER: @@ -1054,12 +1067,15 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char /* We're not allowed to add anything anymore */ item->data.numeric.error_code = 2; item->data.numeric.edit_pos = 0; + item->data.numeric.edit_offs = 0; return MENURESULT_NONE; } /* process numeric keys */ - if ( strlen(key) == 1 && key[0] >= '0' && key[0] <= '9') { + if ((strlen(key) == 1) && isdigit(key[0])) { str[pos] = key[0]; - item->data.numeric.edit_pos ++; + item->data.numeric.edit_pos++; + if (pos >= display_props->width - 2) + item->data.numeric.edit_offs++; } return MENURESULT_NONE; } @@ -1082,7 +1098,7 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * /* Create list of allowed chars */ chars = realloc (chars, 26 + 26 + 10 + strlen(item->data.alpha.allowed_extra) + 1); - chars[0] = 0; /* clear string */ + chars[0] = '\0'; /* clear string */ if (item->data.alpha.allow_caps) strcat (chars, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); if (item->data.alpha.allow_noncaps) @@ -1101,9 +1117,7 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * } else { /* Reset data */ - item->data.alpha.edit_pos = 0; - memset (str, '\0', item->data.alpha.maxlength+1); - strcpy (str, item->data.alpha.value); + menuitem_reset_alpha(item); } return MENURESULT_NONE; case MENUTOKEN_ENTER: @@ -1128,7 +1142,9 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * else { /* The user wants to go to next digit */ if (pos < item->data.alpha.maxlength) { - item->data.alpha.edit_pos ++; + item->data.alpha.edit_pos++; + if (pos >= display_props->width - 2) + item->data.alpha.edit_offs++; } } return MENURESULT_NONE; @@ -1137,6 +1153,7 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * /* We're not allowed to add anything anymore */ item->data.alpha.error_code = 2; item->data.alpha.edit_pos = 0; + item->data.alpha.edit_offs = 0; return MENURESULT_NONE; } if (str[pos] == '\0') { @@ -1158,6 +1175,7 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * /* We're not allowed to add anything anymore */ item->data.alpha.error_code = 2; item->data.alpha.edit_pos = 0; + item->data.alpha.edit_offs = 0; return MENURESULT_NONE; } if (str[pos] == '\0') { @@ -1177,25 +1195,33 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * /* The user wants to go to next digit */ if (str[item->data.alpha.edit_pos] != '\0' && pos < item->data.alpha.maxlength - 1) { - item->data.alpha.edit_pos ++; + item->data.alpha.edit_pos++; + if (pos >= display_props->width - 2) + item->data.alpha.edit_offs++; } return MENURESULT_NONE; case MENUTOKEN_LEFT: /* The user wants to go to back a digit */ - if (pos > 0) - item->data.alpha.edit_pos --; + if (pos > 0) { + item->data.alpha.edit_pos--; + if (item->data.alpha.edit_offs > item->data.alpha.edit_pos) + item->data.alpha.edit_offs = item->data.alpha.edit_pos; + } return MENURESULT_NONE; case MENUTOKEN_OTHER: if (pos >= item->data.alpha.maxlength) { /* We're not allowed to add anything anymore */ item->data.alpha.error_code = 2; item->data.alpha.edit_pos = 0; + item->data.alpha.edit_offs = 0; return MENURESULT_NONE; } - /* proces other keys */ - if ( strlen(key) == 1 && key[0] >= ' ' && key[0] <= 'Z') { + /* process other keys */ + if ((strlen(key) == 1) && (key[0] >= ' ') && (strchr(chars, key[0]) != NULL)) { str[pos] = key[0]; - item->data.alpha.edit_pos ++; + item->data.alpha.edit_pos++; + if (pos >= display_props->width - 2) + item->data.alpha.edit_offs++; } return MENURESULT_NONE; } @@ -1227,14 +1253,12 @@ MenuResult menuitem_process_input_ip (MenuItem *item, MenuToken token, char * ke else { /* Reset data */ menuitem_reset_ip(item); -// item->data.ip.edit_pos = 0; -// memset (str, '\0', item->data.ip.maxlength+1); -// strcpy (str, item->data.ip.value); } return MENURESULT_NONE; case MENUTOKEN_ENTER: if (extended || (pos >= item->data.ip.maxlength - 1)) { - /* remove the loading spaces/zeros in each octet-representing string */ + /* ** we do not need this; the verify function is clever enough ** + // remove the leading spaces/zeros in each octet-representing string char *start = str; while (start != NULL) { @@ -1246,16 +1270,18 @@ MenuResult menuitem_process_input_ip (MenuItem *item, MenuToken token, char * ke skip = strchr(start, ipinfo->sep); start = (skip != NULL) ? (skip + 1) : NULL; } + */ - if (ipinfo->verify(item->data.ip.edit_str)) { + // check IP address entered + if (!ipinfo->verify(item->data.ip.edit_str)) { item->data.ip.error_code = 4; return MENURESULT_NONE; } - /* Store value */ + // store value strcpy (item->data.ip.value, item->data.ip.edit_str); - /* Inform client */ + // Inform client if (item->event_func) item->event_func (item, MENUEVENT_UPDATE); @@ -1265,6 +1291,8 @@ MenuResult menuitem_process_input_ip (MenuItem *item, MenuToken token, char * ke item->data.ip.edit_pos++; if (str[item->data.ip.edit_pos] == ipinfo->sep) item->data.ip.edit_pos++; + while (item->data.ip.edit_pos - item->data.ip.edit_offs > display_props->width - 2) + item->data.ip.edit_offs++; return MENURESULT_NONE; } case MENUTOKEN_UP: @@ -1294,6 +1322,8 @@ MenuResult menuitem_process_input_ip (MenuItem *item, MenuToken token, char * ke item->data.ip.edit_pos++; if (str[item->data.ip.edit_pos] == ipinfo->sep) item->data.ip.edit_pos++; + while (item->data.ip.edit_pos - item->data.ip.edit_offs > display_props->width - 2) + item->data.ip.edit_offs++; } return MENURESULT_NONE; case MENUTOKEN_LEFT: @@ -1302,9 +1332,23 @@ MenuResult menuitem_process_input_ip (MenuItem *item, MenuToken token, char * ke item->data.ip.edit_pos--; if (str[item->data.ip.edit_pos] == ipinfo->sep) item->data.ip.edit_pos--; + if (item->data.ip.edit_offs > item->data.ip.edit_pos) + item->data.ip.edit_offs = item->data.ip.edit_pos; } return MENURESULT_NONE; case MENUTOKEN_OTHER: + /* process other keys */ + if ((strlen(key) == 1) && + ((item->data.ip.v6) ? isxdigit(key[0]) : isdigit(key[0]))) { + str[pos] = tolower(key[0]); + if (pos < item->data.ip.maxlength - 1) { + item->data.ip.edit_pos++; + if (str[item->data.ip.edit_pos] == ipinfo->sep) + item->data.ip.edit_pos++; + while (item->data.ip.edit_pos - item->data.ip.edit_offs > display_props->width - 2) + item->data.ip.edit_offs++; + } + } return MENURESULT_NONE; } return MENURESULT_ERROR; diff --git a/server/menuitem.h b/server/menuitem.h index c9a80a9..62c2867 100644 --- a/server/menuitem.h +++ b/server/menuitem.h @@ -157,6 +157,7 @@ typedef struct MenuItem { int value; /**< Current value */ char *edit_str; /**< Value while being edited */ short edit_pos; /**< Position while editing */ + short edit_offs; /**< Offset while editing */ short error_code; } numeric; struct alpha { @@ -170,6 +171,7 @@ typedef struct MenuItem { char *value; /**< Current value */ char *edit_str; /**< Value while being edited */ short edit_pos; /**< Position while editing */ + short edit_offs; /**< Offset while editing */ short error_code; } alpha; struct ip { @@ -178,6 +180,7 @@ typedef struct MenuItem { short maxlength; bool v6; /**< true if editing ipv6 addr */ short edit_pos; /**< Position while editing */ + short edit_offs; /**< Offset while editing */ short error_code; } ip; } data; diff --git a/server/menuscreens.c b/server/menuscreens.c index 06db61f..f2294ea 100644 --- a/server/menuscreens.c +++ b/server/menuscreens.c @@ -427,7 +427,7 @@ void menuscreen_create_menu () menu_add_item (test_menu, test_item); test_item = menuitem_create_action ("", NULL, "Action,closing", NULL, MENURESULT_CLOSE); menu_add_item (test_menu, test_item); - test_item = menuitem_create_action ("", NULL, "Action,quiting", NULL, MENURESULT_QUIT); + test_item = menuitem_create_action ("", NULL, "Action,quitting", NULL, MENURESULT_QUIT); menu_add_item (test_menu, test_item); test_item = menuitem_create_checkbox ("", NULL, "Checkbox", NULL, false, false); @@ -455,7 +455,7 @@ void menuscreen_create_menu () test_item = menuitem_create_ip ("", NULL, "IPv4", NULL, 0, "192.168.1.245"); menu_add_item (test_menu, test_item); - test_item = menuitem_create_ip ("", NULL, "IPv6", NULL, 1, ":::ffff:ffff:ffff:ffff:ffff"); + test_item = menuitem_create_ip ("", NULL, "IPv6", NULL, 1, "1080:0:0:0:8:800:200C:417A"); menu_add_item (test_menu, test_item); #endif /*LCDPROC_TESTMENUS*/ } diff --git a/server/sock.c b/server/sock.c index e77f474..26016de 100644 --- a/server/sock.c +++ b/server/sock.c @@ -437,26 +437,30 @@ sock_read_from_client(struct ClientSocketMap* clientSocketMap) } -/* return 0 if addr is valid ipv4 */ +/* return 1 if addr is valid IPv4 */ int verify_ipv4(const char *addr) { - int rsts; - struct in_addr a; - rsts = inet_pton(AF_INET, addr, &a); - /* inet_pton returns positive value if it worked */ - if (rsts <=0) - return -1; - return 0; + int result = -1; + + if (addr != NULL) { + struct in_addr a; + + /* inet_pton returns positive value if it worked */ + result = inet_pton(AF_INET, addr, &a); + } + return (result > 0) ? 1 : 0; } -/* return 0 if addr is valid ipv4 */ +/* return 1 if addr is valid IPv6 */ int verify_ipv6(const char *addr) { - int rsts; - struct in6_addr a; - rsts = inet_pton(AF_INET, addr, &a); - /* inet_pton returns positive value if it worked */ - if (rsts <=0) - return -1; - return 0; + int result = 0; + + if (addr != NULL) { + struct in6_addr a; + + /* inet_pton returns positive value if it worked */ + result = inet_pton(AF_INET6, addr, &a); + } + return (result > 0) ? 1 : 0; }