From 245c8022268ab0111cd0c1eba2d98c83e4261181 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 25 Feb 2015 11:27:49 +0100 Subject: [PATCH] Escape FLTK menu entries We don't want it automatically creating submenus when least expected. --- vncviewer/OptionsDialog.cxx | 4 ++-- vncviewer/Viewport.cxx | 45 ++++++++++++++++++++-------------- vncviewer/fltk_layout.h | 48 +++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/vncviewer/OptionsDialog.cxx b/vncviewer/OptionsDialog.cxx index b9752aa1..9fa9a665 100644 --- a/vncviewer/OptionsDialog.cxx +++ b/vncviewer/OptionsDialog.cxx @@ -724,9 +724,9 @@ void OptionsDialog::createInputPage(int tx, int ty, int tw, int th) menuKeyChoice = new Fl_Choice(LBLLEFT(tx, ty, 150, CHOICE_HEIGHT, _("Menu key"))); - menuKeyChoice->add(_("None"), 0, NULL, (void*)0, FL_MENU_DIVIDER); + fltk_menu_add(menuKeyChoice, _("None"), 0, NULL, (void*)0, FL_MENU_DIVIDER); for (int i = 0; i < getMenuKeySymbolCount(); i++) - menuKeyChoice->add(getMenuKeySymbols()[i].name, 0, NULL, 0, 0); + fltk_menu_add(menuKeyChoice, getMenuKeySymbols()[i].name, 0, NULL, 0, 0); ty += CHOICE_HEIGHT + TIGHT_MARGIN; diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx index 33ba24fe..6c77e583 100644 --- a/vncviewer/Viewport.cxx +++ b/vncviewer/Viewport.cxx @@ -1062,39 +1062,48 @@ void Viewport::initContextMenu() { contextMenu->clear(); - contextMenu->add(_("E&xit viewer"), 0, NULL, (void*)ID_EXIT, FL_MENU_DIVIDER); + fltk_menu_add(contextMenu, _("E&xit viewer"), 0, NULL, + (void*)ID_EXIT, FL_MENU_DIVIDER); #ifdef HAVE_FLTK_FULLSCREEN - contextMenu->add(_("&Full screen"), 0, NULL, (void*)ID_FULLSCREEN, - FL_MENU_TOGGLE | (window()->fullscreen_active()?FL_MENU_VALUE:0)); + fltk_menu_add(contextMenu, _("&Full screen"), 0, NULL, (void*)ID_FULLSCREEN, + FL_MENU_TOGGLE | (window()->fullscreen_active()?FL_MENU_VALUE:0)); #endif - contextMenu->add(_("Resize &window to session"), 0, NULL, (void*)ID_RESIZE, + fltk_menu_add(contextMenu, _("Resize &window to session"), 0, NULL, + (void*)ID_RESIZE, #ifdef HAVE_FLTK_FULLSCREEN - (window()->fullscreen_active()?FL_MENU_INACTIVE:0) | + (window()->fullscreen_active()?FL_MENU_INACTIVE:0) | #endif - FL_MENU_DIVIDER); + FL_MENU_DIVIDER); - contextMenu->add(_("&Ctrl"), 0, NULL, (void*)ID_CTRL, - FL_MENU_TOGGLE | (menuCtrlKey?FL_MENU_VALUE:0)); - contextMenu->add(_("&Alt"), 0, NULL, (void*)ID_ALT, - FL_MENU_TOGGLE | (menuAltKey?FL_MENU_VALUE:0)); + fltk_menu_add(contextMenu, _("&Ctrl"), 0, NULL, (void*)ID_CTRL, + FL_MENU_TOGGLE | (menuCtrlKey?FL_MENU_VALUE:0)); + fltk_menu_add(contextMenu, _("&Alt"), 0, NULL, (void*)ID_ALT, + FL_MENU_TOGGLE | (menuAltKey?FL_MENU_VALUE:0)); if (menuKeySym) { char sendMenuKey[64]; snprintf(sendMenuKey, 64, _("Send %s"), (const char *)menuKey); - contextMenu->add(sendMenuKey, 0, NULL, (void*)ID_MENUKEY, 0); - contextMenu->add("Secret shortcut menu key", menuKeyCode, NULL, (void*)ID_MENUKEY, FL_MENU_INVISIBLE); + fltk_menu_add(contextMenu, sendMenuKey, 0, NULL, (void*)ID_MENUKEY, 0); + fltk_menu_add(contextMenu, "Secret shortcut menu key", menuKeyCode, NULL, + (void*)ID_MENUKEY, FL_MENU_INVISIBLE); } - contextMenu->add(_("Send Ctrl-Alt-&Del"), 0, NULL, (void*)ID_CTRLALTDEL, FL_MENU_DIVIDER); + fltk_menu_add(contextMenu, _("Send Ctrl-Alt-&Del"), 0, NULL, + (void*)ID_CTRLALTDEL, FL_MENU_DIVIDER); - contextMenu->add(_("&Refresh screen"), 0, NULL, (void*)ID_REFRESH, FL_MENU_DIVIDER); + fltk_menu_add(contextMenu, _("&Refresh screen"), 0, NULL, + (void*)ID_REFRESH, FL_MENU_DIVIDER); - contextMenu->add(_("&Options..."), 0, NULL, (void*)ID_OPTIONS, 0); - contextMenu->add(_("Connection &info..."), 0, NULL, (void*)ID_INFO, 0); - contextMenu->add(_("About &TigerVNC viewer..."), 0, NULL, (void*)ID_ABOUT, FL_MENU_DIVIDER); + fltk_menu_add(contextMenu, _("&Options..."), 0, NULL, + (void*)ID_OPTIONS, 0); + fltk_menu_add(contextMenu, _("Connection &info..."), 0, NULL, + (void*)ID_INFO, 0); + fltk_menu_add(contextMenu, _("About &TigerVNC viewer..."), 0, NULL, + (void*)ID_ABOUT, FL_MENU_DIVIDER); - contextMenu->add(_("Dismiss &menu"), 0, NULL, (void*)ID_DISMISS, 0); + fltk_menu_add(contextMenu, _("Dismiss &menu"), 0, NULL, + (void*)ID_DISMISS, 0); } diff --git a/vncviewer/fltk_layout.h b/vncviewer/fltk_layout.h index c16a359f..21fb00a3 100644 --- a/vncviewer/fltk_layout.h +++ b/vncviewer/fltk_layout.h @@ -20,6 +20,7 @@ #define __FLTK_LAYOUT_H__ #include +#include /* Calculates the width of a string as printed by FLTK (pixels) */ static inline int gui_str_len(const char *str) @@ -67,6 +68,53 @@ static inline int fltk_escape(const char *in, char *out, size_t maxlen) return len; } +/* Filter out unsafe characters for menu entries */ +static inline int fltk_menu_escape(const char *in, char *out, size_t maxlen) +{ + int len; + + len = 0; + + while (*in != '\0') { + if (*in == '/') { + if (maxlen >= 3) { + *out++ = '\\'; + *out++ = '/'; + maxlen -= 2; + } + + len += 2; + } else { + if (maxlen >= 2) { + *out++ = *in; + maxlen--; + } + + len += 1; + } + + in++; + } + + if (maxlen) + *out = '\0'; + + return len; +} + +/* Helper to add menu entries safely */ +static inline void fltk_menu_add(Fl_Menu_ *menu, const char *text, + int shortcut, Fl_Callback *cb, + void *data = 0, int flags = 0) +{ + char buffer[1024]; + + if (fltk_menu_escape(text, buffer, sizeof(buffer)) >= sizeof(buffer)) + return; + + menu->add(buffer, shortcut, cb, data, flags); +} + /**** MARGINS ****/ #define OUTER_MARGIN 10 -- 2.39.5