/* This file is part of the KDE project Copyright (c) 2004 Kévin Ottens Parts of this file are Copyright 2003 Waldo Bastian This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dialog.h" #include "kio_media_mounthelper.h" const Medium MountHelper::findMedium(const KURL &url) { DCOPRef mediamanager("kded", "mediamanager"); // Try filename first DCOPReply reply = mediamanager.call( "properties", url.fileName() ); if ( !reply.isValid() ) { m_errorStr = i18n("The KDE mediamanager is not running.")+"\n"; return Medium(TQString::null, TQString::null); } const Medium& medium = Medium::create(reply); if ( medium.id().isEmpty() ) { // Try full URL now reply = mediamanager.call( "properties", url.prettyURL() ); if ( !reply.isValid() ) { m_errorStr = i18n("Internal Error"); return Medium(TQString::null, TQString::null); } return Medium::create(reply); } else { return medium; } } MountHelper::MountHelper() : KApplication() { KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); m_errorStr = TQString::null; KURL url(args->url(0)); const Medium medium = findMedium(url); if ( medium.id().isEmpty() ) { if (m_errorStr.isEmpty()) m_errorStr+= i18n("%1 cannot be found.").arg(url.prettyURL()); TQTimer::singleShot(0, this, TQT_SLOT(error()) ); return; } if ( !medium.isMountable() && !args->isSet("e") && !args->isSet("s")) { m_errorStr = i18n("%1 is not a mountable media.").arg(url.prettyURL()); TQTimer::singleShot(0, this, TQT_SLOT(error()) ); return; } TQString device = medium.deviceNode(); TQString mount_point = medium.mountPoint(); m_isCdrom = medium.mimeType().find("dvd")!=-1 || medium.mimeType().find("cd")!=-1; if (args->isSet("d")) { if (!medium.isEncrypted()) { m_errorStr = i18n("%1 is not an encrypted media.").arg(url.prettyURL()); TQTimer::singleShot(0, this, TQT_SLOT(error()) ); return; } if (!medium.needDecryption()) { m_errorStr = i18n("%1 is already decrypted.").arg(url.prettyURL()); TQTimer::singleShot(0, this, TQT_SLOT(error()) ); return; } TQString iconName = medium.iconName(); if (iconName.isEmpty()) { TQString mime = medium.mimeType(); iconName = KMimeType::mimeType(mime)->icon(mime, false); } m_mediumId = medium.id(); dialog = new Dialog(url.prettyURL(), iconName); dialog->show(); connect(dialog, TQT_SIGNAL (user1Clicked()), this, TQT_SLOT (slotSendPassword())); connect(dialog, TQT_SIGNAL (cancelClicked()), this, TQT_SLOT (slotCancel())); connect(this, TQT_SIGNAL (signalPasswordError(TQString)), dialog, TQT_SLOT (slotDialogError(TQString))); } else if (args->isSet("u")) { DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "unmount", medium.id()); if (reply.isValid()) reply.get(m_errorStr); kdDebug() << "medium unmount " << m_errorStr << endl; if (m_errorStr.isNull()) ::exit(0); else error(); } else if (args->isSet("s") || args->isSet("e")) { DCOPRef mediamanager("kded", "mediamanager"); /* * We want to call mediamanager unmount before invoking eject. That's * because unmount would provide an informative error message in case of * failure. However, there are cases when unmount would fail * (supermount, slackware, see bug#116209) but eject would succeed. * Thus if unmount fails, save unmount error message and invokeEject() * anyway. Only if both unmount and eject fail, notify the user by * displaying the saved error message (see ejectFinished()). */ if (medium.isMounted()) { DCOPReply reply = mediamanager.call( "unmount", medium.id()); if (reply.isValid()) reply.get(m_errorStr); } /* If this is a decrypted volume and there is no error yet * we try to teardown the decryption */ if (m_errorStr.isNull() && medium.isEncrypted() && !medium.clearDeviceUdi().isNull()) { DCOPReply reply = mediamanager.call( "undecrypt", medium.id()); if (reply.isValid()) reply.get(m_errorStr); } if (m_errorStr.isNull()) invokeEject(device, true); else error(); } else { DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "mount", medium.id()); if (reply.isValid()) reply.get(m_errorStr); if (m_errorStr.isNull()) ::exit(0); else error(); } } void MountHelper::invokeEject(const TQString &device, bool quiet) { KProcess *proc = new KProcess(TQT_TQOBJECT(this)); *proc << "kdeeject"; if (quiet) { *proc << "-q"; } *proc << device; connect( proc, TQT_SIGNAL(processExited(KProcess *)), this, TQT_SLOT( ejectFinished(KProcess *) ) ); proc->start(); } void MountHelper::ejectFinished(KProcess* proc) { /* * If eject failed, report the error stored in m_errorStr */ if (proc->normalExit() && proc->exitStatus() == 0) { ::exit(0); } else { if (m_errorStr.isEmpty()) { if (m_isCdrom) m_errorStr = i18n("The device was successfully unmounted, but the tray could not be opened"); else m_errorStr = i18n("The device was successfully unmounted, but could not be ejected"); } //X Comment this because the error is useless as long as the unmount is successful. //X TQTimer::singleShot(0, this, TQT_SLOT(error())); ::exit(0); } } void MountHelper::error() { TQString prettyErrorString = m_errorStr; if (m_errorStr.contains("<") && m_errorStr.contains(">")) { if (!m_errorStr.contains("")) { prettyErrorString = TQString("%1").arg(m_errorStr); } } KMessageBox::error(0, prettyErrorString); ::exit(1); } void MountHelper::slotSendPassword() { DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "decrypt", m_mediumId, dialog->getPassword() ); if (!reply.isValid()) { m_errorStr = i18n("The KDE mediamanager is not running."); error(); } else { TQString errorMsg = reply; if (errorMsg.isNull()) { exit(0); } else { emit signalPasswordError(errorMsg); } } } void MountHelper::slotCancel() { exit(0); } static KCmdLineOptions options[] = { { "d", I18N_NOOP("Decrypt given URL"), 0 }, { "u", I18N_NOOP("Unmount given URL"), 0 }, { "m", I18N_NOOP("Mount given URL (default)"), 0 }, { "e", I18N_NOOP("Eject given URL via kdeeject"), 0}, { "s", I18N_NOOP("Unmount and Eject given URL (necessary for some USB devices)"), 0}, {"!+URL", I18N_NOOP("media:/ URL to mount/unmount/eject/remove"), 0 }, KCmdLineLastOption }; int main(int argc, char **argv) { KCmdLineArgs::init(argc, argv, "kio_media_mounthelper", "kio_media_mounthelper", "kio_media_mounthelper", "0.1"); KCmdLineArgs::addCmdLineOptions( options ); KGlobal::locale()->setMainCatalogue("kio_media"); KApplication::addCmdLineOptions(); if (KCmdLineArgs::parsedArgs()->count()==0) KCmdLineArgs::usage(); KApplication *app = new MountHelper(); KStartupInfo::appStarted(); app->dcopClient()->attach(); return app->exec(); } #include "kio_media_mounthelper.moc"