blob: 6c2af38ac0db9e2d0830cda3b8fe04453e79d4a4 [file] [log] [blame]
Pierre Ossman5156d5e2011-03-09 09:42:34 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
Peter Åstrand8a2b0812012-08-08 11:49:01 +00003 * Copyright 2012 Samuel Mannehed <samuel@cendio.se> for Cendio AB
Pierre Ossman5156d5e2011-03-09 09:42:34 +00004 *
5 * This is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this software; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 * USA.
19 */
20
Peter Åstrandc359f362011-08-23 12:04:46 +000021#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
Peter Åstrand8a2b0812012-08-08 11:49:01 +000025#ifdef HAVE_GNUTLS
26#include <rfb/CSecurityTLS.h>
27#endif
28
29#ifdef _WIN32
30#include <windows.h>
31#include <tchar.h>
32#endif
33
Pierre Ossman5156d5e2011-03-09 09:42:34 +000034#include "parameters.h"
35
Peter Åstrand8a2b0812012-08-08 11:49:01 +000036#include <os/os.h>
37#include <rfb/Exception.h>
38#include <rfb/LogWriter.h>
39#include <rfb/SecurityClient.h>
40
41#include <FL/fl_utf8.h>
42
43#include <stdio.h>
44#include <string.h>
45#include <limits.h>
46
Pierre Ossman5156d5e2011-03-09 09:42:34 +000047using namespace rfb;
48
Peter Åstrand8a2b0812012-08-08 11:49:01 +000049static LogWriter vlog("Parameters");
50
51
Pierre Ossman4c8e3112011-06-08 17:21:48 +000052IntParameter pointerEventInterval("PointerEventInterval",
53 "Time in milliseconds to rate-limit"
54 " successive pointer events", 0);
Pierre Ossman5156d5e2011-03-09 09:42:34 +000055BoolParameter dotWhenNoCursor("DotWhenNoCursor",
56 "Show the dot cursor when the server sends an "
Pierre Ossman93f37742011-06-09 08:35:34 +000057 "invisible cursor", false);
Pierre Ossman5156d5e2011-03-09 09:42:34 +000058
59StringParameter passwordFile("PasswordFile",
60 "Password file for VNC authentication", "");
61AliasParameter passwd("passwd", "Alias for PasswordFile", &passwordFile);
62
63BoolParameter autoSelect("AutoSelect",
64 "Auto select pixel format and encoding. "
65 "Default if PreferredEncoding and FullColor are not specified.",
66 true);
67BoolParameter fullColour("FullColor",
68 "Use full color", true);
69AliasParameter fullColourAlias("FullColour", "Alias for FullColor", &fullColour);
70IntParameter lowColourLevel("LowColorLevel",
71 "Color level to use on slow connections. "
72 "0 = Very Low (8 colors), 1 = Low (64 colors), "
73 "2 = Medium (256 colors)", 2);
74AliasParameter lowColourLevelAlias("LowColourLevel", "Alias for LowColorLevel", &lowColourLevel);
75StringParameter preferredEncoding("PreferredEncoding",
76 "Preferred encoding to use (Tight, ZRLE, Hextile or"
77 " Raw)", "Tight");
78BoolParameter customCompressLevel("CustomCompressLevel",
79 "Use custom compression level. "
80 "Default if CompressLevel is specified.", false);
81IntParameter compressLevel("CompressLevel",
DRCba7bc512011-08-17 02:30:34 +000082 "Use specified compression level 0 = Low, 6 = High",
Pierre Ossman701ad682011-11-20 15:39:17 +000083 2);
Pierre Ossman5156d5e2011-03-09 09:42:34 +000084BoolParameter noJpeg("NoJPEG",
85 "Disable lossy JPEG compression in Tight encoding.",
86 false);
87IntParameter qualityLevel("QualityLevel",
88 "JPEG quality level. 0 = Low, 9 = High",
89 8);
90
Peter Åstrand49b11572012-08-01 08:09:09 +000091BoolParameter maximize("Maximize", "Maximize viewer window", false);
Pierre Ossman2441e822012-07-10 11:11:23 +000092#ifdef HAVE_FLTK_FULLSCREEN
Pierre Ossman5156d5e2011-03-09 09:42:34 +000093BoolParameter fullScreen("FullScreen", "Full screen mode", false);
Pierre Ossmanaae38912012-07-13 11:22:55 +000094#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
95BoolParameter fullScreenAllMonitors("FullScreenAllMonitors",
96 "Enable full screen over all monitors",
97 true);
98#endif // HAVE_FLTK_FULLSCREEN_SCREENS
Pierre Ossman2441e822012-07-10 11:11:23 +000099#endif // HAVE_FLTK_FULLSCREEN
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000100StringParameter desktopSize("DesktopSize",
101 "Reconfigure desktop size on the server on "
102 "connect (if possible)", "");
Peter Åstrandb182a9e2012-08-27 07:28:08 +0000103StringParameter geometry("geometry",
104 "Specify size and position of viewer window", "");
Pierre Ossman2a7a8d62013-02-15 08:33:39 +0000105
106BoolParameter listenMode("listen", "Listen for connections from VNC servers", false);
107
Pierre Ossmanff473402012-07-04 11:27:47 +0000108BoolParameter remoteResize("RemoteResize",
109 "Dynamically resize the remote desktop size as "
110 "the size of the local client window changes. "
111 "(Does not work with all servers)", true);
Pierre Ossman5156d5e2011-03-09 09:42:34 +0000112
113BoolParameter viewOnly("ViewOnly",
114 "Don't send any mouse or keyboard events to the server",
115 false);
116BoolParameter shared("Shared",
117 "Don't disconnect other viewers upon connection - "
118 "share the desktop instead",
119 false);
120
121BoolParameter acceptClipboard("AcceptClipboard",
122 "Accept clipboard changes from the server",
123 true);
124BoolParameter sendClipboard("SendClipboard",
125 "Send clipboard changes to the server", true);
126BoolParameter sendPrimary("SendPrimary",
127 "Send the primary selection and cut buffer to the "
128 "server as well as the clipboard selection",
129 true);
130
131StringParameter menuKey("MenuKey", "The key which brings up the popup menu",
132 "F8");
133
Pierre Ossman407a5c32011-05-26 14:48:29 +0000134BoolParameter fullscreenSystemKeys("FullscreenSystemKeys",
135 "Pass special keys (like Alt+Tab) directly "
136 "to the server when in full screen mode.",
137 true);
138
Adam Tkac8ac4b302013-01-23 13:55:46 +0000139#ifndef WIN32
140StringParameter via("via", "Gateway to tunnel via", "");
141#endif
142
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000143const char* IDENTIFIER_STRING = "TigerVNC Configuration file Version 1.0";
144
145VoidParameter* parameterArray[] = {
146#ifdef HAVE_GNUTLS
147 &CSecurityTLS::x509ca,
148 &CSecurityTLS::x509crl,
149#endif // HAVE_GNUTLS
150 &SecurityClient::secTypes,
151 &dotWhenNoCursor,
152 &autoSelect,
153 &fullColour,
154 &lowColourLevel,
155 &preferredEncoding,
156 &customCompressLevel,
157 &compressLevel,
158 &noJpeg,
159 &qualityLevel,
160#ifdef HAVE_FLTK_FULLSCREEN
161 &fullScreen,
162#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
163 &fullScreenAllMonitors,
164#endif // HAVE_FLTK_FULLSCREEN_SCREENS
165#endif // HAVE_FLTK_FULLSCREEN
166 &desktopSize,
Peter Åstrandb182a9e2012-08-27 07:28:08 +0000167 &geometry,
Peter Åstrand8a2b0812012-08-08 11:49:01 +0000168 &remoteResize,
169 &viewOnly,
170 &shared,
171 &acceptClipboard,
172 &sendClipboard,
173 &sendPrimary,
174 &menuKey,
175 &fullscreenSystemKeys
176};
177
178// Encoding Table
179static struct {
180 const char first;
181 const char second;
182} replaceMap[] = {'\n', 'n',
183 '\r', 'r'};
184
185bool encodeValue(const char* val, char* dest, size_t destSize) {
186
187 bool normalCharacter = true;
188 size_t pos = 0;
189
190 for (int i = 0; (val[i] != '\0') && (i < (destSize - 1)); i++) {
191
192 // Check for sequences which will need encoding
193 if (val[i] == '\\') {
194
195 strncpy(dest+pos, "\\\\", 2);
196 pos++;
197 if (pos >= destSize) {
198 vlog.error("Encoding backslash: The size of the buffer dest is to small, "
199 "it needs to be more than %d bytes bigger.", (destSize - 1 - i));
200 return false;
201 }
202
203 } else {
204
205 for (int j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++)
206
207 if (val[i] == replaceMap[j].first) {
208 dest[pos] = '\\';
209 pos++;
210 if (pos >= destSize) {
211 vlog.error("Encoding escape sequence: The size of the buffer dest is to small, "
212 "it needs to be more than %d bytes bigger.", (destSize - 1 - i));
213 return false;
214 }
215
216 dest[pos] = replaceMap[j].second;
217 normalCharacter = false;
218 break;
219 }
220
221 if (normalCharacter) {
222 dest[pos] = val[i];
223 }
224 }
225 normalCharacter = true; // Reset for next loop
226
227 pos++;
228 if (pos >= destSize) {
229 vlog.error("Encoding normal character: The size of the buffer dest is to small, "
230 "it needs to be more than %d bytes bigger.", (destSize - 1 - i));
231 return false;
232 }
233
234 }
235
236 dest[pos] = '\0';
237 return true;
238}
239
240
241bool decodeValue(const char* val, char* dest, size_t destSize) {
242
243 size_t pos = 0;
244 bool escapedCharacter = false;
245
246 for (int i = 0; (val[i] != '\0') && (i < (destSize - 1)); i++) {
247
248 // Check for escape sequences
249 if (val[i] == '\\') {
250
251 for (int j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++) {
252 if (val[i+1] == replaceMap[j].second) {
253 dest[pos] = replaceMap[j].first;
254 escapedCharacter = true;
255 pos--;
256 break;
257 }
258 }
259
260 if (!escapedCharacter) {
261 if (val[i+1] == '\\') {
262 dest[pos] = val[i];
263 i++;
264 } else {
265 vlog.error("Unknown escape sequence at character %d", i);
266 return false;
267 }
268 }
269
270 } else {
271 dest[pos] = val[i];
272 }
273
274 escapedCharacter = false; // Reset for next loop
275 pos++;
276 if (pos >= destSize) {
277 vlog.error("Decoding: The size of the buffer dest is to small, "
278 "it needs to be 1 byte bigger.");
279 return false;
280 }
281 }
282
283 dest[pos] = '\0';
284 return true;
285}
286
287
288#ifdef _WIN32
289void setKeyString(const char *_name, const char *_value, HKEY* hKey) {
290
291 const DWORD buffersize = 256;
292
293 wchar_t name[buffersize];
294 unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
295 if (size >= buffersize) {
296 vlog.error("Could not convert the parameter-name %s to wchar_t* when "
297 "writing to the Registry, the buffersize is to small.", _name);
298 return;
299 }
300
301 char encodingBuffer[buffersize];
302 if (!encodeValue(_value, encodingBuffer, buffersize)) {
303 vlog.error("Could not encode the parameter-value %s when "
304 "writing to the Registry.", _value);
305 return;
306 }
307
308 wchar_t value[buffersize];
309 size = fl_utf8towc(encodingBuffer, strlen(encodingBuffer)+1, value, buffersize);
310 if (size >= buffersize) {
311 vlog.error("Could not convert the parameter-value %s to wchar_t* when "
312 "writing to the Registry, the buffersize is to small.", _value);
313 return;
314 }
315
316 LONG res = RegSetValueExW(*hKey, name, 0, REG_SZ, (BYTE*)&value, (wcslen(value)+1)*2);
317 if (res != ERROR_SUCCESS) {
318 vlog.error("Error(%d) writing %s(REG_SZ) to Registry.", res, _value);
319 return;
320 }
321}
322
323
324void setKeyInt(const char *_name, const int _value, HKEY* hKey) {
325
326 const DWORD buffersize = 256;
327 wchar_t name[buffersize];
328 DWORD value = _value;
329
330 unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
331 if (size >= buffersize) {
332 vlog.error("Could not convert the parameter-name %s to wchar_t* when "
333 "writing to the Registry, the buffersize is to small.", _name);
334 return;
335 }
336
337 LONG res = RegSetValueExW(*hKey, name, 0, REG_DWORD, (BYTE*)&value, sizeof(DWORD));
338 if (res != ERROR_SUCCESS) {
339 vlog.error("Error(%d) writing %d(REG_DWORD) to Registry.", res, _value);
340 return;
341 }
342}
343
344
345bool getKeyString(const char* _name, char* dest, size_t destSize, HKEY* hKey) {
346
347 DWORD buffersize = 256;
348 WCHAR value[destSize];
349 wchar_t name[buffersize];
350
351 unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
352 if (size >= buffersize) {
353 vlog.error("Could not convert the parameter-name %s to wchar_t* when "
354 "reading from the Registry, the buffersize is to small.", _name);
355 return false;
356 }
357
358 LONG res = RegQueryValueExW(*hKey, name, 0, NULL, (LPBYTE)value, &buffersize);
359 if (res != ERROR_SUCCESS){
360 if (res == ERROR_FILE_NOT_FOUND) {
361 // The value does not exist, defaults will be used.
362 } else {
363 vlog.error("Error(%d) reading %s from Registry.", res, _name);
364 }
365 return false;
366 }
367
368 char utf8val[destSize];
369 size = fl_utf8fromwc(utf8val, sizeof(utf8val), value, wcslen(value)+1);
370 if (size >= sizeof(utf8val)) {
371 vlog.error("Could not convert the parameter-value for %s to utf8 char* "
372 "when reading from the Registry, the buffer dest is to small.",
373 _name);
374 return false;
375 }
376 const char *ret = utf8val;
377
378 if(decodeValue(ret, dest, destSize))
379 return true;
380 else
381 return false;
382}
383
384
385bool getKeyInt(const char* _name, int* dest, HKEY* hKey) {
386
387 const DWORD buffersize = 256;
388 DWORD dwordsize = sizeof(DWORD);
389 DWORD value = 0;
390 wchar_t name[buffersize];
391
392 unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
393 if (size >= buffersize) {
394 vlog.error("Could not convert the parameter-name %s to wchar_t* when "
395 "reading from the Registry, the buffersize is to small.", _name);
396 return false;
397 }
398
399 LONG res = RegQueryValueExW(*hKey, name, 0, NULL, (LPBYTE)&value, &dwordsize);
400 if (res != ERROR_SUCCESS){
401 if (res == ERROR_FILE_NOT_FOUND) {
402 // The value does not exist, defaults will be used.
403 } else {
404 vlog.error("Error(%d) reading %s from Registry.", res, _name);
405 }
406 return false;
407 }
408
409 *dest = (int)value;
410 return true;
411}
412
413
414void saveToReg(const char* servername) {
415
416 HKEY hKey;
417
418 LONG res = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\TigerVNC\\vncviewer", 0, NULL,
419 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
420 if (res != ERROR_SUCCESS) {
421 vlog.error("Error(%d) creating key: Software\\TigerVNC\\vncviewer", res);
422 return;
423 }
424
425 setKeyString("ServerName", servername, &hKey);
426
427 for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
428 if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
429 setKeyString(parameterArray[i]->getName(), *(StringParameter*)parameterArray[i], &hKey);
430 } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
431 setKeyInt(parameterArray[i]->getName(), (int)*(IntParameter*)parameterArray[i], &hKey);
432 } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
433 setKeyInt(parameterArray[i]->getName(), (int)*(BoolParameter*)parameterArray[i], &hKey);
434 } else {
435 vlog.info("The parameterArray contains a object of a invalid type at line %d.", i);
436 }
437 }
438
439 res = RegCloseKey(hKey);
440 if (res != ERROR_SUCCESS) {
441 vlog.error("Error(%d) closing key: Software\\TigerVNC\\vncviewer", res);
442 }
443}
444
445
446char* loadFromReg() {
447
448 HKEY hKey;
449
450 LONG res = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\TigerVNC\\vncviewer"
451 , 0, KEY_READ, &hKey);
452 if (res != ERROR_SUCCESS) {
453 if (res == ERROR_FILE_NOT_FOUND) {
454 // The key does not exist, defaults will be used.
455 } else {
456 vlog.error("Error(%d) opening key: Software\\TigerVNC\\vncviewer", res);
457 }
458 return NULL;
459 }
460
461 const size_t buffersize = 256;
462 static char servername[buffersize];
463
464 char servernameBuffer[buffersize];
465 if (getKeyString("ServerName", servernameBuffer, buffersize, &hKey))
466 snprintf(servername, buffersize, "%s", servernameBuffer);
467
468 int intValue = 0;
469 char stringValue[buffersize];
470
471 for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
472 if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
473 if (getKeyString(parameterArray[i]->getName(), stringValue, buffersize, &hKey))
474 parameterArray[i]->setParam(stringValue);
475 } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
476 if (getKeyInt(parameterArray[i]->getName(), &intValue, &hKey))
477 ((IntParameter*)parameterArray[i])->setParam(intValue);
478 } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
479 if (getKeyInt(parameterArray[i]->getName(), &intValue, &hKey))
480 ((BoolParameter*)parameterArray[i])->setParam(intValue);
481 } else {
482 vlog.info("The parameterArray contains a object of a invalid type at line %d.", i);
483 }
484 }
485
486 res = RegCloseKey(hKey);
487 if (res != ERROR_SUCCESS){
488 vlog.error("Error(%d) closing key: Software\\TigerVNC\\vncviewer", res);
489 }
490
491 return servername;
492}
493#endif // _WIN32
494
495
496void saveViewerParameters(const char *filename, const char *servername) {
497
498 const size_t buffersize = 256;
499 char filepath[PATH_MAX];
500 char write_error[buffersize*2];
501 char encodingBuffer[buffersize];
502
503 // Write to the registry or a predefined file if no filename was specified.
504 if(filename == NULL) {
505
506#ifdef _WIN32
507 saveToReg(servername);
508 return;
509#endif
510
511 char* homeDir = NULL;
512 if (getvnchomedir(&homeDir) == -1) {
513 vlog.error("Failed to write configuration file, "
514 "can't obtain home directory path.");
515 return;
516 }
517
518 snprintf(filepath, sizeof(filepath), "%sdefault.tigervnc", homeDir);
519 } else {
520 snprintf(filepath, sizeof(filepath), "%s", filename);
521 }
522
523 /* Write parameters to file */
524 FILE* f = fopen(filepath, "w+");
525 if (!f) {
526 snprintf(write_error, sizeof(filepath), "Failed to write configuration file, "
527 "can't open %s", filepath);
528 throw Exception(write_error);
529 }
530
531 fprintf(f, "%s\r\n", IDENTIFIER_STRING);
532 fprintf(f, "\r\n");
533
534 if (encodeValue(servername, encodingBuffer, buffersize))
535 fprintf(f, "ServerName=%s\n", encodingBuffer);
536
537 for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
538 if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
539 if (encodeValue(*(StringParameter*)parameterArray[i], encodingBuffer, buffersize))
540 fprintf(f, "%s=%s\n", ((StringParameter*)parameterArray[i])->getName(), encodingBuffer);
541 } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
542 fprintf(f, "%s=%d\n", ((IntParameter*)parameterArray[i])->getName(), (int)*(IntParameter*)parameterArray[i]);
543 } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
544 fprintf(f, "%s=%d\n", ((BoolParameter*)parameterArray[i])->getName(), (int)*(BoolParameter*)parameterArray[i]);
545 } else {
546 vlog.info("The parameterArray contains a object of a invalid type at line %d.", i);
547 }
548 }
549 fclose(f);
550}
551
552
553char* loadViewerParameters(const char *filename) {
554
555 const size_t buffersize = 256;
556 char filepath[PATH_MAX];
557 char readError[buffersize*2];
558 char line[buffersize];
559 char decodingBuffer[buffersize];
560 char decodedValue[buffersize];
561 static char servername[sizeof(line)];
562
563 // Load from the registry or a predefined file if no filename was specified.
564 if(filename == NULL) {
565
566#ifdef _WIN32
567 return loadFromReg();
568#endif
569
570 char* homeDir = NULL;
571 if (getvnchomedir(&homeDir) == -1)
572 throw Exception("Failed to read configuration file, "
573 "can't obtain home directory path.");
574
575 snprintf(filepath, sizeof(filepath), "%sdefault.tigervnc", homeDir);
576 } else {
577 snprintf(filepath, sizeof(filepath), "%s", filename);
578 }
579
580 /* Read parameters from file */
581 FILE* f = fopen(filepath, "r");
582 if (!f) {
583 if (!filename)
584 return NULL; // Use defaults.
585 snprintf(readError, sizeof(readError), "Failed to read configuration file, "
586 "can't open %s", filepath);
587 throw Exception(readError);
588 }
589
590 int lineNr = 0;
591 while (!feof(f)) {
592
593 // Read the next line
594 lineNr++;
595 if (!fgets(line, sizeof(line), f)) {
596 if (line[sizeof(line) -1] != '\0') {
597 vlog.error("Could not read the line(%d) in the configuration file,"
598 "the buffersize is to small.", lineNr);
599 return NULL;
600 }
601 if (feof(f))
602 break;
603
604 snprintf(readError, sizeof(readError), "Failed to read line %d in file %s",
605 lineNr, filepath);
606 throw Exception(readError);
607 }
608
609 // Make sure that the first line of the file has the file identifier string
610 if(lineNr == 1) {
611 if(strncmp(line, IDENTIFIER_STRING, strlen(IDENTIFIER_STRING)) == 0) {
612 continue;
613 } else {
614 snprintf(readError, sizeof(readError), "Line 1 in file %s\n"
615 "must contain the TigerVNC configurationfile identifier string:\n"
616 "\"%s\"", filepath, IDENTIFIER_STRING);
617 throw Exception(readError);
618 }
619 }
620
621 // Skip empty lines and comments
622 if ((line[0] == '\n') || (line[0] == '#') || (line[0] == '\r'))
623 continue;
624
625 int len = strlen(line);
626 if (line[len-1] == '\n') {
627 line[len-1] = '\0';
628 len--;
629 }
630
631 // Find the parameter value
632 char *value = strchr(line, '=');
633 if (value == NULL) {
634 vlog.info("Bad Name/Value pair on line: %d in file: %s",
635 lineNr, filepath);
636 continue;
637 }
638 *value = '\0'; // line only contains the parameter name below.
639 value++;
640
641 bool invalidParameterName = true; // Will be set to false below if
642 // the line contains a valid name.
643
644 if (strcasecmp(line, "ServerName") == 0) {
645
646 if(!decodeValue(value, decodingBuffer, sizeof(decodingBuffer))) {
647 vlog.info("The value of the parameter %s on line %d in file %s is invalid.",
648 line, lineNr, filepath);
649 continue;
650 }
651 snprintf(servername, sizeof(decodingBuffer), "%s", decodingBuffer);
652 invalidParameterName = false;
653
654 } else {
655
656 // Find and set the correct parameter
657 for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
658
659 if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
660 if (strcasecmp(line, ((StringParameter*)parameterArray[i])->getName()) == 0) {
661
662 if(!decodeValue(value, decodingBuffer, sizeof(decodingBuffer))) {
663 vlog.info("The value of the parameter %s on line %d in file %s is invalid.",
664 line, lineNr, filepath);
665 continue;
666 }
667 ((StringParameter*)parameterArray[i])->setParam(decodingBuffer);
668 invalidParameterName = false;
669 }
670
671 } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
672 if (strcasecmp(line, ((IntParameter*)parameterArray[i])->getName()) == 0) {
673 ((IntParameter*)parameterArray[i])->setParam(atoi(value));
674 invalidParameterName = false;
675 }
676
677 } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
678 if (strcasecmp(line, ((BoolParameter*)parameterArray[i])->getName()) == 0) {
679 ((BoolParameter*)parameterArray[i])->setParam(atoi(value));
680 invalidParameterName = false;
681 }
682
683 } else {
684 vlog.info("The parameterArray contains a object of a invalid type at line %d.", lineNr);
685 }
686 }
687 }
688
689 if (invalidParameterName)
690 vlog.info("Invalid parameter name on line: %d in file: %s",
691 lineNr, filepath);
692 }
693 fclose(f); f=0;
694
695 return servername;
696}