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

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