1 // $Id: MyXmlConfig.cpp 704 2012-03-14 14:55:15Z felfert $
2 //
3 // Copyright (C) 2006 The OpenNX Team
4 // Author: Fritz Elfert
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU Library General Public License as
8 // published by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU Library General Public
17 // License along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 //
21 
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25 
26 #if defined(__GNUG__) && !defined(__APPLE__)
27 #pragma implementation "MyXmlConfig.h"
28 #endif
29 
30 // For compilers that support precompilation, includes "wx/wx.h".
31 #include "wx/wxprec.h"
32 
33 #ifdef __BORLANDC__
34 #pragma hdrstop
35 #endif
36 
37 #ifndef WX_PRECOMP
38 #include "wx/wx.h"
39 #endif
40 
41 #include <wx/filename.h>
42 #include <wx/xml/xml.h>
43 #include <wx/arrimpl.cpp>
44 #include <wx/file.h>
45 #include <wx/mstream.h>
46 #include <wx/wfstream.h>
47 #include <wx/regex.h>
48 #include <wx/url.h>
49 #include <wx/config.h>
50 #include <wx/display.h>
51 
52 class wxConfigBase;
53 
54 #include "LibUSB.h"
55 #include "MyXmlConfig.h"
56 #include "WinShare.h"
57 
58 #ifdef APP_OPENNX
59 # include "opennxApp.h"
60 #endif
61 #ifdef APP_WATCHUSBIP
62 # include "watchUsbIpApp.h"
63 #endif
64 
65 #include "pwcrypt.h"
66 #include "osdep.h"
67 
68 #ifdef APP_OPENNX
69 # ifdef HAVE_LIBCURL
70 #  include <curl/curl.h>
71 # endif
72 #endif
73 
74 #include "trace.h"
75 ENABLE_TRACE;
76 
77 #define STR_TRUE wxT("true")
78 #define STR_FALSE wxT("false");
79 #define STR_ONE wxT("1")
80 #define STR_ZERO wxT("0")
81 
82 // We use something the user cannot type here!
83 #define DUMMY_MD5_PASSWORD wxT("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b")
84 #define DUMMY_CLR_PASSWORD wxT("\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r")
85 #define DEFAULT_GUEST_USER wxT("NX guest user")
86 
87 IMPLEMENT_DYNAMIC_CLASS(ShareGroup, wxObject);
88 IMPLEMENT_DYNAMIC_CLASS(SharedUsbDevice, wxObject);
89 
90 WX_DEFINE_OBJARRAY(ArrayOfShareGroups);
91 WX_DEFINE_OBJARRAY(ArrayOfUsbForwards);
92 
toString()93 wxString ShareGroup::toString()
94 {
95     wxString ret = wxT("Name: '");
96     ret.Append(m_sGroupName);
97     ret.Append(wxT("', Type: "));
98     switch (m_eType) {
99         case SharedResource::SHARE_UNKNOWN:
100             ret.Append(wxT("unknown"));
101             break;
102         case SharedResource::SHARE_SMB_DISK:
103             ret.Append(wxT("SMBdisk, Share: '"));
104             ret.Append(m_sShareName);
105             ret.Append(wxT("', Alias: '"));
106             ret.Append(m_sAlias);
107             ret.Append(wxT("'"));
108             break;
109         case SharedResource::SHARE_SMB_PRINTER:
110             ret.Append(wxT("SMBprinter, Share: '"));
111             ret.Append(m_sShareName);
112             ret.Append(wxT("', Alias: '"));
113             ret.Append(m_sAlias);
114             ret.Append(wxT("'"));
115             break;
116         case SharedResource::SHARE_CUPS_PRINTER:
117             ret.Append(wxT("CUPSprinter, Share: '"));
118             ret.Append(m_sShareName);
119             ret.Append(wxT("', Driver: '"));
120             ret.Append(m_sDriver);
121             ret.Append(wxT("', Public: "));
122             ret.Append(m_bPublic ? wxT("true") : wxT("false"));
123             ret.Append(wxT(", Default: "));
124             ret.Append(m_bDefault ? wxT("true") : wxT("false"));
125             break;
126     }
127     return ret;
128 }
129 
operator ==(const ShareGroup & other)130 bool ShareGroup::operator ==(const ShareGroup &other)
131 {
132     if (m_eType != other.m_eType) return false;
133     if (m_sGroupName != other.m_sGroupName) return false;
134     if (m_sUsername != other.m_sUsername) return false;
135     if (m_sPassword != other.m_sPassword) return false;
136     if (m_sShareName != other.m_sShareName) return false;
137     switch (m_eType) {
138         case SharedResource::SHARE_UNKNOWN:
139             break;
140         case SharedResource::SHARE_SMB_DISK:
141             if (m_sAlias != other.m_sAlias) return false;
142             break;
143         case SharedResource::SHARE_SMB_PRINTER:
144         case SharedResource::SHARE_CUPS_PRINTER:
145             if (m_sDriver != other.m_sDriver) return false;
146             if (m_bPublic != other.m_bPublic) return false;
147             if (m_bDefault != other.m_bDefault) return false;
148             break;
149     }
150     return true;
151 }
152 
operator !=(const ShareGroup & other)153 bool ShareGroup::operator !=(const ShareGroup &other)
154 {
155     return (!(*this == other));
156 }
157 
operator ==(const SharedUsbDevice & other)158 bool SharedUsbDevice::operator ==(const SharedUsbDevice &other)
159 {
160     if (m_eMode != other.m_eMode) return false;
161     if (m_sVendor != other.m_sVendor) return false;
162     if (m_sProduct != other.m_sProduct) return false;
163     if (m_sSerial != other.m_sSerial) return false;
164     if (m_iVendorID != other.m_iVendorID) return false;
165     if (m_iProductID != other.m_iProductID) return false;
166     if (m_iClass != other.m_iClass) return false;
167     return true;
168 }
169 
cmpNoMode(const SharedUsbDevice & other)170 bool SharedUsbDevice::cmpNoMode(const SharedUsbDevice &other)
171 {
172     if (m_sVendor != other.m_sVendor) return false;
173     if (m_sProduct != other.m_sProduct) return false;
174     if (m_sSerial != other.m_sSerial) return false;
175     if (m_iVendorID != other.m_iVendorID) return false;
176     if (m_iProductID != other.m_iProductID) return false;
177     if (m_iClass != other.m_iClass) return false;
178     return true;
179 }
180 
operator !=(const SharedUsbDevice & other)181 bool SharedUsbDevice::operator !=(const SharedUsbDevice &other)
182 {
183     return (!(*this == other));
184 }
185 
MatchHotplug(const USBDevice & udev)186 bool SharedUsbDevice::MatchHotplug(const USBDevice &udev)
187 {
188     if (m_iVendorID >= 0) {
189         if (m_iVendorID != udev.GetVendorID())
190             return false;
191     }
192     if (m_iProductID >= 0) {
193         if (m_iProductID != udev.GetProductID())
194             return false;
195     }
196     if (m_iClass >= 0) {
197         if (m_iClass != udev.GetDeviceClass())
198             return false;
199     }
200     if (!m_sVendor.IsEmpty()) {
201         if (!udev.GetVendor().StartsWith(m_sVendor))
202             return false;
203     }
204     if (!m_sProduct.IsEmpty()) {
205         if (!udev.GetProduct().StartsWith(m_sProduct))
206             return false;
207     }
208     if (!m_sSerial.IsEmpty()) {
209         if (!udev.GetSerial().StartsWith(m_sSerial))
210             return false;
211     }
212     return true;
213 }
214 
toShortString()215 wxString SharedUsbDevice::toShortString()
216 {
217     wxString ret = m_sVendor.Strip(wxString::both);
218     if ((!ret.IsEmpty()) && (!m_sProduct.IsEmpty()))
219         ret.Append(wxT(" "));
220     ret.Append(m_sProduct.Strip(wxString::both));
221     return ret;
222 }
223 
224 void
init()225 MyXmlConfig::init()
226 {
227     saved = NULL;
228     m_bDisableBackingstore = false;
229     m_bDisableComposite = false;
230     m_bDisableRender = false;
231     m_bDisableShmem = false;
232     m_bDisableShpix = false;
233     m_bDisableTaint = false;
234     m_bDisableTcpNoDelay = false;
235     m_bDisableXagent = false;
236     m_bDisableZlibCompression = false;
237     m_bEnableMultimedia = false;
238     m_bEnableSmbSharing = false;
239     m_bEnableSSL = true;
240     m_bEnableUSBIP = false;
241     m_bExternalProxy = false;
242     m_bGuestMode = false;
243     m_bKbdLayoutOther = false;
244     m_bOldConfig = false;
245     m_bProxyPassRemember = false;
246     m_bRdpCache = true;
247     m_bRdpRememberPassword = false;
248     m_bRdpRunApplication = false;
249     m_bRememberPassword = false;
250     m_bRemoveOldSessionFiles = true;
251     m_bRunConsole = false;
252     m_bRunXclients = false;
253     m_bUseCups = false;
254     m_bUseCustomImageEncoding = false;
255     m_bUseProxy = false;
256     m_bUseSmartCard = false;
257     m_bValid = false;
258     m_bWritable = true;
259     m_bVirtualDesktop = false;
260     m_bVncRememberPassword = false;
261     m_bVncUseNxAuth = false;
262     m_bDisableDirectDraw = false;
263     m_bDisableDeferredUpdates = false;
264     m_bGrabKeyboard = false;
265 
266     m_iClipFilter = 2;
267     m_iCupsPort = 631;
268     m_iDisplayHeight = 480;
269     m_iDisplayWidth = 640;
270     m_iImageEncoding = 3;
271     m_iJpegQuality = 6;
272     m_iProxyPort = 3128;
273     m_iRdpAuthType = 1;
274     m_iRdpColors = 8;
275     m_iRdpImageEncoding = 3;
276     m_iRdpJpegQuality = 6;
277     m_iServerPort = 22;
278     m_iSmbPort = 445;
279     m_iUsedShareGroups = 0;
280     m_iVncDisplayNumber = 0;
281     m_iVncImageEncoding = 3;
282     m_iVncJpegQuality = 6;
283     m_iXdmBroadcastPort = 177;
284     m_iXdmListPort = 177;
285     m_iXdmQueryPort = 177;
286 
287     m_eCacheDisk = CACHEDISK_32MB;
288     m_eCacheMemory = CACHEMEM_8MB;
289     m_eConnectionSpeed = SPEED_ADSL;
290     m_eDesktopType = DTYPE_KDE;
291     m_eDisplayType = DPTYPE_AVAILABLE;
292     m_eSessionType = STYPE_UNIX;
293     m_eXdmMode = XDM_MODE_SERVER;
294 
295     m_sCommandLine = wxEmptyString;
296     wxConfigBase::Get()->Read(wxT("Config/CupsPath"), &m_sCupsPath);
297     if (m_sCupsPath.IsEmpty())
298         m_sCupsPath = wxT(CUPS_DEFAULT_PATH);
299     m_sFileName = wxEmptyString;
300     m_sGuestUser = wxEmptyString;
301     m_sGuestPassword = wxEmptyString;
302     m_sKbdLayoutLanguage = wxString(wxConvLocal.cMB2WX(x11_keyboard_type)).AfterFirst(wxT('/')).BeforeFirst(wxT(','));
303     m_sName = wxEmptyString;
304     m_sPassword = wxEmptyString;
305     m_sProxyCommand = wxEmptyString;
306     m_sProxyHost = wxEmptyString;
307     m_sProxyPass = wxEmptyString;
308     m_sProxyUser = wxEmptyString;
309     m_sRdpApplication = wxEmptyString;
310     m_sRdpDomain = wxEmptyString;
311     m_sRdpHostName = wxEmptyString;
312     m_sRdpPassword = wxEmptyString;
313     m_sRdpUsername = wxEmptyString;
314     m_sServerHost = wxEmptyString;
315     m_sSshKey = wxEmptyString;
316     m_sUsername = wxEmptyString;
317     m_sVncHostName = wxEmptyString;
318     m_sVncPassword = wxEmptyString;
319     m_sXdmListHost = wxT("localhost");
320     m_sXdmQueryHost = wxT("localhost");
321 
322     m_pMd5Password = NULL;
323     m_pClrPassword = NULL;
324 }
325 
MyXmlConfig()326 MyXmlConfig::MyXmlConfig()
327 {
328     init();
329 }
330 
MyXmlConfig(const wxString & filename)331 MyXmlConfig::MyXmlConfig(const wxString &filename)
332 {
333     init();
334     if (filename.StartsWith(wxT("http://")) ||
335             filename.StartsWith(wxT("https://")) ||
336             filename.StartsWith(wxT("ftp://")) ||
337             filename.StartsWith(wxT("file://")))
338         LoadFromURL(filename);
339     else
340         LoadFromFile(filename);
341 }
342 
~MyXmlConfig()343 MyXmlConfig::~MyXmlConfig()
344 {
345     if (saved)
346         delete saved;
347     if (m_pMd5Password)
348         delete m_pMd5Password;
349     if (m_pClrPassword)
350         delete m_pClrPassword;
351 }
352 
353     MyXmlConfig &
operator =(const MyXmlConfig & other)354 MyXmlConfig::operator =(const MyXmlConfig &other)
355 {
356     saved = NULL;
357 
358     m_bDisableBackingstore = other.m_bDisableBackingstore;
359     m_bDisableComposite = other.m_bDisableComposite;
360     m_bDisableRender = other.m_bDisableRender;
361     m_bDisableShmem = other.m_bDisableShmem;
362     m_bDisableShpix = other.m_bDisableShpix;
363     m_bDisableTaint = other.m_bDisableTaint;
364     m_bDisableTcpNoDelay = other.m_bDisableTcpNoDelay;
365     m_bDisableXagent = other.m_bDisableXagent;
366     m_bDisableZlibCompression = other.m_bDisableZlibCompression;
367     m_bEnableMultimedia = other.m_bEnableMultimedia;
368     m_bEnableSmbSharing = other.m_bEnableSmbSharing;
369     m_bEnableSSL = other.m_bEnableSSL;
370     m_bEnableUSBIP = other.m_bEnableUSBIP;
371     m_bExternalProxy = other.m_bExternalProxy;
372     m_bGuestMode = other.m_bGuestMode;
373     m_bKbdLayoutOther = other.m_bKbdLayoutOther;
374     m_bProxyPassRemember = other.m_bProxyPassRemember;
375     m_bRdpCache = other.m_bRdpCache;
376     m_bRdpRememberPassword = other.m_bRdpRememberPassword;
377     m_bRdpRunApplication = other.m_bRdpRunApplication;
378     m_bRememberPassword = other.m_bRememberPassword;
379     m_bRemoveOldSessionFiles = other.m_bRemoveOldSessionFiles;
380     m_bRunConsole = other.m_bRunConsole;
381     m_bRunXclients = other.m_bRunXclients;
382     m_bUseCups = other.m_bUseCups;
383     m_bUseCustomImageEncoding = other.m_bUseCustomImageEncoding;
384     m_bUseProxy = other.m_bUseProxy;
385     m_bUseSmartCard = other.m_bUseSmartCard;
386     m_bValid = other.m_bValid;
387     // Don't copy readonly flag
388     m_bVirtualDesktop = other.m_bVirtualDesktop;
389     m_bVncRememberPassword = other.m_bVncRememberPassword;
390     m_bVncUseNxAuth = other.m_bVncUseNxAuth;
391     m_bDisableDirectDraw = other.m_bDisableDirectDraw;
392     m_bDisableDeferredUpdates = other.m_bDisableDeferredUpdates;
393     m_bGrabKeyboard = other.m_bGrabKeyboard;
394 
395     m_iClipFilter = other.m_iClipFilter;
396     m_iCupsPort = other.m_iCupsPort;
397     m_iDisplayHeight = other.m_iDisplayHeight;
398     m_iDisplayWidth = other.m_iDisplayWidth;
399     m_iImageEncoding = other.m_iImageEncoding;
400     m_iJpegQuality = other.m_iJpegQuality;
401     m_sKbdLayoutLanguage = other.m_sKbdLayoutLanguage;
402     m_iProxyPort = other.m_iProxyPort;
403     m_iRdpAuthType = other.m_iRdpAuthType;
404     m_iRdpColors = other.m_iRdpColors;
405     m_iRdpImageEncoding = other.m_iRdpImageEncoding;
406     m_iRdpJpegQuality = other.m_iRdpJpegQuality;
407     m_iServerPort = other.m_iServerPort;
408     m_iSmbPort = other.m_iSmbPort;
409     m_iUsedShareGroups = other.m_iUsedShareGroups;
410     m_iVncDisplayNumber = other.m_iVncDisplayNumber;
411     m_iVncImageEncoding = other.m_iVncImageEncoding;
412     m_iVncJpegQuality = other.m_iVncJpegQuality;
413     m_iXdmBroadcastPort = other.m_iXdmBroadcastPort;
414     m_iXdmListPort = other.m_iXdmListPort;
415     m_iXdmQueryPort = other.m_iXdmQueryPort;
416 
417     m_eCacheDisk = other.m_eCacheDisk;
418     m_eCacheMemory = other.m_eCacheMemory;
419     m_eConnectionSpeed = other.m_eConnectionSpeed;
420     m_eDesktopType = other.m_eDesktopType;
421     m_eDisplayType = other.m_eDisplayType;
422     m_eSessionType = other.m_eSessionType;
423     m_eXdmMode = other.m_eXdmMode;
424 
425     m_sCommandLine = other.m_sCommandLine;
426     m_sCupsPath = other.m_sCupsPath;
427     m_sGuestPassword = other.m_sGuestPassword;
428     m_sGuestUser = other.m_sGuestUser;
429     m_sName = other.m_sName;
430     m_sPassword = other.m_sPassword;
431     m_sProxyCommand = other.m_sProxyCommand;
432     m_sProxyHost = other.m_sProxyHost;
433     m_sProxyPass = other.m_sProxyPass;
434     m_sProxyUser = other.m_sProxyUser;
435     m_sRdpApplication = other.m_sRdpApplication;
436     m_sRdpDomain = other.m_sRdpDomain;
437     m_sRdpHostName = other.m_sRdpHostName;
438     m_sRdpPassword = other.m_sRdpPassword;
439     m_sRdpUsername = other.m_sRdpUsername;
440     m_sServerHost = other.m_sServerHost;
441     m_sSshKey = other.m_sSshKey;
442     m_sUsername = other.m_sUsername;
443     m_sVncHostName = other.m_sVncHostName;
444     m_sVncPassword = other.m_sVncPassword;
445     m_sXdmListHost = other.m_sXdmListHost;
446     m_sXdmQueryHost = other.m_sXdmQueryHost;
447 
448     m_aShareGroups = other.m_aShareGroups;
449     m_aUsedShareGroups = other.m_aUsedShareGroups;
450     m_aUsbForwards = other.m_aUsbForwards;
451 
452     if (other.m_pMd5Password) {
453         if (m_pMd5Password)
454             delete m_pMd5Password;
455         m_pMd5Password = new wxString(*other.m_pMd5Password);
456     }
457     if (other.m_pClrPassword) {
458         if (m_pClrPassword)
459             delete m_pClrPassword;
460         m_pClrPassword = new wxString(*other.m_pClrPassword);
461     }
462     return *this;
463 }
464 
465 // Retrieve parameters for proxy otion file
466     wxString
sGetProxyParams(const long protocolVersion)467 MyXmlConfig::sGetProxyParams(const long protocolVersion)
468 {
469     wxUnusedVar(protocolVersion);
470     wxString ret = wxEmptyString;
471     ret << wxT(",shmem=") << (m_bDisableShmem ? 0 : 1)
472         << wxT(",shpix=") << (m_bDisableShpix ? 0 : 1)
473         ;
474     // FIXME: use real settings
475     ret << wxT(",font=1");
476     return ret;
477 }
478 
479 // Retrieve parameters for listsession command
480     wxString
sGetListParams(const long protocolVersion)481 MyXmlConfig::sGetListParams(const long protocolVersion)
482 {
483     wxUnusedVar(protocolVersion);
484     wxString ret = wxT(" --user=\"");
485     if (m_eSessionType == STYPE_SHADOW) {
486         ret = wxT(" --type=\"shadow\"");
487         return ret;
488     }
489     if (m_bGuestMode) {
490         if (m_sGuestUser.IsEmpty())
491             ret << DEFAULT_GUEST_USER;
492         else
493             ret << m_sGuestUser;
494     } else
495         ret << m_sUsername;
496     if (protocolVersion >= 0x00040000)
497         ret << wxT("\" --status=\"disconnected,connected\"");
498     else
499         ret << wxT("\" --status=\"suspended,running\"");
500     ret << wxT(" --type=\"");
501     switch (m_eSessionType) {
502         case STYPE_SHADOW:
503             break;
504         case STYPE_UNIX:
505             ret << wxT("unix-");
506             switch (m_eDesktopType) {
507                 case DTYPE_ANY:
508                 case DTYPE_RDP:
509                 case DTYPE_RFB:
510                     break;
511                 case DTYPE_KDE:
512                     ret << wxT("kde\"");
513                     break;
514                 case DTYPE_GNOME:
515                     ret << wxT("gnome\"");
516                     break;
517                 case DTYPE_CDE:
518                     ret << wxT("cde\"");
519                     break;
520                 case DTYPE_XFCE:
521                     ret << wxT("xfce\"");
522                     break;
523                 case DTYPE_XDM:
524                     ret << wxT("xdm\"");
525                     break;
526                 case DTYPE_CUSTOM:
527                     if (m_bRunConsole)
528                         ret << wxT("console\"");
529                     else if (m_bRunXclients)
530                         ret << wxT("default\"");
531                     else
532                         ret << wxT("application\"");
533                     break;
534             }
535             break;
536         case STYPE_WINDOWS:
537             ret << wxT("windows\"");
538             break;
539         case STYPE_VNC:
540             ret << wxT("vnc\"");
541             break;
542     }
543     int w, h;
544     ::wxDisplaySize(&w, &h);
545     ret << wxT(" --geometry=\"") << w << wxT("x") << h << wxT("x")
546         << ::wxDisplayDepth() << (m_bDisableRender ? wxEmptyString : wxT("+render"))
547         << ((m_eDisplayType == DPTYPE_FULLSCREEN) ? wxT("+fullscreen") : wxEmptyString)
548         << wxT("\"");
549     return ret;
550 }
551 
552     wxString
UrlEsc(const wxString & s)553 MyXmlConfig::UrlEsc(const wxString &s)
554 {
555     size_t len = s.Length();
556     wxString ret;
557     for (size_t i = 0; i < len; i++) {
558         switch (s[i]) {
559             case wxT(' '):
560             case wxT(':'):
561             case wxT('"'):
562             case wxT('&'):
563             case wxT('$'):
564             case wxT('`'):
565             case wxT('\''):
566             case wxT('\\'):
567                 ret << wxString::Format(wxT("%%%02X"), s[i]);
568                 break;
569             default:
570                 ret << s[i];
571         }
572     }
573     return ret;
574 }
575 
576     void
getDesktopSize(int & dw,int & dh,int & ww,int & wh)577 MyXmlConfig::getDesktopSize(int &dw, int &dh, int &ww, int &wh)
578 {
579     // Fetch the size of the display and the workarea
580     // (workarea == display size reduced by the size of the taskbar and window
581     // decorations) where our toplevel dialog are shown.
582     wxWindow *tlw = ::wxGetApp().GetTopWindow();
583     if (NULL == tlw) {
584         ::wxLogError(_("Could not find application window"));
585         return;
586     }
587     int dspidx = wxDisplay::GetFromWindow(tlw);
588     wxDisplay dsp(dspidx);
589     wxRect r = dsp.GetGeometry();
590     dw = r.GetWidth();
591     dh = r.GetHeight();
592     r = dsp.GetClientArea();
593     wxSize sz = tlw->GetSize();
594     wxSize clsz = tlw->GetClientSize();
595     ww = r.GetWidth() - (sz.GetWidth() - clsz.GetWidth());
596     wh = r.GetHeight() - (sz.GetHeight() - clsz.GetHeight());
597     ::myLogTrace(MYTRACETAG, wxT("Display: %dx%d, Workarea: %dx%d (netto: %d,%d)"),
598             dw, dh, r.GetWidth(), r.GetHeight(), ww, wh);
599 }
600 
601 // Retrieve parameters for startsession command
602     wxString
sGetSessionParams(const long protocolVersion,bool bNew,const wxString & clrpass)603 MyXmlConfig::sGetSessionParams(const long protocolVersion, bool bNew, const wxString &clrpass)
604 {
605     wxUnusedVar(protocolVersion);
606     wxString ret = wxEmptyString;
607     bool bNeedGeometry = true;
608     int dspw, dsph, clientw, clienth;
609 
610     getDesktopSize(dspw, dsph, clientw, clienth);
611     ret << wxString::Format(wxT(" --session=\"%s\""), m_sName.c_str());
612     ret << wxT(" --type=\"");
613     switch (m_eSessionType) {
614         case STYPE_SHADOW:
615             ret << wxT("shadow\"");
616             if (m_bUseCustomImageEncoding) {
617                 ret << wxT(" --imagecompressionmethod=\"") << m_iImageEncoding << wxT("\"")
618                     << wxT(" --imagecompressionlevel=\"")
619                     << (((-1 == m_iImageEncoding) || (4 == m_iImageEncoding)) ? m_iJpegQuality : -1) << wxT("\"");
620             }
621             break;
622         case STYPE_UNIX:
623             ret << wxT("unix-");
624             switch (m_eDesktopType) {
625                 case DTYPE_ANY:
626                 case DTYPE_RDP:
627                 case DTYPE_RFB:
628                     break;
629                 case DTYPE_KDE:
630                     ret << wxT("kde\"");
631                     break;
632                 case DTYPE_GNOME:
633                     ret << wxT("gnome\"");
634                     break;
635                 case DTYPE_CDE:
636                     ret << wxT("cde\"");
637                     break;
638                 case DTYPE_XFCE:
639                     ret << wxT("xfce\"");
640                     break;
641                 case DTYPE_XDM:
642                     ret << wxT("xdm\"");
643                     switch (m_eXdmMode) {
644                         case XDM_MODE_SERVER:
645                             ret << wxT(" --xdm_port=\"-1\"");
646                             break;
647                         case XDM_MODE_QUERY:
648                             ret << wxT(" --xdm_type=\"query\"")
649                                 << wxT(" --xdm_host=\"") << m_sXdmQueryHost << wxT("\"")
650                                 << wxT(" --xdm_port=\"") << m_iXdmQueryPort << wxT("\"");
651                             break;
652                         case XDM_MODE_BROADCAST:
653                             ret << wxT(" --xdm_type=\"broadcast\"")
654                                 << wxT(" --xdm_port=\"") << m_iXdmBroadcastPort << wxT("\"");
655                             break;
656                         case XDM_MODE_LIST:
657                             ret << wxT(" --xdm_type=\"list\"")
658                                 << wxT(" --xdm_host=\"") << m_sXdmListHost << wxT("\"")
659                                 << wxT(" --xdm_port=\"") << m_iXdmListPort << wxT("\"");
660                             break;
661                     }
662                     break;
663                 case DTYPE_CUSTOM:
664                     if (m_bRunConsole)
665                         ret << wxT("console\"");
666                     else if (m_bRunXclients)
667                         ret << wxT("default\"");
668                     else {
669                         bNeedGeometry = false;
670                         ret << wxT("application\"");
671                         ret << wxT(" --rootless=\"")
672                             << (m_bVirtualDesktop ? 0 : 1)
673                             << wxT("\" --virtualdesktop=\"")
674                             << (m_bVirtualDesktop ? 1 : 0)
675                             << wxT("\" --application=\"")
676                             << UrlEsc(m_sCommandLine) << wxT("\"");
677                     }
678                     break;
679             }
680             if (m_bUseCustomImageEncoding) {
681                 ret << wxT(" --imagecompressionmethod=\"") << m_iImageEncoding << wxT("\"")
682                     << wxT(" --imagecompressionlevel=\"")
683                     << (((-1 == m_iImageEncoding) || (4 == m_iImageEncoding)) ? m_iJpegQuality : -1) << wxT("\"");
684             }
685             break;
686         case STYPE_WINDOWS:
687             ret << wxT("windows\"")
688                 << wxT(" --agent_server=\"") << UrlEsc(m_sRdpHostName)
689                 << wxT("\" --agent_domain=\"") << UrlEsc(m_sRdpDomain)
690                 << wxT("\"");
691             switch (m_iRdpAuthType) {
692                 case 0:
693                     // use specified user/passwd
694                     ret << wxT(" --agent_user=\"") << UrlEsc(m_sRdpUsername)
695                         << wxT("\" --agent_password=\"") << UrlEsc(m_sRdpPassword)
696                         << wxT("\"");
697                     break;
698                 case 1:
699                     // show winlogon (empty username and password)
700                     break;
701                 case 2:
702                     // use NX credentials
703                     ret << wxT(" --agent_user=\"") << UrlEsc(sGetSessionUser())
704                         << wxT("\" --agent_password=\"")
705                         << UrlEsc(m_bRememberPassword ? sGetSessionPassword() : clrpass)
706                         << wxT("\"");
707                     break;
708                     break;
709             }
710             if (m_bRdpRunApplication)
711                 ret << wxT(" --application=\"") << UrlEsc(m_sRdpApplication) << wxT("\"");
712             if (m_bUseCustomImageEncoding) {
713                 ret << wxT(" --rdpcolors=\"");
714                 switch (m_iRdpColors) {
715                     case 0:
716                         ret << wxT("256\"");
717                         break;
718                     case 1:
719                         ret << wxT("32K\"");
720                         break;
721                     case 2:
722                         ret << wxT("64K\"");
723                         break;
724                     case 3:
725                         ret << wxT("16M\"");
726                         break;
727                 }
728                 ret << wxT(" --rdpcache=\"") << (m_bRdpCache ? 1 : 0) << wxT("\"")
729                     << wxT(" --imagecompressionmethod=\"") << m_iRdpImageEncoding << wxT("\"")
730                     << wxT(" --imagecompressionlevel=\"")
731                     << (((-1 == m_iRdpImageEncoding) || (4 == m_iRdpImageEncoding)) ? m_iRdpJpegQuality : -1)
732                     << wxT("\"");
733             }
734             break;
735         case STYPE_VNC:
736             ret << wxT("vnc\"")
737                 << wxT(" --agent_server=\"")
738                 << UrlEsc(m_sVncHostName) << wxT("%3A") << m_iVncDisplayNumber
739                 << wxT("\" --agent_password=\"") << UrlEsc(m_sVncPassword) << wxT("\"");
740             if (m_bUseCustomImageEncoding) {
741                 ret << wxT(" --imagecompressionmethod=\"") << m_iVncImageEncoding << wxT("\"")
742                     << wxT(" --imagecompressionlevel=\"")
743                     << (((-1 == m_iVncImageEncoding) || (4 == m_iVncImageEncoding)) ? m_iVncJpegQuality : -1)
744                     << wxT("\"");
745             }
746             break;
747     }
748     ret << wxT(" --cache=\"");
749     switch (m_eCacheMemory) {
750         case CACHEMEM_0MB:
751             ret << wxT("0M\"");
752             break;
753         case CACHEMEM_1MB:
754             ret << wxT("1M\"");
755             break;
756         case CACHEMEM_2MB:
757             ret << wxT("2M\"");
758             break;
759         case CACHEMEM_4MB:
760             ret << wxT("4M\"");
761             break;
762         case CACHEMEM_8MB:
763             ret << wxT("8M\"");
764             break;
765         case CACHEMEM_16MB:
766             ret << wxT("16M\"");
767             break;
768         case CACHEMEM_32MB:
769             ret << wxT("32M\"");
770             break;
771         case CACHEMEM_64MB:
772             ret << wxT("64M\"");
773             break;
774         case CACHEMEM_128MB:
775             ret << wxT("128M\"");
776             break;
777     }
778     ret << wxT(" --images=\"");
779     switch (m_eCacheDisk) {
780         case CACHEDISK_0MB:
781             ret << wxT("0M\"");
782             break;
783         case CACHEDISK_4MB:
784             ret << wxT("4M\"");
785             break;
786         case CACHEDISK_8MB:
787             ret << wxT("8M\"");
788             break;
789         case CACHEDISK_16MB:
790             ret << wxT("16M\"");
791             break;
792         case CACHEDISK_32MB:
793             ret << wxT("32M\"");
794             break;
795         case CACHEDISK_64MB:
796             ret << wxT("64M\"");
797             break;
798         case CACHEDISK_128MB:
799             ret << wxT("128M\"");
800             break;
801         case CACHEDISK_256MB:
802             ret << wxT("256M\"");
803             break;
804         case CACHEDISK_512MB:
805             ret << wxT("512M\"");
806             break;
807     }
808     ret << wxT(" --link=\"");
809     switch (m_eConnectionSpeed) {
810         case SPEED_MODEM:
811             ret << wxT("modem\"");
812             break;
813         case SPEED_ISDN:
814             ret << wxT("isdn\"");
815             break;
816         case SPEED_ADSL:
817             ret << wxT("adsl\"");
818             break;
819         case SPEED_WAN:
820             ret << wxT("wan\"");
821             break;
822         case SPEED_LAN:
823             ret << wxT("lan\"");
824             break;
825     }
826     if (bNeedGeometry) {
827         ret << wxT(" --geometry=\"");
828         switch (m_eDisplayType) {
829             case DPTYPE_640x480:
830                 ret << wxT("640x480\"");
831                 break;
832             case DPTYPE_800x600:
833                 ret << wxT("800x600\"");
834                 break;
835             case DPTYPE_1024x768:
836                 ret << wxT("1024x768\"");
837                 break;
838             case DPTYPE_AVAILABLE:
839                 ret << wxString::Format(wxT("%dx%d\""), clientw, clienth);
840                 break;
841             case DPTYPE_FULLSCREEN:
842                 ret << wxString::Format(wxT("%dx%d\""), dspw, dsph)
843                     << wxT(" --fullscreen=\"1\"");
844                 break;
845             case DPTYPE_CUSTOM:
846                 ret << wxString::Format(wxT("%dx%d\""), m_iDisplayWidth, m_iDisplayHeight);
847                 break;
848             case DPTYPE_REMOTE:
849                 ret << wxString::Format(wxT("%dx%d\""), dspw, dsph);
850                 break;
851         }
852     }
853     if (m_eSessionType != STYPE_SHADOW) {
854         ret << wxT(" --screeninfo=\"") << dspw << wxT("x") << dsph << wxT("x")
855             << ::wxDisplayDepth() << (m_bDisableRender ? wxEmptyString : wxT("+render"))
856             << ((m_eDisplayType == DPTYPE_FULLSCREEN) ? wxT("+fullscreen") : wxEmptyString)
857             << wxT("\"");
858     }
859 
860     wxString kbdLocal = wxString(wxConvLocal.cMB2WX(x11_keyboard_type)).BeforeFirst(wxT(','));
861     ret << wxT(" --keyboard=\"");
862     if (m_bKbdLayoutOther) {
863         if (wxNOT_FOUND != kbdLocal.Find(wxT('/')))
864             ret << kbdLocal.BeforeFirst(wxT('/')) << wxT("/");
865         ret << m_sKbdLayoutLanguage;
866     } else {
867         if (kbdLocal.IsEmpty())
868             kbdLocal = wxT("query");
869         ret << kbdLocal;
870     }
871     ret << wxT("\"")
872         << wxT(" --backingstore=\"") << (m_bDisableBackingstore ? 0 : 1) << wxT("\"")
873         << wxT(" --encryption=\"") << (m_bEnableSSL ? 1 : 0) << wxT("\"");
874     if (bNew) {
875         ret << wxT(" --render=\"") << (m_bDisableRender ? 0 : 1) << wxT("\"");
876     }
877     ret << wxT(" --composite=\"") << (m_bDisableComposite ? 0 : 1) << wxT("\"")
878         << wxT(" --shmem=\"") << (m_bDisableShmem ? 0 : 1) << wxT("\"")
879         << wxT(" --shpix=\"") << (m_bDisableShpix ? 0 : 1) << wxT("\"");
880     // deprecated << wxT(" --streaming=\"") << (m_bDisableStreaming ? 0 : 1) << wxT("\"")
881     if (bNew) {
882         ret << wxT(" --samba=\"") << (m_bEnableSmbSharing ? 1 : 0) << wxT("\"")
883             << wxT(" --cups=\"") << (m_bUseCups ? 1 : 0) << wxT("\"")
884             << wxT(" --nodelay=\"") << (m_bDisableTcpNoDelay ? 0 : 1) << wxT("\"")
885             << wxT(" --defer=\"") << (m_bDisableDeferredUpdates ? 1 : 0) << wxT("\"");
886     }
887 #ifdef __WXMAC__
888     ret << wxT(" --client=\"macosx\"");
889 #else
890 # ifdef __UNIX__
891     ret << wxT(" --client=\"linux\"");
892 # else
893     // << wxT(" --client=\"winnt\"")
894     ret << wxT(" --client=\"linux\"");
895 # endif
896 #endif
897     ret << wxT(" --media=\"") << (m_bEnableMultimedia ? 1 : 0) << wxT("\"");
898     if (m_bEnableMultimedia) {
899         ret << wxT(" --mediahelper=\"esd\"");
900     }
901     // Original always uses those?!
902     ret << wxT(" --strict=\"0\"");
903     if (bNew) {
904         // With this parameter set, attaching to shadow sessions fails, if the server's display base is >= 10000
905         // so we simply leave it out for shadow sessions.
906         ret << wxT(" --aux=\"1\"");
907     }
908     return ret;
909 }
910 
911 #ifdef __WXMSW__
912     wxString
sGetXserverParams(bool forNXWin)913 MyXmlConfig::sGetXserverParams(bool forNXWin)
914 {
915     wxString ret;
916     int dspw, dsph, clientw, clienth;
917     getDesktopSize(dspw, dsph, clientw, clienth);
918 
919     if (forNXWin) {
920         switch (m_eDisplayType) {
921             case MyXmlConfig::DPTYPE_640x480:
922                 ret << wxT(" -screen 0 640x480");
923                 break;
924             case MyXmlConfig::DPTYPE_800x600:
925                 // fall thru
926             default:
927                 ret << wxT(" -screen 0 800x600");
928                 break;
929             case MyXmlConfig::DPTYPE_1024x768:
930                 ret << wxT(" -screen 0 1024x768");
931                 break;
932             case MyXmlConfig::DPTYPE_AVAILABLE:
933                 ret << wxT(" -screen 0 ") << clientw << wxT("x") << clienth;
934                 break;
935             case MyXmlConfig::DPTYPE_FULLSCREEN:
936                 ret << wxT(" -fullscreen ");
937                 break;
938             case MyXmlConfig::DPTYPE_CUSTOM:
939                 // Fall thru
940             case MyXmlConfig::DPTYPE_REMOTE:
941                 ret << wxT(" -screen 0 ") << m_iDisplayWidth << wxT("x") << m_iDisplayHeight;
942                 break;
943         }
944     } else {
945         if (MyXmlConfig::DPTYPE_FULLSCREEN == m_eDisplayType) {
946             ret << wxT(" -terminate -fullscreen -hide");
947         } else {
948             ret << wxT(" -noreset -lesspointer -multiwindow");
949         }
950     }
951     if (m_bDisableDirectDraw)
952         ret << wxT(" -engine 1");
953     ret << wxT(" -") << (m_bGrabKeyboard ? wxT("") : wxT("no")) << wxT("keyhook");
954     return ret;
955 }
956 #endif
957 
958     ShareGroup &
findShare(const wxString & name)959 MyXmlConfig::findShare(const wxString &name)
960 {
961     size_t cnt = m_aShareGroups.GetCount();
962     static ShareGroup ret;
963     for (size_t i = 0; i < cnt; i++) {
964         if (m_aShareGroups[i].m_sGroupName == name)
965             return m_aShareGroups[i];
966     }
967     return ret;
968 }
969 
970 // Compare two arrays of ShareGroup where sequence of elements is irrelevant
971 // return true, if arrays are different.
972     bool
cmpShareGroups(ArrayOfShareGroups a1,ArrayOfShareGroups a2)973 MyXmlConfig::cmpShareGroups(ArrayOfShareGroups a1, ArrayOfShareGroups a2)
974 {
975     size_t cnt = a1.GetCount();
976     if (cnt != a2.GetCount())
977         return true;
978     ArrayOfShareGroups ca = a2;
979     for (size_t i = 0; i < cnt; i++) {
980         size_t cnt2 = ca.GetCount();
981         int idx = wxNOT_FOUND;
982         for (size_t j = 0; j < cnt2; j++) {
983             if (a1[i] == ca[j]) {
984                 idx = j;
985                 break;
986             }
987         }
988         if (idx == wxNOT_FOUND)
989             return true;
990         ca.RemoveAt(idx);
991     }
992     return (ca.GetCount() != 0);
993 }
994 
995 // Compare two arrays of UsbForwards where sequence of elements is irrelevant
996 // return true, if arrays are different.
997     bool
cmpUsbForwards(ArrayOfUsbForwards a1,ArrayOfUsbForwards a2)998 MyXmlConfig::cmpUsbForwards(ArrayOfUsbForwards a1, ArrayOfUsbForwards a2)
999 {
1000     size_t cnt = a1.GetCount();
1001     if (cnt != a2.GetCount())
1002         return true;
1003     ArrayOfUsbForwards ca = a2;
1004     for (size_t i = 0; i < cnt; i++) {
1005         size_t cnt2 = ca.GetCount();
1006         int idx = wxNOT_FOUND;
1007         for (size_t j = 0; j < cnt2; j++) {
1008             if (a1[i] == ca[j]) {
1009                 idx = j;
1010                 break;
1011             }
1012         }
1013         if (idx == wxNOT_FOUND)
1014             return true;
1015         ca.RemoveAt(idx);
1016     }
1017     return (ca.GetCount() != 0);
1018 }
1019 
1020 // Compare two wxArrayString where sequence of elements is irrelevant
1021 // return true, if arrays are different.
1022     bool
cmpUsedShareGroups(wxArrayString a1,wxArrayString a2)1023 MyXmlConfig::cmpUsedShareGroups(wxArrayString a1, wxArrayString a2)
1024 {
1025     size_t cnt = a1.GetCount();
1026     if (cnt != a2.GetCount())
1027         return true;
1028     wxArrayString ca = a2;
1029     for (size_t i = 0; i < cnt; i++) {
1030         int idx = ca.Index(a1.Item(i));
1031         if (idx == wxNOT_FOUND)
1032             return true;
1033         ca.RemoveAt(idx);
1034     }
1035     return (ca.GetCount() != 0);
1036 }
1037 
1038     bool
operator ==(const MyXmlConfig & other)1039 MyXmlConfig::operator ==(const MyXmlConfig &other)
1040 {
1041     if (m_bDisableBackingstore != other.m_bDisableBackingstore) return false;
1042     if (m_bDisableComposite != other.m_bDisableComposite) return false;
1043     if (m_bDisableRender != other.m_bDisableRender) return false;
1044     if (m_bDisableShmem != other.m_bDisableShmem) return false;
1045     if (m_bDisableShpix != other.m_bDisableShpix) return false;
1046     if (m_bDisableTaint != other.m_bDisableTaint) return false;
1047     if (m_bDisableTcpNoDelay != other.m_bDisableTcpNoDelay) return false;
1048     if (m_bDisableXagent != other.m_bDisableXagent) return false;
1049     if (m_bDisableZlibCompression != other.m_bDisableZlibCompression) return false;
1050     if (m_bEnableMultimedia != other.m_bEnableMultimedia) return false;
1051     if (m_bEnableSmbSharing != other.m_bEnableSmbSharing) return false;
1052     if (m_bEnableSSL != other.m_bEnableSSL) return false;
1053     if (m_bEnableUSBIP != other.m_bEnableUSBIP) return false;
1054     if (m_bExternalProxy != other.m_bExternalProxy) return false;
1055     if (m_bGuestMode != other.m_bGuestMode) return false;
1056     if (m_bKbdLayoutOther != other.m_bKbdLayoutOther) return false;
1057     if (m_bProxyPassRemember != other.m_bProxyPassRemember) return false;
1058     if (m_bRdpCache != other.m_bRdpCache) return false;
1059     if (m_bRdpRememberPassword != other.m_bRdpRememberPassword) return false;
1060     if (m_bRdpRunApplication != other.m_bRdpRunApplication) return false;
1061     if (m_bRememberPassword != other.m_bRememberPassword) return false;
1062     if (m_bRemoveOldSessionFiles != other.m_bRemoveOldSessionFiles) return false;
1063     if (m_bRunConsole != other.m_bRunConsole) return false;
1064     if (m_bRunXclients != other.m_bRunXclients) return false;
1065     if (m_bUseCups != other.m_bUseCups) return false;
1066     if (m_bUseCustomImageEncoding != other.m_bUseCustomImageEncoding) return false;
1067     if (m_bUseProxy != other.m_bUseProxy) return false;
1068     if (m_bUseSmartCard != other.m_bUseSmartCard) return false;
1069     if (m_bValid != other.m_bValid) return false;
1070     // Don't compare readonly flag
1071     if (m_bVirtualDesktop != other.m_bVirtualDesktop) return false;
1072     if (m_bVncRememberPassword != other.m_bVncRememberPassword) return false;
1073     if (m_bVncUseNxAuth != other.m_bVncUseNxAuth) return false;
1074     if (m_bDisableDirectDraw != other.m_bDisableDirectDraw) return false;
1075     if (m_bDisableDeferredUpdates != other.m_bDisableDeferredUpdates) return false;
1076     if (m_bGrabKeyboard != other.m_bGrabKeyboard) return false;
1077 
1078     if (m_iClipFilter != other.m_iClipFilter) return false;
1079     if (m_iCupsPort != other.m_iCupsPort) return false;
1080     if (m_iDisplayHeight != other.m_iDisplayHeight) return false;
1081     if (m_iDisplayWidth != other.m_iDisplayWidth) return false;
1082     if (m_iImageEncoding != other.m_iImageEncoding) return false;
1083     if (m_iJpegQuality != other.m_iJpegQuality) return false;
1084     if (m_iProxyPort != other.m_iProxyPort) return false;
1085     if (m_iRdpAuthType != other.m_iRdpAuthType) return false;
1086     if (m_iRdpColors != other.m_iRdpColors) return false;
1087     if (m_iRdpImageEncoding != other.m_iRdpImageEncoding) return false;
1088     if (m_iRdpJpegQuality != other.m_iRdpJpegQuality) return false;
1089     if (m_iServerPort != other.m_iServerPort) return false;
1090     if (m_iSmbPort != other.m_iSmbPort) return false;
1091     if (m_iUsedShareGroups != other.m_iUsedShareGroups) return false;
1092     if (m_iVncDisplayNumber != other.m_iVncDisplayNumber) return false;
1093     if (m_iVncImageEncoding != other.m_iVncImageEncoding) return false;
1094     if (m_iVncJpegQuality != other.m_iVncJpegQuality) return false;
1095     if (m_iXdmBroadcastPort != other.m_iXdmBroadcastPort) return false;
1096     if (m_iXdmListPort != other.m_iXdmListPort) return false;
1097     if (m_iXdmQueryPort != other.m_iXdmQueryPort) return false;
1098 
1099     if (m_eCacheDisk != other.m_eCacheDisk) return false;
1100     if (m_eCacheMemory != other.m_eCacheMemory) return false;
1101     if (m_eConnectionSpeed != other.m_eConnectionSpeed) return false;
1102     if (m_eDesktopType != other.m_eDesktopType) return false;
1103     if (m_eDisplayType != other.m_eDisplayType) return false;
1104     if (m_eSessionType != other.m_eSessionType) return false;
1105     if (m_eXdmMode != other.m_eXdmMode) return false;
1106 
1107     if (m_sCommandLine != other.m_sCommandLine) return false;
1108     if (m_sCupsPath != other.m_sCupsPath) return false;
1109     // if (m_sFileName != other.m_sFileName) return false;
1110     if (m_sKbdLayoutLanguage != other.m_sKbdLayoutLanguage) return false;
1111     if (m_sName != other.m_sName) return false;
1112     if (m_sPassword != other.m_sPassword) return false;
1113     if (m_sProxyCommand != other.m_sProxyCommand) return false;
1114     if (m_sProxyHost != other.m_sProxyHost) return false;
1115     if (m_sProxyPass != other.m_sProxyPass) return false;
1116     if (m_sProxyUser != other.m_sProxyUser) return false;
1117     if (m_sRdpApplication != other.m_sRdpApplication) return false;
1118     if (m_sRdpDomain != other.m_sRdpDomain) return false;
1119     if (m_sRdpHostName != other.m_sRdpHostName) return false;
1120     if (m_sRdpPassword != other.m_sRdpPassword) return false;
1121     if (m_sRdpUsername != other.m_sRdpUsername) return false;
1122     if (m_sServerHost != other.m_sServerHost) return false;
1123     if (m_sSshKey != other.m_sSshKey) return false;
1124     if (m_sUsername != other.m_sUsername) return false;
1125     if (m_sVncHostName != other.m_sVncHostName) return false;
1126     if (m_sVncPassword != other.m_sVncPassword) return false;
1127     if (m_sXdmListHost != other.m_sXdmListHost) return false;
1128     if (m_sXdmQueryHost != other.m_sXdmQueryHost) return false;
1129 
1130     if (cmpUsedShareGroups(m_aUsedShareGroups, other.m_aUsedShareGroups)) return false;
1131     if (cmpShareGroups(m_aShareGroups, other.m_aShareGroups)) return false;
1132     if (cmpUsbForwards(m_aUsbForwards, other.m_aUsbForwards)) return false;
1133     return true;
1134 }
1135 
1136     bool
LoadFromString(const wxString & content,bool isPush)1137 MyXmlConfig::LoadFromString(const wxString &content, bool isPush)
1138 {
1139     char *cnt = strdup(content.mb_str());
1140     wxMemoryInputStream mis(cnt, strlen(cnt));
1141     bool ret = loadFromStream(mis, isPush);
1142     free(cnt);
1143     return ret;
1144 }
1145 
1146     bool
LoadFromFile(const wxString & filename)1147 MyXmlConfig::LoadFromFile(const wxString &filename)
1148 {
1149     {
1150         wxLogNull dummy;
1151         wxFile *f = new wxFile(filename);
1152         if ((!f->IsOpened()) || f->Eof()) {
1153             delete f;
1154             return false;
1155         }
1156         delete f;
1157     }
1158     ::myLogTrace(MYTRACETAG, wxT("Reading %s"), filename.c_str());
1159     wxFileInputStream fis(filename);
1160     if (loadFromStream(fis, false)) {
1161         m_sName = wxFileName(filename).GetName();
1162         m_sFileName = wxFileName(filename).GetFullPath();
1163         m_bWritable = wxFileName::IsFileWritable(m_sFileName);
1164         return true;
1165     }
1166     return false;
1167 }
1168 
CurlWriteCallback(void * buffer,size_t size,size_t nmemb,void * userp)1169 size_t MyXmlConfig::CurlWriteCallback(void *buffer, size_t size, size_t nmemb, void *userp)
1170 {
1171 #ifdef APP_OPENNX
1172 # ifdef HAVE_LIBCURL
1173     if (userp) {
1174         wxMemoryOutputStream *mos = (wxMemoryOutputStream *)userp;
1175         return mos->GetOutputStreamBuffer()->Write(buffer, size * nmemb);
1176         // return size * nmemb;
1177     }
1178 # endif
1179 #else
1180     wxUnusedVar(buffer);
1181     wxUnusedVar(size);
1182     wxUnusedVar(nmemb);
1183     wxUnusedVar(userp);
1184 #endif
1185     return -1;
1186 }
1187 
1188     bool
LoadFromURL(const wxString & filename)1189 MyXmlConfig::LoadFromURL(const wxString &filename)
1190 {
1191     bool ret = false;
1192 #ifdef APP_OPENNX
1193 # ifdef HAVE_LIBCURL
1194     wxMemoryOutputStream mos;
1195     char ebuf[CURL_ERROR_SIZE];
1196     CURL *c = curl_easy_init();
1197     // curl_easy_setopt(c, CURLOPT_FAILONERROR, 1);
1198     // curl_easy_setopt(c, CURLOPT_VERBOSE, 1);
1199     curl_easy_setopt(c, CURLOPT_NOPROGRESS, 1);
1200     curl_easy_setopt(c, CURLOPT_NOSIGNAL, 1);
1201     curl_easy_setopt(c, CURLOPT_URL, (const char *)filename.mb_str());
1202     curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1);
1203     curl_easy_setopt(c, CURLOPT_MAXREDIRS, 10);
1204     // curl_easy_setopt(c, CURLOPT_COOKIE, "foo=bar");
1205     curl_easy_setopt(c, CURLOPT_TIMEOUT, 10);
1206     curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 1);
1207     curl_easy_setopt(c, CURLOPT_SSL_VERIFYHOST, 2);
1208     if (!::wxGetApp().GetCaCert().IsEmpty())
1209         curl_easy_setopt(c, CURLOPT_CAINFO, (const char *)::wxGetApp().GetCaCert().mb_str());
1210     curl_easy_setopt(c, CURLOPT_WRITEDATA, &mos);
1211     curl_easy_setopt(c, CURLOPT_ERRORBUFFER, ebuf);
1212     curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, CurlWriteCallback);
1213     ::myLogTrace(MYTRACETAG, wxT("Fetching %s"), filename.c_str());
1214     CURLcode r = curl_easy_perform(c);
1215     if (0 == r) {
1216         off_t len = mos.TellO();
1217         if (len > 0) {
1218             int rcode = 200;
1219             if (filename.StartsWith(wxT("http"))) {
1220                 curl_easy_getinfo(c, CURLINFO_RESPONSE_CODE, &rcode);
1221             }
1222             if (200 == rcode) {
1223                 ::myLogTrace(MYTRACETAG, wxT("Fetching %s"), filename.c_str());
1224                 char * const data = new char[len];
1225                 mos.CopyTo(data, len);
1226                 wxMemoryInputStream mis(data, len);
1227                 if (loadFromStream(mis, false)) {
1228                     wxURI uri(filename);
1229                     m_sName = wxFileName(uri.GetPath()).GetName();
1230                     if (0 == uri.GetScheme().CmpNoCase(wxT("file"))) {
1231                         m_sFileName = wxFileName(uri.GetPath()).GetFullPath();
1232                         m_bWritable = wxFileName::IsFileWritable(m_sFileName);
1233                     } else {
1234                         wxURL url(filename);
1235                         m_sFileName = url.BuildUnescapedURI();
1236                         m_bWritable = false;
1237                     }
1238                     ret = true;
1239                 }
1240                 delete data;
1241             } else {
1242                 ::wxLogError(_("Error %d while fetching session configuration"), rcode);
1243             }
1244         }
1245     } else {
1246         wxString msg(ebuf, *wxConvCurrent);
1247         ::wxLogError(_("Error while fetching session configuration:\n%s"), msg.c_str());
1248     }
1249     curl_easy_cleanup(c);
1250 # else
1251     wxURL url(filename);
1252     {
1253         wxLogNull dummy;
1254         if (!url.IsOk())
1255             return false;
1256     }
1257     ::myLogTrace(MYTRACETAG, wxT("Fetching %s"), filename.c_str());
1258     wxInputStream *is = url.GetInputStream();
1259     if (is && loadFromStream(*is, false)) {
1260         wxURI uri(filename);
1261         m_sName = wxFileName(uri.GetPath()).GetName();
1262         if (0 == uri.GetScheme().CmpNoCase(wxT("file"))) {
1263             m_sFileName = wxFileName(uri.GetPath()).GetFullPath();
1264             m_bWritable = wxFileName::IsFileWritable(m_sFileName);
1265         } else {
1266             m_sFileName = url.BuildUnescapedURI();
1267             m_bWritable = false;
1268         }
1269         ret = true;
1270     }
1271 # endif
1272 #else
1273     wxUnusedVar(filename);
1274 #endif
1275     return ret;
1276 }
1277 
1278     bool
loadFromStream(wxInputStream & is,bool isPush)1279 MyXmlConfig::loadFromStream(wxInputStream &is, bool isPush)
1280 {
1281     wxString tmp;
1282     int itmp;
1283     wxXmlDocument cfg(is);
1284 
1285     wxXmlNode *cfgnode = cfg.GetRoot();
1286     if (cfgnode && (cfgnode->GetName() == wxT("NXClientSettings"))) {
1287         if (!(cfgnode->GetPropVal(wxT("application"), wxEmptyString) == wxT("nxclient")))
1288             return false;
1289         if (!(cfgnode->GetPropVal(wxT("version"), wxEmptyString) == wxT("1.3")))
1290             return false;
1291         cfgnode = cfgnode->GetChildren();
1292         while (cfgnode) {
1293             if (cfgnode->GetName() == wxT("group")) {
1294 
1295                 // Tab "Advanced"
1296                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("Advanced")) {
1297                     wxXmlNode *opt = cfgnode->GetChildren();
1298                     while (opt) {
1299 
1300                         itmp = getLong(opt, wxT("Cache size"), -1);
1301                         switch (itmp) {
1302                             case 0:
1303                                 m_eCacheMemory = CACHEMEM_0MB;
1304                                 break;
1305                             case 1:
1306                                 m_eCacheMemory = CACHEMEM_1MB;
1307                                 break;
1308                             case 2:
1309                                 m_eCacheMemory = CACHEMEM_2MB;
1310                                 break;
1311                             case 4:
1312                                 m_eCacheMemory = CACHEMEM_4MB;
1313                                 break;
1314                             case 8:
1315                                 m_eCacheMemory = CACHEMEM_8MB;
1316                                 break;
1317                             case 16:
1318                                 m_eCacheMemory = CACHEMEM_16MB;
1319                                 break;
1320                             case 32:
1321                                 m_eCacheMemory = CACHEMEM_32MB;
1322                                 break;
1323                             case 64:
1324                                 m_eCacheMemory = CACHEMEM_64MB;
1325                                 break;
1326                             case 128:
1327                                 m_eCacheMemory = CACHEMEM_128MB;
1328                                 break;
1329                         }
1330                         itmp = getLong(opt, wxT("Cache size on disk"), -1);
1331                         switch (itmp) {
1332                             case 0:
1333                                 m_eCacheDisk = CACHEDISK_0MB;
1334                                 break;
1335                             case 4:
1336                                 m_eCacheDisk = CACHEDISK_4MB;
1337                                 break;
1338                             case 8:
1339                                 m_eCacheDisk = CACHEDISK_8MB;
1340                                 break;
1341                             case 16:
1342                                 m_eCacheDisk = CACHEDISK_16MB;
1343                                 break;
1344                             case 32:
1345                                 m_eCacheDisk = CACHEDISK_32MB;
1346                                 break;
1347                             case 64:
1348                                 m_eCacheDisk = CACHEDISK_64MB;
1349                                 break;
1350                             case 128:
1351                                 m_eCacheDisk = CACHEDISK_128MB;
1352                                 break;
1353                             case 256:
1354                                 m_eCacheDisk = CACHEDISK_256MB;
1355                                 break;
1356                             case 512:
1357                                 m_eCacheDisk = CACHEDISK_512MB;
1358                                 break;
1359                         }
1360 #if 0
1361                         if (wxGetEnv(wxT("THINCLIENT"), NULL))
1362                             m_eCacheDisk = CACHEDISK_0MB;
1363 #endif
1364                         m_bKbdLayoutOther = !getBool(opt, wxT("Current keyboard"),
1365                                 !m_bKbdLayoutOther);
1366                         m_sKbdLayoutLanguage = getString(opt,
1367                                 wxT("Custom keyboard layout"), m_sKbdLayoutLanguage);
1368                         m_bDisableTcpNoDelay = getBool(opt, wxT("Disable TCP no-delay"),
1369                                 m_bDisableTcpNoDelay);
1370                         m_bDisableZlibCompression = getBool(opt,
1371                                 wxT("Disable ZLIB stream compression"),
1372                                 m_bDisableZlibCompression);
1373                         m_bGrabKeyboard = getBool(opt, wxT("Grab keyboard"),
1374                                 m_bGrabKeyboard);
1375                         m_bDisableDirectDraw = getBool(opt, wxT("Disable DirectDraw"),
1376                                 m_bDisableDirectDraw);
1377                         m_bDisableDeferredUpdates = getBool(opt, wxT("Disable deferred updates"),
1378                                 m_bDisableDeferredUpdates);
1379 
1380                         tmp = getString(opt, wxT("Clipboard filter"), wxEmptyString);
1381                         if (!tmp.IsEmpty()) {
1382                             ::myLogTrace(MYTRACETAG, wxT("read: Clipboard filter '%s'"), tmp.c_str());
1383                             if (tmp.CmpNoCase(wxT("primary")) == 0) {
1384                                 m_iClipFilter = 0;
1385                             }
1386                             if (tmp.CmpNoCase(wxT("clipboard")) == 0) {
1387                                 m_iClipFilter = 1;
1388                             }
1389                             if (tmp.CmpNoCase(wxT("both")) == 0) {
1390                                 m_iClipFilter = 2;
1391                             }
1392                             ::myLogTrace(MYTRACETAG, wxT("read: m_iClipFilter=%d"), m_iClipFilter);
1393                         }
1394                         m_bUseProxy = getBool(opt, wxT("Enable HTTP proxy"), m_bUseProxy);
1395                         m_bExternalProxy = getBool(opt, wxT("Enable external proxy"), m_bExternalProxy);
1396                         m_bEnableSSL = getBool(opt, wxT("Enable SSL encryption"), m_bEnableSSL);
1397                         m_bEnableUSBIP = getBool(opt, wxT("Enable USBIP"), m_bEnableUSBIP);
1398                         // Enable response time optimizations false
1399                         m_sProxyCommand = getString(opt, wxT("Proxy command"), m_sProxyCommand);
1400                         m_sProxyHost = getString(opt, wxT("HTTP proxy host"), m_sProxyHost);
1401                         m_iProxyPort = getLong(opt, wxT("HTTP proxy port"), m_iProxyPort);
1402                         m_sProxyUser = getString(opt, wxT("HTTP proxy username"), m_sProxyUser);
1403                         m_bProxyPassRemember = getBool(opt, wxT("Remember HTTP proxy password"), m_bProxyPassRemember);
1404                         if (m_bProxyPassRemember)
1405                             m_sProxyPass = getPassword(opt, wxT("HTTP proxy password"), m_sProxyPass);
1406                         else
1407                             m_sProxyPass = wxEmptyString;
1408                         // Restore cache true
1409                         // StreamCompression ""
1410 
1411                         opt = opt->GetNext();
1412                     }
1413                     cfgnode = cfgnode->GetNext();
1414                     continue;
1415                 }
1416 
1417                 // Tab "Environment"
1418                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("Environment")) {
1419                     wxXmlNode *opt = cfgnode->GetChildren();
1420                     while (opt) {
1421                         m_sCupsPath = getString(opt, wxT("CUPSD path"), m_sCupsPath);
1422                         opt = opt->GetNext();
1423                     }
1424                     cfgnode = cfgnode->GetNext();
1425                     continue;
1426                 }
1427 
1428                 // Tab "General"
1429                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("General")) {
1430                     wxXmlNode *opt = cfgnode->GetChildren();
1431                     while (opt) {
1432 
1433                         // Automatic reconnect true
1434                         m_sCommandLine = getString(opt, wxT("Command line"), m_sCommandLine);
1435                         tmp = getString(opt,
1436                                 wxT("Custom Unix Desktop"), wxEmptyString);
1437                         if (!tmp.IsEmpty()) {
1438                             if (tmp.CmpNoCase(wxT("application")) == 0) {
1439                                 m_bRunConsole = false;
1440                                 m_bRunXclients = false;
1441                             }
1442                             if (tmp.CmpNoCase(wxT("console")) == 0) {
1443                                 m_bRunConsole = true;
1444                                 m_bRunXclients = false;
1445                             }
1446                             if (tmp.CmpNoCase(wxT("default")) == 0) {
1447                                 m_bRunConsole = false;
1448                                 m_bRunXclients = true;
1449                             }
1450                         }
1451                         tmp = getString(opt, wxT("Desktop"));
1452                         if (tmp.CmpNoCase(wxT("RDP")) == 0)
1453                             m_eDesktopType = DTYPE_RDP;
1454                         if (tmp.CmpNoCase(wxT("RFB")) == 0)
1455                             m_eDesktopType = DTYPE_RFB;
1456                         if (tmp.CmpNoCase(wxT("KDE")) == 0)
1457                             m_eDesktopType = DTYPE_KDE;
1458                         if (tmp.CmpNoCase(wxT("Gnome")) == 0)
1459                             m_eDesktopType = DTYPE_GNOME;
1460                         if (tmp.CmpNoCase(wxT("CDE")) == 0)
1461                             m_eDesktopType = DTYPE_CDE;
1462                         if (tmp.CmpNoCase(wxT("XFCE")) == 0)
1463                             m_eDesktopType = DTYPE_XFCE;
1464                         if (tmp.CmpNoCase(wxT("XDM")) == 0)
1465                             m_eDesktopType = DTYPE_XDM;
1466                         if (tmp.CmpNoCase(wxT("Console")) == 0)
1467                             m_eDesktopType = DTYPE_CUSTOM;
1468                         m_bDisableShmem = getBool(opt, wxT("Disable SHM"), m_bDisableShmem);
1469                         m_bDisableShpix = getBool(opt, wxT("Disable emulate shared pixmaps"), m_bDisableShpix);
1470                         tmp = getString(opt, wxT("Link speed"));
1471                         if (tmp == wxT("modem"))
1472                             m_eConnectionSpeed = SPEED_MODEM;
1473                         if (tmp == wxT("isdn"))
1474                             m_eConnectionSpeed = SPEED_ISDN;
1475                         if (tmp == wxT("adsl"))
1476                             m_eConnectionSpeed = SPEED_ADSL;
1477                         if (tmp == wxT("wan"))
1478                             m_eConnectionSpeed = SPEED_WAN;
1479                         if (tmp == wxT("lan"))
1480                             m_eConnectionSpeed = SPEED_LAN;
1481 
1482                         m_bRememberPassword = getBool(opt, wxT("Remember password"),
1483                                 m_bRememberPassword);
1484 
1485                         tmp = getString(opt, wxT("Resolution"));
1486                         if (!tmp.IsEmpty())
1487                             m_eDisplayType = DPTYPE_CUSTOM;
1488                         if (tmp == wxT("640x480"))
1489                             m_eDisplayType = DPTYPE_640x480;
1490                         if (tmp == wxT("800x600"))
1491                             m_eDisplayType = DPTYPE_800x600;
1492                         if (tmp == wxT("1024x768"))
1493                             m_eDisplayType = DPTYPE_1024x768;
1494                         if (tmp == wxT("available"))
1495                             m_eDisplayType = DPTYPE_AVAILABLE;
1496                         if (tmp == wxT("fullscreen"))
1497                             m_eDisplayType = DPTYPE_FULLSCREEN;
1498                         if (tmp == wxT("remote"))
1499                             m_eDisplayType = DPTYPE_REMOTE;
1500 
1501                         m_iDisplayHeight = getLong(opt, wxT("Resolution height"),
1502                                 m_iDisplayHeight);
1503                         m_iDisplayWidth = getLong(opt, wxT("Resolution width"),
1504                                 m_iDisplayWidth);
1505                         m_sServerHost = getString(opt, wxT("Server host"), m_sServerHost);
1506                         m_iServerPort = getLong(opt, wxT("Server port"), m_iServerPort);
1507 
1508                         tmp = getString(opt, wxT("Session"));
1509                         if (tmp.CmpNoCase(wxT("application")) == 0) {
1510                             m_eSessionType = STYPE_UNIX;
1511                             m_bValid = true;
1512                         }
1513                         if (tmp.CmpNoCase(wxT("unix")) == 0) {
1514                             m_eSessionType = STYPE_UNIX;
1515                             m_bValid = true;
1516                         }
1517                         if (tmp.CmpNoCase(wxT("windows")) == 0) {
1518                             m_eSessionType = STYPE_WINDOWS;
1519                             m_bValid = true;
1520                         }
1521                         if (tmp.CmpNoCase(wxT("vnc")) == 0) {
1522                             m_eSessionType = STYPE_VNC;
1523                             m_bValid = true;
1524                         }
1525                         if (tmp.CmpNoCase(wxT("shadow")) == 0) {
1526                             m_eSessionType = STYPE_SHADOW;
1527                             m_bValid = true;
1528                         }
1529                         // this is 0/1 in NX but getBool can handle that
1530                         m_bUseCustomImageEncoding = getBool(opt,
1531                                 wxT("Use default image encoding"), m_bUseCustomImageEncoding);
1532                         m_bDisableRender = !getBool(opt, wxT("Use render"), !m_bDisableRender);
1533                         m_bUseSmartCard = getBool(opt, wxT("Use smartcard"), m_bUseSmartCard);
1534                         m_bDisableTaint = !getBool(opt, wxT("Use taint"), !m_bDisableTaint);
1535                         m_bVirtualDesktop = getBool(opt, wxT("Virtual desktop"),
1536                                 m_bVirtualDesktop);
1537                         m_bDisableXagent = !getBool(opt, wxT("XAgent encoding"),
1538                                 !m_bDisableXagent);
1539                         // displaySaveOnExit  = true
1540 
1541                         tmp = getString(opt, wxT("xdm mode"));
1542                         if (tmp.CmpNoCase(wxT("server decide")) == 0) {
1543                             m_eXdmMode = XDM_MODE_SERVER;
1544                         }
1545                         if (tmp.CmpNoCase(wxT("server_decide")) == 0) {
1546                             m_eXdmMode = XDM_MODE_SERVER;
1547                         }
1548                         if (tmp.CmpNoCase(wxT("query")) == 0) {
1549                             m_eXdmMode = XDM_MODE_QUERY;
1550                         }
1551                         if (tmp.CmpNoCase(wxT("broadcast")) == 0) {
1552                             m_eXdmMode = XDM_MODE_BROADCAST;
1553                         }
1554                         if (tmp.CmpNoCase(wxT("list")) == 0) {
1555                             m_eXdmMode = XDM_MODE_LIST;
1556                         }
1557                         m_sXdmListHost = getString(opt, wxT("xdm list host"), m_sXdmListHost);
1558                         m_sXdmQueryHost = getString(opt, wxT("xdm query host"), m_sXdmQueryHost);
1559                         m_iXdmBroadcastPort = getLong(opt, wxT("xdm broadcast port"), m_iXdmBroadcastPort);
1560                         m_iXdmListPort = getLong(opt, wxT("xdm list port"), m_iXdmListPort);
1561                         m_iXdmQueryPort = getLong(opt, wxT("xdm query port"), m_iXdmQueryPort);
1562 
1563                         opt = opt->GetNext();
1564                     }
1565                     cfgnode = cfgnode->GetNext();
1566                     continue;
1567                 }
1568 
1569                 // Sub-Dialog Custom image compresion
1570                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("Images")) {
1571                     // First, determine, if we have an old (pre 0.16.173) config file
1572                     wxXmlNode *opt = cfgnode->GetChildren();
1573                     m_bOldConfig = false;
1574                     while (opt) {
1575                         wxString key = opt->GetPropVal(wxT("key"), wxEmptyString);
1576                         if (key == wxT("Windows Image Compression")) {
1577                             m_bOldConfig = true;
1578                             break;
1579                         }
1580                         opt = opt->GetNext();
1581                     }
1582                     opt = cfgnode->GetChildren();
1583                     while (opt) {
1584                         m_bDisableBackingstore = getBool(opt, wxT("Disable backingstore"),
1585                                 m_bDisableBackingstore);
1586                         m_bDisableComposite = getBool(opt, wxT("Disable coposite"),
1587                                 m_bDisableComposite);
1588 
1589                         m_iImageEncoding = getLong(opt, wxT("Image Compression Type"), m_iImageEncoding);
1590                         m_iJpegQuality = getLong(opt, wxT("JPEG Quality"), m_iJpegQuality);
1591                         // RDP optimization for low-bandwidth link = false
1592                         // Reduce colors to = ""
1593                         m_iVncImageEncoding = getLong(opt, wxT("VNC images compression"),
1594                                 m_iVncImageEncoding);
1595                         m_iVncJpegQuality = getLong(opt, wxT("VNC JPEG Quality"), m_iVncJpegQuality);
1596                         m_iRdpImageEncoding = getLong(opt, wxT("RDP Image Encoding"),
1597                                 m_iRdpImageEncoding);
1598                         m_iRdpJpegQuality = getLong(opt, wxT("RDP JPEG Quality"), m_iRdpJpegQuality);
1599                         opt = opt->GetNext();
1600                     }
1601                     if (m_bOldConfig) {
1602                         if (m_bUseCustomImageEncoding) {
1603                             // Convert from old settings format
1604                             switch (m_iImageEncoding) {
1605                                 case 0:
1606                                     m_iImageEncoding = 3;
1607                                     break;
1608                                 case 1:
1609                                     m_iImageEncoding = 4;
1610                                     break;
1611                                 case 2:
1612                                     m_iImageEncoding = 2;
1613                                     break;
1614                             }
1615                             m_iRdpJpegQuality = m_iVncJpegQuality = m_iJpegQuality;
1616 
1617                             opt = cfgnode->GetChildren();
1618                             int oldvncenc = 0;
1619                             int oldrdpenc = 0;
1620                             while (opt) {
1621                                 oldvncenc = getLong(opt, wxT("Image Encoding Type"), oldvncenc);
1622                                 oldrdpenc = getLong(opt, wxT("Windows Image Compression"), oldrdpenc);
1623                                 opt = opt->GetNext();
1624                             }
1625                             m_iVncImageEncoding = (oldvncenc + 1) % 3;
1626                             switch (oldrdpenc) {
1627                                 case 0:
1628                                     m_iRdpImageEncoding = 3;
1629                                     break;
1630                                 case 1:
1631                                     m_iRdpImageEncoding = 1;
1632                                     break;
1633                                 case 2:
1634                                     m_iRdpImageEncoding = 2;
1635                                     break;
1636                                 case 3:
1637                                     m_iRdpImageEncoding = 0;
1638                                     break;
1639                             }
1640                         } else {
1641                             // Custom settings are disabled, so simply set defaults ...
1642                             m_iImageEncoding =  m_iRdpImageEncoding =  m_iVncImageEncoding = 3;
1643                             m_iJpegQuality = m_iRdpJpegQuality = m_iVncJpegQuality = 6;
1644                             // ... and shut up (no need to bother the user)
1645                             m_bOldConfig = false;
1646                         }
1647                     }
1648                     cfgnode = cfgnode->GetNext();
1649                     continue;
1650                 }
1651 
1652                 // Main login params
1653                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("Login")) {
1654                     wxXmlNode *opt = cfgnode->GetChildren();
1655                     while (opt) {
1656                         m_bGuestMode = getBool(opt, wxT("Guest Mode"), m_bGuestMode);
1657                         if (m_bGuestMode && isPush) {
1658                             m_sGuestUser = getString(opt, wxT("User"), m_sGuestUser);
1659                             tmp = getString(opt, wxT("Auth"), wxEmptyString);
1660                             if (!tmp.IsEmpty())
1661                                 m_sGuestPassword = cryptString(tmp);
1662                         } else {
1663                             m_pMd5Password = getStringNew(opt, wxT("Auth"), m_pMd5Password);
1664                             m_sUsername = getString(opt, wxT("User"), m_sUsername);
1665                             m_sGuestPassword = getString(opt, wxT("Guest password"),
1666                                     m_sGuestPassword);
1667                             m_sGuestUser = getString(opt, wxT("Guest username"), m_sGuestUser);
1668                         }
1669                         // Login method = "nx"
1670                         tmp = m_sSshKey;
1671                         m_sSshKey = getString(opt, wxT("Public Key"), m_sSshKey);
1672                         if (tmp != m_sSshKey) {
1673                             if (!m_sSshKey.IsEmpty()) {
1674                                 wxRegEx r(wxT("^(-----BEGIN .SA PRIVATE KEY-----)\\s+(.*)(-----END .SA PRIVATE KEY-----)\\s*$"), wxRE_ADVANCED);
1675                                 if (r.Matches(m_sSshKey)) {
1676                                     tmp = r.GetMatch(m_sSshKey, 2);
1677                                     tmp.Replace(wxT(" "), wxT("\n"));
1678                                     m_sSshKey = r.GetMatch(m_sSshKey, 1) + wxT("\n")
1679                                         + tmp + r.GetMatch(m_sSshKey, 3) + wxT("\n");
1680                                 }
1681                             }
1682                         }
1683                         m_pClrPassword = getStringNew(opt, wxT("Password"), m_pClrPassword);
1684 
1685                         opt = opt->GetNext();
1686                     }
1687                     cfgnode = cfgnode->GetNext();
1688                     continue;
1689                 }
1690 
1691                 // Tab "Services"
1692                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("Services")) {
1693                     wxXmlNode *opt = cfgnode->GetChildren();
1694                     while (opt) {
1695                         m_bEnableMultimedia = getBool(opt, wxT("Audio"), m_bEnableMultimedia);
1696                         m_iCupsPort = getLong(opt, wxT("IPPPort"), m_iCupsPort);
1697                         m_iSmbPort = getLong(opt, wxT("SmbDefaultPort"), m_iSmbPort);
1698                         m_bUseCups = getBool(opt, wxT("IPPPrinting"), m_bUseCups);
1699                         m_bEnableSmbSharing = getBool(opt, wxT("Shares"), m_bEnableSmbSharing);
1700                         opt = opt->GetNext();
1701                     }
1702                     cfgnode = cfgnode->GetNext();
1703                     continue;
1704                 }
1705 
1706                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("VNC Session")) {
1707                     wxXmlNode *opt = cfgnode->GetChildren();
1708                     while (opt) {
1709                         tmp = getString(opt, wxT("Display"));
1710                         if (tmp.Left(1) == wxT(":")) {
1711                             tmp = tmp.Mid(1);
1712                             if (tmp.IsNumber()) {
1713                                 long l;
1714                                 tmp.ToLong(&l, 0);
1715                                 m_iVncDisplayNumber = l;
1716                             }
1717                         }
1718                         m_sVncPassword = getPassword(opt, wxT("Password"), m_sVncPassword);
1719                         m_bVncRememberPassword = getBool(opt, wxT("Remember"),
1720                                 m_bVncRememberPassword);
1721                         m_sVncHostName = getString(opt, wxT("Server"), m_sVncHostName);
1722                         opt = opt->GetNext();
1723                     }
1724                     cfgnode = cfgnode->GetNext();
1725                     continue;
1726                 }
1727 
1728                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("Windows Session")) {
1729                     wxXmlNode *opt = cfgnode->GetChildren();
1730                     while (opt) {
1731                         m_sRdpApplication = getString(opt, wxT("Application"),
1732                                 m_sRdpApplication);
1733                         m_iRdpAuthType = getLong(opt, wxT("Authentication"), m_iRdpAuthType);
1734                         itmp = -1;
1735                         switch (getLong(opt, wxT("Color Depth"), itmp)) {
1736                             case 8:
1737                                 m_iRdpColors = 0;
1738                                 break;
1739                             case 15:
1740                                 m_iRdpColors = 1;
1741                                 break;
1742                             case 16:
1743                                 m_iRdpColors = 2;
1744                                 break;
1745                             case 24:
1746                                 m_iRdpColors = 3;
1747                                 break;
1748                         }
1749                         m_sRdpDomain = getString(opt, wxT("Domain"), m_sRdpDomain);
1750                         m_bRdpCache = getBool(opt, wxT("Image Cache"), m_bRdpCache);
1751                         m_sRdpPassword = getPassword(opt, wxT("Password"), m_sRdpPassword);
1752                         m_bRdpRememberPassword = getBool(opt, wxT("Remember"),
1753                                 m_bRdpRememberPassword);
1754                         m_bRdpRunApplication = getBool(opt, wxT("Run application"),
1755                                 m_bRdpRunApplication);
1756                         m_sRdpHostName = getString(opt, wxT("Server"), m_sRdpHostName);
1757                         m_sRdpUsername = getString(opt, wxT("User"), m_sRdpUsername);
1758                         opt = opt->GetNext();
1759                     }
1760                     cfgnode = cfgnode->GetNext();
1761                     continue;
1762                 }
1763 
1764                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString) == wxT("share chosen")) {
1765                     wxXmlNode *opt = cfgnode->GetChildren();
1766                     while (opt) {
1767                         wxString key = opt->GetPropVal(wxT("key"), wxEmptyString);
1768                         if (key == wxT("Share number")) {
1769                             m_iUsedShareGroups = getLong(opt, wxT("Share number"),
1770                                     m_iUsedShareGroups);
1771                         } else if (key == wxT("default printer")) {
1772                             // Ignoring this key, because it is set in the share as well.
1773                         } else
1774                             m_aUsedShareGroups.Add(opt->GetPropVal(wxT("value"), wxEmptyString));
1775                         opt = opt->GetNext();
1776                     }
1777                     cfgnode = cfgnode->GetNext();
1778                     continue;
1779                 }
1780 
1781                 // When we reach here, we got an "unknown" group name. This is usually
1782                 // either a mounted share description or an UsbForward entry.
1783                 if (cfgnode->GetPropVal(wxT("name"), wxEmptyString).StartsWith(wxT("UsbForward"))) {
1784                     SharedUsbDevice dev;
1785                     wxXmlNode *opt = cfgnode->GetChildren();
1786                     int optcount = 0;
1787                     while (opt) {
1788                         wxString key = opt->GetPropVal(wxT("key"), wxEmptyString);
1789                         if (key == wxT("Vendor")) {
1790                             optcount++;
1791                             dev.m_sVendor = getString(opt, wxT("Vendor"), wxEmptyString);
1792                             opt = opt->GetNext();
1793                             continue;
1794                         }
1795                         if (key == wxT("Product")) {
1796                             optcount++;
1797                             dev.m_sProduct = getString(opt, wxT("Product"), wxEmptyString);
1798                             opt = opt->GetNext();
1799                             continue;
1800                         }
1801                         if (key == wxT("Serial")) {
1802                             optcount++;
1803                             dev.m_sSerial = getString(opt, wxT("Serial"), wxEmptyString);
1804                             opt = opt->GetNext();
1805                             continue;
1806                         }
1807                         if (key == wxT("VendorID")) {
1808                             optcount++;
1809                             dev.m_iVendorID = getLong(opt, wxT("VendorID"), 0);
1810                             opt = opt->GetNext();
1811                             continue;
1812                         }
1813                         if (key == wxT("ProductID")) {
1814                             optcount++;
1815                             dev.m_iProductID = getLong(opt, wxT("ProductID"), 0);
1816                             opt = opt->GetNext();
1817                             continue;
1818                         }
1819                         if (key == wxT("Class")) {
1820                             optcount++;
1821                             dev.m_iClass = getLong(opt, wxT("Class"), 0);
1822                             opt = opt->GetNext();
1823                             continue;
1824                         }
1825                         if (key == wxT("Mode")) {
1826                             optcount++;
1827                             wxString tmp = getString(opt, wxT("Mode"), wxEmptyString);
1828                             if (tmp.IsSameAs(wxT("local")))
1829                                 dev.m_eMode = SharedUsbDevice::MODE_LOCAL;
1830                             if (tmp.IsSameAs(wxT("remote")))
1831                                 dev.m_eMode = SharedUsbDevice::MODE_REMOTE;
1832                             opt = opt->GetNext();
1833                             continue;
1834                         }
1835                         opt = opt->GetNext();
1836                     }
1837                     if ((7 == optcount) && (dev.m_eMode != SharedUsbDevice::MODE_UNKNOWN))
1838                         m_aUsbForwards.Add(dev);
1839                     cfgnode = cfgnode->GetNext();
1840                     continue;
1841                 }
1842 
1843                 // When we reach here, we got an "unknown" group name. This is usually
1844                 // a mounted share description.
1845                 {
1846                     int shareOptions = 0;
1847                     ShareGroup s;
1848                     s.m_sGroupName = cfgnode->GetPropVal(wxT("name"), wxEmptyString);
1849                     s.m_eType = SharedResource::SHARE_UNKNOWN;
1850                     wxXmlNode *opt = cfgnode->GetChildren();
1851                     while (opt) {
1852                         wxString key = opt->GetPropVal(wxT("key"), wxEmptyString);
1853                         if (key == wxT("Alias")) {
1854                             shareOptions++;
1855                             s.m_sAlias = getString(opt, wxT("Alias"), wxEmptyString);
1856                         }
1857                         if (key == wxT("Default")) {
1858                             shareOptions++;
1859                             s.m_bDefault = getBool(opt, wxT("Default"), false);
1860                         }
1861                         if (key == wxT("Driver")) {
1862                             shareOptions++;
1863                             s.m_sDriver = getString(opt, wxT("Driver"), wxEmptyString);
1864                         }
1865                         if (key == wxT("Password")) {
1866                             shareOptions++;
1867                             s.m_sPassword = getPassword(opt, wxT("Password"), wxEmptyString);
1868                         }
1869                         if (key == wxT("Public")) {
1870                             shareOptions++;
1871                             s.m_bPublic = getBool(opt, wxT("Public"), false);
1872                         }
1873                         if (key == wxT("Sharename")) {
1874                             shareOptions++;
1875                             s.m_sShareName = getString(opt, wxT("Sharename"), wxEmptyString);
1876                         }
1877                         if (key == wxT("Type")) {
1878                             shareOptions++;
1879                             wxString tmp = getString(opt, wxT("Type"), wxEmptyString);
1880                             if (tmp.CmpNoCase(wxT("cupsprinter")) == 0)
1881                                 s.m_eType = SharedResource::SHARE_CUPS_PRINTER;
1882                             if (tmp.CmpNoCase(wxT("disk")) == 0)
1883                                 s.m_eType = SharedResource::SHARE_SMB_DISK;
1884                             if (tmp.CmpNoCase(wxT("smbprinter")) == 0)
1885                                 s.m_eType = SharedResource::SHARE_SMB_PRINTER;
1886                         }
1887                         if (key == wxT("Username")) {
1888                             shareOptions++;
1889                             s.m_sUsername = getString(opt, wxT("Username"), wxEmptyString);
1890                         }
1891                         opt = opt->GetNext();
1892                     }
1893                     if (shareOptions >= 5)
1894                         m_aShareGroups.Add(s);
1895                 }
1896 
1897             }
1898             cfgnode = cfgnode->GetNext();
1899         }
1900     }
1901     if (m_bValid) {
1902         if (m_pMd5Password) {
1903             m_sPassword = DUMMY_MD5_PASSWORD;
1904         } else if (m_pClrPassword) {
1905             m_sPassword = DUMMY_CLR_PASSWORD;
1906         }
1907         if (STYPE_SHADOW == m_eSessionType)
1908             m_eDesktopType = DTYPE_ANY;
1909     } else {
1910         m_sUsername = wxEmptyString;
1911         m_sPassword = wxEmptyString;
1912     }
1913     return m_bValid;
1914 }
1915 
1916     wxString
sGetSessionUser()1917 MyXmlConfig::sGetSessionUser()
1918 {
1919     if (m_bGuestMode) {
1920         if (m_sGuestUser.IsEmpty())
1921             return wxT("NX guest user");
1922         else
1923             return m_sGuestUser;
1924     } else
1925         return m_sUsername;
1926 }
1927 
1928     wxString
sGetSessionPassword()1929 MyXmlConfig::sGetSessionPassword()
1930 {
1931     wxString ret;
1932     if (m_bGuestMode) {
1933         ret = decryptString(m_sGuestPassword);
1934     } else {
1935         if ((m_sPassword == DUMMY_MD5_PASSWORD) && m_pMd5Password)
1936             ret = decryptString(*m_pMd5Password);
1937         else
1938             ret = m_sPassword;
1939     }
1940     return ret;
1941 }
1942 
1943     void
sSetUsername(const wxString & s)1944 MyXmlConfig::sSetUsername(const wxString &s)
1945 {
1946     bool b;
1947     wxConfigBase::Get()->Read(wxT("Config/LowercaseLogin"), &b, false);
1948     if (b) {
1949         m_sUsername = s.Lower();
1950     } else {
1951         m_sUsername = s;
1952     }
1953 }
1954 
1955     void
bAddOption(wxXmlNode * group,const wxString & name,const bool val)1956 MyXmlConfig::bAddOption(wxXmlNode *group, const wxString &name, const bool val)
1957 {
1958     wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("option"));
1959     n->AddProperty(new wxXmlProperty(wxT("key"), name, NULL));
1960     n->AddProperty(new wxXmlProperty(wxT("value"), val ? wxT("true") : wxT("false"), NULL));
1961     group->AddChild(n);
1962 }
1963 
1964     void
iAddOptionBool(wxXmlNode * group,const wxString & name,const bool val)1965 MyXmlConfig::iAddOptionBool(wxXmlNode *group, const wxString &name, const bool val)
1966 {
1967     wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("option"));
1968     n->AddProperty(new wxXmlProperty(wxT("key"), name, NULL));
1969     n->AddProperty(new wxXmlProperty(wxT("value"), wxString::Format(wxT("%d"), val ? 1 : 0), NULL));
1970     group->AddChild(n);
1971 }
1972 
1973     void
iAddOption(wxXmlNode * group,const wxString & name,const long val)1974 MyXmlConfig::iAddOption(wxXmlNode *group, const wxString &name, const long val)
1975 {
1976     wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("option"));
1977     n->AddProperty(new wxXmlProperty(wxT("key"), name, NULL));
1978     n->AddProperty(new wxXmlProperty(wxT("value"), wxString::Format(wxT("%d"), val), NULL));
1979     group->AddChild(n);
1980 }
1981 
1982     void
sAddOption(wxXmlNode * group,const wxString & name,const wxString & val)1983 MyXmlConfig::sAddOption(wxXmlNode *group, const wxString &name, const wxString &val)
1984 {
1985     wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("option"));
1986     n->AddProperty(new wxXmlProperty(wxT("key"), name, NULL));
1987     n->AddProperty(new wxXmlProperty(wxT("value"), val, NULL));
1988     group->AddChild(n);
1989 }
1990 
1991     wxXmlNode *
AddGroup(wxXmlNode * parent,const wxString & name)1992 MyXmlConfig::AddGroup(wxXmlNode *parent, const wxString &name)
1993 {
1994     wxXmlNode *n = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("group"));
1995     n->AddProperty(new wxXmlProperty(wxT("name"), name, NULL));
1996     parent->AddChild(n);
1997     return n;
1998 }
1999 
2000     bool
SaveToFile()2001 MyXmlConfig::SaveToFile()
2002 {
2003     wxXmlDocument cfg;
2004     wxXmlNode *r;
2005     wxXmlNode *g;
2006     wxString optval;
2007     size_t i;
2008 
2009     if (m_sFileName.StartsWith(wxT("http://"))
2010             || m_sFileName.StartsWith(wxT("https://"))
2011             || m_sFileName.StartsWith(wxT("ftp://"))
2012        )
2013         return false;
2014     r = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("NXClientSettings"));
2015     r->AddProperty(new wxXmlProperty(wxT("application"), wxT("nxclient"), NULL));
2016     r->AddProperty(new wxXmlProperty(wxT("version"), wxT("1.3"), NULL));
2017     cfg.SetRoot(r);
2018 
2019     // SessionProperties, Tab "General"
2020     g = AddGroup(r, wxT("General"));
2021     bAddOption(g, wxT("Automatic reconnect"), true); // Not (yet?) configurable
2022     sAddOption(g, wxT("Command line"), m_sCommandLine);
2023     optval = wxT("application");
2024     if (m_bRunConsole)
2025         optval = wxT("console");
2026     if (m_bRunXclients)
2027         optval = wxT("default");
2028     sAddOption(g, wxT("Custom Unix Desktop"), optval);
2029     switch (m_eDesktopType) {
2030         case DTYPE_ANY:
2031             optval = wxT("any");
2032             break;
2033         case DTYPE_RDP:
2034             optval = wxT("rdp");
2035             break;
2036         case DTYPE_RFB:
2037             optval = wxT("rfb");
2038             break;
2039         case DTYPE_KDE:
2040             optval = wxT("kde");
2041             break;
2042         case DTYPE_GNOME:
2043             optval = wxT("gnome");
2044             break;
2045         case DTYPE_CDE:
2046             optval = wxT("cde");
2047             break;
2048         case DTYPE_XFCE:
2049             optval = wxT("xfce");
2050             break;
2051         case DTYPE_XDM:
2052             optval = wxT("xdm");
2053             break;
2054         case DTYPE_CUSTOM:
2055             optval = wxT("console");
2056             break;
2057     }
2058     sAddOption(g, wxT("Desktop"), optval);
2059     bAddOption(g, wxT("Disable SHM"), m_bDisableShmem); // Not in original GUI but in config ?!
2060     bAddOption(g, wxT("Disable emulate shared pixmaps"), m_bDisableShpix); // Not in original GUI but in config ?!
2061     switch (m_eConnectionSpeed) {
2062         case SPEED_MODEM:
2063             optval = wxT("modem");
2064             break;
2065         case SPEED_ISDN:
2066             optval = wxT("isdn");
2067             break;
2068         case SPEED_ADSL:
2069             optval = wxT("adsl");
2070             break;
2071         case SPEED_WAN:
2072             optval = wxT("wan");
2073             break;
2074         case SPEED_LAN:
2075             optval = wxT("lan");
2076             break;
2077     }
2078     sAddOption(g, wxT("Link speed"), optval);
2079     bAddOption(g, wxT("Remember password"), m_bRememberPassword);
2080     switch (m_eDisplayType) {
2081         case DPTYPE_CUSTOM:
2082             optval = wxString::Format(wxT("%dx%d"),
2083                     m_iDisplayWidth, m_iDisplayHeight);
2084             break;
2085         case DPTYPE_640x480:
2086             optval = wxT("640x480");
2087             break;
2088         case DPTYPE_800x600:
2089             optval = wxT("800x600");
2090             break;
2091         case DPTYPE_1024x768:
2092             optval = wxT("1024x768");
2093             break;
2094         case DPTYPE_AVAILABLE:
2095             optval = wxT("available");
2096             break;
2097         case DPTYPE_FULLSCREEN:
2098             optval = wxT("fullscreen");
2099             break;
2100         case DPTYPE_REMOTE:
2101             optval = wxT("remote");
2102             break;
2103     }
2104     sAddOption(g, wxT("Resolution"), optval);
2105     iAddOption(g, wxT("Resolution height"), m_iDisplayHeight);
2106     iAddOption(g, wxT("Resolution width"), m_iDisplayWidth);
2107     sAddOption(g, wxT("Server host"), m_sServerHost);
2108     iAddOption(g, wxT("Server port"), m_iServerPort);
2109     switch (m_eSessionType) {
2110         case STYPE_UNIX:
2111             optval = wxT("unix");
2112             break;
2113         case STYPE_WINDOWS:
2114             optval = wxT("windows");
2115             break;
2116         case STYPE_VNC:
2117             optval = wxT("vnc");
2118             break;
2119         case STYPE_SHADOW:
2120             optval = wxT("shadow");
2121             break;
2122     }
2123     sAddOption(g, wxT("Session"), optval);
2124     iAddOption(g, wxT("Use default image encoding"), m_bUseCustomImageEncoding);
2125     bAddOption(g, wxT("Use render"), !m_bDisableRender);
2126     bAddOption(g, wxT("Use taint"), !m_bDisableTaint);
2127     bAddOption(g, wxT("Virtual desktop"), m_bVirtualDesktop);
2128     bAddOption(g, wxT("XAgent encoding"), !m_bDisableXagent);
2129     bAddOption(g, wxT("displaySaveOnExit"), true); // Not in original GUI but in config ?!
2130     iAddOption(g, wxT("xdm broadcast port"), m_iXdmBroadcastPort);
2131     sAddOption(g, wxT("xdm list host"), m_sXdmListHost);
2132     iAddOption(g, wxT("xdm list port"), m_iXdmListPort);
2133     switch (m_eXdmMode) {
2134         case XDM_MODE_SERVER:
2135             optval = wxT("server decide");
2136             break;
2137         case XDM_MODE_QUERY:
2138             optval = wxT("query");
2139             break;
2140         case XDM_MODE_BROADCAST:
2141             optval = wxT("broadcast");
2142             break;
2143         case XDM_MODE_LIST:
2144             optval = wxT("list");
2145             break;
2146     }
2147     sAddOption(g, wxT("xdm mode"), optval);
2148     sAddOption(g, wxT("xdm query host"), m_sXdmQueryHost);
2149     iAddOption(g, wxT("xdm query port"), m_iXdmQueryPort);
2150     bAddOption(g, wxT("Use smartcard"), m_bUseSmartCard); // Not in original
2151 
2152     // == UnixImageSettingsDialog, RdpImageSettingsDialog, VncImageSettingsDialog
2153     g = AddGroup(r, wxT("Images"));
2154 
2155     // deprecated but written by NX client, m_bDisableJpeg
2156     iAddOption(g, wxT("Disable JPEG Compression"), 0);
2157 
2158     // deprecated but written by NX client, m_bDisableImageCompression
2159     bAddOption(g, wxT("Disable all image optimisations"), false);
2160 
2161     bAddOption(g, wxT("Disable backingstore"), m_bDisableBackingstore);
2162     bAddOption(g, wxT("Disable coposite"), m_bDisableComposite);
2163 
2164     // deprecated bAddOption(g, wxT("Disable image streaming"), m_bDisableStreaming);
2165 
2166     iAddOption(g, wxT("Image Compression Type"), m_iImageEncoding);
2167 
2168     // deprecated but written by NX client
2169     iAddOption(g, wxT("Image Encoding Type"), 0);
2170 
2171     // deprecated but written by NX client, m_bUseTightJpeg
2172     bAddOption(g, wxT("Image JPEG Encoding"), false);
2173 
2174     iAddOption(g, wxT("JPEG Quality"), m_iJpegQuality);
2175     iAddOption(g, wxT("RDP Image Encoding"), m_iRdpImageEncoding);
2176     iAddOption(g, wxT("RDP JPEG Quality"), m_iRdpJpegQuality);
2177 
2178     // Written by NX client, unknown purpose
2179     bAddOption(g, wxT("RDP optimization for low-bandwidth link"), false);
2180 
2181     // Written by NX client, unknown purpose
2182     sAddOption(g, wxT("Reduce colors to"), wxEmptyString);
2183 
2184     // deprecated but written by NX client, m_bImageEncodingPNG
2185     bAddOption(g, wxT("Use PNG Compression"), true);
2186 
2187     iAddOption(g, wxT("VNC images compression"), m_iVncImageEncoding);
2188     iAddOption(g, wxT("VNC JPEG Quality"), m_iVncJpegQuality);
2189 
2190     // deprecated - If this exists, we consider it an "old" config file during read
2191     // iAddOption(g, wxT("Windows Image Compression"), m_iRdpImageCompression);
2192 
2193     g = AddGroup(r, wxT("Login"));
2194     if (m_bRememberPassword) {
2195         if ((m_sPassword != DUMMY_MD5_PASSWORD) &&
2196                 (m_sPassword != DUMMY_CLR_PASSWORD)   ) {
2197             optval = cryptString(m_sPassword);
2198             sAddOption(g, wxT("Auth"), optval);
2199         } else {
2200             if (m_pMd5Password)
2201                 sAddOption(g, wxT("Auth"), *m_pMd5Password);
2202             if (m_pClrPassword)
2203                 sAddOption(g, wxT("Password"), *m_pClrPassword);
2204         }
2205     } else {
2206         optval = wxEmptyString;
2207         sAddOption(g, wxT("Auth"), optval);
2208         sAddOption(g, wxT("Password"), optval);
2209     }
2210     bAddOption(g, wxT("Guest Mode"), m_bGuestMode);
2211     sAddOption(g, wxT("Guest password"), m_sGuestPassword);
2212     sAddOption(g, wxT("Guest username"), m_sGuestUser);
2213     sAddOption(g, wxT("Login Method"), wxT("nx"));
2214     sAddOption(g, wxT("Public Key"), m_sSshKey);
2215     sAddOption(g, wxT("User"), m_sUsername);
2216 
2217     g = AddGroup(r, wxT("Environment"));
2218     sAddOption(g, wxT("CUPSD path"), m_sCupsPath);
2219 
2220     g = AddGroup(r, wxT("Services"));
2221     bAddOption(g, wxT("Audio"), m_bEnableMultimedia);
2222     bAddOption(g, wxT("Shares"), m_bEnableSmbSharing);
2223     bAddOption(g, wxT("IPPPrinting"), m_bUseCups);
2224     iAddOption(g, wxT("IPPPort"), m_iCupsPort);
2225     iAddOption(g, wxT("SmbDefaultPort"), m_iSmbPort);
2226 
2227     if (m_aUsedShareGroups.GetCount()) {
2228         g = AddGroup(r, wxT("share chosen"));
2229         iAddOption(g, wxT("Share number"), m_iUsedShareGroups);
2230         wxString sDefaultPrinter = wxEmptyString;
2231         for (i = 0; i < m_aUsedShareGroups.GetCount(); i++) {
2232             optval = wxString::Format(wxT("Share%d"), i);
2233             sAddOption(g, optval, m_aUsedShareGroups[i]);
2234             switch (findShare(optval).m_eType) {
2235                 case SharedResource::SHARE_UNKNOWN:
2236                 case SharedResource::SHARE_SMB_DISK:
2237                     break;
2238                 case SharedResource::SHARE_CUPS_PRINTER:
2239                 case SharedResource::SHARE_SMB_PRINTER:
2240                     if (findShare(optval).m_bDefault)
2241                         sDefaultPrinter = optval;
2242             }
2243         }
2244         if (!sDefaultPrinter.IsEmpty())
2245             sAddOption(g, wxT("default printer"), sDefaultPrinter);
2246     }
2247 
2248     g = AddGroup(r, wxT("Advanced"));
2249     switch (m_eCacheMemory) {
2250         case CACHEMEM_0MB:
2251             optval = wxT("0");
2252             break;
2253         case CACHEMEM_1MB:
2254             optval = wxT("1");
2255             break;
2256         case CACHEMEM_2MB:
2257             optval = wxT("2");
2258             break;
2259         case CACHEMEM_4MB:
2260             optval = wxT("4");
2261             break;
2262         case CACHEMEM_8MB:
2263             optval = wxT("8");
2264             break;
2265         case CACHEMEM_16MB:
2266             optval = wxT("16");
2267             break;
2268         case CACHEMEM_32MB:
2269             optval = wxT("32");
2270             break;
2271         case CACHEMEM_64MB:
2272             optval = wxT("64");
2273             break;
2274         case CACHEMEM_128MB:
2275             optval = wxT("128");
2276             break;
2277     }
2278     sAddOption(g, wxT("Cache size"), optval);
2279     switch (m_eCacheDisk) {
2280         case CACHEDISK_0MB:
2281             optval = wxT("0");
2282             break;
2283         case CACHEDISK_4MB:
2284             optval = wxT("4");
2285             break;
2286         case CACHEDISK_8MB:
2287             optval = wxT("8");
2288             break;
2289         case CACHEDISK_16MB:
2290             optval = wxT("16");
2291             break;
2292         case CACHEDISK_32MB:
2293             optval = wxT("32");
2294             break;
2295         case CACHEDISK_64MB:
2296             optval = wxT("64");
2297             break;
2298         case CACHEDISK_128MB:
2299             optval = wxT("128");
2300             break;
2301         case CACHEDISK_256MB:
2302             optval = wxT("256");
2303             break;
2304         case CACHEDISK_512MB:
2305             optval = wxT("512");
2306             break;
2307     }
2308     sAddOption(g, wxT("Cache size on disk"), optval);
2309     bAddOption(g, wxT("Current keyboard"), !m_bKbdLayoutOther);
2310     sAddOption(g, wxT("Custom keyboard layout"), m_sKbdLayoutLanguage);
2311     bAddOption(g, wxT("Disable TCP no-delay"), m_bDisableTcpNoDelay);
2312     bAddOption(g, wxT("Disable ZLIB stream compression"), m_bDisableZlibCompression);
2313     bAddOption(g, wxT("Enable SSL encryption"), m_bEnableSSL);
2314     switch (m_iClipFilter) {
2315         case 0:
2316             optval = wxT("primary");
2317             break;
2318         case 1:
2319             optval = wxT("clipboard");
2320             break;
2321         default:
2322             optval = wxT("both");
2323             break;
2324     }
2325     sAddOption(g, wxT("Clipboard filter"), optval);
2326     bAddOption(g, wxT("Enable HTTP proxy"), m_bUseProxy);
2327     bAddOption(g, wxT("Enable external proxy"), m_bExternalProxy);
2328     bAddOption(g, wxT("Enable USBIP"), m_bEnableUSBIP);
2329     bAddOption(g, wxT("Enable response time optimisations"), false); // ???
2330     bAddOption(g, wxT("Grab keyboard"), m_bGrabKeyboard);
2331     bAddOption(g, wxT("Disable DirectDraw"), m_bDisableDirectDraw);
2332     bAddOption(g, wxT("Disable deferred updates"), m_bDisableDeferredUpdates);
2333     sAddOption(g, wxT("Proxy command"), m_sProxyCommand);
2334     sAddOption(g, wxT("HTTP proxy host"), m_sProxyHost);
2335     optval = m_bProxyPassRemember ? encodeString(m_sProxyPass) : wxT("");
2336     sAddOption(g, wxT("HTTP proxy password"), optval);
2337     iAddOption(g, wxT("HTTP proxy port"), m_iProxyPort);
2338     sAddOption(g, wxT("HTTP proxy username"), m_sProxyUser);
2339     bAddOption(g, wxT("Remember HTTP proxy password"), m_bProxyPassRemember);
2340     bAddOption(g, wxT("Restore cache"), true); // ???
2341     sAddOption(g, wxT("StreamCompression"), wxEmptyString); // ???
2342 
2343     g = AddGroup(r, wxT("Windows Session"));
2344     bAddOption(g, wxT("Remember"), m_bRdpRememberPassword);
2345     bAddOption(g, wxT("Run application"), m_bRdpRunApplication);
2346     iAddOption(g, wxT("Authentication"), m_iRdpAuthType);
2347     switch (m_iRdpColors) {
2348         default:
2349             optval = wxT("8");
2350             break;
2351         case 1:
2352             optval = wxT("15");
2353             break;
2354         case 2:
2355             optval = wxT("16");
2356             break;
2357         case 3:
2358             optval = wxT("24");
2359             break;
2360     }
2361     sAddOption(g, wxT("Color Depth"), optval);
2362     sAddOption(g, wxT("Domain"), m_sRdpDomain);
2363     bAddOption(g, wxT("Image Cache"), m_bRdpCache);
2364     sAddOption(g, wxT("Server"), m_sRdpHostName);
2365     sAddOption(g, wxT("User"), m_sRdpUsername);
2366     optval = m_bRdpRememberPassword ? encodeString(m_sRdpPassword) : wxT("");
2367     sAddOption(g, wxT("Password"), optval);
2368     sAddOption(g, wxT("Application"), m_sRdpApplication);
2369 
2370     g = AddGroup(r, wxT("VNC Session"));
2371     bAddOption(g, wxT("Remember"), m_bVncRememberPassword);
2372     sAddOption(g, wxT("Server"), m_sVncHostName);
2373     optval = m_bVncRememberPassword ? encodeString(m_sVncPassword) : wxT("");
2374     sAddOption(g, wxT("Password"), optval);
2375     optval = wxString::Format(wxT(":%d"), m_iVncDisplayNumber);
2376     sAddOption(g, wxT("Display"), optval);
2377 
2378     for (i = 0; i < m_aShareGroups.GetCount(); i++) {
2379         g = AddGroup(r, m_aShareGroups[i].m_sGroupName);
2380         sAddOption(g, wxT("Sharename"), m_aShareGroups[i].m_sShareName);
2381         sAddOption(g, wxT("Username"), m_aShareGroups[i].m_sUsername);
2382         optval = encodeString(m_aShareGroups[i].m_sPassword);
2383         sAddOption(g, wxT("Password"), optval);
2384         switch (m_aShareGroups[i].m_eType) {
2385             case SharedResource::SHARE_UNKNOWN:
2386                 break;
2387             case SharedResource::SHARE_SMB_DISK:
2388                 sAddOption(g, wxT("Alias"), m_aShareGroups[i].m_sAlias);
2389                 sAddOption(g, wxT("Type"), wxT("disk"));
2390                 break;
2391             case SharedResource::SHARE_SMB_PRINTER:
2392                 bAddOption(g, wxT("Default"), m_aShareGroups[i].m_bDefault);
2393                 sAddOption(g, wxT("Driver"), m_aShareGroups[i].m_sDriver);
2394                 bAddOption(g, wxT("Public"), m_aShareGroups[i].m_bPublic);
2395                 sAddOption(g, wxT("Type"), wxT("smbprinter"));
2396                 break;
2397             case SharedResource::SHARE_CUPS_PRINTER:
2398                 bAddOption(g, wxT("Default"), m_aShareGroups[i].m_bDefault);
2399                 sAddOption(g, wxT("Driver"), m_aShareGroups[i].m_sDriver);
2400                 bAddOption(g, wxT("Public"), m_aShareGroups[i].m_bPublic);
2401                 sAddOption(g, wxT("Type"), wxT("cupsprinter"));
2402                 break;
2403         }
2404     }
2405     for (i = 0; i < m_aUsbForwards.GetCount(); i++) {
2406         g = AddGroup(r, wxString::Format(wxT("UsbForward%d"), i));
2407         sAddOption(g, wxT("Vendor"), m_aUsbForwards[i].m_sVendor);
2408         sAddOption(g, wxT("Product"), m_aUsbForwards[i].m_sProduct);
2409         sAddOption(g, wxT("Serial"), m_aUsbForwards[i].m_sSerial);
2410         iAddOption(g, wxT("VendorID"), m_aUsbForwards[i].m_iVendorID);
2411         iAddOption(g, wxT("ProductID"), m_aUsbForwards[i].m_iProductID);
2412         iAddOption(g, wxT("Class"), m_aUsbForwards[i].m_iClass);
2413         switch (m_aUsbForwards[i].m_eMode) {
2414             case SharedUsbDevice::MODE_UNKNOWN:
2415                 sAddOption(g, wxT("Mode"), wxT("unknown"));
2416                 break;
2417             case SharedUsbDevice::MODE_LOCAL:
2418                 sAddOption(g, wxT("Mode"), wxT("local"));
2419                 break;
2420             case SharedUsbDevice::MODE_REMOTE:
2421                 sAddOption(g, wxT("Mode"), wxT("remote"));
2422                 break;
2423         }
2424     }
2425 
2426     // Must write to memory first, to get rid of the standard XML
2427     // doctype header
2428     wxMemoryOutputStream mos;
2429     cfg.Save(mos);
2430     off_t len = mos.TellO();
2431     if (len > 0) {
2432         char *data = new char[len];
2433         mos.CopyTo(data, len);
2434         char *secondline = (char *)memchr(data, '\n', len);
2435         if (secondline++) {
2436             // Replace 1st line with non-standard NXclient doctype
2437             len -= (secondline - data);
2438             ::myLogTrace(MYTRACETAG, wxT("Writing '%s'"), m_sFileName.c_str());
2439             wxFile f;
2440             if (!f.Create(m_sFileName, true, wxS_IRUSR|wxS_IWUSR)) {
2441                 delete data;
2442                 return false;
2443             }
2444             wxFileOutputStream fos(f);
2445             if (!fos.Ok()) {
2446                 delete data;
2447                 return false;
2448             }
2449             // NO wxT() here!!
2450             fos.Write("<!DOCTYPE NXClientSettings>\n", 28);
2451             if (fos.LastWrite() != 28) {
2452                 delete data;
2453                 return false;
2454             }
2455             // Write out rest of file
2456             fos.Write(secondline, len);
2457             if (fos.LastWrite() != (size_t)len) {
2458                 delete data;
2459                 return false;
2460             }
2461         } else {
2462             delete data;
2463             return false;
2464         }
2465         delete data;
2466     }
2467 #ifdef __WXMAC__
2468     wxFileName fn(m_sFileName);
2469     fn.MacSetTypeAndCreator('TEXT', 'OPNX');
2470 #endif
2471     return true;
2472 }
2473 
saveState()2474 void MyXmlConfig::saveState()
2475 {
2476     if (saved)
2477         delete saved;
2478     saved = new MyXmlConfig();
2479     *saved = *this;
2480 }
2481 
checkChanged()2482 bool MyXmlConfig::checkChanged()
2483 {
2484     if (!saved)
2485         return true;
2486     return (!(*this == *saved));
2487 }
2488 
getBool(wxXmlNode * opt,const wxString & key,bool defval)2489 bool MyXmlConfig::getBool(wxXmlNode *opt, const wxString &key, bool defval)
2490 {
2491     bool val = defval;
2492 
2493     if (opt->GetName() == wxT("option")) {
2494         if (opt->GetPropVal(wxT("key"), wxEmptyString) == key) {
2495             wxString tmp = opt->GetPropVal(wxT("value"), wxEmptyString);
2496             if (!tmp.IsEmpty())
2497                 val = ((tmp == STR_TRUE) || (tmp == STR_ONE));
2498         }
2499     }
2500     return val;
2501 }
2502 
getLong(wxXmlNode * opt,const wxString & key,long defval)2503 long MyXmlConfig::getLong(wxXmlNode *opt, const wxString &key, long defval)
2504 {
2505     long val = defval;
2506 
2507     if (opt->GetName() == wxT("option")) {
2508         if (opt->GetPropVal(wxT("key"), wxEmptyString) == key) {
2509             wxString tmp = opt->GetPropVal(wxT("value"), wxEmptyString);
2510             if (tmp.IsNumber())
2511                 tmp.ToLong(&val, 0);
2512         }
2513     }
2514     return val;
2515 }
2516 
getLongBool(wxXmlNode * opt,const wxString & key,bool defval)2517 bool MyXmlConfig::getLongBool(wxXmlNode *opt, const wxString &key, bool defval)
2518 {
2519     long val = defval ? 1 : 0;
2520 
2521     if (opt->GetName() == wxT("option")) {
2522         if (opt->GetPropVal(wxT("key"), wxEmptyString) == key) {
2523             wxString tmp = opt->GetPropVal(wxT("value"), wxEmptyString);
2524             if (tmp.IsNumber())
2525                 tmp.ToLong(&val, 0);
2526         }
2527     }
2528     return (val != 0);
2529 }
2530 
getString(wxXmlNode * opt,const wxString & key,const wxString & defval)2531 wxString MyXmlConfig::getString(wxXmlNode *opt, const wxString &key, const wxString &defval)
2532 {
2533     wxString tmp = defval;
2534 
2535     if (opt->GetName() == wxT("option")) {
2536         if (opt->GetPropVal(wxT("key"), wxEmptyString) == key)
2537             tmp = opt->GetPropVal(wxT("value"), defval);
2538     }
2539     return tmp;
2540 }
2541 
getStringNew(wxXmlNode * opt,const wxString & key,wxString * defval)2542 wxString *MyXmlConfig::getStringNew(wxXmlNode *opt, const wxString &key, wxString *defval)
2543 {
2544     wxString *val = defval;
2545 
2546     if (opt->GetName() == wxT("option")) {
2547         if (opt->GetPropVal(wxT("key"), wxEmptyString) == key) {
2548             if (opt->HasProp(wxT("value"))) {
2549                 val = new wxString(opt->GetPropVal(wxT("value"), defval ? *defval : wxT("")));
2550                 if (val && val->IsEmpty() && (!defval)) {
2551                     delete val;
2552                     val = NULL;
2553                 }
2554                 if (defval)
2555                     delete defval;
2556             }
2557         }
2558     }
2559     return val;
2560 }
2561 
getPassword(wxXmlNode * opt,const wxString & key,const wxString & defval)2562 wxString MyXmlConfig::getPassword(wxXmlNode *opt, const wxString &key, const wxString &defval)
2563 {
2564     wxString val = defval;
2565     wxString *enc = getStringNew(opt, key, NULL);
2566     if (enc && enc->Left(1) == wxT(":") && enc->Right(1) == wxT(":") && enc->Length() > 1) {
2567         int idx = 1;
2568         wxString newpw = wxEmptyString;
2569         enc->Remove(0, 1);
2570         while (enc->Length()) {
2571             int p = enc->Find(wxT(":"));
2572             if (p != -1) {
2573                 long l;
2574                 enc->Left(p).ToLong(&l);
2575                 newpw += wxChar(l - idx++);
2576             } else
2577                 break;
2578             enc->Remove(0, p+1);
2579         }
2580         val = newpw;
2581     }
2582     if (enc)
2583         delete enc;
2584     return val;
2585 }
2586