/************************************************************************** * Copyright (C) 2005-2020 by Oleksandr Shneyder * * * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ #include "onmainwindow_privat.h" #include "help.h" #include void x2goSession::operator = ( const x2goSession& s ) { agentPid=s.agentPid; clientIp=s.clientIp; cookie=s.cookie; crTime=s.crTime; display=s.display; grPort=s.grPort; server=s.server; sessionId=s.sessionId; sndPort=s.sndPort; fsPort=s.fsPort; status=s.status; sessionType=s.sessionType; command=s.command; } bool ONMainWindow::portable=false; QString ONMainWindow::homeDir; QString ONMainWindow::sessionCfg; #ifdef Q_OS_WIN QString ONMainWindow::u3Device; #endif bool ONMainWindow::debugging=false; bool ONMainWindow::libssh_debugging = false; bool ONMainWindow::libssh_packetlog = false; ONMainWindow::ONMainWindow ( QWidget *parent ) :QMainWindow ( parent ) { haveTerminal=false; #ifndef Q_OS_WIN QFile fl("/dev/tty"); if(fl.open( QIODevice::ReadOnly)) { haveTerminal=true; fl.close(); } #endif #ifdef Q_OS_UNIX image=shape=0; #endif x2goInfof(1) << tr("Starting X2Go Client %1...").arg (QString (VERSION)); debugging = false; libssh_debugging = false; libssh_packetlog = false; setFocusPolicy ( Qt::NoFocus ); installTranslator(); autoresume=true; cleanAllFiles=false; drawMenu=true; usePGPCard=false; PGPInited=false; extLogin=false; startMaximized=false; startHidden=false; keepTrayIcon=false; hideFolderSharing=false; brokerNoauthWithSessionUsername=false; brokerCredsForSession=false; thinMode=false; closeDisconnect=false; showHaltBtn=false; showBrokerLogoutBtn=false; defaultUseSound=true; defaultSetKbd=true; extStarted=false; cmdAutologin=false; defaultLink=2; defaultFullscreen=false; defaultXinerama=false; acceptRsa=false; cardStarted=false; cardReady=false; shadowSession=false; proxyRunning=false; // useSshAgent=false; closeEventSent=false; miniMode=false; embedMode=false; proxyWinEmbedded=false; proxyWinId=0; embedParent=embedChild=0l; defaultSession=false; connTest=false; defaultUser=false; defaultWidth=800; defaultHeight=600; defaultPack="16m-jpeg"; defaultQuality=9; defaultLayout<physicalDpiX(); int dpiy = QApplication::desktop()->physicalDpiY(); if ( dpix >0 && dpiy >0) { defaultSetDPI=true; defaultDPI=(dpix+dpiy)/2; } else { defaultSetDPI=false; defaultDPI=96; } #ifdef Q_OS_WIN clientSshPort="7022"; X2goSettings st ( "settings" ); winSshdStarted=false; #else sshd=0l; #endif appDir=QApplication::applicationDirPath(); homeDir=QDir::homePath(); #ifdef Q_OS_WIN xorg=0l; xDisplay=0; x_start_tries_ = 0; x_start_limit_ = 3; #endif if(X2goSettings::centralSettings()) { x2goInfof(0)<<"using central configuration"; noSessionEdit=true; } cleanAskPass(); setWindowTitle ( tr ( "X2Go Client" ) ); ld=0; tunnel=0l; sndTunnel=0l; fsTunnel=0l; nxproxy=0l; soundServer=0l; scDaemon=0l; statusLabel=0; gpg=0l; bBrokerLogout = NULL; restartResume=false; isPassShown=true; readExportsFrom=QString::null; spoolTimer=0l; brokerAliveTimer=0l; #ifdef Q_OS_DARWIN modMapTimer = NULL; kbMap = QString (); #endif /* defined(Q_OS_DARWIN) */ ldapOnly=false; embedControlChanged=false; statusString=tr ( "connecting" ); #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN) pulseManager = NULL; pulseManagerThread = NULL; #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */ connectionType=DEFAULT; hide(); kdeIconsPath=getKdeIconsPath(); addToAppNames ( "WWWBROWSER",tr ( "Internet browser" ) ); addToAppNames ( "MAILCLIENT",tr ( "Email client" ) ); addToAppNames ( "OFFICE",tr ( "OpenOffice.org" ) ); addToAppNames ( "TERMINAL",tr ( "Terminal" ) ); #ifndef Q_OS_UNIX #if QT_VERSION < 0x050000 widgetExtraStyle = new QPlastiqueStyle (); #else widgetExtraStyle = QStyleFactory::create ("fusion"); #endif #endif #ifdef CFGCLIENT QStringList args; if(!X2goSettings::centralSettings()) args=QCoreApplication::arguments(); else { X2goSettings st ( "settings" ); QString cmdLine=st.setting()->value ( "commandline", "" ).toString(); // x2goErrorf(100)<<"cmd line:"<0 ) { portableDataPath=u3Path; ONMainWindow::portable=true; setWindowTitle ( "X2Go Client - U3" ); } #endif if ( ONMainWindow::portable ) { if ( portableDataPath.length() <=0 ) portableDataPath=QDir::currentPath(); homeDir=portableDataPath; x2goInfof(2)<start(1000); } loadSettings(); trayIconActiveConnectionMenu = NULL; trayIconMenu=NULL; trayAutoHidden=false; trayEnabled=trayMinToTray=trayMinCon=trayMaxDiscon=false; trayIconInit(); if ( embedMode ) { miniMode=false; useLdap=false; } if ( readExportsFrom!=QString::null ) { exportTimer=new QTimer ( this ); connect ( exportTimer,SIGNAL ( timeout() ),this, SLOT ( slotExportTimer() ) ); } if ( extLogin ) { extTimer=new QTimer ( this ); extTimer->start ( 2000 ); connect ( extTimer,SIGNAL ( timeout() ),this, SLOT ( slotExtTimer() ) ); } if ( startMaximized ) { QTimer::singleShot ( 10, this, SLOT ( slotResize() ) ); } QDesktopWidget wd; if ( wd.screenGeometry(wd.screenNumber(this)).width() <1024 || wd.screenGeometry(wd.screenNumber(this)).height() <768 ) { miniMode=true; x2goDebug<<"Switching to \"mini\" mode..."; } if ( usePGPCard && !useLdap) { QTimer::singleShot ( 10, this, SLOT ( slotStartPGPAuth() ) ); } //fr=new SVGFrame(QString::null,true,this); fr=new IMGFrame ( ( QImage* ) 0l,this ); setCentralWidget ( fr ); #ifndef Q_WS_HILDON // See if BGFile is a directory and retrieve an SVG file randomly from within QFileInfo bg_dir(BGFile); if (bg_dir.isDir()) { QDirIterator it(BGFile, QStringList() << "*.svg", QDir::Files, QDirIterator::NoIteratorFlags); QStringList fileList; while (it.hasNext()) fileList << it.next(); qsrand(QTime::currentTime().msec()); int max=fileList.size(); int random_selector=qrand() % max; BGFile=fileList.at(random_selector); } if (BGFile.size()) bgFrame=new SVGFrame ( ( QString ) BGFile,true,fr ); else bgFrame=new SVGFrame ( ( QString ) ":/img/svg/bg.svg",true,fr ); #else bgFrame=new SVGFrame ( ( QString ) ":/img/svg/bg_hildon.svg",true,fr ); #endif //bgFrame=new SVGFrame((QString)"/home/admin/test.svg",false,fr); SVGFrame* x2g=new SVGFrame ( ( QString ) ":/img/svg/x2gologo.svg", false,fr ); QPalette pl=x2g->palette(); pl.setColor ( QPalette::Base, QColor ( 255,255,255,0 ) ); pl.setColor ( QPalette::Window, QColor ( 255,255,255,0 ) ); x2g->setPalette ( pl ); if (OnFile.size()) on=new SVGFrame ( ( QString ) OnFile,false,fr ); else on=new SVGFrame ( ( QString ) ":/img/svg/onlogo.svg",false,fr ); on->setPalette ( pl ); if ( !miniMode ) { x2g->setFixedSize ( 100,100 ); on->setFixedSize ( 100,100 ); } else { x2g->setFixedSize ( 50,50 ); on->setFixedSize ( 50,50 ); } mainL=new QHBoxLayout ( fr ); QVBoxLayout* onlay=new QVBoxLayout(); onlay->addStretch(); onlay->addWidget ( on ); QVBoxLayout* x2golay=new QVBoxLayout(); x2golay->addStretch(); x2golay->addWidget ( x2g ); bgLay=new QHBoxLayout ( bgFrame ); bgLay->setSpacing ( 0 ); bgLay->setMargin ( 0 ); bgLay->addLayout ( onlay ); bgLay->addStretch(); username=new QHBoxLayout(); bgLay->addLayout ( username ); if ( embedMode ) bgLay->addStretch(); bgLay->addLayout ( x2golay ); act_set=new QAction ( QIcon ( iconsPath ( "/32x32/edit_settings.png" ) ), tr ( "&Settings ..." ),this ); if (supportMenuFile!=QString::null) { act_support=new QAction ( tr ( "Support ..." ),this ); connect ( act_support,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotSupport() ) ); } act_abclient=new QAction ( QIcon ( ":/img/icons/32x32/x2goclient.png" ), tr ( "About X2Go Client" ),this ); connect ( act_set,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotConfig() ) ); connect ( act_abclient,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotAbout() ) ); sessionExplorer=new SessionExplorer(this); #ifdef Q_OS_DARWIN embedMode=false; #endif #if defined (Q_OS_WIN) //&& defined (CFGCLIENT ) xorgSettings(); #endif #ifdef Q_OS_WIN winServersReady=false; saveCygnusSettings(); #endif initPassDlg(); initStatusDlg(); interDlg=new InteractionDialog(bgFrame); connect(interDlg, SIGNAL(closeInterractionDialog()), this, SLOT(slotCloseInteractionDialog())); username->addWidget ( interDlg ); if ( !embedMode ) { initWidgetsNormal(); } #ifdef Q_OS_WIN QProcess::startDetached("x2gohelper.exe "+QString::number(GetCurrentProcessId())); QTimer::singleShot ( 500, this, SLOT ( startWinServers() ) ); #endif /* FIXME: add Linux. */ #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN) QTimer::singleShot (500, this, SLOT (pulseManagerWrapper ())); #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */ mainL->setSpacing ( 0 ); mainL->setMargin ( 0 ); mainL->insertWidget ( 0, bgFrame ); hide(); QTimer::singleShot ( 1, this, SLOT ( slotResize() ) ); connect ( fr,SIGNAL ( resized ( const QSize ) ),this, SLOT ( slotResize ( const QSize ) ) ); slotResize ( fr->size() ); #ifdef Q_OS_UNIX if (thinMode) { QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(slotSyncX())); timer->start(200); } #endif if (showHaltBtn) { QPushButton* bHalt=new QPushButton(bgFrame); QPixmap p(":/img/png/power-button.png"); bHalt->setIcon(p); bHalt->setFocusPolicy(Qt::NoFocus); bHalt->setFixedSize(32,32); bHalt->move(10,10); bHalt->show(); connect(bHalt,SIGNAL(clicked()),this, SLOT(slotShutdownThinClient())); } bBrokerLogout = new QPushButton (bgFrame); QPixmap p (":/img/png/broker-logout-button.png"); bBrokerLogout->setIcon (p); bBrokerLogout->setFocusPolicy (Qt::NoFocus); bBrokerLogout->setFixedSize (32,32); if (showHaltBtn) { bBrokerLogout->move (40,10); } else { bBrokerLogout->move (10,10); } bBrokerLogout->setEnabled (false); if (showBrokerLogoutBtn) { bBrokerLogout->show (); } else { bBrokerLogout->hide (); } connect (bBrokerLogout, SIGNAL (clicked ()), this, SLOT (slotBrokerLogoutButton ())); if (brokerMode) { broker=new HttpBrokerClient ( this, &config ); connect ( broker,SIGNAL ( fatalHttpError() ),this, SLOT ( close() ) ); connect ( broker, SIGNAL ( authFailed()), this ,SLOT ( slotGetBrokerAuth())); connect ( broker, SIGNAL( sessionsLoaded()), this, SLOT (slotReadSessions())); connect ( broker, SIGNAL ( sessionSelected()), this, SLOT (slotGetBrokerSession())); connect ( broker, SIGNAL ( passwordChanged(QString)), this, SLOT ( slotPassChanged(QString))); connect (broker, SIGNAL (enableBrokerLogoutButton ()), this, SLOT (slotEnableBrokerLogoutButton ())); brokerAliveTimer=new QTimer(this); connect ( brokerAliveTimer, SIGNAL ( timeout() ), this, SLOT ( slotSendBrokerAlive() ) ); } initSelectSessDlg(); proxyWinTimer=new QTimer ( this ); connect ( proxyWinTimer, SIGNAL ( timeout() ), this, SLOT ( slotFindProxyWin() ) ); xineramaTimer=new QTimer (this); connect( xineramaTimer, SIGNAL(timeout()), this, SLOT(slotConfigXinerama())); x2goInfof(3)<setEnabled (true); } void ONMainWindow::slotBrokerLogoutButton () { /* * Log out of the broker if currently logged in, otherwise * does nothing. */ if (config.brokerAuthenticated) { x2goDebug << "Logging off from broker via logout button."; QTimer::singleShot (1, this, SLOT (slotGetBrokerAuth ())); } } void ONMainWindow::slotSendBrokerAlive() { sendEventToBroker(ALIVE); } void ONMainWindow::slotSyncX() { if (proxyRunning) { if (!isHidden()) hide(); #ifdef Q_OS_UNIX XSync(QX11Info::display(),false); #endif } else { if (isHidden()) { showMaximized(); activateWindow(); raise(); } } } bool ONMainWindow::get_translator (QString file_name_start, QTranslator **translator) { QTranslator *tmp_translator = new QTranslator (); /* Qt 4.8.0 introduced a new overload for QTranslator::load(), taking a QLocale * object and loading up the UI language. * Additionally, a lower-cased version is automatically added to the search * list on case-sensitive file systems. * We still need to iterate over the UI languages list in case an English * locale is in there. As we do not ship a nop-English translation, loading * an English translation will always fail and the next language in the list * be preferred. * We also still need the original "compat" version for Qt < 4.8.0. */ QString filename = file_name_start; QStringList ui_languages; #if QT_VERSION < 0x040800 filename = QString (filename + "_%1" ).arg (QLocale::system ().name ()); filename = filename.toLower (); #else /* QT_VERSION < 0x040800 */ ui_languages = QLocale::system ().uiLanguages (); #endif /* QT_VERSION < 0x040800 */ #if QT_VERSION < 0x040800 if (tmp_translator->load (filename)) { *translator = tmp_translator; x2goInfof (4) << tr ("Translator: ") + filename.toLatin1 () + tr (" found."); return (true); } else { x2goWarningf (1) << tr ("Can't load translator: ") + filename.toLatin1 (); return (false); } #else /* QT_VERSION < 0x040800 */ QString load_filename = ""; bool translator_found = false; for (QStringList::const_iterator it = ui_languages.constBegin (); it != ui_languages.constEnd (); ++it) { /* Respect English locales. Don't try to load any translation, because we do not ship nop-English translations. */ if ((*it).startsWith ("en")) { x2goWarningf (1) << "English language requested, not loading translator."; break; } else { /* * QLocale::uiLanguages() may return an unexpected format. * See: https://bugreports.qt.io/browse/QTBUG-25973 */ QString tmp_locale = (*it); tmp_locale.replace ("-", "_"); load_filename = filename; load_filename.append ("_").append (tmp_locale.toLower ()); if (tmp_translator->load (load_filename)) { /* Some translation successfully loaded. That's good enough. */ x2goInfof (4) << tr ("Translator: ") + load_filename.toLatin1 () + tr (" found."); translator_found = true; *translator = tmp_translator; break; } else { x2goWarningf (1) << tr ("Non-fatal: can't load translator: ") + load_filename.toLatin1 (); x2goWarningf (1) << tr ("Trying to load language with lower preference, if existent."); } } } return (translator_found); #endif /* QT_VERSION < 0x040800 */ } void ONMainWindow::installTranslator () { QTranslator *x2goclientTranslator = new QTranslator (); bool translator_found = get_translator (QString (":/i18n/x2goclient"), &x2goclientTranslator); if (translator_found) { QCoreApplication::installTranslator (x2goclientTranslator); } QTranslator *qtTranslator = new QTranslator (); translator_found = get_translator (QString (":/i18n/qt"), &qtTranslator); if (translator_found) { QCoreApplication::installTranslator (qtTranslator); } } void ONMainWindow::initWidgetsEmbed() { } void ONMainWindow::initWidgetsNormal() { username->setSpacing ( 10 ); username->addStretch(); username->addStretch(); ln=new SVGFrame ( ( QString ) ":/img/svg/line.svg",true,fr ); ln->setFixedWidth ( ln->sizeHint().width() ); uname=new QLineEdit ( bgFrame ); setWidgetStyle ( uname ); uname->hide(); uname->setFrame ( false ); u=new QLabel ( tr ( "Session:" ),bgFrame ); u->hide(); QFont fnt=u->font(); fnt.setPointSize ( 16 ); #ifndef Q_WS_HILDON if ( miniMode ) { fnt.setPointSize ( 12 ); } #endif u->setFont ( fnt ); connect ( uname,SIGNAL ( returnPressed() ),this, SLOT ( slotUnameEntered() ) ); QPalette pal=u->palette(); pal.setColor ( QPalette::WindowText, QColor ( 200,200,200,255 ) ); u->setPalette ( pal ); uname->setFont ( fnt ); pal=uname->palette(); pal.setColor ( QPalette::Base, QColor ( 255,255,255,0 ) ); pal.setColor ( QPalette::Text, QColor ( 200,200,200,255 ) ); uname->setPalette ( pal ); u->show(); uname->show(); QVBoxLayout* vblay=new QVBoxLayout(); users=new QScrollArea ( fr ); vblay->addLayout(sessionExplorer->getNavigationLayout()); vblay->addWidget(users); pal=users->verticalScrollBar()->palette(); pal.setBrush ( QPalette::Window, QColor ( 110,112,127,255 ) ); pal.setBrush ( QPalette::Base, QColor ( 110,112,127,255 ) ); pal.setBrush ( QPalette::Button, QColor ( 110,112,127,255 ) ); users->verticalScrollBar()->setPalette ( pal ); users->setFrameStyle ( QFrame::Plain ); users->setFocusPolicy ( Qt::NoFocus ); pal=users->palette(); pal.setBrush ( QPalette::Window, QColor ( 110,112,127,255 ) ); users->setPalette ( pal ); users->setWidgetResizable ( true ); uframe=new QFrame(); users->setWidget ( uframe ); mainL->insertWidget ( 1, ln ); // mainL->addWidget ( users ); mainL->addLayout(vblay); QAction *act_exit=new QAction ( QIcon ( iconsPath ( "/32x32/exit.png" ) ), tr ( "&Quit" ),this ); act_exit->setShortcut ( tr ( "Ctrl+Q" ) ); act_exit->setStatusTip ( tr ( "Quit" ) ); act_new=new QAction ( QIcon ( iconsPath ( "/32x32/new_file.png" ) ), tr ( "&New session ..." ),this ); act_new->setShortcut ( tr ( "Ctrl+N" ) ); setWindowIcon ( QIcon ( ":/img/icons/128x128/x2go.png" ) ); act_edit=new QAction ( QIcon ( iconsPath ( "/32x32/edit.png" ) ), tr ( "Session management ..." ),this ); act_edit->setShortcut ( tr ( "Ctrl+E" ) ); if (noSessionEdit) { act_edit->setEnabled(false); act_new->setEnabled(false); } act_sessicon=new QAction ( QIcon ( iconsPath ( "/32x32/create_file.png" ) ), tr ( "&Create session icon on desktop ..." ), this ); if (brokerMode) act_sessicon->setEnabled(false); if (changeBrokerPass) { act_changeBrokerPass=new QAction ( QIcon ( iconsPath ( "/32x32/auth.png" ) ), tr ( "&Set broker password ..." ), this ); connect ( act_changeBrokerPass,SIGNAL ( triggered(bool)),this, SLOT ( slotChangeBrokerPass()) ); act_changeBrokerPass->setEnabled(false); } if (connTest) { act_testCon=new QAction ( QIcon ( iconsPath ( "/32x32/contest.png" ) ), tr ( "&Connectivity test ..." ), this ); connect ( act_testCon,SIGNAL ( triggered(bool)),this, SLOT ( slotTestConnection()) ); } QAction *act_tb=new QAction ( tr ( "Show toolbar" ),this ); act_tb->setCheckable ( true ); act_tb->setChecked ( showToolBar ); QAction *act_abqt=new QAction ( tr ( "About Qt" ),this ); connect ( act_abqt,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotAboutQt() ) ); connect ( act_new,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotNewSession() ) ); connect ( act_sessicon,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotCreateSessionIcon() ) ); connect ( act_edit,SIGNAL ( triggered ( bool ) ),this, SLOT ( slotManage() ) ); connect ( act_exit,SIGNAL ( triggered ( bool ) ),this, SLOT ( trayQuit()) ) ; connect ( act_tb,SIGNAL ( toggled ( bool ) ),this, SLOT ( displayToolBar ( bool ) ) ); stb=addToolBar ( tr ( "Show toolbar" ) ); if ( drawMenu ) { QMenu* menu_sess=menuBar()->addMenu ( tr ( "&Session" ) ); QMenu* menu_opts=0; if(!X2goSettings::centralSettings()) menu_opts=menuBar()->addMenu ( tr ( "&Options" ) ); if (!brokerMode && !X2goSettings::centralSettings()) { menu_sess->addAction ( act_new ); menu_sess->addAction ( act_edit ); #if (!defined Q_WS_HILDON) && (!defined Q_OS_DARWIN) if ( !portable ) menu_sess->addAction ( act_sessicon ); #endif menu_sess->addSeparator(); } menu_sess->addAction ( act_exit ); if(!X2goSettings::centralSettings()) { menu_opts->addAction ( act_set ); menu_opts->addAction ( act_tb ); if (changeBrokerPass) menu_opts->addAction(act_changeBrokerPass); if (connTest) menu_opts->addAction(act_testCon); } QMenu* menu_help=menuBar()->addMenu ( tr ( "&Help" ) ); if (supportMenuFile!=QString::null) menu_help->addAction ( act_support ); menu_help->addAction ( act_abclient ); menu_help->addAction ( act_abqt ); if (!brokerMode) { stb->addAction ( act_new ); stb->addAction ( act_edit ); #if (!defined Q_WS_HILDON) && (!defined Q_OS_DARWIN) if ( !portable ) stb->addAction ( act_sessicon ); #endif stb->addSeparator(); } stb->addAction ( act_set ); if (changeBrokerPass) stb->addAction(act_changeBrokerPass); if (connTest) stb->addAction(act_testCon); if ( !showToolBar || X2goSettings::centralSettings()) stb->hide(); connect ( act_tb,SIGNAL ( toggled ( bool ) ),stb, SLOT ( setVisible ( bool ) ) ); } else stb->hide(); #if !defined USELDAP useLdap=false; #endif if ( useLdap ) { act_new->setEnabled ( false ); act_edit->setEnabled ( false ); u->setText ( tr ( "Login:" ) ); QTimer::singleShot ( 1500, this, SLOT ( readUsers() ) ); } else { if (!brokerMode) QTimer::singleShot ( 1, this, SLOT ( slotReadSessions() ) ); else { QTimer::singleShot(1, this,SLOT(slotGetBrokerAuth())); } } } void ONMainWindow::slotPassChanged(const QString& result) { if (result==QString::null) { QMessageBox::critical(this, tr("Error"),tr("Operation failed")); } else { QMessageBox::information(this, tr("Password changed"),tr("Password changed")); config.brokerPass=result; } setEnabled(true); slotClosePass(); sessionStatusDlg->hide(); } void ONMainWindow::slotTestConnection() { ConTest test( broker, config.brokerurl, this); test.exec(); } void ONMainWindow::slotChangeBrokerPass() { x2goDebug<<"Changing broker password."; BrokerPassDlg passDlg; if (passDlg.exec()!=QDialog::Accepted) return; if (passDlg.oldPass()!=config.brokerPass) { QMessageBox::critical(this,tr("Error"),tr("Wrong password!")); return; } broker->changePassword(passDlg.newPass()); setStatStatus ( tr ( "Connecting to broker" ) ); stInfo->insertPlainText ( "broker url: "+config.brokerurl ); setEnabled ( false ); uname->hide(); u->hide(); return; } void ONMainWindow::slotCheckPortableDir() { if (!QFile::exists(homeDir)) { x2goDebug<<"Portable directory does not exist, closing."; close(); } } void ONMainWindow::slotGetBrokerAuth() { pass->clear(); login->clear(); QString pixFile=":/img/icons/128x128/x2gosession.png"; if (SPixFile!=QString::null) pixFile=SPixFile; QPixmap pix(pixFile); if ( !miniMode ) { fotoLabel->setPixmap ( pix.scaled ( 64,64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ); fotoLabel->setFixedSize ( 64,64 ); } else { fotoLabel->setPixmap ( pix.scaled ( 48,48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ); fotoLabel->setFixedSize ( 48,48 ); } if(users->isVisible()) { users->hide(); ln->hide(); bgLay->insertStretch(3); } QString text=tr("Authentication"); /* if(config.brokerName.length()>0) text+=config.brokerName; else text+=config.brokerurl;*/ nameLabel->setText ( text ); slotShowPassForm(); config.brokerAuthenticated = false; bBrokerLogout->setEnabled (false); if(config.brokerUser.length()>0) { login->setText(config.brokerUser); pass->setFocus(); } if(config.brokerNoAuth) slotSessEnter(); else if(config.brokerurl.indexOf("ssh://")==0 && (config.brokerAutologin || config.brokerKrbLogin|| config.brokerSshKey.length()>0)) slotSessEnter(); } void ONMainWindow::trayIconInit() { X2goSettings st ( "settings" ); trayEnabled=st.setting()->value ( "trayicon/enabled", false ).toBool(); trayMinCon=st.setting()->value ( "trayicon/mincon", false ).toBool(); trayMaxDiscon=st.setting()->value ( "trayicon/maxdiscon", false ).toBool(); trayNoclose=st.setting()->value ( "trayicon/noclose", false ).toBool(); trayMinToTray=st.setting()->value ( "trayicon/mintotray", false ).toBool(); if (!trayEnabled) { trayMinCon=trayMaxDiscon=trayNoclose=trayMinToTray=false; if (trayIcon) { delete trayIcon; delete trayIconMenu; trayIcon=0l; trayIconMenu=0l; } } else { if (!trayIcon) { trayIconMenu = new QMenu(this); trayIconMenu->addAction(tr("Restore"),this, SLOT(showNormal())); trayIconActiveConnectionMenu = trayIconMenu->addMenu(tr("Not connected")); appMenu[Application::MULTIMEDIA]=initTrayAppMenu(tr("Multimedia"), QPixmap(":/img/icons/22x22/applications-multimedia.png")); appMenu[Application::DEVELOPMENT]=initTrayAppMenu(tr("Development"), QPixmap(":/img/icons/22x22/applications-development.png")); appMenu[Application::EDUCATION]=initTrayAppMenu(tr("Education"), QPixmap(":/img/icons/22x22/applications-education.png")); appMenu[Application::GAME]=initTrayAppMenu(tr("Game"), QPixmap(":/img/icons/22x22/applications-games.png")); appMenu[Application::GRAPHICS]=initTrayAppMenu(tr("Graphics"), QPixmap(":/img/icons/22x22/applications-graphics.png")); appMenu[Application::NETWORK]=initTrayAppMenu(tr("Network"), QPixmap(":/img/icons/22x22/applications-internet.png")); appMenu[Application::OFFICE]=initTrayAppMenu(tr("Office"), QPixmap(":/img/icons/22x22/applications-office.png")); appMenu[Application::SETTINGS]=initTrayAppMenu(tr("Settings"), QPixmap(":/img/icons/22x22/preferences-system.png")); appMenu[Application::SYSTEM]=initTrayAppMenu(tr("System"), QPixmap(":/img/icons/22x22/applications-system.png")); appMenu[Application::UTILITY]=initTrayAppMenu(tr("Utility"), QPixmap(":/img/icons/22x22/applications-utilities.png")); appMenu[Application::OTHER]=initTrayAppMenu(tr("Other"), QPixmap(":/img/icons/22x22/applications-other.png")); appSeparator=trayIconActiveConnectionMenu->addSeparator(); if (!hideFolderSharing) trayIconActiveConnectionMenu->addAction(tr ("Share folder ..." ),this, SLOT(slotExportDirectory())); trayIconActiveConnectionMenu->addAction(tr("Suspend"),this, SLOT(slotSuspendSessFromSt())); trayIconActiveConnectionMenu->addAction(tr("Terminate"),this, SLOT(slotTermSessFromSt())); connect (trayIconActiveConnectionMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotAppMenuTriggered(QAction*))); if (sessionStatusDlg && sessionStatusDlg->isVisible()) { if (!useLdap) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, not setting tray icon title."; } else { trayIconActiveConnectionMenu->setTitle(sessionExplorer->getLastSession()->name()); } } else trayIconActiveConnectionMenu->setTitle(lastUser->username()); } else { trayIconActiveConnectionMenu->setEnabled(false); } trayIconMenu->addSeparator(); trayIconMenu->addAction(tr("Quit"),this, SLOT(trayQuit())); // setup the tray icon itself trayIcon = new QSystemTrayIcon(this); #ifndef Q_OS_DARWIN connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); #endif connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(trayMessageClicked())); trayIcon->setContextMenu(trayIconMenu); trayIcon->setIcon(QIcon ( ":/img/icons/128x128/x2go.png") ); #ifdef Q_OS_DARWIN trayIcon->setToolTip(tr("A click displays the context menu.")); #else trayIcon->setToolTip(tr("A left click hides or restores the window. A right click displays the context menu.")); #endif } if (!startHidden | forceToShowTrayicon) { trayIcon->show(); plugAppsInTray(); } } } QMenu* ONMainWindow::initTrayAppMenu(QString text, QPixmap icon) { QMenu* menu=trayIconActiveConnectionMenu->addMenu(text); if (!keepTrayIcon) { menu->setIcon(icon); } return menu; } void ONMainWindow::slotAppMenuTriggered(QAction* action) { x2goDebug<<"slotAppMenuTriggered: "<data().toString(); if (action->data().toString() != "") runApplication(action->data().toString()); } void ONMainWindow::plugAppsInTray() { if (!trayIcon) return; removeAppsFromTray(); x2goDebug<<"Plugging apps in tray."; bool empty=true; topActions.clear(); foreach(Application app, applications) { QAction* act; if (app.category==Application::TOP) { act=new QAction(app.icon,app.name,trayIconActiveConnectionMenu); trayIconActiveConnectionMenu->insertAction(appSeparator, act); topActions.append(act); } else { act=appMenu[app.category]->addAction(app.icon,app.name); appMenu[app.category]->menuAction()->setVisible(true); } act->setToolTip(app.comment); act->setData(app.exec); empty=false; } if (!empty) appSeparator->setVisible(true); } void ONMainWindow::removeAppsFromTray() { if (!trayIcon) return; x2goDebug<<"Removing apps from tray"; for (int i=0; i<=Application::OTHER; ++i) { appMenu[i]->clear(); appMenu[i]->menuAction()->setVisible(false); } foreach (QAction* act, topActions) { trayIconActiveConnectionMenu->removeAction(act); delete act; } topActions.clear(); appSeparator->setVisible(false); } QString ONMainWindow::findTheme ( QString /*theme*/ ) { return QString::null; } QString ONMainWindow::getKdeIconsPath() { return ":/img/icons"; } void ONMainWindow::slotResize ( const QSize sz ) { if ( startHidden ) { return; } int height; int usize; height=sz.height(); if ( !embedMode ) { if ( !miniMode ) { usize=sz.width()-800; if ( usize<360 ) usize=360; if ( usize>500 ) usize=500; } else { usize=285; } if ( users->width() !=usize ) { users->setFixedWidth ( usize ); if ( useLdap ) { QList::iterator it; QList::iterator end=names.end(); for ( it=names.begin(); it!=end; it++ ) { if ( !miniMode ) ( *it )->move ( ( usize-360 ) /2, ( *it )->pos().y() ); else ( *it )->move ( ( usize-250 ) /2, ( *it )->pos().y() ); } } else { QList::iterator fit; QList::iterator fend=sessionExplorer->getFoldersList()->end(); for ( fit=sessionExplorer->getFoldersList()->begin(); fit!=fend; fit++ ) { if ( !miniMode ) ( *fit )->move ( ( usize-360 ) /2, ( *fit )->pos().y() ); else ( *fit )->move ( ( usize-250 ) /2, ( *fit )->pos().y() ); } QList::iterator it; QList::iterator end=sessionExplorer->getSessionsList()->end(); for ( it=sessionExplorer->getSessionsList()->begin(); it!=end; it++ ) { if ( !miniMode ) ( *it )->move ( ( usize-360 ) /2, ( *it )->pos().y() ); else ( *it )->move ( ( usize-250 ) /2, ( *it )->pos().y() ); } } } u->setFixedWidth ( u->sizeHint().width() ); int bwidth=bgFrame->width(); int upos= ( bwidth-u->width() ) /2; if ( upos<0 ) upos=0; int rwidth=bwidth- ( upos+u->width() +5 ); if ( rwidth<0 ) rwidth=1; uname->setMinimumWidth ( rwidth ); u->move ( upos,height/2 ); uname->move ( u->pos().x() +u->width() +5,u->pos().y() ); sessionExplorer->resize(); } } void ONMainWindow::closeClient() { x2goInfof(6)<hide(); closeEventSent=true; if ( !startMaximized && !startHidden && !embedMode ) { x2goDebug<<"Saving settings ..."; X2goSettings st ( "sizes" ); st.setting()->setValue ( "mainwindow/size", QVariant ( size() ) ); st.setting()->setValue ( "mainwindow/pos",QVariant ( mapToGlobal(QPoint(0,0) ) )); st.setting()->setValue ( "mainwindow/maximized", QVariant ( isMaximized() ) ); st.setting()->sync(); x2goDebug<<"Saved settings."; #ifdef Q_OS_UNIX if (image) XFreePixmap(QX11Info::display(),image); if (shape) XFreePixmap(QX11Info::display(),shape); #endif } if ( nxproxy!=0l ) { if ( nxproxy->state() ==QProcess::Running ) { x2goDebug<<"Terminating proxy ..."; nxproxy->terminate(); x2goDebug<<"Terminated proxy."; } x2goDebug<<"Deleting proxy ..."; delete nxproxy; x2goDebug<<"Deleted proxy."; } if ( sshConnection && !useLdap) { x2goDebug<<"Waiting for the SSH connection to finish ..."; delete sshConnection; x2goDebug<<"SSH connection finished."; sshConnection=0; } if (useLdap) { for (int i=0; iterminate(); x2goDebug<<"Terminated the X.Org Server."; x2goDebug<<"Deleting the X.Org Server ..."; delete xorg; x2goDebug<<"Deleted the X.Org Server."; } if ( winSshdStarted ) { TerminateProcess ( sshd.hProcess,0 ); CloseHandle ( sshd.hProcess ); CloseHandle ( sshd.hThread ); } #endif /* defined (Q_OS_WIN) */ #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN) if (pulseManager) { disconnect(pulseManager, SIGNAL(sig_pulse_user_warning(bool, const QString&, const QString&, bool)), this, SLOT(slotShowPAMSGDialog(bool, const QString&, const QString&, bool))); delete (pulseManager); if (pulseManagerThread) { pulseManagerThread->quit (); pulseManagerThread->wait (); } delete (pulseManagerThread); } #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */ #ifndef Q_OS_WIN if (sshd) { x2goDebug << "Terminating the OpenSSH server ..."; sshd->terminate (); /* Allow sshd a grace time of 5 seconds to terminate. */ QTime sleep_time = QTime::currentTime ().addSecs (5); bool killed = false; while (QTime::currentTime () < sleep_time) { if (QProcess::NotRunning == sshd->state ()) { killed = true; break; } QCoreApplication::processEvents (QEventLoop::AllEvents, 100); } if (!killed) { /* Grace period over, force termination. */ sshd->kill (); if (!(sshd->waitForFinished (500))) { x2goWarningf (8) << "OpenSSH Server failed to terminate in time " " and the kill command timed out."; } } x2goDebug << "Terminated the OpenSSH server."; delete sshd; } #endif /* !defined (Q_OS_WIN) */ if ( embedMode ) { passForm->close(); selectSessionDlg->close(); #ifndef Q_OS_DARWIN // closeEmbedWidget(); #endif } if ( ONMainWindow::portable ) { #ifdef Q_OS_WIN if ( !cyEntry ) { removeCygwinEntry(); } #endif cleanPortable(); } if (ssh_finalize ()) { x2goDebug << "Unable to finalize libssh. Something may be wrong!"; } else { x2goDebug << "libssh finalized."; } delete (bBrokerLogout); x2goInfof(7)<ignore(); } else { trayQuit(); } } void ONMainWindow::hideEvent(QHideEvent* event) { QMainWindow::hideEvent(event); if (event->spontaneous() && trayMinToTray) hide(); } void ONMainWindow::trayQuit() { x2goDebug<<"Quitting from tray icon and closing application."<quit(); } void ONMainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason ) { switch (reason) { // use single left click on unix // and double click on windows (Is it standard behaviour conform?) #ifdef Q_OS_UNIX case QSystemTrayIcon::Trigger: #else case QSystemTrayIcon::DoubleClick: #endif x2goDebug << "tray icon clicked with Trigger (left click)"; if (isVisible()) hide(); else { showNormal(); } break; default: break; } } void ONMainWindow::trayMessageClicked() { } void ONMainWindow::loadSettings() { X2goSettings st ( "sizes" ); mwSize=st.setting()->value ( "mainwindow/size", ( QVariant ) QSize ( 800,600 ) ).toSize(); mwPos=st.setting()->value ( "mainwindow/pos", ( QVariant ) QPoint ( 20,20 ) ).toPoint(); mwMax=st.setting()->value ( "mainwindow/maximized", ( QVariant ) false ).toBool(); /* * Sanity check for X2Go Client main window position. * Check whether the given position is within bounds of any connected display. * Otherwise use the default. */ bool placement_found = false; QDesktopWidget *desktop_widget = QApplication::desktop (); QRect main_window_geom (mwPos, mwSize); for (size_t i = 0; i < static_cast (desktop_widget->screenCount ()); ++i) { QRect tmp_geom = desktop_widget->availableGeometry (i); if (tmp_geom.intersects (main_window_geom)) { placement_found = true; break; } } if (!placement_found) { mwPos = QPoint (20, 20); } X2goSettings st1 ( "settings" ); if ( !ldapOnly ) { useLdap=st1.setting()->value ( "LDAP/useldap", ( QVariant ) false ).toBool(); ldapServer=st1.setting()->value ( "LDAP/server", ( QVariant ) "localhost" ).toString(); ldapPort=st1.setting()->value ( "LDAP/port", ( QVariant ) 389 ).toInt(); ldapDn=st1.setting()->value ( "LDAP/basedn", ( QVariant ) QString::null ).toString(); ldapServer1=st1.setting()->value ( "LDAP/server1", ( QVariant ) QString::null ).toString(); ldapPort1=st1.setting()->value ( "LDAP/port1", ( QVariant ) 0 ).toInt(); ldapServer2=st1.setting()->value ( "LDAP/server2", ( QVariant ) QString::null ).toString(); ldapPort2=st1.setting()->value ( "LDAP/port2", ( QVariant ) 0 ).toInt(); } showToolBar=st1.setting()->value ( "toolbar/show", ( QVariant ) true ).toBool(); } QString ONMainWindow::iconsPath ( const QString &fname ) const { /* QFile fl(this->kdeIconsPath+fname); if(fl.exists()) return kdeIconsPath+fname;*/ return (images_resource_path (fname, "/icons/")); } QString ONMainWindow::images_resource_path (const QString &filename, const QString &base) const { QString ret = ":/img"; /* * The base parameter is optional and might be empty. * In this case, it's completely skipped. * Otherwise, we want to make sure that the base parameter * is appended to the fixed start with a slash, but doesn't * end in a slash to avoid double-slashes. * We add a trailing slash if the file name doesn't start * with one. */ if (!(base.isEmpty ())) { if (!(base.startsWith ('/'))) { ret.append ('/'); } ret.append (base); if (ret.endsWith ('/')) { ret.chop (1); } } if (!(filename.startsWith ('/'))) { ret.append ('/'); } ret.append (filename); return (ret); } void ONMainWindow::displayUsers() { QPixmap pix; if ( !miniMode ) pix=QPixmap ( ":/img/png/ico.png" ); else pix=QPixmap ( ":/img/png/ico_mini.png" ); QPixmap foto=QPixmap ( iconsPath ( "/64x64/personal.png" ) ); QPalette pal=palette(); pal.setBrush ( QPalette::Window, QBrush ( pix ) ); pal.setBrush ( QPalette::Base, QBrush ( pix ) ); pal.setBrush ( QPalette::Button, QBrush ( pix ) ); QFont fnt=font(); fnt.setPointSize ( 12 ); uframe->setFont ( fnt ); QList::iterator it; QList::iterator end=userList.end(); int i=0; for ( it=userList.begin(); it!=end; it++ ) { int val=i+1; UserButton* l; if ( ( *it ).foto.isNull() ) l=new UserButton ( this, uframe, ( *it ).uid, ( *it ).name,foto,pal ); else l=new UserButton ( this, uframe, ( *it ).uid, ( *it ).name, ( *it ).foto,pal ); connect ( l,SIGNAL ( userSelected ( UserButton* ) ),this, SLOT ( slotSelectedFromList ( UserButton* ) ) ); if ( !miniMode ) l->move ( ( users->width()-360 ) /2, i*120+ ( val-1 ) *25+5 ); else l->move ( ( users->width()-260 ) /2, i*120+ ( val-1 ) *25+5 ); l->show(); names.append ( l ); i++; } int val=i; uframe->setFixedHeight ( val*120+ ( val-1 ) *25 ); uname->setText ( "" ); disconnect ( uname,SIGNAL ( textEdited ( const QString& ) ),this, SLOT ( slotSnameChanged ( const QString& ) ) ); connect ( uname,SIGNAL ( textEdited ( const QString& ) ),this, SLOT ( slotUnameChanged ( const QString& ) ) ); if ( usePGPCard && !PGPInited) { PGPInited=true; x2goDebug<<"Users loaded, starting smart card daemon."; QTimer::singleShot ( 10, this, SLOT ( slotStartPGPAuth() ) ); } } void ONMainWindow::showPass ( UserButton* user ) { QPalette pal=users->palette(); setUsersEnabled ( false ); QString fullName; QPixmap foto; if ( user ) { foto=user->foto(); nick=user->username(); fullName=user->fullName(); user->hide(); lastUser=user; } else { lastUser=0; foto.load ( iconsPath ( "/64x64/personal.png" ) ); foto=foto.scaled ( 100,100 ); nick=uname->text(); fullName="User Unknown"; } fotoLabel->setPixmap ( foto ); QString text=""+nick+"
("+fullName+")"; nameLabel->setText ( text ); login->setText ( nick ); login->hide(); pass->setEchoMode ( QLineEdit::Password ); pass->setFocus(); slotShowPassForm(); } void ONMainWindow::slotSelectedFromList ( UserButton* user ) { pass->setText ( "" ); showPass ( user ); } void ONMainWindow::slotClosePass() { if (brokerMode) { if (!config.brokerAuthenticated) { x2goErrorf(15)<hide(); if ( !embedMode ) { u->show(); uname->show(); if ( useLdap ) { if ( lastUser ) { lastUser->show(); uname->setText ( lastUser->username() ); } } else { if (sessionExplorer->getLastSession()) { sessionExplorer->getLastSession()->show(); uname->setText ( sessionExplorer->getLastSession()->name() ); } } uname->setEnabled ( true ); u->setEnabled ( true ); setUsersEnabled ( true ); uname->selectAll(); uname->setFocus(); } } void ONMainWindow::slotPassEnter() { if(!embedMode) shadowSession=false; #if defined ( Q_OS_WIN ) || defined (Q_OS_DARWIN ) QString disp=getXDisplay(); if ( disp==QString::null ) return; #endif #ifdef USELDAP if ( ! initLdapSession() ) { QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Please check LDAP settings" ), QMessageBox::Ok,QMessageBox::NoButton ); slotConfig(); return; } passForm->setEnabled ( false ); x2goServers.clear(); list attr; attr.push_back ( "cn" ); attr.push_back ( "serialNumber" ); attr.push_back ( "l" ); list res; QString searchBase="ou=Servers,ou=ON,"+ldapDn; try { ld->stringSearch ( searchBase.toStdString(),attr, "objectClass=ipHost",res ); } catch ( LDAPExeption e ) { QString message="Exception in: "; message=message+e.err_type.c_str(); message=message+" : "+e.err_str.c_str(); QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok,QMessageBox::NoButton ); slotConfig(); return; } if ( res.size() ==0 ) { QString message=tr ( "no X2Go Server found in LDAP " ); QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok,QMessageBox::NoButton ); slotConfig(); return; } list::iterator it=res.begin(); list::iterator end=res.end(); QString freeServer; QString firstServer; bool isFirstServerSet=false; for ( ; it!=end; ++it ) { serv server; server.name=LDAPSession::getStringAttrValues ( *it,"cn" ).front().c_str(); QString sPort="22"; list sL=LDAPSession::getStringAttrValues ( *it,"l" ); if ( sL.size() >0 ) { sPort=sL.front().c_str(); } x2goDebug<<"SSH server: "< serialNumber=LDAPSession::getStringAttrValues ( *it,"serialNumber" ); if ( serialNumber.size() >0 ) { sFactor=serialNumber.front().c_str(); } x2goDebug<<"SSH server: "<setEnabled ( false ); QString passwd; if ( !extLogin ) currentKey=QString::null; QString user=getCurrentUname(); // get x2gogetservers not from ldap server, but from first x2goserver // QString host=ldapServer; QString host=firstServer; passwd=getCurrentPass(); if (sshConnection) delete sshConnection; sshConnection=startSshConnection ( host,sshPort,acceptRsa,user,passwd,true, false ); #endif } void ONMainWindow::slotUnameChanged ( const QString& text ) { if ( prevText==text ) return; if ( text=="" ) return; QList::iterator it; QList::iterator endit=names.end(); for ( it=names.begin(); it!=endit; it++ ) { QString username= ( *it )->username(); if ( username.indexOf ( text,0,Qt::CaseInsensitive ) ==0 ) { QPoint pos= ( *it )->pos(); uname->setText ( username ); QScrollBar* bar=users->verticalScrollBar(); int docLang=bar->maximum()-bar->minimum() + bar->pageStep(); double position= ( double ) ( pos.y() ) / ( double ) ( uframe->height() ); bar->setValue ( ( int ) ( docLang*position-height() /2+ ( *it )->height() /2 ) ); uname->setSelection ( username.length(),text.length()- username.length() ); break; } } prevText=text; } void ONMainWindow::slotUnameEntered() { QString text=uname->text(); if ( useLdap ) { UserButton* user=NULL; QList::iterator it; QList::iterator endit=names.end(); for ( it=names.begin(); it!=endit; it++ ) { QString username= ( *it )->username(); if ( username==text ) { user=*it; break; } } showPass ( user ); } else { SessionButton* sess=NULL; QList::iterator it; QList::iterator endit=sessionExplorer->getSessionsList()->end(); for ( it=sessionExplorer->getSessionsList()->begin(); it!=endit; it++ ) { QString name= ( *it )->name(); if ( name==text ) { sess=*it; break; } } if ( sess ) slotSelectedFromList ( sess ); } } void ONMainWindow::readUsers() { #ifdef USELDAP if ( ! initLdapSession() ) { QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Please check LDAP settings" ), QMessageBox::Ok,QMessageBox::NoButton ); slotConfig(); return; } list attr; attr.push_back ( "uidNumber" ); attr.push_back ( "uid" ); attr.push_back ( "cn" ); attr.push_back ( "jpegPhoto" ); list result; try { ld->binSearch ( ldapDn.toStdString(),attr, "objectClass=posixAccount",result ); } catch ( LDAPExeption e ) { QString message="Exception in: "; message=message+e.err_type.c_str(); message=message+" : "+e.err_str.c_str(); QMessageBox::critical ( 0l,tr ( "Error" ), message,QMessageBox::Ok, QMessageBox::NoButton ); QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Please check LDAP settings" ), QMessageBox::Ok,QMessageBox::NoButton ); slotConfig(); return; } list::iterator it=result.begin(); list::iterator end=result.end(); for ( ; it!=end; ++it ) { user u; QString uin=LDAPSession::getBinAttrValues ( *it,"uidNumber" ).front().getData(); u.uin=uin.toUInt(); if ( u.uinlastUid ) { continue; } u.uid=LDAPSession::getBinAttrValues ( *it, "uid" ).front().getData(); u.name=u.name.fromUtf8 ( LDAPSession::getBinAttrValues ( *it, "cn" ).front().getData() ); list lst=LDAPSession::getBinAttrValues ( *it,"jpegPhoto" ); if ( lst.size() ) { u.foto.loadFromData ( ( const uchar* ) ( lst.front().getData() ), lst.front().length() ); } userList.append ( u ); } qSort ( userList.begin(),userList.end(),user::lessThen ); delete ld; ld=0; displayUsers(); if ( defaultUser ) { defaultUser=false; for ( int i=0; isetText ( defaultUserName ); slotUnameChanged ( defaultUserName ); QTimer::singleShot ( 100, this, SLOT ( slotUnameEntered() ) ); break; } } } #endif } void ONMainWindow::slotConfig() { if ( !startMaximized && !startHidden && !embedMode ) { X2goSettings st ( "sizes" ); st.setting()->setValue ( "mainwindow/size", QVariant ( size() ) ); st.setting()->setValue ( "mainwindow/pos",QVariant ( pos() ) ); st.setting()->sync(); } if ( ld ) delete ld; ld=0; #if defined (Q_OS_WIN) || defined (Q_OS_DARWIN) bool oldDisableInput = false; { X2goSettings st ("settings"); oldDisableInput = st.setting ()->value ("pulse/norecord", (QVariant) false).toBool (); } #endif /* defined (Q_OS_WIN) || defined (Q_OS_DARWIN) */ ConfigDialog dlg ( this ); if ( dlg.exec() ==QDialog::Accepted ) { int i; #if defined (Q_OS_WIN) || defined (Q_OS_DARWIN) if(!systemDisablePA) { X2goSettings st ("settings"); bool disablePA = st.setting ()->value ("pulse/disable", (QVariant) false).toBool (); if(!pulseManager && !disablePA) { x2goDebug<<"PA manager not inited yet, starting PA thread"; QTimer::singleShot (10, this, SLOT (pulseManagerWrapper ())); } else if(pulseManager && disablePA) { if(pulseManager->is_server_running()) { x2goDebug<<"Stopping PulseAudio"; pulseManager->shutdown(); } } else if(pulseManager && !disablePA)//pulse is already inited and not disabled by config dialog { bool newDisableInput = st.setting ()->value ("pulse/norecord", (QVariant) false).toBool (); if(systemDisablePARecord) newDisableInput=true; if (oldDisableInput != newDisableInput) { bool ret = pulseManager->set_record (!newDisableInput); if (!ret) { x2goDebug << "Failed to change recording status of PulseManager. PulseAudio not started?" << endl; } pulseManager->restart (); } } } #endif /* defined (Q_OS_WIN) || defined (Q_OS_DARWIN) */ if ( passForm->isVisible() && !embedMode ) slotClosePass(); if ( sessionStatusDlg->isVisible() || embedMode ) { trayIconInit(); //if session is running or embed mode, save changes, //but not accept // return; } if ( !embedMode ) { for ( i=0; iclose(); sessionExplorer->cleanSessions(); userList.clear(); } loadSettings(); trayIconInit(); if ( useLdap ) { act_new->setEnabled ( false ); act_edit->setEnabled ( false ); u->setText ( tr ( "Login:" ) ); QTimer::singleShot ( 1, this, SLOT ( readUsers() ) ); } else { act_new->setEnabled ( true ); act_edit->setEnabled ( true ); u->setText ( tr ( "Session:" ) ); QTimer::singleShot ( 1, this, SLOT ( slotReadSessions() ) ); } slotResize ( fr->size() ); } } void ONMainWindow::slotReadSessions() { users->show(); ln->show(); if(brokerMode) { bgLay->removeItem(bgLay->itemAt(3)); slotResize(QSize(width(), height())); } X2goSettings *st; sessionExplorer->cleanSessions(); sessionExplorer->setLastSession(0); if (brokerMode) { if (changeBrokerPass) act_changeBrokerPass->setEnabled(true); config.key=QString::null; config.user=QString::null; config.sessiondata=QString::null; for (int i=sessionExplorer->getSessionsList()->count()-1; i>=0; --i) { SessionButton* but=sessionExplorer->getSessionsList()->takeAt(i); if (but) delete but; } st=new X2goSettings(config.iniFile,QSettings::IniFormat); sessionStatusDlg->hide(); selectSessionDlg->hide(); setEnabled ( true ); slotClosePass(); } else st= new X2goSettings( "sessions" ); QStringList slst=st->setting()->childGroups(); x2goDebug<<"Reading "<createBut ( slst[i] ); } sessionExplorer->placeButtons(); if ( slst.size() ==0 ) slotNewSession(); uname->setText ( "" ); disconnect ( uname,SIGNAL ( textEdited ( const QString& ) ),this, SLOT ( slotUnameChanged ( const QString& ) ) ); connect ( uname,SIGNAL ( textEdited ( const QString& ) ),this, SLOT ( slotSnameChanged ( const QString& ) ) ); if(usePGPCard &&brokerMode&&cardReady) { if(sessionExplorer->getSessionsList()->count()==1) { slotSelectedFromList(sessionExplorer->getSessionsList()->at(0)); } } if ( !defaultSession&& startHidden ) { startHidden=false; slotResize(); show(); activateWindow(); raise(); } if ( defaultSession ) { bool sfound=false; defaultSession=false; if ( defaultSessionId.length() >0 ) { for ( int i=0; i< sessionExplorer->getSessionsList()->size(); ++i ) { if ( sessionExplorer->getSessionsList()->at(i)->id() ==defaultSessionId ) { sessionExplorer->setCurrrentPath(sessionExplorer->getSessionsList()->at(i)->getPath()); sessionExplorer->placeButtons(); sfound=true; slotSelectedFromList ( sessionExplorer->getSessionsList()->at(i) ); break; } } } else { QString normalDefaultSName=defaultSessionName.split("/",QString::SkipEmptyParts).join("/"); for ( int i=0; igetSessionsList()->size(); ++i ) { QString normalName=(sessionExplorer->getSessionsList()->at(i)->getPath()+"/"+sessionExplorer->getSessionsList()->at(i)->name()); normalName=normalName.split("/",QString::SkipEmptyParts).join("/"); if ( normalName == normalDefaultSName ) { sessionExplorer->setCurrrentPath(sessionExplorer->getSessionsList()->at(i)->getPath()); sessionExplorer->placeButtons(); sfound=true; uname->setText ( sessionExplorer->getSessionsList()->at(i)->name() ); QTimer::singleShot ( 100, this, SLOT ( slotUnameEntered() ) ); slotSnameChanged ( defaultSessionName ); break; } } } if ( !sfound && startHidden ) { startHidden=false; slotResize(); show(); activateWindow(); raise(); } } delete st; } void ONMainWindow::slotNewSession() { if(X2goSettings::centralSettings()) return; QString id=QDateTime::currentDateTime(). toString ( "yyyyMMddhhmmsszzz" ); EditConnectionDialog dlg (true, id, this ); if ( dlg.exec() ==QDialog::Accepted ) { SessionButton* bt=sessionExplorer->createBut ( id ); sessionExplorer->placeButtons(); users->ensureVisible ( bt->x(),bt->y(),50,220 ); } } void ONMainWindow::slotManage() { SessionManageDialog dlg ( this ); dlg.exec(); } void ONMainWindow::slotCreateSessionIcon() { SessionManageDialog dlg ( this,true ); dlg.exec(); } void ONMainWindow::displayToolBar ( bool show ) { X2goSettings st1 ( "settings" ); st1.setting()->setValue ( "toolbar/show",show ); st1.setting()->sync(); } bool ONMainWindow::initLdapSession ( bool showError ) { #ifdef USELDAP x2goDebug<<"Initializing LDAP sessions ..."; try { ld=new LDAPSession ( ldapServer.toStdString(), ldapPort,"","",true,false ); } catch ( LDAPExeption e ) { QString message="Exception0 in: "; message=message+e.err_type.c_str(); message=message+" : "+e.err_str.c_str(); x2goDebug< attr; attr.push_back ( SESSIONCMD ); attr.push_back ( FIRSTUID ); attr.push_back ( LASTUID ); list res; QString searchBase="ou=Settings,ou=ON,"+ldapDn; QString srch="cn=session settings"; try { ld->stringSearch ( searchBase.toStdString(),attr, srch.toStdString(),res ); } catch ( LDAPExeption e ) { QString message="Exception in: "; message=message+e.err_type.c_str(); message=message+" : "+e.err_str.c_str(); QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); return false; } if ( res.size() !=0 ) { LDAPStringEntry entry=res.front(); list str=LDAPSession::getStringAttrValues ( entry,SESSIONCMD ); if ( str.size() ) { sessionCmd=str.front().c_str(); } str=LDAPSession::getStringAttrValues ( entry,FIRSTUID ); if ( str.size() ) { firstUid= ( ( QString ) str.front().c_str() ).toInt(); } str=LDAPSession::getStringAttrValues ( entry,LASTUID ); if ( str.size() ) { lastUid= ( ( QString ) str.front().c_str() ).toInt(); } } attr.clear(); res.clear(); attr.push_back ( NETSOUNDSYSTEM ); attr.push_back ( SNDSUPPORT ); attr.push_back ( SNDPORT ); attr.push_back ( STARTSNDSERVER ); srch="cn=sound settings"; try { ld->stringSearch ( searchBase.toStdString(),attr, srch.toStdString(),res ); } catch ( LDAPExeption e ) { QString message="Exception in: "; message=message+e.err_type.c_str(); message=message+" : "+e.err_str.c_str(); QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); return false; } if ( res.size() !=0 ) { LDAPStringEntry entry=res.front(); list str=LDAPSession::getStringAttrValues ( entry,NETSOUNDSYSTEM ); if ( str.size() ) { LDAPSndSys=str.front().c_str(); } if ( LDAPSndSys=="PULSE" ) { LDAPSndSys="pulse"; LDAPSndStartServer=false; LDAPSndPort="4713"; } if ( LDAPSndSys=="ARTS_SERVER" ) { LDAPSndPort="20221"; LDAPSndSys="arts"; } if ( LDAPSndSys=="ESPEAKER" ) { LDAPSndPort="16001"; LDAPSndSys="esd"; } str=LDAPSession::getStringAttrValues ( entry,SNDSUPPORT ); if ( str.size() ) { startSound= ( str.front() =="yes" ) ?true:false; } str=LDAPSession::getStringAttrValues ( entry,SNDPORT ); if ( str.size() ) { LDAPSndPort=str.front().c_str(); } str=LDAPSession::getStringAttrValues ( entry,STARTSNDSERVER ); if ( str.size() ) { LDAPSndStartServer= ( str.front() =="yes" ) ?true:false; } } #endif x2goDebug<<"Initialized LDAP sessions."; return true; } void ONMainWindow::slotSnameChanged ( const QString& text ) { if ( prevText==text ) return; if ( text=="" ) return; QList::iterator it; QList::iterator endit=sessionExplorer->getSessionsList()->end(); for ( it=sessionExplorer->getSessionsList()->begin(); it!=endit; it++ ) { if((*it)->getPath()!=sessionExplorer->getCurrentPath()) continue; QString name= ( *it )->name(); if ( name.indexOf ( text,0,Qt::CaseInsensitive ) ==0 ) { QPoint pos= ( *it )->pos(); uname->setText ( name ); QScrollBar* bar=users->verticalScrollBar(); int docLang=bar->maximum()-bar->minimum() + bar->pageStep(); double position= ( double ) ( pos.y() ) / ( double ) ( uframe->height() ); bar->setValue ( ( int ) ( docLang*position-height() / 2+ ( *it )->height() /2 ) ); uname->setSelection ( name.length(), text.length()-name.length() ); break; } } prevText=text; } void ONMainWindow::slotSelectedFromList ( SessionButton* session ) { pass->setText ( "" ); sessionExplorer->setLastSession(session); QString command; QString server; QString userName; bool autologin=false; bool krblogin=false; bool usebrokerpass=false; QString sessIcon; QPalette pal; QString sessionName; if ( !embedMode ) { session->hide(); pal=users->palette(); setUsersEnabled ( false ); sessionName=session->name(); QString sid=session->id(); X2goSettings* st; if (brokerMode) { st=new X2goSettings( config.iniFile, QSettings::IniFormat ); } else { st = new X2goSettings( "sessions" ); } sessIcon = wrap_legacy_resource_URIs (st->setting()->value (sid+"/icon", (QVariant) ":/img/icons/128x128/x2gosession.png" ).toString ()); sessIcon = expandHome(sessIcon); command=st->setting()->value ( sid+"/command", ( QVariant ) tr ( "KDE" ) ).toString(); server=st->setting()->value ( sid+"/host", ( QVariant ) QString::null ).toString(); userName=st->setting()->value ( sid+"/user", ( QVariant ) QString::null ).toString(); if (defaultUser && userName.length()<1) userName=defaultUserName; if(brokerMode) usebrokerpass=st->setting()->value ( sid+"/usebrokerpass", false ).toBool(); sshPort=st->setting()->value ( sid+"/sshport", ( QVariant ) defaultSshPort ).toString(); currentKey=st->setting()->value ( sid+"/key", ( QVariant ) QString::null ).toString(); currentKey=expandHome(currentKey); autologin=st->setting()->value ( sid+"/autologin", ( QVariant ) false ).toBool(); #ifdef Q_OS_UNIX if(command =="XDMCP" && st->setting()->value ( sid+"/directxdmcp", ( QVariant ) false ).toBool()) autologin=true; #endif krblogin=st->setting()->value ( sid+"/krblogin", ( QVariant ) false ).toBool(); delete st; #ifdef Q_OS_WIN if ( portable && u3Device.length() >0 ) { currentKey.replace ( "(U3)",u3Device ); } #endif } else { command=config.command; server=config.server; userName=config.user; sshPort=config.sshport; sessIcon=":/img/icons/128x128/x2gosession.png"; sessionName=config.session; currentKey=config.key; } selectedCommand=command.split("/").last(); command=transAppName ( command ); login->setText ( userName ); x2goDebug << "Creating QPixmap with session icon: '" << sessIcon << "'."; QPixmap pix ( sessIcon ); if ( !miniMode ) { fotoLabel->setPixmap ( pix.scaled ( 64,64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ); fotoLabel->setFixedSize ( 64,64 ); } else { fotoLabel->setPixmap ( pix.scaled ( 48,48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ); fotoLabel->setFixedSize ( 48,48 ); } if(currentKey.length()<=0) { currentKey=findSshKeyForServer(userName, server, sshPort); } if ( command=="RDP" ) { command=tr ( "RDP connection" ); } if ( command=="XDMCP" ) { command=tr ( "XDMCP" ); } if ( command=="SHADOW" ) { command=tr ( "Connection to local desktop" ); } QString text=""+sessionName +"
"+ command+tr ( " on " ) +server; nameLabel->setText ( text ); if ( userName.length() <=0 ) login->setFocus(); bool nopass=false; if ( !embedMode ) slotShowPassForm(); /////////////////////////////////////////////////// if ( currentKey.length() >0 ) { nopass=true; } if(brokerMode &&usebrokerpass) { pass->setText(config.brokerPass); slotSessEnter(); } else if ( currentKey != QString::null && currentKey != "" && nopass ) { x2goDebug<<"Starting session with key."; slotSessEnter(); } else if ( cardReady || autologin || krblogin ) { x2goDebug<<"Starting session via Smart Card, SSH Agent or Kerberos token."; nopass=true; if ( cardReady ) login->setText ( cardLogin ); slotSessEnter(); return; } if ( startHidden && nopass==false ) { startHidden=false; slotResize(); show(); activateWindow(); raise(); } if ( embedMode ) { QTimer::singleShot ( 50, this, SLOT ( slotShowPassForm() ) ); } } SshMasterConnection* ONMainWindow::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) { x2goInfof(8)<setEnabled ( false ); if(cmdAutologin) { autologin=true; } con=new SshMasterConnection (this, host, port.toInt(),acceptUnknownHosts, login, password,currentKey, autologin, krbLogin,useproxy, type, proxyserver, proxyport, proxylogin, proxypassword, proxyKey,proxyAutologin, proxyKrbLogin); if (!getSrv) connect ( con, SIGNAL ( connectionOk(QString) ), this, SLOT ( slotSshConnectionOk() ) ); else connect ( con, SIGNAL ( connectionOk(QString)), this, SLOT ( slotServSshConnectionOk(QString) ) ); qRegisterMetaType ("SshMasterConnection::passphrase_types"); connect ( con, SIGNAL ( serverAuthError ( int,QString, SshMasterConnection* ) ),this, SLOT ( slotSshServerAuthError ( int,QString, SshMasterConnection* ) ) ); connect ( con, SIGNAL ( needPassPhrase(SshMasterConnection*, SshMasterConnection::passphrase_types)),this, SLOT ( slotSshServerAuthPassphrase(SshMasterConnection*, SshMasterConnection::passphrase_types)) ); connect ( con, SIGNAL ( needChallengeResponse(SshMasterConnection*, QString)),this, SLOT ( slotSshServerAuthChallengeResponse(SshMasterConnection*, QString)) ); connect ( con, SIGNAL ( userAuthError ( QString ) ),this,SLOT ( slotSshUserAuthError ( QString ) ) ); connect ( con, SIGNAL ( connectionError ( QString,QString ) ), this, SLOT ( slotSshConnectionError ( QString,QString ) ) ); connect ( con, SIGNAL(startInteraction(SshMasterConnection*,QString)),this, SLOT(slotSshInteractionStart(SshMasterConnection*,QString)) ); connect ( con, SIGNAL(updateInteraction(SshMasterConnection*,QString)),this, SLOT(slotSshInteractionUpdate(SshMasterConnection*,QString)) ); connect (con, SIGNAL(finishInteraction(SshMasterConnection*)),this, SLOT(slotSshInteractionFinish(SshMasterConnection*))); connect ( interDlg, SIGNAL(textEntered(QString)), con, SLOT(interactionTextEnter(QString))); connect ( interDlg, SIGNAL(interrupt()), con, SLOT(interactionInterruptSlot())); con->start(); return con; } void ONMainWindow::slotSshConnectionError ( QString message, QString lastSessionError ) { x2goErrorf(2)<< tr("Connection error: ") + message + ": " + lastSessionError; if ( sshConnection ) { sshConnection->wait(); delete sshConnection; sshConnection=0l; } if (!startHidden) { QMessageBox::critical ( 0l,message,lastSessionError, QMessageBox::Ok, QMessageBox::NoButton ); setEnabled ( true ); passForm->setEnabled ( true ); slotShowPassForm(); pass->setFocus(); pass->selectAll(); passForm->setEnabled ( true ); } else { // In order to get this interaction free, we need to free this from windows and stuff // if ( startHidden ) // { // startHidden=false; // slotResize(); // show(); // activateWindow(); // raise(); // } // completely quit the application trayQuit(); } } void ONMainWindow::slotSshConnectionOk() { x2goDebug<<"SSH connection established."; passForm->setEnabled ( true ); if ( useLdap ) { continueLDAPSession(); } else { if(brokerMode && (connectionType != DEFAULT)) { if(connectionType==SUSPEND) { suspendSession(suspendTerminateSessionFromBroker); } else { termSession(suspendTerminateSessionFromBroker, false); } } else continueNormalSession(); } } void ONMainWindow::cleanServerSshConnections() { for(int i=serverSshConnections.size()-1;i>=0;--i) { if(serverSshConnections[i]!=sshConnection) { delete serverSshConnections[i]; } } serverSshConnections.clear(); } SshMasterConnection* ONMainWindow::findServerSshConnection(QString host) { x2goDebug<<"Searching for SSH connections ..."; for (int i=0; igetHost()==host) { x2goDebug<<"Found SSH connection."; return serverSshConnections[i]; } } } x2goWarningf(3)<< tr("Couldn't find an SSH connection."); return 0l; } void ONMainWindow::slotServSshConnectionOk(QString server) { SshMasterConnection* con=findServerSshConnection(server); if (!con) return; x2goDebug<<"Getting sessions on host: " + server; con->executeCommand( "x2golistsessions", this, SLOT (slotListAllSessions ( bool,QString,int ) )); } void ONMainWindow::slotSshInteractionFinish(SshMasterConnection* connection) { if(interDlg->isInterrupted()) { slotCloseInteractionDialog(); } else { interDlg->setDisplayMode(); } } void ONMainWindow::slotCloseInteractionDialog() { if(interDlg->getInteractionMode()==InteractionDialog::SESSION) { x2goDebug<<"Closed SSH Session interaction"; slotSshUserAuthError("NO_ERROR"); } else { x2goDebug<<"Closed SSH Broker interaction"; if(broker) { interDlg->hide(); broker->closeSSHInteractionDialog(); } } } void ONMainWindow::slotSshInteractionStart(SshMasterConnection* connection, QString prompt) { sessionStatusDlg->hide(); interDlg->show(); interDlg->reset(); interDlg->appendText(prompt); setEnabled(true); interDlg->setEnabled(true); x2goDebug<<"SSH Session prompt:"<setInteractionMode(InteractionDialog::SESSION); } else { interDlg->setInteractionMode(InteractionDialog::BROKER); x2goDebug<<"SSH Broker interaction"; } } void ONMainWindow::slotSshInteractionUpdate(SshMasterConnection* connection, QString output) { if(connection==sshConnection) { x2goDebug<<"SSH Session interaction"; interDlg->setInteractionMode(InteractionDialog::SESSION); } else { interDlg->setInteractionMode(InteractionDialog::BROKER); x2goDebug<<"SSH Broker interaction"; } interDlg->appendText(output); x2goDebug<<"SSH Interaction update:"<getUser () + "@" + connection->getHost () + ":" + QString::number (connection->getPort ()), message, QLineEdit::Password, QString (""), &ok); if (!ok) { phrase = QString (""); } connection->setKeyPhrase (phrase); if(isHidden ()) { show (); QTimer::singleShot (1, this, SLOT (hide ())); } } } void ONMainWindow::slotSshServerAuthChallengeResponse(SshMasterConnection* connection, QString challenge) { bool ok = false; QString message; message = challenge; QString phrase = QInputDialog::getText (0, connection->getUser () + "@" + connection->getHost () + ":" + QString::number (connection->getPort ()), message, QLineEdit::Password, QString::null, &ok); if (!ok) { phrase = QString::null; } else { if (phrase == QString::null) { phrase = ""; } } connection->setKeyPhrase (phrase); if (isHidden ()) { show (); QTimer::singleShot (1, this, SLOT (hide ())); } } void ONMainWindow::slotSshServerAuthError ( int error, QString sshMessage, SshMasterConnection* connection ) { interDlg->hide(); if ( startHidden ) { startHidden=false; slotResize(); show(); activateWindow(); raise(); } QString errMsg; switch ( error ) { case SSH_SERVER_KNOWN_CHANGED: errMsg=tr ( "Host key for server changed.\nIt is now: " ) +sshMessage+"\n"+ tr ( "This can be an indication of a man-in-the-middle attack.\n" "Somebody might be eavesdropping on you.\n" "For security reasons, it is recommended to stop the connection attempt.\n" "Do you want to terminate the connection?\n" ); if (QMessageBox::warning (0, tr ("Host key verification failed."), errMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { connection->writeKnownHosts(false); connection->wait(); if(sshConnection && sshConnection !=connection) { sshConnection->wait(); delete sshConnection; } slotSshUserAuthError ( tr ( "Host key verification failed." ) ); sshConnection=0; return; } else { errMsg = tr( "If you accept the new host key the security of your " "connection may be compromised.\n" "Do you want to update the host key?" ); } break; case SSH_SERVER_FOUND_OTHER: errMsg=tr ( "The host key for this server was not found but another " "type of key exists. An attacker might have changed the default server key to " "trick your client into thinking the key does not exist yet.\n" "For security reasons, it is recommended to stop the connection attempt.\n" "Do you want to terminate the connection?\n"); if (QMessageBox::warning (0, tr ("Host key verification failed."), errMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) { connection->writeKnownHosts(false); connection->wait(); if(sshConnection && sshConnection !=connection) { sshConnection->wait(); delete sshConnection; } slotSshUserAuthError ( tr ( "Host key verification failed." ) ); sshConnection=0; return; } else { errMsg = tr( "If you accept the new host key the security of your " "connection may be compromised.\n" "Do you want to update the host key?" ); } break; case SSH_SERVER_ERROR: connection->writeKnownHosts(false); connection->wait(); if(sshConnection && sshConnection !=connection) { sshConnection->wait(); delete sshConnection; } sshConnection=0; slotSshUserAuthError ( sshMessage ); return ; case SSH_SERVER_FILE_NOT_FOUND: errMsg=tr ( "Could not find known hosts file. " "If you accept the host key here, the file will be automatically created." ); break; case SSH_SERVER_NOT_KNOWN: errMsg=tr ( "The server is unknown. Do you trust the host key?\nPublic key hash: " ) +sshMessage; break; } if (QMessageBox::warning (this, tr ("Host key verification failed."), errMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No) { connection->writeKnownHosts(false); connection->wait(); if(sshConnection && sshConnection !=connection) { sshConnection->wait(); delete sshConnection; } sshConnection=0; slotSshUserAuthError ( tr ( "Host key verification failed." ) ); return; } connection->writeKnownHosts(true); connection->wait(); connection->start(); } void ONMainWindow::slotSshUserAuthError ( QString error ) { interDlg->hide(); if ( sshConnection ) { sshConnection->wait(); delete sshConnection; sshConnection=0l; } // if ( startHidden ) // { // startHidden=false; // slotResize(); // show(); // activateWindow(); // raise(); // } // hidden means hidden, we'll close the client afterwards. if ( startHidden ) { x2goErrorf(3)<< tr("Authentication failed: ") + error; trayQuit(); } if(error != "NO_ERROR") QMessageBox::critical (0l, tr ("Authentication failed."), error, QMessageBox::Ok, QMessageBox::NoButton); setEnabled ( true ); passForm->setEnabled ( true ); slotShowPassForm(); pass->setFocus(); pass->selectAll(); passForm->setEnabled ( true ); } void ONMainWindow::slotSessEnter() { if ( useLdap ) { slotPassEnter(); return; } if (brokerMode) { if (!config.brokerAuthenticated) { x2goDebug<<"Starting broker request."; slotStartBroker(); return; } } if ((brokerMode || !embedMode) && !(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, returning without starting a session."; return; } resumingSession.sessionId=QString::null; resumingSession.server=QString::null; resumingSession.display=QString::null; setStatStatus ( tr ( "connecting" ) ); if(brokerMode) { if (config.brokerNoAuth && brokerNoauthWithSessionUsername) { config.brokerUser = login->text(); } #ifdef Q_OS_UNIX X2goSettings* st=new X2goSettings(config.iniFile, QSettings::IniFormat); QString sid=sessionExplorer->getLastSession()->id(); QString cmd=st->setting()->value ( sid+"/command", ( QVariant ) QString::null ).toString(); directRDP=(st->setting()->value ( sid+"/directrdp", ( QVariant ) false ).toBool() && cmd == "RDP"); if (cmd =="RDP" && directRDP) { x2goDebug<<"Starting direct RDP Session from broker"; startSession ( sid ); return; } directRDP=(st->setting()->value ( sid+"/directxdmcp", ( QVariant ) false ).toBool() && cmd == "RDP"); if (cmd =="XDMCP" && directRDP) { x2goDebug<<"Starting direct RDP Session from broker"; startSession ( sid ); return; } #endif broker->selectUserSession(sessionExplorer->getLastSession()->id(),login->text()); config.session=sessionExplorer->getLastSession()->id(); setStatStatus ( tr ( "Connecting to broker" ) ); stInfo->insertPlainText ( "broker url: "+config.brokerurl ); setEnabled ( false ); uname->hide(); u->hide(); return; } QString sid=""; if ( !embedMode ) sid=sessionExplorer->getLastSession()->id(); startSession ( sid ); } void ONMainWindow::continueNormalSession() { x2goDebug<<"Continue normal X2Go session"; if (brokerMode && !shadowSession) { slotListSessions(true,QString::null,0); return; } if ( !shadowSession ) sshConnection->executeCommand ( "x2golistsessions", this,SLOT ( slotListSessions ( bool, QString,int ))); else sshConnection->executeCommand ( "x2golistdesktops", this,SLOT ( slotListSessions ( bool, QString,int ))); } void ONMainWindow::continueLDAPSession() { sshConnection->executeCommand ( "x2gogetservers", this, SLOT ( slotGetServers ( bool, QString,int ) )); } #ifdef Q_OS_UNIX void ONMainWindow::startDirectRDP() { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, returning without starting a session."; return; } X2goSettings* st; if(brokerMode) { st=new X2goSettings(config.iniFile, QSettings::IniFormat); } else { st=new X2goSettings ( "sessions" ); } QString sid; bool freeRDPNew=false; if ( !embedMode ) sid=sessionExplorer->getLastSession()->id(); else sid="embedded"; bool fullscreen=st->setting()->value ( sid+"/fullscreen", ( QVariant ) defaultFullscreen ).toBool(); bool maxRes=st->setting()->value ( sid+"/maxdim", ( QVariant ) false ).toBool(); int height=st->setting()->value ( sid+"/height", ( QVariant ) defaultHeight ).toInt(); int width=st->setting()->value ( sid+"/width", ( QVariant ) defaultWidth ).toInt(); QString sessionType=st->setting()->value ( sid+"/command", ( QVariant ) "").toString(); QString client=st->setting()->value ( sid+"/rdpclient", ( QVariant ) "rdesktop").toString(); if(client=="xfreerdpnew") { client="xfreerdp"; freeRDPNew=true; } QString host=st->setting()->value ( sid+"/host", ( QVariant ) "").toString(); QString port=st->setting()->value ( sid+"/rdpport", ( QVariant ) "3389").toString(); QString params=st->setting()->value ( sid+"/directrdpsettings", ( QVariant ) "").toString(); QString user,password; if ((!brokerMode) || (brokerCredsForSession)) { user=getCurrentUname(); password=getCurrentPass(); } else { user=st->setting()->value ( sid+"/user", ( QVariant ) "").toString(); } nxproxy=new QProcess; proxyErrString=""; connect ( nxproxy,SIGNAL ( error ( QProcess::ProcessError ) ),this, SLOT ( slotProxyError ( QProcess::ProcessError ) ) ); connect ( nxproxy,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, SLOT ( slotProxyFinished ( int,QProcess::ExitStatus ) ) ); connect ( nxproxy,SIGNAL ( readyReadStandardError() ),this, SLOT ( slotProxyStderr() ) ); connect ( nxproxy,SIGNAL ( readyReadStandardOutput() ),this, SLOT ( slotProxyStdout() ) ); QString userOpt; QString passOpt; QString grOpt; QString proxyCmd; if(!freeRDPNew) { if (user.length()>0) { userOpt=" -u "; userOpt+=user+" "; } if (password.length()>0) { passOpt=" -p \""; passOpt+=password+"\" "; } if (fullscreen) { grOpt=" -f "; } else if (maxRes) { QDesktopWidget wd; grOpt=" -D -g "+QString::number( wd.screenGeometry().width())+"x"+QString::number(wd.screenGeometry().height())+" "; } else { grOpt=" -g "+QString::number(width)+"x"+QString::number(height); } proxyCmd=client +" "+params+ grOpt +userOpt+passOpt + host +":"+port ; } else { if (user.length()>0) { userOpt=" /u:"; userOpt+=user+" "; } if (password.length()>0) { passOpt=" /p:\""; passOpt+=password+"\" "; } if (fullscreen) { grOpt=" /f "; } else if (maxRes) { QDesktopWidget wd; grOpt=" /w:"+QString::number( wd.screenGeometry().width())+" /h:"+QString::number(wd.screenGeometry().height())+" "; } else { grOpt=" /w:"+QString::number(width)+" /h:"+QString::number(height); } proxyCmd= client +" "+params+ grOpt +userOpt+passOpt + "/v:"+host +":"+port ; } if(sessionType=="XDMCP") { x2goDebug<<"starting direct XDMCP session"; client=st->setting()->value ( sid+"/xdmcpclient", ( QVariant ) "Xnest").toString(); params=st->setting()->value ( sid+"/directxdmcpsettings", ( QVariant ) "").toString(); if(client == "Xephyr") { if (fullscreen) { grOpt=" -fullscreen "; } else if (maxRes) { QDesktopWidget wd; grOpt=" -screen "+QString::number( wd.screenGeometry().width())+"x"+QString::number(wd.screenGeometry().height())+" "; } else { grOpt=" -screen "+QString::number(width)+"x"+QString::number(height); } } else { if (maxRes) { QDesktopWidget wd; grOpt=" -geometry "+QString::number( wd.screenGeometry().width())+"x"+QString::number(wd.screenGeometry().height())+" "; } else { grOpt=" -geometry "+QString::number(width)+"x"+QString::number(height); } } int p=0; while(true) { QString fname="/tmp/.X"+QString::number(p)+"-lock"; if(QFile::exists(fname)) { ++p; } else break; } proxyCmd= client +" "+params+ grOpt + " -query "+host +" :"+QString::number(p) ; login->setText(tr("XDM")); resumingSession.display=tr("XDMCP"); } else { x2goDebug<<"starting direct RDP session"; resumingSession.display=tr("RDP"); } // x2goDebug<<"starting direct session with cmd:"<start ( proxyCmd ); resumingSession.server=host; resumingSession.sessionId=user+"-RDP-"; #if QT_VERSION < 0x040700 resumingSession.sessionId += QString::number(QDateTime::currentDateTime().toTime_t()); #else resumingSession.sessionId += QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()/1000); #endif resumingSession.sessionId += "_stRRDP_dp24"; resumingSession.display="RDP"; resumingSession.command="RDP"; resumingSession.crTime=QDateTime::currentDateTime().toString("dd.MM.yy HH:mm:ss"); showSessionStatus(); if(brokerMode) { sendEventToBroker(CONNECTED); } // QTimer::singleShot ( 30000,this,SLOT ( slotRestartProxy() ) ); proxyRunning=true; delete st; } #endif QString ONMainWindow::findSshKeyForServer(QString user, QString server, QString port) { foreach (sshKey key, cmdSshKeys) { if(key.server == server && key.user == user && key.port == port) return key.key; } foreach (sshKey key, cmdSshKeys) { if(key.server == server && key.user == user && key.port.length()<=0) return key.key; } foreach (sshKey key, cmdSshKeys) { if(key.server == server && key.user.length()<=0 && key.port==port) return key.key; } foreach (sshKey key, cmdSshKeys) { if(key.server == server && key.user.length()<=0 && key.port.length()<=0) return key.key; } foreach (sshKey key, cmdSshKeys) { if(key.server.length()<=0 && key.user.length()<=0 && key.port.length()<=0) return key.key; } return QString::null; } bool ONMainWindow::startSession ( const QString& sid, CONTYPE conType ) { connectionType=conType; setEnabled ( false ); #ifdef Q_OS_UNIX directRDP=false; #endif QString passwd; QString user; QString host; bool autologin=false; bool krblogin=false; bool krbDelegation=false; bool useproxy=false; SshMasterConnection::ProxyType proxyType= SshMasterConnection::PROXYHTTP; QString proxyserver; int proxyport=22; QString proxylogin; QString proxypassword; QString proxyKey; bool proxyAutologin=false; bool proxyKrbLogin=false; user=getCurrentUname(); runRemoteCommand=true; if(!embedMode) shadowSession=false; applications.clear(); removeAppsFromTray(); if ( managedMode ) { slotListSessions ( true, QString::null,0 ); return true; } X2goSettings* st; if(!brokerMode) st=new X2goSettings( "sessions" ); else st=new X2goSettings(config.iniFile, QSettings::IniFormat); passForm->setEnabled ( false ); if(brokerMode) { if(connectionType==DEFAULT) host=config.serverIp; else host=suspendTerminateHostFromBroker; sshPort=config.sshport; x2goDebug<<"Server: "<setting()->value ( sid+"/host", ( QVariant ) QString::null ).toString(); } QString cmd=st->setting()->value ( sid+"/command", ( QVariant ) QString::null ).toString(); autologin=st->setting()->value ( sid+"/autologin", ( QVariant ) false ).toBool(); krblogin=st->setting()->value ( sid+"/krblogin", ( QVariant ) false ).toBool(); krbDelegation=st->setting()->value ( sid+"/krbdelegation", ( QVariant ) false ).toBool(); #ifdef Q_OS_UNIX directRDP=(st->setting()->value ( sid+"/directrdp", ( QVariant ) false ).toBool() && cmd == "RDP"); if (cmd =="RDP" && directRDP) { startDirectRDP(); return true; } directRDP=(st->setting()->value ( sid+"/directxdmcp", ( QVariant ) false ).toBool() && cmd == "XDMCP"); if (cmd =="XDMCP" && directRDP) { startDirectRDP(); return true; } #endif if ( cmd=="SHADOW" ) shadowSession=true; passwd=getCurrentPass(); if(brokerMode) { currentKey=config.key; sshPort=config.sshport; } if (sshConnection) delete sshConnection; if(currentKey.length()<=0) { currentKey=findSshKeyForServer(user, host, sshPort); } if (!embedMode) { useproxy = (st->setting ()->value (sid + "/usesshproxy", false).toBool ()); QString prtype = (st->setting ()->value (sid + "/sshproxytype", "SSH").toString ()); if (prtype.toLower () == "http") { proxyType = SshMasterConnection::PROXYHTTP; } else { proxyType = SshMasterConnection::PROXYSSH; } proxylogin = (st->setting ()->value (sid + "/sshproxyuser", QString ()).toString ()); proxyKey = (st->setting ()->value (sid + "/sshproxykeyfile", QString ()).toString ()); proxyKey = expandHome (proxyKey); proxyserver = (st->setting ()->value (sid + "/sshproxyhost", QString ()).toString ()); proxyport = (st->setting ()->value (sid + "/sshproxyport", 22).toInt ()); proxyAutologin = (st->setting ()->value (sid + "/sshproxyautologin", false).toBool ()); proxyKrbLogin = (st->setting ()->value (sid + "/sshproxykrblogin", false).toBool ()); } else { useproxy = config.useproxy; proxyType = config.proxyType; proxylogin = config.proxylogin; proxyKey = config.proxyKey; proxyserver = config.proxyserver; proxyport = config.proxyport; proxyAutologin = config.proxyAutologin; proxyKrbLogin = config.proxyKrbLogin; } bool proxySamePass=(st->setting()->value ( sid+"/sshproxysamepass", false ).toBool() ); bool proxySameUser (st->setting()->value ( sid+"/sshproxysameuser", false ).toBool() ); bool proxySameKey=(st->setting()->value ( sid+"/sshproxysamekey", false ).toBool() ); if(proxyKey.length()<=0 && proxyType==SshMasterConnection::PROXYSSH) { proxyKey=findSshKeyForServer(proxylogin, proxyserver, QString::number(proxyport)); } if(proxySameKey) { proxyKey=currentKey; } if(proxySameUser) proxylogin=user; if(proxySamePass) proxypassword=passwd; else { if(useproxy && !proxyAutologin && !proxyKrbLogin && proxyKey.length()<=0) { bool ok; bool useBrokerPassForProxy=false; bool useBrokerUserForProxy=false; if(brokerMode) { useBrokerPassForProxy=(st->setting()->value ( sid+"/usebrokerpassforproxy", false ).toBool() ); useBrokerUserForProxy=(st->setting()->value ( sid+"/usebrokeruserforproxy", false ).toBool() ); if(useBrokerUserForProxy) { proxylogin=config.brokerUser; } } if(useBrokerPassForProxy) proxypassword=config.brokerPass; else proxypassword=QInputDialog::getText(0,proxylogin+"@"+proxyserver+":"+QString::number(proxyport), tr("Enter password for SSH proxy"),QLineEdit::Password,QString::null, &ok); } } delete st; sshConnection=startSshConnection ( host,sshPort,acceptRsa,user,passwd,autologin, krblogin, false, useproxy,proxyType,proxyserver, proxyport, proxylogin, proxypassword, proxyKey,proxyAutologin, proxyKrbLogin); sshConnection->set_kerberosDelegation(krbDelegation); return true; } void ONMainWindow::slotListSessions ( bool result,QString output, int ) { interDlg->hide(); x2goDebug<Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } if ( !startHidden ) { QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } else { QString printout = tr( "Connection failed: ") + output.toLatin1(); if ( output.indexOf ( "publickey,password" ) !=-1 ) x2goErrorf(4)<< tr( "Connection failed: ") + output + tr(" - Wrong password."); else x2goErrorf(5)<< tr( "Connection failed: ") + output; trayQuit(); } // currentKey=QString::null; setEnabled ( true ); passForm->setEnabled ( true ); slotShowPassForm(); pass->setFocus(); pass->selectAll(); return; } passForm->hide(); if ( !embedMode ) { setUsersEnabled ( false ); uname->setEnabled ( false ); u->setEnabled ( false ); } if ( managedMode ) { x2goDebug<<"Session data: " + config.sessiondata; if ( config.sessiondata.indexOf ( "|S|" ) ==-1 ) { x2goDebug<<"Starting new managed session."; startNewSession(); } else { x2goSession s=getSessionFromString (config.sessiondata); /* Check getSessionFromString for what this "invalid" string means. */ if (s.agentPid == "invalid") { startNewSession (); } else { x2goDebug << "Resuming managed session with ID: " + s.sessionId; resumeSession (s); } } return; } QStringList sessions; if(!brokerMode || shadowSession) { sessions=output.trimmed().split ( '\n', QString::SkipEmptyParts ); } else { sessions=config.sessiondata.trimmed().split ( '\n', QString::SkipEmptyParts ); } if ( shadowSession ) { selectSession ( sessions ); } else { if ( ( sessions.size() ==0 ) || ( sessions.size() ==1&&sessions[0].length() <5 ) ) startNewSession(); else if ( sessions.size() ==1 ) { x2goSession s=getSessionFromString ( sessions[0] ); QDesktopWidget wd; //we already selected the session if(brokerMode) { resumeSession(s); return; } /* Check getSessionFromString for what this "invalid" string means. */ if ((s.agentPid != "invalid") && (s.status == "S") && (isColorDepthOk (wd.depth (), s.colorDepth)) && (s.command == selectedCommand)&&autoresume) resumeSession ( s ); else { if ((startHidden) || (s.agentPid == "invalid")) startNewSession(); else selectSession ( sessions ); } } else { if ( !startHidden ) selectSession ( sessions ); else { for ( int i=0; i13 ) s.fsPort=lst[13]; if (brokerMode && lst.count()>14) s.brokerUser=lst[14]; s.colorDepth=0; if ( s.sessionId.indexOf ( "_dp" ) !=-1 ) { s.colorDepth=s.sessionId.split ( "_dp" ) [1].toInt(); } s.sessionType=x2goSession::DESKTOP; s.command=tr ( "unknown" ); if ( s.sessionId.indexOf ( "_st" ) !=-1 ) { QString cmdinfo=s.sessionId.split ( "_st" ) [1]; cmdinfo=cmdinfo.split ( "_" ) [0]; QChar st=cmdinfo[0]; if ( st=='R' ) s.sessionType=x2goSession::ROOTLESS; if ( st=='S' ) s.sessionType=x2goSession::SHADOW; if ( st=='K' ) { s.sessionType=x2goSession::KDRIVE; } QString command=cmdinfo.mid ( 1 ); if ( command.length() >0 ) s.command=command; } return s; } void ONMainWindow::sendEventToBroker(ONMainWindow::client_events ev) { if(!config.brokerEvents) { return; } if(ev <= lastBrokerEvent && resumingSession.sessionId == lastBrokerEventSession && ev != ALIVE) { return; } if(ev!=ALIVE) lastBrokerEvent=ev; lastBrokerEventSession=resumingSession.sessionId; QString event; switch(ev) { case CONNECTING: { event="CONNECTING"; resumingSession.connectedSince=QDateTime::currentDateTime().toTime_t(); break; } case CONNECTED: { event="CONNECTED"; resumingSession.connectedSince=QDateTime::currentDateTime().toTime_t(); if(config.brokerLiveEventsTimeout) brokerAliveTimer->start(config.brokerLiveEventsTimeout*1000); break; } case SUSPENDING: { event="SUSPENDING"; break; } case TERMINATING: { event="TERMINATING"; break; } case FINISHED: { event="FINISHED"; brokerAliveTimer->stop(); break; } case ALIVE: { event="ALIVE"; break; } } broker->sendEvent(event, resumingSession.sessionId,resumingSession.server, resumingSession.clientIp, getCurrentUname(), resumingSession.command, resumingSession.display, resumingSession.crTime, QDateTime::currentDateTime().toTime_t()-resumingSession.connectedSince); } void ONMainWindow::startNewSession() { newSession=true; QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString pack; bool kdrive=false; bool fullscreen; int height; int width; int quality; int speed; bool usekbd; bool rootless=false; resumingSession.published=false; bool setDPI=defaultSetDPI; bool xinerama = false; uint dpi=defaultDPI; QString layout; QString type; QString command; QString clipMode=defaultClipboardMode; QString xdmcpServer; runRemoteCommand=true; QString host=QString::null; runStartApp=true; removeAppsFromTray(); if ( useLdap ) { pack=defaultPack; fullscreen=defaultFullscreen; height=defaultHeight; width=defaultWidth; quality=defaultQuality; speed=defaultLink; xinerama = defaultXinerama; usekbd=defaultSetKbd; layout=defaultLayout[0]; type=defaultKbdType; command=defaultCmd; shadowSession=false; for ( int j=0; jgetLastSession())) { x2goDebug << "No session selected, returning without starting a session."; delete st; return; } sid=sessionExplorer->getLastSession()->id(); } else sid="embedded"; pack=st->setting()->value ( sid+"/pack", ( QVariant ) defaultPack ).toString(); fullscreen=st->setting()->value ( sid+"/fullscreen", ( QVariant ) defaultFullscreen ).toBool(); //if maxdim = true we set maximun display area available for the selected monitor if ( st->setting()->value(sid + "/maxdim", (QVariant) false).toBool()) { int selectedScreen = st->setting()->value(sid + "/display", (QVariant) -1).toInt(); height=QApplication::desktop()->availableGeometry(selectedScreen).height(); width=QApplication::desktop()->availableGeometry(selectedScreen).width(); } else if(st->setting()->value(sid + "/multidisp", (QVariant) false).toBool()) { //workaround to avoid wm set windows maximized, which will break moving and resizing of window width=800; height=600; } else { height=st->setting()->value ( sid+"/height", ( QVariant ) defaultHeight ).toInt(); width=st->setting()->value ( sid+"/width", ( QVariant ) defaultWidth ).toInt(); } setDPI=st->setting()->value ( sid+"/setdpi", ( QVariant ) defaultSetDPI ).toBool(); dpi=st->setting()->value ( sid+"/dpi", ( QVariant ) defaultDPI ).toUInt(); quality=st->setting()->value ( sid+"/quality", ( QVariant ) defaultQuality ).toInt(); speed=st->setting()->value ( sid+"/speed", ( QVariant ) defaultLink ).toInt(); xinerama = st->setting ()->value (sid + "/xinerama", static_cast(defaultXinerama)).toBool (); clipMode=st->setting()->value ( sid+"/clipboard", ( QVariant ) defaultClipboardMode ).toString(); usekbd=st->setting()->value ( sid+"/usekbd", ( QVariant ) defaultSetKbd ).toBool(); layout=st->setting()->value ( sid+"/layout", ( QVariant ) defaultLayout[0] ).toString(); type=st->setting()->value ( sid+"/type", ( QVariant ) defaultKbdType ).toString(); type.replace("\\",""); type.replace("(","\\("); type.replace(")","\\)"); if ( !embedMode ) { command=st->setting()->value ( sid+"/command", ( QVariant ) defaultCmd ).toString(); kdrive=st->setting()->value ( sid+"/kdrive", ( QVariant ) false ).toBool(); host=st->setting()->value ( sid+"/host", ( QVariant ) ( QString ) "localhost" ).toString(); rootless=st->setting()->value ( sid+"/rootless", ( QVariant ) false ).toBool(); resumingSession.published=st->setting()->value ( sid+"/published", ( QVariant ) false ).toBool(); xdmcpServer=st->setting()->value ( sid+"/xdmcpserver", ( QVariant ) "localhost" ).toString(); } else { command=config.command; if ( command=="SHADOW" ) { shadowSession=true; runRemoteCommand=false; } rootless= config.rootless; host=config.server; startEmbedded=false; resumingSession.published=config.published; if ( st->setting()->value ( sid+"/startembed", ( QVariant ) true ).toBool() ) { startEmbedded=true; fullscreen=false; height=bgFrame->size().height()-stb->height(); width=bgFrame->size().width(); if ( height<0 ||width<0 ) { height=defaultHeight; width=defaultWidth; } } if ( config.confConSpd ) speed=config.conSpeed; if ( config.confCompMet ) pack=config.compMet; if ( config.confImageQ ) quality=config.imageQ; if ( config.confDPI ) { dpi=config.dpi; setDPI=true; } if ( config.confKbd ) { layout=config.kbdLay; type=config.kbdType; usekbd=true; } } resumingSession.command=command; if ( command=="RDP" ) { if (fullscreen) { rootless=false; } else { rootless=true; } } if ( command=="XDMCP" ) { runRemoteCommand=false; } #ifdef Q_OS_WIN x2goDebug<<"Fullscreen: "<numScreens(); if ((!rootless) && (st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool())) { xorgMode=MULTIDISPLAY; uint disp=st->setting()->value ( sid+"/display",( QVariant ) 1 ).toUInt(); if (disp>displays) { disp=1; } localDisplayNumber=disp; } if(kdrive) { x2goDebug<<"KDRIVE session don't start X Server"; slotSetWinServersReady(); } if (! startXorgOnStart && ! kdrive) startXOrg(); #endif delete st; } if ( shadowSession ) { runRemoteCommand=false; } resumingSession.server=host; if (defaultLayout.size()>0) layout=cbLayout->currentText(); QString geometry; if ( fullscreen ) { geometry="fullscreen"; #ifdef Q_OS_WIN // fullscreen=false; maximizeProxyWin=true; x2goDebug<<"Maximize proxy win: "<pos() ); geometry+="+"+QString::number ( position.x() ) +"+"+ QString::number ( position.y() + stb->height() ); } } QString link; switch ( speed ) { case MODEM: link="modem"; break; case ISDN: link="isdn"; break; case ADSL: link="adsl"; break; case WAN: link="wan"; break; case LAN: link="lan"; break; } QFile file ( ":/txt/packs" ); if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) return; QTextStream in ( &file ); while ( !in.atEnd() ) { QString pc=in.readLine(); if ( pc.indexOf ( "-%" ) !=-1 ) { pc=pc.left ( pc.indexOf ( "-%" ) ); if ( pc==pack ) { pack+="-"+QString::number ( quality ); break; } } } file.close(); if ( selectSessionDlg->isVisible() ) { if ( !embedMode ) slotCloseSelectDlg(); else selectSessionDlg->hide(); } QDesktopWidget wd; QString depth=QString::number ( wd.depth() ); #ifdef Q_OS_DARWIN usekbd=0; type="query"; #endif QString sessTypeStr="D "; if ( rootless ) sessTypeStr="R "; if ( shadowSession ) sessTypeStr="S "; if ( resumingSession.published) { sessTypeStr="P "; command="PUBLISHED"; } if(kdrive) sessTypeStr="K "; QString dpiEnv; QString xdmcpEnv; QString xinerama_env = "X2GO_XINERAMA="; if ( runRemoteCommand==false && command=="XDMCP" ) xdmcpEnv="X2GOXDMCP="+xdmcpServer+" "; if ( setDPI ) { dpiEnv="X2GODPI="+QString::number ( dpi ) +" "; } if (xinerama) { xinerama_env += "yes"; } else { xinerama_env += "no"; } QString cmd=dpiEnv+xdmcpEnv+ xinerama_env + " x2gostartagent "+ geometry+" "+link+" "+pack+ " unix-kde-depth_"+depth+" "+layout+" "+type+" "; if ( usekbd ) cmd += "1 "; else cmd += "0 "; QFileInfo f ( command ); if ( !shadowSession ) { cmd+=sessTypeStr+f.fileName(); cmd+=" "+clipMode; } else { cmd+=sessTypeStr+QString::number ( shadowMode ) +"XSHAD"+ shadowUser+"XSHAD"+shadowDisplay; } resumingSession.fullscreen=fullscreen; x2goDebug<<"Executing remote command: "<hide(); return; } sshConnection->executeCommand ( cmd, this, SLOT ( slotRetResumeSess ( bool, QString,int ) ) ); passForm->hide(); } void ONMainWindow::resumeSession ( const x2goSession& s ) { newSession=false; runStartApp=false; applications.clear(); removeAppsFromTray(); QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString host=s.server; bool rootless=false; QString clipMode=defaultClipboardMode; QString pack; bool fullscreen; int height; int width; int quality; int speed; bool xinerama = false; bool usekbd; QString layout; QString type; removeAppsFromTray(); if ( useLdap ) { pack=defaultPack; fullscreen=defaultFullscreen; height=defaultHeight; width=defaultWidth; quality=defaultQuality; speed=defaultLink; xinerama = defaultXinerama; usekbd=defaultSetKbd; layout=defaultLayout[0]; type=defaultKbdType; sshConnection=findServerSshConnection(host); if (!sshConnection) { QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Server not available." ), QMessageBox::Ok, QMessageBox::NoButton ); return; } cleanServerSshConnections(); } else { QString sid; if ( !embedMode ) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, returning without resuming a session."; return; } sid=sessionExplorer->getLastSession()->id(); } else sid="embedded"; X2goSettings* st; if (!brokerMode) st=new X2goSettings( "sessions" ); else st=new X2goSettings(config.iniFile,QSettings::IniFormat); pack=st->setting()->value ( sid+"/pack", ( QVariant ) defaultPack ).toString(); fullscreen=st->setting()->value ( sid+"/fullscreen", ( QVariant ) defaultFullscreen ).toBool(); height=st->setting()->value ( sid+"/height", ( QVariant ) defaultHeight ).toInt(); width=st->setting()->value ( sid+"/width", ( QVariant ) defaultWidth ).toInt(); quality=st->setting()->value ( sid+"/quality", ( QVariant ) defaultQuality ).toInt(); speed=st->setting()->value ( sid+"/speed", ( QVariant ) defaultLink ).toInt(); xinerama = st->setting ()->value (sid + "/xinerama", static_cast(defaultXinerama)).toBool (); clipMode=st->setting()->value ( sid+"/clipboard", ( QVariant ) defaultClipboardMode ).toString(); usekbd=st->setting()->value ( sid+"/usekbd", ( QVariant ) defaultSetKbd ).toBool(); layout=st->setting()->value ( sid+"/layout", ( QVariant ) defaultLayout[0] ).toString(); type=st->setting()->value ( sid+"/type", ( QVariant ) defaultKbdType ).toString(); rootless=st->setting()->value ( sid+"/rootless", ( QVariant ) false ).toBool(); if ( brokerMode ) { host = config.serverIp; } else if ( embedMode ) { startEmbedded=false; if ( st->setting()->value ( sid+"/startembed", ( QVariant ) true ).toBool() ) { fullscreen=false; startEmbedded=true; height=bgFrame->size().height()-stb->height(); width=bgFrame->size().width(); if ( height<0 ||width<0 ) { height=defaultHeight; width=defaultWidth; } } rootless=config.rootless; host=config.server; if ( config.confConSpd ) speed=config.conSpeed; if ( config.confCompMet ) pack=config.compMet; if ( config.confImageQ ) quality=config.imageQ; if ( config.confKbd ) { layout=config.kbdLay; type=config.kbdType; usekbd=true; } } else { host=st->setting()->value ( sid+"/host", ( QVariant ) s.server ).toString(); } delete st; } if (defaultLayout.size()>0) layout=cbLayout->currentText(); QString geometry; #ifdef Q_OS_WIN maximizeProxyWin=false; proxyWinWidth=width; proxyWinHeight=height; // #ifdef CFGCLIENT xorgMode=WIN; if (fullscreen) xorgMode=FS; if (rootless) xorgMode=SAPP; xorgWidth=QString::number(width); xorgHeight=QString::number(height); if(s.sessionType == x2goSession::KDRIVE) { x2goDebug<<"KDRIVE session, don't start X-Server"; slotSetWinServersReady(); } if (! startXorgOnStart && (s.sessionType != x2goSession::KDRIVE)) startXOrg(); // #endif #else /* defined (Q_OS_WIN) */ UNUSED (rootless); #endif /* defined (Q_OS_WIN) */ if ( fullscreen ) { geometry="fullscreen"; #ifdef Q_OS_WIN // fullscreen=false; maximizeProxyWin=true; x2goDebug<<"Maximize proxy win: "<setDisabled(true); } else resumingSession.published=false; if ( selectSessionDlg->isVisible() ) { if ( !embedMode ) slotCloseSelectDlg(); else selectSessionDlg->hide(); } QString cmd="x2goresume-session "+s.sessionId+" "+geometry+ " "+link+" "+pack+" "+layout+ " "+type+" "; if ( usekbd ) cmd += "1"; else cmd += "0"; cmd +=" "+clipMode; QString xinerama_opt; if (xinerama) { xinerama_opt = "yes"; } else { xinerama_opt = "no"; } cmd += " " + xinerama_opt; sshConnection->executeCommand ( cmd, this, SLOT ( slotRetResumeSess ( bool, QString, int ) )); resumingSession=s; passForm->hide(); } /** * @brief ONMainWindow::setTrayIconToSessionIcon * @param info: message to be displayed in tray icon message * * Sets the tray session icon picture as the tray icon picture and * shows a tray icon information message about what X2Go Client * is currently doing. * * This message gives the user some feedback while the X2Go session * window is displayed. * */ void ONMainWindow::setTrayIconToSessionIcon(QString info) { //set session icon to tray icon if (trayIcon && sessionExplorer->getLastSession()) { X2goSettings* st; if (!brokerMode) st=new X2goSettings( "sessions" ); else st= new X2goSettings(config.iniFile,QSettings::IniFormat); QString sid; if ( !embedMode ) sid=sessionExplorer->getLastSession()->id(); else sid="embedded"; if (!keepTrayIcon) { QString imagePath = wrap_legacy_resource_URIs (expandHome(st->setting()->value(sid + "/icon", (QVariant) QString(":/img/icons/128x128/x2go.png")).toString())); trayIcon->setIcon(QIcon (imagePath)); } QString name=st->setting()->value ( sid +"/name").toString() ; //send a information notification about the connection is done trayIcon->showMessage("X2Go - " + name, info, QSystemTrayIcon::Information, 15000); delete (st); } } void ONMainWindow::selectSession ( QStringList& sessions ) { setEnabled ( true ); sessionStatusDlg->hide(); passForm->hide(); if ( !shadowSession ) { x2goDebug<<"No shadow session."; if ( !miniMode ) selectSesDlgLayout->setContentsMargins ( 25,25,10,10 ); bNew->show(); bSusp->show(); bTerm->show(); sOk->show(); sCancel->show(); desktopFilter->hide(); desktopFilterCb->hide(); bShadow->hide(); bShadowView->hide(); bCancel->hide(); // model->clear(); model->removeRows ( 0,model->rowCount() ); selectSessionLabel->setText ( tr ( "Select session:" ) ); selectedSessions.clear(); QFontMetrics fm ( sessTv->font() ); for ( int row = 0; row < sessions.size(); ++row ) { x2goDebug<<"Decoding session string:" + sessions[row]; x2goSession s=getSessionFromString ( sessions[row] ); /* Check getSessionFromString for what this "invalid" string means. */ if (s.agentPid == "invalid") { continue; } selectedSessions.append ( s ); QStandardItem *item; if(!brokerMode) item= new QStandardItem ( s.display ); else item= new QStandardItem ( s.brokerUser ); model->setItem ( row,S_DISPLAY,item ); if ( s.status=="R" ) item= new QStandardItem ( tr ( "running" ) ); else item= new QStandardItem ( tr ( "suspended" ) ); model->setItem ( row,S_STATUS,item ); item= new QStandardItem ( transAppName ( s.command ) ); model->setItem ( row,S_COMMAND,item ); QString type=tr ( "Desktop" ); if ( s.sessionType==x2goSession::ROOTLESS ) type=tr ( "single application" ); if ( s.sessionType==x2goSession::SHADOW ) type=tr ( "shadow session" ); if ( s.sessionType==x2goSession::KDRIVE ) type=tr ( "X2GoKDrive session" ); item= new QStandardItem ( type ); model->setItem ( row,S_TYPE,item ); item= new QStandardItem ( s.crTime ); model->setItem ( row,S_CRTIME,item ); item= new QStandardItem ( s.server ); model->setItem ( row,S_SERVER,item ); item= new QStandardItem ( s.clientIp ); model->setItem ( row,S_IP,item ); item= new QStandardItem ( s.sessionId ); model->setItem ( row,S_ID,item ); for ( int j=0; j<8; ++j ) { QString txt= model->index ( row,j ).data().toString(); if ( sessTv->header()->sectionSize ( j ) < fm.width ( txt ) +6 ) { sessTv->header()->resizeSection ( j,fm.width ( txt ) +6 ); } } } } else { shadowMode=SHADOW_VIEWONLY; selectedDesktops.clear(); selectedDesktops=sessions; if ( sessions.size() ==0 ) { QMessageBox::information ( this,tr ( "Information" ), tr ( "No accessible desktop " "found." ) ); slotCloseSelectDlg(); return; } sessTv->setModel ( ( QAbstractItemModel* ) modelDesktop ); desktopFilter->show(); desktopFilterCb->show(); sOk->hide(); sCancel->hide(); bShadow->show(); bCancel->show(); bShadowView->show(); desktopFilter->setText ( tr ( "Filter" ) ); sessions.sort(); if ( !miniMode ) selectSesDlgLayout->setContentsMargins ( 25,25,25,25 ); bNew->hide(); bSusp->hide(); bTerm->hide(); selectSessionLabel->setText ( tr ( "Select desktop:" ) ); filterDesktops ( "" ); desktopFilter->setFocus(); desktopFilter->selectAll(); if ( !embedMode ) { X2goSettings* st; if (!brokerMode) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, returning without starting a shadow session."; return; } st=new X2goSettings( "sessions" ); QString sid=sessionExplorer->getLastSession()->id(); QString suser = st->setting()->value(sid + "/shadowuser", (QVariant) QString::null).toString(); QString sdisplay = st->setting()->value(sid + "/shadowdisplay", (QVariant) QString::null).toString(); bool fullAccess= st->setting()->value(sid + "/shadowfullaccess", (QVariant) false).toBool(); delete (st); if(suser != QString::null && sdisplay != QString::null) { shadowUser=suser; shadowDisplay=sdisplay; if(fullAccess) shadowMode=SHADOW_FULL; else shadowMode=SHADOW_VIEWONLY; startNewSession(); return; } } } } sessTv->setCurrentIndex ( sessTv->model()->index ( 0, 0 ) ); sessTv->setFocus(); selectSessionDlg->show(); if( startHidden && shadowSession && sessTv->model()->rowCount() == 1 ) slotShadowSess(); } void ONMainWindow::slotCloseSelectDlg() { selectSessionDlg->hide(); if ( !embedMode ) { u->setEnabled ( true ); uname->setEnabled ( true ); } slotShowPassForm(); } void ONMainWindow::slotActivated ( const QModelIndex& index ) { if ( !shadowSession ) { QString status=sessTv->model()->index ( index.row(), S_STATUS ).data().toString(); if ( status==tr ( "running" ) ) { bSusp->setEnabled ( true ); sOk->setEnabled ( false ); } else { bSusp->setEnabled ( false ); sOk->setEnabled ( true ); } bTerm->setEnabled ( true ); if ( status==QString::null ) { sOk->setEnabled ( false ); bTerm->setEnabled ( false ); } } else { QString user=sessTv->model()->index ( index.row(), D_USER ).data().toString(); bShadowView->setEnabled ( true ); bShadow->setEnabled ( true ); } } void ONMainWindow::slotResumeSess() { x2goSession s=getSelectedSession(); if(brokerMode) { broker->resumeSession(s.sessionId, s.server); return; } QDesktopWidget wd; if ( isColorDepthOk ( wd.depth(),s.colorDepth ) ) { if ( s.status=="R" && ! resumeAfterSuspending) { resumeAfterSuspending=true; slotSuspendSess(); return; } resumeAfterSuspending=false; resumeSession ( s ); } else { int res; res=QMessageBox::warning ( 0l,tr ( "Warning" ), tr ("Your current color depth is different from " "the session's color depth. This may cause " "problems reconnecting to this session and " "in most cases you will lose the " "session and have to start a new one! ") + tr ("It's highly recommended to change the color " "depth of your display to %n bit(s) and " "restart your X.Org Server before you " "reconnect to this X2Go session.", "%n will be replaced with a number", s.colorDepth) + tr ("
" "Do you want to resume this session anyway?"), tr ( "Yes" ), tr ( "No" ) ); if ( res==0 ) resumeSession ( s ); } } void ONMainWindow::suspendFromBroker(const QString& sid) { if(proxyRunning && sid ==resumingSession.sessionId) { x2goDebug<<"Suspending session from broker"; sendEventToBroker(SUSPENDING); suspendSession(sid); } } void ONMainWindow::terminateFromBroker(const QString& sid) { if(proxyRunning && sid ==resumingSession.sessionId) { x2goDebug<<"Suspending session from broker"; sendEventToBroker(TERMINATING); termSession(sid,false); } } void ONMainWindow::slotSuspendSess() { #ifdef Q_OS_UNIX if (directRDP) { nxproxy->terminate(); proxyRunning=false; return; } #endif QString passwd; QString user=getCurrentUname(); passwd=getCurrentPass(); selectSessionDlg->setEnabled ( false ); QString sessId=sessTv->model()->index ( sessTv->currentIndex().row(), S_ID ).data().toString(); QString host=sessTv->model()->index ( sessTv->currentIndex().row(), S_SERVER ).data().toString(); if ( !useLdap ) { if ( !brokerMode ) { if ( embedMode ) { host=config.server; } else { X2goSettings st ( "sessions" ); if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, returning without suspending a session."; return; } QString sid=sessionExplorer->getLastSession()->id(); host=st.setting()->value ( sid+"/host", ( QVariant ) host ).toString(); } } } else { sshConnection=findServerSshConnection(host); if (!sshConnection) { QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Server not available." ), QMessageBox::Ok, QMessageBox::NoButton ); return; } } if(brokerMode) { suspendBrokerSession(sessId, host); } else { suspendSession ( sessId ); } } void ONMainWindow::slotSuspendSessFromSt() { if(brokerMode) { sendEventToBroker(SUSPENDING); } #ifdef Q_OS_UNIX if (directRDP) { nxproxy->terminate(); proxyRunning=false; return; } #endif QString passwd; QString user=getCurrentUname(); passwd=getCurrentPass(); setStatStatus ( tr ( "suspending" ) ); sbExp->setEnabled ( false ); if ( !shadowSession ) suspendSession ( resumingSession.sessionId ); else termSession ( resumingSession.sessionId,false ); } void ONMainWindow::slotTermSessFromSt() { #ifdef Q_OS_UNIX if (directRDP) { if(brokerMode) { sendEventToBroker(TERMINATING); } x2goDebug<<"Terminating direct RDP session."; nxproxy->terminate(); proxyRunning=false; return; } #endif if ( !shadowSession ) { if ( termSession ( resumingSession.sessionId ) ) { sbExp->setEnabled ( false ); if(brokerMode) { sendEventToBroker(TERMINATING); } setStatStatus ( tr ( "terminating" ) ); } } else { sbExp->setEnabled ( false ); if(brokerMode) { sendEventToBroker(TERMINATING); } termSession ( resumingSession.sessionId,false ); } } void ONMainWindow::slotRetSuspSess ( bool result, QString output, int ) { setEnabled ( true ); if ( result==false ) { QString message=tr ( "Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) +message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } else { if ( selectSessionDlg->isVisible() ) { ( ( QStandardItemModel* ) ( sessTv->model() ) )->item ( sessTv->currentIndex().row(), S_STATUS )->setData ( QVariant ( ( QString ) tr ( "suspended" ) ), Qt::DisplayRole ); bSusp->setEnabled ( false ); sOk->setEnabled ( true ); } } if ( selectSessionDlg->isVisible() ) selectSessionDlg->setEnabled ( true ); if (resumeAfterSuspending) { slotResumeSess(); } } void ONMainWindow::slotTermSess() { #ifdef Q_OS_UNIX if (directRDP) { nxproxy->terminate(); proxyRunning=false; return; } #endif selectSessionDlg->setEnabled ( false ); QString sessId=sessTv->model()->index ( sessTv->currentIndex().row(), S_ID ).data().toString(); QString host=sessTv->model()->index ( sessTv->currentIndex().row(), S_SERVER ).data().toString(); if ( !useLdap ) { if ( !embedMode ) { X2goSettings st ( "sessions" ); if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, returning without terminating a session."; return; } QString sid=sessionExplorer->getLastSession()->id(); } } else { sshConnection=findServerSshConnection(host); if (!sshConnection) { QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Server not available." ), QMessageBox::Ok, QMessageBox::NoButton ); return; } } if(brokerMode) { termBrokerSession(sessId, host); } else { termSession ( sessId ); } } void ONMainWindow::slotNewSess() { startNewSession(); } void ONMainWindow::slotRetTermSess ( bool result, QString output, int ) { setEnabled ( true ); if ( result==false ) { QString message=tr ( "Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) +message; } QMessageBox::critical ( 0l,tr ( "Error" ), message,QMessageBox::Ok, QMessageBox::NoButton ); } else { if ( selectSessionDlg->isVisible() ) { sessTv->model()->removeRow ( sessTv->currentIndex().row() ); slotActivated ( sessTv->currentIndex() ); } } if ( selectSessionDlg->isVisible() ) selectSessionDlg->setEnabled ( true ); } void ONMainWindow::slotRetResumeSess ( bool result, QString output, int ) { x2goDebug<<"Agent output: "<Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong Password!

" ) +message; } if ( output.indexOf ( "LIMIT" ) !=-1 ) { QString sessions=output.mid ( output.indexOf ( "LIMIT" ) +6 ); message="Sessions limit reached:"+sessions; } if ( output.indexOf ( "ACCESS DENIED" ) !=-1 ) { message="Access denied for user"; } QMessageBox::critical ( 0l,tr ( "Error" ), message,QMessageBox::Ok, QMessageBox::NoButton ); slotShowPassForm(); return; } output.replace ( " ","" ); QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString host; bool sound=true; bool kdrive=false; int sndSystem=PULSE; QString sndPort; #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) sndPort="4713"; #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ bool startSoundServer=true; bool sshSndTunnel=true; if ( useLdap ) { sound=startSound; startSoundServer=LDAPSndStartServer; if ( LDAPSndSys=="arts" ) sndSystem=ARTS; if ( LDAPSndSys=="esd" ) sndSystem=ESD; sndPort=LDAPSndPort; } else { QString sid; if ( !embedMode ) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, this should not happen since we already started resuming a session."; return; } sid=sessionExplorer->getLastSession()->id(); } else sid="embedded"; X2goSettings* st; if (!brokerMode) st= new X2goSettings( "sessions" ); else st= new X2goSettings(config.iniFile,QSettings::IniFormat); kdrive=st->setting()->value ( sid+"/kdrive", ( QVariant ) false ).toBool(); sound=st->setting()->value ( sid+"/sound", ( QVariant ) true ).toBool(); QString sndsys=st->setting()->value ( sid+"/soundsystem", ( QVariant ) "pulse" ).toString(); if ( sndsys=="arts" ) sndSystem=ARTS; if ( sndsys=="esd" ) sndSystem=ESD; #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) sndPort=st->setting()->value ( sid+"/sndport" ).toString(); #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ startSoundServer=st->setting()->value ( sid+"/startsoundsystem", true ).toBool(); if ( embedMode&&config.confSnd ) { sound=config.useSnd; } #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) bool defPort=st->setting()->value ( sid+ "/defsndport",true ).toBool(); if ( defPort ) { switch ( sndSystem ) { case PULSE: sndPort="4713"; break; case ESD: sndPort="16001"; break; } } #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ sshSndTunnel=st->setting()->value ( sid+"/soundtunnel", true ).toBool(); #if defined (Q_OS_WIN) || defined (Q_OS_DARWIN) if (sound) { if(!pulseManager || !(pulseManager->is_server_running())) { X2goSettings st ("settings"); bool disablePA = st.setting ()->value ("pulse/disable", (QVariant) false).toBool (); if(!systemDisablePA && ! disablePA) { show_RichText_WarningMsgBox (tr("PulseAudio is not running"), tr("Sound output will be disabled for this session. Please enable PulseAudio in the configuration dialog or disable sound in the session settings"),true); } sound=false; } else { switch (sndSystem) { case PULSE: sndPort = QString::number (pulseManager->get_pulse_port ()); break; case ESD: sndPort = QString::number (pulseManager->get_esd_port ()); break; } } } #endif /* defined (Q_OS_WIN) || defined (Q_OS_DARWIN) */ delete st; } //Will be used in runCommand startSessSound=sound; startSessSndSystem=sndSystem; if ( newSession ) { QString sString=output.trimmed(); sString.replace ( '\n','|' ); host=resumingSession.server; resumingSession=getNewSessionFromString ( sString ); if(kdrive) { resumingSession.sessionType=x2goSession::KDRIVE; } resumingSession.server=host; resumingSession.crTime=QDateTime::currentDateTime().toString ( "dd.MM.yy HH:mm:ss" ); if ( managedMode ) { //replace session data for future resuming config.sessiondata=resumingSession.agentPid+"|"+ resumingSession.sessionId+"|"+ resumingSession.display+"|"+ resumingSession.server+"|"+ "S|"+ resumingSession.crTime+"|"+ resumingSession.cookie+"|"+ resumingSession.clientIp+"|"+ resumingSession.grPort+"|"+ resumingSession.sndPort+"|"+ resumingSession.crTime+"|"+ user+"|"+ "0|"+ resumingSession.fsPort; } //change the trayicon picture if (debugging) { setTrayIconToSessionIcon(tr("New session started") + ": " + resumingSession.sessionId); } else { setTrayIconToSessionIcon(tr("New session started") + "."); } } else { if(resumingSession.sessionType==x2goSession::KDRIVE) { qDebug()<<"resuming kdrive session"; } else { qDebug()<<"resuming normal session"; } host=resumingSession.server; QStringList outputLines=output.split("\n",QString::SkipEmptyParts); foreach(QString line,outputLines) { if (line.indexOf("gr_port=")!=-1) { resumingSession.grPort=line.replace("gr_port=",""); x2goDebug<<"New gr_port: "<getLastSession()->id(); host=st.setting()->value ( sid+"/host", ( QVariant ) host ).toString(); } resumingSession.server=host; } localGraphicPort=resumingSession.grPort; int iport=localGraphicPort.toInt() +1000; while ( iport == resumingSession.sndPort.toInt() || iport == resumingSession.fsPort.toInt() || isServerRunning ( iport ) ) ++iport; localGraphicPort=QString::number ( iport ); sshConnection->startTunnel ( "localhost",resumingSession.grPort.toInt(),"localhost", localGraphicPort.toInt(), false, this, SLOT ( slotTunnelOk(int) ), SLOT ( slotTunnelFailed ( bool, QString,int ) ) ); if ( shadowSession ) return; sndTunnel=0l; if ( sound ) { if ( sndSystem==PULSE ) { startSoundServer=false; QString scmd; if ( !sshSndTunnel ) scmd="echo \"default-server=$(echo " "\"$SSH_CLIENT\" | awk '{print $1}'):"+ sndPort+ "\" > \"${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf\"" ";echo \"cookie-file=${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie"+ "\" >> \"${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf\"" ";echo \"autospawn=no\" >>" "\"${HOME}/.x2go/C-" + resumingSession.sessionId + "/.pulse-client.conf\""; else scmd="echo \"default-server=localhost:"+ resumingSession.sndPort+ "\" > \"${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf\"" ";echo \"cookie-file=${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie"+ "\" >> \"${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf\"" ";echo \"autospawn=no\" >>" "\"${HOME}/.x2go/C-" + resumingSession.sessionId + "/.pulse-client.conf\""; sshConnection->executeCommand (scmd); bool sysPulse=false; #ifdef Q_OS_UNIX loadPulseModuleNativeProtocol(); QFile file ( "/etc/default/pulseaudio" ); if ( file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) { while ( !file.atEnd() ) { QByteArray line = file.readLine(); int pos=line.indexOf ( "PULSEAUDIO_SYSTEM_START=1" ); if ( pos!=-1 ) { int commentPos=line.indexOf ( "#" ); if ( commentPos==-1 || commentPos>pos ) { sysPulse=true; break; } } } file.close(); } #endif QString pulsecookie_filename = ""; if ( sysPulse ) { if ( QFile::exists("/run/pulse/.config/pulse/cookie") ) { pulsecookie_filename = "/run/pulse/.config/pulse/cookie"; } else if ( QFile::exists("/run/pulse/.pulse-cookie") ) { pulsecookie_filename = "/run/pulse/.pulse-cookie"; } else if ( QFile::exists("/var/run/pulse/.config/pulse/cookie") ) { pulsecookie_filename = "/var/run/pulse/.config/pulse/cookie"; } else if ( QFile::exists("/var/run/pulse/.pulse-cookie") ) { pulsecookie_filename = "/var/run/pulse/.pulse-cookie"; } if ( pulsecookie_filename.length() > 0 ) { sshConnection->copyFile( pulsecookie_filename, "$HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie", this, SLOT ( slotPCookieReady ( bool, QString,int ))); } } else { #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) if ( QFile::exists(homeDir+"/.config/pulse/cookie") ) { pulsecookie_filename = homeDir+"/.config/pulse/cookie"; } else if ( QFile::exists(homeDir+"/.pulse-cookie") ) { pulsecookie_filename = homeDir+"/.pulse-cookie"; } if ( pulsecookie_filename.length() > 0 ) { sshConnection->copyFile(pulsecookie_filename, "$HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie", this, SLOT ( slotPCookieReady ( bool, QString,int ))); } #else /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ QString cooFile = QDir::toNativeSeparators (QDir (pulseManager->get_pulse_dir ().absolutePath () + "/.pulse-cookie").absolutePath ()); QString destFile="$HOME/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-cookie"; sshConnection->copyFile(cooFile, destFile, this, SLOT ( slotPCookieReady ( bool, QString,int ))); #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ } } if ( sndSystem==ESD ) { #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) sshConnection->copyFile(homeDir+"/.esd_auth", "$HOME/.esd_auth" ); #else /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ QString cooFile = QDir::toNativeSeparators (QDir (pulseManager->get_pulse_dir ().absolutePath () + "/.esd_auth").absolutePath ()); QString destFile="$HOME/.esd_auth"; sshConnection->copyFile(cooFile, destFile ); #endif /* defined (Q_OS_UNIX) */ } /* Windows and Darwin are covered by PulseManager. */ #if !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) if ( startSoundServer ) { soundServer=new QProcess ( this ); QString acmd="artsd",ecmd="esd"; if ( sndSystem==ESD ) soundServer->start ( ecmd+ " -tcp -nobeeps -bind localhost -port "+ resumingSession.sndPort ); if ( sndSystem==ARTS ) soundServer->start ( acmd+" -u -N -p "+ resumingSession.sndPort ); sndPort=resumingSession.sndPort; } #endif /* !defined (Q_OS_WIN) && !defined (Q_OS_DARWIN) */ if ( sshSndTunnel ) { sndTunnel=sshConnection->startTunnel ( "localhost", resumingSession.sndPort.toInt(),"127.0.0.1", sndPort.toInt(),true,this,NULL, SLOT ( slotSndTunnelFailed ( bool, QString, int ) )); } } } x2goSession ONMainWindow::getSelectedSession() { QString sessId=sessTv->model()->index ( sessTv->currentIndex().row(), S_ID ).data().toString(); for ( int i=0; igetLastSession())) { x2goDebug << "No session selected, not searching for proxy window."; return; } sid=sessionExplorer->getLastSession()->id(); } else sid="embedded"; if (brokerMode) st=new X2goSettings(config.iniFile,QSettings::IniFormat); else st= new X2goSettings( "sessions" ); randr=st->setting()->value ( sid+"/xinerama", ( QVariant ) defaultXinerama ).toBool(); fs=st->setting()->value ( sid+"/fullscreen", ( QVariant ) defaultFullscreen).toBool(); width=st->setting()->value ( sid+"/width", ( QVariant ) "800").toString(); height=st->setting()->value ( sid+"/height", ( QVariant ) "600").toString(); if (st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool()) { dispNumber=st->setting()->value ( sid+"/display", (QVariant ) "1").toString(); multidisp=st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool(); } delete st; } } QStringList options; #ifdef Q_OS_WIN //restore real path, as we not using cygwin for x2gokdriveclient nxroot=homeDir +"/.x2go"; dirpath=nxroot+"/S-"+resumingSession.sessionId; #endif proxyCmd="x2gokdriveclient"; options<<"--connect"<<"localhost"<<"--port"<start ( proxyCmd, options ); } else { x2goDebug<<"Starting NX proxy, command: " + proxyCmd; nxproxy->start ( proxyCmd); } proxyRunning=true; if(brokerMode) { sendEventToBroker(CONNECTING); } // always search for proxy window on linux. On Windows only in window mode #ifdef Q_OS_WIN if (xorgMode==WIN) { #endif proxyWinTimer->start ( 300 ); #ifdef Q_OS_WIN } #endif if ( embedMode ) { // proxyWinTimer->start ( 300 ); if ( !startEmbedded ) { act_embedContol->setText ( tr ( "Attach X2Go window" ) ); } } #ifdef Q_OS_WIN else { // #ifdef CFGCLIENT // // if using XMing, we must find proxy win for case, that we should make it fullscreen // if(useInternalX&& (internalX==XMING)) // #endif // proxyWinTimer->start ( 300 ); } #endif showSessionStatus(); QTimer::singleShot ( 30000,this,SLOT ( slotRestartProxy() ) ); } void ONMainWindow::slotTunnelFailed ( bool result, QString output, int ) { if ( result==false ) { if ( !managedMode ) { QString message=tr ( "Unable to create SSH tunnel for X2Go session (NX) startup:\n" ) +output; QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } // if ( tunnel ) // delete tunnel; // if ( sndTunnel ) // delete sndTunnel; // if ( fsTunnel ) // delete fsTunnel; // if ( soundServer ) // delete soundServer; tunnel=sndTunnel=fsTunnel=0l; soundServer=0l; nxproxy=0l; proxyRunning=false; if ( !managedMode ) slotShowPassForm(); } } void ONMainWindow::slotSndTunnelFailed ( bool result, QString output, int ) { if ( result==false ) { if ( !managedMode ) { QString message=tr ( "Unable to create SSH tunnel for audio data:\n" ) +output; QMessageBox::warning ( 0l,tr ( "Warning" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } sndTunnel=0l; } } #ifdef Q_OS_DARWIN void ONMainWindow::slotSetModMap() { if (!nxproxy) { return; } if (kbMap.isEmpty ()) { QProcess pr (this); QProcessEnvironment tmp_env = QProcessEnvironment::systemEnvironment (); QString path_val = tmp_env.value ("PATH"); /* Let's set a reasonable default value if none is provided. */ if (path_val.isEmpty ()) { /* Prefer the default MacPorts prefix. */ 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"; tmp_env.insert ("PATH", path_val); } else { /* Search for and add specific directories to the PATH value, if necessary. */ QStringList to_back, to_front; to_back << "/opt/X11/bin"; to_front << MACPORTS_PREFIX "/bin" << "/usr/local/bin"; path_val = add_to_path (path_val, to_back); path_val = add_to_path (path_val, to_front, false); /* Insert will overwrite the value automatically. */ tmp_env.insert ("PATH", path_val); /* * Also alter our own environment so we can actually * execute xmodmap and friends later on. */ qputenv ("PATH", path_val.toUtf8 ()); } pr.setProcessEnvironment (tmp_env); QStringList key_map_fetch_args; key_map_fetch_args << "-pke"; pr.start ("xmodmap", key_map_fetch_args); bool key_map_fetch_ret = pr.waitForStarted (); if (!key_map_fetch_ret) { handle_xmodmap_error (pr); } else { key_map_fetch_ret = pr.waitForFinished (); if (!key_map_fetch_ret) { handle_xmodmap_error (pr); } kbMap = pr.readAllStandardOutput (); QStringList mod_fetch_args; mod_fetch_args << "-pm"; pr.start ("xmodmap", mod_fetch_args); bool mod_fetch_ret = pr.waitForStarted (); if (!mod_fetch_ret) { handle_xmodmap_error (pr); } else { mod_fetch_ret = pr.waitForFinished (); if (!mod_fetch_ret) { handle_xmodmap_error (pr); } QString modifiers = pr.readAllStandardOutput (); x2goDebug << "modifiers: " << modifiers; /* Reset all modifiers first. */ kbMap += "clear shift\nclear lock\nclear control\nclear mod1\nclear mod2\nclear mod3\nclear mod4\nclear mod5\n"; /* And set them back again. */ QStringList lines = modifiers.split ("\n", QString::SkipEmptyParts); for (int i = 0; i < lines.count (); ++i) { QStringList parts = lines[i].split (" ", QString::SkipEmptyParts); if (parts.count () < 2) { continue; } QString mod = parts[0]; if ((mod == "shift") || (mod == "lock") || (mod == "control") || (mod == "mod1") || (mod == "mod2") || (mod == "mod3") || (mod == "mod4") || (mod == "mod5")) { for (int j = 1; j < parts.count (); ++j) { if (parts[j].indexOf ("(") == -1) { kbMap += "add " + mod + " = " + parts[j] + "\n"; } } } } } } } if (kbMap.isEmpty ()) { x2goWarningf (9) << "Could not fetch keyboard map via xmodmap. Internal error. Not synchronizing with remote side."; } else { /* Send modified map to server. */ QString cmd = "export DISPLAY=\":" + resumingSession.display + "\"; echo \"" + kbMap + "\" | xmodmap -"; sshConnection->executeCommand (cmd); } } void ONMainWindow::handle_xmodmap_error (QProcess &proc) { QString main_text ("xmodmap "); QString informative_text; QProcessEnvironment proc_env = QProcessEnvironment::systemEnvironment (); /* If the process has a special env, fetch it. */ if (!(proc.processEnvironment ().isEmpty ())) { proc_env = proc.processEnvironment (); } switch (proc.error ()) { case QProcess::FailedToStart: { main_text += tr ("failed to start."); informative_text += tr ("This likely means the binary is not available.\n" "The current search path is: "); QString path_val = proc_env.value ("PATH", "unknown"); /* Add a newline every 100 characters. */ for (std::size_t i = 100; i < static_cast (path_val.size ()); i += 100) { path_val.insert (i, "\n"); } informative_text += path_val; break; } case QProcess::Crashed: { main_text += tr ("returned a non-zero exit code or crashed otherwise."); informative_text += tr ("Execution failed, exit code was: "); informative_text += QString::number (proc.exitCode ()); break; } case QProcess::Timedout: { main_text += tr ("didn't start up in time."); informative_text = tr ("This error shouldn't come up."); break; } case QProcess::WriteError: { main_text += tr ("didn't accept a write operation."); informative_text = tr ("It is probably not running correctly or crashed in-between."); break; } case QProcess::ReadError: { main_text = tr ("Unable to read from xmodmap."); informative_text = tr ("It is probably not running correctly or crashed in-between."); break; } case QProcess::UnknownError: { main_text += tr ("encountered an unknown error during start up or execution."); break; } default: { main_text += tr ("experienced an undefined error."); break; } } if (!informative_text.isEmpty ()) { informative_text += "\n\n"; } informative_text += tr ("X2Go Client will now terminate.\n\n" "File a bug report as outlined on the bugs wiki page."); show_RichText_ErrorMsgBox (main_text, informative_text); trayQuit (); } #endif void ONMainWindow::slotProxyError ( QProcess::ProcessError err ) { #ifdef Q_OS_UNIX if(err==QProcess::FailedToStart && directRDP) { QString main_text = tr("Failed to start RDP or XDMCP client"); QString informative_text = tr ("Check session settings and ensure that selected client is installed on your system."); show_RichText_ErrorMsgBox (main_text, informative_text); } #endif slotProxyFinished ( -1,QProcess::CrashExit ); } void ONMainWindow::slotProxyFinished ( int,QProcess::ExitStatus ) { if(brokerMode) { sendEventToBroker(FINISHED); } #ifdef Q_OS_DARWIN if (modMapTimer) { disconnect (modMapTimer, SIGNAL (timeout ()), this, SLOT (slotSetModMap ())); modMapTimer->stop (); delete (modMapTimer); modMapTimer = 0; } kbMap = QString (); //fixes bug, when mainwindow inputs not accepting focus under mac setFocus (); #endif //set tray icon to default if (trayIcon && !keepTrayIcon) trayIcon->setIcon(QIcon ( ":/img/icons/128x128/x2go.png") ); if ( embedMode ) { proxyWinTimer->stop(); setEmbedSessionActionsEnabled ( false ); } #ifdef Q_OS_WIN else proxyWinTimer->stop(); if (! startXorgOnStart) { if (xorg) { if (xorg->state() ==QProcess::Running) { xorg->terminate(); delete xorg; xorg=0; } } } #endif if ( closeEventSent ) return; if ( soundServer ) delete soundServer; if ( spoolTimer ) delete spoolTimer; x2goDebug<<"Deleting Proxy." ; disconnect ( nxproxy,SIGNAL ( error ( QProcess::ProcessError ) ),this, SLOT ( slotProxyError ( QProcess::ProcessError ) ) ); disconnect ( nxproxy,SIGNAL ( finished ( int,QProcess::ExitStatus ) ),this, SLOT ( slotProxyFinished ( int,QProcess::ExitStatus ) ) ); disconnect ( nxproxy,SIGNAL ( readyReadStandardError() ),this, SLOT ( slotProxyStderr() ) ); disconnect ( nxproxy,SIGNAL ( readyReadStandardOutput() ),this, SLOT ( slotProxyStdout() ) ); proxyRunning=false; if (trayEnabled) { trayIconActiveConnectionMenu->setTitle(tr("Not connected")); trayIconActiveConnectionMenu->setEnabled(false); if (trayMaxDiscon) showNormal(); } trayAutoHidden=false; bool emergencyExit=false; if(proxyErrString.indexOf("No data received from remote proxy")!=-1) { emergencyExit=true; x2goWarningf(4)<< tr( "Emergency exit." ); } if ( nxproxy ) { if ( nxproxy->state() ==QProcess::Running ) { emergencyExit=true; x2goWarningf(5)<< tr( "Waiting for proxy to exit." ); if ( !nxproxy->waitForFinished ( 3000 ) ) { x2goWarningf(6)<< tr( "Proxy didn't terminate after 3 seconds. Killing the proxy." ); nxproxy->kill(); } } #ifdef Q_OS_UNIX if (directRDP) nxproxy=0; #endif } x2goDebug<<"Waiting for proxy to exit."; spoolTimer=0l; tunnel=sndTunnel=fsTunnel=0l; soundServer=0l; nxproxy=0l; proxyWinId=0; #ifdef Q_OS_UNIX if (directRDP) { if (closeDisconnect) { close(); } pass->setText ( "" ); QTimer::singleShot ( 2000,this, SLOT ( slotShowPassForm() ) ); return; } #endif if ( !emergencyExit && !shadowSession && !usePGPCard && ! ( embedMode && ( config.checkexitstatus==false ) ) ) { x2goDebug<<"Checking exit status."; check_cmd_status(); } else { x2goDebug<<"Deleting SSH connection instance."; delete sshConnection; x2goDebug<<"Deleted SSH connection instance." ; sshConnection=0; if (startHidden) { x2goInfof(9) << tr("Closing X2Go Client because it was started in hidden mode."); close(); } else if (closeDisconnect) { x2goInfof(10) << tr("Closing X2Go Client because the --close-disconnect parameter was passed."); close(); } } if ( readExportsFrom!=QString::null ) { exportTimer->stop(); if ( extLogin ) { currentKey=QString::null; } } if ( printSupport ) cleanPrintSpool(); if ( !restartResume ) { if ( brokerMode && (!config.brokerAutologoff) ) { x2goDebug<<"Re-reading user's session profiles from broker."; QTimer::singleShot ( 2000,broker, SLOT ( getUserSessions() ) ); } else if ( brokerMode && config.brokerAutologoff ) { x2goDebug<<"Logging off from broker as requested via command line."; QTimer::singleShot(1, this,SLOT(slotGetBrokerAuth())); } else if ( !embedMode ) { pass->setText ( "" ); QTimer::singleShot ( 2000,this, SLOT ( slotShowPassForm() ) ); } } else { restartResume=false; sessionStatusDlg->hide(); resumeSession ( resumingSession ); } x2goDebug<<"Finished proxy."; setStatStatus ( tr ( "Finished" ) ); #ifdef Q_OS_DARWIN //fixes bug, when mainwindow inputs not accepting focus under mac setFocus(); #endif } void ONMainWindow::slotProxyStderr() { QString reserr; if ( nxproxy ) reserr= nxproxy->readAllStandardError(); proxyErrString+=reserr; x2goDebug<<"Proxy wrote on stderr: "<insertPlainText ( reserr ); stInfo->ensureCursorVisible(); if ( stInfo->toPlainText().indexOf ( "Connecting to remote host 'localhost:"+ /*resumingSession.grPort*/ localGraphicPort ) !=-1 ) { setStatStatus ( tr ( "connecting" ) ); } if ( stInfo->toPlainText().indexOf ( "Connection to remote proxy 'localhost:"+ /*resumingSession.grPort*/ localGraphicPort+"' established" ) !=-1 ) { if ( newSession ) { setStatStatus ( tr ( "starting" ) ); } else { setStatStatus ( tr ( "resuming" ) ); } } if ( stInfo->toPlainText().indexOf ( "Established X server connection" ) !=-1 ) { if(brokerMode) { sendEventToBroker(CONNECTED); } setStatStatus ( tr ( "running" ) ); if (trayEnabled) { if (!useLdap) trayIconActiveConnectionMenu->setTitle(sessionExplorer->getLastSession()->name()); else trayIconActiveConnectionMenu->setTitle(lastUser->username()); trayIconActiveConnectionMenu->setEnabled(true); if (trayMinCon && !trayAutoHidden) { trayAutoHidden=true; hide(); } } if ( embedMode ) setEmbedSessionActionsEnabled ( true ); disconnect ( sbSusp,SIGNAL ( clicked() ),this, SLOT ( slotTestSessionStatus() ) ); disconnect ( sbSusp,SIGNAL ( clicked() ),this, SLOT ( slotSuspendSessFromSt() ) ); connect ( sbSusp,SIGNAL ( clicked() ),this, SLOT ( slotSuspendSessFromSt() ) ); if ( !showExport ) { showExport=true; /*connect ( sbExp,SIGNAL ( clicked() ),this, SLOT ( slot_exportDirectory() ) );*/ sbExp->setEnabled ( true ); exportDefaultDirs(); if ( readExportsFrom!=QString::null ) { exportTimer->start ( 2000 ); } } sbSusp->setToolTip ( tr ( "Suspend" ) ); #ifdef Q_OS_DARWIN // Only start this once... if (!modMapTimer) { modMapTimer = new QTimer (this); connect (modMapTimer, SIGNAL (timeout ()), this, SLOT (slotSetModMap ())); modMapTimer->start (10000); slotSetModMap (); } #endif if ( newSession ) { runCommand(); newSession=false; } #ifdef Q_WS_HILDON else { if ( !xmodExecuted ) { xmodExecuted=true; QTimer::singleShot ( 2000, this, SLOT ( slotExecXmodmap() ) ); } } #endif } if ( stInfo->toPlainText().indexOf ( tr ( "Connection timeout, aborting" ) ) !=-1 ) setStatStatus ( tr ( "aborting" ) ); } void ONMainWindow::slotProxyStdout() { QString resout ( nxproxy->readAllStandardOutput() ); x2goDebug<<"Proxy wrote on stdout: "<isVisible()) { if(pass && pass->isVisible()&& pass->hasFocus()) { passFocus=true; } if(login && login->isVisible()&& login->hasFocus()) { userFocus=true; } } #endif QWidget::setFocus(); #ifdef Q_OS_DARWIN if(userFocus) { login->setFocus(); } if(passFocus) { pass->setFocus(); } #endif } void ONMainWindow::slotShowPassForm() { #ifdef Q_OS_DARWIN //fixes bug, when mainwindow inputs not accepting focus under mac x2goDebug<<"Setting focus."<show(); login->show(); } else { loginPrompt->hide(); login->hide(); } setEnabled ( true ); if ( !embedMode ) { u->hide(); uname->hide(); } sessionStatusDlg->hide(); selectSessionDlg->hide(); setEnabled ( true ); if ( isPassShown ) { passForm->show(); passForm->setEnabled ( true ); } isPassShown=true; login->setEnabled ( true ); if ( login->text().length() >0 ) { pass->setFocus(); pass->selectAll(); } else { login->setFocus(); login->selectAll(); } if ( !embedMode ) { u->setEnabled ( true ); } else { if ( config.user.length() >0 ) login->setEnabled ( false ); } } void ONMainWindow::showSessionStatus() { setStatStatus(); } void ONMainWindow::slotShowAdvancedStat() { if ( !miniMode ) { if ( sbAdv->isChecked() ) { sessionStatusDlg->setFixedSize ( sessionStatusDlg->width(), sessionStatusDlg->height() *2 ); } else { sessionStatusDlg->setFixedSize ( sessionStatusDlg->sizeHint() ); stInfo->hide(); } } else { if ( sbAdv->isChecked() ) { sessionStatusDlg->setFixedSize ( 310,300 ); } else { stInfo->hide(); sessionStatusDlg->setFixedSize ( 310,200 ); } } // username->invalidate(); if ( sbAdv->isChecked() ) { stInfo->show(); } X2goSettings st ( "settings" ); st.setting()->setValue ( "showStatus", ( QVariant ) sbAdv->isChecked() ); st.setting()->sync(); } void ONMainWindow::slotResumeDoubleClick ( const QModelIndex& ) { if ( !shadowSession ) slotResumeSess(); } void ONMainWindow::suspendBrokerSession(const QString& sessId, const QString& host) { suspendTerminateHostFromBroker=host; suspendTerminateSessionFromBroker=sessId; startSession(config.session, SUSPEND); } void ONMainWindow::termBrokerSession(const QString& sessId, const QString& host) { if(QMessageBox::warning ( this,tr ( "Warning" ), tr ( "Are you sure you want to terminate " "this session?\n" "Unsaved documents will be lost." ), QMessageBox::Yes,QMessageBox::No )!= QMessageBox::Yes) { setEnabled(true); selectSessionDlg->setEnabled ( true ); return; } suspendTerminateHostFromBroker=host; suspendTerminateSessionFromBroker=sessId; startSession(config.session, TERMINATE); } void ONMainWindow::suspendSession ( QString sessId ) { sshConnection->executeCommand ( "x2gosuspend-session "+sessId, this, SLOT ( slotRetSuspSess ( bool, QString, int ) ) ); } bool ONMainWindow::termSession ( QString sessId, bool warn ) { if ( warn ) { bool hide_after=false; if (isHidden()) { showNormal(); hide_after=true; } int answer=QMessageBox::warning ( this,tr ( "Warning" ), tr ( "Are you sure you want to terminate " "this session?\n" "Unsaved documents will be lost." ), QMessageBox::Yes,QMessageBox::No ); if (hide_after) hide(); if ( answer != QMessageBox::Yes ) { if ( selectSessionDlg->isVisible() ) selectSessionDlg->setEnabled ( true ); return false; } } if ( shadowSession ) { nxproxy->terminate(); return true; } x2goDebug<<"Terminating session."; sshConnection->executeCommand ( "x2goterminate-session "+sessId, this, SLOT ( slotRetTermSess ( bool, QString,int) ) ); proxyRunning=false; return true; } void ONMainWindow::setStatStatus ( QString status ) { setEnabled ( true ); passForm->hide(); selectSessionDlg->hide(); if ( status == QString::null ) status=statusString; else statusString=status; QString tstr; if ( statusLabel ) statusLabel->setText ( QString::null ); if ( resumingSession.sessionId!=QString::null ) { QString f="dd.MM.yy HH:mm:ss"; QDateTime dt=QDateTime::fromString ( resumingSession.crTime,f ); dt=dt.addYears ( 100 ); tstr=dt.toString(); } if ( !embedMode || !proxyWinEmbedded ) { statusBar()->showMessage ( ""); statusBar()->hide(); QString srv; if ( brokerMode ) { srv=config.serverIp; } else if ( embedMode ) { srv=config.server; } else { srv=resumingSession.server; } slVal->setText ( resumingSession.sessionId+"\n"+ srv+"\n"+ getCurrentUname() +"\n"+ resumingSession.display+ "\n"+tstr+"\n"+status ); slVal->setFixedSize ( slVal->sizeHint() ); sessionStatusDlg->show(); if (resumingSession.published) sbApps->show(); else sbApps->hide(); } else { QString srv; if ( brokerMode ) { srv=config.serverIp; } else { srv=config.server; } QString message=getCurrentUname() +"@"+ srv+ ", "+tr ( "Session" ) +": "+ resumingSession.sessionId+", "+ tr ( "Display" ) +": "+ resumingSession.display+", "+ tr ( "Creation time" ) +": "+tstr; if ( statusLabel ) { statusLabel->setText ( " "+message ); } else { if ( config.showstatusbar ) { statusBar()->show(); statusBar()->showMessage ( message ); } } sessionStatusDlg->hide(); } } void ONMainWindow::slotRestartProxy() { if ( !sessionStatusDlg->isVisible() ) return; if ( stInfo->toPlainText().indexOf ( "Established X server connection" ) ==-1 ) { stInfo->insertPlainText ( tr ( "Connection timeout, aborting" ) ); if ( nxproxy ) nxproxy->terminate(); proxyRunning=false; restartResume=true; } } void ONMainWindow::slotTestSessionStatus() { if ( !sessionStatusDlg->isVisible() ) return; if ( stInfo->toPlainText().indexOf ( "Established X server connection" ) ==-1 ) { stInfo->insertPlainText ( tr ( "Connection timeout, aborting" ) ); if ( nxproxy ) nxproxy->terminate(); proxyRunning=false; } } x2goSession ONMainWindow::getNewSessionFromString ( const QString& string ) { QStringList lst=string.split ( '|' ); x2goSession s; s.display=lst[0]; s.cookie=lst[1]; s.agentPid=lst[2]; s.sessionId=lst[3]; s.grPort=lst[4]; s.sndPort=lst[5]; if ( lst.count() >6 ) s.fsPort=lst[6]; return s; } #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN) void ONMainWindow::pulseManagerWrapper () { #ifdef Q_OS_WIN if (!embedMode || !config.confSnd || (config.confSnd && config.useSnd)) #endif /* defined (Q_OS_WIN) */ { X2goSettings st ("settings"); bool disablePulse = st.setting ()->value ("pulse/disable", (QVariant) false).toBool (); if(disablePulse||systemDisablePA) { x2goDebug<<"Not starting PulseAudio"; return; } pulseManagerThread = new QThread (0); pulseManager = new PulseManager (); connect(pulseManager, SIGNAL(sig_pulse_user_warning(bool, const QString&, const QString&, bool)), this, SLOT(slotShowPAMSGDialog(bool, const QString&, const QString&, bool))); bool disableInput = st.setting ()->value ("pulse/norecord", (QVariant) false).toBool (); pulseManager->set_record (!disableInput); pulseManager->set_debug (debugging); pulseManager->moveToThread (pulseManagerThread); /* * Spawn PulseManager::start() once the thread started up successfully. * Another means of doing that would be via * QMetaObject::invokeMethod (pulseManager, "start", Qt::QueuedConnection); */ connect (pulseManagerThread, SIGNAL (started ()), pulseManager, SLOT (start ())); pulseManagerThread->start (); } } #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */ void ONMainWindow::slotAppDialog() { AppDialog dlg(this); dlg.exec(); } void ONMainWindow::runCommand() { if ( runRemoteCommand ) { /* 1st override PATH and determine the base path to x2goruncommand. * Then in SlotRunCommand, call x2goruncommand without overriding PATH. * This ensures that the PATH is never overridden for the actual user * session. * Fixes: #1100 */ sshConnection->executeCommand ( "x2gobasepath", this, SLOT ( SlotRunCommand ( bool, QString, int )), true); } #ifdef Q_WS_HILDON //wait 5 seconds and execute xkbcomp QTimer::singleShot ( 5000, this, SLOT ( slotExecXmodmap() ) ); #endif } void ONMainWindow::runApplication(QString exec) { QString cmd = "PULSE_CLIENTCONFIG=\"${HOME}/.x2go/C-" + resumingSession.sessionId+"/.pulse-client.conf\" DISPLAY=:" + resumingSession.display + " setsid " + exec + " 1> /dev/null 2>/dev/null & exit"; sshConnection->executeCommand (cmd, 0, 0, false); } void ONMainWindow::SlotRunCommand(bool, QString output, int) { QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString host=resumingSession.server; QString command; QString sessionType="D"; QString rdpOpts,rdpServer; bool rdpFS=false; QString rdpWidth; QString rdpHeight; bool rootless=false; resumingSession.published=false; if ( !embedMode ) { X2goSettings* st; if (!brokerMode) st=new X2goSettings( "sessions" ); else st=new X2goSettings(config.iniFile, QSettings::IniFormat); if ( useLdap ) command=sessionCmd; else { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, not running command."; return; } QString sid=sessionExplorer->getLastSession()->id(); command=st->setting()->value ( sid+"/command", ( QVariant ) tr ( "KDE" ) ).toString(); rdpOpts=st->setting()->value ( sid+"/rdpoptions", ( QVariant ) "" ).toString(); if ( user != "" ) { rdpOpts.replace("X2GO_USER", user); } if ( passwd != "" ) { rdpOpts.replace("X2GO_PASSWORD", passwd); } rdpServer=st->setting()->value ( sid+"/rdpserver", ( QVariant ) "" ).toString(); rootless=st->setting()->value ( sid+"/rootless", ( QVariant ) false ).toBool(); resumingSession.published=st->setting()->value ( sid+"/published", ( QVariant ) false ).toBool(); rdpFS=st->setting()->value ( sid+"/fullscreen", ( QVariant ) defaultFullscreen ).toBool(); rdpHeight=st->setting()->value ( sid+"/height", ( QVariant ) defaultHeight ).toString(); rdpWidth=st->setting()->value ( sid+"/width", ( QVariant ) defaultWidth ).toString(); } delete st; } else { command=config.command; rootless=config.rootless; resumingSession.published=config.published; } resumingSession.command=command; if ( rootless ) sessionType="R"; if ( resumingSession.published ) { sessionType="P"; command="PUBLISHED"; } if ( command=="KDE" ) { command="startkde"; } else if ( command=="GNOME" ) { command="gnome-session"; } else if ( command=="UNITY" ) { command="unity"; } else if ( command=="XFCE" ) { command="xfce4-session"; } else if ( command=="MATE" ) { command="mate-session"; } else if ( command=="LXDE" ) { command="startlxde"; } else if (command == "LXQt") { command = "startlxqt"; } // Note that there are multiple possible Cinnamon commands that the server // may call. else if ( command=="CINNAMON" ) { command="cinnamon-session"; } else if ( command=="TRINITY" ) { command="starttrinity"; } else if ( command=="OPENBOX" ) { command="openbox-session"; } else if ( command=="ICEWM" ) { command="icewm-session"; } else if ( command=="RDP" ) { command="rdesktop "; if ( rdpFS ) { command+=" -f "; sessionType="D"; rootless=false; } else { command+=" -g "+rdpWidth+"x"+rdpHeight; rootless=true; } command+=" "+rdpOpts+ " "+rdpServer; } if ( managedMode ) return; QString cmd; command.replace ( " ","X2GO_SPACE_CHAR" ); QString krbFwString; if(sshConnection->useKerberos() && sshConnection->get_kerberosDelegation()) { krbFwString="KRB5CCNAME=`echo $KRB5CCNAME |sed 's/FILE://g'` \ KRBFL=$HOME/.x2go/C-"+resumingSession.sessionId+"/krb5cc ;\ cp -a $KRB5CCNAME $KRBFL;KRB5CCNAME=$KRBFL "; } if ( !startSessSound || startSessSndSystem==PULSE ) { cmd=krbFwString+"setsid " + output + "/bin/x2goruncommand "+ resumingSession.display+" "+ resumingSession.agentPid + " " + resumingSession.sessionId+" "+ resumingSession.sndPort+ " "+ command+" nosnd "+ sessionType +" 1> /dev/null 2>/dev/null & exit"; if ( startSessSndSystem ==PULSE ) { cmd="export PULSE_CLIENTCONFIG=\"${HOME}/.x2go/C-"+ resumingSession.sessionId+ "/.pulse-client.conf\";"+cmd; } } else { switch ( startSessSndSystem ) { case ESD: cmd=krbFwString+"setsid " + output + "/bin/x2goruncommand "+ resumingSession.display+" "+ resumingSession.agentPid + " " + resumingSession.sessionId+" "+ resumingSession.sndPort+ " "+ command+" esd "+ sessionType +" 1> /dev/null 2>/dev/null & exit"; break; case ARTS: cmd=krbFwString+"setsid " + output + "/bin/x2goruncommand "+ resumingSession.display+" "+ resumingSession.agentPid + " " + resumingSession.sessionId+" "+ resumingSession.sndPort+ " "+ command+" arts "+ sessionType +" 1> /dev/null 2>/dev/null & exit"; break; } } sshConnection->executeCommand ( cmd, this, SLOT ( slotRetRunCommand ( bool, QString, int )), false); } void ONMainWindow::slotRetRunCommand ( bool result, QString output, int ) { if ( result==false ) { QString message=tr ( "Connection failed.\n:\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } else { if (resumingSession.published) readApplications(); } } void ONMainWindow::readApplications() { sshConnection->executeCommand ( "x2gogetapps", this, SLOT ( slotReadApplications ( bool, QString, int) )); sbApps->setEnabled(false); } void ONMainWindow::slotReadApplications(bool result, QString output, int) { if ( result==false ) { QString message=tr ( "Connection failed.\n:\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); return; } sbApps->setEnabled(true); applications.clear(); QString locallong=QLocale::system().name(); QString localshort=QLocale::system().name().split("_")[0]; QStringList startAppsFound; foreach(QString appstr, output.split("",QString::SkipEmptyParts)) { bool localcomment=false; bool localname=false; Application app; app.category=Application::OTHER; QStringList lines=appstr.split("\n", QString::SkipEmptyParts); for (int i=0; i")!=-1) { bool isSvg=false; line=lines[++i]; QByteArray pic; while (line.indexOf("")==-1) { pic+=QByteArray::fromBase64(line.toLatin1()); line=lines[++i]; if (QString(QByteArray::fromBase64(line.toLatin1())).indexOf("",Qt::CaseInsensitive)!=-1) { isSvg=true; } } if (!isSvg) app.icon.loadFromData(pic); else { QPixmap pix(32,32); QSvgRenderer svgRenderer( pic ); QPainter pixPainter(&pix); svgRenderer.render(&pixPainter); app.icon=pix; } } } if (app.name.length()>0) { if (app.comment.length()<=0) app.comment=app.name; applications.append(app); } } qSort(applications.begin(), applications.end(),Application::lessThen); plugAppsInTray(); if (runStartApp && autostartApps.length()>0) { for (int i=0; isetVisible(true); slotAppDialog(); } } } bool ONMainWindow::parseParameter ( QString param ) { #if defined (Q_OS_UNIX) if ("--bypass-cleanup-helper" == param) { return (true); } #endif /* defined (Q_OS_UNIX) */ if ( param=="--help" ) { showHelp(); return false; } if ( param=="--help-pack" ) { showHelpPack(); return false; } if ( param=="--version" || param=="-v") { showVersion(); return false; } if ( param=="--changelog" ) { showChangelog(); return false; } if ( param=="--git-info" ) { showGit(); return false; } if (param == "--debug") { ONMainWindow::debugging = true; return true; } if ("--libssh-debug" == param) { ONMainWindow::libssh_debugging = true; return true; } if ("--libssh-packetlog" == param) { ONMainWindow::libssh_packetlog = true; return true; } #if defined (Q_OS_DARWIN) || defined (Q_OS_WIN) if (param == "--disable-pulse") { systemDisablePA=true; return true; } if (param == "--disable-pulse-record") { systemDisablePARecord=true; return true; } #endif /* defined (Q_OS_DARWIN) || defined (Q_OS_WIN) */ if (param == "--no-autoresume") { autoresume=false; return true; } if ( param == "--portable" ) { ONMainWindow::portable=true; return true; } if ( param == "--clean-all-files" ) { cleanAllFiles=true; return true; } if (param == "--connectivity-test") { connTest=true; return true; } if ( param=="--no-menu" ) { drawMenu=false; return true; } if ( param=="--maximize" ) { startMaximized=true; return true; } if ( param=="--xinerama" ) { defaultXinerama=true; return true; } if (param == "--thinclient") { thinMode=true; startMaximized=true; return true; } if (param == "--haltbt") { showHaltBtn=true; return true; } if (param == "--broker-logoutbt") { showBrokerLogoutBtn=true; return true; } if ( param=="--hide" ) { startHidden=true; return true; } if ( param=="--keep-trayicon" ) { keepTrayIcon=true; return true; } if ( param=="--hide-foldersharing" ) { hideFolderSharing=true; return true; } if ( param=="--pgp-card" ) { usePGPCard=true; return true; } if ( param=="--ldap-printing" ) { LDAPPrintSupport=true; return true; } if ( param=="--add-to-known-hosts" ) { acceptRsa=true; return true; } if ( param=="--no-session-edit" ) { noSessionEdit=true; return true; } if ( param=="--change-broker-pass") { changeBrokerPass=true; return true; } if ( param == "--autologin") { cmdAutologin=true; return true; } if ( param == "--broker-autologin") { config.brokerAutologin=true; return true; } if ( param == "--broker-krblogin") { config.brokerKrbLogin=true; return true; } if ( param == "--broker-autologoff") { config.brokerAutologoff=true; return true; } if ( param == "--broker-noauth") { config.brokerNoAuth=true; return true; } if ( param=="--broker-noauth-with-session-username" ) { brokerNoauthWithSessionUsername=true; return true; } if ( param=="--broker-use-creds-for-session" ) { brokerCredsForSession=true; return true; } //force to show trayicon if (param == "--tray-icon") { forceToShowTrayicon = true; return true; } if ( param=="--close-disconnect" ) { closeDisconnect=true; return true; } QString setting,value; QStringList vals=param.split ( "=" ); if ( vals.size() <2 ) { printError ( param ); return false; } setting=vals[0]; vals.removeFirst(); value=vals.join ( "=" ); if ( setting=="--link" ) { return linkParameter ( value ); } if ( setting=="--clipboard" ) { return clipboardParameter ( value ); } if ( setting=="--sound" ) { return soundParameter ( value ); } if ( setting=="--geometry" ) { return geometry_par ( value ); } if ( setting=="--pack" ) { return packParameter ( value ); } if ( setting=="--kbd-layout" ) { defaultLayout=value.split(",",QString::SkipEmptyParts); if (defaultLayout.size()==0) defaultLayout<0) { if(authPart.indexOf("@")!=-1) { key.user=authPart.split("@")[0]; key.server=authPart.split("@")[1]; } else key.server=authPart; } cmdSshKeys<trimmed (); } return true; } if ( setting == "--auth-id") { QFile file(expandHome(value)); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { printError ( param + tr(" (can't open file)")); return false; } QTextStream in(&file); config.brokerUserId = in.readLine(); return true; } if (setting == "--support-menu") { value = expandHome(value); if (! QFile::exists(value)) { printError( param + tr(" (file does not exist)")); return false; } supportMenuFile=value; return true; } if (setting == "--background") { value = expandHome(value); if (! QFile::exists(value)) { printError( param + tr(" (file does not exist)")); return false; } BGFile=value; return true; } if (setting == "--session-icon") { value=expandHome(value); if (! QFile::exists(value)) { printError( param + tr(" (file does not exist)")); return false; } SPixFile=value; return true; } if (setting == "--home") { QDir dr; value = expandHome(value); #ifdef Q_OS_WIN int find=value.indexOf("("); int lind=value.indexOf(")"); if (find!=-1 && lind !=-1) { QString label=value.mid(find+1,lind-find-1); x2goDebug<<"Searching for drive with label: "<= conv) { x2goDebug << "Not limiting X.Org Server starts."; x_start_limit_ = 0; } else { if (SIZE_MAX < conv) { conv = SIZE_MAX; x2goDebug << "Clamped X.Org Server start limit to SIZE_MAX."; } x_start_limit_ = conv; x2goDebug << "Limiting X.Org Server starts to " << x_start_limit_ << " tries."; } } else { x2goDebug << "Conversion for --xserver-start-limit value " << value << " failed; assuming default of 3."; x_start_limit_ = 3; } return (true); } #endif /* defined(Q_OS_WIN) */ printError ( param ); return false; } bool ONMainWindow::linkParameter ( QString value ) { if ( value=="modem" ) defaultLink=MODEM; else if ( value=="isdn" ) defaultLink=ISDN; else if ( value=="adsl" ) defaultLink=ADSL; else if ( value=="wan" ) defaultLink=WAN; else if ( value=="lan" ) defaultLink=LAN; else { printError( tr ( "Invalid value for parameter \"--link\"." ).toLocal8Bit().data() ); return false; } return true; } bool ONMainWindow::clipboardParameter ( QString value ) { if ( value=="both" || value=="client" || value=="server"||value == "none") { defaultClipboardMode=value; return true; } else { printError( tr ( "Invalid value for parameter \"--clipboard\"." ).toLocal8Bit().data() ); return false; } } bool ONMainWindow::soundParameter ( QString val ) { if ( val=="1" ) defaultUseSound=true; else if ( val=="0" ) defaultUseSound=false; else { printError( tr ( "Invalid value for " "parameter \"--sound\"." ).toLocal8Bit().data() ); return false; } return true; } bool ONMainWindow::geometry_par ( QString val ) { if ( val=="fullscreen" ) defaultFullscreen=true; else { QStringList res=val.split ( "x" ); if ( res.size() !=2 ) { printError( tr ( "Invalid value for parameter \"--geometry\"." ). toLocal8Bit().data() ); return false; } bool o1,o2; defaultWidth=res[0].toInt ( &o1 ); defaultHeight=res[1].toInt ( &o2 ); if ( ! ( defaultWidth >0 && defaultHeight >0 && o1 && o2 ) ) { printError( tr ( "Invalid value for parameter \"--geometry\"." ). toLocal8Bit().data() ); return false; } } return true; } bool ONMainWindow::setKbd_par ( QString val ) { if ( val=="1" ) defaultSetKbd=true; else if ( val=="0" ) defaultSetKbd=false; else { printError( tr ( "Invalid value for parameter \"--set-kbd\"." ). toLocal8Bit().data() ); return false; } return true; } bool ONMainWindow::ldapParameter ( QString val ) { QString ldapstring=val; useLdap=true; ldapstring.replace ( "\"","" ); QStringList lst=ldapstring.split ( ':',QString::SkipEmptyParts ); if ( lst.size() !=3 ) { printError( tr ( "Invalid value for parameter \"--ldap\"." ). toLocal8Bit().data() ); return false; } ldapOnly=true; ldapServer=lst[0]; ldapPort=lst[1].toInt(); ldapDn=lst[2]; return true; } bool ONMainWindow::ldap1Parameter ( QString val ) { QString ldapstring=val; ldapstring.replace ( "\"","" ); QStringList lst=ldapstring.split ( ':',QString::SkipEmptyParts ); if ( lst.size() !=2 ) { printError( tr ( "Invalid value for parameter \"--ldap1\"." ). toLocal8Bit().data() ); return false; } ldapServer1=lst[0]; ldapPort1=lst[1].toInt(); return true; } bool ONMainWindow::ldap2Parameter ( QString val ) { QString ldapstring=val; ldapstring.replace ( "\"","" ); QStringList lst=ldapstring.split ( ':',QString::SkipEmptyParts ); if ( lst.size() !=2 ) { printError( tr ( "Invalid value for parameter \"--ldap2\"." ). toLocal8Bit().data() ); return false; } ldapServer2=lst[0]; ldapPort2=lst[1].toInt(); return true; } bool ONMainWindow::packParameter ( QString val ) { QFile file ( ":/txt/packs" ); if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) return true; QTextStream in ( &file ); while ( !in.atEnd() ) { QString pc=in.readLine(); if ( pc.indexOf ( "-%" ) !=-1 ) { pc=pc.left ( pc.indexOf ( "-%" ) ); QStringList pctails=val.split ( "-" ); QString pcq=pctails[pctails.size()-1]; pctails.removeLast(); if ( pctails.join ( "-" ) ==pc ) { bool ok; int v=pcq.toInt ( &ok ); if ( ok && v>=0 && v<=9 ) { defaultPack=pc; defaultQuality=v; return true; } else break; } } else { if ( pc==val ) { defaultPack=val; return true; } } } file.close(); printError ( tr("Invalid value for parameter \"--pack\"." )); return false; } void ONMainWindow::printError ( QString param ) { if( !startHidden ) { qCritical ( "%s", ( tr ( "Wrong parameter: " ) +param ). toLocal8Bit().data() ); if (!startHidden && !haveTerminal) { QMessageBox::critical(0,tr("Error"), tr ( "Wrong parameter: " ) +param); } } else { x2goErrorf(8)<Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); setEnabled ( true ); passForm->setEnabled ( true ); pass->setFocus(); pass->selectAll(); return; } passForm->hide(); setUsersEnabled ( false ); uname->setEnabled ( false ); u->setEnabled ( false ); QStringList servers=output.trimmed().split ( '\n' ); for ( int i=0; i1 ) { for ( int j=0; jConnection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); QString sv=output.split ( ":" ) [0]; for ( int j=0; jgetLastSession()->id(),this ); if ( dlg.exec() ==QDialog::Accepted ) path=dlg.getExport(); } else path= QFileDialog::getExistingDirectory ( this,QString::null, homeDir ); if (hide_after) hide(); #ifdef Q_OS_WIN if ( ONMainWindow::getPortable() && ONMainWindow::U3DevicePath().length() >0 ) { path.replace ( "(U3)",u3Device ); } path=cygwinPath ( wapiShortFileName ( path ) ); #endif if ( path!=QString::null ) exportDirs ( path ); } void ONMainWindow::exportDirs ( QString exports,bool removable ) { if ( shadowSession ) return; if ( embedMode ) { if ( config.confFS && ! ( config.useFs ) ) { return; } } fsExportKeyReady=false; directory dr; dr.dirList=exports; dr.key=createKeyBundle(); // Key creation failure or the like. if (dr.key.isEmpty ()) { return; } QString passwd; x2goDebug<<"Key created on: "<getLastSession())) { x2goDebug << "No session selected, not exporting directories."; return; } QString sid=sessionExplorer->getLastSession()->id(); fsInTun=st.setting()->value ( sid+"/fstunnel", ( QVariant ) true ).toBool(); } else fsInTun=true; } if ( fsInTun ) { if ( fsTunnel==0l ) if ( startSshFsTunnel() ) return; } QString uname=getCurrentUname(); /* For the destination, fetch the base name only. */ QFileInfo tmp_file_info (dr.key); QString dst = tmp_file_info.fileName (); dst="~"+uname +"/.x2go/ssh/"+dst; dr.dstKey=dst; dr.isRemovable=removable; exportDir.append ( dr ); QString keyFile=dr.key; sshConnection->copyFile ( keyFile,dst, this, SLOT ( slotCopyKey ( bool, QString,int ) )); } void ONMainWindow::exportDefaultDirs() { QStringList dirs; bool clientPrinting= ( useLdap && LDAPPrintSupport ); if ( !useLdap ) { if ( !embedMode ) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, not exporting default directories."; return; } X2goSettings* st; if (!brokerMode) st= new X2goSettings( "sessions" ); else st= new X2goSettings(config.iniFile,QSettings::IniFormat); clientPrinting= st->setting()->value ( sessionExplorer->getLastSession()->id() + "/print", true ).toBool(); QString exd=st->setting()->value ( sessionExplorer->getLastSession()->id() +"/export", ( QVariant ) QString::null ).toString(); QStringList lst=exd.split ( ";", QString::SkipEmptyParts ); for ( int i=0; i0 ) { tails[0].replace ( "(U3)",u3Device ); } #endif if(!QFile::exists(tails[0])) { x2goDebug<<"Path "<start ( 2000 ); } if ( dirs.size() <=0 ) return; exportDirs ( dirs.join ( ":" ) ); } void ONMainWindow::slotCopyKey ( bool result, QString output, int pid) { fsExportKey=sshConnection->getSourceFile(pid); x2goDebug<<"Exported key: "<Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } if (!startHidden) { QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } else { QString printout = tr( "Connection failed: ") + output.toLatin1(); if ( output.indexOf ( "publickey,password" ) !=-1 ) x2goErrorf(11)<< tr( "Connection failed: ") + output + tr(" - Wrong password."); else x2goErrorf(12)<< tr( "Connection failed: ") + output; trayQuit(); } QFile::remove ( fsExportKey+".pub" ); return; } fsExportKeyReady=true; //start reverse mounting if RSA Key and FS tunnel are ready //start only once from slotFsTunnelOk() or slotCopyKey(). if ( !fsInTun || fsTunReady ) startX2goMount(); } directory* ONMainWindow::getExpDir ( QString key ) { for ( int i=0; iConnection failed.\n" ) +output; x2goDebug<<"startX2goMount failed to mount client-side folder, reason: "<Wrong password!

" ) + message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } QFile file ( key+".pub" ); x2goDebug << "Deactivating public key from " << QString (key + ".pub") << " again."; if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) { printSshDError_noExportPubKey(); QFile::remove ( key+".pub" ); return; } QByteArray line = file.readLine(); file.close(); QDir authorized_keys_dir (homeDir); authorized_keys_dir = QDir (authorized_keys_dir.absolutePath () + "/.x2go/.ssh/"); QFile authorized_keys_file (authorized_keys_dir.absolutePath () + "/authorized_keys"); /* * We do not try to create the file first. * This has been already done in startX2goMount(). * We wouldn't be here if that failed. */ if (!authorized_keys_file.open (QIODevice::ReadOnly | QIODevice::Text)) { printSshDError_noAuthorizedKeysFile (); QFile::remove (key + ".pub"); return; } QTemporaryFile tfile (authorized_keys_file.fileName ()); tfile.open (); tfile.setPermissions (QFile::ReadOwner | QFile::WriteOwner); tfile.setAutoRemove (true); QTextStream out (&tfile); /* * Copy the content of the authorized_keys file to our new temporary file * and remove the public authorized key for the current "session" again. */ while (!authorized_keys_file.atEnd ()) { QByteArray newline = authorized_keys_file.readLine (); if (newline != line) out << newline; } authorized_keys_file.close (); tfile.close (); authorized_keys_file.remove (); tfile.copy (authorized_keys_file.fileName ()); QFile::remove (key + ".pub"); } void ONMainWindow::slotExtTimer() { if ( QFile::permissions ( readLoginsFrom ) != ( QFile::ReadUser|QFile::WriteUser|QFile::ExeUser| QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner ) ) { x2goDebug<<"Wrong permissions on "<stop(); return; } QString loginDir; QString logoutDir; QDir dir ( readLoginsFrom ); QStringList list = dir.entryList ( QDir::Files ); for ( int i=0; iisActive() ) //running session { if ( logoutDir != QString::null ) { x2goDebug<<"External logout received"; externalLogout ( logoutDir ); } } else { if ( loginDir != QString::null ) { x2goDebug<<"External login."; externalLogin ( loginDir ); } } } void ONMainWindow::slotExportTimer() { if ( QFile::permissions ( readExportsFrom ) != ( QFile::ReadUser| QFile::WriteUser| QFile::ExeUser| QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner ) ) { x2goDebug<<"Wrong permissions on "<< readExportsFrom <<":"<stop(); return; } QDir dir ( readExportsFrom ); QStringList list = dir.entryList ( QDir::Files ); QString expList; QString unexpList; QString loginDir; QString logoutDir; for ( int i=0; i0 ) { exportDirs ( expList,true ); } args.clear(); args=unexpList.split ( ":",QString::SkipEmptyParts ); QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString host=resumingSession.server; QString sessionId=resumingSession.sessionId; for ( int i=0; iexecuteCommand ( "x2goumount_session "+ sessionId+" "+args[i] ); } } void ONMainWindow::slotAboutQt() { QMessageBox::aboutQt ( this ); } void ONMainWindow::slotSupport() { QFile file(supportMenuFile); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QTextStream in(&file); QString sup; while (!in.atEnd()) { sup+=in.readLine(); } QMessageBox::information (this,tr ( "Support" ),sup); } void ONMainWindow::slotAbout() { /* * This (extra) comment (for translators) looks fucked up, and it is, but * this can't be changed. * * Adding asterisks in front of a line will cause them to literally appear * in the comment, so I'd rather just drop them. * * Adding any whitespace in front of a line will lead to one whitespace * character surviving the lupdate scan, so we have to drop them as well. * * NOT adding an escape character to the end of a line will make lupdate * stupidly replace the newline character with a whitespace character. */ /*: Translators, feel free to add a localized version of your translation including a copyright notice and your name(s). Remember to keep a
at the end, though.\n\n\ \ English example for a potential translation:\n\n\ \
(C) 2005-2020 by obviously nice: \ Oleksandr Shneyder, Heinz-Markus Graesing
\ English version: (C) 20AB-20CD Trans Lator
*/ QString aboutStr=tr ("
(C) 2005-2020 by obviously nice: " "Oleksandr Shneyder, Heinz-Markus Graesing
" ); aboutStr+= tr ( "
This is a client to access the X2Go network-based " "computing environment. This client will be able " "to connect to X2Go Server(s) and start, stop, " "resume and terminate (running) desktop sessions. " "X2Go Client stores different server connections " "and may automatically request authentication " "data from LDAP directories. Furthermore, it can be " "used as a fullscreen login screen (replacement for " "login managers like XDM). Please visit the project home page at " "x2go.org for further information." ); QMessageBox::about ( this,tr ( "About X2Go Client" ), tr ( "X2Go Client v. " ) +VERSION+ " (Qt - "+qVersion() +")"+ aboutStr ); } void ONMainWindow::slotRereadUsers() { if ( !useLdap ) return; #ifdef USELDAP if ( ld ) { delete ld; ld=0; } if ( ! initLdapSession ( false ) ) { return; } list attr; attr.push_back ( "uidNumber" ); attr.push_back ( "uid" ); list result; try { ld->binSearch ( ldapDn.toStdString(),attr, "objectClass=posixAccount",result ); } catch ( LDAPExeption e ) { QString message="Exception in: "; message=message+e.err_type.c_str(); message=message+" : "+e.err_str.c_str(); QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok,QMessageBox::NoButton ); QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Please check LDAP Settings." ), QMessageBox::Ok,QMessageBox::NoButton ); slotConfig(); return; } list::iterator it=result.begin(); list::iterator end=result.end(); for ( ; it!=end; ++it ) { user u; QString uin=LDAPSession::getBinAttrValues ( *it,"uidNumber" ).front().getData(); u.uin=uin.toUInt(); if ( u.uinlastUid ) { continue; } u.uid=LDAPSession::getBinAttrValues ( *it,"uid" ).front().getData(); if ( !findInList ( u.uid ) ) { reloadUsers(); return; } } #endif } void ONMainWindow::reloadUsers() { int i; for ( i=0; iclose(); userList.clear(); sessionExplorer->cleanSessions(); loadSettings(); if ( useLdap ) { act_new->setEnabled ( false ); act_edit->setEnabled ( false ); u->setText ( tr ( "Login:" ) ); QTimer::singleShot ( 1, this, SLOT ( readUsers() ) ); } else { act_new->setEnabled ( true ); act_edit->setEnabled ( true ); u->setText ( tr ( "Session:" ) ); QTimer::singleShot ( 1, this, SLOT ( slotReadSessions() ) ); } slotResize ( fr->size() ); } bool ONMainWindow::findInList ( const QString& uid ) { for ( int i=0; iverticalScrollBar(); bar->setEnabled ( enable ); int upos=bar->value(); QDesktopWidget dw; int height=dw.screenGeometry ( fr ).height(); QList::iterator it; QList::iterator endit=names.end(); if ( !enable ) { for ( it=names.begin(); it!=endit; it++ ) { QPoint pos= ( *it )->pos(); if ( ( pos.y() >upos-height ) && ( pos.y() setEnabled ( false ); if ( pos.y() >upos+height ) break; } } else { for ( it=names.begin(); it!=endit; it++ ) { if ( ! ( *it )->isEnabled() ) ( *it )->setEnabled ( true ); } } } else { users->setEnabled ( enable ); sessionExplorer->setEnable(enable); } } void ONMainWindow::externalLogin ( const QString& loginDir ) { QFile file ( loginDir+"/username" ); QString user; if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) return; QTextStream in ( &file ); while ( !in.atEnd() ) { user=in.readLine(); break; } file.close(); if ( passForm->isVisible() ) slotClosePass(); uname->setText ( user ); slotUnameEntered(); currentKey=loginDir+"/dsa.key"; extStarted=true; slotPassEnter(); } void ONMainWindow::externalLogout ( const QString& ) { if ( extStarted ) { extStarted=false; currentKey=QString::null; if ( nxproxy ) if ( nxproxy->state() ==QProcess::Running ) nxproxy->terminate(); proxyRunning=false; } } void ONMainWindow::slotStartPGPAuth() { scDaemon=new QProcess ( this ); connect ( scDaemon,SIGNAL ( readyReadStandardError() ),this, SLOT ( slotScDaemonStdErr() ) ); connect ( scDaemon,SIGNAL ( readyReadStandardOutput() ),this, SLOT ( slotScDaemonStdOut() ) ); connect ( scDaemon,SIGNAL ( finished ( int,QProcess::ExitStatus ) ), this, SLOT ( slotScDaemonFinished ( int, QProcess::ExitStatus ) ) ); connect (scDaemon, SIGNAL (error (QProcess::ProcessError)), this, SLOT (slotScDaemonError (QProcess::ProcessError))); scDaemon->start ( "pcsc_scan -n"); } void ONMainWindow::slotScDaemonStdErr() { QString stdOut ( scDaemon->readAllStandardError() ); stdOut=stdOut.simplified(); x2goDebug<<"PCSC error: "<readAllStandardOutput() ); stdOut=stdOut.simplified(); x2goDebug<<"PCSC out: |"<state() ==QProcess::Running ) { x2goDebug<<"Suspending session ..."; slotSuspendSessFromSt(); x2goDebug<<"Suspended session."; } } } } void ONMainWindow::slotScDaemonFinished ( int , QProcess::ExitStatus ) { //this should not happen, restart... scDaemon=0l; x2goDebug<<"SCDAEMON finished."<bugs wiki page."); show_RichText_ErrorMsgBox (main_text, informative_text); trayQuit (); } void ONMainWindow::slotShowPAMSGDialog(bool error, const QString& main_text, const QString& info_text, bool modal) { if(error) { show_RichText_ErrorMsgBox(main_text, info_text,modal); } else { show_RichText_WarningMsgBox(main_text, info_text, modal); } } void ONMainWindow::slotGpgError() { QString stdOut ( gpg->readAllStandardError() ); stdOut=stdOut.simplified(); x2goDebug<<"GPG error: "<kill(); } } void ONMainWindow::slotGpgFinished ( int exitCode, QProcess::ExitStatus exitStatus ) { x2goDebug<<"GPG finished, exit code: "<readAllStandardOutput() ); stdOut.chop ( 1 ); x2goDebug<<"GPG out: "<start ( "gpg",arguments ); x2goDebug<<"gpg started"; } void ONMainWindow::GPGCardLogin ( const QString& cardLogin) { if ( !useLdap ) { if ( passForm->isVisible() && !brokerMode) { if ( passForm->isEnabled() ) { if ( login->isEnabled() ) { login->setText ( cardLogin ); slotSessEnter(); } } } if(brokerMode && (!config.brokerAutologoff)) { broker->getUserSessions(); } } else { if ( passForm->isVisible() ) slotClosePass(); uname->setText ( cardLogin ); slotUnameEntered(); slotPassEnter(); } } #if defined ( Q_OS_DARWIN ) QString ONMainWindow::getXDisplay() { QLocalSocket unixSocket (this); QString xsocket (getenv ("DISPLAY")); if (xsocket.isEmpty ()) { // Mac OS X 10.4 compatibility mode. // There, it is possible no $DISPLAY variable is set. // Start X11 manually. First, find a free display number. x2goDebug<< "Entering 10.4 compat mode, checking for free X11 display."; int xFreeDisp = 0; QDir xtmpdir ("/tmp/.X11-unix"); if (xtmpdir.exists ()) { xtmpdir.setFilter (QDir::Files | QDir::System | QDir::NoSymLinks | QDir::NoDotAndDotDot); xtmpdir.setSorting (QDir::Name); QFileInfoList xtmpdirList = xtmpdir.entryInfoList (); bool foundFreeDisp = FALSE; xFreeDisp = -1; for (int i = 0; (i < 2000) && (!foundFreeDisp); ++i) { QFileInfo xtmpdirFile (xtmpdir.absolutePath () + "/X" + QString::number (i)); if ((!xtmpdirFile.exists ()) && (!xtmpdirFile.isSymLink ())) { xFreeDisp = i; foundFreeDisp = TRUE; } } } // Control flow will go to error condition if no free display port has been found. if (xFreeDisp != -1) { xsocket = "/tmp/.X11-unix/X" + QString::number (xFreeDisp); x2goDebug<< "Successfully detected free socket " << xsocket << "."; } if (!(xsocket.isEmpty ())) { QString xname = ConfigDialog::getXDarwinDirectory () + "/Contents/MacOS/X11"; QString xopt = ":" + QString::number (xFreeDisp); QProcessEnvironment env = QProcessEnvironment::systemEnvironment (); QProcess* startx = new QProcess (this); x2goDebug<< "Starting the X server on free display port."; /* FIXME: why not passing our current environment, maybe extended via add_to_path ()? */ env.insert (0, "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11R6/bin"); startx->setProcessEnvironment (env); startx->start (xname + QString (" ") + xopt, QIODevice::NotOpen); if (startx->waitForStarted (3000)) { x2goDebug<< "Sleeping for three seconds"; int sleeptime = 3; while ((sleeptime = sleep (sleeptime))) {}; x2goDebug<< "Leaving OS X 10.4 compat mode."; } } } // OS X >= 10.5 starts the X11 server automatically, as soon as the // launchd UNIX socket is accessed. // On user login, the DISPLAY environment variable is set to this said existing // socket. // By now, we should have a socket, even on 10.4. Test, if connecting works. // Note: common sense may tell you to change this if into an else. Don't. // We do not want to skip this part, if coming from the compat section above. if (!(xsocket.isEmpty ())) { if (xsocket[0] == ':') { // Be backwards compatible with 10.4. // Delete the ":" character. xsocket.remove (0, 1); // xsocket may now contain the display value (one integer), // or something like "0.0" - we're only interested in the // display value, so keep the first char only. if (xsocket.indexOf (".") != -1) { xsocket = xsocket.left (xsocket.indexOf (".")); } // Prepend the well-known socket path. xsocket.prepend ("/tmp/.X11-unix/X"); x2goDebug<< "xsocket in compat mode: " << xsocket; } unixSocket.connectToServer (xsocket); if (unixSocket.waitForConnected (10000)) { unixSocket.disconnectFromServer (); // Mac OS X 10.4 compat: nxproxy expects // a DISPLAY variable like ":0", passing // an UNIX socket will just make it error out. // Instead of altering the nxproxy code, which does // already try to connect to "/tmp/.X11-unix/Xi" with // i = display number, pass ":i" as DISPLAY. if (xsocket.left (16).compare ("/tmp/.x11-unix/x", Qt::CaseInsensitive) == 0) { bool ok = FALSE; int tmp = -1; xsocket = xsocket.mid (16); tmp = xsocket.toInt (&ok); if (ok) { x2goDebug<<"Returning " << QString (":") + xsocket; return (QString (":") + xsocket); } } else { return (xsocket); } } } // And if not, error out. show_XQuartz_start_error (); slotConfig(); return QString::null; } #endif #ifdef Q_OS_WIN QString ONMainWindow::getXDisplay() { if ( !isServerRunning ( 6000+xDisplay ) ) { QMessageBox::critical ( this,QString::null, tr ( "Can't start X.Org Server.\nPlease check your installation." ) ); close(); } return QString::number ( xDisplay ); } QString ONMainWindow::cygwinPath ( const QString& winPath ) { QString cPath="/cygdrive/"+winPath; cPath.replace ( "\\","/" ); cPath.replace ( ":","" ); return cPath; } #endif bool ONMainWindow::isColorDepthOk ( int disp, int sess ) { if ( sess==0 ) return true; if ( disp==sess ) return true; if ( ( disp == 24 || disp == 32 ) && ( sess == 24 || sess == 32 ) ) return true; return false; } #ifndef Q_OS_UNIX void ONMainWindow::setWidgetStyle ( QWidget* widget ) { widget->setStyle ( widgetExtraStyle ); } #else void ONMainWindow::setWidgetStyle ( QWidget* ) { } #endif QString ONMainWindow::internAppName ( const QString& transAppName, bool* found ) { if ( found ) *found=false; int ind=_transApplicationsNames.indexOf ( transAppName ); if ( ind!=-1 ) { if ( found ) *found=true; return _internApplicationsNames[ind]; } return transAppName; } QString ONMainWindow::transAppName ( const QString& internAppName, bool* found ) { if ( found ) *found=false; int ind=_internApplicationsNames.indexOf ( internAppName ); if ( ind!=-1 ) { if ( found ) *found=true; return _transApplicationsNames[ind]; } return internAppName; } void ONMainWindow::addToAppNames ( QString intName, QString transName ) { _internApplicationsNames.append ( intName ); _transApplicationsNames.append ( transName ); } void ONMainWindow::slotExecXmodmap() { #ifdef Q_WS_HILDON QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString host=resumingSession.server; QString cmd; cmd="(xmodmap -pke ;" "echo keycode 73= ;" // "echo clear shift ;" // "echo clear lock ;" // "echo clear control ;" // "echo clear mod1 ;" // "echo clear mod2 ;" // "echo clear mod3 ;" // "echo clear mod4 ;" // "echo clear mod5 ;" // "echo add shift = Shift_L ;" "echo add control = Control_R " // "echo add mod5 = ISO_Level3_Shift" ")| DISPLAY=:" +resumingSession.display+" xmodmap - "; x2goDebug<<"Executing xmodmap with cmd: "<environment(); env+=sshEnv; xmodProc->setEnvironment ( env ); } xmodProc->setFwX ( true ); xmodProc->startNormal(); #endif } void ONMainWindow::check_cmd_status() { QString passwd; QString user=getCurrentUname(); QString host=resumingSession.server; passwd=getCurrentPass(); sshConnection->executeCommand ( "x2gocmdexitmessage "+ resumingSession.sessionId , this, SLOT(slotCmdMessage(bool, QString, int))); } void ONMainWindow::slotCmdMessage ( bool result,QString output, int) { x2goDebug<<"Command message: " + output; if ( result==false ) { cardReady=false; cardStarted=false; QString message=tr ( "Connection failed.\n" ) +output; if ( message.indexOf ( "publickey,password" ) !=-1 ) { message=tr ( "Wrong password!

" ) + message; } QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); setEnabled ( true ); passForm->setEnabled ( true ); pass->setFocus(); pass->selectAll(); } if ( output.indexOf ( "X2GORUNCOMMAND ERR NOEXEC:" ) !=-1 ) { QString cmd=output; cmd.replace ( "X2GORUNCOMMAND ERR NOEXEC:","" ); if(startHidden) { x2goErrorf(14)<< tr( "Unable to execute: ") + cmd; } else { QMessageBox::critical ( 0l,tr ( "Error" ), tr ( "Unable to execute: " ) + cmd,QMessageBox::Ok, QMessageBox::NoButton ); } } if(sshConnection) delete sshConnection; sshConnection=0; if (startHidden) { x2goInfof(11) << tr("Closing X2Go Client because it was started in hidden mode."); close(); } else if (closeDisconnect) { x2goInfof(12) << tr("Closing X2Go Client because the --close-disconnect parameter was passed."); close(); } } int ONMainWindow::startSshFsTunnel() { fsTunReady=false; x2goDebug<<"Starting Folder Sharing tunnel for: "<startTunnel ( "localhost",resumingSession.fsPort.toUInt(),"127.0.0.1", clientSshPort.toInt(), true, this, SLOT ( slotFsTunnelOk(int)), SLOT ( slotFsTunnelFailed ( bool, QString,int ) ) ); return 0; } void ONMainWindow::slotFsTunnelFailed ( bool result, QString output, int) { if ( result==false ) { if ( !managedMode ) { QString message=tr ( "Unable to create SSH tunnel for Folder Sharing and Printing support:\n" ) +output; QMessageBox::critical ( 0l,tr ( "Error" ),message, QMessageBox::Ok, QMessageBox::NoButton ); } fsTunnel=0l; fsTunReady=false; } } void ONMainWindow::slotFsTunnelOk(int) { x2goDebug<<"FS tunnel through SSH seems to be up and running ..."<isRemovable; if (!dir) { return; } QTextStream out (&authorized_keys_file); out << line; authorized_keys_file.close (); x2goDebug << "Temporarily activated public key from file " << QString (fsExportKey + ".pub") << "."; QString passwd=getCurrentPass(); QString user=getCurrentUname(); QString host=resumingSession.server; QString sessionId=resumingSession.sessionId; QStringList env=QProcess::systemEnvironment(); QString cuser; #ifdef Q_WS_HILDON cuser="user"; #elif defined (Q_OS_WIN) cuser=wapiGetUserName(); #else for ( int i=0; idirList; if ( !fsInTun && clientSshPort!="22" ) { dirs=dirs+"__SSH_PORT__"+clientSshPort; } if ( fsInTun ) { dirs=dirs+"__REVERSESSH_PORT__"+resumingSession.fsPort; } if ( !rem ) cmd = "x2gomountdirs dir " + sessionId + " \"" + cuser + "\" " + dir->dstKey + " " + dirs; else cmd = "x2gomountdirs rem " + sessionId + " \"" + cuser + "\" " + dir->dstKey + " " + dirs; #ifdef Q_OS_WIN cmd="chmod 600 "+dir->dstKey+"&&"+cmd; #endif X2goSettings st ( "sessions" ); if ( !useLdap ) { QString sid; if ( !embedMode ) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, not calling startx2gomount command."; return; } sid=sessionExplorer->getLastSession()->id(); } else sid="embedded"; if ( st.setting()->value ( sid+"/useiconv", ( QVariant ) false ).toBool() ) { QString toCode=st.setting()->value ( sid+"/iconvto", ( QVariant ) "UTF-8" ).toString(); #ifdef Q_OS_WIN QString fromCode=st.setting()->value ( sid+"/iconvfrom", ( QVariant ) tr ( "WINDOWS-1252" ) ).toString(); #endif #ifdef Q_OS_DARWIN QString fromCode=st.setting()->value ( sid+"/iconvfrom", ( QVariant ) "UTF-8" ).toString(); #endif #ifdef Q_OS_UNIX QString fromCode=st.setting()->value ( sid+"/iconvfrom", ( QVariant ) tr ( "ISO8859-1" ) ).toString(); #endif cmd="export X2GO_ICONV=modules=iconv,from_code="+ fromCode+ ",to_code="+toCode+"&&"+cmd; } } x2goDebug<<"Calling startX2goMount command."<pid=sshConnection->executeCommand(cmd,this,SLOT ( slotRetExportDir ( bool, QString,int) )); } void ONMainWindow::slotCheckPrintSpool() { QDir dir ( spoolDir ); QStringList list = dir.entryList ( QDir::Files ); for ( int i=0; i #include #include #endif bool ONMainWindow::isServerRunning ( int port ) { #ifdef Q_OS_WIN SOCKET ConnectSocket = INVALID_SOCKET; struct sockaddr_in saServer; hostent* localHost; char* localIP; int iResult; WSADATA wsaData; struct in_addr addr = {{ }}; iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { x2goDebug<<"WARNING: WSAStartup failed: "<< iResult; return false; } addr.s_addr = inet_addr("127.0.0.1"); if (addr.s_addr == INADDR_NONE) { x2goDebug<< "WARNING: The IPv4 address entered was invalid.\n"; return false; } localHost = gethostbyaddr((char*)&addr,4, AF_INET); if (!localHost) { x2goDebug<<"WARNING: gethostbyaddr failed: "<h_addr_list); saServer.sin_family = AF_INET; saServer.sin_addr.s_addr = inet_addr(localIP); saServer.sin_port = htons(port); ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (ConnectSocket == INVALID_SOCKET) { x2goDebug<<"WARNING: Socket failed with error: "<< WSAGetLastError(); return false; } iResult = ::connect( ConnectSocket, (SOCKADDR*) &saServer, sizeof(saServer)); if (iResult == SOCKET_ERROR) { closesocket(ConnectSocket); x2goDebug<<"Port is free: "<stop(); slotSetWinServersReady(); xorgLogMutex.unlock(); return; } } xorgLogMutex.unlock(); } void ONMainWindow::startXOrg (std::size_t start_offset) { xDisplay += start_offset; while ( isServerRunning ( 6000+xDisplay ) ) ++xDisplay; QString dispString; QTextStream ( &dispString ) <<":"<setEnvironment ( env ); xorg-> setWorkingDirectory ( workingDir); } x2goDebug<<"Running "<start ( exec, args ); if ( !xorg->waitForStarted ( 3000 ) ) { QMessageBox::critical ( 0,QString::null, tr ( "Can't start X.Org Server." ) + "\n" + tr ( "Please check your installation." ) ); close(); } // #ifdef CFGCLIENT if ( !useInternalX || internalX!= XMING) { //check connection in slot and launch setWinServerReady waitingForX=0; x_start_tries_ += 1; QTimer::singleShot(1000, this, SLOT(slotCheckXOrgConnection())); } // #endif } void ONMainWindow::slotCheckXOrgConnection() { ++waitingForX; /* Before we try to connect to the socket, let's check if the server actually is still running. */ if (xorg->state () != QProcess::Running) { /* * Process died (crashed, terminated, whatever). We need to restart it, unless we already tried * to do so multiple times unsuccessfully. */ if ((x_start_limit_) && (x_start_limit_ < x_start_tries_)) { x2goDebug << "Unable to start X.Org Server for " << x_start_limit_ << " times, terminating."; QMessageBox::critical (NULL, QString::null, tr ("X.Org Server did not launch correctly after %n tries.", "%n will be substituted with the current number of tries", x_start_tries_) + "\n" + tr ("Please check your installation.")); close (); return; } x2goDebug << "Trying to re-start X.Org Server. Try count: " << x_start_tries_; delete xorg; xorg = NULL; startXOrg (1); return; } if (isServerRunning(6000+xDisplay)) { x2goDebug<<"X.Org Server started on DISPLAY " << xDisplay << "."; slotSetWinServersReady(); } else { if (waitingForX > 10) { /* * Timeout reached. If we tried starting the X.Org Server less times than the limit, * continue doing so (with a higher DISPLAY value). * Otherwise error out. */ if ((!(x_start_limit_)) || (x_start_limit_ >= x_start_tries_)) { /* * Server might still be running here, but deleting the QProcess object * should kill it. */ x2goDebug << "Timeout reached waiting for the X.Org Server to open a listening TCP socket." << endl << "Restarting on higher DISPLAY port. Try count: " << x_start_tries_; xorg->terminate (); delete xorg; xorg = NULL; startXOrg (1); return; } else { QMessageBox::critical (NULL, QString::null, tr ("Can't start X.Org Server.") + "\n" + tr ("Please check your installation.")); close(); return; } } else { x2goDebug<<"Waiting for X.Org Server to start."; QTimer::singleShot(1000, this, SLOT(slotCheckXOrgConnection())); } } } WinServerStarter::WinServerStarter ( daemon server, ONMainWindow * par ) : QThread ( 0 ), mode (server), parent (par), ssh_key_type_ (ONMainWindow::RSA_KEY_TYPE) { } void WinServerStarter::run() { switch ( mode ) { case SSH: parent->startSshd(ssh_key_type_); break; case X: parent->startXOrg(); break; } } void WinServerStarter::set_ssh_key_type (ONMainWindow::key_types key_type) { ssh_key_type_ = key_type; } ONMainWindow::key_types WinServerStarter::get_ssh_key_type () { return (ssh_key_type_); } void ONMainWindow::startWinServers(ONMainWindow::key_types key_type) { key_type = check_key_type (key_type); x2goDebug<<"Starting helper servers for Windows ..."; QString etcDir=homeDir+"/.x2go/etc"; QDir dr ( homeDir ); WinServerStarter* xStarter = new WinServerStarter ( WinServerStarter::X, this ); WinServerStarter* sshStarter = new WinServerStarter ( WinServerStarter::SSH, this ); if ( !embedMode || !config.confFS || ( config.confFS && config.useFs ) ) { dr.mkpath ( etcDir ); UNUSED (generateKey (key_type, true)); sshStarter->set_ssh_key_type (key_type); sshStarter->start(); } // #ifdef CFGCLIENT //x2goDebug<<"Xorg settings: "<< startXorgOnStart <<" useXming: "<< useXming; if ( useInternalX && (internalX== XMING)) { // #endif xStarter->start(); xorgLogTimer=new QTimer ( this ); connect ( xorgLogTimer,SIGNAL ( timeout() ),this, SLOT ( slotCheckXOrgLog() ) ); xorgLogTimer->start ( 500 ); // #ifdef CFGCLIENT } else { if (startXorgOnStart) { startXOrg(); } } // #endif } bool ONMainWindow::haveCygwinEntry() { QSettings CygwSt ( "HKEY_CURRENT_USER\\Software" "\\Cygwin", QSettings::NativeFormat ); return ( CygwSt.childGroups().count() >0||CygwSt.childKeys().count() ); } void ONMainWindow::saveCygnusSettings() { if ( ONMainWindow::portable ) { if ( haveCygwinEntry() ) { x2goDebug<<"Cygnus Solutions entry exists."; cyEntry=true; } else { x2goDebug<<"Cygnus Solutions entry does not exist."; cyEntry=false; } } } void ONMainWindow::restoreCygnusSettings() { if ( ONMainWindow::portable ) { if ( !cyEntry ) { removeCygwinEntry(); } } } void ONMainWindow::removeCygwinEntry() { QSettings st ( "HKEY_CURRENT_USER\\Software" "\\Cygwin", QSettings::NativeFormat ); x2goDebug<<"Removing cygwin entry from registry."; st.remove ( "" ); st.sync(); } // #ifdef CFGCLIENT void ONMainWindow::xorgSettings() { x2goDebug<<"Getting X.Org Server settings."; X2goSettings st ( "settings" ); useInternalX=(st.setting()->value("useintx",true).toBool()); xorgExe=(st.setting()->value("xexec","C:\\program files\\vcxsrv\\vcxsrv.exe").toString()); xorgOptions=(st.setting()->value("options","-multiwindow -notrayicon -clipboard").toString()); startXorgOnStart=(st.setting()->value("onstart",true).toBool()); xorgWinOptions=(st.setting()->value("optionswin","-screen 0 %wx%h -notrayicon -clipboard").toString()); xorgFSOptions=(st.setting()->value("optionsfs","-fullscreen -notrayicon -clipboard").toString()); xorgSAppOptions=(st.setting()->value("optionssingle","-multiwindow -notrayicon -clipboard").toString()); xorgMDOptions=(st.setting()->value("optionswholedisplay","-nodecoration -notrayicon -clipboard -screen 0 @").toString()); if (QFile::exists(appDir+"\\vcxsrv")) internalX=VCXSRV; if (QFile::exists(appDir+"\\xming")) internalX=XMING; QString primClip; if(st.setting()->value("noprimaryclip",false).toBool() && internalX==VCXSRV) primClip=" -noprimary"; if (useInternalX) { startXorgOnStart=(internalX==XMING); xorgOptions="-multiwindow -notrayicon -clipboard"+primClip; if (internalX==VCXSRV) { // xorgWinOptions="-screen 0 %wx%h -notrayicon -clipboard"; xorgWinOptions="-multiwindow -notrayicon -clipboard"+primClip; xorgFSOptions="-fullscreen -notrayicon -clipboard"+primClip; xorgSAppOptions="-multiwindow -notrayicon -clipboard"+primClip; xorgMDOptions="-nodecoration -notrayicon -clipboard"+primClip+" -screen 0 @"; } } } // #endif void ONMainWindow::slotSetWinServersReady() { x2goDebug<<"All helper servers for Windows are started."; winServersReady=true; restoreCygnusSettings(); } #include #include #endif void ONMainWindow::generateEtcFiles() { QString etcDir=homeDir+"/.x2go/etc"; QString varDir = homeDir + "/.x2go/var"; QDir dr ( homeDir ); dr.mkpath ( etcDir ); dr.mkpath (varDir); QFile file ( etcDir +"/sshd_config" ); if ( !file.open ( QIODevice::WriteOnly | QIODevice::Text ) ) return; QString authKeyPath = homeDir + "/.x2go/.ssh/authorized_keys"; #ifdef Q_OS_WIN authKeyPath = cygwinPath (authKeyPath); authKeyPath.replace (wapiGetUserName (), "%u"); varDir = cygwinPath (varDir); x2goDebug << varDir << " cygwin var path"; #endif /* defined (Q_OS_WIN) */ QTextStream out ( &file ); out<<"StrictModes no\n"<< #ifdef Q_OS_WIN "StrictKeyModes no\n" << #endif "UsePrivilegeSeparation no\n"<< "PidFile \"" + varDir + "/sshd.pid\"\n" << "AuthorizedKeysFile \"" << authKeyPath << "\"\n"; #ifdef Q_OS_WIN out << "Subsystem shell "<< wapiShortFileName ( appDir) +"/sh"+"\n"<< "Subsystem sftp "<< wapiShortFileName ( appDir) +"/sftp-server"+"\n"; #else /* * We need to find the sftp-server binary. * This turns out to be surprisingly difficult, because there is no standard place * for this binary. Instead, every distribution installs it where they see fit. * Needless to say, we're screwed... */ QString sftp_binary; QStringList common_sftp_dirs; common_sftp_dirs << "/usr/lib/openssh" /* Debian and Ubuntu */ << "/usr/libexec/openssh" /* Fedora, CentOS, hopefully also RHEL */ << "/usr/lib/ssh" /* Mageia, OpenSUSE, SLE{S,D} < 12 x86, SLE{S,D} 12, Arch */ << "/usr/lib64/ssh" /* SLE{S,D} < 12 x86_64 */ << "/usr/lib64/misc" /* Gentoo *64 with 17.1 profile - has no lib compat-symlink. */ << "/usr/lib/misc" /* Gentoo */ << "/run/current-system/sw/bin" /* NixOS */ << "/usr/libexec"; /* Slackware, OS X */ #if QT_VERSION < 0x050000 QProcessEnvironment tmp_env = QProcessEnvironment::systemEnvironment (); QString path_val = tmp_env.value ("PATH"); path_val = add_to_path (path_val, common_sftp_dirs); /* Just in case we bundle sftp-server ourselves. */ sftp_binary = find_binary (appDir, "sftp-server"); if (sftp_binary.isEmpty ()) { sftp_binary = find_binary (path_val, "sftp-server"); } #else /* QT_VERSION < 0x050000 */ QStringList search_paths; search_paths << appDir; sftp_binary = QStandardPaths::findExecutable ("sftp-server", search_paths); if (sftp_binary.isEmpty ()) { search_paths = QStringList (); sftp_binary = QStandardPaths::findExecutable ("sftp-server", search_paths); if (sftp_binary.isEmpty ()) { search_paths = common_sftp_dirs; sftp_binary = QStandardPaths::findExecutable ("sftp-server", search_paths); } } #endif /* QT_VERSION < 0x050000 */ if (sftp_binary.isEmpty ()) { x2goErrorf (31) << "Unable to find the sftp-server binary. Neither bundled, nor found in $PATH nor additional directories."; show_RichText_ErrorMsgBox (tr ("Unable to find the sftp-server binary. Neither bundled, nor found in $PATH nor additional directories."), tr ("If you are using a Linux-based operating system, please ask your system administrator " "to install the package containing the sftp-server binary. Common names are openssh, " "openssh-server or openssh-sftp-server depending upon distribution.\n\n" "If the sftp-server binary is installed on your system, please report a bug " "mentioning its path on:\n" "
" "https://wiki.x2go.org/doku.php/wiki:bugs" "
\n"), true); abort (); } out << "Subsystem sftp " << sftp_binary << "\n"; #endif /* The log file in startSshd() is specific to Windows. */ #ifdef Q_OS_WIN if (debugging){ out<<"LogLevel DEBUG1\n"; } #endif file.close(); x2goDebug<exists()) sshLogsDir->mkpath("."); QTemporaryFile* sshLogTemp=new QTemporaryFile ( sshLogsDir->absolutePath()+"/XXXXXX.log" ); sshLogTemp->open(); sshLog=sshLogTemp->fileName(); sshLogTemp->close(); delete sshLogsDir; delete sshLogTemp; x2goDebug<<"Logging cygwin sshd to: "<start (binary, arguments); /* Allow sshd a grace time of 5 seconds to come up. */ QTime sleep_time = QTime::currentTime ().addSecs (5); while (QTime::currentTime () < sleep_time) { if (QProcess::Running == sshd->state ()) { /* * Additionally, spin up to 3 seconds to give sshd * the opportunity to launch its listening socket. */ QTime new_sleep_time = QTime::currentTime ().addSecs (3); while (QTime::currentTime () < new_sleep_time) { if (isServerRunning (clientSshPort.toInt ())) { break; } QCoreApplication::processEvents (QEventLoop::AllEvents, 100); } break; } QCoreApplication::processEvents (QEventLoop::AllEvents, 100); } #endif /* defined (Q_OS_WIN) */ /* Check to see if connecting to the listening socket works. */ if (!isServerRunning (clientSshPort.toInt ())) { printSshDError_startupFailure (); x2goDebug << "Failed to start user mode OpenSSH server."; return (false); } else { x2goDebug << "User mode OpenSSH server started successfully."; return (true); } } void ONMainWindow::setProxyWinTitle() { if (embedMode) return; QString title; if (!useLdap) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, not setting proxy window title."; return; } title=sessionExplorer->getLastSession()->name(); } else title=getCurrentUname()+"@"+resumingSession.server; QPixmap pixmap; if (useLdap) pixmap=lastUser->foto(); else pixmap=*(sessionExplorer->getLastSession()->sessIcon()); #ifdef Q_OS_UNIX XStoreName(QX11Info::display(), proxyWinId, title.toLocal8Bit().data()); XWMHints* win_hints; QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer, "XPM"); int rez; if (image) XFreePixmap(QX11Info::display(),image); if (shape) XFreePixmap(QX11Info::display(),shape); rez=XpmCreatePixmapFromBuffer(QX11Info::display(), proxyWinId, bytes.data(), (Pixmap *) &image, (Pixmap *) &shape, NULL); if (!rez) { win_hints = XAllocWMHints(); if (win_hints) { win_hints->flags = IconPixmapHint|IconMaskHint; win_hints->icon_pixmap = image; win_hints->icon_mask = shape; XSetWMHints(QX11Info::display(), proxyWinId, win_hints); XFree(win_hints); } } #endif #ifdef Q_OS_WIN wapiSetWindowText((HWND)proxyWinId, title); // wapiSetWindowIcon((HWND)proxyWinId, pixmap); #endif } void ONMainWindow::slotSetProxyWinFullscreen() { #ifdef Q_OS_UNIX QRect geom=QApplication::desktop()->screenGeometry(localDisplayNumber-1); Atom atom = XInternAtom ( QX11Info::display(), "_NET_WM_STATE_FULLSCREEN", True ); XChangeProperty ( QX11Info::display(), proxyWinId, XInternAtom ( QX11Info::display(), "_NET_WM_STATE", True ), XA_ATOM, 32, PropModeReplace, (unsigned char*) &atom, 1 ); XMapWindow(QX11Info::display(), proxyWinId); XSync(QX11Info::display(),false); XEvent event; event.xclient.type = ClientMessage; event.xclient.serial = 0; event.xclient.send_event = True; event.xclient.display = QX11Info::display(); event.xclient.window = proxyWinId; event.xclient.message_type = XInternAtom(QX11Info::display(),"_NET_WM_STATE",False); event.xclient.format = 32; event.xclient.data.l[0] = 1; event.xclient.data.l[1] = XInternAtom(QX11Info::display(),"_NET_WM_STATE_FULLSCREEN",False); event.xclient.data.l[2] = 0; event.xclient.data.l[3] = 1; event.xclient.data.l[4] = 0; Status st; st=XSendEvent(QX11Info::display(), DefaultRootWindow(QX11Info::display()), False, SubstructureNotifyMask ,&event); if(!st) { x2goDebug<<"Couldn't fetch fullscreen setting."; } XSync(QX11Info::display(),false); XMapWindow(QX11Info::display(), proxyWinId); QString geoStr = QString("%1").arg(geom.width()) + "x"+ QString("%1").arg(geom.height()); sshConnection->executeCommand("DISPLAY=:"+resumingSession.display+" xrandr --output default --mode "+geoStr); #endif } void ONMainWindow::resizeProxyWinOnDisplay(int disp) { QRect geom=QApplication::desktop()->screenGeometry(disp-1); QString geoStr = "(x: " + QString("%1").arg(geom.x()) + ", y: "+ QString("%1").arg(geom.y()) + ", w: "+ QString("%1").arg(geom.width()) + ", h: "+ QString("%1").arg(geom.height()); x2goDebug<<"Resizing proxy window to fit display: " + QString("%1").arg(disp) + " " + geoStr; #ifdef Q_OS_UNIX XSync(QX11Info::display(),false); XMoveResizeWindow(QX11Info::display(), proxyWinId, geom.x(), geom.y(), 800, 600); XMapWindow(QX11Info::display(), proxyWinId); XFlush(QX11Info::display()); #endif #ifdef Q_OS_WIN dispGeometry=geom; #endif QTimer::singleShot(500, this, SLOT(slotSetProxyWinFullscreen())); } QRect ONMainWindow::proxyWinGeometry() { #ifdef Q_OS_WIN QRect proxyRect; if (!wapiWindowRectWithoutDecoration((HWND)proxyWinId,proxyRect)) return QRect(); return proxyRect; #endif #ifdef Q_OS_UNIX QRect proxyRect; Window root; int x,y; uint w,h,border,depth; if (XGetGeometry(QX11Info::display(), proxyWinId, &root,&x,&y,&w,&h,&border,&depth)) { int realx,realy; Window child; XTranslateCoordinates(QX11Info::display(), proxyWinId, root, 0, 0, &realx, &realy, &child); proxyRect.setRect(realx, realy, w,h); } return proxyRect; #endif return QRect(); } void ONMainWindow::slotConfigXinerama() { QRect newGeometry=proxyWinGeometry(); if (newGeometry.isNull()) { x2goWarningf(7)<< tr("Error getting window geometry. (Did you close the window?)"); xineramaTimer->stop(); return; } if (newGeometry==lastDisplayGeometry) return; lastDisplayGeometry=newGeometry; QString geoStr = "(x: " + QString("%1").arg(lastDisplayGeometry.x()) + ", y: "+ QString("%1").arg(lastDisplayGeometry.y()) + ", w: "+ QString("%1").arg(lastDisplayGeometry.width()) + ", h: "+ QString("%1").arg(lastDisplayGeometry.height()); x2goDebug<<"New proxy geometry: " + geoStr; QDesktopWidget* root=QApplication::desktop(); QList newXineramaScreens; for (int i=0; i< root->numScreens(); ++i) { QRect intersection; if (resumingSession.fullscreen) { x2goDebug<<"correcting display geometry for full screen session"; lastDisplayGeometry.setX(0); lastDisplayGeometry.setY(0); intersection=root->screenGeometry(i); } else intersection=root->screenGeometry(i).intersected(lastDisplayGeometry); if (!intersection.isNull()) { // x2goDebug<<"intersected with "<stop(); QStringList screens; foreach (QRect disp, xineramaScreens) screens< $HOME/.x2go/C-"+ resumingSession.sessionId+"/xinerama.conf"; sshConnection->executeCommand(cmd, this, SLOT(slotXineramaConfigured())); } } void ONMainWindow::slotXineramaConfigured() { if (resumingSession.fullscreen) return; if (xinSizeInc == -1) xinSizeInc=1; else xinSizeInc=-1; #ifdef Q_OS_UNIX lastDisplayGeometry.setWidth(lastDisplayGeometry.width()+xinSizeInc); XSync(QX11Info::display(),false); XResizeWindow(QX11Info::display(), proxyWinId, lastDisplayGeometry.width(),lastDisplayGeometry.height()); XSync(QX11Info::display(),false); #endif #ifdef Q_OS_WIN QRect geom; wapiWindowRect ( (HWND) proxyWinId, geom ); wapiMoveWindow( (HWND) proxyWinId, geom.x(), geom.y(), geom.width()+xinSizeInc, geom.height(),true); lastDisplayGeometry=proxyWinGeometry(); #endif xineramaTimer->start(500); } void ONMainWindow::slotFindProxyWin() { #ifndef Q_OS_DARWIN x2goDebug<<"Searching proxy window: X2GO-" + resumingSession.sessionId; proxyWinId=findWindow ( "X2GO-"+resumingSession.sessionId ); bool xinerama=defaultXinerama; if ( proxyWinId ) { x2goDebug<<"Proxy window found: " + QString("%1").arg(proxyWinId); setProxyWinTitle(); proxyWinTimer->stop(); if (!embedMode && !(resumingSession.sessionType==x2goSession::KDRIVE)) { if (!useLdap) { X2goSettings *st; QString sid; if ( !embedMode ) { if (!(sessionExplorer->getLastSession())) { x2goDebug << "No session selected, not searching for proxy window."; return; } sid=sessionExplorer->getLastSession()->id(); } else sid="embedded"; if (brokerMode) st=new X2goSettings(config.iniFile,QSettings::IniFormat); else st= new X2goSettings( "sessions" ); xinerama=st->setting()->value ( sid+"/xinerama", ( QVariant ) defaultXinerama ).toBool(); #ifndef Q_OS_WIN uint displays=QApplication::desktop()->numScreens(); if (st->setting()->value ( sid+"/multidisp", ( QVariant ) false ).toBool()) { uint disp=st->setting()->value ( sid+"/display", ( QVariant ) 1 ).toUInt(); delete st; if (disp>displays) { disp=1; } localDisplayNumber=disp; resizeProxyWinOnDisplay(disp); return; } #endif delete st; } if (xinerama) { x2goDebug<<"Starting Xinerama timer."; lastDisplayGeometry=QRect(); xineramaScreens.clear(); xineramaTimer->start(500); } } if ( embedMode ) { x2goDebug<<"Checking rootless config."; if ( config.rootless ) { x2goDebug<<"Window is rootless."; act_embedContol->setEnabled ( false ); } else slotAttachProxyWindow(); } #ifdef Q_OS_WIN x2goDebug<<"Maximize proxy window: "<text(); } QString ONMainWindow::getCurrentPass() { return pass->text(); } void ONMainWindow::slotDetachProxyWindow() { proxyWinEmbedded=false; bgFrame->show(); setStatStatus(); act_embedContol->setText ( tr ( "Attach X2Go window" ) ); act_embedContol->setIcon ( QIcon ( ":/img/icons/32x32/attach.png" ) ); #ifdef Q_OS_UNIX //if QX11EmbedContainer cannot embed window, check if window exists //and reconnect if ( !embedControlChanged ) { slotFindProxyWin(); x2goDebug<<"Proxy window detached, proxywin is: "<hide(); proxyWinEmbedded=true; setStatStatus(); act_embedContol->setText ( tr ( "Detach X2Go window" ) ); act_embedContol->setIcon ( QIcon ( ":/img/icons/32x32/detach.png" ) ); QTimer::singleShot ( 100, this, SLOT ( slotEmbedWindow() ) ); } else { x2goDebug<<"Start embedded was false."; startEmbedded=true; } } void ONMainWindow::slotEmbedWindow() { #ifndef Q_OS_DARWIN QTimer::singleShot ( 1000, this, SLOT ( slotActivateWindow() ) ); #endif } void ONMainWindow::setEmbedSessionActionsEnabled ( bool enable ) { act_shareFolder->setEnabled ( enable ); if(!enable) act_showApps->setVisible(enable); act_suspend->setEnabled ( enable ); act_terminate->setEnabled ( enable ); act_embedContol->setEnabled ( enable ); act_reconnect->setEnabled ( !enable ); } void ONMainWindow::slotEmbedControlAction() { #ifndef Q_OS_DARWIN embedControlChanged=true; if ( !proxyWinEmbedded ) { slotAttachProxyWindow(); } #endif } void ONMainWindow::slotEmbedIntoParentWindow() { #ifndef Q_OS_DARWIN // embedInto ( embedParent ); #endif } void ONMainWindow::processSessionConfig() { bool haveKey=false; UNUSED (haveKey); config.command="KDE"; config.brokerNoAuth=false; config.sshport="22"; config.session=tr ( "X2Go Session" ); config.checkexitstatus=true; config.showtermbutton=true; config.showexpbutton=true; config.showconfig=true; config.showextconfig=true; config.showtoolbar=true; config.showstatusbar=true; config.kbdType=getDefaultKbdType(); config.kbdLay=getDefaultLayout()[0]; config.confSnd=false; config.confFS=false; config.confConSpd=false; config.confCompMet=false; config.confImageQ=false; config.confDPI=false; config.confKbd=false; QStringList lines=m_x2goconfig.split ( "\n" ); for ( int i=0; isetVisible ( config.showtermbutton ); act_shareFolder->setVisible ( config.showexpbutton ); act_set->setVisible ( config.showconfig ); if (!config.showstatusbar) { statusBar()->hide(); } if ( managedMode ) { QTimer::singleShot ( 500, this, SLOT ( slotStartBroker() ) ); return; } slotSelectedFromList ( ( SessionButton* ) 0 ); } void ONMainWindow::processCfgLine ( QString line ) { QStringList lst=line.split ( "=" ); if ( lst[0]=="command" ) { config.command=lst[1]; if ( config.command=="SHADOW" ) { shadowSession=true; runRemoteCommand=false; } return; } if ( lst[0]=="server" ) { config.server=lst[1]; return; } if ( lst[0]=="session" ) { config.session=lst[1]; return; } if ( lst[0]=="sshport" ) { config.sshport=lst[1]; return; } if ( lst[0]=="user" ) { config.user=lst[1]; return; } if ( lst[0]=="rootless" ) { if ( lst[1]=="true" ) config.rootless=true; else config.rootless=false; return; } if ( lst[0]=="published" ) { if ( lst[1]=="true" ) config.published=true; else config.published=false; return; } if ( lst[0]=="checkexitstatus" ) { if ( lst[1]=="true" ) config.checkexitstatus=true; else config.checkexitstatus=false; return; } if ( lst[0]=="showtermbutton" ) { if ( lst[1]=="true" ) config.showtermbutton=true; else config.showtermbutton=false; return; } if ( lst[0]=="showexpbutton" ) { if ( lst[1]=="true" ) config.showexpbutton=true; else config.showexpbutton=false; return; } if ( lst[0]=="showconfig" ) { if ( lst[1]=="true" ) config.showconfig=true; else config.showconfig=false; return; } if ( lst[0]=="showextconfig" ) { if ( lst[1]=="true" ) config.showextconfig=true; else config.showextconfig=false; return; } if ( lst[0]=="showstatusbar" ) { if ( lst[1]=="true" ) config.showstatusbar=true; else config.showstatusbar=false; return; } if ( lst[0]=="showtoolbar" ) { if ( lst[1]=="true" ) config.showtoolbar=true; else config.showtoolbar=false; return; } if ( lst[0]=="sound" ) { config.confSnd=true; if ( lst[1]=="true" ) config.useSnd=true; else config.useSnd=false; return; } if ( lst[0]=="exportfs" ) { config.confFS=true; if ( lst[1]=="true" ) config.useFs=true; else config.useFs=false; return; } if ( lst[0]=="speed" ) { config.confConSpd=true; config.conSpeed=ADSL; if ( lst[1]=="modem" ) config.conSpeed=MODEM; else if ( lst[1]=="isdn" ) config.conSpeed=ISDN; else if ( lst[1]=="adsl" ) config.conSpeed=ADSL; else if ( lst[1]=="wan" ) config.conSpeed=WAN; else if ( lst[1]=="lan" ) config.conSpeed=LAN; else { qCritical ( "%s",tr ( "Invalid value for argument \"speed\"" ).toLocal8Bit().data() ); } return; } if ( lst[0]=="compression" ) { config.confCompMet=true; config.compMet=lst[1]; return; } if ( lst[0]=="quality" ) { config.confImageQ=true; config.imageQ=lst[1].toInt(); return; } if ( lst[0]=="dpi" ) { config.confDPI=true; config.dpi=lst[1].toInt(); return; } if ( lst[0]=="kbdlayout" ) { config.confKbd=true; config.kbdLay=lst[1]; return; } if ( lst[0]=="kbdtype" ) { config.confKbd=true; config.kbdType=lst[1]; return; } if ( lst[0]=="brokerurl" ) { config.brokerurl=lst[1]; managedMode=true; acceptRsa=true; } if ( lst[0]=="cookie" ) { config.cookie=lst[1]; return; } if ( lst[0]=="x2gosession" ) { config.sessiondata=lst[1]; return; } if ( lst[0]=="connectionts" ) { config.connectionts=lst[1]; return; } if (lst[0] == "usesshproxy") { config.useproxy = true; if (lst[1].toLower () == "true") { config.useproxy = true; } else { config.useproxy = false; } return; } if (lst[0] == "sshproxytype") { if (lst[1].toLower () == "http") { config.proxyType = SshMasterConnection::PROXYHTTP; } else { config.proxyType = SshMasterConnection::PROXYSSH; } return; } if (lst[0] == "sshproxyuser") { config.proxylogin = lst[1]; return; } if (lst[0] == "sshproxyhost") { config.proxyserver = lst[1]; return; } if (lst[0] == "sshproxyport") { config.proxyport = lst[1].toInt (); return; } if (lst[0] == "sshproxyautologin") { if (lst[1].toLower () == "true") { config.proxyAutologin = true; } else { config.proxyAutologin = false; } return; } if (lst[0] == "sshproxykrblogin") { if (lst[1].toLower () == "true") { config.proxyKrbLogin = true; } else { config.proxyKrbLogin = false; } return; } if (lst[0] == "sshproxykeyfile") { config.proxyKey = lst[1]; return; } } void ONMainWindow::slotChangeKbdLayout(const QString& layout) { #ifdef Q_OS_UNIX QStringList args; args<<"-layout"<setMainWidget ( ( QWidget* ) this ); #endif username->addWidget ( passForm ); passForm->hide(); setWidgetStyle ( passForm ); if ( !miniMode ) passForm->setFixedSize ( passForm->sizeHint() ); else passForm->setFixedSize ( 310,180 ); QPalette pal=passForm->palette(); pal.setBrush ( QPalette::Window, QColor ( 255,255,255,0 ) ); pal.setColor ( QPalette::Active, QPalette::WindowText, QPalette::Mid ); pal.setColor ( QPalette::Active, QPalette::ButtonText, QPalette::Mid ); pal.setColor ( QPalette::Active, QPalette::Text, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::WindowText, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::ButtonText, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::Text, QPalette::Mid ); passForm->setPalette ( pal ); pal.setColor ( QPalette::Button, QColor ( 255,255,255,0 ) ); pal.setColor ( QPalette::Window, QColor ( 255,255,255,255 ) ); pal.setColor ( QPalette::Base, QColor ( 255,255,255,255 ) ); QFont fnt=passForm->font(); if ( miniMode ) #ifdef Q_WS_HILDON fnt.setPointSize ( 10 ); #else fnt.setPointSize ( 9 ); #endif passForm->setFont ( fnt ); fotoLabel=new QLabel ( passForm ); fotoLabel->hide(); nameLabel=new QLabel ( "",passForm ); nameLabel->hide(); loginPrompt=new QLabel ( tr ( "Login:" ),passForm ); passPrompt=new QLabel ( tr ( "Password:" ),passForm ); layoutPrompt=new QLabel ( tr ( "Keyboard layout:" ),passForm ); login=new ClickLineEdit ( passForm ); setWidgetStyle ( login ); login->setFrame ( false ); login->setEnabled ( false ); login->hide(); loginPrompt->hide(); pass=new ClickLineEdit ( passForm ); setWidgetStyle ( pass ); pass->setFrame ( false ); fnt.setBold ( true ); pass->setFont ( fnt ); pass->setEchoMode ( QLineEdit::Password ); pass->setFocus(); #ifdef Q_OS_UNIX connect ( login,SIGNAL ( clicked() ),this, SLOT ( slotActivateWindow() ) ); connect ( pass,SIGNAL ( clicked() ),this, SLOT ( slotActivateWindow() ) ); #endif pass->hide(); passPrompt->hide(); cbLayout=new QComboBox(passForm); cbLayout->addItems(defaultLayout); cbLayout->setFocusPolicy(Qt::NoFocus); cbLayout->setFrame(false); setWidgetStyle(cbLayout); cbLayout->hide(); layoutPrompt->hide(); QHBoxLayout* cbLayoutLay=new QHBoxLayout(); cbLayoutLay->addWidget(cbLayout); cbLayoutLay->addStretch(); ok=new QPushButton ( tr ( "Ok" ),passForm ); setWidgetStyle ( ok ); cancel=new QPushButton ( tr ( "Cancel" ),passForm ); setWidgetStyle ( cancel ); ok->hide(); cancel->hide(); cbLayout->setPalette ( pal ); ok->setPalette ( pal ); cancel->setPalette ( pal ); #ifndef Q_WS_HILDON ok->setFixedSize ( ok->sizeHint() ); cancel->setFixedSize ( cancel->sizeHint() ); #else QSize sz=cancel->sizeHint(); sz.setWidth ( ( int ) ( sz.width() /1.5 ) ); sz.setHeight ( ( int ) ( sz.height() /1.5 ) ); cancel->setFixedSize ( sz ); sz=ok->sizeHint(); sz.setWidth ( ( int ) ( sz.width() /1.5 ) ); sz.setHeight ( ( int ) ( sz.height() /1.5 ) ); ok->setFixedSize ( sz ); #endif QVBoxLayout *layout=new QVBoxLayout ( passForm ); QHBoxLayout *labelLay=new QHBoxLayout(); QHBoxLayout *inputLay=new QHBoxLayout(); QHBoxLayout *buttonLay=new QHBoxLayout(); labelLay->setSpacing ( 20 ); inputLay->setSpacing ( 10 ); layout->setContentsMargins ( 20,20,10,10 ); layout->addLayout ( labelLay ); layout->addStretch(); layout->addLayout ( inputLay ); layout->addStretch(); layout->addLayout ( buttonLay ); labelLay->addWidget ( fotoLabel ); labelLay->addWidget ( nameLabel ); labelLay->addStretch(); QVBoxLayout* il1=new QVBoxLayout(); il1->addWidget ( loginPrompt ); il1->addWidget ( passPrompt ); il1->addWidget ( layoutPrompt ); QVBoxLayout* il2=new QVBoxLayout(); il2->addWidget ( login ); il2->addWidget ( pass ); il2->addLayout ( cbLayoutLay ); inputLay->addLayout ( il1 ); inputLay->addLayout ( il2 ); inputLay->addStretch(); buttonLay->addStretch(); buttonLay->addWidget ( ok ); buttonLay->addWidget ( cancel ); buttonLay->addStretch(); pal.setColor ( QPalette::Base, QColor ( 239,239,239,255 ) ); login->setPalette ( pal ); pass->setPalette ( pal ); connect ( ok,SIGNAL ( clicked() ),this, SLOT ( slotSessEnter() ) ); connect ( cancel,SIGNAL ( clicked() ),this, SLOT ( slotClosePass() ) ); connect ( pass,SIGNAL ( returnPressed() ),this, SLOT ( slotSessEnter() ) ); connect ( login,SIGNAL ( returnPressed() ),pass, SLOT ( selectAll() ) ); connect ( login,SIGNAL ( returnPressed() ),pass, SLOT ( setFocus() ) ); passPrompt->show(); pass->show(); ok->show(); cancel->show(); fotoLabel->show(); nameLabel->show(); if ( !useLdap ) { login->show(); loginPrompt->show(); } if ( embedMode ) { cancel->setEnabled ( false ); #ifdef Q_OS_WIN QRect r; wapiWindowRect ( (HWND)ok->winId(),r ); #endif } if (defaultLayout.size()>1) { layoutPrompt->show(); cbLayout->show(); slotChangeKbdLayout(cbLayout->currentText()); connect (cbLayout,SIGNAL(currentIndexChanged(QString)),this,SLOT(slotChangeKbdLayout(QString))); } } void ONMainWindow::initStatusDlg() { sessionStatusDlg = new SVGFrame ( ":/img/svg/passform.svg", false,bgFrame ); sessionStatusDlg->hide(); if ( !miniMode ) sessionStatusDlg->setFixedSize ( sessionStatusDlg->sizeHint() ); else sessionStatusDlg->setFixedSize ( 310,200 ); QFont fnt=sessionStatusDlg->font(); if ( miniMode ) #ifdef Q_WS_HILDON fnt.setPointSize ( 10 ); #else fnt.setPointSize ( 9 ); #endif sessionStatusDlg->setFont ( fnt ); username->addWidget ( sessionStatusDlg ); QPalette pal=sessionStatusDlg->palette(); pal.setBrush ( QPalette::Window, QColor ( 0,0,0,0 ) ); pal.setColor ( QPalette::Active, QPalette::WindowText, QPalette::Mid ); pal.setColor ( QPalette::Active, QPalette::ButtonText, QPalette::Mid ); pal.setColor ( QPalette::Active, QPalette::Text, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::WindowText, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::ButtonText, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::Text, QPalette::Mid ); sessionStatusDlg->setPalette ( pal ); slName=new QLabel ( sessionStatusDlg ); slVal=new QLabel ( sessionStatusDlg ); slName->setText ( tr ( "Session ID:
Server:
Username:" "
Display:
Creation time:
Status:
" ) ); slName->setFixedSize ( slName->sizeHint() ); slName->hide(); slVal->hide(); slVal->setFixedHeight ( slName->sizeHint().height() ); sbApps=new QToolButton (sessionStatusDlg ); sbApps->setToolTip(tr ( "Applications ..." )); sbApps->setIcon(QPixmap(":/img/icons/32x32/apps.png")); sbApps->setAutoRaise(true); sbApps->setFocusPolicy(Qt::NoFocus); sbExp=new QToolButton (sessionStatusDlg ); sbExp->setIcon(QPixmap(":/img/icons/32x32/open_dir.png")); sbExp->setToolTip (tr ("Share folder ..." )); sbExp->setAutoRaise(true); sbExp->setFocusPolicy(Qt::NoFocus); sbSusp=new QToolButton (sessionStatusDlg ); sbSusp->setIcon(QPixmap(":/img/icons/32x32/suspend_session.png")); sbSusp->setToolTip(tr ( "Abort" )); sbSusp->setAutoRaise(true); sbSusp->setFocusPolicy(Qt::NoFocus); sbTerm=new QToolButton (sessionStatusDlg ); sbTerm->setIcon(QPixmap(":/img/icons/32x32/stop_session.png")); sbTerm->setToolTip(tr ( "Terminate" )); sbTerm->setAutoRaise(true); sbTerm->setFocusPolicy(Qt::NoFocus); sbAdv=new QCheckBox ( tr ( "Show details" ),sessionStatusDlg ); setWidgetStyle ( sbTerm ); setWidgetStyle ( sbApps ); setWidgetStyle ( sbExp ); setWidgetStyle ( sbSusp ); setWidgetStyle ( sbAdv ); sbAdv->setFixedSize ( sbAdv->sizeHint() ); sbApps->setFixedSize ( 32,32 ); sbSusp->setFixedSize ( 32,32 ); sbTerm->setFixedSize ( 32,32 ); sbExp->setFixedSize ( 32,32 ); /* sbApps->setFocusPolicy(Qt::NoFocus); sbSusp->setFocusPolicy(Qt::NoFocus); sbTerm->setFocusPolicy(Qt::NoFocus); sbExp->setFocusPolicy(Qt::NoFocus);*/ sbAdv->hide(); sbSusp->hide(); sbTerm->hide(); sbExp->hide(); sbApps->hide(); pal.setColor ( QPalette::Button, QColor ( 255,255,255,0 ) ); pal.setColor ( QPalette::Window, QColor ( 255,255,255,255 ) ); pal.setColor ( QPalette::Base, QColor ( 255,255,255,255 ) ); sbAdv->setPalette ( pal ); sbApps->setPalette ( pal ); sbSusp->setPalette ( pal ); sbTerm->setPalette ( pal ); sbExp->setPalette ( pal ); stInfo=new QTextEdit ( sessionStatusDlg ); setWidgetStyle ( stInfo ); setWidgetStyle ( stInfo->verticalScrollBar() ); stInfo->setReadOnly ( true ); stInfo->hide(); stInfo->setFrameStyle ( QFrame::StyledPanel|QFrame::Plain ); stInfo->setPalette ( pal ); sbExp->setEnabled ( false ); connect ( sbSusp,SIGNAL ( clicked() ),this, SLOT ( slotTestSessionStatus() ) ); connect ( sbTerm,SIGNAL ( clicked() ),this, SLOT ( slotTermSessFromSt() ) ); connect ( sbAdv,SIGNAL ( clicked() ),this, SLOT ( slotShowAdvancedStat() ) ); connect ( sbExp,SIGNAL ( clicked() ),this, SLOT ( slotExportDirectory() ) ); connect ( sbApps,SIGNAL ( clicked() ),this, SLOT ( slotAppDialog()) ); QVBoxLayout* layout=new QVBoxLayout ( sessionStatusDlg ); QHBoxLayout* ll=new QHBoxLayout(); ll->addWidget ( slName ); ll->addWidget ( slVal ); ll->addStretch(); ll->setSpacing ( 10 ); if ( !miniMode ) layout->setContentsMargins ( 25,25,10,10 ); else layout->setContentsMargins ( 10,10,10,10 ); QHBoxLayout* bl=new QHBoxLayout(); bl->addStretch(); bl->addWidget ( sbApps ); bl->addWidget ( sbExp ); bl->addWidget ( sbSusp ); bl->addWidget ( sbTerm ); // bl->addStretch(); layout->addLayout ( ll ); layout->addStretch(); layout->addWidget ( stInfo ); layout->addWidget ( sbAdv ); layout->addStretch(); layout->addLayout ( bl ); layout->setSizeConstraint( QLayout::SetFixedSize ); slName->show(); slVal->show(); sbAdv->show(); if ( !embedMode ) { sbSusp->show(); sbTerm->show(); if (! hideFolderSharing ) sbExp->show(); } X2goSettings st ( "settings" ); if ( st.setting()->value ( "showStatus", ( QVariant ) false ).toBool() ) { sbAdv->setChecked ( true ); slotShowAdvancedStat(); } #ifdef Q_OS_WIN if ( embedMode ) { QRect r; wapiWindowRect ( (HWND)sbAdv->winId(),r ); wapiWindowRect ( (HWND)stInfo->verticalScrollBar ()->winId(),r ); } #endif } void ONMainWindow::initSelectSessDlg() { selectSessionDlg = new SVGFrame ( ":/img/svg/passform.svg", false,bgFrame ); username->addWidget ( selectSessionDlg ); setWidgetStyle ( selectSessionDlg ); if ( !miniMode ) selectSessionDlg->setFixedSize ( selectSessionDlg->sizeHint() ); else selectSessionDlg->setFixedSize ( 310,180 ); QPalette pal=selectSessionDlg->palette(); pal.setBrush ( QPalette::Window, QColor ( 255,255,255,0 ) ); pal.setColor ( QPalette::Active, QPalette::WindowText, QPalette::Mid ); pal.setColor ( QPalette::Active, QPalette::ButtonText, QPalette::Mid ); pal.setColor ( QPalette::Active, QPalette::Text, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::WindowText, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::ButtonText, QPalette::Mid ); pal.setColor ( QPalette::Inactive, QPalette::Text, QPalette::Mid ); selectSessionDlg->setPalette ( pal ); pal.setColor ( QPalette::Button, QColor ( 255,255,255,0 ) ); pal.setColor ( QPalette::Window, QColor ( 255,255,255,255 ) ); pal.setColor ( QPalette::Base, QColor ( 255,255,255,255 ) ); QFont fnt=selectSessionDlg->font(); if ( miniMode ) #ifdef Q_WS_HILDON fnt.setPointSize ( 10 ); #else fnt.setPointSize ( 9 ); #endif selectSessionDlg->setFont ( fnt ); selectSessionLabel=new QLabel ( tr ( "Select session:" ), selectSessionDlg ); sOk=new QPushButton ( tr ( "Resume" ),selectSessionDlg ); setWidgetStyle ( sOk ); sCancel=new QPushButton ( tr ( "Cancel" ),selectSessionDlg ); setWidgetStyle ( sCancel ); bCancel=new QPushButton ( tr ( "Cancel" ),selectSessionDlg ); setWidgetStyle ( bCancel ); bSusp=new QPushButton ( tr ( "Suspend" ),selectSessionDlg ); setWidgetStyle ( bSusp ); bTerm=new QPushButton ( tr ( "Terminate" ),selectSessionDlg ); setWidgetStyle ( bTerm ); bNew=new QPushButton ( tr ( "New" ),selectSessionDlg ); setWidgetStyle ( bNew ); bShadow=new QPushButton ( tr ( "Full access" ),selectSessionDlg ); setWidgetStyle ( bShadow ); bShadowView=new QPushButton ( tr ( "View only" ),selectSessionDlg ); setWidgetStyle ( bShadowView ); sOk->setPalette ( pal ); sCancel->setPalette ( pal ); connect ( sCancel,SIGNAL ( clicked() ),this, SLOT ( slotCloseSelectDlg() ) ); connect ( bCancel,SIGNAL ( clicked() ),this, SLOT ( slotCloseSelectDlg() ) ); selectSessionDlg->show(); #ifndef Q_WS_HILDON sOk->setFixedSize ( ok->sizeHint() ); sCancel->setFixedSize ( cancel->sizeHint() ); #else QSize sz=sCancel->sizeHint(); sz.setWidth ( ( int ) ( sz.width() /1.5 ) ); sz.setHeight ( ( int ) ( sz.height() /1.5 ) ); sCancel->setFixedSize ( sz ); sz=sOk->sizeHint(); sz.setWidth ( ( int ) ( sz.width() /1.5 ) ); sz.setHeight ( ( int ) ( sz.height() /1.5 ) ); sOk->setFixedSize ( sz ); sz=bSusp->sizeHint(); if ( bTerm->sizeHint().width() > sz.width() ) sz=bTerm->sizeHint(); if ( bNew->sizeHint().width() > sz.width() ) sz=bNew->sizeHint(); sz.setWidth ( ( int ) ( sz.width() /1.5 ) ); sz.setHeight ( ( int ) ( sz.height() /1.5 ) ); bSusp->setFixedSize ( sz ); bTerm->setFixedSize ( sz ); bNew->setFixedSize ( sz ); #endif int bmaxw=bNew->size().width(); if ( bSusp->size().width() >bmaxw ) bmaxw=bSusp->size().width(); if ( bTerm->size().width() >bmaxw ) bmaxw=bTerm->size().width(); bNew->setFixedWidth ( bmaxw ); bSusp->setFixedWidth ( bmaxw ); bTerm->setFixedWidth ( bmaxw ); sOk->setEnabled ( true ); sCancel->setEnabled ( true ); selectSessionDlg->setEnabled ( true ); setEnabled ( true ); sessTv=new SessTreeView ( selectSessionDlg ); setWidgetStyle ( sessTv ); setWidgetStyle ( sessTv->horizontalScrollBar() ); setWidgetStyle ( sessTv->verticalScrollBar() ); sessTv->setItemsExpandable ( false ); sessTv->setRootIsDecorated ( false ); model=new QStandardItemModel ( sessionExplorer->getSessionsList()->size(), 8 ); if(!brokerMode) model->setHeaderData ( S_DISPLAY,Qt::Horizontal, QVariant ( ( QString ) tr ( "Display" ) ) ); else { model->setHeaderData ( S_DISPLAY,Qt::Horizontal, QVariant ( ( QString ) tr ( "User" ) ) ); } model->setHeaderData ( S_STATUS,Qt::Horizontal, QVariant ( ( QString ) tr ( "Status" ) ) ); model->setHeaderData ( S_COMMAND,Qt::Horizontal, QVariant ( ( QString ) tr ( "Command" ) ) ); model->setHeaderData ( S_TYPE,Qt::Horizontal, QVariant ( ( QString ) tr ( "Type" ) ) ); model->setHeaderData ( S_SERVER,Qt::Horizontal, QVariant ( ( QString ) tr ( "Server" ) ) ); model->setHeaderData ( S_CRTIME,Qt::Horizontal, QVariant ( ( QString ) tr ( "Creation time" ) ) ); model->setHeaderData ( S_IP,Qt::Horizontal, QVariant ( ( QString ) tr ( "Client IP" ) ) ); model->setHeaderData ( S_ID,Qt::Horizontal, QVariant ( ( QString ) tr ( "Session ID" ) ) ); modelDesktop=new QStandardItemModel ( sessionExplorer->getSessionsList()->size(), 2 ); modelDesktop->setHeaderData ( D_USER,Qt::Horizontal, QVariant ( ( QString ) tr ( "User" ) ) ); modelDesktop->setHeaderData ( D_DISPLAY,Qt::Horizontal, QVariant ( ( QString ) tr ( "Display" ) ) ); sessTv->setModel ( ( QAbstractItemModel* ) model ); QFontMetrics fm ( sessTv->font() ); sessTv->setEditTriggers ( QAbstractItemView::NoEditTriggers ); sessTv->setPalette ( pal ); sessTv->setModel ( ( QAbstractItemModel* ) model ); bNew->setPalette ( pal ); bShadow->setPalette ( pal ); bShadowView->setPalette ( pal ); bSusp->setPalette ( pal ); bTerm->setPalette ( pal ); sessTv->setFrameStyle ( QFrame::StyledPanel|QFrame::Plain ); sOk->setEnabled ( false ); bSusp->setEnabled ( false ); bTerm->setEnabled ( false ); bShadow->setEnabled ( false ); selectSessionLabel->hide(); bCancel->setPalette ( pal ); bCancel->hide(); desktopFilter=new QLineEdit ( selectSessionDlg ); setWidgetStyle ( desktopFilter ); // desktopFilter->setFrame ( false ); desktopFilterCb=new QCheckBox ( tr ( "Only my desktops" ), selectSessionDlg ); desktopFilterCb->hide(); QVBoxLayout* layout=new QVBoxLayout ( selectSessionDlg ); QHBoxLayout* filterLay=new QHBoxLayout(); QHBoxLayout* blay=new QHBoxLayout(); QVBoxLayout* alay=new QVBoxLayout(); QHBoxLayout* tvlay=new QHBoxLayout(); selectSesDlgLayout=layout; layout->addWidget ( selectSessionLabel ); layout->addLayout ( filterLay ); layout->addLayout ( tvlay ); layout->addLayout ( blay ); filterLay->addWidget ( desktopFilter ); filterLay->addWidget ( desktopFilterCb ); alay->addWidget ( bSusp ); alay->addWidget ( bTerm ); alay->addWidget ( bShadowView ); alay->addWidget ( bShadow ); alay->addStretch(); alay->addWidget ( bNew ); alay->addWidget ( bCancel ); tvlay->addWidget ( sessTv ); tvlay->addLayout ( alay ); blay->addStretch(); blay->addWidget ( sOk ); blay->addWidget ( sCancel ); blay->addStretch(); if ( !miniMode ) layout->setContentsMargins ( 25,25,10,10 ); else layout->setContentsMargins ( 10,10,10,10 ); sOk->hide(); sCancel->hide(); bNew->hide(); bSusp->hide(); bTerm->hide(); connect ( sessTv,SIGNAL ( selected ( const QModelIndex& ) ), this,SLOT ( slotActivated ( const QModelIndex& ) ) ); connect ( sOk,SIGNAL ( clicked() ),this, SLOT ( slotResumeSess() ) ); connect ( sessTv,SIGNAL ( doubleClicked ( const QModelIndex& ) ), this,SLOT ( slotResumeDoubleClick ( const QModelIndex& ) ) ); if(!brokerMode) { connect ( bNew,SIGNAL ( clicked() ),this, SLOT ( slotNewSess() ) ); } else { connect ( bNew,SIGNAL ( clicked() ),broker, SIGNAL ( sessionSelected() ) ); } connect ( bSusp,SIGNAL ( clicked() ),this, SLOT ( slotSuspendSess() ) ); connect ( bTerm,SIGNAL ( clicked() ),this, SLOT ( slotTermSess() ) ); connect ( bShadow,SIGNAL ( clicked() ),this, SLOT ( slotShadowSess() ) ); connect ( bShadowView,SIGNAL ( clicked() ),this, SLOT ( slotShadowViewSess() ) ); connect ( desktopFilter,SIGNAL ( textEdited ( const QString& ) ),this, SLOT ( slotDesktopFilterChanged ( const QString& ) ) ); connect ( desktopFilterCb,SIGNAL ( stateChanged ( int ) ), this, SLOT ( slotDesktopFilterCb ( int ) ) ); selectSessionLabel->show(); sOk->show(); sCancel->show(); bNew->show(); bSusp->show(); bTerm->show(); sessTv->show(); selectSessionDlg->hide(); #ifdef Q_OS_WIN if ( embedMode ) { QRect r; wapiWindowRect ( (HWND)sOk->winId(),r ); wapiWindowRect ( (HWND)sessTv->verticalScrollBar ()->winId(),r ); wapiWindowRect ( (HWND)sessTv->horizontalScrollBar ()->winId(),r ); wapiWindowRect ( (HWND)sessTv->header ()->viewport()->winId(),r ); } #endif } void ONMainWindow::printSshDError_startupFailure() { if ( closeEventSent ) return; QString error_message; error_message = tr ("SSH daemon could not be started.\n\n"); QString detailed_error_message = tr ("You have enabled Remote Printing or File Sharing.\n" "These features require a running and functioning SSH server on your computer.\n" "Printing and File Sharing will be disabled for this session.\n\n"); #ifdef Q_OS_WIN detailed_error_message += tr ("Normally, this should not happen as X2Go Client for Windows " "ships its own internal SSH server.\n\n" "If you see this message, please report a bug on:\n"); #else /* defined (Q_OS_WIN) */ detailed_error_message += tr ("The SSH server failed to start.\n\n" "Please report a bug on:\n"); #endif /* defined (Q_OS_WIN) */ detailed_error_message += tr ("
" "https://wiki.x2go.org/doku.php/wiki:bugs" "
\n"); detailed_error_message += tr ("Disabling Remote Printing or File Sharing support " "in the session settings will get rid of this message."); Non_Modal_MessageBox::critical (0l, "X2Go Client", error_message, detailed_error_message, true, QMessageBox::Ok, QMessageBox::NoButton); } void ONMainWindow::printSshDError_noHostPubKey() { if ( closeEventSent ) return; QString error_message = tr ("SSH daemon failed to open its public host key."); QString detailed_error_message = tr ("You have enabled Remote Printing or File Sharing.\n" "These features require a running and functioning SSH server on your computer.\n" "Printing and File Sharing will be disabled for this session.\n\n"); #ifdef Q_OS_WIN detailed_error_message += tr ("Normally, this should not happen as X2Go Client for Windows " "ships its own internal SSH server and automatically " "generates the required keys.\n\n" "If you see this message, please report a bug on:\n"); #else /* defined (Q_OS_WIN) */ detailed_error_message += tr ("X2Go Client was unable to create SSH host keys.\n\n" "Please report a bug on:\n"); #endif /* defined (Q_OS_WIN) */ detailed_error_message += tr ("
" "https://wiki.x2go.org/doku.php/wiki:bugs" "
\n"); detailed_error_message += tr ("Disabling Remote Printing or File Sharing support " "in the session settings will get rid of this message."); Non_Modal_MessageBox::critical (0l, "X2Go Client", error_message, detailed_error_message, true, QMessageBox::Ok, QMessageBox::NoButton); } void ONMainWindow::printSshDError_noExportPubKey() { if ( closeEventSent ) return; QMessageBox::critical ( 0l,tr ( "SSH Error" ), tr ( "SSH daemon failed to open the application's public key\n" "used for exporting folders and printers." ), QMessageBox::Ok,QMessageBox::NoButton ); } void ONMainWindow::printSshDError_noAuthorizedKeysFile() { if ( closeEventSent ) return; QMessageBox::critical ( 0l,tr ( "SSH Error" ), tr ( "SSH daemon failed to open the application's\n" "authorized_keys file." ), QMessageBox::Ok,QMessageBox::NoButton ); } void ONMainWindow::slotPCookieReady ( bool result, QString , int ) { /* Silence warning. */ UNUSED (result); } void ONMainWindow::loadPulseModuleNativeProtocol() { QProcess* proc=new QProcess ( this ); QStringList args; args<<"load-module"<<"module-native-protocol-tcp"; proc->start ( "pactl",args ); proc->waitForFinished ( 3000 ); } void ONMainWindow::slotEmbedToolBar() { if ( statusLabel ) { delete statusLabel; statusLabel=0; } if ( embedTbVisible ) { stb->clear(); act_embedToolBar->setIcon ( QIcon ( ":/img/icons/16x16/tbshow.png" ) ); stb->addAction ( act_embedToolBar ); stb->setToolButtonStyle ( Qt::ToolButtonIconOnly ); stb->widgetForAction ( act_embedToolBar )->setFixedHeight ( 16 ); act_embedToolBar->setText ( tr ( "Restore toolbar" ) ); statusLabel=new QLabel; stb->addWidget ( statusLabel ); #ifndef Q_OS_WIN statusBar()->hide(); #endif } else { initEmbedToolBar(); act_embedToolBar->setIcon ( QIcon ( ":/img/icons/32x32/tbhide.png" ) ); act_embedToolBar->setText ( tr ( "Minimize toolbar" ) ); } embedTbVisible=!embedTbVisible; if ( proxyWinEmbedded ) setStatStatus(); X2goSettings st ( "sessions" ); st.setting()->setValue ( "embedded/tbvisible", embedTbVisible ); st.setting()->sync(); } void ONMainWindow::initEmbedToolBar() { stb->addAction ( act_embedToolBar ); stb->addSeparator(); stb->setToolButtonStyle ( Qt::ToolButtonTextUnderIcon ); stb->addAction ( act_shareFolder ); stb->addAction ( act_showApps ); stb->addAction ( act_reconnect ); stb->addAction ( act_suspend ); stb->addAction ( act_terminate ); stb->addSeparator(); stb->addAction ( act_embedContol ); stb->addSeparator(); stb->addAction ( act_set ); stb->addAction ( act_abclient ); } void ONMainWindow::slotEmbedToolBarToolTip() { if ( !showTbTooltip ) return; QWidget* widg=stb->widgetForAction ( act_embedToolBar ); QToolTip::showText ( this->mapToGlobal ( QPoint ( 6,6 ) ), tr ( "
   Click this " "button   
" "   to restore toolbar" "   

" ), widg ); } void ONMainWindow::slotActivateWindow() { if ( embedMode ) { QApplication::setActiveWindow ( this ) ; activateWindow(); /* x2goDebug<<"focus:"<hasFocus(); x2goDebug<<"activ:"<isActiveWindow();*/ QTimer::singleShot ( 50, this, SLOT ( slotEmbedToolBarToolTip() ) ); } } #ifndef Q_OS_WIN void ONMainWindow::mouseReleaseEvent ( QMouseEvent * event ) { QMainWindow::mouseReleaseEvent ( event ); slotActivateWindow(); } #endif void ONMainWindow::slotHideEmbedToolBarToolTip() { showTbTooltip=false; QToolTip::hideText(); } void ONMainWindow::slotDesktopFilterChanged ( const QString& text ) { filterDesktops ( text ); } void ONMainWindow::slotDesktopFilterCb ( int state ) { if ( state==Qt::Checked ) { filterDesktops ( getCurrentUname(),true ); desktopFilter->setEnabled ( false ); } else { filterDesktops ( desktopFilter->text() ); desktopFilter->setEnabled ( true ); } } void ONMainWindow::filterDesktops ( const QString& filter, bool strict ) { modelDesktop->setRowCount ( 0 ); bShadow->setEnabled ( false ); bShadowView->setEnabled ( false ); QFontMetrics fm ( sessTv->font() ); uint nextRow=0; for ( int row = 0; row < selectedDesktops.size(); ++row ) { QStringList desktop=selectedDesktops[row].split ( "@" ); if ( filter==tr ( "Filter" ) ||filter.length() <=0|| ( strict && desktop[0]==filter ) || ( !strict && desktop[0].startsWith ( filter ) ) ) { QStandardItem *item; item= new QStandardItem ( desktop[0] ); modelDesktop->setItem ( nextRow,D_USER,item ); item= new QStandardItem ( desktop[1] ); modelDesktop->setItem ( nextRow++,D_DISPLAY,item ); for ( int j=0; j<2; ++j ) { QString txt= modelDesktop->index ( row,j ).data().toString(); if ( sessTv->header()->sectionSize ( j ) < fm.width ( txt ) +6 ) { sessTv->header()->resizeSection ( j,fm.width ( txt ) +6 ); } } } } } void ONMainWindow::slotShadowSess() { shadowMode=SHADOW_FULL; slotShadowViewSess(); } void ONMainWindow::slotShadowViewSess() { shadowUser=sessTv->model()->index ( sessTv->currentIndex().row(), D_USER ).data().toString(); shadowDisplay=sessTv->model()->index ( sessTv->currentIndex().row(), D_DISPLAY ).data().toString(); startNewSession(); } void ONMainWindow::slotReconnectSession() { if ( !managedMode ) slotSelectedFromList ( ( SessionButton* ) 0 ); else { setEnabled ( false ); } } QSize ONMainWindow::getEmbedAreaSize() { if ( embedTbVisible && config.showstatusbar ) statusBar()->show(); QSize sz=bgFrame->size(); // sz.setHeight(sz.height()-statusBar()->size().height()); statusBar()->hide(); return sz; } void ONMainWindow::slotStartBroker() { config.brokerPass=pass->text(); config.brokerUser=login->text(); setStatStatus ( tr ( "Connecting to broker" ) ); stInfo->insertPlainText ( "broker url: "+config.brokerurl ); setEnabled ( false ); if(!usePGPCard) broker->getUserSessions(); } void ONMainWindow::slotGetBrokerSession() { startSession ( config.session); } void ONMainWindow::slotStartNewBrokerSession ( ) { if ( managedMode ) { setEnabled ( true ); slotSelectedFromList ( ( SessionButton* ) 0 ); } } #ifdef Q_OS_WIN QString ONMainWindow::u3DataPath() { QStringList env=QProcess::systemEnvironment(); QString dpath; for ( int i=0; i0 ) { dpath.replace ( "U3_APP_DATA_PATH=","" ); portableDataPath=dpath; return dpath; } return QString::null; } #endif void ONMainWindow::cleanPortable() { removeDir ( homeDir +"/.ssh" ); removeDir ( homeDir +"/ssh" ); removeDir ( homeDir+"/.x2go" ); if (cleanAllFiles) removeDir(homeDir+"/.x2goclient"); } void ONMainWindow::removeDir ( QString path ) { x2goDebug<<"removeDir, entering: " <