diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-12-11 20:21:27 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-12-11 20:21:27 +0000 |
commit | 10e41144596fc9ced40fc349d9ecd099b1c2ea19 (patch) | |
tree | 88ab04e475ff5a4cd889cb082f5760b6e0bf5e4e /kioslave | |
parent | 4aed2c8219774f5d797760606b8489a92ddc5163 (diff) | |
download | tdebase-10e41144596fc9ced40fc349d9ecd099b1c2ea19.tar.gz tdebase-10e41144596fc9ced40fc349d9ecd099b1c2ea19.zip |
Initial import of Trinity 3.5.11 to kdebase
Extends krandrtray, adds iccconfig kcontrol module, adds run dialog autocomplete and lots of bugfixes
Will need to check for commit warnings and repair as encountered
Also needs full compile test
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1061475 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kioslave')
50 files changed, 1326 insertions, 91 deletions
diff --git a/kioslave/fish/Makefile.am b/kioslave/fish/Makefile.am index 27308245b..444d037fb 100644 --- a/kioslave/fish/Makefile.am +++ b/kioslave/fish/Makefile.am @@ -4,8 +4,8 @@ INCLUDES = $(all_includes) AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) kio_fish_la_SOURCES = fish.cpp -kio_fish_la_LIBADD = $(LIB_KSYCOCA) #$(LIBUTIL) -kio_fish_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) +kio_fish_la_LIBADD = $(LIB_KSYCOCA) $(LIBUTIL) +kio_fish_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -lutil noinst_HEADERS = fishcode.h fish.h EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL README TODO FAQ fish.pl diff --git a/kioslave/man/kio_man.cpp b/kioslave/man/kio_man.cpp index 0511a165d..068287b7e 100644 --- a/kioslave/man/kio_man.cpp +++ b/kioslave/man/kio_man.cpp @@ -517,6 +517,11 @@ void MANProtocol::slotGetStdOutput(KProcess* /* p */, char *s, int len) myStdStream += QString::fromLocal8Bit(s, len); } +void MANProtocol::slotGetStdOutputUtf8(KProcess* /* p */, char *s, int len) +{ + myStdStream += QString::fromUtf8(s, len); +} + char *MANProtocol::readManPage(const char *_filename) { QCString filename = _filename; @@ -564,24 +569,20 @@ char *MANProtocol::readManPage(const char *_filename) } lastdir = filename.left(filename.findRev('/')); - QIODevice *fd= KFilterDev::deviceForFile(filename); - - if ( !fd || !fd->open(IO_ReadOnly)) - { - delete fd; - return 0; - } - QByteArray array(fd->readAll()); - kdDebug(7107) << "read " << array.size() << endl; - fd->close(); - delete fd; - - if (array.isEmpty()) - return 0; - - const int len = array.size(); + myStdStream = QString::null; + KProcess proc; + /* TODO: detect availability of 'man --recode' so that this can go + * upstream */ + proc << "man" << "--recode" << "UTF-8" << filename; + + QApplication::connect(&proc, SIGNAL(receivedStdout (KProcess *, char *, int)), + this, SLOT(slotGetStdOutputUtf8(KProcess *, char *, int))); + proc.start(KProcess::Block, KProcess::All); + + const QCString cstr=myStdStream.utf8(); + const int len = cstr.size()-1; buf = new char[len + 4]; - qmemmove(buf + 1, array.data(), len); + qmemmove(buf + 1, cstr.data(), len); buf[0]=buf[len]='\n'; // Start and end with a end of line buf[len+1]=buf[len+2]='\0'; // Two NUL characters at end } diff --git a/kioslave/man/kio_man.h b/kioslave/man/kio_man.h index f571082db..d1d924ce0 100644 --- a/kioslave/man/kio_man.h +++ b/kioslave/man/kio_man.h @@ -61,6 +61,7 @@ public: private slots: void slotGetStdOutput(KProcess*, char*, int); + void slotGetStdOutputUtf8(KProcess*, char*, int); private: void checkManPaths(); diff --git a/kioslave/man/man2html.cpp b/kioslave/man/man2html.cpp index 725fba36a..b502e8edc 100644 --- a/kioslave/man/man2html.cpp +++ b/kioslave/man/man2html.cpp @@ -705,17 +705,18 @@ static void add_links(char *c) } int i,j,nr; - char *f, *g,*h; + char *f, *h; + char *g; const int numtests=6; // Nmber of tests char *idtest[numtests]; // url, mailto, www, ftp, manpage, C header file bool ok; /* search for (section) */ nr=0; idtest[0]=strstr(c+1,"://"); - idtest[1]=strchr(c+1,'@'); + idtest[1]=(char*)strchr(c+1,'@'); idtest[2]=strstr(c,"www."); idtest[3]=strstr(c,"ftp."); - idtest[4]=strchr(c+1,'('); + idtest[4]=(char*)strchr(c+1,'('); idtest[5]=strstr(c+1,".h>"); for (i=0; i<numtests; ++i) nr += (idtest[i]!=NULL); while (nr) { @@ -770,7 +771,7 @@ static void add_links(char *c) case 4: /* manpage */ f=idtest[j]; /* check section */ - g=strchr(f,')'); + g=(char*)strchr(f,')'); // The character before f must alphanumeric, the end of a HTML tag or the end of a if (g!=NULL && f>c && (g-f)<12 && (isalnum(f[-1]) || f[-1]=='>' || ( f[-1] == ';' ) ) && isdigit(f[1]) && f[1]!='0' && ((g-f)<=2 || isalpha(f[2]))) @@ -936,10 +937,10 @@ static void add_links(char *c) } nr=0; if (idtest[0] && idtest[0]<=c) idtest[0]=strstr(c+1,"://"); - if (idtest[1] && idtest[1]<=c) idtest[1]=strchr(c+1,'@'); + if (idtest[1] && idtest[1]<=c) idtest[1]=(char*)strchr(c+1,'@'); if (idtest[2] && idtest[2]<c) idtest[2]=strstr(c,"www."); if (idtest[3] && idtest[3]<c) idtest[3]=strstr(c,"ftp."); - if (idtest[4] && idtest[4]<=c) idtest[4]=strchr(c+1,'('); + if (idtest[4] && idtest[4]<=c) idtest[4]=(char*)strchr(c+1,'('); if (idtest[5] && idtest[5]<=c) idtest[5]=strstr(c+1,".h>"); for (i=0; i<numtests; i++) nr += (idtest[i]!=NULL); } @@ -3714,8 +3715,8 @@ static char *scan_request(char *c) char* font[2] = { "B", "R" }; c+=j; if (*c=='\n') c++; - char *eol=strchr(c,'\n'); - char *semicolon=strchr(c,';'); + char *eol=(char*)strchr(c,'\n'); + char *semicolon=(char*)strchr(c,';'); if ((semicolon!=0) && (semicolon<eol)) *semicolon=' '; sl=fill_words(c, wordlist, &words, true, &c); @@ -4338,7 +4339,7 @@ static char *scan_request(char *c) case REQ_Bl: // mdoc(7) "Begin List" { char list_options[NULL_TERMINATED(MED_STR_MAX)]; - char *nl = strchr(c,'\n'); + char *nl = (char*)strchr(c,'\n'); c=c+j; if (dl_set[itemdepth]) /* These things can nest. */ @@ -4519,7 +4520,7 @@ static char *scan_request(char *c) case REQ_Bd: /* mdoc(7) */ { /* Seems like a kind of example/literal mode */ char bd_options[NULL_TERMINATED(MED_STR_MAX)]; - char *nl = strchr(c,'\n'); + char *nl = (char*)strchr(c,'\n'); c=c+j; if (nl) strlimitcpy(bd_options, c, nl - c, MED_STR_MAX); @@ -4877,8 +4878,8 @@ static char *scan_request(char *c) } else if (!mandoc_name_count) { - const char *nextbreak = strchr(c, '\n'); - const char *nextspace = strchr(c, ' '); + char *nextbreak = (char*)strchr(c, '\n'); + char *nextspace = (char*)strchr(c, ' '); if (nextspace < nextbreak) nextbreak = nextspace; diff --git a/kioslave/media/kfile-plugin/kfile_media.desktop b/kioslave/media/kfile-plugin/kfile_media.desktop index 474ab12b2..c29d590e3 100644 --- a/kioslave/media/kfile-plugin/kfile_media.desktop +++ b/kioslave/media/kfile-plugin/kfile_media.desktop @@ -72,4 +72,4 @@ Name[zh_CN]=介质信息 Name[zh_TW]=媒體資訊 ServiceTypes=KFilePlugin X-KDE-Library=kfile_media -MimeType=media/audiocd;media/hdd_mounted;media/blankcd;media/hdd_unmounted;media/blankdvd;media/cdrom_mounted;media/cdrom_unmounted;media/cdwriter_mounted;media/nfs_mounted;media/cdwriter_unmounted;media/nfs_unmounted;media/removable_mounted;media/dvd_mounted;media/removable_unmounted;media/dvd_unmounted;media/smb_mounted;media/dvdvideo;media/smb_unmounted;media/floppy5_mounted;media/svcd;media/floppy5_unmounted;media/vcd;media/floppy_mounted;media/zip_mounted;media/floppy_unmounted;media/zip_unmounted;media/gphoto2camera;media/camera_mounted;media/camera_unmounted +MimeType=media/audiocd;media/hdd_mounted;media/hdd_mounted_decrypted;media/blankcd;media/hdd_unmounted;media/hdd_unmounted_decrypted;media/blankdvd;media/cdrom_mounted;media/cdrom_mounted_decrypted;media/cdrom_unmounted;media/cdrom_unmounted_decrypted;media/cdwriter_mounted;media/cdwriter_mounted_decrypted;media/nfs_mounted;media/cdwriter_unmounted;media/cdwriter_unmounted_decrypted;media/nfs_unmounted;media/removable_mounted;media/removable_mounted_decrypted;media/dvd_mounted;media/dvd_mounted_decrypted;media/removable_unmounted;media/removable_unmounted_decrypted;media/dvd_unmounted;media/dvd_unmounted_decrypted;media/smb_mounted;media/dvdvideo;media/smb_unmounted;media/floppy5_mounted;media/svcd;media/floppy5_unmounted;media/vcd;media/floppy_mounted;media/zip_mounted;media/floppy_unmounted;media/zip_unmounted;media/gphoto2camera;media/camera_mounted;media/camera_unmounted diff --git a/kioslave/media/kfile-plugin/kfilemediaplugin.cpp b/kioslave/media/kfile-plugin/kfilemediaplugin.cpp index c91dbf21a..37aa7d61f 100644 --- a/kioslave/media/kfile-plugin/kfilemediaplugin.cpp +++ b/kioslave/media/kfile-plugin/kfilemediaplugin.cpp @@ -47,19 +47,29 @@ KFileMediaPlugin::KFileMediaPlugin(QObject *parent, const char *name, { addMimeType( "media/audiocd" ); addMimeType( "media/hdd_mounted" ); + addMimeType( "media/hdd_mounted_decrypted" ); addMimeType( "media/blankcd" ); addMimeType( "media/hdd_unmounted" ); + addMimeType( "media/hdd_unmounted_decrypted" ); addMimeType( "media/blankdvd" ); addMimeType( "media/cdrom_mounted" ); + addMimeType( "media/cdrom_mounted_decrypted" ); addMimeType( "media/cdrom_unmounted" ); + addMimeType( "media/cdrom_unmounted_decrypted" ); addMimeType( "media/cdwriter_mounted" ); + addMimeType( "media/cdwriter_mounted_decrypted" ); addMimeType( "media/nfs_mounted" ); addMimeType( "media/cdwriter_unmounted" ); + addMimeType( "media/cdwriter_unmounted_decrypted" ); addMimeType( "media/nfs_unmounted" ); addMimeType( "media/removable_mounted" ); + addMimeType( "media/removable_mounted_decrypted" ); addMimeType( "media/dvd_mounted" ); + addMimeType( "media/dvd_mounted_decrypted" ); addMimeType( "media/removable_unmounted" ); + addMimeType( "media/removable_unmounted_decrypted" ); addMimeType( "media/dvd_unmounted" ); + addMimeType( "media/dvd_unmounted_decrypted" ); addMimeType( "media/smb_mounted" ); addMimeType( "media/dvdvideo" ); addMimeType( "media/smb_unmounted" ); diff --git a/kioslave/media/libmediacommon/medium.cpp b/kioslave/media/libmediacommon/medium.cpp index 5767a6c9a..4cba32aeb 100644 --- a/kioslave/media/libmediacommon/medium.cpp +++ b/kioslave/media/libmediacommon/medium.cpp @@ -38,6 +38,8 @@ Medium::Medium(const QString &id, const QString &name) m_properties+= QString::null; /* BASE_URL */ m_properties+= QString::null; /* MIME_TYPE */ m_properties+= QString::null; /* ICON_NAME */ + m_properties+= "false"; /* ENCRYPTED */ + m_properties+= QString::null; /* CLEAR_DEVICE_UDI */ loadUserLabel(); @@ -59,6 +61,8 @@ Medium::Medium() m_properties+= QString::null; /* BASE_URL */ m_properties+= QString::null; /* MIME_TYPE */ m_properties+= QString::null; /* ICON_NAME */ + m_properties+= QString::null; /* ENCRYPTED */ + m_properties+= QString::null; /* CLEAR_DEVICE_UDI */ m_halmounted = false; } @@ -82,6 +86,8 @@ const Medium Medium::create(const QStringList &properties) m.m_properties[BASE_URL] = properties[BASE_URL]; m.m_properties[MIME_TYPE] = properties[MIME_TYPE]; m.m_properties[ICON_NAME] = properties[ICON_NAME]; + m.m_properties[ENCRYPTED] = properties[ENCRYPTED]; + m.m_properties[CLEAR_DEVICE_UDI] = properties[CLEAR_DEVICE_UDI]; } return m; @@ -123,6 +129,11 @@ void Medium::setLabel(const QString &label) m_properties[LABEL] = label; } +void Medium::setEncrypted(bool state) +{ + m_properties[ENCRYPTED] = ( state ? "true" : "false" ); +} + void Medium::setUserLabel(const QString &label) { KConfig cfg("mediamanagerrc"); @@ -185,6 +196,19 @@ void Medium::mountableState(const QString &deviceNode, m_properties[MOUNTED] = ( mounted ? "true" : "false" ); } +void Medium::mountableState(const QString &deviceNode, + const QString &clearDeviceUdi, + const QString &mountPoint, + const QString &fsType, bool mounted) +{ + m_properties[MOUNTABLE] = "true"; + m_properties[DEVICE_NODE] = deviceNode; + m_properties[CLEAR_DEVICE_UDI] = clearDeviceUdi; + m_properties[MOUNT_POINT] = mountPoint; + m_properties[FS_TYPE] = fsType; + m_properties[MOUNTED] = ( mounted ? "true" : "false" ); +} + void Medium::unmountableState(const QString &baseURL) { m_properties[MOUNTABLE] = "false"; @@ -206,6 +230,11 @@ bool Medium::needMounting() const return isMountable() && !isMounted(); } +bool Medium::needDecryption() const +{ + return isEncrypted() && clearDeviceUdi().isEmpty(); +} + KURL Medium::prettyBaseURL() const { if ( !baseURL().isEmpty() ) diff --git a/kioslave/media/libmediacommon/medium.h b/kioslave/media/libmediacommon/medium.h index f94545e8e..543bdf596 100644 --- a/kioslave/media/libmediacommon/medium.h +++ b/kioslave/media/libmediacommon/medium.h @@ -41,7 +41,9 @@ public: static const uint BASE_URL = 9; static const uint MIME_TYPE = 10; static const uint ICON_NAME = 11; - static const uint PROPERTIES_COUNT = 12; + static const uint ENCRYPTED = 12; + static const uint CLEAR_DEVICE_UDI = 13; + static const uint PROPERTIES_COUNT = 14; static const QString SEPARATOR; Medium(const QString &id, const QString &name); @@ -62,19 +64,27 @@ public: QString baseURL() const { return m_properties[BASE_URL]; } QString mimeType() const { return m_properties[MIME_TYPE]; } QString iconName() const { return m_properties[ICON_NAME]; } + bool isEncrypted() const { return m_properties[ENCRYPTED]=="true"; }; + QString clearDeviceUdi() const { return m_properties[CLEAR_DEVICE_UDI]; }; bool needMounting() const; + bool needDecryption() const; KURL prettyBaseURL() const; QString prettyLabel() const; void setName(const QString &name); void setLabel(const QString &label); void setUserLabel(const QString &label); + void setEncrypted(bool state); bool mountableState(bool mounted); void mountableState(const QString &deviceNode, const QString &mountPoint, const QString &fsType, bool mounted); + void mountableState(const QString &deviceNode, + const QString &clearDeviceUdi, + const QString &mountPoint, + const QString &fsType, bool mounted); void unmountableState(const QString &baseURL = QString::null); void setMimeType(const QString &mimeType); diff --git a/kioslave/media/libmediacommon/notifieropenaction.cpp b/kioslave/media/libmediacommon/notifieropenaction.cpp index 82db14b97..2cf664cc6 100644 --- a/kioslave/media/libmediacommon/notifieropenaction.cpp +++ b/kioslave/media/libmediacommon/notifieropenaction.cpp @@ -40,6 +40,6 @@ void NotifierOpenAction::execute(KFileItem &medium) bool NotifierOpenAction::supportsMimetype( const QString &mimetype ) const { - return !mimetype.contains( "blank" ); + return !mimetype.contains( "blank" ) && !mimetype.contains( "encrypted" ); } diff --git a/kioslave/media/libmediacommon/notifiersettings.cpp b/kioslave/media/libmediacommon/notifiersettings.cpp index c7ad616a5..c7ba40e85 100644 --- a/kioslave/media/libmediacommon/notifiersettings.cpp +++ b/kioslave/media/libmediacommon/notifiersettings.cpp @@ -32,16 +32,28 @@ NotifierSettings::NotifierSettings() { m_supportedMimetypes.append( "media/removable_unmounted" ); + m_supportedMimetypes.append( "media/removable_unmounted_encrypted" ); + m_supportedMimetypes.append( "media/removable_unmounted_decrypted" ); m_supportedMimetypes.append( "media/removable_mounted" ); + m_supportedMimetypes.append( "media/removable_mounted_decrypted" ); m_supportedMimetypes.append( "media/camera_unmounted" ); m_supportedMimetypes.append( "media/camera_mounted" ); m_supportedMimetypes.append( "media/gphoto2camera" ); m_supportedMimetypes.append( "media/cdrom_unmounted" ); + m_supportedMimetypes.append( "media/cdrom_unmounted_encrypted" ); + m_supportedMimetypes.append( "media/cdrom_unmounted_decrypted" ); m_supportedMimetypes.append( "media/cdrom_mounted" ); + m_supportedMimetypes.append( "media/cdrom_mounted_decrypted" ); m_supportedMimetypes.append( "media/dvd_unmounted" ); + m_supportedMimetypes.append( "media/dvd_unmounted_encrypted" ); + m_supportedMimetypes.append( "media/dvd_unmounted_decrypted" ); m_supportedMimetypes.append( "media/dvd_mounted" ); + m_supportedMimetypes.append( "media/dvd_mounted_decrypted" ); m_supportedMimetypes.append( "media/cdwriter_unmounted" ); + m_supportedMimetypes.append( "media/cdwriter_unmounted_encrypted" ); + m_supportedMimetypes.append( "media/cdwriter_unmounted_decrypted" ); m_supportedMimetypes.append( "media/cdwriter_mounted" ); + m_supportedMimetypes.append( "media/cdwriter_mounted_decrypted" ); m_supportedMimetypes.append( "media/blankcd" ); m_supportedMimetypes.append( "media/blankdvd" ); m_supportedMimetypes.append( "media/audiocd" ); diff --git a/kioslave/media/mediaimpl.cpp b/kioslave/media/mediaimpl.cpp index 741227cdb..516bcdb01 100644 --- a/kioslave/media/mediaimpl.cpp +++ b/kioslave/media/mediaimpl.cpp @@ -226,6 +226,13 @@ bool MediaImpl::ensureMediumMounted(Medium &medium) m_lastErrorMessage = i18n("No such medium."); return false; } + + if ( medium.isEncrypted() && medium.clearDeviceUdi().isEmpty() ) + { + m_lastErrorCode = KIO::ERR_COULD_NOT_MOUNT; + m_lastErrorMessage = i18n("The drive is encrypted."); + return false; + } if ( medium.needMounting() ) { diff --git a/kioslave/media/mediamanager/halbackend.cpp b/kioslave/media/mediamanager/halbackend.cpp index 65c796605..4d6d9b19d 100644 --- a/kioslave/media/mediamanager/halbackend.cpp +++ b/kioslave/media/mediamanager/halbackend.cpp @@ -20,8 +20,10 @@ #include "linuxcdpolling.h" #include <stdlib.h> +#include <locale.h> #include <kapplication.h> +#include <kmessagebox.h> #include <qeventloop.h> #include <qfile.h> #include <klocale.h> @@ -33,9 +35,17 @@ #include <kmountpoint.h> #include <kmessagebox.h> #include <kio/job.h> +#include <kstandarddirs.h> +#include <kprocess.h> -#define MOUNT_SUFFIX (libhal_volume_is_mounted(halVolume) ? QString("_mounted") : QString("_unmounted")) -#define MOUNT_ICON_SUFFIX (libhal_volume_is_mounted(halVolume) ? QString("_mount") : QString("_unmount")) +#define MOUNT_SUFFIX ( \ + (medium->isMounted() ? QString("_mounted") : QString("_unmounted")) + \ + (medium->isEncrypted() ? (halClearVolume ? "_decrypted" : "_encrypted") : "" ) \ + ) +#define MOUNT_ICON_SUFFIX ( \ + (medium->isMounted() ? QString("_mount") : QString("_unmount")) + \ + (medium->isEncrypted() ? (halClearVolume ? "_decrypt" : "_encrypt") : "" ) \ + ) /* Static instance of this class, for static HAL callbacks */ static HALBackend* s_HALBackend; @@ -211,8 +221,15 @@ void HALBackend::AddDevice(const char *udi, bool allowNotification) /* Add volume block devices */ if (libhal_device_query_capability(m_halContext, udi, "volume", NULL)) { - /* We only list volume that have a filesystem or volume that have an audio track*/ - if ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") != "filesystem" && + /* We only list volumes that... + * - are encrypted with LUKS or + * - have a filesystem or + * - have an audio track + */ + if ( ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") != "crypto" || + libhal_device_get_property_QString(m_halContext, udi, "volume.fstype") != "crypto_LUKS" + ) && + libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") != "filesystem" && !libhal_device_get_property_bool(m_halContext, udi, "volume.disc.has_audio", NULL) && !libhal_device_get_property_bool(m_halContext, udi, "volume.disc.is_blank", NULL) ) return; @@ -232,6 +249,21 @@ void HALBackend::AddDevice(const char *udi, bool allowNotification) /** @todo check exclusion list **/ + /* Special handling for clear crypto volumes */ + LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, udi); + if (!halVolume) + return; + const char* backingVolumeUdi = libhal_volume_crypto_get_backing_volume_udi(halVolume); + if ( backingVolumeUdi != NULL ) + { + /* The crypto drive was unlocked and may now be mounted... */ + kdDebug(1219) << "HALBackend::AddDevice : ClearVolume appeared for " << backingVolumeUdi << endl; + ResetProperties(backingVolumeUdi, allowNotification); + libhal_volume_free(halVolume); + return; + } + libhal_volume_free(halVolume); + /* Create medium */ Medium* medium = new Medium(udi, ""); setVolumeProperties(medium); @@ -247,6 +279,11 @@ void HALBackend::AddDevice(const char *udi, bool allowNotification) return; } } + + // instert medium into list + m_mediaList.addMedium(medium, allowNotification); + + // finally check for automount QMap<QString,QString> options = MediaManagerUtils::splitOptions(mountoptions(udi)); kdDebug() << "automount " << options["automount"] << endl; if (options["automount"] == "true" && allowNotification ) { @@ -254,7 +291,6 @@ void HALBackend::AddDevice(const char *udi, bool allowNotification) if (!error.isEmpty()) kdDebug() << "error " << error << endl; } - m_mediaList.addMedium(medium, allowNotification); return; } @@ -295,11 +331,18 @@ void HALBackend::AddDevice(const char *udi, bool allowNotification) void HALBackend::RemoveDevice(const char *udi) { - m_mediaList.removeMedium(udi, true); + const Medium *medium = m_mediaList.findByClearUdi(udi); + if (medium) { + ResetProperties(medium->id().ascii()); + } else { + m_mediaList.removeMedium(udi, true); + } } void HALBackend::ModifyDevice(const char *udi, const char* key) { + kdDebug(1219) << "HALBackend::ModifyDevice for '" << udi << "' on '" << key << "'\n"; + const char* mediumUdi = findMediumUdiFromUdi(udi); if (!mediumUdi) return; @@ -381,6 +424,18 @@ const char* HALBackend::findMediumUdiFromUdi(const char* udi) if (libhal_device_property_exists(m_halContext, udi, "info.capabilities", NULL)) if (libhal_device_query_capability(m_halContext, udi, "volume", NULL)) { + /* check if this belongs to an encrypted volume */ + LibHalVolume* halVolume = libhal_volume_from_udi(m_halContext, udi); + if (!halVolume) return NULL; + const char* backingUdi = libhal_volume_crypto_get_backing_volume_udi(halVolume); + if (backingUdi != NULL) { + const char* result = findMediumUdiFromUdi(backingUdi); + libhal_volume_free(halVolume); + return result; + } + libhal_volume_free(halVolume); + + /* this is a volume whose drive is registered */ QString driveUdi = libhal_device_get_property_QString(m_halContext, udi, "block.storage_device"); return findMediumUdiFromUdi(driveUdi.ascii()); } @@ -445,11 +500,47 @@ void HALBackend::setVolumeProperties(Medium* medium) medium->setName( generateName(libhal_volume_get_device_file(halVolume)) ); - medium->mountableState( - libhal_volume_get_device_file(halVolume), /* Device node */ - libhal_volume_get_mount_point(halVolume), /* Mount point */ - libhal_volume_get_fstype(halVolume), /* Filesystem type */ - libhal_volume_is_mounted(halVolume) ); /* Mounted ? */ + LibHalVolume* halClearVolume = NULL; + if ( libhal_device_get_property_QString(m_halContext, udi, "volume.fsusage") == "crypto" ) + { + kdDebug(1219) << "HALBackend::setVolumeProperties : crypto volume" << endl; + + medium->setEncrypted(true); + char* clearUdi = libhal_volume_crypto_get_clear_volume_udi(m_halContext, halVolume); + QString clearUdiString; + if (clearUdi != NULL) { + kdDebug(1219) << "HALBackend::setVolumeProperties : crypto clear volume avail - " << clearUdi << endl; + halClearVolume = libhal_volume_from_udi(m_halContext, clearUdi); + // ignore if halClearVolume is NULL -> just not decrypted in this case + clearUdiString = clearUdi; + libhal_free_string(clearUdi); + } + + if (halClearVolume) + medium->mountableState( + libhal_volume_get_device_file(halVolume), /* Device node */ + clearUdiString, + libhal_volume_get_mount_point(halClearVolume), /* Mount point */ + libhal_volume_get_fstype(halClearVolume), /* Filesystem type */ + libhal_volume_is_mounted(halClearVolume) ); /* Mounted ? */ + else + medium->mountableState( + libhal_volume_get_device_file(halVolume), /* Device node */ + QString::null, + QString::null, /* Mount point */ + QString::null, /* Filesystem type */ + false ); /* Mounted ? */ + } + else + { + kdDebug(1219) << "HALBackend::setVolumeProperties : normal volume" << endl; + medium->mountableState( + libhal_volume_get_device_file(halVolume), /* Device node */ + libhal_volume_get_mount_point(halVolume), /* Mount point */ + libhal_volume_get_fstype(halVolume), /* Filesystem type */ + libhal_volume_is_mounted(halVolume) ); /* Mounted ? */ + } + char* name = libhal_volume_policy_compute_display_name(halDrive, halVolume, m_halStoragePolicy); QString volume_name = QString::fromUtf8(name); @@ -777,13 +868,35 @@ void HALBackend::hal_device_condition(LibHalContext *ctx, const char *udi, QStringList HALBackend::mountoptions(const QString &name) { const Medium* medium = m_mediaList.findById(name); - if (medium && !isInFstab(medium).isNull()) + if (!medium) + return QStringList(); // we don't know about that one + if (!isInFstab(medium).isNull()) return QStringList(); // not handled by HAL - fstab entry + QString volume_udi = name; + if (medium->isEncrypted()) { + // 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) { + volume_udi = clearUdi; + libhal_free_string(clearUdi); + } else { + // if not decrypted yet then no mountoptions + return QStringList(); + } + libhal_volume_free(halVolume); + } else { + // strange... + return QStringList(); + } + } + KConfig config("mediamanagerrc"); config.setGroup(name); - char ** array = libhal_device_get_property_strlist(m_halContext, name.latin1(), "volume.mount.valid_options", NULL); + char ** array = libhal_device_get_property_strlist(m_halContext, volume_udi.latin1(), "volume.mount.valid_options", NULL); QMap<QString,bool> valids; for (int index = 0; array && array[index]; ++index) { @@ -797,11 +910,11 @@ QStringList HALBackend::mountoptions(const QString &name) QStringList result; QString tmp; - QString fstype = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.fstype"); + QString fstype = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.fstype"); if (fstype.isNull()) - fstype = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.policy.mount_filesystem"); + fstype = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.policy.mount_filesystem"); - QString drive_udi = libhal_device_get_property_QString(m_halContext, name.latin1(), "block.storage_device"); + QString drive_udi = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "block.storage_device"); bool removable = false; if ( !drive_udi.isNull() ) @@ -812,11 +925,11 @@ QStringList HALBackend::mountoptions(const QString &name) bool value = config.readBoolEntry("automount", false); config.setGroup(name); - if (libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_blank", NULL) - || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_vcd", NULL) - || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_svcd", NULL) - || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_videodvd", NULL) - || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.has_audio", NULL)) + if (libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_blank", NULL) + || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_vcd", NULL) + || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_svcd", NULL) + || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.is_videodvd", NULL) + || libhal_device_get_property_bool(m_halContext, volume_udi.latin1(), "volume.disc.has_audio", NULL)) value = false; result << QString("automount=%1").arg(value ? "true" : "false"); @@ -898,9 +1011,9 @@ QStringList HALBackend::mountoptions(const QString &name) result << tmp; } - QString mount_point = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.mount_point"); + QString mount_point = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.mount_point"); if (mount_point.isEmpty()) - mount_point = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.policy.desired_mount_point"); + mount_point = libhal_device_get_property_QString(m_halContext, volume_udi.latin1(), "volume.policy.desired_mount_point"); mount_point = config.readEntry("mountpoint", mount_point); @@ -958,6 +1071,120 @@ bool HALBackend::setMountoptions(const QString &name, const QStringList &options return true; } +QString startKdeSudoProcess(const QString& kdesudoPath, const QString& command, + const QString& dialogCaption, const QString& dialogComment) +{ + KProcess kdesudoProcess; + + kdesudoProcess << kdesudoPath + << "-d" + << "--noignorebutton" + << "--caption" << dialogCaption + << "--comment" << dialogComment + << "-c" << command; + + // @todo handle kdesudo output + kdesudoProcess.start(KProcess::Block); + + return QString(); +} + +QString startKdeSuProcess(const QString& kdesuPath, const QString& command, + const QString& dialogCaption) +{ + KProcess kdesuProcess; + + kdesuProcess << kdesuPath + << "-d" + << "--noignorebutton" + << "--caption" << dialogCaption + << "-c" << command; + + // @todo handle kdesu output + kdesuProcess.start(KProcess::Block); + + return QString(); +} + +QString startPrivilegedProcess(const QString& command, const QString& dialogCaption, const QString& dialogComment) +{ + QString error; + + QString kdesudoPath = KStandardDirs::findExe("kdesudo"); + + if (!kdesudoPath.isEmpty()) + error = startKdeSudoProcess(kdesudoPath, command, dialogCaption, dialogComment); + else { + QString kdesuPath = KStandardDirs::findExe("kdesu"); + + if (!kdesuPath.isEmpty()) + error = startKdeSuProcess(kdesuPath, command, dialogCaption); + } + + return error; +} + +QString privilegedMount(const char* udi, const char* mountPoint, const char** options, int numberOfOptions) +{ + QString error; + + kdDebug() << "run privileged mount for " << udi << endl; + + QString dbusSendPath = KStandardDirs::findExe("dbus-send"); + + // @todo return error message + if (dbusSendPath.isEmpty()) + return QString(); + + QString mountOptions; + QTextOStream optionsStream(&mountOptions); + for (int optionIndex = 0; optionIndex < numberOfOptions; optionIndex++) { + optionsStream << options[optionIndex]; + if (optionIndex < numberOfOptions - 1) + optionsStream << ","; + } + + QString command; + QTextOStream(&command) << dbusSendPath + << " --system --print-reply --dest=org.freedesktop.Hal " << udi + << " org.freedesktop.Hal.Device.Volume.Mount string:" << mountPoint + << " string: array:string:" << mountOptions; + + kdDebug() << "command: " << command << endl; + + error = startPrivilegedProcess(command, + i18n("Authenticate"), + i18n("<big><b>System policy prevents mounting internal media</b></big><br/>Authentication is required to perform this action. Please enter your password to verify.")); + + return error; +} + +QString privilegedUnmount(const char* udi) +{ + QString error; + + kdDebug() << "run privileged unmount for " << udi << endl; + + QString dbusSendPath = KStandardDirs::findExe("dbus-send"); + + // @todo return error message + if (dbusSendPath.isEmpty()) + return QString(); + + QString command; + QTextOStream(&command) << dbusSendPath + << " --system --print-reply --dest=org.freedesktop.Hal " << udi + << " org.freedesktop.Hal.Device.Volume.Unmount array:string:force"; + + kdDebug() << "command: " << command << endl; + + error = startPrivilegedProcess(command, + i18n("Authenticate"), + i18n("<big><b>System policy prevents unmounting media mounted by other users</b></big><br/>Authentication is required to perform this action. Please enter your password to verify.")); + + return error; +} + static QString mount_priv(const char *udi, const char *mount_point, const char **poptions, int noptions, DBusConnection *dbus_connection) { @@ -992,6 +1219,8 @@ static QString mount_priv(const char *udi, const char *mount_point, const char * qerror = i18n("Invalid filesystem type"); else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied")) qerror = i18n("Permissions denied"); + else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy")) + qerror = privilegedMount(udi, mount_point, poptions, noptions); else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.AlreadyMounted")) qerror = i18n("Device is already mounted."); else if ( !strcmp(error.name, "org.freedesktop.Hal.Device.Volume.InvalidMountpoint") && strlen(mount_point)) { @@ -1050,6 +1279,41 @@ QString HALBackend::listUsingProcesses(const Medium* medium) } } +QString HALBackend::killUsingProcesses(const Medium* medium) +{ + QString proclist, fullmsg; + QString cmdline = QString("/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>"; + QTextIStream is(fuser); + QString tmp; + while (!is.atEnd()) { + tmp = is.readLine(); + tmp = QStyleSheet::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 QString::null; + } +} + void HALBackend::slotResult(KIO::Job *job) { kdDebug() << "slotResult " << mount_jobs[job] << endl; @@ -1148,7 +1412,7 @@ QString HALBackend::mount(const Medium *medium) if (valids["flush"] == "true") soptions << "flush"; - if (valids["uid"] == "true") + if ((valids["uid"] == "true") && (medium->fsType() != "ntfs")) { soptions << QString("uid=%1").arg(getuid()); } @@ -1168,6 +1432,13 @@ QString HALBackend::mount(const Medium *medium) if (valids["sync"] == "true") soptions << "sync"; + if (medium->fsType() == "ntfs") { + QString fsLocale("locale="); + fsLocale += setlocale(LC_ALL, ""); + + soptions << fsLocale; + } + QString mount_point = valids["mountpoint"]; if (mount_point.startsWith("/media/")) mount_point = mount_point.mid(7); @@ -1199,7 +1470,24 @@ QString HALBackend::mount(const Medium *medium) options[noptions] = (*it).latin1(); options[noptions] = NULL; - QString qerror = mount_priv(medium->id().latin1(), mount_point.utf8(), options, noptions, dbus_connection); + QString qerror = i18n("Cannot mount encrypted drives!"); + + if (!medium->isEncrypted()) { + // normal volume + 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()) { kdError() << "mounting " << medium->id() << " returned " << qerror << endl; return qerror; @@ -1266,8 +1554,26 @@ QString HALBackend::unmount(const QString &_udi) DBusMessage *dmesg, *reply; DBusError error; const char *options[2]; + QString udi = QString::null; + + if (!medium->isEncrypted()) { + // normal volume + udi = medium->id(); + } 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); + udi = clearUdi; + libhal_free_string(clearUdi); + libhal_volume_free(halVolume); + } + } + if (udi.isNull()) { + kdDebug() << "unmount failed: no udi" << endl; + return i18n("Internal Error"); + } - const char *udi = medium->id().latin1(); kdDebug() << "unmounting " << udi << "..." << endl; dbus_error_init(&error); @@ -1278,7 +1584,7 @@ QString HALBackend::unmount(const QString &_udi) return false; } - if (!(dmesg = dbus_message_new_method_call ("org.freedesktop.Hal", udi, + if (!(dmesg = dbus_message_new_method_call ("org.freedesktop.Hal", udi.latin1(), "org.freedesktop.Hal.Device.Volume", "Unmount"))) { kdDebug() << "unmount failed for " << udi << ": could not create dbus message\n"; @@ -1296,11 +1602,25 @@ QString HALBackend::unmount(const QString &_udi) return i18n("Internal Error"); } + char thisunmounthasfailed = 0; dbus_error_init (&error); if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, dmesg, -1, &error))) { - QString qerror, reason; + thisunmounthasfailed = 1; + QString qerror, reason, origqerror; + if (!strcmp(error.name, "org.freedesktop.Hal.Device.PermissionDeniedByPolicy")) { + qerror = privilegedUnmount(udi.latin1()); + + if (qerror.isEmpty()) { + dbus_message_unref(dmesg); + dbus_error_free(&error); + return QString(); + } + + // @todo handle unmount error message + } + kdDebug() << "unmount failed for " << udi << ": " << error.name << " " << error.message << endl; qerror = "<qt>"; qerror += "<p>" + i18n("Unfortunately, the device <b>%1</b> (%2) named <b>'%3'</b> and " @@ -1312,6 +1632,7 @@ QString HALBackend::unmount(const QString &_udi) qerror += "<p>" + i18n("Unmounting failed due to the following error:") + "</p>"; if (!strcmp(error.name, "org.freedesktop.Hal.Device.Volume.Busy")) { reason = i18n("Device is Busy:"); + thisunmounthasfailed = 2; } else if (!strcmp(error.name, "org.freedesktop.Hal.Device.Volume.NotMounted")) { // this is faking. The error is that the device wasn't mounted by hal (but by the system) reason = i18n("Permissions denied"); @@ -1319,16 +1640,29 @@ QString HALBackend::unmount(const QString &_udi) reason = error.message; } qerror += "<p><b>" + reason + "</b></p>"; + origqerror = qerror; // Include list of processes (if any) using the device in the error message reason = listUsingProcesses(medium); if (!reason.isEmpty()) { qerror += reason; + if (thisunmounthasfailed == 2) { // Failed as BUSY + if (KMessageBox::warningYesNo(0, i18n("%1<p><b>Would you like to forcibly terminate these processes?</b><br><i>All unsaved data would be lost</i>").arg(qerror)) == KMessageBox::Yes) { + qerror = origqerror; + reason = killUsingProcesses(medium); + qerror = HALBackend::unmount(udi); + if (qerror.isNull()) { + thisunmounthasfailed = 0; + } + } + } } - dbus_message_unref (dmesg); - dbus_error_free (&error); - return qerror; + if (thisunmounthasfailed != 0) { + dbus_message_unref (dmesg); + dbus_error_free (&error); + return qerror; + } } kdDebug() << "unmount queued for " << udi << endl; @@ -1337,8 +1671,117 @@ QString HALBackend::unmount(const QString &_udi) dbus_message_unref (reply); medium->setHalMounted(false); + ResetProperties(medium->id().latin1()); + + while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ; + + return QString(); +} + +QString HALBackend::decrypt(const QString &_udi, const QString &password) +{ + const Medium* medium = m_mediaList.findById(_udi); + if (!medium) + return i18n("No such medium: %1").arg(_udi); + + if (!medium->isEncrypted() || !medium->clearDeviceUdi().isNull()) + return QString(); + + const char *udi = medium->id().latin1(); + DBusMessage *msg = NULL; + DBusMessage *reply = NULL; + DBusError error; + + kdDebug() << "Setting up " << udi << " for crypto\n" <<endl; + + msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi, + "org.freedesktop.Hal.Device.Volume.Crypto", + "Setup"); + if (msg == NULL) { + kdDebug() << "decrypt failed for " << udi << ": could not create dbus message\n"; + return i18n("Internal Error"); + } + + QCString pwdUtf8 = password.utf8(); + const char *pwd_utf8 = pwdUtf8; + if (!dbus_message_append_args (msg, DBUS_TYPE_STRING, &pwd_utf8, DBUS_TYPE_INVALID)) { + kdDebug() << "decrypt failed for " << udi << ": could not append args to dbus message\n"; + dbus_message_unref (msg); + return i18n("Internal Error"); + } + + dbus_error_init (&error); + if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error)) || + dbus_error_is_set (&error)) + { + QString qerror = i18n("Internal Error"); + kdDebug() << "decrypt failed for " << udi << ": " << error.name << " " << error.message << endl; + if (strcmp (error.name, "org.freedesktop.Hal.Device.Volume.Crypto.SetupPasswordError") == 0) { + qerror = i18n("Wrong password"); + } + dbus_error_free (&error); + dbus_message_unref (msg); + while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ; + return qerror; + } + + dbus_message_unref (msg); + dbus_message_unref (reply); + + while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ; + + return QString(); +} + +QString HALBackend::undecrypt(const QString &_udi) +{ + const Medium* medium = m_mediaList.findById(_udi); + if (!medium) + return i18n("No such medium: %1").arg(_udi); + + if (!medium->isEncrypted() || medium->clearDeviceUdi().isNull()) + return QString(); + + const char *udi = medium->id().latin1(); + DBusMessage *msg = NULL; + DBusMessage *reply = NULL; + DBusError error; + + kdDebug() << "Tear down " << udi << "\n" <<endl; + + msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi, + "org.freedesktop.Hal.Device.Volume.Crypto", + "Teardown"); + if (msg == NULL) { + kdDebug() << "teardown failed for " << udi << ": could not create dbus message\n"; + return i18n("Internal Error"); + } + + if (!dbus_message_append_args (msg, DBUS_TYPE_INVALID)) { + kdDebug() << "teardown failed for " << udi << ": could not append args to dbus message\n"; + dbus_message_unref (msg); + return i18n("Internal Error"); + } + + dbus_error_init (&error); + if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error)) || + dbus_error_is_set (&error)) + { + QString qerror = i18n("Internal Error"); + kdDebug() << "teardown failed for " << udi << ": " << error.name << " " << error.message << endl; + dbus_error_free (&error); + dbus_message_unref (msg); + while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ; + return qerror; + } + + dbus_message_unref (msg); + dbus_message_unref (reply); + ResetProperties(udi); + while (dbus_connection_dispatch(dbus_connection) == DBUS_DISPATCH_DATA_REMAINS) ; + return QString(); } diff --git a/kioslave/media/mediamanager/halbackend.h b/kioslave/media/mediamanager/halbackend.h index 31c682374..c5bdd532c 100644 --- a/kioslave/media/mediamanager/halbackend.h +++ b/kioslave/media/mediamanager/halbackend.h @@ -85,6 +85,8 @@ public: QString mount(const QString &id); QString mount(const Medium *medium); QString unmount(const QString &id); + QString decrypt(const QString &id, const QString &password); + QString undecrypt(const QString &id); private: /** @@ -143,6 +145,7 @@ private: QString generateName(const QString &devNode); static QString isInFstab(const Medium *medium); static QString listUsingProcesses(const Medium *medium); + static QString killUsingProcesses(const Medium *medium); private slots: void slotResult(KIO::Job *job); diff --git a/kioslave/media/mediamanager/medialist.cpp b/kioslave/media/mediamanager/medialist.cpp index fed6091fb..974eddbf6 100644 --- a/kioslave/media/mediamanager/medialist.cpp +++ b/kioslave/media/mediamanager/medialist.cpp @@ -52,6 +52,18 @@ const Medium *MediaList::findByName(const QString &name) const return m_nameMap[name]; } +const Medium *MediaList::findByClearUdi(const QString &name) +{ + kdDebug(1219) << "MediaList::findByClearUdi(" << name << ")" << endl; + + Medium *medium; + for (medium = m_media.first(); medium; medium = m_media.next()) { + if (medium->clearDeviceUdi() == name) return medium; + } + + return 0L; +} + QString MediaList::addMedium(Medium *medium, bool allowNotification) { @@ -121,11 +133,12 @@ bool MediaList::changeMediumState(const Medium &medium, bool allowNotification) if ( medium.isMountable() ) { QString device_node = medium.deviceNode(); + QString clear_device_udi = medium.clearDeviceUdi(); QString mount_point = medium.mountPoint(); QString fs_type = medium.fsType(); bool mounted = medium.isMounted(); - m->mountableState( device_node, mount_point, + m->mountableState( device_node, clear_device_udi, mount_point, fs_type, mounted ); } else diff --git a/kioslave/media/mediamanager/medialist.h b/kioslave/media/mediamanager/medialist.h index 590491b0c..4de333875 100644 --- a/kioslave/media/mediamanager/medialist.h +++ b/kioslave/media/mediamanager/medialist.h @@ -34,6 +34,7 @@ public: const QPtrList<Medium> list() const; const Medium *findById(const QString &id) const; const Medium *findByName(const QString &name) const; + const Medium *findByClearUdi(const QString &name); public: QString addMedium(Medium *medium, bool allowNotification = true); diff --git a/kioslave/media/mediamanager/mediamanager.cpp b/kioslave/media/mediamanager/mediamanager.cpp index ad8f1b447..f1569e817 100644 --- a/kioslave/media/mediamanager/mediamanager.cpp +++ b/kioslave/media/mediamanager/mediamanager.cpp @@ -232,6 +232,28 @@ QString MediaManager::unmount(const QString &name) #endif } +QString MediaManager::decrypt(const QString &name, const QString &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 +} + +QString MediaManager::undecrypt(const QString &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 +} + QString MediaManager::nameForLabel(const QString &label) { const QPtrList<Medium> media = m_mediaList.list(); diff --git a/kioslave/media/mediamanager/mediamanager.h b/kioslave/media/mediamanager/mediamanager.h index 1e5aa1d84..36942362d 100644 --- a/kioslave/media/mediamanager/mediamanager.h +++ b/kioslave/media/mediamanager/mediamanager.h @@ -47,6 +47,8 @@ k_dcop: QString mount(const QString &uid); QString unmount(const QString &uid); + QString decrypt(const QString &uid, const QString &password); + QString undecrypt(const QString &uid); QString nameForLabel(const QString &label); ASYNC setUserLabel(const QString &name, const QString &label); diff --git a/kioslave/media/medianotifier/medianotifier.cpp b/kioslave/media/medianotifier/medianotifier.cpp index 98a474ba7..ce39215d9 100644 --- a/kioslave/media/medianotifier/medianotifier.cpp +++ b/kioslave/media/medianotifier/medianotifier.cpp @@ -19,8 +19,12 @@ #include "medianotifier.h" +#include <sys/vfs.h> + #include <qfile.h> #include <qfileinfo.h> +#include <qdir.h> +#include <qcheckbox.h> #include <kapplication.h> #include <kglobal.h> @@ -44,6 +48,11 @@ MediaNotifier::MediaNotifier(const QCString &name) : KDEDModule(name) connectDCOPSignal( "kded", "mediamanager", "mediumChanged(QString, bool)", "onMediumChange(QString, bool)", true ); + + m_freeTimer = new QTimer( this ); + connect( m_freeTimer, SIGNAL( timeout() ), SLOT( checkFreeDiskSpace() ) ); + m_freeTimer->start( 1000*6*2 /* 20 minutes */ ); + m_freeDialog = 0; } MediaNotifier::~MediaNotifier() @@ -103,12 +112,12 @@ bool MediaNotifier::autostart( const KFileItem &medium ) { QString mimetype = medium.mimetype(); - bool is_cdrom = mimetype.startsWith( "cd" ) || mimetype.startsWith( "dvd" ); - bool is_mounted = mimetype.endsWith( "_mounted" ); + bool is_cdrom = mimetype.startsWith( "media/cd" ) || mimetype.startsWith( "media/dvd" ); + bool is_mounted = mimetype.contains( "_mounted" ); // We autorun only on CD/DVD or removable disks (USB, Firewire) if ( !( is_cdrom || is_mounted ) - && mimetype!="media/removable_mounted" ) + && !mimetype.startsWith("media/removable_mounted") ) { return false; } @@ -309,4 +318,69 @@ extern "C" } } +void MediaNotifier::checkFreeDiskSpace() +{ + struct statfs sfs; + long total, avail; + if ( m_freeDialog ) + return; + + if ( statfs( QFile::encodeName( QDir::homeDirPath() ), &sfs ) == 0 ) + { + total = sfs.f_blocks; + avail = ( getuid() ? sfs.f_bavail : sfs.f_bfree ); + + if (avail < 0 || total <= 0) + return; // we better do not say anything about it + + int freeperc = static_cast<int>(100 * double(avail) / total); + + if ( freeperc < 5 && KMessageBox::shouldBeShownContinue( "dontagainfreespace" ) ) // free disk space dropped under a limit + { + m_freeDialog= new KDialogBase( + i18n( "Low Disk Space" ), + KDialogBase::Yes | KDialogBase::No, + KDialogBase::Yes, KDialogBase::No, + 0, "warningYesNo", false, true, + i18n( "Start Konqueror" ), KStdGuiItem::cancel()); + + QString text = i18n( "You are running low on disk space on your home partition (currently %1% free), would you like to " + "run Konqueror to free some disk space and fix the problem?" ).arg( freeperc ); + bool checkboxResult = false; + KMessageBox::createKMessageBox(m_freeDialog, QMessageBox::Warning, text, QStringList(), + i18n("Do not ask again"), + &checkboxResult, KMessageBox::Notify | KMessageBox::NoExec); + m_freeDialog->show(); + connect( m_freeDialog, SIGNAL( yesClicked() ), SLOT( slotFreeContinue() ) ); + connect( m_freeDialog, SIGNAL( noClicked() ), SLOT( slotFreeCancel() ) ); + } + } +} + +void MediaNotifier::slotFreeContinue() +{ + slotFreeFinished( KMessageBox::Continue ); +} + +void MediaNotifier::slotFreeCancel() +{ + slotFreeFinished( KMessageBox::Cancel ); +} + +void MediaNotifier::slotFreeFinished( KMessageBox::ButtonCode res ) +{ + QCheckBox *checkbox = ::qt_cast<QCheckBox*>( m_freeDialog->child( 0, "QCheckBox" ) ); + if ( checkbox && checkbox->isChecked() ) + KMessageBox::saveDontShowAgainYesNo("dontagainfreespace", res); + m_freeDialog->delayedDestruct(); + m_freeDialog = 0; + + if ( res == KMessageBox::Continue ) // start Konqi + { + ( void ) new KRun( KURL::fromPathOrURL( QDir::homeDirPath() ) ); + } + else // people don't want to be bothered, at least stop the timer; there's no way to save the dontshowagain entry in this case + m_freeTimer->stop(); +} + #include "medianotifier.moc" diff --git a/kioslave/media/medianotifier/medianotifier.h b/kioslave/media/medianotifier/medianotifier.h index c3e4b9bf9..e070ac7ac 100644 --- a/kioslave/media/medianotifier/medianotifier.h +++ b/kioslave/media/medianotifier/medianotifier.h @@ -23,10 +23,13 @@ #include <kdedmodule.h> #include <kfileitem.h> #include <kio/job.h> +#include <kmessagebox.h> #include <qstring.h> #include <qmap.h> +class KDialogBase; + class MediaNotifier: public KDEDModule { Q_OBJECT @@ -41,6 +44,10 @@ k_dcop: private slots: void slotStatResult( KIO::Job *job ); + void checkFreeDiskSpace(); + void slotFreeFinished( KMessageBox::ButtonCode ); + void slotFreeContinue(); + void slotFreeCancel(); private: bool autostart( const KFileItem &medium ); @@ -52,6 +59,8 @@ private: const QString &autoopenFile ); QMap<KIO::Job*,bool> m_allowNotificationMap; + QTimer * m_freeTimer; + KDialogBase * m_freeDialog; }; #endif diff --git a/kioslave/media/mimetypes/Makefile.am b/kioslave/media/mimetypes/Makefile.am index 25c718035..cdb66a1ac 100644 --- a/kioslave/media/mimetypes/Makefile.am +++ b/kioslave/media/mimetypes/Makefile.am @@ -4,10 +4,20 @@ mimetype_DATA = floppy_mounted.desktop floppy_unmounted.desktop \ floppy5_unmounted.desktop floppy5_mounted.desktop \ zip_mounted.desktop zip_unmounted.desktop \ hdd_mounted.desktop hdd_unmounted.desktop \ + hdd_mounted_decrypted.desktop hdd_unmounted_encrypted.desktop \ + hdd_unmounted_decrypted.desktop \ removable_mounted.desktop removable_unmounted.desktop \ + removable_mounted_decrypted.desktop removable_unmounted_encrypted.desktop \ + removable_unmounted_decrypted.desktop \ cdrom_mounted.desktop cdrom_unmounted.desktop \ + cdrom_mounted_decrypted.desktop cdrom_unmounted_encrypted.desktop \ + cdrom_unmounted_decrypted.desktop \ dvd_mounted.desktop dvd_unmounted.desktop \ + dvd_mounted_decrypted.desktop dvd_unmounted_encrypted.desktop \ + dvd_unmounted_decrypted.desktop \ cdwriter_mounted.desktop cdwriter_unmounted.desktop \ + cdwriter_mounted_decrypted.desktop cdwriter_unmounted_encrypted.desktop \ + cdwriter_unmounted_decrypted.desktop \ smb_mounted.desktop smb_unmounted.desktop \ nfs_mounted.desktop nfs_unmounted.desktop \ audiocd.desktop \ diff --git a/kioslave/media/mimetypes/cdrom_mounted_decrypted.desktop b/kioslave/media/mimetypes/cdrom_mounted_decrypted.desktop new file mode 100644 index 000000000..2729ff4f5 --- /dev/null +++ b/kioslave/media/mimetypes/cdrom_mounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=cdrom_mount_decrypt +Type=MimeType +MimeType=media/cdrom_mounted_decrypted +Comment=Mounted Decrypted CD-ROM +Comment[de]=Eingebundene, entschlüsselte CD-ROM +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/cdrom_unmounted_decrypted.desktop b/kioslave/media/mimetypes/cdrom_unmounted_decrypted.desktop new file mode 100644 index 000000000..d6b2be0c2 --- /dev/null +++ b/kioslave/media/mimetypes/cdrom_unmounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=cdrom_unmount_decrypt +Type=MimeType +MimeType=media/cdrom_unmounted_decrypted +Comment=Unmounted Decrypted CD-ROM +Comment[de]=Nicht eingebundene, entschlüsselte CD-ROM +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/cdrom_unmounted_encrypted.desktop b/kioslave/media/mimetypes/cdrom_unmounted_encrypted.desktop new file mode 100644 index 000000000..95fa31b3b --- /dev/null +++ b/kioslave/media/mimetypes/cdrom_unmounted_encrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=cdrom_unmount_encrypt +Type=MimeType +MimeType=media/cdrom_unmounted_encrypted +Comment=Unmounted Encrypted CD-ROM +Comment[de]=Nicht eingebundene, verschlüsselte CD-ROM +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/cdwriter_mounted_decrypted.desktop b/kioslave/media/mimetypes/cdwriter_mounted_decrypted.desktop new file mode 100644 index 000000000..b831be152 --- /dev/null +++ b/kioslave/media/mimetypes/cdwriter_mounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=cdwriter_mount_decrypt +Type=MimeType +MimeType=media/cdwriter_mounted_decrypted +Comment=Mounted Decrypted CD Writer +Comment[de]=Eingebundener, entschlüsselter CD-Brenner +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/cdwriter_unmounted_decrypted.desktop b/kioslave/media/mimetypes/cdwriter_unmounted_decrypted.desktop new file mode 100644 index 000000000..48f49ccb4 --- /dev/null +++ b/kioslave/media/mimetypes/cdwriter_unmounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=cdwriter_unmount_decrypt +Type=MimeType +MimeType=media/cdwriter_unmounted_decrypted +Comment=Unmounted Decrypted CD Writer +Comment[de]=Nicht eingebundener, entschlüsselter CD-Brenner +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/cdwriter_unmounted_encrypted.desktop b/kioslave/media/mimetypes/cdwriter_unmounted_encrypted.desktop new file mode 100644 index 000000000..c31e66089 --- /dev/null +++ b/kioslave/media/mimetypes/cdwriter_unmounted_encrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=cdwriter_unmount_encrypt +Type=MimeType +MimeType=media/cdwriter_unmounted_encrypted +Comment=Unmounted Encrypted CD Writer +Comment[de]=Nicht eingebundener, entschlüsselter CD-Brenner +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/dvd_mounted_decrypted.desktop b/kioslave/media/mimetypes/dvd_mounted_decrypted.desktop new file mode 100644 index 000000000..22a90b52d --- /dev/null +++ b/kioslave/media/mimetypes/dvd_mounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=dvd_mount_decrypt +Type=MimeType +MimeType=media/dvd_mounted_decrypted +Comment=Mounted Decrypted DVD +Comment[de]=Eingebundene, entschlüsselte DVD +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/dvd_unmounted_decrypted.desktop b/kioslave/media/mimetypes/dvd_unmounted_decrypted.desktop new file mode 100644 index 000000000..129f3f177 --- /dev/null +++ b/kioslave/media/mimetypes/dvd_unmounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=dvd_unmount_decrypt +Type=MimeType +MimeType=media/dvd_unmounted_decrypted +Comment=Unmounted Decrypted DVD +Comment[de]=Nicht eingebundene, entschlüsselte DVD +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/dvd_unmounted_encrypted.desktop b/kioslave/media/mimetypes/dvd_unmounted_encrypted.desktop new file mode 100644 index 000000000..23d2353b5 --- /dev/null +++ b/kioslave/media/mimetypes/dvd_unmounted_encrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=dvd_unmount_encrypt +Type=MimeType +MimeType=media/dvd_unmounted_encrypted +Comment=Unmounted Encrypted DVD +Comment[de]=Nicht eingebundene, verschlüsselte DVD +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/hdd_mounted_decrypted.desktop b/kioslave/media/mimetypes/hdd_mounted_decrypted.desktop new file mode 100644 index 000000000..f4b1c1749 --- /dev/null +++ b/kioslave/media/mimetypes/hdd_mounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=hdd_mount_decrypt +Type=MimeType +MimeType=media/hdd_mounted_decrypted +Comment=Mounted Decrypted Hard Disk Volume +Comment[de]=Eingebundene, entschlüsselte Festplattenpartition +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/hdd_unmounted_decrypted.desktop b/kioslave/media/mimetypes/hdd_unmounted_decrypted.desktop new file mode 100644 index 000000000..f41411314 --- /dev/null +++ b/kioslave/media/mimetypes/hdd_unmounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=hdd_unmount_decrypt +Type=MimeType +MimeType=media/hdd_unmounted_decrypted +Comment=Unmounted Decrypted Hard Disk Volume +Comment[de]=Nicht eingebundene, entschlüsselte Festplattenpartition +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/hdd_unmounted_encrypted.desktop b/kioslave/media/mimetypes/hdd_unmounted_encrypted.desktop new file mode 100644 index 000000000..60e277811 --- /dev/null +++ b/kioslave/media/mimetypes/hdd_unmounted_encrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=hdd_unmount_encrypt +Type=MimeType +MimeType=media/hdd_unmounted_encrypted +Comment=Unmounted Encrypted Hard Disk Volume +Comment[de]=Nicht eingebundene, verschlüsselte Festplattenpartition +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/removable_mounted_decrypted.desktop b/kioslave/media/mimetypes/removable_mounted_decrypted.desktop new file mode 100644 index 000000000..6a025119d --- /dev/null +++ b/kioslave/media/mimetypes/removable_mounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=usbpendrive_mount_decrypt +Type=MimeType +MimeType=media/removable_mounted_decrypted +Comment=Mounted Decrypted Removable Medium +Comment[de]=Eingebundenes, entschlüsseltes Wechsellaufwerk +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/removable_unmounted_decrypted.desktop b/kioslave/media/mimetypes/removable_unmounted_decrypted.desktop new file mode 100644 index 000000000..fe3ecd6a8 --- /dev/null +++ b/kioslave/media/mimetypes/removable_unmounted_decrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=usbpendrive_unmount_decrypt +Type=MimeType +MimeType=media/removable_unmounted_decrypted +Comment=Unmounted Decrypted Removable Medium +Comment[de]=Nicht eingebundenes, entschlüsseltes Wechsellaufwerk +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mimetypes/removable_unmounted_encrypted.desktop b/kioslave/media/mimetypes/removable_unmounted_encrypted.desktop new file mode 100644 index 000000000..e2949bfed --- /dev/null +++ b/kioslave/media/mimetypes/removable_unmounted_encrypted.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Icon=usbpendrive_unmount_encrypt +Type=MimeType +MimeType=media/removable_unmounted_encrypted +Comment=Unmounted Encrypted Removable Medium +Comment[de]=Nicht eingebundenes, verschlüsseltes Wechsellaufwerk +Patterns= + +X-KDE-AutoEmbed=true +X-KDE-IsAlso=inode/directory diff --git a/kioslave/media/mounthelper/Makefile.am b/kioslave/media/mounthelper/Makefile.am index 9080ba81a..9c03ba688 100644 --- a/kioslave/media/mounthelper/Makefile.am +++ b/kioslave/media/mounthelper/Makefile.am @@ -3,10 +3,10 @@ bin_PROGRAMS = kio_media_mounthelper INCLUDES = -I$(srcdir)/../libmediacommon $(all_includes) AM_LDFLAGS = $(all_libraries) -kio_media_mounthelper_SOURCES = kio_media_mounthelper.cpp +kio_media_mounthelper_SOURCES = kio_media_mounthelper.cpp decryptdialog.ui dialog.cpp kio_media_mounthelper_LDFLAGS = $(KDE_RPATH) $(all_libraries) -kio_media_mounthelper_LDADD = ../libmediacommon/libmediacommon.la $(LIB_KIO) +kio_media_mounthelper_LDADD = ../libmediacommon/libmediacommon.la $(LIB_KIO) $(LIB_KDEUI) METASOURCES = AUTO diff --git a/kioslave/media/mounthelper/decryptdialog.ui b/kioslave/media/mounthelper/decryptdialog.ui new file mode 100644 index 000000000..15790c8ef --- /dev/null +++ b/kioslave/media/mounthelper/decryptdialog.ui @@ -0,0 +1,201 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DecryptDialog</class> +<widget class="QWidget"> + <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="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <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="QLabel"> + <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="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <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="QLineEdit"> + <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="QGroupBox" 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="QLabel" 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/mounthelper/dialog.cpp b/kioslave/media/mounthelper/dialog.cpp new file mode 100644 index 000000000..74bcfb388 --- /dev/null +++ b/kioslave/media/mounthelper/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(QString url, QString 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 ); + + QPixmap pixmap = KGlobal::iconLoader()->loadIcon(iconName, KIcon::NoGroup, KIcon::SizeLarge); + decryptDialog->encryptedIcon->setPixmap( pixmap ); + + connect(decryptDialog->passwordEdit, SIGNAL (textChanged(const QString &)), this, SLOT (slotPasswordChanged(const QString &))); + + setMainWidget(decryptDialog); +} + +Dialog::~Dialog() +{ + delete decryptDialog; +} + +QString Dialog::getPassword() +{ + return decryptDialog->passwordEdit->text(); +} + +void Dialog::slotDialogError(QString errorMsg) +{ + kdDebug() << __func__ << "(" << errorMsg << " )" << endl; + + decryptDialog->errorLabel->setText(QString("<b>%1</b>").arg(errorMsg)); + decryptDialog->errorBox->show(); +} + +void Dialog::slotPasswordChanged(const QString &text) +{ + enableButton( User1, !text.isEmpty() ); +} + +#include "dialog.moc" diff --git a/kioslave/media/mounthelper/dialog.h b/kioslave/media/mounthelper/dialog.h new file mode 100644 index 000000000..1f544c370 --- /dev/null +++ b/kioslave/media/mounthelper/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 <qlineedit.h> +#include <qlabel.h> +#include <qgroupbox.h> + +#include "decryptdialog.h" + +class KryptoMedia; + +class Dialog : public KDialogBase +{ + +Q_OBJECT + +public: + Dialog(QString url, QString iconName); + ~Dialog(); + + QString getPassword(); + +public slots: + void slotDialogError(QString errorMsg); + void slotPasswordChanged(const QString &text); + +private: + DecryptDialog *decryptDialog; +}; + +#endif // DIALOG_H_ + diff --git a/kioslave/media/mounthelper/kio_media_mounthelper.cpp b/kioslave/media/mounthelper/kio_media_mounthelper.cpp index 12743847f..5dae9e0d3 100644 --- a/kioslave/media/mounthelper/kio_media_mounthelper.cpp +++ b/kioslave/media/mounthelper/kio_media_mounthelper.cpp @@ -32,7 +32,9 @@ #include <kglobal.h> #include <kprocess.h> #include <kstartupinfo.h> +#include <kmimetype.h> +#include "dialog.h" #include "kio_media_mounthelper.h" const Medium MountHelper::findMedium(const KURL &url) @@ -63,7 +65,7 @@ MountHelper::MountHelper() : KApplication() { KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); - m_errorStr = ""; + m_errorStr = QString::null; KURL url(args->url(0)); const Medium medium = findMedium(url); @@ -89,7 +91,37 @@ MountHelper::MountHelper() : KApplication() m_isCdrom = medium.mimeType().find("dvd")!=-1 || medium.mimeType().find("cd")!=-1; - if (args->isSet("u")) + if (args->isSet("d")) + { + if (!medium.isEncrypted()) + { + m_errorStr = i18n("%1 is not an encrypted media.").arg(url.prettyURL()); + QTimer::singleShot(0, this, SLOT(error()) ); + return; + } + if (!medium.needDecryption()) + { + m_errorStr = i18n("%1 is already decrypted.").arg(url.prettyURL()); + QTimer::singleShot(0, this, SLOT(error()) ); + return; + } + + QString iconName = medium.iconName(); + if (iconName.isEmpty()) + { + QString mime = medium.mimeType(); + iconName = KMimeType::mimeType(mime)->icon(mime, false); + } + + m_mediumId = medium.id(); + dialog = new Dialog(url.prettyURL(), iconName); + dialog->show(); + + connect(dialog, SIGNAL (user1Clicked()), this, SLOT (slotSendPassword())); + connect(dialog, SIGNAL (cancelClicked()), this, SLOT (slotCancel())); + connect(this, SIGNAL (signalPasswordError(QString)), dialog, SLOT (slotDialogError(QString))); + } + else if (args->isSet("u")) { DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "unmount", medium.id()); @@ -103,6 +135,8 @@ MountHelper::MountHelper() : KApplication() } 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 @@ -114,17 +148,24 @@ MountHelper::MountHelper() : KApplication() */ if (medium.isMounted()) { - DCOPRef mediamanager("kded", "mediamanager"); DCOPReply reply = mediamanager.call( "unmount", medium.id()); if (reply.isValid()) reply.get(m_errorStr); - if (m_errorStr.isNull()) - invokeEject(device, true); - else - error(); - m_device = device; - } else - invokeEject(device, true); + } + + /* 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 { @@ -167,7 +208,9 @@ void MountHelper::ejectFinished(KProcess* proc) else m_errorStr = i18n("The device was successfully unmounted, but could not be ejected"); } - QTimer::singleShot(0, this, SLOT(error())); +//X Comment this because the error is useless as long as the unmount is successfull. +//X QTimer::singleShot(0, this, SLOT(error())); + ::exit(0); } } @@ -177,8 +220,32 @@ void MountHelper::error() ::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 { + QString 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}, diff --git a/kioslave/media/mounthelper/kio_media_mounthelper.h b/kioslave/media/mounthelper/kio_media_mounthelper.h index 478d802f9..ed5884d4f 100644 --- a/kioslave/media/mounthelper/kio_media_mounthelper.h +++ b/kioslave/media/mounthelper/kio_media_mounthelper.h @@ -28,6 +28,8 @@ #include "medium.h" +class Dialog; + class MountHelper : public KApplication { Q_OBJECT @@ -38,12 +40,18 @@ private: const Medium findMedium(const KURL &url); void invokeEject(const QString &device, bool quiet=false); QString m_errorStr; - QString m_device; bool m_isCdrom; + QString m_mediumId; + Dialog *dialog; private slots: + void slotSendPassword(); + void slotCancel(); void ejectFinished(KProcess* proc); void error(); + +signals: + void signalPasswordError(QString errorMsg); }; #endif diff --git a/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop b/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop index c0cdcbbba..d5e13eda5 100644 --- a/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop +++ b/kioslave/media/propsdlgplugin/media_propsdlgplugin.desktop @@ -99,4 +99,4 @@ Comment[wa]=Tchôke-divins di dvize di prôpietés Konqueror po-z apontyî l' du Comment[zh_CN]=配置挂载行为的 Konqueror 属性对话框插件 Comment[zh_TW]=Konqueror 內容對話框外掛程式,用於設定掛載的行為 X-KDE-Library=media_propsdlgplugin -ServiceTypes=KPropsDlg/Plugin,media/audiocd,media/hdd_mounted,media/hdd_unmounted,media/cdrom_mounted,media/cdrom_unmounted,media/cdwriter_mounted,media/nfs_mounted,media/cdwriter_unmounted,media/nfs_unmounted,media/removable_mounted,media/dvd_mounted,media/removable_unmounted,media/dvd_unmounted,media/smb_mounted,media/dvdvideo,media/smb_unmounted,media/floppy5_mounted,media/floppy5_unmounted,media/floppy_mounted,media/zip_mounted,media/floppy_unmounted,media/zip_unmounted,media/camera_mounted,media/camera_unmounted +ServiceTypes=KPropsDlg/Plugin,media/audiocd,media/hdd_mounted,media/hdd_unmounted,media/hdd_mounted_decrypted,media/hdd_unmounted_decrypted,media/cdrom_mounted,media/cdrom_unmounted,media/cdrom_mounted_decrypted,media/cdrom_unmounted_decrypted,media/cdwriter_mounted,media/cdwriter_mounted_decrypted,media/nfs_mounted,media/cdwriter_unmounted,media/cdwriter_unmounted_decrypted,media/nfs_unmounted,media/removable_mounted,media/removable_mounted_decrypted,media/dvd_mounted,media/dvd_mounted_decrypted,media/removable_unmounted,media/removable_unmounted_decrypted,media/dvd_unmounted,media/dvd_unmounted_decrypted,media/smb_mounted,media/dvdvideo,media/smb_unmounted,media/floppy5_mounted,media/floppy5_unmounted,media/floppy_mounted,media/zip_mounted,media/floppy_unmounted,media/zip_unmounted,media/camera_mounted,media/camera_unmounted diff --git a/kioslave/media/services/Makefile.am b/kioslave/media/services/Makefile.am index dded3c403..c744934f2 100644 --- a/kioslave/media/services/Makefile.am +++ b/kioslave/media/services/Makefile.am @@ -1,3 +1,3 @@ servicesdir = $(kde_datadir)/konqueror/servicemenus -services_DATA = media_mount.desktop media_unmount.desktop media_eject.desktop media_safelyremove.desktop +services_DATA = media_decrypt.desktop media_mount.desktop media_unmount.desktop media_eject.desktop media_safelyremove.desktop diff --git a/kioslave/media/services/media_decrypt.desktop b/kioslave/media/services/media_decrypt.desktop new file mode 100644 index 000000000..dd8dadc39 --- /dev/null +++ b/kioslave/media/services/media_decrypt.desktop @@ -0,0 +1,9 @@ +[Desktop Action Decrypt] +Exec=kio_media_mounthelper -d %u +Icon=decrypted +Name=Decrypt +Name[de]=Entschlüsseln + +[Desktop Entry] +Actions=Decrypt +ServiceTypes=media/removable_unmounted_encrypted,media/hdd_unmounted_encrypted,media/cdrom_unmounted_encrypted,media/cdwriter_unmounted_encrypted,media/dvd_unmounted_encrypted diff --git a/kioslave/media/services/media_eject.desktop b/kioslave/media/services/media_eject.desktop index 1ecd29fa8..f5ab3582e 100644 --- a/kioslave/media/services/media_eject.desktop +++ b/kioslave/media/services/media_eject.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -ServiceTypes=media/cdrom_mounted,media/cdrom_unmounted,media/cdwriter_mounted,media/cdwriter_unmounted,media/dvd_mounted,media/dvd_unmounted,media/audiocd,media/blankcd,media/blankdvd,media/dvdvideo,media/svcd,media/vcd +ServiceTypes=media/cdrom_mounted,media/cdrom_unmounted,media/cdrom_mounted_decrypted,media/cdrom_unmounted_decrypted,media/cdrom_unmounted_encrypted,media/cdwriter_mounted,media/cdwriter_unmounted,media/cdwriter_mounted_decrypted,media/cdwriter_unmounted_decrypted,media/cdwriter_unmounted_encrypted,media/dvd_mounted,media/dvd_unmounted,media/dvd_mounted_decrypted,media/dvd_unmounted_decrypted,media/dvd_unmounted_encrypted,media/audiocd,media/blankcd,media/blankdvd,media/dvdvideo,media/svcd,media/vcd Actions=MediaEject; X-KDE-Priority=TopLevel X-KDE-MediaNotifierHide=true diff --git a/kioslave/media/services/media_mount.desktop b/kioslave/media/services/media_mount.desktop index 1779d2208..b2166f8ea 100644 --- a/kioslave/media/services/media_mount.desktop +++ b/kioslave/media/services/media_mount.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -ServiceTypes=media/cdrom_unmounted,media/cdwriter_unmounted,media/dvd_unmounted,media/floppy5_unmounted,media/floppy_unmounted,media/hdd_unmounted,media/nfs_unmounted,media/removable_unmounted,media/smb_unmounted,media/zip_unmounted,media/camera_unmounted +ServiceTypes=media/cdrom_unmounted,media/cdrom_unmounted_decrypted,media/cdwriter_unmounted,media/cdwriter_unmounted_decrypted,media/dvd_unmounted,media/dvd_unmounted_decrypted,media/floppy5_unmounted,media/floppy_unmounted,media/hdd_unmounted,media/hdd_unmounted_decrypted,media/nfs_unmounted,media/removable_unmounted,media/removable_unmounted_decrypted,media/smb_unmounted,media/zip_unmounted,media/camera_unmounted Actions=MediaMount; X-KDE-Priority=TopLevel X-KDE-MediaNotifierHide=true diff --git a/kioslave/media/services/media_safelyremove.desktop b/kioslave/media/services/media_safelyremove.desktop index 298a5f2e5..ce92f348c 100644 --- a/kioslave/media/services/media_safelyremove.desktop +++ b/kioslave/media/services/media_safelyremove.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -ServiceTypes=media/removable_mounted,media/removable_unmounted,media/camera_mounted,media/camera_unmounted +ServiceTypes=media/removable_mounted,media/removable_mounted_decrypted,media/removable_unmounted,media/removable_unmounted_decrypted,media/camera_mounted,media/camera_unmounted Actions=MediaSafelyRemove; X-KDE-Priority=TopLevel X-KDE-MediaNotifierHide=true diff --git a/kioslave/media/services/media_unmount.desktop b/kioslave/media/services/media_unmount.desktop index 537750095..5877e484e 100644 --- a/kioslave/media/services/media_unmount.desktop +++ b/kioslave/media/services/media_unmount.desktop @@ -1,5 +1,5 @@ [Desktop Entry] -ServiceTypes=media/cdrom_mounted,media/cdwriter_mounted,media/dvd_mounted,media/floppy5_mounted,media/floppy_mounted,media/hdd_mounted,media/nfs_mounted,media/smb_mounted,media/zip_mounted,media/vcd,media/svcd,media/dvdvideo +ServiceTypes=media/cdrom_mounted,media/cdrom_mounted_decrypted,media/cdwriter_mounted,media/cdwriter_mounted_decrypted,media/dvd_mounted,media/dvd_mounted_decrypted,media/floppy5_mounted,media/floppy_mounted,media/hdd_mounted,media/hdd_mounted_decrypted,media/nfs_mounted,media/smb_mounted,media/zip_mounted,media/vcd,media/svcd,media/dvdvideo Actions=MediaUnmount; X-KDE-Priority=TopLevel X-KDE-MediaNotifierHide=true diff --git a/kioslave/nfs/kio_nfs.cpp b/kioslave/nfs/kio_nfs.cpp index 18a7f1393..b35489c8d 100644 --- a/kioslave/nfs/kio_nfs.cpp +++ b/kioslave/nfs/kio_nfs.cpp @@ -89,7 +89,7 @@ int x_getdomainname(char *name, size_t len) { if ((hent = gethostbyname(uts.nodename)) != 0L) { - char *p = strchr(hent->h_name, '.'); + char *p = (char*)strchr(hent->h_name, '.'); if (p != 0L) { ++p; diff --git a/kioslave/system/systemimpl.cpp b/kioslave/system/systemimpl.cpp index f773dc20e..46214ce20 100644 --- a/kioslave/system/systemimpl.cpp +++ b/kioslave/system/systemimpl.cpp @@ -228,8 +228,16 @@ void SystemImpl::createEntry(KIO::UDSEntry &entry, QString new_filename = file; new_filename.truncate(file.length()-8); - addAtom(entry, KIO::UDS_URL, 0, "system:/"+new_filename); + if ( desktop.readURL().isEmpty() ) + { + addAtom(entry, KIO::UDS_URL, 0, desktop.readPath()); + } + else + { + addAtom(entry, KIO::UDS_URL, 0, "system:/"+new_filename); + } + addAtom(entry, KIO::UDS_FILE_TYPE, S_IFDIR); addAtom(entry, KIO::UDS_MIME_TYPE, 0, "inode/directory"); |