File indexing completed on 2024-05-05 17:42:16

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