• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

kdesktopfileactions.cpp

Go to the documentation of this file.
00001 /*  This file is part of the KDE libraries
00002  *  Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
00003  *                     David Faure   <faure@kde.org>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation;
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "kdesktopfileactions.h"
00021 #include "krun.h"
00022 #include "kautomount.h"
00023 #include <kmessageboxwrapper.h>
00024 #include <kdirnotify.h>
00025 #include <kmountpoint.h>
00026 
00027 #include <kglobal.h>
00028 #include <kstandarddirs.h>
00029 #include <kdesktopfile.h>
00030 #include <kconfiggroup.h>
00031 #include <klocale.h>
00032 #include "kservice.h"
00033 
00034 enum BuiltinServiceType { ST_MOUNT = 0x0E1B05B0, ST_UNMOUNT = 0x0E1B05B1 }; // random numbers
00035 
00036 static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg );
00037 static bool runApplication( const KUrl& _url, const QString & _serviceFile );
00038 static bool runLink( const KUrl& _url, const KDesktopFile &cfg );
00039 
00040 bool KDesktopFileActions::run( const KUrl& u, bool _is_local )
00041 {
00042     // It might be a security problem to run external untrusted desktop
00043     // entry files
00044     if ( !_is_local )
00045         return false;
00046 
00047     KDesktopFile cfg( u.path() );
00048     if ( !cfg.desktopGroup().hasKey("Type") )
00049     {
00050         QString tmp = i18n("The desktop entry file %1 "
00051                            "has no Type=... entry.", u.path() );
00052         KMessageBoxWrapper::error( 0, tmp);
00053         return false;
00054     }
00055 
00056     //kDebug(7000) << "TYPE = " << type.data();
00057 
00058     if ( cfg.hasDeviceType() )
00059         return runFSDevice( u, cfg );
00060     else if ( cfg.hasApplicationType() )
00061         return runApplication( u, u.path() );
00062     else if ( cfg.hasLinkType() )
00063         return runLink( u, cfg );
00064 
00065     QString tmp = i18n("The desktop entry of type\n%1\nis unknown.",  cfg.readType() );
00066     KMessageBoxWrapper::error( 0, tmp);
00067 
00068     return false;
00069 }
00070 
00071 static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg )
00072 {
00073     bool retval = false;
00074 
00075     QString dev = cfg.readDevice();
00076 
00077     if ( dev.isEmpty() )
00078     {
00079         QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.",  _url.path() );
00080         KMessageBoxWrapper::error( 0, tmp);
00081         return retval;
00082     }
00083 
00084     KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00085     // Is the device already mounted ?
00086     if (mp) {
00087         KUrl mpURL(mp->mountPoint());
00088         // Open a new window
00089         retval = KRun::runUrl( mpURL, QLatin1String("inode/directory"), 0 /*TODO - window*/ );
00090     } else {
00091         KConfigGroup cg = cfg.desktopGroup();
00092         bool ro = cg.readEntry("ReadOnly", false);
00093         QString fstype = cg.readEntry( "FSType" );
00094         if ( fstype == "Default" ) // KDE-1 thing
00095             fstype.clear();
00096         QString point = cg.readEntry( "MountPoint" );
00097 #ifndef Q_WS_WIN
00098         (void) new KAutoMount( ro, fstype.toLatin1(), dev, point, _url.path() );
00099 #endif
00100         retval = false;
00101     }
00102 
00103     return retval;
00104 }
00105 
00106 static bool runApplication( const KUrl& , const QString & _serviceFile )
00107 {
00108     KService s( _serviceFile );
00109     if ( !s.isValid() )
00110         // The error message was already displayed, so we can just quit here
00111         // ### KDE4: is this still the case?
00112         return false;
00113 
00114     KUrl::List lst;
00115     return KRun::run( s, lst, 0 /*TODO - window*/ );
00116 }
00117 
00118 static bool runLink( const KUrl& _url, const KDesktopFile &cfg )
00119 {
00120     QString u = cfg.readUrl();
00121     if ( u.isEmpty() )
00122     {
00123         QString tmp = i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.",  _url.prettyUrl() );
00124         KMessageBoxWrapper::error( 0, tmp );
00125         return false;
00126     }
00127 
00128     KUrl url ( u );
00129     KRun* run = new KRun(url,(QWidget*)0);
00130 
00131     // X-KDE-LastOpenedWith holds the service desktop entry name that
00132     // was should be preferred for opening this URL if possible.
00133     // This is used by the Recent Documents menu for instance.
00134     QString lastOpenedWidth = cfg.desktopGroup().readEntry( "X-KDE-LastOpenedWith" );
00135     if ( !lastOpenedWidth.isEmpty() )
00136         run->setPreferredService( lastOpenedWidth );
00137 
00138     return false;
00139 }
00140 
00141 QList<KServiceAction> KDesktopFileActions::builtinServices( const KUrl& _url )
00142 {
00143     QList<KServiceAction> result;
00144 
00145     if ( !_url.isLocalFile() )
00146         return result;
00147 
00148     KDesktopFile cfg( _url.path() );
00149     QString type = cfg.readType();
00150 
00151     if ( type.isEmpty() )
00152         return result;
00153 
00154     if ( cfg.hasDeviceType() ) {
00155         const QString dev = cfg.readDevice();
00156         if ( dev.isEmpty() ) {
00157             QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.",  _url.path() );
00158             KMessageBoxWrapper::error(0, tmp);
00159         } else {
00160             KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00161             // not mounted ?
00162             if ( !mp ) {
00163                 KServiceAction mount("mount", i18n("Mount"), QString(), QString(), false);
00164                 mount.setData(QVariant(ST_MOUNT));
00165                 result.append(mount);
00166             } else {
00167                 QString text;
00168 #ifdef HAVE_VOLMGT
00169                 /*
00170                  *  Solaris' volume management can only umount+eject
00171                  */
00172                 text = i18n("Eject");
00173 #else
00174                 text = i18n("Unmount");
00175 #endif
00176                 KServiceAction unmount("unmount", text, QString(), QString(), false);
00177                 unmount.setData(QVariant(ST_UNMOUNT));
00178                 result.append(unmount);
00179             }
00180         }
00181     }
00182 
00183     return result;
00184 }
00185 
00186 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, bool bLocalFiles )
00187 {
00188     KDesktopFile cfg( path );
00189     return userDefinedServices( path, cfg, bLocalFiles );
00190 }
00191 
00192 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, const KDesktopFile& cfg, bool bLocalFiles, const KUrl::List & file_list )
00193 {
00194     Q_UNUSED(path); // this was just for debugging; we use service.entryPath() now.
00195     KService service(&cfg);
00196     return userDefinedServices(service, bLocalFiles, file_list);
00197 }
00198 
00199 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const KService& service, bool bLocalFiles, const KUrl::List & file_list )
00200 {
00201     QList<KServiceAction> result;
00202 
00203     if (!service.isValid()) // e.g. TryExec failed
00204         return result;
00205 
00206     QStringList keys;
00207     const QString actionMenu = service.property("X-KDE-GetActionMenu", QVariant::String).toString();
00208     if (!actionMenu.isEmpty()) {
00209         const QStringList dbuscall = actionMenu.split(QChar(' '));
00210         if (dbuscall.count() >= 4) {
00211             const QString& app       = dbuscall.at( 0 );
00212             const QString& object    = dbuscall.at( 1 );
00213             const QString& interface = dbuscall.at( 2 );
00214             const QString& function  = dbuscall.at( 3 );
00215 
00216             QDBusInterface remote( app, object, interface );
00217             // Do NOT use QDBus::BlockWithGui here. It runs a nested event loop,
00218             // in which timers can fire, leading to crashes like #149736.
00219             QDBusReply<QStringList> reply = remote.call(function, file_list.toStringList());
00220             keys = reply;               // ensures that the reply was a QStringList
00221             if (keys.isEmpty())
00222                 return result;
00223         } else {
00224             kWarning(7000) << "The desktop file" << service.entryPath()
00225                            << "has an invalid X-KDE-GetActionMenu entry."
00226                            << "Syntax is: app object interface function";
00227         }
00228     }
00229 
00230     // Now, either keys is empty (all actions) or it's set to the actions we want
00231 
00232     foreach(const KServiceAction& action, service.actions()) {
00233         if (keys.isEmpty() || keys.contains(action.name())) {
00234             const QString exec = action.exec();
00235             if (bLocalFiles || exec.contains("%U") || exec.contains("%u")) {
00236                 result.append( action );
00237             }
00238         }
00239     }
00240 
00241     return result;
00242 }
00243 
00244 void KDesktopFileActions::executeService( const KUrl::List& urls, const KServiceAction& action )
00245 {
00246     //kDebug(7000) << "EXECUTING Service " << action.name();
00247 
00248     int actionData = action.data().toInt();
00249     if ( actionData == ST_MOUNT || actionData == ST_UNMOUNT ) {
00250         Q_ASSERT( urls.count() == 1 );
00251         const QString path = urls.first().path();
00252         //kDebug(7000) << "MOUNT&UNMOUNT";
00253 
00254         KDesktopFile cfg( path );
00255         const QString dev = cfg.readDevice();
00256         if ( dev.isEmpty() ) {
00257             QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.",  path );
00258             KMessageBoxWrapper::error( 0, tmp );
00259             return;
00260         }
00261         KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00262 
00263         if ( actionData == ST_MOUNT ) {
00264             // Already mounted? Strange, but who knows ...
00265             if ( mp ) {
00266                 kDebug(7000) << "ALREADY Mounted";
00267                 return;
00268             }
00269 
00270             const KConfigGroup group = cfg.desktopGroup();
00271             bool ro = group.readEntry("ReadOnly", false);
00272             QString fstype = group.readEntry( "FSType" );
00273             if ( fstype == "Default" ) // KDE-1 thing
00274                 fstype.clear();
00275             QString point = group.readEntry( "MountPoint" );
00276 #ifndef Q_WS_WIN
00277             (void)new KAutoMount( ro, fstype.toLatin1(), dev, point, path, false );
00278 #endif
00279         } else if ( actionData == ST_UNMOUNT ) {
00280             // Not mounted? Strange, but who knows ...
00281             if ( !mp )
00282                 return;
00283 
00284 #ifndef Q_WS_WIN
00285             (void)new KAutoUnmount( mp->mountPoint(), path );
00286 #endif
00287         }
00288     } else {
00289         kDebug() << action.name() << "first url's path=" << urls.first().path() << "exec=" << action.exec();
00290         KRun::run( action.exec(), urls, 0, action.text(), action.icon(), "0" /*no startup notification for actions*/ );
00291         // The action may update the desktop file. Example: eject unmounts (#5129).
00292         org::kde::KDirNotify::emitFilesChanged( urls.toStringList() );
00293     }
00294 }
00295 

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal