1 /**************************************************************************
2 *   Copyright (C) 2005-2020 by Oleksandr Shneyder                         *
3 *                              <o.shneyder@phoca-gmbh.de>                 *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 *   This program is distributed in the hope that it will be useful,       *
10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12 *   GNU General Public License for more details.                          *
13 *                                                                         *
14 *   You should have received a copy of the GNU General Public License     *
15 *   along with this program.  If not, see <https://www.gnu.org/licenses/>. *
16 ***************************************************************************/
17 
18 #include "onmainwindow_privat.h"
19 #include "help.h"
20 
21 
22 #include <QStyleFactory>
23 
operator =(const x2goSession & s)24 void x2goSession::operator = ( const x2goSession& s )
25 {
26     agentPid=s.agentPid;
27     clientIp=s.clientIp;
28     cookie=s.cookie;
29     crTime=s.crTime;
30     display=s.display;
31     grPort=s.grPort;
32     server=s.server;
33     sessionId=s.sessionId;
34     sndPort=s.sndPort;
35     fsPort=s.fsPort;
36     status=s.status;
37     sessionType=s.sessionType;
38     command=s.command;
39 }
40 
41 bool	ONMainWindow::portable=false;
42 QString ONMainWindow::homeDir;
43 QString ONMainWindow::sessionCfg;
44 
45 #ifdef Q_OS_WIN
46 QString ONMainWindow::u3Device;
47 #endif
48 
49 bool ONMainWindow::debugging=false;
50 bool ONMainWindow::libssh_debugging = false;
51 bool ONMainWindow::libssh_packetlog = false;
52 
ONMainWindow(QWidget * parent)53 ONMainWindow::ONMainWindow ( QWidget *parent ) :QMainWindow ( parent )
54 {
55     haveTerminal=false;
56 #ifndef Q_OS_WIN
57     QFile fl("/dev/tty");
58     if(fl.open( QIODevice::ReadOnly))
59     {
60         haveTerminal=true;
61         fl.close();
62     }
63 #endif
64 
65 #ifdef Q_OS_UNIX
66     image=shape=0;
67 #endif
68     x2goInfof(1) << tr("Starting X2Go Client %1...").arg (QString (VERSION));
69     debugging = false;
70     libssh_debugging = false;
71     libssh_packetlog = false;
72 
73     setFocusPolicy ( Qt::NoFocus );
74     installTranslator();
75     autoresume=true;
76     cleanAllFiles=false;
77     drawMenu=true;
78     usePGPCard=false;
79     PGPInited=false;
80     extLogin=false;
81     startMaximized=false;
82     startHidden=false;
83     keepTrayIcon=false;
84     hideFolderSharing=false;
85     brokerNoauthWithSessionUsername=false;
86     brokerCredsForSession=false;
87     thinMode=false;
88     closeDisconnect=false;
89     showHaltBtn=false;
90     showBrokerLogoutBtn=false;
91     defaultUseSound=true;
92     defaultSetKbd=true;
93     extStarted=false;
94     cmdAutologin=false;
95     defaultLink=2;
96     defaultFullscreen=false;
97     defaultXinerama=false;
98     acceptRsa=false;
99     cardStarted=false;
100     cardReady=false;
101     shadowSession=false;
102     proxyRunning=false;
103 // 	useSshAgent=false;
104     closeEventSent=false;
105     miniMode=false;
106     embedMode=false;
107     proxyWinEmbedded=false;
108     proxyWinId=0;
109     embedParent=embedChild=0l;
110     defaultSession=false;
111     connTest=false;
112     defaultUser=false;
113     defaultWidth=800;
114     defaultHeight=600;
115     defaultPack="16m-jpeg";
116     defaultQuality=9;
117     defaultLayout<<tr ( "us" );
118     defaultClipboardMode="both";
119     defaultKbdType="auto";
120     defaultCmd="KDE";
121     defaultSshPort=sshPort=clientSshPort="22";
122     LDAPPrintSupport=false;
123     managedMode=false;
124     brokerMode=false;
125     startEmbedded=false;
126     sshConnection=0;
127     sessionStatusDlg=0;
128     noSessionEdit=false;
129     changeBrokerPass=false;
130     resumeAfterSuspending=false;
131     forceToShowTrayicon=false;
132 
133     /* Initialize at least these variables before they get filled via loadSettings()
134      * They have to be initialized as they are used in closeEvent() and closeClient()...
135      */
136     trayIcon=NULL;
137     useLdap=false;
138     trayNoclose=false;
139 
140     appSeparator=0;
141     config.brokerNoAuth=false;
142     config.brokerAutologin=false;
143     config.brokerKrbLogin=false;
144     config.brokerAutologoff=false;
145     config.brokerAuthenticated = false;
146     config.published=false;
147     cmdAutologin=false;
148 #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN)
149     systemDisablePARecord=false;
150     systemDisablePA=false;
151 #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */
152 
153 #ifdef Q_OS_UNIX
154     directRDP = false;
155 #endif /* defined (Q_OS_UNIX) */
156 
157 // Try to determine the native DPI and use it for the default
158     int dpix = QApplication::desktop()->physicalDpiX();
159     int dpiy = QApplication::desktop()->physicalDpiY();
160     if ( dpix >0 && dpiy >0) {
161         defaultSetDPI=true;
162         defaultDPI=(dpix+dpiy)/2;
163     } else {
164         defaultSetDPI=false;
165         defaultDPI=96;
166     }
167 
168 #ifdef Q_OS_WIN
169     clientSshPort="7022";
170     X2goSettings st ( "settings" );
171     winSshdStarted=false;
172 #else
173     sshd=0l;
174 #endif
175 
176     appDir=QApplication::applicationDirPath();
177 
178     homeDir=QDir::homePath();
179 
180 #ifdef Q_OS_WIN
181     xorg=0l;
182     xDisplay=0;
183     x_start_tries_ = 0;
184     x_start_limit_ = 3;
185 #endif
186 
187     if(X2goSettings::centralSettings())
188     {
189         x2goInfof(0)<<"using central configuration";
190         noSessionEdit=true;
191     }
192 
193     cleanAskPass();
194     setWindowTitle ( tr ( "X2Go Client" ) );
195     ld=0;
196     tunnel=0l;
197     sndTunnel=0l;
198     fsTunnel=0l;
199     nxproxy=0l;
200     soundServer=0l;
201     scDaemon=0l;
202     statusLabel=0;
203     gpg=0l;
204     bBrokerLogout = NULL;
205     restartResume=false;
206     isPassShown=true;
207     readExportsFrom=QString::null;
208     spoolTimer=0l;
209     brokerAliveTimer=0l;
210 #ifdef Q_OS_DARWIN
211     modMapTimer = NULL;
212     kbMap = QString ();
213 #endif /* defined(Q_OS_DARWIN) */
214     ldapOnly=false;
215     embedControlChanged=false;
216     statusString=tr ( "connecting" );
217 
218 #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN)
219     pulseManager = NULL;
220     pulseManagerThread = NULL;
221 #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */
222 
223 
224     connectionType=DEFAULT;
225 
226     hide();
227     kdeIconsPath=getKdeIconsPath();
228 
229     addToAppNames ( "WWWBROWSER",tr ( "Internet browser" ) );
230     addToAppNames ( "MAILCLIENT",tr ( "Email client" ) );
231     addToAppNames ( "OFFICE",tr ( "OpenOffice.org" ) );
232     addToAppNames ( "TERMINAL",tr ( "Terminal" ) );
233 
234 #ifndef Q_OS_UNIX
235 #if QT_VERSION < 0x050000
236     widgetExtraStyle = new QPlastiqueStyle ();
237 #else
238     widgetExtraStyle = QStyleFactory::create ("fusion");
239 #endif
240 #endif
241 
242 #ifdef CFGCLIENT
243     QStringList args;
244     if(!X2goSettings::centralSettings())
245         args=QCoreApplication::arguments();
246     else
247     {
248         X2goSettings st ( "settings" );
249         QString cmdLine=st.setting()->value ( "commandline", "" ).toString();
250 //         x2goErrorf(100)<<"cmd line:"<<cmdLine;
251         args=cmdLine.split(";",QString::SkipEmptyParts);
252         args.push_front(QCoreApplication::arguments()[0]);
253     }
254     for ( int i=1; i<args.size(); ++i )
255     {
256         if ( !parseParameter ( args[i] ) )
257         {
258             close();
259             exit ( -1 );
260         }
261     }
262 #endif
263 
264 
265 //set homedir as portable,etc
266 
267 
268 #ifdef Q_OS_WIN
269     QString u3Path=u3DataPath();
270 //we have U3 System
271     if ( u3Path.length() >0 )
272     {
273         portableDataPath=u3Path;
274         ONMainWindow::portable=true;
275         setWindowTitle ( "X2Go Client - U3" );
276     }
277 #endif
278 
279     if ( ONMainWindow::portable )
280     {
281         if ( portableDataPath.length() <=0 )
282             portableDataPath=QDir::currentPath();
283 
284         homeDir=portableDataPath;
285 
286         x2goInfof(2)<<tr("Starting X2Go Client in portable mode. Data directory is: ")<<portableDataPath;
287         QTimer *timer = new QTimer(this);
288         connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckPortableDir()));
289         timer->start(1000);
290     }
291 
292     loadSettings();
293     trayIconActiveConnectionMenu = NULL;
294     trayIconMenu=NULL;
295     trayAutoHidden=false;
296 
297     trayEnabled=trayMinToTray=trayMinCon=trayMaxDiscon=false;
298 
299     trayIconInit();
300 
301 
302     if ( embedMode )
303     {
304         miniMode=false;
305         useLdap=false;
306     }
307 
308     if ( readExportsFrom!=QString::null )
309     {
310         exportTimer=new QTimer ( this );
311         connect ( exportTimer,SIGNAL ( timeout() ),this,
312                   SLOT ( slotExportTimer() ) );
313     }
314     if ( extLogin )
315     {
316         extTimer=new QTimer ( this );
317         extTimer->start ( 2000 );
318         connect ( extTimer,SIGNAL ( timeout() ),this,
319                   SLOT ( slotExtTimer() ) );
320     }
321 
322     if ( startMaximized )
323     {
324         QTimer::singleShot ( 10, this, SLOT ( slotResize() ) );
325     }
326 
327 
328     QDesktopWidget wd;
329 
330     if ( wd.screenGeometry(wd.screenNumber(this)).width() <1024 ||
331             wd.screenGeometry(wd.screenNumber(this)).height() <768 )
332     {
333         miniMode=true;
334         x2goDebug<<"Switching to \"mini\" mode...";
335     }
336 
337 
338     if ( usePGPCard  && !useLdap)
339     {
340         QTimer::singleShot ( 10, this, SLOT ( slotStartPGPAuth() ) );
341     }
342 
343 
344     //fr=new SVGFrame(QString::null,true,this);
345     fr=new IMGFrame ( ( QImage* ) 0l,this );
346     setCentralWidget ( fr );
347 
348 
349 #ifndef Q_WS_HILDON
350 
351     // See if BGFile is a directory and retrieve an SVG file randomly from within
352     QFileInfo bg_dir(BGFile);
353     if (bg_dir.isDir())
354     {
355         QDirIterator it(BGFile, QStringList() << "*.svg", QDir::Files, QDirIterator::NoIteratorFlags);
356         QStringList fileList;
357         while (it.hasNext())
358             fileList << it.next();
359 
360         qsrand(QTime::currentTime().msec());
361         int max=fileList.size();
362         int random_selector=qrand() % max;
363         BGFile=fileList.at(random_selector);
364     }
365 
366     if (BGFile.size())
367         bgFrame=new SVGFrame ( ( QString ) BGFile,true,fr );
368     else
369         bgFrame=new SVGFrame ( ( QString ) ":/img/svg/bg.svg",true,fr );
370 #else
371     bgFrame=new SVGFrame ( ( QString ) ":/img/svg/bg_hildon.svg",true,fr );
372 #endif
373     //bgFrame=new SVGFrame((QString)"/home/admin/test.svg",false,fr);
374 
375 
376     SVGFrame* x2g=new SVGFrame ( ( QString ) ":/img/svg/x2gologo.svg",
377                                  false,fr );
378 
379     QPalette pl=x2g->palette();
380     pl.setColor ( QPalette::Base, QColor ( 255,255,255,0 ) );
381     pl.setColor ( QPalette::Window, QColor ( 255,255,255,0 ) );
382     x2g->setPalette ( pl );
383 
384     if (OnFile.size())
385         on=new SVGFrame ( ( QString ) OnFile,false,fr );
386     else
387         on=new SVGFrame ( ( QString ) ":/img/svg/onlogo.svg",false,fr );
388 
389     on->setPalette ( pl );
390 
391     if ( !miniMode )
392     {
393         x2g->setFixedSize ( 100,100 );
394         on->setFixedSize ( 100,100 );
395     }
396     else
397     {
398         x2g->setFixedSize ( 50,50 );
399         on->setFixedSize ( 50,50 );
400     }
401 
402     mainL=new QHBoxLayout ( fr );
403     QVBoxLayout* onlay=new QVBoxLayout();
404     onlay->addStretch();
405     onlay->addWidget ( on );
406 
407     QVBoxLayout* x2golay=new QVBoxLayout();
408     x2golay->addStretch();
409     x2golay->addWidget ( x2g );
410 
411 
412     bgLay=new QHBoxLayout ( bgFrame );
413     bgLay->setSpacing ( 0 );
414     bgLay->setMargin ( 0 );
415     bgLay->addLayout ( onlay );
416     bgLay->addStretch();
417     username=new QHBoxLayout();
418     bgLay->addLayout ( username );
419     if ( embedMode )
420         bgLay->addStretch();
421     bgLay->addLayout ( x2golay );
422 
423 
424 
425     act_set=new QAction (
426         QIcon ( iconsPath ( "/32x32/edit_settings.png" ) ),
427         tr ( "&Settings ..." ),this );
428 
429     if (supportMenuFile!=QString::null)
430     {
431         act_support=new QAction ( tr ( "Support ..." ),this );
432         connect ( act_support,SIGNAL ( triggered ( bool ) ),this,
433                   SLOT ( slotSupport() ) );
434 
435     }
436 
437     act_abclient=new QAction ( QIcon ( ":/img/icons/32x32/x2goclient.png" ),
438                                tr ( "About X2Go Client" ),this );
439 
440 
441 
442 
443 
444     connect ( act_set,SIGNAL ( triggered ( bool ) ),this,
445               SLOT ( slotConfig() ) );
446     connect ( act_abclient,SIGNAL ( triggered ( bool ) ),this,
447               SLOT ( slotAbout() ) );
448 
449 
450     sessionExplorer=new SessionExplorer(this);
451 
452 
453 #ifdef Q_OS_DARWIN
454     embedMode=false;
455 #endif
456 
457 
458 #if defined (Q_OS_WIN) //&& defined (CFGCLIENT )
459     xorgSettings();
460 #endif
461 
462 
463 #ifdef Q_OS_WIN
464     winServersReady=false;
465     saveCygnusSettings();
466 #endif
467     initPassDlg();
468     initStatusDlg();
469     interDlg=new InteractionDialog(bgFrame);
470     connect(interDlg, SIGNAL(closeInterractionDialog()), this, SLOT(slotCloseInteractionDialog()));
471     username->addWidget ( interDlg );
472 
473     if ( !embedMode )
474     {
475         initWidgetsNormal();
476     }
477 
478 #ifdef Q_OS_WIN
479     QProcess::startDetached("x2gohelper.exe "+QString::number(GetCurrentProcessId()));
480     QTimer::singleShot ( 500, this, SLOT ( startWinServers() ) );
481 #endif
482 
483     /* FIXME: add Linux. */
484 #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN)
485     QTimer::singleShot (500, this, SLOT (pulseManagerWrapper ()));
486 #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */
487 
488     mainL->setSpacing ( 0 );
489     mainL->setMargin ( 0 );
490     mainL->insertWidget ( 0, bgFrame );
491     hide();
492     QTimer::singleShot ( 1, this, SLOT ( slotResize() ) );
493     connect ( fr,SIGNAL ( resized ( const QSize ) ),this,
494               SLOT ( slotResize ( const QSize ) ) );
495     slotResize ( fr->size() );
496 
497 
498 
499 #ifdef Q_OS_UNIX
500     if (thinMode)
501     {
502         QTimer *timer = new QTimer(this);
503         connect(timer, SIGNAL(timeout()), this, SLOT(slotSyncX()));
504         timer->start(200);
505     }
506 #endif
507     if (showHaltBtn)
508     {
509         QPushButton* bHalt=new QPushButton(bgFrame);
510         QPixmap p(":/img/png/power-button.png");
511         bHalt->setIcon(p);
512         bHalt->setFocusPolicy(Qt::NoFocus);
513         bHalt->setFixedSize(32,32);
514         bHalt->move(10,10);
515         bHalt->show();
516         connect(bHalt,SIGNAL(clicked()),this, SLOT(slotShutdownThinClient()));
517     }
518 
519 
520     bBrokerLogout = new QPushButton (bgFrame);
521     QPixmap p (":/img/png/broker-logout-button.png");
522     bBrokerLogout->setIcon (p);
523     bBrokerLogout->setFocusPolicy (Qt::NoFocus);
524     bBrokerLogout->setFixedSize (32,32);
525 
526     if (showHaltBtn)
527     {
528         bBrokerLogout->move (40,10);
529     }
530     else
531     {
532         bBrokerLogout->move (10,10);
533     }
534 
535     bBrokerLogout->setEnabled (false);
536 
537     if (showBrokerLogoutBtn)
538     {
539         bBrokerLogout->show ();
540     }
541     else
542     {
543         bBrokerLogout->hide ();
544     }
545 
546     connect (bBrokerLogout, SIGNAL (clicked ()), this, SLOT (slotBrokerLogoutButton ()));
547 
548 
549     if (brokerMode)
550     {
551         broker=new HttpBrokerClient ( this, &config );
552         connect ( broker,SIGNAL ( fatalHttpError() ),this,
553                   SLOT ( close() ) );
554         connect ( broker, SIGNAL ( authFailed()), this ,SLOT ( slotGetBrokerAuth()));
555         connect ( broker, SIGNAL( sessionsLoaded()), this, SLOT (slotReadSessions()));
556         connect ( broker, SIGNAL ( sessionSelected()), this, SLOT (slotGetBrokerSession()));
557         connect ( broker, SIGNAL ( passwordChanged(QString)), this, SLOT ( slotPassChanged(QString)));
558         connect (broker, SIGNAL (enableBrokerLogoutButton ()), this, SLOT (slotEnableBrokerLogoutButton ()));
559         brokerAliveTimer=new QTimer(this);
560         connect ( brokerAliveTimer, SIGNAL ( timeout() ), this,
561                   SLOT ( slotSendBrokerAlive() ) );
562     }
563 
564     initSelectSessDlg();
565 
566     proxyWinTimer=new QTimer ( this );
567     connect ( proxyWinTimer, SIGNAL ( timeout() ), this,
568               SLOT ( slotFindProxyWin() ) );
569 
570     xineramaTimer=new QTimer (this);
571 
572     connect( xineramaTimer, SIGNAL(timeout()), this, SLOT(slotConfigXinerama()));
573 
574     x2goInfof(3)<<tr("Started X2Go Client.");
575     x2goDebug<<"$HOME=" + homeDir.toLatin1();
576     if (thinMode)
577     {
578         x2goDebug<<"Thin Mode is active.";
579         showMaximized();
580         activateWindow();
581         raise();
582     }
583 
584     QTimer::singleShot (200, this, SLOT (slotInitLibssh ()));
585 }
586 
587 
~ONMainWindow()588 ONMainWindow::~ONMainWindow()
589 {
590     x2goDebug<<"Destroying X2Go Client's main window.";
591     if ( !closeEventSent )
592         closeClient();
593     x2goDebug<<"Finished destructor hooks for X2Go Client's main window.";
594 }
595 
slotShutdownThinClient()596 void ONMainWindow::slotShutdownThinClient()
597 {
598     QFile file(QDir::homePath()+"/.halt");
599     if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
600         return;
601 
602     QTextStream out(&file);
603     out << "\n";
604     file.close();
605 }
606 
slotEnableBrokerLogoutButton()607 void ONMainWindow::slotEnableBrokerLogoutButton () {
608   bBrokerLogout->setEnabled (true);
609 }
610 
slotBrokerLogoutButton()611 void ONMainWindow::slotBrokerLogoutButton () {
612   /*
613    * Log out of the broker if currently logged in, otherwise
614    * does nothing.
615    */
616   if (config.brokerAuthenticated) {
617     x2goDebug << "Logging off from broker via logout button.";
618     QTimer::singleShot (1, this, SLOT (slotGetBrokerAuth ()));
619   }
620 }
621 
622 
slotSendBrokerAlive()623 void ONMainWindow::slotSendBrokerAlive()
624 {
625     sendEventToBroker(ALIVE);
626 }
627 
628 
slotSyncX()629 void ONMainWindow::slotSyncX()
630 {
631     if (proxyRunning)
632     {
633         if (!isHidden())
634             hide();
635 #ifdef Q_OS_UNIX
636         XSync(QX11Info::display(),false);
637 #endif
638     }
639     else
640     {
641         if (isHidden())
642         {
643             showMaximized();
644             activateWindow();
645             raise();
646         }
647     }
648 }
649 
650 
get_translator(QString file_name_start,QTranslator ** translator)651 bool ONMainWindow::get_translator (QString file_name_start, QTranslator **translator) {
652     QTranslator *tmp_translator = new QTranslator ();
653 
654     /* Qt 4.8.0 introduced a new overload for QTranslator::load(), taking a QLocale
655      * object and loading up the UI language.
656      * Additionally, a lower-cased version is automatically added to the search
657      * list on case-sensitive file systems.
658      * We still need to iterate over the UI languages list in case an English
659      * locale is in there. As we do not ship a nop-English translation, loading
660      * an English translation will always fail and the next language in the list
661      * be preferred.
662      * We also still need the original "compat" version for Qt < 4.8.0.
663      */
664 
665     QString filename = file_name_start;
666     QStringList ui_languages;
667 #if QT_VERSION < 0x040800
668     filename = QString (filename + "_%1" ).arg (QLocale::system ().name ());
669     filename = filename.toLower ();
670 #else /* QT_VERSION < 0x040800 */
671     ui_languages = QLocale::system ().uiLanguages ();
672 #endif /* QT_VERSION < 0x040800 */
673 
674 #if QT_VERSION < 0x040800
675     if (tmp_translator->load (filename)) {
676         *translator = tmp_translator;
677         x2goInfof (4) << tr ("Translator: ") + filename.toLatin1 () + tr (" found.");
678         return (true);
679     }
680     else {
681         x2goWarningf (1) << tr ("Can't load translator: ") + filename.toLatin1 ();
682         return (false);
683     }
684 #else /* QT_VERSION < 0x040800 */
685     QString load_filename = "";
686     bool translator_found = false;
687     for (QStringList::const_iterator it = ui_languages.constBegin (); it != ui_languages.constEnd (); ++it) {
688         /* Respect English locales. Don't try to load any translation, because we do not ship nop-English translations. */
689         if ((*it).startsWith ("en")) {
690             x2goWarningf (1) << "English language requested, not loading translator.";
691             break;
692         }
693         else {
694             /*
695              * QLocale::uiLanguages() may return an unexpected format.
696              * See: https://bugreports.qt.io/browse/QTBUG-25973
697              */
698             QString tmp_locale = (*it);
699             tmp_locale.replace ("-", "_");
700             load_filename = filename;
701             load_filename.append ("_").append (tmp_locale.toLower ());
702 
703             if (tmp_translator->load (load_filename)) {
704                 /* Some translation successfully loaded. That's good enough. */
705                 x2goInfof (4) << tr ("Translator: ") + load_filename.toLatin1 () + tr (" found.");
706                 translator_found = true;
707                 *translator = tmp_translator;
708                 break;
709             }
710             else {
711                 x2goWarningf (1) << tr ("Non-fatal: can't load translator: ") + load_filename.toLatin1 ();
712                 x2goWarningf (1) << tr ("Trying to load language with lower preference, if existent.");
713             }
714         }
715     }
716 
717     return (translator_found);
718 #endif /* QT_VERSION < 0x040800 */
719 }
720 
installTranslator()721 void ONMainWindow::installTranslator () {
722     QTranslator *x2goclientTranslator = new QTranslator ();
723 
724     bool translator_found = get_translator (QString (":/i18n/x2goclient"), &x2goclientTranslator);
725 
726     if (translator_found) {
727         QCoreApplication::installTranslator (x2goclientTranslator);
728     }
729 
730     QTranslator *qtTranslator = new QTranslator ();
731 
732     translator_found = get_translator (QString (":/i18n/qt"), &qtTranslator);
733 
734     if (translator_found) {
735         QCoreApplication::installTranslator (qtTranslator);
736     }
737 }
738 
739 
initWidgetsEmbed()740 void ONMainWindow::initWidgetsEmbed()
741 {
742 }
743 
initWidgetsNormal()744 void ONMainWindow::initWidgetsNormal()
745 {
746     username->setSpacing ( 10 );
747     username->addStretch();
748     username->addStretch();
749     ln=new SVGFrame ( ( QString ) ":/img/svg/line.svg",true,fr );
750     ln->setFixedWidth ( ln->sizeHint().width() );
751     uname=new QLineEdit ( bgFrame );
752     setWidgetStyle ( uname );
753 
754     uname->hide();
755     uname->setFrame ( false );
756     u=new QLabel ( tr ( "Session:" ),bgFrame );
757     u->hide();
758     QFont fnt=u->font();
759     fnt.setPointSize ( 16 );
760 #ifndef Q_WS_HILDON
761     if ( miniMode )
762     {
763         fnt.setPointSize ( 12 );
764     }
765 #endif
766 
767     u->setFont ( fnt );
768 
769     connect ( uname,SIGNAL ( returnPressed() ),this,
770               SLOT ( slotUnameEntered() ) );
771 
772     QPalette pal=u->palette();
773     pal.setColor ( QPalette::WindowText,
774                    QColor ( 200,200,200,255 ) );
775     u->setPalette ( pal );
776     uname->setFont ( fnt );
777     pal=uname->palette();
778     pal.setColor ( QPalette::Base, QColor ( 255,255,255,0 ) );
779     pal.setColor ( QPalette::Text, QColor ( 200,200,200,255 ) );
780     uname->setPalette ( pal );
781 
782     u->show();
783     uname->show();
784 
785 
786     QVBoxLayout* vblay=new QVBoxLayout();
787 
788 
789     users=new QScrollArea ( fr );
790     vblay->addLayout(sessionExplorer->getNavigationLayout());
791     vblay->addWidget(users);
792 
793 
794     pal=users->verticalScrollBar()->palette();
795     pal.setBrush ( QPalette::Window, QColor ( 110,112,127,255 ) );
796     pal.setBrush ( QPalette::Base, QColor ( 110,112,127,255 ) );
797     pal.setBrush ( QPalette::Button, QColor ( 110,112,127,255 ) );
798     users->verticalScrollBar()->setPalette ( pal );
799     users->setFrameStyle ( QFrame::Plain );
800     users->setFocusPolicy ( Qt::NoFocus );
801 
802 
803     pal=users->palette();
804     pal.setBrush ( QPalette::Window, QColor ( 110,112,127,255 ) );
805     users->setPalette ( pal );
806     users->setWidgetResizable ( true );
807 
808     uframe=new QFrame();
809     users->setWidget ( uframe );
810 
811     mainL->insertWidget ( 1, ln );
812 //     mainL->addWidget ( users );
813     mainL->addLayout(vblay);
814 
815     QAction *act_exit=new QAction (
816         QIcon ( iconsPath ( "/32x32/exit.png" ) ),
817         tr ( "&Quit" ),this );
818     act_exit->setShortcut ( tr ( "Ctrl+Q" ) );
819     act_exit->setStatusTip ( tr ( "Quit" ) );
820 
821     act_new=new QAction ( QIcon ( iconsPath ( "/32x32/new_file.png" ) ),
822                           tr ( "&New session ..." ),this );
823     act_new->setShortcut ( tr ( "Ctrl+N" ) );
824 
825 
826     setWindowIcon ( QIcon ( ":/img/icons/128x128/x2go.png" ) );
827     act_edit=new QAction ( QIcon ( iconsPath ( "/32x32/edit.png" ) ),
828                            tr ( "Session management ..." ),this );
829     act_edit->setShortcut ( tr ( "Ctrl+E" ) );
830 
831     if (noSessionEdit)
832     {
833         act_edit->setEnabled(false);
834         act_new->setEnabled(false);
835     }
836 
837     act_sessicon=new QAction (
838         QIcon ( iconsPath ( "/32x32/create_file.png" ) ),
839         tr ( "&Create session icon on desktop ..." ),
840         this );
841     if (brokerMode)
842         act_sessicon->setEnabled(false);
843 
844     if (changeBrokerPass)
845     {
846         act_changeBrokerPass=new QAction (
847             QIcon ( iconsPath ( "/32x32/auth.png" ) ),
848             tr ( "&Set broker password ..." ),
849             this );
850         connect ( act_changeBrokerPass,SIGNAL ( triggered(bool)),this,
851                   SLOT ( slotChangeBrokerPass()) );
852         act_changeBrokerPass->setEnabled(false);
853     }
854 
855     if (connTest)
856     {
857         act_testCon=new QAction (
858             QIcon ( iconsPath ( "/32x32/contest.png" ) ),
859             tr ( "&Connectivity test ..." ),
860             this );
861         connect ( act_testCon,SIGNAL ( triggered(bool)),this,
862                   SLOT ( slotTestConnection()) );
863     }
864 
865 
866     QAction *act_tb=new QAction ( tr ( "Show toolbar" ),this );
867     act_tb->setCheckable ( true );
868     act_tb->setChecked ( showToolBar );
869 
870 
871 
872     QAction *act_abqt=new QAction ( tr ( "About Qt" ),this );
873 
874     connect ( act_abqt,SIGNAL ( triggered ( bool ) ),this,
875               SLOT ( slotAboutQt() ) );
876     connect ( act_new,SIGNAL ( triggered ( bool ) ),this,
877               SLOT ( slotNewSession() ) );
878     connect ( act_sessicon,SIGNAL ( triggered ( bool ) ),this,
879               SLOT ( slotCreateSessionIcon() ) );
880     connect ( act_edit,SIGNAL ( triggered ( bool ) ),this,
881               SLOT ( slotManage() ) );
882     connect ( act_exit,SIGNAL ( triggered ( bool ) ),this,
883               SLOT ( trayQuit()) ) ;
884     connect ( act_tb,SIGNAL ( toggled ( bool ) ),this,
885               SLOT ( displayToolBar ( bool ) ) );
886 
887     stb=addToolBar ( tr ( "Show toolbar" ) );
888 
889     if ( drawMenu )
890     {
891         QMenu* menu_sess=menuBar()->addMenu ( tr ( "&Session" ) );
892         QMenu* menu_opts=0;
893         if(!X2goSettings::centralSettings())
894             menu_opts=menuBar()->addMenu ( tr ( "&Options" ) );
895         if (!brokerMode && !X2goSettings::centralSettings())
896         {
897             menu_sess->addAction ( act_new );
898             menu_sess->addAction ( act_edit );
899 #if (!defined Q_WS_HILDON) && (!defined Q_OS_DARWIN)
900             if ( !portable )
901                 menu_sess->addAction ( act_sessicon );
902 #endif
903             menu_sess->addSeparator();
904         }
905         menu_sess->addAction ( act_exit );
906         if(!X2goSettings::centralSettings())
907         {
908             menu_opts->addAction ( act_set );
909             menu_opts->addAction ( act_tb );
910             if (changeBrokerPass)
911                 menu_opts->addAction(act_changeBrokerPass);
912             if (connTest)
913                 menu_opts->addAction(act_testCon);
914         }
915 
916         QMenu* menu_help=menuBar()->addMenu ( tr ( "&Help" ) );
917         if (supportMenuFile!=QString::null)
918             menu_help->addAction ( act_support );
919         menu_help->addAction ( act_abclient );
920         menu_help->addAction ( act_abqt );
921 
922         if (!brokerMode)
923         {
924             stb->addAction ( act_new );
925             stb->addAction ( act_edit );
926 #if (!defined Q_WS_HILDON) && (!defined Q_OS_DARWIN)
927             if ( !portable )
928                 stb->addAction ( act_sessicon );
929 #endif
930             stb->addSeparator();
931         }
932         stb->addAction ( act_set );
933         if (changeBrokerPass)
934             stb->addAction(act_changeBrokerPass);
935         if (connTest)
936             stb->addAction(act_testCon);
937 
938         if ( !showToolBar  || X2goSettings::centralSettings())
939             stb->hide();
940         connect ( act_tb,SIGNAL ( toggled ( bool ) ),stb,
941                   SLOT ( setVisible ( bool ) ) );
942     }
943     else
944         stb->hide();
945 
946 #if !defined USELDAP
947 
948     useLdap=false;
949 #endif
950 
951     if ( useLdap )
952     {
953         act_new->setEnabled ( false );
954         act_edit->setEnabled ( false );
955         u->setText ( tr ( "Login:" ) );
956         QTimer::singleShot ( 1500, this, SLOT ( readUsers() ) );
957     }
958     else
959     {
960         if (!brokerMode)
961             QTimer::singleShot ( 1, this, SLOT ( slotReadSessions() ) );
962         else
963         {
964             QTimer::singleShot(1, this,SLOT(slotGetBrokerAuth()));
965         }
966     }
967 }
968 
969 
970 
slotPassChanged(const QString & result)971 void ONMainWindow::slotPassChanged(const QString& result)
972 {
973 
974     if (result==QString::null)
975     {
976         QMessageBox::critical(this, tr("Error"),tr("Operation failed"));
977     }
978     else
979     {
980         QMessageBox::information(this, tr("Password changed"),tr("Password changed"));
981         config.brokerPass=result;
982     }
983     setEnabled(true);
984 
985     slotClosePass();
986     sessionStatusDlg->hide();
987 
988 }
989 
slotTestConnection()990 void ONMainWindow::slotTestConnection()
991 {
992     ConTest test( broker, config.brokerurl, this);
993     test.exec();
994 }
995 
slotChangeBrokerPass()996 void ONMainWindow::slotChangeBrokerPass()
997 {
998     x2goDebug<<"Changing broker password.";
999 
1000     BrokerPassDlg passDlg;
1001     if (passDlg.exec()!=QDialog::Accepted)
1002         return;
1003     if (passDlg.oldPass()!=config.brokerPass)
1004     {
1005         QMessageBox::critical(this,tr("Error"),tr("Wrong password!"));
1006         return;
1007     }
1008     broker->changePassword(passDlg.newPass());
1009     setStatStatus ( tr ( "Connecting to broker" ) );
1010     stInfo->insertPlainText ( "broker url: "+config.brokerurl );
1011     setEnabled ( false );
1012     uname->hide();
1013     u->hide();
1014     return;
1015 }
1016 
1017 
slotCheckPortableDir()1018 void ONMainWindow::slotCheckPortableDir()
1019 {
1020     if (!QFile::exists(homeDir))
1021     {
1022         x2goDebug<<"Portable directory does not exist, closing.";
1023         close();
1024     }
1025 }
1026 
slotGetBrokerAuth()1027 void ONMainWindow::slotGetBrokerAuth()
1028 {
1029     pass->clear();
1030     login->clear();
1031     QString pixFile=":/img/icons/128x128/x2gosession.png";
1032     if (SPixFile!=QString::null)
1033         pixFile=SPixFile;
1034     QPixmap pix(pixFile);
1035     if ( !miniMode )
1036     {
1037         fotoLabel->setPixmap (
1038             pix.scaled ( 64,64,
1039                          Qt::IgnoreAspectRatio,
1040                          Qt::SmoothTransformation ) );
1041         fotoLabel->setFixedSize ( 64,64 );
1042     }
1043     else
1044     {
1045         fotoLabel->setPixmap (
1046             pix.scaled ( 48,48,
1047                          Qt::IgnoreAspectRatio,
1048                          Qt::SmoothTransformation ) );
1049         fotoLabel->setFixedSize ( 48,48 );
1050     }
1051 
1052     if(users->isVisible())
1053     {
1054         users->hide();
1055         ln->hide();
1056         bgLay->insertStretch(3);
1057     }
1058     QString text=tr("<b>Authentication</b>");
1059     /* if(config.brokerName.length()>0)
1060        text+=config.brokerName;
1061      else
1062        text+=config.brokerurl;*/
1063     nameLabel->setText ( text );
1064     slotShowPassForm();
1065     config.brokerAuthenticated = false;
1066     bBrokerLogout->setEnabled (false);
1067 
1068     if(config.brokerUser.length()>0)
1069     {
1070         login->setText(config.brokerUser);
1071         pass->setFocus();
1072     }
1073     if(config.brokerNoAuth)
1074         slotSessEnter();
1075     else if(config.brokerurl.indexOf("ssh://")==0 && (config.brokerAutologin || config.brokerKrbLogin|| config.brokerSshKey.length()>0))
1076         slotSessEnter();
1077 }
1078 
1079 
trayIconInit()1080 void ONMainWindow::trayIconInit()
1081 {
1082     X2goSettings st ( "settings" );
1083     trayEnabled=st.setting()->value ( "trayicon/enabled", false ).toBool();
1084     trayMinCon=st.setting()->value ( "trayicon/mincon", false ).toBool();
1085     trayMaxDiscon=st.setting()->value ( "trayicon/maxdiscon", false ).toBool();
1086     trayNoclose=st.setting()->value ( "trayicon/noclose", false ).toBool();
1087     trayMinToTray=st.setting()->value ( "trayicon/mintotray", false ).toBool();
1088 
1089 
1090 
1091     if (!trayEnabled)
1092     {
1093         trayMinCon=trayMaxDiscon=trayNoclose=trayMinToTray=false;
1094         if (trayIcon)
1095         {
1096             delete trayIcon;
1097             delete trayIconMenu;
1098             trayIcon=0l;
1099             trayIconMenu=0l;
1100         }
1101     }
1102     else
1103     {
1104         if (!trayIcon)
1105         {
1106             trayIconMenu = new QMenu(this);
1107             trayIconMenu->addAction(tr("Restore"),this, SLOT(showNormal()));
1108 
1109             trayIconActiveConnectionMenu = trayIconMenu->addMenu(tr("Not connected"));
1110 
1111             appMenu[Application::MULTIMEDIA]=initTrayAppMenu(tr("Multimedia"),
1112                                              QPixmap(":/img/icons/22x22/applications-multimedia.png"));
1113             appMenu[Application::DEVELOPMENT]=initTrayAppMenu(tr("Development"),
1114                                               QPixmap(":/img/icons/22x22/applications-development.png"));
1115             appMenu[Application::EDUCATION]=initTrayAppMenu(tr("Education"),
1116                                             QPixmap(":/img/icons/22x22/applications-education.png"));
1117             appMenu[Application::GAME]=initTrayAppMenu(tr("Game"),
1118                                        QPixmap(":/img/icons/22x22/applications-games.png"));
1119             appMenu[Application::GRAPHICS]=initTrayAppMenu(tr("Graphics"),
1120                                            QPixmap(":/img/icons/22x22/applications-graphics.png"));
1121             appMenu[Application::NETWORK]=initTrayAppMenu(tr("Network"),
1122                                           QPixmap(":/img/icons/22x22/applications-internet.png"));
1123             appMenu[Application::OFFICE]=initTrayAppMenu(tr("Office"),
1124                                          QPixmap(":/img/icons/22x22/applications-office.png"));
1125             appMenu[Application::SETTINGS]=initTrayAppMenu(tr("Settings"),
1126                                            QPixmap(":/img/icons/22x22/preferences-system.png"));
1127             appMenu[Application::SYSTEM]=initTrayAppMenu(tr("System"),
1128                                          QPixmap(":/img/icons/22x22/applications-system.png"));
1129             appMenu[Application::UTILITY]=initTrayAppMenu(tr("Utility"),
1130                                           QPixmap(":/img/icons/22x22/applications-utilities.png"));
1131             appMenu[Application::OTHER]=initTrayAppMenu(tr("Other"),
1132                                         QPixmap(":/img/icons/22x22/applications-other.png"));
1133             appSeparator=trayIconActiveConnectionMenu->addSeparator();
1134 
1135 
1136             if (!hideFolderSharing)
1137                 trayIconActiveConnectionMenu->addAction(tr ("Share folder ..." ),this, SLOT(slotExportDirectory()));
1138             trayIconActiveConnectionMenu->addAction(tr("Suspend"),this, SLOT(slotSuspendSessFromSt()));
1139             trayIconActiveConnectionMenu->addAction(tr("Terminate"),this, SLOT(slotTermSessFromSt()));
1140             connect (trayIconActiveConnectionMenu, SIGNAL(triggered(QAction*)), this,
1141                      SLOT(slotAppMenuTriggered(QAction*)));
1142 
1143 
1144             if (sessionStatusDlg && sessionStatusDlg->isVisible())
1145             {
1146                 if (!useLdap) {
1147                     if (!(sessionExplorer->getLastSession())) {
1148                         x2goDebug << "No session selected, not setting tray icon title.";
1149                     }
1150                     else {
1151                         trayIconActiveConnectionMenu->setTitle(sessionExplorer->getLastSession()->name());
1152                     }
1153                 }
1154                 else
1155                     trayIconActiveConnectionMenu->setTitle(lastUser->username());
1156             }
1157             else
1158             {
1159                 trayIconActiveConnectionMenu->setEnabled(false);
1160             }
1161             trayIconMenu->addSeparator();
1162             trayIconMenu->addAction(tr("Quit"),this, SLOT(trayQuit()));
1163 
1164             // setup the tray icon itself
1165             trayIcon = new QSystemTrayIcon(this);
1166 
1167 #ifndef Q_OS_DARWIN
1168             connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
1169                     this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
1170 #endif
1171             connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(trayMessageClicked()));
1172 
1173             trayIcon->setContextMenu(trayIconMenu);
1174             trayIcon->setIcon(QIcon ( ":/img/icons/128x128/x2go.png") );
1175 #ifdef Q_OS_DARWIN
1176             trayIcon->setToolTip(tr("A click displays the context menu."));
1177 #else
1178             trayIcon->setToolTip(tr("A left click hides or restores the window. A right click displays the context menu."));
1179 #endif
1180         }
1181 
1182         if (!startHidden | forceToShowTrayicon)
1183         {
1184             trayIcon->show();
1185             plugAppsInTray();
1186         }
1187     }
1188 }
1189 
initTrayAppMenu(QString text,QPixmap icon)1190 QMenu* ONMainWindow::initTrayAppMenu(QString text, QPixmap icon)
1191 {
1192     QMenu* menu=trayIconActiveConnectionMenu->addMenu(text);
1193     if (!keepTrayIcon) {
1194         menu->setIcon(icon);
1195     }
1196     return menu;
1197 }
1198 
1199 
slotAppMenuTriggered(QAction * action)1200 void ONMainWindow::slotAppMenuTriggered(QAction* action)
1201 {
1202     x2goDebug<<"slotAppMenuTriggered: "<<action->data().toString();
1203 
1204     if (action->data().toString() != "")
1205         runApplication(action->data().toString());
1206 }
1207 
plugAppsInTray()1208 void ONMainWindow::plugAppsInTray()
1209 {
1210     if (!trayIcon)
1211         return;
1212     removeAppsFromTray();
1213 
1214     x2goDebug<<"Plugging apps in tray.";
1215 
1216     bool empty=true;
1217     topActions.clear();
1218     foreach(Application app, applications)
1219     {
1220         QAction* act;
1221         if (app.category==Application::TOP)
1222         {
1223             act=new QAction(app.icon,app.name,trayIconActiveConnectionMenu);
1224             trayIconActiveConnectionMenu->insertAction(appSeparator, act);
1225             topActions.append(act);
1226         }
1227         else
1228         {
1229             act=appMenu[app.category]->addAction(app.icon,app.name);
1230             appMenu[app.category]->menuAction()->setVisible(true);
1231         }
1232         act->setToolTip(app.comment);
1233         act->setData(app.exec);
1234         empty=false;
1235     }
1236     if (!empty)
1237         appSeparator->setVisible(true);
1238 }
1239 
1240 
removeAppsFromTray()1241 void ONMainWindow::removeAppsFromTray()
1242 {
1243     if (!trayIcon)
1244         return;
1245 
1246     x2goDebug<<"Removing apps from tray";
1247 
1248     for (int i=0; i<=Application::OTHER; ++i)
1249     {
1250         appMenu[i]->clear();
1251         appMenu[i]->menuAction()->setVisible(false);
1252     }
1253     foreach (QAction* act, topActions)
1254     {
1255         trayIconActiveConnectionMenu->removeAction(act);
1256         delete act;
1257     }
1258     topActions.clear();
1259     appSeparator->setVisible(false);
1260 }
1261 
1262 
findTheme(QString)1263 QString ONMainWindow::findTheme ( QString /*theme*/ )
1264 {
1265     return QString::null;
1266 }
1267 
getKdeIconsPath()1268 QString ONMainWindow::getKdeIconsPath()
1269 {
1270     return ":/img/icons";
1271 }
1272 
slotResize(const QSize sz)1273 void ONMainWindow::slotResize ( const QSize sz )
1274 {
1275     if ( startHidden )
1276     {
1277         return;
1278     }
1279     int height;
1280     int usize;
1281     height=sz.height();
1282     if ( !embedMode )
1283     {
1284         if ( !miniMode )
1285         {
1286             usize=sz.width()-800;
1287             if ( usize<360 )
1288                 usize=360;
1289             if ( usize>500 )
1290                 usize=500;
1291         }
1292         else
1293         {
1294             usize=285;
1295         }
1296 
1297         if ( users->width() !=usize )
1298         {
1299             users->setFixedWidth ( usize );
1300             if ( useLdap )
1301             {
1302                 QList<UserButton*>::iterator it;
1303                 QList<UserButton*>::iterator end=names.end();
1304                 for ( it=names.begin(); it!=end; it++ )
1305                 {
1306                     if ( !miniMode )
1307                         ( *it )->move (
1308                             ( usize-360 ) /2,
1309                             ( *it )->pos().y() );
1310                     else
1311                         ( *it )->move (
1312                             ( usize-250 ) /2,
1313                             ( *it )->pos().y() );
1314                 }
1315             }
1316             else
1317             {
1318                 QList<FolderButton*>::iterator fit;
1319                 QList<FolderButton*>::iterator fend=sessionExplorer->getFoldersList()->end();
1320                 for ( fit=sessionExplorer->getFoldersList()->begin(); fit!=fend; fit++ )
1321                 {
1322                     if ( !miniMode )
1323                         ( *fit )->move (
1324                             ( usize-360 ) /2,
1325                             ( *fit )->pos().y() );
1326                     else
1327                         ( *fit )->move (
1328                             ( usize-250 ) /2,
1329                             ( *fit )->pos().y() );
1330                 }
1331                 QList<SessionButton*>::iterator it;
1332                 QList<SessionButton*>::iterator end=sessionExplorer->getSessionsList()->end();
1333                 for ( it=sessionExplorer->getSessionsList()->begin(); it!=end; it++ )
1334                 {
1335                     if ( !miniMode )
1336                         ( *it )->move (
1337                             ( usize-360 ) /2,
1338                             ( *it )->pos().y() );
1339                     else
1340                         ( *it )->move (
1341                             ( usize-250 ) /2,
1342                             ( *it )->pos().y() );
1343                 }
1344             }
1345         }
1346         u->setFixedWidth ( u->sizeHint().width() );
1347 
1348         int bwidth=bgFrame->width();
1349         int upos= ( bwidth-u->width() ) /2;
1350         if ( upos<0 )
1351             upos=0;
1352         int rwidth=bwidth- ( upos+u->width() +5 );
1353         if ( rwidth<0 )
1354             rwidth=1;
1355         uname->setMinimumWidth ( rwidth );
1356         u->move ( upos,height/2 );
1357         uname->move ( u->pos().x() +u->width() +5,u->pos().y() );
1358         sessionExplorer->resize();
1359     }
1360 }
1361 
closeClient()1362 void ONMainWindow::closeClient()
1363 {
1364     x2goInfof(6)<<tr("Closing X2Go Client ...");
1365     if(trayIcon)
1366         trayIcon->hide();
1367     closeEventSent=true;
1368     if ( !startMaximized && !startHidden && !embedMode )
1369     {
1370         x2goDebug<<"Saving settings ...";
1371         X2goSettings st ( "sizes" );
1372 
1373         st.setting()->setValue ( "mainwindow/size",
1374                                  QVariant ( size() ) );
1375         st.setting()->setValue ( "mainwindow/pos",QVariant ( mapToGlobal(QPoint(0,0) ) ));
1376         st.setting()->setValue ( "mainwindow/maximized",
1377                                  QVariant ( isMaximized() ) );
1378         st.setting()->sync();
1379         x2goDebug<<"Saved settings.";
1380 #ifdef Q_OS_UNIX
1381         if (image)
1382             XFreePixmap(QX11Info::display(),image);
1383         if (shape)
1384             XFreePixmap(QX11Info::display(),shape);
1385 #endif
1386     }
1387     if ( nxproxy!=0l )
1388     {
1389         if ( nxproxy->state() ==QProcess::Running )
1390         {
1391             x2goDebug<<"Terminating proxy ...";
1392             nxproxy->terminate();
1393             x2goDebug<<"Terminated proxy.";
1394         }
1395         x2goDebug<<"Deleting proxy ...";
1396         delete nxproxy;
1397         x2goDebug<<"Deleted proxy.";
1398     }
1399     if ( sshConnection && !useLdap)
1400     {
1401         x2goDebug<<"Waiting for the SSH connection to finish ...";
1402         delete sshConnection;
1403         x2goDebug<<"SSH connection finished.";
1404         sshConnection=0;
1405     }
1406     if (useLdap)
1407     {
1408         for (int i=0; i<serverSshConnections.count(); ++i)
1409         {
1410             if (serverSshConnections[i])
1411             {
1412                 x2goDebug<<"Waiting for the SSH connection to finish ...";
1413                 delete serverSshConnections[i];
1414                 x2goDebug<<"SSH connection finished.";
1415             }
1416         }
1417         serverSshConnections.clear();
1418     }
1419 
1420     if ( soundServer )
1421     {
1422         x2goDebug<<"Deleting the sound server ...";
1423         delete soundServer;
1424         x2goDebug<<"Deleted the sound server.";
1425     }
1426 #ifdef Q_OS_WIN
1427     if ( xorg )
1428     {
1429         x2goDebug<<"Terminating the X.Org Server ...";
1430         xorg->terminate();
1431         x2goDebug<<"Terminated the X.Org Server.";
1432         x2goDebug<<"Deleting the X.Org Server ...";
1433         delete xorg;
1434         x2goDebug<<"Deleted the X.Org Server.";
1435     }
1436 
1437     if ( winSshdStarted )
1438     {
1439         TerminateProcess ( sshd.hProcess,0 );
1440         CloseHandle ( sshd.hProcess );
1441         CloseHandle ( sshd.hThread );
1442     }
1443 #endif /* defined (Q_OS_WIN) */
1444 
1445 #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN)
1446     if (pulseManager) {
1447         disconnect(pulseManager, SIGNAL(sig_pulse_user_warning(bool, const QString&, const QString&, bool)),
1448                    this, SLOT(slotShowPAMSGDialog(bool, const QString&, const QString&, bool)));
1449         delete (pulseManager);
1450 
1451         if (pulseManagerThread) {
1452 
1453             pulseManagerThread->quit ();
1454             pulseManagerThread->wait ();
1455         }
1456 
1457         delete (pulseManagerThread);
1458     }
1459 #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */
1460 
1461 #ifndef Q_OS_WIN
1462     if (sshd) {
1463         x2goDebug << "Terminating the OpenSSH server ...";
1464         sshd->terminate ();
1465 
1466         /* Allow sshd a grace time of 5 seconds to terminate. */
1467         QTime sleep_time = QTime::currentTime ().addSecs (5);
1468         bool killed = false;
1469         while (QTime::currentTime () < sleep_time) {
1470             if (QProcess::NotRunning == sshd->state ()) {
1471                 killed = true;
1472                 break;
1473             }
1474 
1475             QCoreApplication::processEvents (QEventLoop::AllEvents, 100);
1476         }
1477 
1478         if (!killed) {
1479             /* Grace period over, force termination. */
1480             sshd->kill ();
1481 
1482             if (!(sshd->waitForFinished (500))) {
1483                 x2goWarningf (8) << "OpenSSH Server failed to terminate in time "
1484                                     " and the kill command timed out.";
1485             }
1486         }
1487 
1488         x2goDebug << "Terminated the OpenSSH server.";
1489         delete sshd;
1490     }
1491 #endif /* !defined (Q_OS_WIN) */
1492 
1493     if ( embedMode )
1494     {
1495         passForm->close();
1496         selectSessionDlg->close();
1497 #ifndef Q_OS_DARWIN
1498 // 		closeEmbedWidget();
1499 #endif
1500     }
1501 
1502     if ( ONMainWindow::portable )
1503     {
1504 #ifdef Q_OS_WIN
1505         if ( !cyEntry )
1506         {
1507             removeCygwinEntry();
1508         }
1509 #endif
1510         cleanPortable();
1511     }
1512 
1513     if (ssh_finalize ()) {
1514         x2goDebug << "Unable to finalize libssh. Something may be wrong!";
1515     }
1516     else {
1517         x2goDebug << "libssh finalized.";
1518     }
1519 
1520     delete (bBrokerLogout);
1521 
1522     x2goInfof(7)<<tr("Finished X2Go Client closing hooks.");
1523 }
1524 
closeEvent(QCloseEvent * event)1525 void ONMainWindow::closeEvent ( QCloseEvent* event )
1526 {
1527     x2goDebug<<"Close event received."<<endl;
1528 
1529     if (trayNoclose && !brokerMode)
1530     {
1531         hide();
1532         event->ignore();
1533     }
1534     else
1535     {
1536         trayQuit();
1537     }
1538 }
1539 
1540 
hideEvent(QHideEvent * event)1541 void ONMainWindow::hideEvent(QHideEvent* event)
1542 {
1543     QMainWindow::hideEvent(event);
1544     if (event->spontaneous() && trayMinToTray)
1545         hide();
1546 
1547 }
1548 
trayQuit()1549 void ONMainWindow::trayQuit()
1550 {
1551     x2goDebug<<"Quitting from tray icon and closing application."<<endl;
1552 
1553     closeClient();
1554     qApp->quit();
1555 
1556 }
1557 
trayIconActivated(QSystemTrayIcon::ActivationReason reason)1558 void ONMainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason )
1559 {
1560     switch (reason) {
1561 // use single left click on unix
1562 // and double click on windows (Is it standard behaviour conform?)
1563 #ifdef Q_OS_UNIX
1564     case QSystemTrayIcon::Trigger:
1565 #else
1566     case QSystemTrayIcon::DoubleClick:
1567 #endif
1568         x2goDebug << "tray icon clicked with Trigger (left click)";
1569         if (isVisible())
1570             hide();
1571         else
1572         {
1573             showNormal();
1574         }
1575         break;
1576     default:
1577         break;
1578     }
1579 }
1580 
1581 
1582 
trayMessageClicked()1583 void ONMainWindow::trayMessageClicked()
1584 {
1585 
1586 }
1587 
loadSettings()1588 void ONMainWindow::loadSettings()
1589 {
1590 
1591     X2goSettings st ( "sizes" );
1592     mwSize=st.setting()->value ( "mainwindow/size",
1593                                  ( QVariant ) QSize ( 800,600 ) ).toSize();
1594     mwPos=st.setting()->value ( "mainwindow/pos",
1595                                 ( QVariant ) QPoint ( 20,20 ) ).toPoint();
1596     mwMax=st.setting()->value ( "mainwindow/maximized",
1597                                 ( QVariant ) false ).toBool();
1598 
1599     /*
1600      * Sanity check for X2Go Client main window position.
1601      * Check whether the given position is within bounds of any connected display.
1602      * Otherwise use the default.
1603      */
1604     bool placement_found = false;
1605     QDesktopWidget *desktop_widget = QApplication::desktop ();
1606     QRect main_window_geom (mwPos, mwSize);
1607     for (size_t i = 0; i < static_cast<size_t> (desktop_widget->screenCount ()); ++i) {
1608         QRect tmp_geom = desktop_widget->availableGeometry (i);
1609 
1610         if (tmp_geom.intersects (main_window_geom)) {
1611             placement_found = true;
1612             break;
1613         }
1614     }
1615 
1616     if (!placement_found) {
1617         mwPos = QPoint (20, 20);
1618     }
1619 
1620     X2goSettings st1 ( "settings" );
1621 
1622     if ( !ldapOnly )
1623     {
1624         useLdap=st1.setting()->value ( "LDAP/useldap",
1625                                        ( QVariant ) false ).toBool();
1626         ldapServer=st1.setting()->value ( "LDAP/server",
1627                                           ( QVariant ) "localhost" ).toString();
1628         ldapPort=st1.setting()->value ( "LDAP/port",
1629                                         ( QVariant ) 389 ).toInt();
1630         ldapDn=st1.setting()->value ( "LDAP/basedn",
1631                                       ( QVariant ) QString::null ).toString();
1632         ldapServer1=st1.setting()->value ( "LDAP/server1",
1633                                            ( QVariant ) QString::null ).toString();
1634         ldapPort1=st1.setting()->value ( "LDAP/port1",
1635                                          ( QVariant ) 0 ).toInt();
1636         ldapServer2=st1.setting()->value ( "LDAP/server2",
1637                                            ( QVariant ) QString::null ).toString();
1638         ldapPort2=st1.setting()->value ( "LDAP/port2",
1639                                          ( QVariant ) 0 ).toInt();
1640     }
1641     showToolBar=st1.setting()->value ( "toolbar/show",
1642                                        ( QVariant ) true ).toBool();
1643 
1644 }
1645 
iconsPath(const QString & fname) const1646 QString ONMainWindow::iconsPath ( const QString &fname ) const
1647 {
1648     /*    QFile fl(this->kdeIconsPath+fname);
1649     	if(fl.exists())
1650     	return kdeIconsPath+fname;*/
1651     return (images_resource_path (fname, "/icons/"));
1652 }
1653 
images_resource_path(const QString & filename,const QString & base) const1654 QString ONMainWindow::images_resource_path (const QString &filename, const QString &base) const {
1655   QString ret = ":/img";
1656 
1657   /*
1658    * The base parameter is optional and might be empty.
1659    * In this case, it's completely skipped.
1660    * Otherwise, we want to make sure that the base parameter
1661    * is appended to the fixed start with a slash, but doesn't
1662    * end in a slash to avoid double-slashes.
1663    * We add a trailing slash if the file name doesn't start
1664    * with one.
1665    */
1666   if (!(base.isEmpty ())) {
1667     if (!(base.startsWith ('/'))) {
1668       ret.append ('/');
1669     }
1670 
1671     ret.append (base);
1672 
1673     if (ret.endsWith ('/')) {
1674       ret.chop (1);
1675     }
1676   }
1677 
1678   if (!(filename.startsWith ('/'))) {
1679     ret.append ('/');
1680   }
1681 
1682   ret.append (filename);
1683 
1684   return (ret);
1685 }
1686 
displayUsers()1687 void ONMainWindow::displayUsers()
1688 {
1689 
1690     QPixmap pix;
1691     if ( !miniMode )
1692         pix=QPixmap ( ":/img/png/ico.png" );
1693     else
1694         pix=QPixmap ( ":/img/png/ico_mini.png" );
1695     QPixmap foto=QPixmap ( iconsPath ( "/64x64/personal.png" ) );
1696 
1697     QPalette pal=palette();
1698     pal.setBrush ( QPalette::Window, QBrush ( pix ) );
1699     pal.setBrush ( QPalette::Base, QBrush ( pix ) );
1700     pal.setBrush ( QPalette::Button, QBrush ( pix ) );
1701     QFont fnt=font();
1702     fnt.setPointSize ( 12 );
1703     uframe->setFont ( fnt );
1704     QList<user>::iterator it;
1705     QList<user>::iterator end=userList.end();
1706     int i=0;
1707     for ( it=userList.begin(); it!=end; it++ )
1708     {
1709         int val=i+1;
1710         UserButton* l;
1711         if ( ( *it ).foto.isNull() )
1712             l=new UserButton ( this, uframe, ( *it ).uid,
1713                                ( *it ).name,foto,pal );
1714         else
1715             l=new UserButton ( this, uframe, ( *it ).uid,
1716                                ( *it ).name, ( *it ).foto,pal );
1717         connect ( l,SIGNAL ( userSelected ( UserButton* ) ),this,
1718                   SLOT ( slotSelectedFromList ( UserButton* ) ) );
1719         if ( !miniMode )
1720             l->move ( ( users->width()-360 ) /2,
1721                       i*120+ ( val-1 ) *25+5 );
1722         else
1723             l->move ( ( users->width()-260 ) /2,
1724                       i*120+ ( val-1 ) *25+5 );
1725         l->show();
1726         names.append ( l );
1727         i++;
1728     }
1729     int val=i;
1730     uframe->setFixedHeight ( val*120+ ( val-1 ) *25 );
1731     uname->setText ( "" );
1732     disconnect ( uname,SIGNAL ( textEdited ( const QString& ) ),this,
1733                  SLOT ( slotSnameChanged ( const QString& ) ) );
1734     connect ( uname,SIGNAL ( textEdited ( const QString& ) ),this,
1735               SLOT ( slotUnameChanged ( const QString& ) ) );
1736     if ( usePGPCard  && !PGPInited)
1737     {
1738         PGPInited=true;
1739 
1740         x2goDebug<<"Users loaded, starting smart card daemon.";
1741 
1742         QTimer::singleShot ( 10, this, SLOT ( slotStartPGPAuth() ) );
1743     }
1744 }
1745 
showPass(UserButton * user)1746 void ONMainWindow::showPass ( UserButton* user )
1747 {
1748     QPalette pal=users->palette();
1749     setUsersEnabled ( false );
1750     QString fullName;
1751     QPixmap foto;
1752     if ( user )
1753     {
1754         foto=user->foto();
1755         nick=user->username();
1756         fullName=user->fullName();
1757         user->hide();
1758         lastUser=user;
1759     }
1760     else
1761     {
1762         lastUser=0;
1763         foto.load ( iconsPath ( "/64x64/personal.png" ) );
1764         foto=foto.scaled ( 100,100 );
1765         nick=uname->text();
1766         fullName="User Unknown";
1767     }
1768 
1769     fotoLabel->setPixmap ( foto );
1770 
1771     QString text="<b>"+nick+"</b><br>("+fullName+")";
1772     nameLabel->setText ( text );
1773     login->setText ( nick );
1774     login->hide();
1775 
1776     pass->setEchoMode ( QLineEdit::Password );
1777     pass->setFocus();
1778     slotShowPassForm();
1779 }
1780 
1781 
1782 
slotSelectedFromList(UserButton * user)1783 void ONMainWindow::slotSelectedFromList ( UserButton* user )
1784 {
1785     pass->setText ( "" );
1786     showPass ( user );
1787 }
1788 
slotClosePass()1789 void ONMainWindow::slotClosePass()
1790 {
1791     if (brokerMode)
1792     {
1793         if (!config.brokerAuthenticated)
1794         {
1795             x2goErrorf(15)<<tr("Broker authentication failed!");
1796             close();
1797         }
1798     }
1799     passForm->hide();
1800     if ( !embedMode )
1801     {
1802         u->show();
1803         uname->show();
1804         if ( useLdap )
1805         {
1806             if ( lastUser )
1807             {
1808                 lastUser->show();
1809                 uname->setText ( lastUser->username() );
1810             }
1811         }
1812         else
1813         {
1814             if (sessionExplorer->getLastSession())
1815             {
1816                 sessionExplorer->getLastSession()->show();
1817                 uname->setText ( sessionExplorer->getLastSession()->name() );
1818             }
1819         }
1820         uname->setEnabled ( true );
1821         u->setEnabled ( true );
1822         setUsersEnabled ( true );
1823         uname->selectAll();
1824         uname->setFocus();
1825     }
1826 }
1827 
1828 
slotPassEnter()1829 void ONMainWindow::slotPassEnter()
1830 {
1831 
1832     if(!embedMode)
1833         shadowSession=false;
1834 #if defined ( Q_OS_WIN ) || defined (Q_OS_DARWIN )
1835     QString disp=getXDisplay();
1836     if ( disp==QString::null )
1837         return;
1838 #endif
1839 #ifdef USELDAP
1840 
1841     if ( ! initLdapSession() )
1842     {
1843         QMessageBox::critical ( 0l,tr ( "Error" ),
1844                                 tr ( "Please check LDAP settings" ),
1845                                 QMessageBox::Ok,QMessageBox::NoButton );
1846 
1847         slotConfig();
1848         return;
1849     }
1850 
1851     passForm->setEnabled ( false );
1852 
1853     x2goServers.clear();
1854 
1855     list<string> attr;
1856     attr.push_back ( "cn" );
1857     attr.push_back ( "serialNumber" );
1858     attr.push_back ( "l" );
1859     list<LDAPStringEntry> res;
1860     QString searchBase="ou=Servers,ou=ON,"+ldapDn;
1861 
1862     try
1863     {
1864         ld->stringSearch ( searchBase.toStdString(),attr,
1865                            "objectClass=ipHost",res );
1866     }
1867     catch ( LDAPExeption e )
1868     {
1869         QString message="Exception in: ";
1870         message=message+e.err_type.c_str();
1871         message=message+" : "+e.err_str.c_str();
1872         QMessageBox::critical ( 0l,tr ( "Error" ),message,
1873                                 QMessageBox::Ok,QMessageBox::NoButton );
1874         slotConfig();
1875         return;
1876     }
1877     if ( res.size() ==0 )
1878     {
1879         QString message=tr ( "no X2Go Server found in LDAP " );
1880         QMessageBox::critical ( 0l,tr ( "Error" ),message,
1881                                 QMessageBox::Ok,QMessageBox::NoButton );
1882         slotConfig();
1883         return;
1884     }
1885 
1886 
1887     list<LDAPStringEntry>::iterator it=res.begin();
1888     list<LDAPStringEntry>::iterator end=res.end();
1889     QString freeServer;
1890     QString firstServer;
1891     bool isFirstServerSet=false;
1892     for ( ; it!=end; ++it )
1893     {
1894         serv server;
1895         server.name=LDAPSession::getStringAttrValues (
1896                         *it,"cn" ).front().c_str();
1897 
1898         QString sPort="22";
1899         list<string> sL=LDAPSession::getStringAttrValues (
1900                             *it,"l" );
1901         if ( sL.size() >0 )
1902         {
1903             sPort=sL.front().c_str();
1904         }
1905 
1906         x2goDebug<<"SSH server: "<<server.name<<"; port: "<<sPort;
1907 
1908         QString sFactor="1";
1909         list<string> serialNumber=LDAPSession::getStringAttrValues (
1910                                       *it,"serialNumber" );
1911         if ( serialNumber.size() >0 )
1912         {
1913             sFactor=serialNumber.front().c_str();
1914         }
1915 
1916         x2goDebug<<"SSH server: "<<server.name<<"; factor: "<<sFactor;
1917 
1918         server.factor=sFactor.toFloat();
1919         server.sess=0;
1920         server.sshPort=sPort;
1921         server.connOk=true;
1922         if ( !isFirstServerSet )
1923         {
1924             isFirstServerSet=true;
1925             firstServer=server.name;
1926             sshPort=server.sshPort;
1927         }
1928         x2goServers.append ( server );
1929     }
1930     if ( ld )
1931     {
1932         delete ld;
1933         ld=0;
1934     }
1935     setEnabled ( false );
1936     passForm->setEnabled ( false );
1937 
1938     QString passwd;
1939     if ( !extLogin )
1940         currentKey=QString::null;
1941     QString user=getCurrentUname();
1942 //      get x2gogetservers not from ldap server, but from first x2goserver
1943 // 	QString host=ldapServer;
1944     QString host=firstServer;
1945     passwd=getCurrentPass();
1946     if (sshConnection)
1947         delete sshConnection;
1948     sshConnection=startSshConnection ( host,sshPort,acceptRsa,user,passwd,true, false );
1949 
1950 #endif
1951 }
1952 
1953 
slotUnameChanged(const QString & text)1954 void ONMainWindow::slotUnameChanged ( const QString& text )
1955 {
1956     if ( prevText==text )
1957         return;
1958     if ( text=="" )
1959         return;
1960     QList<UserButton*>::iterator it;
1961     QList<UserButton*>::iterator endit=names.end();
1962     for ( it=names.begin(); it!=endit; it++ )
1963     {
1964         QString username= ( *it )->username();
1965         if ( username.indexOf ( text,0,Qt::CaseInsensitive ) ==0 )
1966         {
1967             QPoint pos= ( *it )->pos();
1968             uname->setText ( username );
1969             QScrollBar* bar=users->verticalScrollBar();
1970             int docLang=bar->maximum()-bar->minimum() +
1971                         bar->pageStep();
1972             double position= ( double ) ( pos.y() ) /
1973                              ( double ) ( uframe->height() );
1974             bar->setValue ( ( int ) ( docLang*position-height() /2+
1975                                       ( *it )->height() /2 ) );
1976             uname->setSelection ( username.length(),text.length()-
1977                                   username.length() );
1978             break;
1979         }
1980     }
1981     prevText=text;
1982 }
1983 
slotUnameEntered()1984 void ONMainWindow::slotUnameEntered()
1985 {
1986     QString text=uname->text();
1987     if ( useLdap )
1988     {
1989         UserButton* user=NULL;
1990         QList<UserButton*>::iterator it;
1991         QList<UserButton*>::iterator endit=names.end();
1992         for ( it=names.begin(); it!=endit; it++ )
1993         {
1994             QString username= ( *it )->username();
1995             if ( username==text )
1996             {
1997                 user=*it;
1998                 break;
1999             }
2000         }
2001         showPass ( user );
2002     }
2003     else
2004     {
2005         SessionButton* sess=NULL;
2006         QList<SessionButton*>::iterator it;
2007         QList<SessionButton*>::iterator endit=sessionExplorer->getSessionsList()->end();
2008         for ( it=sessionExplorer->getSessionsList()->begin(); it!=endit; it++ )
2009         {
2010             QString name= ( *it )->name();
2011             if ( name==text )
2012             {
2013                 sess=*it;
2014                 break;
2015             }
2016         }
2017         if ( sess )
2018             slotSelectedFromList ( sess );
2019     }
2020 }
2021 
2022 
readUsers()2023 void ONMainWindow::readUsers()
2024 {
2025 #ifdef USELDAP
2026     if ( ! initLdapSession() )
2027     {
2028         QMessageBox::critical ( 0l,tr ( "Error" ),
2029                                 tr ( "Please check LDAP settings" ),
2030                                 QMessageBox::Ok,QMessageBox::NoButton );
2031 
2032         slotConfig();
2033         return;
2034     }
2035 
2036 
2037     list<string> attr;
2038     attr.push_back ( "uidNumber" );
2039     attr.push_back ( "uid" );
2040     attr.push_back ( "cn" );
2041     attr.push_back ( "jpegPhoto" );
2042 
2043 
2044     list<LDAPBinEntry> result;
2045     try
2046     {
2047         ld->binSearch ( ldapDn.toStdString(),attr,
2048                         "objectClass=posixAccount",result );
2049     }
2050     catch ( LDAPExeption e )
2051     {
2052         QString message="Exception in: ";
2053         message=message+e.err_type.c_str();
2054         message=message+" : "+e.err_str.c_str();
2055         QMessageBox::critical ( 0l,tr ( "Error" ),
2056                                 message,QMessageBox::Ok,
2057                                 QMessageBox::NoButton );
2058         QMessageBox::critical ( 0l,tr ( "Error" ),
2059                                 tr ( "Please check LDAP settings" ),
2060                                 QMessageBox::Ok,QMessageBox::NoButton );
2061         slotConfig();
2062         return;
2063     }
2064 
2065     list<LDAPBinEntry>::iterator it=result.begin();
2066     list<LDAPBinEntry>::iterator end=result.end();
2067 
2068     for ( ; it!=end; ++it )
2069     {
2070         user u;
2071         QString uin=LDAPSession::getBinAttrValues (
2072                         *it,"uidNumber" ).front().getData();
2073         u.uin=uin.toUInt();
2074         if ( u.uin<firstUid || u.uin>lastUid )
2075         {
2076             continue;
2077         }
2078         u.uid=LDAPSession::getBinAttrValues ( *it,
2079                                               "uid" ).front().getData();
2080         u.name=u.name.fromUtf8 ( LDAPSession::getBinAttrValues ( *it,
2081                                  "cn" ).front().getData() );
2082         list<ByteArray> lst=LDAPSession::getBinAttrValues (
2083                                 *it,"jpegPhoto" );
2084         if ( lst.size() )
2085         {
2086             u.foto.loadFromData ( ( const uchar* ) (
2087                                       lst.front().getData() ),
2088                                   lst.front().length() );
2089         }
2090         userList.append ( u );
2091     }
2092     qSort ( userList.begin(),userList.end(),user::lessThen );
2093     delete ld;
2094     ld=0;
2095     displayUsers();
2096     if ( defaultUser )
2097     {
2098         defaultUser=false;
2099         for ( int i=0; i<userList.size(); ++i )
2100         {
2101             if ( userList[i].uid ==defaultUserName )
2102             {
2103                 uname->setText ( defaultUserName );
2104                 slotUnameChanged ( defaultUserName );
2105                 QTimer::singleShot (
2106                     100, this,
2107                     SLOT ( slotUnameEntered() ) );
2108                 break;
2109             }
2110         }
2111     }
2112 #endif
2113 }
2114 
2115 
slotConfig()2116 void ONMainWindow::slotConfig()
2117 {
2118     if ( !startMaximized && !startHidden && !embedMode )
2119     {
2120         X2goSettings st ( "sizes" );
2121 
2122         st.setting()->setValue ( "mainwindow/size",
2123                                  QVariant ( size() ) );
2124         st.setting()->setValue ( "mainwindow/pos",QVariant ( pos() ) );
2125         st.setting()->sync();
2126     }
2127     if ( ld )
2128         delete ld;
2129     ld=0;
2130 
2131 #if defined (Q_OS_WIN) || defined (Q_OS_DARWIN)
2132     bool oldDisableInput = false;
2133     {
2134         X2goSettings st ("settings");
2135         oldDisableInput = st.setting ()->value ("pulse/norecord",
2136                                                 (QVariant) false).toBool ();
2137     }
2138 #endif /* defined (Q_OS_WIN) || defined (Q_OS_DARWIN) */
2139 
2140     ConfigDialog dlg ( this );
2141     if ( dlg.exec() ==QDialog::Accepted )
2142     {
2143         int i;
2144 
2145 #if defined (Q_OS_WIN) || defined (Q_OS_DARWIN)
2146         if(!systemDisablePA)
2147         {
2148             X2goSettings st ("settings");
2149             bool disablePA = st.setting ()->value ("pulse/disable",
2150                                                      (QVariant) false).toBool ();
2151             if(!pulseManager && !disablePA)
2152 	    {
2153 	        x2goDebug<<"PA manager not inited yet, starting PA thread";
2154 		QTimer::singleShot (10, this, SLOT (pulseManagerWrapper ()));
2155 	    }
2156 	    else if(pulseManager && disablePA)
2157 	    {
2158 	        if(pulseManager->is_server_running())
2159 		{
2160 		    x2goDebug<<"Stopping PulseAudio";
2161 		    pulseManager->shutdown();
2162 		}
2163 	    }
2164 	    else if(pulseManager && !disablePA)//pulse is already inited and not disabled by config dialog
2165 	    {
2166                 bool newDisableInput = st.setting ()->value ("pulse/norecord",
2167                                                          (QVariant) false).toBool ();
2168                 if(systemDisablePARecord)
2169 		    newDisableInput=true;
2170                 if (oldDisableInput != newDisableInput) {
2171                     bool ret = pulseManager->set_record (!newDisableInput);
2172 
2173                     if (!ret) {
2174                       x2goDebug << "Failed to change recording status of PulseManager. PulseAudio not started?" << endl;
2175                     }
2176                     pulseManager->restart ();
2177                 }
2178 	    }
2179 	}
2180 #endif /* defined (Q_OS_WIN) || defined (Q_OS_DARWIN) */
2181 
2182         if ( passForm->isVisible() && !embedMode )
2183             slotClosePass();
2184         if ( sessionStatusDlg->isVisible() || embedMode )
2185         {
2186             trayIconInit();
2187             //if session is running or embed mode, save changes,
2188             //but not accept
2189             //
2190             return;
2191         }
2192         if ( !embedMode )
2193         {
2194 
2195             for ( i=0; i<names.size(); ++i )
2196                 names[i]->close();
2197 
2198             sessionExplorer->cleanSessions();
2199 
2200             userList.clear();
2201         }
2202         loadSettings();
2203         trayIconInit();
2204         if ( useLdap )
2205         {
2206             act_new->setEnabled ( false );
2207             act_edit->setEnabled ( false );
2208             u->setText ( tr ( "Login:" ) );
2209             QTimer::singleShot ( 1, this, SLOT ( readUsers() ) );
2210         }
2211         else
2212         {
2213             act_new->setEnabled ( true );
2214             act_edit->setEnabled ( true );
2215             u->setText ( tr ( "Session:" ) );
2216             QTimer::singleShot ( 1, this,
2217                                  SLOT ( slotReadSessions() ) );
2218         }
2219         slotResize ( fr->size() );
2220     }
2221 }
2222 
2223 
2224 
slotReadSessions()2225 void ONMainWindow::slotReadSessions()
2226 {
2227 
2228     users->show();
2229     ln->show();
2230 
2231     if(brokerMode)
2232     {
2233         bgLay->removeItem(bgLay->itemAt(3));
2234         slotResize(QSize(width(), height()));
2235     }
2236 
2237     X2goSettings *st;
2238     sessionExplorer->cleanSessions();
2239     sessionExplorer->setLastSession(0);
2240 
2241     if (brokerMode)
2242     {
2243         if (changeBrokerPass)
2244             act_changeBrokerPass->setEnabled(true);
2245         config.key=QString::null;
2246         config.user=QString::null;
2247         config.sessiondata=QString::null;
2248         for (int i=sessionExplorer->getSessionsList()->count()-1; i>=0; --i)
2249         {
2250             SessionButton* but=sessionExplorer->getSessionsList()->takeAt(i);
2251             if (but)
2252                 delete but;
2253         }
2254 
2255         st=new X2goSettings(config.iniFile,QSettings::IniFormat);
2256         sessionStatusDlg->hide();
2257         selectSessionDlg->hide();
2258         setEnabled ( true );
2259         slotClosePass();
2260     }
2261     else
2262         st= new X2goSettings( "sessions" );
2263 
2264     QStringList slst=st->setting()->childGroups();
2265 
2266     x2goDebug<<"Reading "<<slst.size()<<" sessions from config file.";
2267 
2268     if (brokerMode && (slst.size()==0))
2269     {
2270         QString error = tr("No X2Go sessions found, closing.");
2271         if(!startHidden)
2272             QMessageBox::critical(this,tr("Error"),error);
2273         else
2274             x2goErrorf(1)<<error;
2275         close();
2276         return;
2277     }
2278     for ( int i=0; i<slst.size(); ++i )
2279     {
2280         if ( slst[i]!="embedded" )
2281             sessionExplorer->createBut ( slst[i] );
2282     }
2283     sessionExplorer->placeButtons();
2284     if ( slst.size() ==0 )
2285         slotNewSession();
2286     uname->setText ( "" );
2287     disconnect ( uname,SIGNAL ( textEdited ( const QString& ) ),this,
2288                  SLOT ( slotUnameChanged ( const QString& ) ) );
2289     connect ( uname,SIGNAL ( textEdited ( const QString& ) ),this,
2290               SLOT ( slotSnameChanged ( const QString& ) ) );
2291 
2292     if(usePGPCard &&brokerMode&&cardReady)
2293     {
2294         if(sessionExplorer->getSessionsList()->count()==1)
2295         {
2296             slotSelectedFromList(sessionExplorer->getSessionsList()->at(0));
2297         }
2298     }
2299 
2300     if ( !defaultSession&& startHidden )
2301     {
2302         startHidden=false;
2303         slotResize();
2304         show();
2305         activateWindow();
2306         raise();
2307 
2308     }
2309     if ( defaultSession )
2310     {
2311         bool sfound=false;
2312         defaultSession=false;
2313         if ( defaultSessionId.length() >0 )
2314         {
2315             for ( int i=0; i< sessionExplorer->getSessionsList()->size(); ++i )
2316             {
2317                 if ( sessionExplorer->getSessionsList()->at(i)->id() ==defaultSessionId )
2318                 {
2319                     sessionExplorer->setCurrrentPath(sessionExplorer->getSessionsList()->at(i)->getPath());
2320                     sessionExplorer->placeButtons();
2321                     sfound=true;
2322                     slotSelectedFromList ( sessionExplorer->getSessionsList()->at(i) );
2323                     break;
2324                 }
2325             }
2326         }
2327         else
2328         {
2329             QString normalDefaultSName=defaultSessionName.split("/",QString::SkipEmptyParts).join("/");
2330             for ( int i=0; i<sessionExplorer->getSessionsList()->size(); ++i )
2331             {
2332                 QString normalName=(sessionExplorer->getSessionsList()->at(i)->getPath()+"/"+sessionExplorer->getSessionsList()->at(i)->name());
2333                 normalName=normalName.split("/",QString::SkipEmptyParts).join("/");
2334                 if ( normalName == normalDefaultSName )
2335                 {
2336                     sessionExplorer->setCurrrentPath(sessionExplorer->getSessionsList()->at(i)->getPath());
2337                     sessionExplorer->placeButtons();
2338                     sfound=true;
2339                     uname->setText ( sessionExplorer->getSessionsList()->at(i)->name() );
2340                     QTimer::singleShot (
2341                         100, this,
2342                         SLOT ( slotUnameEntered() ) );
2343                     slotSnameChanged ( defaultSessionName );
2344                     break;
2345                 }
2346             }
2347         }
2348         if ( !sfound && startHidden )
2349         {
2350             startHidden=false;
2351             slotResize();
2352             show();
2353             activateWindow();
2354             raise();
2355         }
2356     }
2357     delete st;
2358 }
2359 
2360 
slotNewSession()2361 void ONMainWindow::slotNewSession()
2362 {
2363     if(X2goSettings::centralSettings())
2364         return;
2365     QString id=QDateTime::currentDateTime().
2366                toString ( "yyyyMMddhhmmsszzz" );
2367     EditConnectionDialog dlg (true, id, this );
2368     if ( dlg.exec() ==QDialog::Accepted )
2369     {
2370         SessionButton* bt=sessionExplorer->createBut ( id );
2371         sessionExplorer->placeButtons();
2372         users->ensureVisible ( bt->x(),bt->y(),50,220 );
2373     }
2374 }
2375 
slotManage()2376 void ONMainWindow::slotManage()
2377 {
2378     SessionManageDialog dlg ( this );
2379     dlg.exec();
2380 }
2381 
slotCreateSessionIcon()2382 void ONMainWindow::slotCreateSessionIcon()
2383 {
2384     SessionManageDialog dlg ( this,true );
2385     dlg.exec();
2386 }
2387 
2388 
displayToolBar(bool show)2389 void ONMainWindow::displayToolBar ( bool show )
2390 {
2391     X2goSettings st1 ( "settings" );
2392 
2393     st1.setting()->setValue ( "toolbar/show",show );
2394     st1.setting()->sync();
2395 }
2396 
2397 
initLdapSession(bool showError)2398 bool ONMainWindow::initLdapSession ( bool showError )
2399 {
2400 #ifdef USELDAP
2401 
2402     x2goDebug<<"Initializing LDAP sessions ...";
2403 
2404     try
2405     {
2406         ld=new LDAPSession ( ldapServer.toStdString(),
2407                              ldapPort,"","",true,false );
2408     }
2409     catch ( LDAPExeption e )
2410     {
2411         QString message="Exception0 in: ";
2412         message=message+e.err_type.c_str();
2413         message=message+" : "+e.err_str.c_str();
2414 
2415         x2goDebug<<message;
2416 
2417         if ( ldapServer1.length() )
2418         {
2419             try
2420             {
2421                 ld=new LDAPSession ( ldapServer1.toStdString(),
2422                                      ldapPort1,"","",
2423                                      true,false );
2424             }
2425             catch ( LDAPExeption e )
2426             {
2427                 QString message="Exception1 in: ";
2428                 message=message+e.err_type.c_str();
2429                 message=message+" : "+e.err_str.c_str();
2430 
2431                 x2goDebug<<message;
2432 
2433                 if ( ldapServer2.length() )
2434                 {
2435                     try
2436                     {
2437                         ld=new LDAPSession (
2438                             ldapServer2.toStdString(),
2439                             ldapPort2,"","",
2440                             true,false );
2441                     }
2442                     catch ( LDAPExeption e )
2443                     {
2444                         QString message=
2445                             "Exception2 in: ";
2446                         message=message+
2447                                 e.err_type.c_str();
2448                         message=message+" : "+
2449                                 e.err_str.c_str();
2450 
2451                         x2goDebug<<message;
2452                         if ( showError )
2453                             QMessageBox::critical (
2454                                 0l,tr ( "Error" ),
2455                                 message,
2456                                 QMessageBox::Ok,
2457                                 QMessageBox::
2458                                 NoButton );
2459 
2460                         x2goDebug<<"Returning false, 3rd try failed.";
2461                         return false;
2462                     }
2463                 }
2464                 else
2465                 {
2466                     x2goDebug<<"Returning false.";
2467 
2468                     if ( showError )
2469                         QMessageBox::critical (
2470                             0l,tr ( "Error" ),
2471                             message, QMessageBox::Ok,
2472                             QMessageBox::NoButton );
2473 
2474                     return false;
2475                 }
2476 
2477             }
2478         }
2479         else
2480         {
2481             x2goDebug<<"Returning false.";
2482 
2483             if ( showError )
2484                 QMessageBox::critical ( 0l,tr ( "Error" ),
2485                                         message,QMessageBox::Ok,
2486                                         QMessageBox::NoButton );
2487 
2488             return false;
2489         }
2490 
2491     }
2492     sessionCmd="/usr/bin/startkde";
2493     LDAPSndSys="ARTS_SERVER";
2494     LDAPSndStartServer=true;
2495     startSound=false;
2496     firstUid=0;
2497     lastUid=65535;
2498 
2499 
2500     list<string> attr;
2501     attr.push_back ( SESSIONCMD );
2502     attr.push_back ( FIRSTUID );
2503     attr.push_back ( LASTUID );
2504 
2505     list<LDAPStringEntry> res;
2506     QString searchBase="ou=Settings,ou=ON,"+ldapDn;
2507     QString srch="cn=session settings";
2508     try
2509     {
2510         ld->stringSearch ( searchBase.toStdString(),attr,
2511                            srch.toStdString(),res );
2512     }
2513     catch ( LDAPExeption e )
2514     {
2515         QString message="Exception in: ";
2516         message=message+e.err_type.c_str();
2517         message=message+" : "+e.err_str.c_str();
2518         QMessageBox::critical ( 0l,tr ( "Error" ),message,
2519                                 QMessageBox::Ok,
2520                                 QMessageBox::NoButton );
2521         return false;
2522     }
2523 
2524     if ( res.size() !=0 )
2525     {
2526         LDAPStringEntry entry=res.front();
2527         list<string> str=LDAPSession::getStringAttrValues (
2528                              entry,SESSIONCMD );
2529         if ( str.size() )
2530         {
2531             sessionCmd=str.front().c_str();
2532         }
2533         str=LDAPSession::getStringAttrValues ( entry,FIRSTUID );
2534         if ( str.size() )
2535         {
2536             firstUid= ( ( QString ) str.front().c_str() ).toInt();
2537         }
2538         str=LDAPSession::getStringAttrValues ( entry,LASTUID );
2539         if ( str.size() )
2540         {
2541             lastUid= ( ( QString ) str.front().c_str() ).toInt();
2542         }
2543     }
2544     attr.clear();
2545     res.clear();
2546     attr.push_back ( NETSOUNDSYSTEM );
2547     attr.push_back ( SNDSUPPORT );
2548     attr.push_back ( SNDPORT );
2549     attr.push_back ( STARTSNDSERVER );
2550 
2551 
2552     srch="cn=sound settings";
2553     try
2554     {
2555         ld->stringSearch ( searchBase.toStdString(),attr,
2556                            srch.toStdString(),res );
2557     }
2558     catch ( LDAPExeption e )
2559     {
2560         QString message="Exception in: ";
2561         message=message+e.err_type.c_str();
2562         message=message+" : "+e.err_str.c_str();
2563         QMessageBox::critical ( 0l,tr ( "Error" ),message,
2564                                 QMessageBox::Ok,
2565                                 QMessageBox::NoButton );
2566         return false;
2567     }
2568 
2569     if ( res.size() !=0 )
2570     {
2571         LDAPStringEntry entry=res.front();
2572         list<string> str=LDAPSession::getStringAttrValues (
2573                              entry,NETSOUNDSYSTEM );
2574         if ( str.size() )
2575         {
2576             LDAPSndSys=str.front().c_str();
2577         }
2578         if ( LDAPSndSys=="PULSE" )
2579         {
2580             LDAPSndSys="pulse";
2581             LDAPSndStartServer=false;
2582             LDAPSndPort="4713";
2583         }
2584         if ( LDAPSndSys=="ARTS_SERVER" )
2585         {
2586             LDAPSndPort="20221";
2587             LDAPSndSys="arts";
2588         }
2589         if ( LDAPSndSys=="ESPEAKER" )
2590         {
2591             LDAPSndPort="16001";
2592             LDAPSndSys="esd";
2593         }
2594         str=LDAPSession::getStringAttrValues ( entry,SNDSUPPORT );
2595         if ( str.size() )
2596         {
2597             startSound= ( str.front() =="yes" ) ?true:false;
2598         }
2599         str=LDAPSession::getStringAttrValues ( entry,SNDPORT );
2600         if ( str.size() )
2601         {
2602             LDAPSndPort=str.front().c_str();
2603         }
2604         str=LDAPSession::getStringAttrValues ( entry,STARTSNDSERVER );
2605         if ( str.size() )
2606         {
2607             LDAPSndStartServer=
2608                 ( str.front() =="yes" ) ?true:false;
2609         }
2610     }
2611 #endif
2612     x2goDebug<<"Initialized LDAP sessions.";
2613     return true;
2614 
2615 }
2616 
2617 
2618 
slotSnameChanged(const QString & text)2619 void ONMainWindow::slotSnameChanged ( const QString& text )
2620 {
2621     if ( prevText==text )
2622         return;
2623     if ( text=="" )
2624         return;
2625     QList<SessionButton*>::iterator it;
2626     QList<SessionButton*>::iterator endit=sessionExplorer->getSessionsList()->end();
2627     for ( it=sessionExplorer->getSessionsList()->begin(); it!=endit; it++ )
2628     {
2629         if((*it)->getPath()!=sessionExplorer->getCurrentPath())
2630             continue;
2631         QString name= ( *it )->name();
2632         if ( name.indexOf ( text,0,Qt::CaseInsensitive ) ==0 )
2633         {
2634             QPoint pos= ( *it )->pos();
2635             uname->setText ( name );
2636             QScrollBar* bar=users->verticalScrollBar();
2637             int docLang=bar->maximum()-bar->minimum() +
2638                         bar->pageStep();
2639             double position= ( double ) ( pos.y() ) /
2640                              ( double ) ( uframe->height() );
2641             bar->setValue ( ( int ) ( docLang*position-height() /
2642                                       2+ ( *it )->height() /2 ) );
2643             uname->setSelection ( name.length(),
2644                                   text.length()-name.length() );
2645             break;
2646         }
2647     }
2648     prevText=text;
2649 }
2650 
2651 
slotSelectedFromList(SessionButton * session)2652 void ONMainWindow::slotSelectedFromList ( SessionButton* session )
2653 {
2654     pass->setText ( "" );
2655     sessionExplorer->setLastSession(session);
2656     QString command;
2657     QString server;
2658     QString userName;
2659     bool autologin=false;
2660     bool krblogin=false;
2661     bool usebrokerpass=false;
2662     QString sessIcon;
2663     QPalette pal;
2664     QString sessionName;
2665     if ( !embedMode )
2666     {
2667         session->hide();
2668         pal=users->palette();
2669         setUsersEnabled ( false );
2670         sessionName=session->name();
2671 
2672         QString sid=session->id();
2673         X2goSettings* st;
2674         if (brokerMode)
2675         {
2676             st=new X2goSettings( config.iniFile, QSettings::IniFormat );
2677         }
2678         else
2679         {
2680             st = new X2goSettings( "sessions" );
2681         }
2682 
2683 
2684 
2685         sessIcon = wrap_legacy_resource_URIs (st->setting()->value (sid+"/icon",
2686                                                                     (QVariant) ":/img/icons/128x128/x2gosession.png"
2687                                                                    ).toString ());
2688         sessIcon = expandHome(sessIcon);
2689 
2690         command=st->setting()->value (
2691                     sid+"/command",
2692                     ( QVariant ) tr ( "KDE" ) ).toString();
2693 
2694         server=st->setting()->value ( sid+"/host",
2695                                       ( QVariant ) QString::null
2696                                     ).toString();
2697         userName=st->setting()->value (
2698                      sid+"/user",
2699                      ( QVariant ) QString::null ).toString();
2700         if (defaultUser && userName.length()<1)
2701             userName=defaultUserName;
2702 
2703         if(brokerMode)
2704             usebrokerpass=st->setting()->value (
2705                               sid+"/usebrokerpass",
2706                               false ).toBool();
2707 
2708 
2709         sshPort=st->setting()->value (
2710                     sid+"/sshport",
2711                     ( QVariant ) defaultSshPort ).toString();
2712         currentKey=st->setting()->value (
2713                        sid+"/key",
2714                        ( QVariant ) QString::null ).toString();
2715         currentKey=expandHome(currentKey);
2716 
2717         autologin=st->setting()->value (
2718                       sid+"/autologin",
2719                       ( QVariant ) false ).toBool();
2720 #ifdef Q_OS_UNIX
2721         if(command =="XDMCP" && st->setting()->value (
2722                       sid+"/directxdmcp",
2723                       ( QVariant ) false ).toBool())
2724              autologin=true;
2725 #endif
2726         krblogin=st->setting()->value (
2727                      sid+"/krblogin",
2728                      ( QVariant ) false ).toBool();
2729         delete st;
2730 #ifdef Q_OS_WIN
2731         if ( portable &&
2732                 u3Device.length() >0 )
2733         {
2734             currentKey.replace ( "(U3)",u3Device );
2735         }
2736 #endif
2737     }
2738     else
2739     {
2740         command=config.command;
2741         server=config.server;
2742         userName=config.user;
2743         sshPort=config.sshport;
2744         sessIcon=":/img/icons/128x128/x2gosession.png";
2745         sessionName=config.session;
2746         currentKey=config.key;
2747     }
2748 
2749     selectedCommand=command.split("/").last();
2750     command=transAppName ( command );
2751     login->setText ( userName );
2752     x2goDebug << "Creating QPixmap with session icon: '" << sessIcon << "'.";
2753     QPixmap pix ( sessIcon );
2754     if ( !miniMode )
2755     {
2756         fotoLabel->setPixmap (
2757             pix.scaled ( 64,64,
2758                          Qt::IgnoreAspectRatio,
2759                          Qt::SmoothTransformation ) );
2760         fotoLabel->setFixedSize ( 64,64 );
2761     }
2762     else
2763     {
2764         fotoLabel->setPixmap (
2765             pix.scaled ( 48,48,
2766                          Qt::IgnoreAspectRatio,
2767                          Qt::SmoothTransformation ) );
2768         fotoLabel->setFixedSize ( 48,48 );
2769     }
2770 
2771     if(currentKey.length()<=0)
2772     {
2773         currentKey=findSshKeyForServer(userName, server, sshPort);
2774     }
2775 
2776 
2777     if ( command=="RDP" )
2778     {
2779         command=tr ( "RDP connection" );
2780     }
2781     if ( command=="XDMCP" )
2782     {
2783         command=tr ( "XDMCP" );
2784     }
2785     if ( command=="SHADOW" )
2786     {
2787         command=tr ( "Connection to local desktop" );
2788     }
2789 
2790     QString text="<b>"+sessionName +"</b><br>"+
2791                  command+tr ( " on " ) +server;
2792     nameLabel->setText ( text );
2793     if ( userName.length() <=0 )
2794         login->setFocus();
2795 
2796     bool nopass=false;
2797     if ( !embedMode )
2798         slotShowPassForm();
2799 
2800 
2801 ///////////////////////////////////////////////////
2802 
2803     if ( currentKey.length() >0 )
2804     {
2805         nopass=true;
2806     }
2807     if(brokerMode &&usebrokerpass)
2808     {
2809         pass->setText(config.brokerPass);
2810         slotSessEnter();
2811     }
2812     else if ( currentKey != QString::null && currentKey != "" && nopass )
2813     {
2814         x2goDebug<<"Starting session with key.";
2815         slotSessEnter();
2816     }
2817     else if ( cardReady || autologin || krblogin  )
2818     {
2819         x2goDebug<<"Starting session via Smart Card, SSH Agent or Kerberos token.";
2820         nopass=true;
2821         if ( cardReady )
2822             login->setText ( cardLogin );
2823         slotSessEnter();
2824         return;
2825     }
2826     if ( startHidden && nopass==false )
2827     {
2828         startHidden=false;
2829         slotResize();
2830         show();
2831         activateWindow();
2832         raise();
2833     }
2834     if ( embedMode )
2835     {
2836         QTimer::singleShot ( 50, this,
2837                              SLOT ( slotShowPassForm() ) );
2838     }
2839 }
2840 
2841 
startSshConnection(QString host,QString port,bool acceptUnknownHosts,QString login,QString password,bool autologin,bool krbLogin,bool getSrv,bool useproxy,SshMasterConnection::ProxyType type,QString proxyserver,quint16 proxyport,QString proxylogin,QString proxypassword,QString proxyKey,bool proxyAutologin,bool proxyKrbLogin)2842 SshMasterConnection* ONMainWindow::startSshConnection ( QString host, QString port, bool acceptUnknownHosts,
2843         QString login,
2844         QString password, bool autologin, bool krbLogin, bool getSrv, bool useproxy,
2845         SshMasterConnection::ProxyType type,
2846         QString proxyserver, quint16 proxyport,
2847         QString proxylogin, QString proxypassword, QString proxyKey,
2848         bool proxyAutologin, bool proxyKrbLogin)
2849 {
2850     x2goInfof(8)<<tr("Starting connection to server: ") + host + ":" + port;
2851     SshMasterConnection* con;
2852 
2853     x2goDebug<<"Starting new ssh connection to server:"<<host<<":"<<port<<" krbLogin: "<<krbLogin;
2854 
2855 
2856     if ( usePGPCard/*||useSshAgent*/ )
2857         autologin=true;
2858     if ( cardReady )
2859         cardStarted=true;
2860 
2861 
2862     /////key/sshagent/env/
2863 
2864     passForm->setEnabled ( false );
2865     if(cmdAutologin)
2866     {
2867         autologin=true;
2868     }
2869 
2870 
2871     con=new SshMasterConnection (this, host, port.toInt(),acceptUnknownHosts,
2872                                  login, password,currentKey, autologin, krbLogin,useproxy,
2873                                  type, proxyserver, proxyport, proxylogin, proxypassword, proxyKey,proxyAutologin, proxyKrbLogin);
2874     if (!getSrv)
2875         connect ( con, SIGNAL ( connectionOk(QString) ), this, SLOT ( slotSshConnectionOk() ) );
2876     else
2877         connect ( con, SIGNAL ( connectionOk(QString)), this, SLOT ( slotServSshConnectionOk(QString) ) );
2878 
2879     qRegisterMetaType<SshMasterConnection::passphrase_types> ("SshMasterConnection::passphrase_types");
2880 
2881     connect ( con, SIGNAL ( serverAuthError ( int,QString, SshMasterConnection* ) ),this,
2882               SLOT ( slotSshServerAuthError ( int,QString, SshMasterConnection* ) ) );
2883     connect ( con, SIGNAL ( needPassPhrase(SshMasterConnection*, SshMasterConnection::passphrase_types)),this,
2884               SLOT ( slotSshServerAuthPassphrase(SshMasterConnection*, SshMasterConnection::passphrase_types)) );
2885     connect ( con, SIGNAL ( needChallengeResponse(SshMasterConnection*, QString)),this,
2886               SLOT ( slotSshServerAuthChallengeResponse(SshMasterConnection*, QString)) );
2887     connect ( con, SIGNAL ( userAuthError ( QString ) ),this,SLOT ( slotSshUserAuthError ( QString ) ) );
2888     connect ( con, SIGNAL ( connectionError ( QString,QString ) ), this,
2889               SLOT ( slotSshConnectionError ( QString,QString ) ) );
2890     connect ( con, SIGNAL(startInteraction(SshMasterConnection*,QString)),this,
2891                SLOT(slotSshInteractionStart(SshMasterConnection*,QString)) );
2892     connect ( con, SIGNAL(updateInteraction(SshMasterConnection*,QString)),this,
2893               SLOT(slotSshInteractionUpdate(SshMasterConnection*,QString)) );
2894     connect (con, SIGNAL(finishInteraction(SshMasterConnection*)),this, SLOT(slotSshInteractionFinish(SshMasterConnection*)));
2895     connect ( interDlg, SIGNAL(textEntered(QString)), con, SLOT(interactionTextEnter(QString)));
2896     connect ( interDlg, SIGNAL(interrupt()), con, SLOT(interactionInterruptSlot()));
2897     con->start();
2898     return con;
2899 }
2900 
slotSshConnectionError(QString message,QString lastSessionError)2901 void ONMainWindow::slotSshConnectionError ( QString message, QString lastSessionError )
2902 {
2903     x2goErrorf(2)<< tr("Connection error: ") + message + ": " + lastSessionError;
2904     if ( sshConnection )
2905     {
2906         sshConnection->wait();
2907         delete sshConnection;
2908         sshConnection=0l;
2909     }
2910 
2911     if (!startHidden)
2912     {
2913         QMessageBox::critical ( 0l,message,lastSessionError,
2914                                 QMessageBox::Ok,
2915                                 QMessageBox::NoButton );
2916         setEnabled ( true );
2917         passForm->setEnabled ( true );
2918         slotShowPassForm();
2919         pass->setFocus();
2920         pass->selectAll();
2921 
2922 
2923         passForm->setEnabled ( true );
2924     }
2925     else
2926     {
2927         // In order to get this interaction free, we need to free this from windows and stuff
2928         //    if ( startHidden )
2929         //    {
2930         //        startHidden=false;
2931         //        slotResize();
2932         //        show();
2933         //        activateWindow();
2934         //        raise();
2935         //    }
2936 
2937         // completely quit the application
2938         trayQuit();
2939     }
2940 }
2941 
2942 
2943 
2944 
slotSshConnectionOk()2945 void ONMainWindow::slotSshConnectionOk()
2946 {
2947     x2goDebug<<"SSH connection established.";
2948     passForm->setEnabled ( true );
2949     if ( useLdap )
2950     {
2951         continueLDAPSession();
2952     }
2953     else
2954     {
2955         if(brokerMode && (connectionType != DEFAULT))
2956         {
2957             if(connectionType==SUSPEND)
2958             {
2959                 suspendSession(suspendTerminateSessionFromBroker);
2960             }
2961             else
2962             {
2963                 termSession(suspendTerminateSessionFromBroker, false);
2964             }
2965         }
2966         else
2967             continueNormalSession();
2968     }
2969 }
2970 
cleanServerSshConnections()2971 void ONMainWindow::cleanServerSshConnections()
2972 {
2973     for(int i=serverSshConnections.size()-1;i>=0;--i)
2974     {
2975         if(serverSshConnections[i]!=sshConnection)
2976         {
2977             delete serverSshConnections[i];
2978         }
2979     }
2980     serverSshConnections.clear();
2981 }
2982 
2983 
findServerSshConnection(QString host)2984 SshMasterConnection*  ONMainWindow::findServerSshConnection(QString host)
2985 {
2986     x2goDebug<<"Searching for SSH connections ...";
2987     for (int i=0; i<serverSshConnections.count(); ++i)
2988     {
2989         if (serverSshConnections[i])
2990         {
2991             if (serverSshConnections[i]->getHost()==host)
2992             {
2993                 x2goDebug<<"Found SSH connection.";
2994                 return serverSshConnections[i];
2995             }
2996         }
2997     }
2998     x2goWarningf(3)<< tr("Couldn't find an SSH connection.");
2999     return 0l;
3000 }
3001 
slotServSshConnectionOk(QString server)3002 void ONMainWindow::slotServSshConnectionOk(QString server)
3003 {
3004     SshMasterConnection* con=findServerSshConnection(server);
3005     if (!con)
3006         return;
3007     x2goDebug<<"Getting sessions on host: " + server;
3008     con->executeCommand( "x2golistsessions", this, SLOT (slotListAllSessions ( bool,QString,int ) ));
3009 }
3010 
slotSshInteractionFinish(SshMasterConnection * connection)3011 void ONMainWindow::slotSshInteractionFinish(SshMasterConnection* connection)
3012 {
3013     if(interDlg->isInterrupted())
3014     {
3015           slotCloseInteractionDialog();
3016     }
3017     else
3018     {
3019          interDlg->setDisplayMode();
3020     }
3021 }
3022 
slotCloseInteractionDialog()3023 void ONMainWindow::slotCloseInteractionDialog()
3024 {
3025     if(interDlg->getInteractionMode()==InteractionDialog::SESSION)
3026     {
3027           x2goDebug<<"Closed SSH Session interaction";
3028           slotSshUserAuthError("NO_ERROR");
3029     }
3030     else
3031     {
3032         x2goDebug<<"Closed SSH Broker interaction";
3033         if(broker)
3034         {
3035 	    interDlg->hide();
3036             broker->closeSSHInteractionDialog();
3037         }
3038     }
3039 }
3040 
3041 
slotSshInteractionStart(SshMasterConnection * connection,QString prompt)3042 void ONMainWindow::slotSshInteractionStart(SshMasterConnection* connection, QString prompt)
3043 {
3044     sessionStatusDlg->hide();
3045     interDlg->show();
3046     interDlg->reset();
3047     interDlg->appendText(prompt);
3048 
3049     setEnabled(true);
3050     interDlg->setEnabled(true);
3051     x2goDebug<<"SSH Session prompt:"<<prompt;
3052     if(connection==sshConnection)
3053     {
3054          x2goDebug<<"SSH Session interaction";
3055 	 interDlg->setInteractionMode(InteractionDialog::SESSION);
3056     }
3057     else
3058     {
3059 	 interDlg->setInteractionMode(InteractionDialog::BROKER);
3060          x2goDebug<<"SSH Broker interaction";
3061     }
3062 }
3063 
slotSshInteractionUpdate(SshMasterConnection * connection,QString output)3064 void ONMainWindow::slotSshInteractionUpdate(SshMasterConnection* connection, QString output)
3065 {
3066     if(connection==sshConnection)
3067     {
3068          x2goDebug<<"SSH Session interaction";
3069 	 interDlg->setInteractionMode(InteractionDialog::SESSION);
3070     }
3071     else
3072     {
3073 	 interDlg->setInteractionMode(InteractionDialog::BROKER);
3074          x2goDebug<<"SSH Broker interaction";
3075     }
3076     interDlg->appendText(output);
3077     x2goDebug<<"SSH Interaction update:"<<output;
3078 }
3079 
slotSshServerAuthPassphrase(SshMasterConnection * connection,SshMasterConnection::passphrase_types passphrase_type)3080 void ONMainWindow::slotSshServerAuthPassphrase(SshMasterConnection* connection, SshMasterConnection::passphrase_types passphrase_type)
3081 {
3082     bool ok;
3083     QString message;
3084 
3085     switch (passphrase_type) {
3086         case SshMasterConnection::PASSPHRASE_PRIVKEY:
3087                                                         message = tr ("Enter passphrase to decrypt a key");
3088                                                         ok = true;
3089                                                         break;
3090         case SshMasterConnection::PASSPHRASE_CHALLENGE:
3091                                                         message = tr ("Verification code:");
3092                                                         ok = true;
3093                                                         break;
3094         case SshMasterConnection::PASSPHRASE_PASSWORD:
3095                                                         message = tr ("Enter user account password:");
3096                                                         ok = true;
3097                                                         break;
3098         default:
3099                                                         x2goDebug << "Unknown passphrase type requested! Was: " << passphrase_type << endl;
3100                                                         ok = false;
3101                                                         break;
3102     }
3103 
3104     if (ok) {
3105         QString phrase = QInputDialog::getText (0, connection->getUser () + "@" + connection->getHost () + ":" + QString::number (connection->getPort ()),
3106                                                 message, QLineEdit::Password, QString (""), &ok);
3107         if (!ok) {
3108             phrase = QString ("");
3109         }
3110         connection->setKeyPhrase (phrase);
3111         if(isHidden ()) {
3112             show ();
3113             QTimer::singleShot (1, this, SLOT (hide ()));
3114         }
3115     }
3116 }
3117 
3118 
slotSshServerAuthChallengeResponse(SshMasterConnection * connection,QString challenge)3119 void ONMainWindow::slotSshServerAuthChallengeResponse(SshMasterConnection* connection, QString challenge)
3120 {
3121     bool ok = false;
3122     QString message;
3123 
3124     message = challenge;
3125 
3126     QString phrase = QInputDialog::getText (0, connection->getUser () + "@" + connection->getHost () + ":" + QString::number (connection->getPort ()),
3127                                             message, QLineEdit::Password, QString::null, &ok);
3128     if (!ok) {
3129         phrase = QString::null;
3130     }
3131     else {
3132         if (phrase == QString::null) {
3133             phrase = "";
3134         }
3135     }
3136 
3137     connection->setKeyPhrase (phrase);
3138 
3139     if (isHidden ()) {
3140         show ();
3141         QTimer::singleShot (1, this, SLOT (hide ()));
3142     }
3143 }
3144 
3145 
slotSshServerAuthError(int error,QString sshMessage,SshMasterConnection * connection)3146 void ONMainWindow::slotSshServerAuthError ( int error, QString sshMessage, SshMasterConnection* connection )
3147 {
3148     interDlg->hide();
3149     if ( startHidden )
3150     {
3151         startHidden=false;
3152         slotResize();
3153         show();
3154         activateWindow();
3155         raise();
3156     }
3157     QString errMsg;
3158     switch ( error )
3159     {
3160     case SSH_SERVER_KNOWN_CHANGED:
3161         errMsg=tr ( "Host key for server changed.\nIt is now: " ) +sshMessage+"\n"+
3162                tr ( "This can be an indication of a man-in-the-middle attack.\n"
3163                     "Somebody might be eavesdropping on you.\n"
3164                     "For security reasons, it is recommended to stop the connection attempt.\n"
3165                     "Do you want to terminate the connection?\n" );
3166         if (QMessageBox::warning (0, tr ("Host key verification failed."),
3167                                   errMsg, QMessageBox::Yes | QMessageBox::No,
3168                                   QMessageBox::No) == QMessageBox::Yes)
3169         {
3170             connection->writeKnownHosts(false);
3171             connection->wait();
3172             if(sshConnection && sshConnection !=connection)
3173             {
3174                 sshConnection->wait();
3175                 delete sshConnection;
3176             }
3177             slotSshUserAuthError ( tr ( "Host key verification failed." ) );
3178             sshConnection=0;
3179             return;
3180         }
3181         else
3182         {
3183             errMsg = tr( "If you accept the new host key the security of your "
3184                          "connection may be compromised.\n"
3185                          "Do you want to update the host key?" );
3186         }
3187         break;
3188     case SSH_SERVER_FOUND_OTHER:
3189         errMsg=tr ( "The host key for this server was not found but another "
3190                     "type of key exists. An attacker might have changed the default server key to "
3191                     "trick your client into thinking the key does not exist yet.\n"
3192                     "For security reasons, it is recommended to stop the connection attempt.\n"
3193                     "Do you want to terminate the connection?\n");
3194         if (QMessageBox::warning (0, tr ("Host key verification failed."),
3195                                   errMsg, QMessageBox::Yes | QMessageBox::No,
3196                                   QMessageBox::No) == QMessageBox::Yes)
3197         {
3198             connection->writeKnownHosts(false);
3199             connection->wait();
3200             if(sshConnection && sshConnection !=connection)
3201             {
3202                 sshConnection->wait();
3203                 delete sshConnection;
3204             }
3205             slotSshUserAuthError ( tr ( "Host key verification failed." ) );
3206             sshConnection=0;
3207             return;
3208         }
3209         else
3210         {
3211             errMsg = tr( "If you accept the new host key the security of your "
3212                          "connection may be compromised.\n"
3213                          "Do you want to update the host key?" );
3214         }
3215         break;
3216     case SSH_SERVER_ERROR:
3217         connection->writeKnownHosts(false);
3218         connection->wait();
3219         if(sshConnection && sshConnection !=connection)
3220         {
3221             sshConnection->wait();
3222             delete sshConnection;
3223         }
3224         sshConnection=0;
3225         slotSshUserAuthError ( sshMessage );
3226         return ;
3227     case SSH_SERVER_FILE_NOT_FOUND:
3228         errMsg=tr ( "Could not find known hosts file. "
3229                     "If you accept the host key here, the file will be automatically created." );
3230         break;
3231 
3232     case SSH_SERVER_NOT_KNOWN:
3233         errMsg=tr ( "The server is unknown. Do you trust the host key?\nPublic key hash: " ) +sshMessage;
3234         break;
3235     }
3236 
3237     if (QMessageBox::warning (this, tr ("Host key verification failed."),
3238                               errMsg, QMessageBox::Yes | QMessageBox::No,
3239                               QMessageBox::No) == QMessageBox::No)
3240     {
3241         connection->writeKnownHosts(false);
3242         connection->wait();
3243         if(sshConnection && sshConnection !=connection)
3244         {
3245             sshConnection->wait();
3246             delete sshConnection;
3247         }
3248         sshConnection=0;
3249         slotSshUserAuthError ( tr ( "Host key verification failed." ) );
3250         return;
3251     }
3252     connection->writeKnownHosts(true);
3253     connection->wait();
3254     connection->start();
3255 }
3256 
slotSshUserAuthError(QString error)3257 void ONMainWindow::slotSshUserAuthError ( QString error )
3258 {
3259     interDlg->hide();
3260     if ( sshConnection )
3261     {
3262         sshConnection->wait();
3263         delete sshConnection;
3264         sshConnection=0l;
3265     }
3266 
3267     //    if ( startHidden )
3268     //    {
3269     //        startHidden=false;
3270     //        slotResize();
3271     //        show();
3272     //        activateWindow();
3273     //        raise();
3274     //    }
3275     // hidden means hidden, we'll close the client afterwards.
3276     if ( startHidden )
3277     {
3278         x2goErrorf(3)<< tr("Authentication failed: ") + error;
3279         trayQuit();
3280     }
3281 
3282     if(error != "NO_ERROR")
3283         QMessageBox::critical (0l, tr ("Authentication failed."),
3284                                error, QMessageBox::Ok,
3285                                QMessageBox::NoButton);
3286     setEnabled ( true );
3287     passForm->setEnabled ( true );
3288     slotShowPassForm();
3289     pass->setFocus();
3290     pass->selectAll();
3291 
3292 
3293 
3294     passForm->setEnabled ( true );
3295 }
3296 
slotSessEnter()3297 void ONMainWindow::slotSessEnter()
3298 {
3299 
3300     if ( useLdap )
3301     {
3302         slotPassEnter();
3303         return;
3304     }
3305     if (brokerMode)
3306     {
3307         if (!config.brokerAuthenticated)
3308         {
3309 
3310             x2goDebug<<"Starting broker request.";
3311             slotStartBroker();
3312             return;
3313         }
3314     }
3315 
3316     if ((brokerMode || !embedMode) && !(sessionExplorer->getLastSession())) {
3317         x2goDebug << "No session selected, returning without starting a session.";
3318         return;
3319     }
3320 
3321     resumingSession.sessionId=QString::null;
3322     resumingSession.server=QString::null;
3323     resumingSession.display=QString::null;
3324     setStatStatus ( tr ( "connecting" ) );
3325 
3326     if(brokerMode)
3327     {
3328         if (config.brokerNoAuth && brokerNoauthWithSessionUsername) {
3329             config.brokerUser = login->text();
3330         }
3331 #ifdef Q_OS_UNIX
3332         X2goSettings* st=new X2goSettings(config.iniFile, QSettings::IniFormat);
3333         QString sid=sessionExplorer->getLastSession()->id();
3334         QString cmd=st->setting()->value ( sid+"/command",
3335                                            ( QVariant ) QString::null ).toString();
3336         directRDP=(st->setting()->value ( sid+"/directrdp",
3337                                                ( QVariant ) false ).toBool() && cmd == "RDP");
3338 
3339         if (cmd =="RDP" && directRDP)
3340         {
3341             x2goDebug<<"Starting direct RDP Session from broker";
3342             startSession ( sid );
3343             return;
3344         }
3345 
3346         directRDP=(st->setting()->value ( sid+"/directxdmcp",
3347                                                ( QVariant ) false ).toBool() && cmd == "RDP");
3348 
3349         if (cmd =="XDMCP" && directRDP)
3350         {
3351             x2goDebug<<"Starting direct RDP Session from broker";
3352             startSession ( sid );
3353             return;
3354         }
3355 #endif
3356         broker->selectUserSession(sessionExplorer->getLastSession()->id(),login->text());
3357         config.session=sessionExplorer->getLastSession()->id();
3358         setStatStatus ( tr ( "Connecting to broker" ) );
3359         stInfo->insertPlainText ( "broker url: "+config.brokerurl );
3360         setEnabled ( false );
3361         uname->hide();
3362         u->hide();
3363         return;
3364     }
3365 
3366     QString sid="";
3367     if ( !embedMode )
3368         sid=sessionExplorer->getLastSession()->id();
3369     startSession ( sid );
3370 }
3371 
continueNormalSession()3372 void ONMainWindow::continueNormalSession()
3373 {
3374     x2goDebug<<"Continue normal X2Go session";
3375 
3376     if (brokerMode && !shadowSession)
3377     {
3378         slotListSessions(true,QString::null,0);
3379         return;
3380     }
3381     if ( !shadowSession )
3382         sshConnection->executeCommand ( "x2golistsessions", this,SLOT ( slotListSessions ( bool, QString,int )));
3383     else
3384         sshConnection->executeCommand ( "x2golistdesktops", this,SLOT ( slotListSessions ( bool, QString,int )));
3385 
3386 }
3387 
continueLDAPSession()3388 void ONMainWindow::continueLDAPSession()
3389 {
3390     sshConnection->executeCommand ( "x2gogetservers", this, SLOT ( slotGetServers ( bool, QString,int ) ));
3391 }
3392 
3393 #ifdef Q_OS_UNIX
startDirectRDP()3394 void ONMainWindow::startDirectRDP()
3395 {
3396     if (!(sessionExplorer->getLastSession())) {
3397         x2goDebug << "No session selected, returning without starting a session.";
3398         return;
3399     }
3400 
3401     X2goSettings* st;
3402     if(brokerMode)
3403     {
3404         st=new X2goSettings(config.iniFile, QSettings::IniFormat);
3405     }
3406     else
3407     {
3408         st=new X2goSettings ( "sessions" );
3409     }
3410 
3411     QString sid;
3412     bool freeRDPNew=false;
3413     if ( !embedMode )
3414         sid=sessionExplorer->getLastSession()->id();
3415     else
3416         sid="embedded";
3417 
3418 
3419     bool fullscreen=st->setting()->value ( sid+"/fullscreen",
3420                                           ( QVariant )
3421                                           defaultFullscreen ).toBool();
3422     bool maxRes=st->setting()->value ( sid+"/maxdim",
3423                                       ( QVariant )
3424                                       false ).toBool();
3425     int height=st->setting()->value ( sid+"/height",
3426                                      ( QVariant ) defaultHeight ).toInt();
3427     int width=st->setting()->value ( sid+"/width",
3428                                     ( QVariant ) defaultWidth ).toInt();
3429     QString sessionType=st->setting()->value ( sid+"/command",
3430                                          ( QVariant ) "").toString();
3431 
3432     QString client=st->setting()->value ( sid+"/rdpclient",
3433                                          ( QVariant ) "rdesktop").toString();
3434     if(client=="xfreerdpnew")
3435     {
3436         client="xfreerdp";
3437         freeRDPNew=true;
3438     }
3439     QString host=st->setting()->value ( sid+"/host",
3440                                        ( QVariant ) "").toString();
3441     QString port=st->setting()->value ( sid+"/rdpport",
3442                                        ( QVariant ) "3389").toString();
3443     QString params=st->setting()->value ( sid+"/directrdpsettings",
3444                                          ( QVariant ) "").toString();
3445 
3446     QString user,password;
3447     if ((!brokerMode) || (brokerCredsForSession))
3448     {
3449         user=getCurrentUname();
3450         password=getCurrentPass();
3451     }
3452     else
3453     {
3454         user=st->setting()->value ( sid+"/user",
3455                                        ( QVariant ) "").toString();
3456     }
3457 
3458     nxproxy=new QProcess;
3459     proxyErrString="";
3460     connect ( nxproxy,SIGNAL ( error ( QProcess::ProcessError ) ),this,
3461               SLOT ( slotProxyError ( QProcess::ProcessError ) ) );
3462     connect ( nxproxy,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this,
3463               SLOT ( slotProxyFinished ( int,QProcess::ExitStatus ) ) );
3464     connect ( nxproxy,SIGNAL ( readyReadStandardError() ),this,
3465               SLOT ( slotProxyStderr() ) );
3466     connect ( nxproxy,SIGNAL ( readyReadStandardOutput() ),this,
3467               SLOT ( slotProxyStdout() ) );
3468 
3469 
3470     QString userOpt;
3471     QString passOpt;
3472     QString grOpt;
3473     QString proxyCmd;
3474     if(!freeRDPNew)
3475     {
3476         if (user.length()>0)
3477         {
3478             userOpt=" -u ";
3479             userOpt+=user+" ";
3480         }
3481         if (password.length()>0)
3482         {
3483             passOpt=" -p \"";
3484             passOpt+=password+"\" ";
3485         }
3486         if (fullscreen)
3487         {
3488             grOpt=" -f ";
3489         }
3490         else if (maxRes)
3491         {
3492             QDesktopWidget wd;
3493             grOpt=" -D -g "+QString::number( wd.screenGeometry().width())+"x"+QString::number(wd.screenGeometry().height())+" ";
3494         }
3495         else
3496         {
3497             grOpt=" -g "+QString::number(width)+"x"+QString::number(height);
3498         }
3499         proxyCmd=client +" "+params+ grOpt +userOpt+passOpt + host +":"+port ;
3500     }
3501     else
3502     {
3503         if (user.length()>0)
3504         {
3505             userOpt=" /u:";
3506             userOpt+=user+" ";
3507         }
3508         if (password.length()>0)
3509         {
3510             passOpt=" /p:\"";
3511             passOpt+=password+"\" ";
3512         }
3513         if (fullscreen)
3514         {
3515             grOpt=" /f ";
3516         }
3517         else if (maxRes)
3518         {
3519             QDesktopWidget wd;
3520             grOpt=" /w:"+QString::number( wd.screenGeometry().width())+" /h:"+QString::number(wd.screenGeometry().height())+" ";
3521         }
3522         else
3523         {
3524             grOpt=" /w:"+QString::number(width)+" /h:"+QString::number(height);
3525         }
3526         proxyCmd= client +" "+params+ grOpt +userOpt+passOpt + "/v:"+host +":"+port ;
3527     }
3528     if(sessionType=="XDMCP")
3529     {
3530         x2goDebug<<"starting direct XDMCP session";
3531         client=st->setting()->value ( sid+"/xdmcpclient",
3532                                          ( QVariant ) "Xnest").toString();
3533         params=st->setting()->value ( sid+"/directxdmcpsettings",
3534                                          ( QVariant ) "").toString();
3535         if(client == "Xephyr")
3536         {
3537             if (fullscreen)
3538             {
3539                 grOpt=" -fullscreen ";
3540             }
3541             else if (maxRes)
3542             {
3543                 QDesktopWidget wd;
3544                 grOpt=" -screen "+QString::number( wd.screenGeometry().width())+"x"+QString::number(wd.screenGeometry().height())+" ";
3545             }
3546             else
3547             {
3548                 grOpt=" -screen "+QString::number(width)+"x"+QString::number(height);
3549             }
3550         }
3551         else
3552         {
3553             if (maxRes)
3554             {
3555                 QDesktopWidget wd;
3556                 grOpt=" -geometry "+QString::number( wd.screenGeometry().width())+"x"+QString::number(wd.screenGeometry().height())+" ";
3557             }
3558             else
3559             {
3560                 grOpt=" -geometry "+QString::number(width)+"x"+QString::number(height);
3561             }
3562         }
3563         int p=0;
3564         while(true)
3565         {
3566              QString fname="/tmp/.X"+QString::number(p)+"-lock";
3567              if(QFile::exists(fname))
3568              {
3569                  ++p;
3570              }
3571              else
3572                  break;
3573         }
3574         proxyCmd= client +" "+params+ grOpt + " -query "+host +" :"+QString::number(p) ;
3575         login->setText(tr("XDM"));
3576         resumingSession.display=tr("XDMCP");
3577     }
3578     else
3579     {
3580         x2goDebug<<"starting direct RDP session";
3581         resumingSession.display=tr("RDP");
3582     }
3583 //     x2goDebug<<"starting direct session with cmd:"<<proxyCmd;
3584     nxproxy->start ( proxyCmd );
3585     resumingSession.server=host;
3586     resumingSession.sessionId=user+"-RDP-";
3587 #if QT_VERSION < 0x040700
3588     resumingSession.sessionId += QString::number(QDateTime::currentDateTime().toTime_t());
3589 #else
3590     resumingSession.sessionId += QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()/1000);
3591 #endif
3592     resumingSession.sessionId += "_stRRDP_dp24";
3593     resumingSession.display="RDP";
3594     resumingSession.command="RDP";
3595     resumingSession.crTime=QDateTime::currentDateTime().toString("dd.MM.yy HH:mm:ss");
3596     showSessionStatus();
3597     if(brokerMode)
3598     {
3599         sendEventToBroker(CONNECTED);
3600     }
3601 
3602 //     QTimer::singleShot ( 30000,this,SLOT ( slotRestartProxy() ) );
3603     proxyRunning=true;
3604     delete st;
3605 }
3606 
3607 #endif
3608 
3609 
findSshKeyForServer(QString user,QString server,QString port)3610 QString ONMainWindow::findSshKeyForServer(QString user, QString server, QString port)
3611 {
3612     foreach (sshKey key, cmdSshKeys)
3613     {
3614         if(key.server == server && key.user == user && key.port == port)
3615             return key.key;
3616     }
3617     foreach (sshKey key, cmdSshKeys)
3618     {
3619         if(key.server == server && key.user == user && key.port.length()<=0)
3620             return key.key;
3621     }
3622 
3623     foreach (sshKey key, cmdSshKeys)
3624     {
3625         if(key.server == server && key.user.length()<=0 && key.port==port)
3626             return key.key;
3627     }
3628 
3629     foreach (sshKey key, cmdSshKeys)
3630     {
3631         if(key.server == server && key.user.length()<=0 && key.port.length()<=0)
3632             return key.key;
3633     }
3634 
3635     foreach (sshKey key, cmdSshKeys)
3636     {
3637         if(key.server.length()<=0 && key.user.length()<=0 && key.port.length()<=0)
3638             return key.key;
3639     }
3640     return QString::null;
3641 }
3642 
3643 
startSession(const QString & sid,CONTYPE conType)3644 bool ONMainWindow::startSession ( const QString& sid, CONTYPE conType )
3645 {
3646     connectionType=conType;
3647     setEnabled ( false );
3648 #ifdef Q_OS_UNIX
3649     directRDP=false;
3650 #endif
3651     QString passwd;
3652     QString user;
3653     QString host;
3654     bool autologin=false;
3655     bool krblogin=false;
3656     bool krbDelegation=false;
3657 
3658     bool useproxy=false;
3659     SshMasterConnection::ProxyType proxyType= SshMasterConnection::PROXYHTTP;
3660     QString proxyserver;
3661     int proxyport=22;
3662     QString proxylogin;
3663     QString proxypassword;
3664     QString proxyKey;
3665     bool proxyAutologin=false;
3666     bool proxyKrbLogin=false;
3667 
3668     user=getCurrentUname();
3669     runRemoteCommand=true;
3670     if(!embedMode)
3671         shadowSession=false;
3672     applications.clear();
3673     removeAppsFromTray();
3674 
3675     if ( managedMode )
3676     {
3677         slotListSessions ( true, QString::null,0 );
3678         return true;
3679     }
3680 
3681     X2goSettings* st;
3682     if(!brokerMode)
3683         st=new  X2goSettings( "sessions" );
3684     else
3685         st=new X2goSettings(config.iniFile, QSettings::IniFormat);
3686 
3687     passForm->setEnabled ( false );
3688     if(brokerMode)
3689     {
3690         if(connectionType==DEFAULT)
3691             host=config.serverIp;
3692         else
3693             host=suspendTerminateHostFromBroker;
3694         sshPort=config.sshport;
3695         x2goDebug<<"Server: "<<host;
3696     }
3697     else if (embedMode)
3698     {
3699         host=config.server;
3700     }
3701     else
3702     {
3703         host=st->setting()->value ( sid+"/host",
3704                                     ( QVariant ) QString::null ).toString();
3705     }
3706 
3707     QString cmd=st->setting()->value ( sid+"/command",
3708                                        ( QVariant ) QString::null ).toString();
3709     autologin=st->setting()->value ( sid+"/autologin",
3710                                      ( QVariant ) false ).toBool();
3711     krblogin=st->setting()->value ( sid+"/krblogin",
3712                                     ( QVariant ) false ).toBool();
3713     krbDelegation=st->setting()->value ( sid+"/krbdelegation",
3714                                          ( QVariant ) false ).toBool();
3715 #ifdef Q_OS_UNIX
3716     directRDP=(st->setting()->value ( sid+"/directrdp",
3717                                       ( QVariant ) false ).toBool() && cmd == "RDP");
3718 
3719 
3720     if (cmd =="RDP" && directRDP)
3721     {
3722         startDirectRDP();
3723         return true;
3724     }
3725 
3726     directRDP=(st->setting()->value ( sid+"/directxdmcp",
3727                                       ( QVariant ) false ).toBool() && cmd == "XDMCP");
3728 
3729 
3730     if (cmd =="XDMCP" && directRDP)
3731     {
3732         startDirectRDP();
3733         return true;
3734     }
3735 #endif
3736     if ( cmd=="SHADOW" )
3737         shadowSession=true;
3738     passwd=getCurrentPass();
3739     if(brokerMode)
3740     {
3741         currentKey=config.key;
3742         sshPort=config.sshport;
3743     }
3744     if (sshConnection)
3745         delete sshConnection;
3746 
3747     if(currentKey.length()<=0)
3748     {
3749         currentKey=findSshKeyForServer(user, host, sshPort);
3750     }
3751 
3752     if (!embedMode) {
3753         useproxy = (st->setting ()->value (sid + "/usesshproxy",
3754                                            false).toBool ());
3755 
3756         QString prtype = (st->setting ()->value (sid + "/sshproxytype",
3757                                                  "SSH").toString ());
3758         if (prtype.toLower () == "http") {
3759             proxyType = SshMasterConnection::PROXYHTTP;
3760         }
3761         else {
3762             proxyType = SshMasterConnection::PROXYSSH;
3763         }
3764 
3765         proxylogin = (st->setting ()->value (sid + "/sshproxyuser",
3766                                              QString ()).toString ());
3767 
3768         proxyKey = (st->setting ()->value (sid + "/sshproxykeyfile",
3769                                            QString ()).toString ());
3770         proxyKey = expandHome (proxyKey);
3771 
3772         proxyserver = (st->setting ()->value (sid + "/sshproxyhost",
3773                                               QString ()).toString ());
3774 
3775         proxyport = (st->setting ()->value (sid + "/sshproxyport",
3776                                             22).toInt ());
3777 
3778         proxyAutologin = (st->setting ()->value (sid + "/sshproxyautologin",
3779                                                  false).toBool ());
3780 
3781         proxyKrbLogin = (st->setting ()->value (sid + "/sshproxykrblogin",
3782                                                 false).toBool ());
3783     }
3784     else {
3785         useproxy = config.useproxy;
3786         proxyType = config.proxyType;
3787         proxylogin = config.proxylogin;
3788         proxyKey = config.proxyKey;
3789         proxyserver = config.proxyserver;
3790         proxyport = config.proxyport;
3791         proxyAutologin = config.proxyAutologin;
3792         proxyKrbLogin = config.proxyKrbLogin;
3793     }
3794 
3795     bool proxySamePass=(st->setting()->value (
3796                             sid+"/sshproxysamepass",
3797                             false
3798                         ).toBool() );
3799     bool proxySameUser (st->setting()->value (
3800                             sid+"/sshproxysameuser",
3801                             false
3802                         ).toBool() );
3803     bool proxySameKey=(st->setting()->value (
3804                             sid+"/sshproxysamekey",
3805                             false
3806                         ).toBool() );
3807     if(proxyKey.length()<=0 && proxyType==SshMasterConnection::PROXYSSH)
3808     {
3809         proxyKey=findSshKeyForServer(proxylogin, proxyserver, QString::number(proxyport));
3810     }
3811     if(proxySameKey)
3812     {
3813         proxyKey=currentKey;
3814     }
3815 
3816     if(proxySameUser)
3817         proxylogin=user;
3818     if(proxySamePass)
3819         proxypassword=passwd;
3820     else
3821     {
3822         if(useproxy && !proxyAutologin && !proxyKrbLogin && proxyKey.length()<=0)
3823         {
3824             bool ok;
3825             bool useBrokerPassForProxy=false;
3826             bool useBrokerUserForProxy=false;
3827             if(brokerMode)
3828             {
3829                 useBrokerPassForProxy=(st->setting()->value (
3830                     sid+"/usebrokerpassforproxy", false
3831                 ).toBool() );
3832                 useBrokerUserForProxy=(st->setting()->value (
3833                     sid+"/usebrokeruserforproxy", false
3834                 ).toBool() );
3835                 if(useBrokerUserForProxy)
3836                 {
3837                     proxylogin=config.brokerUser;
3838                 }
3839             }
3840             if(useBrokerPassForProxy)
3841                 proxypassword=config.brokerPass;
3842             else
3843                 proxypassword=QInputDialog::getText(0,proxylogin+"@"+proxyserver+":"+QString::number(proxyport),
3844                                                     tr("Enter password for SSH proxy"),QLineEdit::Password,QString::null, &ok);
3845         }
3846     }
3847 
3848     delete st;
3849 
3850     sshConnection=startSshConnection ( host,sshPort,acceptRsa,user,passwd,autologin, krblogin, false, useproxy,proxyType,proxyserver,
3851                                        proxyport, proxylogin, proxypassword, proxyKey,proxyAutologin, proxyKrbLogin);
3852     sshConnection->set_kerberosDelegation(krbDelegation);
3853     return true;
3854 }
3855 
3856 
slotListSessions(bool result,QString output,int)3857 void ONMainWindow::slotListSessions ( bool result,QString output,
3858                                       int  )
3859 {
3860     interDlg->hide();
3861     x2goDebug<<output;
3862     if ( result==false )
3863     {
3864         cardReady=false;
3865         cardStarted=false;
3866         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
3867         if ( message.indexOf ( "publickey,password" ) !=-1 )
3868         {
3869             message=tr ( "<b>Wrong password!</b><br><br>" ) +
3870                     message;
3871         }
3872 
3873         if ( !startHidden )
3874         {
3875             QMessageBox::critical ( 0l,tr ( "Error" ),message,
3876                                     QMessageBox::Ok,
3877                                     QMessageBox::NoButton );
3878         }
3879         else
3880         {
3881             QString printout = tr( "Connection failed: ")  + output.toLatin1();
3882 
3883             if ( output.indexOf ( "publickey,password" ) !=-1 )
3884                 x2goErrorf(4)<< tr( "Connection failed: ")  + output + tr(" - Wrong password.");
3885             else
3886                 x2goErrorf(5)<< tr( "Connection failed: ")  + output;
3887             trayQuit();
3888         }
3889 
3890 
3891 // 		currentKey=QString::null;
3892         setEnabled ( true );
3893         passForm->setEnabled ( true );
3894         slotShowPassForm();
3895         pass->setFocus();
3896         pass->selectAll();
3897         return;
3898     }
3899 
3900     passForm->hide();
3901     if ( !embedMode )
3902     {
3903         setUsersEnabled ( false );
3904         uname->setEnabled ( false );
3905         u->setEnabled ( false );
3906     }
3907     if ( managedMode )
3908     {
3909         x2goDebug<<"Session data: " + config.sessiondata;
3910         if ( config.sessiondata.indexOf ( "|S|" ) ==-1 )
3911         {
3912             x2goDebug<<"Starting new managed session.";
3913             startNewSession();
3914         }
3915         else
3916         {
3917             x2goSession s=getSessionFromString (config.sessiondata);
3918 
3919             /* Check getSessionFromString for what this "invalid" string means. */
3920             if (s.agentPid == "invalid") {
3921                 startNewSession ();
3922             }
3923             else {
3924                 x2goDebug << "Resuming managed session with ID: " + s.sessionId;
3925                 resumeSession (s);
3926             }
3927         }
3928         return;
3929     }
3930 
3931     QStringList sessions;
3932     if(!brokerMode || shadowSession)
3933     {
3934         sessions=output.trimmed().split ( '\n',
3935                                           QString::SkipEmptyParts );
3936     }
3937     else
3938     {
3939         sessions=config.sessiondata.trimmed().split ( '\n',
3940                  QString::SkipEmptyParts );
3941     }
3942     if ( shadowSession )
3943     {
3944         selectSession ( sessions );
3945     }
3946     else
3947     {
3948         if ( ( sessions.size() ==0 ) ||
3949                 ( sessions.size() ==1&&sessions[0].length() <5 ) )
3950             startNewSession();
3951         else if ( sessions.size() ==1 )
3952         {
3953             x2goSession s=getSessionFromString ( sessions[0] );
3954 
3955             QDesktopWidget wd;
3956 
3957             //we already selected the session
3958             if(brokerMode)
3959             {
3960                 resumeSession(s);
3961                 return;
3962             }
3963 
3964             /* Check getSessionFromString for what this "invalid" string means. */
3965             if ((s.agentPid != "invalid") && (s.status == "S")
3966                 && (isColorDepthOk (wd.depth (), s.colorDepth))
3967                 && (s.command == selectedCommand)&&autoresume)
3968                 resumeSession ( s );
3969             else
3970             {
3971                 if ((startHidden) || (s.agentPid == "invalid"))
3972                     startNewSession();
3973                 else
3974                     selectSession ( sessions );
3975             }
3976         }
3977         else
3978         {
3979             if ( !startHidden )
3980                 selectSession ( sessions );
3981             else
3982             {
3983                 for ( int i=0; i<sessions.size(); ++i )
3984                 {
3985                     x2goSession s=getSessionFromString (
3986                                       sessions[i] );
3987 
3988                     QDesktopWidget wd;
3989 
3990                     /* Check getSessionFromString for what this "invalid" string means. */
3991                     if ((s.agentPid != "invalid") && (s.status == "S")
3992                         && (isColorDepthOk (wd.depth (), s.colorDepth))
3993                         && (s.command == selectedCommand))
3994                     {
3995                         resumeSession ( s );
3996                         return;
3997                     }
3998                 }
3999                 startNewSession();
4000             }
4001         }
4002     }
4003 }
4004 
4005 
getSessionFromString(const QString & string)4006 x2goSession ONMainWindow::getSessionFromString ( const QString& string )
4007 {
4008     QStringList lst=string.split ( '|' );
4009 
4010     x2goSession s;
4011 
4012     /*
4013      * Skip over invalid sessions strings...
4014      * This can happen if the perl interpreter outputs warning or error messages
4015      * to stdout.
4016      */
4017     if (lst.size () < 10) {
4018         s.agentPid = "invalid";
4019         return (s);
4020     }
4021 
4022     s.agentPid=lst[0];
4023     s.sessionId=lst[1];
4024     s.display=lst[2];
4025     s.server=lst[3];
4026     s.status=lst[4];
4027     s.crTime=lst[5];
4028     s.cookie=lst[6];
4029     s.clientIp=lst[7];
4030     s.grPort=lst[8];
4031     s.sndPort=lst[9];
4032     if ( lst.count() >13 )
4033         s.fsPort=lst[13];
4034     if (brokerMode && lst.count()>14)
4035         s.brokerUser=lst[14];
4036     s.colorDepth=0;
4037     if ( s.sessionId.indexOf ( "_dp" ) !=-1 )
4038     {
4039         s.colorDepth=s.sessionId.split ( "_dp" ) [1].toInt();
4040     }
4041     s.sessionType=x2goSession::DESKTOP;
4042     s.command=tr ( "unknown" );
4043     if ( s.sessionId.indexOf ( "_st" ) !=-1 )
4044     {
4045         QString cmdinfo=s.sessionId.split ( "_st" ) [1];
4046         cmdinfo=cmdinfo.split ( "_" ) [0];
4047         QChar st=cmdinfo[0];
4048         if ( st=='R' )
4049             s.sessionType=x2goSession::ROOTLESS;
4050         if ( st=='S' )
4051             s.sessionType=x2goSession::SHADOW;
4052         if ( st=='K' )
4053         {
4054             s.sessionType=x2goSession::KDRIVE;
4055         }
4056         QString command=cmdinfo.mid ( 1 );
4057         if ( command.length() >0 )
4058             s.command=command;
4059     }
4060     return s;
4061 }
4062 
4063 
sendEventToBroker(ONMainWindow::client_events ev)4064 void ONMainWindow::sendEventToBroker(ONMainWindow::client_events ev)
4065 {
4066     if(!config.brokerEvents)
4067     {
4068         return;
4069     }
4070     if(ev <= lastBrokerEvent && resumingSession.sessionId == lastBrokerEventSession && ev != ALIVE)
4071     {
4072         return;
4073     }
4074     if(ev!=ALIVE)
4075         lastBrokerEvent=ev;
4076     lastBrokerEventSession=resumingSession.sessionId;
4077     QString event;
4078     switch(ev)
4079     {
4080         case CONNECTING:
4081         {
4082             event="CONNECTING";
4083             resumingSession.connectedSince=QDateTime::currentDateTime().toTime_t();
4084             break;
4085         }
4086         case CONNECTED:
4087         {
4088             event="CONNECTED";
4089             resumingSession.connectedSince=QDateTime::currentDateTime().toTime_t();
4090             if(config.brokerLiveEventsTimeout)
4091                 brokerAliveTimer->start(config.brokerLiveEventsTimeout*1000);
4092             break;
4093         }
4094         case SUSPENDING:
4095         {
4096             event="SUSPENDING";
4097             break;
4098         }
4099         case TERMINATING:
4100         {
4101             event="TERMINATING";
4102             break;
4103         }
4104         case FINISHED:
4105         {
4106             event="FINISHED";
4107             brokerAliveTimer->stop();
4108             break;
4109         }
4110         case ALIVE:
4111         {
4112             event="ALIVE";
4113             break;
4114         }
4115     }
4116     broker->sendEvent(event, resumingSession.sessionId,resumingSession.server, resumingSession.clientIp, getCurrentUname(),
4117                       resumingSession.command, resumingSession.display, resumingSession.crTime,
4118                       QDateTime::currentDateTime().toTime_t()-resumingSession.connectedSince);
4119 }
4120 
4121 
startNewSession()4122 void ONMainWindow::startNewSession()
4123 {
4124     newSession=true;
4125     QString passwd=getCurrentPass();
4126     QString user=getCurrentUname();
4127 
4128     QString pack;
4129     bool kdrive=false;
4130     bool fullscreen;
4131     int height;
4132     int width;
4133     int quality;
4134     int speed;
4135     bool usekbd;
4136     bool rootless=false;
4137     resumingSession.published=false;
4138     bool setDPI=defaultSetDPI;
4139     bool xinerama = false;
4140     uint dpi=defaultDPI;
4141     QString layout;
4142     QString type;
4143     QString command;
4144     QString clipMode=defaultClipboardMode;
4145     QString xdmcpServer;
4146     runRemoteCommand=true;
4147     QString host=QString::null;
4148     runStartApp=true;
4149     removeAppsFromTray();
4150     if ( useLdap )
4151     {
4152         pack=defaultPack;
4153         fullscreen=defaultFullscreen;
4154         height=defaultHeight;
4155         width=defaultWidth;
4156         quality=defaultQuality;
4157         speed=defaultLink;
4158         xinerama = defaultXinerama;
4159         usekbd=defaultSetKbd;
4160         layout=defaultLayout[0];
4161         type=defaultKbdType;
4162         command=defaultCmd;
4163         shadowSession=false;
4164         for ( int j=0; j<x2goServers.size(); ++j )
4165         {
4166             if ( x2goServers[j].connOk )
4167             {
4168                 host=x2goServers[j].name;
4169                 break;
4170             }
4171         }
4172         if ( host==QString::null )
4173         {
4174             QMessageBox::critical ( 0l,tr ( "Error" ),
4175                                     tr ( "No server available." ),
4176                                     QMessageBox::Ok,
4177                                     QMessageBox::NoButton );
4178             return;
4179         }
4180         sshConnection=findServerSshConnection(host);
4181         if (!sshConnection)
4182         {
4183             QMessageBox::critical ( 0l,tr ( "Error" ),
4184                                     tr ( "Server not available." ),
4185                                     QMessageBox::Ok,
4186                                     QMessageBox::NoButton );
4187             return;
4188         }
4189         cleanServerSshConnections();
4190     }
4191     else
4192     {
4193         X2goSettings* st;
4194 
4195         if (!brokerMode)
4196             st=new X2goSettings( "sessions" );
4197         else
4198             st= new X2goSettings(config.iniFile,QSettings::IniFormat);
4199 
4200         QString sid;
4201         if ( !embedMode ) {
4202             if (!(sessionExplorer->getLastSession())) {
4203                 x2goDebug << "No session selected, returning without starting a session.";
4204 
4205                 delete st;
4206 
4207                 return;
4208             }
4209 
4210             sid=sessionExplorer->getLastSession()->id();
4211         }
4212         else
4213             sid="embedded";
4214         pack=st->setting()->value ( sid+"/pack",
4215                                     ( QVariant ) defaultPack ).toString();
4216         fullscreen=st->setting()->value ( sid+"/fullscreen",
4217                                           ( QVariant )
4218                                           defaultFullscreen ).toBool();
4219 
4220         //if maxdim = true we set maximun display area available for the selected monitor
4221         if ( st->setting()->value(sid + "/maxdim", (QVariant) false).toBool())
4222         {
4223             int selectedScreen = st->setting()->value(sid + "/display", (QVariant) -1).toInt();
4224             height=QApplication::desktop()->availableGeometry(selectedScreen).height();
4225             width=QApplication::desktop()->availableGeometry(selectedScreen).width();
4226         }
4227         else if(st->setting()->value(sid + "/multidisp", (QVariant) false).toBool())
4228         {
4229             //workaround to avoid wm set windows maximized, which will break moving and resizing of window
4230             width=800;
4231             height=600;
4232         }
4233         else
4234         {
4235             height=st->setting()->value ( sid+"/height",
4236                                           ( QVariant ) defaultHeight ).toInt();
4237             width=st->setting()->value ( sid+"/width",
4238                                          ( QVariant ) defaultWidth ).toInt();
4239         }
4240 
4241 
4242         setDPI=st->setting()->value ( sid+"/setdpi",
4243                                       ( QVariant ) defaultSetDPI ).toBool();
4244         dpi=st->setting()->value ( sid+"/dpi",
4245                                    ( QVariant ) defaultDPI ).toUInt();
4246         quality=st->setting()->value (
4247                     sid+"/quality",
4248                     ( QVariant ) defaultQuality ).toInt();
4249         speed=st->setting()->value ( sid+"/speed",
4250                                      ( QVariant ) defaultLink ).toInt();
4251 
4252         xinerama = st->setting ()->value (sid + "/xinerama",
4253                                           static_cast<QVariant>(defaultXinerama)).toBool ();
4254 
4255         clipMode=st->setting()->value ( sid+"/clipboard",
4256                                         ( QVariant ) defaultClipboardMode ).toString();
4257 
4258         usekbd=st->setting()->value ( sid+"/usekbd",
4259                                       ( QVariant ) defaultSetKbd ).toBool();
4260         layout=st->setting()->value ( sid+"/layout",
4261                                       ( QVariant )
4262                                       defaultLayout[0] ).toString();
4263         type=st->setting()->value ( sid+"/type",
4264                                     ( QVariant )
4265                                     defaultKbdType ).toString();
4266         type.replace("\\","");
4267         type.replace("(","\\(");
4268         type.replace(")","\\)");
4269         if ( !embedMode )
4270         {
4271             command=st->setting()->value ( sid+"/command",
4272                                            ( QVariant ) defaultCmd ).toString();
4273 
4274             kdrive=st->setting()->value ( sid+"/kdrive",
4275                                            ( QVariant ) false ).toBool();
4276 
4277             host=st->setting()->value (
4278                      sid+"/host",
4279                      ( QVariant )
4280                      ( QString ) "localhost" ).toString();
4281 
4282             rootless=st->setting()->value ( sid+"/rootless",
4283                                             ( QVariant ) false ).toBool();
4284             resumingSession.published=st->setting()->value ( sid+"/published",
4285                                       ( QVariant ) false ).toBool();
4286             xdmcpServer=st->setting()->value ( sid+"/xdmcpserver",
4287                                                ( QVariant )
4288                                                "localhost" ).toString();
4289         }
4290         else
4291         {
4292             command=config.command;
4293             if ( command=="SHADOW" )
4294             {
4295                 shadowSession=true;
4296                 runRemoteCommand=false;
4297             }
4298 
4299             rootless= config.rootless;
4300             host=config.server;
4301             startEmbedded=false;
4302             resumingSession.published=config.published;
4303             if ( st->setting()->value ( sid+"/startembed",
4304                                         ( QVariant ) true ).toBool() )
4305             {
4306                 startEmbedded=true;
4307                 fullscreen=false;
4308                 height=bgFrame->size().height()-stb->height();
4309                 width=bgFrame->size().width();
4310 
4311                 if ( height<0 ||width<0 )
4312                 {
4313                     height=defaultHeight;
4314                     width=defaultWidth;
4315                 }
4316             }
4317             if ( config.confConSpd )
4318                 speed=config.conSpeed;
4319             if ( config.confCompMet )
4320                 pack=config.compMet;
4321             if ( config.confImageQ )
4322                 quality=config.imageQ;
4323             if ( config.confDPI )
4324             {
4325                 dpi=config.dpi;
4326                 setDPI=true;
4327             }
4328             if ( config.confKbd )
4329             {
4330                 layout=config.kbdLay;
4331                 type=config.kbdType;
4332                 usekbd=true;
4333             }
4334         }
4335         resumingSession.command=command;
4336         if ( command=="RDP" )
4337         {
4338             if (fullscreen) {
4339                 rootless=false;
4340             } else {
4341                 rootless=true;
4342             }
4343         }
4344         if ( command=="XDMCP" )
4345         {
4346             runRemoteCommand=false;
4347         }
4348 #ifdef Q_OS_WIN
4349         x2goDebug<<"Fullscreen: "<<fullscreen;
4350         maximizeProxyWin=false;
4351         proxyWinWidth=width;
4352         proxyWinHeight=height;
4353         xorgMode=WIN;
4354         if (fullscreen)
4355             xorgMode=FS;
4356         if (rootless)
4357             xorgMode=SAPP;
4358         xorgWidth=QString::number(width);
4359         xorgHeight=QString::number(height);
4360         uint displays=QApplication::desktop()->numScreens();
4361         if ((!rootless) && (st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool()))
4362         {
4363             xorgMode=MULTIDISPLAY;
4364             uint disp=st->setting()->value ( sid+"/display",( QVariant ) 1 ).toUInt();
4365             if (disp>displays)
4366             {
4367                 disp=1;
4368             }
4369             localDisplayNumber=disp;
4370         }
4371         if(kdrive)
4372         {
4373             x2goDebug<<"KDRIVE session don't start X Server";
4374             slotSetWinServersReady();
4375         }
4376         if (! startXorgOnStart && ! kdrive)
4377             startXOrg();
4378 #endif
4379         delete st;
4380     }
4381 
4382     if ( shadowSession )
4383     {
4384         runRemoteCommand=false;
4385     }
4386 
4387 
4388     resumingSession.server=host;
4389 
4390     if (defaultLayout.size()>0)
4391         layout=cbLayout->currentText();
4392 
4393 
4394     QString geometry;
4395     if ( fullscreen )
4396     {
4397         geometry="fullscreen";
4398 #ifdef Q_OS_WIN
4399 //        fullscreen=false;
4400         maximizeProxyWin=true;
4401 
4402         x2goDebug<<"Maximize proxy win: "<<maximizeProxyWin;
4403 
4404 #endif
4405     }
4406     if ( ! fullscreen )
4407     {
4408         geometry=QString::number ( width ) +"x"+
4409                  QString::number ( height );
4410         if ( embedMode )
4411         {
4412             QPoint position=mapToGlobal ( bgFrame->pos() );
4413             geometry+="+"+QString::number ( position.x() ) +"+"+
4414                       QString::number ( position.y() +
4415                                         stb->height() );
4416         }
4417 
4418     }
4419     QString link;
4420     switch ( speed )
4421     {
4422     case MODEM:
4423         link="modem";
4424         break;
4425     case ISDN:
4426         link="isdn";
4427         break;
4428     case ADSL:
4429         link="adsl";
4430         break;
4431     case WAN:
4432         link="wan";
4433         break;
4434     case LAN:
4435         link="lan";
4436         break;
4437     }
4438 
4439     QFile file ( ":/txt/packs" );
4440     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
4441         return;
4442     QTextStream in ( &file );
4443     while ( !in.atEnd() )
4444     {
4445         QString pc=in.readLine();
4446         if ( pc.indexOf ( "-%" ) !=-1 )
4447         {
4448             pc=pc.left ( pc.indexOf ( "-%" ) );
4449             if ( pc==pack )
4450             {
4451                 pack+="-"+QString::number ( quality );
4452                 break;
4453             }
4454         }
4455     }
4456     file.close();
4457 
4458 
4459     if ( selectSessionDlg->isVisible() )
4460     {
4461         if ( !embedMode )
4462             slotCloseSelectDlg();
4463         else
4464             selectSessionDlg->hide();
4465     }
4466     QDesktopWidget wd;
4467     QString depth=QString::number ( wd.depth() );
4468 #ifdef Q_OS_DARWIN
4469     usekbd=0;
4470     type="query";
4471 #endif
4472     QString sessTypeStr="D ";
4473     if ( rootless )
4474         sessTypeStr="R ";
4475     if ( shadowSession )
4476         sessTypeStr="S ";
4477     if ( resumingSession.published)
4478     {
4479         sessTypeStr="P ";
4480         command="PUBLISHED";
4481     }
4482     if(kdrive)
4483         sessTypeStr="K ";
4484     QString dpiEnv;
4485     QString xdmcpEnv;
4486     QString xinerama_env = "X2GO_XINERAMA=";
4487     if ( runRemoteCommand==false && command=="XDMCP" )
4488         xdmcpEnv="X2GOXDMCP="+xdmcpServer+" ";
4489     if ( setDPI )
4490     {
4491         dpiEnv="X2GODPI="+QString::number ( dpi ) +" ";
4492     }
4493 
4494     if (xinerama) {
4495       xinerama_env += "yes";
4496     }
4497     else {
4498       xinerama_env += "no";
4499     }
4500 
4501     QString cmd=dpiEnv+xdmcpEnv+ xinerama_env + " x2gostartagent "+
4502                 geometry+" "+link+" "+pack+
4503                 " unix-kde-depth_"+depth+" "+layout+" "+type+" ";
4504     if ( usekbd )
4505         cmd += "1 ";
4506     else
4507         cmd += "0 ";
4508     QFileInfo f ( command );
4509     if ( !shadowSession ) {
4510         cmd+=sessTypeStr+f.fileName();
4511         cmd+=" "+clipMode;
4512     }
4513     else
4514     {
4515         cmd+=sessTypeStr+QString::number ( shadowMode ) +"XSHAD"+
4516              shadowUser+"XSHAD"+shadowDisplay;
4517     }
4518 
4519     resumingSession.fullscreen=fullscreen;
4520 
4521     x2goDebug<<"Executing remote command: "<<cmd;
4522 
4523     if ( managedMode )
4524     {
4525         slotRetResumeSess ( true,config.sessiondata,0 );
4526         passForm->hide();
4527         return;
4528     }
4529 
4530     sshConnection->executeCommand ( cmd, this, SLOT ( slotRetResumeSess ( bool,
4531                                     QString,int ) ) );
4532     passForm->hide();
4533 }
4534 
4535 
resumeSession(const x2goSession & s)4536 void ONMainWindow::resumeSession ( const x2goSession& s )
4537 {
4538     newSession=false;
4539     runStartApp=false;
4540     applications.clear();
4541     removeAppsFromTray();
4542     QString passwd=getCurrentPass();
4543     QString user=getCurrentUname();
4544     QString host=s.server;
4545     bool rootless=false;
4546 
4547     QString clipMode=defaultClipboardMode;
4548 
4549     QString pack;
4550     bool fullscreen;
4551     int height;
4552     int width;
4553     int quality;
4554     int speed;
4555     bool xinerama = false;
4556     bool usekbd;
4557     QString layout;
4558     QString type;
4559     removeAppsFromTray();
4560 
4561     if ( useLdap )
4562     {
4563         pack=defaultPack;
4564         fullscreen=defaultFullscreen;
4565         height=defaultHeight;
4566         width=defaultWidth;
4567         quality=defaultQuality;
4568         speed=defaultLink;
4569         xinerama = defaultXinerama;
4570         usekbd=defaultSetKbd;
4571         layout=defaultLayout[0];
4572         type=defaultKbdType;
4573         sshConnection=findServerSshConnection(host);
4574         if (!sshConnection)
4575         {
4576             QMessageBox::critical ( 0l,tr ( "Error" ),
4577                                     tr ( "Server not available." ),
4578                                     QMessageBox::Ok,
4579                                     QMessageBox::NoButton );
4580             return;
4581         }
4582         cleanServerSshConnections();
4583     }
4584     else
4585     {
4586 
4587         QString sid;
4588         if ( !embedMode ) {
4589             if (!(sessionExplorer->getLastSession())) {
4590                 x2goDebug << "No session selected, returning without resuming a session.";
4591                 return;
4592             }
4593 
4594             sid=sessionExplorer->getLastSession()->id();
4595         }
4596         else
4597             sid="embedded";
4598         X2goSettings* st;
4599         if (!brokerMode)
4600             st=new X2goSettings( "sessions" );
4601         else
4602             st=new X2goSettings(config.iniFile,QSettings::IniFormat);
4603 
4604         pack=st->setting()->value ( sid+"/pack",
4605                                     ( QVariant ) defaultPack ).toString();
4606 
4607         fullscreen=st->setting()->value ( sid+"/fullscreen",
4608                                           ( QVariant )
4609                                           defaultFullscreen ).toBool();
4610         height=st->setting()->value ( sid+"/height",
4611                                       ( QVariant ) defaultHeight ).toInt();
4612         width=st->setting()->value ( sid+"/width",
4613                                      ( QVariant ) defaultWidth ).toInt();
4614         quality=st->setting()->value ( sid+"/quality",
4615                                        ( QVariant )
4616                                        defaultQuality ).toInt();
4617         speed=st->setting()->value ( sid+"/speed",
4618                                      ( QVariant ) defaultLink ).toInt();
4619 
4620         xinerama = st->setting ()->value (sid + "/xinerama",
4621                                           static_cast<QVariant>(defaultXinerama)).toBool ();
4622 
4623         clipMode=st->setting()->value ( sid+"/clipboard",
4624                                         ( QVariant ) defaultClipboardMode ).toString();
4625 
4626         usekbd=st->setting()->value ( sid+"/usekbd",
4627                                       ( QVariant ) defaultSetKbd ).toBool();
4628         layout=st->setting()->value ( sid+"/layout",
4629                                       ( QVariant )
4630                                       defaultLayout[0] ).toString();
4631         type=st->setting()->value ( sid+"/type",
4632                                     ( QVariant )
4633                                     defaultKbdType ).toString();
4634         rootless=st->setting()->value ( sid+"/rootless",
4635                                         ( QVariant ) false ).toBool();
4636 
4637         if ( brokerMode )
4638         {
4639             host = config.serverIp;
4640         }
4641         else if ( embedMode )
4642         {
4643             startEmbedded=false;
4644             if ( st->setting()->value ( sid+"/startembed",
4645                                         ( QVariant ) true ).toBool() )
4646             {
4647                 fullscreen=false;
4648                 startEmbedded=true;
4649                 height=bgFrame->size().height()-stb->height();
4650                 width=bgFrame->size().width();
4651                 if ( height<0 ||width<0 )
4652                 {
4653                     height=defaultHeight;
4654                     width=defaultWidth;
4655                 }
4656             }
4657             rootless=config.rootless;
4658             host=config.server;
4659             if ( config.confConSpd )
4660                 speed=config.conSpeed;
4661             if ( config.confCompMet )
4662                 pack=config.compMet;
4663             if ( config.confImageQ )
4664                 quality=config.imageQ;
4665             if ( config.confKbd )
4666             {
4667                 layout=config.kbdLay;
4668                 type=config.kbdType;
4669                 usekbd=true;
4670             }
4671         }
4672         else
4673         {
4674             host=st->setting()->value ( sid+"/host",
4675                                         ( QVariant ) s.server ).toString();
4676         }
4677         delete st;
4678     }
4679 
4680     if (defaultLayout.size()>0)
4681         layout=cbLayout->currentText();
4682 
4683     QString geometry;
4684 #ifdef Q_OS_WIN
4685     maximizeProxyWin=false;
4686     proxyWinWidth=width;
4687     proxyWinHeight=height;
4688 // #ifdef CFGCLIENT
4689     xorgMode=WIN;
4690     if (fullscreen)
4691         xorgMode=FS;
4692     if (rootless)
4693         xorgMode=SAPP;
4694     xorgWidth=QString::number(width);
4695     xorgHeight=QString::number(height);
4696     if(s.sessionType == x2goSession::KDRIVE)
4697     {
4698         x2goDebug<<"KDRIVE session, don't start X-Server";
4699         slotSetWinServersReady();
4700     }
4701     if (! startXorgOnStart  && (s.sessionType != x2goSession::KDRIVE))
4702         startXOrg();
4703 // #endif
4704 #else /* defined (Q_OS_WIN) */
4705     UNUSED (rootless);
4706 #endif /* defined (Q_OS_WIN) */
4707 
4708     if ( fullscreen )
4709     {
4710         geometry="fullscreen";
4711 #ifdef Q_OS_WIN
4712 //        fullscreen=false;
4713         maximizeProxyWin=true;
4714 
4715         x2goDebug<<"Maximize proxy win: "<<maximizeProxyWin;
4716 
4717 #endif
4718     }
4719     if ( !fullscreen )
4720     {
4721         geometry=QString::number ( width ) +"x"+
4722                  QString::number ( height );
4723     }
4724     resumingSession.fullscreen=fullscreen;
4725     QString link;
4726     switch ( speed )
4727     {
4728     case MODEM:
4729         link="modem";
4730         break;
4731     case ISDN:
4732         link="isdn";
4733         break;
4734     case ADSL:
4735         link="adsl";
4736         break;
4737     case WAN:
4738         link="wan";
4739         break;
4740     case LAN:
4741         link="lan";
4742         break;
4743     }
4744 
4745     QFile file ( ":/txt/packs" );
4746     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
4747         return;
4748     QTextStream in ( &file );
4749     while ( !in.atEnd() )
4750     {
4751         QString pc=in.readLine();
4752         if ( pc.indexOf ( "-%" ) !=-1 )
4753         {
4754             pc=pc.left ( pc.indexOf ( "-%" ) );
4755             if ( pc==pack )
4756             {
4757                 pack+="-"+QString::number ( quality );
4758                 break;
4759             }
4760         }
4761     }
4762     file.close();
4763 
4764 #ifdef Q_OS_DARWIN
4765     usekbd=0;
4766     type="query";
4767 #endif
4768 
4769     if (s.sessionId.indexOf("RPUBLISHED")!=-1)
4770     {
4771         resumingSession.published=true;
4772         sbApps->setDisabled(true);
4773     }
4774     else
4775         resumingSession.published=false;
4776 
4777 
4778 
4779     if ( selectSessionDlg->isVisible() )
4780     {
4781         if ( !embedMode )
4782             slotCloseSelectDlg();
4783         else
4784             selectSessionDlg->hide();
4785     }
4786     QString cmd="x2goresume-session "+s.sessionId+" "+geometry+
4787                 " "+link+" "+pack+" "+layout+
4788                 " "+type+" ";
4789     if ( usekbd )
4790         cmd += "1";
4791     else
4792         cmd += "0";
4793     cmd +=" "+clipMode;
4794 
4795     QString xinerama_opt;
4796     if (xinerama) {
4797       xinerama_opt = "yes";
4798     }
4799     else {
4800       xinerama_opt = "no";
4801     }
4802 
4803     cmd += " " + xinerama_opt;
4804 
4805     sshConnection->executeCommand ( cmd, this,  SLOT ( slotRetResumeSess ( bool, QString,
4806                                     int ) ));
4807     resumingSession=s;
4808     passForm->hide();
4809 }
4810 
4811 /**
4812  * @brief ONMainWindow::setTrayIconToSessionIcon
4813  * @param info: message to be displayed in tray icon message
4814  *
4815  * Sets the tray session icon picture as the tray icon picture and
4816  * shows a tray icon information message about what X2Go Client
4817  * is currently doing.
4818  *
4819  * This message gives the user some feedback while the X2Go session
4820  * window is displayed.
4821  *
4822  */
setTrayIconToSessionIcon(QString info)4823 void ONMainWindow::setTrayIconToSessionIcon(QString info) {
4824 
4825     //set session icon to tray icon
4826     if (trayIcon && sessionExplorer->getLastSession()) {
4827 
4828         X2goSettings* st;
4829 
4830         if (!brokerMode)
4831             st=new X2goSettings( "sessions" );
4832         else
4833             st= new X2goSettings(config.iniFile,QSettings::IniFormat);
4834 
4835         QString sid;
4836         if ( !embedMode )
4837             sid=sessionExplorer->getLastSession()->id();
4838         else
4839             sid="embedded";
4840 
4841         if (!keepTrayIcon) {
4842             QString imagePath = wrap_legacy_resource_URIs (expandHome(st->setting()->value(sid + "/icon", (QVariant) QString(":/img/icons/128x128/x2go.png")).toString()));
4843             trayIcon->setIcon(QIcon (imagePath));
4844         }
4845 
4846         QString name=st->setting()->value ( sid +"/name").toString() ;
4847 
4848         //send a information notification about the connection is done
4849         trayIcon->showMessage("X2Go - " + name, info, QSystemTrayIcon::Information, 15000);
4850 
4851         delete (st);
4852     }
4853 
4854 }
4855 
selectSession(QStringList & sessions)4856 void ONMainWindow::selectSession ( QStringList& sessions )
4857 {
4858     setEnabled ( true );
4859     sessionStatusDlg->hide();
4860     passForm->hide();
4861 
4862     if ( !shadowSession )
4863     {
4864         x2goDebug<<"No shadow session.";
4865         if ( !miniMode )
4866             selectSesDlgLayout->setContentsMargins ( 25,25,10,10 );
4867 
4868         bNew->show();
4869         bSusp->show();
4870         bTerm->show();
4871         sOk->show();
4872         sCancel->show();
4873 
4874         desktopFilter->hide();
4875         desktopFilterCb->hide();
4876         bShadow->hide();
4877         bShadowView->hide();
4878         bCancel->hide();
4879 
4880 // 		model->clear();
4881         model->removeRows ( 0,model->rowCount() );
4882         selectSessionLabel->setText ( tr ( "Select session:" ) );
4883         selectedSessions.clear();
4884         QFontMetrics fm ( sessTv->font() );
4885         for ( int row = 0; row < sessions.size(); ++row )
4886         {
4887             x2goDebug<<"Decoding session string:" + sessions[row];
4888             x2goSession s=getSessionFromString ( sessions[row] );
4889 
4890             /* Check getSessionFromString for what this "invalid" string means. */
4891             if (s.agentPid == "invalid") {
4892                 continue;
4893             }
4894 
4895             selectedSessions.append ( s );
4896             QStandardItem *item;
4897 
4898             if(!brokerMode)
4899                 item= new QStandardItem ( s.display );
4900             else
4901                 item= new QStandardItem ( s.brokerUser );
4902             model->setItem ( row,S_DISPLAY,item );
4903 
4904             if ( s.status=="R" )
4905                 item= new QStandardItem ( tr ( "running" ) );
4906             else
4907                 item= new QStandardItem ( tr ( "suspended" ) );
4908             model->setItem ( row,S_STATUS,item );
4909 
4910             item= new QStandardItem ( transAppName ( s.command ) );
4911             model->setItem ( row,S_COMMAND,item );
4912 
4913             QString type=tr ( "Desktop" );
4914             if ( s.sessionType==x2goSession::ROOTLESS )
4915                 type=tr ( "single application" );
4916             if ( s.sessionType==x2goSession::SHADOW )
4917                 type=tr ( "shadow session" );
4918             if ( s.sessionType==x2goSession::KDRIVE )
4919                 type=tr ( "X2GoKDrive session" );
4920 
4921 
4922             item= new QStandardItem ( type );
4923             model->setItem ( row,S_TYPE,item );
4924 
4925             item= new QStandardItem ( s.crTime );
4926             model->setItem ( row,S_CRTIME,item );
4927             item= new QStandardItem ( s.server );
4928             model->setItem ( row,S_SERVER,item );
4929             item= new QStandardItem ( s.clientIp );
4930             model->setItem ( row,S_IP,item );
4931             item= new QStandardItem ( s.sessionId );
4932             model->setItem ( row,S_ID,item );
4933             for ( int j=0; j<8; ++j )
4934             {
4935                 QString txt=
4936                     model->index ( row,j ).data().toString();
4937                 if ( sessTv->header()->sectionSize ( j ) <
4938                         fm.width ( txt ) +6 )
4939                 {
4940                     sessTv->header()->resizeSection (
4941                         j,fm.width ( txt ) +6 );
4942                 }
4943             }
4944         }
4945     }
4946     else
4947     {
4948         shadowMode=SHADOW_VIEWONLY;
4949         selectedDesktops.clear();
4950         selectedDesktops=sessions;
4951         if ( sessions.size() ==0 )
4952         {
4953             QMessageBox::information ( this,tr ( "Information" ),
4954                                        tr ( "No accessible desktop "
4955                                             "found." ) );
4956             slotCloseSelectDlg();
4957             return;
4958         }
4959         sessTv->setModel ( ( QAbstractItemModel* ) modelDesktop );
4960         desktopFilter->show();
4961         desktopFilterCb->show();
4962         sOk->hide();
4963         sCancel->hide();
4964         bShadow->show();
4965         bCancel->show();
4966         bShadowView->show();
4967         desktopFilter->setText ( tr ( "Filter" ) );
4968         sessions.sort();
4969         if ( !miniMode )
4970             selectSesDlgLayout->setContentsMargins ( 25,25,25,25 );
4971         bNew->hide();
4972         bSusp->hide();
4973         bTerm->hide();
4974         selectSessionLabel->setText ( tr ( "Select desktop:" ) );
4975         filterDesktops ( "" );
4976         desktopFilter->setFocus();
4977         desktopFilter->selectAll();
4978         if ( !embedMode )
4979         {
4980             X2goSettings* st;
4981 
4982             if (!brokerMode)
4983             {
4984                 if (!(sessionExplorer->getLastSession())) {
4985                     x2goDebug << "No session selected, returning without starting a shadow session.";
4986                     return;
4987                 }
4988 
4989                 st=new X2goSettings( "sessions" );
4990 
4991                 QString sid=sessionExplorer->getLastSession()->id();
4992                 QString suser = st->setting()->value(sid + "/shadowuser", (QVariant) QString::null).toString();
4993                 QString sdisplay = st->setting()->value(sid + "/shadowdisplay", (QVariant) QString::null).toString();
4994                 bool fullAccess= st->setting()->value(sid + "/shadowfullaccess", (QVariant) false).toBool();
4995 
4996                 delete (st);
4997 
4998                 if(suser != QString::null && sdisplay != QString::null)
4999                 {
5000                     shadowUser=suser;
5001                     shadowDisplay=sdisplay;
5002                     if(fullAccess)
5003                         shadowMode=SHADOW_FULL;
5004                     else
5005                         shadowMode=SHADOW_VIEWONLY;
5006                     startNewSession();
5007                     return;
5008                 }
5009             }
5010         }
5011     }
5012 
5013 
5014     sessTv->setCurrentIndex ( sessTv->model()->index ( 0, 0 ) );
5015     sessTv->setFocus();
5016     selectSessionDlg->show();
5017 
5018     if( startHidden && shadowSession && sessTv->model()->rowCount() == 1 )
5019         slotShadowSess();
5020 }
5021 
slotCloseSelectDlg()5022 void ONMainWindow::slotCloseSelectDlg()
5023 {
5024     selectSessionDlg->hide();
5025     if ( !embedMode )
5026     {
5027         u->setEnabled ( true );
5028         uname->setEnabled ( true );
5029     }
5030     slotShowPassForm();
5031 }
5032 
5033 
5034 
slotActivated(const QModelIndex & index)5035 void ONMainWindow::slotActivated ( const QModelIndex& index )
5036 {
5037     if ( !shadowSession )
5038     {
5039         QString status=sessTv->model()->index (
5040                            index.row(),
5041                            S_STATUS ).data().toString();
5042         if ( status==tr ( "running" ) )
5043         {
5044             bSusp->setEnabled ( true );
5045             sOk->setEnabled ( false );
5046         }
5047         else
5048         {
5049             bSusp->setEnabled ( false );
5050             sOk->setEnabled ( true );
5051         }
5052         bTerm->setEnabled ( true );
5053         if ( status==QString::null )
5054         {
5055             sOk->setEnabled ( false );
5056             bTerm->setEnabled ( false );
5057         }
5058     }
5059     else
5060     {
5061         QString user=sessTv->model()->index (
5062                          index.row(),
5063                          D_USER ).data().toString();
5064         bShadowView->setEnabled ( true );
5065         bShadow->setEnabled ( true );
5066     }
5067 }
5068 
5069 
slotResumeSess()5070 void ONMainWindow::slotResumeSess()
5071 {
5072     x2goSession s=getSelectedSession();
5073     if(brokerMode)
5074     {
5075         broker->resumeSession(s.sessionId, s.server);
5076         return;
5077     }
5078     QDesktopWidget wd;
5079     if ( isColorDepthOk ( wd.depth(),s.colorDepth ) )
5080     {
5081         if ( s.status=="R" && ! resumeAfterSuspending)
5082         {
5083             resumeAfterSuspending=true;
5084             slotSuspendSess();
5085             return;
5086         }
5087         resumeAfterSuspending=false;
5088         resumeSession ( s );
5089     }
5090     else
5091     {
5092         int res;
5093         res=QMessageBox::warning (
5094                 0l,tr ( "Warning" ),
5095                 tr ("Your current color depth is different from "
5096                     "the session's color depth. This may cause "
5097                     "problems reconnecting to this session and "
5098                     "in most cases <b>you will lose the "
5099                     "session</b> and have to start a new one! ")
5100               + tr ("It's highly recommended to change the color "
5101                     "depth of your display to %n bit(s) and "
5102                     "restart your X.Org Server before you "
5103                     "reconnect to this X2Go session.",
5104                     "%n will be replaced with a number",
5105                     s.colorDepth)
5106               + tr ("<br />"
5107                     "Do you want to resume this session anyway?"),
5108                 tr ( "Yes" ),
5109                 tr ( "No" ) );
5110         if ( res==0 )
5111             resumeSession ( s );
5112     }
5113 
5114 }
5115 
suspendFromBroker(const QString & sid)5116 void ONMainWindow::suspendFromBroker(const QString& sid)
5117 {
5118     if(proxyRunning && sid ==resumingSession.sessionId)
5119     {
5120         x2goDebug<<"Suspending session from broker";
5121         sendEventToBroker(SUSPENDING);
5122         suspendSession(sid);
5123     }
5124 }
5125 
5126 
terminateFromBroker(const QString & sid)5127 void ONMainWindow::terminateFromBroker(const QString& sid)
5128 {
5129     if(proxyRunning && sid ==resumingSession.sessionId)
5130     {
5131         x2goDebug<<"Suspending session from broker";
5132         sendEventToBroker(TERMINATING);
5133         termSession(sid,false);
5134     }
5135 }
5136 
5137 
slotSuspendSess()5138 void ONMainWindow::slotSuspendSess()
5139 {
5140 
5141 #ifdef Q_OS_UNIX
5142     if (directRDP)
5143     {
5144         nxproxy->terminate();
5145         proxyRunning=false;
5146         return;
5147     }
5148 #endif
5149     QString passwd;
5150     QString user=getCurrentUname();
5151 
5152     passwd=getCurrentPass();
5153 
5154     selectSessionDlg->setEnabled ( false );
5155 
5156 
5157     QString sessId=sessTv->model()->index (
5158                        sessTv->currentIndex().row(),
5159                        S_ID ).data().toString();
5160     QString host=sessTv->model()->index (
5161                      sessTv->currentIndex().row(),
5162                      S_SERVER ).data().toString();
5163 
5164 
5165     if ( !useLdap )
5166     {
5167         if ( !brokerMode )
5168         {
5169             if ( embedMode )
5170             {
5171                 host=config.server;
5172             }
5173             else
5174             {
5175                 X2goSettings st ( "sessions" );
5176 
5177                 if (!(sessionExplorer->getLastSession())) {
5178                     x2goDebug << "No session selected, returning without suspending a session.";
5179                     return;
5180                 }
5181 
5182                 QString sid=sessionExplorer->getLastSession()->id();
5183                 host=st.setting()->value ( sid+"/host",
5184                                            ( QVariant ) host ).toString();
5185             }
5186         }
5187     }
5188     else
5189     {
5190         sshConnection=findServerSshConnection(host);
5191         if (!sshConnection)
5192         {
5193             QMessageBox::critical ( 0l,tr ( "Error" ),
5194                                     tr ( "Server not available." ),
5195                                     QMessageBox::Ok,
5196                                     QMessageBox::NoButton );
5197             return;
5198         }
5199     }
5200 
5201     if(brokerMode)
5202     {
5203        suspendBrokerSession(sessId, host);
5204     }
5205     else
5206     {
5207        suspendSession ( sessId );
5208     }
5209 }
5210 
5211 
slotSuspendSessFromSt()5212 void ONMainWindow::slotSuspendSessFromSt()
5213 {
5214 
5215     if(brokerMode)
5216     {
5217         sendEventToBroker(SUSPENDING);
5218     }
5219 #ifdef Q_OS_UNIX
5220     if (directRDP)
5221     {
5222         nxproxy->terminate();
5223         proxyRunning=false;
5224         return;
5225     }
5226 #endif
5227     QString passwd;
5228     QString user=getCurrentUname();
5229     passwd=getCurrentPass();
5230     setStatStatus ( tr ( "suspending" ) );
5231 
5232 
5233     sbExp->setEnabled ( false );
5234 
5235     if ( !shadowSession )
5236         suspendSession ( resumingSession.sessionId );
5237     else
5238         termSession ( resumingSession.sessionId,false );
5239 }
5240 
slotTermSessFromSt()5241 void ONMainWindow::slotTermSessFromSt()
5242 {
5243 #ifdef Q_OS_UNIX
5244     if (directRDP)
5245     {
5246 
5247         if(brokerMode)
5248         {
5249             sendEventToBroker(TERMINATING);
5250         }
5251         x2goDebug<<"Terminating direct RDP session.";
5252 
5253         nxproxy->terminate();
5254         proxyRunning=false;
5255         return;
5256     }
5257 #endif
5258 
5259 
5260     if ( !shadowSession )
5261     {
5262         if ( termSession ( resumingSession.sessionId ) )
5263         {
5264             sbExp->setEnabled ( false );
5265             if(brokerMode)
5266             {
5267                 sendEventToBroker(TERMINATING);
5268             }
5269             setStatStatus ( tr ( "terminating" ) );
5270         }
5271     }
5272     else
5273     {
5274         sbExp->setEnabled ( false );
5275         if(brokerMode)
5276         {
5277             sendEventToBroker(TERMINATING);
5278         }
5279         termSession ( resumingSession.sessionId,false );
5280     }
5281 }
5282 
5283 
slotRetSuspSess(bool result,QString output,int)5284 void ONMainWindow::slotRetSuspSess ( bool result, QString output,
5285                                      int )
5286 {
5287     setEnabled ( true );
5288     if ( result==false )
5289     {
5290         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
5291         if ( message.indexOf ( "publickey,password" ) !=-1 )
5292         {
5293             message=tr (
5294                         "<b>Wrong password!</b><br><br>" ) +message;
5295         }
5296 
5297         QMessageBox::critical ( 0l,tr ( "Error" ),message,
5298                                 QMessageBox::Ok,
5299                                 QMessageBox::NoButton );
5300     }
5301     else
5302     {
5303         if ( selectSessionDlg->isVisible() )
5304         {
5305             ( ( QStandardItemModel* )
5306               ( sessTv->model() ) )->item (
5307                   sessTv->currentIndex().row(),
5308                   S_STATUS )->setData (
5309                       QVariant ( ( QString ) tr ( "suspended" ) ),
5310                       Qt::DisplayRole );
5311             bSusp->setEnabled ( false );
5312             sOk->setEnabled ( true );
5313 
5314         }
5315     }
5316     if ( selectSessionDlg->isVisible() )
5317         selectSessionDlg->setEnabled ( true );
5318     if (resumeAfterSuspending)
5319     {
5320         slotResumeSess();
5321     }
5322 }
5323 
5324 
5325 
slotTermSess()5326 void ONMainWindow::slotTermSess()
5327 {
5328 
5329 #ifdef Q_OS_UNIX
5330     if (directRDP)
5331     {
5332         nxproxy->terminate();
5333         proxyRunning=false;
5334         return;
5335     }
5336 #endif
5337 
5338     selectSessionDlg->setEnabled ( false );
5339 
5340 
5341     QString sessId=sessTv->model()->index ( sessTv->currentIndex().row(),
5342                                             S_ID ).data().toString();
5343     QString host=sessTv->model()->index (
5344                                             sessTv->currentIndex().row(),
5345                                             S_SERVER ).data().toString();
5346 
5347     if ( !useLdap )
5348     {
5349         if ( !embedMode )
5350         {
5351             X2goSettings st ( "sessions" );
5352 
5353             if (!(sessionExplorer->getLastSession())) {
5354                 x2goDebug << "No session selected, returning without terminating a session.";
5355                 return;
5356             }
5357 
5358             QString sid=sessionExplorer->getLastSession()->id();
5359         }
5360     }
5361     else
5362     {
5363         sshConnection=findServerSshConnection(host);
5364         if (!sshConnection)
5365         {
5366             QMessageBox::critical ( 0l,tr ( "Error" ),
5367                                     tr ( "Server not available." ),
5368                                     QMessageBox::Ok,
5369                                     QMessageBox::NoButton );
5370             return;
5371         }
5372     }
5373     if(brokerMode)
5374     {
5375         termBrokerSession(sessId, host);
5376     }
5377     else
5378     {
5379         termSession ( sessId );
5380     }
5381 }
5382 
5383 
slotNewSess()5384 void ONMainWindow::slotNewSess()
5385 {
5386     startNewSession();
5387 }
5388 
5389 
slotRetTermSess(bool result,QString output,int)5390 void ONMainWindow::slotRetTermSess ( bool result,  QString output,
5391                                      int )
5392 {
5393     setEnabled ( true );
5394     if ( result==false )
5395     {
5396         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
5397         if ( message.indexOf ( "publickey,password" ) !=-1 )
5398         {
5399             message=tr (
5400                         "<b>Wrong password!</b><br><br>" ) +message;
5401         }
5402 
5403         QMessageBox::critical ( 0l,tr ( "Error" ),
5404                                 message,QMessageBox::Ok,
5405                                 QMessageBox::NoButton );
5406     }
5407     else
5408     {
5409         if ( selectSessionDlg->isVisible()  )
5410         {
5411             sessTv->model()->removeRow (
5412                 sessTv->currentIndex().row() );
5413             slotActivated ( sessTv->currentIndex() );
5414         }
5415     }
5416     if ( selectSessionDlg->isVisible() )
5417         selectSessionDlg->setEnabled ( true );
5418 }
5419 
slotRetResumeSess(bool result,QString output,int)5420 void ONMainWindow::slotRetResumeSess ( bool result,
5421                                        QString output,
5422                                        int )
5423 {
5424 
5425     x2goDebug<<"Agent output: "<<output;
5426 
5427     if ( result==false )
5428     {
5429         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
5430         if ( message.indexOf ( "publickey,password" ) !=-1 )
5431         {
5432             message=tr (
5433                         "<b>Wrong Password!</b><br><br>" ) +message;
5434         }
5435         if ( output.indexOf ( "LIMIT" ) !=-1 )
5436         {
5437             QString sessions=output.mid (
5438                                  output.indexOf ( "LIMIT" ) +6 );
5439 
5440             message="Sessions limit reached:"+sessions;
5441         }
5442         if ( output.indexOf ( "ACCESS DENIED" ) !=-1 )
5443         {
5444             message="Access denied for user";
5445         }
5446 
5447         QMessageBox::critical ( 0l,tr ( "Error" ),
5448                                 message,QMessageBox::Ok,
5449                                 QMessageBox::NoButton );
5450         slotShowPassForm();
5451         return;
5452     }
5453 
5454     output.replace ( " ","" );
5455     QString passwd=getCurrentPass();
5456     QString user=getCurrentUname();
5457     QString host;
5458 
5459     bool sound=true;
5460     bool kdrive=false;
5461     int sndSystem=PULSE;
5462     QString sndPort;
5463 #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN)
5464     sndPort="4713";
5465 #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5466     bool startSoundServer=true;
5467     bool sshSndTunnel=true;
5468 
5469     if ( useLdap )
5470     {
5471         sound=startSound;
5472         startSoundServer=LDAPSndStartServer;
5473         if ( LDAPSndSys=="arts" )
5474             sndSystem=ARTS;
5475         if ( LDAPSndSys=="esd" )
5476             sndSystem=ESD;
5477         sndPort=LDAPSndPort;
5478     }
5479     else
5480     {
5481         QString sid;
5482         if ( !embedMode ) {
5483             if (!(sessionExplorer->getLastSession())) {
5484                 x2goDebug << "No session selected, this should not happen since we already started resuming a session.";
5485                 return;
5486             }
5487 
5488             sid=sessionExplorer->getLastSession()->id();
5489         }
5490         else
5491             sid="embedded";
5492 
5493         X2goSettings* st;
5494         if (!brokerMode)
5495             st= new X2goSettings( "sessions" );
5496         else
5497             st= new X2goSettings(config.iniFile,QSettings::IniFormat);
5498 
5499         kdrive=st->setting()->value ( sid+"/kdrive",
5500                                      ( QVariant ) false ).toBool();
5501         sound=st->setting()->value ( sid+"/sound",
5502                                      ( QVariant ) true ).toBool();
5503         QString sndsys=st->setting()->value (
5504                            sid+"/soundsystem",
5505                            ( QVariant ) "pulse" ).toString();
5506         if ( sndsys=="arts" )
5507             sndSystem=ARTS;
5508         if ( sndsys=="esd" )
5509             sndSystem=ESD;
5510 #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN)
5511         sndPort=st->setting()->value ( sid+"/sndport" ).toString();
5512 #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5513         startSoundServer=st->setting()->value (
5514                              sid+"/startsoundsystem",
5515                              true ).toBool();
5516 
5517         if ( embedMode&&config.confSnd )
5518         {
5519             sound=config.useSnd;
5520         }
5521 
5522 
5523 #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN)
5524         bool defPort=st->setting()->value ( sid+
5525                                             "/defsndport",true ).toBool();
5526         if ( defPort )
5527         {
5528             switch ( sndSystem )
5529             {
5530             case PULSE:
5531                 sndPort="4713";
5532                 break;
5533             case ESD:
5534                 sndPort="16001";
5535                 break;
5536             }
5537         }
5538 #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5539         sshSndTunnel=st->setting()->value ( sid+"/soundtunnel",
5540                                             true ).toBool();
5541 
5542 #if defined (Q_OS_WIN) || defined (Q_OS_DARWIN)
5543         if (sound)
5544         {
5545             if(!pulseManager || !(pulseManager->is_server_running()))
5546             {
5547                 X2goSettings st ("settings");
5548                 bool disablePA = st.setting ()->value ("pulse/disable",
5549                                                    (QVariant) false).toBool ();
5550                 if(!systemDisablePA && ! disablePA)
5551                 {
5552                     show_RichText_WarningMsgBox (tr("PulseAudio is not running"),
5553                                                  tr("Sound output will be disabled for this session. Please enable PulseAudio in the configuration dialog or disable sound in the session settings"),true);
5554                 }
5555                 sound=false;
5556             }
5557             else
5558             {
5559                 switch (sndSystem)
5560                 {
5561                     case PULSE:
5562                         sndPort = QString::number (pulseManager->get_pulse_port ());
5563                     break;
5564                     case ESD:
5565                         sndPort = QString::number (pulseManager->get_esd_port ());
5566                     break;
5567                }
5568             }
5569         }
5570 
5571 #endif /* defined (Q_OS_WIN) || defined (Q_OS_DARWIN) */
5572 
5573         delete st;
5574 
5575     }
5576 
5577     //Will be used in runCommand
5578     startSessSound=sound;
5579     startSessSndSystem=sndSystem;
5580 
5581     if ( newSession )
5582     {
5583         QString sString=output.trimmed();
5584         sString.replace ( '\n','|' );
5585         host=resumingSession.server;
5586         resumingSession=getNewSessionFromString ( sString );
5587         if(kdrive)
5588         {
5589             resumingSession.sessionType=x2goSession::KDRIVE;
5590         }
5591         resumingSession.server=host;
5592         resumingSession.crTime=QDateTime::currentDateTime().toString (
5593                                    "dd.MM.yy HH:mm:ss" );
5594         if ( managedMode )
5595         {
5596             //replace session data for future resuming
5597             config.sessiondata=resumingSession.agentPid+"|"+
5598                                resumingSession.sessionId+"|"+
5599                                resumingSession.display+"|"+
5600                                resumingSession.server+"|"+
5601                                "S|"+
5602                                resumingSession.crTime+"|"+
5603                                resumingSession.cookie+"|"+
5604                                resumingSession.clientIp+"|"+
5605                                resumingSession.grPort+"|"+
5606                                resumingSession.sndPort+"|"+
5607                                resumingSession.crTime+"|"+
5608                                user+"|"+
5609                                "0|"+
5610                                resumingSession.fsPort;
5611         }
5612 
5613         //change the trayicon picture
5614         if (debugging) {
5615             setTrayIconToSessionIcon(tr("New session started") + ": " + resumingSession.sessionId);
5616         } else {
5617             setTrayIconToSessionIcon(tr("New session started") + ".");
5618         }
5619 
5620     }
5621     else
5622     {
5623 
5624         if(resumingSession.sessionType==x2goSession::KDRIVE)
5625         {
5626             qDebug()<<"resuming kdrive session";
5627         }
5628         else
5629         {
5630             qDebug()<<"resuming normal session";
5631         }
5632         host=resumingSession.server;
5633         QStringList outputLines=output.split("\n",QString::SkipEmptyParts);
5634         foreach(QString line,outputLines)
5635         {
5636             if (line.indexOf("gr_port=")!=-1)
5637             {
5638                 resumingSession.grPort=line.replace("gr_port=","");
5639 
5640                 x2goDebug<<"New gr_port: "<<resumingSession.grPort;
5641 
5642             }
5643             if (line.indexOf("sound_port=")!=-1)
5644             {
5645                 resumingSession.sndPort=line.replace("sound_port=","");
5646 
5647                 x2goDebug<<"New sound_port: "<<resumingSession.sndPort;
5648 
5649             }
5650             if (line.indexOf("fs_port=")!=-1)
5651             {
5652                 resumingSession.fsPort=line.replace("fs_port=","");
5653 
5654                 x2goDebug<<"New fs_port: "<<resumingSession.fsPort;
5655 
5656             }
5657         }
5658         if (resumingSession.published)
5659             readApplications();
5660 
5661         //change the trayicon picture
5662         if (debugging) {
5663             setTrayIconToSessionIcon(tr("Session resumed") + ": " + resumingSession.sessionId);
5664         } else {
5665             setTrayIconToSessionIcon(tr("Session resumed") + ".");
5666         }
5667 
5668     }
5669     if ( !useLdap )
5670     {
5671         if ( brokerMode )
5672         {
5673             host=config.serverIp;
5674         }
5675         else if ( embedMode )
5676         {
5677             host=config.server;
5678         }
5679         else
5680         {
5681             X2goSettings st ( "sessions" );
5682 
5683             QString sid=sessionExplorer->getLastSession()->id();
5684             host=st.setting()->value ( sid+"/host",
5685                                        ( QVariant ) host ).toString();
5686         }
5687         resumingSession.server=host;
5688     }
5689 
5690 
5691     localGraphicPort=resumingSession.grPort;
5692     int iport=localGraphicPort.toInt() +1000;
5693     while ( iport == resumingSession.sndPort.toInt() ||
5694             iport == resumingSession.fsPort.toInt() ||
5695             isServerRunning ( iport ) )
5696         ++iport;
5697     localGraphicPort=QString::number ( iport );
5698 
5699     sshConnection->startTunnel ( "localhost",resumingSession.grPort.toInt(),"localhost",
5700                                  localGraphicPort.toInt(), false, this,  SLOT ( slotTunnelOk(int) ), SLOT ( slotTunnelFailed ( bool,
5701                                          QString,int ) ) );
5702     if ( shadowSession )
5703         return;
5704 
5705     sndTunnel=0l;
5706     if ( sound )
5707     {
5708         if ( sndSystem==PULSE )
5709         {
5710             startSoundServer=false;
5711             QString scmd;
5712             if ( !sshSndTunnel )
5713                 scmd="echo \"default-server=$(echo "
5714                      "\"$SSH_CLIENT\" | awk '{print $1}'):"+
5715                      sndPort+
5716                      "\" > \"${HOME}/.x2go/C-"+
5717                      resumingSession.sessionId+
5718                      "/.pulse-client.conf\""
5719                      ";echo \"cookie-file=${HOME}/.x2go/C-"+
5720                      resumingSession.sessionId+
5721                      "/.pulse-cookie"+
5722                      "\" >> \"${HOME}/.x2go/C-"+
5723                      resumingSession.sessionId+
5724                      "/.pulse-client.conf\""
5725                      ";echo \"autospawn=no\" >>"
5726                      "\"${HOME}/.x2go/C-" +
5727                      resumingSession.sessionId +
5728                      "/.pulse-client.conf\"";
5729             else
5730                 scmd="echo \"default-server=localhost:"+
5731                      resumingSession.sndPort+
5732                      "\" > \"${HOME}/.x2go/C-"+
5733                      resumingSession.sessionId+
5734                      "/.pulse-client.conf\""
5735                      ";echo \"cookie-file=${HOME}/.x2go/C-"+
5736                      resumingSession.sessionId+
5737                      "/.pulse-cookie"+
5738                      "\" >> \"${HOME}/.x2go/C-"+
5739                      resumingSession.sessionId+
5740                      "/.pulse-client.conf\""
5741                      ";echo \"autospawn=no\" >>"
5742                      "\"${HOME}/.x2go/C-" +
5743                      resumingSession.sessionId +
5744                      "/.pulse-client.conf\"";
5745 
5746             sshConnection->executeCommand (scmd);
5747 
5748             bool sysPulse=false;
5749 #ifdef Q_OS_UNIX
5750             loadPulseModuleNativeProtocol();
5751             QFile file ( "/etc/default/pulseaudio" );
5752             if ( file.open ( QIODevice::ReadOnly |
5753                              QIODevice::Text ) )
5754             {
5755 
5756                 while ( !file.atEnd() )
5757                 {
5758                     QByteArray line = file.readLine();
5759                     int pos=line.indexOf (
5760                                 "PULSEAUDIO_SYSTEM_START=1"
5761                             );
5762                     if ( pos!=-1 )
5763                     {
5764                         int commentPos=line.indexOf (
5765                                            "#" );
5766                         if ( commentPos==-1 ||
5767                                 commentPos>pos )
5768                         {
5769                             sysPulse=true;
5770                             break;
5771                         }
5772                     }
5773                 }
5774                 file.close();
5775             }
5776 #endif
5777             QString pulsecookie_filename = "";
5778             if ( sysPulse )
5779             {
5780                 if ( QFile::exists("/run/pulse/.config/pulse/cookie") ) {
5781                     pulsecookie_filename = "/run/pulse/.config/pulse/cookie";
5782                 }
5783                 else if ( QFile::exists("/run/pulse/.pulse-cookie") ) {
5784                     pulsecookie_filename = "/run/pulse/.pulse-cookie";
5785                 }
5786                 else if ( QFile::exists("/var/run/pulse/.config/pulse/cookie") ) {
5787                     pulsecookie_filename = "/var/run/pulse/.config/pulse/cookie";
5788                 }
5789                 else if ( QFile::exists("/var/run/pulse/.pulse-cookie") ) {
5790                     pulsecookie_filename = "/var/run/pulse/.pulse-cookie";
5791                 }
5792                 if ( pulsecookie_filename.length() > 0 )
5793                 {
5794                     sshConnection->copyFile(
5795                         pulsecookie_filename,
5796                         "$HOME/.x2go/C-"+
5797                         resumingSession.sessionId+
5798                         "/.pulse-cookie", this, SLOT ( slotPCookieReady ( bool, QString,int )));
5799                 }
5800             }
5801             else
5802             {
5803 #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN)
5804                 if ( QFile::exists(homeDir+"/.config/pulse/cookie") ) {
5805                     pulsecookie_filename = homeDir+"/.config/pulse/cookie";
5806                 }
5807                 else if ( QFile::exists(homeDir+"/.pulse-cookie") ) {
5808                     pulsecookie_filename = homeDir+"/.pulse-cookie";
5809                 }
5810                 if ( pulsecookie_filename.length() > 0 )
5811                 {
5812                     sshConnection->copyFile(pulsecookie_filename,
5813                                             "$HOME/.x2go/C-"+
5814                                             resumingSession.sessionId+
5815                                             "/.pulse-cookie", this, SLOT ( slotPCookieReady ( bool, QString,int )));
5816                 }
5817 #else /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5818                 QString cooFile = QDir::toNativeSeparators (QDir (pulseManager->get_pulse_dir ().absolutePath () +
5819                                                                   "/.pulse-cookie").absolutePath ());
5820                 QString destFile="$HOME/.x2go/C-"+
5821                                  resumingSession.sessionId+
5822                                  "/.pulse-cookie";
5823                 sshConnection->copyFile(cooFile,
5824                                         destFile, this, SLOT ( slotPCookieReady ( bool, QString,int )));
5825 #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5826             }
5827         }
5828         if ( sndSystem==ESD )
5829         {
5830 #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN)
5831             sshConnection->copyFile(homeDir+"/.esd_auth",
5832                                     "$HOME/.esd_auth" );
5833 #else /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5834             QString cooFile = QDir::toNativeSeparators (QDir (pulseManager->get_pulse_dir ().absolutePath () +
5835                                                               "/.esd_auth").absolutePath ());
5836             QString destFile="$HOME/.esd_auth";
5837             sshConnection->copyFile(cooFile,
5838                                     destFile );
5839 #endif /* defined (Q_OS_UNIX) */
5840         }
5841 /* Windows and Darwin are covered by PulseManager. */
5842 #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN)
5843         if ( startSoundServer )
5844         {
5845             soundServer=new QProcess ( this );
5846             QString acmd="artsd",ecmd="esd";
5847             if ( sndSystem==ESD )
5848                 soundServer->start (
5849                     ecmd+
5850                     " -tcp -nobeeps -bind localhost -port "+
5851                     resumingSession.sndPort );
5852             if ( sndSystem==ARTS )
5853                 soundServer->start ( acmd+" -u -N -p "+
5854                                      resumingSession.sndPort );
5855             sndPort=resumingSession.sndPort;
5856         }
5857 #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */
5858         if ( sshSndTunnel )
5859         {
5860             sndTunnel=sshConnection->startTunnel (
5861                           "localhost",
5862                           resumingSession.sndPort.toInt(),"127.0.0.1",
5863                           sndPort.toInt(),true,this,NULL, SLOT (
5864                               slotSndTunnelFailed ( bool,
5865                                                     QString,
5866                                                     int ) ));
5867         }
5868     }
5869 }
5870 
5871 
5872 
getSelectedSession()5873 x2goSession ONMainWindow::getSelectedSession()
5874 {
5875     QString sessId=sessTv->model()->index ( sessTv->currentIndex().row(),
5876                                             S_ID ).data().toString();
5877     for ( int i=0; i<selectedSessions.size(); ++i )
5878     {
5879         if ( selectedSessions[i].sessionId==sessId )
5880             return selectedSessions[i];
5881     }
5882     return selectedSessions[0]; //warning !!!!! undefined session
5883 }
5884 
5885 
slotTunnelOk(int)5886 void ONMainWindow::slotTunnelOk(int)
5887 {
5888 
5889 #ifdef Q_OS_WIN
5890     //waiting for X
5891     if ( !winServersReady )
5892     {
5893 
5894         x2goDebug<<"Waiting for win-servers.";
5895 
5896         QTimer::singleShot ( 100, this, SLOT ( slotTunnelOk() ) );
5897         return;
5898     }
5899 #endif
5900 
5901     showExport=false;
5902     QString nxroot=homeDir +"/.x2go";
5903     QString dirpath=nxroot+"/S-"+resumingSession.sessionId;
5904     QDir d ( dirpath );
5905     if ( !d.exists() )
5906         if ( !d.mkpath ( dirpath ) )
5907         {
5908             if (startHidden)
5909             {
5910                 x2goErrorf(6)<< tr( "Unable to create folder: ")  + dirpath;
5911                 trayQuit();
5912             }
5913 
5914             QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Unable to create folder: " ) + dirpath,
5915                                     QMessageBox::Ok,
5916                                     QMessageBox::NoButton );
5917             slotShowPassForm();
5918 //             if ( tunnel )
5919 //                 delete tunnel;
5920 //             if ( sndTunnel )
5921 //                 delete sndTunnel;
5922 //             if ( fsTunnel )
5923 //                 delete fsTunnel;
5924 //             if ( soundServer )
5925 //                 delete soundServer;
5926             tunnel=sndTunnel=fsTunnel=0l;
5927             soundServer=0l;
5928             nxproxy=0l;
5929             return;
5930         }
5931 #ifdef Q_OS_WIN
5932     dirpath=wapiShortFileName ( dirpath );
5933     nxroot=wapiShortFileName ( nxroot );
5934 #endif
5935     QFile file ( dirpath+"/options" );
5936     if ( !file.open ( QIODevice::WriteOnly | QIODevice::Text ) )
5937     {
5938         if (startHidden)
5939         {
5940             x2goErrorf(7)<< tr( "Unable to write file: " ) + dirpath + "/options";
5941             trayQuit();
5942         }
5943 
5944         QMessageBox::critical ( 0l,tr ( "Error" ), tr( "Unable to write file: " ) + dirpath + "/options",
5945                                 QMessageBox::Ok,
5946                                 QMessageBox::NoButton );
5947         slotShowPassForm();
5948         return;
5949     }
5950 
5951     QTextStream out ( &file );
5952 #ifdef Q_OS_WIN
5953     dirpath=cygwinPath ( dirpath );
5954     nxroot=cygwinPath ( nxroot );
5955 #endif
5956     out << "nx/nx,root="<<nxroot<<",connect=localhost,cookie="<<
5957         resumingSession.cookie<<",port="
5958         <<localGraphicPort/*resumingSession.grPort*/<<
5959         ",errors="<<dirpath<<"/sessions:"<<
5960         resumingSession.display;
5961     file.close();
5962     xmodExecuted=false;
5963 
5964 
5965     qDebug()<<"RESUMING SESSION is KDRIVE: "<<(resumingSession.sessionType== x2goSession::KDRIVE);
5966 
5967     nxproxy=new QProcess;
5968     proxyErrString="";
5969     QStringList env = QProcess::systemEnvironment();
5970 #if defined ( Q_OS_WIN ) || defined ( Q_OS_DARWIN )
5971     int dispInd=-1;
5972 #endif
5973     for ( int l=0; l<env.size(); ++l )
5974     {
5975 // 		x2goDebug<<env[l]<<endl;
5976 
5977 #if defined ( Q_OS_WIN ) || defined ( Q_OS_DARWIN )
5978         if ( env[l].indexOf ( "DISPLAY" ) ==0 )
5979         {
5980             dispInd=l;
5981         }
5982 #endif
5983     }
5984     env << "NX_CLIENT="+QCoreApplication::applicationFilePath ();
5985 
5986 #if defined ( Q_OS_WIN ) || defined ( Q_OS_DARWIN )
5987     // On Mac OS X, we want to make sure that DISPLAY is set to a proper value,
5988     // but at the same time don't want to set the value ourselves but keep
5989     // the provided one.
5990 
5991     QString disp="0";
5992     if(resumingSession.sessionType!= x2goSession::KDRIVE)
5993     {
5994         disp=getXDisplay();
5995         if ( disp==QString::null )
5996         {
5997             //slotProxyerror ( QProcess::FailedToStart );
5998             return;
5999         }
6000     }
6001 #endif // Q_OS_WIN || Q_OS_DARWIN
6002 #if defined ( Q_OS_WIN )
6003     if ( dispInd==-1 )
6004     {
6005         env <<"DISPLAY=localhost:"+disp;
6006 
6007         /*		x2goDebug<<"new env DISPLAY"<<"DISPLAY=localhost:"+disp<<endl;*/
6008 
6009     }
6010     else
6011     {
6012         env[dispInd]="DISPLAY=localhost:"+disp;
6013 
6014         /*		x2goDebug<<"existing env DISPLAY("<<dispInd<<
6015         		") DISPLAY=localhost:"+disp<<endl;*/
6016 
6017     }
6018 #endif // Q_OS_WIN
6019 #if defined ( Q_OS_DARWIN )
6020     // setting /usr/X11/bin to find xauth
6021     // /usr/X11R6/bin is added for compatibility reasons with OS X 10.4.
6022     /* FIXME: don't just overwrite this stuff, use add_to_path () instead. */
6023     env.insert (
6024         0,
6025         "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/X11R6/bin" );
6026     // Set the NX base dir to bundle/exe/, used for finding nxauth.
6027     {
6028         QDir tmpDir (appDir);
6029         tmpDir.cd ("../exe");
6030         env.append ("NX_SYSTEM=" + tmpDir.absolutePath ());
6031     }
6032     if (dispInd == -1)
6033     {
6034 
6035         x2goDebug<< "No DISPLAY variable found in global environment, using autodetected setting.";
6036 
6037         env.append ("DISPLAY=" + disp);
6038     }
6039 #endif
6040     nxproxy->setEnvironment ( env );
6041 
6042     connect ( nxproxy,SIGNAL ( error ( QProcess::ProcessError ) ),this,
6043               SLOT ( slotProxyError ( QProcess::ProcessError ) ) );
6044     connect ( nxproxy,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this,
6045               SLOT ( slotProxyFinished ( int,QProcess::ExitStatus ) ) );
6046     connect ( nxproxy,SIGNAL ( readyReadStandardError() ),this,
6047               SLOT ( slotProxyStderr() ) );
6048     connect ( nxproxy,SIGNAL ( readyReadStandardOutput() ),this,
6049               SLOT ( slotProxyStdout() ) );
6050 
6051     QString proxyCmd="nxproxy -S nx/nx,options="+dirpath+"/options:"+
6052                      resumingSession.display;
6053 
6054 #ifdef Q_OS_DARWIN
6055     //run nxproxy from bundle
6056     QDir dir ( appDir );
6057     dir.cdUp();
6058     dir.cd ( "exe" );
6059     proxyCmd="\""+dir.absolutePath() +"/\""+proxyCmd;
6060 #endif //Q_OS_DARWIN
6061 
6062 
6063     if(resumingSession.sessionType==x2goSession::KDRIVE)
6064     {
6065         bool randr=false;
6066         bool fs=false;
6067         QString width;
6068         QString height;
6069         bool multidisp=false;
6070         QString dispNumber="1";
6071 
6072         if (!embedMode )
6073         {
6074             if (!useLdap)
6075             {
6076                 X2goSettings *st;
6077                 QString sid;
6078                 if ( !embedMode ) {
6079                     if (!(sessionExplorer->getLastSession())) {
6080                         x2goDebug << "No session selected, not searching for proxy window.";
6081                         return;
6082                     }
6083 
6084                     sid=sessionExplorer->getLastSession()->id();
6085                 }
6086                 else
6087                     sid="embedded";
6088 
6089                 if (brokerMode)
6090                     st=new X2goSettings(config.iniFile,QSettings::IniFormat);
6091                 else
6092                     st= new X2goSettings( "sessions" );
6093                 randr=st->setting()->value ( sid+"/xinerama",
6094                                              ( QVariant ) defaultXinerama ).toBool();
6095                 fs=st->setting()->value ( sid+"/fullscreen", ( QVariant ) defaultFullscreen).toBool();
6096 
6097                 width=st->setting()->value ( sid+"/width", ( QVariant ) "800").toString();
6098                 height=st->setting()->value ( sid+"/height", ( QVariant ) "600").toString();
6099 
6100 
6101                 if (st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool())
6102                 {
6103                     dispNumber=st->setting()->value ( sid+"/display", (QVariant ) "1").toString();
6104                     multidisp=st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool();
6105                 }
6106                 delete st;
6107             }
6108         }
6109 
6110         QStringList options;
6111 #ifdef Q_OS_WIN
6112         //restore real path, as we not using cygwin for x2gokdriveclient
6113         nxroot=homeDir +"/.x2go";
6114         dirpath=nxroot+"/S-"+resumingSession.sessionId;
6115 #endif
6116         proxyCmd="x2gokdriveclient";
6117         options<<"--connect"<<"localhost"<<"--port"<<localGraphicPort<<"--title"<<resumingSession.sessionId<<"-S"<<"nx/nx,options="+dirpath+
6118         "/options:"+resumingSession.display;
6119         if(randr)
6120         {
6121             options<<"--randr";
6122         }
6123         if(fs)
6124         {
6125             options<<"--fs";
6126         }
6127         else
6128             if(multidisp)
6129             {
6130                 options<<"--screen"<<dispNumber;
6131             }
6132             else
6133             {
6134                 options<<"--width"<<width<<"--height"<<height;
6135             }
6136 
6137         x2goDebug<<"Starting NX proxy, command: " + proxyCmd<<options;
6138         nxproxy->start ( proxyCmd, options );
6139     }
6140     else
6141     {
6142         x2goDebug<<"Starting NX proxy, command: " + proxyCmd;
6143         nxproxy->start ( proxyCmd);
6144     }
6145 
6146     proxyRunning=true;
6147     if(brokerMode)
6148     {
6149         sendEventToBroker(CONNECTING);
6150     }
6151 
6152 // always search for proxy window on linux. On Windows only in window mode
6153 #ifdef Q_OS_WIN
6154     if (xorgMode==WIN) {
6155 #endif
6156         proxyWinTimer->start ( 300 );
6157 #ifdef Q_OS_WIN
6158     }
6159 #endif
6160     if ( embedMode )
6161     {
6162 //         proxyWinTimer->start ( 300 );
6163         if ( !startEmbedded )
6164         {
6165             act_embedContol->setText (
6166                 tr ( "Attach X2Go window" ) );
6167         }
6168     }
6169 #ifdef Q_OS_WIN
6170     else
6171     {
6172 // #ifdef CFGCLIENT
6173 //         // if using XMing, we must find proxy win for case, that we should make it fullscreen
6174         //         if(useInternalX&& (internalX==XMING))
6175 // #endif
6176 //         proxyWinTimer->start ( 300 );
6177     }
6178 #endif
6179 
6180     showSessionStatus();
6181     QTimer::singleShot ( 30000,this,SLOT ( slotRestartProxy() ) );
6182 
6183 }
6184 
slotTunnelFailed(bool result,QString output,int)6185 void ONMainWindow::slotTunnelFailed ( bool result,  QString output,
6186                                       int )
6187 {
6188     if ( result==false )
6189     {
6190         if ( !managedMode )
6191         {
6192             QString message=tr ( "Unable to create SSH tunnel for X2Go session (NX) startup:\n" )
6193                             +output;
6194             QMessageBox::critical ( 0l,tr ( "Error" ),message,
6195                                     QMessageBox::Ok,
6196                                     QMessageBox::NoButton );
6197         }
6198 //         if ( tunnel )
6199 //             delete tunnel;
6200 //         if ( sndTunnel )
6201 //             delete sndTunnel;
6202 //         if ( fsTunnel )
6203 //             delete fsTunnel;
6204 //         if ( soundServer )
6205 //             delete soundServer;
6206         tunnel=sndTunnel=fsTunnel=0l;
6207         soundServer=0l;
6208         nxproxy=0l;
6209         proxyRunning=false;
6210         if ( !managedMode )
6211             slotShowPassForm();
6212     }
6213 }
6214 
slotSndTunnelFailed(bool result,QString output,int)6215 void ONMainWindow::slotSndTunnelFailed ( bool result,  QString output,
6216         int )
6217 {
6218     if ( result==false )
6219     {
6220         if ( !managedMode )
6221         {
6222             QString message=tr ( "Unable to create SSH tunnel for audio data:\n" )
6223                             +output;
6224             QMessageBox::warning ( 0l,tr ( "Warning" ),message,
6225                                    QMessageBox::Ok,
6226                                    QMessageBox::NoButton );
6227         }
6228         sndTunnel=0l;
6229     }
6230 }
6231 
6232 
6233 #ifdef Q_OS_DARWIN
slotSetModMap()6234 void ONMainWindow::slotSetModMap()
6235 {
6236     if (!nxproxy) {
6237         return;
6238     }
6239     if (kbMap.isEmpty ()) {
6240         QProcess pr (this);
6241         QProcessEnvironment tmp_env = QProcessEnvironment::systemEnvironment ();
6242         QString path_val = tmp_env.value ("PATH");
6243 
6244         /* Let's set a reasonable default value if none is provided. */
6245         if (path_val.isEmpty ()) {
6246             /* Prefer the default MacPorts prefix. */
6247             path_val = MACPORTS_PREFIX "/bin:" MACPORTS_PREFIX "/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:/opt/X11/bin";
6248             tmp_env.insert ("PATH", path_val);
6249         }
6250         else {
6251             /* Search for and add specific directories to the PATH value, if necessary. */
6252             QStringList to_back, to_front;
6253             to_back << "/opt/X11/bin";
6254             to_front << MACPORTS_PREFIX "/bin" << "/usr/local/bin";
6255 
6256             path_val = add_to_path (path_val, to_back);
6257             path_val = add_to_path (path_val, to_front, false);
6258 
6259             /* Insert will overwrite the value automatically. */
6260             tmp_env.insert ("PATH", path_val);
6261 
6262             /*
6263              * Also alter our own environment so we can actually
6264              * execute xmodmap and friends later on.
6265              */
6266             qputenv ("PATH", path_val.toUtf8 ());
6267         }
6268 
6269         pr.setProcessEnvironment (tmp_env);
6270 
6271         QStringList key_map_fetch_args;
6272         key_map_fetch_args << "-pke";
6273         pr.start ("xmodmap", key_map_fetch_args);
6274         bool key_map_fetch_ret = pr.waitForStarted ();
6275 
6276         if (!key_map_fetch_ret) {
6277             handle_xmodmap_error (pr);
6278         }
6279         else {
6280             key_map_fetch_ret = pr.waitForFinished ();
6281 
6282             if (!key_map_fetch_ret) {
6283                 handle_xmodmap_error (pr);
6284             }
6285 
6286             kbMap = pr.readAllStandardOutput ();
6287 
6288             QStringList mod_fetch_args;
6289             mod_fetch_args << "-pm";
6290             pr.start ("xmodmap", mod_fetch_args);
6291             bool mod_fetch_ret = pr.waitForStarted ();
6292 
6293             if (!mod_fetch_ret) {
6294                 handle_xmodmap_error (pr);
6295             }
6296             else {
6297                 mod_fetch_ret = pr.waitForFinished ();
6298 
6299                 if (!mod_fetch_ret) {
6300                     handle_xmodmap_error (pr);
6301                 }
6302 
6303                 QString modifiers = pr.readAllStandardOutput ();
6304                 x2goDebug << "modifiers: " << modifiers;
6305 
6306                 /* Reset all modifiers first. */
6307                 kbMap += "clear shift\nclear lock\nclear control\nclear mod1\nclear mod2\nclear mod3\nclear mod4\nclear mod5\n";
6308 
6309                 /* And set them back again. */
6310                 QStringList lines = modifiers.split ("\n", QString::SkipEmptyParts);
6311                 for (int i = 0; i < lines.count (); ++i) {
6312                     QStringList parts = lines[i].split (" ", QString::SkipEmptyParts);
6313                     if (parts.count () < 2) {
6314                         continue;
6315                     }
6316 
6317                     QString mod = parts[0];
6318                     if ((mod == "shift") || (mod == "lock") || (mod == "control") || (mod == "mod1") || (mod == "mod2") || (mod == "mod3") || (mod == "mod4") || (mod == "mod5")) {
6319                         for (int j = 1; j < parts.count (); ++j) {
6320                             if (parts[j].indexOf ("(") == -1) {
6321                                 kbMap += "add " + mod + " = " + parts[j] + "\n";
6322                             }
6323                         }
6324                     }
6325                 }
6326             }
6327         }
6328     }
6329 
6330     if (kbMap.isEmpty ()) {
6331         x2goWarningf (9) << "Could not fetch keyboard map via xmodmap. Internal error. Not synchronizing with remote side.";
6332     }
6333     else {
6334         /* Send modified map to server. */
6335         QString cmd = "export DISPLAY=\":" + resumingSession.display + "\"; echo \"" + kbMap + "\" | xmodmap -";
6336         sshConnection->executeCommand (cmd);
6337     }
6338 }
6339 
handle_xmodmap_error(QProcess & proc)6340 void ONMainWindow::handle_xmodmap_error (QProcess &proc) {
6341   QString main_text ("xmodmap ");
6342   QString informative_text;
6343 
6344   QProcessEnvironment proc_env = QProcessEnvironment::systemEnvironment ();
6345 
6346   /* If the process has a special env, fetch it. */
6347   if (!(proc.processEnvironment ().isEmpty ())) {
6348     proc_env = proc.processEnvironment ();
6349   }
6350 
6351   switch (proc.error ()) {
6352     case QProcess::FailedToStart: {
6353       main_text += tr ("failed to start.");
6354       informative_text += tr ("This likely means the binary is not available.\n"
6355                               "The current search path is: ");
6356 
6357       QString path_val = proc_env.value ("PATH", "unknown");
6358 
6359       /* Add a newline every 100 characters. */
6360       for (std::size_t i = 100; i < static_cast<std::size_t> (path_val.size ()); i += 100) {
6361           path_val.insert (i, "\n");
6362       }
6363 
6364       informative_text += path_val;
6365       break;
6366     }
6367     case QProcess::Crashed: {
6368       main_text += tr ("returned a non-zero exit code or crashed otherwise.");
6369       informative_text += tr ("Execution failed, exit code was: ");
6370       informative_text += QString::number (proc.exitCode ());
6371       break;
6372     }
6373     case QProcess::Timedout: {
6374       main_text += tr ("didn't start up in time.");
6375       informative_text = tr ("This error shouldn't come up.");
6376       break;
6377     }
6378     case QProcess::WriteError: {
6379       main_text += tr ("didn't accept a write operation.");
6380       informative_text = tr ("It is probably not running correctly or crashed in-between.");
6381       break;
6382     }
6383     case QProcess::ReadError: {
6384       main_text = tr ("Unable to read from xmodmap.");
6385       informative_text = tr ("It is probably not running correctly or crashed in-between.");
6386       break;
6387     }
6388     case QProcess::UnknownError: {
6389       main_text += tr ("encountered an unknown error during start up or execution.");
6390       break;
6391     }
6392     default: {
6393       main_text += tr ("experienced an undefined error.");
6394       break;
6395     }
6396   }
6397 
6398   if (!informative_text.isEmpty ()) {
6399     informative_text += "\n\n";
6400   }
6401 
6402   informative_text += tr ("X2Go Client will now terminate.\n\n"
6403                           "File a bug report as outlined on the <a href=\"http://wiki.x2go.org/doku.php/wiki:bugs\">bugs wiki page</a>.");
6404 
6405   show_RichText_ErrorMsgBox (main_text, informative_text);
6406   trayQuit ();
6407 }
6408 #endif
6409 
slotProxyError(QProcess::ProcessError err)6410 void ONMainWindow::slotProxyError ( QProcess::ProcessError err )
6411 {
6412 #ifdef Q_OS_UNIX
6413     if(err==QProcess::FailedToStart && directRDP)
6414     {
6415         QString main_text = tr("Failed to start RDP or XDMCP client");
6416         QString informative_text = tr ("Check session settings and ensure that selected client is installed on your system.");
6417 
6418         show_RichText_ErrorMsgBox (main_text, informative_text);
6419     }
6420 #endif
6421     slotProxyFinished ( -1,QProcess::CrashExit );
6422 }
6423 
6424 
slotProxyFinished(int,QProcess::ExitStatus)6425 void ONMainWindow::slotProxyFinished ( int,QProcess::ExitStatus )
6426 {
6427     if(brokerMode)
6428     {
6429         sendEventToBroker(FINISHED);
6430     }
6431 #ifdef Q_OS_DARWIN
6432     if (modMapTimer) {
6433       disconnect (modMapTimer, SIGNAL (timeout ()), this, SLOT (slotSetModMap ()));
6434       modMapTimer->stop ();
6435       delete (modMapTimer);
6436       modMapTimer = 0;
6437     }
6438     kbMap = QString ();
6439 //fixes bug, when mainwindow inputs not accepting focus under mac
6440     setFocus ();
6441 #endif
6442     //set tray icon to default
6443     if (trayIcon && !keepTrayIcon)
6444         trayIcon->setIcon(QIcon ( ":/img/icons/128x128/x2go.png") );
6445 
6446 
6447     if ( embedMode )
6448     {
6449         proxyWinTimer->stop();
6450         setEmbedSessionActionsEnabled ( false );
6451     }
6452 #ifdef Q_OS_WIN
6453     else
6454         proxyWinTimer->stop();
6455     if (! startXorgOnStart)
6456     {
6457         if (xorg)
6458         {
6459             if (xorg->state() ==QProcess::Running)
6460             {
6461                 xorg->terminate();
6462                 delete xorg;
6463                 xorg=0;
6464             }
6465         }
6466     }
6467 #endif
6468     if ( closeEventSent )
6469         return;
6470     if ( soundServer )
6471         delete soundServer;
6472     if ( spoolTimer )
6473         delete spoolTimer;
6474 
6475     x2goDebug<<"Deleting Proxy." ;
6476 
6477     disconnect ( nxproxy,SIGNAL ( error ( QProcess::ProcessError ) ),this,
6478                  SLOT ( slotProxyError ( QProcess::ProcessError ) ) );
6479     disconnect ( nxproxy,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this,
6480                  SLOT ( slotProxyFinished ( int,QProcess::ExitStatus ) ) );
6481     disconnect ( nxproxy,SIGNAL ( readyReadStandardError() ),this,
6482                  SLOT ( slotProxyStderr() ) );
6483     disconnect ( nxproxy,SIGNAL ( readyReadStandardOutput() ),this,
6484                  SLOT ( slotProxyStdout() ) );
6485     proxyRunning=false;
6486     if (trayEnabled)
6487     {
6488         trayIconActiveConnectionMenu->setTitle(tr("Not connected"));
6489         trayIconActiveConnectionMenu->setEnabled(false);
6490         if (trayMaxDiscon)
6491             showNormal();
6492     }
6493     trayAutoHidden=false;
6494     bool emergencyExit=false;
6495 
6496     if(proxyErrString.indexOf("No data received from remote proxy")!=-1)
6497     {
6498         emergencyExit=true;
6499         x2goWarningf(4)<< tr( "Emergency exit." );
6500     }
6501 
6502     if ( nxproxy )
6503     {
6504         if ( nxproxy->state() ==QProcess::Running )
6505         {
6506             emergencyExit=true;
6507             x2goWarningf(5)<< tr( "Waiting for proxy to exit." );
6508             if ( !nxproxy->waitForFinished ( 3000 ) )
6509             {
6510                 x2goWarningf(6)<< tr( "Proxy didn't terminate after 3 seconds. Killing the proxy." );
6511                 nxproxy->kill();
6512             }
6513         }
6514 
6515 #ifdef Q_OS_UNIX
6516         if (directRDP)
6517             nxproxy=0;
6518 #endif
6519     }
6520     x2goDebug<<"Waiting for proxy to exit.";
6521 
6522     spoolTimer=0l;
6523     tunnel=sndTunnel=fsTunnel=0l;
6524     soundServer=0l;
6525     nxproxy=0l;
6526     proxyWinId=0;
6527 
6528 #ifdef Q_OS_UNIX
6529     if (directRDP)
6530     {
6531         if (closeDisconnect)
6532         {
6533             close();
6534         }
6535         pass->setText ( "" );
6536         QTimer::singleShot ( 2000,this,
6537                              SLOT ( slotShowPassForm() ) );
6538         return;
6539     }
6540 #endif
6541     if ( !emergencyExit && !shadowSession && !usePGPCard && ! ( embedMode &&
6542             ( config.checkexitstatus==false ) ) )
6543     {
6544         x2goDebug<<"Checking exit status.";
6545         check_cmd_status();
6546     }
6547     else
6548     {
6549         x2goDebug<<"Deleting SSH connection instance.";
6550         delete sshConnection;
6551         x2goDebug<<"Deleted SSH connection instance." ;
6552         sshConnection=0;
6553         if (startHidden)
6554         {
6555             x2goInfof(9) << tr("Closing X2Go Client because it was started in hidden mode.");
6556             close();
6557         }
6558         else if (closeDisconnect)
6559         {
6560             x2goInfof(10) << tr("Closing X2Go Client because the --close-disconnect parameter was passed.");
6561             close();
6562         }
6563     }
6564 
6565     if ( readExportsFrom!=QString::null )
6566     {
6567         exportTimer->stop();
6568         if ( extLogin )
6569         {
6570             currentKey=QString::null;
6571         }
6572     }
6573     if ( printSupport )
6574         cleanPrintSpool();
6575     if ( !restartResume )
6576     {
6577         if ( brokerMode && (!config.brokerAutologoff) )
6578         {
6579             x2goDebug<<"Re-reading user's session profiles from broker.";
6580             QTimer::singleShot ( 2000,broker,
6581                                  SLOT ( getUserSessions() ) );
6582         }
6583         else if ( brokerMode && config.brokerAutologoff )
6584         {
6585             x2goDebug<<"Logging off from broker as requested via command line.";
6586             QTimer::singleShot(1, this,SLOT(slotGetBrokerAuth()));
6587         }
6588         else if ( !embedMode )
6589         {
6590             pass->setText ( "" );
6591             QTimer::singleShot ( 2000,this,
6592                                  SLOT ( slotShowPassForm() ) );
6593         }
6594     }
6595     else
6596     {
6597         restartResume=false;
6598         sessionStatusDlg->hide();
6599         resumeSession ( resumingSession );
6600     }
6601     x2goDebug<<"Finished proxy.";
6602     setStatStatus ( tr ( "Finished" ) );
6603 #ifdef Q_OS_DARWIN
6604 //fixes bug, when mainwindow inputs not accepting focus under mac
6605     setFocus();
6606 #endif
6607 
6608 }
6609 
6610 
slotProxyStderr()6611 void ONMainWindow::slotProxyStderr()
6612 {
6613     QString reserr;
6614     if ( nxproxy )
6615         reserr= nxproxy->readAllStandardError();
6616     proxyErrString+=reserr;
6617 
6618     x2goDebug<<"Proxy wrote on stderr: "<<reserr;
6619 
6620     if(debugging)
6621     {
6622         QFile fl(homeDir+"/.x2go/S-"+resumingSession.sessionId+"/session.log");
6623         fl.open(QIODevice::WriteOnly|QIODevice::Append);
6624         fl.write(reserr.toLocal8Bit());
6625         fl.close();
6626     }
6627 
6628     stInfo->insertPlainText ( reserr );
6629     stInfo->ensureCursorVisible();
6630     if ( stInfo->toPlainText().indexOf (
6631         "Connecting to remote host 'localhost:"+
6632         /*resumingSession.grPort*/ localGraphicPort ) !=-1 )
6633     {
6634         setStatStatus ( tr ( "connecting" ) );
6635     }
6636 
6637     if ( stInfo->toPlainText().indexOf (
6638                 "Connection to remote proxy 'localhost:"+
6639                 /*resumingSession.grPort*/
6640                 localGraphicPort+"' established" ) !=-1 )
6641     {
6642         if ( newSession )
6643         {
6644             setStatStatus ( tr ( "starting" ) );
6645         }
6646         else
6647         {
6648             setStatStatus ( tr ( "resuming" ) );
6649         }
6650     }
6651 
6652     if ( stInfo->toPlainText().indexOf (
6653                 "Established X server connection" ) !=-1 )
6654     {
6655         if(brokerMode)
6656         {
6657             sendEventToBroker(CONNECTED);
6658         }
6659         setStatStatus ( tr ( "running" ) );
6660         if (trayEnabled)
6661         {
6662             if (!useLdap)
6663                 trayIconActiveConnectionMenu->setTitle(sessionExplorer->getLastSession()->name());
6664             else
6665                 trayIconActiveConnectionMenu->setTitle(lastUser->username());
6666             trayIconActiveConnectionMenu->setEnabled(true);
6667             if (trayMinCon && !trayAutoHidden)
6668             {
6669                 trayAutoHidden=true;
6670                 hide();
6671             }
6672         }
6673         if ( embedMode )
6674             setEmbedSessionActionsEnabled ( true );
6675         disconnect ( sbSusp,SIGNAL ( clicked() ),this,
6676                      SLOT ( slotTestSessionStatus() ) );
6677         disconnect ( sbSusp,SIGNAL ( clicked() ),this,
6678                      SLOT ( slotSuspendSessFromSt() ) );
6679         connect ( sbSusp,SIGNAL ( clicked() ),this,
6680                   SLOT ( slotSuspendSessFromSt() ) );
6681         if ( !showExport )
6682         {
6683             showExport=true;
6684             /*connect ( sbExp,SIGNAL ( clicked() ),this,
6685               SLOT ( slot_exportDirectory() ) );*/
6686             sbExp->setEnabled ( true );
6687             exportDefaultDirs();
6688             if ( readExportsFrom!=QString::null )
6689             {
6690                 exportTimer->start ( 2000 );
6691             }
6692         }
6693         sbSusp->setToolTip ( tr ( "Suspend" ) );
6694 #ifdef Q_OS_DARWIN
6695         // Only start this once...
6696         if (!modMapTimer) {
6697             modMapTimer = new QTimer (this);
6698             connect (modMapTimer, SIGNAL (timeout ()), this, SLOT (slotSetModMap ()));
6699             modMapTimer->start (10000);
6700             slotSetModMap ();
6701         }
6702 #endif
6703         if ( newSession )
6704         {
6705             runCommand();
6706             newSession=false;
6707         }
6708 #ifdef 	Q_WS_HILDON
6709         else
6710         {
6711             if ( !xmodExecuted )
6712             {
6713                 xmodExecuted=true;
6714                 QTimer::singleShot (
6715                     2000, this,
6716                     SLOT ( slotExecXmodmap() ) );
6717             }
6718         }
6719 #endif
6720     }
6721     if ( stInfo->toPlainText().indexOf (
6722                 tr ( "Connection timeout, aborting" ) ) !=-1 )
6723         setStatStatus ( tr ( "aborting" ) );
6724 }
6725 
6726 
slotProxyStdout()6727 void ONMainWindow::slotProxyStdout()
6728 {
6729     QString resout ( nxproxy->readAllStandardOutput() );
6730 
6731     x2goDebug<<"Proxy wrote on stdout: "<<resout;
6732 }
6733 
setFocus()6734 void ONMainWindow::setFocus()
6735 {
6736 
6737 #ifdef Q_OS_DARWIN
6738     bool userFocus=false;
6739     bool passFocus=false;
6740     if(passForm && passForm->isVisible())
6741     {
6742         if(pass && pass->isVisible()&& pass->hasFocus())
6743         {
6744             passFocus=true;
6745         }
6746         if(login && login->isVisible()&& login->hasFocus())
6747         {
6748             userFocus=true;
6749         }
6750     }
6751 #endif
6752     QWidget::setFocus();
6753 #ifdef Q_OS_DARWIN
6754     if(userFocus)
6755     {
6756         login->setFocus();
6757     }
6758     if(passFocus)
6759     {
6760         pass->setFocus();
6761     }
6762 #endif
6763 
6764 }
6765 
6766 
slotShowPassForm()6767 void ONMainWindow::slotShowPassForm()
6768 {
6769 #ifdef Q_OS_DARWIN
6770 //fixes bug, when mainwindow inputs not accepting focus under mac
6771     x2goDebug<<"Setting focus."<<endl;
6772     QTimer::singleShot(500, this, SLOT(setFocus()));
6773     setFocus();
6774 #endif
6775     if ( !useLdap )
6776     {
6777         loginPrompt->show();
6778         login->show();
6779     }
6780     else
6781     {
6782         loginPrompt->hide();
6783         login->hide();
6784     }
6785     setEnabled ( true );
6786     if ( !embedMode )
6787     {
6788         u->hide();
6789         uname->hide();
6790     }
6791     sessionStatusDlg->hide();
6792     selectSessionDlg->hide();
6793     setEnabled ( true );
6794     if ( isPassShown )
6795     {
6796         passForm->show();
6797         passForm->setEnabled ( true );
6798     }
6799     isPassShown=true;
6800     login->setEnabled ( true );
6801     if ( login->text().length() >0 )
6802     {
6803         pass->setFocus();
6804         pass->selectAll();
6805     }
6806     else
6807     {
6808         login->setFocus();
6809         login->selectAll();
6810     }
6811 
6812 
6813     if ( !embedMode )
6814     {
6815         u->setEnabled ( true );
6816     }
6817     else
6818     {
6819         if ( config.user.length() >0 )
6820             login->setEnabled ( false );
6821     }
6822 }
6823 
6824 
showSessionStatus()6825 void ONMainWindow::showSessionStatus()
6826 {
6827     setStatStatus();
6828 }
6829 
6830 
slotShowAdvancedStat()6831 void ONMainWindow::slotShowAdvancedStat()
6832 {
6833     if ( !miniMode )
6834     {
6835         if ( sbAdv->isChecked() )
6836         {
6837             sessionStatusDlg->setFixedSize (
6838                 sessionStatusDlg->width(),
6839                 sessionStatusDlg->height() *2 );
6840         }
6841         else
6842         {
6843             sessionStatusDlg->setFixedSize (
6844                 sessionStatusDlg->sizeHint() );
6845             stInfo->hide();
6846         }
6847     }
6848     else
6849     {
6850         if ( sbAdv->isChecked() )
6851         {
6852             sessionStatusDlg->setFixedSize ( 310,300 );
6853         }
6854         else
6855         {
6856             stInfo->hide();
6857             sessionStatusDlg->setFixedSize ( 310,200 );
6858         }
6859     }
6860 
6861 
6862 // 	username->invalidate();
6863 
6864 
6865     if ( sbAdv->isChecked() )
6866     {
6867         stInfo->show();
6868     }
6869 
6870     X2goSettings st ( "settings" );
6871     st.setting()->setValue ( "showStatus",
6872                              ( QVariant ) sbAdv->isChecked() );
6873     st.setting()->sync();
6874 }
6875 
6876 
6877 
6878 
slotResumeDoubleClick(const QModelIndex &)6879 void ONMainWindow::slotResumeDoubleClick ( const QModelIndex& )
6880 {
6881     if ( !shadowSession )
6882         slotResumeSess();
6883 }
6884 
suspendBrokerSession(const QString & sessId,const QString & host)6885 void ONMainWindow::suspendBrokerSession(const QString& sessId, const QString& host)
6886 {
6887     suspendTerminateHostFromBroker=host;
6888     suspendTerminateSessionFromBroker=sessId;
6889     startSession(config.session, SUSPEND);
6890 }
6891 
termBrokerSession(const QString & sessId,const QString & host)6892 void ONMainWindow::termBrokerSession(const QString& sessId, const QString& host)
6893 {
6894     if(QMessageBox::warning (
6895         this,tr ( "Warning" ),
6896                                      tr (
6897                                          "Are you sure you want to terminate "
6898                                          "this session?\n"
6899                                          "Unsaved documents will be lost." ),
6900                              QMessageBox::Yes,QMessageBox::No )!= QMessageBox::Yes)
6901     {
6902         setEnabled(true);
6903         selectSessionDlg->setEnabled ( true );
6904         return;
6905     }
6906 
6907     suspendTerminateHostFromBroker=host;
6908     suspendTerminateSessionFromBroker=sessId;
6909     startSession(config.session, TERMINATE);
6910 }
6911 
6912 
suspendSession(QString sessId)6913 void ONMainWindow::suspendSession ( QString sessId )
6914 {
6915 
6916     sshConnection->executeCommand ( "x2gosuspend-session "+sessId, this,  SLOT ( slotRetSuspSess ( bool,  QString,
6917                                     int ) ) );
6918 }
6919 
6920 
termSession(QString sessId,bool warn)6921 bool ONMainWindow::termSession ( QString sessId, bool warn )
6922 {
6923     if ( warn )
6924     {
6925         bool hide_after=false;
6926         if (isHidden())
6927         {
6928             showNormal();
6929             hide_after=true;
6930         }
6931         int answer=QMessageBox::warning (
6932                        this,tr ( "Warning" ),
6933                        tr (
6934                            "Are you sure you want to terminate "
6935                            "this session?\n"
6936                            "Unsaved documents will be lost." ),
6937                        QMessageBox::Yes,QMessageBox::No );
6938         if (hide_after)
6939             hide();
6940 
6941         if ( answer !=
6942                 QMessageBox::Yes )
6943         {
6944             if ( selectSessionDlg->isVisible() )
6945                 selectSessionDlg->setEnabled ( true );
6946             return false;
6947         }
6948     }
6949     if ( shadowSession )
6950     {
6951         nxproxy->terminate();
6952         return true;
6953     }
6954     x2goDebug<<"Terminating session.";
6955     sshConnection->executeCommand ( "x2goterminate-session "+sessId, this, SLOT ( slotRetTermSess ( bool,
6956                                     QString,int) )  );
6957     proxyRunning=false;
6958     return true;
6959 }
6960 
6961 
6962 
setStatStatus(QString status)6963 void ONMainWindow::setStatStatus ( QString status )
6964 {
6965     setEnabled ( true );
6966     passForm->hide();
6967     selectSessionDlg->hide();
6968     if ( status == QString::null )
6969         status=statusString;
6970     else
6971         statusString=status;
6972     QString tstr;
6973     if ( statusLabel )
6974         statusLabel->setText ( QString::null );
6975     if ( resumingSession.sessionId!=QString::null )
6976     {
6977         QString f="dd.MM.yy HH:mm:ss";
6978         QDateTime dt=QDateTime::fromString ( resumingSession.crTime,f );
6979         dt=dt.addYears ( 100 );
6980         tstr=dt.toString();
6981     }
6982     if ( !embedMode || !proxyWinEmbedded )
6983     {
6984         statusBar()->showMessage ( "");
6985         statusBar()->hide();
6986         QString srv;
6987         if ( brokerMode )
6988         {
6989             srv=config.serverIp;
6990         }
6991         else if ( embedMode )
6992         {
6993             srv=config.server;
6994         }
6995         else
6996         {
6997             srv=resumingSession.server;
6998         }
6999         slVal->setText ( resumingSession.sessionId+"\n"+
7000                          srv+"\n"+
7001                          getCurrentUname() +"\n"+
7002                          resumingSession.display+
7003                          "\n"+tstr+"\n"+status );
7004 
7005         slVal->setFixedSize ( slVal->sizeHint() );
7006         sessionStatusDlg->show();
7007         if (resumingSession.published)
7008             sbApps->show();
7009         else
7010             sbApps->hide();
7011     }
7012     else
7013     {
7014 
7015         QString srv;
7016         if ( brokerMode )
7017         {
7018             srv=config.serverIp;
7019         }
7020         else
7021         {
7022             srv=config.server;
7023         }
7024         QString message=getCurrentUname() +"@"+
7025                         srv+
7026                         ", "+tr ( "Session" ) +": "+
7027                         resumingSession.sessionId+", "+
7028                         tr ( "Display" ) +": "+
7029                         resumingSession.display+", "+
7030                         tr ( "Creation time" ) +": "+tstr;
7031         if ( statusLabel )
7032         {
7033             statusLabel->setText ( "   "+message );
7034         }
7035         else
7036         {
7037             if ( config.showstatusbar )
7038             {
7039                 statusBar()->show();
7040                 statusBar()->showMessage ( message );
7041             }
7042         }
7043         sessionStatusDlg->hide();
7044     }
7045 }
7046 
7047 
slotRestartProxy()7048 void ONMainWindow::slotRestartProxy()
7049 {
7050     if ( !sessionStatusDlg->isVisible() )
7051         return;
7052     if ( stInfo->toPlainText().indexOf (
7053                 "Established X server connection" ) ==-1 )
7054     {
7055         stInfo->insertPlainText (
7056             tr (
7057                 "Connection timeout, aborting" ) );
7058         if ( nxproxy )
7059             nxproxy->terminate();
7060         proxyRunning=false;
7061         restartResume=true;
7062     }
7063 }
7064 
7065 
slotTestSessionStatus()7066 void ONMainWindow::slotTestSessionStatus()
7067 {
7068 
7069     if ( !sessionStatusDlg->isVisible() )
7070         return;
7071     if ( stInfo->toPlainText().indexOf (
7072                 "Established X server connection" ) ==-1 )
7073     {
7074         stInfo->insertPlainText (
7075             tr ( "Connection timeout, aborting" ) );
7076         if ( nxproxy )
7077             nxproxy->terminate();
7078         proxyRunning=false;
7079     }
7080 }
7081 
7082 
getNewSessionFromString(const QString & string)7083 x2goSession ONMainWindow::getNewSessionFromString ( const QString& string )
7084 {
7085     QStringList lst=string.split ( '|' );
7086     x2goSession s;
7087     s.display=lst[0];
7088     s.cookie=lst[1];
7089     s.agentPid=lst[2];
7090     s.sessionId=lst[3];
7091     s.grPort=lst[4];
7092     s.sndPort=lst[5];
7093     if ( lst.count() >6 )
7094         s.fsPort=lst[6];
7095     return s;
7096 }
7097 
7098 #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN)
pulseManagerWrapper()7099 void ONMainWindow::pulseManagerWrapper () {
7100 #ifdef Q_OS_WIN
7101   if (!embedMode || !config.confSnd ||
7102       (config.confSnd && config.useSnd))
7103 #endif /* defined (Q_OS_WIN) */
7104   {
7105     X2goSettings st ("settings");
7106     bool disablePulse = st.setting ()->value ("pulse/disable",
7107                                                      (QVariant) false).toBool ();
7108     if(disablePulse||systemDisablePA)
7109     {
7110         x2goDebug<<"Not starting PulseAudio";
7111         return;
7112     }
7113     pulseManagerThread = new QThread (0);
7114     pulseManager = new PulseManager ();
7115     connect(pulseManager, SIGNAL(sig_pulse_user_warning(bool, const QString&, const QString&, bool)),
7116             this, SLOT(slotShowPAMSGDialog(bool, const QString&, const QString&, bool)));
7117 
7118     bool disableInput = st.setting ()->value ("pulse/norecord",
7119                                                      (QVariant) false).toBool ();
7120     pulseManager->set_record (!disableInput);
7121     pulseManager->set_debug (debugging);
7122 
7123     pulseManager->moveToThread (pulseManagerThread);
7124 
7125     /*
7126      * Spawn PulseManager::start() once the thread started up successfully.
7127      * Another means of doing that would be via
7128      * QMetaObject::invokeMethod (pulseManager, "start", Qt::QueuedConnection);
7129      */
7130     connect (pulseManagerThread, SIGNAL (started ()), pulseManager, SLOT (start ()));
7131 
7132     pulseManagerThread->start ();
7133   }
7134 }
7135 #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */
7136 
slotAppDialog()7137 void ONMainWindow::slotAppDialog()
7138 {
7139     AppDialog dlg(this);
7140     dlg.exec();
7141 }
7142 
runCommand()7143 void ONMainWindow::runCommand()
7144 {
7145 
7146     if ( runRemoteCommand )
7147     {
7148         /* 1st override PATH and determine the base path to x2goruncommand.
7149          * Then in SlotRunCommand, call x2goruncommand without overriding PATH.
7150          * This ensures that the PATH is never overridden for the actual user
7151          * session.
7152          * Fixes: #1100
7153          */
7154         sshConnection->executeCommand ( "x2gobasepath", this,
7155                                         SLOT ( SlotRunCommand ( bool,
7156                                         QString,
7157                                         int )), true);
7158     }
7159 #ifdef Q_WS_HILDON
7160     //wait 5 seconds and execute xkbcomp
7161     QTimer::singleShot ( 5000, this, SLOT ( slotExecXmodmap() ) );
7162 #endif
7163 }
7164 
7165 
runApplication(QString exec)7166 void ONMainWindow::runApplication(QString exec)
7167 {
7168     QString cmd = "PULSE_CLIENTCONFIG=\"${HOME}/.x2go/C-"
7169                 + resumingSession.sessionId+"/.pulse-client.conf\" DISPLAY=:"
7170                 + resumingSession.display
7171                 + " setsid " + exec + " 1> /dev/null 2>/dev/null & exit";
7172 
7173     sshConnection->executeCommand (cmd, 0, 0, false);
7174 }
7175 
SlotRunCommand(bool,QString output,int)7176 void ONMainWindow::SlotRunCommand(bool, QString output, int)
7177 {
7178     QString passwd=getCurrentPass();
7179     QString user=getCurrentUname();
7180     QString host=resumingSession.server;
7181     QString command;
7182     QString sessionType="D";
7183     QString rdpOpts,rdpServer;
7184     bool rdpFS=false;
7185     QString rdpWidth;
7186     QString rdpHeight;
7187     bool rootless=false;
7188     resumingSession.published=false;
7189     if ( !embedMode )
7190     {
7191         X2goSettings* st;
7192         if (!brokerMode)
7193             st=new X2goSettings( "sessions" );
7194         else
7195             st=new X2goSettings(config.iniFile, QSettings::IniFormat);
7196 
7197 
7198         if ( useLdap )
7199             command=sessionCmd;
7200         else
7201         {
7202             if (!(sessionExplorer->getLastSession())) {
7203                 x2goDebug << "No session selected, not running command.";
7204                 return;
7205             }
7206 
7207             QString sid=sessionExplorer->getLastSession()->id();
7208             command=st->setting()->value (
7209                         sid+"/command",
7210                         ( QVariant ) tr ( "KDE" ) ).toString();
7211             rdpOpts=st->setting()->value (
7212                         sid+"/rdpoptions",
7213                         ( QVariant ) "" ).toString();
7214             if ( user != "" ) {
7215                 rdpOpts.replace("X2GO_USER", user);
7216             }
7217             if ( passwd != "" ) {
7218                 rdpOpts.replace("X2GO_PASSWORD", passwd);
7219             }
7220             rdpServer=st->setting()->value (
7221                           sid+"/rdpserver",
7222                           ( QVariant ) "" ).toString();
7223             rootless=st->setting()->value ( sid+"/rootless",
7224                                             ( QVariant ) false ).toBool();
7225             resumingSession.published=st->setting()->value ( sid+"/published",
7226                                       ( QVariant ) false ).toBool();
7227 
7228             rdpFS=st->setting()->value (
7229                       sid+"/fullscreen",
7230                       ( QVariant ) defaultFullscreen ).toBool();
7231             rdpHeight=st->setting()->value (
7232                           sid+"/height",
7233                           ( QVariant ) defaultHeight ).toString();
7234             rdpWidth=st->setting()->value (
7235                          sid+"/width",
7236                          ( QVariant ) defaultWidth ).toString();
7237 
7238         }
7239         delete st;
7240     }
7241     else
7242     {
7243         command=config.command;
7244         rootless=config.rootless;
7245         resumingSession.published=config.published;
7246     }
7247 
7248     resumingSession.command=command;
7249 
7250     if ( rootless )
7251         sessionType="R";
7252     if ( resumingSession.published )
7253     {
7254         sessionType="P";
7255         command="PUBLISHED";
7256     }
7257 
7258     if ( command=="KDE" )
7259     {
7260         command="startkde";
7261     }
7262     else if ( command=="GNOME" )
7263     {
7264         command="gnome-session";
7265     }
7266     else if ( command=="UNITY" )
7267     {
7268         command="unity";
7269     }
7270     else if ( command=="XFCE" )
7271     {
7272         command="xfce4-session";
7273     }
7274     else if ( command=="MATE" )
7275     {
7276         command="mate-session";
7277     }
7278     else if ( command=="LXDE" )
7279     {
7280         command="startlxde";
7281     }
7282     else if (command == "LXQt")
7283     {
7284         command = "startlxqt";
7285     }
7286     // Note that there are multiple possible Cinnamon commands that the server
7287     // may call.
7288     else if ( command=="CINNAMON" )
7289     {
7290         command="cinnamon-session";
7291     }
7292     else if ( command=="TRINITY" )
7293     {
7294         command="starttrinity";
7295     }
7296     else if ( command=="OPENBOX" )
7297     {
7298         command="openbox-session";
7299     }
7300     else if ( command=="ICEWM" )
7301     {
7302         command="icewm-session";
7303     }
7304     else if ( command=="RDP" )
7305     {
7306         command="rdesktop ";
7307         if ( rdpFS )
7308         {
7309             command+=" -f ";
7310             sessionType="D";
7311             rootless=false;
7312         } else {
7313             command+=" -g "+rdpWidth+"x"+rdpHeight;
7314             rootless=true;
7315         }
7316         command+=" "+rdpOpts+ " "+rdpServer;
7317 
7318     }
7319 
7320     if ( managedMode )
7321         return;
7322 
7323 
7324     QString cmd;
7325 
7326     command.replace ( " ","X2GO_SPACE_CHAR" );
7327     QString krbFwString;
7328 
7329     if(sshConnection->useKerberos() && sshConnection->get_kerberosDelegation())
7330     {
7331         krbFwString="KRB5CCNAME=`echo $KRB5CCNAME |sed 's/FILE://g'` \
7332         KRBFL=$HOME/.x2go/C-"+resumingSession.sessionId+"/krb5cc ;\
7333         cp -a $KRB5CCNAME $KRBFL;KRB5CCNAME=$KRBFL ";
7334     }
7335 
7336     if ( !startSessSound  || startSessSndSystem==PULSE )
7337     {
7338         cmd=krbFwString+"setsid " + output + "/bin/x2goruncommand "+
7339             resumingSession.display+" "+
7340             resumingSession.agentPid + " " +
7341             resumingSession.sessionId+" "+
7342             resumingSession.sndPort+ " "+ command+" nosnd "+
7343             sessionType +" 1> /dev/null 2>/dev/null & exit";
7344         if ( startSessSndSystem ==PULSE )
7345         {
7346             cmd="export PULSE_CLIENTCONFIG=\"${HOME}/.x2go/C-"+
7347                 resumingSession.sessionId+
7348                 "/.pulse-client.conf\";"+cmd;
7349         }
7350     }
7351     else
7352     {
7353         switch ( startSessSndSystem )
7354         {
7355         case ESD:
7356             cmd=krbFwString+"setsid " + output + "/bin/x2goruncommand "+
7357                 resumingSession.display+" "+
7358                 resumingSession.agentPid + " " +
7359                 resumingSession.sessionId+" "+
7360                 resumingSession.sndPort+ " "+
7361                 command+" esd "+
7362                 sessionType +" 1> /dev/null 2>/dev/null & exit";
7363             break;
7364         case ARTS:
7365             cmd=krbFwString+"setsid " + output + "/bin/x2goruncommand "+
7366                 resumingSession.display+" "+
7367                 resumingSession.agentPid + " " +
7368                 resumingSession.sessionId+" "+
7369                 resumingSession.sndPort+ " "+
7370                 command+" arts "+
7371                 sessionType +" 1> /dev/null 2>/dev/null & exit";
7372             break;
7373 
7374         }
7375     }
7376 
7377     sshConnection->executeCommand ( cmd, this,
7378                                     SLOT ( slotRetRunCommand ( bool,
7379                                     QString,
7380                                     int )), false);
7381 }
7382 
slotRetRunCommand(bool result,QString output,int)7383 void ONMainWindow::slotRetRunCommand ( bool result, QString output,
7384                                        int )
7385 {
7386     if ( result==false )
7387     {
7388         QString message=tr ( "<b>Connection failed.</b>\n:\n" ) +output;
7389         if ( message.indexOf ( "publickey,password" ) !=-1 )
7390         {
7391             message=tr ( "<b>Wrong password!</b><br><br>" ) +
7392                     message;
7393         }
7394         QMessageBox::critical ( 0l,tr ( "Error" ),message,
7395                                 QMessageBox::Ok,
7396                                 QMessageBox::NoButton );
7397     }
7398     else
7399     {
7400         if (resumingSession.published)
7401             readApplications();
7402     }
7403 }
7404 
readApplications()7405 void ONMainWindow::readApplications()
7406 {
7407     sshConnection->executeCommand ( "x2gogetapps", this,  SLOT ( slotReadApplications ( bool,
7408                                     QString,
7409                                     int) ));
7410     sbApps->setEnabled(false);
7411 }
7412 
slotReadApplications(bool result,QString output,int)7413 void ONMainWindow::slotReadApplications(bool result, QString output,
7414                                         int)
7415 {
7416     if ( result==false )
7417     {
7418         QString message=tr ( "<b>Connection failed.</b>\n:\n" ) +output;
7419         if ( message.indexOf ( "publickey,password" ) !=-1 )
7420         {
7421             message=tr ( "<b>Wrong password!</b><br><br>" ) +
7422                     message;
7423         }
7424         QMessageBox::critical ( 0l,tr ( "Error" ),message,
7425                                 QMessageBox::Ok,
7426                                 QMessageBox::NoButton );
7427         return;
7428     }
7429     sbApps->setEnabled(true);
7430     applications.clear();
7431     QString locallong=QLocale::system().name();
7432     QString localshort=QLocale::system().name().split("_")[0];
7433     QStringList startAppsFound;
7434 
7435     foreach(QString appstr, output.split("</desktop>",QString::SkipEmptyParts))
7436     {
7437         bool localcomment=false;
7438         bool localname=false;
7439         Application app;
7440         app.category=Application::OTHER;
7441         QStringList lines=appstr.split("\n", QString::SkipEmptyParts);
7442         for (int i=0; i<lines.count(); ++i)
7443         {
7444             QString line=lines[i];
7445             if (line.indexOf("Name["+localshort+"]=")!=-1  || line.indexOf("Name["+locallong+"]=")!=-1)
7446             {
7447                 app.name=QString::fromUtf8(line.split("=")[1].toLatin1());
7448 
7449                 //                 x2goDebug<<"local name: "<<app.name<<endl;
7450 
7451                 localname=true;
7452             }
7453             if (line.indexOf("Comment["+localshort+"]=")!=-1 || line.indexOf("Comment["+locallong+"]=")!=-1)
7454             {
7455                 app.comment=QString::fromUtf8(line.split("=")[1].toLatin1());
7456                 //                 x2goDebug<<"local comment: "<<app.comment<<endl;
7457                 localcomment=true;
7458             }
7459             if (line.indexOf("Name=")!=-1 && !localname)
7460             {
7461                 app.name=line.split("=")[1];
7462                 for (int i=0; i<autostartApps.length(); ++i)
7463                 {
7464                     if (app.name==autostartApps[i])
7465                         startAppsFound.append(app.name);
7466                     //                 x2goDebug<<"name: "<<app.name<<endl;
7467                 }
7468             }
7469             if (line.indexOf("Comment=")!=-1 && !localcomment)
7470             {
7471                 app.comment=line.split("=")[1];
7472                 //                 x2goDebug<<"comment: "<<app.comment<<endl;
7473             }
7474             if (line.indexOf("Exec=")!=-1)
7475             {
7476                 app.exec=line.split("=")[1];
7477                 app.exec.replace(" %f","",Qt::CaseInsensitive);
7478                 app.exec.replace(" %u","",Qt::CaseInsensitive);
7479                 app.exec.replace("%f","",Qt::CaseInsensitive);
7480                 app.exec.replace("%u","",Qt::CaseInsensitive);
7481                 app.exec.replace("%i","",Qt::CaseInsensitive);
7482                 app.exec.replace("%c",app.name,Qt::CaseInsensitive);
7483                 for (int i=0; i<autostartApps.length(); ++i)
7484                 {
7485                     if (app.exec==autostartApps[i])
7486                         startAppsFound.append(app.exec);
7487                     //                 x2goDebug<<"exec: "<<app.exec<<endl;
7488                 }
7489             }
7490             if (line.indexOf("Categories=")!=-1)
7491             {
7492                 if (line.indexOf("Audio")!=-1)
7493                     app.category=Application::MULTIMEDIA;
7494                 if (line.indexOf("Vide")!=-1)
7495                     app.category=Application::MULTIMEDIA;
7496                 if (line.indexOf("Development")!=-1)
7497                     app.category=Application::DEVELOPMENT;
7498                 if (line.indexOf("Education")!=-1)
7499                     app.category=Application::EDUCATION;
7500                 if (line.indexOf("Game")!=-1)
7501                     app.category=Application::GAME;
7502                 if (line.indexOf("Graphics")!=-1)
7503                     app.category=Application::GRAPHICS;
7504                 if (line.indexOf("Network")!=-1)
7505                     app.category=Application::NETWORK;
7506                 if (line.indexOf("Office")!=-1)
7507                     app.category=Application::OFFICE;
7508                 if (line.indexOf("Settings")!=-1)
7509                     app.category=Application::SETTINGS;
7510                 if (line.indexOf("System")!=-1)
7511                     app.category=Application::SYSTEM;
7512                 if (line.indexOf("Utility")!=-1)
7513                     app.category=Application::UTILITY;
7514                 if (line.indexOf("X2Go-Top",0,Qt::CaseInsensitive)!=-1)
7515                     app.category=Application::TOP;
7516             }
7517             if (line.indexOf("<icon>")!=-1)
7518             {
7519                 bool isSvg=false;
7520                 line=lines[++i];
7521                 QByteArray pic;
7522                 while (line.indexOf("</icon>")==-1)
7523                 {
7524                     pic+=QByteArray::fromBase64(line.toLatin1());
7525                     line=lines[++i];
7526                     if (QString(QByteArray::fromBase64(line.toLatin1())).indexOf("</svg>",Qt::CaseInsensitive)!=-1)
7527                     {
7528                         isSvg=true;
7529                     }
7530                 }
7531                 if (!isSvg)
7532                     app.icon.loadFromData(pic);
7533                 else
7534                 {
7535                     QPixmap pix(32,32);
7536                     QSvgRenderer svgRenderer( pic );
7537                     QPainter pixPainter(&pix);
7538                     svgRenderer.render(&pixPainter);
7539                     app.icon=pix;
7540                 }
7541             }
7542         }
7543         if (app.name.length()>0)
7544         {
7545             if (app.comment.length()<=0)
7546                 app.comment=app.name;
7547             applications.append(app);
7548         }
7549     }
7550 
7551     qSort(applications.begin(), applications.end(),Application::lessThen);
7552     plugAppsInTray();
7553     if (runStartApp && autostartApps.length()>0)
7554     {
7555         for (int i=0; i<autostartApps.length(); ++i)
7556         {
7557             bool startAppFound = false;
7558             for (int j=0; j<startAppsFound.length(); ++j)
7559             {
7560                 if (startAppsFound[j] == autostartApps[i])
7561                 {
7562                     startAppFound = true;
7563                 }
7564             }
7565             if (!startAppFound) {
7566                 x2goDebug<<"Autostart application "<<autostartApps[i]<< " not found in desktop files.";
7567             }
7568             else
7569             {
7570                 runApplication(autostartApps[i]);
7571             }
7572         }
7573     }
7574     else
7575     {
7576         if(embedMode)
7577         {
7578             act_showApps->setVisible(true);
7579             slotAppDialog();
7580         }
7581     }
7582 }
7583 
7584 
parseParameter(QString param)7585 bool ONMainWindow::parseParameter ( QString param )
7586 {
7587 #if defined (Q_OS_UNIX)
7588     if ("--bypass-cleanup-helper" == param) {
7589         return (true);
7590     }
7591 #endif /* defined (Q_OS_UNIX) */
7592 
7593     if ( param=="--help" )
7594     {
7595         showHelp();
7596         return false;
7597     }
7598 
7599     if ( param=="--help-pack" )
7600     {
7601         showHelpPack();
7602         return false;
7603     }
7604 
7605     if ( param=="--version" || param=="-v")
7606     {
7607         showVersion();
7608         return false;
7609     }
7610 
7611     if ( param=="--changelog" )
7612     {
7613         showChangelog();
7614         return false;
7615     }
7616 
7617     if ( param=="--git-info" )
7618     {
7619         showGit();
7620         return false;
7621     }
7622 
7623     if (param == "--debug")
7624     {
7625         ONMainWindow::debugging = true;
7626         return true;
7627     }
7628 
7629     if ("--libssh-debug" == param) {
7630         ONMainWindow::libssh_debugging = true;
7631         return true;
7632     }
7633 
7634     if ("--libssh-packetlog" == param) {
7635         ONMainWindow::libssh_packetlog = true;
7636         return true;
7637     }
7638 
7639 #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN)
7640     if (param == "--disable-pulse")
7641     {
7642         systemDisablePA=true;
7643         return true;
7644     }
7645     if (param == "--disable-pulse-record")
7646     {
7647         systemDisablePARecord=true;
7648         return true;
7649     }
7650 #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */
7651 
7652     if (param == "--no-autoresume")
7653     {
7654         autoresume=false;
7655         return true;
7656     }
7657 
7658     if ( param == "--portable" )
7659     {
7660         ONMainWindow::portable=true;
7661         return true;
7662     }
7663     if ( param == "--clean-all-files" )
7664     {
7665         cleanAllFiles=true;
7666         return true;
7667     }
7668     if (param == "--connectivity-test")
7669     {
7670         connTest=true;
7671         return true;
7672     }
7673 
7674     if ( param=="--no-menu" )
7675     {
7676         drawMenu=false;
7677         return true;
7678     }
7679 
7680     if ( param=="--maximize" )
7681     {
7682         startMaximized=true;
7683         return true;
7684     }
7685     if ( param=="--xinerama" )
7686     {
7687         defaultXinerama=true;
7688         return true;
7689     }
7690     if (param == "--thinclient")
7691     {
7692         thinMode=true;
7693         startMaximized=true;
7694         return true;
7695     }
7696     if (param == "--haltbt")
7697     {
7698         showHaltBtn=true;
7699         return true;
7700     }
7701     if (param == "--broker-logoutbt")
7702     {
7703         showBrokerLogoutBtn=true;
7704         return true;
7705     }
7706     if ( param=="--hide" )
7707     {
7708         startHidden=true;
7709         return true;
7710     }
7711     if ( param=="--keep-trayicon" )
7712     {
7713         keepTrayIcon=true;
7714         return true;
7715     }
7716     if ( param=="--hide-foldersharing" )
7717     {
7718         hideFolderSharing=true;
7719         return true;
7720     }
7721     if ( param=="--pgp-card" )
7722     {
7723         usePGPCard=true;
7724         return true;
7725     }
7726     if ( param=="--ldap-printing" )
7727     {
7728         LDAPPrintSupport=true;
7729         return true;
7730     }
7731     if ( param=="--add-to-known-hosts" )
7732     {
7733         acceptRsa=true;
7734         return true;
7735     }
7736     if ( param=="--no-session-edit" )
7737     {
7738         noSessionEdit=true;
7739         return true;
7740     }
7741     if ( param=="--change-broker-pass")
7742     {
7743         changeBrokerPass=true;
7744         return true;
7745     }
7746     if ( param == "--autologin")
7747     {
7748         cmdAutologin=true;
7749         return true;
7750     }
7751 
7752     if ( param == "--broker-autologin")
7753     {
7754         config.brokerAutologin=true;
7755         return true;
7756     }
7757     if ( param == "--broker-krblogin")
7758     {
7759         config.brokerKrbLogin=true;
7760         return true;
7761     }
7762 
7763     if ( param == "--broker-autologoff")
7764     {
7765         config.brokerAutologoff=true;
7766         return true;
7767     }
7768 
7769     if ( param == "--broker-noauth")
7770     {
7771         config.brokerNoAuth=true;
7772         return true;
7773     }
7774 
7775     if ( param=="--broker-noauth-with-session-username" )
7776     {
7777         brokerNoauthWithSessionUsername=true;
7778         return true;
7779     }
7780 
7781     if ( param=="--broker-use-creds-for-session" )
7782     {
7783         brokerCredsForSession=true;
7784         return true;
7785     }
7786 
7787     //force to show trayicon
7788     if (param == "--tray-icon")
7789     {
7790         forceToShowTrayicon = true;
7791         return true;
7792     }
7793 
7794     if ( param=="--close-disconnect" )
7795     {
7796         closeDisconnect=true;
7797         return true;
7798     }
7799 
7800     QString setting,value;
7801     QStringList vals=param.split ( "=" );
7802     if ( vals.size() <2 )
7803     {
7804         printError ( param );
7805         return false;
7806     }
7807     setting=vals[0];
7808     vals.removeFirst();
7809     value=vals.join ( "=" );
7810     if ( setting=="--link" )
7811     {
7812         return linkParameter ( value );
7813     }
7814     if ( setting=="--clipboard" )
7815     {
7816         return clipboardParameter ( value );
7817     }
7818     if ( setting=="--sound" )
7819     {
7820         return soundParameter ( value );
7821     }
7822     if ( setting=="--geometry" )
7823     {
7824         return geometry_par ( value );
7825     }
7826     if ( setting=="--pack" )
7827     {
7828         return packParameter ( value );
7829     }
7830     if ( setting=="--kbd-layout" )
7831     {
7832         defaultLayout=value.split(",",QString::SkipEmptyParts);
7833         if (defaultLayout.size()==0)
7834             defaultLayout<<tr("us");
7835         return true;
7836     }
7837     if ( setting=="--session" )
7838     {
7839         defaultSession=true;
7840         defaultSessionName=value;
7841         return true;
7842     }
7843     if ( setting=="--session-conf" )
7844     {
7845         ONMainWindow::sessionCfg=expandHome(value);
7846         return true;
7847     }
7848     if ( setting=="--sessionid" )
7849     {
7850         defaultSession=true;
7851         defaultSessionId=value;
7852         return true;
7853     }
7854     if ( setting=="--user" )
7855     {
7856         defaultUser=true;
7857         defaultUserName=value;
7858         return true;
7859     }
7860     if ( setting=="--kbd-type" )
7861     {
7862         defaultKbdType=value;
7863         return true;
7864     }
7865     if ( setting=="--set-kbd" )
7866     {
7867         return setKbd_par ( value );
7868     }
7869     if ( setting=="--ldap" )
7870     {
7871         return ldapParameter ( value );
7872     }
7873     if ( setting=="--ldap1" )
7874     {
7875         return ldap1Parameter ( value );
7876     }
7877     if ( setting=="--ldap2" )
7878     {
7879         return ldap2Parameter ( value );
7880     }
7881     if ( setting=="--command" )
7882     {
7883         defaultCmd=value;
7884         return true;
7885     }
7886     if ( setting=="--read-exports-from" )
7887     {
7888         readExportsFrom=expandHome(value);
7889         return true;
7890     }
7891     if ( setting=="--external-login" )
7892     {
7893         extLogin=true;
7894         readLoginsFrom=expandHome(value);
7895         return true;
7896     }
7897     if ( setting=="--ssh-port" )
7898     {
7899         defaultSshPort=value;
7900         return true;
7901     }
7902     if ( setting=="--dpi" )
7903     {
7904         defaultSetDPI=true;
7905         defaultDPI=value.toUInt();
7906         return true;
7907     }
7908     if ( setting=="--client-ssh-port" )
7909     {
7910         clientSshPort=value;
7911         return true;
7912     }
7913     if ( setting == "--embed-into" )
7914     {
7915         embedMode=true;
7916         embedParent=value.toLong();
7917         return true;
7918     }
7919     if ( setting == "--broker-url")
7920     {
7921         brokerMode=true;
7922         noSessionEdit=true;
7923         config.brokerurl=value;
7924         return true;
7925     }
7926     if ( setting == "--broker-cacertfile")
7927     {
7928         config.brokerCaCertFile=expandHome(value);
7929         return true;
7930     }
7931     if ( setting == "--broker-ssh-key")
7932     {
7933         config.brokerSshKey=expandHome(value);
7934         return true;
7935     }
7936     if ( setting == "--ssh-key")
7937     {
7938         sshKey key;
7939         QStringList parts=value.split(":");
7940         QString authPart;
7941         switch(parts.length())
7942         {
7943         case 1:
7944             key.key=expandHome(parts[0]);
7945             break;
7946         case 2:
7947             key.key=expandHome(parts[1]);
7948             authPart=parts[0];
7949             break;
7950         case 3:
7951             authPart=parts[0];
7952             key.key=expandHome(parts[2]);
7953             key.port=parts[1];
7954             break;
7955         }
7956         if(authPart.length()>0)
7957         {
7958             if(authPart.indexOf("@")!=-1)
7959             {
7960                 key.user=authPart.split("@")[0];
7961                 key.server=authPart.split("@")[1];
7962             }
7963             else
7964                 key.server=authPart;
7965         }
7966         cmdSshKeys<<key;
7967         return true;
7968     }
7969     if ( setting == "--broker-name")
7970     {
7971         config.brokerName=value;
7972         return true;
7973     }
7974     if ( setting == "--autostart")
7975     {
7976         autostartApps.append(value.split(','));
7977 
7978         /* Fix up by trimming whitespace. */
7979         for (QStringList::iterator it = autostartApps.begin (); it != autostartApps.end (); ++it) {
7980             *it = it->trimmed ();
7981         }
7982 
7983         return true;
7984     }
7985     if ( setting == "--auth-id")
7986     {
7987         QFile file(expandHome(value));
7988         if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
7989         {
7990             printError ( param + tr(" (can't open file)"));
7991             return false;
7992         }
7993         QTextStream in(&file);
7994         config.brokerUserId = in.readLine();
7995         return true;
7996     }
7997     if (setting == "--support-menu")
7998     {
7999         value = expandHome(value);
8000         if (! QFile::exists(value))
8001         {
8002             printError( param + tr(" (file does not exist)"));
8003             return false;
8004         }
8005         supportMenuFile=value;
8006         return true;
8007     }
8008     if (setting == "--background")
8009     {
8010         value = expandHome(value);
8011         if (! QFile::exists(value))
8012         {
8013             printError( param + tr(" (file does not exist)"));
8014             return false;
8015         }
8016         BGFile=value;
8017         return true;
8018     }
8019     if (setting == "--session-icon")
8020     {
8021         value=expandHome(value);
8022         if (! QFile::exists(value))
8023         {
8024             printError( param + tr(" (file does not exist)"));
8025             return false;
8026         }
8027         SPixFile=value;
8028         return true;
8029     }
8030     if (setting == "--home")
8031     {
8032         QDir dr;
8033 
8034         value = expandHome(value);
8035 
8036 #ifdef Q_OS_WIN
8037         int find=value.indexOf("(");
8038         int lind=value.indexOf(")");
8039         if (find!=-1 && lind !=-1)
8040         {
8041             QString label=value.mid(find+1,lind-find-1);
8042             x2goDebug<<"Searching for drive with label: "<<label;
8043 
8044             QString drive=wapiGetDriveByLabel(label);
8045             value.replace("("+label+")",drive);
8046             x2goDebug<<"New path: "<<value;
8047         }
8048 #endif
8049         if (! dr.exists(value))
8050         {
8051             printError( param + tr(" (directory does not exist)"));
8052             return false;
8053         }
8054         homeDir=value;
8055         portableDataPath=value;
8056         return true;
8057     }
8058     if (setting == "--branding")
8059     {
8060         value = expandHome(value);
8061         if (! QFile::exists(value))
8062         {
8063             printError( param + tr(" (file does not exist)"));
8064             return false;
8065         }
8066         OnFile=value;
8067         return true;
8068     }
8069 #if defined(Q_OS_WIN)
8070     if ("--xserver-start-limit" == setting) {
8071         bool conv_ret = false;
8072         signed long long conv = value.toLongLong (&conv_ret);
8073 
8074         if (conv_ret) {
8075             if (0 >= conv) {
8076                 x2goDebug << "Not limiting X.Org Server starts.";
8077 
8078                 x_start_limit_ = 0;
8079             }
8080             else {
8081                 if (SIZE_MAX < conv) {
8082                     conv = SIZE_MAX;
8083 
8084                     x2goDebug << "Clamped X.Org Server start limit to SIZE_MAX.";
8085                 }
8086 
8087                 x_start_limit_ = conv;
8088 
8089                 x2goDebug << "Limiting X.Org Server starts to " << x_start_limit_ << " tries.";
8090             }
8091         }
8092         else {
8093             x2goDebug << "Conversion for --xserver-start-limit value " << value << " failed; assuming default of 3.";
8094 
8095             x_start_limit_ = 3;
8096         }
8097 
8098         return (true);
8099     }
8100 #endif /* defined(Q_OS_WIN) */
8101 
8102     printError ( param );
8103     return false;
8104 }
8105 
8106 
linkParameter(QString value)8107 bool ONMainWindow::linkParameter ( QString value )
8108 {
8109     if ( value=="modem" )
8110         defaultLink=MODEM;
8111     else if ( value=="isdn" )
8112         defaultLink=ISDN;
8113     else if ( value=="adsl" )
8114         defaultLink=ADSL;
8115     else if ( value=="wan" )
8116         defaultLink=WAN;
8117     else if ( value=="lan" )
8118         defaultLink=LAN;
8119     else
8120     {
8121         printError( tr (
8122                         "Invalid value for parameter \"--link\"."
8123                     ).toLocal8Bit().data() );
8124         return false;
8125     }
8126     return true;
8127 }
8128 
clipboardParameter(QString value)8129 bool ONMainWindow::clipboardParameter ( QString value )
8130 {
8131     if ( value=="both"  || value=="client" || value=="server"||value == "none")
8132     {
8133         defaultClipboardMode=value;
8134         return true;
8135     }
8136     else
8137     {
8138         printError( tr (
8139                         "Invalid value for parameter \"--clipboard\"."
8140                     ).toLocal8Bit().data() );
8141         return false;
8142     }
8143 
8144 }
8145 
soundParameter(QString val)8146 bool ONMainWindow::soundParameter ( QString val )
8147 {
8148     if ( val=="1" )
8149         defaultUseSound=true;
8150     else if ( val=="0" )
8151         defaultUseSound=false;
8152     else
8153     {
8154         printError( tr ( "Invalid value for "
8155                          "parameter \"--sound\"." ).toLocal8Bit().data() );
8156         return false;
8157     }
8158     return true;
8159 }
8160 
geometry_par(QString val)8161 bool ONMainWindow::geometry_par ( QString val )
8162 {
8163     if ( val=="fullscreen" )
8164         defaultFullscreen=true;
8165     else
8166     {
8167         QStringList res=val.split ( "x" );
8168         if ( res.size() !=2 )
8169         {
8170             printError( tr (
8171                             "Invalid value for parameter \"--geometry\"." ).
8172                         toLocal8Bit().data() );
8173             return false;
8174         }
8175         bool o1,o2;
8176         defaultWidth=res[0].toInt ( &o1 );
8177         defaultHeight=res[1].toInt ( &o2 );
8178         if ( ! ( defaultWidth >0 && defaultHeight >0 && o1 && o2 ) )
8179         {
8180             printError( tr (
8181                             "Invalid value for parameter \"--geometry\"." ).
8182                         toLocal8Bit().data() );
8183             return false;
8184         }
8185     }
8186     return true;
8187 }
8188 
setKbd_par(QString val)8189 bool ONMainWindow::setKbd_par ( QString val )
8190 {
8191     if ( val=="1" )
8192         defaultSetKbd=true;
8193     else if ( val=="0" )
8194         defaultSetKbd=false;
8195     else
8196     {
8197         printError( tr (
8198                         "Invalid value for parameter \"--set-kbd\"." ).
8199                     toLocal8Bit().data() );
8200         return false;
8201     }
8202     return true;
8203 }
8204 
ldapParameter(QString val)8205 bool ONMainWindow::ldapParameter ( QString val )
8206 {
8207     QString ldapstring=val;
8208     useLdap=true;
8209     ldapstring.replace ( "\"","" );
8210     QStringList lst=ldapstring.split ( ':',QString::SkipEmptyParts );
8211     if ( lst.size() !=3 )
8212     {
8213         printError( tr (
8214                         "Invalid value for parameter \"--ldap\"." ).
8215                     toLocal8Bit().data() );
8216         return false;
8217     }
8218     ldapOnly=true;
8219     ldapServer=lst[0];
8220     ldapPort=lst[1].toInt();
8221     ldapDn=lst[2];
8222 
8223 
8224     return true;
8225 }
8226 
ldap1Parameter(QString val)8227 bool ONMainWindow::ldap1Parameter ( QString val )
8228 {
8229     QString ldapstring=val;
8230     ldapstring.replace ( "\"","" );
8231     QStringList lst=ldapstring.split ( ':',QString::SkipEmptyParts );
8232     if ( lst.size() !=2 )
8233     {
8234         printError( tr (
8235                         "Invalid value for parameter \"--ldap1\"." ).
8236                     toLocal8Bit().data() );
8237         return false;
8238     }
8239     ldapServer1=lst[0];
8240     ldapPort1=lst[1].toInt();
8241 
8242     return true;
8243 }
8244 
ldap2Parameter(QString val)8245 bool ONMainWindow::ldap2Parameter ( QString val )
8246 {
8247     QString ldapstring=val;
8248     ldapstring.replace ( "\"","" );
8249     QStringList lst=ldapstring.split ( ':',QString::SkipEmptyParts );
8250     if ( lst.size() !=2 )
8251     {
8252         printError(
8253             tr (
8254                 "Invalid value for parameter \"--ldap2\"." ).
8255             toLocal8Bit().data() );
8256         return false;
8257     }
8258     ldapServer2=lst[0];
8259     ldapPort2=lst[1].toInt();
8260 
8261     return true;
8262 }
8263 
8264 
packParameter(QString val)8265 bool ONMainWindow::packParameter ( QString val )
8266 {
8267 
8268     QFile file ( ":/txt/packs" );
8269     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
8270         return true;
8271     QTextStream in ( &file );
8272     while ( !in.atEnd() )
8273     {
8274         QString pc=in.readLine();
8275         if ( pc.indexOf ( "-%" ) !=-1 )
8276         {
8277             pc=pc.left ( pc.indexOf ( "-%" ) );
8278 
8279             QStringList pctails=val.split ( "-" );
8280             QString pcq=pctails[pctails.size()-1];
8281             pctails.removeLast();
8282 
8283             if ( pctails.join ( "-" ) ==pc )
8284             {
8285                 bool ok;
8286                 int v=pcq.toInt ( &ok );
8287                 if ( ok && v>=0 && v<=9 )
8288                 {
8289                     defaultPack=pc;
8290                     defaultQuality=v;
8291                     return true;
8292                 }
8293                 else
8294                     break;
8295             }
8296         }
8297         else
8298         {
8299             if ( pc==val )
8300             {
8301                 defaultPack=val;
8302                 return true;
8303             }
8304         }
8305     }
8306     file.close();
8307     printError ( tr("Invalid value for parameter \"--pack\"." ));
8308     return false;
8309 }
8310 
8311 
printError(QString param)8312 void ONMainWindow::printError ( QString param )
8313 {
8314     if( !startHidden )
8315     {
8316         qCritical ( "%s", ( tr ( "Wrong parameter: " ) +param ).
8317                     toLocal8Bit().data() );
8318         if (!startHidden && !haveTerminal)
8319         {
8320             QMessageBox::critical(0,tr("Error"), tr ( "Wrong parameter: " ) +param);
8321         }
8322     }
8323     else
8324     {
8325         x2goErrorf(8)<<tr("Wrong parameter: ")<<param;
8326     }
8327 }
8328 
showHelp()8329 void ONMainWindow::showHelp ()
8330 {
8331     QString out = help::pretty_print ();
8332     if (!startHidden && !haveTerminal) {
8333         HelpDialog dlg (this);
8334         dlg.setWindowTitle (tr ("Help"));
8335         dlg.setText (help::pretty_print (false));
8336         dlg.exec ();
8337     }
8338 }
8339 
showHelpPack()8340 void ONMainWindow::showHelpPack()
8341 {
8342     qCritical ( "%s",tr (
8343                     "Available pack methods:" ).toLocal8Bit().data() );
8344     QFile file ( ":/txt/packs" );
8345     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
8346         return;
8347     QTextStream in ( &file );
8348     QString msg;
8349     while ( !in.atEnd() )
8350     {
8351         QString pc=in.readLine();
8352         if ( pc.indexOf ( "-%" ) !=-1 )
8353         {
8354             pc=pc.left ( pc.indexOf ( "-%" ) );
8355             pc+="-[0-9]";
8356         }
8357         msg+=pc+"\n";
8358     }
8359     file.close();
8360     qCritical().nospace () << qPrintable (msg);
8361     if (!startHidden && !haveTerminal)
8362     {
8363         HelpDialog dlg(this);
8364         dlg.setWindowTitle(tr("Pack Methods"));
8365         dlg.setText(msg);
8366         dlg.exec();
8367     }
8368 }
8369 
showTextFile(QString fname,QString title)8370 void ONMainWindow::showTextFile(QString fname, QString title)
8371 {
8372     QFile file ( fname );
8373     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
8374         return;
8375     QTextStream in ( &file );
8376     QString msg=in.readAll();
8377     file.close();
8378     qCritical().nospace () << qPrintable (msg);
8379     if (!startHidden && !haveTerminal)
8380     {
8381         HelpDialog dlg(this);
8382         dlg.setWindowTitle(title);
8383         dlg.setText(msg);
8384         dlg.exec();
8385     }
8386 
8387 }
8388 
8389 
showChangelog()8390 void ONMainWindow::showChangelog()
8391 {
8392     if(!QFile::exists(":/txt/changelog"))
8393     {
8394         qCritical()<<tr("Option is not available in this build.");
8395         return;
8396     }
8397     showTextFile(":/txt/changelog", tr("Changelog"));
8398 }
8399 
showGit()8400 void ONMainWindow::showGit()
8401 {
8402     if(!QFile::exists(":/txt/git-info"))
8403     {
8404         qCritical()<<tr("Option is not available in this build.");
8405         return;
8406     }
8407     showTextFile(":/txt/git-info", tr("Git Info"));
8408 }
8409 
showVersion()8410 void ONMainWindow::showVersion()
8411 {
8412     qCritical().nospace () << VERSION;
8413 
8414     if (!startHidden && !haveTerminal)
8415     {
8416         slotAbout();
8417     }
8418 }
8419 
8420 
slotGetServers(bool result,QString output,int)8421 void ONMainWindow::slotGetServers ( bool result, QString output,
8422                                     int )
8423 {
8424     if ( result==false )
8425     {
8426         cardReady=false;
8427         cardStarted=false;
8428 
8429         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
8430         if ( message.indexOf ( "publickey,password" ) !=-1 )
8431         {
8432             message=tr ( "<b>Wrong password!</b><br><br>" ) +
8433                     message;
8434         }
8435 
8436         QMessageBox::critical ( 0l,tr ( "Error" ),message,
8437                                 QMessageBox::Ok,
8438                                 QMessageBox::NoButton );
8439         setEnabled ( true );
8440         passForm->setEnabled ( true );
8441         pass->setFocus();
8442         pass->selectAll();
8443         return;
8444     }
8445 
8446     passForm->hide();
8447     setUsersEnabled ( false );
8448     uname->setEnabled ( false );
8449     u->setEnabled ( false );
8450     QStringList servers=output.trimmed().split ( '\n' );
8451     for ( int i=0; i<servers.size(); ++i )
8452     {
8453         QStringList lst=servers[i].simplified().split ( ' ' );
8454         if ( lst.size() >1 )
8455         {
8456             for ( int j=0; j<x2goServers.size(); ++j )
8457                 if ( x2goServers[j].name==lst[0] )
8458                 {
8459                     x2goServers[j].sess=
8460                         lst[1].toInt() *
8461                         x2goServers[j].factor;
8462 
8463                     x2goDebug<<x2goServers[j].name<<
8464                              ": sessions "<<
8465                              lst[1].toInt() <<
8466                              ", multiplied "<<x2goServers[j].sess;
8467 
8468                     break;
8469                 }
8470         }
8471     }
8472 
8473     qSort ( x2goServers.begin(),x2goServers.end(),serv::lt );
8474 
8475     listedSessions.clear();
8476     retSessions=0;
8477     if (sshConnection)
8478     {
8479         delete sshConnection;
8480         sshConnection=0;
8481     }
8482     QString passwd;
8483     QString user=getCurrentUname();
8484     passwd=getCurrentPass();
8485     for (int i=0; i< serverSshConnections.count(); ++i)
8486     {
8487         if (serverSshConnections[i])
8488             delete serverSshConnections[i];
8489     }
8490     serverSshConnections.clear();
8491     for ( int j=0; j<x2goServers.size(); ++j )
8492     {
8493         QString host=x2goServers[j].name;
8494         sshPort=x2goServers[j].sshPort;
8495         serverSshConnections<<startSshConnection ( host,sshPort,acceptRsa,user,passwd,true,false,true);
8496     }
8497 }
8498 
8499 
slotListAllSessions(bool result,QString output,int)8500 void ONMainWindow::slotListAllSessions ( bool result,QString output,
8501         int )
8502 {
8503     bool last=false;
8504 
8505     ++retSessions;
8506     if ( retSessions == x2goServers.size() )
8507         last=true;
8508 
8509     if ( result==false )
8510     {
8511         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
8512         if ( message.indexOf ( "publickey,password" ) !=-1 )
8513         {
8514             message=tr ( "<b>Wrong password!</b><br><br>" ) +
8515                     message;
8516         }
8517 
8518         QMessageBox::critical ( 0l,tr ( "Error" ),message,
8519                                 QMessageBox::Ok,
8520                                 QMessageBox::NoButton );
8521         QString sv=output.split ( ":" ) [0];
8522         for ( int j=0; j<x2goServers.size(); ++j )
8523         {
8524             if ( x2goServers[j].name==sv )
8525             {
8526                 x2goServers[j].connOk=false;
8527             }
8528         }
8529     }
8530     else
8531     {
8532         listedSessions+=output.trimmed().split ( '\n',
8533                         QString::SkipEmptyParts );
8534     }
8535     if ( last )
8536     {
8537         if ( listedSessions.size() ==0||
8538                 ( listedSessions.size() ==1 &&
8539                   listedSessions[0].length() <5 ) )
8540         {
8541             x2goDebug<<"Starting new session.";
8542             startNewSession();
8543         }
8544         else if ( listedSessions.size() ==1 )
8545         {
8546             x2goDebug<<"Already having a session.";
8547             x2goSession s=getSessionFromString (
8548                               listedSessions[0] );
8549 
8550             x2goDebug<<"Will proceed with this session.";
8551 
8552             QDesktopWidget wd;
8553 
8554             /* Check getSessionFromString for what this "invalid" string means. */
8555             if ((s.agentPid != "invalid") && (s.status == "S")
8556                 && (isColorDepthOk (wd.depth (), s.colorDepth)))
8557             {
8558                 resumeSession ( s );
8559             }
8560             else
8561             {
8562                 x2goDebug<<"Please select one session ...";
8563                 selectSession ( listedSessions );
8564             }
8565         }
8566         else
8567         {
8568             selectSession ( listedSessions );
8569         }
8570     }
8571 }
8572 
slotResize()8573 void ONMainWindow::slotResize()
8574 {
8575     if ( startHidden )
8576     {
8577         hide();
8578         return;
8579     }
8580     if ( !startMaximized && !mwMax )
8581     {
8582         resize ( mwSize );
8583         move ( mwPos );
8584 
8585         show();
8586     }
8587     else
8588         showMaximized();
8589 }
8590 
slotExportDirectory()8591 void ONMainWindow::slotExportDirectory()
8592 {
8593     if ( shadowSession )
8594         return;
8595 
8596     bool hide_after=false;
8597     if (isHidden())
8598     {
8599         showNormal();
8600         hide_after=true;
8601     }
8602     QString path;
8603     if ( !useLdap && !embedMode )
8604     {
8605         ExportDialog dlg ( sessionExplorer->getLastSession()->id(),this );
8606         if ( dlg.exec() ==QDialog::Accepted )
8607             path=dlg.getExport();
8608     }
8609     else
8610 
8611         path= QFileDialog::getExistingDirectory (
8612                   this,QString::null,
8613                   homeDir );
8614     if (hide_after)
8615         hide();
8616 #ifdef Q_OS_WIN
8617     if ( ONMainWindow::getPortable() &&
8618             ONMainWindow::U3DevicePath().length() >0 )
8619     {
8620         path.replace ( "(U3)",u3Device );
8621     }
8622 
8623     path=cygwinPath ( wapiShortFileName ( path ) );
8624 #endif
8625     if ( path!=QString::null )
8626         exportDirs ( path );
8627 }
8628 
8629 
exportDirs(QString exports,bool removable)8630 void ONMainWindow::exportDirs ( QString exports,bool removable )
8631 {
8632     if ( shadowSession )
8633         return;
8634     if ( embedMode )
8635     {
8636         if ( config.confFS  && ! ( config.useFs ) )
8637         {
8638             return;
8639         }
8640     }
8641     fsExportKeyReady=false;
8642     directory dr;
8643 
8644 
8645     dr.dirList=exports;
8646     dr.key=createKeyBundle();
8647 
8648     // Key creation failure or the like.
8649     if (dr.key.isEmpty ()) {
8650       return;
8651     }
8652 
8653     QString passwd;
8654 
8655     x2goDebug<<"Key created on: "<<dr.key;
8656 
8657     passwd=getCurrentPass();
8658 
8659     fsInTun=false;
8660     if ( !useLdap )
8661     {
8662         if ( !embedMode )
8663         {
8664             X2goSettings st ( "sessions" );
8665 
8666             if (!(sessionExplorer->getLastSession())) {
8667                 x2goDebug << "No session selected, not exporting directories.";
8668                 return;
8669             }
8670 
8671             QString sid=sessionExplorer->getLastSession()->id();
8672 
8673             fsInTun=st.setting()->value ( sid+"/fstunnel",
8674                                           ( QVariant ) true ).toBool();
8675         }
8676         else
8677             fsInTun=true;
8678     }
8679     if ( fsInTun )
8680     {
8681         if ( fsTunnel==0l )
8682             if ( startSshFsTunnel() )
8683                 return;
8684     }
8685 
8686 
8687     QString uname=getCurrentUname();
8688 
8689     /* For the destination, fetch the base name only. */
8690     QFileInfo tmp_file_info (dr.key);
8691     QString dst = tmp_file_info.fileName ();
8692 
8693     dst="~"+uname +"/.x2go/ssh/"+dst;
8694     dr.dstKey=dst;
8695     dr.isRemovable=removable;
8696     exportDir.append ( dr );
8697     QString keyFile=dr.key;
8698     sshConnection->copyFile ( keyFile,dst, this,  SLOT ( slotCopyKey ( bool, QString,int ) ));
8699 
8700 }
8701 
8702 
exportDefaultDirs()8703 void ONMainWindow::exportDefaultDirs()
8704 {
8705     QStringList dirs;
8706     bool clientPrinting= ( useLdap && LDAPPrintSupport );
8707 
8708     if ( !useLdap )
8709     {
8710         if ( !embedMode )
8711         {
8712             if (!(sessionExplorer->getLastSession())) {
8713                 x2goDebug << "No session selected, not exporting default directories.";
8714                 return;
8715             }
8716 
8717             X2goSettings* st;
8718             if (!brokerMode)
8719                 st= new X2goSettings( "sessions" );
8720             else
8721                 st= new X2goSettings(config.iniFile,QSettings::IniFormat);
8722 
8723             clientPrinting= st->setting()->value (
8724                                 sessionExplorer->getLastSession()->id() +
8725                                 "/print", true ).toBool();
8726 
8727             QString exd=st->setting()->value (
8728                             sessionExplorer->getLastSession()->id() +"/export",
8729                             ( QVariant ) QString::null ).toString();
8730             QStringList lst=exd.split ( ";",
8731                                         QString::SkipEmptyParts );
8732             for ( int i=0; i<lst.size(); ++i )
8733             {
8734                 //check if directory is in Windows client format
8735                 QChar splitChar='#';
8736                 if(lst[i].indexOf(splitChar)==-1)
8737                 {
8738                     //Linux client format
8739                     splitChar=':';
8740                 }
8741                 QStringList tails=lst[i].split (
8742                                       splitChar,
8743                                       QString::SkipEmptyParts );
8744                 if(tails.length()!=2)
8745                 {
8746                     //wrong format
8747                     continue;
8748                 }
8749                 if ( tails[1]=="1" )
8750                 {
8751 #ifdef Q_OS_WIN
8752                     if ( ONMainWindow::getPortable() &&
8753                             ONMainWindow::U3DevicePath (
8754                             ).length() >0 )
8755                     {
8756                         tails[0].replace (
8757                             "(U3)",u3Device );
8758                     }
8759 #endif
8760 
8761                     if(!QFile::exists(tails[0]))
8762                     {
8763                         x2goDebug<<"Path "<<tails[0]<<" not found";
8764                         continue;
8765                     }
8766 
8767 #ifdef Q_OS_WIN
8768                     tails[0]=cygwinPath (
8769                                  wapiShortFileName (
8770                                      tails[0] ) );
8771 #endif
8772                     dirs+=tails[0];
8773                 }
8774             }
8775             delete st;
8776         }
8777         else
8778         {
8779             clientPrinting=true;
8780             if ( config.confFS )
8781             {
8782                 clientPrinting=config.useFs;
8783             }
8784         }
8785     }
8786 
8787     if ( clientPrinting )
8788     {
8789         QString path= homeDir +
8790                       "/.x2go/S-"+
8791                       resumingSession.sessionId +"/spool";
8792         QDir spooldir;
8793         if ( !spooldir.exists ( path ) )
8794         {
8795             if ( !spooldir.mkpath ( path ) )
8796             {
8797                 QString message=
8798                     tr (
8799                         "Unable to create directory:" ) + path;
8800                 QMessageBox::critical ( 0l,tr (
8801                                             "Error" ),message,
8802                                         QMessageBox::Ok,
8803                                         QMessageBox::NoButton );
8804 
8805             }
8806         }
8807         spoolDir=path;
8808 #ifdef Q_OS_WIN
8809         path=cygwinPath (
8810                  wapiShortFileName (
8811                      path ) );
8812 #endif
8813         QFile::setPermissions (
8814             path,QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner );
8815 
8816         path+="__PRINT_SPOOL_";
8817         dirs+=path;
8818         printSupport=true;
8819         if ( spoolTimer )
8820             delete spoolTimer;
8821         spoolTimer=new QTimer ( this );
8822         connect ( spoolTimer,SIGNAL ( timeout() ),this,
8823                   SLOT ( slotCheckPrintSpool() ) );
8824         spoolTimer->start ( 2000 );
8825     }
8826     if ( dirs.size() <=0 )
8827         return;
8828 
8829     exportDirs ( dirs.join ( ":" ) );
8830 }
8831 
slotCopyKey(bool result,QString output,int pid)8832 void ONMainWindow::slotCopyKey ( bool result, QString output, int pid)
8833 {
8834     fsExportKey=sshConnection->getSourceFile(pid);
8835 
8836     x2goDebug<<"Exported key: "<<fsExportKey;
8837 
8838     QFile::remove ( fsExportKey );
8839     x2goDebug<<"Key removed.";
8840 
8841     if ( result==false )
8842     {
8843         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
8844         if ( message.indexOf ( "publickey,password" ) !=-1 )
8845         {
8846             message=tr ( "<b>Wrong password!</b><br><br>" ) +
8847                     message;
8848         }
8849 
8850         if (!startHidden)
8851         {
8852             QMessageBox::critical ( 0l,tr ( "Error" ),message,
8853                                     QMessageBox::Ok,
8854                                     QMessageBox::NoButton );
8855         }
8856         else
8857         {
8858             QString printout = tr( "Connection failed: ")  + output.toLatin1();
8859 
8860             if ( output.indexOf ( "publickey,password" ) !=-1 )
8861                 x2goErrorf(11)<< tr( "Connection failed: ")  + output + tr(" - Wrong password.");
8862             else
8863                 x2goErrorf(12)<< tr( "Connection failed: ")  + output;
8864             trayQuit();
8865         }
8866 
8867         QFile::remove ( fsExportKey+".pub" );
8868         return;
8869     }
8870     fsExportKeyReady=true;
8871 
8872     //start reverse mounting if RSA Key and FS tunnel are ready
8873     //start only once from slotFsTunnelOk() or slotCopyKey().
8874     if ( !fsInTun || fsTunReady )
8875         startX2goMount();
8876 
8877 }
8878 
getExpDir(QString key)8879 directory* ONMainWindow::getExpDir ( QString key )
8880 {
8881     for ( int i=0; i<exportDir.size(); ++i )
8882     {
8883         if ( exportDir[i].key==key )
8884             return &exportDir[i];
8885     }
8886     return 0l;
8887 }
8888 
8889 
8890 
8891 
slotRetExportDir(bool result,QString output,int pid)8892 void ONMainWindow::slotRetExportDir ( bool result,QString output,
8893                                       int pid)
8894 {
8895     x2goDebug<<"Post-cleanup for startX2goMount triggered."<<endl;
8896     QString key;
8897     for ( int i=0; i<exportDir.size(); ++i )
8898         if ( exportDir[i].pid==pid )
8899         {
8900             key=exportDir[i].key;
8901             exportDir.removeAt ( i );
8902             break;
8903         }
8904 
8905     if ( result==false )
8906     {
8907         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
8908         x2goDebug<<"startX2goMount failed to mount client-side folder, reason: "<<message<<endl;
8909         if ( message.indexOf ( "publickey,password" ) !=-1 )
8910         {
8911             message=tr ( "<b>Wrong password!</b><br><br>" ) +
8912                     message;
8913         }
8914 
8915         QMessageBox::critical ( 0l,tr ( "Error" ),message,
8916                                 QMessageBox::Ok,
8917                                 QMessageBox::NoButton );
8918     }
8919     QFile file ( key+".pub" );
8920     x2goDebug << "Deactivating public key from " << QString (key + ".pub") << " again.";
8921     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
8922     {
8923         printSshDError_noExportPubKey();
8924         QFile::remove
8925         ( key+".pub" );
8926         return;
8927     }
8928 
8929     QByteArray line = file.readLine();
8930     file.close();
8931 
8932     QDir authorized_keys_dir (homeDir);
8933     authorized_keys_dir = QDir (authorized_keys_dir.absolutePath () + "/.x2go/.ssh/");
8934 
8935     QFile authorized_keys_file (authorized_keys_dir.absolutePath () + "/authorized_keys");
8936 
8937     /*
8938      * We do not try to create the file first.
8939      * This has been already done in startX2goMount().
8940      * We wouldn't be here if that failed.
8941      */
8942     if (!authorized_keys_file.open (QIODevice::ReadOnly | QIODevice::Text)) {
8943       printSshDError_noAuthorizedKeysFile ();
8944       QFile::remove (key + ".pub");
8945       return;
8946     }
8947 
8948     QTemporaryFile tfile (authorized_keys_file.fileName ());
8949     tfile.open ();
8950     tfile.setPermissions (QFile::ReadOwner | QFile::WriteOwner);
8951     tfile.setAutoRemove (true);
8952     QTextStream out (&tfile);
8953 
8954     /*
8955      * Copy the content of the authorized_keys file to our new temporary file
8956      * and remove the public authorized key for the current "session" again.
8957      */
8958     while (!authorized_keys_file.atEnd ()) {
8959       QByteArray newline = authorized_keys_file.readLine ();
8960       if (newline != line)
8961         out << newline;
8962     }
8963 
8964     authorized_keys_file.close ();
8965     tfile.close ();
8966 
8967     authorized_keys_file.remove ();
8968 
8969     tfile.copy (authorized_keys_file.fileName ());
8970     QFile::remove (key + ".pub");
8971 }
8972 
8973 
slotExtTimer()8974 void ONMainWindow::slotExtTimer()
8975 {
8976 
8977     if ( QFile::permissions ( readLoginsFrom ) !=
8978             ( QFile::ReadUser|QFile::WriteUser|QFile::ExeUser|
8979               QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner ) )
8980     {
8981 
8982         x2goDebug<<"Wrong permissions on "<<readLoginsFrom <<":";
8983         x2goDebug<< ( int ) ( QFile::permissions (
8984                                   readLoginsFrom+"/." ) )
8985                  <<"must be"<< ( int ) ( QFile::ReadUser|QFile::WriteUser
8986                                          |QFile::ExeUser|QFile::ReadOwner|
8987                                          QFile::WriteOwner|
8988                                          QFile::ExeOwner ) <<endl;
8989 
8990         if ( extLogin )
8991             extTimer->stop();
8992         return;
8993     }
8994     QString loginDir;
8995     QString logoutDir;
8996     QDir dir ( readLoginsFrom );
8997     QStringList list = dir.entryList ( QDir::Files );
8998     for ( int i=0; i<list.size(); ++i )
8999     {
9000         QFile file ( readLoginsFrom+"/"+list[i] );
9001         if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
9002             continue;
9003         if ( !file.atEnd() )
9004         {
9005             QByteArray line = file.readLine();
9006             QString ln ( line );
9007             QStringList args=ln.split ( "=",
9008                                         QString::SkipEmptyParts );
9009             if ( args.size() >1 )
9010             {
9011                 if ( args[0]=="login" )
9012                 {
9013                     args[1].replace ( "\n","" );
9014                     if ( args[1].size() )
9015                         loginDir=args[1];
9016                 }
9017                 if ( args[0]=="logout" )
9018                 {
9019 
9020                     x2goDebug<<"External logout.";
9021 
9022                     args[1].replace ( "\n","" );
9023                     if ( args[1].size() )
9024                         logoutDir=args[1];
9025                 }
9026             }
9027         }
9028         file.close();
9029         file.remove();
9030     }
9031     if ( exportTimer->isActive() ) //running session
9032     {
9033         if ( logoutDir != QString::null )
9034         {
9035             x2goDebug<<"External logout received";
9036             externalLogout ( logoutDir );
9037         }
9038     }
9039     else
9040     {
9041         if ( loginDir != QString::null )
9042         {
9043             x2goDebug<<"External login.";
9044             externalLogin ( loginDir );
9045         }
9046     }
9047 }
9048 
9049 
slotExportTimer()9050 void ONMainWindow::slotExportTimer()
9051 {
9052 
9053     if ( QFile::permissions ( readExportsFrom ) != ( QFile::ReadUser|
9054             QFile::WriteUser|
9055             QFile::ExeUser|
9056             QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner ) )
9057     {
9058 
9059         x2goDebug<<"Wrong permissions on "<<
9060                  readExportsFrom <<":"<<endl;
9061         x2goDebug<< ( int ) ( QFile::permissions (
9062                                   readExportsFrom+"/." ) )
9063                  <<"must be"<< ( int ) ( QFile::ReadUser|QFile::WriteUser
9064                                          |QFile::ExeUser|QFile::ReadOwner|
9065                                          QFile::WriteOwner|
9066                                          QFile::ExeOwner ) <<endl;
9067         exportTimer->stop();
9068         return;
9069     }
9070 
9071     QDir dir ( readExportsFrom );
9072     QStringList list = dir.entryList ( QDir::Files );
9073     QString expList;
9074     QString unexpList;
9075     QString loginDir;
9076     QString logoutDir;
9077     for ( int i=0; i<list.size(); ++i )
9078     {
9079         QFile file ( readExportsFrom+"/"+list[i] );
9080         if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
9081             continue;
9082         if ( !file.atEnd() )
9083         {
9084             QByteArray line = file.readLine();
9085             QString ln ( line );
9086             QStringList args=ln.split ( "=",
9087                                         QString::SkipEmptyParts );
9088             if ( args.size() >1 )
9089             {
9090                 if ( args[0]=="export" )
9091                 {
9092                     args[1].replace ( "\n","" );
9093                     if ( args[1].size() )
9094                         expList+=":"+args[1];
9095                 }
9096                 if ( args[0]=="unexport" )
9097                 {
9098                     args[1].replace ( "\n","" );
9099                     if ( args[1].size() )
9100                         unexpList+=":"+args[1];
9101                 }
9102             }
9103         }
9104         file.close();
9105         file.remove();
9106     }
9107     QStringList args=expList.split ( ":",QString::SkipEmptyParts );
9108     expList=args.join ( ":" );
9109     if ( expList.size() >0 )
9110     {
9111         exportDirs ( expList,true );
9112     }
9113     args.clear();
9114     args=unexpList.split ( ":",QString::SkipEmptyParts );
9115 
9116     QString passwd=getCurrentPass();
9117     QString user=getCurrentUname();
9118     QString host=resumingSession.server;
9119     QString sessionId=resumingSession.sessionId;
9120 
9121     for ( int i=0; i<args.size(); ++i )
9122     {
9123         sshConnection->executeCommand ( "x2goumount_session "+
9124                                         sessionId+" "+args[i] );
9125     }
9126 }
9127 
slotAboutQt()9128 void ONMainWindow::slotAboutQt()
9129 {
9130     QMessageBox::aboutQt ( this );
9131 }
9132 
slotSupport()9133 void ONMainWindow::slotSupport()
9134 {
9135     QFile file(supportMenuFile);
9136     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
9137         return;
9138 
9139     QTextStream in(&file);
9140     QString sup;
9141     while (!in.atEnd())
9142     {
9143         sup+=in.readLine();
9144     }
9145     QMessageBox::information (this,tr ( "Support" ),sup);
9146 }
9147 
slotAbout()9148 void ONMainWindow::slotAbout()
9149 {
9150     /*
9151      * This (extra) comment (for translators) looks fucked up, and it is, but
9152      * this can't be changed.
9153      *
9154      * Adding asterisks in front of a line will cause them to literally appear
9155      * in the comment, so I'd rather just drop them.
9156      *
9157      * Adding any whitespace in front of a line will lead to one whitespace
9158      * character surviving the lupdate scan, so we have to drop them as well.
9159      *
9160      * NOT adding an escape character to the end of a line will make lupdate
9161      * stupidly replace the newline character with a whitespace character.
9162      */
9163     /*:
9164 Translators, feel free to add a localized version of your translation
9165 including a copyright notice and your name(s). Remember to keep a <br>
9166 at the end, though.\n\n\
9167 \
9168 English example for a potential translation:\n\n\
9169 \
9170 <br>(C) 2005-2020 by <b>obviously nice</b>: \
9171 Oleksandr Shneyder, Heinz-Markus Graesing<br>\
9172 English version: (C) 20AB-20CD Trans Lator <trans@la.tor><br>
9173      */
9174     QString aboutStr=tr ("<br>(C) 2005-2020 by <b>obviously nice</b>: "
9175                          "Oleksandr Shneyder, Heinz-Markus Graesing<br>" );
9176     aboutStr+=
9177         tr (
9178             "<br>This is a client to access the X2Go network-based "
9179             "computing environment. This client will be able "
9180             "to connect to X2Go Server(s) and start, stop, "
9181             "resume and terminate (running) desktop sessions. "
9182             "X2Go Client stores different server connections "
9183             "and may automatically request authentication "
9184             "data from LDAP directories. Furthermore, it can be "
9185             "used as a fullscreen login screen (replacement for "
9186             "login managers like XDM). Please visit <a "
9187             "href=\"http://www.x2go.org\">the project home page at "
9188             "x2go.org</a> for further information." );
9189     QMessageBox::about (
9190         this,tr ( "About X2Go Client" ),
9191         tr ( "<b>X2Go Client v. " ) +VERSION+
9192         "</b> (Qt - "+qVersion() +")"+
9193         aboutStr );
9194 }
9195 
9196 
9197 
slotRereadUsers()9198 void ONMainWindow::slotRereadUsers()
9199 {
9200     if ( !useLdap )
9201         return;
9202 #ifdef USELDAP
9203 
9204     if ( ld )
9205     {
9206         delete ld;
9207         ld=0;
9208     }
9209 
9210 
9211     if ( ! initLdapSession ( false ) )
9212     {
9213         return;
9214     }
9215 
9216 
9217     list<string> attr;
9218     attr.push_back ( "uidNumber" );
9219     attr.push_back ( "uid" );
9220 
9221 
9222     list<LDAPBinEntry> result;
9223     try
9224     {
9225         ld->binSearch ( ldapDn.toStdString(),attr,
9226                         "objectClass=posixAccount",result );
9227     }
9228     catch ( LDAPExeption e )
9229     {
9230         QString message="Exception in: ";
9231         message=message+e.err_type.c_str();
9232         message=message+" : "+e.err_str.c_str();
9233         QMessageBox::critical ( 0l,tr ( "Error" ),message,
9234                                 QMessageBox::Ok,QMessageBox::NoButton );
9235         QMessageBox::critical ( 0l,tr ( "Error" ),
9236                                 tr ( "Please check LDAP Settings." ),
9237                                 QMessageBox::Ok,QMessageBox::NoButton );
9238         slotConfig();
9239         return;
9240     }
9241 
9242     list<LDAPBinEntry>::iterator it=result.begin();
9243     list<LDAPBinEntry>::iterator end=result.end();
9244 
9245     for ( ; it!=end; ++it )
9246     {
9247         user u;
9248         QString uin=LDAPSession::getBinAttrValues (
9249                         *it,"uidNumber" ).front().getData();
9250         u.uin=uin.toUInt();
9251         if ( u.uin<firstUid || u.uin>lastUid )
9252         {
9253             continue;
9254         }
9255         u.uid=LDAPSession::getBinAttrValues (
9256                   *it,"uid" ).front().getData();
9257         if ( !findInList ( u.uid ) )
9258         {
9259             reloadUsers();
9260             return;
9261         }
9262     }
9263 #endif
9264 }
9265 
reloadUsers()9266 void ONMainWindow::reloadUsers()
9267 {
9268     int i;
9269     for ( i=0; i<names.size(); ++i )
9270         names[i]->close();
9271 
9272     userList.clear();
9273 
9274     sessionExplorer->cleanSessions();
9275 
9276 
9277     loadSettings();
9278     if ( useLdap )
9279     {
9280         act_new->setEnabled ( false );
9281         act_edit->setEnabled ( false );
9282         u->setText ( tr ( "Login:" ) );
9283         QTimer::singleShot ( 1, this, SLOT ( readUsers() ) );
9284     }
9285     else
9286     {
9287         act_new->setEnabled ( true );
9288         act_edit->setEnabled ( true );
9289         u->setText ( tr ( "Session:" ) );
9290         QTimer::singleShot ( 1, this, SLOT ( slotReadSessions() ) );
9291     }
9292     slotResize ( fr->size() );
9293 }
9294 
9295 
findInList(const QString & uid)9296 bool ONMainWindow::findInList ( const QString& uid )
9297 {
9298     for ( int i=0; i<userList.size(); ++i )
9299     {
9300         if ( userList[i].uid==uid )
9301             return true;
9302     }
9303     return false;
9304 }
9305 
setUsersEnabled(bool enable)9306 void ONMainWindow::setUsersEnabled ( bool enable )
9307 {
9308 
9309     if ( useLdap )
9310     {
9311         QScrollBar* bar=users->verticalScrollBar();
9312         bar->setEnabled ( enable );
9313         int upos=bar->value();
9314         QDesktopWidget dw;
9315         int height=dw.screenGeometry ( fr ).height();
9316         QList<UserButton*>::iterator it;
9317         QList<UserButton*>::iterator endit=names.end();
9318         if ( !enable )
9319         {
9320             for ( it=names.begin(); it!=endit; it++ )
9321             {
9322                 QPoint pos= ( *it )->pos();
9323                 if ( ( pos.y() >upos-height ) &&
9324                         ( pos.y() <upos+height ) )
9325                     ( *it )->setEnabled ( false );
9326                 if ( pos.y() >upos+height )
9327                     break;
9328             }
9329         }
9330         else
9331         {
9332             for ( it=names.begin(); it!=endit; it++ )
9333             {
9334                 if ( ! ( *it )->isEnabled() )
9335                     ( *it )->setEnabled ( true );
9336             }
9337         }
9338     }
9339     else
9340     {
9341         users->setEnabled ( enable );
9342         sessionExplorer->setEnable(enable);
9343     }
9344 }
9345 
9346 
externalLogin(const QString & loginDir)9347 void ONMainWindow::externalLogin ( const QString& loginDir )
9348 {
9349     QFile file ( loginDir+"/username" );
9350     QString user;
9351 
9352     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
9353         return;
9354     QTextStream in ( &file );
9355     while ( !in.atEnd() )
9356     {
9357         user=in.readLine();
9358         break;
9359     }
9360     file.close();
9361 
9362 
9363     if ( passForm->isVisible() )
9364         slotClosePass();
9365     uname->setText ( user );
9366     slotUnameEntered();
9367     currentKey=loginDir+"/dsa.key";
9368     extStarted=true;
9369     slotPassEnter();
9370 }
9371 
9372 
externalLogout(const QString &)9373 void ONMainWindow::externalLogout ( const QString& )
9374 {
9375     if ( extStarted )
9376     {
9377         extStarted=false;
9378         currentKey=QString::null;
9379         if ( nxproxy )
9380             if ( nxproxy->state() ==QProcess::Running )
9381                 nxproxy->terminate();
9382         proxyRunning=false;
9383     }
9384 }
9385 
9386 
slotStartPGPAuth()9387 void ONMainWindow::slotStartPGPAuth()
9388 {
9389     scDaemon=new QProcess ( this );
9390 
9391     connect ( scDaemon,SIGNAL ( readyReadStandardError() ),this,
9392               SLOT ( slotScDaemonStdErr() ) );
9393     connect ( scDaemon,SIGNAL ( readyReadStandardOutput() ),this,
9394               SLOT ( slotScDaemonStdOut() ) );
9395     connect ( scDaemon,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),
9396               this,
9397               SLOT (
9398                   slotScDaemonFinished ( int, QProcess::ExitStatus ) ) );
9399     connect (scDaemon, SIGNAL (error (QProcess::ProcessError)), this,
9400              SLOT (slotScDaemonError (QProcess::ProcessError)));
9401     scDaemon->start ( "pcsc_scan -n");
9402 
9403 }
9404 
9405 
slotScDaemonStdErr()9406 void ONMainWindow::slotScDaemonStdErr()
9407 {
9408     QString stdOut ( scDaemon->readAllStandardError() );
9409     stdOut=stdOut.simplified();
9410     x2goDebug<<"PCSC error: "<<stdOut;
9411 }
9412 
slotScDaemonStdOut()9413 void ONMainWindow::slotScDaemonStdOut()
9414 {
9415     QString stdOut ( scDaemon->readAllStandardOutput() );
9416     stdOut=stdOut.simplified();
9417 
9418     x2goDebug<<"PCSC out: |"<<stdOut<<"|";
9419     if(stdOut.indexOf("Card inserted")!=-1)
9420     {
9421         x2goDebug<<"GOT NEW CARD!!!!!";
9422         startGPG();
9423     }
9424     if(stdOut.indexOf("Card removed")!=-1)
9425     {
9426        cardReady=false;
9427        if ( cardStarted )
9428        {
9429            cardStarted=false;
9430            if ( nxproxy )
9431               if ( nxproxy->state() ==QProcess::Running )
9432               {
9433                   x2goDebug<<"Suspending session ...";
9434                   slotSuspendSessFromSt();
9435                   x2goDebug<<"Suspended session.";
9436               }
9437        }
9438     }
9439 }
9440 
slotScDaemonFinished(int,QProcess::ExitStatus)9441 void ONMainWindow::slotScDaemonFinished ( int , QProcess::ExitStatus )
9442 {
9443     //this should not happen, restart...
9444     scDaemon=0l;
9445     x2goDebug<<"SCDAEMON finished."<<endl;
9446     slotStartPGPAuth();
9447 }
9448 
slotScDaemonError(QProcess::ProcessError error)9449 void ONMainWindow::slotScDaemonError (QProcess::ProcessError error) {
9450     QString main_text ("pcsc_scan ");
9451     QString informative_text;
9452 
9453     switch (error) {
9454         case QProcess::FailedToStart: {
9455             main_text += tr ("failed to start.");
9456             informative_text = tr ("Check whether the package providing \"pcsc_scan\" is installed.\n"
9457                                    "The current search path is: ");
9458 
9459             break;
9460         }
9461         case QProcess::Crashed: {
9462             /* This means the process exited with a non-zero exit code.
9463              * It didn't really crash at all. Everything is fine.
9464              * Just restart it. */
9465             return;
9466         }
9467         case QProcess::Timedout: {
9468             main_text += tr ("didn't start yet.");
9469             informative_text = tr ("This error shouldn't come up.");
9470             break;
9471         }
9472         case QProcess::WriteError: {
9473             main_text += tr ("didn't accept a write operation.");
9474             informative_text = tr ("It is probably not running correctly or crashed in-between.");
9475             break;
9476         }
9477         case QProcess::ReadError: {
9478             main_text = tr ("Unable to read from scdaemon.");
9479             informative_text = tr ("It is probably not running correctly or crashed in-between.");
9480             break;
9481         }
9482         case QProcess::UnknownError: {
9483             main_text += tr ("encountered an unknown error during start up or execution.");
9484             break;
9485         }
9486         default: {
9487             main_text += tr ("experienced an undefined error.");
9488             break;
9489         }
9490     }
9491 
9492     if (!informative_text.isEmpty ()) {
9493         informative_text += "\n\n";
9494     }
9495 
9496     informative_text += tr ("X2Go Client will now terminate.\n\n"
9497                             "File a bug report as outlined on the <a href=\"http://wiki.x2go.org/doku.php/wiki:bugs\">bugs wiki page</a>.");
9498 
9499     show_RichText_ErrorMsgBox (main_text, informative_text);
9500     trayQuit ();
9501 }
9502 
slotShowPAMSGDialog(bool error,const QString & main_text,const QString & info_text,bool modal)9503 void ONMainWindow::slotShowPAMSGDialog(bool error, const QString& main_text, const QString& info_text, bool modal)
9504 {
9505     if(error)
9506     {
9507         show_RichText_ErrorMsgBox(main_text, info_text,modal);
9508     }
9509     else
9510     {
9511         show_RichText_WarningMsgBox(main_text, info_text, modal);
9512     }
9513 }
9514 
9515 
slotGpgError()9516 void ONMainWindow::slotGpgError()
9517 {
9518     QString stdOut ( gpg->readAllStandardError() );
9519     stdOut=stdOut.simplified();
9520 
9521     x2goDebug<<"GPG error: "<<stdOut;
9522 
9523     if ( stdOut.indexOf ( "failed" ) !=-1 )
9524     {
9525         QMessageBox::critical ( 0l,tr ( "Error" ),
9526                                 tr ( "No valid card found." ),
9527                                 QMessageBox::Ok,
9528                                 QMessageBox::NoButton );
9529         gpg->kill();
9530     }
9531 }
9532 
9533 
slotGpgFinished(int exitCode,QProcess::ExitStatus exitStatus)9534 void ONMainWindow::slotGpgFinished ( int exitCode,
9535                                      QProcess::ExitStatus exitStatus )
9536 {
9537 
9538     x2goDebug<<"GPG finished, exit code: "<<exitCode;
9539     x2goDebug<<"GPG finished, exit status:"<<exitStatus;
9540 
9541     if ( exitStatus==0 )
9542     {
9543         QString stdOut ( gpg->readAllStandardOutput() );
9544         stdOut.chop ( 1 );
9545 
9546         x2goDebug<<"GPG out: "<<stdOut;
9547 
9548         QStringList lines=stdOut.split ( "\n" );
9549         QString login;
9550         QString appId;
9551         QString authKey;
9552         for ( int i=0; i<lines.count(); ++i )
9553         {
9554             if ( lines[i].indexOf ( "Application ID" ) !=-1 )
9555             {
9556                 appId=lines[i].split ( ":" ) [1];
9557             }
9558             else if ( lines[i].indexOf ( "Login data" ) !=-1 )
9559             {
9560                 login=lines[i].split ( ":" ) [1];
9561             }
9562             else if ( lines[i].indexOf (
9563                           "Authentication key" ) !=-1 )
9564             {
9565                 authKey=lines[i].split ( ":" ) [1];
9566                 break;
9567             }
9568         }
9569         appId=appId.simplified();
9570         login=login.simplified();
9571         authKey=authKey.simplified();
9572 
9573         x2goDebug<<"Card data: "<<appId<<login<<authKey;
9574 
9575         if ( login=="[not set]" || authKey == "[none]" )
9576         {
9577 
9578             x2goErrorf(13)<<tr("Card not configured.");
9579 
9580             QMessageBox::critical (
9581                 0l,tr ( "Error" ),
9582                 tr (
9583                     "This card is unknown to the X2Go system." ),
9584                 QMessageBox::Ok,
9585                 QMessageBox::NoButton );
9586         }
9587         else
9588         {
9589             cardReady=true;
9590             cardLogin=login;
9591             //card is ready
9592             GPGCardLogin(login);
9593         }
9594     }
9595     gpg=0l;
9596 }
9597 
startGPG()9598 void ONMainWindow::startGPG()
9599 {
9600 
9601         QStringList arguments;
9602         gpg=new QProcess ( this );
9603         arguments<<"--card-status";
9604         connect ( gpg,SIGNAL ( readyReadStandardError() ),
9605                   this,SLOT ( slotGpgError() ) );
9606         connect ( gpg,SIGNAL ( finished ( int,
9607                                           QProcess::ExitStatus ) ),this,
9608                   SLOT ( slotGpgFinished ( int,
9609                                            QProcess::ExitStatus ) ) );
9610         gpg->start ( "gpg",arguments );
9611         x2goDebug<<"gpg started";
9612 
9613 }
9614 
GPGCardLogin(const QString & cardLogin)9615 void ONMainWindow::GPGCardLogin ( const QString& cardLogin)
9616 {
9617     if ( !useLdap )
9618     {
9619          if ( passForm->isVisible() && !brokerMode)
9620          {
9621              if ( passForm->isEnabled() )
9622              {
9623                  if ( login->isEnabled() )
9624                  {
9625                      login->setText ( cardLogin );
9626                      slotSessEnter();
9627                  }
9628              }
9629         }
9630         if(brokerMode && (!config.brokerAutologoff))
9631         {
9632             broker->getUserSessions();
9633         }
9634     }
9635     else
9636     {
9637         if ( passForm->isVisible() )
9638             slotClosePass();
9639         uname->setText ( cardLogin );
9640         slotUnameEntered();
9641         slotPassEnter();
9642     }
9643 }
9644 
9645 
9646 #if defined ( Q_OS_DARWIN )
getXDisplay()9647 QString ONMainWindow::getXDisplay()
9648 {
9649     QLocalSocket unixSocket (this);
9650     QString xsocket (getenv ("DISPLAY"));
9651 
9652     if (xsocket.isEmpty ())
9653     {
9654         // Mac OS X 10.4 compatibility mode.
9655         // There, it is possible no $DISPLAY variable is set.
9656         // Start X11 manually. First, find a free display number.
9657 
9658         x2goDebug<< "Entering 10.4 compat mode, checking for free X11 display.";
9659 
9660 
9661         int xFreeDisp = 0;
9662         QDir xtmpdir ("/tmp/.X11-unix");
9663 
9664         if (xtmpdir.exists ())
9665         {
9666             xtmpdir.setFilter (QDir::Files | QDir::System | QDir::NoSymLinks | QDir::NoDotAndDotDot);
9667             xtmpdir.setSorting (QDir::Name);
9668 
9669             QFileInfoList xtmpdirList = xtmpdir.entryInfoList ();
9670             bool foundFreeDisp = FALSE;
9671             xFreeDisp = -1;
9672 
9673             for (int i = 0; (i < 2000) && (!foundFreeDisp); ++i)
9674             {
9675                 QFileInfo xtmpdirFile (xtmpdir.absolutePath () + "/X" + QString::number (i));
9676 
9677                 if ((!xtmpdirFile.exists ()) && (!xtmpdirFile.isSymLink ()))
9678                 {
9679                     xFreeDisp = i;
9680                     foundFreeDisp = TRUE;
9681                 }
9682             }
9683         }
9684 
9685         // Control flow will go to error condition if no free display port has been found.
9686         if (xFreeDisp != -1)
9687         {
9688             xsocket = "/tmp/.X11-unix/X" + QString::number (xFreeDisp);
9689 
9690             x2goDebug<< "Successfully detected free socket " << xsocket << ".";
9691         }
9692 
9693         if (!(xsocket.isEmpty ()))
9694         {
9695             QString xname = ConfigDialog::getXDarwinDirectory () + "/Contents/MacOS/X11";
9696             QString xopt = ":" + QString::number (xFreeDisp);
9697             QProcessEnvironment env = QProcessEnvironment::systemEnvironment ();
9698             QProcess* startx = new QProcess (this);
9699 
9700             x2goDebug<< "Starting the X server on free display port.";
9701 
9702             /* FIXME: why not passing our current environment, maybe extended via add_to_path ()? */
9703             env.insert (0, "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11R6/bin");
9704 
9705             startx->setProcessEnvironment (env);
9706             startx->start (xname + QString (" ") + xopt, QIODevice::NotOpen);
9707             if (startx->waitForStarted (3000))
9708             {
9709 
9710                 x2goDebug<< "Sleeping for three seconds";
9711                 int sleeptime = 3;
9712                 while ((sleeptime = sleep (sleeptime))) {};
9713 
9714                 x2goDebug<< "Leaving OS X 10.4 compat mode.";
9715 
9716             }
9717         }
9718     }
9719 
9720     // OS X >= 10.5 starts the X11 server automatically, as soon as the
9721     // launchd UNIX socket is accessed.
9722     // On user login, the DISPLAY environment variable is set to this said existing
9723     // socket.
9724     // By now, we should have a socket, even on 10.4. Test, if connecting works.
9725     // Note: common sense may tell you to change this if into an else. Don't.
9726     // We do not want to skip this part, if coming from the compat section above.
9727     if (!(xsocket.isEmpty ()))
9728     {
9729         if (xsocket[0] == ':')
9730         {
9731             // Be backwards compatible with 10.4.
9732             // Delete the ":" character.
9733             xsocket.remove (0, 1);
9734             // xsocket may now contain the display value (one integer),
9735             // or something like "0.0" - we're only interested in the
9736             // display value, so keep the first char only.
9737             if (xsocket.indexOf (".") != -1)
9738             {
9739                 xsocket = xsocket.left (xsocket.indexOf ("."));
9740             }
9741             // Prepend the well-known socket path.
9742             xsocket.prepend ("/tmp/.X11-unix/X");
9743 
9744             x2goDebug<< "xsocket in compat mode: " << xsocket;
9745 
9746         }
9747 
9748         unixSocket.connectToServer (xsocket);
9749 
9750         if (unixSocket.waitForConnected (10000))
9751         {
9752             unixSocket.disconnectFromServer ();
9753 
9754             // Mac OS X 10.4 compat: nxproxy expects
9755             // a DISPLAY variable like ":0", passing
9756             // an UNIX socket will just make it error out.
9757             // Instead of altering the nxproxy code, which does
9758             // already try to connect to "/tmp/.X11-unix/Xi" with
9759             // i = display number, pass ":i" as DISPLAY.
9760             if (xsocket.left (16).compare ("/tmp/.x11-unix/x", Qt::CaseInsensitive) == 0)
9761             {
9762                 bool ok = FALSE;
9763                 int tmp = -1;
9764 
9765                 xsocket = xsocket.mid (16);
9766                 tmp = xsocket.toInt (&ok);
9767 
9768                 if (ok)
9769                 {
9770                     x2goDebug<<"Returning " << QString (":") + xsocket;
9771                     return (QString (":") + xsocket);
9772                 }
9773             }
9774             else
9775             {
9776                 return (xsocket);
9777             }
9778         }
9779     }
9780     // And if not, error out.
9781     show_XQuartz_start_error ();
9782     slotConfig();
9783     return QString::null;
9784 }
9785 #endif
9786 
9787 #ifdef Q_OS_WIN
getXDisplay()9788 QString ONMainWindow::getXDisplay()
9789 {
9790     if ( !isServerRunning ( 6000+xDisplay ) )
9791     {
9792         QMessageBox::critical (
9793             this,QString::null,
9794             tr (
9795                 "Can't start X.Org Server.\nPlease check your installation." )
9796         );
9797         close();
9798     }
9799     return QString::number ( xDisplay );
9800 
9801 }
9802 
cygwinPath(const QString & winPath)9803 QString ONMainWindow::cygwinPath ( const QString& winPath )
9804 {
9805     QString cPath="/cygdrive/"+winPath;
9806     cPath.replace ( "\\","/" );
9807     cPath.replace ( ":","" );
9808     return cPath;
9809 }
9810 #endif
9811 
isColorDepthOk(int disp,int sess)9812 bool ONMainWindow::isColorDepthOk ( int disp, int sess )
9813 {
9814     if ( sess==0 )
9815         return true;
9816     if ( disp==sess )
9817         return true;
9818     if ( ( disp == 24 || disp == 32 ) && ( sess == 24 || sess == 32 ) )
9819         return true;
9820     return false;
9821 }
9822 
9823 #ifndef Q_OS_UNIX
setWidgetStyle(QWidget * widget)9824 void ONMainWindow::setWidgetStyle ( QWidget* widget )
9825 {
9826     widget->setStyle ( widgetExtraStyle );
9827 }
9828 #else
setWidgetStyle(QWidget *)9829 void ONMainWindow::setWidgetStyle ( QWidget* )
9830 {
9831 }
9832 #endif
9833 
internAppName(const QString & transAppName,bool * found)9834 QString ONMainWindow::internAppName ( const QString& transAppName, bool* found )
9835 {
9836     if ( found )
9837         *found=false;
9838     int ind=_transApplicationsNames.indexOf ( transAppName );
9839     if ( ind!=-1 )
9840     {
9841         if ( found )
9842             *found=true;
9843         return _internApplicationsNames[ind];
9844     }
9845     return transAppName;
9846 }
9847 
9848 
transAppName(const QString & internAppName,bool * found)9849 QString ONMainWindow::transAppName ( const QString& internAppName, bool* found )
9850 {
9851     if ( found )
9852         *found=false;
9853     int ind=_internApplicationsNames.indexOf ( internAppName );
9854     if ( ind!=-1 )
9855     {
9856         if ( found )
9857             *found=true;
9858         return _transApplicationsNames[ind];
9859     }
9860     return internAppName;
9861 }
9862 
addToAppNames(QString intName,QString transName)9863 void ONMainWindow::addToAppNames ( QString intName, QString transName )
9864 {
9865     _internApplicationsNames.append ( intName );
9866     _transApplicationsNames.append ( transName );
9867 }
9868 
9869 
slotExecXmodmap()9870 void ONMainWindow::slotExecXmodmap()
9871 {
9872 #ifdef Q_WS_HILDON
9873     QString passwd=getCurrentPass();
9874     QString user=getCurrentUname();
9875     QString host=resumingSession.server;
9876     QString cmd;
9877 
9878     cmd="(xmodmap -pke ;"
9879         "echo keycode 73= ;"
9880 // 	    "echo clear shift ;"
9881 // 	    "echo clear lock ;"
9882 // 	    "echo clear control ;"
9883 // 	    "echo clear mod1 ;"
9884 // 	    "echo clear mod2 ;"
9885 // 	    "echo clear mod3 ;"
9886 // 	    "echo clear mod4 ;"
9887 // 	    "echo clear mod5 ;"
9888 //  	    "echo add shift = Shift_L ;"
9889         "echo add control = Control_R "
9890 //  	    "echo add mod5 = ISO_Level3_Shift"
9891         ")| DISPLAY=:"
9892         +resumingSession.display+" xmodmap - ";
9893 
9894     x2goDebug<<"Executing xmodmap with cmd: "<<cmd;
9895 
9896     SshProcess* xmodProc;
9897     try
9898     {
9899         xmodProc=new SshProcess ( this,user,host,sshPort,
9900                                   cmd,
9901                                   passwd,currentKey,acceptRsa );
9902     }
9903     catch ( QString message )
9904     {
9905         return;
9906     }
9907 
9908     if ( cardReady /*|| useSshAgent*/ )
9909     {
9910         QStringList env=xmodProc->environment();
9911         env+=sshEnv;
9912         xmodProc->setEnvironment ( env );
9913     }
9914     xmodProc->setFwX ( true );
9915     xmodProc->startNormal();
9916 #endif
9917 }
9918 
check_cmd_status()9919 void ONMainWindow::check_cmd_status()
9920 {
9921     QString passwd;
9922     QString user=getCurrentUname();
9923     QString host=resumingSession.server;
9924     passwd=getCurrentPass();
9925 
9926     sshConnection->executeCommand ( "x2gocmdexitmessage "+
9927                                     resumingSession.sessionId , this, SLOT(slotCmdMessage(bool, QString, int)));
9928 }
9929 
slotCmdMessage(bool result,QString output,int)9930 void ONMainWindow::slotCmdMessage ( bool result,QString output,
9931                                     int)
9932 {
9933     x2goDebug<<"Command message: " + output;
9934     if ( result==false )
9935     {
9936         cardReady=false;
9937         cardStarted=false;
9938         QString message=tr ( "<b>Connection failed.</b>\n" ) +output;
9939         if ( message.indexOf ( "publickey,password" ) !=-1 )
9940         {
9941             message=tr ( "<b>Wrong password!</b><br><br>" ) +
9942                     message;
9943         }
9944 
9945         QMessageBox::critical ( 0l,tr ( "Error" ),message,
9946                                 QMessageBox::Ok,
9947                                 QMessageBox::NoButton );
9948         setEnabled ( true );
9949         passForm->setEnabled ( true );
9950         pass->setFocus();
9951         pass->selectAll();
9952     }
9953     if ( output.indexOf ( "X2GORUNCOMMAND ERR NOEXEC:" ) !=-1 )
9954     {
9955         QString cmd=output;
9956         cmd.replace ( "X2GORUNCOMMAND ERR NOEXEC:","" );
9957 
9958         if(startHidden)
9959         {
9960             x2goErrorf(14)<< tr( "Unable to execute: ") + cmd;
9961         }
9962         else
9963         {
9964             QMessageBox::critical ( 0l,tr ( "Error" ),
9965                                     tr ( "Unable to execute: " ) +
9966                                     cmd,QMessageBox::Ok,
9967                                     QMessageBox::NoButton );
9968         }
9969     }
9970     if(sshConnection)
9971         delete sshConnection;
9972     sshConnection=0;
9973     if (startHidden)
9974     {
9975         x2goInfof(11) << tr("Closing X2Go Client because it was started in hidden mode.");
9976         close();
9977     }
9978     else if (closeDisconnect)
9979     {
9980         x2goInfof(12) << tr("Closing X2Go Client because the --close-disconnect parameter was passed.");
9981         close();
9982     }
9983 }
9984 
9985 
startSshFsTunnel()9986 int ONMainWindow::startSshFsTunnel()
9987 {
9988     fsTunReady=false;
9989 
9990     x2goDebug<<"Starting Folder Sharing tunnel for: "<<resumingSession.sessionId;
9991     x2goDebug<<"FS port: "<<resumingSession.fsPort;
9992 
9993 
9994     if ( resumingSession.fsPort.length() <=0 )
9995     {
9996         QString message=tr ("Remote server does not "
9997                             "support file system exports "
9998                             "through SSH tunnels.\n"
9999                             "Please update your x2goserver "
10000                             "package." );
10001         slotFsTunnelFailed ( false,message,0 );
10002         return 1;
10003     }
10004     QString passwd=getCurrentPass();
10005     QString uname=getCurrentUname();
10006 
10007     fsTunnel=sshConnection->startTunnel ( "localhost",resumingSession.fsPort.toUInt(),"127.0.0.1",
10008                                           clientSshPort.toInt(), true, this, SLOT ( slotFsTunnelOk(int)), SLOT ( slotFsTunnelFailed ( bool,
10009                                                   QString,int ) ) );
10010     return 0;
10011 }
10012 
slotFsTunnelFailed(bool result,QString output,int)10013 void ONMainWindow::slotFsTunnelFailed ( bool result,  QString output,
10014                                         int)
10015 {
10016     if ( result==false )
10017     {
10018         if ( !managedMode )
10019         {
10020 
10021             QString message=tr ( "Unable to create SSH tunnel for Folder Sharing and Printing support:\n" )
10022                             +output;
10023             QMessageBox::critical ( 0l,tr ( "Error" ),message,
10024                                     QMessageBox::Ok,
10025                                     QMessageBox::NoButton );
10026         }
10027         fsTunnel=0l;
10028         fsTunReady=false;
10029     }
10030 }
10031 
10032 
slotFsTunnelOk(int)10033 void ONMainWindow::slotFsTunnelOk(int)
10034 {
10035     x2goDebug<<"FS tunnel through SSH seems to be up and running ..."<<endl;
10036 
10037     fsTunReady=true;
10038     //start reverse mounting if RSA Key and FS tunnel are ready
10039     //start only once from slotFsTunnelOk() or slotCopyKey().
10040     if ( fsExportKeyReady )
10041         startX2goMount();
10042 }
10043 
10044 
startX2goMount()10045 void ONMainWindow::startX2goMount()
10046 {
10047     QFile file ( fsExportKey+".pub" );
10048     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
10049     {
10050         QString message=tr ( "Unable to read:\n" ) +fsExportKey+".pub";
10051         QMessageBox::critical ( 0l,tr ( "Error" ),message,
10052                                 QMessageBox::Ok,
10053                                 QMessageBox::NoButton );
10054         QFile::remove
10055         ( fsExportKey+".pub" );
10056         return;
10057     }
10058 
10059     QByteArray line = file.readLine();
10060     file.close();
10061 
10062     QDir authorized_keys_dir (homeDir);
10063     authorized_keys_dir = QDir (authorized_keys_dir.absolutePath () + "/.x2go/.ssh/");
10064 
10065     QFile authorized_keys_file (authorized_keys_dir.absolutePath () + "/authorized_keys");
10066 
10067     x2goDebug << "Potentially creating dir " << authorized_keys_dir.absolutePath ();
10068     authorized_keys_dir.mkpath (authorized_keys_dir.absolutePath ());
10069 
10070     x2goDebug << "Potentially creating file " << authorized_keys_file.fileName ();
10071     if (!authorized_keys_file.open (QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
10072       QString message = tr ("Unable to create or append to file: ") + authorized_keys_file.fileName ();
10073       QMessageBox::critical (0l, tr ("Error"), message,
10074                              QMessageBox::Ok, QMessageBox::NoButton);
10075       QFile::remove (fsExportKey + ".pub");
10076       return;
10077     }
10078 
10079 #ifdef Q_OS_UNIX
10080     QFile::Permissions authorized_keys_file_perm = authorized_keys_file.permissions ();
10081     QFile::Permissions authorized_keys_file_target_perm = QFile::ReadOwner | QFile::WriteOwner;
10082 
10083     bool permission_error = false;
10084 
10085     /*
10086      * Try to set the permissions if they are wrong.
10087      * (sshd would disallow such a file.)
10088      */
10089     if (authorized_keys_file_perm != authorized_keys_file_target_perm) {
10090       if (!authorized_keys_file.setPermissions (authorized_keys_file_target_perm)) {
10091         /* FIXME: use a function for this... */
10092         QString message = tr ("Unable to change the permissions of file: ") + authorized_keys_file.fileName ();
10093         message += "\n" + tr ("This is an error because sshd would deny such a file.");
10094         QMessageBox::critical (NULL, tr ("Error"), message,
10095                                QMessageBox::Ok, QMessageBox::NoButton);
10096         permission_error = true;
10097       }
10098     }
10099 
10100     QFile::Permissions authorized_keys_dir_perm = QFile (authorized_keys_dir.absolutePath ()).permissions ();
10101     QFile::Permissions authorized_keys_dir_target_perm = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
10102 
10103     /*
10104      * Try to set the permissions if they are wrong.
10105      * (sshd would disallow such a directory.)
10106      */
10107     if (authorized_keys_dir_perm != authorized_keys_dir_target_perm) {
10108       if (!QFile (authorized_keys_dir.absolutePath ()).setPermissions (authorized_keys_dir_target_perm)) {
10109         /* FIXME: use a function for this... */
10110         QString message = tr ("Unable to change the permissions of directory: ") + authorized_keys_dir.absolutePath ();
10111         message += "\n" + tr ("This is an error because sshd would deny such a directory.");
10112         QMessageBox::critical (NULL, tr ("Error"), message,
10113                                QMessageBox::Ok, QMessageBox::NoButton);
10114         permission_error = true;
10115       }
10116     }
10117 
10118     if (permission_error) {
10119       QFile::remove (fsExportKey + ".pub");
10120       return;
10121     }
10122 #endif /* defined (Q_OS_UNIX) */
10123 
10124     directory* dir = getExpDir (fsExportKey);
10125     bool rem = dir->isRemovable;
10126     if (!dir) {
10127       return;
10128     }
10129 
10130     QTextStream out (&authorized_keys_file);
10131     out << line;
10132     authorized_keys_file.close ();
10133 
10134     x2goDebug << "Temporarily activated public key from file " << QString (fsExportKey + ".pub") << ".";
10135 
10136     QString passwd=getCurrentPass();
10137     QString user=getCurrentUname();
10138     QString host=resumingSession.server;
10139     QString sessionId=resumingSession.sessionId;
10140 
10141     QStringList env=QProcess::systemEnvironment();
10142 
10143 
10144     QString cuser;
10145 #ifdef Q_WS_HILDON
10146     cuser="user";
10147 #elif defined (Q_OS_WIN)
10148     cuser=wapiGetUserName();
10149 #else
10150     for ( int i=0; i<env.size(); ++i )
10151     {
10152         QStringList ls=env[i].split ( "=" );
10153         if ( ls[0]=="USER" )
10154 
10155         {
10156             cuser=ls[1];
10157             break;
10158         }
10159     }
10160 #endif
10161     QString cmd;
10162     QString dirs=dir->dirList;
10163 
10164     if ( !fsInTun && clientSshPort!="22" )
10165     {
10166         dirs=dirs+"__SSH_PORT__"+clientSshPort;
10167     }
10168     if ( fsInTun )
10169     {
10170         dirs=dirs+"__REVERSESSH_PORT__"+resumingSession.fsPort;
10171     }
10172     if ( !rem )
10173         cmd = "x2gomountdirs dir " + sessionId + " \"" + cuser +
10174               "\" " + dir->dstKey + " " + dirs;
10175     else
10176         cmd = "x2gomountdirs rem " + sessionId + " \"" + cuser +
10177               "\" " + dir->dstKey + " " + dirs;
10178 
10179 #ifdef Q_OS_WIN
10180 
10181     cmd="chmod 600 "+dir->dstKey+"&&"+cmd;
10182 #endif
10183 
10184 
10185 
10186     X2goSettings st ( "sessions" );
10187 
10188     if ( !useLdap )
10189     {
10190         QString sid;
10191         if ( !embedMode ) {
10192             if (!(sessionExplorer->getLastSession())) {
10193                 x2goDebug << "No session selected, not calling startx2gomount command.";
10194                 return;
10195             }
10196 
10197             sid=sessionExplorer->getLastSession()->id();
10198         }
10199         else
10200             sid="embedded";
10201         if ( st.setting()->value (
10202                     sid+"/useiconv", ( QVariant ) false ).toBool() )
10203         {
10204             QString toCode=st.setting()->value (
10205                                sid+"/iconvto",
10206                                ( QVariant ) "UTF-8" ).toString();
10207 
10208 #ifdef Q_OS_WIN
10209             QString fromCode=st.setting()->value (
10210                                  sid+"/iconvfrom",
10211                                  ( QVariant ) tr (
10212                                      "WINDOWS-1252" ) ).toString();
10213 #endif
10214 #ifdef Q_OS_DARWIN
10215             QString fromCode=st.setting()->value (
10216                                  sid+"/iconvfrom",
10217                                  ( QVariant )
10218                                  "UTF-8" ).toString();
10219 #endif
10220 #ifdef Q_OS_UNIX
10221             QString fromCode=st.setting()->value (
10222                                  sid+"/iconvfrom",
10223                                  ( QVariant ) tr (
10224                                      "ISO8859-1" ) ).toString();
10225 #endif
10226             cmd="export X2GO_ICONV=modules=iconv,from_code="+
10227                 fromCode+
10228                 ",to_code="+toCode+"&&"+cmd;
10229         }
10230     }
10231 
10232     x2goDebug<<"Calling startX2goMount command."<<endl;
10233     dir->pid=sshConnection->executeCommand(cmd,this,SLOT ( slotRetExportDir ( bool,
10234                                            QString,int) ));
10235 }
10236 
slotCheckPrintSpool()10237 void ONMainWindow::slotCheckPrintSpool()
10238 {
10239     QDir dir ( spoolDir );
10240     QStringList list = dir.entryList ( QDir::Files );
10241     for ( int i=0; i<list.size(); ++i )
10242     {
10243         if ( !list[i].endsWith ( ".ready" ) )
10244             continue;
10245         QFile file ( spoolDir+"/"+list[i] );
10246         if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
10247             continue;
10248         bool startProc=false;
10249         QString fname,title;
10250         if ( !file.atEnd() )
10251         {
10252             QByteArray line = file.readLine();
10253             QString fn ( line );
10254             fn.replace ( "\n","" );
10255             fname=fn;
10256             if ( !file.atEnd() )
10257             {
10258                 line = file.readLine();
10259                 title=line;
10260                 title.replace ( "\n","" );
10261             }
10262             startProc=true;
10263         }
10264         file.close();
10265         file.remove();
10266         if ( startProc )
10267             new PrintProcess ( spoolDir+"/"+fname,title ,this );
10268 
10269     }
10270 }
10271 
10272 
cleanPrintSpool()10273 void ONMainWindow::cleanPrintSpool()
10274 {
10275     QDir dir ( spoolDir );
10276     QStringList list = dir.entryList ( QDir::Files );
10277     for ( int i=0; i<list.size(); ++i )
10278     {
10279         QFile::remove ( spoolDir+"/"+list[i] );
10280     }
10281 }
10282 
10283 
cleanAskPass()10284 void ONMainWindow::cleanAskPass()
10285 {
10286     QString path=homeDir +"/.x2go/ssh/";
10287     QDir dir ( path );
10288     QStringList list = dir.entryList ( QDir::Files );
10289     for ( int i=0; i<list.size(); ++i )
10290     {
10291         if ( list[i].startsWith ( "askpass" ) )
10292             QFile::remove ( path+list[i] );
10293     }
10294 
10295 }
10296 
10297 
10298 #ifdef Q_OS_WIN
10299 #include <windows.h>
10300 #include <winsock2.h>
10301 #include <ws2tcpip.h>
10302 #endif
10303 
10304 
isServerRunning(int port)10305 bool ONMainWindow::isServerRunning ( int port )
10306 {
10307 #ifdef Q_OS_WIN
10308     SOCKET ConnectSocket = INVALID_SOCKET;
10309     struct sockaddr_in saServer;
10310     hostent* localHost;
10311     char* localIP;
10312     int iResult;
10313     WSADATA wsaData;
10314 
10315     struct in_addr addr = {{ }};
10316 
10317     iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
10318     if (iResult != 0)
10319     {
10320 
10321         x2goDebug<<"WARNING: WSAStartup failed: "<< iResult;
10322 
10323         return false;
10324     }
10325 
10326     addr.s_addr = inet_addr("127.0.0.1");
10327     if (addr.s_addr == INADDR_NONE)
10328     {
10329 
10330         x2goDebug<< "WARNING: The IPv4 address entered was invalid.\n";
10331 
10332         return false;
10333     }
10334 
10335 
10336     localHost = gethostbyaddr((char*)&addr,4, AF_INET);
10337     if (!localHost)
10338     {
10339 
10340         x2goDebug<<"WARNING: gethostbyaddr failed: "<<WSAGetLastError();
10341 
10342         return false;
10343     }
10344     x2goDebug<<"Resolved localhost.";
10345 
10346 
10347     localIP = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list);
10348 
10349     saServer.sin_family = AF_INET;
10350     saServer.sin_addr.s_addr = inet_addr(localIP);
10351     saServer.sin_port = htons(port);
10352 
10353     ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
10354     if (ConnectSocket == INVALID_SOCKET)
10355     {
10356         x2goDebug<<"WARNING: Socket failed with error: "<< WSAGetLastError();
10357 
10358         return false;
10359     }
10360 
10361     iResult = ::connect( ConnectSocket, (SOCKADDR*) &saServer, sizeof(saServer));
10362     if (iResult == SOCKET_ERROR)
10363     {
10364         closesocket(ConnectSocket);
10365 
10366         x2goDebug<<"Port is free: "<<port;
10367 
10368         return false;
10369     }
10370     closesocket(ConnectSocket);
10371 
10372     x2goDebug<<"Port already in use: "<<port;
10373 
10374     return true;
10375 #endif
10376     QTcpSocket tcpSocket ( 0 );
10377     tcpSocket.connectToHost ( "127.0.0.1",port );
10378 
10379     if ( tcpSocket.waitForConnected ( 1000 ) )
10380     {
10381         tcpSocket.close();
10382         return true;
10383     }
10384     return false;
10385 }
10386 #ifdef Q_OS_WIN
slotCheckXOrgLog()10387 void ONMainWindow::slotCheckXOrgLog()
10388 {
10389     xorgLogMutex.lock();
10390     if ( xorgLogFile.length() <=0 )
10391     {
10392         xorgLogMutex.unlock();
10393         return;
10394     }
10395     QFile file ( xorgLogFile );
10396     if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) )
10397     {
10398         xorgLogMutex.unlock();
10399         return;
10400     }
10401 
10402     QTextStream in ( &file );
10403     while ( !in.atEnd() )
10404     {
10405         QString line = in.readLine();
10406         if ( line.indexOf ( "successfully opened the display" ) !=-1 )
10407         {
10408             xorgLogTimer->stop();
10409             slotSetWinServersReady();
10410             xorgLogMutex.unlock();
10411             return;
10412         }
10413     }
10414     xorgLogMutex.unlock();
10415 }
10416 
startXOrg(std::size_t start_offset)10417 void ONMainWindow::startXOrg (std::size_t start_offset)
10418 {
10419     xDisplay += start_offset;
10420 
10421     while ( isServerRunning ( 6000+xDisplay ) )
10422         ++xDisplay;
10423     QString dispString;
10424     QTextStream ( &dispString ) <<":"<<xDisplay;
10425 
10426     QStringList args;
10427     QString exec;
10428     if (internalX==XMING)
10429         exec=appDir+"\\xming\\Xming.exe";
10430     if (internalX==VCXSRV)
10431         exec=appDir+"\\vcxsrv\\vcxsrv.exe";
10432     winServersReady=false;
10433 
10434     x2goDebug<<"Using internal X.Org Server: "<<useInternalX;
10435 
10436 //#ifdef CFGCLIENT
10437     if (!useInternalX || internalX!=XMING)
10438     {
10439         if (!useInternalX)
10440             exec=xorgExe;
10441         QString cmdLine;
10442         if (startXorgOnStart)
10443             cmdLine=xorgOptions;
10444         else
10445         {
10446             switch (xorgMode)
10447             {
10448             case FS:
10449                 cmdLine=xorgFSOptions;
10450                 break;
10451             case SAPP:
10452                 cmdLine=xorgSAppOptions;
10453                 break;
10454             case WIN:
10455                 cmdLine=xorgWinOptions;
10456 
10457                 x2goDebug<<"WxH:"<<xorgWidth<<"x"<<xorgHeight;
10458 
10459                 cmdLine.replace("%w",xorgWidth);
10460                 cmdLine.replace("%h",xorgHeight);
10461 
10462                 x2goDebug<<cmdLine;
10463                 break;
10464             case MULTIDISPLAY:
10465                 cmdLine=xorgMDOptions+QString::number(localDisplayNumber);
10466                 break;
10467             }
10468         }
10469         QStringList options=cmdLine.split(" ",QString::SkipEmptyParts);
10470         QString option;
10471         foreach(option,options)
10472         {
10473             args<< option;
10474         }
10475 
10476         if (useInternalX) {
10477             /*
10478              * -nopn lets the server terminate if it couldn't bind on all interfaces.
10479              * Only VcXsrv supports this option, though, and we don't want have external
10480              * X servers fail to start due to unknown options, so only add the option
10481              * if using the internal X server and the internal copy is VcXsrv-based.
10482              */
10483             args << "-nopn";
10484 
10485             /*
10486              * -silent-dup-error makes VcXsrv and Cygwin/X error out silently if either:
10487              *   - the global(!) MUTEX for the X display number is already taken by another
10488              *     process
10489              *   - binding to the socket (mostly TCP, though maybe increasingly UNIX since
10490              *     newer Windows version [10 with the April 2018 update] started supporting
10491              *     this natively) failed.
10492              *
10493              * The latter also triggers if some other process is listening on the selected
10494              * end point, which also covers other applications.
10495              *
10496              * The key part here is "silently": without this option, the process keeps
10497              * running - showing a dialog to the user. For X2Go Client, it looks as though
10498              * the server was started successfully and if connecting to the socket end
10499              * point also worked out, we get a false-positive in X.Org Server startup
10500              * detection.
10501              *
10502              * With this option, no dialog pops up and the X.Org Server terminates
10503              * immediately.
10504              *
10505              * FIXME: we currently only use this option when the internal X.Org Server
10506              * option is used (the default) and the variant is VcXsrv. Given that Cygwin/X
10507              * also supports the option, it would be nice to use it for external X.Org
10508              * Server settings as well - but we don't know their type.
10509              */
10510             args << "-silent-dup-error";
10511         }
10512 
10513         args<<dispString;
10514     }
10515 //#endif
10516     xorg=new QProcess ( 0 );
10517     if (useInternalX && (internalX==XMING))
10518     {
10519 
10520         QString workingDir=appDir+"\\xming";
10521         QStringList env=QProcess::systemEnvironment();
10522         env<<"GLWIN_ENABLE_DEBUG=0";
10523         xorgLogMutex.lock();
10524         xorgLogFile=homeDir+"/.x2go/xorg";
10525         QDir dr ( homeDir );
10526         dr.mkpath ( xorgLogFile );
10527         xorgLogFile=wapiShortFileName ( xorgLogFile ) +"\\xorg.log."+
10528                     QString::number ( xDisplay );
10529         if ( QFile::exists ( xorgLogFile ) )
10530             QFile::remove ( xorgLogFile );
10531         xorgLogMutex.unlock();
10532 //run xming with clipboard support
10533         args<<dispString<<"-multiwindow"<<"-notrayicon"<<"-clipboard"<<
10534             "-logfile"<<xorgLogFile;
10535         xorg->setEnvironment ( env );
10536         xorg-> setWorkingDirectory ( workingDir);
10537     }
10538 
10539 
10540     x2goDebug<<"Running "<<exec<<" "<<args.join(" ");
10541     x2goDebug << "Trying to start X.Org Server on DISPLAY: " << xDisplay;
10542 
10543     xorg->start ( exec, args );
10544 
10545 
10546     if ( !xorg->waitForStarted ( 3000 ) )
10547     {
10548         QMessageBox::critical (
10549             0,QString::null,
10550             tr ( "Can't start X.Org Server." )
10551             + "\n"
10552             + tr ( "Please check your installation." ) );
10553         close();
10554     }
10555 // #ifdef CFGCLIENT
10556     if ( !useInternalX || internalX!= XMING)
10557     {
10558         //check connection in slot and launch setWinServerReady
10559         waitingForX=0;
10560         x_start_tries_ += 1;
10561 
10562         QTimer::singleShot(1000, this, SLOT(slotCheckXOrgConnection()));
10563     }
10564 // #endif
10565 }
10566 
slotCheckXOrgConnection()10567 void ONMainWindow::slotCheckXOrgConnection()
10568 {
10569     ++waitingForX;
10570 
10571     /* Before we try to connect to the socket, let's check if the server actually is still running. */
10572     if (xorg->state () != QProcess::Running) {
10573         /*
10574          * Process died (crashed, terminated, whatever). We need to restart it, unless we already tried
10575          * to do so multiple times unsuccessfully.
10576          */
10577         if ((x_start_limit_) && (x_start_limit_ < x_start_tries_)) {
10578             x2goDebug << "Unable to start X.Org Server for " << x_start_limit_ << " times, terminating.";
10579 
10580             QMessageBox::critical (NULL, QString::null,
10581                                    tr ("X.Org Server did not launch correctly after %n tries.", "%n will be substituted with the current number of tries", x_start_tries_)
10582                                    + "\n"
10583                                    + tr ("Please check your installation."));
10584 
10585             close ();
10586 
10587             return;
10588         }
10589 
10590         x2goDebug << "Trying to re-start X.Org Server. Try count: " << x_start_tries_;
10591 
10592         delete xorg;
10593         xorg = NULL;
10594 
10595         startXOrg (1);
10596 
10597         return;
10598     }
10599 
10600     if (isServerRunning(6000+xDisplay))
10601     {
10602         x2goDebug<<"X.Org Server started on DISPLAY " << xDisplay << ".";
10603 
10604         slotSetWinServersReady();
10605     }
10606     else
10607     {
10608         if (waitingForX > 10)
10609         {
10610             /*
10611              * Timeout reached. If we tried starting the X.Org Server less times than the limit,
10612              * continue doing so (with a higher DISPLAY value).
10613              * Otherwise error out.
10614              */
10615             if ((!(x_start_limit_)) || (x_start_limit_ >= x_start_tries_)) {
10616                 /*
10617                  * Server might still be running here, but deleting the QProcess object
10618                  * should kill it.
10619                  */
10620                 x2goDebug << "Timeout reached waiting for the X.Org Server to open a listening TCP socket." << endl
10621                           << "Restarting on higher DISPLAY port. Try count: " << x_start_tries_;
10622 
10623                 xorg->terminate ();
10624                 delete xorg;
10625                 xorg = NULL;
10626 
10627                 startXOrg (1);
10628 
10629                 return;
10630             }
10631             else {
10632                 QMessageBox::critical (NULL, QString::null,
10633                                        tr ("Can't start X.Org Server.")
10634                                        + "\n"
10635                                        + tr ("Please check your installation."));
10636                 close();
10637 
10638                 return;
10639             }
10640         }
10641         else
10642         {
10643 
10644             x2goDebug<<"Waiting for X.Org Server to start.";
10645 
10646             QTimer::singleShot(1000, this, SLOT(slotCheckXOrgConnection()));
10647         }
10648     }
10649 }
10650 
WinServerStarter(daemon server,ONMainWindow * par)10651 WinServerStarter::WinServerStarter ( daemon server, ONMainWindow * par ) :
10652     QThread ( 0 ), mode (server), parent (par), ssh_key_type_ (ONMainWindow::RSA_KEY_TYPE)
10653 {
10654 }
10655 
run()10656 void WinServerStarter::run()
10657 {
10658     switch ( mode )
10659     {
10660     case SSH:
10661         parent->startSshd(ssh_key_type_);
10662         break;
10663     case X:
10664         parent->startXOrg();
10665         break;
10666     }
10667 }
10668 
set_ssh_key_type(ONMainWindow::key_types key_type)10669 void WinServerStarter::set_ssh_key_type (ONMainWindow::key_types key_type) {
10670   ssh_key_type_ = key_type;
10671 }
10672 
get_ssh_key_type()10673 ONMainWindow::key_types WinServerStarter::get_ssh_key_type () {
10674   return (ssh_key_type_);
10675 }
10676 
10677 
startWinServers(ONMainWindow::key_types key_type)10678 void ONMainWindow::startWinServers(ONMainWindow::key_types key_type)
10679 {
10680     key_type = check_key_type (key_type);
10681 
10682     x2goDebug<<"Starting helper servers for Windows ...";
10683 
10684     QString etcDir=homeDir+"/.x2go/etc";
10685     QDir dr ( homeDir );
10686 
10687     WinServerStarter* xStarter = new WinServerStarter ( WinServerStarter::X,
10688             this );
10689     WinServerStarter* sshStarter = new WinServerStarter (
10690         WinServerStarter::SSH, this );
10691 
10692     if ( !embedMode || !config.confFS || ( config.confFS && config.useFs ) )
10693     {
10694 
10695         dr.mkpath ( etcDir );
10696         UNUSED (generateKey (key_type, true));
10697         sshStarter->set_ssh_key_type (key_type);
10698         sshStarter->start();
10699     }
10700 
10701 // #ifdef CFGCLIENT
10702 
10703     //x2goDebug<<"Xorg settings: "<< startXorgOnStart <<" useXming: "<< useXming;
10704 
10705     if ( useInternalX && (internalX== XMING))
10706     {
10707 // #endif
10708         xStarter->start();
10709         xorgLogTimer=new QTimer ( this );
10710         connect ( xorgLogTimer,SIGNAL ( timeout() ),this,
10711                   SLOT ( slotCheckXOrgLog() ) );
10712         xorgLogTimer->start ( 500 );
10713 // #ifdef CFGCLIENT
10714     }
10715     else
10716     {
10717         if (startXorgOnStart)
10718         {
10719             startXOrg();
10720         }
10721     }
10722 // #endif
10723 }
10724 
haveCygwinEntry()10725 bool ONMainWindow::haveCygwinEntry()
10726 {
10727     QSettings CygwSt ( "HKEY_CURRENT_USER\\Software"
10728                        "\\Cygwin",
10729                        QSettings::NativeFormat );
10730     return ( CygwSt.childGroups().count() >0||CygwSt.childKeys().count() );
10731 }
10732 
10733 
10734 
saveCygnusSettings()10735 void ONMainWindow::saveCygnusSettings()
10736 {
10737     if ( ONMainWindow::portable )
10738     {
10739         if ( haveCygwinEntry() )
10740         {
10741             x2goDebug<<"Cygnus Solutions entry exists.";
10742             cyEntry=true;
10743         }
10744         else
10745         {
10746             x2goDebug<<"Cygnus Solutions entry does not exist.";
10747             cyEntry=false;
10748         }
10749     }
10750 }
10751 
restoreCygnusSettings()10752 void ONMainWindow::restoreCygnusSettings()
10753 {
10754     if ( ONMainWindow::portable )
10755     {
10756         if ( !cyEntry )
10757         {
10758             removeCygwinEntry();
10759         }
10760     }
10761 }
10762 
removeCygwinEntry()10763 void ONMainWindow::removeCygwinEntry()
10764 {
10765     QSettings st ( "HKEY_CURRENT_USER\\Software"
10766                    "\\Cygwin",
10767                    QSettings::NativeFormat );
10768     x2goDebug<<"Removing cygwin entry from registry.";
10769     st.remove ( "" );
10770     st.sync();
10771 
10772 }
10773 
10774 
10775 // #ifdef CFGCLIENT
xorgSettings()10776 void ONMainWindow::xorgSettings()
10777 {
10778 
10779     x2goDebug<<"Getting X.Org Server settings.";
10780 
10781 
10782     X2goSettings st ( "settings" );
10783 
10784     useInternalX=(st.setting()->value("useintx",true).toBool());
10785 
10786     xorgExe=(st.setting()->value("xexec","C:\\program files\\vcxsrv\\vcxsrv.exe").toString());
10787     xorgOptions=(st.setting()->value("options","-multiwindow -notrayicon -clipboard").toString());
10788     startXorgOnStart=(st.setting()->value("onstart",true).toBool());
10789     xorgWinOptions=(st.setting()->value("optionswin","-screen 0 %wx%h -notrayicon -clipboard").toString());
10790     xorgFSOptions=(st.setting()->value("optionsfs","-fullscreen -notrayicon -clipboard").toString());
10791     xorgSAppOptions=(st.setting()->value("optionssingle","-multiwindow -notrayicon -clipboard").toString());
10792     xorgMDOptions=(st.setting()->value("optionswholedisplay","-nodecoration -notrayicon -clipboard -screen 0 @").toString());
10793 
10794 
10795     if (QFile::exists(appDir+"\\vcxsrv"))
10796         internalX=VCXSRV;
10797     if (QFile::exists(appDir+"\\xming"))
10798         internalX=XMING;
10799 
10800     QString primClip;
10801     if(st.setting()->value("noprimaryclip",false).toBool() && internalX==VCXSRV)
10802         primClip=" -noprimary";
10803 
10804     if (useInternalX)
10805     {
10806         startXorgOnStart=(internalX==XMING);
10807         xorgOptions="-multiwindow -notrayicon -clipboard"+primClip;
10808         if (internalX==VCXSRV)
10809         {
10810 // 	xorgWinOptions="-screen 0 %wx%h -notrayicon -clipboard";
10811             xorgWinOptions="-multiwindow -notrayicon -clipboard"+primClip;
10812             xorgFSOptions="-fullscreen -notrayicon -clipboard"+primClip;
10813             xorgSAppOptions="-multiwindow -notrayicon -clipboard"+primClip;
10814             xorgMDOptions="-nodecoration -notrayicon -clipboard"+primClip+" -screen 0 @";
10815         }
10816     }
10817 
10818 }
10819 // #endif
10820 
slotSetWinServersReady()10821 void ONMainWindow::slotSetWinServersReady()
10822 {
10823 
10824     x2goDebug<<"All helper servers for Windows are started.";
10825 
10826     winServersReady=true;
10827     restoreCygnusSettings();
10828 }
10829 
10830 #include <windows.h>
10831 #include<sstream>
10832 #endif
10833 
generateEtcFiles()10834 void ONMainWindow::generateEtcFiles()
10835 {
10836     QString etcDir=homeDir+"/.x2go/etc";
10837     QString varDir = homeDir + "/.x2go/var";
10838     QDir dr ( homeDir );
10839     dr.mkpath ( etcDir );
10840     dr.mkpath (varDir);
10841     QFile file ( etcDir +"/sshd_config" );
10842     if ( !file.open ( QIODevice::WriteOnly | QIODevice::Text ) )
10843         return;
10844     QString authKeyPath = homeDir + "/.x2go/.ssh/authorized_keys";
10845 #ifdef Q_OS_WIN
10846     authKeyPath = cygwinPath (authKeyPath);
10847     authKeyPath.replace (wapiGetUserName (), "%u");
10848     varDir = cygwinPath (varDir);
10849     x2goDebug << varDir << " cygwin var path";
10850 #endif /* defined (Q_OS_WIN) */
10851     QTextStream out ( &file );
10852     out<<"StrictModes no\n"<<
10853 #ifdef Q_OS_WIN
10854          "StrictKeyModes no\n" <<
10855 #endif
10856          "UsePrivilegeSeparation no\n"<<
10857          "PidFile \"" + varDir + "/sshd.pid\"\n" <<
10858          "AuthorizedKeysFile \"" << authKeyPath << "\"\n";
10859 #ifdef Q_OS_WIN
10860     out << "Subsystem shell "<< wapiShortFileName ( appDir) +"/sh"+"\n"<<
10861            "Subsystem sftp "<< wapiShortFileName ( appDir) +"/sftp-server"+"\n";
10862 #else
10863     /*
10864      * We need to find the sftp-server binary.
10865      * This turns out to be surprisingly difficult, because there is no standard place
10866      * for this binary. Instead, every distribution installs it where they see fit.
10867      * Needless to say, we're screwed...
10868      */
10869 
10870     QString sftp_binary;
10871     QStringList common_sftp_dirs;
10872     common_sftp_dirs << "/usr/lib/openssh" /* Debian and Ubuntu */
10873                      << "/usr/libexec/openssh" /* Fedora, CentOS, hopefully also RHEL */
10874                      << "/usr/lib/ssh" /* Mageia, OpenSUSE, SLE{S,D} < 12 x86, SLE{S,D} 12, Arch */
10875                      << "/usr/lib64/ssh" /* SLE{S,D} < 12 x86_64 */
10876                      << "/usr/lib64/misc" /* Gentoo *64 with 17.1 profile - has no lib compat-symlink. */
10877                      << "/usr/lib/misc" /* Gentoo */
10878                      << "/run/current-system/sw/bin" /* NixOS */
10879                      << "/usr/libexec"; /* Slackware, OS X */
10880 
10881 #if QT_VERSION < 0x050000
10882     QProcessEnvironment tmp_env = QProcessEnvironment::systemEnvironment ();
10883     QString path_val = tmp_env.value ("PATH");
10884 
10885     path_val = add_to_path (path_val, common_sftp_dirs);
10886 
10887     /* Just in case we bundle sftp-server ourselves. */
10888     sftp_binary = find_binary (appDir, "sftp-server");
10889 
10890     if (sftp_binary.isEmpty ()) {
10891       sftp_binary = find_binary (path_val, "sftp-server");
10892     }
10893 #else /* QT_VERSION < 0x050000 */
10894     QStringList search_paths;
10895     search_paths << appDir;
10896 
10897     sftp_binary = QStandardPaths::findExecutable ("sftp-server", search_paths);
10898 
10899     if (sftp_binary.isEmpty ()) {
10900       search_paths = QStringList ();
10901 
10902       sftp_binary = QStandardPaths::findExecutable ("sftp-server", search_paths);
10903 
10904       if (sftp_binary.isEmpty ()) {
10905         search_paths = common_sftp_dirs;
10906 
10907         sftp_binary = QStandardPaths::findExecutable ("sftp-server", search_paths);
10908       }
10909     }
10910 #endif /* QT_VERSION < 0x050000 */
10911 
10912     if (sftp_binary.isEmpty ()) {
10913       x2goErrorf (31) << "Unable to find the sftp-server binary. Neither bundled, nor found in $PATH nor additional directories.";
10914       show_RichText_ErrorMsgBox (tr ("Unable to find the sftp-server binary. Neither bundled, nor found in $PATH nor additional directories."),
10915                                  tr ("If you are using a Linux-based operating system, please ask your system administrator "
10916                                      "to install the package containing the sftp-server binary. Common names are <b>openssh</b>, "
10917                                      "<b>openssh-server</b> or <b>openssh-sftp-server</b> depending upon distribution.\n\n"
10918                                      "If the sftp-server binary is installed on your system, please report a bug "
10919                                      "mentioning its path on:\n"
10920                                      "<center><a href=\"https://wiki.x2go.org/doku.php/wiki:bugs\">"
10921                                        "https://wiki.x2go.org/doku.php/wiki:bugs"
10922                                      "</a></center>\n"),
10923                                  true);
10924       abort ();
10925     }
10926 
10927     out << "Subsystem sftp " << sftp_binary << "\n";
10928 #endif
10929 
10930     /* The log file in startSshd() is specific to Windows. */
10931 #ifdef Q_OS_WIN
10932     if (debugging){
10933         out<<"LogLevel DEBUG1\n";
10934     }
10935 #endif
10936     file.close();
10937     x2goDebug<<etcDir +"/sshd_config created.";
10938 }
10939 
check_key_type(ONMainWindow::key_types key_type)10940 ONMainWindow::key_types ONMainWindow::check_key_type (ONMainWindow::key_types key_type) {
10941   ONMainWindow::key_types ret = key_type;
10942 
10943   switch (key_type) {
10944     case RSA_KEY_TYPE:
10945                            break;
10946     case DSA_KEY_TYPE:
10947                            break;
10948     case ECDSA_KEY_TYPE:
10949                            break;
10950     case ED25519_KEY_TYPE:
10951                            break;
10952     default:
10953                            ret = UNKNOWN_KEY_TYPE;
10954   }
10955 
10956   if (UNKNOWN_KEY_TYPE == ret) {
10957     QMessageBox::critical (this, tr ("SSH key type selection error"),
10958                            tr ("Unknown SSH key selected.")
10959                            + "\n"
10960                            + tr ("Terminating application."));
10961     close ();
10962   }
10963 
10964   return (ret);
10965 }
10966 
key_type_to_string(ONMainWindow::key_types key_type)10967 QString ONMainWindow::key_type_to_string (ONMainWindow::key_types key_type) {
10968   ONMainWindow::key_types sanitized_key_type = check_key_type (key_type);
10969   QString ret ("");
10970 
10971   switch (sanitized_key_type) {
10972     case RSA_KEY_TYPE:
10973                            ret = "rsa";
10974                            break;
10975     case DSA_KEY_TYPE:
10976                            ret = "dsa";
10977                            break;
10978     case ECDSA_KEY_TYPE:
10979                            ret = "ecdsa";
10980                            break;
10981     case ED25519_KEY_TYPE:
10982                            ret = "ed25519";
10983                            break;
10984     default:
10985                            ret = "unknown";
10986   }
10987 
10988   return (ret);
10989 }
10990 
default_size_for_key_type(ONMainWindow::key_types key_type)10991 std::size_t ONMainWindow::default_size_for_key_type (ONMainWindow::key_types key_type) {
10992   ONMainWindow::key_types sanitized_key_type = check_key_type (key_type);
10993   std::size_t ret = 0;
10994 
10995   switch (sanitized_key_type) {
10996     case RSA_KEY_TYPE:
10997                            ret = 4096;
10998                            break;
10999     case DSA_KEY_TYPE:
11000                            ret = 1024;
11001                            break;
11002     case ECDSA_KEY_TYPE:
11003                            ret = 384;
11004                            break;
11005     case ED25519_KEY_TYPE:
11006                            /* Fixed key length, flag will be unused. */
11007                            ret = 0;
11008                            break;
11009     default:
11010                            ret = 0;
11011   }
11012 
11013   return (ret);
11014 }
11015 
generateKey(ONMainWindow::key_types key_type,bool host_key)11016 QString ONMainWindow::generateKey (ONMainWindow::key_types key_type, bool host_key) {
11017   QString stringified_key_type (key_type_to_string (key_type));
11018   std::size_t key_bits = default_size_for_key_type (key_type);
11019 
11020   QString base_dir (homeDir);
11021   QString private_key_file ("");
11022 
11023   if (host_key) {
11024     base_dir += "/.x2go/etc/";
11025   }
11026   else {
11027     base_dir += "/.x2go/ssh/gen/";
11028   }
11029 
11030   {
11031     QDir dir (homeDir);
11032     if (!(dir.mkpath (base_dir))) {
11033       QMessageBox::critical (this, tr ("SSH key base directory creation error"),
11034                              tr ("Unable to create SSH key base directory '%1'.").arg (base_dir)
11035                              + "\n"
11036                              + tr ("Terminating application."));
11037       close ();
11038     }
11039   }
11040 
11041   private_key_file = base_dir;
11042 #ifdef Q_OS_WIN
11043   QString private_key_file_cygwin = cygwinPath (wapiShortFileName (base_dir));
11044 #endif
11045 
11046   {
11047     QString tmp_to_add ("");
11048 
11049     if (host_key) {
11050       tmp_to_add = "/ssh_host_" + stringified_key_type + "_key";
11051     }
11052     else {
11053       QTemporaryFile temp_file (base_dir + "/key");
11054       temp_file.open ();
11055 
11056       /* Extract base name. */
11057       QFileInfo tmp_file_info (temp_file.fileName ());
11058       tmp_to_add = tmp_file_info.fileName ();
11059 
11060       /* Clean up again. We don't need the temporary file anymore. */
11061       temp_file.setAutoRemove (false);
11062       temp_file.close ();
11063       temp_file.remove ();
11064     }
11065 
11066     private_key_file += tmp_to_add;
11067 #ifdef Q_OS_WIN
11068     private_key_file_cygwin += tmp_to_add;
11069 #endif
11070   }
11071 
11072   QString public_key_file (private_key_file + ".pub");
11073 
11074   if ((!(QFile::exists (private_key_file))) || (!(QFile::exists (public_key_file)))) {
11075     x2goDebug << "Generating SSH key. Type: " << stringified_key_type.toUpper ()
11076               << "; Location: "
11077               <<
11078 #ifdef Q_OS_WIN
11079                  private_key_file_cygwin
11080 #else
11081                  private_key_file
11082 #endif
11083               ;
11084 
11085     QStringList args;
11086 
11087     QString comment = "X2Go Client " + stringified_key_type.toUpper () + " ";
11088 
11089     if (host_key) {
11090       comment += "host";
11091     }
11092     else {
11093       comment += "user";
11094     }
11095 
11096     comment += " key";
11097 
11098     args << "-t"
11099          << stringified_key_type
11100          << "-b"
11101          << QString::number (key_bits)
11102          << "-N"
11103          << ""
11104          << "-C"
11105          << comment
11106          << "-f"
11107          << private_key_file;
11108 
11109     const int keygen_ret = QProcess::execute ("ssh-keygen", args);
11110 
11111     if (-2 == keygen_ret) {
11112       QMessageBox::critical (this, tr ("ssh-keygen launching error"),
11113                              tr ("Unable to start the ssh-keygen binary.")
11114                              + "\n"
11115                              + tr ("Terminating application."));
11116       close ();
11117     }
11118 
11119     if (-1 == keygen_ret) {
11120       QMessageBox::critical (this, tr ("ssh-keygen crashed"),
11121                              tr ("The ssh-keygen binary crashed.")
11122                              + "\n"
11123                              + tr ("Terminating application."));
11124       close ();
11125     }
11126 
11127     if (0 != keygen_ret) {
11128       QMessageBox::critical (this, tr ("ssh-keygen program error"),
11129                              tr ("The ssh-keygen binary did not exit cleanly.")
11130                              + " "
11131                              + tr ("It was probably called with unknown arguments.")
11132                              + "\n"
11133                              + tr ("Terminating application."));
11134       close ();
11135     }
11136   }
11137 
11138   return (private_key_file);
11139 }
11140 
createKeyBundle(key_types key_type)11141 QString ONMainWindow::createKeyBundle (key_types key_type) {
11142   /*
11143    * I spent multiple hours on trying to understand this function
11144    * and directory exporting in general, so I'd better document
11145    * this.
11146    *
11147    * This function first generates a new RSA private-public key
11148    * pair as ~/.x2go/ssh/gen/key.XXXXX{,.pub}.
11149    *
11150    * Then, the SSH daemon's public host key is read and appended
11151    * to the *private* SSH key file after a marker looking like
11152    * this: "----BEGIN RSA IDENTITY----"
11153    *
11154    * Later on, this *private* SSH key file is transferred to the
11155    * remote server, which parses it in the "x2gomountdirs" perl
11156    * script and extracts the public key (used for logging in
11157    * to the client machine) and the public *host* key, used to
11158    * circumvent the "untrusted host" message by SSH by
11159    * explicitly giving the aforementioned public *host* key as
11160    * the only element in a fake "authorized_keys" file. Again,
11161    * this is all happening server-side.
11162    *
11163    * The *public* key part generated here is then taken and
11164    * later added to the "authorized_keys" file on the client
11165    * side, to allow auto-logins via the generated and transferred
11166    * private SSH key.
11167    */
11168 
11169   QString stringified_key_type (key_type_to_string (key_type));
11170 
11171   QString user_key = generateKey (key_type);
11172 
11173   /*
11174    * Now taking the *host* pub key here...
11175    */
11176   const QString host_pub_key_file_name ("ssh_host_" + stringified_key_type + "_key.pub");
11177   QFile rsa (homeDir + "/.x2go/etc/" + host_pub_key_file_name);
11178 #ifdef Q_OS_WIN
11179   rsa.setFileName (wapiShortFileName (homeDir + "\\.x2go\\etc\\" + host_pub_key_file_name));
11180 #endif
11181 
11182   if (!(rsa.open (QIODevice::ReadOnly | QIODevice::Text))) {
11183     x2goDebug << "Unable to open public host key file.";
11184 #ifdef Q_OS_UNIX
11185     x2goDebug << "Creating a new one.";
11186     QString tmp_file_name (generateKey (key_type, true));
11187 
11188     rsa.setFileName (tmp_file_name + ".pub");
11189     if (!(rsa.open (QIODevice::ReadOnly | QIODevice::Text))) {
11190       x2goErrorf (9) << tr ("Unable to open newly generated %1 public host key file.").arg (stringified_key_type.toUpper ());
11191       return (QString::null);
11192     }
11193 #else
11194     printSshDError_noHostPubKey ();
11195     return (QString::null);
11196 #endif
11197   }
11198 
11199   if (!(startSshd (key_type))) {
11200     x2goDebug << "Failed to start OpenSSH Server pro-actively.";
11201     return (QString::null);
11202   }
11203 
11204   QByteArray rsa_pub;
11205 
11206   if (!(rsa.atEnd ())) {
11207     rsa_pub = rsa.readLine ();
11208   }
11209   else {
11210     x2goErrorf (9) << tr ("%1 public host key file empty.").arg (stringified_key_type.toUpper ());
11211     return (QString::null);
11212   }
11213 
11214   QFile file (user_key);
11215   if (!(file.open (QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))) {
11216     x2goErrorf (10) << tr ("Cannot open key: ") << user_key;
11217     return (user_key);
11218   }
11219 
11220   /* Append public host key into private user key file. */
11221   QTextStream out (&file);
11222 
11223   /*
11224    * The string here should be changed, but this requires
11225    * changes to X2Go Server as well.
11226    * As such, I'll be not changing it here for now.
11227    */
11228   out << "----BEGIN RSA IDENTITY----" << rsa_pub;
11229   file.close ();
11230   return (user_key);
11231 }
11232 
startSshd(ONMainWindow::key_types key_type)11233 bool ONMainWindow::startSshd(ONMainWindow::key_types key_type)
11234 {
11235     if ( embedMode && config.confFS && !config.useFs )
11236     {
11237         return false;
11238     }
11239 
11240     const QString stringified_key_type = key_type_to_string (key_type);
11241 
11242     /* Don't start sshd, if it's already running. */
11243 #ifdef Q_OS_WIN
11244     if (winSshdStarted)
11245 #else /* defined (Q_OS_WIN) */
11246     if (sshd)
11247 #endif /* defined (Q_OS_WIN) */
11248     {
11249         if (isServerRunning (clientSshPort.toInt ())) {
11250             return (true);
11251         }
11252     }
11253 
11254     /*
11255      * Pro-actively (re-)create sshd_config file, we'll need it for sshd
11256      * and more importantly make sure that it's up-to-date.
11257      */
11258     generateEtcFiles ();
11259 
11260     clientSshPort = "7022";
11261     QString etcDir=homeDir+"/.x2go/etc";
11262 
11263     int port=clientSshPort.toInt();
11264     //clientSshPort have initvalue
11265     while ( isServerRunning ( port ) )
11266         ++port;
11267     clientSshPort=QString::number ( port );
11268 #ifdef Q_OS_WIN
11269     std::string clientdir=wapiShortFileName ( appDir ).toStdString();
11270     std::stringstream strm;
11271     std::string config="\""+cygwinPath(etcDir+"/sshd_config").toStdString()+"\"";
11272     std::string key="\""+cygwinPath(etcDir+"/ssh_host_" + stringified_key_type + "_key").toStdString()+"\"";
11273 
11274     // generate a unique sshLog filepath, and create its directory
11275     if (debugging)
11276     {
11277         QDir* sshLogsDir= new QDir( homeDir+"/.x2go/sshLogs" );
11278         if (!sshLogsDir->exists())
11279             sshLogsDir->mkpath(".");
11280 
11281         QTemporaryFile* sshLogTemp=new QTemporaryFile ( sshLogsDir->absolutePath()+"/XXXXXX.log" );
11282         sshLogTemp->open();
11283         sshLog=sshLogTemp->fileName();
11284         sshLogTemp->close();
11285 
11286         delete sshLogsDir;
11287         delete sshLogTemp;
11288         x2goDebug<<"Logging cygwin sshd to: "<<sshLog;
11289     }
11290 
11291     strm<<clientdir<<"\\sshd.exe -D -p "<<clientSshPort.toInt()<<" -f "<< config <<" -h "<<key;
11292     if (debugging){
11293         strm<<" -E "<<"\""<<sshLog.toStdString()<<"\"";
11294     }
11295 
11296     STARTUPINFOA si;
11297     std::string desktopName="x2go_";
11298     desktopName+=getenv ( "USERNAME" );
11299     char* desktop=new char[desktopName.size() +1];
11300     strcpy ( desktop,desktopName.c_str() );
11301 
11302     x2goDebug<<"Creating desktop: "<<desktop;
11303 
11304     if ( !CreateDesktopA (
11305                 desktop,
11306                 0,
11307                 0,
11308                 0,
11309                 GENERIC_ALL,
11310                 0
11311             ) )
11312     {
11313         strcpy ( desktop,"" );
11314 
11315         x2goDebug<<"Desktop creation failed, using default.";
11316 
11317     }
11318     ZeroMemory ( &si, sizeof ( si ) );
11319     ZeroMemory ( &sshd, sizeof ( sshd ) );
11320     si.lpDesktop=desktop;
11321     si.cb = sizeof ( si );
11322     const BOOL ret = CreateProcessA ( NULL,  // No module name (use command line)
11323                                       ( LPSTR ) strm.str().c_str(),  // Command line
11324                                       NULL,           // Process handle not inheritable
11325                                       NULL,           // Thread handle not inheritable
11326                                       TRUE,          // Set handle inheritance to FALSE
11327                                       0/*CREATE_NO_WINDOW|CREATE_NEW_PROCESS_GROUP*/,
11328                                       //creation flags
11329                                       NULL,           // Use parent's environment block
11330                                       clientdir.c_str(), // Starting directory
11331                                       &si,            // Pointer to STARTUPINFO structure
11332                                       &sshd );// Pointer to PROCESS_INFORMATION structure
11333 
11334     /* Test successful SSH daemon startup for at most 5 seconds. */
11335     if (ret) {
11336         QTime sleep_time = QTime::currentTime ().addSecs (5);
11337 
11338         while (QTime::currentTime () < sleep_time) {
11339             if (isServerRunning (clientSshPort.toInt ())) {
11340                 winSshdStarted = true;
11341 
11342                 break;
11343             }
11344 
11345             QCoreApplication::processEvents (QEventLoop::AllEvents, 100);
11346         }
11347     }
11348     else {
11349         winSshdStarted = false;
11350     }
11351 
11352     delete []desktop;
11353 #else // defined (Q_OS_WIN)
11354     sshd=new QProcess ( this );
11355 
11356     QString binary ("/usr/sbin/sshd");
11357 #ifndef Q_OS_UNIX
11358     binary = appDir + "/sshd";
11359 #endif /* !(defined (Q_OS_UNIX)) */
11360 
11361     QStringList arguments;
11362     arguments<<"-f"<<etcDir +"/sshd_config"<< "-h" <<
11363              etcDir+"/ssh_host_" + stringified_key_type + "_key"<<"-D"<<"-p"<<clientSshPort;
11364 
11365     sshd->start (binary, arguments);
11366 
11367     /* Allow sshd a grace time of 5 seconds to come up. */
11368     QTime sleep_time = QTime::currentTime ().addSecs (5);
11369     while (QTime::currentTime () < sleep_time) {
11370         if (QProcess::Running == sshd->state ()) {
11371             /*
11372              * Additionally, spin up to 3 seconds to give sshd
11373              * the opportunity to launch its listening socket.
11374              */
11375             QTime new_sleep_time = QTime::currentTime ().addSecs (3);
11376 
11377             while (QTime::currentTime () < new_sleep_time) {
11378                 if (isServerRunning (clientSshPort.toInt ())) {
11379                     break;
11380                 }
11381 
11382                 QCoreApplication::processEvents (QEventLoop::AllEvents, 100);
11383             }
11384 
11385             break;
11386         }
11387 
11388         QCoreApplication::processEvents (QEventLoop::AllEvents, 100);
11389     }
11390 #endif /* defined (Q_OS_WIN) */
11391 
11392     /* Check to see if connecting to the listening socket works. */
11393     if (!isServerRunning (clientSshPort.toInt ())) {
11394         printSshDError_startupFailure ();
11395         x2goDebug << "Failed to start user mode OpenSSH server.";
11396         return (false);
11397     }
11398     else {
11399         x2goDebug << "User mode OpenSSH server started successfully.";
11400         return (true);
11401     }
11402 }
11403 
setProxyWinTitle()11404 void ONMainWindow::setProxyWinTitle()
11405 {
11406 
11407     if (embedMode)
11408         return;
11409 
11410     QString title;
11411 
11412     if (!useLdap) {
11413         if (!(sessionExplorer->getLastSession())) {
11414             x2goDebug << "No session selected, not setting proxy window title.";
11415             return;
11416         }
11417 
11418         title=sessionExplorer->getLastSession()->name();
11419     }
11420     else
11421         title=getCurrentUname()+"@"+resumingSession.server;
11422 
11423     QPixmap pixmap;
11424 
11425     if (useLdap)
11426         pixmap=lastUser->foto();
11427     else
11428         pixmap=*(sessionExplorer->getLastSession()->sessIcon());
11429 
11430 #ifdef Q_OS_UNIX
11431 
11432     XStoreName(QX11Info::display(), proxyWinId, title.toLocal8Bit().data());
11433 
11434     XWMHints* win_hints;
11435 
11436 
11437     QByteArray bytes;
11438     QBuffer buffer(&bytes);
11439     buffer.open(QIODevice::WriteOnly);
11440     pixmap.save(&buffer, "XPM");
11441 
11442 
11443     int rez;
11444 
11445     if (image)
11446         XFreePixmap(QX11Info::display(),image);
11447     if (shape)
11448         XFreePixmap(QX11Info::display(),shape);
11449 
11450 
11451     rez=XpmCreatePixmapFromBuffer(QX11Info::display(), proxyWinId, bytes.data(),
11452                                   (Pixmap *) &image, (Pixmap *) &shape, NULL);
11453     if (!rez)
11454     {
11455 
11456         win_hints = XAllocWMHints();
11457         if (win_hints)
11458         {
11459             win_hints->flags = IconPixmapHint|IconMaskHint;
11460             win_hints->icon_pixmap = image;
11461             win_hints->icon_mask = shape;
11462             XSetWMHints(QX11Info::display(), proxyWinId, win_hints);
11463             XFree(win_hints);
11464         }
11465     }
11466 
11467 #endif
11468 #ifdef Q_OS_WIN
11469     wapiSetWindowText((HWND)proxyWinId, title);
11470 //       wapiSetWindowIcon((HWND)proxyWinId, pixmap);
11471 #endif
11472 }
11473 
slotSetProxyWinFullscreen()11474 void ONMainWindow::slotSetProxyWinFullscreen()
11475 {
11476 
11477 #ifdef Q_OS_UNIX
11478 
11479     QRect geom=QApplication::desktop()->screenGeometry(localDisplayNumber-1);
11480     Atom atom = XInternAtom ( QX11Info::display(), "_NET_WM_STATE_FULLSCREEN", True );
11481     XChangeProperty (
11482         QX11Info::display(), proxyWinId,
11483         XInternAtom ( QX11Info::display(), "_NET_WM_STATE", True ),
11484         XA_ATOM,  32,  PropModeReplace,
11485         (unsigned char*) &atom,  1 );
11486 
11487     XMapWindow(QX11Info::display(), proxyWinId);
11488 
11489     XSync(QX11Info::display(),false);
11490     XEvent event;
11491     event.xclient.type = ClientMessage;
11492     event.xclient.serial = 0;
11493     event.xclient.send_event = True;
11494     event.xclient.display = QX11Info::display();
11495     event.xclient.window = proxyWinId;
11496     event.xclient.message_type = XInternAtom(QX11Info::display(),"_NET_WM_STATE",False);
11497     event.xclient.format = 32;
11498     event.xclient.data.l[0] = 1;
11499     event.xclient.data.l[1] = XInternAtom(QX11Info::display(),"_NET_WM_STATE_FULLSCREEN",False);
11500     event.xclient.data.l[2] = 0;
11501     event.xclient.data.l[3] = 1;
11502     event.xclient.data.l[4] = 0;
11503     Status st;
11504     st=XSendEvent(QX11Info::display(), DefaultRootWindow(QX11Info::display()),
11505                   False, SubstructureNotifyMask ,&event);
11506     if(!st)
11507     {
11508         x2goDebug<<"Couldn't fetch fullscreen setting.";
11509     }
11510     XSync(QX11Info::display(),false);
11511     XMapWindow(QX11Info::display(), proxyWinId);
11512 
11513     QString geoStr = QString("%1").arg(geom.width()) + "x"+ QString("%1").arg(geom.height());
11514 
11515 
11516 
11517     sshConnection->executeCommand("DISPLAY=:"+resumingSession.display+" xrandr --output default --mode "+geoStr);
11518 #endif
11519 }
11520 
11521 
resizeProxyWinOnDisplay(int disp)11522 void ONMainWindow::resizeProxyWinOnDisplay(int disp)
11523 {
11524     QRect geom=QApplication::desktop()->screenGeometry(disp-1);
11525 
11526     QString geoStr =
11527         "(x: " + QString("%1").arg(geom.x()) +
11528         ", y: "+ QString("%1").arg(geom.y()) +
11529         ", w: "+ QString("%1").arg(geom.width()) +
11530         ", h: "+ QString("%1").arg(geom.height());
11531     x2goDebug<<"Resizing proxy window to fit display: " + QString("%1").arg(disp) + " " + geoStr;
11532 
11533 #ifdef Q_OS_UNIX
11534     XSync(QX11Info::display(),false);
11535     XMoveResizeWindow(QX11Info::display(), proxyWinId, geom.x(), geom.y(), 800, 600);
11536     XMapWindow(QX11Info::display(), proxyWinId);
11537     XFlush(QX11Info::display());
11538 #endif
11539 #ifdef Q_OS_WIN
11540     dispGeometry=geom;
11541 #endif
11542     QTimer::singleShot(500, this, SLOT(slotSetProxyWinFullscreen()));
11543 }
11544 
proxyWinGeometry()11545 QRect ONMainWindow::proxyWinGeometry()
11546 {
11547 #ifdef Q_OS_WIN
11548     QRect proxyRect;
11549     if (!wapiWindowRectWithoutDecoration((HWND)proxyWinId,proxyRect))
11550         return QRect();
11551     return proxyRect;
11552 #endif
11553 #ifdef Q_OS_UNIX
11554     QRect proxyRect;
11555     Window root;
11556     int x,y;
11557     uint w,h,border,depth;
11558     if (XGetGeometry(QX11Info::display(), proxyWinId, &root,&x,&y,&w,&h,&border,&depth))
11559     {
11560 
11561         int realx,realy;
11562         Window child;
11563         XTranslateCoordinates(QX11Info::display(), proxyWinId, root, 0, 0, &realx, &realy, &child);
11564         proxyRect.setRect(realx, realy, w,h);
11565     }
11566     return proxyRect;
11567 #endif
11568     return QRect();
11569 }
11570 
slotConfigXinerama()11571 void ONMainWindow::slotConfigXinerama()
11572 {
11573     QRect newGeometry=proxyWinGeometry();
11574     if (newGeometry.isNull())
11575     {
11576         x2goWarningf(7)<< tr("Error getting window geometry. (Did you close the window?)");
11577         xineramaTimer->stop();
11578         return;
11579     }
11580     if (newGeometry==lastDisplayGeometry)
11581         return;
11582     lastDisplayGeometry=newGeometry;
11583 
11584     QString geoStr =
11585         "(x: " + QString("%1").arg(lastDisplayGeometry.x()) +
11586         ", y: "+ QString("%1").arg(lastDisplayGeometry.y()) +
11587         ", w: "+ QString("%1").arg(lastDisplayGeometry.width()) +
11588         ", h: "+ QString("%1").arg(lastDisplayGeometry.height());
11589     x2goDebug<<"New proxy geometry: " + geoStr;
11590 
11591     QDesktopWidget* root=QApplication::desktop();
11592     QList<QRect> newXineramaScreens;
11593     for (int i=0; i< root->numScreens(); ++i)
11594     {
11595         QRect intersection;
11596         if (resumingSession.fullscreen)
11597         {
11598             x2goDebug<<"correcting display geometry for full screen session";
11599             lastDisplayGeometry.setX(0);
11600             lastDisplayGeometry.setY(0);
11601             intersection=root->screenGeometry(i);
11602         }
11603         else
11604             intersection=root->screenGeometry(i).intersected(lastDisplayGeometry);
11605         if (!intersection.isNull())
11606         {
11607             //            x2goDebug<<"intersected with "<<i<<": "<<intersection<<endl;
11608             intersection.moveLeft(intersection.x()-lastDisplayGeometry.x());
11609             intersection.moveTop(intersection.y()-lastDisplayGeometry.y());
11610 
11611             //            x2goDebug<<"xinerama screen: "<<intersection<<endl;
11612             newXineramaScreens<<intersection;
11613         }
11614     }
11615     if (xineramaScreens != newXineramaScreens)
11616     {
11617         xineramaScreens=newXineramaScreens;
11618         //        x2goDebug<<"xinerama screen changed, new screens: "<<xineramaScreens<<endl;
11619 
11620         xineramaTimer->stop();
11621         QStringList screens;
11622         foreach (QRect disp, xineramaScreens)
11623             screens<<QString::number(disp.x())+" "+QString::number(disp.y())+" "+QString::number(disp.width())+
11624                    " "+QString::number(disp.height());
11625         QString cmd="export DISPLAY=:"+resumingSession.display+" ;printf %b '\\''"+screens.join("\\n")+"'\\'' >  $HOME/.x2go/C-"+
11626                     resumingSession.sessionId+"/xinerama.conf";
11627 
11628         sshConnection->executeCommand(cmd, this, SLOT(slotXineramaConfigured()));
11629     }
11630 }
11631 
slotXineramaConfigured()11632 void ONMainWindow::slotXineramaConfigured()
11633 {
11634     if (resumingSession.fullscreen)
11635         return;
11636     if (xinSizeInc == -1)
11637         xinSizeInc=1;
11638     else
11639         xinSizeInc=-1;
11640 #ifdef Q_OS_UNIX
11641     lastDisplayGeometry.setWidth(lastDisplayGeometry.width()+xinSizeInc);
11642     XSync(QX11Info::display(),false);
11643     XResizeWindow(QX11Info::display(), proxyWinId,
11644                   lastDisplayGeometry.width(),lastDisplayGeometry.height());
11645     XSync(QX11Info::display(),false);
11646 #endif
11647 #ifdef Q_OS_WIN
11648     QRect geom;
11649     wapiWindowRect ( (HWND) proxyWinId, geom );
11650     wapiMoveWindow( (HWND) proxyWinId, geom.x(), geom.y(), geom.width()+xinSizeInc, geom.height(),true);
11651     lastDisplayGeometry=proxyWinGeometry();
11652 #endif
11653     xineramaTimer->start(500);
11654 }
11655 
slotFindProxyWin()11656 void ONMainWindow::slotFindProxyWin()
11657 {
11658 #ifndef Q_OS_DARWIN
11659     x2goDebug<<"Searching proxy window: X2GO-" + resumingSession.sessionId;
11660 
11661     proxyWinId=findWindow ( "X2GO-"+resumingSession.sessionId );
11662     bool xinerama=defaultXinerama;
11663     if ( proxyWinId )
11664     {
11665         x2goDebug<<"Proxy window found: " + QString("%1").arg(proxyWinId);
11666 
11667         setProxyWinTitle();
11668         proxyWinTimer->stop();
11669         if (!embedMode && !(resumingSession.sessionType==x2goSession::KDRIVE))
11670         {
11671             if (!useLdap)
11672             {
11673                 X2goSettings *st;
11674                 QString sid;
11675                 if ( !embedMode ) {
11676                     if (!(sessionExplorer->getLastSession())) {
11677                         x2goDebug << "No session selected, not searching for proxy window.";
11678                         return;
11679                     }
11680 
11681                     sid=sessionExplorer->getLastSession()->id();
11682                 }
11683                 else
11684                     sid="embedded";
11685 
11686                 if (brokerMode)
11687                     st=new X2goSettings(config.iniFile,QSettings::IniFormat);
11688                 else
11689                     st= new X2goSettings( "sessions" );
11690                 xinerama=st->setting()->value ( sid+"/xinerama",
11691                                                 ( QVariant ) defaultXinerama ).toBool();
11692 #ifndef Q_OS_WIN
11693                 uint displays=QApplication::desktop()->numScreens();
11694                 if (st->setting()->value ( sid+"/multidisp",
11695                                            ( QVariant ) false ).toBool())
11696                 {
11697                     uint disp=st->setting()->value ( sid+"/display",
11698                                                      ( QVariant ) 1 ).toUInt();
11699                     delete st;
11700                     if (disp>displays)
11701                     {
11702                         disp=1;
11703                     }
11704                     localDisplayNumber=disp;
11705                     resizeProxyWinOnDisplay(disp);
11706                     return;
11707                 }
11708 #endif
11709                 delete st;
11710             }
11711             if (xinerama)
11712             {
11713                 x2goDebug<<"Starting Xinerama timer.";
11714 
11715                 lastDisplayGeometry=QRect();
11716                 xineramaScreens.clear();
11717                 xineramaTimer->start(500);
11718             }
11719         }
11720 
11721         if ( embedMode )
11722         {
11723             x2goDebug<<"Checking rootless config.";
11724 
11725             if ( config.rootless )
11726             {
11727                 x2goDebug<<"Window is rootless.";
11728                 act_embedContol->setEnabled ( false );
11729             }
11730             else
11731                 slotAttachProxyWindow();
11732         }
11733 
11734 #ifdef Q_OS_WIN
11735         x2goDebug<<"Maximize proxy window: "<<maximizeProxyWin;
11736 
11737         if ( !startEmbedded &&!(resumingSession.sessionType==x2goSession::KDRIVE))
11738         {
11739             if ( maximizeProxyWin )
11740             {
11741                 QDesktopWidget dw;
11742 
11743                 x2goDebug<<"Putting proxy window into fullscreen.";
11744                 wapiSetFSWindow ( ( HWND ) proxyWinId,
11745                                   dw.screenGeometry ( this ) );
11746                 /*wapiShowWindow ( ( HWND ) proxyWinId,
11747                    WAPI_SHOWMAXIMIZED );*/
11748             }
11749             else
11750             {
11751                 wapiMoveWindow ( ( HWND ) proxyWinId,0,0,
11752                                  proxyWinWidth,
11753                                  proxyWinHeight,true );
11754             }
11755         }
11756 #endif
11757     }
11758 #endif
11759 }
11760 
11761 
getCurrentUname()11762 QString ONMainWindow::getCurrentUname()
11763 {
11764     return login->text();
11765 }
11766 
getCurrentPass()11767 QString ONMainWindow::getCurrentPass()
11768 {
11769     return pass->text();
11770 }
11771 
slotDetachProxyWindow()11772 void ONMainWindow::slotDetachProxyWindow()
11773 {
11774     proxyWinEmbedded=false;
11775     bgFrame->show();
11776     setStatStatus();
11777     act_embedContol->setText ( tr ( "Attach X2Go window" ) );
11778     act_embedContol->setIcon ( QIcon ( ":/img/icons/32x32/attach.png" ) );
11779 #ifdef Q_OS_UNIX
11780     //if QX11EmbedContainer cannot embed window, check if window exists
11781     //and reconnect
11782     if ( !embedControlChanged )
11783     {
11784         slotFindProxyWin();
11785         x2goDebug<<"Proxy window detached, proxywin is: "<<proxyWinId;
11786     }
11787 #endif
11788     embedControlChanged=false;
11789 }
11790 
11791 
slotAttachProxyWindow()11792 void ONMainWindow::slotAttachProxyWindow()
11793 {
11794     x2goDebug<<"slotAttachProxyWindow.";
11795 
11796     if ( startEmbedded )
11797     {
11798         embedControlChanged=false;
11799         bgFrame->hide();
11800         proxyWinEmbedded=true;
11801         setStatStatus();
11802         act_embedContol->setText ( tr ( "Detach X2Go window" ) );
11803         act_embedContol->setIcon (
11804             QIcon ( ":/img/icons/32x32/detach.png" ) );
11805         QTimer::singleShot ( 100, this, SLOT ( slotEmbedWindow() ) );
11806     }
11807     else
11808     {
11809 
11810         x2goDebug<<"Start embedded was false.";
11811 
11812         startEmbedded=true;
11813     }
11814 
11815 }
11816 
slotEmbedWindow()11817 void ONMainWindow::slotEmbedWindow()
11818 {
11819 #ifndef Q_OS_DARWIN
11820     QTimer::singleShot ( 1000, this,
11821                          SLOT ( slotActivateWindow() ) );
11822 
11823 #endif
11824 }
11825 
setEmbedSessionActionsEnabled(bool enable)11826 void ONMainWindow::setEmbedSessionActionsEnabled ( bool enable )
11827 {
11828     act_shareFolder->setEnabled ( enable );
11829     if(!enable)
11830         act_showApps->setVisible(enable);
11831     act_suspend->setEnabled ( enable );
11832     act_terminate->setEnabled ( enable );
11833     act_embedContol->setEnabled ( enable );
11834     act_reconnect->setEnabled ( !enable );
11835 }
11836 
slotEmbedControlAction()11837 void ONMainWindow::slotEmbedControlAction()
11838 {
11839 #ifndef Q_OS_DARWIN
11840     embedControlChanged=true;
11841     if ( !proxyWinEmbedded )
11842     {
11843         slotAttachProxyWindow();
11844     }
11845 #endif
11846 }
11847 
slotEmbedIntoParentWindow()11848 void ONMainWindow::slotEmbedIntoParentWindow()
11849 {
11850 #ifndef Q_OS_DARWIN
11851 // 	embedInto ( embedParent );
11852 #endif
11853 }
11854 
11855 
processSessionConfig()11856 void ONMainWindow::processSessionConfig()
11857 {
11858     bool haveKey=false;
11859     UNUSED (haveKey);
11860 
11861     config.command="KDE";
11862     config.brokerNoAuth=false;
11863     config.sshport="22";
11864     config.session=tr ( "X2Go Session" );
11865     config.checkexitstatus=true;
11866     config.showtermbutton=true;
11867     config.showexpbutton=true;
11868     config.showconfig=true;
11869     config.showextconfig=true;
11870     config.showtoolbar=true;
11871     config.showstatusbar=true;
11872     config.kbdType=getDefaultKbdType();
11873     config.kbdLay=getDefaultLayout()[0];
11874 
11875 
11876     config.confSnd=false;
11877     config.confFS=false;
11878     config.confConSpd=false;
11879     config.confCompMet=false;
11880     config.confImageQ=false;
11881     config.confDPI=false;
11882     config.confKbd=false;
11883 
11884     QStringList lines=m_x2goconfig.split ( "\n" );
11885 
11886 
11887     for ( int i=0; i<lines.count(); ++i )
11888     {
11889         QString line = lines[i];
11890 
11891         // strip left/right whitespaces, important for plugin settings via x2goconfig
11892         line.remove(QRegExp("^\\s+"));
11893         line.remove(QRegExp("\\s+$"));
11894 
11895         if ( ( line=="-----BEGIN DSA PRIVATE KEY-----" ) ||
11896                 ( line=="-----BEGIN RSA PRIVATE KEY-----" ) )
11897         {
11898             while ( i<lines.count() )
11899                 config.key+=lines[i++] +"\n";
11900             haveKey=true;
11901         }
11902         else
11903             processCfgLine ( line );
11904     }
11905     act_terminate->setVisible ( config.showtermbutton );
11906     act_shareFolder->setVisible ( config.showexpbutton );
11907     act_set->setVisible ( config.showconfig );
11908     if (!config.showstatusbar)
11909     {
11910         statusBar()->hide();
11911     }
11912     if ( managedMode )
11913     {
11914         QTimer::singleShot ( 500, this, SLOT ( slotStartBroker() ) );
11915         return;
11916     }
11917     slotSelectedFromList ( ( SessionButton* ) 0 );
11918 }
11919 
11920 
processCfgLine(QString line)11921 void ONMainWindow::processCfgLine ( QString line )
11922 {
11923     QStringList lst=line.split ( "=" );
11924     if ( lst[0]=="command" )
11925     {
11926         config.command=lst[1];
11927         if ( config.command=="SHADOW" )
11928         {
11929             shadowSession=true;
11930             runRemoteCommand=false;
11931         }
11932 
11933         return;
11934     }
11935     if ( lst[0]=="server" )
11936     {
11937         config.server=lst[1];
11938         return;
11939     }
11940     if ( lst[0]=="session" )
11941     {
11942         config.session=lst[1];
11943         return;
11944     }
11945     if ( lst[0]=="sshport" )
11946     {
11947         config.sshport=lst[1];
11948         return;
11949     }
11950     if ( lst[0]=="user" )
11951     {
11952         config.user=lst[1];
11953         return;
11954     }
11955     if ( lst[0]=="rootless" )
11956     {
11957         if ( lst[1]=="true" )
11958             config.rootless=true;
11959         else
11960             config.rootless=false;
11961         return;
11962     }
11963     if ( lst[0]=="published" )
11964     {
11965         if ( lst[1]=="true" )
11966             config.published=true;
11967         else
11968             config.published=false;
11969         return;
11970     }
11971     if ( lst[0]=="checkexitstatus" )
11972     {
11973         if ( lst[1]=="true" )
11974             config.checkexitstatus=true;
11975         else
11976             config.checkexitstatus=false;
11977         return;
11978     }
11979     if ( lst[0]=="showtermbutton" )
11980     {
11981         if ( lst[1]=="true" )
11982             config.showtermbutton=true;
11983         else
11984             config.showtermbutton=false;
11985         return;
11986     }
11987     if ( lst[0]=="showexpbutton" )
11988     {
11989         if ( lst[1]=="true" )
11990             config.showexpbutton=true;
11991         else
11992             config.showexpbutton=false;
11993         return;
11994     }
11995     if ( lst[0]=="showconfig" )
11996     {
11997         if ( lst[1]=="true" )
11998             config.showconfig=true;
11999         else
12000             config.showconfig=false;
12001         return;
12002     }
12003     if ( lst[0]=="showextconfig" )
12004     {
12005         if ( lst[1]=="true" )
12006             config.showextconfig=true;
12007         else
12008             config.showextconfig=false;
12009         return;
12010     }
12011     if ( lst[0]=="showstatusbar" )
12012     {
12013         if ( lst[1]=="true" )
12014             config.showstatusbar=true;
12015         else
12016             config.showstatusbar=false;
12017         return;
12018     }
12019     if ( lst[0]=="showtoolbar" )
12020     {
12021         if ( lst[1]=="true" )
12022             config.showtoolbar=true;
12023         else
12024             config.showtoolbar=false;
12025         return;
12026     }
12027 
12028     if ( lst[0]=="sound" )
12029     {
12030         config.confSnd=true;
12031         if ( lst[1]=="true" )
12032             config.useSnd=true;
12033         else
12034             config.useSnd=false;
12035         return;
12036     }
12037     if ( lst[0]=="exportfs" )
12038     {
12039         config.confFS=true;
12040         if ( lst[1]=="true" )
12041             config.useFs=true;
12042         else
12043             config.useFs=false;
12044         return;
12045     }
12046 
12047     if ( lst[0]=="speed" )
12048     {
12049         config.confConSpd=true;
12050         config.conSpeed=ADSL;
12051 
12052         if ( lst[1]=="modem" )
12053             config.conSpeed=MODEM;
12054         else if ( lst[1]=="isdn" )
12055             config.conSpeed=ISDN;
12056         else if ( lst[1]=="adsl" )
12057             config.conSpeed=ADSL;
12058         else if ( lst[1]=="wan" )
12059             config.conSpeed=WAN;
12060         else if ( lst[1]=="lan" )
12061             config.conSpeed=LAN;
12062         else
12063         {
12064             qCritical (
12065                 "%s",tr (
12066                     "Invalid value for argument \"speed\""
12067                 ).toLocal8Bit().data() );
12068         }
12069         return;
12070     }
12071     if ( lst[0]=="compression" )
12072     {
12073         config.confCompMet=true;
12074         config.compMet=lst[1];
12075         return;
12076     }
12077     if ( lst[0]=="quality" )
12078     {
12079         config.confImageQ=true;
12080         config.imageQ=lst[1].toInt();
12081         return;
12082     }
12083     if ( lst[0]=="dpi" )
12084     {
12085         config.confDPI=true;
12086         config.dpi=lst[1].toInt();
12087         return;
12088     }
12089     if ( lst[0]=="kbdlayout" )
12090     {
12091         config.confKbd=true;
12092         config.kbdLay=lst[1];
12093         return;
12094     }
12095     if ( lst[0]=="kbdtype" )
12096     {
12097         config.confKbd=true;
12098         config.kbdType=lst[1];
12099         return;
12100     }
12101     if ( lst[0]=="brokerurl" )
12102     {
12103         config.brokerurl=lst[1];
12104         managedMode=true;
12105         acceptRsa=true;
12106     }
12107     if ( lst[0]=="cookie" )
12108     {
12109         config.cookie=lst[1];
12110         return;
12111     }
12112     if ( lst[0]=="x2gosession" )
12113     {
12114         config.sessiondata=lst[1];
12115         return;
12116     }
12117     if ( lst[0]=="connectionts" )
12118     {
12119         config.connectionts=lst[1];
12120         return;
12121     }
12122     if (lst[0] == "usesshproxy")
12123     {
12124         config.useproxy = true;
12125         if (lst[1].toLower () == "true") {
12126           config.useproxy = true;
12127         }
12128         else {
12129           config.useproxy = false;
12130         }
12131         return;
12132     }
12133     if (lst[0] == "sshproxytype")
12134     {
12135         if (lst[1].toLower () == "http") {
12136             config.proxyType = SshMasterConnection::PROXYHTTP;
12137         }
12138         else {
12139             config.proxyType = SshMasterConnection::PROXYSSH;
12140         }
12141         return;
12142     }
12143     if (lst[0] == "sshproxyuser")
12144     {
12145         config.proxylogin = lst[1];
12146         return;
12147     }
12148     if (lst[0] == "sshproxyhost")
12149     {
12150         config.proxyserver = lst[1];
12151         return;
12152     }
12153     if (lst[0] == "sshproxyport")
12154     {
12155         config.proxyport = lst[1].toInt ();
12156         return;
12157     }
12158     if (lst[0] == "sshproxyautologin")
12159     {
12160         if (lst[1].toLower () == "true") {
12161             config.proxyAutologin = true;
12162         }
12163         else {
12164             config.proxyAutologin = false;
12165         }
12166         return;
12167     }
12168     if (lst[0] == "sshproxykrblogin")
12169     {
12170         if (lst[1].toLower () == "true") {
12171             config.proxyKrbLogin = true;
12172         }
12173         else {
12174             config.proxyKrbLogin = false;
12175         }
12176         return;
12177     }
12178     if (lst[0] == "sshproxykeyfile")
12179     {
12180         config.proxyKey = lst[1];
12181         return;
12182     }
12183 }
12184 
slotChangeKbdLayout(const QString & layout)12185 void ONMainWindow::slotChangeKbdLayout(const QString& layout)
12186 {
12187 #ifdef Q_OS_UNIX
12188     QStringList args;
12189     args<<"-layout"<<layout;
12190 
12191     x2goDebug<<"Running setxkbmap with params: "<<args.join(" ");
12192 
12193     QProcess::startDetached("setxkbmap",args);
12194 #else
12195     /* Silence warning. */
12196     UNUSED (layout);
12197 #endif /* defined (Q_OS_UNIX) */
12198 }
12199 
initPassDlg()12200 void ONMainWindow::initPassDlg()
12201 {
12202     passForm = new SVGFrame ( ":/img/svg/passform.svg",
12203                               false,bgFrame );
12204 #ifdef Q_OS_WIN
12205     passForm->setMainWidget ( ( QWidget* ) this );
12206 #endif
12207     username->addWidget ( passForm );
12208     passForm->hide();
12209     setWidgetStyle ( passForm );
12210     if ( !miniMode )
12211         passForm->setFixedSize ( passForm->sizeHint() );
12212     else
12213         passForm->setFixedSize ( 310,180 );
12214     QPalette pal=passForm->palette();
12215     pal.setBrush ( QPalette::Window, QColor ( 255,255,255,0 ) );
12216     pal.setColor ( QPalette::Active, QPalette::WindowText, QPalette::Mid );
12217     pal.setColor ( QPalette::Active, QPalette::ButtonText, QPalette::Mid );
12218     pal.setColor ( QPalette::Active, QPalette::Text, QPalette::Mid );
12219     pal.setColor ( QPalette::Inactive, QPalette::WindowText, QPalette::Mid );
12220     pal.setColor ( QPalette::Inactive, QPalette::ButtonText, QPalette::Mid );
12221     pal.setColor ( QPalette::Inactive, QPalette::Text, QPalette::Mid );
12222     passForm->setPalette ( pal );
12223 
12224     pal.setColor ( QPalette::Button, QColor ( 255,255,255,0 ) );
12225     pal.setColor ( QPalette::Window, QColor ( 255,255,255,255 ) );
12226     pal.setColor ( QPalette::Base, QColor ( 255,255,255,255 ) );
12227 
12228 
12229     QFont fnt=passForm->font();
12230     if ( miniMode )
12231 #ifdef Q_WS_HILDON
12232         fnt.setPointSize ( 10 );
12233 #else
12234         fnt.setPointSize ( 9 );
12235 #endif
12236     passForm->setFont ( fnt );
12237 
12238     fotoLabel=new QLabel ( passForm );
12239     fotoLabel->hide();
12240 
12241     nameLabel=new QLabel ( "",passForm );
12242     nameLabel->hide();
12243 
12244     loginPrompt=new QLabel ( tr ( "Login:" ),passForm );
12245     passPrompt=new QLabel ( tr ( "Password:" ),passForm );
12246     layoutPrompt=new QLabel ( tr ( "Keyboard layout:" ),passForm );
12247 
12248     login=new ClickLineEdit ( passForm );
12249     setWidgetStyle ( login );
12250     login->setFrame ( false );
12251     login->setEnabled ( false );
12252 
12253     login->hide();
12254     loginPrompt->hide();
12255 
12256     pass=new ClickLineEdit ( passForm );
12257     setWidgetStyle ( pass );
12258     pass->setFrame ( false );
12259     fnt.setBold ( true );
12260     pass->setFont ( fnt );
12261     pass->setEchoMode ( QLineEdit::Password );
12262     pass->setFocus();
12263 
12264 #ifdef Q_OS_UNIX
12265     connect ( login,SIGNAL ( clicked() ),this,
12266               SLOT ( slotActivateWindow() ) );
12267     connect ( pass,SIGNAL ( clicked() ),this,
12268               SLOT ( slotActivateWindow() ) );
12269 #endif
12270 
12271     pass->hide();
12272     passPrompt->hide();
12273 
12274 
12275     cbLayout=new QComboBox(passForm);
12276     cbLayout->addItems(defaultLayout);
12277     cbLayout->setFocusPolicy(Qt::NoFocus);
12278     cbLayout->setFrame(false);
12279     setWidgetStyle(cbLayout);
12280     cbLayout->hide();
12281     layoutPrompt->hide();
12282     QHBoxLayout* cbLayoutLay=new QHBoxLayout();
12283     cbLayoutLay->addWidget(cbLayout);
12284     cbLayoutLay->addStretch();
12285 
12286 
12287     ok=new QPushButton ( tr ( "Ok" ),passForm );
12288     setWidgetStyle ( ok );
12289     cancel=new QPushButton ( tr ( "Cancel" ),passForm );
12290     setWidgetStyle ( cancel );
12291     ok->hide();
12292     cancel->hide();
12293 
12294 
12295 
12296     cbLayout->setPalette ( pal );
12297     ok->setPalette ( pal );
12298     cancel->setPalette ( pal );
12299 
12300 
12301 
12302 #ifndef Q_WS_HILDON
12303     ok->setFixedSize ( ok->sizeHint() );
12304     cancel->setFixedSize ( cancel->sizeHint() );
12305 #else
12306     QSize sz=cancel->sizeHint();
12307     sz.setWidth ( ( int ) ( sz.width() /1.5 ) );
12308     sz.setHeight ( ( int ) ( sz.height() /1.5 ) );
12309     cancel->setFixedSize ( sz );
12310     sz=ok->sizeHint();
12311     sz.setWidth ( ( int ) ( sz.width() /1.5 ) );
12312     sz.setHeight ( ( int ) ( sz.height() /1.5 ) );
12313     ok->setFixedSize ( sz );
12314 #endif
12315 
12316     QVBoxLayout *layout=new QVBoxLayout ( passForm );
12317     QHBoxLayout *labelLay=new QHBoxLayout();
12318     QHBoxLayout *inputLay=new QHBoxLayout();
12319     QHBoxLayout *buttonLay=new QHBoxLayout();
12320 
12321     labelLay->setSpacing ( 20 );
12322     inputLay->setSpacing ( 10 );
12323     layout->setContentsMargins ( 20,20,10,10 );
12324     layout->addLayout ( labelLay );
12325     layout->addStretch();
12326     layout->addLayout ( inputLay );
12327     layout->addStretch();
12328     layout->addLayout ( buttonLay );
12329 
12330     labelLay->addWidget ( fotoLabel );
12331     labelLay->addWidget ( nameLabel );
12332     labelLay->addStretch();
12333 
12334     QVBoxLayout* il1=new QVBoxLayout();
12335     il1->addWidget ( loginPrompt );
12336     il1->addWidget ( passPrompt );
12337     il1->addWidget ( layoutPrompt );
12338 
12339     QVBoxLayout* il2=new QVBoxLayout();
12340     il2->addWidget ( login );
12341     il2->addWidget ( pass );
12342     il2->addLayout ( cbLayoutLay );
12343     inputLay->addLayout ( il1 );
12344     inputLay->addLayout ( il2 );
12345     inputLay->addStretch();
12346 
12347     buttonLay->addStretch();
12348     buttonLay->addWidget ( ok );
12349     buttonLay->addWidget ( cancel );
12350     buttonLay->addStretch();
12351 
12352     pal.setColor ( QPalette::Base, QColor ( 239,239,239,255 ) );
12353     login->setPalette ( pal );
12354     pass->setPalette ( pal );
12355 
12356     connect ( ok,SIGNAL ( clicked() ),this, SLOT ( slotSessEnter() ) );
12357     connect ( cancel,SIGNAL ( clicked() ),this, SLOT ( slotClosePass() ) );
12358     connect ( pass,SIGNAL ( returnPressed() ),this,
12359               SLOT ( slotSessEnter() ) );
12360     connect ( login,SIGNAL ( returnPressed() ),pass, SLOT ( selectAll() ) );
12361     connect ( login,SIGNAL ( returnPressed() ),pass, SLOT ( setFocus() ) );
12362 
12363     passPrompt->show();
12364     pass->show();
12365     ok->show();
12366     cancel->show();
12367     fotoLabel->show();
12368     nameLabel->show();
12369     if ( !useLdap )
12370     {
12371         login->show();
12372         loginPrompt->show();
12373     }
12374     if ( embedMode )
12375     {
12376         cancel->setEnabled ( false );
12377 #ifdef Q_OS_WIN
12378         QRect r;
12379         wapiWindowRect ( (HWND)ok->winId(),r );
12380 #endif
12381     }
12382     if (defaultLayout.size()>1)
12383     {
12384         layoutPrompt->show();
12385         cbLayout->show();
12386         slotChangeKbdLayout(cbLayout->currentText());
12387         connect (cbLayout,SIGNAL(currentIndexChanged(QString)),this,SLOT(slotChangeKbdLayout(QString)));
12388     }
12389 }
12390 
12391 
initStatusDlg()12392 void ONMainWindow::initStatusDlg()
12393 {
12394     sessionStatusDlg = new SVGFrame ( ":/img/svg/passform.svg",
12395                                       false,bgFrame );
12396     sessionStatusDlg->hide();
12397     if ( !miniMode )
12398         sessionStatusDlg->setFixedSize (
12399             sessionStatusDlg->sizeHint() );
12400     else
12401         sessionStatusDlg->setFixedSize ( 310,200 );
12402     QFont fnt=sessionStatusDlg->font();
12403     if ( miniMode )
12404 #ifdef Q_WS_HILDON
12405         fnt.setPointSize ( 10 );
12406 #else
12407         fnt.setPointSize ( 9 );
12408 #endif
12409     sessionStatusDlg->setFont ( fnt );
12410     username->addWidget ( sessionStatusDlg );
12411     QPalette pal=sessionStatusDlg->palette();
12412     pal.setBrush ( QPalette::Window, QColor ( 0,0,0,0 ) );
12413     pal.setColor ( QPalette::Active, QPalette::WindowText, QPalette::Mid );
12414     pal.setColor ( QPalette::Active, QPalette::ButtonText, QPalette::Mid );
12415     pal.setColor ( QPalette::Active, QPalette::Text, QPalette::Mid );
12416     pal.setColor ( QPalette::Inactive, QPalette::WindowText, QPalette::Mid );
12417     pal.setColor ( QPalette::Inactive, QPalette::ButtonText, QPalette::Mid );
12418     pal.setColor ( QPalette::Inactive, QPalette::Text, QPalette::Mid );
12419 
12420     sessionStatusDlg->setPalette ( pal );
12421 
12422     slName=new QLabel ( sessionStatusDlg );
12423     slVal=new QLabel ( sessionStatusDlg );
12424 
12425     slName->setText (
12426         tr (
12427             "<b>Session ID:<br>Server:<br>Username:"
12428             "<br>Display:<br>Creation time:<br>Status:</b>" ) );
12429     slName->setFixedSize ( slName->sizeHint() );
12430     slName->hide();
12431 
12432     slVal->hide();
12433     slVal->setFixedHeight ( slName->sizeHint().height() );
12434 
12435     sbApps=new QToolButton (sessionStatusDlg );
12436     sbApps->setToolTip(tr ( "Applications ..." ));
12437     sbApps->setIcon(QPixmap(":/img/icons/32x32/apps.png"));
12438     sbApps->setAutoRaise(true);
12439     sbApps->setFocusPolicy(Qt::NoFocus);
12440 
12441     sbExp=new QToolButton (sessionStatusDlg );
12442     sbExp->setIcon(QPixmap(":/img/icons/32x32/open_dir.png"));
12443     sbExp->setToolTip (tr ("Share folder ..." ));
12444     sbExp->setAutoRaise(true);
12445     sbExp->setFocusPolicy(Qt::NoFocus);
12446 
12447     sbSusp=new QToolButton (sessionStatusDlg );
12448     sbSusp->setIcon(QPixmap(":/img/icons/32x32/suspend_session.png"));
12449     sbSusp->setToolTip(tr ( "Abort" ));
12450     sbSusp->setAutoRaise(true);
12451     sbSusp->setFocusPolicy(Qt::NoFocus);
12452 
12453 
12454     sbTerm=new QToolButton (sessionStatusDlg );
12455     sbTerm->setIcon(QPixmap(":/img/icons/32x32/stop_session.png"));
12456     sbTerm->setToolTip(tr ( "Terminate" ));
12457     sbTerm->setAutoRaise(true);
12458     sbTerm->setFocusPolicy(Qt::NoFocus);
12459 
12460 
12461     sbAdv=new QCheckBox ( tr ( "Show details" ),sessionStatusDlg );
12462     setWidgetStyle ( sbTerm );
12463     setWidgetStyle ( sbApps );
12464     setWidgetStyle ( sbExp );
12465     setWidgetStyle ( sbSusp );
12466     setWidgetStyle ( sbAdv );
12467 
12468     sbAdv->setFixedSize ( sbAdv->sizeHint() );
12469     sbApps->setFixedSize ( 32,32 );
12470     sbSusp->setFixedSize ( 32,32 );
12471     sbTerm->setFixedSize ( 32,32 );
12472     sbExp->setFixedSize ( 32,32 );
12473 
12474     /*
12475         sbApps->setFocusPolicy(Qt::NoFocus);
12476         sbSusp->setFocusPolicy(Qt::NoFocus);
12477         sbTerm->setFocusPolicy(Qt::NoFocus);
12478         sbExp->setFocusPolicy(Qt::NoFocus);*/
12479 
12480     sbAdv->hide();
12481     sbSusp->hide();
12482     sbTerm->hide();
12483     sbExp->hide();
12484     sbApps->hide();
12485 
12486 
12487     pal.setColor ( QPalette::Button, QColor ( 255,255,255,0 ) );
12488     pal.setColor ( QPalette::Window, QColor ( 255,255,255,255 ) );
12489     pal.setColor ( QPalette::Base, QColor ( 255,255,255,255 ) );
12490 
12491     sbAdv->setPalette ( pal );
12492     sbApps->setPalette ( pal );
12493     sbSusp->setPalette ( pal );
12494     sbTerm->setPalette ( pal );
12495     sbExp->setPalette ( pal );
12496 
12497     stInfo=new QTextEdit ( sessionStatusDlg );
12498     setWidgetStyle ( stInfo );
12499     setWidgetStyle ( stInfo->verticalScrollBar() );
12500     stInfo->setReadOnly ( true );
12501     stInfo->hide();
12502     stInfo->setFrameStyle ( QFrame::StyledPanel|QFrame::Plain );
12503     stInfo->setPalette ( pal );
12504 
12505     sbExp->setEnabled ( false );
12506 
12507     connect ( sbSusp,SIGNAL ( clicked() ),this,
12508               SLOT ( slotTestSessionStatus() ) );
12509     connect ( sbTerm,SIGNAL ( clicked() ),this,
12510               SLOT ( slotTermSessFromSt() ) );
12511     connect ( sbAdv,SIGNAL ( clicked() ),this,
12512               SLOT ( slotShowAdvancedStat() ) );
12513     connect ( sbExp,SIGNAL ( clicked() ),this,
12514               SLOT ( slotExportDirectory() ) );
12515     connect ( sbApps,SIGNAL ( clicked() ),this,
12516               SLOT ( slotAppDialog()) );
12517 
12518     QVBoxLayout* layout=new QVBoxLayout ( sessionStatusDlg );
12519     QHBoxLayout* ll=new QHBoxLayout();
12520     ll->addWidget ( slName );
12521     ll->addWidget ( slVal );
12522     ll->addStretch();
12523     ll->setSpacing ( 10 );
12524     if ( !miniMode )
12525         layout->setContentsMargins ( 25,25,10,10 );
12526     else
12527         layout->setContentsMargins ( 10,10,10,10 );
12528 
12529     QHBoxLayout* bl=new QHBoxLayout();
12530     bl->addStretch();
12531     bl->addWidget ( sbApps );
12532     bl->addWidget ( sbExp );
12533     bl->addWidget ( sbSusp );
12534     bl->addWidget ( sbTerm );
12535 //     bl->addStretch();
12536     layout->addLayout ( ll );
12537     layout->addStretch();
12538     layout->addWidget ( stInfo );
12539     layout->addWidget ( sbAdv );
12540     layout->addStretch();
12541     layout->addLayout ( bl );
12542     layout->setSizeConstraint( QLayout::SetFixedSize );
12543 
12544 
12545     slName->show();
12546     slVal->show();
12547     sbAdv->show();
12548     if ( !embedMode )
12549     {
12550         sbSusp->show();
12551         sbTerm->show();
12552         if (! hideFolderSharing )
12553             sbExp->show();
12554     }
12555 
12556     X2goSettings st ( "settings" );
12557 
12558 
12559     if ( st.setting()->value ( "showStatus", ( QVariant ) false ).toBool() )
12560     {
12561         sbAdv->setChecked ( true );
12562         slotShowAdvancedStat();
12563     }
12564 #ifdef Q_OS_WIN
12565     if ( embedMode )
12566     {
12567         QRect r;
12568         wapiWindowRect ( (HWND)sbAdv->winId(),r );
12569         wapiWindowRect ( (HWND)stInfo->verticalScrollBar ()->winId(),r );
12570     }
12571 #endif
12572 
12573 }
12574 
12575 
initSelectSessDlg()12576 void ONMainWindow::initSelectSessDlg()
12577 {
12578     selectSessionDlg = new SVGFrame ( ":/img/svg/passform.svg",
12579                                       false,bgFrame );
12580     username->addWidget ( selectSessionDlg );
12581     setWidgetStyle ( selectSessionDlg );
12582     if ( !miniMode )
12583         selectSessionDlg->setFixedSize ( selectSessionDlg->sizeHint() );
12584     else
12585         selectSessionDlg->setFixedSize ( 310,180 );
12586     QPalette pal=selectSessionDlg->palette();
12587     pal.setBrush ( QPalette::Window, QColor ( 255,255,255,0 ) );
12588     pal.setColor ( QPalette::Active, QPalette::WindowText, QPalette::Mid );
12589     pal.setColor ( QPalette::Active, QPalette::ButtonText, QPalette::Mid );
12590     pal.setColor ( QPalette::Active, QPalette::Text, QPalette::Mid );
12591     pal.setColor ( QPalette::Inactive, QPalette::WindowText, QPalette::Mid );
12592     pal.setColor ( QPalette::Inactive, QPalette::ButtonText, QPalette::Mid );
12593     pal.setColor ( QPalette::Inactive, QPalette::Text, QPalette::Mid );
12594 
12595     selectSessionDlg->setPalette ( pal );
12596 
12597     pal.setColor ( QPalette::Button, QColor ( 255,255,255,0 ) );
12598     pal.setColor ( QPalette::Window, QColor ( 255,255,255,255 ) );
12599     pal.setColor ( QPalette::Base, QColor ( 255,255,255,255 ) );
12600 
12601     QFont fnt=selectSessionDlg->font();
12602     if ( miniMode )
12603 #ifdef Q_WS_HILDON
12604         fnt.setPointSize ( 10 );
12605 #else
12606         fnt.setPointSize ( 9 );
12607 #endif
12608     selectSessionDlg->setFont ( fnt );
12609     selectSessionLabel=new QLabel ( tr ( "Select session:" ),
12610                                     selectSessionDlg );
12611     sOk=new QPushButton ( tr ( "Resume" ),selectSessionDlg );
12612     setWidgetStyle ( sOk );
12613     sCancel=new QPushButton ( tr ( "Cancel" ),selectSessionDlg );
12614     setWidgetStyle ( sCancel );
12615     bCancel=new QPushButton ( tr ( "Cancel" ),selectSessionDlg );
12616     setWidgetStyle ( bCancel );
12617 
12618     bSusp=new QPushButton ( tr ( "Suspend" ),selectSessionDlg );
12619     setWidgetStyle ( bSusp );
12620     bTerm=new QPushButton ( tr ( "Terminate" ),selectSessionDlg );
12621     setWidgetStyle ( bTerm );
12622 
12623     bNew=new QPushButton ( tr ( "New" ),selectSessionDlg );
12624     setWidgetStyle ( bNew );
12625 
12626     bShadow=new QPushButton ( tr ( "Full access" ),selectSessionDlg );
12627     setWidgetStyle ( bShadow );
12628 
12629     bShadowView=new QPushButton ( tr ( "View only" ),selectSessionDlg );
12630     setWidgetStyle ( bShadowView );
12631 
12632     sOk->setPalette ( pal );
12633     sCancel->setPalette ( pal );
12634 
12635     connect ( sCancel,SIGNAL ( clicked() ),this,
12636               SLOT ( slotCloseSelectDlg() ) );
12637     connect ( bCancel,SIGNAL ( clicked() ),this,
12638               SLOT ( slotCloseSelectDlg() ) );
12639 
12640     selectSessionDlg->show();
12641 #ifndef Q_WS_HILDON
12642     sOk->setFixedSize ( ok->sizeHint() );
12643     sCancel->setFixedSize ( cancel->sizeHint() );
12644 #else
12645     QSize sz=sCancel->sizeHint();
12646     sz.setWidth ( ( int ) ( sz.width() /1.5 ) );
12647     sz.setHeight ( ( int ) ( sz.height() /1.5 ) );
12648     sCancel->setFixedSize ( sz );
12649     sz=sOk->sizeHint();
12650     sz.setWidth ( ( int ) ( sz.width() /1.5 ) );
12651     sz.setHeight ( ( int ) ( sz.height() /1.5 ) );
12652     sOk->setFixedSize ( sz );
12653     sz=bSusp->sizeHint();
12654     if ( bTerm->sizeHint().width() > sz.width() )
12655         sz=bTerm->sizeHint();
12656     if ( bNew->sizeHint().width() > sz.width() )
12657         sz=bNew->sizeHint();
12658     sz.setWidth ( ( int ) ( sz.width() /1.5 ) );
12659     sz.setHeight ( ( int ) ( sz.height() /1.5 ) );
12660     bSusp->setFixedSize ( sz );
12661     bTerm->setFixedSize ( sz );
12662     bNew->setFixedSize ( sz );
12663 #endif
12664     int bmaxw=bNew->size().width();
12665     if ( bSusp->size().width() >bmaxw )
12666         bmaxw=bSusp->size().width();
12667     if ( bTerm->size().width() >bmaxw )
12668         bmaxw=bTerm->size().width();
12669 
12670     bNew->setFixedWidth ( bmaxw );
12671     bSusp->setFixedWidth ( bmaxw );
12672     bTerm->setFixedWidth ( bmaxw );
12673 
12674 
12675 
12676     sOk->setEnabled ( true );
12677     sCancel->setEnabled ( true );
12678     selectSessionDlg->setEnabled ( true );
12679     setEnabled ( true );
12680 
12681     sessTv=new SessTreeView ( selectSessionDlg );
12682     setWidgetStyle ( sessTv );
12683     setWidgetStyle ( sessTv->horizontalScrollBar() );
12684     setWidgetStyle ( sessTv->verticalScrollBar() );
12685     sessTv->setItemsExpandable ( false );
12686     sessTv->setRootIsDecorated ( false );
12687 
12688     model=new QStandardItemModel ( sessionExplorer->getSessionsList()->size(), 8 );
12689     if(!brokerMode)
12690         model->setHeaderData ( S_DISPLAY,Qt::Horizontal,
12691                                QVariant ( ( QString ) tr ( "Display" ) ) );
12692     else
12693     {
12694         model->setHeaderData ( S_DISPLAY,Qt::Horizontal,
12695                                QVariant ( ( QString ) tr ( "User" ) ) );
12696     }
12697     model->setHeaderData ( S_STATUS,Qt::Horizontal,
12698                            QVariant ( ( QString ) tr ( "Status" ) ) );
12699     model->setHeaderData ( S_COMMAND,Qt::Horizontal,
12700                            QVariant ( ( QString ) tr ( "Command" ) ) );
12701     model->setHeaderData ( S_TYPE,Qt::Horizontal,
12702                            QVariant ( ( QString ) tr ( "Type" ) ) );
12703     model->setHeaderData ( S_SERVER,Qt::Horizontal,
12704                            QVariant ( ( QString ) tr ( "Server" ) ) );
12705     model->setHeaderData (
12706         S_CRTIME,Qt::Horizontal,
12707         QVariant ( ( QString ) tr ( "Creation time" ) ) );
12708     model->setHeaderData ( S_IP,Qt::Horizontal,
12709                            QVariant ( ( QString ) tr ( "Client IP" ) ) );
12710     model->setHeaderData ( S_ID,Qt::Horizontal,
12711                            QVariant ( ( QString ) tr ( "Session ID" ) ) );
12712 
12713     modelDesktop=new QStandardItemModel ( sessionExplorer->getSessionsList()->size(), 2 );
12714     modelDesktop->setHeaderData ( D_USER,Qt::Horizontal,
12715                                   QVariant ( ( QString ) tr ( "User" ) ) );
12716     modelDesktop->setHeaderData (
12717         D_DISPLAY,Qt::Horizontal,
12718         QVariant ( ( QString ) tr ( "Display" ) ) );
12719 
12720     sessTv->setModel ( ( QAbstractItemModel* ) model );
12721 
12722     QFontMetrics fm ( sessTv->font() );
12723     sessTv->setEditTriggers ( QAbstractItemView::NoEditTriggers );
12724     sessTv->setPalette ( pal );
12725 
12726     sessTv->setModel ( ( QAbstractItemModel* ) model );
12727 
12728     bNew->setPalette ( pal );
12729     bShadow->setPalette ( pal );
12730     bShadowView->setPalette ( pal );
12731     bSusp->setPalette ( pal );
12732     bTerm->setPalette ( pal );
12733     sessTv->setFrameStyle ( QFrame::StyledPanel|QFrame::Plain );
12734     sOk->setEnabled ( false );
12735     bSusp->setEnabled ( false );
12736     bTerm->setEnabled ( false );
12737     bShadow->setEnabled ( false );
12738     selectSessionLabel->hide();
12739     bCancel->setPalette ( pal );
12740     bCancel->hide();
12741 
12742     desktopFilter=new QLineEdit ( selectSessionDlg );
12743     setWidgetStyle ( desktopFilter );
12744 // 	desktopFilter->setFrame ( false );
12745 
12746     desktopFilterCb=new QCheckBox ( tr ( "Only my desktops" ),
12747                                     selectSessionDlg );
12748     desktopFilterCb->hide();
12749 
12750     QVBoxLayout* layout=new QVBoxLayout ( selectSessionDlg );
12751     QHBoxLayout* filterLay=new QHBoxLayout();
12752     QHBoxLayout* blay=new QHBoxLayout();
12753     QVBoxLayout* alay=new QVBoxLayout();
12754     QHBoxLayout* tvlay=new QHBoxLayout();
12755 
12756     selectSesDlgLayout=layout;
12757 
12758     layout->addWidget ( selectSessionLabel );
12759     layout->addLayout ( filterLay );
12760     layout->addLayout ( tvlay );
12761     layout->addLayout ( blay );
12762 
12763     filterLay->addWidget ( desktopFilter );
12764     filterLay->addWidget ( desktopFilterCb );
12765 
12766     alay->addWidget ( bSusp );
12767     alay->addWidget ( bTerm );
12768     alay->addWidget ( bShadowView );
12769     alay->addWidget ( bShadow );
12770     alay->addStretch();
12771     alay->addWidget ( bNew );
12772     alay->addWidget ( bCancel );
12773 
12774     tvlay->addWidget ( sessTv );
12775     tvlay->addLayout ( alay );
12776 
12777     blay->addStretch();
12778     blay->addWidget ( sOk );
12779     blay->addWidget ( sCancel );
12780     blay->addStretch();
12781     if ( !miniMode )
12782         layout->setContentsMargins ( 25,25,10,10 );
12783     else
12784         layout->setContentsMargins ( 10,10,10,10 );
12785 
12786 
12787 
12788     sOk->hide();
12789     sCancel->hide();
12790     bNew->hide();
12791     bSusp->hide();
12792     bTerm->hide();
12793 
12794     connect ( sessTv,SIGNAL ( selected ( const QModelIndex& ) ),
12795               this,SLOT ( slotActivated ( const QModelIndex& ) ) );
12796 
12797     connect ( sOk,SIGNAL ( clicked() ),this, SLOT ( slotResumeSess() ) );
12798     connect ( sessTv,SIGNAL ( doubleClicked ( const QModelIndex& ) ),
12799               this,SLOT ( slotResumeDoubleClick ( const QModelIndex& ) ) );
12800 
12801     if(!brokerMode)
12802     {
12803         connect ( bNew,SIGNAL ( clicked() ),this, SLOT ( slotNewSess() ) );
12804     }
12805     else
12806     {
12807         connect ( bNew,SIGNAL ( clicked() ),broker, SIGNAL ( sessionSelected() ) );
12808     }
12809 
12810     connect ( bSusp,SIGNAL ( clicked() ),this, SLOT ( slotSuspendSess() ) );
12811     connect ( bTerm,SIGNAL ( clicked() ),this, SLOT ( slotTermSess() ) );
12812 
12813     connect ( bShadow,SIGNAL ( clicked() ),this,
12814               SLOT ( slotShadowSess() ) );
12815     connect ( bShadowView,SIGNAL ( clicked() ),this,
12816               SLOT ( slotShadowViewSess() ) );
12817 
12818     connect ( desktopFilter,SIGNAL ( textEdited ( const QString& ) ),this,
12819               SLOT ( slotDesktopFilterChanged ( const QString& ) ) );
12820     connect ( desktopFilterCb,SIGNAL ( stateChanged ( int ) ),
12821               this,
12822               SLOT ( slotDesktopFilterCb ( int ) ) );
12823 
12824     selectSessionLabel->show();
12825     sOk->show();
12826     sCancel->show();
12827     bNew->show();
12828     bSusp->show();
12829     bTerm->show();
12830     sessTv->show();
12831     selectSessionDlg->hide();
12832 #ifdef Q_OS_WIN
12833     if ( embedMode )
12834     {
12835         QRect r;
12836         wapiWindowRect ( (HWND)sOk->winId(),r );
12837         wapiWindowRect ( (HWND)sessTv->verticalScrollBar ()->winId(),r );
12838         wapiWindowRect ( (HWND)sessTv->horizontalScrollBar ()->winId(),r );
12839         wapiWindowRect ( (HWND)sessTv->header ()->viewport()->winId(),r );
12840     }
12841 #endif
12842 
12843 }
12844 
12845 
printSshDError_startupFailure()12846 void ONMainWindow::printSshDError_startupFailure()
12847 {
12848     if ( closeEventSent )
12849         return;
12850     QString error_message;
12851 
12852     error_message = tr ("SSH daemon could not be started.\n\n");
12853 
12854     QString detailed_error_message = tr ("You have enabled Remote Printing or File Sharing.\n"
12855                                          "These features require a running and functioning SSH server on your computer.\n"
12856                                          "<b>Printing and File Sharing will be disabled for this session.</b>\n\n");
12857 #ifdef Q_OS_WIN
12858     detailed_error_message += tr ("Normally, this should not happen as X2Go Client for Windows "
12859                                   "ships its own internal SSH server.\n\n"
12860 
12861                                   "If you see this message, please report a bug on:\n");
12862 #else /* defined (Q_OS_WIN) */
12863     detailed_error_message += tr ("The SSH server failed to start.\n\n"
12864 
12865                                   "Please report a bug on:\n");
12866 #endif /* defined (Q_OS_WIN) */
12867     detailed_error_message += tr ("<center><a href=\"https://wiki.x2go.org/doku.php/wiki:bugs\">"
12868                                       "https://wiki.x2go.org/doku.php/wiki:bugs"
12869                                   "</a></center>\n");
12870     detailed_error_message += tr ("Disabling Remote Printing or File Sharing support "
12871                                   "in the session settings will get rid of this message.");
12872 
12873     Non_Modal_MessageBox::critical (0l, "X2Go Client",
12874                                     error_message, detailed_error_message, true,
12875                                     QMessageBox::Ok, QMessageBox::NoButton);
12876 }
12877 
printSshDError_noHostPubKey()12878 void ONMainWindow::printSshDError_noHostPubKey()
12879 {
12880     if ( closeEventSent )
12881         return;
12882 
12883     QString error_message = tr ("SSH daemon failed to open its public host key.");
12884 
12885     QString detailed_error_message = tr ("You have enabled Remote Printing or File Sharing.\n"
12886                                          "These features require a running and functioning SSH server on your computer.\n"
12887                                          "<b>Printing and File Sharing will be disabled for this session.</b>\n\n");
12888 #ifdef Q_OS_WIN
12889     detailed_error_message += tr ("Normally, this should not happen as X2Go Client for Windows "
12890                                   "ships its own internal SSH server and automatically "
12891                                   "generates the required keys.\n\n"
12892 
12893                                   "If you see this message, please report a bug on:\n");
12894 #else /* defined (Q_OS_WIN) */
12895     detailed_error_message += tr ("X2Go Client was unable to create SSH host keys.\n\n"
12896 
12897                                   "Please report a bug on:\n");
12898 #endif /* defined (Q_OS_WIN) */
12899     detailed_error_message += tr ("<center><a href=\"https://wiki.x2go.org/doku.php/wiki:bugs\">"
12900                                       "https://wiki.x2go.org/doku.php/wiki:bugs"
12901                                   "</a></center>\n");
12902 
12903     detailed_error_message += tr ("Disabling Remote Printing or File Sharing support "
12904                                   "in the session settings will get rid of this message.");
12905 
12906     Non_Modal_MessageBox::critical (0l, "X2Go Client", error_message, detailed_error_message,
12907                                     true,
12908                                     QMessageBox::Ok, QMessageBox::NoButton);
12909 }
12910 
printSshDError_noExportPubKey()12911 void ONMainWindow::printSshDError_noExportPubKey()
12912 {
12913     if ( closeEventSent )
12914         return;
12915     QMessageBox::critical ( 0l,tr ( "SSH Error" ),
12916                             tr ( "SSH daemon failed to open the application's public key\n"
12917                                  "used for exporting folders and printers."
12918                                ),
12919                             QMessageBox::Ok,QMessageBox::NoButton );
12920 }
12921 
printSshDError_noAuthorizedKeysFile()12922 void ONMainWindow::printSshDError_noAuthorizedKeysFile()
12923 {
12924     if ( closeEventSent )
12925         return;
12926     QMessageBox::critical ( 0l,tr ( "SSH Error" ),
12927                             tr ( "SSH daemon failed to open the application's\n"
12928                                  "authorized_keys file."
12929                                ),
12930                             QMessageBox::Ok,QMessageBox::NoButton );
12931 }
12932 
12933 
slotPCookieReady(bool result,QString,int)12934 void ONMainWindow::slotPCookieReady (	bool result,
12935                                         QString ,
12936                                         int )
12937 {
12938     /* Silence warning. */
12939     UNUSED (result);
12940 }
12941 
12942 
loadPulseModuleNativeProtocol()12943 void ONMainWindow::loadPulseModuleNativeProtocol()
12944 {
12945     QProcess* proc=new QProcess ( this );
12946     QStringList args;
12947     args<<"load-module"<<"module-native-protocol-tcp";
12948     proc->start ( "pactl",args );
12949     proc->waitForFinished ( 3000 );
12950 }
12951 
slotEmbedToolBar()12952 void ONMainWindow::slotEmbedToolBar()
12953 {
12954     if ( statusLabel )
12955     {
12956         delete statusLabel;
12957         statusLabel=0;
12958     }
12959     if ( embedTbVisible )
12960     {
12961         stb->clear();
12962         act_embedToolBar->setIcon (
12963             QIcon ( ":/img/icons/16x16/tbshow.png" ) );
12964         stb->addAction ( act_embedToolBar );
12965         stb->setToolButtonStyle ( Qt::ToolButtonIconOnly );
12966         stb->widgetForAction (
12967             act_embedToolBar )->setFixedHeight ( 16 );
12968         act_embedToolBar->setText ( tr ( "Restore toolbar" ) );
12969         statusLabel=new QLabel;
12970         stb->addWidget ( statusLabel );
12971 #ifndef Q_OS_WIN
12972         statusBar()->hide();
12973 #endif
12974     }
12975     else
12976     {
12977         initEmbedToolBar();
12978         act_embedToolBar->setIcon (
12979             QIcon ( ":/img/icons/32x32/tbhide.png" ) );
12980         act_embedToolBar->setText ( tr ( "Minimize toolbar" ) );
12981     }
12982     embedTbVisible=!embedTbVisible;
12983     if ( proxyWinEmbedded )
12984         setStatStatus();
12985     X2goSettings st ( "sessions" );
12986     st.setting()->setValue ( "embedded/tbvisible", embedTbVisible );
12987     st.setting()->sync();
12988 }
12989 
initEmbedToolBar()12990 void ONMainWindow::initEmbedToolBar()
12991 {
12992     stb->addAction ( act_embedToolBar );
12993     stb->addSeparator();
12994     stb->setToolButtonStyle ( Qt::ToolButtonTextUnderIcon );
12995     stb->addAction ( act_shareFolder );
12996     stb->addAction ( act_showApps );
12997     stb->addAction ( act_reconnect );
12998     stb->addAction ( act_suspend );
12999     stb->addAction ( act_terminate );
13000     stb->addSeparator();
13001     stb->addAction ( act_embedContol );
13002     stb->addSeparator();
13003     stb->addAction ( act_set );
13004     stb->addAction ( act_abclient );
13005 }
13006 
slotEmbedToolBarToolTip()13007 void ONMainWindow::slotEmbedToolBarToolTip()
13008 {
13009     if ( !showTbTooltip )
13010         return;
13011     QWidget* widg=stb->widgetForAction (
13012                       act_embedToolBar );
13013     QToolTip::showText ( this->mapToGlobal ( QPoint ( 6,6 ) ),
13014                          tr ( "<br><b>&nbsp;&nbsp;&nbsp;Click this "
13015                               "button&nbsp;&nbsp;&nbsp;<br>"
13016                               "&nbsp;&nbsp;&nbsp;to restore toolbar"
13017                               "&nbsp;&nbsp;&nbsp;</b><br>" ),
13018                          widg );
13019 }
13020 
13021 
slotActivateWindow()13022 void ONMainWindow::slotActivateWindow()
13023 {
13024     if ( embedMode )
13025     {
13026         QApplication::setActiveWindow ( this ) ;
13027         activateWindow();
13028 
13029 
13030         /*		x2goDebug<<"focus:"<<pass->hasFocus();
13031                 x2goDebug<<"activ:"<<pass->isActiveWindow();*/
13032 
13033         QTimer::singleShot ( 50, this,
13034                              SLOT ( slotEmbedToolBarToolTip() ) );
13035     }
13036 }
13037 
13038 #ifndef Q_OS_WIN
mouseReleaseEvent(QMouseEvent * event)13039 void ONMainWindow::mouseReleaseEvent ( QMouseEvent * event )
13040 {
13041     QMainWindow::mouseReleaseEvent ( event );
13042     slotActivateWindow();
13043 }
13044 #endif
13045 
slotHideEmbedToolBarToolTip()13046 void ONMainWindow::slotHideEmbedToolBarToolTip()
13047 {
13048     showTbTooltip=false;
13049     QToolTip::hideText();
13050 }
13051 
13052 
slotDesktopFilterChanged(const QString & text)13053 void ONMainWindow::slotDesktopFilterChanged ( const QString& text )
13054 {
13055     filterDesktops ( text );
13056 }
13057 
13058 
slotDesktopFilterCb(int state)13059 void ONMainWindow::slotDesktopFilterCb ( int state )
13060 {
13061     if ( state==Qt::Checked )
13062     {
13063         filterDesktops ( getCurrentUname(),true );
13064         desktopFilter->setEnabled ( false );
13065     }
13066     else
13067     {
13068         filterDesktops ( desktopFilter->text() );
13069         desktopFilter->setEnabled ( true );
13070     }
13071 }
13072 
13073 
filterDesktops(const QString & filter,bool strict)13074 void ONMainWindow::filterDesktops ( const QString& filter, bool strict )
13075 {
13076     modelDesktop->setRowCount ( 0 );
13077     bShadow->setEnabled ( false );
13078     bShadowView->setEnabled ( false );
13079     QFontMetrics fm ( sessTv->font() );
13080     uint nextRow=0;
13081     for ( int row = 0; row < selectedDesktops.size(); ++row )
13082     {
13083         QStringList desktop=selectedDesktops[row].split ( "@" );
13084         if ( filter==tr ( "Filter" ) ||filter.length() <=0||
13085                 ( strict && desktop[0]==filter )  ||
13086                 ( !strict && desktop[0].startsWith ( filter ) ) )
13087         {
13088             QStandardItem *item;
13089             item= new QStandardItem ( desktop[0] );
13090             modelDesktop->setItem ( nextRow,D_USER,item );
13091             item= new QStandardItem ( desktop[1] );
13092             modelDesktop->setItem ( nextRow++,D_DISPLAY,item );
13093             for ( int j=0; j<2; ++j )
13094             {
13095                 QString txt=
13096                     modelDesktop->index (
13097                         row,j ).data().toString();
13098                 if ( sessTv->header()->sectionSize ( j ) <
13099                         fm.width ( txt ) +6 )
13100                 {
13101                     sessTv->header()->resizeSection (
13102                         j,fm.width ( txt ) +6 );
13103                 }
13104             }
13105         }
13106     }
13107 }
13108 
13109 
slotShadowSess()13110 void ONMainWindow::slotShadowSess()
13111 {
13112     shadowMode=SHADOW_FULL;
13113     slotShadowViewSess();
13114 }
13115 
slotShadowViewSess()13116 void ONMainWindow::slotShadowViewSess()
13117 {
13118     shadowUser=sessTv->model()->index ( sessTv->currentIndex().row(),
13119                                         D_USER ).data().toString();
13120     shadowDisplay=sessTv->model()->index ( sessTv->currentIndex().row(),
13121                                            D_DISPLAY ).data().toString();
13122     startNewSession();
13123 }
13124 
13125 
slotReconnectSession()13126 void ONMainWindow::slotReconnectSession()
13127 {
13128     if ( !managedMode )
13129         slotSelectedFromList ( ( SessionButton* ) 0 );
13130     else
13131     {
13132         setEnabled ( false );
13133     }
13134 }
13135 
13136 
getEmbedAreaSize()13137 QSize ONMainWindow::getEmbedAreaSize()
13138 {
13139     if ( embedTbVisible && config.showstatusbar )
13140         statusBar()->show();
13141     QSize sz=bgFrame->size();
13142 //     sz.setHeight(sz.height()-statusBar()->size().height());
13143     statusBar()->hide();
13144     return sz;
13145 }
13146 
13147 
slotStartBroker()13148 void ONMainWindow::slotStartBroker()
13149 {
13150     config.brokerPass=pass->text();
13151     config.brokerUser=login->text();
13152     setStatStatus ( tr ( "Connecting to broker" ) );
13153     stInfo->insertPlainText ( "broker url: "+config.brokerurl );
13154     setEnabled ( false );
13155     if(!usePGPCard)
13156         broker->getUserSessions();
13157 }
13158 
slotGetBrokerSession()13159 void ONMainWindow::slotGetBrokerSession()
13160 {
13161     startSession ( config.session);
13162 }
13163 
slotStartNewBrokerSession()13164 void ONMainWindow::slotStartNewBrokerSession ( )
13165 {
13166     if ( managedMode )
13167     {
13168         setEnabled ( true );
13169         slotSelectedFromList ( ( SessionButton* ) 0 );
13170     }
13171 }
13172 
13173 #ifdef Q_OS_WIN
u3DataPath()13174 QString ONMainWindow::u3DataPath()
13175 {
13176     QStringList env=QProcess::systemEnvironment();
13177     QString dpath;
13178     for ( int i=0; i<env.size(); ++i )
13179     {
13180         //check if we have U3 System
13181         if ( env[i].indexOf ( "U3_APP_DATA_PATH=" ) ==0 )
13182         {
13183             dpath=env[i];
13184         }
13185         if ( env[i].indexOf ( "U3_DEVICE_PATH=" ) ==0 )
13186         {
13187             u3Device=env[i];
13188             u3Device.replace ( "U3_DEVICE_PATH=","" );
13189         }
13190 
13191     }
13192 
13193     if ( dpath.length() >0 )
13194     {
13195         dpath.replace ( "U3_APP_DATA_PATH=","" );
13196         portableDataPath=dpath;
13197         return dpath;
13198     }
13199     return QString::null;
13200 }
13201 
13202 #endif
13203 
cleanPortable()13204 void ONMainWindow::cleanPortable()
13205 {
13206     removeDir ( homeDir +"/.ssh" );
13207     removeDir ( homeDir +"/ssh" );
13208     removeDir ( homeDir+"/.x2go" );
13209     if (cleanAllFiles)
13210         removeDir(homeDir+"/.x2goclient");
13211 }
13212 
removeDir(QString path)13213 void ONMainWindow::removeDir ( QString path )
13214 {
13215 
13216     x2goDebug<<"removeDir, entering: " <<path;
13217 
13218     QDir dr ( path );
13219     QStringList files=dr.entryList ( QDir::Files );
13220     for ( int i=0; i<files.size(); ++i )
13221     {
13222         if ( files[i]!="known_hosts" || cleanAllFiles)
13223         {
13224 
13225             x2goDebug<<"Cleaning file: "<<path+"/"+files[i];
13226 
13227             dr.remove ( path+"/"+files[i] );
13228         }
13229     }
13230     QStringList dirs=dr.entryList ( QDir::AllDirs|QDir::NoDotAndDotDot );
13231     for ( int i=0; i<dirs.size(); ++i )
13232     {
13233         removeDir ( path+"/"+dirs[i] );
13234     }
13235     dr.rmdir ( path );
13236 }
13237 
13238 #ifdef Q_OS_UNIX
X11FindWindow(QString text,long rootWin)13239 long ONMainWindow::X11FindWindow ( QString text, long rootWin )
13240 {
13241     Window    wParent;
13242     Window    wRoot;
13243     Window   *child_list;
13244     unsigned  nChildren;
13245     long proxyId=0;
13246     if ( !rootWin )
13247         rootWin= XDefaultRootWindow ( QX11Info::display() );
13248 
13249     if ( XQueryTree ( QX11Info::display(),rootWin,&wRoot,&wParent,
13250                       &child_list,&nChildren ) )
13251     {
13252         for ( uint i=0; i<nChildren; ++i )
13253         {
13254             char *wname;
13255             if ( XFetchName ( QX11Info::display(),
13256                               child_list[i],&wname ) )
13257             {
13258                 QString title ( wname );
13259                 XFree ( wname );
13260                 if ( title==text )
13261                 {
13262                     proxyId=child_list[i];
13263                     break;
13264                 }
13265             }
13266             proxyId=X11FindWindow ( text, child_list[i] );
13267             if ( proxyId )
13268                 break;
13269         }
13270         XFree ( child_list );
13271     }
13272     return proxyId;
13273 }
13274 #endif
13275 
findWindow(QString text)13276 long ONMainWindow::findWindow ( QString text )
13277 {
13278     x2goDebug<<"Searching window with title: " + text;
13279 #ifdef Q_OS_UNIX
13280     return X11FindWindow ( text );
13281 #endif
13282 #ifdef Q_OS_WIN
13283     return ( long ) wapiFindWindow ( 0,text.utf16() );
13284 #endif
13285     return 0;
13286 }
13287 
slotInitLibssh()13288 void ONMainWindow::slotInitLibssh () {
13289   /* Initialize libssh. This must be done outside of any threading context. */
13290   x2goDebug << "libssh not initialized yet. Initializing.";
13291   ssh_threads_set_callbacks(ssh_threads_get_pthread ());
13292   if (ssh_init ()) {
13293       x2goDebug << "Cannot initialize libssh.";
13294       QMessageBox::critical (this, tr ("libssh initialization failure"),
13295                              tr ("Unable to initialize libssh."));
13296       trayQuit ();
13297   }
13298 }
13299