kmimetype.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kmimetype.cpp

    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., 59 Temple Place - Suite 330,
    00017  *  Boston, MA 02111-1307, USA.
    00018  **/
    00019 // $Id: kmimetype.cpp,v 1.157.2.2 2003/06/29 21:43:01 deller Exp $
    00020
    00021 #include <config.h>
    00022
    00023 #include <sys/types.h>
    00024 #include <sys/stat.h>
    00025
    00026 #include <assert.h>
    00027 #include <dirent.h>
    00028 #include <errno.h>
    00029 #include <stddef.h>
    00030 #include <unistd.h>
    00031 #include <stdlib.h>
    00032
    00033 #include <kprotocolinfo.h>
    00034 #include <kio/global.h>
    00035 #include "kmimetype.h"
    00036 #include "kservicetypefactory.h"
    00037 #include "kmimemagic.h"
    00038 #include "kservice.h"
    00039 #include "krun.h"
    00040 #include "kautomount.h"
    00041 #include <kdirnotify_stub.h>
    00042
    00043 #include <qstring.h>
    00044 #include <qfile.h>
    00045 #include <kmessageboxwrapper.h>
    00046
    00047 #include <dcopclient.h>
    00048 #include <kapplication.h>
    00049 #include <kprocess.h>
    00050 #include <kdebug.h>
    00051 #include <kdesktopfile.h>
    00052 #include <kdirwatch.h>
    00053 #include <kiconloader.h>
    00054 #include <klocale.h>
    00055 #include <ksimpleconfig.h>
    00056 #include <kstandarddirs.h>
    00057 #include <kurl.h>
    00058
    00059 template class KSharedPtr<KMimeType>;
    00060 template class QValueList<KMimeType::Ptr>;
    00061
    00062 KMimeType::Ptr KMimeType::s_pDefaultType = 0L;
    00063 bool KMimeType::s_bChecked = false;
    00064
    00065 void KMimeType::buildDefaultType()
    00066 {
    00067   assert ( !s_pDefaultType );
    00068   // Try to find the default type
    00069   KServiceType * mime = KServiceTypeFactory::self()->
    00070         findServiceTypeByName( defaultMimeType() );
    00071
    00072   if (mime && mime->isType( KST_KMimeType ))
    00073   {
    00074       s_pDefaultType = KMimeType::Ptr((KMimeType *) mime);
    00075   }
    00076   else
    00077   {
    00078      errorMissingMimeType( defaultMimeType() );
    00079      KStandardDirs stdDirs;
    00080      QString sDefaultMimeType = stdDirs.resourceDirs("mime").first()+defaultMimeType()+".desktop";
    00081      s_pDefaultType = new KMimeType( sDefaultMimeType, defaultMimeType(),
    00082                                      "unknown", "mime", QStringList() );
    00083   }
    00084 }
    00085
    00086 // Check for essential mimetypes
    00087 void KMimeType::checkEssentialMimeTypes()
    00088 {
    00089   if ( s_bChecked ) // already done
    00090     return;
    00091   if ( !s_pDefaultType ) // we need a default type first
    00092     buildDefaultType();
    00093
    00094   s_bChecked = true; // must be done before building mimetypes
    00095
    00096   // No Mime-Types installed ?
    00097   // Lets do some rescue here.
    00098   if ( !KServiceTypeFactory::self()->checkMimeTypes() )
    00099   {
    00100     KMessageBoxWrapper::error( 0L, i18n( "No mime types installed!" ) );
    00101     return; // no point in going any further
    00102   }
    00103
    00104   if ( KMimeType::mimeType( "inode/directory" ) == s_pDefaultType )
    00105     errorMissingMimeType( "inode/directory" );
    00106   if ( KMimeType::mimeType( "inode/directory-locked" ) == s_pDefaultType )
    00107     errorMissingMimeType( "inode/directory-locked" );
    00108   if ( KMimeType::mimeType( "inode/blockdevice" ) == s_pDefaultType )
    00109     errorMissingMimeType( "inode/blockdevice" );
    00110   if ( KMimeType::mimeType( "inode/chardevice" ) == s_pDefaultType )
    00111     errorMissingMimeType( "inode/chardevice" );
    00112   if ( KMimeType::mimeType( "inode/socket" ) == s_pDefaultType )
    00113     errorMissingMimeType( "inode/socket" );
    00114   if ( KMimeType::mimeType( "inode/fifo" ) == s_pDefaultType )
    00115     errorMissingMimeType( "inode/fifo" );
    00116   if ( KMimeType::mimeType( "application/x-shellscript" ) == s_pDefaultType )
    00117     errorMissingMimeType( "application/x-shellscript" );
    00118   if ( KMimeType::mimeType( "application/x-executable" ) == s_pDefaultType )
    00119     errorMissingMimeType( "application/x-executable" );
    00120   if ( KMimeType::mimeType( "application/x-desktop" ) == s_pDefaultType )
    00121     errorMissingMimeType( "application/x-desktop" );
    00122 }
    00123
    00124 void KMimeType::errorMissingMimeType( const QString& _type )
    00125 {
    00126   QString tmp = i18n( "Could not find mime type\n%1" ).arg( _type );
    00127
    00128   KMessageBoxWrapper::sorry( 0, tmp );
    00129 }
    00130
    00131 KMimeType::Ptr KMimeType::mimeType( const QString& _name )
    00132 {
    00133   KServiceType * mime = KServiceTypeFactory::self()->findServiceTypeByName( _name );
    00134
    00135   if ( !mime || !mime->isType( KST_KMimeType ) )
    00136   {
    00137     delete mime;
    00138     if ( !s_pDefaultType )
    00139       buildDefaultType();
    00140     return s_pDefaultType;
    00141   }
    00142
    00143   // We got a mimetype
    00144   return KMimeType::Ptr((KMimeType *) mime);
    00145 }
    00146
    00147 KMimeType::List KMimeType::allMimeTypes()
    00148 {
    00149   return KServiceTypeFactory::self()->allMimeTypes();
    00150 }
    00151
    00152 KMimeType::Ptr KMimeType::findByURL( const KURL& _url, mode_t _mode,
    00153                                  bool _is_local_file, bool _fast_mode )
    00154 {
    00155   checkEssentialMimeTypes();
    00156   QString path = _url.path();
    00157
    00158   if ( !_fast_mode && !_is_local_file && _url.isLocalFile() )
    00159     _is_local_file = true;
    00160
    00161   if ( !_fast_mode && _is_local_file && (_mode == 0 || _mode == (mode_t)-1) )
    00162   {
    00163     struct stat buff;
    00164     if ( stat( QFile::encodeName(path), &buff ) != -1 )
    00165       _mode = buff.st_mode;
    00166   }
    00167
    00168   // Look at mode_t first
    00169   if ( S_ISDIR( _mode ) )
    00170   {
    00171     // Special hack for local files. We want to see whether we
    00172     // are allowed to enter the directory
    00173     if ( _is_local_file )
    00174     {
    00175       if ( access( QFile::encodeName(path), R_OK ) == -1 )
    00176         return mimeType( "inode/directory-locked" );
    00177     }
    00178     return mimeType( "inode/directory" );
    00179   }
    00180   if ( S_ISCHR( _mode ) )
    00181     return mimeType( "inode/chardevice" );
    00182   if ( S_ISBLK( _mode ) )
    00183     return mimeType( "inode/blockdevice" );
    00184   if ( S_ISFIFO( _mode ) )
    00185     return mimeType( "inode/fifo" );
    00186   if ( S_ISSOCK( _mode ) )
    00187     return mimeType( "inode/socket" );
    00188   // KMimeMagic can do that better for local files
    00189   if ( !_is_local_file && S_ISREG( _mode ) && ( _mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) )
    00190     return mimeType( "application/x-executable" );
    00191
    00192   QString fileName ( _url.fileName() );
    00193
    00194   static const QString& slash = KGlobal::staticQString("/");
    00195   if ( ! fileName.isNull() && !path.endsWith( slash ) )
    00196   {
    00197       // Try to find it out by looking at the filename
    00198       KMimeType::Ptr mime = KServiceTypeFactory::self()->findFromPattern( fileName );
    00199       if ( mime )
    00200       {
    00201         // Found something - can we trust it ? (e.g. don't trust *.pl over HTTP, could be anything)
    00202         if ( _is_local_file ||
    00203              KProtocolInfo::determineMimetypeFromExtension( _url.protocol() ) )
    00204           return mime;
    00205       }
    00206
    00207       static const QString& dotdesktop = KGlobal::staticQString(".desktop");
    00208       static const QString& dotkdelnk = KGlobal::staticQString(".kdelnk");
    00209       static const QString& dotdirectory = KGlobal::staticQString(".directory");
    00210
    00211       // Another filename binding, hardcoded, is .desktop:
    00212       if ( fileName.endsWith( dotdesktop ) )
    00213         return mimeType( "application/x-desktop" );
    00214       // Another filename binding, hardcoded, is .kdelnk;
    00215       // this is preserved for backwards compatibility
    00216       if ( fileName.endsWith( dotkdelnk ) )
    00217         return mimeType( "application/x-desktop" );
    00218       // .directory files are detected as x-desktop by mimemagic
    00219       // but don't have a Type= entry. Better cheat and say they are text files
    00220       if ( fileName == dotdirectory )
    00221         return mimeType( "text/plain" );
    00222     }
    00223
    00224   if ( !_is_local_file || _fast_mode )
    00225   {
    00226     if ( path.endsWith( slash ) || path.isEmpty() )
    00227     {
    00228       // We have no filename at all. Maybe the protocol has a setting for
    00229       // which mimetype this means. For HTTP we set unknown now, because
    00230       // of redirections (e.g. freshmeat downloads).
    00231       // Assume inode/directory otherwise.
    00232       QString def = KProtocolInfo::defaultMimetype( _url );
    00233       return mimeType( def.isEmpty() ? QString::fromLatin1("inode/directory") : def );
    00234     }
    00235   }
    00236
    00237   // No more chances for non local URLs
    00238   if ( !_is_local_file || _fast_mode )
    00239     return mimeType( defaultMimeType() );
    00240
    00241   // Do some magic for local files
    00242   //kdDebug(7009) << QString("Mime Type finding for '%1'").arg(path) << endl;
    00243   KMimeMagicResult* result = KMimeMagic::self()->findFileType( path );
    00244
    00245   // If we still did not find it, we must assume the default mime type
    00246   if ( !result || !result->isValid() )
    00247     return mimeType( defaultMimeType() );
    00248
    00249   // The mimemagic stuff was successful
    00250   return mimeType( result->mimeType() );
    00251 }
    00252
    00253 KMimeType::Ptr KMimeType::findByPath( const QString& path, mode_t mode, bool fast_mode )
    00254 {
    00255     KURL u;
    00256     u.setPath(path);
    00257     return findByURL( u, mode, true, fast_mode );
    00258 }
    00259
    00260 KMimeType::Ptr KMimeType::findByContent( const QByteArray &data, int *accuracy )
    00261 {
    00262   KMimeMagicResult *result = KMimeMagic::self()->findBufferType(data);
    00263   QString type = (result && result->isValid())?
    00264     result->mimeType() : defaultMimeType();
    00265   if (accuracy)
    00266       *accuracy = result->accuracy();
    00267   return mimeType( result->mimeType() );
    00268 }
    00269
    00270 KMimeType::Ptr KMimeType::findByFileContent( const QString &fileName, int *accuracy )
    00271 {
    00272   KMimeMagicResult *result = KMimeMagic::self()->findFileType(fileName);
    00273   QString type = (result && result->isValid())?
    00274     result->mimeType() : defaultMimeType();
    00275   if (accuracy)
    00276       *accuracy = result->accuracy();
    00277   return mimeType( result->mimeType() );
    00278 }
    00279
    00280 KMimeType::KMimeType( const QString & _fullpath, const QString& _type, const QString& _icon,
    00281                       const QString& _comment, const QStringList& _patterns )
    00282   : KServiceType( _fullpath, _type, _icon, _comment )
    00283 {
    00284   m_lstPatterns = _patterns;
    00285 }
    00286
    00287 KMimeType::KMimeType( const QString & _fullpath ) : KServiceType( _fullpath )
    00288 {
    00289   KDesktopFile _cfg( _fullpath, true );
    00290   init ( &_cfg );
    00291
    00292   if ( !isValid() )
    00293     kdWarning(7009) << "mimetype not valid '" << m_strName << "' (missing entry in the file ?)" << endl;
    00294 }
    00295
    00296 KMimeType::KMimeType( KDesktopFile *config ) : KServiceType( config )
    00297 {
    00298   init( config );
    00299
    00300   if ( !isValid() )
    00301     kdWarning(7009) << "mimetype not valid '" << m_strName << "' (missing entry in the file ?)" << endl;
    00302 }
    00303
    00304 void KMimeType::init( KDesktopFile * config )
    00305 {
    00306   config->setDesktopGroup();
    00307   m_lstPatterns = config->readListEntry( "Patterns", ';' );
    00308
    00309   // Read the X-KDE-AutoEmbed setting and store it in the properties map
    00310   QString XKDEAutoEmbed = QString::fromLatin1("X-KDE-AutoEmbed");
    00311   if ( config->hasKey( XKDEAutoEmbed ) )
    00312     m_mapProps.insert( XKDEAutoEmbed, QVariant( config->readBoolEntry( XKDEAutoEmbed ), 0 ) );
    00313
    00314 }
    00315
    00316 KMimeType::KMimeType( QDataStream& _str, int offset ) : KServiceType( _str, offset )
    00317 {
    00318   loadInternal( _str ); // load our specific stuff
    00319 }
    00320
    00321 void KMimeType::load( QDataStream& _str )
    00322 {
    00323   KServiceType::load( _str );
    00324   loadInternal( _str );
    00325 }
    00326
    00327 void KMimeType::loadInternal( QDataStream& _str )
    00328 {
    00329   // kdDebug(7009) << "KMimeType::load( QDataStream& ) : loading list of patterns" << endl;
    00330   _str >> m_lstPatterns;
    00331 }
    00332
    00333 void KMimeType::save( QDataStream& _str )
    00334 {
    00335   KServiceType::save( _str );
    00336   // Warning adding/removing fields here involves a binary incompatible change - update version
    00337   // number in ksycoca.h
    00338   _str << m_lstPatterns;
    00339 }
    00340
    00341 QVariant KMimeType::property( const QString& _name ) const
    00342 {
    00343   if ( _name == "Patterns" )
    00344     return QVariant( m_lstPatterns );
    00345
    00346   return KServiceType::property( _name );
    00347 }
    00348
    00349 QStringList KMimeType::propertyNames() const
    00350 {
    00351   QStringList res = KServiceType::propertyNames();
    00352   res.append( "Patterns" );
    00353
    00354   return res;
    00355 }
    00356
    00357 KMimeType::~KMimeType()
    00358 {
    00359 }
    00360
    00361 QPixmap KMimeType::pixmap( KIcon::Group _group, int _force_size, int _state,
    00362                            QString * _path ) const
    00363 {
    00364   KIconLoader *iconLoader=KGlobal::iconLoader();
    00365   QString iconName=icon( QString::null, false );
    00366   if (!iconLoader->extraDesktopThemesAdded())
    00367   {
    00368     QPixmap pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path, true );
    00369     if (!pixmap.isNull() ) return pixmap;
    00370
    00371     iconLoader->addExtraDesktopThemes();
    00372   }
    00373
    00374   return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path, false );
    00375 }
    00376
    00377 QPixmap KMimeType::pixmap( const KURL& _url, KIcon::Group _group, int _force_size,
    00378                            int _state, QString * _path ) const
    00379 {
    00380   KIconLoader *iconLoader=KGlobal::iconLoader();
    00381   QString iconName=icon( _url, _url.isLocalFile() );
    00382   if (!iconLoader->extraDesktopThemesAdded())
    00383   {
    00384     QPixmap pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path, true );
    00385     if (!pixmap.isNull() ) return pixmap;
    00386
    00387     iconLoader->addExtraDesktopThemes();
    00388   }
    00389
    00390   return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path, false );
    00391 }
    00392
    00393 QPixmap KMimeType::pixmapForURL( const KURL & _url, mode_t _mode, KIcon::Group _group,
    00394                                  int _force_size, int _state, QString * _path )
    00395 {
    00396   KIconLoader *iconLoader=KGlobal::iconLoader();
    00397   QString iconName = iconForURL( _url, _mode );
    00398
    00399   if (!iconLoader->extraDesktopThemesAdded())
    00400   {
    00401     QPixmap pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path, true );
    00402     if (!pixmap.isNull() ) return pixmap;
    00403
    00404     iconLoader->addExtraDesktopThemes();
    00405   }
    00406
    00407   return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path, false );
    00408
    00409 }
    00410
    00411 QString KMimeType::iconForURL( const KURL & _url, mode_t _mode )
    00412 {
    00413     KMimeType::Ptr mt = findByURL( _url, _mode, _url.isLocalFile(),
    00414                                    false /*HACK*/);
    00415     static const QString& unknown = KGlobal::staticQString("unknown");
    00416     QString i( mt->icon( _url, _url.isLocalFile() ));
    00417
    00418     // if we don't find an icon, maybe we can use the one for the protocol
    00419     if ( i == unknown || i.isEmpty() || mt->name() == defaultMimeType()) {
    00420         i = favIconForURL( _url ); // maybe there is a favicon?
    00421
    00422         if ( i.isEmpty() )
    00423             i = KProtocolInfo::icon( _url.protocol() );
    00424     }
    00425     return i;
    00426 }
    00427
    00428 QString KMimeType::favIconForURL( const KURL& url )
    00429 {
    00430     // this method will be called quite often, so better not read the config
    00431     // again and again.
    00432     static bool useFavIcons = true;
    00433     static bool check = true;
    00434     if ( check ) {
    00435         check = false;
    00436         KConfig *config = KGlobal::config();
    00437         KConfigGroupSaver cs( config, "HTML Settings" );
    00438         useFavIcons = config->readBoolEntry( "EnableFavicon", true );
    00439     }
    00440
    00441     if ( url.isLocalFile() || !url.protocol().startsWith("http")
    00442          || !useFavIcons )
    00443         return QString::null;
    00444
    00445     QByteArray data;
    00446     QDataStream str(data, IO_WriteOnly);
    00447     str << url;
    00448     QCString replyType;
    00449     QByteArray reply;
    00450     kapp->dcopClient()->call("kded", "favicons", "iconForURL(KURL)", data,
    00451                              replyType, reply);
    00452     if (replyType == "QString")
    00453     {
    00454         QDataStream replyStr(reply, IO_ReadOnly);
    00455         QString result;
    00456         replyStr >> result;
    00457         return result;
    00458     }
    00459
    00460     return QString::null;
    00461 }
    00462
    00463
    00464
    00465 /*******************************************************
    00466  *
    00467  * KFolderType
    00468  *
    00469  ******************************************************/
    00470
    00471 QString KFolderType::icon( const QString& _url, bool _is_local ) const
    00472 {
    00473   if ( !_is_local || _url.isEmpty() )
    00474     return KMimeType::icon( _url, _is_local );
    00475
    00476   return KFolderType::icon( KURL(_url), _is_local );
    00477 }
    00478
    00479 QString KFolderType::icon( const KURL& _url, bool _is_local ) const
    00480 {
    00481   if ( !_is_local )
    00482     return KMimeType::icon( _url, _is_local );
    00483
    00484   KURL u( _url );
    00485   u.addPath( ".directory" );
    00486
    00487   QString icon;
    00488   // using KStandardDirs as this one checks for path beeing
    00489   // a file instead of a directory
    00490   if ( KStandardDirs::exists( u.path() ) )
    00491   {
    00492     KSimpleConfig cfg( u.path(), true );
    00493     cfg.setDesktopGroup();
    00494     icon = cfg.readEntry( "Icon" );
    00495     QString empty_icon = cfg.readEntry( "EmptyIcon" );
    00496
    00497     if ( !empty_icon.isEmpty() )
    00498     {
    00499       bool isempty = false;
    00500       DIR *dp = 0L;
    00501       struct dirent *ep;
    00502       dp = opendir( QFile::encodeName(_url.path()) );
    00503       if ( dp )
    00504       {
    00505         ep=readdir( dp );
    00506         ep=readdir( dp );      // ignore '.' and '..' dirent
    00507         if ( (ep=readdir( dp )) == 0L ) // third file is NULL entry -> empty directory
    00508           isempty = true;
    00509         // if third file is .directory and no fourth file -> empty directory
    00510         if (!isempty && !strcmp(ep->d_name, ".directory"))
    00511           isempty = (readdir(dp) == 0L);
    00512         closedir( dp );
    00513       }
    00514
    00515       if ( isempty )
    00516         return empty_icon;
    00517     }
    00518   }
    00519
    00520   if ( icon.isEmpty() )
    00521     return KMimeType::icon( _url, _is_local );
    00522
    00523   return icon;
    00524 }
    00525
    00526 QString KFolderType::comment( const QString& _url, bool _is_local ) const
    00527 {
    00528   if ( !_is_local || _url.isEmpty() )
    00529     return KMimeType::comment( _url, _is_local );
    00530
    00531   return KFolderType::comment( KURL(_url), _is_local );
    00532 }
    00533
    00534 QString KFolderType::comment( const KURL& _url, bool _is_local ) const
    00535 {
    00536   if ( !_is_local )
    00537     return KMimeType::comment( _url, _is_local );
    00538
    00539   KURL u( _url );
    00540   u.addPath( ".directory" );
    00541
    00542   KSimpleConfig cfg( u.path(), true );
    00543   cfg.setDesktopGroup();
    00544   QString comment = cfg.readEntry( "Comment" );
    00545   if ( comment.isEmpty() )
    00546     return KMimeType::comment( _url, _is_local );
    00547
    00548   return comment;
    00549 }
    00550
    00551 /*******************************************************
    00552  *
    00553  * KDEDesktopMimeType
    00554  *
    00555  ******************************************************/
    00556
    00557 QString KDEDesktopMimeType::icon( const QString& _url, bool _is_local ) const
    00558 {
    00559   if ( !_is_local || _url.isEmpty() )
    00560     return KMimeType::icon( _url, _is_local );
    00561
    00562   KURL u( _url );
    00563   return icon( u, _is_local );
    00564 }
    00565
    00566 QString KDEDesktopMimeType::icon( const KURL& _url, bool _is_local ) const
    00567 {
    00568   if ( !_is_local )
    00569     return KMimeType::icon( _url, _is_local );
    00570
    00571   KSimpleConfig cfg( _url.path(), true );
    00572   cfg.setDesktopGroup();
    00573   QString icon = cfg.readEntry( "Icon" );
    00574   QString type = cfg.readEntry( "Type" );
    00575
    00576   if ( type == "FSDevice" || type == "FSDev") // need to provide FSDev for
    00577                                               // backwards compatibility
    00578   {
    00579     QString unmount_icon = cfg.readEntry( "UnmountIcon" );
    00580     QString dev = cfg.readEntry( "Dev" );
    00581     if ( !icon.isEmpty() && !unmount_icon.isEmpty() && !dev.isEmpty() )
    00582     {
    00583       QString mp = KIO::findDeviceMountPoint( dev );
    00584       // Is the device not mounted ?
    00585       if ( mp.isNull() )
    00586         return unmount_icon;
    00587     }
    00588   }
    00589
    00590   if ( icon.isEmpty() )
    00591     return KMimeType::icon( _url, _is_local );
    00592
    00593   return icon;
    00594 }
    00595
    00596 QPixmap KDEDesktopMimeType::pixmap( const KURL& _url, KIcon::Group _group, int _force_size,
    00597                                     int _state, QString * _path ) const
    00598 {
    00599   QString _icon = icon( _url, _url.isLocalFile() );
    00600   QPixmap pix = KGlobal::iconLoader()->loadIcon( _icon, _group,
    00601         _force_size, _state, _path, false );
    00602   if ( pix.isNull() )
    00603       pix = KGlobal::iconLoader()->loadIcon( "unknown", _group,
    00604         _force_size, _state, _path, false );
    00605   return pix;
    00606 }
    00607
    00608 QString KDEDesktopMimeType::comment( const QString& _url, bool _is_local ) const
    00609 {
    00610   if ( !_is_local || _url.isEmpty() )
    00611     return KMimeType::comment( _url, _is_local );
    00612
    00613   KURL u( _url );
    00614   return comment( u, _is_local );
    00615 }
    00616
    00617 QString KDEDesktopMimeType::comment( const KURL& _url, bool _is_local ) const
    00618 {
    00619   if ( !_is_local )
    00620     return KMimeType::comment( _url, _is_local );
    00621
    00622   KSimpleConfig cfg( _url.path(), true );
    00623   cfg.setDesktopGroup();
    00624   QString comment = cfg.readEntry( "Comment" );
    00625   if ( comment.isEmpty() )
    00626     return KMimeType::comment( _url, _is_local );
    00627
    00628   return comment;
    00629 }
    00630
    00631 pid_t KDEDesktopMimeType::run( const KURL& u, bool _is_local )
    00632 {
    00633   // It might be a security problem to run external untrusted desktop
    00634   // entry files
    00635   if ( !_is_local )
    00636     return 0;
    00637
    00638   KSimpleConfig cfg( u.path(), true );
    00639   cfg.setDesktopGroup();
    00640   QString type = cfg.readEntry( "Type" );
    00641   if ( type.isEmpty() )
    00642   {
    00643     QString tmp = i18n("The desktop entry file %1 "
    00644                        "has no Type=... entry.").arg(u.path() );
    00645     KMessageBoxWrapper::error( 0, tmp);
    00646     return 0;
    00647   }
    00648
    00649   //kdDebug(7009) << "TYPE = " << type.data() << endl;
    00650
    00651   if ( type == "FSDevice" )
    00652     return runFSDevice( u, cfg );
    00653   else if ( type == "Application" )
    00654     return runApplication( u, u.path() );
    00655   else if ( type == "Link" )
    00656   {
    00657     cfg.setDollarExpansion( true ); // for URL=file:$HOME (Simon)
    00658     return runLink( u, cfg );
    00659   }
    00660   else if ( type == "MimeType" )
    00661     return runMimeType( u, cfg );
    00662
    00663
    00664   QString tmp = i18n("The desktop entry of type\n%1\nis unknown.").arg( type );
    00665   KMessageBoxWrapper::error( 0, tmp);
    00666
    00667   return 0;
    00668 }
    00669
    00670 pid_t KDEDesktopMimeType::runFSDevice( const KURL& _url, const KSimpleConfig &cfg )
    00671 {
    00672   pid_t retval = 0;
    00673
    00674   QString dev = cfg.readEntry( "Dev" );
    00675
    00676   if ( dev.isEmpty() )
    00677   {
    00678     QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( _url.path() );
    00679     KMessageBoxWrapper::error( 0, tmp);
    00680     return retval;
    00681   }
    00682
    00683   QString mp = KIO::findDeviceMountPoint( dev );
    00684   // Is the device already mounted ?
    00685   if ( !mp.isNull() )
    00686   {
    00687     KURL mpURL;
    00688     mpURL.setPath( mp );
    00689     // Open a new window
    00690     retval = KRun::runURL( mpURL, QString::fromLatin1("inode/directory") );
    00691   }
    00692   else
    00693   {
    00694     bool ro = cfg.readBoolEntry( "ReadOnly", false );
    00695     QString fstype = cfg.readEntry( "FSType" );
    00696     QString point = cfg.readEntry( "MountPoint" );
    00697     (void) new KAutoMount( ro, fstype, dev, point, _url.path() );
    00698     retval = -1; // we don't want to return 0, but we don't want to return a pid
    00699   }
    00700
    00701   return retval;
    00702 }
    00703
    00704 pid_t KDEDesktopMimeType::runApplication( const KURL& , const QString & _serviceFile )
    00705 {
    00706   KService s( _serviceFile );
    00707   if ( !s.isValid() )
    00708     // The error message was already displayed, so we can just quit here
    00709     return 0;
    00710
    00711   KURL::List lst;
    00712   return KRun::run( s, lst );
    00713 }
    00714
    00715 pid_t KDEDesktopMimeType::runLink( const KURL& _url, const KSimpleConfig &cfg )
    00716 {
    00717   QString url = cfg.readPathEntry( "URL" );
    00718   if ( url.isEmpty() )
    00719   {
    00720     QString tmp = i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.").arg( _url.url() );
    00721     KMessageBoxWrapper::error( 0, tmp );
    00722     return 0;
    00723   }
    00724
    00725   KRun* run = new KRun( url );
    00726
    00727   // X-KDE-LastOpenedWith holds the service desktop entry name that
    00728   // was should be preferred for opening this URL if possible.
    00729   // This is used by the Recent Documents menu for instance.
    00730   QString lastOpenedWidth = cfg.readEntry( "X-KDE-LastOpenedWith" );
    00731   if ( !lastOpenedWidth.isEmpty() )
    00732       run->setPreferredService( lastOpenedWidth );
    00733
    00734   return -1; // we don't want to return 0, but we don't want to return a pid
    00735 }
    00736
    00737 pid_t KDEDesktopMimeType::runMimeType( const KURL& url , const KSimpleConfig & )
    00738 {
    00739   // Hmm, can't really use keditfiletype since we might be looking
    00740   // at the global file, or at a file not in share/mimelnk...
    00741
    00742   QStringList args;
    00743   args << "openProperties";
    00744   args << url.path();
    00745
    00746   int pid;
    00747   if ( !KApplication::kdeinitExec("kfmclient", args, 0, &pid) )
    00748       return pid;
    00749
    00750   KProcess p;
    00751   p << "kfmclient" << args;
    00752   p.start(KProcess::DontCare);
    00753   return p.getPid();
    00754 }
    00755
    00756 QValueList<KDEDesktopMimeType::Service> KDEDesktopMimeType::builtinServices( const KURL& _url )
    00757 {
    00758   QValueList<Service> result;
    00759
    00760   if ( !_url.isLocalFile() )
    00761     return result;
    00762
    00763   KSimpleConfig cfg( _url.path(), true );
    00764   cfg.setDesktopGroup();
    00765   QString type = cfg.readEntry( "Type" );
    00766
    00767   if ( type.isEmpty() )
    00768     return result;
    00769
    00770   if ( type == "FSDevice" )
    00771   {
    00772     QString dev = cfg.readEntry( "Dev" );
    00773     if ( dev.isEmpty() )
    00774     {
    00775       QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( _url.path() );
    00776       KMessageBoxWrapper::error( 0, tmp);
    00777     }
    00778     else
    00779     {
    00780       QString mp = KIO::findDeviceMountPoint( dev );
    00781       // not mounted ?
    00782       if ( mp.isEmpty() )
    00783       {
    00784         Service mount;
    00785         mount.m_strName = i18n("Mount");
    00786         mount.m_type = ST_MOUNT;
    00787         result.append( mount );
    00788       }
    00789       else
    00790       {
    00791         Service unmount;
    00792 #ifdef HAVE_VOLMGT
    00793         /*
    00794          *  Solaris' volume management can only umount+eject
    00795          */
    00796         unmount.m_strName = i18n("Eject");
    00797 #else
    00798         unmount.m_strName = i18n("Unmount");
    00799 #endif
    00800         unmount.m_type = ST_UNMOUNT;
    00801         result.append( unmount );
    00802       }
    00803     }
    00804   }
    00805
    00806   return result;
    00807 }
    00808
    00809 QValueList<KDEDesktopMimeType::Service> KDEDesktopMimeType::userDefinedServices( const QString& path, bool bLocalFiles )
    00810 {
    00811   QValueList<Service> result;
    00812
    00813   KSimpleConfig cfg( path, true );
    00814
    00815   cfg.setDesktopGroup();
    00816
    00817   if ( !cfg.hasKey( "Actions" ) )
    00818     return result;
    00819
    00820   if ( cfg.hasKey( "TryExec" ) )
    00821   {
    00822       QString tryexec = cfg.readPathEntry( "TryExec" );
    00823       QString exe =  KStandardDirs::findExe( tryexec );
    00824       if (exe.isEmpty()) {
    00825           return result;
    00826       }
    00827   }
    00828
    00829   QStringList keys = cfg.readListEntry( "Actions", ';' ); //the desktop standard defines ";" as separator!
    00830
    00831   if ( keys.count() == 0 )
    00832     return result;
    00833
    00834   QStringList::ConstIterator it = keys.begin();
    00835   QStringList::ConstIterator end = keys.end();
    00836   for ( ; it != end; ++it )
    00837   {
    00838     //kdDebug(7009) << "CURRENT KEY = " << (*it) << endl;
    00839
    00840     QString group = *it;
    00841     group.prepend( "Desktop Action " );
    00842
    00843     bool bInvalidMenu = false;
    00844
    00845     if ( cfg.hasGroup( group ) )
    00846     {
    00847       cfg.setGroup( group );
    00848
    00849       if ( !cfg.hasKey( "Name" ) || !cfg.hasKey( "Exec" ) )
    00850         bInvalidMenu = true;
    00851       else
    00852       {
    00853         QString exec = cfg.readPathEntry( "Exec" );
    00854         if ( bLocalFiles || exec.contains("%U") || exec.contains("%u") )
    00855         {
    00856           Service s;
    00857           s.m_strName = cfg.readEntry( "Name" );
    00858           s.m_strIcon = cfg.readEntry( "Icon" );
    00859           s.m_strExec = exec;
    00860           s.m_type = ST_USER_DEFINED;
    00861           s.m_display = !cfg.readBoolEntry( "NoDisplay" );
    00862           result.append( s );
    00863         }
    00864       }
    00865     }
    00866     else
    00867       bInvalidMenu = true;
    00868
    00869     if ( bInvalidMenu )
    00870     {
    00871       QString tmp = i18n("The desktop entry file\n%1\n has an invalid menu entry\n%2.").arg( path ).arg( *it );
    00872       KMessageBoxWrapper::error( 0, tmp );
    00873     }
    00874   }
    00875
    00876   return result;
    00877 }
    00878
    00879 void KDEDesktopMimeType::executeService( const QString& _url, KDEDesktopMimeType::Service& _service )
    00880 {
    00881     KURL u;
    00882     u.setPath(_url);
    00883     KURL::List lst;
    00884     lst.append( _url );
    00885     executeService( lst, _service );
    00886 }
    00887
    00888 void KDEDesktopMimeType::executeService( const KURL::List& urls, KDEDesktopMimeType::Service& _service )
    00889 {
    00890   //kdDebug(7009) << "EXECUTING Service " << _service.m_strName << endl;
    00891
    00892   if ( _service.m_type == ST_USER_DEFINED )
    00893   {
    00894     kdDebug() << "KDEDesktopMimeType::executeService " << _service.m_strName
    00895               << " first url's path=" << urls.first().path() << " exec=" << _service.m_strExec << endl;
    00896     KRun::run( _service.m_strExec, urls, _service.m_strName, _service.m_strIcon, _service.m_strIcon );
    00897     // The action may update the desktop file. Example: eject unmounts (#5129).
    00898     KDirNotify_stub allDirNotify("*", "KDirNotify*");
    00899     allDirNotify.FilesChanged( urls );
    00900     return;
    00901   }
    00902   else if ( _service.m_type == ST_MOUNT || _service.m_type == ST_UNMOUNT )
    00903   {
    00904     Q_ASSERT( urls.count() == 1 );
    00905     QString path = urls.first().path();
    00906     //kdDebug(7009) << "MOUNT&UNMOUNT" << endl;
    00907
    00908     KSimpleConfig cfg( path, true );
    00909     cfg.setDesktopGroup();
    00910     QString dev = cfg.readEntry( "Dev" );
    00911     if ( dev.isEmpty() )
    00912     {
    00913       QString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( path );
    00914       KMessageBoxWrapper::error( 0, tmp );
    00915       return;
    00916     }
    00917     QString mp = KIO::findDeviceMountPoint( dev );
    00918
    00919     if ( _service.m_type == ST_MOUNT )
    00920     {
    00921       // Already mounted? Strange, but who knows ...
    00922       if ( !mp.isEmpty() )
    00923       {
    00924         kdDebug(7009) << "ALREADY Mounted" << endl;
    00925         return;
    00926       }
    00927
    00928       bool ro = cfg.readBoolEntry( "ReadOnly", false );
    00929       QString fstype = cfg.readEntry( "FSType" );
    00930       if ( fstype == "Default" ) // KDE-1 thing
    00931           fstype = QString::null;
    00932       QString point = cfg.readEntry( "MountPoint" );
    00933       (void)new KAutoMount( ro, fstype, dev, point, path, false );
    00934     }
    00935     else if ( _service.m_type == ST_UNMOUNT )
    00936     {
    00937       // Not mounted? Strange, but who knows ...
    00938       if ( mp.isEmpty() )
    00939         return;
    00940
    00941       (void)new KAutoUnmount( mp, path );
    00942     }
    00943   }
    00944   else
    00945     assert( 0 );
    00946 }
    00947
    00948 const QString & KMimeType::defaultMimeType()
    00949 {
    00950     static const QString & s_strDefaultMimeType =
    00951         KGlobal::staticQString( "application/octet-stream" );
    00952     return s_strDefaultMimeType;
    00953 }
    00954
    00955 void KMimeType::virtual_hook( int id, void* data )
    00956 { KServiceType::virtual_hook( id, data ); }
    00957
    00958 void KFolderType::virtual_hook( int id, void* data )
    00959 { KMimeType::virtual_hook( id, data ); }
    00960
    00961 void KDEDesktopMimeType::virtual_hook( int id, void* data )
    00962 { KMimeType::virtual_hook( id, data ); }
    00963
    00964 void KExecMimeType::virtual_hook( int id, void* data )
    00965 { KMimeType::virtual_hook( id, data ); }
    00966
    00967 #include "kmimetyperesolver.moc"
    00968

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:13:43 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001