diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-03-31 20:18:41 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2012-03-31 20:18:41 -0500 |
commit | 03d905ea268bd893030264b0e7b5b98f783c58ff (patch) | |
tree | 3bef5cc590009bc63b9f68a422da1b958c229dcb /kioslave/media | |
parent | d4e6607ad6a9bfc49f4dfeced379c136704714b1 (diff) | |
download | tdebase-03d905ea268bd893030264b0e7b5b98f783c58ff.tar.gz tdebase-03d905ea268bd893030264b0e7b5b98f783c58ff.zip |
Initial merge of alpha quality HAL replacement backend for the media kioslave
Pass the WITH_TDEHWLIB CMake option to enable this backend
Diffstat (limited to 'kioslave/media')
-rw-r--r-- | kioslave/media/CMakeLists.txt | 1 | ||||
-rw-r--r-- | kioslave/media/libmediacommon/mediamanagersettings.kcfg | 5 | ||||
-rw-r--r-- | kioslave/media/mediaimpl.cpp | 6 | ||||
-rw-r--r-- | kioslave/media/mediamanager/CMakeLists.txt | 9 | ||||
-rw-r--r-- | kioslave/media/mediamanager/decryptdialog.ui | 201 | ||||
-rw-r--r-- | kioslave/media/mediamanager/dialog.cpp | 68 | ||||
-rw-r--r-- | kioslave/media/mediamanager/dialog.h | 61 | ||||
-rw-r--r-- | kioslave/media/mediamanager/mediamanager.cpp | 135 | ||||
-rw-r--r-- | kioslave/media/mediamanager/mediamanager.h | 4 | ||||
-rw-r--r-- | kioslave/media/mediamanager/tdehardwarebackend.cpp | 924 | ||||
-rw-r--r-- | kioslave/media/mediamanager/tdehardwarebackend.h | 165 |
11 files changed, 1532 insertions, 47 deletions
diff --git a/kioslave/media/CMakeLists.txt b/kioslave/media/CMakeLists.txt index e140b1488..c8e43cb98 100644 --- a/kioslave/media/CMakeLists.txt +++ b/kioslave/media/CMakeLists.txt @@ -23,6 +23,7 @@ tde_conditional_add_subdirectory( WITH_HAL propsdlgplugin ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/libmediacommon + ${CMAKE_BINARY_DIR} ${TDE_INCLUDE_DIR} ${TQT_INCLUDE_DIRS} ) diff --git a/kioslave/media/libmediacommon/mediamanagersettings.kcfg b/kioslave/media/libmediacommon/mediamanagersettings.kcfg index cd9537859..2994680cd 100644 --- a/kioslave/media/libmediacommon/mediamanagersettings.kcfg +++ b/kioslave/media/libmediacommon/mediamanagersettings.kcfg @@ -9,6 +9,11 @@ <whatsthis>When HAL (Hardware Abstraction Layer) support is enabled, TDE will use it to gather information on the storage media available in your system.</whatsthis> <default>true</default> </entry> + <entry name="TdeHardwareBackendEnabled" type="Bool"> + <label>Enable TDE hardware library backend</label> + <whatsthis>When TDE hardware library support is enabled, TDE will use it to gather information on the storage media available in your system.</whatsthis> + <default>true</default> + </entry> <entry name="CdPollingEnabled" type="Bool"> <label>Enable CD polling</label> <whatsthis>Allows TDE to poll CD-Rom or DVD-Rom drives itself in order to detect medium insert.</whatsthis> diff --git a/kioslave/media/mediaimpl.cpp b/kioslave/media/mediaimpl.cpp index f8d298e27..ccb9af0a2 100644 --- a/kioslave/media/mediaimpl.cpp +++ b/kioslave/media/mediaimpl.cpp @@ -34,6 +34,8 @@ #include "medium.h" +#include <config.h> + MediaImpl::MediaImpl() : TQObject(), DCOPObject("mediaimpl"), mp_mounting(0L) { @@ -226,13 +228,15 @@ bool MediaImpl::ensureMediumMounted(Medium &medium) m_lastErrorMessage = i18n("No such medium."); return false; } - + +#ifdef COMPILE_HALBACKEND if ( medium.isEncrypted() && medium.clearDeviceUdi().isEmpty() ) { m_lastErrorCode = KIO::ERR_COULD_NOT_MOUNT; m_lastErrorMessage = i18n("The drive is encrypted."); return false; } +#endif // COMPILE_HALBACKEND if ( medium.needMounting() ) { diff --git a/kioslave/media/mediamanager/CMakeLists.txt b/kioslave/media/mediamanager/CMakeLists.txt index fcd564d43..1c1a076b3 100644 --- a/kioslave/media/mediamanager/CMakeLists.txt +++ b/kioslave/media/mediamanager/CMakeLists.txt @@ -9,9 +9,6 @@ # ################################################# -# FIXME there is no support for HAL and linuxcdpolling yet - - include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_BINARY_DIR}/kioslave/media/libmediacommon @@ -43,7 +40,8 @@ if( WITH_HAL ) mediamanager.cpp mediamanager.skel medialist.cpp backendbase.cpp fstabbackend.cpp removablebackend.cpp mediadirnotify.cpp mediadirnotify.skel - halbackend.cpp linuxcdpolling.cpp + decryptdialog.ui dialog.cpp + halbackend.cpp linuxcdpolling.cpp tdehardwarebackend.cpp ) tde_add_kpart( ${target} AUTOMOC @@ -55,7 +53,8 @@ else( ) set( ${target}_SRCS mediamanager.cpp mediamanager.skel medialist.cpp backendbase.cpp fstabbackend.cpp removablebackend.cpp - mediadirnotify.cpp mediadirnotify.skel + decryptdialog.ui dialog.cpp + mediadirnotify.cpp mediadirnotify.skel tdehardwarebackend.cpp ) tde_add_kpart( ${target} AUTOMOC diff --git a/kioslave/media/mediamanager/decryptdialog.ui b/kioslave/media/mediamanager/decryptdialog.ui new file mode 100644 index 000000000..939f0a36a --- /dev/null +++ b/kioslave/media/mediamanager/decryptdialog.ui @@ -0,0 +1,201 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DecryptDialog</class> +<widget class="TQWidget"> + <property name="name"> + <cstring>DecryptDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>207</width> + <height>172</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Decrypting Storage Device</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>encryptedIcon</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>48</width> + <height>48</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="scaledContents"> + <bool>true</bool> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>31</width> + <height>41</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="TQLabel"> + <property name="name"> + <cstring>descLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><p><b>%1</b> is an encrypted storage device.</p> +<p>Please enter the password to decrypt the storage device.</p></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignTop</set> + </property> + </widget> + </hbox> + </widget> + <widget class="TQLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&Password:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>passwordEdit</cstring> + </property> + </widget> + <widget class="TQLineEdit"> + <property name="name"> + <cstring>passwordEdit</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="echoMode"> + <enum>Password</enum> + </property> + </widget> + </hbox> + </widget> + <widget class="TQGroupBox" row="2" column="0"> + <property name="name"> + <cstring>errorBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Error</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="TQLabel" row="0" column="0"> + <property name="name"> + <cstring>errorLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignTop</set> + </property> + </widget> + </grid> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/kioslave/media/mediamanager/dialog.cpp b/kioslave/media/mediamanager/dialog.cpp new file mode 100644 index 000000000..549bbdc4a --- /dev/null +++ b/kioslave/media/mediamanager/dialog.cpp @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + * Copyright (C) 2007 Jan Klötzke <jan kloetzke at freenet de> + * + * Based on kryptomedia- Another KDE cryto media application. + * Copyright (C) 2006 Daniel Gollub <dgollub@suse.de> + * + * 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 "dialog.h" + +Dialog::Dialog(TQString url, TQString iconName) : + KDialogBase(NULL, "Dialog", true, "Decrypt Storage Device", (Cancel|User1), User1, false, KGuiItem(i18n("Decrypt"), "decrypted" )) +{ + decryptDialog = new DecryptDialog(this); + + decryptDialog->errorBox->hide(); + decryptDialog->descLabel->setText(decryptDialog->descLabel->text().arg(url)); + decryptDialog->descLabel->adjustSize(); + decryptDialog->adjustSize(); + + enableButton( User1, false ); + + TQPixmap pixmap = KGlobal::iconLoader()->loadIcon(iconName, KIcon::NoGroup, KIcon::SizeLarge); + decryptDialog->encryptedIcon->setPixmap( pixmap ); + + connect(decryptDialog->passwordEdit, TQT_SIGNAL (textChanged(const TQString &)), this, TQT_SLOT (slotPasswordChanged(const TQString &))); + + setMainWidget(decryptDialog); +} + +Dialog::~Dialog() +{ + delete decryptDialog; +} + +TQString Dialog::getPassword() +{ + return decryptDialog->passwordEdit->text(); +} + +void Dialog::slotDialogError(TQString errorMsg) +{ + kdDebug() << __func__ << "(" << errorMsg << " )" << endl; + + decryptDialog->errorLabel->setText(TQString("<b>%1</b>").arg(errorMsg)); + decryptDialog->errorBox->show(); +} + +void Dialog::slotPasswordChanged(const TQString &text) +{ + enableButton( User1, !text.isEmpty() ); +} + +#include "dialog.moc" diff --git a/kioslave/media/mediamanager/dialog.h b/kioslave/media/mediamanager/dialog.h new file mode 100644 index 000000000..872486f5b --- /dev/null +++ b/kioslave/media/mediamanager/dialog.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + * Copyright (C) 2007 Jan Klötzke <jan kloetzke at freenet de> + * + * Based on kryptomedia- Another KDE cryto media application. + * Copyright (C) 2006 Daniel Gollub <dgollub@suse.de> + * + * 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. + */ + +#ifndef DIALOG_H_ +#define DIALOG_H_ + +#include <kmessagebox.h> +#include <klocale.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdialogbase.h> +#include <kiconloader.h> + +#include <tqlineedit.h> +#include <tqlabel.h> +#include <tqgroupbox.h> + +#include "decryptdialog.h" + +class KryptoMedia; + +class Dialog : public KDialogBase +{ + +Q_OBJECT + +public: + Dialog(TQString url, TQString iconName); + ~Dialog(); + + TQString getPassword(); + +public slots: + void slotDialogError(TQString errorMsg); + void slotPasswordChanged(const TQString &text); + +private: + DecryptDialog *decryptDialog; +}; + +#endif // DIALOG_H_ + diff --git a/kioslave/media/mediamanager/mediamanager.cpp b/kioslave/media/mediamanager/mediamanager.cpp index 913de4353..5510a4b17 100644 --- a/kioslave/media/mediamanager/mediamanager.cpp +++ b/kioslave/media/mediamanager/mediamanager.cpp @@ -32,6 +32,10 @@ #include "fstabbackend.h" +#ifdef COMPILE_TDEHARDWAREBACKEND +#include "tdehardwarebackend.h" +#endif // COMPILE_TDEHARDWAREBACKEND + #ifdef COMPILE_HALBACKEND #include "halbackend.h" #endif //COMPILE_HALBACKEND @@ -78,6 +82,7 @@ void MediaManager::loadBackends() mp_removableBackend = 0L; m_halbackend = 0L; + m_tdebackend = 0L; m_fstabbackend = 0L; #ifdef COMPILE_HALBACKEND @@ -103,6 +108,20 @@ void MediaManager::loadBackends() } #endif // COMPILE_HALBACKEND +#ifdef COMPILE_TDEHARDWAREBACKEND + if ( MediaManagerSettings::self()->tdeHardwareBackendEnabled() ) + { + m_mediaList.blockSignals(false); + m_tdebackend = new TDEBackend(m_mediaList, this); + m_backends.append( m_tdebackend ); + m_fstabbackend = new FstabBackend(m_mediaList, true); + m_backends.append( m_fstabbackend ); + // No need to load something else... + m_mediaList.blockSignals(false); + return; + } +#endif // COMPILE_TDEHARDWAREBACKEND + mp_removableBackend = new RemovableBackend(m_mediaList); m_backends.append( mp_removableBackend ); @@ -189,71 +208,107 @@ TQStringList MediaManager::properties(const TQString &name) TQStringList MediaManager::mountoptions(const TQString &name) { #ifdef COMPILE_HALBACKEND - if (!m_halbackend) - return TQStringList(); - return m_halbackend->mountoptions(name); -#else - return TQStringList(); -#endif + if (!m_halbackend) + return TQStringList(); + return m_halbackend->mountoptions(name); +#else // COMPILE_HALBACKEND + #ifdef COMPILE_TDEHARDWAREBACKEND + if (!m_tdebackend) + return TQStringList(); + return m_tdebackend->mountoptions(name); + #else // COMPILE_TDEHARDWAREBACKEND + return TQStringList(); + #endif // COMPILE_TDEHARDWAREBACKEND +#endif // COMPILE_HALBACKEND } bool MediaManager::setMountoptions(const TQString &name, const TQStringList &options) { #ifdef COMPILE_HALBACKEND - if (!m_halbackend) - return false; - return m_halbackend->setMountoptions(name, options); -#else - return false; -#endif + if (!m_halbackend) + return false; + return m_halbackend->setMountoptions(name, options); +#else // COMPILE_HALBACKEND + #ifdef COMPILE_TDEHARDWAREBACKEND + if (!m_tdebackend) + return false; + return m_tdebackend->setMountoptions(name, options); + #else // COMPILE_TDEHARDWAREBACKEND + return false; + #endif // COMPILE_TDEHARDWAREBACKEND +#endif // COMPILE_HALBACKEND } TQString MediaManager::mount(const TQString &name) { #ifdef COMPILE_HALBACKEND - if (!m_halbackend) - return i18n("Feature only available with HAL"); - return m_halbackend->mount(name); -#else - if ( !m_fstabbackend ) // lying :) - return i18n("Feature only available with HAL"); - return m_fstabbackend->mount( name ); -#endif + if (!m_halbackend) + return i18n("Feature only available with HAL"); + return m_halbackend->mount(name); +#else // COMPILE_HALBACKEND + #ifdef COMPILE_TDEHARDWAREBACKEND + if (!m_tdebackend) + return i18n("Feature only available with the TDE hardware backend"); + return m_tdebackend->mount(name); + #else // COMPILE_TDEHARDWAREBACKEND + if ( !m_fstabbackend ) // lying :) + return i18n("Feature only available with HAL or TDE hardware backend"); + return m_fstabbackend->mount( name ); + #endif // COMPILE_TDEHARDWAREBACKEND +#endif // COMPILE_HALBACKEND } TQString MediaManager::unmount(const TQString &name) { #ifdef COMPILE_HALBACKEND - if (!m_halbackend) - return i18n("Feature only available with HAL"); - return m_halbackend->unmount(name); -#else - if ( !m_fstabbackend ) // lying :) - return i18n("Feature only available with HAL"); - return m_fstabbackend->unmount( name ); -#endif + if (!m_halbackend) + return i18n("Feature only available with HAL"); + return m_halbackend->unmount(name); +#else // COMPILE_HALBACKEND + #ifdef COMPILE_TDEHARDWAREBACKEND + if (!m_tdebackend) + return i18n("Feature only available with HAL or TDE hardware backend"); + return m_tdebackend->unmount(name); + #else // COMPILE_TDEHARDWAREBACKEND + if ( !m_fstabbackend ) // lying :) + return i18n("Feature only available with HAL or TDE hardware backend"); + return m_fstabbackend->unmount( name ); + #endif // COMPILE_TDEHARDWAREBACKEND +#endif // COMPILE_HALBACKEND } TQString MediaManager::decrypt(const TQString &name, const TQString &password) { #ifdef COMPILE_HALBACKEND - if (!m_halbackend) - return i18n("Feature only available with HAL"); - return m_halbackend->decrypt(name, password); -#else - return i18n("Feature only available with HAL"); -#endif + if (!m_halbackend) + return i18n("Feature only available with HAL"); + return m_halbackend->decrypt(name, password); +#else // COMPILE_HALBACKEND +// #ifdef COMPILE_TDEHARDWAREBACKEND +// if (!m_tdebackend) +// return i18n("Feature only available with HAL or TDE hardware backend"); +// return m_tdebackend->decrypt(name, password); +// #else // COMPILE_TDEHARDWAREBACKEND + return i18n("Feature only available with HAL"); +// #endif // COMPILE_TDEHARDWAREBACKEND +#endif // COMPILE_HALBACKEND } TQString MediaManager::undecrypt(const TQString &name) { #ifdef COMPILE_HALBACKEND - if (!m_halbackend) - return i18n("Feature only available with HAL"); - return m_halbackend->undecrypt(name); -#else - return i18n("Feature only available with HAL"); -#endif + if (!m_halbackend) + return i18n("Feature only available with HAL"); + return m_halbackend->undecrypt(name); +#else // COMPILE_HALBACKEND +// #ifdef COMPILE_TDEHARDWAREBACKEND +// if (!m_tdebackend) +// return i18n("Feature only available with HAL or TDE hardware backend"); +// return m_tdebackend->undecrypt(name); +// #else // COMPILE_TDEHARDWAREBACKEND + return i18n("Feature only available with HAL"); +// #endif // COMPILE_TDEHARDWAREBACKEND +#endif // COMPILE_HALBACKEND } TQString MediaManager::nameForLabel(const TQString &label) diff --git a/kioslave/media/mediamanager/mediamanager.h b/kioslave/media/mediamanager/mediamanager.h index 2cc46f8cf..256d11bf8 100644 --- a/kioslave/media/mediamanager/mediamanager.h +++ b/kioslave/media/mediamanager/mediamanager.h @@ -1,5 +1,5 @@ /* This file is part of the KDE Project - Copyright (c) 2004 Kévin Ottens <ervin ipsquad net> + Copyright (c) 2004 K�vin Ottens <ervin ipsquad net> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -29,6 +29,7 @@ #include "mediadirnotify.h" class HALBackend; +class TDEBackend; class FstabBackend; class MediaManager : public KDEDModule @@ -85,6 +86,7 @@ private: TQValueList<BackendBase*> m_backends; RemovableBackend *mp_removableBackend; HALBackend *m_halbackend; + TDEBackend *m_tdebackend; MediaDirNotify m_dirNotify; FstabBackend *m_fstabbackend; }; diff --git a/kioslave/media/mediamanager/tdehardwarebackend.cpp b/kioslave/media/mediamanager/tdehardwarebackend.cpp index e69de29bb..7b0315b1a 100644 --- a/kioslave/media/mediamanager/tdehardwarebackend.cpp +++ b/kioslave/media/mediamanager/tdehardwarebackend.cpp @@ -0,0 +1,924 @@ +/* This file is part of the TDE Project + Copyright (c) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net> + + 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 "tdehardwarebackend.h" + +#include <tqfile.h> +#include <tqeventloop.h> +#include <tqstylesheet.h> + +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <kio/job.h> +#include <kprocess.h> +#include <kmimetype.h> +#include <kmountpoint.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <kprotocolinfo.h> + +#include "dialog.h" + +#define MOUNT_SUFFIX ( \ + (medium->isMounted() ? TQString("_mounted") : TQString("_unmounted")) + \ + (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypted" : "_encrypted") : "" ) \ + ) +#define MOUNT_ICON_SUFFIX ( \ + (medium->isMounted() ? TQString("_mount") : TQString("_unmount")) + \ + (medium->isEncrypted() ? (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt) ? "_decrypt" : "_encrypt") : "" ) \ + ) + +/* Constructor */ +TDEBackend::TDEBackend(MediaList &list, TQObject* parent) + : TQObject() + , BackendBase(list) + , m_decryptDialog(0) + , m_parent(parent) +{ + // Initialize the TDE device manager + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + // Connect device monitoring signals/slots + connect(hwdevices, TQT_SIGNAL(hardwareAdded(TDEGenericDevice*)), this, TQT_SLOT(AddDeviceHandler(TDEGenericDevice*))); + connect(hwdevices, TQT_SIGNAL(hardwareRemoved(TDEGenericDevice*)), this, TQT_SLOT(RemoveDeviceHandler(TDEGenericDevice*))); + connect(hwdevices, TQT_SIGNAL(hardwareUpdated(TDEGenericDevice*)), this, TQT_SLOT(ModifyDeviceHandler(TDEGenericDevice*))); + + // List devices at startup + ListDevices(); +} + +/* Destructor */ +TDEBackend::~TDEBackend() +{ + // Remove all media from the media list + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices(); + TDEGenericDevice *hwdevice; + for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { + if (hwdevice->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice); + RemoveDevice(sdevice); + } + } +} + +void TDEBackend::AddDeviceHandler(TDEGenericDevice *device) { + if (device->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device); + AddDevice(sdevice); + } +} + +void TDEBackend::RemoveDeviceHandler(TDEGenericDevice *device) { + if (device->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device); + RemoveDevice(sdevice); + } +} + +void TDEBackend::ModifyDeviceHandler(TDEGenericDevice *device) { + if (device->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device); + ModifyDevice(sdevice); + } +} + +// List devices (at startup) +bool TDEBackend::ListDevices() +{ + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices(); + TDEGenericDevice *hwdevice; + for ( hwdevice = hwlist.first(); hwdevice; hwdevice = hwlist.next() ) { + if (hwdevice->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice); + AddDevice(sdevice, false); + } + } + + return true; +} + +// Create a media instance for a new storage device +void TDEBackend::AddDevice(TDEStorageDevice * sdevice, bool allowNotification) +{ + // If the device is already listed, do not process it + // This should not happen, but who knows... + /** @todo : refresh properties instead ? */ + if (m_mediaList.findById(sdevice->uniqueID())) { + return; + } + + // Add volume block devices + if (sdevice->isDiskOfType(TDEDiskDeviceType::HDD)) { + /* We only list volumes that... + * - are encrypted with LUKS or + * - have a filesystem or + * - have an audio track + */ + if (!(sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) + && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::ContainsFilesystem)) + && !(sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) + && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) + ) { + // + } + else { + // Do not list the LUKS backend device if it has been unlocked elsewhere + if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) { + if (sdevice->slaveDevices().count() > 0) { + return; + } + } + + // Create medium + Medium* medium = new Medium(sdevice->uniqueID(), ""); + setVolumeProperties(medium); + + // Insert medium into list + m_mediaList.addMedium(medium, allowNotification); + } + } + + // Add CD drives + if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo)) + ) { + + // Create medium + Medium* medium = new Medium(sdevice->uniqueID(), ""); + setVolumeProperties(medium); + + // Insert medium into list + m_mediaList.addMedium(medium, allowNotification); + } + + // Floppy & zip drives + if ((sdevice->isDiskOfType(TDEDiskDeviceType::Floppy)) || + (sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) || + (sdevice->isDiskOfType(TDEDiskDeviceType::Jaz)) + ) { + if ((sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) && (!(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Inserted)))) { + allowNotification = false; + } + // Create medium + Medium* medium = new Medium(sdevice->uniqueID(), ""); + // If the storage has a volume, we ignore it + if ( setFloppyProperties(medium) ) + m_mediaList.addMedium(medium, allowNotification); + else + delete medium; + return; + } + + // PTP camera + if (sdevice->isDiskOfType(TDEDiskDeviceType::Camera)) { + // PTP cameras are handled by the "camera" kioslave + if (KProtocolInfo::isKnownProtocol( TQString("camera") ) ) + { + // Create medium + Medium* medium = new Medium(sdevice->uniqueID(), ""); + setCameraProperties(medium); + m_mediaList.addMedium(medium, allowNotification); + + return; + } + } +} + +void TDEBackend::RemoveDevice(TDEStorageDevice * sdevice) +{ + const Medium *medium = m_mediaList.findByClearUdi(sdevice->uniqueID()); + if (medium) { + ResetProperties(sdevice); + } + else { + m_mediaList.removeMedium(sdevice->uniqueID(), true); + } +} + +void TDEBackend::ModifyDevice(TDEStorageDevice * sdevice) +{ + bool allowNotification = true; + if (!sdevice->checkDiskStatus(TDEDiskDeviceStatus::Removable)) { // TODO Is this the only condition under which we would not want notification? + allowNotification = false; + } + ResetProperties(sdevice, allowNotification); +} + +void TDEBackend::ResetProperties(TDEStorageDevice * sdevice, bool allowNotification) +{ + Medium* m = new Medium(sdevice->uniqueID(), ""); + + // Keep these conditions in sync with ::AddDevice above, OR ELSE!!! + // BEGIN + + if (!(sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) + && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::ContainsFilesystem)) + && !(sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) + && !(sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) + ) { + } + else { + if (sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) { + if (sdevice->slaveDevices().count() > 0) { + // Do not list the LUKS backend device if it has been unlocked elsewhere + RemoveDevice(sdevice); + return; + } + } + setVolumeProperties(m); + } + + if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo)) + ) { + setVolumeProperties(m); + } + + // Floppy & zip drives + if ((sdevice->isDiskOfType(TDEDiskDeviceType::Floppy)) || + (sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) || + (sdevice->isDiskOfType(TDEDiskDeviceType::Jaz)) + ) { + setFloppyProperties(m); + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::Camera)) { + setCameraProperties(m); + } + + // END + + m_mediaList.changeMediumState(*m, allowNotification); + + delete m; +} + +void TDEBackend::setVolumeProperties(Medium* medium) +{ + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id()); + if (!sdevice) { + return; + } + + medium->setName(generateName(sdevice->deviceNode())); + if ((sdevice->isDiskOfType(TDEDiskDeviceType::LUKS)) || (sdevice->isDiskOfType(TDEDiskDeviceType::UnlockedCrypt))) { + medium->setEncrypted(true); + } + else { + medium->setEncrypted(false); + } + + // USAGE: mountableState(Device node, Mount point, Filesystem type, Mounted ?) + medium->mountableState(sdevice->deviceNode(), sdevice->mountPath(), sdevice->fileSystemName(), !sdevice->mountPath().isNull()); + + TQString diskLabel = sdevice->diskLabel(); + if (diskLabel.isNull()) { + diskLabel = i18n("%1 Removable Device").arg(sdevice->deviceFriendlySize()); + } + medium->setLabel(diskLabel); + + TQString mimeType; + + if ((sdevice->isDiskOfType(TDEDiskDeviceType::CDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo)) + || (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo)) + ) { + // This device is a CD drive of some sort + + // Default + mimeType = "media/cdrom" + MOUNT_SUFFIX; + + if (sdevice->isDiskOfType(TDEDiskDeviceType::CDROM)) { + mimeType = "media/cdrom" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankcd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::CDRW)) { + mimeType = "media/cdwriter" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankcd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDROM)) { + mimeType = "media/dvd" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankdvd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRAM)) { + mimeType = "media/dvd" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankdvd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDRW)) { + mimeType = "media/dvd" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankdvd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::BDROM)) { + mimeType = "media/bluray" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankbd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::BDRW)) { + mimeType = "media/bluray" + MOUNT_SUFFIX; + if (sdevice->checkDiskStatus(TDEDiskDeviceStatus::Blank)) { + mimeType = "media/blankbd" + MOUNT_SUFFIX; + medium->unmountableState(""); + } + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::CDAudio)) { + mimeType = "media/audiocd" + MOUNT_SUFFIX; + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::CDVideo)) { + mimeType = "media/vcd"; + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::DVDVideo)) { + mimeType = "media/dvdvideo"; + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::BDVideo)) { + mimeType = "media/bdvideo"; + } + + medium->setIconName(TQString::null); + } + else { + // This device is a hard or flash disk of some kind + + // Default + mimeType = "media/hdd" + MOUNT_SUFFIX; + + if (sdevice->isDiskOfType(TDEDiskDeviceType::USB)) { + mimeType = "media/removable" + MOUNT_SUFFIX; + medium->needMounting(); + + if (sdevice->isDiskOfType(TDEDiskDeviceType::CompactFlash)) { + medium->setIconName("compact_flash" + MOUNT_ICON_SUFFIX); + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::CompactFlash)) { + medium->setIconName("memory_stick" + MOUNT_ICON_SUFFIX); + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::CompactFlash)) { + medium->setIconName("smart_media" + MOUNT_ICON_SUFFIX); + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::CompactFlash)) { + medium->setIconName("sd_mmc" + MOUNT_ICON_SUFFIX); + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::MediaDevice)) { + medium->setIconName("ipod" + MOUNT_ICON_SUFFIX); + + if (sdevice->vendorModel().upper().contains("IPOD") && KProtocolInfo::isKnownProtocol( TQString("ipod") ) ) + { + medium->unmountableState( "ipod:/" ); + medium->mountableState(!sdevice->mountPath().isNull()); + } + } + if (sdevice->isDiskOfType(TDEDiskDeviceType::Tape)) { + medium->setIconName("magnetic_tape" + MOUNT_ICON_SUFFIX); + } + if (medium->isMounted() && TQFile::exists(medium->mountPoint() + "/dcim")) + { + mimeType = "media/camera" + MOUNT_SUFFIX; + } + } + } + + medium->setMimeType(mimeType); +} + +// Handle floppies and zip drives +bool TDEBackend::setFloppyProperties(Medium* medium) +{ + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id()); + if (!sdevice) { + return false; + } + + medium->setName(generateName(sdevice->deviceNode())); + medium->setLabel(i18n("Unknown Drive")); + + if (sdevice->isDiskOfType(TDEDiskDeviceType::Floppy)) { + if (sdevice->mountPath().isNull()) { + medium->setMimeType("media/floppy_unmounted"); + } + else { + medium->setMimeType("media/floppy_mounted" ); + } + medium->setLabel(i18n("Floppy Drive")); + } + + if (sdevice->isDiskOfType(TDEDiskDeviceType::Zip)) { + if (sdevice->mountPath().isNull()) { + medium->setMimeType("media/zip_unmounted"); + } + else { + medium->setMimeType("media/zip_mounted" ); + } + medium->setLabel(i18n("Zip Drive")); + } + + /** @todo Mimetype for JAZ drives ? */ + + medium->setIconName(TQString::null); + + return true; +} + +void TDEBackend::setCameraProperties(Medium* medium) +{ + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id()); + if (!sdevice) { + return; + } + + /** @todo find name */ + medium->setName("camera"); + + TQString device = "camera:/"; + + // FIXME + // I don't have a PTP camera to develop with + // Getting this working should be fairly easy; you just have to query udev for this information via the /sys/... path returned by sdevice->systemPath() +// if () { +// device.sprintf("camera://%s@[usb:%03d,%03d]/", <camera's libgphoto2 name>, <usb bus number>, <usb linux device number>); +// } + + /** @todo find the rest of this URL */ + medium->unmountableState(device); + medium->setMimeType("media/gphoto2camera"); + medium->setIconName(TQString::null); + + if (sdevice->vendorModel() != "") { + medium->setLabel(sdevice->vendorModel()); + } + else { + medium->setLabel(i18n("Camera")); + } +} + +TQStringList TDEBackend::mountoptions(const TQString &name) +{ + const Medium* medium = m_mediaList.findById(name); + if (!medium) { + return TQStringList(); // we know nothing about that device + } + if (!isInFstab(medium).isNull()) { + return TQStringList(); // device is listed in fstab, therefore is not handled by us + } + + TQString volume_udi = name; + if (medium->isEncrypted()) { + // if not decrypted yet then there are no mountoptions + return TQStringList(); + } + + // FIXME + // Just use the default mount options for now + return TQStringList(); +} + +bool TDEBackend::setMountoptions(const TQString &name, const TQStringList &options ) +{ + // FIXME + // Just use the default mount options for now + return true; +} + +void TDEBackend::slotPasswordReady() { + m_decryptionPassword = m_decryptDialog->getPassword(); + m_decryptPasswordValid = true; +} + +void TDEBackend::slotPasswordCancel() { + m_decryptionPassword = TQString::null; + m_decryptPasswordValid = true; +} + +TQString TDEBackend::mount(const Medium *medium) +{ + if (medium->isMounted()) { + return TQString(); // that was easy + } + + TQString mountPoint = isInFstab(medium); + if (!mountPoint.isNull()) + { + struct mount_job_data data; + data.completed = false; + data.medium = medium; + + KIO::Job *job = KIO::mount( false, 0, medium->deviceNode(), mountPoint ); + connect(job, TQT_SIGNAL( result (KIO::Job *)), TQT_SLOT( slotResult( KIO::Job *))); + mount_jobs[job] = &data; + // The caller expects the device to be mounted when the function + // completes. Thus block until the job completes. + while (!data.completed) { + kapp->eventLoop()->enterLoop(); + } + // Return the error message (if any) to the caller + return (data.error) ? data.errorMessage : TQString::null; + + } + + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id()); + if (!sdevice) { + return i18n("Internal error"); + } + + TQString optionString; + TQString diskLabel; + + TQMap<TQString,TQString> valids = MediaManagerUtils::splitOptions(mountoptions(medium->id())); + if (valids["ro"] == "true") { + optionString.append(" -r"); + } + + if (valids["atime"] != "true") { + optionString.append(" -A"); + } + + if (valids["utf8"] == "true") { + optionString.append(" -c utf8"); + } + + if (valids["sync"] == "true") { + optionString.append(" -s"); + } + + TQString mount_point = valids["mountpoint"]; + if (mount_point.startsWith("/media/")) { + mount_point = mount_point.mid(7); + } + + if (valids.contains("shortname")) { + diskLabel = TQString("shortname=%1").arg(valids["shortname"]); + } + + TQString qerror = i18n("Cannot mount encrypted drives!"); + + if (!medium->isEncrypted()) { + // normal volume + TQString mountMessages; + TQString mountedPath = sdevice->mountDevice(diskLabel, optionString, &mountMessages); + if (mountedPath.isNull()) { + qerror = i18n("<qt>Unable to mount this device.<p>Potential reasons include:<br>Improper device and/or user privilege level<br>Corrupt data on storage device"); + if (!mountMessages.isNull()) { + qerror.append(i18n("<p>Technical details:<br>").append(mountMessages)); + } + qerror.append("</qt>"); + } + else { + qerror = ""; + } + } + else { + TQString iconName = medium->iconName(); + if (iconName.isEmpty()) + { + TQString mime = medium->mimeType(); + iconName = KMimeType::mimeType(mime)->icon(mime, false); + } + + bool continue_trying_to_decrypt = true; + while (continue_trying_to_decrypt == true) { + m_decryptPasswordValid = false; + + m_decryptDialog = new Dialog(sdevice->deviceNode(), iconName); + m_decryptDialog->show(); + + connect(m_decryptDialog, TQT_SIGNAL (user1Clicked()), this, TQT_SLOT (slotPasswordReady())); + connect(m_decryptDialog, TQT_SIGNAL (cancelClicked()), this, TQT_SLOT (slotPasswordCancel())); + connect(this, TQT_SIGNAL (signalDecryptionPasswordError(TQString)), m_decryptDialog, TQT_SLOT (slotDialogError(TQString))); + + while (m_decryptPasswordValid == false) { + tqApp->processEvents(); + } + + m_decryptDialog->setEnabled(false); + + if (m_decryptionPassword.isNull()) { + delete m_decryptDialog; + return TQString("Decryption aborted"); + } + else { + // mount encrypted volume with password + int mountRetcode; + TQString mountMessages; + TQString mountedPath = sdevice->mountEncryptedDevice(m_decryptionPassword, diskLabel, optionString, &mountMessages, &mountRetcode); + if (mountedPath.isNull()) { + if (mountRetcode == 25600) { + // Probable LUKS failure + // Retry + m_decryptDialog->setEnabled(true); + continue_trying_to_decrypt = true; + } + else { + qerror = i18n("<qt>Unable to mount this device.<p>Potential reasons include:<br>Improper device and/or user privilege level<br>Corrupt data on storage device<br>Incorrect encryption password"); + if (!mountMessages.isNull()) { + qerror.append(i18n("<p>Technical details:<br>").append(mountMessages)); + } + qerror.append("</qt>"); + continue_trying_to_decrypt = false; + } + } + else { + qerror = ""; + continue_trying_to_decrypt = false; + } + + delete m_decryptDialog; + } + } + } + + // FIXME + // Handle encrypted devices + +// qerror = mount_priv(medium->id().latin1(), mount_point.utf8(), options, noptions, dbus_connection); +// } else { +// // see if we have a clear volume +// LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, medium->id().latin1()); +// if (halVolume) { +// char* clearUdi = libhal_volume_crypto_get_clear_volume_udi(m_halContext, halVolume); +// if (clearUdi != NULL) { +// qerror = mount_priv(clearUdi, mount_point.utf8(), options, noptions, dbus_connection); +// libhal_free_string(clearUdi); +// } +// libhal_volume_free(halVolume); +// } +// } + + if (!qerror.isEmpty()) { + return qerror; + } + + ResetProperties(sdevice); + + return TQString(); +} + +TQString TDEBackend::mount(const TQString &_udi) +{ + const Medium* medium = m_mediaList.findById(_udi); + if (!medium) + return i18n("No such medium: %1").arg(_udi); + + return mount(medium); +} + +TQString TDEBackend::unmount(const TQString &_udi) +{ + const Medium* medium = m_mediaList.findById(_udi); + + if ( !medium ) + return i18n("No such medium: %1").arg(_udi); + + if (!medium->isMounted()) + return TQString(); // that was easy + + TQString mountPoint = isInFstab(medium); + if (!mountPoint.isNull()) + { + struct mount_job_data data; + data.completed = false; + data.medium = medium; + + KIO::Job *job = KIO::unmount( medium->mountPoint(), false ); + connect(job, TQT_SIGNAL( result (KIO::Job *)), TQT_SLOT( slotResult( KIO::Job *))); + mount_jobs[job] = &data; + // The caller expects the device to be unmounted when the function + // completes. Thus block until the job completes. + while (!data.completed) { + kapp->eventLoop()->enterLoop(); + } + // Return the error message (if any) to the caller + return (data.error) ? data.errorMessage : TQString::null; + } + + TQString udi = TQString::null; + + TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); + + TDEStorageDevice * sdevice = hwdevices->findDiskByUID(medium->id()); + if (!sdevice) { + return i18n("Internal error"); + } + + TQString qerror; + TQString origqerror; + + TQString unmountMessages; + int unmountRetcode = 0; + if (!sdevice->unmountDevice(&unmountMessages, &unmountRetcode)) { + // Unmount failed! + qerror = "<qt>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and currently mounted at <b>%4</b> could not be unmounted. ").arg("system:/media/" + medium->name(), medium->deviceNode(), medium->prettyLabel(), medium->prettyBaseURL().pathOrURL()); + if (!unmountMessages.isNull()) { + qerror.append(i18n("<p>Technical details:<br>").append(unmountMessages)); + } + qerror.append("</qt>"); + } + else { + qerror = ""; + } + + if (unmountRetcode == 1280) { + // Failed as BUSY + TQString processesUsingDev = listUsingProcesses(medium); + if (!processesUsingDev.isNull()) { + if (KMessageBox::warningYesNo(0, i18n("<qt>The device <b>%1</b> (%2) named <b>'%3'</b> and currently mounted at <b>%4</b> can not be unmounted at this time.<p>%5<p><b>Would you like to forcibly terminate these processes?</b><br><i>All unsaved data would be lost</i>").arg("system:/media/" + medium->name()).arg(medium->deviceNode()).arg(medium->prettyLabel()).arg(medium->prettyBaseURL().pathOrURL()).arg(processesUsingDev)) == KMessageBox::Yes) { + killUsingProcesses(medium); + if (!sdevice->unmountDevice(&unmountMessages, &unmountRetcode)) { + // Unmount failed! + qerror = "<qt>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and currently mounted at <b>%4</b> could not be unmounted. ").arg("system:/media/" + medium->name(), medium->deviceNode(), medium->prettyLabel(), medium->prettyBaseURL().pathOrURL()); + if (!unmountMessages.isNull()) { + qerror.append(i18n("<p>Technical details:<br>").append(unmountMessages)); + } + qerror.append("</qt>"); + } + else { + qerror = ""; + } + } + } + } + + if (qerror != "") { + return qerror; + } + + ResetProperties(sdevice); + + return TQString(); +} + +TQString TDEBackend::isInFstab(const Medium *medium) +{ + KMountPoint::List fstab = KMountPoint::possibleMountPoints(KMountPoint::NeedMountOptions|KMountPoint::NeedRealDeviceName); + + KMountPoint::List::iterator it = fstab.begin(); + KMountPoint::List::iterator end = fstab.end(); + + for (; it!=end; ++it) + { + TQString reald = (*it)->realDeviceName(); + if ( reald.endsWith( "/" ) ) { + reald = reald.left( reald.length() - 1 ); + } + if ((*it)->mountedFrom() == medium->deviceNode() || ( !medium->deviceNode().isEmpty() && reald == medium->deviceNode() ) ) + { + TQStringList opts = (*it)->mountOptions(); + if (opts.contains("user") || opts.contains("users")) { + return (*it)->mountPoint(); + } + } + } + + return TQString::null; +} + +TQString TDEBackend::listUsingProcesses(const Medium* medium) +{ + TQString proclist, fullmsg; + TQString cmdline = TQString("/usr/bin/env fuser -vm %1 2>&1").arg(KProcess::quote(medium->mountPoint())); + FILE *fuser = popen(cmdline.latin1(), "r"); + + uint counter = 0; + if (fuser) { + proclist += "<pre>"; + TQTextIStream is(fuser); + TQString tmp; + while (!is.atEnd()) { + tmp = is.readLine(); + tmp = TQStyleSheet::escape(tmp) + "\n"; + + proclist += tmp; + if (counter++ > 10) { + proclist += "..."; + break; + } + } + proclist += "</pre>"; + (void)pclose( fuser ); + } + if (counter) { + fullmsg = i18n("Programs still using the device " + "have been detected. They are listed below. You have to " + "close them or change their working directory before " + "attempting to unmount the device again."); + fullmsg += "<br>" + proclist; + return fullmsg; + } + else { + return TQString::null; + } +} + +TQString TDEBackend::killUsingProcesses(const Medium* medium) +{ + TQString proclist, fullmsg; + TQString cmdline = TQString("/usr/bin/env fuser -vmk %1 2>&1").arg(KProcess::quote(medium->mountPoint())); + FILE *fuser = popen(cmdline.latin1(), "r"); + + uint counter = 0; + if (fuser) { + proclist += "<pre>"; + TQTextIStream is(fuser); + TQString tmp; + while (!is.atEnd()) { + tmp = is.readLine(); + tmp = TQStyleSheet::escape(tmp) + "\n"; + + proclist += tmp; + if (counter++ > 10) { + proclist += "..."; + break; + } + } + proclist += "</pre>"; + (void)pclose( fuser ); + } + if (counter) { + fullmsg = i18n("Programs that were still using the device " + "have been forcibly terminated. They are listed below."); + fullmsg += "<br>" + proclist; + return fullmsg; + } + else { + return TQString::null; + } +} + +TQString TDEBackend::generateName(const TQString &devNode) +{ + return KURL(devNode).fileName(); +} +#include "tdehardwarebackend.moc"
\ No newline at end of file diff --git a/kioslave/media/mediamanager/tdehardwarebackend.h b/kioslave/media/mediamanager/tdehardwarebackend.h index e69de29bb..40181b062 100644 --- a/kioslave/media/mediamanager/tdehardwarebackend.h +++ b/kioslave/media/mediamanager/tdehardwarebackend.h @@ -0,0 +1,165 @@ +/* This file is part of the TDE Project + Copyright (c) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net> + + 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. +*/ + +/** +* This is a media:/ backend for the builtin TDE hardware library +* +* @author Timothy Pearson <kb9vqf@pearsoncomputing.net> +* @short media:/ backend for the TDE hardware library +*/ + +#ifndef _TDEBACKEND_H_ +#define _TDEBACKEND_H_ + +#include "backendbase.h" + +#include <tqobject.h> +#include <tqstringlist.h> +#include <tqstring.h> + +#include <config.h> + +#include <tdehardwaredevices.h> + +namespace KIO { + class Job; +} + +class Dialog; + +class TDEBackend : public TQObject, public BackendBase +{ +Q_OBJECT + +public: + /** + * Constructor + */ + TDEBackend(MediaList &list, TQObject* parent); + + /** + * Destructor + */ + ~TDEBackend(); + + /** + * List all devices and append them to the media device list (called only once, at startup). + * + * @return true if succeded, false otherwise + */ + bool ListDevices(); + + TQStringList mountoptions(const TQString &id); + + bool setMountoptions(const TQString &id, const TQStringList &options); + + TQString mount(const TQString &id); + TQString mount(const Medium *medium); + TQString unmount(const TQString &id); +// TQString decrypt(const TQString &id, const TQString &password); +// TQString undecrypt(const TQString &id); + +private: + /** + * Append a device in the media list. This function will check if the device + * is worth listing. + * + * @param sdevice A pointer to a TDEStorageDevice object + * @param allowNotification Indicates if this event will be notified to the user + */ + void AddDevice(TDEStorageDevice * sdevice, bool allowNotification=true); + + /** + * Remove a device from the device list + * + * @param sdevice A pointer to a TDEStorageDevice object + */ + void RemoveDevice(TDEStorageDevice * sdevice); + + /** + * A device has changed, update it + * + * @param sdevice A pointer to a TDEStorageDevice object + */ + void ModifyDevice(TDEStorageDevice * sdevice); + +private slots: + void AddDeviceHandler(TDEGenericDevice* device); + void RemoveDeviceHandler(TDEGenericDevice* device); + void ModifyDeviceHandler(TDEGenericDevice* device); + + void slotPasswordReady(); + void slotPasswordCancel(); + +signals: + void signalDecryptionPasswordError(TQString); + +/* Set media properties */ +private: + /** + * Reset properties for the given medium + * + * @param sdevice A pointer to a TDEStorageDevice objec + */ + void ResetProperties(TDEStorageDevice * sdevice, bool allowNotification=false); + + /** + * Find the medium that is concerned with device udi + */ +// const char* findMediumUdiFromUdi(const char* udi); + + void setVolumeProperties(Medium* medium); + bool setFloppyProperties(Medium* medium); +// void setFloppyMountState( Medium* medium ); +// bool setFstabProperties(Medium* medium); + void setCameraProperties(Medium* medium); + TQString generateName(const TQString &devNode); + static TQString isInFstab(const Medium *medium); + static TQString listUsingProcesses(const Medium *medium); + static TQString killUsingProcesses(const Medium *medium); + + // Decryption + Dialog* m_decryptDialog; + TQString m_decryptionPassword; + bool m_decryptPasswordValid; + +/* TDE structures */ +private: + /** + * Object for the kded module + */ + TQObject* m_parent; + + /** + * Data structure for fstab mount/unmount jobs + */ + struct mount_job_data { + // [in] Medium, which is being mounted/unmounted by the job + const Medium* medium; + // [in,out] Should be set to true when the job completes + bool completed; + // [out] KIO::Error if an error occured during operation. Otherwise, 0 + int error; + // [out] Error message to be displayed to the user + TQString errorMessage; + }; + + TQMap<KIO::Job *, struct mount_job_data*> mount_jobs; +}; + +#endif /* _TDEBACKEND_H_ */ |