File indexing completed on 2024-04-28 05:33:25

0001 /*
0002     SPDX-FileCopyrightText: 2004 George Staikos <staikos@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "knetattach.h"
0008 
0009 #include <QUrlQuery>
0010 #include <QVariant>
0011 
0012 #include <KCharsets>
0013 #include <KConfig>
0014 #include <KConfigGroup>
0015 #include <KDirNotify>
0016 #include <KIO/JobUiDelegateFactory>
0017 #include <KIO/OpenUrlJob>
0018 #include <KIO/StatJob>
0019 #include <KJobWidgets>
0020 #include <KMessageBox>
0021 #include <QDesktopServices>
0022 #include <QIcon>
0023 
0024 KNetAttach::KNetAttach(QWidget *parent)
0025     : QWizard(parent)
0026     , Ui_KNetAttach()
0027 {
0028     setupUi(this);
0029 
0030     connect(_recent, &QAbstractButton::toggled, _recentConnectionName, &QWidget::setEnabled);
0031     connect(_connectionName, &QLineEdit::textChanged, this, &KNetAttach::updateParametersPageStatus);
0032     connect(_user, &QLineEdit::textChanged, this, &KNetAttach::updateParametersPageStatus);
0033     connect(_host, &QLineEdit::textChanged, this, &KNetAttach::updateParametersPageStatus);
0034     connect(_port, (void (QSpinBox::*)(int)) & QSpinBox::valueChanged, this, &KNetAttach::updateParametersPageStatus);
0035     connect(_path, &QLineEdit::textChanged, this, &KNetAttach::updateParametersPageStatus);
0036     connect(_useEncryption, &QAbstractButton::toggled, this, &KNetAttach::updatePort);
0037     connect(_createIcon, &QAbstractButton::toggled, this, &KNetAttach::updateFinishButtonText);
0038     connect(this, &QWizard::helpRequested, this, &KNetAttach::slotHelpClicked);
0039     connect(this, &QWizard::currentIdChanged, this, &KNetAttach::slotPageChanged);
0040     setWindowIcon(QIcon::fromTheme(QStringLiteral("knetattach")));
0041     setOption(HaveHelpButton, true);
0042     // setResizeMode(Fixed); FIXME: make the wizard fixed-geometry
0043     button(FinishButton)->setEnabled(false);
0044     KConfig crecent(QStringLiteral("krecentconnections"), KConfig::NoGlobals);
0045     KConfigGroup recent(&crecent, QStringLiteral("General"));
0046     QStringList idx = recent.readEntry("Index", QStringList());
0047     if (idx.isEmpty()) {
0048         _recent->setEnabled(false);
0049         if (_recent->isChecked()) {
0050             _webfolder->setChecked(true);
0051         }
0052     } else {
0053         _recent->setEnabled(true);
0054         _recentConnectionName->addItems(idx);
0055     }
0056     _encoding->clear();
0057     _encoding->addItems(KCharsets::charsets()->descriptiveEncodingNames());
0058     const int codecForLocaleIdx = _encoding->findText(QLatin1String("UTF-8"), Qt::MatchContains);
0059     _encoding->setCurrentIndex(codecForLocaleIdx != -1 ? codecForLocaleIdx : 0);
0060 }
0061 
0062 void KNetAttach::slotPageChanged(int)
0063 {
0064     updateFinishButtonText(true);
0065 }
0066 
0067 void KNetAttach::slotHelpClicked()
0068 {
0069     QDesktopServices::openUrl(QUrl(QStringLiteral("help:/")));
0070 }
0071 
0072 void KNetAttach::setInformationText(const QString &type)
0073 {
0074     QString text;
0075 
0076     if (type == QLatin1String("WebFolder")) {
0077         text =
0078             i18n("Enter a name for this <i>WebFolder</i> as well as a server address, port and folder path to use and press the <b>Save & Connect</b> button.");
0079     } else if (type == QLatin1String("Fish")) {
0080         text = i18n(
0081             "Enter a name for this <i>Secure shell connection</i> as well as a server address, port and folder path to use and press the <b>Save & Connect</b> "
0082             "button.");
0083     } else if (type == QLatin1String("FTP")) {
0084         text = i18n(
0085             "Enter a name for this <i>File Transfer Protocol connection</i> as well as a server address and folder path to use and press the <b>Save & "
0086             "Connect</b> button.");
0087     } else if (type == QLatin1String("SMB")) {
0088         text = i18n(
0089             "Enter a name for this <i>Microsoft Windows network drive</i> as well as a server address and folder path to use and press the <b>Save & "
0090             "Connect</b> button.");
0091     }
0092 
0093     _informationText->setText(text);
0094 }
0095 
0096 void KNetAttach::updateParametersPageStatus()
0097 {
0098     button(FinishButton)->setEnabled(!_host->text().trimmed().isEmpty() && !_path->text().trimmed().isEmpty() && !_connectionName->text().trimmed().isEmpty());
0099 }
0100 
0101 bool KNetAttach::validateCurrentPage()
0102 {
0103     if (currentPage() == _folderType) {
0104         _host->setFocus();
0105         _connectionName->setFocus();
0106 
0107         if (_webfolder->isChecked()) {
0108             setInformationText(QStringLiteral("WebFolder"));
0109             updateForProtocol(QStringLiteral("WebFolder"));
0110             _port->setValue(80);
0111         } else if (_fish->isChecked()) {
0112             setInformationText(QStringLiteral("Fish"));
0113             updateForProtocol(QStringLiteral("Fish"));
0114             _port->setValue(22);
0115         } else if (_ftp->isChecked()) {
0116             setInformationText(QStringLiteral("FTP"));
0117             updateForProtocol(QStringLiteral("FTP"));
0118             _port->setValue(21);
0119             if (_path->text().isEmpty()) {
0120                 _path->setText(QStringLiteral("/"));
0121             }
0122         } else if (_smb->isChecked()) {
0123             setInformationText(QStringLiteral("SMB"));
0124             updateForProtocol(QStringLiteral("SMB"));
0125         } else { // if (_recent->isChecked()) {
0126             KConfig recent(QStringLiteral("krecentconnections"), KConfig::NoGlobals);
0127             if (!recent.hasGroup(_recentConnectionName->currentText())) {
0128                 KConfigGroup group = recent.group(QStringLiteral("General"));
0129                 QStringList idx = group.readEntry("Index", QStringList());
0130                 if (idx.isEmpty()) {
0131                     _recent->setEnabled(false);
0132                     if (_recent->isChecked()) {
0133                         _webfolder->setChecked(true);
0134                     }
0135                 } else {
0136                     _recent->setEnabled(true);
0137                     _recentConnectionName->addItems(idx);
0138                 }
0139                 return false;
0140             }
0141             KConfigGroup group = recent.group(_recentConnectionName->currentText());
0142             _type = group.readEntry("Type");
0143             setInformationText(_type);
0144             if (!updateForProtocol(_type)) {
0145                 // FIXME: handle error
0146             }
0147             QUrl u(group.readEntry("URL"));
0148             _host->setText(u.host());
0149             _user->setText(u.userName());
0150             _path->setText(u.path());
0151             if (group.hasKey("Port")) {
0152                 _port->setValue(group.readEntry("Port", 0));
0153             } else {
0154                 _port->setValue(u.port());
0155             }
0156             _connectionName->setText(_recentConnectionName->currentText());
0157             _createIcon->setChecked(false);
0158         }
0159         updateParametersPageStatus();
0160 
0161     } else {
0162         button(BackButton)->setEnabled(false);
0163         button(FinishButton)->setEnabled(false);
0164         QUrl url;
0165         if (_type == QLatin1String("WebFolder")) {
0166             if (_useEncryption->isChecked()) {
0167                 url.setScheme(QStringLiteral("webdavs"));
0168             } else {
0169                 url.setScheme(QStringLiteral("webdav"));
0170             }
0171             url.setPort(_port->value());
0172         } else if (_type == QLatin1String("Fish")) {
0173             KConfig config(QStringLiteral("kio_fishrc"));
0174             KConfigGroup cg(&config, _host->text().trimmed());
0175             cg.writeEntry("Charset", KCharsets::charsets()->encodingForName(_encoding->currentText()));
0176             url.setScheme(_protocolText->currentText());
0177             url.setPort(_port->value());
0178         } else if (_type == QLatin1String("FTP")) {
0179             url.setScheme(QStringLiteral("ftp"));
0180             url.setPort(_port->value());
0181             KConfig config(QStringLiteral("kio_ftprc"));
0182             KConfigGroup cg(&config, _host->text().trimmed());
0183             cg.writeEntry("Charset", KCharsets::charsets()->encodingForName(_encoding->currentText()));
0184             config.sync();
0185         } else if (_type == QLatin1String("SMB")) {
0186             url.setScheme(QStringLiteral("smb"));
0187         } else { // recent
0188         }
0189 
0190         url.setHost(_host->text().trimmed());
0191         const QString trimmedUser = _user->text().trimmed();
0192         if (!trimmedUser.isEmpty() && _type != QLatin1String("WebFolder")) {
0193             url.setUserName(trimmedUser);
0194         }
0195         QString path = _path->text().trimmed();
0196 #ifndef Q_WS_WIN
0197         // could a relative path really be made absolute by simply prepending a '/' ?
0198         if (!path.startsWith(QLatin1Char('/'))) {
0199             path = QLatin1Char('/') + path;
0200         }
0201 #endif
0202         url.setPath(path);
0203         _folderParameters->setEnabled(false);
0204         bool success = doConnectionTest(url);
0205         _folderParameters->setEnabled(true);
0206         if (!success) {
0207             KMessageBox::error(this, i18n("Unable to connect to server.  Please check your settings and try again."));
0208             button(BackButton)->setEnabled(true);
0209             return false;
0210         }
0211 
0212         auto job = new KIO::OpenUrlJob(url, QStringLiteral("inode/directory"));
0213         job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
0214         job->setRunExecutables(true);
0215         job->start();
0216 
0217         QString name = _connectionName->text().trimmed();
0218 
0219         if (_createIcon->isChecked()) {
0220             QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/remoteview/");
0221             path += name + QStringLiteral(".desktop");
0222             KConfig _desktopFile(path, KConfig::SimpleConfig);
0223             KConfigGroup desktopFile(&_desktopFile, QStringLiteral("Desktop Entry"));
0224             desktopFile.writeEntry("Icon", "folder-remote");
0225             desktopFile.writeEntry("Name", name);
0226             desktopFile.writeEntry("Type", "Link");
0227             desktopFile.writeEntry("URL", url.toDisplayString());
0228             desktopFile.writeEntry("Charset", QUrlQuery(url).queryItemValue(QStringLiteral("charset")));
0229             desktopFile.sync();
0230             org::kde::KDirNotify::emitFilesAdded(QUrl(QStringLiteral("remote:/")));
0231         }
0232 
0233         if (!name.isEmpty()) {
0234             KConfig _recent(QStringLiteral("krecentconnections"), KConfig::NoGlobals);
0235             KConfigGroup recent(&_recent, QStringLiteral("General"));
0236             QStringList idx = recent.readEntry("Index", QStringList());
0237             _recent.deleteGroup(name); // erase anything stale
0238             if (idx.contains(name)) {
0239                 idx.removeAll(name);
0240                 idx.prepend(name);
0241                 recent.writeEntry("Index", idx);
0242             } else {
0243                 QString last;
0244                 if (!idx.isEmpty()) {
0245                     last = idx.last();
0246                     idx.pop_back();
0247                 }
0248                 idx.prepend(name);
0249                 _recent.deleteGroup(last);
0250                 recent.writeEntry("Index", idx);
0251             }
0252             recent = KConfigGroup(&_recent, name);
0253             recent.writeEntry("URL", url.toDisplayString());
0254             if (_type == QLatin1String("WebFolder") || _type == QLatin1String("Fish") || _type == QLatin1String("FTP")) {
0255                 recent.writeEntry("Port", _port->value());
0256             }
0257             recent.writeEntry("Type", _type);
0258             recent.sync();
0259         }
0260     }
0261     return true;
0262 }
0263 
0264 void KNetAttach::updatePort(bool encryption)
0265 {
0266     if (_webfolder->isChecked()) {
0267         if (encryption) {
0268             _port->setValue(443);
0269         } else {
0270             _port->setValue(80);
0271         }
0272     }
0273 }
0274 
0275 bool KNetAttach::doConnectionTest(const QUrl &url)
0276 {
0277     KIO::StatJob *job = KIO::stat(url);
0278     KJobWidgets::setWindow(job, this);
0279     return job->exec();
0280 }
0281 
0282 bool KNetAttach::updateForProtocol(const QString &protocol)
0283 {
0284     _type = protocol;
0285     if (protocol == QLatin1String("WebFolder")) {
0286         _useEncryption->show();
0287         _portText->show();
0288         _port->show();
0289         _protocol->hide();
0290         _protocolText->hide();
0291         _userText->hide();
0292         _user->hide();
0293         _encodingText->hide();
0294         _encoding->hide();
0295     } else if (protocol == QLatin1String("Fish")) {
0296         _useEncryption->hide();
0297         _portText->show();
0298         _port->show();
0299         _protocol->show();
0300         _protocolText->show();
0301         _userText->show();
0302         _user->show();
0303         _encodingText->show();
0304         _encoding->show();
0305     } else if (protocol == QLatin1String("FTP")) {
0306         _useEncryption->hide();
0307         _portText->show();
0308         _port->show();
0309         _protocol->hide();
0310         _protocolText->hide();
0311         _userText->show();
0312         _user->show();
0313         _encodingText->show();
0314         _encoding->show();
0315     } else if (protocol == QLatin1String("SMB")) {
0316         _useEncryption->hide();
0317         _portText->hide();
0318         _port->hide();
0319         _protocol->hide();
0320         _protocolText->hide();
0321         _userText->hide();
0322         _user->hide();
0323         _encodingText->hide();
0324         _encoding->hide();
0325     } else {
0326         _type = QString();
0327         return false;
0328     }
0329     return true;
0330 }
0331 
0332 void KNetAttach::updateFinishButtonText(bool save)
0333 {
0334     if (save) {
0335         button(FinishButton)->setText(i18n("Save && C&onnect"));
0336     } else {
0337         button(FinishButton)->setText(i18n("C&onnect"));
0338     }
0339 }
0340 
0341 // vim: ts=8 sw=4 noet