• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kio/kio
 

kio/kio

  • kio
  • kio
kmimetype.cpp
1 /* This file is part of the KDE libraries
2  * Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
3  * David Faure <faure@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License version 2 as published by the Free Software Foundation;
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB. If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  **/
19 // $Id$
20 
21 #include <config.h>
22 
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 
26 #include <assert.h>
27 #include <dirent.h>
28 #include <errno.h>
29 #include <stddef.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 
33 #include <kprotocolinfo.h>
34 #include <kio/global.h>
35 #include "kmimetype.h"
36 #include "kservicetypefactory.h"
37 #include "kmimemagic.h"
38 #include "kservice.h"
39 #include "krun.h"
40 #include "kautomount.h"
41 #include <kdirnotify_stub.h>
42 
43 #include <tqstring.h>
44 #include <tqfile.h>
45 #include <kmessageboxwrapper.h>
46 
47 #include <dcopclient.h>
48 #include <dcopref.h>
49 #include <kapplication.h>
50 #include <kprocess.h>
51 #include <kdebug.h>
52 #include <kdesktopfile.h>
53 #include <kdirwatch.h>
54 #include <kiconloader.h>
55 #include <klocale.h>
56 #include <ksimpleconfig.h>
57 #include <kstandarddirs.h>
58 #include <kurl.h>
59 #include <ksycoca.h>
60 #include <kde_file.h>
61 
62 template class KSharedPtr<KMimeType>;
63 template class TQValueList<KMimeType::Ptr>;
64 
65 KMimeType::Ptr KMimeType::s_pDefaultType = 0L;
66 bool KMimeType::s_bChecked = false;
67 
68 void KMimeType::buildDefaultType()
69 {
70  assert ( !s_pDefaultType );
71  // Try to find the default type
72  KServiceType * mime = KServiceTypeFactory::self()->
73  findServiceTypeByName( defaultMimeType() );
74 
75  if (mime && mime->isType( KST_KMimeType ))
76  {
77  s_pDefaultType = KMimeType::Ptr((KMimeType *) mime);
78  }
79  else
80  {
81  errorMissingMimeType( defaultMimeType() );
82  KStandardDirs stdDirs;
83  TQString sDefaultMimeType = stdDirs.resourceDirs("mime").first()+defaultMimeType()+".desktop";
84  s_pDefaultType = new KMimeType( sDefaultMimeType, defaultMimeType(),
85  "unknown", "mime", TQStringList() );
86  }
87 }
88 
89 KMimeType::Ptr KMimeType::defaultMimeTypePtr()
90 {
91  if ( !s_pDefaultType ) // we need a default type first
92  buildDefaultType();
93  return s_pDefaultType;
94 }
95 
96 // Check for essential mimetypes
97 void KMimeType::checkEssentialMimeTypes()
98 {
99  if ( s_bChecked ) // already done
100  return;
101  if ( !s_pDefaultType ) // we need a default type first
102  buildDefaultType();
103 
104  s_bChecked = true; // must be done before building mimetypes
105 
106  // No Mime-Types installed ?
107  // Lets do some rescue here.
108  if ( !KServiceTypeFactory::self()->checkMimeTypes() )
109  {
110  KMessageBoxWrapper::error( 0L, i18n( "No mime types installed." ) );
111  return; // no point in going any further
112  }
113 
114  if ( KMimeType::mimeType( "inode/directory" ) == s_pDefaultType )
115  errorMissingMimeType( "inode/directory" );
116  if ( KMimeType::mimeType( "inode/directory-locked" ) == s_pDefaultType )
117  errorMissingMimeType( "inode/directory-locked" );
118  if ( KMimeType::mimeType( "inode/blockdevice" ) == s_pDefaultType )
119  errorMissingMimeType( "inode/blockdevice" );
120  if ( KMimeType::mimeType( "inode/chardevice" ) == s_pDefaultType )
121  errorMissingMimeType( "inode/chardevice" );
122  if ( KMimeType::mimeType( "inode/socket" ) == s_pDefaultType )
123  errorMissingMimeType( "inode/socket" );
124  if ( KMimeType::mimeType( "inode/fifo" ) == s_pDefaultType )
125  errorMissingMimeType( "inode/fifo" );
126  if ( KMimeType::mimeType( "application/x-shellscript" ) == s_pDefaultType )
127  errorMissingMimeType( "application/x-shellscript" );
128  if ( KMimeType::mimeType( "application/x-executable" ) == s_pDefaultType )
129  errorMissingMimeType( "application/x-executable" );
130  if ( KMimeType::mimeType( "application/x-desktop" ) == s_pDefaultType )
131  errorMissingMimeType( "application/x-desktop" );
132 }
133 
134 void KMimeType::errorMissingMimeType( const TQString& _type )
135 {
136  TQString tmp = i18n( "Could not find mime type\n%1" ).arg( _type );
137 
138  KMessageBoxWrapper::sorry( 0, tmp );
139 }
140 
141 KMimeType::Ptr KMimeType::mimeType( const TQString& _name )
142 {
143  KServiceType * mime = KServiceTypeFactory::self()->findServiceTypeByName( _name );
144 
145  if ( !mime || !mime->isType( KST_KMimeType ) )
146  {
147  // When building ksycoca, findServiceTypeByName doesn't create an object
148  // but returns one from a dict.
149  if ( !KSycoca::self()->isBuilding() )
150  delete mime;
151  if ( !s_pDefaultType )
152  buildDefaultType();
153  return s_pDefaultType;
154  }
155 
156  // We got a mimetype
157  return KMimeType::Ptr((KMimeType *) mime);
158 }
159 
160 KMimeType::List KMimeType::allMimeTypes()
161 {
162  return KServiceTypeFactory::self()->allMimeTypes();
163 }
164 
165 KMimeType::Ptr KMimeType::findByURL( const KURL& _url, mode_t _mode,
166  bool _is_local_file, bool _fast_mode )
167 {
168  checkEssentialMimeTypes();
169  TQString path = _url.path();
170 
171  if ( !_fast_mode && !_is_local_file && _url.isLocalFile() )
172  _is_local_file = true;
173 
174  if ( !_fast_mode && _is_local_file && (_mode == 0 || _mode == (mode_t)-1) )
175  {
176  KDE_struct_stat buff;
177  if ( KDE_stat( TQFile::encodeName(path), &buff ) != -1 )
178  _mode = buff.st_mode;
179  }
180 
181  // Look at mode_t first
182  if ( S_ISDIR( _mode ) )
183  {
184  // Special hack for local files. We want to see whether we
185  // are allowed to enter the directory
186  if ( _is_local_file )
187  {
188  if ( access( TQFile::encodeName(path), R_OK ) == -1 )
189  return mimeType( "inode/directory-locked" );
190  }
191  return mimeType( "inode/directory" );
192  }
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 ) )
198  return mimeType( "inode/fifo" );
199  if ( S_ISSOCK( _mode ) )
200  return mimeType( "inode/socket" );
201  // KMimeMagic can do that better for local files
202  if ( !_is_local_file && S_ISREG( _mode ) && ( _mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) )
203  return mimeType( "application/x-executable" );
204 
205  TQString fileName ( _url.fileName() );
206 
207  static const TQString& slash = KGlobal::staticQString("/");
208  if ( ! fileName.isNull() && !path.endsWith( slash ) )
209  {
210  // Try to find it out by looking at the filename
211  KMimeType::Ptr mime = KServiceTypeFactory::self()->findFromPattern( fileName );
212  if ( mime )
213  {
214  // Found something - can we trust it ? (e.g. don't trust *.pl over HTTP, could be anything)
215  if ( _is_local_file || _url.hasSubURL() || // Explicitly trust suburls
216  KProtocolInfo::determineMimetypeFromExtension( _url.protocol() ) )
217  {
218  if ( _is_local_file && !_fast_mode ) {
219  if ( mime->patternsAccuracy()<100 )
220  {
221  KMimeMagicResult* result =
222  KMimeMagic::self()->findFileType( path );
223 
224  if ( result && result->isValid() && result->accuracy() > 0 )
225  return mimeType( result->mimeType() );
226  }
227  }
228 
229  return mime;
230  }
231  }
232 
233  static const TQString& dotdesktop = KGlobal::staticQString(".desktop");
234  static const TQString& dotkdelnk = KGlobal::staticQString(".kdelnk");
235  static const TQString& dotdirectory = KGlobal::staticQString(".directory");
236 
237  // Another filename binding, hardcoded, is .desktop:
238  if ( fileName.endsWith( dotdesktop ) )
239  return mimeType( "application/x-desktop" );
240  // Another filename binding, hardcoded, is .kdelnk;
241  // this is preserved for backwards compatibility
242  if ( fileName.endsWith( dotkdelnk ) )
243  return mimeType( "application/x-desktop" );
244  // .directory files are detected as x-desktop by mimemagic
245  // but don't have a Type= entry. Better cheat and say they are text files
246  if ( fileName == dotdirectory )
247  return mimeType( "text/plain" );
248  }
249 
250  if ( !_is_local_file || _fast_mode )
251  {
252  TQString def = KProtocolInfo::defaultMimetype( _url );
253  if ( !def.isEmpty() && def != defaultMimeType() )
254  {
255  // The protocol says it always returns a given mimetype (e.g. text/html for "man:")
256  return mimeType( def );
257  }
258  if ( path.endsWith( slash ) || path.isEmpty() )
259  {
260  // We have no filename at all. Maybe the protocol has a setting for
261  // which mimetype this means (e.g. directory).
262  // For HTTP (def==defaultMimeType()) we don't assume anything,
263  // because of redirections (e.g. freshmeat downloads).
264  if ( def.isEmpty() )
265  {
266  // Assume inode/directory, if the protocol supports listing.
267  if ( KProtocolInfo::supportsListing( _url ) )
268  return mimeType( TQString::fromLatin1("inode/directory") );
269  else
270  return defaultMimeTypePtr(); // == 'no idea', e.g. for "data:,foo/"
271  }
272  }
273 
274  // No more chances for non local URLs
275  return defaultMimeTypePtr();
276  }
277 
278  // Do some magic for local files
279  //kdDebug(7009) << TQString("Mime Type finding for '%1'").arg(path) << endl;
280  KMimeMagicResult* result = KMimeMagic::self()->findFileType( path );
281 
282  // If we still did not find it, we must assume the default mime type
283  if ( !result || !result->isValid() )
284  return defaultMimeTypePtr();
285 
286  // The mimemagic stuff was successful
287  return mimeType( result->mimeType() );
288 }
289 
290 KMimeType::Ptr KMimeType::findByURL( const KURL& _url, mode_t _mode,
291  bool _is_local_file, bool _fast_mode,
292  bool *accurate)
293 {
294  KMimeType::Ptr mime = findByURL(_url, _mode, _is_local_file, _fast_mode);
295  if (accurate) *accurate = !(_fast_mode) || ((mime->patternsAccuracy() == 100) && mime != defaultMimeTypePtr());
296  return mime;
297 }
298 
299 KMimeType::Ptr KMimeType::diagnoseFileName(const TQString &fileName, TQString &pattern)
300 {
301  return KServiceTypeFactory::self()->findFromPattern( fileName, &pattern );
302 }
303 
304 KMimeType::Ptr KMimeType::findByPath( const TQString& path, mode_t mode, bool fast_mode )
305 {
306  KURL u;
307  u.setPath(path);
308  return findByURL( u, mode, true, fast_mode );
309 }
310 
311 KMimeType::Ptr KMimeType::findByContent( const TQByteArray &data, int *accuracy )
312 {
313  KMimeMagicResult *result = KMimeMagic::self()->findBufferType(data);
314  if (accuracy)
315  *accuracy = result->accuracy();
316  return mimeType( result->mimeType() );
317 }
318 
319 KMimeType::Ptr KMimeType::findByFileContent( const TQString &fileName, int *accuracy )
320 {
321  KMimeMagicResult *result = KMimeMagic::self()->findFileType(fileName);
322  if (accuracy)
323  *accuracy = result->accuracy();
324  return mimeType( result->mimeType() );
325 }
326 
327 #define GZIP_MAGIC1 0x1f
328 #define GZIP_MAGIC2 0x8b
329 
330 KMimeType::Format KMimeType::findFormatByFileContent( const TQString &fileName )
331 {
332  KMimeType::Format result;
333  result.compression = Format::NoCompression;
334  KMimeType::Ptr mime = findByPath(fileName);
335 
336  result.text = mime->name().startsWith("text/");
337  TQVariant v = mime->property("X-KDE-text");
338  if (v.isValid())
339  result.text = v.toBool();
340 
341  if (mime->name().startsWith("inode/"))
342  return result;
343 
344  TQFile f(fileName);
345  if (f.open(IO_ReadOnly))
346  {
347  unsigned char buf[10+1];
348  int l = f.readBlock((char *)buf, 10);
349  if ((l > 2) && (buf[0] == GZIP_MAGIC1) && (buf[1] == GZIP_MAGIC2))
350  result.compression = Format::GZipCompression;
351  }
352  return result;
353 }
354 
355 KMimeType::KMimeType( const TQString & _fullpath, const TQString& _type, const TQString& _icon,
356  const TQString& _comment, const TQStringList& _patterns )
357  : KServiceType( _fullpath, _type, _icon, _comment )
358 {
359  m_lstPatterns = _patterns;
360 }
361 
362 KMimeType::KMimeType( const TQString & _fullpath ) : KServiceType( _fullpath )
363 {
364  KDesktopFile _cfg( _fullpath, true );
365  init ( &_cfg );
366 
367  if ( !isValid() )
368  kdWarning(7009) << "mimetype not valid '" << m_strName << "' (missing entry in the file ?)" << endl;
369 }
370 
371 KMimeType::KMimeType( KDesktopFile *config ) : KServiceType( config )
372 {
373  init( config );
374 
375  if ( !isValid() )
376  kdWarning(7009) << "mimetype not valid '" << m_strName << "' (missing entry in the file ?)" << endl;
377 }
378 
379 void KMimeType::init( KDesktopFile * config )
380 {
381  config->setDesktopGroup();
382  m_lstPatterns = config->readListEntry( "Patterns", ';' );
383 
384  // Read the X-KDE-AutoEmbed setting and store it in the properties map
385  TQString XKDEAutoEmbed = TQString::fromLatin1("X-KDE-AutoEmbed");
386  if ( config->hasKey( XKDEAutoEmbed ) )
387  m_mapProps.insert( XKDEAutoEmbed, TQVariant( config->readBoolEntry( XKDEAutoEmbed ), 0 ) );
388 
389  TQString XKDEText = TQString::fromLatin1("X-KDE-text");
390  if ( config->hasKey( XKDEText ) )
391  m_mapProps.insert( XKDEText, config->readBoolEntry( XKDEText ) );
392 
393  TQString XKDEIsAlso = TQString::fromLatin1("X-KDE-IsAlso");
394  if ( config->hasKey( XKDEIsAlso ) ) {
395  TQString inherits = config->readEntry( XKDEIsAlso );
396  if ( inherits != name() )
397  m_mapProps.insert( XKDEIsAlso, inherits );
398  else
399  kdWarning(7009) << "Error: " << inherits << " inherits from itself!!!!" << endl;
400  }
401 
402  TQString XKDEPatternsAccuracy = TQString::fromLatin1("X-KDE-PatternsAccuracy");
403  if ( config->hasKey( XKDEPatternsAccuracy ) )
404  m_mapProps.insert( XKDEPatternsAccuracy, config->readEntry( XKDEPatternsAccuracy ) );
405 
406 }
407 
408 KMimeType::KMimeType( TQDataStream& _str, int offset ) : KServiceType( _str, offset )
409 {
410  loadInternal( _str ); // load our specific stuff
411 }
412 
413 void KMimeType::load( TQDataStream& _str )
414 {
415  KServiceType::load( _str );
416  loadInternal( _str );
417 }
418 
419 void KMimeType::loadInternal( TQDataStream& _str )
420 {
421  // kdDebug(7009) << "KMimeType::load( TQDataStream& ) : loading list of patterns" << endl;
422  _str >> m_lstPatterns;
423 }
424 
425 void KMimeType::save( TQDataStream& _str )
426 {
427  KServiceType::save( _str );
428  // Warning adding/removing fields here involves a binary incompatible change - update version
429  // number in ksycoca.h
430  _str << m_lstPatterns;
431 }
432 
433 TQVariant KMimeType::property( const TQString& _name ) const
434 {
435  if ( _name == "Patterns" )
436  return TQVariant( m_lstPatterns );
437 
438  return KServiceType::property( _name );
439 }
440 
441 TQStringList KMimeType::propertyNames() const
442 {
443  TQStringList res = KServiceType::propertyNames();
444  res.append( "Patterns" );
445 
446  return res;
447 }
448 
449 KMimeType::~KMimeType()
450 {
451 }
452 
453 TQPixmap KMimeType::pixmap( KIcon::Group _group, int _force_size, int _state,
454  TQString * _path ) const
455 {
456  KIconLoader *iconLoader=KGlobal::iconLoader();
457  TQString iconName=icon( TQString::null, false );
458  if (!iconLoader->extraDesktopThemesAdded())
459  {
460  TQPixmap pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path, true );
461  if (!pixmap.isNull() ) return pixmap;
462 
463  iconLoader->addExtraDesktopThemes();
464  }
465 
466  return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path, false );
467 }
468 
469 TQPixmap KMimeType::pixmap( const KURL& _url, KIcon::Group _group, int _force_size,
470  int _state, TQString * _path ) const
471 {
472  KIconLoader *iconLoader=KGlobal::iconLoader();
473  TQString iconName=icon( _url, _url.isLocalFile() );
474  if (!iconLoader->extraDesktopThemesAdded())
475  {
476  TQPixmap pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path, true );
477  if (!pixmap.isNull() ) return pixmap;
478 
479  iconLoader->addExtraDesktopThemes();
480  }
481 
482  return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path, false );
483 }
484 
485 TQPixmap KMimeType::pixmapForURL( const KURL & _url, mode_t _mode, KIcon::Group _group,
486  int _force_size, int _state, TQString * _path )
487 {
488  KIconLoader *iconLoader=KGlobal::iconLoader();
489  TQString iconName = iconForURL( _url, _mode );
490 
491  if (!iconLoader->extraDesktopThemesAdded())
492  {
493  TQPixmap pixmap=iconLoader->loadIcon( iconName, _group, _force_size, _state, _path, true );
494  if (!pixmap.isNull() ) return pixmap;
495 
496  iconLoader->addExtraDesktopThemes();
497  }
498 
499  return iconLoader->loadIcon( iconName , _group, _force_size, _state, _path, false );
500 
501 }
502 
503 TQString KMimeType::iconForURL( const KURL & _url, mode_t _mode )
504 {
505  const KMimeType::Ptr mt = findByURL( _url, _mode, _url.isLocalFile(),
506  false /*HACK*/);
507  static const TQString& unknown = KGlobal::staticQString("unknown");
508  const TQString mimeTypeIcon = mt->icon( _url, _url.isLocalFile() );
509  TQString i = mimeTypeIcon;
510 
511  // if we don't find an icon, maybe we can use the one for the protocol
512  if ( i == unknown || i.isEmpty() || mt == defaultMimeTypePtr()
513  // and for the root of the protocol (e.g. trash:/) the protocol icon has priority over the mimetype icon
514  || _url.path().length() <= 1 )
515  {
516  i = favIconForURL( _url ); // maybe there is a favicon?
517 
518  if ( i.isEmpty() )
519  i = KProtocolInfo::icon( _url.protocol() );
520 
521  // root of protocol: if we found nothing, revert to mimeTypeIcon (which is usually "folder")
522  if ( _url.path().length() <= 1 && ( i == unknown || i.isEmpty() ) )
523  i = mimeTypeIcon;
524  }
525  return i;
526 }
527 
528 TQString KMimeType::favIconForURL( const KURL& url )
529 {
530  // this method will be called quite often, so better not read the config
531  // again and again.
532  static bool useFavIcons = true;
533  static bool check = true;
534  if ( check ) {
535  check = false;
536  KConfig *config = KGlobal::config();
537  KConfigGroupSaver cs( config, "HTML Settings" );
538  useFavIcons = config->readBoolEntry( "EnableFavicon", true );
539  }
540 
541  if ( url.isLocalFile() || !url.protocol().startsWith("http")
542  || !useFavIcons )
543  return TQString::null;
544 
545  DCOPRef kded( "kded", "favicons" );
546  DCOPReply result = kded.call( "iconForURL(KURL)", url );
547  if ( result.isValid() )
548  return result;
549 
550  return TQString::null;
551 }
552 
553 TQString KMimeType::parentMimeType() const
554 {
555  TQVariant v = property("X-KDE-IsAlso");
556  return v.toString();
557 }
558 
559 bool KMimeType::is( const TQString& mimeTypeName ) const
560 {
561  if ( name() == mimeTypeName )
562  return true;
563  TQString st = parentMimeType();
564  //if (st.isEmpty()) kdDebug(7009)<<"Parent mimetype is empty"<<endl;
565  while ( !st.isEmpty() )
566  {
567  //kdDebug(7009)<<"Checking parent mime type: "<<st<<endl;
568  KMimeType::Ptr ptr = KMimeType::mimeType( st );
569  if (!ptr) return false; //error
570  if ( ptr->name() == mimeTypeName )
571  return true;
572  st = ptr->parentMimeType();
573  }
574  return false;
575 }
576 
577 int KMimeType::patternsAccuracy() const {
578  TQVariant v = property("X-KDE-PatternsAccuracy");
579  if (!v.isValid()) return 100;
580  else
581  return v.toInt();
582 }
583 
584 
585 /*******************************************************
586  *
587  * KFolderType
588  *
589  ******************************************************/
590 
591 TQString KFolderType::icon( const TQString& _url, bool _is_local ) const
592 {
593  if ( !_is_local || _url.isEmpty() )
594  return KMimeType::icon( _url, _is_local );
595 
596  return KFolderType::icon( KURL(_url), _is_local );
597 }
598 
599 TQString KFolderType::icon( const KURL& _url, bool _is_local ) const
600 {
601  if ( !_is_local )
602  return KMimeType::icon( _url, _is_local );
603 
604  KURL u( _url );
605  u.addPath( ".directory" );
606 
607  TQString icon;
608  // using KStandardDirs as this one checks for path being
609  // a file instead of a directory
610  if ( KStandardDirs::exists( u.path() ) )
611  {
612  KSimpleConfig cfg( u.path(), true );
613  cfg.setDesktopGroup();
614  icon = cfg.readEntry( "Icon" );
615  TQString empty_icon = cfg.readEntry( "EmptyIcon" );
616 
617  if ( !empty_icon.isEmpty() )
618  {
619  bool isempty = false;
620  DIR *dp = 0L;
621  struct dirent *ep;
622  dp = opendir( TQFile::encodeName(_url.path()) );
623  if ( dp )
624  {
625  TQValueList<TQCString> entries;
626  // Note that readdir isn't guaranteed to return "." and ".." first (#79826)
627  ep=readdir( dp ); if ( ep ) entries.append( ep->d_name );
628  ep=readdir( dp ); if ( ep ) entries.append( ep->d_name );
629  if ( (ep=readdir( dp )) == 0L ) // third file is NULL entry -> empty directory
630  isempty = true;
631  else {
632  entries.append( ep->d_name );
633  if ( readdir( dp ) == 0 ) { // only three
634  // check if we got "." ".." and ".directory"
635  isempty = entries.find( "." ) != entries.end() &&
636  entries.find( ".." ) != entries.end() &&
637  entries.find( ".directory" ) != entries.end();
638  }
639  }
640  if (!isempty && !strcmp(ep->d_name, ".directory"))
641  isempty = (readdir(dp) == 0L);
642  closedir( dp );
643  }
644 
645  if ( isempty )
646  return empty_icon;
647  }
648  }
649 
650  if ( icon.isEmpty() )
651  return KMimeType::icon( _url, _is_local );
652 
653  if ( icon.startsWith( "./" ) ) {
654  // path is relative with respect to the location
655  // of the .directory file (#73463)
656  KURL v( _url );
657  v.addPath( icon.mid( 2 ) );
658  icon = v.path();
659  }
660 
661  return icon;
662 }
663 
664 TQString KFolderType::comment( const TQString& _url, bool _is_local ) const
665 {
666  if ( !_is_local || _url.isEmpty() )
667  return KMimeType::comment( _url, _is_local );
668 
669  return KFolderType::comment( KURL(_url), _is_local );
670 }
671 
672 TQString KFolderType::comment( const KURL& _url, bool _is_local ) const
673 {
674  if ( !_is_local )
675  return KMimeType::comment( _url, _is_local );
676 
677  KURL u( _url );
678  u.addPath( ".directory" );
679 
680  KDesktopFile cfg( u.path(), true );
681  TQString comment = cfg.readComment();
682  if ( comment.isEmpty() )
683  return KMimeType::comment( _url, _is_local );
684 
685  return comment;
686 }
687 
688 /*******************************************************
689  *
690  * KDEDesktopMimeType
691  *
692  ******************************************************/
693 
694 TQString KDEDesktopMimeType::icon( const TQString& _url, bool _is_local ) const
695 {
696  if ( !_is_local || _url.isEmpty() )
697  return KMimeType::icon( _url, _is_local );
698 
699  KURL u( _url );
700  return icon( u, _is_local );
701 }
702 
703 TQString KDEDesktopMimeType::icon( const KURL& _url, bool _is_local ) const
704 {
705  if ( !_is_local )
706  return KMimeType::icon( _url, _is_local );
707 
708  KSimpleConfig cfg( _url.path(), true );
709  cfg.setDesktopGroup();
710  TQString icon = cfg.readEntry( "Icon" );
711  TQString type = cfg.readEntry( "Type" );
712 
713  if ( type == "FSDevice" || type == "FSDev") // need to provide FSDev for
714  // backwards compatibility
715  {
716  TQString unmount_icon = cfg.readEntry( "UnmountIcon" );
717  TQString dev = cfg.readEntry( "Dev" );
718  if ( !icon.isEmpty() && !unmount_icon.isEmpty() && !dev.isEmpty() )
719  {
720  TQString mp = KIO::findDeviceMountPoint( dev );
721  // Is the device not mounted ?
722  if ( mp.isNull() )
723  return unmount_icon;
724  }
725  } else if ( type == "Link" ) {
726  const TQString emptyIcon = cfg.readEntry( "EmptyIcon" );
727  if ( !emptyIcon.isEmpty() ) {
728  const TQString u = cfg.readPathEntry( "URL" );
729  const KURL url( u );
730  if ( url.protocol() == "trash" ) {
731  // We need to find if the trash is empty, preferrably without using a KIO job.
732  // So instead kio_trash leaves an entry in its config file for us.
733  KSimpleConfig trashConfig( "trashrc", true );
734  trashConfig.setGroup( "Status" );
735  if ( trashConfig.readBoolEntry( "Empty", true ) ) {
736  return emptyIcon;
737  }
738  }
739  }
740  }
741 
742  if ( icon.isEmpty() )
743  return KMimeType::icon( _url, _is_local );
744 
745  return icon;
746 }
747 
748 TQPixmap KDEDesktopMimeType::pixmap( const KURL& _url, KIcon::Group _group, int _force_size,
749  int _state, TQString * _path ) const
750 {
751  TQString _icon = icon( _url, _url.isLocalFile() );
752  TQPixmap pix = KGlobal::iconLoader()->loadIcon( _icon, _group,
753  _force_size, _state, _path, false );
754  if ( pix.isNull() )
755  pix = KGlobal::iconLoader()->loadIcon( "unknown", _group,
756  _force_size, _state, _path, false );
757  return pix;
758 }
759 
760 TQString KDEDesktopMimeType::comment( const TQString& _url, bool _is_local ) const
761 {
762  if ( !_is_local || _url.isEmpty() )
763  return KMimeType::comment( _url, _is_local );
764 
765  KURL u( _url );
766  return comment( u, _is_local );
767 }
768 
769 TQString KDEDesktopMimeType::comment( const KURL& _url, bool _is_local ) const
770 {
771  if ( !_is_local )
772  return KMimeType::comment( _url, _is_local );
773 
774  KDesktopFile cfg( _url.path(), true );
775  TQString comment = cfg.readComment();
776  if ( comment.isEmpty() )
777  return KMimeType::comment( _url, _is_local );
778 
779  return comment;
780 }
781 
782 pid_t KDEDesktopMimeType::run( const KURL& u, bool _is_local )
783 {
784  // It might be a security problem to run external untrusted desktop
785  // entry files
786  if ( !_is_local )
787  return 0;
788 
789  KSimpleConfig cfg( u.path(), true );
790  cfg.setDesktopGroup();
791  TQString type = cfg.readEntry( "Type" );
792  if ( type.isEmpty() )
793  {
794  TQString tmp = i18n("The desktop entry file %1 "
795  "has no Type=... entry.").arg(u.path() );
796  KMessageBoxWrapper::error( 0, tmp);
797  return 0;
798  }
799 
800  //kdDebug(7009) << "TYPE = " << type.data() << endl;
801 
802  if ( type == "FSDevice" )
803  return runFSDevice( u, cfg );
804  else if ( type == "Application" )
805  return runApplication( u, u.path() );
806  else if ( type == "Link" )
807  {
808  cfg.setDollarExpansion( true ); // for URL=file:$HOME (Simon)
809  return runLink( u, cfg );
810  }
811  else if ( type == "MimeType" )
812  return runMimeType( u, cfg );
813 
814 
815  TQString tmp = i18n("The desktop entry of type\n%1\nis unknown.").arg( type );
816  KMessageBoxWrapper::error( 0, tmp);
817 
818  return 0;
819 }
820 
821 pid_t KDEDesktopMimeType::runFSDevice( const KURL& _url, const KSimpleConfig &cfg )
822 {
823  pid_t retval = 0;
824 
825  TQString dev = cfg.readEntry( "Dev" );
826 
827  if ( dev.isEmpty() )
828  {
829  TQString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( _url.path() );
830  KMessageBoxWrapper::error( 0, tmp);
831  return retval;
832  }
833 
834  TQString mp = KIO::findDeviceMountPoint( dev );
835  // Is the device already mounted ?
836  if ( !mp.isNull() )
837  {
838  KURL mpURL;
839  mpURL.setPath( mp );
840  // Open a new window
841  retval = KRun::runURL( mpURL, TQString::fromLatin1("inode/directory") );
842  }
843  else
844  {
845  bool ro = cfg.readBoolEntry( "ReadOnly", false );
846  TQString fstype = cfg.readEntry( "FSType" );
847  if ( fstype == "Default" ) // KDE-1 thing
848  fstype = TQString::null;
849  TQString point = cfg.readEntry( "MountPoint" );
850 #ifndef Q_WS_WIN
851  (void) new KAutoMount( ro, fstype, dev, point, _url.path() );
852 #endif
853  retval = -1; // we don't want to return 0, but we don't want to return a pid
854  }
855 
856  return retval;
857 }
858 
859 pid_t KDEDesktopMimeType::runApplication( const KURL& , const TQString & _serviceFile )
860 {
861  KService s( _serviceFile );
862  if ( !s.isValid() )
863  // The error message was already displayed, so we can just quit here
864  return 0;
865 
866  KURL::List lst;
867  return KRun::run( s, lst );
868 }
869 
870 pid_t KDEDesktopMimeType::runLink( const KURL& _url, const KSimpleConfig &cfg )
871 {
872  TQString u = cfg.readPathEntry( "URL" );
873  if ( u.isEmpty() )
874  {
875  TQString tmp = i18n("The desktop entry file\n%1\nis of type Link but has no URL=... entry.").arg( _url.prettyURL() );
876  KMessageBoxWrapper::error( 0, tmp );
877  return 0;
878  }
879 
880  KURL url ( u );
881  KRun* run = new KRun(url);
882 
883  // X-KDE-LastOpenedWith holds the service desktop entry name that
884  // was should be preferred for opening this URL if possible.
885  // This is used by the Recent Documents menu for instance.
886  TQString lastOpenedWidth = cfg.readEntry( "X-KDE-LastOpenedWith" );
887  if ( !lastOpenedWidth.isEmpty() )
888  run->setPreferredService( lastOpenedWidth );
889 
890  return -1; // we don't want to return 0, but we don't want to return a pid
891 }
892 
893 pid_t KDEDesktopMimeType::runMimeType( const KURL& url , const KSimpleConfig & )
894 {
895  // Hmm, can't really use keditfiletype since we might be looking
896  // at the global file, or at a file not in share/mimelnk...
897 
898  TQStringList args;
899  args << "openProperties";
900  args << url.path();
901 
902  int pid;
903  if ( !KApplication::kdeinitExec("kfmclient", args, 0, &pid) )
904  return pid;
905 
906  KProcess p;
907  p << "kfmclient" << args;
908  p.start(KProcess::DontCare);
909  return p.pid();
910 }
911 
912 TQValueList<KDEDesktopMimeType::Service> KDEDesktopMimeType::builtinServices( const KURL& _url )
913 {
914  TQValueList<Service> result;
915 
916  if ( !_url.isLocalFile() )
917  return result;
918 
919  KSimpleConfig cfg( _url.path(), true );
920  cfg.setDesktopGroup();
921  TQString type = cfg.readEntry( "Type" );
922 
923  if ( type.isEmpty() )
924  return result;
925 
926  if ( type == "FSDevice" )
927  {
928  TQString dev = cfg.readEntry( "Dev" );
929  if ( dev.isEmpty() )
930  {
931  TQString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( _url.path() );
932  KMessageBoxWrapper::error( 0, tmp);
933  }
934  else
935  {
936  TQString mp = KIO::findDeviceMountPoint( dev );
937  // not mounted ?
938  if ( mp.isEmpty() )
939  {
940  Service mount;
941  mount.m_strName = i18n("Mount");
942  mount.m_type = ST_MOUNT;
943  result.append( mount );
944  }
945  else
946  {
947  Service unmount;
948 #ifdef HAVE_VOLMGT
949  /*
950  * Solaris' volume management can only umount+eject
951  */
952  unmount.m_strName = i18n("Eject");
953 #else
954  unmount.m_strName = i18n("Unmount");
955 #endif
956  unmount.m_type = ST_UNMOUNT;
957  result.append( unmount );
958  }
959  }
960  }
961 
962  return result;
963 }
964 
965 TQValueList<KDEDesktopMimeType::Service> KDEDesktopMimeType::userDefinedServices( const TQString& path, bool bLocalFiles )
966 {
967  KSimpleConfig cfg( path, true );
968  return userDefinedServices( path, cfg, bLocalFiles );
969 }
970 
971 TQValueList<KDEDesktopMimeType::Service> KDEDesktopMimeType::userDefinedServices( const TQString& path, KConfig& cfg, bool bLocalFiles )
972 {
973  return userDefinedServices( path, cfg, bLocalFiles, KURL::List() );
974 }
975 
976 TQValueList<KDEDesktopMimeType::Service> KDEDesktopMimeType::userDefinedServices( const TQString& path, KConfig& cfg, bool bLocalFiles, const KURL::List & file_list )
977 {
978  TQValueList<Service> result;
979 
980  cfg.setDesktopGroup();
981 
982  if ( !cfg.hasKey( "Actions" ) && !cfg.hasKey( "X-KDE-GetActionMenu") )
983  return result;
984 
985  if ( cfg.hasKey( "TryExec" ) )
986  {
987  TQString tryexec = cfg.readPathEntry( "TryExec" );
988  TQString exe = KStandardDirs::findExe( tryexec );
989  if (exe.isEmpty()) {
990  return result;
991  }
992  }
993 
994  TQStringList keys;
995 
996  if( cfg.hasKey( "X-KDE-GetActionMenu" )) {
997  TQString dcopcall = cfg.readEntry( "X-KDE-GetActionMenu" );
998  const TQCString app = TQString(dcopcall.section(' ', 0,0)).utf8();
999 
1000  TQByteArray dataToSend;
1001  TQDataStream dataStream(dataToSend, IO_WriteOnly);
1002  dataStream << file_list;
1003  TQCString replyType;
1004  TQByteArray replyData;
1005  TQCString object = TQString(dcopcall.section(' ', 1,-2)).utf8();
1006  TQString function = dcopcall.section(' ', -1);
1007  if(!function.endsWith("(KURL::List)")) {
1008  kdWarning() << "Desktop file " << path << " contains an invalid X-KDE-ShowIfDcopCall - the function must take the exact parameter (KURL::List) and must be specified." << endl;
1009  } else {
1010  if(kapp->dcopClient()->call( app, object,
1011  function.utf8(),
1012  dataToSend, replyType, replyData, true, -1)
1013  && replyType == "TQStringList" ) {
1014 
1015  TQDataStream dataStreamIn(replyData, IO_ReadOnly);
1016  dataStreamIn >> keys;
1017  }
1018  }
1019  }
1020 
1021  keys += cfg.readListEntry( "Actions", ';' ); //the desktop standard defines ";" as separator!
1022 
1023  if ( keys.count() == 0 )
1024  return result;
1025 
1026  TQStringList::ConstIterator it = keys.begin();
1027  TQStringList::ConstIterator end = keys.end();
1028  for ( ; it != end; ++it )
1029  {
1030  //kdDebug(7009) << "CURRENT KEY = " << (*it) << endl;
1031 
1032  TQString group = *it;
1033 
1034  if (group == "_SEPARATOR_")
1035  {
1036  Service s;
1037  result.append(s);
1038  continue;
1039  }
1040 
1041  group.prepend( "Desktop Action " );
1042 
1043  bool bInvalidMenu = false;
1044 
1045  if ( cfg.hasGroup( group ) )
1046  {
1047  cfg.setGroup( group );
1048 
1049  if ( !cfg.hasKey( "Name" ) || !cfg.hasKey( "Exec" ) )
1050  bInvalidMenu = true;
1051  else
1052  {
1053  TQString exec = cfg.readPathEntry( "Exec" );
1054  if ( bLocalFiles || exec.contains("%U") || exec.contains("%u") )
1055  {
1056  Service s;
1057  s.m_strName = cfg.readEntry( "Name" );
1058  s.m_strIcon = cfg.readEntry( "Icon" );
1059  s.m_strExec = exec;
1060  s.m_type = ST_USER_DEFINED;
1061  s.m_display = !cfg.readBoolEntry( "NoDisplay" );
1062  result.append( s );
1063  }
1064  }
1065  }
1066  else
1067  bInvalidMenu = true;
1068 
1069  if ( bInvalidMenu )
1070  {
1071  TQString tmp = i18n("The desktop entry file\n%1\n has an invalid menu entry\n%2.").arg( path ).arg( *it );
1072  KMessageBoxWrapper::error( 0, tmp );
1073  }
1074  }
1075 
1076  return result;
1077 }
1078 
1079 void KDEDesktopMimeType::executeService( const TQString& _url, KDEDesktopMimeType::Service& _service )
1080 {
1081  KURL u;
1082  u.setPath(_url);
1083  KURL::List lst;
1084  lst.append( u );
1085  executeService( lst, _service );
1086 }
1087 
1088 void KDEDesktopMimeType::executeService( const KURL::List& urls, KDEDesktopMimeType::Service& _service )
1089 {
1090  //kdDebug(7009) << "EXECUTING Service " << _service.m_strName << endl;
1091 
1092  if ( _service.m_type == ST_USER_DEFINED )
1093  {
1094  kdDebug() << "KDEDesktopMimeType::executeService " << _service.m_strName
1095  << " first url's path=" << urls.first().path() << " exec=" << _service.m_strExec << endl;
1096  KRun::run( _service.m_strExec, urls, _service.m_strName, _service.m_strIcon, _service.m_strIcon );
1097  // The action may update the desktop file. Example: eject unmounts (#5129).
1098  KDirNotify_stub allDirNotify("*", "KDirNotify*");
1099  allDirNotify.FilesChanged( urls );
1100  return;
1101  }
1102  else if ( _service.m_type == ST_MOUNT || _service.m_type == ST_UNMOUNT )
1103  {
1104  Q_ASSERT( urls.count() == 1 );
1105  TQString path = urls.first().path();
1106  //kdDebug(7009) << "MOUNT&UNMOUNT" << endl;
1107 
1108  KSimpleConfig cfg( path, true );
1109  cfg.setDesktopGroup();
1110  TQString dev = cfg.readEntry( "Dev" );
1111  if ( dev.isEmpty() )
1112  {
1113  TQString tmp = i18n("The desktop entry file\n%1\nis of type FSDevice but has no Dev=... entry.").arg( path );
1114  KMessageBoxWrapper::error( 0, tmp );
1115  return;
1116  }
1117  TQString mp = KIO::findDeviceMountPoint( dev );
1118 
1119  if ( _service.m_type == ST_MOUNT )
1120  {
1121  // Already mounted? Strange, but who knows ...
1122  if ( !mp.isEmpty() )
1123  {
1124  kdDebug(7009) << "ALREADY Mounted" << endl;
1125  return;
1126  }
1127 
1128  bool ro = cfg.readBoolEntry( "ReadOnly", false );
1129  TQString fstype = cfg.readEntry( "FSType" );
1130  if ( fstype == "Default" ) // KDE-1 thing
1131  fstype = TQString::null;
1132  TQString point = cfg.readEntry( "MountPoint" );
1133 #ifndef Q_WS_WIN
1134  (void)new KAutoMount( ro, fstype, dev, point, path, false );
1135 #endif
1136  }
1137  else if ( _service.m_type == ST_UNMOUNT )
1138  {
1139  // Not mounted? Strange, but who knows ...
1140  if ( mp.isEmpty() )
1141  return;
1142 
1143 #ifndef Q_WS_WIN
1144  (void)new KAutoUnmount( mp, path );
1145 #endif
1146  }
1147  }
1148  else
1149  assert( 0 );
1150 }
1151 
1152 const TQString & KMimeType::defaultMimeType()
1153 {
1154  static const TQString & s_strDefaultMimeType =
1155  KGlobal::staticQString( "application/octet-stream" );
1156  return s_strDefaultMimeType;
1157 }
1158 
1159 void KMimeType::virtual_hook( int id, void* data )
1160 { KServiceType::virtual_hook( id, data ); }
1161 
1162 void KFolderType::virtual_hook( int id, void* data )
1163 { KMimeType::virtual_hook( id, data ); }
1164 
1165 void KDEDesktopMimeType::virtual_hook( int id, void* data )
1166 { KMimeType::virtual_hook( id, data ); }
1167 
1168 void KExecMimeType::virtual_hook( int id, void* data )
1169 { KMimeType::virtual_hook( id, data ); }
1170 
1171 #include "kmimetyperesolver.moc"
1172 

kio/kio

Skip menu "kio/kio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kio/kio

Skip menu "kio/kio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kio/kio by doxygen 1.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |