• Skip to content
  • Skip to link menu
KDE 4.3 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               || (cfg.readType() == "Service" && !cfg.desktopGroup().readEntry("Exec").isEmpty())) // for kio_settings
00062         return runApplication( u, u.toLocalFile() );
00063     else if ( cfg.hasLinkType() )
00064         return runLink( u, cfg );
00065 
00066     QString tmp = i18n("The desktop entry of type\n%1\nis unknown.",  cfg.readType() );
00067     KMessageBoxWrapper::error( 0, tmp);
00068 
00069     return false;
00070 }
00071 
00072 static bool runFSDevice( const KUrl& _url, const KDesktopFile &cfg )
00073 {
00074     bool retval = false;
00075 
00076     QString dev = cfg.readDevice();
00077 
00078     if ( dev.isEmpty() )
00079     {
00080         QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.",  _url.path() );
00081         KMessageBoxWrapper::error( 0, tmp);
00082         return retval;
00083     }
00084 
00085     KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00086     // Is the device already mounted ?
00087     if (mp) {
00088         KUrl mpURL(mp->mountPoint());
00089         // Open a new window
00090         retval = KRun::runUrl( mpURL, QLatin1String("inode/directory"), 0 /*TODO - window*/ );
00091     } else {
00092         KConfigGroup cg = cfg.desktopGroup();
00093         bool ro = cg.readEntry("ReadOnly", false);
00094         QString fstype = cg.readEntry( "FSType" );
00095         if ( fstype == "Default" ) // KDE-1 thing
00096             fstype.clear();
00097         QString point = cg.readEntry( "MountPoint" );
00098 #ifndef Q_WS_WIN
00099         (void) new KAutoMount( ro, fstype.toLatin1(), dev, point, _url.path() );
00100 #endif
00101         retval = false;
00102     }
00103 
00104     return retval;
00105 }
00106 
00107 static bool runApplication( const KUrl& , const QString & _serviceFile )
00108 {
00109     KService s( _serviceFile );
00110     if ( !s.isValid() )
00111         // The error message was already displayed, so we can just quit here
00112         // ### KDE4: is this still the case?
00113         return false;
00114 
00115     KUrl::List lst;
00116     return KRun::run( s, lst, 0 /*TODO - window*/ );
00117 }
00118 
00119 static bool runLink( const KUrl& _url, const KDesktopFile &cfg )
00120 {
00121     QString u = cfg.readUrl();
00122     if ( u.isEmpty() )
00123     {
00124         QString tmp = i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.",  _url.prettyUrl() );
00125         KMessageBoxWrapper::error( 0, tmp );
00126         return false;
00127     }
00128 
00129     KUrl url ( u );
00130     KRun* run = new KRun(url,(QWidget*)0);
00131 
00132     // X-KDE-LastOpenedWith holds the service desktop entry name that
00133     // was should be preferred for opening this URL if possible.
00134     // This is used by the Recent Documents menu for instance.
00135     QString lastOpenedWidth = cfg.desktopGroup().readEntry( "X-KDE-LastOpenedWith" );
00136     if ( !lastOpenedWidth.isEmpty() )
00137         run->setPreferredService( lastOpenedWidth );
00138 
00139     return false;
00140 }
00141 
00142 QList<KServiceAction> KDesktopFileActions::builtinServices( const KUrl& _url )
00143 {
00144     QList<KServiceAction> result;
00145 
00146     if ( !_url.isLocalFile() )
00147         return result;
00148 
00149     KDesktopFile cfg( _url.toLocalFile() );
00150     QString type = cfg.readType();
00151 
00152     if ( type.isEmpty() )
00153         return result;
00154 
00155     if ( cfg.hasDeviceType() ) {
00156         const QString dev = cfg.readDevice();
00157         if ( dev.isEmpty() ) {
00158             QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.",  _url.toLocalFile() );
00159             KMessageBoxWrapper::error(0, tmp);
00160         } else {
00161             KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00162             // not mounted ?
00163             if ( !mp ) {
00164                 KServiceAction mount("mount", i18n("Mount"), QString(), QString(), false);
00165                 mount.setData(QVariant(ST_MOUNT));
00166                 result.append(mount);
00167             } else {
00168                 QString text;
00169 #ifdef HAVE_VOLMGT
00170                 /*
00171                  *  Solaris' volume management can only umount+eject
00172                  */
00173                 text = i18n("Eject");
00174 #else
00175                 text = i18n("Unmount");
00176 #endif
00177                 KServiceAction unmount("unmount", text, QString(), QString(), false);
00178                 unmount.setData(QVariant(ST_UNMOUNT));
00179                 result.append(unmount);
00180             }
00181         }
00182     }
00183 
00184     return result;
00185 }
00186 
00187 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, bool bLocalFiles )
00188 {
00189     KDesktopFile cfg( path );
00190     return userDefinedServices( path, cfg, bLocalFiles );
00191 }
00192 
00193 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const QString& path, const KDesktopFile& cfg, bool bLocalFiles, const KUrl::List & file_list )
00194 {
00195     Q_UNUSED(path); // this was just for debugging; we use service.entryPath() now.
00196     KService service(&cfg);
00197     return userDefinedServices(service, bLocalFiles, file_list);
00198 }
00199 
00200 QList<KServiceAction> KDesktopFileActions::userDefinedServices( const KService& service, bool bLocalFiles, const KUrl::List & file_list )
00201 {
00202     QList<KServiceAction> result;
00203 
00204     if (!service.isValid()) // e.g. TryExec failed
00205         return result;
00206 
00207     QStringList keys;
00208     const QString actionMenu = service.property("X-KDE-GetActionMenu", QVariant::String).toString();
00209     if (!actionMenu.isEmpty()) {
00210         const QStringList dbuscall = actionMenu.split(QChar(' '));
00211         if (dbuscall.count() >= 4) {
00212             const QString& app       = dbuscall.at( 0 );
00213             const QString& object    = dbuscall.at( 1 );
00214             const QString& interface = dbuscall.at( 2 );
00215             const QString& function  = dbuscall.at( 3 );
00216 
00217             QDBusInterface remote( app, object, interface );
00218             // Do NOT use QDBus::BlockWithGui here. It runs a nested event loop,
00219             // in which timers can fire, leading to crashes like #149736.
00220             QDBusReply<QStringList> reply = remote.call(function, file_list.toStringList());
00221             keys = reply;               // ensures that the reply was a QStringList
00222             if (keys.isEmpty())
00223                 return result;
00224         } else {
00225             kWarning(7000) << "The desktop file" << service.entryPath()
00226                            << "has an invalid X-KDE-GetActionMenu entry."
00227                            << "Syntax is: app object interface function";
00228         }
00229     }
00230 
00231     // Now, either keys is empty (all actions) or it's set to the actions we want
00232 
00233     foreach(const KServiceAction& action, service.actions()) {
00234         if (keys.isEmpty() || keys.contains(action.name())) {
00235             const QString exec = action.exec();
00236             if (bLocalFiles || exec.contains("%U") || exec.contains("%u")) {
00237                 result.append( action );
00238             }
00239         }
00240     }
00241 
00242     return result;
00243 }
00244 
00245 void KDesktopFileActions::executeService( const KUrl::List& urls, const KServiceAction& action )
00246 {
00247     //kDebug(7000) << "EXECUTING Service " << action.name();
00248 
00249     int actionData = action.data().toInt();
00250     if ( actionData == ST_MOUNT || actionData == ST_UNMOUNT ) {
00251         Q_ASSERT( urls.count() == 1 );
00252         const QString path = urls.first().toLocalFile();
00253         //kDebug(7000) << "MOUNT&UNMOUNT";
00254 
00255         KDesktopFile cfg( path );
00256         const QString dev = cfg.readDevice();
00257         if ( dev.isEmpty() ) {
00258             QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.",  path );
00259             KMessageBoxWrapper::error( 0, tmp );
00260             return;
00261         }
00262         KMountPoint::Ptr mp = KMountPoint::currentMountPoints().findByDevice( dev );
00263 
00264         if ( actionData == ST_MOUNT ) {
00265             // Already mounted? Strange, but who knows ...
00266             if ( mp ) {
00267                 kDebug(7000) << "ALREADY Mounted";
00268                 return;
00269             }
00270 
00271             const KConfigGroup group = cfg.desktopGroup();
00272             bool ro = group.readEntry("ReadOnly", false);
00273             QString fstype = group.readEntry( "FSType" );
00274             if ( fstype == "Default" ) // KDE-1 thing
00275                 fstype.clear();
00276             QString point = group.readEntry( "MountPoint" );
00277 #ifndef Q_WS_WIN
00278             (void)new KAutoMount( ro, fstype.toLatin1(), dev, point, path, false );
00279 #endif
00280         } else if ( actionData == ST_UNMOUNT ) {
00281             // Not mounted? Strange, but who knows ...
00282             if ( !mp )
00283                 return;
00284 
00285 #ifndef Q_WS_WIN
00286             (void)new KAutoUnmount( mp->mountPoint(), path );
00287 #endif
00288         }
00289     } else {
00290         kDebug() << action.name() << "first url's path=" << urls.first().path() << "exec=" << action.exec();
00291         KRun::run( action.exec(), urls, 0, action.text(), action.icon(), "0" /*no startup notification for actions*/ );
00292         // The action may update the desktop file. Example: eject unmounts (#5129).
00293         org::kde::KDirNotify::emitFilesChanged( urls.toStringList() );
00294     }
00295 }
00296 

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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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