File indexing completed on 2024-04-21 05:47:44

0001 /*************************************************************************************
0002  *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 #include "mountinfo.h"
0020 
0021 #include <QtCore/QProcess>
0022 #include <QDir>
0023 
0024 #include <QDebug>
0025 #include <KColorScheme>
0026 #include <solid/device.h>
0027 #include <solid/storageaccess.h>
0028 #include <KPixmapSequenceOverlayPainter>
0029 #include <KLineEdit>
0030 #include <KDesktopFile>
0031 #include "kpasswdserver_interface.h"
0032 
0033 MountInfo::MountInfo(OrgKdeKPasswdServerInterface* iface, KConfigGroup config, QWidget* parent)
0034 : QWidget(parent)
0035 , m_share(false)
0036 , m_mount(false)
0037 , m_editMode(false)
0038 , m_process(new QProcess)
0039 , m_config(config)
0040 , m_painter1(new KPixmapSequenceOverlayPainter)
0041 , m_painter2(new KPixmapSequenceOverlayPainter)
0042 , m_interface(iface)
0043 {
0044     setupUi(this);
0045 
0046     m_painter1->setWidget(working1);
0047     m_painter2->setWidget(working2);
0048 
0049     KColorScheme scheme(QPalette::Normal);
0050 
0051     QPalette palette(error->palette());
0052     palette.setColor(QPalette::Foreground, scheme.foreground(KColorScheme::NegativeText).color());
0053 
0054     error->setPalette(palette);
0055 
0056     sambaRequester->setUrl(QUrl("smb://"));
0057     connect(sambaRequester, SIGNAL(urlSelected(QUrl)), SLOT(checkValidSamba(QUrl)));
0058     connect(sambaRequester, SIGNAL(textChanged(QString)),SLOT(checkValidSamba(QString)));
0059     connect(username, &QLineEdit::textChanged, this, &MountInfo::changed);
0060     connect(password, &QLineEdit::textChanged, this, &MountInfo::changed);
0061 
0062     connect(m_process, SIGNAL(finished(int)), SLOT(nameResolveFinished(int)));
0063 
0064     connect(shareName, SIGNAL(textChanged(QString)), SLOT(checkMountPoint(QString)));
0065 
0066     connect(saveButton, SIGNAL(clicked(bool)), SLOT(buttonClicked()));
0067 
0068     connect(m_interface, &OrgKdeKPasswdServerInterface::checkAuthInfoAsyncResult, this, &MountInfo::authInfoReceived);
0069 }
0070 
0071 MountInfo::~MountInfo()
0072 {
0073     delete m_process;
0074     delete m_painter1;
0075     delete m_painter2;
0076 }
0077 
0078 QString MountInfo::id() const
0079 {
0080     return m_id;
0081 }
0082 
0083 void MountInfo::setConfigGroup(const QString& name)
0084 {
0085     m_id = name;
0086     sambaRequester->setUrl(m_config.group(name).readEntry("fullSambaUrl"));
0087     shareName->setText(m_config.group(name).readEntry("mountName"));
0088     username->setText(m_config.group(name).readEntry("username"));
0089     password->setText(m_config.group(name).readEntry("password"));
0090 
0091     setEditMode();
0092 }
0093 
0094 void MountInfo::checkValidSamba(const QString& url)
0095 {
0096     checkValidSamba(QUrl(url));
0097 }
0098 
0099 void MountInfo::checkValidSamba(const QUrl &url)
0100 {
0101     KIO::AuthInfo info;
0102     info.url = url;
0103     m_interface->checkAuthInfoAsync(info, window()->winId(), 0);
0104 
0105     qDebug() << "check valid url. Host: " << url.host() << url;
0106     m_process->close();
0107 
0108     m_share = false;
0109     setResult(working1, Empty);
0110 
0111     m_fullSambaUrl = url.url();
0112     //If path and file are the same thing for example smb://foo/public
0113     m_sambaDir = url.path();
0114 
0115     qDebug() << "fullSambaUrl" << m_fullSambaUrl << "sambaDir:" << m_sambaDir;
0116     if (m_sambaDir.isEmpty() || m_sambaDir == "/") {
0117         error->setText(i18n("You must select a folder"));
0118         setResult(working1, Fail);
0119         return;
0120     }
0121 
0122     m_host = url.host();
0123     if (isIp(m_host))
0124         checkValidIp(m_host);
0125     else
0126         checkValidHost(m_host);
0127 
0128     Q_EMIT changed();
0129 }
0130 
0131 bool MountInfo::isIp(const QString& host)
0132 {
0133     QStringList split = host.split('.');
0134     if (split.count() != 4) {
0135         return false;
0136     }
0137 
0138     Q_FOREACH(const QString &oc, split) {
0139         if (oc.toInt() > 254) {
0140             return false;
0141         }
0142     }
0143 
0144     return true;
0145 }
0146 
0147 void MountInfo::checkValidIp(const QString& host)
0148 {
0149     m_painter1->start();
0150 
0151     QStringList args;
0152     args.append("-T");
0153     args.append("-A");
0154     args.append(host);
0155     qDebug() << "valid IP" << args;
0156     m_process->start("nmblookup", args);
0157 }
0158 
0159 void MountInfo::checkValidHost(const QString& host)
0160 {
0161     m_painter1->start();
0162     m_process->start("nmblookup", QStringList(host));
0163 }
0164 
0165 void MountInfo::nameResolveFinished(int status)
0166 {
0167     qDebug() << "Status: " << status;
0168 
0169     m_painter1->stop();
0170 
0171     QByteArray output = m_process->readAllStandardOutput();
0172 //     qDebug() << "name resolved:" << output;
0173 
0174     if (output.isEmpty()) {
0175         error->setText(i18n("Couldn't get the server IP"));
0176         setResult(working1, Fail);
0177         return;
0178     }
0179 
0180     QString ipLine;
0181     const QList<QByteArray> lines = output.split('\n');
0182     Q_FOREACH(const QString &line, lines) {
0183         if (line.contains(m_host)) {
0184             ipLine = line;
0185             break;
0186         }
0187     }
0188     QString ip = ipLine.left(ipLine.indexOf(' ')).trimmed();
0189 
0190     qDebug() << "Ip: " << ip;
0191     if (ip.isEmpty() || ip == "name_query") {
0192         error->setText(i18n("Couldn't get the server IP"));
0193         setResult(working1, Fail);
0194         return;
0195     }
0196 
0197     if (!isIp(ip)) {
0198         m_ip = m_host;
0199         m_host = ip.toLower();
0200     } else {
0201         m_ip = ip;
0202     }
0203 
0204     m_share = true;
0205     setResult(working1, Ok);
0206 
0207     autoFillMountName();
0208 }
0209 
0210 bool MountInfo::checkMountPoint(const QString& name)
0211 {
0212     m_mountName = name;
0213     return checkMountPoint(QUrl::fromLocalFile(QDir::homePath() + "/Network/" + name));
0214 }
0215 
0216 bool MountInfo::checkMountPoint(const QUrl &url)
0217 {
0218     qDebug() << "ckecking mount point..." << url;
0219     QDir dir(url.toLocalFile());
0220 
0221     const QString networkDir(QDir::homePath() + "/Network");
0222     dir.mkdir(networkDir);
0223 
0224     KDesktopFile cfg(networkDir + QString::fromLatin1("/.directory"));
0225     if (cfg.desktopGroup().readEntry("Icon", "").isEmpty()) {
0226         cfg.desktopGroup().writeEntry("Icon", "folder-remote");
0227         cfg.sync();
0228 
0229         cfg.reparseConfiguration();
0230     }
0231 
0232     m_mount = false;
0233     m_mountPoint = url.toLocalFile();
0234 
0235     if (dir.exists() && dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).count() != 0) {
0236         error->setText(i18n("Please, choose another name"));
0237         setResult(working2, Fail);
0238         Q_EMIT checkDone();
0239         return false;
0240     }
0241 
0242     QList <Solid::Device> devices = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess);
0243     Q_FOREACH(const Solid::Device &device, devices) {
0244         if (device.as<Solid::StorageAccess>()->filePath() == url.toLocalFile()) {
0245             error->setText(i18n("Please, choose another name"));
0246             setResult(working2, Fail);
0247             return false;
0248         }
0249     }
0250 
0251     m_mount = true;
0252     setResult(working2, Ok);
0253 
0254     return true;
0255 }
0256 
0257 void MountInfo::setResult(QLabel* lbl, MountInfo::Status status)
0258 {
0259     switch(status)
0260     {
0261         case Empty:
0262             lbl->setPixmap(QPixmap());
0263             break;
0264         case Ok:
0265             lbl->setPixmap(QIcon::fromTheme("dialog-ok-apply").pixmap(lbl->sizeHint()));
0266             error->clear();
0267             Q_EMIT checkDone();
0268             break;
0269         case Fail:
0270             lbl->setPixmap(QIcon::fromTheme("dialog-close").pixmap(lbl->sizeHint()));
0271             Q_EMIT checkDone();
0272             break;
0273     }
0274 }
0275 
0276 void MountInfo::buttonClicked()
0277 {
0278     checkMountPoint(shareName->text());
0279     checkValidSamba(sambaRequester->url());
0280 
0281     connect(this, SIGNAL(checkDone()), SLOT(mountIsValid()));
0282 }
0283 
0284 void MountInfo::mountIsValid()
0285 {
0286     qDebug() << "Mount is valid";
0287     disconnect(this, SIGNAL(checkDone()), this, SLOT(mountIsValid()));
0288 
0289     if (!m_mount || !m_share) {
0290         return;
0291     }
0292 
0293     if (m_editMode) {
0294         m_config.deleteGroup(m_id);
0295     }
0296 
0297     m_id = m_fullSambaUrl + "-" + m_mountPoint;
0298 
0299     KConfigGroup group = m_config.group(m_id);
0300 
0301     saveConfig(group);
0302 
0303     qDebug() << "Edit mode:" << m_editMode;
0304     if (m_editMode) {
0305         Q_EMIT mountEditted(group);
0306         return;
0307     }
0308 
0309     Q_EMIT mountCreated(group);
0310     setEditMode();
0311 }
0312 
0313 void MountInfo::saveConfig()
0314 {
0315     if (m_id.isEmpty() && !m_fullSambaUrl.isEmpty() && !m_mountPoint.isEmpty()) {
0316         m_id = m_fullSambaUrl + "-" + m_mountPoint;
0317     }
0318 
0319     if (m_id.isEmpty()) {
0320         return;
0321     }
0322 
0323     saveConfig(m_config.group(m_id));
0324 }
0325 
0326 void MountInfo::saveConfig(KConfigGroup group)
0327 {
0328     qDebug() << "Saving mount";
0329 
0330     group.writeEntry("ip", m_ip);
0331     group.writeEntry("hostname", m_host);
0332     group.writeEntry("mountPoint", m_mountPoint);
0333     group.writeEntry("sambaDir", m_sambaDir);
0334     group.writeEntry("fullSambaUrl", m_fullSambaUrl);
0335     group.writeEntry("mountName", m_mountName);
0336     group.writeEntry("username", username->text());
0337     group.writeEntry("password", password->text());
0338 
0339     group.sync();
0340 
0341     QDir().mkdir(m_mountPoint);
0342 }
0343 
0344 void MountInfo::setEditMode()
0345 {
0346     setResult(working1, Empty);
0347     setResult(working2, Empty);
0348 
0349     m_editMode = true;
0350 }
0351 
0352 void MountInfo::autoFillMountName()
0353 {
0354     if (!shareName->text().isEmpty()) {
0355         return;
0356     }
0357 
0358     QString name = sambaRequester->url().fileName();
0359 
0360     if (!checkMountPoint(name)) {
0361         setResult(working2, Empty);
0362         error->clear();
0363         return;
0364     }
0365 
0366     shareName->setText(name);
0367 }
0368 
0369 void MountInfo::authInfoReceived(qlonglong /*requestId*/, qlonglong /*seqNr*/, const KIO::AuthInfo & info)
0370 {
0371     if (!username->text().isEmpty() || !password->text().isEmpty())
0372         return;
0373 
0374     if (info.url == sambaRequester->url()) {
0375 //         qDebug() << "awesomeeeeeeeeeee" << requestId << info.username << info.password;
0376         username->setText(info.username);
0377         password->setText(info.password);
0378     }
0379 }