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 "sambamount.h"
0020 #include "mountinfo.h"
0021 #include "ui_kcm.h"
0022 
0023 #include <QStackedLayout>
0024 
0025 #include <QDebug>
0026 #include <QAction>
0027 #include <QDBusMessage>
0028 #include <QDBusConnection>
0029 #include <QDBusArgument>
0030 #include <KAuthAction>
0031 #include <KAuthExecuteJob>
0032 #include <KPluginFactory>
0033 #include <KSharedConfig>
0034 #include <unistd.h>
0035 #include "kpasswdserver_interface.h"
0036 
0037 using namespace KAuth;
0038 
0039 K_PLUGIN_FACTORY(SambaMountFactory, registerPlugin<SambaMount>();)
0040 K_EXPORT_PLUGIN(SambaMountFactory("sambamount", "sambamount"))
0041 
0042 SambaMount::SambaMount(QWidget *parent, const QVariantList &args)
0043 : KCModule(parent)
0044 , m_layout(new QStackedLayout)
0045 {
0046     if (args.count() > 1 && args.first() == QLatin1String("--new")) {
0047         m_selectNew = true;
0048     }
0049 
0050     setButtons(KCModule::Help);
0051     m_ui = new Ui::KCMSambaMount();
0052     m_ui->setupUi(this);
0053 
0054     m_ui->mountInfo->setLayout(m_layout);
0055     m_ui->mountList->setIconSize(QSize(48, 48));
0056     m_ui->errorWidget->setMessageType(KMessageWidget::Error);
0057     m_ui->errorWidget->hide();
0058 
0059     connect(m_ui->remoteBtn, SIGNAL(clicked(bool)), SLOT(rmBtnClicked()));
0060     connect(m_ui->addBtn, SIGNAL(clicked(bool)), SLOT(addBtnClicked()));
0061     connect(m_ui->mountList, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
0062             this, SLOT(currentItemChanged(QListWidgetItem*,QListWidgetItem*)));
0063 
0064     QMetaObject::invokeMethod(this, "initSambaMounts", Qt::QueuedConnection);
0065 
0066     m_interface = new OrgKdeKPasswdServerInterface("org.kde.kpasswdserver", "/modules/kpasswdserver", QDBusConnection::sessionBus(), this);
0067 }
0068 
0069 SambaMount::~SambaMount()
0070 {
0071     delete m_ui;
0072 }
0073 
0074 void SambaMount::initSambaMounts()
0075 {
0076     KConfigGroup configMounts = mounts();
0077     Q_FOREACH(const QString &id, configMounts.groupList()) {
0078         addMount(configMounts.group(id));
0079     }
0080 
0081     MountInfo *widget = new MountInfo(m_interface, mounts(), this);
0082     connect(widget, &MountInfo::changed, this, [this]() { changed(true); });
0083     connect(widget, SIGNAL(mountCreated(KConfigGroup)), SLOT(mountCreated(KConfigGroup)));
0084 
0085     m_layout->addWidget(widget);
0086 
0087     m_newMountItem = new QListWidgetItem();
0088     m_newMountItem->setIcon(QIcon::fromTheme("applications-education-miscellaneous"));
0089     m_newMountItem->setText(i18n("New Share"));
0090     m_newMountItem->setData(Qt::UserRole, QVariant(i18n("New Share")));
0091     m_newMountItem->setData(Qt::UserRole + 1, QVariant::fromValue<QWidget *>(widget));
0092 
0093     m_ui->mountList->addItem(m_newMountItem);
0094 
0095     if (m_ui->mountList->count() == 0 || m_selectNew) {
0096         m_ui->mountList->setCurrentItem(m_newMountItem);
0097         return;
0098     }
0099 
0100     m_ui->mountList->setCurrentItem(m_ui->mountList->item(0));
0101 }
0102 
0103 void SambaMount::save()
0104 {
0105     QListWidgetItem* item = m_ui->mountList->currentItem();
0106     QWidget *widget = item->data(Qt::UserRole + 1).value<QWidget *>();
0107     MountInfo *info = qobject_cast<MountInfo*>(widget);
0108     if (info) {
0109         info->saveConfig();
0110         if (!info->id().isEmpty()) {
0111             mountSamba(mounts().group(info->id()));
0112         }
0113     }
0114 }
0115 
0116 void SambaMount::currentItemChanged(QListWidgetItem* current, QListWidgetItem* previous)
0117 {
0118     if (!current) {
0119         return;
0120     }
0121 
0122     m_ui->mountInfo->setTitle(current->text());
0123     m_layout->setCurrentWidget(current->data(Qt::UserRole + 1).value<QWidget *>());
0124     m_ui->remoteBtn->setEnabled(current != m_newMountItem);
0125 }
0126 
0127 void SambaMount::mountCreated(KConfigGroup group)
0128 {
0129     qDebug() << "New Mount Created";
0130     QListWidgetItem *item = new QListWidgetItem();
0131     item->setIcon(QIcon::fromTheme("network-server"));
0132     item->setText(QUrl(group.readEntry("fullSambaUrl", "")).fileName() + " on " + group.readEntry("hostname", ""));
0133     item->setData(Qt::UserRole, group.readEntry("ip", ""));
0134     item->setData(Qt::UserRole + 1, QVariant::fromValue<QWidget *>(qobject_cast<QWidget *>(sender())));
0135     item->setData(Qt::UserRole + 2, group.name());
0136 
0137     m_ui->mountList->addItem(item);
0138 
0139     MountInfo *widget = new MountInfo(m_interface, mounts(), this);
0140     connect(widget, &MountInfo::changed, this, [this]() { changed(true); });
0141     connect(widget, SIGNAL(mountCreated(KConfigGroup)), SLOT(mountCreated(KConfigGroup)));
0142 
0143     m_layout->addWidget(widget);
0144 
0145     m_newMountItem->setData(Qt::UserRole + 1, QVariant::fromValue<QWidget *>(widget));
0146 
0147     int row = m_ui->mountList->row(m_newMountItem);
0148 
0149     m_ui->mountList->takeItem(row);
0150     m_ui->mountList->insertItem(row, item);
0151     m_ui->mountList->addItem(m_newMountItem);
0152     m_ui->mountList->setCurrentItem(item);
0153 
0154     mountSamba(group);
0155 }
0156 
0157 void SambaMount::mountEditted(KConfigGroup group)
0158 {
0159     qDebug() << "Mount editted" << group.name();
0160     if (umountSamba(group.name()))
0161         mountSamba(group);
0162 }
0163 
0164 void SambaMount::addBtnClicked()
0165 {
0166     m_ui->mountList->setCurrentItem(m_newMountItem, QItemSelectionModel::SelectCurrent);
0167 }
0168 
0169 void SambaMount::rmBtnClicked()
0170 {
0171     QListWidgetItem *item = m_ui->mountList->currentItem();
0172     if (item == m_newMountItem) {
0173         return;
0174     }
0175 
0176     QString groupName = item->data(Qt::UserRole + 2).toString();
0177     umountSamba(groupName);
0178     QDir().rmdir(mounts().group(groupName).readEntry("mountPoint", ""));
0179     mounts().deleteGroup(groupName);
0180 
0181     QWidget *widget = item->data(Qt::UserRole + 1).value<QWidget *>();
0182     item->setData(Qt::UserRole + 1, 0);
0183     m_layout->removeWidget(widget);
0184     m_ui->mountList->removeItemWidget(item);
0185 
0186     delete widget;
0187     delete item;
0188 }
0189 
0190 KConfigGroup SambaMount::mounts()
0191 {
0192     return KSharedConfig::openConfig("samba-mounter")->group("mounts");
0193 }
0194 
0195 void SambaMount::addMount(KConfigGroup group)
0196 {
0197     MountInfo *info = new MountInfo(m_interface, mounts(), this);
0198     connect(info, SIGNAL(mountEditted(KConfigGroup)), SLOT(mountEditted(KConfigGroup)));
0199     connect(info, &MountInfo::changed, this, [this]() { changed(true); });
0200     info->setConfigGroup(group.name());
0201     m_layout->addWidget(info);
0202 
0203     QListWidgetItem *item = new QListWidgetItem();
0204     item->setIcon(QIcon::fromTheme("network-server"));
0205     item->setText(QUrl(group.readEntry("fullSambaUrl", "")).fileName() + " on " + group.readEntry("hostname", ""));
0206     item->setData(Qt::UserRole, group.readEntry("ip", ""));
0207     item->setData(Qt::UserRole + 1, QVariant::fromValue<QWidget *>(info));
0208     item->setData(Qt::UserRole + 2, group.name());
0209 
0210     m_ui->mountList->addItem(item);
0211 }
0212 
0213 bool SambaMount::mountSamba(KConfigGroup group)
0214 {
0215     qDebug() << "Mounting samba: " << group.name();
0216     Action readAction("org.kde.sambamounter.mount");
0217     readAction.setHelperId("org.kde.sambamounter");
0218 
0219     readAction.addArgument("uid", QString::number(getuid()));
0220     readAction.addArgument("ip", group.readEntry("ip", ""));
0221     readAction.addArgument("locale", qgetenv("LANG"));
0222     readAction.addArgument("path", qgetenv("PATH"));
0223     readAction.addArgument("sambaDir", group.readEntry("sambaDir", "").toLocal8Bit().toBase64());
0224     readAction.addArgument("mountPoint", group.readEntry("mountPoint", "").toLocal8Bit().toBase64());
0225     readAction.addArgument("username", group.readEntry("username", "").toLocal8Bit().toBase64());
0226     readAction.addArgument("password", group.readEntry("password", "").toLocal8Bit().toBase64());
0227     return executeJob(readAction.execute());
0228 }
0229 
0230 bool SambaMount::umountSamba(const QString& name)
0231 {
0232     KConfigGroup group = mounts().group(name);
0233     Action readAction("org.kde.sambamounter.umount");
0234     readAction.setHelperId("org.kde.sambamounter");
0235 
0236     readAction.addArgument("locale", qgetenv("LANG"));
0237     readAction.addArgument("path", qgetenv("PATH"));
0238     readAction.addArgument("mountPoint", group.readEntry("mountPoint", "").toLocal8Bit().toBase64());
0239     return executeJob(readAction.execute());
0240 }
0241 
0242 bool SambaMount::executeJob(ExecuteJob* reply)
0243 {
0244     if (!reply->action().isValid()) {
0245         m_ui->errorWidget->setText(i18n("Couldn't find action '%1'", reply->action().name()));
0246         m_ui->errorWidget->animatedShow();
0247         qWarning() << "error while executing" << m_ui->errorWidget->text();
0248         return false;
0249     }
0250 
0251     bool ret = reply->exec();
0252     if (ret) {
0253         qDebug() << "executed" << reply->action().name() << reply->data();
0254         if (reply->data()["exitCode"] != 0) {
0255             m_ui->errorWidget->setText(i18n("Error triggering mount:\n%1", reply->data()["error"].toString()));
0256             m_ui->errorWidget->setToolTip(m_ui->errorWidget->text());
0257             m_ui->errorWidget->animatedShow();
0258         } else
0259             m_ui->errorWidget->animatedHide();
0260     } else {
0261         m_ui->errorWidget->setText(i18n("Error %1 on '%2':\n%3", reply->error(), reply->action().name(), reply->errorString()));
0262         m_ui->errorWidget->animatedShow();
0263         qWarning() << "error while executing" << m_ui->errorWidget->text();
0264     }
0265     return ret;
0266 }
0267 
0268 #include "sambamount.moc"
0269