/* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2012 Samuel Mannehed <samuel@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <FL/Fl_Button.H>
#include <FL/Fl_Return_Button.H>
#include <FL/fl_draw.H>
+#include <FL/fl_ask.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_File_Chooser.H>
#include "ServerDialog.h"
#include "OptionsDialog.h"
#include "fltk_layout.h"
#include "i18n.h"
#include "vncviewer.h"
+#include "parameters.h"
+#include "rfb/Exception.h"
ServerDialog::ServerDialog()
- : Fl_Window(400, 112, _("VNC Viewer: Connection Details"))
+ : Fl_Window(450, 160, _("VNC Viewer: Connection Details"))
{
- int width;
+ int x, y;
Fl_Button *button;
+ Fl_Box *divider;
- width = gui_str_len(_("VNC server:"));
- serverName = new Fl_Input(20 + width, 20, w() - 20*2 - width, 25, _("VNC server:"));
+ int margin = 20;
+ int server_label_width = gui_str_len(_("VNC server:"));
- width = (w() - 20) / 4;
+ x = margin + server_label_width;
+ y = margin;
+
+ serverName = new Fl_Input(x, y, w() - margin*2 - server_label_width, INPUT_HEIGHT, _("VNC server:"));
- button = new Fl_Button(20 + width*0, 20+25+20, width - 20, 27, _("About..."));
- button->callback(this->handleAbout, this);
+ int adjust = (w() - 20) / 4;
+ int button_width = adjust - margin/2;
+
+ x = margin;
+ y = margin + margin/2 + INPUT_HEIGHT;
+
+ y += margin/2;
- button = new Fl_Button(20 + width*1, 20+25+20, width - 20, 27, _("Options..."));
+ button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Options..."));
button->callback(this->handleOptions, this);
+
+ x += adjust;
+
+ button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Load..."));
+ button->callback(this->handleLoad, this);
+
+ x += adjust;
+
+ button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Save As..."));
+ button->callback(this->handleSaveAs, this);
+
+ x = 0;
+ y += margin/2 + BUTTON_HEIGHT;
+
+ divider = new Fl_Box(x, y, w(), 2);
+ divider->box(FL_THIN_DOWN_FRAME);
+
+ x += margin;
+ y += margin/2;
+
+ button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("About..."));
+ button->callback(this->handleAbout, this);
+
+ x = w() - margin - adjust - button_width - 20;
- button = new Fl_Button(20 + width*2, 20+25+20, width - 20, 27, _("Cancel"));
+ button = new Fl_Button(x, y, button_width, BUTTON_HEIGHT, _("Cancel"));
button->callback(this->handleCancel, this);
- button = new Fl_Return_Button(20 + width*3, 20+25+20, width - 20, 27, _("OK"));
- button->callback(this->handleOK, this);
+ x += adjust;
+
+ button = new Fl_Return_Button(x, y, button_width+20, BUTTON_HEIGHT, _("Connect"));
+ button->callback(this->handleConnect, this);
callback(this->handleCancel, this);
}
-const char *ServerDialog::run()
+const char *ServerDialog::run(const char* servername)
{
ServerDialog dialog;
static char buffer[256];
+ dialog.serverName->value(servername);
+
dialog.show();
while (dialog.shown()) Fl::wait();
return buffer;
}
+void ServerDialog::handleOptions(Fl_Widget *widget, void *data)
+{
+ OptionsDialog::showDialog();
+}
-void ServerDialog::handleAbout(Fl_Widget *widget, void *data)
+
+void ServerDialog::handleLoad(Fl_Widget *widget, void *data)
{
- about_vncviewer();
+ ServerDialog *dialog = (ServerDialog*)data;
+ Fl_File_Chooser* file_chooser = new Fl_File_Chooser("", "TigerVNC configuration (*.tigervnc)",
+ 0, "Select a TigerVNC configuration file");
+ file_chooser->preview(0);
+ file_chooser->previewButton->hide();
+ file_chooser->show();
+
+ // Block until user picks something.
+ while(file_chooser->shown())
+ Fl::wait();
+
+ // Did the user hit cancel?
+ if (file_chooser->value() == NULL) {
+ delete(file_chooser);
+ return;
+ }
+
+ const char* filename = strdup(file_chooser->value());
+
+ try {
+ dialog->serverName->value(loadViewerParameters(filename));
+ } catch (rfb::Exception& e) {
+ fl_alert("%s", e.str());
+ }
+
+ delete(file_chooser);
}
-void ServerDialog::handleOptions(Fl_Widget *widget, void *data)
+void ServerDialog::handleSaveAs(Fl_Widget *widget, void *data)
+{
+ ServerDialog *dialog = (ServerDialog*)data;
+ const char* servername = strdup(dialog->serverName->value());
+ char* filename;
+
+ Fl_File_Chooser* file_chooser = new Fl_File_Chooser("", "TigerVNC configuration (*.tigervnc)",
+ 2, "Save the TigerVNC configuration to file");
+
+ file_chooser->preview(0);
+ file_chooser->previewButton->hide();
+ file_chooser->show();
+
+ while(1) {
+
+ // Block until user picks something.
+ while(file_chooser->shown())
+ Fl::wait();
+
+ // Did the user hit cancel?
+ if (file_chooser->value() == NULL) {
+ delete(file_chooser);
+ return;
+ }
+
+ filename = strdup(file_chooser->value());
+
+ FILE* f = fopen(filename, "r");
+ if (f) {
+
+ // The file already exists.
+ fclose(f);
+ int overwrite_choice = fl_choice("%s already exists. Do you want to overwrite?",
+ "Overwrite", "No", NULL, filename);
+ if (overwrite_choice == 1) {
+
+ // If the user doesn't want to overwrite:
+ file_chooser->show();
+ continue;
+ }
+ }
+
+ break;
+ }
+
+ try {
+ saveViewerParameters(filename, servername);
+ } catch (rfb::Exception& e) {
+ fl_alert("%s", e.str());
+ }
+
+ delete(file_chooser);
+}
+
+
+void ServerDialog::handleAbout(Fl_Widget *widget, void *data)
{
- OptionsDialog::showDialog();
+ about_vncviewer();
}
}
-void ServerDialog::handleOK(Fl_Widget *widget, void *data)
+void ServerDialog::handleConnect(Fl_Widget *widget, void *data)
{
ServerDialog *dialog = (ServerDialog*)data;
+ const char* servername = strdup(dialog->serverName->value());
dialog->hide();
+
+ try {
+ saveViewerParameters(NULL, servername);
+ } catch (rfb::Exception& e) {
+ fl_alert("%s", e.str());
+ }
}
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2012 Samuel Mannehed <samuel@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <config.h>
#endif
+#ifdef HAVE_GNUTLS
+#include <rfb/CSecurityTLS.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#include <tchar.h>
+#endif
+
#include "parameters.h"
+#include <os/os.h>
+#include <rfb/Exception.h>
+#include <rfb/LogWriter.h>
+#include <rfb/SecurityClient.h>
+
+#include <FL/fl_utf8.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
using namespace rfb;
+static LogWriter vlog("Parameters");
+
+
IntParameter pointerEventInterval("PointerEventInterval",
"Time in milliseconds to rate-limit"
" successive pointer events", 0);
"to the server when in full screen mode.",
true);
+const char* IDENTIFIER_STRING = "TigerVNC Configuration file Version 1.0";
+
+VoidParameter* parameterArray[] = {
+#ifdef HAVE_GNUTLS
+ &CSecurityTLS::x509ca,
+ &CSecurityTLS::x509crl,
+#endif // HAVE_GNUTLS
+ &SecurityClient::secTypes,
+ &dotWhenNoCursor,
+ &autoSelect,
+ &fullColour,
+ &lowColourLevel,
+ &preferredEncoding,
+ &customCompressLevel,
+ &compressLevel,
+ &noJpeg,
+ &qualityLevel,
+#ifdef HAVE_FLTK_FULLSCREEN
+ &fullScreen,
+#ifdef HAVE_FLTK_FULLSCREEN_SCREENS
+ &fullScreenAllMonitors,
+#endif // HAVE_FLTK_FULLSCREEN_SCREENS
+#endif // HAVE_FLTK_FULLSCREEN
+ &desktopSize,
+ &remoteResize,
+ &viewOnly,
+ &shared,
+ &acceptClipboard,
+ &sendClipboard,
+ &sendPrimary,
+ &menuKey,
+ &fullscreenSystemKeys
+};
+
+// Encoding Table
+static struct {
+ const char first;
+ const char second;
+} replaceMap[] = {'\n', 'n',
+ '\r', 'r'};
+
+bool encodeValue(const char* val, char* dest, size_t destSize) {
+
+ bool normalCharacter = true;
+ size_t pos = 0;
+
+ for (int i = 0; (val[i] != '\0') && (i < (destSize - 1)); i++) {
+
+ // Check for sequences which will need encoding
+ if (val[i] == '\\') {
+
+ strncpy(dest+pos, "\\\\", 2);
+ pos++;
+ if (pos >= destSize) {
+ vlog.error("Encoding backslash: The size of the buffer dest is to small, "
+ "it needs to be more than %d bytes bigger.", (destSize - 1 - i));
+ return false;
+ }
+
+ } else {
+
+ for (int j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++)
+
+ if (val[i] == replaceMap[j].first) {
+ dest[pos] = '\\';
+ pos++;
+ if (pos >= destSize) {
+ vlog.error("Encoding escape sequence: The size of the buffer dest is to small, "
+ "it needs to be more than %d bytes bigger.", (destSize - 1 - i));
+ return false;
+ }
+
+ dest[pos] = replaceMap[j].second;
+ normalCharacter = false;
+ break;
+ }
+
+ if (normalCharacter) {
+ dest[pos] = val[i];
+ }
+ }
+ normalCharacter = true; // Reset for next loop
+
+ pos++;
+ if (pos >= destSize) {
+ vlog.error("Encoding normal character: The size of the buffer dest is to small, "
+ "it needs to be more than %d bytes bigger.", (destSize - 1 - i));
+ return false;
+ }
+
+ }
+
+ dest[pos] = '\0';
+ return true;
+}
+
+
+bool decodeValue(const char* val, char* dest, size_t destSize) {
+
+ size_t pos = 0;
+ bool escapedCharacter = false;
+
+ for (int i = 0; (val[i] != '\0') && (i < (destSize - 1)); i++) {
+
+ // Check for escape sequences
+ if (val[i] == '\\') {
+
+ for (int j = 0; j < sizeof(replaceMap)/sizeof(replaceMap[0]); j++) {
+ if (val[i+1] == replaceMap[j].second) {
+ dest[pos] = replaceMap[j].first;
+ escapedCharacter = true;
+ pos--;
+ break;
+ }
+ }
+
+ if (!escapedCharacter) {
+ if (val[i+1] == '\\') {
+ dest[pos] = val[i];
+ i++;
+ } else {
+ vlog.error("Unknown escape sequence at character %d", i);
+ return false;
+ }
+ }
+
+ } else {
+ dest[pos] = val[i];
+ }
+
+ escapedCharacter = false; // Reset for next loop
+ pos++;
+ if (pos >= destSize) {
+ vlog.error("Decoding: The size of the buffer dest is to small, "
+ "it needs to be 1 byte bigger.");
+ return false;
+ }
+ }
+
+ dest[pos] = '\0';
+ return true;
+}
+
+
+#ifdef _WIN32
+void setKeyString(const char *_name, const char *_value, HKEY* hKey) {
+
+ const DWORD buffersize = 256;
+
+ wchar_t name[buffersize];
+ unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
+ if (size >= buffersize) {
+ vlog.error("Could not convert the parameter-name %s to wchar_t* when "
+ "writing to the Registry, the buffersize is to small.", _name);
+ return;
+ }
+
+ char encodingBuffer[buffersize];
+ if (!encodeValue(_value, encodingBuffer, buffersize)) {
+ vlog.error("Could not encode the parameter-value %s when "
+ "writing to the Registry.", _value);
+ return;
+ }
+
+ wchar_t value[buffersize];
+ size = fl_utf8towc(encodingBuffer, strlen(encodingBuffer)+1, value, buffersize);
+ if (size >= buffersize) {
+ vlog.error("Could not convert the parameter-value %s to wchar_t* when "
+ "writing to the Registry, the buffersize is to small.", _value);
+ return;
+ }
+
+ LONG res = RegSetValueExW(*hKey, name, 0, REG_SZ, (BYTE*)&value, (wcslen(value)+1)*2);
+ if (res != ERROR_SUCCESS) {
+ vlog.error("Error(%d) writing %s(REG_SZ) to Registry.", res, _value);
+ return;
+ }
+}
+
+
+void setKeyInt(const char *_name, const int _value, HKEY* hKey) {
+
+ const DWORD buffersize = 256;
+ wchar_t name[buffersize];
+ DWORD value = _value;
+
+ unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
+ if (size >= buffersize) {
+ vlog.error("Could not convert the parameter-name %s to wchar_t* when "
+ "writing to the Registry, the buffersize is to small.", _name);
+ return;
+ }
+
+ LONG res = RegSetValueExW(*hKey, name, 0, REG_DWORD, (BYTE*)&value, sizeof(DWORD));
+ if (res != ERROR_SUCCESS) {
+ vlog.error("Error(%d) writing %d(REG_DWORD) to Registry.", res, _value);
+ return;
+ }
+}
+
+
+bool getKeyString(const char* _name, char* dest, size_t destSize, HKEY* hKey) {
+
+ DWORD buffersize = 256;
+ WCHAR value[destSize];
+ wchar_t name[buffersize];
+
+ unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
+ if (size >= buffersize) {
+ vlog.error("Could not convert the parameter-name %s to wchar_t* when "
+ "reading from the Registry, the buffersize is to small.", _name);
+ return false;
+ }
+
+ LONG res = RegQueryValueExW(*hKey, name, 0, NULL, (LPBYTE)value, &buffersize);
+ if (res != ERROR_SUCCESS){
+ if (res == ERROR_FILE_NOT_FOUND) {
+ // The value does not exist, defaults will be used.
+ } else {
+ vlog.error("Error(%d) reading %s from Registry.", res, _name);
+ }
+ return false;
+ }
+
+ char utf8val[destSize];
+ size = fl_utf8fromwc(utf8val, sizeof(utf8val), value, wcslen(value)+1);
+ if (size >= sizeof(utf8val)) {
+ vlog.error("Could not convert the parameter-value for %s to utf8 char* "
+ "when reading from the Registry, the buffer dest is to small.",
+ _name);
+ return false;
+ }
+ const char *ret = utf8val;
+
+ if(decodeValue(ret, dest, destSize))
+ return true;
+ else
+ return false;
+}
+
+
+bool getKeyInt(const char* _name, int* dest, HKEY* hKey) {
+
+ const DWORD buffersize = 256;
+ DWORD dwordsize = sizeof(DWORD);
+ DWORD value = 0;
+ wchar_t name[buffersize];
+
+ unsigned size = fl_utf8towc(_name, strlen(_name)+1, name, buffersize);
+ if (size >= buffersize) {
+ vlog.error("Could not convert the parameter-name %s to wchar_t* when "
+ "reading from the Registry, the buffersize is to small.", _name);
+ return false;
+ }
+
+ LONG res = RegQueryValueExW(*hKey, name, 0, NULL, (LPBYTE)&value, &dwordsize);
+ if (res != ERROR_SUCCESS){
+ if (res == ERROR_FILE_NOT_FOUND) {
+ // The value does not exist, defaults will be used.
+ } else {
+ vlog.error("Error(%d) reading %s from Registry.", res, _name);
+ }
+ return false;
+ }
+
+ *dest = (int)value;
+ return true;
+}
+
+
+void saveToReg(const char* servername) {
+
+ HKEY hKey;
+
+ LONG res = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\TigerVNC\\vncviewer", 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
+ if (res != ERROR_SUCCESS) {
+ vlog.error("Error(%d) creating key: Software\\TigerVNC\\vncviewer", res);
+ return;
+ }
+
+ setKeyString("ServerName", servername, &hKey);
+
+ for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
+ if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
+ setKeyString(parameterArray[i]->getName(), *(StringParameter*)parameterArray[i], &hKey);
+ } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
+ setKeyInt(parameterArray[i]->getName(), (int)*(IntParameter*)parameterArray[i], &hKey);
+ } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
+ setKeyInt(parameterArray[i]->getName(), (int)*(BoolParameter*)parameterArray[i], &hKey);
+ } else {
+ vlog.info("The parameterArray contains a object of a invalid type at line %d.", i);
+ }
+ }
+
+ res = RegCloseKey(hKey);
+ if (res != ERROR_SUCCESS) {
+ vlog.error("Error(%d) closing key: Software\\TigerVNC\\vncviewer", res);
+ }
+}
+
+
+char* loadFromReg() {
+
+ HKEY hKey;
+
+ LONG res = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\TigerVNC\\vncviewer"
+ , 0, KEY_READ, &hKey);
+ if (res != ERROR_SUCCESS) {
+ if (res == ERROR_FILE_NOT_FOUND) {
+ // The key does not exist, defaults will be used.
+ } else {
+ vlog.error("Error(%d) opening key: Software\\TigerVNC\\vncviewer", res);
+ }
+ return NULL;
+ }
+
+ const size_t buffersize = 256;
+ static char servername[buffersize];
+
+ char servernameBuffer[buffersize];
+ if (getKeyString("ServerName", servernameBuffer, buffersize, &hKey))
+ snprintf(servername, buffersize, "%s", servernameBuffer);
+
+ int intValue = 0;
+ char stringValue[buffersize];
+
+ for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
+ if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
+ if (getKeyString(parameterArray[i]->getName(), stringValue, buffersize, &hKey))
+ parameterArray[i]->setParam(stringValue);
+ } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
+ if (getKeyInt(parameterArray[i]->getName(), &intValue, &hKey))
+ ((IntParameter*)parameterArray[i])->setParam(intValue);
+ } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
+ if (getKeyInt(parameterArray[i]->getName(), &intValue, &hKey))
+ ((BoolParameter*)parameterArray[i])->setParam(intValue);
+ } else {
+ vlog.info("The parameterArray contains a object of a invalid type at line %d.", i);
+ }
+ }
+
+ res = RegCloseKey(hKey);
+ if (res != ERROR_SUCCESS){
+ vlog.error("Error(%d) closing key: Software\\TigerVNC\\vncviewer", res);
+ }
+
+ return servername;
+}
+#endif // _WIN32
+
+
+void saveViewerParameters(const char *filename, const char *servername) {
+
+ const size_t buffersize = 256;
+ char filepath[PATH_MAX];
+ char write_error[buffersize*2];
+ char encodingBuffer[buffersize];
+
+ // Write to the registry or a predefined file if no filename was specified.
+ if(filename == NULL) {
+
+#ifdef _WIN32
+ saveToReg(servername);
+ return;
+#endif
+
+ char* homeDir = NULL;
+ if (getvnchomedir(&homeDir) == -1) {
+ vlog.error("Failed to write configuration file, "
+ "can't obtain home directory path.");
+ return;
+ }
+
+ snprintf(filepath, sizeof(filepath), "%sdefault.tigervnc", homeDir);
+ } else {
+ snprintf(filepath, sizeof(filepath), "%s", filename);
+ }
+
+ /* Write parameters to file */
+ FILE* f = fopen(filepath, "w+");
+ if (!f) {
+ snprintf(write_error, sizeof(filepath), "Failed to write configuration file, "
+ "can't open %s", filepath);
+ throw Exception(write_error);
+ }
+
+ fprintf(f, "%s\r\n", IDENTIFIER_STRING);
+ fprintf(f, "\r\n");
+
+ if (encodeValue(servername, encodingBuffer, buffersize))
+ fprintf(f, "ServerName=%s\n", encodingBuffer);
+
+ for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
+ if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
+ if (encodeValue(*(StringParameter*)parameterArray[i], encodingBuffer, buffersize))
+ fprintf(f, "%s=%s\n", ((StringParameter*)parameterArray[i])->getName(), encodingBuffer);
+ } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
+ fprintf(f, "%s=%d\n", ((IntParameter*)parameterArray[i])->getName(), (int)*(IntParameter*)parameterArray[i]);
+ } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
+ fprintf(f, "%s=%d\n", ((BoolParameter*)parameterArray[i])->getName(), (int)*(BoolParameter*)parameterArray[i]);
+ } else {
+ vlog.info("The parameterArray contains a object of a invalid type at line %d.", i);
+ }
+ }
+ fclose(f);
+}
+
+
+char* loadViewerParameters(const char *filename) {
+
+ const size_t buffersize = 256;
+ char filepath[PATH_MAX];
+ char readError[buffersize*2];
+ char line[buffersize];
+ char decodingBuffer[buffersize];
+ char decodedValue[buffersize];
+ static char servername[sizeof(line)];
+
+ // Load from the registry or a predefined file if no filename was specified.
+ if(filename == NULL) {
+
+#ifdef _WIN32
+ return loadFromReg();
+#endif
+
+ char* homeDir = NULL;
+ if (getvnchomedir(&homeDir) == -1)
+ throw Exception("Failed to read configuration file, "
+ "can't obtain home directory path.");
+
+ snprintf(filepath, sizeof(filepath), "%sdefault.tigervnc", homeDir);
+ } else {
+ snprintf(filepath, sizeof(filepath), "%s", filename);
+ }
+
+ /* Read parameters from file */
+ FILE* f = fopen(filepath, "r");
+ if (!f) {
+ if (!filename)
+ return NULL; // Use defaults.
+ snprintf(readError, sizeof(readError), "Failed to read configuration file, "
+ "can't open %s", filepath);
+ throw Exception(readError);
+ }
+
+ int lineNr = 0;
+ while (!feof(f)) {
+
+ // Read the next line
+ lineNr++;
+ if (!fgets(line, sizeof(line), f)) {
+ if (line[sizeof(line) -1] != '\0') {
+ vlog.error("Could not read the line(%d) in the configuration file,"
+ "the buffersize is to small.", lineNr);
+ return NULL;
+ }
+ if (feof(f))
+ break;
+
+ snprintf(readError, sizeof(readError), "Failed to read line %d in file %s",
+ lineNr, filepath);
+ throw Exception(readError);
+ }
+
+ // Make sure that the first line of the file has the file identifier string
+ if(lineNr == 1) {
+ if(strncmp(line, IDENTIFIER_STRING, strlen(IDENTIFIER_STRING)) == 0) {
+ continue;
+ } else {
+ snprintf(readError, sizeof(readError), "Line 1 in file %s\n"
+ "must contain the TigerVNC configurationfile identifier string:\n"
+ "\"%s\"", filepath, IDENTIFIER_STRING);
+ throw Exception(readError);
+ }
+ }
+
+ // Skip empty lines and comments
+ if ((line[0] == '\n') || (line[0] == '#') || (line[0] == '\r'))
+ continue;
+
+ int len = strlen(line);
+ if (line[len-1] == '\n') {
+ line[len-1] = '\0';
+ len--;
+ }
+
+ // Find the parameter value
+ char *value = strchr(line, '=');
+ if (value == NULL) {
+ vlog.info("Bad Name/Value pair on line: %d in file: %s",
+ lineNr, filepath);
+ continue;
+ }
+ *value = '\0'; // line only contains the parameter name below.
+ value++;
+
+ bool invalidParameterName = true; // Will be set to false below if
+ // the line contains a valid name.
+
+ if (strcasecmp(line, "ServerName") == 0) {
+
+ if(!decodeValue(value, decodingBuffer, sizeof(decodingBuffer))) {
+ vlog.info("The value of the parameter %s on line %d in file %s is invalid.",
+ line, lineNr, filepath);
+ continue;
+ }
+ snprintf(servername, sizeof(decodingBuffer), "%s", decodingBuffer);
+ invalidParameterName = false;
+
+ } else {
+
+ // Find and set the correct parameter
+ for (int i = 0; i < sizeof(parameterArray)/sizeof(VoidParameter*); i++) {
+
+ if (dynamic_cast<StringParameter*>(parameterArray[i]) != NULL) {
+ if (strcasecmp(line, ((StringParameter*)parameterArray[i])->getName()) == 0) {
+
+ if(!decodeValue(value, decodingBuffer, sizeof(decodingBuffer))) {
+ vlog.info("The value of the parameter %s on line %d in file %s is invalid.",
+ line, lineNr, filepath);
+ continue;
+ }
+ ((StringParameter*)parameterArray[i])->setParam(decodingBuffer);
+ invalidParameterName = false;
+ }
+
+ } else if (dynamic_cast<IntParameter*>(parameterArray[i]) != NULL) {
+ if (strcasecmp(line, ((IntParameter*)parameterArray[i])->getName()) == 0) {
+ ((IntParameter*)parameterArray[i])->setParam(atoi(value));
+ invalidParameterName = false;
+ }
+
+ } else if (dynamic_cast<BoolParameter*>(parameterArray[i]) != NULL) {
+ if (strcasecmp(line, ((BoolParameter*)parameterArray[i])->getName()) == 0) {
+ ((BoolParameter*)parameterArray[i])->setParam(atoi(value));
+ invalidParameterName = false;
+ }
+
+ } else {
+ vlog.info("The parameterArray contains a object of a invalid type at line %d.", lineNr);
+ }
+ }
+ }
+
+ if (invalidParameterName)
+ vlog.info("Invalid parameter name on line: %d in file: %s",
+ lineNr, filepath);
+ }
+ fclose(f); f=0;
+
+ return servername;
+}