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 m_time[ Modification ] = buf.st_mtime;
00192 m_time[ Access ] = buf.st_atime;
00193 }
00194 }
00195 if ( m_fileMode == KFileItem::Unknown )
00196 m_fileMode = mode & S_IFMT;
00197 if ( m_permissions == KFileItem::Unknown )
00198 m_permissions = mode & 07777;
00199 }
00200
00201
00202 if (!m_pMimeType )
00203 {
00204 m_pMimeType = KMimeType::findByURL( m_url, m_fileMode, m_bIsLocalURL,
00205
00206 _determineMimeTypeOnDemand );
00207
00208
00209 m_bMimeTypeKnown = (!_determineMimeTypeOnDemand) || (m_pMimeType->name() != KMimeType::defaultMimeType());
00210 }
00211
00212 }
00213
00214 void KFileItem::refresh()
00215 {
00216 m_fileMode = KFileItem::Unknown;
00217 m_permissions = KFileItem::Unknown;
00218 m_user = QString::null;
00219 m_group = QString::null;
00220 m_access = QString::null;
00221 m_size = (KIO::filesize_t) -1;
00222 m_metaInfo = KFileMetaInfo();
00223 for ( int i = 0; i < NumFlags; i++ )
00224 m_time[i] = (time_t) -1;
00225
00226
00227
00228
00229
00230 m_entry = KIO::UDSEntry();
00231 init( false );
00232 }
00233
00234 void KFileItem::refreshMimeType()
00235 {
00236 m_pMimeType = 0L;
00237 init( false );
00238 }
00239
00240 void KFileItem::setURL( const KURL &url )
00241 {
00242 m_url = url;
00243 m_strName = url.fileName();
00244 m_strText = KIO::decodeFileName( m_strName );
00245 }
00246
00247 QString KFileItem::linkDest() const
00248 {
00249
00250 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00251 for( ; it != m_entry.end(); it++ )
00252 if ( (*it).m_uds == KIO::UDS_LINK_DEST )
00253 return (*it).m_str;
00254
00255 if ( m_bIsLocalURL )
00256 {
00257 char buf[1000];
00258 int n = readlink( QFile::encodeName(m_url.path( -1 )), buf, sizeof(buf)-1 );
00259 if ( n != -1 )
00260 {
00261 buf[ n ] = 0;
00262 return QFile::decodeName( buf );
00263 }
00264 }
00265 return QString::null;
00266 }
00267
00268 KIO::filesize_t KFileItem::size() const
00269 {
00270 if ( m_size != (KIO::filesize_t) -1 )
00271 return m_size;
00272
00273
00274 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00275 for( ; it != m_entry.end(); it++ )
00276 if ( (*it).m_uds == KIO::UDS_SIZE ) {
00277 m_size = (*it).m_long;
00278 return m_size;
00279 }
00280
00281 if ( m_bIsLocalURL )
00282 {
00283 KDE_struct_stat buf;
00284 if ( KDE_stat( QFile::encodeName(m_url.path( -1 )), &buf ) == 0 )
00285 return buf.st_size;
00286 }
00287 return 0L;
00288 }
00289
00290 time_t KFileItem::time( unsigned int which ) const
00291 {
00292 unsigned int mappedWhich = 0;
00293
00294 switch( which ) {
00295 case KIO::UDS_MODIFICATION_TIME:
00296 mappedWhich = Modification;
00297 break;
00298 case KIO::UDS_ACCESS_TIME:
00299 mappedWhich = Access;
00300 break;
00301 case KIO::UDS_CREATION_TIME:
00302 mappedWhich = Creation;
00303 break;
00304 }
00305
00306 if ( m_time[mappedWhich] != (time_t) -1 )
00307 return m_time[mappedWhich];
00308
00309
00310 KIO::UDSEntry::ConstIterator it = m_entry.begin();
00311 for( ; it != m_entry.end(); it++ )
00312 if ( (*it).m_uds == which ) {
00313 m_time[mappedWhich] = static_cast<time_t>((*it).m_long);
00314 return m_time[mappedWhich];
00315 }
00316
00317
00318 if ( m_bIsLocalURL )
00319 {
00320 KDE_struct_stat buf;
00321 if ( KDE_stat( QFile::encodeName(m_url.path(-1)), &buf ) == 0 )
00322 {
00323 m_time[mappedWhich] = (which == KIO::UDS_MODIFICATION_TIME) ?
00324 buf.st_mtime :
00325 (which == KIO::UDS_ACCESS_TIME) ? buf.st_atime :
00326 static_cast<time_t>(0);
00327 return m_time[mappedWhich];
00328 }
00329 }
00330 return static_cast<time_t>(0);
00331 }
00332
00333
00334 QString KFileItem::user() const
00335 {
00336 if ( m_user.isEmpty() && m_bIsLocalURL )
00337 {
00338 KDE_struct_stat buff;
00339 if ( KDE_lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0)
00340 {
00341 struct passwd *user = getpwuid( buff.st_uid );
00342 if ( user != 0L )
00343 m_user = QString::fromLocal8Bit(user->pw_name);
00344 }
00345 }
00346 return m_user;
00347 }
00348
00349 QString KFileItem::group() const
00350 {
00351 if (m_group.isEmpty() && m_bIsLocalURL )
00352 {
00353 KDE_struct_stat buff;
00354 if ( KDE_lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0)
00355 {
00356 struct group *ge = getgrgid( buff.st_gid );
00357 if ( ge != 0L ) {
00358 m_group = QString::fromLocal8Bit(ge->gr_name);
00359 if (m_group.isEmpty())
00360 m_group.sprintf("%d",ge->gr_gid);
00361 } else
00362 m_group.sprintf("%d",buff.st_gid);
00363 }
00364 }
00365 return m_group;
00366 }
00367
00368 QString KFileItem::mimetype() const
00369 {
00370 KFileItem * that = const_cast<KFileItem *>(this);
00371 return that->determineMimeType()->name();
00372 }
00373
00374 KMimeType::Ptr KFileItem::determineMimeType()
00375 {
00376 if ( !m_pMimeType || !m_bMimeTypeKnown )
00377 {
00378 m_pMimeType = KMimeType::findByURL( m_url, m_fileMode, m_bIsLocalURL );
00379
00380 m_bMimeTypeKnown = true;
00381 }
00382
00383 return m_pMimeType;
00384 }
00385
00386 bool KFileItem::isMimeTypeKnown() const
00387 {
00388
00389
00390
00391 return m_bMimeTypeKnown && m_guessedMimeType.isEmpty();
00392 }
00393
00394 QString KFileItem::mimeComment()
00395 {
00396 KMimeType::Ptr mType = determineMimeType();
00397 QString comment = mType->comment( m_url, m_bIsLocalURL );
00398 if (!comment.isEmpty())
00399 return comment;
00400 else
00401 return mType->name();
00402 }
00403
00404 QString KFileItem::iconName()
00405 {
00406 return determineMimeType()->icon(m_url, m_bIsLocalURL);
00407 }
00408
00409 int KFileItem::overlays() const
00410 {
00411 int _state = 0;
00412 if ( m_bLink )
00413 _state |= KIcon::LinkOverlay;
00414
00415 if ( !S_ISDIR( m_fileMode )
00416 && !isReadable())
00417 _state |= KIcon::LockOverlay;
00418
00419 if ( m_strName[0] == '.' )
00420 _state |= KIcon::HiddenOverlay;
00421
00422 if( S_ISDIR( m_fileMode ) && m_bIsLocalURL)
00423 {
00424 if (KFileShare::isDirectoryShared( m_url.path() ))
00425 {
00426 kdDebug()<<"KFileShare::isDirectoryShared : "<<m_url.path()<<endl;
00427 _state |= KIcon::ShareOverlay;
00428 }
00429 }
00430
00431 if ( m_pMimeType->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
00432 _state |= KIcon::ZipOverlay;
00433 return _state;
00434 }
00435
00436 QPixmap KFileItem::pixmap( int _size, int _state ) const
00437 {
00438 if ( !m_pMimeType )
00439 {
00440 static const QString & defaultFolderIcon =
00441 KGlobal::staticQString(KMimeType::mimeType( "inode/directory" )->KServiceType::icon());
00442 if ( S_ISDIR( m_fileMode ) )
00443 return DesktopIcon( defaultFolderIcon, _size, _state );
00444
00445 return DesktopIcon( "unknown", _size, _state );
00446 }
00447
00448 _state |= overlays();
00449
00450 KMimeType::Ptr mime;
00451
00452 if ( !m_bMimeTypeKnown && !m_guessedMimeType.isEmpty() )
00453 mime = KMimeType::mimeType( m_guessedMimeType );
00454 else
00455 mime = m_pMimeType;
00456
00457
00458
00459 if ( mime->name() == "application/x-gzip" && m_url.fileName().right(3) == ".gz" )
00460 {
00461 QString subFileName = m_url.path().left( m_url.path().length() - 3 );
00462
00463 mime = KMimeType::findByURL( subFileName, 0, m_bIsLocalURL );
00464 }
00465
00466 QPixmap p = mime->pixmap( m_url, KIcon::Desktop, _size, _state );
00467 if (p.isNull())
00468 kdWarning() << "Pixmap not found for mimetype " << m_pMimeType->name() << endl;
00469
00470 return p;
00471 }
00472
00473 bool KFileItem::isReadable() const
00474 {
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 if ( !(S_IRUSR & m_permissions) && !(S_IRGRP & m_permissions) && !(S_IROTH & m_permissions) )
00485 return false;
00486
00487
00488 else if ( m_bIsLocalURL && ::access( QFile::encodeName(m_url.path()), R_OK ) == -1 )
00489 return false;
00490
00491 return true;
00492 }
00493
00494 bool KFileItem::isDir() const
00495 {
00496 if ( !m_bMimeTypeKnown && !m_guessedMimeType.isEmpty() )
00497 {
00498 kdDebug() << " KFileItem::isDir can't say -> false " << endl;
00499 return false;
00500 }
00501 return S_ISDIR(m_fileMode);
00502 }
00503
00504 bool KFileItem::acceptsDrops()
00505 {
00506
00507 if ( S_ISDIR( mode() ) )
00508 {
00509 if ( m_bIsLocalURL )
00510 return (::access( QFile::encodeName(m_url.path()), X_OK ) == 0);
00511 else
00512 return true;
00513 }
00514
00515
00516 if ( !m_bIsLocalURL )
00517 return false;
00518
00519 if ( mimetype() == "application/x-desktop")
00520 return true;
00521
00522
00523 if ( ::access( QFile::encodeName(m_url.path()), X_OK ) == 0 )
00524 return true;
00525
00526 return false;
00527 }
00528
00529 QString KFileItem::getStatusBarInfo()
00530 {
00531 QString comment = determineMimeType()->comment( m_url, m_bIsLocalURL );
00532 QString text = m_strText;
00533
00534 QString myLinkDest = linkDest();
00535 KIO::filesize_t mySize = size();
00536
00537 if ( m_bLink )
00538 {
00539 QString tmp;
00540 if ( comment.isEmpty() )
00541 tmp = i18n ( "Symbolic Link" );
00542 else
00543 tmp = i18n("%1 (Link)").arg(comment);
00544 text += "->";
00545 text += myLinkDest;
00546 text += " ";
00547 text += tmp;
00548 }
00549 else if ( S_ISREG( m_fileMode ) )
00550 {
00551 text += QString(" (%1)").arg( KIO::convertSize( mySize ) );
00552 text += " ";
00553 text += comment;
00554 }
00555 else if ( S_ISDIR ( m_fileMode ) )
00556 {
00557 text += "/ ";
00558 text += comment;
00559 }
00560 else
00561 {
00562 text += " ";
00563 text += comment;
00564 }
00565 return text;
00566 }
00567
00568 QString KFileItem::getToolTipText(int maxcount)
00569 {
00570
00571 QString tip;
00572 KFileMetaInfo info = metaInfo();
00573
00574
00575
00576 const char* start = "<tr><td><nobr><font color=\"black\">";
00577 const char* mid = "</font></nobr></td><td><nobr><font color=\"black\">";
00578 const char* end = "</font></nobr></td></tr>";
00579
00580 tip = "<table cellspacing=0 cellpadding=0>";
00581
00582
00583
00584 tip += start + i18n("Type:") + mid;
00585
00586 QString type = QStyleSheet::escape(determineMimeType()->comment());
00587 if ( m_bLink )
00588 tip += i18n("Link to %1").arg(type) + end;
00589 else
00590 tip += type + end;
00591
00592 if ( !S_ISDIR ( m_fileMode ) )
00593 tip += start + i18n("Size:") + mid +
00594 KIO::convertSize( size() ) + end;
00595
00596 tip += start + i18n("Modified:") + mid +
00597 timeString( KIO::UDS_MODIFICATION_TIME) + end +
00598 start + i18n("Owner:") + mid + user() + " - " + group() + end +
00599 start + i18n("Permissions:") + mid +
00600 parsePermissions(m_permissions) + end;
00601
00602 if (info.isValid() && !info.isEmpty() )
00603 {
00604 QStringList keys = info.preferredKeys();
00605
00606
00607 QStringList::Iterator it = keys.begin();
00608 for (int count = 0; count<maxcount && it!=keys.end() ; ++it)
00609 {
00610 KFileMetaInfoItem item = info.item( *it );
00611 if ( item.isValid() )
00612 {
00613 QString s = item.string();
00614 if (s.length() > 50) s = s.left(47) + "...";
00615 if ( !s.isEmpty() )
00616 {
00617 count++;
00618 tip += start +
00619 QStyleSheet::escape( item.translatedKey() ) + ":" +
00620 mid +
00621 QStyleSheet::escape( s ) +
00622 end;
00623 }
00624
00625 }
00626 }
00627 tip += "</table>";
00628 }
00629
00630
00631
00632
00633 return tip;
00634 }
00635
00636 void KFileItem::run()
00637 {
00638 KURL url( m_url );
00639
00640
00641
00642 if ( m_bLink && m_bIsLocalURL )
00643 url = KURL( m_url, linkDest() );
00644 (void) new KRun( url, m_fileMode, m_bIsLocalURL );
00645 }
00646
00647 bool KFileItem::cmp( const KFileItem & item )
00648 {
00649 return ( m_strName == item.m_strName
00650 && m_bIsLocalURL == item.m_bIsLocalURL
00651 && m_fileMode == item.m_fileMode
00652 && m_permissions == item.m_permissions
00653 && m_user == item.m_user
00654 && m_group == item.m_group
00655 && m_bLink == item.m_bLink
00656 && size() == item.size()
00657 && time(KIO::UDS_MODIFICATION_TIME) == item.time(KIO::UDS_MODIFICATION_TIME) );
00658 }
00659
00660 void KFileItem::assign( const KFileItem & item )
00661 {
00662 m_entry = item.m_entry;
00663 m_url = item.m_url;
00664 m_bIsLocalURL = item.m_bIsLocalURL;
00665 m_strName = item.m_strName;
00666 m_strText = item.m_strText;
00667 m_fileMode = item.m_fileMode;
00668 m_permissions = item.m_permissions;
00669 m_user = item.m_user;
00670 m_group = item.m_group;
00671 m_bLink = item.m_bLink;
00672 m_pMimeType = item.m_pMimeType;
00673 m_strLowerCaseName = item.m_strLowerCaseName;
00674 m_bMimeTypeKnown = item.m_bMimeTypeKnown;
00675 m_guessedMimeType = item.m_guessedMimeType;
00676 m_access = item.m_access;
00677 m_metaInfo = item.m_metaInfo;
00678 for ( int i = 0; i < NumFlags; i++ )
00679 m_time[i] = item.m_time[i];
00680 m_size = item.m_size;
00681
00682
00683
00684
00685 determineMimeType();
00686 }
00687
00688 void KFileItem::setExtraData( const void *key, void *value )
00689 {
00690 if ( !key )
00691 return;
00692
00693 m_extra.replace( key, value );
00694 }
00695
00696 const void * KFileItem::extraData( const void *key ) const
00697 {
00698 QMapConstIterator<const void*,void*> it = m_extra.find( key );
00699 if ( it != m_extra.end() )
00700 return it.data();
00701 return 0L;
00702 }
00703
00704 void * KFileItem::extraData( const void *key )
00705 {
00706 QMapIterator<const void*,void*> it = m_extra.find( key );
00707 if ( it != m_extra.end() )
00708 return it.data();
00709 return 0L;
00710 }
00711
00712 void KFileItem::removeExtraData( const void *key )
00713 {
00714 m_extra.remove( key );
00715 }
00716
00717 QString KFileItem::permissionsString() const
00718 {
00719 if (m_access.isNull())
00720 m_access = parsePermissions( m_permissions );
00721
00722 return m_access;
00723 }
00724
00725 QString KFileItem::parsePermissions(mode_t perm) const
00726 {
00727 char p[] = "----------";
00728
00729 if (isDir())
00730 p[0]='d';
00731 else if (isLink())
00732 p[0]='l';
00733
00734 if (perm & QFileInfo::ReadUser)
00735 p[1]='r';
00736 if (perm & QFileInfo::WriteUser)
00737 p[2]='w';
00738 if (perm & QFileInfo::ExeUser)
00739 p[3]='x';
00740
00741 if (perm & QFileInfo::ReadGroup)
00742 p[4]='r';
00743 if (perm & QFileInfo::WriteGroup)
00744 p[5]='w';
00745 if (perm & QFileInfo::ExeGroup)
00746 p[6]='x';
00747
00748 if (perm & QFileInfo::ReadOther)
00749 p[7]='r';
00750 if (perm & QFileInfo::WriteOther)
00751 p[8]='w';
00752 if (perm & QFileInfo::ExeOther)
00753 p[9]='x';
00754
00755 return QString::fromLatin1(p);
00756 }
00757
00758
00759 QString KFileItem::timeString( unsigned int which ) const
00760 {
00761 QDateTime t;
00762 t.setTime_t( time(which) );
00763 return KGlobal::locale()->formatDateTime( t );
00764 }
00765
00766 void KFileItem::setMetaInfo( const KFileMetaInfo & info )
00767 {
00768 m_metaInfo = info;
00769 }
00770
00771 const KFileMetaInfo & KFileItem::metaInfo(bool autoget, int) const
00772 {
00773 if ( autoget && m_url.isLocalFile() && !m_metaInfo.isValid() )
00774 {
00775 m_metaInfo = KFileMetaInfo( m_url.path(), mimetype() );
00776 }
00777
00778 return m_metaInfo;
00779 }
00780
00781 void KFileItem::virtual_hook( int, void* )
00782 { }
00783