diff options
Diffstat (limited to 'kioslave/sftp/sftpfileattr.cpp')
-rw-r--r-- | kioslave/sftp/sftpfileattr.cpp | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/kioslave/sftp/sftpfileattr.cpp b/kioslave/sftp/sftpfileattr.cpp new file mode 100644 index 000000000..07aada36d --- /dev/null +++ b/kioslave/sftp/sftpfileattr.cpp @@ -0,0 +1,346 @@ +/*************************************************************************** + sftpfileattr.cpp - description + ------------------- + begin : Sat Jun 30 2001 + copyright : (C) 2001 by Lucas Fisher + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "sftpfileattr.h" + +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <qstring.h> +#include <qdatastream.h> + +#include <kio/global.h> +#include <kremoteencoding.h> + +using namespace KIO; + +sftpFileAttr::sftpFileAttr(){ + clear(); + mDirAttrs = false; +} + +sftpFileAttr::sftpFileAttr(KRemoteEncoding* encoding){ + clear(); + mDirAttrs = false; + mEncoding = encoding; +} + + +/** Constructor to initialize the file attributes on declaration. */ +sftpFileAttr::sftpFileAttr(Q_ULLONG size, uid_t uid, gid_t gid, + mode_t permissions, time_t atime, + time_t mtime, Q_UINT32 extendedCount) { + clear(); + mDirAttrs = false; + mSize = size; + mUid = uid; + mGid = gid; + mAtime = atime; + mMtime = mtime; + mPermissions = permissions; + mExtendedCount = extendedCount; +} + +sftpFileAttr::~sftpFileAttr(){ +} + +/** Returns a UDSEntry describing the file. +The UDSEntry is generated from the sftp file attributes. */ +UDSEntry sftpFileAttr::entry() { + UDSEntry entry; + UDSAtom atom; + + atom.m_uds = UDS_NAME; + atom.m_str = mFilename; + entry.append(atom); + + if( mFlags & SSH2_FILEXFER_ATTR_SIZE ) { + atom.m_uds = UDS_SIZE; + atom.m_long = mSize; + entry.append(atom); + } + + if( mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) { + atom.m_uds = UDS_ACCESS_TIME; + atom.m_long = mAtime; + entry.append(atom); + + atom.m_uds = UDS_MODIFICATION_TIME; + atom.m_long = mMtime; + entry.append(atom); + } + + if( mFlags & SSH2_FILEXFER_ATTR_UIDGID ) { + if( mUserName.isEmpty() || mGroupName.isEmpty() ) + getUserGroupNames(); + + atom.m_uds = UDS_USER; + atom.m_str = mUserName; + entry.append(atom); + + atom.m_uds = UDS_GROUP; + atom.m_str = mGroupName; + entry.append(atom); + } + + if( mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) { + atom.m_uds = UDS_ACCESS; + atom.m_long = mPermissions; + entry.append(atom); + + mode_t type = fileType(); + + // Set the type if we know what it is + if( type != 0 ) { + atom.m_uds = UDS_FILE_TYPE; + atom.m_long = (mLinkType ? mLinkType:type); + entry.append(atom); + } + + if( S_ISLNK(type) ) { + atom.m_uds = UDS_LINK_DEST; + atom.m_str = mLinkDestination; + entry.append(atom); + } + } + + return entry; +} + +/** Use to output the file attributes to a sftp packet */ +QDataStream& operator<< (QDataStream& s, const sftpFileAttr& fa) { + s << (Q_UINT32)fa.mFlags; + + if( fa.mFlags & SSH2_FILEXFER_ATTR_SIZE ) + { s << (Q_ULLONG)fa.mSize; } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_UIDGID ) + { s << (Q_UINT32)fa.mUid << (Q_UINT32)fa.mGid; } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) + { s << (Q_UINT32)fa.mPermissions; } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) + { s << (Q_UINT32)fa.mAtime << (Q_UINT32)fa.mMtime; } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) { + s << (Q_UINT32)fa.mExtendedCount; + // XXX: Write extensions to data stream here + // s.writeBytes(extendedtype).writeBytes(extendeddata); + } + return s; +} + + +/** Use to read a file attribute from a sftp packet */ +QDataStream& operator>> (QDataStream& s, sftpFileAttr& fa) { + + // XXX Add some error checking in here in case + // we get a bad sftp packet. + + fa.clear(); + + if( fa.mDirAttrs ) { + QCString fn; + s >> fn; + fn.truncate( fn.size() ); + + fa.mFilename = fa.mEncoding->decode( fn ); + + s >> fa.mLongname; + fa.mLongname.truncate( fa.mLongname.size() ); + //kdDebug() << ">>: ftpfileattr long filename (" << fa.mLongname.size() << ")= " << fa.mLongname << endl; + } + + s >> fa.mFlags; // get flags + + if( fa.mFlags & SSH2_FILEXFER_ATTR_SIZE ) { + Q_ULLONG fileSize; + s >> fileSize; + fa.setFileSize(fileSize); + } + + Q_UINT32 x; + + if( fa.mFlags & SSH2_FILEXFER_ATTR_UIDGID ) { + s >> x; fa.setUid(x); + s >> x; fa.setGid(x); + } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) { + s >> x; fa.setPermissions(x); + } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) { + s >> x; fa.setAtime(x); + s >> x; fa.setMtime(x); + } + + if( fa.mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) { + s >> x; fa.setExtendedCount(x); + // XXX: Read in extensions from data stream here + // s.readBytes(extendedtype).readBytes(extendeddata); + } + + fa.getUserGroupNames(); + return s; +} +/** Parse longname for the owner and group names. */ +void sftpFileAttr::getUserGroupNames(){ + // Get the name of the owner and group of the file from longname. + QString user, group; + if( mLongname.isEmpty() ) { + // do not have the user name so use the user id instead + user.setNum(mUid); + group.setNum(mGid); + } + else { + int field = 0; + int i = 0; + int l = mLongname.length(); + + QString longName = mEncoding->decode( mLongname ); + + kdDebug(7120) << "Decoded: " << longName << endl; + + // Find the beginning of the third field which contains the user name. + while( field != 2 ) { + if( longName[i].isSpace() ) { + field++; i++; + while( i < l && longName[i].isSpace() ) { i++; } + } + else { i++; } + } + // i is the index of the first character of the third field. + while( i < l && !longName[i].isSpace() ) { + user.append(longName[i]); + i++; + } + + // i is the first character of the space between fields 3 and 4 + // user contains the owner's user name + while( i < l && longName[i].isSpace() ) { + i++; + } + + // i is the first character of the fourth field + while( i < l && !longName[i].isSpace() ) { + group.append(longName[i]); + i++; + } + // group contains the name of the group. + } + + mUserName = user; + mGroupName = group; +} + +/** No descriptions */ +kdbgstream& operator<< (kdbgstream& s, sftpFileAttr& a) { + s << "Filename: " << a.mFilename + << ", Uid: " << a.mUid + << ", Gid: " << a.mGid + << ", Username: " << a.mUserName + << ", GroupName: " << a.mGroupName + << ", Permissions: " << a.mPermissions + << ", size: " << a.mSize + << ", atime: " << a.mAtime + << ", mtime: " << a.mMtime + << ", extended cnt: " << a.mExtendedCount; + + if (S_ISLNK(a.mLinkType)) { + s << ", Link Type: " << a.mLinkType; + s << ", Link Destination: " << a.mLinkDestination; + } + + return s; +} + +/** Make sure it builds with NDEBUG */ +kndbgstream& operator<< (kndbgstream& s, sftpFileAttr& ) { + return s; +} + +/** Clear all attributes and flags. */ +void sftpFileAttr::clear(){ + clearAtime(); + clearMtime(); + clearGid(); + clearUid(); + clearFileSize(); + clearPermissions(); + clearExtensions(); + mFilename = QString::null; + mGroupName = QString::null; + mUserName = QString::null; + mLinkDestination = QString::null; + mFlags = 0; + mLongname = "\0"; + mLinkType = 0; +} + +/** Return the size of the sftp attribute. */ +Q_UINT32 sftpFileAttr::size() const{ + Q_UINT32 size = 4; // for the attr flag + if( mFlags & SSH2_FILEXFER_ATTR_SIZE ) + size += 8; + + if( mFlags & SSH2_FILEXFER_ATTR_UIDGID ) + size += 8; + + if( mFlags & SSH2_FILEXFER_ATTR_PERMISSIONS ) + size += 4; + + if( mFlags & SSH2_FILEXFER_ATTR_ACMODTIME ) + size += 8; + + if( mFlags & SSH2_FILEXFER_ATTR_EXTENDED ) { + size += 4; + // add size of extensions + } + return size; +} + +/** Returns the file type as determined from the file permissions */ +mode_t sftpFileAttr::fileType() const{ + mode_t type = 0; + + if( S_ISLNK(mPermissions) ) + type |= S_IFLNK; + + if( S_ISREG(mPermissions) ) + type |= S_IFREG; + else if( S_ISDIR(mPermissions) ) + type |= S_IFDIR; + else if( S_ISCHR(mPermissions) ) + type |= S_IFCHR; + else if( S_ISBLK(mPermissions) ) + type |= S_IFBLK; + else if( S_ISFIFO(mPermissions) ) + type |= S_IFIFO; + else if( S_ISSOCK(mPermissions) ) + type |= S_IFSOCK; + + return type; +} + +void sftpFileAttr::setEncoding( KRemoteEncoding* encoding ) +{ + mEncoding = encoding; +} +// vim:ts=4:sw=4 |