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> Click this "
13015 "button <br>"
13016 " to restore toolbar"
13017 " </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