You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CViewOptions.cxx 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. #include <vncviewer/CViewOptions.h>
  19. #include <rfb/Configuration.h>
  20. #include <rfb/encodings.h>
  21. #include <rfb/vncAuth.h>
  22. #include <rfb/LogWriter.h>
  23. #include <rfb_win32/Win32Util.h>
  24. #include <rfb_win32/Registry.h>
  25. #include <rdr/HexInStream.h>
  26. #include <rdr/HexOutStream.h>
  27. #include <stdlib.h>
  28. using namespace rfb;
  29. using namespace rfb::win32;
  30. static StringParameter passwordFile("PasswordFile",
  31. "Password file for VNC authentication", "");
  32. static BoolParameter useLocalCursor("UseLocalCursor", "Render the mouse cursor locally", true);
  33. static BoolParameter useDesktopResize("UseDesktopResize", "Support dynamic desktop resizing", true);
  34. static BoolParameter fullColour("FullColor",
  35. "Use full color", true);
  36. static AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour);
  37. static IntParameter lowColourLevel("LowColorLevel",
  38. "Color level to use on slow connections. "
  39. "0 = Very Low (8 colors), 1 = Low (64 colors), 2 = Medium (256 colors)",
  40. 2);
  41. static AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel);
  42. static BoolParameter fullScreen("FullScreen",
  43. "Use the whole display to show the remote desktop."
  44. "(Press F8 to access the viewer menu)",
  45. false);
  46. static StringParameter preferredEncoding("PreferredEncoding",
  47. "Preferred encoding to use (Tight, ZRLE, Hextile or"
  48. " Raw)", "Tight");
  49. static BoolParameter autoSelect("AutoSelect",
  50. "Auto select pixel format and encoding. "
  51. "Default if PreferredEncoding and FullColor are not specified.",
  52. true);
  53. static BoolParameter sharedConnection("Shared",
  54. "Allow existing connections to the server to continue."
  55. "(Default is to disconnect all other clients)",
  56. false);
  57. static BoolParameter sendPtrEvents("SendPointerEvents",
  58. "Send pointer (mouse) events to the server.", true);
  59. static BoolParameter sendKeyEvents("SendKeyEvents",
  60. "Send key presses (and releases) to the server.", true);
  61. static BoolParameter clientCutText("ClientCutText",
  62. "Send clipboard changes to the server.", true);
  63. static BoolParameter serverCutText("ServerCutText",
  64. "Accept clipboard changes from the server.", true);
  65. static BoolParameter protocol3_3("Protocol3.3",
  66. "Only use protocol version 3.3", false);
  67. static IntParameter ptrEventInterval("PointerEventInterval",
  68. "The interval to delay between sending one pointer event "
  69. "and the next.", 0);
  70. static BoolParameter emulate3("Emulate3",
  71. "Emulate middle mouse button when left and right buttons "
  72. "are used simulatenously.", false);
  73. static BoolParameter acceptBell("AcceptBell",
  74. "Produce a system beep when requested to by the server.",
  75. true);
  76. static StringParameter monitor("Monitor", "The monitor to open the VNC Viewer window on, if available.", "");
  77. static StringParameter menuKey("MenuKey", "The key which brings up the popup menu", "F8");
  78. static BoolParameter customCompressLevel("CustomCompressLevel",
  79. "Use custom compression level. "
  80. "Default if CompressLevel is specified.", false);
  81. static IntParameter compressLevel("CompressLevel",
  82. "Use specified compression level"
  83. "0 = Low, 9 = High",
  84. 6);
  85. static BoolParameter noJpeg("NoJPEG",
  86. "Disable lossy JPEG compression in Tight encoding.",
  87. false);
  88. static IntParameter qualityLevel("QualityLevel",
  89. "JPEG quality level. "
  90. "0 = Low, 9 = High",
  91. 6);
  92. CViewOptions::CViewOptions()
  93. : useLocalCursor(::useLocalCursor), useDesktopResize(::useDesktopResize),
  94. autoSelect(::autoSelect), fullColour(::fullColour), fullScreen(::fullScreen),
  95. shared(::sharedConnection), sendPtrEvents(::sendPtrEvents), sendKeyEvents(::sendKeyEvents),
  96. preferredEncoding(encodingZRLE), clientCutText(::clientCutText), serverCutText(::serverCutText),
  97. protocol3_3(::protocol3_3), acceptBell(::acceptBell), lowColourLevel(::lowColourLevel),
  98. pointerEventInterval(ptrEventInterval), emulate3(::emulate3), monitor(::monitor.getData()),
  99. customCompressLevel(::customCompressLevel), compressLevel(::compressLevel),
  100. noJpeg(::noJpeg), qualityLevel(::qualityLevel), passwordFile(::passwordFile.getData())
  101. {
  102. CharArray encodingName(::preferredEncoding.getData());
  103. preferredEncoding = encodingNum(encodingName.buf);
  104. setMenuKey(CharArray(::menuKey.getData()).buf);
  105. if (!::autoSelect.hasBeenSet()) {
  106. // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
  107. autoSelect = (!::preferredEncoding.hasBeenSet()
  108. && !::fullColour.hasBeenSet()
  109. && !::fullColourAlias.hasBeenSet());
  110. }
  111. if (!::customCompressLevel.hasBeenSet()) {
  112. // Default to CustomCompressLevel=1 if CompressLevel is used.
  113. customCompressLevel = ::compressLevel.hasBeenSet();
  114. }
  115. }
  116. void CViewOptions::readFromFile(const char* filename) {
  117. FILE* f = fopen(filename, "r");
  118. if (!f)
  119. throw rdr::Exception("Failed to read configuration file");
  120. try {
  121. char line[4096];
  122. CharArray section;
  123. CharArray hostTmp;
  124. int portTmp = 0;
  125. while (!feof(f)) {
  126. // Read the next line
  127. if (!fgets(line, sizeof(line), f)) {
  128. if (feof(f))
  129. break;
  130. throw rdr::SystemException("fgets", ferror(f));
  131. }
  132. int len=strlen(line);
  133. if (line[len-1] == '\n') {
  134. line[len-1] = 0;
  135. len--;
  136. }
  137. // Process the line
  138. if (line[0] == ';') {
  139. // Comment
  140. } else if (line[0] == '[') {
  141. // Entering a new section
  142. if (!strSplit(&line[1], ']', &section.buf, 0))
  143. throw rdr::Exception("bad Section");
  144. } else {
  145. // Reading an option
  146. CharArray name;
  147. CharArray value;
  148. if (!strSplit(line, '=', &name.buf, &value.buf))
  149. throw rdr::Exception("bad Name/Value pair");
  150. if (stricmp(section.buf, "Connection") == 0) {
  151. if (stricmp(name.buf, "Host") == 0) {
  152. hostTmp.replaceBuf(value.takeBuf());
  153. } else if (stricmp(name.buf, "Port") == 0) {
  154. portTmp = atoi(value.buf);
  155. } else if (stricmp(name.buf, "UserName") == 0) {
  156. userName.replaceBuf(value.takeBuf());
  157. } else if (stricmp(name.buf, "Password") == 0) {
  158. int len = 0;
  159. CharArray obfuscated;
  160. rdr::HexInStream::hexStrToBin(value.buf, &obfuscated.buf, &len);
  161. if (len == 8) {
  162. password.replaceBuf(new char[9]);
  163. memcpy(password.buf, obfuscated.buf, 8);
  164. vncAuthUnobfuscatePasswd(password.buf);
  165. password.buf[8] = 0;
  166. }
  167. }
  168. } else if (stricmp(section.buf, "Options") == 0) {
  169. // V4 options
  170. if (stricmp(name.buf, "UseLocalCursor") == 0) {
  171. useLocalCursor = atoi(value.buf);
  172. } else if (stricmp(name.buf, "UseDesktopResize") == 0) {
  173. useDesktopResize = atoi(value.buf);
  174. } else if (stricmp(name.buf, "FullScreen") == 0) {
  175. fullScreen = atoi(value.buf);
  176. } else if (stricmp(name.buf, "FullColour") == 0) {
  177. fullColour = atoi(value.buf);
  178. } else if (stricmp(name.buf, "LowColourLevel") == 0) {
  179. lowColourLevel = atoi(value.buf);
  180. } else if (stricmp(name.buf, "PreferredEncoding") == 0) {
  181. preferredEncoding = encodingNum(value.buf);
  182. } else if ((stricmp(name.buf, "AutoDetect") == 0) ||
  183. (stricmp(name.buf, "AutoSelect") == 0)) {
  184. autoSelect = atoi(value.buf);
  185. } else if (stricmp(name.buf, "Shared") == 0) {
  186. shared = atoi(value.buf);
  187. } else if (stricmp(name.buf, "SendPtrEvents") == 0) {
  188. sendPtrEvents = atoi(value.buf);
  189. } else if (stricmp(name.buf, "SendKeyEvents") == 0) {
  190. sendKeyEvents = atoi(value.buf);
  191. } else if (stricmp(name.buf, "SendCutText") == 0) {
  192. clientCutText = atoi(value.buf);
  193. } else if (stricmp(name.buf, "AcceptCutText") == 0) {
  194. serverCutText = atoi(value.buf);
  195. } else if (stricmp(name.buf, "Emulate3") == 0) {
  196. emulate3 = atoi(value.buf);
  197. } else if (stricmp(name.buf, "PointerEventInterval") == 0) {
  198. pointerEventInterval = atoi(value.buf);
  199. } else if (stricmp(name.buf, "Monitor") == 0) {
  200. monitor.replaceBuf(value.takeBuf());
  201. } else if (stricmp(name.buf, "MenuKey") == 0) {
  202. setMenuKey(value.buf);
  203. } else if (stricmp(name.buf, "CustomCompressLevel") == 0) {
  204. customCompressLevel = atoi(value.buf);
  205. } else if (stricmp(name.buf, "CompressLevel") == 0) {
  206. compressLevel = atoi(value.buf);
  207. } else if (stricmp(name.buf, "NoJPEG") == 0) {
  208. noJpeg = atoi(value.buf);
  209. } else if (stricmp(name.buf, "QualityLevel") == 0) {
  210. qualityLevel = atoi(value.buf);
  211. // Legacy options
  212. } else if (stricmp(name.buf, "Preferred_Encoding") == 0) {
  213. preferredEncoding = atoi(value.buf);
  214. } else if (stricmp(name.buf, "8bit") == 0) {
  215. fullColour = !atoi(value.buf);
  216. } else if (stricmp(name.buf, "FullScreen") == 0) {
  217. fullScreen = atoi(value.buf);
  218. } else if (stricmp(name.buf, "ViewOnly") == 0) {
  219. sendPtrEvents = sendKeyEvents = !atoi(value.buf);
  220. } else if (stricmp(name.buf, "DisableClipboard") == 0) {
  221. clientCutText = serverCutText = !atoi(value.buf);
  222. }
  223. }
  224. }
  225. }
  226. fclose(f); f=0;
  227. // Process the Host and Port
  228. if (hostTmp.buf) {
  229. int hostLen = strlen(hostTmp.buf) + 2 + 17;
  230. host.replaceBuf(new char[hostLen]);
  231. strCopy(host.buf, hostTmp.buf, hostLen);
  232. if (portTmp) {
  233. strncat(host.buf, "::", hostLen-1);
  234. char tmp[16];
  235. sprintf(tmp, "%d", portTmp);
  236. strncat(host.buf, tmp, hostLen-1);
  237. }
  238. }
  239. setConfigFileName(filename);
  240. } catch (rdr::Exception&) {
  241. if (f) fclose(f);
  242. throw;
  243. }
  244. }
  245. void CViewOptions::writeToFile(const char* filename) {
  246. FILE* f = fopen(filename, "w");
  247. if (!f)
  248. throw rdr::Exception("Failed to write configuration file");
  249. try {
  250. // - Split server into host and port and save
  251. fprintf(f, "[Connection]\n");
  252. fprintf(f, "Host=%s\n", host.buf);
  253. if (userName.buf)
  254. fprintf(f, "UserName=%s\n", userName.buf);
  255. if (password.buf) {
  256. // - Warn the user before saving the password
  257. if (MsgBox(0, _T("Do you want to include the VNC Password in this configuration file?\n")
  258. _T("Storing the password is more convenient but poses a security risk."),
  259. MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDYES) {
  260. char obfuscated[9];
  261. memset(obfuscated, 0, sizeof(obfuscated));
  262. strCopy(obfuscated, password.buf, sizeof(obfuscated));
  263. vncAuthObfuscatePasswd(obfuscated);
  264. CharArray obfuscatedHex = rdr::HexOutStream::binToHexStr(obfuscated, 8);
  265. fprintf(f, "Password=%s\n", obfuscatedHex.buf);
  266. }
  267. }
  268. // - Save the other options
  269. fprintf(f, "[Options]\n");
  270. fprintf(f, "UseLocalCursor=%d\n", (int)useLocalCursor);
  271. fprintf(f, "UseDesktopResize=%d\n", (int)useDesktopResize);
  272. fprintf(f, "FullScreen=%d\n", (int)fullScreen);
  273. fprintf(f, "FullColour=%d\n", (int)fullColour);
  274. fprintf(f, "LowColourLevel=%d\n", lowColourLevel);
  275. fprintf(f, "PreferredEncoding=%s\n", encodingName(preferredEncoding));
  276. fprintf(f, "AutoSelect=%d\n", (int)autoSelect);
  277. fprintf(f, "Shared=%d\n", (int)shared);
  278. fprintf(f, "SendPtrEvents=%d\n", (int)sendPtrEvents);
  279. fprintf(f, "SendKeyEvents=%d\n", (int)sendKeyEvents);
  280. fprintf(f, "SendCutText=%d\n", (int)clientCutText);
  281. fprintf(f, "AcceptCutText=%d\n", (int)serverCutText);
  282. fprintf(f, "Emulate3=%d\n", (int)emulate3);
  283. fprintf(f, "PointerEventInterval=%d\n", pointerEventInterval);
  284. if (monitor.buf)
  285. fprintf(f, "Monitor=%s\n", monitor.buf);
  286. fprintf(f, "MenuKey=%s\n", CharArray(menuKeyName()).buf);
  287. fprintf(f, "CustomCompressLevel=%d\n", customCompressLevel);
  288. fprintf(f, "CompressLevel=%d\n", compressLevel);
  289. fprintf(f, "NoJPEG=%d\n", noJpeg);
  290. fprintf(f, "QualityLevel=%d\n", qualityLevel);
  291. fclose(f); f=0;
  292. setConfigFileName(filename);
  293. } catch (rdr::Exception&) {
  294. if (f) fclose(f);
  295. throw;
  296. }
  297. }
  298. void CViewOptions::writeDefaults() {
  299. RegKey key;
  300. key.createKey(HKEY_CURRENT_USER, _T("Software\\TightVNC\\VNCviewer4"));
  301. key.setBool(_T("UseLocalCursor"), useLocalCursor);
  302. key.setBool(_T("UseDesktopResize"), useDesktopResize);
  303. key.setBool(_T("FullScreen"), fullScreen);
  304. key.setBool(_T("FullColour"), fullColour);
  305. key.setInt(_T("LowColourLevel"), lowColourLevel);
  306. key.setString(_T("PreferredEncoding"), TStr(encodingName(preferredEncoding)));
  307. key.setBool(_T("AutoSelect"), autoSelect);
  308. key.setBool(_T("Shared"), shared);
  309. key.setBool(_T("SendPointerEvents"), sendPtrEvents);
  310. key.setBool(_T("SendKeyEvents"), sendKeyEvents);
  311. key.setBool(_T("ClientCutText"), clientCutText);
  312. key.setBool(_T("ServerCutText"), serverCutText);
  313. key.setBool(_T("Protocol3.3"), protocol3_3);
  314. key.setBool(_T("AcceptBell"), acceptBell);
  315. key.setBool(_T("Emulate3"), emulate3);
  316. key.setInt(_T("PointerEventInterval"), pointerEventInterval);
  317. if (monitor.buf)
  318. key.setString(_T("Monitor"), TStr(monitor.buf));
  319. key.setString(_T("MenuKey"), TCharArray(menuKeyName()).buf);
  320. key.setInt(_T("CustomCompressLevel"), customCompressLevel);
  321. key.setInt(_T("CompressLevel"), compressLevel);
  322. key.setInt(_T("NoJPEG"), noJpeg);
  323. key.setInt(_T("QualityLevel"), qualityLevel);
  324. }
  325. void CViewOptions::setUserName(const char* user) {userName.replaceBuf(strDup(user));}
  326. void CViewOptions::setPassword(const char* pwd) {password.replaceBuf(strDup(pwd));}
  327. void CViewOptions::setConfigFileName(const char* cfn) {configFileName.replaceBuf(strDup(cfn));}
  328. void CViewOptions::setHost(const char* h) {host.replaceBuf(strDup(h));}
  329. void CViewOptions::setMonitor(const char* m) {monitor.replaceBuf(strDup(m));}
  330. void CViewOptions::setMenuKey(const char* keyName) {
  331. if (!keyName[0]) {
  332. menuKey = 0;
  333. } else {
  334. menuKey = VK_F8;
  335. if (keyName[0] == 'F') {
  336. UINT fKey = atoi(&keyName[1]);
  337. if (fKey >= 1 && fKey <= 12)
  338. menuKey = fKey-1 + VK_F1;
  339. }
  340. }
  341. }
  342. char* CViewOptions::menuKeyName() {
  343. int fNum = (menuKey-VK_F1)+1;
  344. if (fNum<1 || fNum>12)
  345. return strDup("");
  346. CharArray menuKeyStr(4);
  347. sprintf(menuKeyStr.buf, "F%d", fNum);
  348. return menuKeyStr.takeBuf();
  349. }
  350. CViewOptions& CViewOptions::operator=(const CViewOptions& o) {
  351. useLocalCursor = o.useLocalCursor;
  352. useDesktopResize = o.useDesktopResize;
  353. fullScreen = o.fullScreen;
  354. fullColour = o.fullColour;
  355. lowColourLevel = o.lowColourLevel;
  356. preferredEncoding = o.preferredEncoding;
  357. autoSelect = o.autoSelect;
  358. shared = o.shared;
  359. sendPtrEvents = o.sendPtrEvents;
  360. sendKeyEvents = o.sendKeyEvents;
  361. clientCutText = o.clientCutText;
  362. serverCutText = o.serverCutText;
  363. emulate3 = o.emulate3;
  364. pointerEventInterval = o.pointerEventInterval;
  365. protocol3_3 = o.protocol3_3;
  366. acceptBell = o.acceptBell;
  367. setUserName(o.userName.buf);
  368. setPassword(o.password.buf);
  369. setConfigFileName(o.configFileName.buf);
  370. setHost(o.host.buf);
  371. setMonitor(o.monitor.buf);
  372. menuKey = o.menuKey;
  373. customCompressLevel = o.customCompressLevel;
  374. compressLevel = o.compressLevel;
  375. noJpeg = o.noJpeg;
  376. qualityLevel = o.qualityLevel;
  377. return *this;
  378. }