File indexing completed on 2024-04-21 04:58:41
0001 /* This file is part of the KDE project 0002 Copyright (C) 2007 Alessandro Praduroux <pradu@pradu.it> 0003 Copyright (C) 2013 Amandeep Singh <aman.dedman@gmail.com> 0004 0005 This program is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 */ 0010 #include "mainwindow.h" 0011 #include "invitationsrfbserver.h" 0012 0013 #include "krfbconfig.h" 0014 #include "ui_configtcp.h" 0015 #include "ui_configsecurity.h" 0016 #include "ui_configframebuffer.h" 0017 0018 #include <KConfigDialog> 0019 #include <KLocalizedString> 0020 #include <KMessageBox> 0021 #include <KMessageWidget> 0022 #include <KStandardAction> 0023 #include <KActionCollection> 0024 #include <KNewPasswordDialog> 0025 #include <KPluginMetaData> 0026 0027 #include <QIcon> 0028 #include <QWidget> 0029 #include <QLineEdit> 0030 #include <QComboBox> 0031 #include <QSizePolicy> 0032 #include <QVector> 0033 #include <QSet> 0034 #include <QNetworkInterface> 0035 #include <QHostInfo> 0036 #include <QMessageBox> 0037 0038 class TCP: public QWidget, public Ui::TCP 0039 { 0040 public: 0041 explicit TCP(QWidget *parent = nullptr) : QWidget(parent) { 0042 setupUi(this); 0043 } 0044 }; 0045 0046 class Security: public QWidget, public Ui::Security 0047 { 0048 public: 0049 explicit Security(QWidget *parent = nullptr) : QWidget(parent) { 0050 setupUi(this); 0051 walletWarning = new KMessageWidget(this); 0052 walletWarning->setText(i18n("Storing passwords in config file is insecure!")); 0053 walletWarning->setCloseButtonVisible(false); 0054 walletWarning->setMessageType(KMessageWidget::Warning); 0055 walletWarning->hide(); 0056 vboxLayout->addWidget(walletWarning); 0057 0058 // show warning when "noWallet" checkbox is checked 0059 QObject::connect(kcfg_noWallet, &QCheckBox::toggled, this, [this] (bool checked) { 0060 walletWarning->setVisible(checked); 0061 }); 0062 } 0063 0064 KMessageWidget *walletWarning = nullptr; 0065 }; 0066 0067 class ConfigFramebuffer: public QWidget, public Ui::Framebuffer 0068 { 0069 public: 0070 ConfigFramebuffer(QWidget *parent = nullptr) : QWidget(parent) { 0071 setupUi(this); 0072 // hide the line edit with framebuffer string 0073 kcfg_preferredFrameBufferPlugin->hide(); 0074 // fill drop-down combo with a list of real existing plugins 0075 this->fillFrameBuffersCombo(); 0076 // initialize combo with currently configured framebuffer plugin 0077 cb_preferredFrameBufferPlugin->setCurrentText(KrfbConfig::preferredFrameBufferPlugin()); 0078 // connect signals between combo<->lineedit 0079 // if we change selection in combo, lineedit is updated 0080 QObject::connect(cb_preferredFrameBufferPlugin, &QComboBox::currentTextChanged, 0081 kcfg_preferredFrameBufferPlugin, &QLineEdit::setText); 0082 } 0083 0084 void fillFrameBuffersCombo() { 0085 const QVector<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), {}, KPluginMetaData::AllowEmptyMetaData); 0086 for (const KPluginMetaData &metadata : plugins) { 0087 cb_preferredFrameBufferPlugin->addItem(metadata.pluginId()); 0088 } 0089 } 0090 }; 0091 0092 0093 MainWindow::MainWindow(QWidget *parent) 0094 : KXmlGuiWindow(parent) 0095 { 0096 setAttribute(Qt::WA_DeleteOnClose, false); 0097 0098 m_passwordEditable = false; 0099 m_passwordLineEdit = new QLineEdit(this); 0100 m_passwordLineEdit->setVisible(false); 0101 m_passwordLineEdit->setAlignment(Qt::AlignHCenter); 0102 0103 auto mainWidget = new QWidget; 0104 m_ui.setupUi(mainWidget); 0105 m_ui.krfbIconLabel->setPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(128)); 0106 m_ui.enableUnattendedCheckBox->setChecked( 0107 InvitationsRfbServer::instance->allowUnattendedAccess()); 0108 0109 setCentralWidget(mainWidget); 0110 0111 connect(m_ui.passwordEditButton, &QToolButton::clicked, 0112 this, &MainWindow::editPassword); 0113 connect(m_ui.enableSharingCheckBox, &QCheckBox::toggled, 0114 this, &MainWindow::toggleDesktopSharing); 0115 connect(m_ui.enableUnattendedCheckBox, &QCheckBox::toggled, 0116 InvitationsRfbServer::instance, &InvitationsRfbServer::toggleUnattendedAccess); 0117 connect(m_ui.unattendedPasswordButton, &QPushButton::clicked, 0118 this, &MainWindow::editUnattendedPassword); 0119 connect(m_ui.addressAboutButton, &QToolButton::clicked, 0120 this, &MainWindow::aboutConnectionAddress); 0121 connect(m_ui.unattendedAboutButton, &QToolButton::clicked, 0122 this, &MainWindow::aboutUnattendedMode); 0123 connect(InvitationsRfbServer::instance, &InvitationsRfbServer::passwordChanged, 0124 this, &MainWindow::passwordChanged); 0125 0126 // Figure out the address 0127 int port = KrfbConfig::port(); 0128 const QList<QNetworkInterface> interfaceList = QNetworkInterface::allInterfaces(); 0129 for (const QNetworkInterface& interface : interfaceList) { 0130 if(interface.flags() & QNetworkInterface::IsLoopBack) 0131 continue; 0132 0133 if(interface.flags() & QNetworkInterface::IsRunning && 0134 !interface.addressEntries().isEmpty()) { 0135 const QString hostName = QHostInfo::localHostName(); 0136 const QString ipAddress = interface.addressEntries().constFirst().ip().toString(); 0137 const QString addressLabelText = hostName.isEmpty() 0138 ? QStringLiteral("%1 : %2").arg(ipAddress).arg(port) 0139 : QStringLiteral("%1 (%2) : %3").arg(hostName, ipAddress).arg(port); 0140 m_ui.addressDisplayLabel->setText(addressLabelText); 0141 } 0142 } 0143 0144 //Figure out the password 0145 m_ui.passwordDisplayLabel->setText( 0146 InvitationsRfbServer::instance->desktopPassword()); 0147 0148 KStandardAction::quit(QCoreApplication::instance(), SLOT(quit()), actionCollection()); 0149 KStandardAction::preferences(this, SLOT(showConfiguration()), actionCollection()); 0150 0151 setupGUI(); 0152 0153 if (KrfbConfig::allowDesktopControl()) { 0154 m_ui.enableSharingCheckBox->setChecked(true); 0155 } 0156 0157 setAutoSaveSettings(); 0158 } 0159 0160 MainWindow::~MainWindow() 0161 { 0162 } 0163 0164 void MainWindow::editPassword() 0165 { 0166 if(m_passwordEditable) { 0167 m_passwordEditable = false; 0168 m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties"))); 0169 m_ui.passwordGridLayout->removeWidget(m_passwordLineEdit); 0170 InvitationsRfbServer::instance->setDesktopPassword( 0171 m_passwordLineEdit->text()); 0172 m_ui.passwordDisplayLabel->setText( 0173 InvitationsRfbServer::instance->desktopPassword()); 0174 m_passwordLineEdit->setVisible(false); 0175 } else { 0176 m_passwordEditable = true; 0177 m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-save"))); 0178 m_ui.passwordGridLayout->addWidget(m_passwordLineEdit,0,0); 0179 m_passwordLineEdit->setText( 0180 InvitationsRfbServer::instance->desktopPassword()); 0181 m_passwordLineEdit->setVisible(true); 0182 m_passwordLineEdit->setFocus(Qt::MouseFocusReason); 0183 } 0184 } 0185 0186 void MainWindow::editUnattendedPassword() 0187 { 0188 KNewPasswordDialog dialog(this); 0189 dialog.setPrompt(i18n("Enter a new password for Unattended Access")); 0190 if(dialog.exec()) { 0191 InvitationsRfbServer::instance->setUnattendedPassword(dialog.password()); 0192 } 0193 } 0194 0195 void MainWindow::toggleDesktopSharing(bool enable) 0196 { 0197 if(enable) { 0198 if(!InvitationsRfbServer::instance->start()) { 0199 KMessageBox::error(this, 0200 i18n("Failed to start the krfb server. Desktop sharing " 0201 "will not work. Try setting another port in the settings " 0202 "and restart krfb.")); 0203 } 0204 } else { 0205 InvitationsRfbServer::instance->stop(); 0206 if(m_passwordEditable) { 0207 m_passwordEditable = false; 0208 m_passwordLineEdit->setVisible(false); 0209 m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties"))); 0210 } 0211 } 0212 } 0213 0214 void MainWindow::passwordChanged(const QString& password) 0215 { 0216 m_passwordLineEdit->setText(password); 0217 m_ui.passwordDisplayLabel->setText(password); 0218 } 0219 0220 void MainWindow::aboutConnectionAddress() 0221 { 0222 QMessageBox::about(this, 0223 i18n("KDE Desktop Sharing"), 0224 i18n("This field contains the address of your computer and the port number, separated by a colon.\n\nThe address is just a hint - you can use any address that can reach your computer.\n\nDesktop Sharing tries to guess your address from your network configuration, but does not always succeed in doing so.\n\nIf your computer is behind a firewall it may have a different address or be unreachable for other computers.")); 0225 } 0226 0227 void MainWindow::aboutUnattendedMode() 0228 { 0229 QMessageBox::about(this, 0230 i18n("KDE Desktop Sharing"), 0231 i18n("Any remote user with normal desktop sharing password will have to be authenticated.\n\nIf unattended access is on, and the remote user provides unattended mode password, desktop sharing access will be granted without explicit confirmation.")); 0232 } 0233 0234 void MainWindow::showConfiguration() 0235 { 0236 static QString s_prevFramebufferPlugin; 0237 static bool s_prevNoWallet; 0238 // ^^ needs to be static, because lambda will be called long time 0239 // after showConfiguration() ends, so auto variable would go out of scope 0240 // save previously selected framebuffer plugin config 0241 s_prevFramebufferPlugin = KrfbConfig::preferredFrameBufferPlugin(); 0242 s_prevNoWallet = KrfbConfig::noWallet(); 0243 0244 if (KConfigDialog::showDialog(QStringLiteral("settings"))) { 0245 return; 0246 } 0247 0248 auto dialog = new KConfigDialog(this, QStringLiteral("settings"), KrfbConfig::self()); 0249 dialog->addPage(new TCP, i18n("Network"), QStringLiteral("network-wired")); 0250 dialog->addPage(new Security, i18n("Security"), QStringLiteral("security-high")); 0251 dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), QStringLiteral("video-display")); 0252 dialog->show(); 0253 connect(dialog, &KConfigDialog::settingsChanged, this, [this] () { 0254 // check if framebuffer plugin config has changed 0255 if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) { 0256 KMessageBox::information(this, i18n("To apply framebuffer plugin setting, " 0257 "you need to restart the program.")); 0258 } 0259 // check if kwallet config has changed 0260 if (s_prevNoWallet != KrfbConfig::noWallet()) { 0261 // try to apply settings immediately 0262 if (KrfbConfig::noWallet()) { 0263 InvitationsRfbServer::instance->closeKWallet(); 0264 } else { 0265 InvitationsRfbServer::instance->openKWallet(); 0266 // erase stored passwords from krfbconfig file 0267 KConfigGroup securityConfigGroup(KSharedConfig::openConfig(), QStringLiteral("Security")); 0268 securityConfigGroup.deleteEntry("desktopPassword"); 0269 securityConfigGroup.deleteEntry("unattendedPassword"); 0270 } 0271 } 0272 }); 0273 } 0274 0275 void MainWindow::readProperties(const KConfigGroup& group) 0276 { 0277 if (group.readEntry("Visible", true)) { 0278 show(); 0279 } 0280 KMainWindow::readProperties(group); 0281 } 0282 0283 void MainWindow::saveProperties(KConfigGroup& group) 0284 { 0285 group.writeEntry("Visible", isVisible()); 0286 KMainWindow::saveProperties(group); 0287 }