summaryrefslogtreecommitdiffstats
path: root/kioslave/trash/kio_trash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave/trash/kio_trash.cpp')
-rw-r--r--kioslave/trash/kio_trash.cpp596
1 files changed, 0 insertions, 596 deletions
diff --git a/kioslave/trash/kio_trash.cpp b/kioslave/trash/kio_trash.cpp
deleted file mode 100644
index f77cbf9ab..000000000
--- a/kioslave/trash/kio_trash.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-/* This file is part of the KDE project
- Copyright (C) 2004 David Faure <faure@kde.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "kio_trash.h"
-#include <kio/job.h>
-
-#include <kapplication.h>
-#include <kdebug.h>
-#include <klocale.h>
-#include <klargefile.h>
-#include <kcmdlineargs.h>
-#include <kmimetype.h>
-#include <kprocess.h>
-
-#include <dcopclient.h>
-#include <tqdatastream.h>
-#include <tqtextstream.h>
-#include <tqfile.h>
-#include <tqeventloop.h>
-
-#include <time.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-
-static const KCmdLineOptions options[] =
-{
- { "+protocol", I18N_NOOP( "Protocol name" ), 0 },
- { "+pool", I18N_NOOP( "Socket name" ), 0 },
- { "+app", I18N_NOOP( "Socket name" ), 0 },
- KCmdLineLastOption
-};
-
-extern "C" {
- int KDE_EXPORT kdemain( int argc, char **argv )
- {
- //TDEInstance instance( "kio_trash" );
- // TDEApplication is necessary to use kio_file
- putenv(strdup("SESSION_MANAGER="));
- TDEApplication::disableAutoDcopRegistration();
- TDECmdLineArgs::init(argc, argv, "kio_trash", 0, 0, 0, 0);
- TDECmdLineArgs::addCmdLineOptions( options );
- TDEApplication app( false, false );
-
- TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();
- TrashProtocol slave( args->arg(0), args->arg(1), args->arg(2) );
- slave.dispatchLoop();
- return 0;
- }
-}
-
-#define INIT_IMPL \
- if ( !impl.init() ) { \
- error( impl.lastErrorCode(), impl.lastErrorMessage() ); \
- return; \
- }
-
-TrashProtocol::TrashProtocol( const TQCString& protocol, const TQCString &pool, const TQCString &app)
- : SlaveBase(protocol, pool, app )
-{
- struct passwd *user = getpwuid( getuid() );
- if ( user )
- m_userName = TQString::fromLatin1(user->pw_name);
- struct group *grp = getgrgid( getgid() );
- if ( grp )
- m_groupName = TQString::fromLatin1(grp->gr_name);
-}
-
-TrashProtocol::~TrashProtocol()
-{
-}
-
-void TrashProtocol::restore( const KURL& trashURL )
-{
- int trashId;
- TQString fileId, relativePath;
- bool ok = TrashImpl::parseURL( trashURL, trashId, fileId, relativePath );
- if ( !ok ) {
- error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( trashURL.prettyURL() ) );
- return;
- }
- TrashedFileInfo info;
- ok = impl.infoForFile( trashId, fileId, info );
- if ( !ok ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- return;
- }
- KURL dest;
- dest.setPath( info.origPath );
- if ( !relativePath.isEmpty() )
- dest.addPath( relativePath );
-
- // Check that the destination directory exists, to improve the error code in case it doesn't.
- const TQString destDir = dest.directory();
- KDE_struct_stat buff;
- if ( KDE_lstat( TQFile::encodeName( destDir ), &buff ) == -1 ) {
- error( TDEIO::ERR_SLAVE_DEFINED,
- i18n( "The directory %1 does not exist anymore, so it is not possible to restore this item to its original location. "
- "You can either recreate that directory and use the restore operation again, or drag the item anywhere else to restore it." ).arg( destDir ) );
- return;
- }
-
- copyOrMove( trashURL, dest, false /*overwrite*/, Move );
-}
-
-void TrashProtocol::rename( const KURL &oldURL, const KURL &newURL, bool overwrite )
-{
- INIT_IMPL;
-
- kdDebug()<<"TrashProtocol::rename(): old="<<oldURL<<" new="<<newURL<<" overwrite=" << overwrite<<endl;
-
- if ( oldURL.protocol() == "trash" && newURL.protocol() == "trash" ) {
- error( TDEIO::ERR_CANNOT_RENAME, oldURL.prettyURL() );
- return;
- }
-
- copyOrMove( oldURL, newURL, overwrite, Move );
-}
-
-void TrashProtocol::copy( const KURL &src, const KURL &dest, int /*permissions*/, bool overwrite )
-{
- INIT_IMPL;
-
- kdDebug()<<"TrashProtocol::copy(): " << src << " " << dest << endl;
-
- if ( src.protocol() == "trash" && dest.protocol() == "trash" ) {
- error( TDEIO::ERR_UNSUPPORTED_ACTION, i18n( "This file is already in the trash bin." ) );
- return;
- }
-
- copyOrMove( src, dest, overwrite, Copy );
-}
-
-void TrashProtocol::copyOrMove( const KURL &src, const KURL &dest, bool overwrite, CopyOrMove action )
-{
- if ( src.protocol() == "trash" && dest.isLocalFile() ) {
- // Extracting (e.g. via dnd). Ignore original location stored in info file.
- int trashId;
- TQString fileId, relativePath;
- bool ok = TrashImpl::parseURL( src, trashId, fileId, relativePath );
- if ( !ok ) {
- error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( src.prettyURL() ) );
- return;
- }
- const TQString destPath = dest.path();
- if ( TQFile::exists( destPath ) ) {
- if ( overwrite ) {
- ok = TQFile::remove( destPath );
- Q_ASSERT( ok ); // ### TODO
- } else {
- error( TDEIO::ERR_FILE_ALREADY_EXIST, destPath );
- return;
- }
- }
-
- if ( action == Move ) {
- kdDebug() << "calling moveFromTrash(" << destPath << " " << trashId << " " << fileId << ")" << endl;
- ok = impl.moveFromTrash( destPath, trashId, fileId, relativePath );
- } else { // Copy
- kdDebug() << "calling copyFromTrash(" << destPath << " " << trashId << " " << fileId << ")" << endl;
- ok = impl.copyFromTrash( destPath, trashId, fileId, relativePath );
- }
- if ( !ok ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- } else {
- if ( action == Move && relativePath.isEmpty() )
- (void)impl.deleteInfo( trashId, fileId );
- finished();
- }
- return;
- } else if ( src.isLocalFile() && dest.protocol() == "trash" ) {
- TQString dir = dest.directory();
- //kdDebug() << "trashing a file to " << dir << endl;
- // Trashing a file
- // We detect the case where this isn't normal trashing, but
- // e.g. if kwrite tries to save (moving tempfile over destination)
- if ( dir.length() <= 1 && src.fileName() == dest.fileName() ) // new toplevel entry
- {
- const TQString srcPath = src.path();
- // In theory we should use TrashImpl::parseURL to give the right filename to createInfo,
- // in case the trash URL didn't contain the same filename as srcPath.
- // But this can only happen with copyAs/moveAs, not available in the GUI
- // for the trash (New/... or Rename from iconview/listview).
- int trashId;
- TQString fileId;
- if ( !impl.createInfo( srcPath, trashId, fileId ) ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- } else {
- bool ok;
- if ( action == Move ) {
- kdDebug() << "calling moveToTrash(" << srcPath << " " << trashId << " " << fileId << ")" << endl;
- ok = impl.moveToTrash( srcPath, trashId, fileId );
- } else { // Copy
- kdDebug() << "calling copyToTrash(" << srcPath << " " << trashId << " " << fileId << ")" << endl;
- ok = impl.copyToTrash( srcPath, trashId, fileId );
- }
- if ( !ok ) {
- (void)impl.deleteInfo( trashId, fileId );
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- } else {
- // Inform caller of the final URL. Used by konq_undo.
- const KURL url = impl.makeURL( trashId, fileId, TQString::null );
- setMetaData( "trashURL-" + srcPath, url.url() );
- finished();
- }
- }
- return;
- } else {
- kdDebug() << "returning TDEIO::ERR_ACCESS_DENIED, it's not allowed to add a file to an existing trash directory" << endl;
- // It's not allowed to add a file to an existing trash directory.
- error( TDEIO::ERR_ACCESS_DENIED, dest.prettyURL() );
- return;
- }
- } else
- error( TDEIO::ERR_UNSUPPORTED_ACTION, "should never happen" );
-}
-
-static void addAtom(TDEIO::UDSEntry& entry, unsigned int ID, long long l, const TQString& s = TQString::null)
-{
- TDEIO::UDSAtom atom;
- atom.m_uds = ID;
- atom.m_long = l;
- atom.m_str = s;
- entry.append(atom);
-}
-
-void TrashProtocol::createTopLevelDirEntry(TDEIO::UDSEntry& entry)
-{
- entry.clear();
- addAtom(entry, TDEIO::UDS_NAME, 0, ".");
- addAtom(entry, TDEIO::UDS_FILE_TYPE, S_IFDIR);
- addAtom(entry, TDEIO::UDS_ACCESS, 0700);
- addAtom(entry, TDEIO::UDS_MIME_TYPE, 0, "inode/directory");
- addAtom(entry, TDEIO::UDS_USER, 0, m_userName);
- addAtom(entry, TDEIO::UDS_GROUP, 0, m_groupName);
-}
-
-void TrashProtocol::stat(const KURL& url)
-{
- INIT_IMPL;
- const TQString path = url.path();
- if( path.isEmpty() || path == "/" ) {
- // The root is "virtual" - it's not a single physical directory
- TDEIO::UDSEntry entry;
- createTopLevelDirEntry( entry );
- statEntry( entry );
- finished();
- } else {
- int trashId;
- TQString fileId, relativePath;
-
- bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath );
-
- if ( !ok ) {
- // ######## do we still need this?
- kdDebug() << k_funcinfo << url << " looks fishy, returning does-not-exist" << endl;
- // A URL like trash:/file simply means that CopyJob is trying to see if
- // the destination exists already (it made up the URL by itself).
- error( TDEIO::ERR_DOES_NOT_EXIST, url.prettyURL() );
- //error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( url.prettyURL() ) );
- return;
- }
-
- const TQString filePath = impl.physicalPath( trashId, fileId, relativePath );
- if ( filePath.isEmpty() ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- return;
- }
-
- TQString fileName = filePath.section('/', -1, -1, TQString::SectionSkipEmpty);
-
- TQString fileURL = TQString::null;
- if ( url.path().length() > 1 ) {
- fileURL = url.url();
- }
-
- TDEIO::UDSEntry entry;
- TrashedFileInfo info;
- ok = impl.infoForFile( trashId, fileId, info );
- if ( ok )
- ok = createUDSEntry( filePath, fileName, fileURL, entry, info );
-
- if ( !ok ) {
- error( TDEIO::ERR_COULD_NOT_STAT, url.prettyURL() );
- }
-
- statEntry( entry );
- finished();
- }
-}
-
-void TrashProtocol::del( const KURL &url, bool /*isfile*/ )
-{
- int trashId;
- TQString fileId, relativePath;
-
- bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath );
- if ( !ok ) {
- error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( url.prettyURL() ) );
- return;
- }
-
- ok = relativePath.isEmpty();
- if ( !ok ) {
- error( TDEIO::ERR_ACCESS_DENIED, url.prettyURL() );
- return;
- }
-
- ok = impl.del(trashId, fileId);
- if ( !ok ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- return;
- }
-
- finished();
-}
-
-void TrashProtocol::listDir(const KURL& url)
-{
- INIT_IMPL;
- kdDebug() << "listdir: " << url << endl;
- if ( url.path().length() <= 1 ) {
- listRoot();
- return;
- }
- int trashId;
- TQString fileId;
- TQString relativePath;
- bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath );
- if ( !ok ) {
- error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( url.prettyURL() ) );
- return;
- }
- //was: const TQString physicalPath = impl.physicalPath( trashId, fileId, relativePath );
-
- // Get info for deleted directory - the date of deletion and orig path will be used
- // for all the items in it, and we need the physicalPath.
- TrashedFileInfo info;
- ok = impl.infoForFile( trashId, fileId, info );
- if ( !ok || info.physicalPath.isEmpty() ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- return;
- }
- if ( !relativePath.isEmpty() ) {
- info.physicalPath += "/";
- info.physicalPath += relativePath;
- }
-
- // List subdir. Can't use kio_file here since we provide our own info...
- kdDebug() << k_funcinfo << "listing " << info.physicalPath << endl;
- TQStrList entryNames = impl.listDir( info.physicalPath );
- totalSize( entryNames.count() );
- TDEIO::UDSEntry entry;
- TQStrListIterator entryIt( entryNames );
- for (; entryIt.current(); ++entryIt) {
- TQString fileName = TQFile::decodeName( entryIt.current() );
- if ( fileName == ".." )
- continue;
- const TQString filePath = info.physicalPath + "/" + fileName;
- // shouldn't be necessary
- //const TQString url = TrashImpl::makeURL( trashId, fileId, relativePath + "/" + fileName );
- entry.clear();
- TrashedFileInfo infoForItem( info );
- infoForItem.origPath += '/';
- infoForItem.origPath += fileName;
- if ( ok && createUDSEntry( filePath, fileName, TQString::null /*url*/, entry, infoForItem ) ) {
- listEntry( entry, false );
- }
- }
- entry.clear();
- listEntry( entry, true );
- finished();
-}
-
-bool TrashProtocol::createUDSEntry( const TQString& physicalPath, const TQString& fileName, const TQString& url, TDEIO::UDSEntry& entry, const TrashedFileInfo& info )
-{
- TQCString physicalPath_c = TQFile::encodeName( physicalPath );
- KDE_struct_stat buff;
- if ( KDE_lstat( physicalPath_c, &buff ) == -1 ) {
- kdWarning() << "couldn't stat " << physicalPath << endl;
- return false;
- }
- if (S_ISLNK(buff.st_mode)) {
- char buffer2[ 1000 ];
- int n = readlink( physicalPath_c, buffer2, 1000 );
- if ( n != -1 ) {
- buffer2[ n ] = 0;
- }
-
- addAtom( entry, TDEIO::UDS_LINK_DEST, 0, TQFile::decodeName( buffer2 ) );
- // Follow symlink
- // That makes sense in kio_file, but not in the trash, especially for the size
- // #136876
-#if 0
- if ( KDE_stat( physicalPath_c, &buff ) == -1 ) {
- // It is a link pointing to nowhere
- buff.st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
- buff.st_mtime = 0;
- buff.st_atime = 0;
- buff.st_size = 0;
- }
-#endif
- }
- mode_t type = buff.st_mode & S_IFMT; // extract file type
- mode_t access = buff.st_mode & 07777; // extract permissions
- access &= 07555; // make it readonly, since it's in the trashcan
- addAtom( entry, TDEIO::UDS_NAME, 0, fileName );
- addAtom( entry, TDEIO::UDS_FILE_TYPE, type );
- if ( !url.isEmpty() )
- addAtom( entry, TDEIO::UDS_URL, 0, url );
-
- KMimeType::Ptr mt = KMimeType::findByPath( physicalPath, buff.st_mode );
- addAtom( entry, TDEIO::UDS_MIME_TYPE, 0, mt->name() );
- addAtom( entry, TDEIO::UDS_ACCESS, access );
- addAtom( entry, TDEIO::UDS_SIZE, buff.st_size );
- addAtom( entry, TDEIO::UDS_USER, 0, m_userName ); // assumption
- addAtom( entry, TDEIO::UDS_GROUP, 0, m_groupName ); // assumption
- addAtom( entry, TDEIO::UDS_MODIFICATION_TIME, buff.st_mtime );
- addAtom( entry, TDEIO::UDS_ACCESS_TIME, buff.st_atime ); // ## or use it for deletion time?
- addAtom( entry, TDEIO::UDS_EXTRA, 0, info.origPath );
- addAtom( entry, TDEIO::UDS_EXTRA, 0, info.deletionDate.toString( Qt::ISODate ) );
- return true;
-}
-
-void TrashProtocol::listRoot()
-{
- INIT_IMPL;
- const TrashedFileInfoList lst = impl.list();
- totalSize( lst.count() );
- TDEIO::UDSEntry entry;
- createTopLevelDirEntry( entry );
- listEntry( entry, false );
- for ( TrashedFileInfoList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
- const KURL url = TrashImpl::makeURL( (*it).trashId, (*it).fileId, TQString::null );
- KURL origURL;
- origURL.setPath( (*it).origPath );
- entry.clear();
- if ( createUDSEntry( (*it).physicalPath, origURL.fileName(), url.url(), entry, *it ) )
- listEntry( entry, false );
- }
- entry.clear();
- listEntry( entry, true );
- finished();
-}
-
-void TrashProtocol::special( const TQByteArray & data )
-{
- INIT_IMPL;
- TQDataStream stream( data, IO_ReadOnly );
- int cmd;
- stream >> cmd;
-
- switch (cmd) {
- case 1:
- if ( impl.emptyTrash() )
- finished();
- else
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- break;
- case 2:
- impl.migrateOldTrash();
- finished();
- break;
- case 3:
- {
- KURL url;
- stream >> url;
- restore( url );
- break;
- }
- default:
- kdWarning(7116) << "Unknown command in special(): " << cmd << endl;
- error( TDEIO::ERR_UNSUPPORTED_ACTION, TQString::number(cmd) );
- break;
- }
-}
-
-void TrashProtocol::put( const KURL& url, int /*permissions*/, bool /*overwrite*/, bool /*resume*/ )
-{
- INIT_IMPL;
- kdDebug() << "put: " << url << endl;
- // create deleted file. We need to get the mtime and original location from metadata...
- // Maybe we can find the info file for url.fileName(), in case ::rename() was called first, and failed...
- error( TDEIO::ERR_ACCESS_DENIED, url.prettyURL() );
-}
-
-void TrashProtocol::get( const KURL& url )
-{
- INIT_IMPL;
- kdDebug() << "get() : " << url << endl;
- if ( !url.isValid() ) {
- kdDebug() << kdBacktrace() << endl;
- error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( url.url() ) );
- return;
- }
- if ( url.path().length() <= 1 ) {
- error( TDEIO::ERR_IS_DIRECTORY, url.prettyURL() );
- return;
- }
- int trashId;
- TQString fileId;
- TQString relativePath;
- bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath );
- if ( !ok ) {
- error( TDEIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1" ).arg( url.prettyURL() ) );
- return;
- }
- const TQString physicalPath = impl.physicalPath( trashId, fileId, relativePath );
- if ( physicalPath.isEmpty() ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- return;
- }
-
- // Usually we run jobs in TrashImpl (for e.g. future kdedmodule)
- // But for this one we wouldn't use DCOP for every bit of data...
- KURL fileURL;
- fileURL.setPath( physicalPath );
- TDEIO::Job* job = TDEIO::get( fileURL );
- connect( job, TQT_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
- this, TQT_SLOT( slotData( TDEIO::Job*, const TQByteArray& ) ) );
- connect( job, TQT_SIGNAL( mimetype( TDEIO::Job*, const TQString& ) ),
- this, TQT_SLOT( slotMimetype( TDEIO::Job*, const TQString& ) ) );
- connect( job, TQT_SIGNAL( result(TDEIO::Job *) ),
- this, TQT_SLOT( jobFinished(TDEIO::Job *) ) );
- tqApp->eventLoop()->enterLoop();
-}
-
-void TrashProtocol::slotData( TDEIO::Job*, const TQByteArray&arr )
-{
- data( arr );
-}
-
-void TrashProtocol::slotMimetype( TDEIO::Job*, const TQString& mt )
-{
- mimeType( mt );
-}
-
-void TrashProtocol::jobFinished( TDEIO::Job* job )
-{
- if ( job->error() )
- error( job->error(), job->errorText() );
- else
- finished();
- tqApp->eventLoop()->exitLoop();
-}
-
-#if 0
-void TrashProtocol::mkdir( const KURL& url, int /*permissions*/ )
-{
- INIT_IMPL;
- // create info about deleted dir
- // ############ Problem: we don't know the original path.
- // Let's try to avoid this case (we should get to copy() instead, for local files)
- kdDebug() << "mkdir: " << url << endl;
- TQString dir = url.directory();
-
- if ( dir.length() <= 1 ) // new toplevel entry
- {
- // ## we should use TrashImpl::parseURL to give the right filename to createInfo
- int trashId;
- TQString fileId;
- if ( !impl.createInfo( url.path(), trashId, fileId ) ) {
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- } else {
- if ( !impl.mkdir( trashId, fileId, permissions ) ) {
- (void)impl.deleteInfo( trashId, fileId );
- error( impl.lastErrorCode(), impl.lastErrorMessage() );
- } else
- finished();
- }
- } else {
- // Well it's not allowed to add a directory to an existing deleted directory.
- error( TDEIO::ERR_ACCESS_DENIED, url.prettyURL() );
- }
-}
-#endif
-
-#include "kio_trash.moc"