/* This file is part of the KDE libraries
* Copyright ( C ) 1999 Waldo Bastian < bastian @ kde . org >
* David Faure < faure @ kde . org >
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation ;
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public License
* along with this library ; see the file COPYING . LIB . If not , write to
* the Free Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
* Boston , MA 02110 - 1301 , USA .
* */
// $Id$
# include <config.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <assert.h>
# include <dirent.h>
# include <errno.h>
# include <stddef.h>
# include <unistd.h>
# include <stdlib.h>
# include <kprotocolinfo.h>
# include <tdeio/global.h>
# include "kmimetype.h"
# include "kservicetypefactory.h"
# include "kmimemagic.h"
# include "kservice.h"
# include "krun.h"
# include "kautomount.h"
# include <kdirnotify_stub.h>
# include <tqstring.h>
# include <tqfile.h>
# include <kmessageboxwrapper.h>
# include <dcopclient.h>
# include <dcopref.h>
# include <tdeapplication.h>
# include <kprocess.h>
# include <kdebug.h>
# include <kdesktopfile.h>
# include <kdirwatch.h>
# include <kiconloader.h>
# include <tdelocale.h>
# include <ksimpleconfig.h>
# include <kstandarddirs.h>
# include <kurl.h>
# include <tdesycoca.h>
# include <kde_file.h>
template class TDESharedPtr < KMimeType > ;
template class TQValueList < KMimeType : : Ptr > ;
KMimeType : : Ptr KMimeType : : s_pDefaultType = 0L ;
bool KMimeType : : s_bChecked = false ;
void KMimeType : : buildDefaultType ( )
{
assert ( ! s_pDefaultType ) ;
// Try to find the default type
KServiceType * mime = KServiceTypeFactory : : self ( ) - >
findServiceTypeByName ( defaultMimeType ( ) ) ;
if ( mime & & mime - > isType ( KST_KMimeType ) )
{
s_pDefaultType = KMimeType : : Ptr ( ( KMimeType * ) mime ) ;
}
else
{
errorMissingMimeType ( defaultMimeType ( ) ) ;
TDEStandardDirs stdDirs ;
TQString sDefaultMimeType = stdDirs . resourceDirs ( " mime " ) . first ( ) + defaultMimeType ( ) + " .desktop " ;
s_pDefaultType = new KMimeType ( sDefaultMimeType , defaultMimeType ( ) ,
" unknown " , " mime " , TQStringList ( ) ) ;
}
}
KMimeType : : Ptr KMimeType : : defaultMimeTypePtr ( )
{
if ( ! s_pDefaultType ) // we need a default type first
buildDefaultType ( ) ;
return s_pDefaultType ;
}
// Check for essential mimetypes
void KMimeType : : checkEssentialMimeTypes ( )
{
if ( s_bChecked ) // already done
return ;
if ( ! s_pDefaultType ) // we need a default type first
buildDefaultType ( ) ;
s_bChecked = true ; // must be done before building mimetypes
// No Mime-Types installed ?
// Lets do some rescue here.
if ( ! KServiceTypeFactory : : self ( ) - > checkMimeTypes ( ) )
{
KMessageBoxWrapper : : error ( 0L , i18n ( " No mime types installed. " ) ) ;
return ; // no point in going any further
}
if ( KMimeType : : mimeType ( " inode/directory " ) = = s_pDefaultType )
errorMissingMimeType ( " inode/directory " ) ;
if ( KMimeType : : mimeType ( " inode/directory-locked " ) = = s_pDefaultType )
errorMissingMimeType ( " inode/directory-locked " ) ;
if ( KMimeType : : mimeType ( " inode/blockdevice " ) = = s_pDefaultType )
errorMissingMimeType ( " inode/blockdevice " ) ;
if ( KMimeType : : mimeType ( " inode/chardevice " ) = = s_pDefaultType )
errorMissingMimeType ( " inode/chardevice " ) ;
if ( KMimeType : : mimeType ( " inode/socket " ) = = s_pDefaultType )
errorMissingMimeType ( " inode/socket " ) ;
if ( KMimeType : : mimeType ( " inode/fifo " ) = = s_pDefaultType )
errorMissingMimeType ( " inode/fifo " ) ;
if ( KMimeType : : mimeType ( " application/x-shellscript " ) = = s_pDefaultType )
errorMissingMimeType ( " application/x-shellscript " ) ;
if ( KMimeType : : mimeType ( " application/x-executable " ) = = s_pDefaultType )
errorMissingMimeType ( " application/x-executable " ) ;
if ( KMimeType : : mimeType ( " application/x-desktop " ) = = s_pDefaultType )
errorMissingMimeType ( " application/x-desktop " ) ;
}
void KMimeType : : errorMissingMimeType ( const TQString & _type )
{
TQString tmp = i18n ( " Could not find mime type \n %1 " ) . arg ( _type ) ;
KMessageBoxWrapper : : sorry ( 0 , tmp ) ;
}
KMimeType : : Ptr KMimeType : : mimeType ( const TQString & _name )
{
KServiceType * mime = KServiceTypeFactory : : self ( ) - > findServiceTypeByName ( _name ) ;
if ( ! mime | | ! mime - > isType ( KST_KMimeType ) )
{
// When building tdesycoca, findServiceTypeByName doesn't create an object
// but returns one from a dict.
if ( ! KSycoca : : self ( ) - > isBuilding ( ) )
delete mime ;
if ( ! s_pDefaultType )
buildDefaultType ( ) ;
return s_pDefaultType ;
}
// We got a mimetype
return KMimeType : : Ptr ( ( KMimeType * ) mime ) ;
}
KMimeType : : List KMimeType : : allMimeTypes ( )
{
return KServiceTypeFactory : : self ( ) - > allMimeTypes ( ) ;
}
KMimeType : : Ptr KMimeType : : findByURL ( const KURL & _url , mode_t _mode ,
bool _is_local_file , bool _fast_mode )
{
checkEssentialMimeTypes ( ) ;
TQString path = _url . path ( ) ;
if ( ! _fast_mode & & ! _is_local_file & & _url . isLocalFile ( ) )
_is_local_file = true ;
if ( ! _fast_mode & & _is_local_file & & ( _mode = = 0 | | _mode = = ( mode_t ) - 1 ) )
{
KDE_struct_stat buff ;
if ( KDE_stat ( TQFile : : encodeName ( path ) , & buff ) ! = - 1 )
_mode = buff . st_mode ;
}
// Look at mode_t first
if ( S_ISDIR ( _mode ) )
{
// Special hack for local files. We want to see whether we
// are allowed to enter the directory
if ( _is_local_file )
{
if ( access ( TQFile : : encodeName ( path ) , R_OK ) = = - 1 )
return mimeType ( " inode/directory-locked " ) ;
}
return mimeType ( " inode/directory " ) ;
}
if ( S_ISCHR ( _mode ) )
return mimeType ( " inode/chardevice " ) ;
if ( S_ISBLK ( _mode ) )
return mimeType ( " inode/blockdevice " ) ;
if ( S_ISFIFO ( _mode ) )
return mimeType ( " inode/fifo " ) ;
if ( S_ISSOCK ( _mode ) )
return mimeType ( " inode/socket " ) ;
// KMimeMagic can do that better for local files
if ( ! _is_local_file & & S_ISREG ( _mode ) & & ( _mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) )
return mimeType ( " application/x-executable " ) ;
TQString fileName ( _url . fileName ( ) ) ;
static const TQString & slash = TDEGlobal : : staticQString ( " / " ) ;
if ( ! fileName . isNull ( ) & & ! path . endsWith ( slash ) )
{
// Try to find it out by looking at the filename
KMimeType : : Ptr mime = KServiceTypeFactory : : self ( ) - > findFromPattern ( fileName ) ;
if ( mime )
{
// Found something - can we trust it ? (e.g. don't trust *.pl over HTTP, could be anything)
if ( _is_local_file | | _url . hasSubURL ( ) | | // Explicitly trust suburls
KProtocolInfo : : determineMimetypeFromExtension ( _url . protocol ( ) ) )
{
if ( _is_local_file & & ! _fast_mode ) {
if ( mime - > patternsAccuracy ( ) < 100 )
{
KMimeMagicResult * result =
KMimeMagic : : self ( ) - > findFileType ( path ) ;
if ( result & & result - > isValid ( ) & & result - > accuracy ( ) > 0 ) {
KMimeType : : Ptr resultMime = mimeType ( result - > mimeType ( ) ) ;
if ( resultMime - > patternsAccuracy ( ) > 0 ) {
return resultMime ;
}
}
}
}
return mime ;
}
}
static const TQString & dotdesktop = TDEGlobal : : staticQString ( " .desktop " ) ;
static const TQString & dotkdelnk = TDEGlobal : : staticQString ( " .kdelnk " ) ;
static const TQString & dotdirectory = TDEGlobal : : staticQString ( " .directory " ) ;
// Another filename binding, hardcoded, is .desktop:
if ( fileName . endsWith ( dotdesktop ) )
return mimeType ( " application/x-desktop " ) ;
// Another filename binding, hardcoded, is .kdelnk;
// this is preserved for backwards compatibility
if ( fileName . endsWith ( dotkdelnk ) )
return mimeType ( " application/x-desktop " ) ;
// .directory files are detected as x-desktop by mimemagic
// but don't have a Type= entry. Better cheat and say they are text files
if ( fileName = = dotdirectory )
return mimeType ( " text/plain " ) ;
}
if ( ! _is_local_file | | _fast_mode )
{
TQString def = KProtocolInfo : : defaultMimetype ( _url ) ;
if ( ! def . isEmpty ( ) & & def ! = defaultMimeType ( ) )
{
// The protocol says it always returns a given mimetype (e.g. text/html for "man:")
return mimeType ( def ) ;
}
if ( path . endsWith ( slash ) | | path . isEmpty ( ) )
{
// We have no filename at all. Maybe the protocol has a setting for
// which mimetype this means (e.g. directory).
// For HTTP (def==defaultMimeType()) we don't assume anything,
// because of redirections (e.g. freshmeat downloads).
if ( def . isEmpty ( ) )
{
// Assume inode/directory, if the protocol supports listing.
if ( KProtocolInfo : : supportsListing ( _url ) )
return mimeType ( TQString : : fromLatin1 ( " inode/directory " ) ) ;
else
return defaultMimeTypePtr ( ) ; // == 'no idea', e.g. for "data:,foo/"
}
}
// No more chances for non local URLs
return defaultMimeTypePtr ( ) ;
}
// Do some magic for local files
//kdDebug(7009) << TQString("Mime Type finding for '%1'").arg(path) << endl;
KMimeMagicResult * result = KMimeMagic : : self ( ) - > findFileType ( path ) ;
// If we still did not find it, we must assume the default mime type
if ( ! result | | ! result - > isValid ( ) )
return defaultMimeTypePtr ( ) ;
// The mimemagic stuff was successful
return mimeType ( result - > mimeType ( ) ) ;
}
KMimeType : : Ptr KMimeType : : findByURL ( const KURL & _url , mode_t _mode ,
bool _is_local_file , bool _fast_mode ,
bool * accurate )
{
KMimeType : : Ptr mime = findByURL ( _url , _mode , _is_local_file , _fast_mode ) ;
if ( accurate ) * accurate = ! ( _fast_mode ) | | ( ( mime - > patternsAccuracy ( ) = = 100 ) & & mime ! = defaultMimeTypePtr ( ) ) ;
return mime ;
}
KMimeType : : Ptr KMimeType : : diagnoseFileName ( const TQString & fileName , TQString & pattern )
{
return KServiceTypeFactory : : self ( ) - > findFromPattern ( fileName , & pattern ) ;
}
KMimeType : : Ptr KMimeType : : findByPath ( const TQString & path , mode_t mode , bool fast_mode )
{
KURL u ;
u . setPath ( path ) ;
return findByURL ( u , mode , true , fast_mode ) ;
}
KMimeType : : Ptr KMimeType : : findByContent ( const TQByteArray & data , int * accuracy )
{
KMimeMagicResult * result = KMimeMagic : : self ( ) - > findBufferType ( data ) ;
if ( accuracy )
* accuracy = result - > accuracy ( ) ;
return mimeType ( result - > mimeType ( ) ) ;
}
KMimeType : : Ptr KMimeType : : findByFileContent ( const TQString & fileName , int * accuracy )
{
KMimeMagicResult * result = KMimeMagic : : self ( ) - > findFileType ( fileName ) ;
if ( accuracy )
* accuracy = result - > accuracy ( ) ;
return mimeType ( result - > mimeType ( ) ) ;
}
# define GZIP_MAGIC1 0x1f
# define GZIP_MAGIC2 0x8b
KMimeType : : Format KMimeType : : findFormatByFileContent ( const TQString & fileName )
{
KMimeType : : Format result ;
result . compression = Format : : NoCompression ;
KMimeType : : Ptr mime = findByPath ( fileName ) ;
result . text = mime - > name ( ) . startsWith ( " text/ " ) ;
TQVariant v = mime - > property ( " X-TDE-text " ) ;
if ( v . isValid ( ) )
result . text = v . toBool ( ) ;
if ( mime - > name ( ) . startsWith ( " inode/ " ) )
return result ;
TQFile f ( fileName ) ;
if ( f . open ( IO_ReadOnly ) )
{
unsigned char buf [ 10 + 1 ] ;
int l = f . readBlock ( ( char * ) buf , 10 ) ;
if ( ( l > 2 ) & & ( buf [ 0 ] = = GZIP_MAGIC1 ) & & ( buf [ 1 ] = = GZIP_MAGIC2 ) )
result . compression = Format : : GZipCompression ;
}
return result ;
}
KMimeType : : KMimeType ( const TQString & _fullpath , const TQString & _type , const TQString & _icon ,
const TQString & _comment , const TQStringList & _patterns )
: KServiceType ( _fullpath , _type , _icon , _comment )
{
m_lstPatterns = _patterns ;
}
KMimeType : : KMimeType ( const TQString & _fullpath ) : KServiceType ( _fullpath )
{
KDesktopFile _cfg ( _fullpath , true ) ;
init ( & _cfg ) ;
if ( ! isValid ( ) )
kdWarning ( 7009 ) < < " mimetype not valid ' " < < m_strName < < " ' (missing entry in the file ?) " < < endl ;
}
KMimeType : : KMimeType ( KDesktopFile * config ) : KServiceType ( config )
{
init ( config ) ;
if ( ! isValid ( ) )
kdWarning ( 7009 ) < < " mimetype not valid ' " < < m_strName < < " ' (missing entry in the file ?) " < < endl ;
}
void KMimeType : : init ( KDesktopFile * config )
{
config - > setDesktopGroup ( ) ;
m_lstPatterns = config - > readListEntry ( " Patterns " , ' ; ' ) ;
// Read the X-TDE-AutoEmbed setting and store it in the properties map
TQString XKDEAutoEmbed = TQString : : fromLatin1 ( " X-TDE-AutoEmbed " ) ;
if ( config - > hasKey ( XKDEAutoEmbed ) )
m_mapProps . insert ( XKDEAutoEmbed , TQVariant ( config - > readBoolEntry ( XKDEAutoEmbed ) ) ) ;
TQString XKDEText = TQString : : fromLatin1 ( " X-TDE-text " ) ;
if ( config - > hasKey ( XKDEText ) )
m_mapProps . insert ( XKDEText , config - > readBoolEntry ( XKDEText ) ) ;
TQString XKDEIsAlso = TQString : : fromLatin1 ( " X-TDE-IsAlso " ) ;
if ( config - > hasKey ( XKDEIsAlso ) ) {
TQString inherits = config - > readEntry ( XKDEIsAlso ) ;
if ( inherits ! = name ( ) )
m_mapProps . insert ( XKDEIsAlso , inherits ) ;
else
kdWarning ( 7009 ) < < " Error: " < < inherits < < " inherits from itself!!!! " < < endl ;
}
TQString XKDEPatternsAccuracy = TQString : : fromLatin1 ( " X-TDE-PatternsAccuracy " ) ;
if ( config - > hasKey ( XKDEPatternsAccuracy ) )
m_mapProps . insert ( XKDEPatternsAccuracy , config - > readEntry ( XKDEPatternsAccuracy ) ) ;
}
KMimeType : : KMimeType ( TQDataStream & _str , int offset ) : KServiceType ( _str , offset )
{
loadInternal ( _str ) ; // load our specific stuff
}
void KMimeType : : load ( TQDataStream & _str )
{
KServiceType : : load ( _str ) ;
loadInternal ( _str ) ;
}
void KMimeType : : loadInternal ( TQDataStream & _str )
{
// kdDebug(7009) << "KMimeType::load( TQDataStream& ) : loading list of patterns" << endl;
_str > > m_lstPatterns ;
}
void KMimeType : : save ( TQDataStream & _str )
{
KServiceType : : save ( _str ) ;
// Warning adding/removing fields here involves a binary incompatible change - update version
// number in tdesycoca.h
_str < < m_lstPatterns ;
}
TQVariant KMimeType : : property ( const TQString & _name ) const
{
if ( _name = = " Patterns " )
return TQVariant ( m_lstPatterns ) ;
return KServiceType : : property ( _name ) ;
}
TQStringList KMimeType : : propertyNames ( ) const
{
TQStringList res = KServiceType : : propertyNames ( ) ;
res . append ( " Patterns " ) ;
return res ;
}
KMimeType : : ~ KMimeType ( )
{
}
TQPixmap KMimeType : : pixmap ( TDEIcon : : Group _group , int _force_size , int _state ,
TQString * _path ) const
{
TDEIconLoader * iconLoader = TDEGlobal : : iconLoader ( ) ;
TQString iconName = icon ( TQString : : null , false ) ;
if ( ! iconLoader - > extraDesktopThemesAdded ( ) )
{
TQPixmap pixmap = iconLoader - > loadIcon ( iconName , _group , _force_size , _state , _path , true ) ;
if ( ! pixmap . isNull ( ) ) return pixmap ;
iconLoader - > addExtraDesktopThemes ( ) ;
}
return iconLoader - > loadIcon ( iconName , _group , _force_size , _state , _path , false ) ;
}
TQPixmap KMimeType : : pixmap ( const KURL & _url , TDEIcon : : Group _group , int _force_size ,
int _state , TQString * _path ) const
{
TDEIconLoader * iconLoader = TDEGlobal : : iconLoader ( ) ;
TQString iconName = icon ( _url , _url . isLocalFile ( ) ) ;
if ( ! iconLoader - > extraDesktopThemesAdded ( ) )
{
TQPixmap pixmap = iconLoader - > loadIcon ( iconName , _group , _force_size , _state , _path , true ) ;
if ( ! pixmap . isNull ( ) ) return pixmap ;
iconLoader - > addExtraDesktopThemes ( ) ;
}
return iconLoader - > loadIcon ( iconName , _group , _force_size , _state , _path , false ) ;
}
TQPixmap KMimeType : : pixmapForURL ( const KURL & _url , mode_t _mode , TDEIcon : : Group _group ,
int _force_size , int _state , TQString * _path )
{
TDEIconLoader * iconLoader = TDEGlobal : : iconLoader ( ) ;
TQString iconName = iconForURL ( _url , _mode ) ;
if ( ! iconLoader - > extraDesktopThemesAdded ( ) )
{
TQPixmap pixmap = iconLoader - > loadIcon ( iconName , _group , _force_size , _state , _path , true ) ;
if ( ! pixmap . isNull ( ) ) return pixmap ;
iconLoader - > addExtraDesktopThemes ( ) ;
}
return iconLoader - > loadIcon ( iconName , _group , _force_size , _state , _path , false ) ;
}
TQString KMimeType : : iconForURL ( const KURL & _url , mode_t _mode )
{
const KMimeType : : Ptr mt = findByURL ( _url , _mode , _url . isLocalFile ( ) ,
false /*HACK*/ ) ;
static const TQString & unknown = TDEGlobal : : staticQString ( " unknown " ) ;
const TQString mimeTypeIcon = mt - > icon ( _url , _url . isLocalFile ( ) ) ;
TQString i = mimeTypeIcon ;
// if we don't find an icon, maybe we can use the one for the protocol
if ( i = = unknown | | i . isEmpty ( ) | | mt = = defaultMimeTypePtr ( )
// and for the root of the protocol (e.g. trash:/) the protocol icon has priority over the mimetype icon
| | _url . path ( ) . length ( ) < = 1 )
{
i = favIconForURL ( _url ) ; // maybe there is a favicon?
if ( i . isEmpty ( ) )
i = KProtocolInfo : : icon ( _url . protocol ( ) ) ;
// root of protocol: if we found nothing, revert to mimeTypeIcon (which is usually "folder")
if ( _url . path ( ) . length ( ) < = 1 & & ( i = = unknown | | i . isEmpty ( ) ) )
i = mimeTypeIcon ;
// special case: root directory (/) -- Gitea issue #128
if ( _url = = KURL ( " file:/// " ) )
i = " folder_red " ;
}
return i ;
}
TQString KMimeType : : favIconForURL ( const KURL & url )
{
// this method will be called quite often, so better not read the config
// again and again.
static bool useFavIcons = true ;
static bool check = true ;
if ( check ) {
check = false ;
TDEConfig * config = TDEGlobal : : config ( ) ;
TDEConfigGroupSaver cs ( config , " HTML Settings " ) ;
useFavIcons = config - > readBoolEntry ( " EnableFavicon " , true ) ;
}
if ( url . isLocalFile ( ) | | ! url . protocol ( ) . startsWith ( " http " )
| | ! useFavIcons )
return TQString : : null ;
DCOPRef kded ( " kded " , " favicons " ) ;
DCOPReply result = kded . call ( " iconForURL(KURL) " , url ) ;
if ( result . isValid ( ) )
return result ;
return TQString : : null ;
}
TQString KMimeType : : parentMimeType ( ) const
{
TQVariant v = property ( " X-TDE-IsAlso " ) ;
return v . toString ( ) ;
}
bool KMimeType : : is ( const TQString & mimeTypeName ) const
{
if ( name ( ) = = mimeTypeName )
return true ;
TQString st = parentMimeType ( ) ;
//if (st.isEmpty()) kdDebug(7009)<<"Parent mimetype is empty"<<endl;
while ( ! st . isEmpty ( ) )
{
//kdDebug(7009)<<"Checking parent mime type: "<<st<<endl;
KMimeType : : Ptr ptr = KMimeType : : mimeType ( st ) ;
if ( ! ptr ) return false ; //error
if ( ptr - > name ( ) = = mimeTypeName )
return true ;
st = ptr - > parentMimeType ( ) ;
}
return false ;
}
int KMimeType : : patternsAccuracy ( ) const {
TQVariant v = property ( " X-TDE-PatternsAccuracy " ) ;
if ( ! v . isValid ( ) ) return 100 ;
else
return v . toInt ( ) ;
}
/*******************************************************
*
* KFolderType
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TQString KFolderType : : icon ( const TQString & _url , bool _is_local ) const
{
if ( ! _is_local | | _url . isEmpty ( ) )
return KMimeType : : icon ( _url , _is_local ) ;
return KFolderType : : icon ( KURL ( _url ) , _is_local ) ;
}
TQString KFolderType : : icon ( const KURL & _url , bool _is_local ) const
{
if ( ! _is_local )
return KMimeType : : icon ( _url , _is_local ) ;
KURL u ( _url ) ;
u . addPath ( " .directory " ) ;
TQString icon ;
// using TDEStandardDirs as this one checks for path being
// a file instead of a directory
if ( TDEStandardDirs : : exists ( u . path ( ) ) )
{
KSimpleConfig cfg ( u . path ( ) , true ) ;
cfg . setDesktopGroup ( ) ;
icon = cfg . readEntry ( " Icon " ) ;
TQString empty_icon = cfg . readEntry ( " EmptyIcon " ) ;
if ( ! empty_icon . isEmpty ( ) )
{
bool isempty = false ;
DIR * dp = 0L ;
struct dirent * ep ;
dp = opendir ( TQFile : : encodeName ( _url . path ( ) ) ) ;
if ( dp )
{
TQValueList < TQCString > entries ;
// Note that readdir isn't guaranteed to return "." and ".." first (#79826)
ep = readdir ( dp ) ; if ( ep ) entries . append ( ep - > d_name ) ;
ep = readdir ( dp ) ; if ( ep ) entries . append ( ep - > d_name ) ;
if ( ( ep = readdir ( dp ) ) = = 0L ) // third file is NULL entry -> empty directory
isempty = true ;
else {
entries . append ( ep - > d_name ) ;
if ( readdir ( dp ) = = 0 ) { // only three
// check if we got "." ".." and ".directory"
isempty = entries . find ( " . " ) ! = entries . end ( ) & &
entries . find ( " .. " ) ! = entries . end ( ) & &
entries . find ( " .directory " ) ! = entries . end ( ) ;
}
}
if ( ! isempty & & ! strcmp ( ep - > d_name , " .directory " ) )
isempty = ( readdir ( dp ) = = 0L ) ;
closedir ( dp ) ;
}
if ( isempty )
return empty_icon ;
}
}
if ( icon . isEmpty ( ) )
return KMimeType : : icon ( _url , _is_local ) ;
if ( icon . startsWith ( " ./ " ) ) {
// path is relative with respect to the location
// of the .directory file (#73463)
KURL v ( _url ) ;
v . addPath ( icon . mid ( 2 ) ) ;
icon = v . path ( ) ;
}
return icon ;
}
TQString KFolderType : : comment ( const TQString & _url , bool _is_local ) const
{
if ( ! _is_local | | _url . isEmpty ( ) )
return KMimeType : : comment ( _url , _is_local ) ;
return KFolderType : : comment ( KURL ( _url ) , _is_local ) ;
}
TQString KFolderType : : comment ( const KURL & _url , bool _is_local ) const
{
if ( ! _is_local )
return KMimeType : : comment ( _url , _is_local ) ;
KURL u ( _url ) ;
u . addPath ( " .directory " ) ;
KDesktopFile cfg ( u . path ( ) , true ) ;
TQString comment = cfg . readComment ( ) ;
if ( comment . isEmpty ( ) )
return KMimeType : : comment ( _url , _is_local ) ;
return comment ;
}
/*******************************************************
*
* KDEDesktopMimeType
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TQString KDEDesktopMimeType : : icon ( const TQString & _url , bool _is_local ) const
{
if ( ! _is_local | | _url . isEmpty ( ) )
return KMimeType : : icon ( _url , _is_local ) ;
KURL u ( _url ) ;
return icon ( u , _is_local ) ;
}
TQString KDEDesktopMimeType : : icon ( const KURL & _url , bool _is_local ) const
{
if ( ! _is_local )
return KMimeType : : icon ( _url , _is_local ) ;
KSimpleConfig cfg ( _url . path ( ) , true ) ;
cfg . setDesktopGroup ( ) ;
TQString icon = cfg . readEntry ( " Icon " ) ;
TQString type = cfg . readEntry ( " Type " ) ;
if ( type = = " FSDevice " | | type = = " FSDev " ) // need to provide FSDev for
// backwards compatibility
{
TQString unmount_icon = cfg . readEntry ( " UnmountIcon " ) ;
TQString dev = cfg . readEntry ( " Dev " ) ;
if ( ! icon . isEmpty ( ) & & ! unmount_icon . isEmpty ( ) & & ! dev . isEmpty ( ) )
{
TQString mp = TDEIO : : findDeviceMountPoint ( dev ) ;
// Is the device not mounted ?
if ( mp . isNull ( ) )
return unmount_icon ;
}
} else if ( type = = " Link " ) {
const TQString emptyIcon = cfg . readEntry ( " EmptyIcon " ) ;
if ( ! emptyIcon . isEmpty ( ) ) {
const TQString u = cfg . readPathEntry ( " URL " ) ;
const KURL url ( u ) ;
if ( url . protocol ( ) = = " trash " ) {
// We need to find if the trash is empty, preferrably without using a TDEIO job.
// So instead tdeio_trash leaves an entry in its config file for us.
KSimpleConfig trashConfig ( " trashrc " , true ) ;
trashConfig . setGroup ( " Status " ) ;
if ( trashConfig . readBoolEntry ( " Empty " , true ) ) {
return emptyIcon ;
}
}
}
}
if ( icon . isEmpty ( ) )
return KMimeType : : icon ( _url , _is_local ) ;
return icon ;
}
TQPixmap KDEDesktopMimeType : : pixmap ( const KURL & _url , TDEIcon : : Group _group , int _force_size ,
int _state , TQString * _path ) const
{
TQString _icon = icon ( _url , _url . isLocalFile ( ) ) ;
TQPixmap pix = TDEGlobal : : iconLoader ( ) - > loadIcon ( _icon , _group ,
_force_size , _state , _path , false ) ;
if ( pix . isNull ( ) )
pix = TDEGlobal : : iconLoader ( ) - > loadIcon ( " unknown " , _group ,
_force_size , _state , _path , false ) ;
return pix ;
}
TQString KDEDesktopMimeType : : comment ( const TQString & _url , bool _is_local ) const
{
if ( ! _is_local | | _url . isEmpty ( ) )
return KMimeType : : comment ( _url , _is_local ) ;
KURL u ( _url ) ;
return comment ( u , _is_local ) ;
}
TQString KDEDesktopMimeType : : comment ( const KURL & _url , bool _is_local ) const
{
if ( ! _is_local )
return KMimeType : : comment ( _url , _is_local ) ;
KDesktopFile cfg ( _url . path ( ) , true ) ;
TQString comment = cfg . readComment ( ) ;
if ( comment . isEmpty ( ) )
return KMimeType : : comment ( _url , _is_local ) ;
return comment ;
}
pid_t KDEDesktopMimeType : : run ( const KURL & u , bool _is_local )
{
// It might be a security problem to run external untrusted desktop
// entry files
if ( ! _is_local )
return 0 ;
KSimpleConfig cfg ( u . path ( ) , true ) ;
cfg . setDesktopGroup ( ) ;
TQString type = cfg . readEntry ( " Type " ) ;
if ( type . isEmpty ( ) )
{
TQString tmp = i18n ( " The desktop entry file %1 "
" has no Type=... entry. " ) . arg ( u . path ( ) ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
return 0 ;
}
//kdDebug(7009) << "TYPE = " << type.data() << endl;
if ( type = = " FSDevice " )
return runFSDevice ( u , cfg ) ;
else if ( type = = " Application " )
return runApplication ( u , u . path ( ) ) ;
else if ( type = = " Link " )
{
cfg . setDollarExpansion ( true ) ; // for URL=file:$HOME (Simon)
return runLink ( u , cfg ) ;
}
else if ( type = = " MimeType " )
return runMimeType ( u , cfg ) ;
TQString tmp = i18n ( " The desktop entry of type \n %1 \n is unknown. " ) . arg ( type ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
return 0 ;
}
pid_t KDEDesktopMimeType : : runFSDevice ( const KURL & _url , const KSimpleConfig & cfg )
{
pid_t retval = 0 ;
TQString dev = cfg . readEntry ( " Dev " ) ;
if ( dev . isEmpty ( ) )
{
TQString tmp = i18n ( " The desktop entry file \n %1 \n is of type FSDevice but has no Dev=... entry. " ) . arg ( _url . path ( ) ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
return retval ;
}
TQString mp = TDEIO : : findDeviceMountPoint ( dev ) ;
// Is the device already mounted ?
if ( ! mp . isNull ( ) )
{
KURL mpURL ;
mpURL . setPath ( mp ) ;
// Open a new window
retval = KRun : : runURL ( mpURL , TQString : : fromLatin1 ( " inode/directory " ) ) ;
}
else
{
bool ro = cfg . readBoolEntry ( " ReadOnly " , false ) ;
TQString fstype = cfg . readEntry ( " FSType " ) ;
if ( fstype = = " Default " ) // KDE-1 thing
fstype = TQString : : null ;
TQString point = cfg . readEntry ( " MountPoint " ) ;
# ifndef TQ_WS_WIN
( void ) new KAutoMount ( ro , fstype , dev , point , _url . path ( ) ) ;
# endif
retval = - 1 ; // we don't want to return 0, but we don't want to return a pid
}
return retval ;
}
pid_t KDEDesktopMimeType : : runApplication ( const KURL & , const TQString & _serviceFile )
{
KService s ( _serviceFile ) ;
if ( ! s . isValid ( ) )
// The error message was already displayed, so we can just quit here
return 0 ;
KURL : : List lst ;
return KRun : : run ( s , lst ) ;
}
pid_t KDEDesktopMimeType : : runLink ( const KURL & _url , const KSimpleConfig & cfg )
{
TQString u = cfg . readPathEntry ( " URL " ) ;
if ( u . isEmpty ( ) )
{
TQString tmp = i18n ( " The desktop entry file \n %1 \n is of type Link but has no URL=... entry. " ) . arg ( _url . prettyURL ( ) ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
return 0 ;
}
KURL url ( u ) ;
KRun * run = new KRun ( url ) ;
// X-TDE-LastOpenedWith holds the service desktop entry name that
// was should be preferred for opening this URL if possible.
// This is used by the Recent Documents menu for instance.
TQString lastOpenedWidth = cfg . readEntry ( " X-TDE-LastOpenedWith " ) ;
if ( ! lastOpenedWidth . isEmpty ( ) )
run - > setPreferredService ( lastOpenedWidth ) ;
return - 1 ; // we don't want to return 0, but we don't want to return a pid
}
pid_t KDEDesktopMimeType : : runMimeType ( const KURL & url , const KSimpleConfig & )
{
// Hmm, can't really use keditfiletype since we might be looking
// at the global file, or at a file not in share/mimelnk...
TQStringList args ;
args < < " openProperties " ;
args < < url . path ( ) ;
int pid ;
if ( ! TDEApplication : : tdeinitExec ( " kfmclient " , args , 0 , & pid ) )
return pid ;
TDEProcess p ;
p < < " kfmclient " < < args ;
p . start ( TDEProcess : : DontCare ) ;
return p . pid ( ) ;
}
TQValueList < KDEDesktopMimeType : : Service > KDEDesktopMimeType : : builtinServices ( const KURL & _url )
{
TQValueList < Service > result ;
if ( ! _url . isLocalFile ( ) )
return result ;
KSimpleConfig cfg ( _url . path ( ) , true ) ;
cfg . setDesktopGroup ( ) ;
TQString type = cfg . readEntry ( " Type " ) ;
if ( type . isEmpty ( ) )
return result ;
if ( type = = " FSDevice " )
{
TQString dev = cfg . readEntry ( " Dev " ) ;
if ( dev . isEmpty ( ) )
{
TQString tmp = i18n ( " The desktop entry file \n %1 \n is of type FSDevice but has no Dev=... entry. " ) . arg ( _url . path ( ) ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
}
else
{
TQString mp = TDEIO : : findDeviceMountPoint ( dev ) ;
// not mounted ?
if ( mp . isEmpty ( ) )
{
Service mount ;
mount . m_strName = i18n ( " Mount " ) ;
mount . m_type = ST_MOUNT ;
result . append ( mount ) ;
}
else
{
Service unmount ;
# ifdef HAVE_VOLMGT
/*
* Solaris ' volume management can only umount + eject
*/
unmount . m_strName = i18n ( " Eject " ) ;
# else
unmount . m_strName = i18n ( " Unmount " ) ;
# endif
unmount . m_type = ST_UNMOUNT ;
result . append ( unmount ) ;
}
}
}
return result ;
}
TQValueList < KDEDesktopMimeType : : Service > KDEDesktopMimeType : : userDefinedServices ( const TQString & path , bool bLocalFiles )
{
KSimpleConfig cfg ( path , true ) ;
return userDefinedServices ( path , cfg , bLocalFiles ) ;
}
TQValueList < KDEDesktopMimeType : : Service > KDEDesktopMimeType : : userDefinedServices ( const TQString & path , TDEConfig & cfg , bool bLocalFiles )
{
return userDefinedServices ( path , cfg , bLocalFiles , KURL : : List ( ) ) ;
}
TQValueList < KDEDesktopMimeType : : Service > KDEDesktopMimeType : : userDefinedServices ( const TQString & path , TDEConfig & cfg , bool bLocalFiles , const KURL : : List & file_list )
{
TQValueList < Service > result ;
cfg . setDesktopGroup ( ) ;
if ( ! cfg . hasKey ( " Actions " ) & & ! cfg . hasKey ( " X-TDE-GetActionMenu " ) )
return result ;
if ( cfg . hasKey ( " TryExec " ) )
{
TQString tryexec = cfg . readPathEntry ( " TryExec " ) ;
TQString exe = TDEStandardDirs : : findExe ( tryexec ) ;
if ( exe . isEmpty ( ) ) {
return result ;
}
}
TQStringList keys ;
if ( cfg . hasKey ( " X-TDE-GetActionMenu " ) ) {
TQString dcopcall = cfg . readEntry ( " X-TDE-GetActionMenu " ) ;
const TQCString app = TQString ( dcopcall . section ( ' ' , 0 , 0 ) ) . utf8 ( ) ;
TQByteArray dataToSend ;
TQDataStream dataStream ( dataToSend , IO_WriteOnly ) ;
dataStream < < file_list ;
TQCString replyType ;
TQByteArray replyData ;
TQCString object = TQString ( dcopcall . section ( ' ' , 1 , - 2 ) ) . utf8 ( ) ;
TQString function = dcopcall . section ( ' ' , - 1 ) ;
if ( ! function . endsWith ( " (KURL::List) " ) ) {
kdWarning ( ) < < " Desktop file " < < path < < " contains an invalid X-TDE-ShowIfDcopCall - the function must take the exact parameter (KURL::List) and must be specified. " < < endl ;
} else {
if ( kapp - > dcopClient ( ) - > call ( app , object ,
function . utf8 ( ) ,
dataToSend , replyType , replyData , true , - 1 )
& & replyType = = " TQStringList " ) {
TQDataStream dataStreamIn ( replyData , IO_ReadOnly ) ;
dataStreamIn > > keys ;
}
}
}
keys + = cfg . readListEntry ( " Actions " , ' ; ' ) ; //the desktop standard defines ";" as separator!
if ( keys . count ( ) = = 0 )
return result ;
TQStringList : : ConstIterator it = keys . begin ( ) ;
TQStringList : : ConstIterator end = keys . end ( ) ;
for ( ; it ! = end ; + + it )
{
//kdDebug(7009) << "CURRENT KEY = " << (*it) << endl;
TQString group = * it ;
if ( group = = " _SEPARATOR_ " )
{
Service s ;
result . append ( s ) ;
continue ;
}
group . prepend ( " Desktop Action " ) ;
bool bInvalidMenu = false ;
if ( cfg . hasGroup ( group ) )
{
cfg . setGroup ( group ) ;
if ( ! cfg . hasKey ( " Name " ) | | ! cfg . hasKey ( " Exec " ) )
bInvalidMenu = true ;
else
{
TQString exec = cfg . readPathEntry ( " Exec " ) ;
if ( bLocalFiles | | exec . contains ( " %U " ) | | exec . contains ( " %u " ) )
{
Service s ;
s . m_strName = cfg . readEntry ( " Name " ) ;
s . m_strIcon = cfg . readEntry ( " Icon " ) ;
s . m_strExec = exec ;
s . m_type = ST_USER_DEFINED ;
s . m_display = ! cfg . readBoolEntry ( " NoDisplay " ) ;
result . append ( s ) ;
}
}
}
else
bInvalidMenu = true ;
if ( bInvalidMenu )
{
TQString tmp = i18n ( " The desktop entry file \n %1 \n has an invalid menu entry \n %2. " ) . arg ( path ) . arg ( * it ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
}
}
return result ;
}
void KDEDesktopMimeType : : executeService ( const TQString & _url , KDEDesktopMimeType : : Service & _service )
{
KURL u ;
u . setPath ( _url ) ;
KURL : : List lst ;
lst . append ( u ) ;
executeService ( lst , _service ) ;
}
void KDEDesktopMimeType : : executeService ( const KURL : : List & urls , KDEDesktopMimeType : : Service & _service )
{
//kdDebug(7009) << "EXECUTING Service " << _service.m_strName << endl;
if ( _service . m_type = = ST_USER_DEFINED )
{
kdDebug ( ) < < " KDEDesktopMimeType::executeService " < < _service . m_strName
< < " first url's path= " < < urls . first ( ) . path ( ) < < " exec= " < < _service . m_strExec < < endl ;
KRun : : run ( _service . m_strExec , urls , _service . m_strName , _service . m_strIcon , _service . m_strIcon ) ;
// The action may update the desktop file. Example: eject unmounts (#5129).
KDirNotify_stub allDirNotify ( " * " , " KDirNotify* " ) ;
allDirNotify . FilesChanged ( urls ) ;
return ;
}
else if ( _service . m_type = = ST_MOUNT | | _service . m_type = = ST_UNMOUNT )
{
Q_ASSERT ( urls . count ( ) = = 1 ) ;
TQString path = urls . first ( ) . path ( ) ;
//kdDebug(7009) << "MOUNT&UNMOUNT" << endl;
KSimpleConfig cfg ( path , true ) ;
cfg . setDesktopGroup ( ) ;
TQString dev = cfg . readEntry ( " Dev " ) ;
if ( dev . isEmpty ( ) )
{
TQString tmp = i18n ( " The desktop entry file \n %1 \n is of type FSDevice but has no Dev=... entry. " ) . arg ( path ) ;
KMessageBoxWrapper : : error ( 0 , tmp ) ;
return ;
}
TQString mp = TDEIO : : findDeviceMountPoint ( dev ) ;
if ( _service . m_type = = ST_MOUNT )
{
// Already mounted? Strange, but who knows ...
if ( ! mp . isEmpty ( ) )
{
kdDebug ( 7009 ) < < " ALREADY Mounted " < < endl ;
return ;
}
bool ro = cfg . readBoolEntry ( " ReadOnly " , false ) ;
TQString fstype = cfg . readEntry ( " FSType " ) ;
if ( fstype = = " Default " ) // KDE-1 thing
fstype = TQString : : null ;
TQString point = cfg . readEntry ( " MountPoint " ) ;
# ifndef TQ_WS_WIN
( void ) new KAutoMount ( ro , fstype , dev , point , path , false ) ;
# endif
}
else if ( _service . m_type = = ST_UNMOUNT )
{
// Not mounted? Strange, but who knows ...
if ( mp . isEmpty ( ) )
return ;
# ifndef TQ_WS_WIN
( void ) new KAutoUnmount ( mp , path ) ;
# endif
}
}
else
assert ( 0 ) ;
}
const TQString & KMimeType : : defaultMimeType ( )
{
static const TQString & s_strDefaultMimeType =
TDEGlobal : : staticQString ( " application/octet-stream " ) ;
return s_strDefaultMimeType ;
}
void KMimeType : : virtual_hook ( int id , void * data )
{ KServiceType : : virtual_hook ( id , data ) ; }
void KFolderType : : virtual_hook ( int id , void * data )
{ KMimeType : : virtual_hook ( id , data ) ; }
void KDEDesktopMimeType : : virtual_hook ( int id , void * data )
{ KMimeType : : virtual_hook ( id , data ) ; }
void KExecMimeType : : virtual_hook ( int id , void * data )
{ KMimeType : : virtual_hook ( id , data ) ; }
# include "kmimetyperesolver.moc"