Initial revision
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/vncviewer/CViewOptions.cxx b/vncviewer/CViewOptions.cxx
new file mode 100644
index 0000000..089c4c4
--- /dev/null
+++ b/vncviewer/CViewOptions.cxx
@@ -0,0 +1,364 @@
+/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <vncviewer/CViewOptions.h>
+#include <rfb/Configuration.h>
+#include <rfb/encodings.h>
+#include <rfb/vncAuth.h>
+#include <rfb/LogWriter.h>
+#include <rfb_win32/Win32Util.h>
+#include <rfb_win32/Registry.h>
+#include <rdr/HexInStream.h>
+#include <rdr/HexOutStream.h>
+#include <stdlib.h>
+
+using namespace rfb;
+using namespace rfb::win32;
+
+
+static BoolParameter useLocalCursor("UseLocalCursor", "Render the mouse cursor locally", true);
+static BoolParameter useDesktopResize("UseDesktopResize", "Support dynamic desktop resizing", true);
+
+static BoolParameter fullColour("FullColour",
+ "Use full colour (default is to use low colour "
+ "unless auto select decides the link is fast enough)",
+ false);
+static IntParameter lowColourLevel("LowColourLevel",
+ "Colour level to use on slow connections. "
+ "0 = Very Low (8 colours), 1 = Low (64 colours), 2 = Medium (256 colours)",
+ 1);
+static BoolParameter fullScreen("FullScreen",
+ "Use the whole display to show the remote desktop."
+ "(Press F8 to access the viewer menu)",
+ false);
+static StringParameter preferredEncoding("PreferredEncoding",
+ "Preferred graphical encoding to use - overridden by AutoSelect if set. "
+ "(ZRLE, Hextile or Raw)", "ZRLE");
+
+static BoolParameter autoSelect("AutoSelect", "Auto select pixel format and encoding", true);
+static BoolParameter sharedConnection("Shared",
+ "Allow existing connections to the server to continue."
+ "(Default is to disconnect all other clients)",
+ false);
+
+static BoolParameter sendPtrEvents("SendPointerEvents",
+ "Send pointer (mouse) events to the server.", true);
+static BoolParameter sendKeyEvents("SendKeyEvents",
+ "Send key presses (and releases) to the server.", true);
+
+static BoolParameter clientCutText("ClientCutText",
+ "Send clipboard changes to the server.", true);
+static BoolParameter serverCutText("ServerCutText",
+ "Accept clipboard changes from the server.", true);
+
+static BoolParameter protocol3_3("Protocol3.3",
+ "Only use protocol version 3.3", false);
+
+static IntParameter ptrEventInterval("PointerEventInterval",
+ "The interval to delay between sending one pointer event "
+ "and the next.", 0);
+static BoolParameter emulate3("Emulate3",
+ "Emulate middle mouse button when left and right buttons "
+ "are used simulatenously.", false);
+
+static BoolParameter acceptBell("AcceptBell",
+ "Produce a system beep when requested to by the server.",
+ true);
+
+static StringParameter monitor("Monitor", "The monitor to open the VNC Viewer window on, if available.", "");
+static StringParameter menuKey("MenuKey", "The key which brings up the popup menu", "F8");
+
+
+CViewOptions::CViewOptions()
+: useLocalCursor(::useLocalCursor), useDesktopResize(::useDesktopResize),
+autoSelect(::autoSelect), fullColour(::fullColour), fullScreen(::fullScreen),
+shared(::sharedConnection), sendPtrEvents(::sendPtrEvents), sendKeyEvents(::sendKeyEvents),
+preferredEncoding(encodingZRLE), clientCutText(::clientCutText), serverCutText(::serverCutText),
+protocol3_3(::protocol3_3), acceptBell(::acceptBell), lowColourLevel(::lowColourLevel),
+pointerEventInterval(ptrEventInterval), emulate3(::emulate3), monitor(::monitor.getData())
+{
+ CharArray encodingName(::preferredEncoding.getData());
+ preferredEncoding = encodingNum(encodingName.buf);
+ setMenuKey(CharArray(::menuKey.getData()).buf);
+}
+
+
+void CViewOptions::readFromFile(const char* filename) {
+ FILE* f = fopen(filename, "r");
+ if (!f)
+ throw rdr::Exception("Failed to read configuration file");
+
+ try {
+ char line[4096];
+ CharArray section;
+
+ CharArray hostTmp;
+ int portTmp = 0;
+
+ while (!feof(f)) {
+ // Read the next line
+ if (!fgets(line, sizeof(line), f)) {
+ if (feof(f))
+ break;
+ throw rdr::SystemException("fgets", ferror(f));
+ }
+ int len=strlen(line);
+ if (line[len-1] == '\n') {
+ line[len-1] = 0;
+ len--;
+ }
+
+ // Process the line
+ if (line[0] == ';') {
+ // Comment
+ } else if (line[0] == '[') {
+ // Entering a new section
+ if (!strSplit(&line[1], ']', §ion.buf, 0))
+ throw rdr::Exception("bad Section");
+ } else {
+ // Reading an option
+ CharArray name;
+ CharArray value;
+ if (!strSplit(line, '=', &name.buf, &value.buf))
+ throw rdr::Exception("bad Name/Value pair");
+
+ if (stricmp(section.buf, "Connection") == 0) {
+ if (stricmp(name.buf, "Host") == 0) {
+ hostTmp.replaceBuf(value.takeBuf());
+ } else if (stricmp(name.buf, "Port") == 0) {
+ portTmp = atoi(value.buf);
+ } else if (stricmp(name.buf, "UserName") == 0) {
+ userName.replaceBuf(value.takeBuf());
+ } else if (stricmp(name.buf, "Password") == 0) {
+ int len = 0;
+ CharArray obfuscated;
+ rdr::HexInStream::hexStrToBin(value.buf, &obfuscated.buf, &len);
+ if (len == 8) {
+ password.replaceBuf(new char[9]);
+ memcpy(password.buf, obfuscated.buf, 8);
+ vncAuthUnobfuscatePasswd(password.buf);
+ password.buf[8] = 0;
+ }
+ }
+ } else if (stricmp(section.buf, "Options") == 0) {
+ // V4 options
+ if (stricmp(name.buf, "UseLocalCursor") == 0) {
+ useLocalCursor = atoi(value.buf);
+ } else if (stricmp(name.buf, "UseDesktopResize") == 0) {
+ useDesktopResize = atoi(value.buf);
+ } else if (stricmp(name.buf, "FullScreen") == 0) {
+ fullScreen = atoi(value.buf);
+ } else if (stricmp(name.buf, "FullColour") == 0) {
+ fullColour = atoi(value.buf);
+ } else if (stricmp(name.buf, "LowColourLevel") == 0) {
+ lowColourLevel = atoi(value.buf);
+ } else if (stricmp(name.buf, "PreferredEncoding") == 0) {
+ preferredEncoding = encodingNum(value.buf);
+ } else if ((stricmp(name.buf, "AutoDetect") == 0) ||
+ (stricmp(name.buf, "AutoSelect") == 0)) {
+ autoSelect = atoi(value.buf);
+ } else if (stricmp(name.buf, "Shared") == 0) {
+ shared = atoi(value.buf);
+ } else if (stricmp(name.buf, "SendPtrEvents") == 0) {
+ sendPtrEvents = atoi(value.buf);
+ } else if (stricmp(name.buf, "SendKeyEvents") == 0) {
+ sendKeyEvents = atoi(value.buf);
+ } else if (stricmp(name.buf, "SendCutText") == 0) {
+ clientCutText = atoi(value.buf);
+ } else if (stricmp(name.buf, "AcceptCutText") == 0) {
+ serverCutText = atoi(value.buf);
+ } else if (stricmp(name.buf, "Emulate3") == 0) {
+ emulate3 = atoi(value.buf);
+ } else if (stricmp(name.buf, "PointerEventInterval") == 0) {
+ pointerEventInterval = atoi(value.buf);
+ } else if (stricmp(name.buf, "Monitor") == 0) {
+ monitor.replaceBuf(value.takeBuf());
+ } else if (stricmp(name.buf, "MenuKey") == 0) {
+ setMenuKey(value.buf);
+
+ // Legacy options
+ } else if (stricmp(name.buf, "Preferred_Encoding") == 0) {
+ preferredEncoding = atoi(value.buf);
+ } else if (stricmp(name.buf, "8bit") == 0) {
+ fullColour = !atoi(value.buf);
+ } else if (stricmp(name.buf, "FullScreen") == 0) {
+ fullScreen = atoi(value.buf);
+ } else if (stricmp(name.buf, "ViewOnly") == 0) {
+ sendPtrEvents = sendKeyEvents = !atoi(value.buf);
+ } else if (stricmp(name.buf, "DisableClipboard") == 0) {
+ clientCutText = serverCutText = !atoi(value.buf);
+ }
+ }
+ }
+ }
+ fclose(f); f=0;
+
+ // Process the Host and Port
+ if (hostTmp.buf) {
+ int hostLen = strlen(hostTmp.buf) + 2 + 17;
+ host.replaceBuf(new char[hostLen]);
+ strCopy(host.buf, hostTmp.buf, hostLen);
+ if (portTmp) {
+ strncat(host.buf, "::", hostLen-1);
+ char tmp[16];
+ sprintf(tmp, "%d", portTmp);
+ strncat(host.buf, tmp, hostLen-1);
+ }
+ }
+
+ setConfigFileName(filename);
+ } catch (rdr::Exception&) {
+ if (f) fclose(f);
+ throw;
+ }
+}
+
+void CViewOptions::writeToFile(const char* filename) {
+ FILE* f = fopen(filename, "w");
+ if (!f)
+ throw rdr::Exception("Failed to write configuration file");
+
+ try {
+ // - Split server into host and port and save
+ fprintf(f, "[Connection]\n");
+
+ fprintf(f, "Host=%s\n", host.buf);
+ if (userName.buf)
+ fprintf(f, "UserName=%s\n", userName.buf);
+ if (password.buf) {
+ // - Warn the user before saving the password
+ if (MsgBox(0, _T("Do you want to include the VNC Password in this configuration file?\n")
+ _T("Storing the password is more convenient but poses a security risk."),
+ MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDYES) {
+ char obfuscated[9];
+ memset(obfuscated, 0, sizeof(obfuscated));
+ strCopy(obfuscated, password.buf, sizeof(obfuscated));
+ vncAuthObfuscatePasswd(obfuscated);
+ CharArray obfuscatedHex = rdr::HexOutStream::binToHexStr(obfuscated, 8);
+ fprintf(f, "Password=%s\n", obfuscatedHex.buf);
+ }
+ }
+
+ // - Save the other options
+ fprintf(f, "[Options]\n");
+
+ fprintf(f, "UseLocalCursor=%d\n", (int)useLocalCursor);
+ fprintf(f, "UseDesktopResize=%d\n", (int)useDesktopResize);
+ fprintf(f, "FullScreen=%d\n", (int)fullScreen);
+ fprintf(f, "FullColour=%d\n", (int)fullColour);
+ fprintf(f, "LowColourLevel=%d\n", lowColourLevel);
+ fprintf(f, "PreferredEncoding=%s\n", encodingName(preferredEncoding));
+ fprintf(f, "AutoSelect=%d\n", (int)autoSelect);
+ fprintf(f, "Shared=%d\n", (int)shared);
+ fprintf(f, "SendPtrEvents=%d\n", (int)sendPtrEvents);
+ fprintf(f, "SendKeyEvents=%d\n", (int)sendKeyEvents);
+ fprintf(f, "SendCutText=%d\n", (int)clientCutText);
+ fprintf(f, "AcceptCutText=%d\n", (int)serverCutText);
+ fprintf(f, "Emulate3=%d\n", (int)emulate3);
+ fprintf(f, "PointerEventInterval=%d\n", pointerEventInterval);
+ if (monitor.buf)
+ fprintf(f, "Monitor=%s\n", monitor.buf);
+ fprintf(f, "MenuKey=%s\n", CharArray(menuKeyName()).buf);
+ fclose(f); f=0;
+
+ setConfigFileName(filename);
+ } catch (rdr::Exception&) {
+ if (f) fclose(f);
+ throw;
+ }
+}
+
+
+void CViewOptions::writeDefaults() {
+ RegKey key;
+ key.createKey(HKEY_CURRENT_USER, _T("Software\\RealVNC\\VNCviewer4"));
+ key.setBool(_T("UseLocalCursor"), useLocalCursor);
+ key.setBool(_T("UseDesktopResize"), useDesktopResize);
+ key.setBool(_T("FullScreen"), fullScreen);
+ key.setBool(_T("FullColour"), fullColour);
+ key.setInt(_T("LowColourLevel"), lowColourLevel);
+ key.setString(_T("PreferredEncoding"), TStr(encodingName(preferredEncoding)));
+ key.setBool(_T("AutoSelect"), autoSelect);
+ key.setBool(_T("Shared"), shared);
+ key.setBool(_T("SendPointerEvents"), sendPtrEvents);
+ key.setBool(_T("SendKeyEvents"), sendKeyEvents);
+ key.setBool(_T("ClientCutText"), clientCutText);
+ key.setBool(_T("ServerCutText"), serverCutText);
+ key.setBool(_T("Protocol3.3"), protocol3_3);
+ key.setBool(_T("AcceptBell"), acceptBell);
+ key.setBool(_T("Emulate3"), emulate3);
+ key.setInt(_T("PointerEventInterval"), pointerEventInterval);
+ if (monitor.buf)
+ key.setString(_T("Monitor"), TStr(monitor.buf));
+ key.setString(_T("MenuKey"), TCharArray(menuKeyName()).buf);
+}
+
+
+void CViewOptions::setUserName(const char* user) {userName.replaceBuf(strDup(user));}
+void CViewOptions::setPassword(const char* pwd) {password.replaceBuf(strDup(pwd));}
+void CViewOptions::setConfigFileName(const char* cfn) {configFileName.replaceBuf(strDup(cfn));}
+void CViewOptions::setHost(const char* h) {host.replaceBuf(strDup(h));}
+void CViewOptions::setMonitor(const char* m) {monitor.replaceBuf(strDup(m));}
+
+void CViewOptions::setMenuKey(const char* keyName) {
+ if (!keyName[0]) {
+ menuKey = 0;
+ } else {
+ menuKey = VK_F8;
+ if (keyName[0] == 'F') {
+ UINT fKey = atoi(&keyName[1]);
+ if (fKey >= 1 && fKey <= 12)
+ menuKey = fKey-1 + VK_F1;
+ }
+ }
+}
+char* CViewOptions::menuKeyName() {
+ int fNum = (menuKey-VK_F1)+1;
+ if (fNum<1 || fNum>12)
+ return strDup("");
+ CharArray menuKeyStr(4);
+ sprintf(menuKeyStr.buf, "F%d", fNum);
+ return menuKeyStr.takeBuf();
+}
+
+
+CViewOptions& CViewOptions::operator=(const CViewOptions& o) {
+ useLocalCursor = o.useLocalCursor;
+ useDesktopResize = o.useDesktopResize;
+ fullScreen = o.fullScreen;
+ fullColour = o.fullColour;
+ lowColourLevel = o.lowColourLevel;
+ preferredEncoding = o.preferredEncoding;
+ autoSelect = o.autoSelect;
+ shared = o.shared;
+ sendPtrEvents = o.sendPtrEvents;
+ sendKeyEvents = o.sendKeyEvents;
+ clientCutText = o.clientCutText;
+ serverCutText = o.serverCutText;
+ emulate3 = o.emulate3;
+ pointerEventInterval = o.pointerEventInterval;
+ protocol3_3 = o.protocol3_3;
+ acceptBell = o.acceptBell;
+ setUserName(o.userName.buf);
+ setPassword(o.password.buf);
+ setConfigFileName(o.configFileName.buf);
+ setHost(o.host.buf);
+ setMonitor(o.monitor.buf);
+ menuKey = o.menuKey;
+ return *this;
+}
\ No newline at end of file