blob: 71c07f9dd874e95bfb0c20fd58eefdf601e156ad [file] [log] [blame]
Constantin Kaplinsky729598c2006-05-25 05:12:25 +00001/* Copyright (C) 2002-2005 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
19#include <vncviewer/CConnOptions.h>
20#include <rfb/Configuration.h>
21#include <rfb/encodings.h>
22#include <rfb/LogWriter.h>
23#include <rfb_win32/MsgBox.h>
24#include <rfb_win32/Registry.h>
25#include <rdr/HexInStream.h>
26#include <rdr/HexOutStream.h>
27#include <stdlib.h>
28
29using namespace rfb;
30using namespace rfb::win32;
31
32static StringParameter passwordFile("PasswordFile",
33 "Password file for VNC authentication", "");
34
35// - Settings stored in the registry & in .vnc files, by Save Defaults and
36// Save Configuration respectively.
37
38static BoolParameter useLocalCursor("UseLocalCursor", "Render the mouse cursor locally", true);
39static BoolParameter useDesktopResize("UseDesktopResize", "Support dynamic desktop resizing", true);
40
41static BoolParameter fullColour("FullColor",
42 "Use full color", true);
43static AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour);
44
45static IntParameter lowColourLevel("LowColorLevel",
46 "Color level to use on slow connections. "
47 "0 = Very Low (8 colors), 1 = Low (64 colors), 2 = Medium (256 colors)",
48 2);
49static AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel);
50
51static BoolParameter fullScreen("FullScreen",
52 "Use the whole display to show the remote desktop."
53 "(Press F8 to access the viewer menu)",
54 false);
55static StringParameter preferredEncoding("PreferredEncoding",
56 "Preferred encoding to use (Tight, ZRLE, Hextile or"
57 " Raw)", "Tight");
58static BoolParameter autoSelect("AutoSelect",
59 "Auto select pixel format and encoding. "
60 "Default if PreferredEncoding and FullColor are not specified.",
61 true);
62static BoolParameter sharedConnection("Shared",
63 "Allow existing connections to the server to continue."
64 "(Default is to disconnect all other clients)",
65 false);
66
67static BoolParameter sendPtrEvents("SendPointerEvents",
68 "Send pointer (mouse) events to the server.", true);
69static BoolParameter sendKeyEvents("SendKeyEvents",
70 "Send key presses (and releases) to the server.", true);
71
72static BoolParameter clientCutText("ClientCutText",
73 "Send clipboard changes to the server.", true);
74static BoolParameter serverCutText("ServerCutText",
75 "Accept clipboard changes from the server.", true);
76
77static BoolParameter disableWinKeys("DisableWinKeys",
78 "Pass special Windows keys directly to the server.", true);
79
80static BoolParameter protocol3_3("Protocol3.3",
81 "Only use protocol version 3.3", false);
82
83static IntParameter ptrEventInterval("PointerEventInterval",
84 "The interval to delay between sending one pointer event "
85 "and the next.", 0);
86static BoolParameter emulate3("Emulate3",
87 "Emulate middle mouse button when left and right buttons "
88 "are used simulatenously.", false);
89
90static BoolParameter acceptBell("AcceptBell",
91 "Produce a system beep when requested to by the server.",
92 true);
93
94static BoolParameter showToolbar("ShowToolbar", "Show toolbar by default.", true);
95
96static StringParameter monitor("Monitor", "The monitor to open the VNC Viewer window on, if available.", "");
97static StringParameter menuKey("MenuKey", "The key which brings up the popup menu", "F8");
98static BoolParameter autoReconnect("AutoReconnect", "Offer to reconnect to the remote server if the connection"
99 "is dropped because an error occurs.", true);
100
101static BoolParameter customCompressLevel("CustomCompressLevel",
102 "Use custom compression level. "
103 "Default if CompressLevel is specified.", false);
104
105static IntParameter compressLevel("CompressLevel",
106 "Use specified compression level"
107 "0 = Low, 9 = High",
108 6);
109
110static BoolParameter noJpeg("NoJPEG",
111 "Disable lossy JPEG compression in Tight encoding.",
112 false);
113
114static IntParameter qualityLevel("QualityLevel",
115 "JPEG quality level. "
116 "0 = Low, 9 = High",
117 6);
118
george82444e8862006-05-27 10:21:28 +0000119static BoolParameter autoScaling("AutoScaling",
120 "Auto rescale local copy of the remote desktop to the client window.",
121 false);
122static IntParameter scale("Scale",
123 "Scale local copy of the remote desktop, in percent",
124 100);
125
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000126CConnOptions::CConnOptions()
127: useLocalCursor(::useLocalCursor), useDesktopResize(::useDesktopResize),
128autoSelect(::autoSelect), fullColour(::fullColour), fullScreen(::fullScreen),
129shared(::sharedConnection), sendPtrEvents(::sendPtrEvents), sendKeyEvents(::sendKeyEvents),
130preferredEncoding(encodingZRLE), clientCutText(::clientCutText), serverCutText(::serverCutText),
131disableWinKeys(::disableWinKeys), protocol3_3(::protocol3_3), acceptBell(::acceptBell),
132lowColourLevel(::lowColourLevel), pointerEventInterval(ptrEventInterval),
133emulate3(::emulate3), monitor(::monitor.getData()), showToolbar(::showToolbar),
134customCompressLevel(::customCompressLevel), compressLevel(::compressLevel),
135noJpeg(::noJpeg), qualityLevel(::qualityLevel), passwordFile(::passwordFile.getData()),
george82444e8862006-05-27 10:21:28 +0000136autoReconnect(::autoReconnect), autoScaling(::autoScaling), scale(::scale)
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000137{
138 if (autoSelect) {
139 preferredEncoding = encodingZRLE;
140 } else {
141 CharArray encodingName(::preferredEncoding.getData());
142 preferredEncoding = encodingNum(encodingName.buf);
143 }
144 setMenuKey(CharArray(::menuKey.getData()).buf);
145
146 if (!::autoSelect.hasBeenSet()) {
147 // Default to AutoSelect=0 if -PreferredEncoding or -FullColor is used
148 autoSelect = (!::preferredEncoding.hasBeenSet()
149 && !::fullColour.hasBeenSet()
150 && !::fullColourAlias.hasBeenSet());
151 }
152 if (!::customCompressLevel.hasBeenSet()) {
153 // Default to CustomCompressLevel=1 if CompressLevel is used.
154 customCompressLevel = ::compressLevel.hasBeenSet();
155 }
156}
157
158
159void CConnOptions::readFromFile(const char* filename) {
160 FILE* f = fopen(filename, "r");
161 if (!f)
162 throw rdr::Exception("Failed to read configuration file");
163
164 try {
165 char line[4096];
166 CharArray section;
167
168 CharArray hostTmp;
169 int portTmp = 0;
170
171 while (!feof(f)) {
172 // Read the next line
173 if (!fgets(line, sizeof(line), f)) {
174 if (feof(f))
175 break;
176 throw rdr::SystemException("fgets", ferror(f));
177 }
178 int len=strlen(line);
179 if (line[len-1] == '\n') {
180 line[len-1] = 0;
181 len--;
182 }
183
184 // Process the line
185 if (line[0] == ';') {
186 // Comment
187 } else if (line[0] == '[') {
188 // Entering a new section
189 if (!strSplit(&line[1], ']', &section.buf, 0))
190 throw rdr::Exception("bad Section");
191 } else {
192 // Reading an option
193 CharArray name;
194 CharArray value;
195 if (!strSplit(line, '=', &name.buf, &value.buf))
196 throw rdr::Exception("bad Name/Value pair");
197
198 if (stricmp(section.buf, "Connection") == 0) {
199 if (stricmp(name.buf, "Host") == 0) {
200 hostTmp.replaceBuf(value.takeBuf());
201 } else if (stricmp(name.buf, "Port") == 0) {
202 portTmp = atoi(value.buf);
203 } else if (stricmp(name.buf, "UserName") == 0) {
204 userName.replaceBuf(value.takeBuf());
205 } else if (stricmp(name.buf, "Password") == 0) {
206 ObfuscatedPasswd obfPwd;
207 rdr::HexInStream::hexStrToBin(value.buf, (char**)&obfPwd.buf, &obfPwd.length);
208 PlainPasswd passwd(obfPwd);
209 password.replaceBuf(passwd.takeBuf());
210 }
211 } else if (stricmp(section.buf, "Options") == 0) {
212 // V4 options
213 if (stricmp(name.buf, "UseLocalCursor") == 0) {
214 useLocalCursor = atoi(value.buf);
215 } else if (stricmp(name.buf, "UseDesktopResize") == 0) {
216 useDesktopResize = atoi(value.buf);
217 } else if (stricmp(name.buf, "FullScreen") == 0) {
218 fullScreen = atoi(value.buf);
219 } else if (stricmp(name.buf, "FullColour") == 0) {
220 fullColour = atoi(value.buf);
221 } else if (stricmp(name.buf, "LowColourLevel") == 0) {
222 lowColourLevel = atoi(value.buf);
223 } else if (stricmp(name.buf, "PreferredEncoding") == 0) {
224 preferredEncoding = encodingNum(value.buf);
225 } else if ((stricmp(name.buf, "AutoDetect") == 0) ||
226 (stricmp(name.buf, "AutoSelect") == 0)) {
227 autoSelect = atoi(value.buf);
228 } else if (stricmp(name.buf, "Shared") == 0) {
229 shared = atoi(value.buf);
230 } else if (stricmp(name.buf, "SendPtrEvents") == 0) {
231 sendPtrEvents = atoi(value.buf);
232 } else if (stricmp(name.buf, "SendKeyEvents") == 0) {
233 sendKeyEvents = atoi(value.buf);
234 } else if (stricmp(name.buf, "SendCutText") == 0) {
235 clientCutText = atoi(value.buf);
236 } else if (stricmp(name.buf, "AcceptCutText") == 0) {
237 serverCutText = atoi(value.buf);
238 } else if (stricmp(name.buf, "DisableWinKeys") == 0) {
239 disableWinKeys = atoi(value.buf);
240 } else if (stricmp(name.buf, "AcceptBell") == 0) {
241 acceptBell = atoi(value.buf);
242 } else if (stricmp(name.buf, "Emulate3") == 0) {
243 emulate3 = atoi(value.buf);
244 } else if (stricmp(name.buf, "ShowToolbar") == 0) {
245 showToolbar = atoi(value.buf);
246 } else if (stricmp(name.buf, "PointerEventInterval") == 0) {
247 pointerEventInterval = atoi(value.buf);
248 } else if (stricmp(name.buf, "Monitor") == 0) {
249 monitor.replaceBuf(value.takeBuf());
250 } else if (stricmp(name.buf, "MenuKey") == 0) {
251 setMenuKey(value.buf);
252 } else if (stricmp(name.buf, "AutoReconnect") == 0) {
253 autoReconnect = atoi(value.buf);
254
255 } else if (stricmp(name.buf, "CustomCompressLevel") == 0) {
256 customCompressLevel = atoi(value.buf);
257 } else if (stricmp(name.buf, "CompressLevel") == 0) {
258 compressLevel = atoi(value.buf);
259 } else if (stricmp(name.buf, "NoJPEG") == 0) {
260 noJpeg = atoi(value.buf);
261 } else if (stricmp(name.buf, "QualityLevel") == 0) {
262 qualityLevel = atoi(value.buf);
263 // Legacy options
264 } else if (stricmp(name.buf, "Preferred_Encoding") == 0) {
265 preferredEncoding = atoi(value.buf);
266 } else if (stricmp(name.buf, "8bit") == 0) {
267 fullColour = !atoi(value.buf);
268 } else if (stricmp(name.buf, "FullScreen") == 0) {
269 fullScreen = atoi(value.buf);
270 } else if (stricmp(name.buf, "ViewOnly") == 0) {
271 sendPtrEvents = sendKeyEvents = !atoi(value.buf);
272 } else if (stricmp(name.buf, "DisableClipboard") == 0) {
273 clientCutText = serverCutText = !atoi(value.buf);
george82444e8862006-05-27 10:21:28 +0000274 } else if (stricmp(name.buf, "AutoScaling") == 0) {
275 autoScaling = atoi(value.buf);
276 } else if (stricmp(name.buf, "Scale") == 0) {
277 scale = atoi(value.buf);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000278 }
279 }
280 }
281 }
282 fclose(f); f=0;
283
284 // Process the Host and Port
285 if (hostTmp.buf) {
286 int hostLen = strlen(hostTmp.buf) + 2 + 17;
287 host.replaceBuf(new char[hostLen]);
288 strCopy(host.buf, hostTmp.buf, hostLen);
289 if (portTmp) {
290 strncat(host.buf, "::", hostLen-1);
291 char tmp[16];
292 sprintf(tmp, "%d", portTmp);
293 strncat(host.buf, tmp, hostLen-1);
294 }
295 }
296
297 // If AutoSelect is enabled then override the preferred encoding
298 if (autoSelect)
299 preferredEncoding = encodingZRLE;
300
301 setConfigFileName(filename);
302 } catch (rdr::Exception&) {
303 if (f) fclose(f);
304 throw;
305 }
306}
307
308void CConnOptions::writeToFile(const char* filename) {
309 FILE* f = fopen(filename, "w");
310 if (!f)
311 throw rdr::Exception("Failed to write configuration file");
312
313 try {
314 // - Split server into host and port and save
315 fprintf(f, "[Connection]\n");
316
317 fprintf(f, "Host=%s\n", host.buf);
318 if (userName.buf)
319 fprintf(f, "UserName=%s\n", userName.buf);
320 if (password.buf) {
321 // - Warn the user before saving the password
322 if (MsgBox(0, _T("Do you want to include the VNC Password in this configuration file?\n")
323 _T("Storing the password is more convenient but poses a security risk."),
324 MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDYES) {
325 ObfuscatedPasswd obfPwd(password);
326 CharArray obfuscatedHex = rdr::HexOutStream::binToHexStr(obfPwd.buf, obfPwd.length);
327 fprintf(f, "Password=%s\n", obfuscatedHex.buf);
328 }
329 }
330
331 // - Save the other options
332 fprintf(f, "[Options]\n");
333
334 fprintf(f, "UseLocalCursor=%d\n", (int)useLocalCursor);
335 fprintf(f, "UseDesktopResize=%d\n", (int)useDesktopResize);
336 fprintf(f, "FullScreen=%d\n", (int)fullScreen);
337 fprintf(f, "FullColour=%d\n", (int)fullColour);
338 fprintf(f, "LowColourLevel=%d\n", lowColourLevel);
339 fprintf(f, "PreferredEncoding=%s\n", encodingName(preferredEncoding));
340 fprintf(f, "AutoSelect=%d\n", (int)autoSelect);
341 fprintf(f, "Shared=%d\n", (int)shared);
342 fprintf(f, "SendPtrEvents=%d\n", (int)sendPtrEvents);
343 fprintf(f, "SendKeyEvents=%d\n", (int)sendKeyEvents);
344 fprintf(f, "SendCutText=%d\n", (int)clientCutText);
345 fprintf(f, "AcceptCutText=%d\n", (int)serverCutText);
346 fprintf(f, "DisableWinKeys=%d\n", (int)disableWinKeys);
347 fprintf(f, "AcceptBell=%d\n", (int)acceptBell);
348 fprintf(f, "Emulate3=%d\n", (int)emulate3);
349 fprintf(f, "ShowToolbar=%d\n", (int)showToolbar);
350 fprintf(f, "PointerEventInterval=%d\n", pointerEventInterval);
351 if (monitor.buf)
352 fprintf(f, "Monitor=%s\n", monitor.buf);
353 fprintf(f, "MenuKey=%s\n", CharArray(menuKeyName()).buf);
354 fprintf(f, "AutoReconnect=%d\n", (int)autoReconnect);
355 fprintf(f, "CustomCompressLevel=%d\n", customCompressLevel);
356 fprintf(f, "CompressLevel=%d\n", compressLevel);
357 fprintf(f, "NoJPEG=%d\n", noJpeg);
358 fprintf(f, "QualityLevel=%d\n", qualityLevel);
george82444e8862006-05-27 10:21:28 +0000359 fprintf(f, "AutoScaling=%d\n", (int)autoScaling);
360 fprintf(f, "Scale=%d\n", scale);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000361 fclose(f); f=0;
362
363 setConfigFileName(filename);
364 } catch (rdr::Exception&) {
365 if (f) fclose(f);
366 throw;
367 }
368}
369
370
371void CConnOptions::writeDefaults() {
372 RegKey key;
373 key.createKey(HKEY_CURRENT_USER, _T("Software\\TightVNC\\VNCviewer4"));
374 key.setBool(_T("UseLocalCursor"), useLocalCursor);
375 key.setBool(_T("UseDesktopResize"), useDesktopResize);
376 key.setBool(_T("FullScreen"), fullScreen);
377 key.setBool(_T("FullColour"), fullColour);
378 key.setInt(_T("LowColourLevel"), lowColourLevel);
379 key.setString(_T("PreferredEncoding"), TStr(encodingName(preferredEncoding)));
380 key.setBool(_T("AutoSelect"), autoSelect);
381 key.setBool(_T("Shared"), shared);
382 key.setBool(_T("SendPointerEvents"), sendPtrEvents);
383 key.setBool(_T("SendKeyEvents"), sendKeyEvents);
384 key.setBool(_T("ClientCutText"), clientCutText);
385 key.setBool(_T("ServerCutText"), serverCutText);
386 key.setBool(_T("DisableWinKeys"), disableWinKeys);
387 key.setBool(_T("Protocol3.3"), protocol3_3);
388 key.setBool(_T("AcceptBell"), acceptBell);
389 key.setBool(_T("ShowToolbar"), showToolbar);
390 key.setBool(_T("Emulate3"), emulate3);
391 key.setInt(_T("PointerEventInterval"), pointerEventInterval);
392 if (monitor.buf)
393 key.setString(_T("Monitor"), TStr(monitor.buf));
394 key.setString(_T("MenuKey"), TCharArray(menuKeyName()).buf);
395 key.setBool(_T("AutoReconnect"), autoReconnect);
396 key.setInt(_T("CustomCompressLevel"), customCompressLevel);
397 key.setInt(_T("CompressLevel"), compressLevel);
398 key.setInt(_T("NoJPEG"), noJpeg);
399 key.setInt(_T("QualityLevel"), qualityLevel);
george82444e8862006-05-27 10:21:28 +0000400 key.setBool(_T("AutoScaling"), autoScaling);
401 key.setInt(_T("Scale"), scale);
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000402}
403
404
405void CConnOptions::setUserName(const char* user) {userName.replaceBuf(strDup(user));}
406void CConnOptions::setPassword(const char* pwd) {password.replaceBuf(strDup(pwd));}
407void CConnOptions::setConfigFileName(const char* cfn) {configFileName.replaceBuf(strDup(cfn));}
408void CConnOptions::setHost(const char* h) {host.replaceBuf(strDup(h));}
409void CConnOptions::setMonitor(const char* m) {monitor.replaceBuf(strDup(m));}
410
411void CConnOptions::setMenuKey(const char* keyName) {
412 if (!keyName[0]) {
413 menuKey = 0;
414 } else {
415 menuKey = VK_F8;
416 if (keyName[0] == 'F') {
417 UINT fKey = atoi(&keyName[1]);
418 if (fKey >= 1 && fKey <= 12)
419 menuKey = fKey-1 + VK_F1;
420 }
421 }
422}
423char* CConnOptions::menuKeyName() {
424 int fNum = (menuKey-VK_F1)+1;
425 if (fNum<1 || fNum>12)
426 return strDup("");
427 CharArray menuKeyStr(4);
428 sprintf(menuKeyStr.buf, "F%d", fNum);
429 return menuKeyStr.takeBuf();
430}
431
432
433CConnOptions& CConnOptions::operator=(const CConnOptions& o) {
434 useLocalCursor = o.useLocalCursor;
435 useDesktopResize = o.useDesktopResize;
436 fullScreen = o.fullScreen;
437 fullColour = o.fullColour;
438 lowColourLevel = o.lowColourLevel;
439 preferredEncoding = o.preferredEncoding;
440 autoSelect = o.autoSelect;
441 shared = o.shared;
442 sendPtrEvents = o.sendPtrEvents;
443 sendKeyEvents = o.sendKeyEvents;
444 clientCutText = o.clientCutText;
445 serverCutText = o.serverCutText;
446 disableWinKeys = o.disableWinKeys;
447 emulate3 = o.emulate3;
448 pointerEventInterval = o.pointerEventInterval;
449 protocol3_3 = o.protocol3_3;
450 acceptBell = o.acceptBell;
451 showToolbar = o.showToolbar;
452 setUserName(o.userName.buf);
453 setPassword(o.password.buf);
454 setConfigFileName(o.configFileName.buf);
455 setHost(o.host.buf);
456 setMonitor(o.monitor.buf);
457 menuKey = o.menuKey;
458 autoReconnect = o.autoReconnect;
459 customCompressLevel = o.customCompressLevel;
460 compressLevel = o.compressLevel;
461 noJpeg = o.noJpeg;
462 qualityLevel = o.qualityLevel;
george82444e8862006-05-27 10:21:28 +0000463 autoScaling = o.autoScaling;
464 scale = o.scale;
Constantin Kaplinsky729598c2006-05-25 05:12:25 +0000465
466 return *this;
467}