00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sys/time.h>
00023 #include <pwd.h>
00024 #include <grp.h>
00025 #include <sys/types.h>
00026
00027 #include <assert.h>
00028 #include <unistd.h>
00029
00030 #include "kfileitem.h"
00031
00032 #include <qdir.h>
00033 #include <qfile.h>
00034 #include <qmap.h>
00035 #include <qstylesheet.h>
00036
00037 #include <klargefile.h>
00038 #include <kiconloader.h>
00039 #include <kglobal.h>
00040 #include <kdebug.h>
00041 #include <klocale.h>
00042 #include <kmimetype.h>
00043 #include <krun.h>
00044 #include <kfilemetainfo.h>
00045 #include <kfileshare.h>
00046
00047 KFileItem::KFileItem( const KIO::UDSEntry& _entry, const KURL& _url,
00048 bool _determineMimeTypeOnDemand, bool _urlIsDirectory ) :
00049 m_entry( _entry ),
00050 m_url( _url ),
00051 m_pMimeType( 0 ),
00052 m_fileMode( KFileItem::Unknown ),
00053 m_permissions( KFileItem::Unknown ),
00054 m_bMarked( false ),
00055 m_bLink( false ),
00056 m_bIsLocalURL( _url.isLocalFile() ),
00057 m_bMimeTypeKnown( false ),
00058 d(0L)
00059 {
00060 bool UDS_URL_seen = false;
00061
00062 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00063 for( ; it != m_entry.end(); it++ ) {
00064 switch ((*it).m_uds) {
00065
00066 case KIO::UDS_FILE_TYPE:
00067 m_fileMode = (mode_t)((*it).m_long);
00068 break;
00069
00070 case KIO::UDS_ACCESS:
00071 m_permissions = (mode_t)((*it).m_long);
00072 break;
00073
00074 case KIO::UDS_USER:
00075 m_user = ((*it).m_str);
00076 break;
00077
00078 case KIO::UDS_GROUP:
00079 m_group = ((*it).m_str);
00080 break;
00081
00082 case KIO::UDS_NAME:
00083 m_strName = (*it).m_str;
00084 m_strText = KIO::decodeFileName( m_strName );
00085 break;
00086
00087 case KIO::UDS_URL:
00088 UDS_URL_seen = true;
00089 m_url = KURL((*it).m_str);
00090 break;
00091
00092 case KIO::UDS_MIME_TYPE:
00093 m_pMimeType = KMimeType::mimeType((*it).m_str);
00094 m_bMimeTypeKnown = true;
00095 break;
00096
00097 case KIO::UDS_GUESSED_MIME_TYPE:
00098 m_guessedMimeType = (*it).m_str;
00099 break;
00100
00101 case KIO::UDS_LINK_DEST:
00102 m_bLink = !(*it).m_str.isEmpty();
00103 break;
00104 }
00105 }
00106
00107 static const QString& dot = KGlobal::staticQString(".");
00108 if ( _urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != dot )
00109 m_url.addPath( m_strName );
00110 init( _determineMimeTypeOnDemand );
00111 }
00112
00113 KFileItem::KFileItem( mode_t _mode, mode_t _permissions, const KURL& _url, bool _determineMimeTypeOnDemand ) :
00114 m_entry(),
00115 m_url( _url ),
00116 m_strName( _url.fileName() ),
00117 m_strText( KIO::decodeFileName( m_strName ) ),
00118 m_pMimeType( 0 ),
00119 m_fileMode ( _mode ),
00120 m_permissions( _permissions ),
00121 m_bMarked( false ),
00122 m_bLink( false ),
00123 m_bIsLocalURL( _url.isLocalFile() ),
00124 m_bMimeTypeKnown( false ),
00125 d(0L)
00126 {
00127 init( _determineMimeTypeOnDemand );
00128 }
00129
00130 KFileItem::KFileItem( const KURL &url, const QString &mimeType, mode_t mode )
00131 : m_url( url ),
00132 m_strName( url.fileName() ),
00133 m_strText( KIO::decodeFileName( m_strName ) ),
00134 m_fileMode( mode ),
00135 m_permissions( KFileItem::Unknown ),
00136 m_bMarked( false ),
00137 m_bLink( false ),
00138 m_bIsLocalURL( url.isLocalFile() ),
00139 m_bMimeTypeKnown( false ),
00140 d(0L)
00141 {
00142 m_pMimeType = KMimeType::mimeType( mimeType );
00143 init( false );
00144 }
00145
00146 KFileItem::KFileItem( const KFileItem & item ) :
00147 d(0L)
00148 {
00149 assign( item );
00150 }
00151
00152 KFileItem::~KFileItem()
00153 {
00154 }
00155
00156 void KFileItem::init( bool _determineMimeTypeOnDemand )
00157 {
00158 m_access = QString::null;
00159 m_size = (KIO::filesize_t) -1;
00160
00161 for ( int i = 0; i < NumFlags; i++ )
00162 m_time[i] = (time_t) -1;
00163
00164
00165 if ( m_fileMode == KFileItem::Unknown || m_permissions == KFileItem::Unknown )
00166 {
00167 mode_t mode = 0;
00168 if ( m_url.isLocalFile() )
00169 {
00170
00171
00172
00173
00174
00175
00176
00177 KDE_struct_stat buf;
00178 QCString path = QFile::encodeName(m_url.path( -1 ));
00179 if ( KDE_lstat( path.data(), &buf ) == 0 )
00180 {
00181 mode = buf.st_mode;
00182 if ( S_ISLNK( mode ) )
00183 {
00184 m_bLink = true;
00185 if ( KDE_stat( path.data(), &buf ) == 0 )
00186 mode = buf.st_mode;
00187 else
00188 mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO;
00189 }
00190 }
00191 }
00192 if ( m_fileMode == KFileItem::Unknown )
00193 m_fileMode = mode & S_IFMT;
00194 if ( m_permissions == KFileItem::Unknown )
00195 m_permissions = mode & 07777;
00196 }
00197
00198
00199 if (!m_pMimeType )
00200 {
00201 m_pMimeType = KMimeType::findByURL( m_url, m_fileMode, m_bIsLocalURL,
00202
00203 _determineMimeTypeOnDemand );
00204
00205
00206 m_bMimeTypeKnown = (!_determineMimeTypeOnDemand) || (m_pMimeType->name() != KMimeType::defaultMimeType());
00207 }
00208
00209 }
00210
00211 void KFileItem::refresh()
00212 {
00213 m_fileMode = KFileItem::Unknown;
00214 m_permissions = KFileItem::Unknown;
00215 m_user = QString::null;
00216 m_group = QString::null;
00217 m_access = QString::null;
00218 m_size = (KIO::filesize_t) -1;
00219 m_metaInfo = KFileMetaInfo();
00220 for ( int i = 0; i < NumFlags; i++ )
00221 m_time[i] = (time_t) -1;
00222
00223
00224
00225
00226
00227 m_entry = KIO::UDSEntry();
00228 init( false );
00229 }
00230
00231 void KFileItem::refreshMimeType()
00232 {
00233 m_pMimeType = 0L;
00234 init( false );
00235 }
00236
00237 void KFileItem::setURL( const KURL &url )
00238 {
00239 m_url = url;
00240 m_strName = url.fileName();
00241 m_strText = KIO::decodeFileName( m_strName );
00242 }
00243
00244 QString KFileItem::linkDest() const
00245 {
00246
00247 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00248 for( ; it != m_entry.end(); it++ )
00249 if ( (*it).m_uds == KIO::UDS_LINK_DEST )
00250 return (*it).m_str;
00251
00252 if ( m_bIsLocalURL )
00253 {
00254 char buf[1000];
00255 int n = readlink( QFile::encodeName(m_url.path( -1 )), buf, sizeof(buf)-1 );
00256 if ( n != -1 )
00257 {
00258 buf[ n ] = 0;
00259 return QString::fromLocal8Bit( buf );
00260 }
00261 }
00262 return QString::null;
00263 }
00264
00265 KIO::filesize_t KFileItem::size() const
00266 {
00267 if ( m_size != (KIO::filesize_t) -1 )
00268 return m_size;
00269
00270
00271 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00272 for( ; it != m_entry.end(); it++ )
00273 if ( (*it).m_uds == KIO::UDS_SIZE ) {
00274 m_size = (*it).m_long;
00275 return m_size;
00276 }
00277
00278 if ( m_bIsLocalURL )
00279 {
00280 KDE_struct_stat buf;
00281 KDE_stat( QFile::encodeName(m_url.path( -1 )), &buf );
00282 return buf.st_size;
00283 }
00284 return 0L;
00285 }
00286
00287 time_t KFileItem::time( unsigned int which ) const
00288 {
00289 unsigned int mappedWhich = 0;
00290
00291 switch( which ) {
00292 case KIO::UDS_MODIFICATION_TIME:
00293 mappedWhich = Modification;
00294 break;
00295 case KIO::UDS_ACCESS_TIME:
00296 mappedWhich = Access;
00297 break;
00298 case KIO::UDS_CREATION_TIME:
00299 mappedWhich = Creation;
00300 break;
00301 }
00302
00303 if ( m_time[mappedWhich] != (time_t) -1 )
00304 return m_time[mappedWhich];
00305
00306
00307 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00308 for( ; it != m_entry.end(); it++ )
00309 if ( (*it).m_uds == which ) {
00310 m_time[mappedWhich] = static_cast<time_t>((*it).m_long);
00311 return m_time[mappedWhich];
00312 }
00313
00314
00315 if ( m_bIsLocalURL )
00316 {
00317 KDE_struct_stat buf;
00318 KDE_stat( QFile::encodeName(m_url.path( -1 )), &buf );
00319 m_time[mappedWhich] = (which == KIO::UDS_MODIFICATION_TIME) ?
00320 buf.st_mtime :
00321 (which == KIO::UDS_ACCESS_TIME) ? buf.st_atime :
00322 static_cast<time_t>(0);
00323 return m_time[mappedWhich];
00324 }
00325 return static_cast<time_t>(0);
00326 }
00327
00328
00329 QString KFileItem::user() const
00330 {
00331 if ( m_user.isEmpty() && m_bIsLocalURL )
00332 {
00333 KDE_struct_stat buff;
00334 if ( KDE_lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0)
00335 {
00336 struct passwd *user = getpwuid( buff.st_uid );
00337 if ( user != 0L )
00338 m_user = QString::fromLocal8Bit(user->pw_name);
00339 }
00340 }
00341 return m_user;
00342 }
00343
00344 QString KFileItem::group() const
00345 {
00346 if (m_group.isEmpty() && m_bIsLocalURL )
00347 {
00348 KDE_struct_stat buff;
00349 if ( KDE_lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0)
00350 {
00351 struct group *ge = getgrgid( buff.st_gid );
00352 if ( ge != 0L ) {
00353 m_group = QString::fromLocal8Bit(ge->gr_name);
00354 if (m_group.isEmpty())
00355 m_group.sprintf("%d",ge->gr_gid);
00356 } else
00357 m_group.sprintf("%d",buff.st_gid);
00358 }
00359 }
00360 return m_group;
00361 }
00362
00363 QString KFileItem::mimetype() const
00364 {
00365 KFileItem * that = const_cast<KFileItem *>(this);
00366 return that->determineMimeType()->name();
00367 }
00368
00369 KMimeType::Ptr KFileItem::determineMimeType()
00370 {
00371 if ( !m_pMimeType || !m_bMimeTypeKnown )
00372 {
00373 m_pMimeType = KMimeType::findByURL( m_url, m_fileMode, m_bIsLocalURL );
00374
00375 m_bMimeTypeKnown = true;
00376 }
00377
00378 return m_pMimeType;
00379 }
00380
00381 bool KFileItem::isMimeTypeKnown() const
00382 {
00383
00384
00385
00386 return m_bMimeTypeKnown && m_guessedMimeType.isEmpty();
00387 }
00388
00389 QString KFileItem::mimeComment()
00390 {
00391 KMimeType::Ptr mType = determineMimeType();
00392 QString comment = mType->comment( m_url, m_bIsLocalURL );
00393 if (!comment.isEmpty())
00394 return comment;
00395 else
00396 return mType->name();
00397 }
00398
00399 QString KFileItem::iconName()
00400 {
00401 return determineMimeType()->icon(m_url, m_bIsLocalURL);
00402 }
00403
00404 int KFileItem::overlays() const
00405 {
00406 int _state = 0;
00407 if ( m_bLink )
00408 _state |= KIcon::LinkOverlay;
00409
00410 if ( !S_ISDIR( m_fileMode )
00411 && !isReadable())
00412 _state |= KIcon::LockOverlay;
00413
00414 if ( m_strName[0] == '.' )
00415 _state |= KIcon::HiddenOverlay;
00416
00417 if( S_ISDIR( m_fileMode ) && m_bIsLocalURL)
00418 {
00419 if (KFileShare::isDirectoryShared( m_url.path() ))
00420 {
00421 kdDebug()<<"KFileShare::isDirectoryShared : "<<m_url.path()<<endl;
00422 _state |= KIcon::ShareOverlay;
00423 }
00424 }
00425
00426 if ( m_pMimeType->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
00427 _state |= KIcon::ZipOverlay;
00428 return _state;
00429 }
00430
00431 QPixmap KFileItem::pixmap( int _size, int _state ) const
00432 {
00433 if ( !m_pMimeType )
00434 {
00435 static const QString & defaultFolderIcon =
00436 KGlobal::staticQString(KMimeType::mimeType( "inode/directory" )->KServiceType::icon());
00437 if ( S_ISDIR( m_fileMode ) )
00438 return DesktopIcon( defaultFolderIcon, _size, _state );
00439
00440 return DesktopIcon( "unknown", _size, _state );
00441 }
00442
00443 _state |= overlays();
00444
00445 KMimeType::Ptr mime;
00446
00447 if ( !m_bMimeTypeKnown && !m_guessedMimeType.isEmpty() )
00448 mime = KMimeType::mimeType( m_guessedMimeType );
00449 else
00450 mime = m_pMimeType;
00451
00452
00453
00454 if ( mime->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
00455 {
00456 QString subFileName = m_url.path().left( m_url.path().length() - 3 );
00457
00458 mime = KMimeType::findByURL( subFileName, 0, m_bIsLocalURL );
00459 }
00460
00461 QPixmap p = mime->pixmap( m_url, KIcon::Desktop, _size, _state );
00462 if (p.isNull())
00463 kdWarning() << "Pixmap not found for mimetype " << m_pMimeType->name() << endl;
00464
00465 return p;
00466 }
00467
00468 bool KFileItem::isReadable() const
00469 {
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 if ( !(S_IRUSR & m_permissions) && !(S_IRGRP & m_permissions) && !(S_IROTH & m_permissions) )
00480 return false;
00481
00482
00483 else if ( m_bIsLocalURL && ::access( QFile::encodeName(m_url.path()), R_OK ) == -1 )
00484 return false;
00485
00486 return true;
00487 }
00488
00489 bool KFileItem::isDir() const
00490 {
00491 if ( !m_bMimeTypeKnown && !m_guessedMimeType.isEmpty() )
00492 {
00493 kdDebug() << " KFileItem::isDir can't say -> false " << endl;
00494 return false;
00495 }
00496 return S_ISDIR(m_fileMode);
00497 }
00498
00499 bool KFileItem::acceptsDrops()
00500 {
00501
00502 if ( S_ISDIR( mode() ) )
00503 {
00504 if ( m_bIsLocalURL )
00505 return (::access( QFile::encodeName(m_url.path()), X_OK ) == 0);
00506 else
00507 return true;
00508 }
00509
00510
00511 if ( !m_bIsLocalURL )
00512 return false;
00513
00514 if ( mimetype() == "application/x-desktop")
00515 return true;
00516
00517
00518 if ( ::access( QFile::encodeName(m_url.path()), X_OK ) == 0 )
00519 return true;
00520
00521 return false;
00522 }
00523
00524 QString KFileItem::getStatusBarInfo()
00525 {
00526 QString comment = determineMimeType()->comment( m_url, m_bIsLocalURL );
00527 QString text = m_strText;
00528
00529 QString myLinkDest = linkDest();
00530 KIO::filesize_t mySize = size();
00531
00532 if ( m_bLink )
00533 {
00534 QString tmp;
00535 if ( comment.isEmpty() )
00536 tmp = i18n ( "Symbolic Link" );
00537 else
00538 tmp = i18n("%1 (Link)").arg(comment);
00539 text += "->";
00540 text += myLinkDest;
00541 text += " ";
00542 text += tmp;
00543 }
00544 else if ( S_ISREG( m_fileMode ) )
00545 {
00546 text += QString(" (%1)").arg( KIO::convertSize( mySize ) );
00547 text += " ";
00548 text += comment;
00549 }
00550 else if ( S_ISDIR ( m_fileMode ) )
00551 {
00552 text += "/ ";
00553 text += comment;
00554 }
00555 else
00556 {
00557 text += " ";
00558 text += comment;
00559 }
00560 return text;
00561 }
00562
00563 QString KFileItem::getToolTipText(int maxcount)
00564 {
00565
00566 QString tip;
00567 KFileMetaInfo info = metaInfo();
00568
00569
00570
00571 const char* start = "<tr><td><nobr><font color=\"black\">";
00572 const char* mid = "</font></nobr></td><td><nobr><font color=\"black\">";
00573 const char* end = "</font></nobr></td></tr>";
00574
00575 tip = "<table cellspacing=0 cellpadding=0>";
00576
00577
00578
00579 tip += start + i18n("Type:") + mid;
00580
00581 QString type = QStyleSheet::escape(determineMimeType()->comment());
00582 if ( m_bLink )
00583 tip += i18n("Link to %1").arg(type) + end;
00584 else
00585 tip += type + end;
00586
00587 if ( !S_ISDIR ( m_fileMode ) )
00588 tip += start + i18n("Size:") + mid +
00589 KIO::convertSize( size() ) + end;
00590
00591 tip += start + i18n("Modified:") + mid +
00592 timeString( KIO::UDS_MODIFICATION_TIME) + end +
00593 start + i18n("Owner:") + mid + user() + " - " + group() + end +
00594 start + i18n("Permissions:") + mid +
00595 parsePermissions(m_permissions) + end;
00596
00597 if (info.isValid() && !info.isEmpty() )
00598 {
00599 QStringList keys = info.preferredKeys();
00600
00601
00602 QStringList::Iterator it = keys.begin();
00603 for (int count = 0; count<maxcount && it!=keys.end() ; ++it)
00604 {
00605 KFileMetaInfoItem item = info.item( *it );
00606 if ( item.isValid() )
00607 {
00608 QString s = item.string();
00609 if ( !s.isEmpty() )
00610 {
00611 count++;
00612 tip += start +
00613 QStyleSheet::escape( item.translatedKey() ) + ":" +
00614 mid +
00615 QStyleSheet::escape( s ) +
00616 end;
00617 }
00618
00619 }
00620 }
00621 tip += "</table>";
00622 }
00623
00624
00625
00626
00627 return tip;
00628 }
00629
00630 void KFileItem::run()
00631 {
00632 KURL url( m_url );
00633
00634
00635
00636 if ( m_bLink && m_bIsLocalURL )
00637 url = KURL( m_url, linkDest() );
00638 (void) new KRun( url, m_fileMode, m_bIsLocalURL );
00639 }
00640
00641 bool KFileItem::cmp( const KFileItem & item )
00642 {
00643 return ( m_strName == item.m_strName
00644 && m_bIsLocalURL == item.m_bIsLocalURL
00645 && m_fileMode == item.m_fileMode
00646 && m_permissions == item.m_permissions
00647 && m_user == item.m_user
00648 && m_group == item.m_group
00649 && m_bLink == item.m_bLink
00650 && size() == item.size()
00651 && time(KIO::UDS_MODIFICATION_TIME) == item.time(KIO::UDS_MODIFICATION_TIME) );
00652 }
00653
00654 void KFileItem::assign( const KFileItem & item )
00655 {
00656 m_entry = item.m_entry;
00657 m_url = item.m_url;
00658 m_bIsLocalURL = item.m_bIsLocalURL;
00659 m_strName = item.m_strName;
00660 m_strText = item.m_strText;
00661 m_fileMode = item.m_fileMode;
00662 m_permissions = item.m_permissions;
00663 m_user = item.m_user;
00664 m_group = item.m_group;
00665 m_bLink = item.m_bLink;
00666 m_pMimeType = item.m_pMimeType;
00667 m_strLowerCaseName = item.m_strLowerCaseName;
00668 m_bMimeTypeKnown = item.m_bMimeTypeKnown;
00669 m_guessedMimeType = item.m_guessedMimeType;
00670 m_access = item.m_access;
00671 m_metaInfo = item.m_metaInfo;
00672 for ( int i = 0; i < NumFlags; i++ )
00673 m_time[i] = item.m_time[i];
00674 m_size = item.m_size;
00675
00676
00677
00678
00679 determineMimeType();
00680 }
00681
00682 void KFileItem::setExtraData( const void *key, void *value )
00683 {
00684 if ( !key )
00685 return;
00686
00687 m_extra.replace( key, value );
00688 }
00689
00690 const void * KFileItem::extraData( const void *key ) const
00691 {
00692 QMapConstIterator<const void*,void*> it = m_extra.find( key );
00693 if ( it != m_extra.end() )
00694 return it.data();
00695 return 0L;
00696 }
00697
00698 void * KFileItem::extraData( const void *key )
00699 {
00700 QMapIterator<const void*,void*> it = m_extra.find( key );
00701 if ( it != m_extra.end() )
00702 return it.data();
00703 return 0L;
00704 }
00705
00706 void KFileItem::removeExtraData( const void *key )
00707 {
00708 m_extra.remove( key );
00709 }
00710
00711 QString KFileItem::permissionsString() const
00712 {
00713 if (m_access.isNull())
00714 m_access = parsePermissions( m_permissions );
00715
00716 return m_access;
00717 }
00718
00719 QString KFileItem::parsePermissions(mode_t perm) const
00720 {
00721 char p[] = "----------";
00722
00723 if (isDir())
00724 p[0]='d';
00725 else if (isLink())
00726 p[0]='l';
00727
00728 if (perm & QFileInfo::ReadUser)
00729 p[1]='r';
00730 if (perm & QFileInfo::WriteUser)
00731 p[2]='w';
00732 if (perm & QFileInfo::ExeUser)
00733 p[3]='x';
00734
00735 if (perm & QFileInfo::ReadGroup)
00736 p[4]='r';
00737 if (perm & QFileInfo::WriteGroup)
00738 p[5]='w';
00739 if (perm & QFileInfo::ExeGroup)
00740 p[6]='x';
00741
00742 if (perm & QFileInfo::ReadOther)
00743 p[7]='r';
00744 if (perm & QFileInfo::WriteOther)
00745 p[8]='w';
00746 if (perm & QFileInfo::ExeOther)
00747 p[9]='x';
00748
00749 return QString::fromLatin1(p);
00750 }
00751
00752
00753 QString KFileItem::timeString( unsigned int which ) const
00754 {
00755 QDateTime t;
00756 t.setTime_t( time(which) );
00757 return KGlobal::locale()->formatDateTime( t );
00758 }
00759
00760 void KFileItem::setMetaInfo( const KFileMetaInfo & info )
00761 {
00762 m_metaInfo = info;
00763 }
00764
00765 const KFileMetaInfo & KFileItem::metaInfo(bool autoget, int) const
00766 {
00767 if ( autoget && m_url.isLocalFile() && !m_metaInfo.isValid() )
00768 {
00769 m_metaInfo = KFileMetaInfo( m_url.path(), mimetype() );
00770 }
00771
00772 return m_metaInfo;
00773 }
00774
00775 void KFileItem::virtual_hook( int, void* )
00776 { }
00777