/* This file is part of the KDE libraries * Copyright (C) 1999 Waldo Bastian * David Faure * * 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 #include #include #include #include #include #include #include #include #include #include #include "kmimetype.h" #include "kservicetypefactory.h" #include "kmimemagic.h" #include "kservice.h" #include "krun.h" #include "kautomount.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include template class KSharedPtr; template class TQValueList; 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() ); KStandardDirs 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 ) return mimeType( result->mimeType() ); } } 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 ), 0 ) ); 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( KIcon::Group _group, int _force_size, int _state, TQString * _path ) const { KIconLoader *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, KIcon::Group _group, int _force_size, int _state, TQString * _path ) const { KIconLoader *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, KIcon::Group _group, int _force_size, int _state, TQString * _path ) { KIconLoader *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; } 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"<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 KStandardDirs as this one checks for path being // a file instead of a directory if ( KStandardDirs::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 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 KIO 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, KIcon::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\nis 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\nis 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 Q_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\nis 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::builtinServices( const KURL& _url ) { TQValueList 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\nis 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::userDefinedServices( const TQString& path, bool bLocalFiles ) { KSimpleConfig cfg( path, true ); return userDefinedServices( path, cfg, bLocalFiles ); } TQValueList KDEDesktopMimeType::userDefinedServices( const TQString& path, TDEConfig& cfg, bool bLocalFiles ) { return userDefinedServices( path, cfg, bLocalFiles, KURL::List() ); } TQValueList KDEDesktopMimeType::userDefinedServices( const TQString& path, TDEConfig& cfg, bool bLocalFiles, const KURL::List & file_list ) { TQValueList 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 = KStandardDirs::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\nis 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 Q_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 Q_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"