23 #include <sys/types.h>
33 #include <kprotocolinfo.h>
34 #include <tdeio/global.h>
35 #include "kmimetype.h"
36 #include "kservicetypefactory.h"
37 #include "kmimemagic.h"
40 #include "kautomount.h"
41 #include <kdirnotify_stub.h>
45 #include <kmessageboxwrapper.h>
47 #include <dcopclient.h>
49 #include <tdeapplication.h>
52 #include <kdesktopfile.h>
53 #include <kdirwatch.h>
54 #include <kiconloader.h>
55 #include <tdelocale.h>
56 #include <ksimpleconfig.h>
57 #include <kstandarddirs.h>
59 #include <tdesycoca.h>
62 template class TDESharedPtr<KMimeType>;
63 template class TQValueList<KMimeType::Ptr>;
65 KMimeType::Ptr KMimeType::s_pDefaultType = 0L;
70 assert ( !s_pDefaultType );
75 if (mime && mime->isType( KST_KMimeType ))
77 s_pDefaultType = KMimeType::Ptr((
KMimeType *) mime);
82 TDEStandardDirs stdDirs;
83 TQString sDefaultMimeType = stdDirs.resourceDirs(
"mime").first()+
defaultMimeType()+
".desktop";
85 "unknown",
"mime", TQStringList() );
91 if ( !s_pDefaultType )
93 return s_pDefaultType;
101 if ( !s_pDefaultType )
108 if ( !KServiceTypeFactory::self()->checkMimeTypes() )
110 KMessageBoxWrapper::error( 0L, i18n(
"No mime types installed." ) );
136 TQString tmp = i18n(
"Could not find mime type\n%1" ).arg( _type );
138 KMessageBoxWrapper::sorry( 0, tmp );
143 KServiceType * mime = KServiceTypeFactory::self()->findServiceTypeByName( _name );
145 if ( !mime || !mime->isType( KST_KMimeType ) )
149 if ( !KSycoca::self()->isBuilding() )
151 if ( !s_pDefaultType )
153 return s_pDefaultType;
157 return KMimeType::Ptr((
KMimeType *) mime);
162 return KServiceTypeFactory::self()->allMimeTypes();
166 bool _is_local_file,
bool _fast_mode )
169 TQString path = _url.path();
171 if ( !_fast_mode && !_is_local_file && _url.isLocalFile() )
172 _is_local_file =
true;
174 if ( !_fast_mode && _is_local_file && (_mode == 0 || _mode == (mode_t)-1) )
176 KDE_struct_stat buff;
177 if ( KDE_stat( TQFile::encodeName(path), &buff ) != -1 )
178 _mode = buff.st_mode;
182 if ( S_ISDIR( _mode ) )
186 if ( _is_local_file )
188 if ( access( TQFile::encodeName(path), R_OK ) == -1 )
189 return mimeType(
"inode/directory-locked" );
191 return mimeType(
"inode/directory" );
193 if ( S_ISCHR( _mode ) )
194 return mimeType(
"inode/chardevice" );
195 if ( S_ISBLK( _mode ) )
196 return mimeType(
"inode/blockdevice" );
197 if ( S_ISFIFO( _mode ) )
199 if ( S_ISSOCK( _mode ) )
202 if ( !_is_local_file && S_ISREG( _mode ) && ( _mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) )
203 return mimeType(
"application/x-executable" );
205 TQString fileName ( _url.fileName() );
207 static const TQString& slash = TDEGlobal::staticQString(
"/");
208 if ( ! fileName.isNull() && !path.endsWith( slash ) )
211 KMimeType::Ptr mime = KServiceTypeFactory::self()->findFromPattern( fileName );
215 if ( _is_local_file || _url.hasSubURL() ||
218 if ( _is_local_file && !_fast_mode ) {
219 if ( mime->patternsAccuracy()<100 )
226 if (resultMime->patternsAccuracy() > 0) {
237 static const TQString& dotdesktop = TDEGlobal::staticQString(
".desktop");
238 static const TQString& dotkdelnk = TDEGlobal::staticQString(
".kdelnk");
239 static const TQString& dotdirectory = TDEGlobal::staticQString(
".directory");
242 if ( fileName.endsWith( dotdesktop ) )
243 return mimeType(
"application/x-desktop" );
246 if ( fileName.endsWith( dotkdelnk ) )
247 return mimeType(
"application/x-desktop" );
250 if ( fileName == dotdirectory )
254 if ( !_is_local_file || _fast_mode )
262 if ( path.endsWith( slash ) || path.isEmpty() )
272 return mimeType( TQString::fromLatin1(
"inode/directory") );
287 if ( !result || !result->
isValid() )
295 bool _is_local_file,
bool _fast_mode,
298 KMimeType::Ptr mime =
findByURL(_url, _mode, _is_local_file, _fast_mode);
299 if (accurate) *accurate = !(_fast_mode) || ((mime->patternsAccuracy() == 100) && mime !=
defaultMimeTypePtr());
303 KMimeType::Ptr KMimeType::diagnoseFileName(
const TQString &fileName, TQString &pattern)
305 return KServiceTypeFactory::self()->findFromPattern( fileName, &pattern );
312 return findByURL( u, mode,
true, fast_mode );
331 #define GZIP_MAGIC1 0x1f
332 #define GZIP_MAGIC2 0x8b
336 KMimeType::Format result;
337 result.compression = Format::NoCompression;
340 result.text = mime->name().startsWith(
"text/");
341 TQVariant v = mime->property(
"X-TDE-text");
343 result.text = v.toBool();
345 if (mime->name().startsWith(
"inode/"))
349 if (f.open(IO_ReadOnly))
351 unsigned char buf[10+1];
352 int l = f.readBlock((
char *)buf, 10);
353 if ((l > 2) && (buf[0] == GZIP_MAGIC1) && (buf[1] == GZIP_MAGIC2))
354 result.compression = Format::GZipCompression;
360 const TQString& _comment,
const TQStringList& _patterns )
363 m_lstPatterns = _patterns;
368 KDesktopFile _cfg( _fullpath,
true );
372 kdWarning(7009) <<
"mimetype not valid '" << m_strName <<
"' (missing entry in the file ?)" << endl;
380 kdWarning(7009) <<
"mimetype not valid '" << m_strName <<
"' (missing entry in the file ?)" << endl;
383 void KMimeType::init( KDesktopFile * config )
385 config->setDesktopGroup();
386 m_lstPatterns = config->readListEntry(
"Patterns",
';' );
389 TQString XKDEAutoEmbed = TQString::fromLatin1(
"X-TDE-AutoEmbed");
390 if ( config->hasKey( XKDEAutoEmbed ) )
391 m_mapProps.insert( XKDEAutoEmbed, TQVariant( config->readBoolEntry( XKDEAutoEmbed ), 0 ) );
393 TQString XKDEText = TQString::fromLatin1(
"X-TDE-text");
394 if ( config->hasKey( XKDEText ) )
395 m_mapProps.insert( XKDEText, config->readBoolEntry( XKDEText ) );
397 TQString XKDEIsAlso = TQString::fromLatin1(
"X-TDE-IsAlso");
398 if ( config->hasKey( XKDEIsAlso ) ) {
399 TQString
inherits = config->readEntry( XKDEIsAlso );
400 if ( inherits !=
name() )
401 m_mapProps.insert( XKDEIsAlso, inherits );
403 kdWarning(7009) <<
"Error: " << inherits <<
" inherits from itself!!!!" << endl;
406 TQString XKDEPatternsAccuracy = TQString::fromLatin1(
"X-TDE-PatternsAccuracy");
407 if ( config->hasKey( XKDEPatternsAccuracy ) )
408 m_mapProps.insert( XKDEPatternsAccuracy, config->readEntry( XKDEPatternsAccuracy ) );
414 loadInternal( _str );
420 loadInternal( _str );
423 void KMimeType::loadInternal( TQDataStream& _str )
426 _str >> m_lstPatterns;
434 _str << m_lstPatterns;
439 if ( _name ==
"Patterns" )
440 return TQVariant( m_lstPatterns );
448 res.append(
"Patterns" );
453 KMimeType::~KMimeType()
458 TQString * _path )
const
460 TDEIconLoader *iconLoader=TDEGlobal::iconLoader();
461 TQString iconName=
icon( TQString::null,
false );
462 if (!iconLoader->extraDesktopThemesAdded())
464 TQPixmap
pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path,
true );
465 if (!pixmap.isNull() )
return pixmap;
467 iconLoader->addExtraDesktopThemes();
470 return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path,
false );
474 int _state, TQString * _path )
const
476 TDEIconLoader *iconLoader=TDEGlobal::iconLoader();
477 TQString iconName=
icon( _url, _url.isLocalFile() );
478 if (!iconLoader->extraDesktopThemesAdded())
480 TQPixmap
pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path,
true );
481 if (!pixmap.isNull() )
return pixmap;
483 iconLoader->addExtraDesktopThemes();
486 return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path,
false );
490 int _force_size,
int _state, TQString * _path )
492 TDEIconLoader *iconLoader=TDEGlobal::iconLoader();
493 TQString iconName =
iconForURL( _url, _mode );
495 if (!iconLoader->extraDesktopThemesAdded())
497 TQPixmap
pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path,
true );
498 if (!pixmap.isNull() )
return pixmap;
500 iconLoader->addExtraDesktopThemes();
503 return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path,
false );
509 const KMimeType::Ptr mt =
findByURL( _url, _mode, _url.isLocalFile(),
511 static const TQString& unknown = TDEGlobal::staticQString(
"unknown");
512 const TQString mimeTypeIcon = mt->icon( _url, _url.isLocalFile() );
513 TQString i = mimeTypeIcon;
518 || _url.path().length() <= 1 )
526 if ( _url.path().length() <= 1 && ( i == unknown || i.isEmpty() ) )
530 if ( _url == KURL(
"file:///") )
540 static bool useFavIcons =
true;
541 static bool check =
true;
544 TDEConfig *config = TDEGlobal::config();
545 TDEConfigGroupSaver cs( config,
"HTML Settings" );
546 useFavIcons = config->readBoolEntry(
"EnableFavicon",
true );
549 if ( url.isLocalFile() || !url.protocol().startsWith(
"http")
551 return TQString::null;
553 DCOPRef kded(
"kded",
"favicons" );
554 DCOPReply result = kded.call(
"iconForURL(KURL)", url );
555 if ( result.isValid() )
558 return TQString::null;
563 TQVariant v =
property(
"X-TDE-IsAlso");
569 if (
name() == mimeTypeName )
573 while ( !st.isEmpty() )
577 if (!ptr)
return false;
578 if ( ptr->name() == mimeTypeName )
580 st = ptr->parentMimeType();
585 int KMimeType::patternsAccuracy()
const {
586 TQVariant v =
property(
"X-TDE-PatternsAccuracy");
587 if (!v.isValid())
return 100;
601 if ( !_is_local || _url.isEmpty() )
613 u.addPath(
".directory" );
618 if ( TDEStandardDirs::exists( u.path() ) )
620 KSimpleConfig cfg( u.path(), true );
621 cfg.setDesktopGroup();
622 icon = cfg.readEntry(
"Icon" );
623 TQString empty_icon = cfg.readEntry(
"EmptyIcon" );
625 if ( !empty_icon.isEmpty() )
627 bool isempty =
false;
630 dp = opendir( TQFile::encodeName(_url.path()) );
633 TQValueList<TQCString> entries;
635 ep=readdir( dp );
if ( ep ) entries.append( ep->d_name );
636 ep=readdir( dp );
if ( ep ) entries.append( ep->d_name );
637 if ( (ep=readdir( dp )) == 0L )
640 entries.append( ep->d_name );
641 if ( readdir( dp ) == 0 ) {
643 isempty = entries.find(
"." ) != entries.end() &&
644 entries.find(
".." ) != entries.end() &&
645 entries.find(
".directory" ) != entries.end();
648 if (!isempty && !strcmp(ep->d_name,
".directory"))
649 isempty = (readdir(dp) == 0L);
658 if ( icon.isEmpty() )
661 if ( icon.startsWith(
"./" ) ) {
665 v.addPath( icon.mid( 2 ) );
674 if ( !_is_local || _url.isEmpty() )
686 u.addPath(
".directory" );
688 KDesktopFile cfg( u.path(), true );
689 TQString
comment = cfg.readComment();
690 if ( comment.isEmpty() )
704 if ( !_is_local || _url.isEmpty() )
708 return icon( u, _is_local );
716 KSimpleConfig cfg( _url.path(), true );
717 cfg.setDesktopGroup();
718 TQString
icon = cfg.readEntry(
"Icon" );
719 TQString type = cfg.readEntry(
"Type" );
721 if ( type ==
"FSDevice" || type ==
"FSDev")
724 TQString unmount_icon = cfg.readEntry(
"UnmountIcon" );
725 TQString dev = cfg.readEntry(
"Dev" );
726 if ( !icon.isEmpty() && !unmount_icon.isEmpty() && !dev.isEmpty() )
733 }
else if ( type ==
"Link" ) {
734 const TQString emptyIcon = cfg.readEntry(
"EmptyIcon" );
735 if ( !emptyIcon.isEmpty() ) {
736 const TQString u = cfg.readPathEntry(
"URL" );
738 if ( url.protocol() ==
"trash" ) {
741 KSimpleConfig trashConfig(
"trashrc",
true );
742 trashConfig.setGroup(
"Status" );
743 if ( trashConfig.readBoolEntry(
"Empty",
true ) ) {
750 if ( icon.isEmpty() )
757 int _state, TQString * _path )
const
759 TQString _icon =
icon( _url, _url.isLocalFile() );
760 TQPixmap pix = TDEGlobal::iconLoader()->loadIcon( _icon, _group,
761 _force_size, _state, _path,
false );
763 pix = TDEGlobal::iconLoader()->loadIcon(
"unknown", _group,
764 _force_size, _state, _path,
false );
770 if ( !_is_local || _url.isEmpty() )
774 return comment( u, _is_local );
782 KDesktopFile cfg( _url.path(), true );
783 TQString
comment = cfg.readComment();
784 if ( comment.isEmpty() )
797 KSimpleConfig cfg( u.path(), true );
798 cfg.setDesktopGroup();
799 TQString type = cfg.readEntry(
"Type" );
800 if ( type.isEmpty() )
802 TQString tmp = i18n(
"The desktop entry file %1 "
803 "has no Type=... entry.").arg(u.path() );
804 KMessageBoxWrapper::error( 0, tmp);
810 if ( type ==
"FSDevice" )
811 return runFSDevice( u, cfg );
812 else if ( type ==
"Application" )
813 return runApplication( u, u.path() );
814 else if ( type ==
"Link" )
816 cfg.setDollarExpansion(
true );
817 return runLink( u, cfg );
819 else if ( type ==
"MimeType" )
820 return runMimeType( u, cfg );
823 TQString tmp = i18n(
"The desktop entry of type\n%1\nis unknown.").arg( type );
824 KMessageBoxWrapper::error( 0, tmp);
829 pid_t KDEDesktopMimeType::runFSDevice(
const KURL& _url,
const KSimpleConfig &cfg )
833 TQString dev = cfg.readEntry(
"Dev" );
837 TQString tmp = i18n(
"The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( _url.path() );
838 KMessageBoxWrapper::error( 0, tmp);
849 retval =
KRun::runURL( mpURL, TQString::fromLatin1(
"inode/directory") );
853 bool ro = cfg.readBoolEntry(
"ReadOnly",
false );
854 TQString fstype = cfg.readEntry(
"FSType" );
855 if ( fstype ==
"Default" )
856 fstype = TQString::null;
857 TQString point = cfg.readEntry(
"MountPoint" );
859 (void)
new KAutoMount( ro, fstype, dev, point, _url.path() );
867 pid_t KDEDesktopMimeType::runApplication(
const KURL& ,
const TQString & _serviceFile )
878 pid_t KDEDesktopMimeType::runLink(
const KURL& _url,
const KSimpleConfig &cfg )
880 TQString u = cfg.readPathEntry(
"URL" );
883 TQString tmp = i18n(
"The desktop entry file\n%1\nis of type Link but has no URL=... entry.").arg( _url.prettyURL() );
884 KMessageBoxWrapper::error( 0, tmp );
894 TQString lastOpenedWidth = cfg.readEntry(
"X-TDE-LastOpenedWith" );
895 if ( !lastOpenedWidth.isEmpty() )
901 pid_t KDEDesktopMimeType::runMimeType(
const KURL& url ,
const KSimpleConfig & )
907 args <<
"openProperties";
911 if ( !TDEApplication::tdeinitExec(
"kfmclient", args, 0, &pid) )
915 p <<
"kfmclient" << args;
916 p.start(TDEProcess::DontCare);
922 TQValueList<Service> result;
924 if ( !_url.isLocalFile() )
927 KSimpleConfig cfg( _url.path(), true );
928 cfg.setDesktopGroup();
929 TQString type = cfg.readEntry(
"Type" );
931 if ( type.isEmpty() )
934 if ( type ==
"FSDevice" )
936 TQString dev = cfg.readEntry(
"Dev" );
939 TQString tmp = i18n(
"The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( _url.path() );
940 KMessageBoxWrapper::error( 0, tmp);
949 mount.m_strName = i18n(
"Mount");
950 mount.m_type = ST_MOUNT;
951 result.append( mount );
960 unmount.m_strName = i18n(
"Eject");
962 unmount.m_strName = i18n(
"Unmount");
964 unmount.m_type = ST_UNMOUNT;
965 result.append( unmount );
975 KSimpleConfig cfg( path,
true );
986 TQValueList<Service> result;
988 cfg.setDesktopGroup();
990 if ( !cfg.hasKey(
"Actions" ) && !cfg.hasKey(
"X-TDE-GetActionMenu") )
993 if ( cfg.hasKey(
"TryExec" ) )
995 TQString tryexec = cfg.readPathEntry(
"TryExec" );
996 TQString exe = TDEStandardDirs::findExe( tryexec );
1004 if( cfg.hasKey(
"X-TDE-GetActionMenu" )) {
1005 TQString dcopcall = cfg.readEntry(
"X-TDE-GetActionMenu" );
1006 const TQCString app = TQString(dcopcall.section(
' ', 0,0)).utf8();
1008 TQByteArray dataToSend;
1009 TQDataStream dataStream(dataToSend, IO_WriteOnly);
1010 dataStream << file_list;
1011 TQCString replyType;
1012 TQByteArray replyData;
1013 TQCString
object = TQString(dcopcall.section(
' ', 1,-2)).utf8();
1014 TQString
function = dcopcall.section(
' ', -1);
1015 if(!
function.endsWith(
"(KURL::List)")) {
1016 kdWarning() <<
"Desktop file " << path <<
" contains an invalid X-TDE-ShowIfDcopCall - the function must take the exact parameter (KURL::List) and must be specified." << endl;
1018 if(kapp->dcopClient()->call( app,
object,
1020 dataToSend, replyType, replyData,
true, -1)
1021 && replyType ==
"TQStringList" ) {
1023 TQDataStream dataStreamIn(replyData, IO_ReadOnly);
1024 dataStreamIn >> keys;
1029 keys += cfg.readListEntry(
"Actions",
';' );
1031 if ( keys.count() == 0 )
1034 TQStringList::ConstIterator it = keys.begin();
1035 TQStringList::ConstIterator end = keys.end();
1036 for ( ; it != end; ++it )
1040 TQString group = *it;
1042 if (group ==
"_SEPARATOR_")
1049 group.prepend(
"Desktop Action " );
1051 bool bInvalidMenu =
false;
1053 if ( cfg.hasGroup( group ) )
1055 cfg.setGroup( group );
1057 if ( !cfg.hasKey(
"Name" ) || !cfg.hasKey(
"Exec" ) )
1058 bInvalidMenu =
true;
1061 TQString exec = cfg.readPathEntry(
"Exec" );
1062 if ( bLocalFiles || exec.contains(
"%U") || exec.contains(
"%u") )
1065 s.m_strName = cfg.readEntry(
"Name" );
1066 s.m_strIcon = cfg.readEntry(
"Icon" );
1068 s.m_type = ST_USER_DEFINED;
1069 s.m_display = !cfg.readBoolEntry(
"NoDisplay" );
1075 bInvalidMenu =
true;
1079 TQString tmp = i18n(
"The desktop entry file\n%1\n has an invalid menu entry\n%2.").arg( path ).arg( *it );
1080 KMessageBoxWrapper::error( 0, tmp );
1100 if ( _service.m_type == ST_USER_DEFINED )
1102 kdDebug() <<
"KDEDesktopMimeType::executeService " << _service.m_strName
1103 <<
" first url's path=" << urls.first().path() <<
" exec=" << _service.m_strExec << endl;
1104 KRun::run( _service.m_strExec, urls, _service.m_strName, _service.m_strIcon, _service.m_strIcon );
1106 KDirNotify_stub allDirNotify(
"*",
"KDirNotify*");
1107 allDirNotify.FilesChanged( urls );
1110 else if ( _service.m_type == ST_MOUNT || _service.m_type == ST_UNMOUNT )
1112 Q_ASSERT( urls.count() == 1 );
1113 TQString path = urls.first().path();
1116 KSimpleConfig cfg( path,
true );
1117 cfg.setDesktopGroup();
1118 TQString dev = cfg.readEntry(
"Dev" );
1119 if ( dev.isEmpty() )
1121 TQString tmp = i18n(
"The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( path );
1122 KMessageBoxWrapper::error( 0, tmp );
1127 if ( _service.m_type == ST_MOUNT )
1130 if ( !mp.isEmpty() )
1132 kdDebug(7009) <<
"ALREADY Mounted" << endl;
1136 bool ro = cfg.readBoolEntry(
"ReadOnly",
false );
1137 TQString fstype = cfg.readEntry(
"FSType" );
1138 if ( fstype ==
"Default" )
1139 fstype = TQString::null;
1140 TQString point = cfg.readEntry(
"MountPoint" );
1142 (void)
new KAutoMount( ro, fstype, dev, point, path,
false );
1145 else if ( _service.m_type == ST_UNMOUNT )
1162 static const TQString & s_strDefaultMimeType =
1163 TDEGlobal::staticQString(
"application/octet-stream" );
1164 return s_strDefaultMimeType;
1167 void KMimeType::virtual_hook(
int id,
void* data )
1168 { KServiceType::virtual_hook(
id, data ); }
1170 void KFolderType::virtual_hook(
int id,
void* data )
1171 { KMimeType::virtual_hook(
id, data ); }
1173 void KDEDesktopMimeType::virtual_hook(
int id,
void* data )
1174 { KMimeType::virtual_hook(
id, data ); }
1176 void KExecMimeType::virtual_hook(
int id,
void* data )
1177 { KMimeType::virtual_hook(
id, data ); }
1179 #include "kmimetyperesolver.moc"