/* This file is part of the KDE Project Copyright (c) 2005 Jean-Remy Falleri Copyright (c) 2005-2007 Kevin Ottens Copyright (c) 2007 Alexis Ménard Copyright (c) 2011 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "soliduiserver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "deviceactionsdialog.h" #include "deviceaction.h" #include "deviceserviceaction.h" #include "devicenothingaction.h" #include #include K_PLUGIN_FACTORY(SolidUiServerFactory, registerPlugin(); ) K_EXPORT_PLUGIN(SolidUiServerFactory("soliduiserver")) SolidUiServer::SolidUiServer(QObject* parent, const QList&) : KDEDModule(parent) { } SolidUiServer::~SolidUiServer() { } void SolidUiServer::showActionsDialog(const QString &udi, const QStringList &desktopFiles) { if (m_udiToActionsDialog.contains(udi)) { DeviceActionsDialog *dialog = m_udiToActionsDialog[udi]; dialog->activateWindow(); return; } QList actions; foreach (const QString &desktop, desktopFiles) { QString filePath = KStandardDirs::locate("data", "solid/actions/"+desktop); QList services = KDesktopFileActions::userDefinedServices(filePath, true); foreach (const KServiceAction &service, services) { DeviceServiceAction *action = new DeviceServiceAction(); action->setService(service); actions << action; } } // Only one action, execute directly if (actions.size()==1) { DeviceAction *action = actions.takeFirst(); Solid::Device device(udi); action->execute(device); delete action; return; } actions << new DeviceNothingAction(); DeviceActionsDialog *dialog = new DeviceActionsDialog(); dialog->setDevice(Solid::Device(udi)); dialog->setActions(actions); connect(dialog, SIGNAL(finished()), this, SLOT(onActionDialogFinished())); m_udiToActionsDialog[udi] = dialog; // Update user activity timestamp, otherwise the notification dialog will be shown // in the background due to focus stealing prevention. Entering a new media can // be seen as a kind of user activity after all. It'd be better to update the timestamp // as soon as the media is entered, but it apparently takes some time to get here. kapp->updateUserTimestamp(); dialog->show(); } void SolidUiServer::onActionDialogFinished() { DeviceActionsDialog *dialog = qobject_cast(sender()); if (dialog) { QString udi = dialog->device().udi(); m_udiToActionsDialog.remove(udi); } } int SolidUiServer::mountDevice(const QString &udi) { Solid::Device device(udi); Solid::StorageVolume *storagevolume = device.as(); Solid::Block *block = device.as(); if (!storagevolume || !block) { return int(Solid::ErrorType::InvalidOption); } QString devicenode = block->device(); const QString deviceuuid(storagevolume->uuid()); bool didcryptopen = false; #ifdef Q_OS_LINUX const QString dmnode = QLatin1String("/dev/mapper/") + deviceuuid; if (storagevolume->usage() == Solid::StorageVolume::Encrypted) { KPasswordDialog passworddialog(0, KPasswordDialog::NoFlags); QString label = device.vendor(); if (!label.isEmpty()) { label += ' '; } label += device.product(); passworddialog.setPrompt(i18n("'%1' needs a password to be accessed. Please enter a password.", label)); passworddialog.setPixmap(KIcon(device.icon()).pixmap(64, 64)); if (!passworddialog.exec()) { return int(Solid::ErrorType::UserCanceled); } KAuth::Action cryptopenaction("org.kde.soliduiserver.mountunmounthelper.cryptopen"); cryptopenaction.setHelperID("org.kde.soliduiserver.mountunmounthelper"); cryptopenaction.addArgument("device", devicenode); cryptopenaction.addArgument("name", deviceuuid); cryptopenaction.addArgument("password", passworddialog.password().toLocal8Bit().toHex()); KAuth::ActionReply cryptopenreply = cryptopenaction.execute(); // qDebug() << "cryptopen" << cryptopenreply.errorCode() << cryptopenreply.errorDescription(); if (cryptopenreply == KAuth::ActionReply::UserCancelled) { return int(Solid::ErrorType::UserCanceled); } else if (cryptopenreply == KAuth::ActionReply::AuthorizationDenied) { return int(Solid::ErrorType::UnauthorizedOperation); } else if (cryptopenreply != KAuth::ActionReply::SuccessReply) { return int(Solid::ErrorType::OperationFailed); } didcryptopen = true; // NOTE: keep in sync with kdelibs/solid/solid/backends/udev/udevstorageaccess.cpp devicenode = dmnode; } #else #warning crypto storage devices are not supported on this platform #endif // permission denied on /run/mount so.. using base directory that is writable const QString mountbase = KGlobal::dirs()->saveLocation("tmp"); QString mountpoint = mountbase + QLatin1Char('/') + deviceuuid; QDir mountdir(mountbase); if (!mountdir.exists(deviceuuid) && !mountdir.mkdir(deviceuuid)) { kWarning() << "could not create" << mountpoint; return int(Solid::ErrorType::OperationFailed); } KAuth::Action mountaction("org.kde.soliduiserver.mountunmounthelper.mount"); mountaction.setHelperID("org.kde.soliduiserver.mountunmounthelper"); mountaction.addArgument("device", devicenode); mountaction.addArgument("mountpoint", mountpoint); KAuth::ActionReply mountreply = mountaction.execute(); // qDebug() << "mount" << mountreply.errorCode() << mountreply.errorDescription(); if (mountreply == KAuth::ActionReply::SuccessReply) { return int(Solid::ErrorType::NoError); } if (didcryptopen) { KAuth::Action cryptcloseaction("org.kde.soliduiserver.mountunmounthelper.cryptclose"); cryptcloseaction.setHelperID("org.kde.soliduiserver.mountunmounthelper"); cryptcloseaction.addArgument("name", storagevolume->uuid()); cryptcloseaction.execute(); } if (mountreply == KAuth::ActionReply::UserCancelled) { return int(Solid::ErrorType::UserCanceled); } else if (mountreply == KAuth::ActionReply::AuthorizationDenied) { return int(Solid::ErrorType::UnauthorizedOperation); } return int(Solid::ErrorType::OperationFailed); } int SolidUiServer::unmountDevice(const QString &udi) { Solid::Device device(udi); Solid::StorageVolume *storagevolume = device.as(); Solid::StorageAccess *storageaccess = device.as(); if (!storagevolume || !storageaccess) { return int(Solid::ErrorType::InvalidOption); } KAuth::Action unmountaction("org.kde.soliduiserver.mountunmounthelper.unmount"); unmountaction.setHelperID("org.kde.soliduiserver.mountunmounthelper"); unmountaction.addArgument("mountpoint", storageaccess->filePath()); KAuth::ActionReply unmountreply = unmountaction.execute(); // qDebug() << "unmount" << unmountreply.errorCode() << unmountreply.errorDescription(); if (unmountreply == KAuth::ActionReply::UserCancelled) { return int(Solid::ErrorType::UserCanceled); } else if (unmountreply == KAuth::ActionReply::AuthorizationDenied) { return int(Solid::ErrorType::UnauthorizedOperation); } else if (unmountreply != KAuth::ActionReply::SuccessReply) { return int(Solid::ErrorType::OperationFailed); } if (storagevolume->usage() == Solid::StorageVolume::Encrypted) { KAuth::Action cryptcloseaction("org.kde.soliduiserver.mountunmounthelper.cryptclose"); cryptcloseaction.setHelperID("org.kde.soliduiserver.mountunmounthelper"); cryptcloseaction.addArgument("name", storagevolume->uuid()); KAuth::ActionReply cryptclosereply = cryptcloseaction.execute(); // qDebug() << "cryptclose" << cryptclosereply.errorCode() << cryptclosereply.errorDescription(); if (cryptclosereply == KAuth::ActionReply::UserCancelled) { return int(Solid::ErrorType::UserCanceled); } else if (cryptclosereply == KAuth::ActionReply::AuthorizationDenied) { return int(Solid::ErrorType::UnauthorizedOperation); } else if (cryptclosereply != KAuth::ActionReply::SuccessReply) { return int(Solid::ErrorType::OperationFailed); } } return int(Solid::ErrorType::NoError); } #include "moc_soliduiserver.cpp"