diff options
Diffstat (limited to 'kioslave/trash')
-rw-r--r-- | kioslave/trash/CMakeLists.txt | 59 | ||||
-rw-r--r-- | kioslave/trash/DESIGN | 53 | ||||
-rw-r--r-- | kioslave/trash/Makefile.am | 31 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/CMakeLists.txt | 38 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/Makefile.am | 14 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/RETURNED_ITEMS | 4 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/kfile_trash.cpp | 93 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/kfile_trash.desktop | 79 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/kfile_trash.h | 42 | ||||
-rw-r--r-- | kioslave/trash/kfile-plugin/kfile_trash_system.desktop | 79 | ||||
-rw-r--r-- | kioslave/trash/kio_trash.cpp | 596 | ||||
-rw-r--r-- | kioslave/trash/kio_trash.h | 71 | ||||
-rw-r--r-- | kioslave/trash/ktrash.cpp | 102 | ||||
-rw-r--r-- | kioslave/trash/testtrash.cpp | 1198 | ||||
-rw-r--r-- | kioslave/trash/testtrash.h | 118 | ||||
-rw-r--r-- | kioslave/trash/trash.protocol | 89 | ||||
-rw-r--r-- | kioslave/trash/trashimpl.cpp | 962 | ||||
-rw-r--r-- | kioslave/trash/trashimpl.h | 182 |
18 files changed, 0 insertions, 3810 deletions
diff --git a/kioslave/trash/CMakeLists.txt b/kioslave/trash/CMakeLists.txt deleted file mode 100644 index 5dfd62cb2..000000000 --- a/kioslave/trash/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -################################################# -# -# (C) 2010-2011 Serghei Amelian -# serghei (DOT) amelian (AT) gmail.com -# -# Improvements and feedback are welcome -# -# This file is released under GPL >= 2 -# -################################################# - -add_subdirectory( kfile-plugin ) - - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ${TDE_INCLUDE_DIR} - ${TQT_INCLUDE_DIRS} -) - -link_directories( - ${TQT_LIBRARY_DIRS} -) - - -##### other data ################################ - -install( FILES trash.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) - - -##### trashcommon (static) ###################### - -set( target trashcommon ) - -tde_add_library( ${target} STATIC_PIC AUTOMOC - SOURCES trashimpl.cpp -) - - -##### kio_trash (module) ######################## - -set( target kio_trash ) - -tde_add_kpart( ${target} AUTOMOC - SOURCES kio_trash.cpp - LINK trashcommon-static kio-shared - DESTINATION ${PLUGIN_INSTALL_DIR} -) - - -##### ktrash (executable) ####################### - -set( target ktrash ) - -tde_add_executable( ${target} - SOURCES ktrash.cpp - LINK kio-shared - DESTINATION ${BIN_INSTALL_DIR} -) diff --git a/kioslave/trash/DESIGN b/kioslave/trash/DESIGN deleted file mode 100644 index 63179da08..000000000 --- a/kioslave/trash/DESIGN +++ /dev/null @@ -1,53 +0,0 @@ -DESIGN -====== -kio_trash implements the XDG trash standard currently at http://www.ramendik.ru/docs/trashspec.html - -In case race conditions between the various instances of kio_trash -are a problem, trashimpl could be moved to a kded module, and -kio_trash would use DCOP to talk to it. It's a bit hard to come up -with use cases where the race conditions would matter though. - -BUGS -==== -* Undo of "restore" isn't available. Need to get origPath by metadata I guess. - -TODO -==== -* Clean up konq_popupmenu.cc for Type=Link URL=trash:/ :( -* Also, provide metainfo for trash contents for that desktop link. -=> maybe we need a new mimetype? - Like application/x-trash-desktop, inheriting application/x-desktop. - And a "trash.trashdesktop" filename or so (ouch, migration issues...) - -* Detect removeable media to avoid .Trash-foo on it. How? - -* Trashcan properties (properties for trash:/? hmm. Easier with separate dialog) - - Maximum size for trash can (#18109 suggests a %, but a MB size is easier). - This means to delete the oldest files from the trash automatically. #79553 - -* Err, should we support renaming? :) Difficult to disable... - In fact it's already not disabled in readonly directories (e.g. "/") -> todo - (for F2 and kpropertiesdialog) - -* Deleting oldest files when size is bigger than a certain configurable amount (#79553) - -Bugs closed by kio_trash -======================== -#79826 (3.3 only) -#62848 (configurable trash location) -#78116 (.directory) -#18109 (general one) -#17744 (restore) -#76380 #56821 (trashing on same partition) - -Choice of URL scheme -==================== -We use trash:/trashid-fileid[/relativepath] -This gave problems with CopyJob::startRenameJob which exposed trashid-fileid -to the user as a filename when dropping a file out of the trash. -But this was fixed with the fileNameUsedForCopying=Name setting. - -A previous experiment was trash:/filename[/relativepath]?t=trashid&id=fileid -but this gives problems with going Up (it first removes the query), -with KDirLister (it wouldn't know when to remove the query, to find the URL -of the parent directory). diff --git a/kioslave/trash/Makefile.am b/kioslave/trash/Makefile.am deleted file mode 100644 index 94b7ab519..000000000 --- a/kioslave/trash/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -INCLUDES = $(all_includes) -METASOURCES = AUTO - -SUBDIRS = . kfile-plugin - -kde_module_LTLIBRARIES = kio_trash.la - -kio_trash_la_SOURCES = kio_trash.cpp -kio_trash_la_LIBADD = libtrashcommon.la $(LIB_KIO) -kio_trash_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -no-undefined - -bin_PROGRAMS = ktrash -ktrash_SOURCES = ktrash.cpp -ktrash_LDADD = $(LIB_KIO) -ktrash_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -ltdetexteditor - -kde_services_DATA = trash.protocol - -noinst_LTLIBRARIES = libtrashcommon.la -libtrashcommon_la_SOURCES = trashimpl.cpp - -check_PROGRAMS = testtrash -testtrash_SOURCES = testtrash.cpp -testtrash_LDADD = libtrashcommon.la $(LIB_KIO) -testtrash_LDFLAGS = $(all_libraries) - -TESTS = testtrash - -messages: - $(XGETTEXT) `find . -name "*.cc" -o -name "*.cpp" -o -name "*.h"` -o $(podir)/kio_trash.pot - diff --git a/kioslave/trash/kfile-plugin/CMakeLists.txt b/kioslave/trash/kfile-plugin/CMakeLists.txt deleted file mode 100644 index 920144faa..000000000 --- a/kioslave/trash/kfile-plugin/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -################################################# -# -# (C) 2010-2011 Serghei Amelian -# serghei (DOT) amelian (AT) gmail.com -# -# Improvements and feedback are welcome -# -# This file is released under GPL >= 2 -# -################################################# - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ${TDE_INCLUDE_DIR} - ${TQT_INCLUDE_DIRS} -) - -link_directories( - ${TQT_LIBRARY_DIRS} -) - - -##### other data ################################ - -install( FILES - kfile_trash.desktop kfile_trash_system.desktop - DESTINATION ${SERVICES_INSTALL_DIR} ) - - -##### kfile_trash (module) ###################### - -set( target kfile_trash ) - -tde_add_kpart( ${target} AUTOMOC - SOURCES kfile_trash.cpp - LINK trashcommon-static kio-shared - DESTINATION ${PLUGIN_INSTALL_DIR} -) diff --git a/kioslave/trash/kfile-plugin/Makefile.am b/kioslave/trash/kfile-plugin/Makefile.am deleted file mode 100644 index 0668553a8..000000000 --- a/kioslave/trash/kfile-plugin/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -## Makefile.am for trash file meta info plugin - -AM_CPPFLAGS = $(all_includes) - -kde_module_LTLIBRARIES = kfile_trash.la - -kfile_trash_la_SOURCES = kfile_trash.cpp -kfile_trash_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) -kfile_trash_la_LIBADD = ../libtrashcommon.la $(LIB_KIO) - -METASOURCES = AUTO - -services_DATA = kfile_trash.desktop kfile_trash_system.desktop -servicesdir = $(kde_servicesdir) diff --git a/kioslave/trash/kfile-plugin/RETURNED_ITEMS b/kioslave/trash/kfile-plugin/RETURNED_ITEMS deleted file mode 100644 index 3e34c5b6d..000000000 --- a/kioslave/trash/kfile-plugin/RETURNED_ITEMS +++ /dev/null @@ -1,4 +0,0 @@ -kfile_trash -=========== -QString OriginalPath -DateTime DateOfDeletion diff --git a/kioslave/trash/kfile-plugin/kfile_trash.cpp b/kioslave/trash/kfile-plugin/kfile_trash.cpp deleted file mode 100644 index 182d9c40e..000000000 --- a/kioslave/trash/kfile-plugin/kfile_trash.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* This file is part of the KDE project - * Copyright (C) 2004 David Faure <[email protected]> - * Based on kfile_txt.cpp by Nadeem Hasan <[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 version 2. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "kfile_trash.h" - -#include <kgenericfactory.h> -#include <kdebug.h> - -#include <tqfile.h> -#include <tqstringlist.h> -#include <tqdatetime.h> - -typedef KGenericFactory<KTrashPlugin> TrashFactory; - -K_EXPORT_COMPONENT_FACTORY(kfile_trash, TrashFactory("kfile_trash")) - -KTrashPlugin::KTrashPlugin(TQObject *parent, const char *name, - const TQStringList &args) : KFilePlugin(parent, name, args) -{ - TDEGlobal::locale()->insertCatalogue( "kio_trash" ); - - kdDebug(7034) << "Trash file meta info plugin\n"; - - makeMimeTypeInfo("trash"); - makeMimeTypeInfo("system"); - - (void)impl.init(); -} - -void KTrashPlugin::makeMimeTypeInfo(const TQString& mimeType) -{ - KFileMimeTypeInfo* info = addMimeTypeInfo( mimeType ); - - KFileMimeTypeInfo::GroupInfo* group = - addGroupInfo(info, "General", i18n("General")); - - KFileMimeTypeInfo::ItemInfo* item; - item = addItemInfo(group, "OriginalPath", i18n("Original Path"), TQVariant::String); - item = addItemInfo(group, "DateOfDeletion", i18n("Date of Deletion"), TQVariant::DateTime); -} - -bool KTrashPlugin::readInfo(KFileMetaInfo& info, uint) -{ - KURL url = info.url(); - - if ( url.protocol()=="system" - && url.path().startsWith("/trash") ) - { - TQString path = url.path(); - path.remove(0, 6); - url.setProtocol("trash"); - url.setPath(path); - } - - //kdDebug() << k_funcinfo << info.url() << endl; - if ( url.protocol() != "trash" ) - return false; - - int trashId; - TQString fileId; - TQString relativePath; - if ( !TrashImpl::parseURL( url, trashId, fileId, relativePath ) ) - return false; - - TrashImpl::TrashedFileInfo trashInfo; - if ( !impl.infoForFile( trashId, fileId, trashInfo ) ) - return false; - - KFileMetaInfoGroup group = appendGroup(info, "General"); - appendItem(group, "OriginalPath", trashInfo.origPath); - appendItem(group, "DateOfDeletion", trashInfo.deletionDate); - - return true; -} - -#include "kfile_trash.moc" diff --git a/kioslave/trash/kfile-plugin/kfile_trash.desktop b/kioslave/trash/kfile-plugin/kfile_trash.desktop deleted file mode 100644 index 4b58a68dc..000000000 --- a/kioslave/trash/kfile-plugin/kfile_trash.desktop +++ /dev/null @@ -1,79 +0,0 @@ -[Desktop Entry] -Type=Service -Name=Trash File Info -Name[af]=Asblik inligting -Name[ar]=معلومات مفل المهملات -Name[az]=Zibil Faylı Məlumatı -Name[be]=Інфармацыя аб файле сметніцы -Name[bg]=Информация за кошчето -Name[bn]=আবর্জনা ফাইল তথ্য -Name[br]=Titouroù diwar-benn ar pod-lastez -Name[bs]=Smeće informacije o datoteci -Name[ca]=Informació del fitxer paperera -Name[cs]=Info o koši -Name[csb]=Wëdowiédzô ò lopkù w kòszu -Name[da]=Fil-info om affald -Name[de]=Mülleimer-Information -Name[el]=Πληροφορίες για τον Κάδο Απορριμμάτων -Name[en_GB]=Wastebin File Info -Name[eo]=Rubuja informo -Name[es]=Información de la papelera -Name[et]=Prügikasti failiinfo -Name[eu]=Zakarontziaren infoa -Name[fa]=اطلاعات پروندۀ زباله -Name[fi]=Roskakorin tiedot -Name[fr]=Info Fichier Corbeille -Name[fy]=Jiskefet ynformaasje -Name[gl]=Información do Lixo -Name[he]=מידע אודות קובץ אשפה -Name[hi]=रद्दी फ़ाइल जानकारी -Name[hr]=Podaci o otpadu -Name[hu]=Szemétkosár-jellemzők -Name[is]=Upplýsingar um ruslaskrá -Name[it]=Informazioni file del cestino -Name[ja]=ごみ箱情報 -Name[ka]=ურნაში არსებული ფაილის შესახებ ცნობი -Name[kk]=Өшірілген файл мәліметі -Name[km]=ព័ត៌មានឯកសារសំរាម -Name[ko]=휴지통 파일 정보 -Name[lt]=Šiukšlių bylos informacija -Name[lv]=Atkritumu faila informācija -Name[mk]=Инфо. за датотека од Корпата -Name[ms]=Maklumat Fail Sampah -Name[mt]=Skart -Name[nb]=Søppelfilinformasjon -Name[nds]=Affalltünn-Informatschonen -Name[ne]=रद्दीटोकरी फाइल सूचना -Name[nl]=Prullenbakinformatie -Name[nn]=Søppelfilinformasjon -Name[pa]=ਰੱਦੀ ਫਾਇਲ ਜਾਣਕਾਰੀ -Name[pl]=Informacja o pliku w koszu -Name[pt]=Informações de Ficheiros no Lixo -Name[pt_BR]=Informações sobre o Arquivo de Lixo -Name[ro]=Informații fișier șters -Name[ru]=Сведения о файле в корзине -Name[rw]=Ibisobanuro byo Guta Idosiye -Name[se]=Ruskalihttedieđut -Name[sk]=Informácie o koši -Name[sl]=Informacije o Smeteh -Name[sr]=Информације о фајлу у смећу -Name[sr@Latn]=Informacije o fajlu u smeću -Name[sv]=Information om filer i papperskorgen -Name[ta]=குப்பைத்தொட்டி கோப்பு தகவல் -Name[te]=చెత్త బుట్ట దస్త్ర వివరాలు -Name[tg]=Файли ахборотии ахлотдон -Name[th]=ข้อมูลแฟ้มถังขยะ -Name[tr]=Çöp Dosya Bilgisi -Name[tt]=Taşlanğan Birem Turında -Name[uk]=Інформація про файл у смітнику -Name[uz]=Chiqindilar qutisi haqida maʼlumot -Name[uz@cyrillic]=Чиқиндилар қутиси ҳақида маълумот -Name[vi]=Thông tin về Tập tin trong Thùng rác -Name[wa]=Informåcion sol fitchî batch -Name[zh_CN]=回收站文件信息 -Name[zh_TW]=資源回收桶檔案資訊 -ServiceTypes=KFilePlugin -X-TDE-Library=kfile_trash -X-TDE-Protocol=trash -PreferredGroups=General -PreferredItems=OriginalPath,DateOfDeletion diff --git a/kioslave/trash/kfile-plugin/kfile_trash.h b/kioslave/trash/kfile-plugin/kfile_trash.h deleted file mode 100644 index 33f83e911..000000000 --- a/kioslave/trash/kfile-plugin/kfile_trash.h +++ /dev/null @@ -1,42 +0,0 @@ -/* This file is part of the KDE project - * Copyright (C) 2004 David Faure <[email protected]> - * Based on kfile_txt.h by Nadeem Hasan <[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 version 2. - * - * This program 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 - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef __KFILE_TRASH_H_ -#define __KFILE_TRASH_H_ - -#include <kfilemetainfo.h> -#include "../trashimpl.h" - -class TQStringList; - -class KTrashPlugin: public KFilePlugin -{ - Q_OBJECT - -public: - KTrashPlugin(TQObject *parent, const char *name, const TQStringList& args); - virtual bool readInfo(KFileMetaInfo& info, uint what); - -private: - void makeMimeTypeInfo(const TQString& mimeType); - TrashImpl impl; -}; - -#endif diff --git a/kioslave/trash/kfile-plugin/kfile_trash_system.desktop b/kioslave/trash/kfile-plugin/kfile_trash_system.desktop deleted file mode 100644 index 3e3c8fe47..000000000 --- a/kioslave/trash/kfile-plugin/kfile_trash_system.desktop +++ /dev/null @@ -1,79 +0,0 @@ -[Desktop Entry] -Type=Service -Name=Trash File Info -Name[af]=Asblik inligting -Name[ar]=معلومات مفل المهملات -Name[az]=Zibil Faylı Məlumatı -Name[be]=Інфармацыя аб файле сметніцы -Name[bg]=Информация за кошчето -Name[bn]=আবর্জনা ফাইল তথ্য -Name[br]=Titouroù diwar-benn ar pod-lastez -Name[bs]=Smeće informacije o datoteci -Name[ca]=Informació del fitxer paperera -Name[cs]=Info o koši -Name[csb]=Wëdowiédzô ò lopkù w kòszu -Name[da]=Fil-info om affald -Name[de]=Mülleimer-Information -Name[el]=Πληροφορίες για τον Κάδο Απορριμμάτων -Name[en_GB]=Wastebin File Info -Name[eo]=Rubuja informo -Name[es]=Información de la papelera -Name[et]=Prügikasti failiinfo -Name[eu]=Zakarontziaren infoa -Name[fa]=اطلاعات پروندۀ زباله -Name[fi]=Roskakorin tiedot -Name[fr]=Info Fichier Corbeille -Name[fy]=Jiskefet ynformaasje -Name[gl]=Información do Lixo -Name[he]=מידע אודות קובץ אשפה -Name[hi]=रद्दी फ़ाइल जानकारी -Name[hr]=Podaci o otpadu -Name[hu]=Szemétkosár-jellemzők -Name[is]=Upplýsingar um ruslaskrá -Name[it]=Informazioni file del cestino -Name[ja]=ごみ箱情報 -Name[ka]=ურნაში არსებული ფაილის შესახებ ცნობი -Name[kk]=Өшірілген файл мәліметі -Name[km]=ព័ត៌មានឯកសារសំរាម -Name[ko]=휴지통 파일 정보 -Name[lt]=Šiukšlių bylos informacija -Name[lv]=Atkritumu faila informācija -Name[mk]=Инфо. за датотека од Корпата -Name[ms]=Maklumat Fail Sampah -Name[mt]=Skart -Name[nb]=Søppelfilinformasjon -Name[nds]=Affalltünn-Informatschonen -Name[ne]=रद्दीटोकरी फाइल सूचना -Name[nl]=Prullenbakinformatie -Name[nn]=Søppelfilinformasjon -Name[pa]=ਰੱਦੀ ਫਾਇਲ ਜਾਣਕਾਰੀ -Name[pl]=Informacja o pliku w koszu -Name[pt]=Informações de Ficheiros no Lixo -Name[pt_BR]=Informações sobre o Arquivo de Lixo -Name[ro]=Informații fișier șters -Name[ru]=Сведения о файле в корзине -Name[rw]=Ibisobanuro byo Guta Idosiye -Name[se]=Ruskalihttedieđut -Name[sk]=Informácie o koši -Name[sl]=Informacije o Smeteh -Name[sr]=Информације о фајлу у смећу -Name[sr@Latn]=Informacije o fajlu u smeću -Name[sv]=Information om filer i papperskorgen -Name[ta]=குப்பைத்தொட்டி கோப்பு தகவல் -Name[te]=చెత్త బుట్ట దస్త్ర వివరాలు -Name[tg]=Файли ахборотии ахлотдон -Name[th]=ข้อมูลแฟ้มถังขยะ -Name[tr]=Çöp Dosya Bilgisi -Name[tt]=Taşlanğan Birem Turında -Name[uk]=Інформація про файл у смітнику -Name[uz]=Chiqindilar qutisi haqida maʼlumot -Name[uz@cyrillic]=Чиқиндилар қутиси ҳақида маълумот -Name[vi]=Thông tin về Tập tin trong Thùng rác -Name[wa]=Informåcion sol fitchî batch -Name[zh_CN]=回收站文件信息 -Name[zh_TW]=資源回收桶檔案資訊 -ServiceTypes=KFilePlugin -X-TDE-Library=kfile_trash -X-TDE-Protocol=system -PreferredGroups=General -PreferredItems=OriginalPath,DateOfDeletion 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 <[email protected]> - - 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" diff --git a/kioslave/trash/kio_trash.h b/kioslave/trash/kio_trash.h deleted file mode 100644 index 6f94512d7..000000000 --- a/kioslave/trash/kio_trash.h +++ /dev/null @@ -1,71 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 David Faure <[email protected]> - - 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. -*/ - -#ifndef KIO_TRASH_H -#define KIO_TRASH_H - -#include <kio/slavebase.h> -#include "trashimpl.h" -namespace TDEIO { class Job; } - -typedef TrashImpl::TrashedFileInfo TrashedFileInfo; -typedef TrashImpl::TrashedFileInfoList TrashedFileInfoList; - -class TrashProtocol : public TQObject, public TDEIO::SlaveBase -{ - Q_OBJECT -public: - TrashProtocol( const TQCString& protocol, const TQCString &pool, const TQCString &app); - virtual ~TrashProtocol(); - virtual void stat(const KURL& url); - virtual void listDir(const KURL& url); - virtual void get( const KURL& url ); - virtual void put( const KURL& url, int , bool overwrite, bool ); - virtual void rename( const KURL &, const KURL &, bool ); - virtual void copy( const KURL &src, const KURL &dest, int permissions, bool overwrite ); - // TODO (maybe) chmod( const KURL& url, int permissions ); - virtual void del( const KURL &url, bool isfile ); - /** - * Special actions: (first int in the byte array) - * 1 : empty trash - * 2 : migrate old (pre-kde-3.4) trash contents - * 3 : restore a file to its original location. Args: KURL trashURL. - */ - virtual void special( const TQByteArray & data ); - -private slots: - void slotData( TDEIO::Job*, const TQByteArray& ); - void slotMimetype( TDEIO::Job*, const TQString& ); - void jobFinished( TDEIO::Job* job ); - -private: - typedef enum CopyOrMove { Copy, Move }; - void copyOrMove( const KURL& src, const KURL& dest, bool overwrite, CopyOrMove action ); - void createTopLevelDirEntry(TDEIO::UDSEntry& entry); - bool createUDSEntry( const TQString& physicalPath, const TQString& fileName, const TQString& url, - TDEIO::UDSEntry& entry, const TrashedFileInfo& info ); - void listRoot(); - void restore( const KURL& trashURL ); - - TrashImpl impl; - TQString m_userName; - TQString m_groupName; -}; - -#endif diff --git a/kioslave/trash/ktrash.cpp b/kioslave/trash/ktrash.cpp deleted file mode 100644 index b05cac249..000000000 --- a/kioslave/trash/ktrash.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 David Faure <[email protected]> - - 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 <kapplication.h> -#include <kio/netaccess.h> -#include <kio/job.h> -#include <kcmdlineargs.h> -#include <klocale.h> -#include <kdirnotify_stub.h> -#include <kdebug.h> - -static KCmdLineOptions options[] = -{ - { "empty", I18N_NOOP( "Empty the contents of the trash" ), 0 }, - //{ "migrate", I18N_NOOP( "Migrate contents of old trash" ), 0 }, - { "restore <file>", I18N_NOOP( "Restore a trashed file to its original location" ), 0 }, - // This hack is for the servicemenu on trash.desktop which uses Exec=ktrash -empty. %f is implied... - { "+[ignored]", I18N_NOOP( "Ignored" ), 0 }, - KCmdLineLastOption -}; - -int main(int argc, char *argv[]) -{ - TDEApplication::disableAutoDcopRegistration(); - TDECmdLineArgs::init( argc, argv, "ktrash", - I18N_NOOP( "ktrash" ), - I18N_NOOP( "Helper program to handle the TDE trash can\n" - "Note: to move files to the trash, do not use ktrash, but \"kfmclient move 'url' trash:/\"" ), - TDE_VERSION_STRING ); - TDECmdLineArgs::addCmdLineOptions( options ); - TDEApplication app; - - TDECmdLineArgs* args = TDECmdLineArgs::parsedArgs(); - if ( args->isSet( "empty" ) ) { - // We use a kio job instead of linking to TrashImpl, for a smaller binary - // (and the possibility of a central service at some point) - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)1; - TDEIO::Job* job = TDEIO::special( "trash:/", packedArgs ); - (void)TDEIO::NetAccess::synchronousRun( job, 0 ); - - // Update konq windows opened on trash:/ - KDirNotify_stub allDirNotify("*", "KDirNotify*"); - allDirNotify.FilesAdded( "trash:/" ); // yeah, files were removed, but we don't know which ones... - return 0; - } - -#if 0 - // This is only for testing. KDesktop handles it automatically. - if ( args->isSet( "migrate" ) ) { - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)2; - TDEIO::Job* job = TDEIO::special( "trash:/", packedArgs ); - (void)TDEIO::NetAccess::synchronousRun( job, 0 ); - return 0; - } -#endif - - TQCString restoreArg = args->getOption( "restore" ); - if ( !restoreArg.isEmpty() ) { - - if (restoreArg.find("system:/trash")==0) { - restoreArg.remove(0, 13); - restoreArg.prepend("trash:"); - } - - KURL trashURL( restoreArg ); - if ( !trashURL.isValid() || trashURL.protocol() != "trash" ) { - kdError() << "Invalid URL for restoring a trashed file:" << trashURL << endl; - return 1; - } - - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)3 << trashURL; - TDEIO::Job* job = TDEIO::special( trashURL, packedArgs ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - if ( !ok ) - kdError() << TDEIO::NetAccess::lastErrorString() << endl; - return 0; - } - - return 0; -} diff --git a/kioslave/trash/testtrash.cpp b/kioslave/trash/testtrash.cpp deleted file mode 100644 index e3d06a6d2..000000000 --- a/kioslave/trash/testtrash.cpp +++ /dev/null @@ -1,1198 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 David Faure <[email protected]> - - 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. -*/ - -// Get those asserts to work -#undef NDEBUG -#undef NO_DEBUG - -#include "kio_trash.h" -#include "testtrash.h" - -#include <config.h> - -#include <kurl.h> -#include <klocale.h> -#include <kapplication.h> -#include <kio/netaccess.h> -#include <kio/job.h> -#include <kdebug.h> -#include <kcmdlineargs.h> - -#include <tqdir.h> -#include <tqfileinfo.h> -#include <tqvaluevector.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <assert.h> -#include <kfileitem.h> -#include <kstandarddirs.h> - -static bool check(const TQString& txt, TQString a, TQString b) -{ - if (a.isEmpty()) - a = TQString::null; - if (b.isEmpty()) - b = TQString::null; - if (a == b) { - kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "ok" << endl; - } - else { - kdDebug() << txt << " : checking '" << a << "' against expected value '" << b << "'... " << "KO !" << endl; - exit(1); - } - return true; -} - -// There are two ways to test encoding things: -// * with utf8 filenames -// * with latin1 filenames -// -//#define UTF8TEST 1 - -int main(int argc, char *argv[]) -{ - // Ensure a known TQFile::encodeName behavior for trashUtf8FileFromHome - // However this assume your $HOME doesn't use characters from other locales... - setenv( "LC_ALL", "en_GB.ISO-8859-1", 1 ); -#ifdef UTF8TEST - setenv( "TDE_UTF8_FILENAMES", "true", 1 ); -#else - unsetenv( "TDE_UTF8_FILENAMES" ); -#endif - - // Use another directory than the real one, just to keep things clean - setenv( "XDG_DATA_HOME", TQFile::encodeName( TQDir::homeDirPath() + "/.local-testtrash" ), true ); - setenv( "TDE_FORK_SLAVES", "yes", true ); - - TDEApplication::disableAutoDcopRegistration(); - TDECmdLineArgs::init(argc,argv,"testtrash", 0, 0, 0, 0); - TDEApplication app; - - TestTrash test; - test.setup(); - test.runAll(); - kdDebug() << "All tests OK." << endl; - return 0; // success. The exit(1) in check() is what happens in case of failure. -} - -TQString TestTrash::homeTmpDir() const -{ - return TQDir::homeDirPath() + "/.trinity/testtrash/"; -} - -TQString TestTrash::readOnlyDirPath() const -{ - return homeTmpDir() + TQString( "readonly" ); -} - -TQString TestTrash::otherTmpDir() const -{ - // This one needs to be on another partition - return "/tmp/testtrash/"; -} - -TQString TestTrash::utf8FileName() const -{ - return TQString( "test" ) + TQChar( 0x2153 ); // "1/3" character, not part of latin1 -} - -TQString TestTrash::umlautFileName() const -{ - return TQString( "umlaut" ) + TQChar( 0xEB ); -} - -static void removeFile( const TQString& trashDir, const TQString& fileName ) -{ - TQDir dir; - dir.remove( trashDir + fileName ); - assert( !TQDir( trashDir + fileName ).exists() ); -} - -static void removeDir( const TQString& trashDir, const TQString& dirName ) -{ - TQDir dir; - dir.rmdir( trashDir + dirName ); - assert( !TQDir( trashDir + dirName ).exists() ); -} - -void TestTrash::setup() -{ - m_trashDir = TDEGlobal::dirs()->localxdgdatadir() + "Trash"; - kdDebug() << "setup: using trash directory " << m_trashDir << endl; - - // Look for another writable partition than $HOME (not mandatory) - TrashImpl impl; - impl.init(); - - TrashImpl::TrashDirMap trashDirs = impl.trashDirectories(); - TrashImpl::TrashDirMap topDirs = impl.topDirectories(); - bool foundTrashDir = false; - m_otherPartitionId = 0; - m_tmpIsWritablePartition = false; - m_tmpTrashId = -1; - TQValueVector<int> writableTopDirs; - for ( TrashImpl::TrashDirMap::ConstIterator it = trashDirs.begin(); it != trashDirs.end() ; ++it ) { - if ( it.key() == 0 ) { - assert( it.data() == m_trashDir ); - assert( topDirs.find( 0 ) == topDirs.end() ); - foundTrashDir = true; - } else { - assert( topDirs.find( it.key() ) != topDirs.end() ); - const TQString topdir = topDirs[it.key()]; - if ( TQFileInfo( topdir ).isWritable() ) { - writableTopDirs.append( it.key() ); - if ( topdir == "/tmp/" ) { - m_tmpIsWritablePartition = true; - m_tmpTrashId = it.key(); - kdDebug() << "/tmp is on its own partition (trashid=" << m_tmpTrashId << "), some tests will be skipped" << endl; - removeFile( it.data(), "/info/fileFromOther.trashinfo" ); - removeFile( it.data(), "/files/fileFromOther" ); - removeFile( it.data(), "/info/symlinkFromOther.trashinfo" ); - removeFile( it.data(), "/files/symlinkFromOther" ); - removeFile( it.data(), "/info/trashDirFromOther.trashinfo" ); - removeFile( it.data(), "/files/trashDirFromOther/testfile" ); - removeDir( it.data(), "/files/trashDirFromOther" ); - } - } - } - } - for ( TQValueVector<int>::const_iterator it = writableTopDirs.begin(); it != writableTopDirs.end(); ++it ) { - const TQString topdir = topDirs[ *it ]; - const TQString trashdir = trashDirs[ *it ]; - assert( !topdir.isEmpty() ); - assert( !trashDirs.isEmpty() ); - if ( topdir != "/tmp/" || // we'd prefer not to use /tmp here, to separate the tests - ( writableTopDirs.count() > 1 ) ) // but well, if we have no choice, take it - { - m_otherPartitionTopDir = topdir; - m_otherPartitionTrashDir = trashdir; - m_otherPartitionId = *it; - kdDebug() << "OK, found another writable partition: topDir=" << m_otherPartitionTopDir - << " trashDir=" << m_otherPartitionTrashDir << " id=" << m_otherPartitionId << endl; - break; - } - } - // Check that m_trashDir got listed - assert( foundTrashDir ); - if ( m_otherPartitionTrashDir.isEmpty() ) - kdWarning() << "No writable partition other than $HOME found, some tests will be skipped" << endl; - - // Start with a clean base dir - if ( TQFileInfo( homeTmpDir() ).exists() ) { - bool ok = TDEIO::NetAccess::del( homeTmpDir(), 0 ); - if ( !ok ) - kdFatal() << "Couldn't delete " << homeTmpDir() << endl; - } - if ( TQFileInfo( otherTmpDir() ).exists() ) { - bool ok = TDEIO::NetAccess::del( otherTmpDir(), 0 ); - if ( !ok ) - kdFatal() << "Couldn't delete " << otherTmpDir() << endl; - } - TQDir dir; // TT: why not a static method? - bool ok = dir.mkdir( homeTmpDir() ); - if ( !ok ) - kdFatal() << "Couldn't create " << homeTmpDir() << endl; - ok = dir.mkdir( otherTmpDir() ); - if ( !ok ) - kdFatal() << "Couldn't create " << otherTmpDir() << endl; - cleanTrash(); -} - - -void TestTrash::cleanTrash() -{ - kdDebug() << k_funcinfo << endl; - // Start with a relatively clean trash too - removeFile( m_trashDir, "/info/fileFromHome.trashinfo" ); - removeFile( m_trashDir, "/files/fileFromHome" ); - removeFile( m_trashDir, "/info/fileFromHome_1.trashinfo" ); - removeFile( m_trashDir, "/files/fileFromHome_1" ); - removeFile( m_trashDir, "/info/file%2f.trashinfo" ); - removeFile( m_trashDir, "/files/file%2f" ); - removeFile( m_trashDir, "/info/" + utf8FileName() + ".trashinfo" ); - removeFile( m_trashDir, "/files/" + utf8FileName() ); - removeFile( m_trashDir, "/info/" + umlautFileName() + ".trashinfo" ); - removeFile( m_trashDir, "/files/" + umlautFileName() ); - removeFile( m_trashDir, "/info/fileFromOther.trashinfo" ); - removeFile( m_trashDir, "/files/fileFromOther" ); - removeFile( m_trashDir, "/info/symlinkFromHome.trashinfo" ); - removeFile( m_trashDir, "/files/symlinkFromHome" ); - removeFile( m_trashDir, "/info/symlinkFromOther.trashinfo" ); - removeFile( m_trashDir, "/files/symlinkFromOther" ); - removeFile( m_trashDir, "/info/brokenSymlinkFromHome.trashinfo" ); - removeFile( m_trashDir, "/files/brokenSymlinkFromHome" ); - removeFile( m_trashDir, "/info/trashDirFromHome.trashinfo" ); - removeFile( m_trashDir, "/files/trashDirFromHome/testfile" ); - removeFile( m_trashDir, "/info/readonly.trashinfo" ); - removeDir( m_trashDir, "/files/trashDirFromHome" ); - removeFile( m_trashDir, "/info/trashDirFromHome_1.trashinfo" ); - removeFile( m_trashDir, "/files/trashDirFromHome_1/testfile" ); - removeDir( m_trashDir, "/files/trashDirFromHome_1" ); - removeFile( m_trashDir, "/info/trashDirFromOther.trashinfo" ); - removeFile( m_trashDir, "/files/trashDirFromOther/testfile" ); - removeDir( m_trashDir, "/files/trashDirFromOther" ); - TDEIO::NetAccess::del( m_trashDir + "/files/readonly", 0 ); - // for trashDirectoryOwnedByRoot - TDEIO::NetAccess::del( m_trashDir + "/files/cups", 0 ); - TDEIO::NetAccess::del( m_trashDir + "/files/boot", 0 ); - TDEIO::NetAccess::del( m_trashDir + "/files/etc", 0 ); - - //system( "find ~/.local-testtrash/share/Trash" ); -} - -void TestTrash::runAll() -{ - urlTestFile(); - urlTestDirectory(); - urlTestSubDirectory(); - - trashFileFromHome(); - trashPercentFileFromHome(); -#ifdef UTF8TEST - trashUtf8FileFromHome(); -#endif - trashUmlautFileFromHome(); - trashReadOnlyDirFromHome(); - testTrashNotEmpty(); - trashFileFromOther(); - trashFileIntoOtherPartition(); - trashFileOwnedByRoot(); - trashSymlinkFromHome(); - trashSymlinkFromOther(); - trashBrokenSymlinkFromHome(); - trashDirectoryFromHome(); - trashDirectoryFromOther(); - trashDirectoryOwnedByRoot(); - - tryRenameInsideTrash(); - - statRoot(); - statFileInRoot(); - statDirectoryInRoot(); - statSymlinkInRoot(); - statFileInDirectory(); - - copyFileFromTrash(); - // To test case of already-existing destination, uncomment this. - // This brings up the "rename" dialog though, so it can't be fully automated - //copyFileFromTrash(); - copyFileInDirectoryFromTrash(); - copyDirectoryFromTrash(); - copySymlinkFromTrash(); - - moveFileFromTrash(); - moveFileInDirectoryFromTrash(); - moveDirectoryFromTrash(); - moveSymlinkFromTrash(); - - listRootDir(); - listRecursiveRootDir(); - listSubDir(); - - delRootFile(); - delFileInDirectory(); - delDirectory(); - - getFile(); - restoreFile(); - restoreFileFromSubDir(); - restoreFileToDeletedDirectory(); - - emptyTrash(); - - // TODO: test - // - trash migration - // - the actual updating of the trash icon on the desktop -} - -void TestTrash::urlTestFile() -{ - const KURL url = TrashImpl::makeURL( 1, "fileId", TQString::null ); - check( "makeURL for a file", url.url(), "trash:/1-fileId" ); - - int trashId; - TQString fileId; - TQString relativePath; - bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath ); - assert( ok ); - check( "parseURL: trashId", TQString::number( trashId ), "1" ); - check( "parseURL: fileId", fileId, "fileId" ); - check( "parseURL: relativePath", relativePath, TQString::null ); -} - -void TestTrash::urlTestDirectory() -{ - const KURL url = TrashImpl::makeURL( 1, "fileId", "subfile" ); - check( "makeURL", url.url(), "trash:/1-fileId/subfile" ); - - int trashId; - TQString fileId; - TQString relativePath; - bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath ); - assert( ok ); - check( "parseURL: trashId", TQString::number( trashId ), "1" ); - check( "parseURL: fileId", fileId, "fileId" ); - check( "parseURL: relativePath", relativePath, "subfile" ); -} - -void TestTrash::urlTestSubDirectory() -{ - const KURL url = TrashImpl::makeURL( 1, "fileId", "subfile/foobar" ); - check( "makeURL", url.url(), "trash:/1-fileId/subfile/foobar" ); - - int trashId; - TQString fileId; - TQString relativePath; - bool ok = TrashImpl::parseURL( url, trashId, fileId, relativePath ); - assert( ok ); - check( "parseURL: trashId", TQString::number( trashId ), "1" ); - check( "parseURL: fileId", fileId, "fileId" ); - check( "parseURL: relativePath", relativePath, "subfile/foobar" ); -} - -static void checkInfoFile( const TQString& infoPath, const TQString& origFilePath ) -{ - kdDebug() << k_funcinfo << infoPath << endl; - TQFileInfo info( infoPath ); - assert( info.exists() ); - assert( info.isFile() ); - KSimpleConfig infoFile( info.absFilePath(), true ); - if ( !infoFile.hasGroup( "Trash Info" ) ) - kdFatal() << "no Trash Info group in " << info.absFilePath() << endl; - infoFile.setGroup( "Trash Info" ); - const TQString origPath = infoFile.readEntry( "Path" ); - assert( !origPath.isEmpty() ); - assert( origPath == KURL::encode_string( origFilePath, TDEGlobal::locale()->fileEncodingMib() ) ); - const TQString date = infoFile.readEntry( "DeletionDate" ); - assert( !date.isEmpty() ); - assert( date.contains( "T" ) ); -} - -static void createTestFile( const TQString& path ) -{ - TQFile f( path ); - if ( !f.open( IO_WriteOnly ) ) - kdFatal() << "Can't create " << path << endl; - f.writeBlock( "Hello world\n", 12 ); - f.close(); - assert( TQFile::exists( path ) ); -} - -void TestTrash::trashFile( const TQString& origFilePath, const TQString& fileId ) -{ - // setup - if ( !TQFile::exists( origFilePath ) ) - createTestFile( origFilePath ); - KURL u; - u.setPath( origFilePath ); - - // test - TDEIO::Job* job = TDEIO::move( u, "trash:/" ); - TQMap<TQString, TQString> metaData; - //bool ok = TDEIO::NetAccess::move( u, "trash:/" ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0, 0, 0, &metaData ); - if ( !ok ) - kdError() << "moving " << u << " to trash failed with error " << TDEIO::NetAccess::lastError() << " " << TDEIO::NetAccess::lastErrorString() << endl; - assert( ok ); - if ( origFilePath.startsWith( "/tmp" ) && m_tmpIsWritablePartition ) { - kdDebug() << " TESTS SKIPPED" << endl; - } else { - checkInfoFile( m_trashDir + "/info/" + fileId + ".trashinfo", origFilePath ); - - TQFileInfo files( m_trashDir + "/files/" + fileId ); - assert( files.isFile() ); - assert( files.size() == 12 ); - } - - // coolo suggests testing that the original file is actually gone, too :) - assert( !TQFile::exists( origFilePath ) ); - - assert( !metaData.isEmpty() ); - bool found = false; - TQMap<TQString, TQString>::ConstIterator it = metaData.begin(); - for ( ; it != metaData.end() ; ++it ) { - if ( it.key().startsWith( "trashURL" ) ) { - const TQString origPath = it.key().mid( 9 ); - KURL trashURL( it.data() ); - kdDebug() << trashURL << endl; - assert( !trashURL.isEmpty() ); - assert( trashURL.protocol() == "trash" ); - int trashId = 0; - if ( origFilePath.startsWith( "/tmp" ) && m_tmpIsWritablePartition ) - trashId = m_tmpTrashId; - assert( trashURL.path() == "/" + TQString::number( trashId ) + "-" + fileId ); - found = true; - } - } - assert( found ); -} - -void TestTrash::trashFileFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = "fileFromHome"; - trashFile( homeTmpDir() + fileName, fileName ); - - // Do it again, check that we got a different id - trashFile( homeTmpDir() + fileName, fileName + "_1" ); -} - -void TestTrash::trashPercentFileFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = "file%2f"; - trashFile( homeTmpDir() + fileName, fileName ); -} - -void TestTrash::trashUtf8FileFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = utf8FileName(); - trashFile( homeTmpDir() + fileName, fileName ); -} - -void TestTrash::trashUmlautFileFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = umlautFileName(); - trashFile( homeTmpDir() + fileName, fileName ); -} - -void TestTrash::testTrashNotEmpty() -{ - KSimpleConfig cfg( "trashrc", true ); - assert( cfg.hasGroup( "Status" ) ); - cfg.setGroup( "Status" ); - assert( cfg.readBoolEntry( "Empty", true ) == false ); -} - -void TestTrash::trashFileFromOther() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = "fileFromOther"; - trashFile( otherTmpDir() + fileName, fileName ); -} - -void TestTrash::trashFileIntoOtherPartition() -{ - if ( m_otherPartitionTrashDir.isEmpty() ) { - kdDebug() << k_funcinfo << " - SKIPPED" << endl; - return; - } - kdDebug() << k_funcinfo << endl; - const TQString fileName = "testtrash-file"; - const TQString origFilePath = m_otherPartitionTopDir + fileName; - const TQString fileId = fileName; - // cleanup - TQFile::remove( m_otherPartitionTrashDir + "/info/" + fileId + ".trashinfo" ); - TQFile::remove( m_otherPartitionTrashDir + "/files/" + fileId ); - - // setup - if ( !TQFile::exists( origFilePath ) ) - createTestFile( origFilePath ); - KURL u; - u.setPath( origFilePath ); - - // test - TDEIO::Job* job = TDEIO::move( u, "trash:/" ); - TQMap<TQString, TQString> metaData; - bool ok = TDEIO::NetAccess::synchronousRun( job, 0, 0, 0, &metaData ); - assert( ok ); - // Note that the Path stored in the info file is relative, on other partitions (#95652) - checkInfoFile( m_otherPartitionTrashDir + "/info/" + fileId + ".trashinfo", fileName ); - - TQFileInfo files( m_otherPartitionTrashDir + "/files/" + fileId ); - assert( files.isFile() ); - assert( files.size() == 12 ); - - // coolo suggests testing that the original file is actually gone, too :) - assert( !TQFile::exists( origFilePath ) ); - - assert( !metaData.isEmpty() ); - bool found = false; - TQMap<TQString, TQString>::ConstIterator it = metaData.begin(); - for ( ; it != metaData.end() ; ++it ) { - if ( it.key().startsWith( "trashURL" ) ) { - const TQString origPath = it.key().mid( 9 ); - KURL trashURL( it.data() ); - kdDebug() << trashURL << endl; - assert( !trashURL.isEmpty() ); - assert( trashURL.protocol() == "trash" ); - assert( trashURL.path() == TQString( "/%1-%2" ).arg( m_otherPartitionId ).arg( fileId ) ); - found = true; - } - } - assert( found ); -} - -void TestTrash::trashFileOwnedByRoot() -{ - kdDebug() << k_funcinfo << endl; - KURL u; - u.setPath( "/etc/passwd" ); - const TQString fileId = "passwd"; - - TDEIO::CopyJob* job = TDEIO::move( u, "trash:/" ); - job->setInteractive( false ); // no skip dialog, thanks - TQMap<TQString, TQString> metaData; - //bool ok = TDEIO::NetAccess::move( u, "trash:/" ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0, 0, 0, &metaData ); - assert( !ok ); - assert( TDEIO::NetAccess::lastError() == TDEIO::ERR_ACCESS_DENIED ); - const TQString infoPath( m_trashDir + "/info/" + fileId + ".trashinfo" ); - assert( !TQFile::exists( infoPath ) ); - - TQFileInfo files( m_trashDir + "/files/" + fileId ); - assert( !files.exists() ); - - assert( TQFile::exists( u.path() ) ); -} - -void TestTrash::trashSymlink( const TQString& origFilePath, const TQString& fileId, bool broken ) -{ - kdDebug() << k_funcinfo << endl; - // setup - const char* target = broken ? "/nonexistent" : "/tmp"; - bool ok = ::symlink( target, TQFile::encodeName( origFilePath ) ) == 0; - assert( ok ); - KURL u; - u.setPath( origFilePath ); - - // test - ok = TDEIO::NetAccess::move( u, "trash:/" ); - assert( ok ); - if ( origFilePath.startsWith( "/tmp" ) && m_tmpIsWritablePartition ) { - kdDebug() << " TESTS SKIPPED" << endl; - return; - } - checkInfoFile( m_trashDir + "/info/" + fileId + ".trashinfo", origFilePath ); - - TQFileInfo files( m_trashDir + "/files/" + fileId ); - assert( files.isSymLink() ); - assert( files.readLink() == TQFile::decodeName( target ) ); - assert( !TQFile::exists( origFilePath ) ); -} - -void TestTrash::trashSymlinkFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = "symlinkFromHome"; - trashSymlink( homeTmpDir() + fileName, fileName, false ); -} - -void TestTrash::trashSymlinkFromOther() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = "symlinkFromOther"; - trashSymlink( otherTmpDir() + fileName, fileName, false ); -} - -void TestTrash::trashBrokenSymlinkFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileName = "brokenSymlinkFromHome"; - trashSymlink( homeTmpDir() + fileName, fileName, true ); -} - -void TestTrash::trashDirectory( const TQString& origPath, const TQString& fileId ) -{ - kdDebug() << k_funcinfo << fileId << endl; - // setup - if ( !TQFileInfo( origPath ).exists() ) { - TQDir dir; - bool ok = dir.mkdir( origPath ); - Q_ASSERT( ok ); - } - createTestFile( origPath + "/testfile" ); - KURL u; u.setPath( origPath ); - - // test - bool ok = TDEIO::NetAccess::move( u, "trash:/" ); - assert( ok ); - if ( origPath.startsWith( "/tmp" ) && m_tmpIsWritablePartition ) { - kdDebug() << " TESTS SKIPPED" << endl; - return; - } - checkInfoFile( m_trashDir + "/info/" + fileId + ".trashinfo", origPath ); - - TQFileInfo filesDir( m_trashDir + "/files/" + fileId ); - assert( filesDir.isDir() ); - TQFileInfo files( m_trashDir + "/files/" + fileId + "/testfile" ); - assert( files.exists() ); - assert( files.isFile() ); - assert( files.size() == 12 ); - assert( !TQFile::exists( origPath ) ); -} - -void TestTrash::trashDirectoryFromHome() -{ - kdDebug() << k_funcinfo << endl; - TQString dirName = "trashDirFromHome"; - trashDirectory( homeTmpDir() + dirName, dirName ); - // Do it again, check that we got a different id - trashDirectory( homeTmpDir() + dirName, dirName + "_1" ); -} - -void TestTrash::trashReadOnlyDirFromHome() -{ - kdDebug() << k_funcinfo << endl; - const TQString dirName = readOnlyDirPath(); - TQDir dir; - bool ok = dir.mkdir( dirName ); - Q_ASSERT( ok ); - // #130780 - const TQString subDirPath = dirName + "/readonly_subdir"; - ok = dir.mkdir( subDirPath ); - Q_ASSERT( ok ); - createTestFile( subDirPath + "/testfile_in_subdir" ); - ::chmod( TQFile::encodeName( subDirPath ), 0500 ); - - trashDirectory( dirName, "readonly" ); -} - -void TestTrash::trashDirectoryFromOther() -{ - kdDebug() << k_funcinfo << endl; - TQString dirName = "trashDirFromOther"; - trashDirectory( otherTmpDir() + dirName, dirName ); -} - -void TestTrash::tryRenameInsideTrash() -{ - kdDebug() << k_funcinfo << " with file_move" << endl; - bool worked = TDEIO::NetAccess::file_move( "trash:/0-tryRenameInsideTrash", "trash:/foobar" ); - assert( !worked ); - assert( TDEIO::NetAccess::lastError() == TDEIO::ERR_CANNOT_RENAME ); - - kdDebug() << k_funcinfo << " with move" << endl; - worked = TDEIO::NetAccess::move( "trash:/0-tryRenameInsideTrash", "trash:/foobar" ); - assert( !worked ); - assert( TDEIO::NetAccess::lastError() == TDEIO::ERR_CANNOT_RENAME ); -} - -void TestTrash::delRootFile() -{ - kdDebug() << k_funcinfo << endl; - - // test deleting a trashed file - bool ok = TDEIO::NetAccess::del( "trash:/0-fileFromHome", 0L ); - assert( ok ); - - TQFileInfo file( m_trashDir + "/files/fileFromHome" ); - assert( !file.exists() ); - TQFileInfo info( m_trashDir + "/info/fileFromHome.trashinfo" ); - assert( !info.exists() ); - - // trash it again, we might need it later - const TQString fileName = "fileFromHome"; - trashFile( homeTmpDir() + fileName, fileName ); -} - -void TestTrash::delFileInDirectory() -{ - kdDebug() << k_funcinfo << endl; - - // test deleting a file inside a trashed directory -> not allowed - bool ok = TDEIO::NetAccess::del( "trash:/0-trashDirFromHome/testfile", 0L ); - assert( !ok ); - assert( TDEIO::NetAccess::lastError() == TDEIO::ERR_ACCESS_DENIED ); - - TQFileInfo dir( m_trashDir + "/files/trashDirFromHome" ); - assert( dir.exists() ); - TQFileInfo file( m_trashDir + "/files/trashDirFromHome/testfile" ); - assert( file.exists() ); - TQFileInfo info( m_trashDir + "/info/trashDirFromHome.trashinfo" ); - assert( info.exists() ); -} - -void TestTrash::delDirectory() -{ - kdDebug() << k_funcinfo << endl; - - // test deleting a trashed directory - bool ok = TDEIO::NetAccess::del( "trash:/0-trashDirFromHome", 0L ); - assert( ok ); - - TQFileInfo dir( m_trashDir + "/files/trashDirFromHome" ); - assert( !dir.exists() ); - TQFileInfo file( m_trashDir + "/files/trashDirFromHome/testfile" ); - assert( !file.exists() ); - TQFileInfo info( m_trashDir + "/info/trashDirFromHome.trashinfo" ); - assert( !info.exists() ); - - // trash it again, we'll need it later - TQString dirName = "trashDirFromHome"; - trashDirectory( homeTmpDir() + dirName, dirName ); -} - -void TestTrash::statRoot() -{ - kdDebug() << k_funcinfo << endl; - KURL url( "trash:/" ); - TDEIO::UDSEntry entry; - bool ok = TDEIO::NetAccess::stat( url, entry, 0 ); - assert( ok ); - KFileItem item( entry, url ); - assert( item.isDir() ); - assert( !item.isLink() ); - assert( item.isReadable() ); - assert( item.isWritable() ); - assert( !item.isHidden() ); - assert( item.name() == "." ); - assert( item.acceptsDrops() ); -} - -void TestTrash::statFileInRoot() -{ - kdDebug() << k_funcinfo << endl; - KURL url( "trash:/0-fileFromHome" ); - TDEIO::UDSEntry entry; - bool ok = TDEIO::NetAccess::stat( url, entry, 0 ); - assert( ok ); - KFileItem item( entry, url ); - assert( item.isFile() ); - assert( !item.isDir() ); - assert( !item.isLink() ); - assert( item.isReadable() ); - assert( !item.isWritable() ); - assert( !item.isHidden() ); - assert( item.name() == "fileFromHome" ); - assert( !item.acceptsDrops() ); -} - -void TestTrash::statDirectoryInRoot() -{ - kdDebug() << k_funcinfo << endl; - KURL url( "trash:/0-trashDirFromHome" ); - TDEIO::UDSEntry entry; - bool ok = TDEIO::NetAccess::stat( url, entry, 0 ); - assert( ok ); - KFileItem item( entry, url ); - assert( item.isDir() ); - assert( !item.isLink() ); - assert( item.isReadable() ); - assert( !item.isWritable() ); - assert( !item.isHidden() ); - assert( item.name() == "trashDirFromHome" ); - assert( !item.acceptsDrops() ); -} - -void TestTrash::statSymlinkInRoot() -{ - kdDebug() << k_funcinfo << endl; - KURL url( "trash:/0-symlinkFromHome" ); - TDEIO::UDSEntry entry; - bool ok = TDEIO::NetAccess::stat( url, entry, 0 ); - assert( ok ); - KFileItem item( entry, url ); - assert( item.isLink() ); - assert( item.linkDest() == "/tmp" ); - assert( item.isReadable() ); - assert( !item.isWritable() ); - assert( !item.isHidden() ); - assert( item.name() == "symlinkFromHome" ); - assert( !item.acceptsDrops() ); -} - -void TestTrash::statFileInDirectory() -{ - kdDebug() << k_funcinfo << endl; - KURL url( "trash:/0-trashDirFromHome/testfile" ); - TDEIO::UDSEntry entry; - bool ok = TDEIO::NetAccess::stat( url, entry, 0 ); - assert( ok ); - KFileItem item( entry, url ); - assert( item.isFile() ); - assert( !item.isLink() ); - assert( item.isReadable() ); - assert( !item.isWritable() ); - assert( !item.isHidden() ); - assert( item.name() == "testfile" ); - assert( !item.acceptsDrops() ); -} - -void TestTrash::copyFromTrash( const TQString& fileId, const TQString& destPath, const TQString& relativePath ) -{ - KURL src( "trash:/0-" + fileId ); - if ( !relativePath.isEmpty() ) - src.addPath( relativePath ); - KURL dest; - dest.setPath( destPath ); - - assert( TDEIO::NetAccess::exists( src, true, (TQWidget*)0 ) ); - - // A dnd would use copy(), but we use copyAs to ensure the final filename - //kdDebug() << k_funcinfo << "copyAs:" << src << " -> " << dest << endl; - TDEIO::Job* job = TDEIO::copyAs( src, dest ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - TQString infoFile( m_trashDir + "/info/" + fileId + ".trashinfo" ); - assert( TQFile::exists( infoFile ) ); - - TQFileInfo filesItem( m_trashDir + "/files/" + fileId ); - assert( filesItem.exists() ); - - assert( TQFile::exists( destPath ) ); -} - -void TestTrash::copyFileFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "fileFromHome_copied"; - copyFromTrash( "fileFromHome", destPath ); - assert( TQFileInfo( destPath ).isFile() ); - assert( TQFileInfo( destPath ).size() == 12 ); -} - -void TestTrash::copyFileInDirectoryFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "testfile_copied"; - copyFromTrash( "trashDirFromHome", destPath, "testfile" ); - assert( TQFileInfo( destPath ).isFile() ); - assert( TQFileInfo( destPath ).size() == 12 ); -} - -void TestTrash::copyDirectoryFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "trashDirFromHome_copied"; - copyFromTrash( "trashDirFromHome", destPath ); - assert( TQFileInfo( destPath ).isDir() ); -} - -void TestTrash::copySymlinkFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "symlinkFromHome_copied"; - copyFromTrash( "symlinkFromHome", destPath ); - assert( TQFileInfo( destPath ).isSymLink() ); -} - -void TestTrash::moveFromTrash( const TQString& fileId, const TQString& destPath, const TQString& relativePath ) -{ - KURL src( "trash:/0-" + fileId ); - if ( !relativePath.isEmpty() ) - src.addPath( relativePath ); - KURL dest; - dest.setPath( destPath ); - - assert( TDEIO::NetAccess::exists( src, true, (TQWidget*)0 ) ); - - // A dnd would use move(), but we use moveAs to ensure the final filename - TDEIO::Job* job = TDEIO::moveAs( src, dest ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - TQString infoFile( m_trashDir + "/info/" + fileId + ".trashinfo" ); - assert( !TQFile::exists( infoFile ) ); - - TQFileInfo filesItem( m_trashDir + "/files/" + fileId ); - assert( !filesItem.exists() ); - - assert( TQFile::exists( destPath ) ); -} - -void TestTrash::moveFileFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "fileFromHome_restored"; - moveFromTrash( "fileFromHome", destPath ); - assert( TQFileInfo( destPath ).isFile() ); - assert( TQFileInfo( destPath ).size() == 12 ); - - // trash it again for later - const TQString fileName = "fileFromHome"; - trashFile( homeTmpDir() + fileName, fileName ); -} - -void TestTrash::moveFileInDirectoryFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "testfile_restored"; - copyFromTrash( "trashDirFromHome", destPath, "testfile" ); - assert( TQFileInfo( destPath ).isFile() ); - assert( TQFileInfo( destPath ).size() == 12 ); -} - -void TestTrash::moveDirectoryFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "trashDirFromHome_restored"; - moveFromTrash( "trashDirFromHome", destPath ); - assert( TQFileInfo( destPath ).isDir() ); - - // trash it again, we'll need it later - TQString dirName = "trashDirFromHome"; - trashDirectory( homeTmpDir() + dirName, dirName ); -} - -void TestTrash::trashDirectoryOwnedByRoot() -{ - KURL u; - if ( TQFile::exists( "/etc/cups" ) ) - u.setPath( "/etc/cups" ); - else if ( TQFile::exists( "/boot" ) ) - u.setPath( "/boot" ); - else - u.setPath( "/etc" ); - const TQString fileId = u.path(); - kdDebug() << k_funcinfo << "fileId=" << fileId << endl; - - TDEIO::CopyJob* job = TDEIO::move( u, "trash:/" ); - job->setInteractive( false ); // no skip dialog, thanks - TQMap<TQString, TQString> metaData; - bool ok = TDEIO::NetAccess::synchronousRun( job, 0, 0, 0, &metaData ); - assert( !ok ); - const int err = TDEIO::NetAccess::lastError(); - assert( err == TDEIO::ERR_ACCESS_DENIED - || err == TDEIO::ERR_CANNOT_OPEN_FOR_READING ); - - const TQString infoPath( m_trashDir + "/info/" + fileId + ".trashinfo" ); - assert( !TQFile::exists( infoPath ) ); - - TQFileInfo files( m_trashDir + "/files/" + fileId ); - assert( !files.exists() ); - - assert( TQFile::exists( u.path() ) ); -} - -void TestTrash::moveSymlinkFromTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString destPath = otherTmpDir() + "symlinkFromHome_restored"; - moveFromTrash( "symlinkFromHome", destPath ); - assert( TQFileInfo( destPath ).isSymLink() ); -} - -void TestTrash::getFile() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileId = "fileFromHome_1"; - const KURL url = TrashImpl::makeURL( 0, fileId, TQString::null ); - TQString tmpFile; - bool ok = TDEIO::NetAccess::download( url, tmpFile, 0 ); - assert( ok ); - TQFile file( tmpFile ); - ok = file.open( IO_ReadOnly ); - assert( ok ); - TQByteArray str = file.readAll(); - TQCString cstr( str.data(), str.size() + 1 ); - if ( cstr != "Hello world\n" ) - kdFatal() << "get() returned the following data:" << cstr << endl; - file.close(); - TDEIO::NetAccess::removeTempFile( tmpFile ); -} - -void TestTrash::restoreFile() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileId = "fileFromHome_1"; - const KURL url = TrashImpl::makeURL( 0, fileId, TQString::null ); - const TQString infoFile( m_trashDir + "/info/" + fileId + ".trashinfo" ); - const TQString filesItem( m_trashDir + "/files/" + fileId ); - - assert( TQFile::exists( infoFile ) ); - assert( TQFile::exists( filesItem ) ); - - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)3 << url; - TDEIO::Job* job = TDEIO::special( url, packedArgs ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - - assert( !TQFile::exists( infoFile ) ); - assert( !TQFile::exists( filesItem ) ); - - const TQString destPath = homeTmpDir() + "fileFromHome"; - assert( TQFile::exists( destPath ) ); -} - -void TestTrash::restoreFileFromSubDir() -{ - kdDebug() << k_funcinfo << endl; - const TQString fileId = "trashDirFromHome_1/testfile"; - assert( !TQFile::exists( homeTmpDir() + "trashDirFromHome_1" ) ); - - const KURL url = TrashImpl::makeURL( 0, fileId, TQString::null ); - const TQString infoFile( m_trashDir + "/info/trashDirFromHome_1.trashinfo" ); - const TQString filesItem( m_trashDir + "/files/trashDirFromHome_1/testfile" ); - - assert( TQFile::exists( infoFile ) ); - assert( TQFile::exists( filesItem ) ); - - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)3 << url; - TDEIO::Job* job = TDEIO::special( url, packedArgs ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( !ok ); - // dest dir doesn't exist -> error message - assert( TDEIO::NetAccess::lastError() == TDEIO::ERR_SLAVE_DEFINED ); - - // check that nothing happened - assert( TQFile::exists( infoFile ) ); - assert( TQFile::exists( filesItem ) ); - assert( !TQFile::exists( homeTmpDir() + "trashDirFromHome_1" ) ); -} - -void TestTrash::restoreFileToDeletedDirectory() -{ - kdDebug() << k_funcinfo << endl; - // Ensure we'll get "fileFromHome" as fileId - removeFile( m_trashDir, "/info/fileFromHome.trashinfo" ); - removeFile( m_trashDir, "/files/fileFromHome" ); - trashFileFromHome(); - // Delete orig dir - bool delOK = TDEIO::NetAccess::del( homeTmpDir(), 0 ); - assert( delOK ); - - const TQString fileId = "fileFromHome"; - const KURL url = TrashImpl::makeURL( 0, fileId, TQString::null ); - const TQString infoFile( m_trashDir + "/info/" + fileId + ".trashinfo" ); - const TQString filesItem( m_trashDir + "/files/" + fileId ); - - assert( TQFile::exists( infoFile ) ); - assert( TQFile::exists( filesItem ) ); - - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)3 << url; - TDEIO::Job* job = TDEIO::special( url, packedArgs ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( !ok ); - // dest dir doesn't exist -> error message - assert( TDEIO::NetAccess::lastError() == TDEIO::ERR_SLAVE_DEFINED ); - - // check that nothing happened - assert( TQFile::exists( infoFile ) ); - assert( TQFile::exists( filesItem ) ); - - const TQString destPath = homeTmpDir() + "fileFromHome"; - assert( !TQFile::exists( destPath ) ); -} - -void TestTrash::listRootDir() -{ - kdDebug() << k_funcinfo << endl; - m_entryCount = 0; - m_listResult.clear(); - TDEIO::ListJob* job = TDEIO::listDir( "trash:/" ); - connect( job, TQT_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ), - TQT_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - kdDebug() << "listDir done - m_entryCount=" << m_entryCount << endl; - assert( m_entryCount > 1 ); - - kdDebug() << k_funcinfo << m_listResult << endl; - assert( m_listResult.contains( "." ) == 1 ); // found it, and only once -} - -void TestTrash::listRecursiveRootDir() -{ - kdDebug() << k_funcinfo << endl; - m_entryCount = 0; - m_listResult.clear(); - TDEIO::ListJob* job = TDEIO::listRecursive( "trash:/" ); - connect( job, TQT_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ), - TQT_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - kdDebug() << "listDir done - m_entryCount=" << m_entryCount << endl; - assert( m_entryCount > 1 ); - - kdDebug() << k_funcinfo << m_listResult << endl; - assert( m_listResult.contains( "." ) == 1 ); // found it, and only once -} - -void TestTrash::listSubDir() -{ - kdDebug() << k_funcinfo << endl; - m_entryCount = 0; - m_listResult.clear(); - TDEIO::ListJob* job = TDEIO::listDir( "trash:/0-trashDirFromHome" ); - connect( job, TQT_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ), - TQT_SLOT( slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - kdDebug() << "listDir done - m_entryCount=" << m_entryCount << endl; - assert( m_entryCount == 2 ); - - kdDebug() << k_funcinfo << m_listResult << endl; - assert( m_listResult.contains( "." ) == 1 ); // found it, and only once - assert( m_listResult.contains( "testfile" ) == 1 ); // found it, and only once -} - -void TestTrash::slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& lst ) -{ - for( TDEIO::UDSEntryList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) { - TDEIO::UDSEntry::ConstIterator it2 = (*it).begin(); - TQString displayName; - KURL url; - for( ; it2 != (*it).end(); it2++ ) { - switch ((*it2).m_uds) { - case TDEIO::UDS_NAME: - displayName = (*it2).m_str; - break; - case TDEIO::UDS_URL: - url = (*it2).m_str; - break; - } - } - kdDebug() << k_funcinfo << displayName << " " << url << endl; - if ( !url.isEmpty() ) { - assert( url.protocol() == "trash" ); - } - m_listResult << displayName; - } - m_entryCount += lst.count(); -} - -void TestTrash::emptyTrash() -{ - // ## Even though we use a custom XDG_DATA_HOME value, emptying the - // trash would still empty the other trash directories in other partitions. - // So we can't activate this test by default. -#if 0 - kdDebug() << k_funcinfo << endl; - TQByteArray packedArgs; - TQDataStream stream( packedArgs, IO_WriteOnly ); - stream << (int)1; - TDEIO::Job* job = TDEIO::special( "trash:/", packedArgs ); - bool ok = TDEIO::NetAccess::synchronousRun( job, 0 ); - assert( ok ); - - KSimpleConfig cfg( "trashrc", true ); - assert( cfg.hasGroup( "Status" ) ); - cfg.setGroup( "Status" ); - assert( cfg.readBoolEntry( "Empty", false ) == true ); - - assert( !TQFile::exists( m_trashDir + "/files/fileFromHome" ) ); - assert( !TQFile::exists( m_trashDir + "/files/readonly" ) ); - assert( !TQFile::exists( m_trashDir + "/info/readonly.trashinfo" ) ); - -#else - kdDebug() << k_funcinfo << " : SKIPPED" << endl; -#endif -} - -#include "testtrash.moc" diff --git a/kioslave/trash/testtrash.h b/kioslave/trash/testtrash.h deleted file mode 100644 index ebc217aac..000000000 --- a/kioslave/trash/testtrash.h +++ /dev/null @@ -1,118 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 David Faure <[email protected]> - - 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. -*/ - -#ifndef TESTTRASH_H -#define TESTTRASH_H - -#include <tqobject.h> - -class TestTrash : public QObject -{ - Q_OBJECT - -public: - TestTrash() {} - void setup(); - void cleanTrash(); - void runAll(); - - // tests - - void urlTestFile(); - void urlTestDirectory(); - void urlTestSubDirectory(); - - void trashFileFromHome(); - void trashPercentFileFromHome(); - void trashUtf8FileFromHome(); - void trashUmlautFileFromHome(); - void testTrashNotEmpty(); - void trashFileFromOther(); - void trashFileIntoOtherPartition(); - void trashFileOwnedByRoot(); - void trashSymlinkFromHome(); - void trashSymlinkFromOther(); - void trashBrokenSymlinkFromHome(); - void trashDirectoryFromHome(); - void trashReadOnlyDirFromHome(); - void trashDirectoryFromOther(); - void trashDirectoryOwnedByRoot(); - - void tryRenameInsideTrash(); - - void statRoot(); - void statFileInRoot(); - void statDirectoryInRoot(); - void statSymlinkInRoot(); - void statFileInDirectory(); - - void copyFileFromTrash(); - void copyFileInDirectoryFromTrash(); - void copyDirectoryFromTrash(); - void copySymlinkFromTrash(); - - void moveFileFromTrash(); - void moveFileInDirectoryFromTrash(); - void moveDirectoryFromTrash(); - void moveSymlinkFromTrash(); - - void listRootDir(); - void listRecursiveRootDir(); - void listSubDir(); - - void delRootFile(); - void delFileInDirectory(); - void delDirectory(); - - void getFile(); - void restoreFile(); - void restoreFileFromSubDir(); - void restoreFileToDeletedDirectory(); - - void emptyTrash(); - -private slots: - void slotEntries( TDEIO::Job*, const TDEIO::UDSEntryList& ); - -private: - void trashFile( const TQString& origFilePath, const TQString& fileId ); - void trashSymlink( const TQString& origFilePath, const TQString& fileName, bool broken ); - void trashDirectory( const TQString& origPath, const TQString& fileName ); - void copyFromTrash( const TQString& fileId, const TQString& destPath, const TQString& relativePath = TQString::null ); - void moveFromTrash( const TQString& fileId, const TQString& destPath, const TQString& relativePath = TQString::null ); - - TQString homeTmpDir() const; - TQString otherTmpDir() const; - TQString utf8FileName() const; - TQString umlautFileName() const; - TQString readOnlyDirPath() const; - - TQString m_trashDir; - - TQString m_otherPartitionTopDir; - TQString m_otherPartitionTrashDir; - bool m_tmpIsWritablePartition; - int m_tmpTrashId; - int m_otherPartitionId; - - int m_entryCount; - TQStringList m_listResult; -}; - -#endif diff --git a/kioslave/trash/trash.protocol b/kioslave/trash/trash.protocol deleted file mode 100644 index 8387fdcb7..000000000 --- a/kioslave/trash/trash.protocol +++ /dev/null @@ -1,89 +0,0 @@ -[Protocol] -exec=kio_trash -protocol=trash -input=none -output=filesystem -# AccessDate doesn't make sense. -# OTOH we need deletion date :) -listing=Name,Type,Size,Extra1,Extra2,Date,Access,Owner,Group,Link -reading=true -writing=true -makedir=false -deleting=true -linking=false -moving=true -Icon=trashcan_full -maxInstances=2 -Class=:local -renameFromFile=true -renameToFile=true -copyFromFile=true -copyToFile=true -deleteRecursive=true -fileNameUsedForCopying=Name -#TODO DocPath -ExtraNames=Original Path,Deletion Date -ExtraNames[af]=Oorspronklike gids, Uitvee datum -ExtraNames[ar]=المسار الأصلي ، تاريخ المحو -ExtraNames[be]=Арыгінальнае месцазнаходжанне,Час выдалення -ExtraNames[bg]=Местоположение, дата на изтриване -ExtraNames[bn]=পূর্বতন পাথ, মোছার তারিখ -ExtraNames[bs]=Originalni put,Datum brisanja -ExtraNames[ca]=Camí original,Data d'esborrat -ExtraNames[cs]=Původní cesta,Datum smazání -ExtraNames[csb]=Òriginalnô stegna,Datum remniãcô -ExtraNames[da]=Original sti, sletningsdato -ExtraNames[de]=Ursprünglicher Pfad, Löschzeitpunkt -ExtraNames[el]=Αρχική διαδρομή,Ημερομηνία διαγραφής -ExtraNames[eo]=Originala Vojo,Forigo Dato -ExtraNames[es]=Ruta original,Fecha de borrado -ExtraNames[et]=Algne asukoht,Kustutamisaeg -ExtraNames[eu]=Jatorrizko bideizena, ezabatzeko data -ExtraNames[fa]=مسیر اصلی، تاریخ حذف -ExtraNames[fi]=Alkuperäinen polku, poistopäivä -ExtraNames[fr]=Emplacement d'origine, date de suppression -ExtraNames[fy]=Oarspronklike lokaasje,datum fan wiskjen -ExtraNames[ga]=Bunchonair,Dáta Scriosta -ExtraNames[gl]=Rota Orixinal,Data de Eliminación -ExtraNames[he]=נתיב מקורי, תאריך מחיקה -ExtraNames[hi]=मूल पथ, मिटाने की तिथि -ExtraNames[hr]=Izvorna putanja,Datum brisanja -ExtraNames[hu]=Eredeti elérési út,Törlési dátum -ExtraNames[is]=Upprunaleg slóð,dagsetning á eyðingu -ExtraNames[it]=Percorso originale,ora di eliminazione -ExtraNames[ja]=元のパス,削除日 -ExtraNames[ka]=საწყისი გეზი, წაშლის თარიღი -ExtraNames[kk]=Бұрынғы жолы, Өшірілген кезі -ExtraNames[km]=ផ្លូវលំនាំដើម កាលបរិច្ឆេទលុប -ExtraNames[ko]=원본 경로,삭제 날짜 -ExtraNames[lt]=Originalus kelias,Trynimo data -ExtraNames[lv]=Orģinālais ceļš,Dzēšanas datums -ExtraNames[mk]=Оригинална патека,Датум на бришење -ExtraNames[ms]=Laluan Asli, Tarikh Penghapusan -ExtraNames[nb]=Opprinnelig sti, slettedato -ExtraNames[nds]=Orginaalpadd,Wegdodatum -ExtraNames[ne]=मौलिक मार्ग, मेट्ने मिति -ExtraNames[nl]=Oorspronkelijke locatie,Datum van verwijdering -ExtraNames[nn]=Opprinneleg stig, slettedato -ExtraNames[pa]=ਅਸਲੀ ਮਾਰਗ,ਹਟਾਉਣ ਮਿਤੀ -ExtraNames[pl]=Ścieżka oryginalna,Data usunięcia -ExtraNames[pt]=Localização Original,Data de Remoção -ExtraNames[pt_BR]=Caminho Original,Data da Remoção -ExtraNames[ro]=Calea originală,Data ștergerii -ExtraNames[ru]=Исходный путь, дата удаления -ExtraNames[rw]=Inzira Mwimerere, Itariki y'Ihanagura -ExtraNames[sl]=Prvotna pot,Datum brisanja -ExtraNames[sr]=првобитна путања,датум брисања -ExtraNames[sr@Latn]=prvobitna putanja,datum brisanja -ExtraNames[sv]=Ursprunglig sökväg,Borttagsdatum -ExtraNames[ta]=மூல பாதை,நீக்கப்பட்ட தேதி -ExtraNames[te]=అసలు దారు, తీసివేసిన తేది -ExtraNames[th]=พาธเดิม,วันที่ที่ลบ -ExtraNames[tr]=Orjinal Yol, Silinme Tarihi -ExtraNames[tt]=Çığanaq Yulı,Beterelü Çağı -ExtraNames[uk]=Шлях,Дата вилучення -ExtraNames[vi]=Đường dẫn Trước khi vứt,Ngày Vứt -ExtraNames[wa]=Oridjinå tchmin,Date di disfaçaedje -ExtraNames[zh_CN]=原始路径,删除日期 -ExtraNames[zh_TW]=原始路徑,刪除日期 -ExtraTypes=QString,QDateTime diff --git a/kioslave/trash/trashimpl.cpp b/kioslave/trash/trashimpl.cpp deleted file mode 100644 index 3e109c119..000000000 --- a/kioslave/trash/trashimpl.cpp +++ /dev/null @@ -1,962 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 David Faure <[email protected]> - - 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 "trashimpl.h" -#include <klocale.h> -#include <klargefile.h> -#include <kio/global.h> -#include <kio/renamedlg.h> -#include <kio/job.h> -#include <kdebug.h> -#include <kurl.h> -#include <kdirnotify_stub.h> -#include <kglobal.h> -#include <kstandarddirs.h> -#include <kglobalsettings.h> -#include <kmountpoint.h> -#include <kfileitem.h> -#include <kio/chmodjob.h> - -#include <dcopref.h> - -#include <tqapplication.h> -#include <tqeventloop.h> -#include <tqfile.h> -#include <tqdir.h> - -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/param.h> -#include <fcntl.h> -#include <unistd.h> -#include <dirent.h> -#include <stdlib.h> -#include <errno.h> - -TrashImpl::TrashImpl() : - TQObject(), - m_lastErrorCode( 0 ), - m_initStatus( InitToBeDone ), - m_lastId( 0 ), - m_homeDevice( 0 ), - m_trashDirectoriesScanned( false ), - m_mibEnum( TDEGlobal::locale()->fileEncodingMib() ), - // not using kio_trashrc since KIO uses that one already for kio_trash - // so better have a separate one, for faster parsing by e.g. kmimetype.cpp - m_config( "trashrc" ) -{ - KDE_struct_stat buff; - if ( KDE_lstat( TQFile::encodeName( TQDir::homeDirPath() ), &buff ) == 0 ) { - m_homeDevice = buff.st_dev; - } else { - kdError() << "Should never happen: couldn't stat $HOME " << strerror( errno ) << endl; - } -} - -/** - * Test if a directory exists, create otherwise - * @param _name full path of the directory - * @return errorcode, or 0 if the dir was created or existed already - * Warning, don't use return value like a bool - */ -int TrashImpl::testDir( const TQString &_name ) const -{ - DIR *dp = opendir( TQFile::encodeName(_name) ); - if ( dp == NULL ) - { - TQString name = _name; - if ( name.endsWith( "/" ) ) - name.truncate( name.length() - 1 ); - TQCString path = TQFile::encodeName(name); - - bool ok = ::mkdir( path, S_IRWXU ) == 0; - if ( !ok && errno == EEXIST ) { -#if 0 // this would require to use SlaveBase's method to ask the question - //int ret = KMessageBox::warningYesNo( 0, i18n("%1 is a file, but TDE needs it to be a directory. Move it to %2.orig and create directory?").arg(name).arg(name) ); - //if ( ret == KMessageBox::Yes ) { -#endif - if ( ::rename( path, path + ".orig" ) == 0 ) { - ok = ::mkdir( path, S_IRWXU ) == 0; - } else { // foo.orig existed already. How likely is that? - ok = false; - } - if ( !ok ) { - return TDEIO::ERR_DIR_ALREADY_EXIST; - } -#if 0 - //} else { - // return 0; - //} -#endif - } - if ( !ok ) - { - //KMessageBox::sorry( 0, i18n( "Couldn't create directory %1. Check for permissions." ).arg( name ) ); - kdWarning() << "could not create " << name << endl; - return TDEIO::ERR_COULD_NOT_MKDIR; - } else { - kdDebug() << name << " created." << endl; - } - } - else // exists already - { - closedir( dp ); - } - return 0; // success -} - -bool TrashImpl::init() -{ - if ( m_initStatus == InitOK ) - return true; - if ( m_initStatus == InitError ) - return false; - - // Check the trash directory and its info and files subdirs - // see also kdesktop/init.cc for first time initialization - m_initStatus = InitError; - // $XDG_DATA_HOME/Trash, i.e. ~/.local/share/Trash by default. - const TQString xdgDataDir = TDEGlobal::dirs()->localxdgdatadir(); - if ( !KStandardDirs::makeDir( xdgDataDir, 0700 ) ) { - kdWarning() << "failed to create " << xdgDataDir << endl; - return false; - } - - const TQString trashDir = xdgDataDir + "Trash"; - int err; - if ( ( err = testDir( trashDir ) ) ) { - error( err, trashDir ); - return false; - } - if ( ( err = testDir( trashDir + "/info" ) ) ) { - error( err, trashDir + "/info" ); - return false; - } - if ( ( err = testDir( trashDir + "/files" ) ) ) { - error( err, trashDir + "/files" ); - return false; - } - m_trashDirectories.insert( 0, trashDir ); - m_initStatus = InitOK; - kdDebug() << k_funcinfo << "initialization OK, home trash dir: " << trashDir << endl; - return true; -} - -void TrashImpl::migrateOldTrash() -{ - kdDebug() << k_funcinfo << endl; - const TQString oldTrashDir = TDEGlobalSettings::trashPath(); - const TQStrList entries = listDir( oldTrashDir ); - bool allOK = true; - TQStrListIterator entryIt( entries ); - for (; entryIt.current(); ++entryIt) { - TQString srcPath = TQFile::decodeName( *entryIt ); - if ( srcPath == "." || srcPath == ".." || srcPath == ".directory" ) - continue; - srcPath.prepend( oldTrashDir ); // make absolute - int trashId; - TQString fileId; - if ( !createInfo( srcPath, trashId, fileId ) ) { - kdWarning() << "Trash migration: failed to create info for " << srcPath << endl; - allOK = false; - } else { - bool ok = moveToTrash( srcPath, trashId, fileId ); - if ( !ok ) { - (void)deleteInfo( trashId, fileId ); - kdWarning() << "Trash migration: failed to create info for " << srcPath << endl; - allOK = false; - } else { - kdDebug() << "Trash migration: moved " << srcPath << endl; - } - } - } - if ( allOK ) { - // We need to remove the old one, otherwise the desktop will have two trashcans... - kdDebug() << "Trash migration: all OK, removing old trash directory" << endl; - synchronousDel( oldTrashDir, false, true ); - } -} - -bool TrashImpl::createInfo( const TQString& origPath, int& trashId, TQString& fileId ) -{ - kdDebug() << k_funcinfo << origPath << endl; - // Check source - const TQCString origPath_c( TQFile::encodeName( origPath ) ); - KDE_struct_stat buff_src; - if ( KDE_lstat( origPath_c.data(), &buff_src ) == -1 ) { - if ( errno == EACCES ) - error( TDEIO::ERR_ACCESS_DENIED, origPath ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, origPath ); - return false; - } - - // Choose destination trash - trashId = findTrashDirectory( origPath ); - if ( trashId < 0 ) { - kdWarning() << "OUCH - internal error, TrashImpl::findTrashDirectory returned " << trashId << endl; - return false; // ### error() needed? - } - kdDebug() << k_funcinfo << "trashing to " << trashId << endl; - - // Grab original filename - KURL url; - url.setPath( origPath ); - const TQString origFileName = url.fileName(); - - // Make destination file in info/ - url.setPath( infoPath( trashId, origFileName ) ); // we first try with origFileName - KURL baseDirectory; - baseDirectory.setPath( url.directory() ); - // Here we need to use O_EXCL to avoid race conditions with other kioslave processes - int fd = 0; - do { - kdDebug() << k_funcinfo << "trying to create " << url.path() << endl; - fd = ::open( TQFile::encodeName( url.path() ), O_WRONLY | O_CREAT | O_EXCL, 0600 ); - if ( fd < 0 ) { - if ( errno == EEXIST ) { - url.setFileName( TDEIO::RenameDlg::suggestName( baseDirectory, url.fileName() ) ); - // and try again on the next iteration - } else { - error( TDEIO::ERR_COULD_NOT_WRITE, url.path() ); - return false; - } - } - } while ( fd < 0 ); - const TQString infoPath = url.path(); - fileId = url.fileName(); - Q_ASSERT( fileId.endsWith( ".trashinfo" ) ); - fileId.truncate( fileId.length() - 10 ); // remove .trashinfo from fileId - - FILE* file = ::fdopen( fd, "w" ); - if ( !file ) { // can't see how this would happen - error( TDEIO::ERR_COULD_NOT_WRITE, infoPath ); - return false; - } - - // Contents of the info file. We could use KSimpleConfig, but that would - // mean closing and reopening fd, i.e. opening a race condition... - TQCString info = "[Trash Info]\n"; - info += "Path="; - // Escape filenames according to the way they are encoded on the filesystem - // All this to basically get back to the raw 8-bit representation of the filename... - if ( trashId == 0 ) // home trash: absolute path - info += KURL::encode_string( origPath, m_mibEnum ).latin1(); - else - info += KURL::encode_string( makeRelativePath( topDirectoryPath( trashId ), origPath ), m_mibEnum ).latin1(); - info += "\n"; - info += "DeletionDate="; - info += TQDateTime::currentDateTime().toString( Qt::ISODate ).latin1(); - info += "\n"; - size_t sz = info.size() - 1; // avoid trailing 0 from QCString - - size_t written = ::fwrite(info.data(), 1, sz, file); - if ( written != sz ) { - ::fclose( file ); - TQFile::remove( infoPath ); - error( TDEIO::ERR_DISK_FULL, infoPath ); - return false; - } - - ::fclose( file ); - - kdDebug() << k_funcinfo << "info file created in trashId=" << trashId << " : " << fileId << endl; - return true; -} - -TQString TrashImpl::makeRelativePath( const TQString& topdir, const TQString& path ) -{ - const TQString realPath = KStandardDirs::realFilePath( path ); - // topdir ends with '/' - if ( realPath.startsWith( topdir ) ) { - const TQString rel = realPath.mid( topdir.length() ); - Q_ASSERT( rel[0] != '/' ); - return rel; - } else { // shouldn't happen... - kdWarning() << "Couldn't make relative path for " << realPath << " (" << path << "), with topdir=" << topdir << endl; - return realPath; - } -} - -TQString TrashImpl::infoPath( int trashId, const TQString& fileId ) const -{ - TQString trashPath = trashDirectoryPath( trashId ); - trashPath += "/info/"; - trashPath += fileId; - trashPath += ".trashinfo"; - return trashPath; -} - -TQString TrashImpl::filesPath( int trashId, const TQString& fileId ) const -{ - TQString trashPath = trashDirectoryPath( trashId ); - trashPath += "/files/"; - trashPath += fileId; - return trashPath; -} - -bool TrashImpl::deleteInfo( int trashId, const TQString& fileId ) -{ - bool ok = TQFile::remove( infoPath( trashId, fileId ) ); - if ( ok ) - fileRemoved(); - return ok; -} - -bool TrashImpl::moveToTrash( const TQString& origPath, int trashId, const TQString& fileId ) -{ - kdDebug() << k_funcinfo << endl; - const TQString dest = filesPath( trashId, fileId ); - if ( !move( origPath, dest ) ) { - // Maybe the move failed due to no permissions to delete source. - // In that case, delete dest to keep things consistent, since KIO doesn't do it. - if ( TQFileInfo( dest ).isFile() ) - TQFile::remove( dest ); - else - synchronousDel( dest, false, true ); - return false; - } - fileAdded(); - return true; -} - -bool TrashImpl::moveFromTrash( const TQString& dest, int trashId, const TQString& fileId, const TQString& relativePath ) -{ - TQString src = filesPath( trashId, fileId ); - if ( !relativePath.isEmpty() ) { - src += '/'; - src += relativePath; - } - if ( !move( src, dest ) ) - return false; - return true; -} - -bool TrashImpl::move( const TQString& src, const TQString& dest ) -{ - if ( directRename( src, dest ) ) { - // This notification is done by TDEIO::moveAs when using the code below - // But if we do a direct rename we need to do the notification ourselves - KDirNotify_stub allDirNotify( "*", "KDirNotify*" ); - KURL urlDest; urlDest.setPath( dest ); - urlDest.setPath( urlDest.directory() ); - allDirNotify.FilesAdded( urlDest ); - return true; - } - if ( m_lastErrorCode != TDEIO::ERR_UNSUPPORTED_ACTION ) - return false; - - KURL urlSrc, urlDest; - urlSrc.setPath( src ); - urlDest.setPath( dest ); - kdDebug() << k_funcinfo << urlSrc << " -> " << urlDest << endl; - TDEIO::CopyJob* job = TDEIO::moveAs( urlSrc, urlDest, false ); -#ifdef KIO_COPYJOB_HAS_SETINTERACTIVE - job->setInteractive( false ); -#endif - connect( job, TQT_SIGNAL( result(TDEIO::Job *) ), - this, TQT_SLOT( jobFinished(TDEIO::Job *) ) ); - tqApp->eventLoop()->enterLoop(); - - return m_lastErrorCode == 0; -} - -void TrashImpl::jobFinished(TDEIO::Job* job) -{ - kdDebug() << k_funcinfo << " error=" << job->error() << endl; - error( job->error(), job->errorText() ); - tqApp->eventLoop()->exitLoop(); -} - -bool TrashImpl::copyToTrash( const TQString& origPath, int trashId, const TQString& fileId ) -{ - kdDebug() << k_funcinfo << endl; - const TQString dest = filesPath( trashId, fileId ); - if ( !copy( origPath, dest ) ) - return false; - fileAdded(); - return true; -} - -bool TrashImpl::copyFromTrash( const TQString& dest, int trashId, const TQString& fileId, const TQString& relativePath ) -{ - TQString src = filesPath( trashId, fileId ); - if ( !relativePath.isEmpty() ) { - src += '/'; - src += relativePath; - } - return copy( src, dest ); -} - -bool TrashImpl::copy( const TQString& src, const TQString& dest ) -{ - // kio_file's copy() method is quite complex (in order to be fast), let's just call it... - m_lastErrorCode = 0; - KURL urlSrc; - urlSrc.setPath( src ); - KURL urlDest; - urlDest.setPath( dest ); - kdDebug() << k_funcinfo << "copying " << src << " to " << dest << endl; - TDEIO::CopyJob* job = TDEIO::copyAs( urlSrc, urlDest, false ); -#ifdef KIO_COPYJOB_HAS_SETINTERACTIVE - job->setInteractive( false ); -#endif - connect( job, TQT_SIGNAL( result( TDEIO::Job* ) ), - this, TQT_SLOT( jobFinished( TDEIO::Job* ) ) ); - tqApp->eventLoop()->enterLoop(); - - return m_lastErrorCode == 0; -} - -bool TrashImpl::directRename( const TQString& src, const TQString& dest ) -{ - kdDebug() << k_funcinfo << src << " -> " << dest << endl; - if ( ::rename( TQFile::encodeName( src ), TQFile::encodeName( dest ) ) != 0 ) { - if (errno == EXDEV) { - error( TDEIO::ERR_UNSUPPORTED_ACTION, TQString::fromLatin1("rename") ); - } else { - if (( errno == EACCES ) || (errno == EPERM)) { - error( TDEIO::ERR_ACCESS_DENIED, dest ); - } else if (errno == EROFS) { // The file is on a read-only filesystem - error( TDEIO::ERR_CANNOT_DELETE, src ); - } else { - error( TDEIO::ERR_CANNOT_RENAME, src ); - } - } - return false; - } - return true; -} - -#if 0 -bool TrashImpl::mkdir( int trashId, const TQString& fileId, int permissions ) -{ - const TQString path = filesPath( trashId, fileId ); - if ( ::mkdir( TQFile::encodeName( path ), permissions ) != 0 ) { - if ( errno == EACCES ) { - error( TDEIO::ERR_ACCESS_DENIED, path ); - return false; - } else if ( errno == ENOSPC ) { - error( TDEIO::ERR_DISK_FULL, path ); - return false; - } else { - error( TDEIO::ERR_COULD_NOT_MKDIR, path ); - return false; - } - } else { - if ( permissions != -1 ) - ::chmod( TQFile::encodeName( path ), permissions ); - } - return true; -} -#endif - -bool TrashImpl::del( int trashId, const TQString& fileId ) -{ - TQString info = infoPath(trashId, fileId); - TQString file = filesPath(trashId, fileId); - - TQCString info_c = TQFile::encodeName(info); - - KDE_struct_stat buff; - if ( KDE_lstat( info_c.data(), &buff ) == -1 ) { - if ( errno == EACCES ) - error( TDEIO::ERR_ACCESS_DENIED, file ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, file ); - return false; - } - - if ( !synchronousDel( file, true, TQFileInfo(file).isDir() ) ) - return false; - - TQFile::remove( info ); - fileRemoved(); - return true; -} - -bool TrashImpl::synchronousDel( const TQString& path, bool setLastErrorCode, bool isDir ) -{ - const int oldErrorCode = m_lastErrorCode; - const TQString oldErrorMsg = m_lastErrorMessage; - KURL url; - url.setPath( path ); - - // First ensure that all dirs have u+w permissions, - // otherwise we won't be able to delete files in them (#130780). - if ( isDir ) { - kdDebug() << k_funcinfo << "chmod'ing " << url << endl; - KFileItem fileItem( url, "inode/directory", KFileItem::Unknown ); - KFileItemList fileItemList; - fileItemList.append( &fileItem ); - TDEIO::ChmodJob* chmodJob = TDEIO::chmod( fileItemList, 0200, 0200, TQString::null, TQString::null, true /*recursive*/, false /*showProgressInfo*/ ); - connect( chmodJob, TQT_SIGNAL( result(TDEIO::Job *) ), - this, TQT_SLOT( jobFinished(TDEIO::Job *) ) ); - tqApp->eventLoop()->enterLoop(); - } - - kdDebug() << k_funcinfo << "deleting " << url << endl; - TDEIO::DeleteJob *job = TDEIO::del( url, false, false ); - connect( job, TQT_SIGNAL( result(TDEIO::Job *) ), - this, TQT_SLOT( jobFinished(TDEIO::Job *) ) ); - tqApp->eventLoop()->enterLoop(); - bool ok = m_lastErrorCode == 0; - if ( !setLastErrorCode ) { - m_lastErrorCode = oldErrorCode; - m_lastErrorMessage = oldErrorMsg; - } - return ok; -} - -bool TrashImpl::emptyTrash() -{ - kdDebug() << k_funcinfo << endl; - // The naive implementation "delete info and files in every trash directory" - // breaks when deleted directories contain files owned by other users. - // We need to ensure that the .trashinfo file is only removed when the - // corresponding files could indeed be removed. - - const TrashedFileInfoList fileInfoList = list(); - - TrashedFileInfoList::const_iterator it = fileInfoList.begin(); - const TrashedFileInfoList::const_iterator end = fileInfoList.end(); - for ( ; it != end ; ++it ) { - const TrashedFileInfo& info = *it; - const TQString filesPath = info.physicalPath; - if ( synchronousDel( filesPath, true, true ) ) { - TQFile::remove( infoPath( info.trashId, info.fileId ) ); - } // else error code is set - } - fileRemoved(); - - return m_lastErrorCode == 0; -} - -TrashImpl::TrashedFileInfoList TrashImpl::list() -{ - // Here we scan for trash directories unconditionally. This allows - // noticing plugged-in [e.g. removeable] devices, or new mounts etc. - scanTrashDirectories(); - - TrashedFileInfoList lst; - // For each known trash directory... - TrashDirMap::const_iterator it = m_trashDirectories.begin(); - for ( ; it != m_trashDirectories.end() ; ++it ) { - const int trashId = it.key(); - TQString infoPath = it.data(); - infoPath += "/info"; - // Code taken from kio_file - TQStrList entryNames = listDir( infoPath ); - //char path_buffer[PATH_MAX]; - //getcwd(path_buffer, PATH_MAX - 1); - //if ( chdir( infoPathEnc ) ) - // continue; - TQStrListIterator entryIt( entryNames ); - for (; entryIt.current(); ++entryIt) { - TQString fileName = TQFile::decodeName( *entryIt ); - if ( fileName == "." || fileName == ".." ) - continue; - if ( !fileName.endsWith( ".trashinfo" ) ) { - kdWarning() << "Invalid info file found in " << infoPath << " : " << fileName << endl; - continue; - } - fileName.truncate( fileName.length() - 10 ); - - TrashedFileInfo info; - if ( infoForFile( trashId, fileName, info ) ) - lst << info; - } - } - return lst; -} - -// Returns the entries in a given directory - including "." and ".." -TQStrList TrashImpl::listDir( const TQString& physicalPath ) -{ - const TQCString physicalPathEnc = TQFile::encodeName( physicalPath ); - kdDebug() << k_funcinfo << "listing " << physicalPath << endl; - TQStrList entryNames; - DIR *dp = opendir( physicalPathEnc ); - if ( dp == 0 ) - return entryNames; - KDE_struct_dirent *ep; - while ( ( ep = KDE_readdir( dp ) ) != 0L ) - entryNames.append( ep->d_name ); - closedir( dp ); - return entryNames; -} - -bool TrashImpl::infoForFile( int trashId, const TQString& fileId, TrashedFileInfo& info ) -{ - kdDebug() << k_funcinfo << trashId << " " << fileId << endl; - info.trashId = trashId; // easy :) - info.fileId = fileId; // equally easy - info.physicalPath = filesPath( trashId, fileId ); - return readInfoFile( infoPath( trashId, fileId ), info, trashId ); -} - -bool TrashImpl::readInfoFile( const TQString& infoPath, TrashedFileInfo& info, int trashId ) -{ - KSimpleConfig cfg( infoPath, true ); - if ( !cfg.hasGroup( "Trash Info" ) ) { - error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, infoPath ); - return false; - } - cfg.setGroup( "Trash Info" ); - info.origPath = KURL::decode_string( cfg.readEntry( "Path" ), m_mibEnum ); - if ( info.origPath.isEmpty() ) - return false; // path is mandatory... - if ( trashId == 0 ) - Q_ASSERT( info.origPath[0] == '/' ); - else { - const TQString topdir = topDirectoryPath( trashId ); // includes trailing slash - info.origPath.prepend( topdir ); - } - TQString line = cfg.readEntry( "DeletionDate" ); - if ( !line.isEmpty() ) { - info.deletionDate = TQT_TQDATETIME_OBJECT(TQDateTime::fromString( line, Qt::ISODate )); - } - return true; -} - -TQString TrashImpl::physicalPath( int trashId, const TQString& fileId, const TQString& relativePath ) -{ - TQString filePath = filesPath( trashId, fileId ); - if ( !relativePath.isEmpty() ) { - filePath += "/"; - filePath += relativePath; - } - return filePath; -} - -void TrashImpl::error( int e, const TQString& s ) -{ - if ( e ) - kdDebug() << k_funcinfo << e << " " << s << endl; - m_lastErrorCode = e; - m_lastErrorMessage = s; -} - -bool TrashImpl::isEmpty() const -{ - // For each known trash directory... - if ( !m_trashDirectoriesScanned ) - scanTrashDirectories(); - TrashDirMap::const_iterator it = m_trashDirectories.begin(); - for ( ; it != m_trashDirectories.end() ; ++it ) { - TQString infoPath = it.data(); - infoPath += "/info"; - - DIR *dp = opendir( TQFile::encodeName( infoPath ) ); - if ( dp ) - { - struct dirent *ep; - ep = readdir( dp ); - ep = readdir( dp ); // ignore '.' and '..' dirent - ep = readdir( dp ); // look for third file - closedir( dp ); - if ( ep != 0 ) { - //kdDebug() << ep->d_name << " in " << infoPath << " -> not empty" << endl; - return false; // not empty - } - } - } - return true; -} - -void TrashImpl::fileAdded() -{ - m_config.setGroup( "Status" ); - if ( m_config.readBoolEntry( "Empty", true ) == true ) { - m_config.writeEntry( "Empty", false ); - m_config.sync(); - } - // The apps showing the trash (e.g. kdesktop) will be notified - // of this change when KDirNotify::FilesAdded("trash:/") is emitted, - // which will be done by the job soon after this. -} - -void TrashImpl::fileRemoved() -{ - if ( isEmpty() ) { - m_config.setGroup( "Status" ); - m_config.writeEntry( "Empty", true ); - m_config.sync(); - } - // The apps showing the trash (e.g. kdesktop) will be notified - // of this change when KDirNotify::FilesRemoved(...) is emitted, - // which will be done by the job soon after this. -} - -int TrashImpl::findTrashDirectory( const TQString& origPath ) -{ - kdDebug() << k_funcinfo << origPath << endl; - // First check if same device as $HOME, then we use the home trash right away. - KDE_struct_stat buff; - if ( KDE_lstat( TQFile::encodeName( origPath ), &buff ) == 0 - && buff.st_dev == m_homeDevice ) - return 0; - - TQString mountPoint = TDEIO::findPathMountPoint( origPath ); - const TQString trashDir = trashForMountPoint( mountPoint, true ); - kdDebug() << "mountPoint=" << mountPoint << " trashDir=" << trashDir << endl; - if ( trashDir.isEmpty() ) - return 0; // no trash available on partition - int id = idForTrashDirectory( trashDir ); - if ( id > -1 ) { - kdDebug() << " known with id " << id << endl; - return id; - } - // new trash dir found, register it - // but we need stability in the trash IDs, so that restoring or asking - // for properties works even kio_trash gets killed because idle. -#if 0 - kdDebug() << k_funcinfo << "found " << trashDir << endl; - m_trashDirectories.insert( ++m_lastId, trashDir ); - if ( !mountPoint.endsWith( "/" ) ) - mountPoint += '/'; - m_topDirectories.insert( m_lastId, mountPoint ); - return m_lastId; -#endif - scanTrashDirectories(); - return idForTrashDirectory( trashDir ); -} - -void TrashImpl::scanTrashDirectories() const -{ - const KMountPoint::List lst = KMountPoint::currentMountPoints(); - for ( KMountPoint::List::ConstIterator it = lst.begin() ; it != lst.end() ; ++it ) { - const TQCString str = (*it)->mountType().latin1(); - // Skip pseudo-filesystems, there's no chance we'll find a .Trash on them :) - // ## Maybe we should also skip readonly filesystems - if ( str != "proc" && str != "devfs" && str != "usbdevfs" && - str != "sysfs" && str != "devpts" && str != "subfs" /* #96259 */ && - str != "autofs" /* #101116 */ ) { - TQString topdir = (*it)->mountPoint(); - TQString trashDir = trashForMountPoint( topdir, false ); - if ( !trashDir.isEmpty() ) { - // OK, trashDir is a valid trash directory. Ensure it's registered. - int trashId = idForTrashDirectory( trashDir ); - if ( trashId == -1 ) { - // new trash dir found, register it - m_trashDirectories.insert( ++m_lastId, trashDir ); - kdDebug() << k_funcinfo << "found " << trashDir << " gave it id " << m_lastId << endl; - if ( !topdir.endsWith( "/" ) ) - topdir += '/'; - m_topDirectories.insert( m_lastId, topdir ); - } - } - } - } - m_trashDirectoriesScanned = true; -} - -TrashImpl::TrashDirMap TrashImpl::trashDirectories() const -{ - if ( !m_trashDirectoriesScanned ) - scanTrashDirectories(); - return m_trashDirectories; -} - -TrashImpl::TrashDirMap TrashImpl::topDirectories() const -{ - if ( !m_trashDirectoriesScanned ) - scanTrashDirectories(); - return m_topDirectories; -} - -TQString TrashImpl::trashForMountPoint( const TQString& topdir, bool createIfNeeded ) const -{ - // (1) Administrator-created $topdir/.Trash directory - - const TQString rootTrashDir = topdir + "/.Trash"; - const TQCString rootTrashDir_c = TQFile::encodeName( rootTrashDir ); - // Can't use TQFileInfo here since we need to test for the sticky bit - uid_t uid = getuid(); - KDE_struct_stat buff; - const uint requiredBits = S_ISVTX; // Sticky bit required - if ( KDE_lstat( rootTrashDir_c, &buff ) == 0 ) { - if ( (S_ISDIR(buff.st_mode)) // must be a dir - && (!S_ISLNK(buff.st_mode)) // not a symlink - && ((buff.st_mode & requiredBits) == requiredBits) - && (::access(rootTrashDir_c, W_OK)) - ) { - const TQString trashDir = rootTrashDir + "/" + TQString::number( uid ); - const TQCString trashDir_c = TQFile::encodeName( trashDir ); - if ( KDE_lstat( trashDir_c, &buff ) == 0 ) { - if ( (buff.st_uid == uid) // must be owned by user - && (S_ISDIR(buff.st_mode)) // must be a dir - && (!S_ISLNK(buff.st_mode)) // not a symlink - && (buff.st_mode & 0777) == 0700 ) { // rwx for user - return trashDir; - } - kdDebug() << "Directory " << trashDir << " exists but didn't pass the security checks, can't use it" << endl; - } - else if ( createIfNeeded && initTrashDirectory( trashDir_c ) ) { - return trashDir; - } - } else { - kdDebug() << "Root trash dir " << rootTrashDir << " exists but didn't pass the security checks, can't use it" << endl; - } - } - - // (2) $topdir/.Trash-$uid - const TQString trashDir = topdir + "/.Trash-" + TQString::number( uid ); - const TQCString trashDir_c = TQFile::encodeName( trashDir ); - if ( KDE_lstat( trashDir_c, &buff ) == 0 ) - { - if ( (buff.st_uid == uid) // must be owned by user - && (S_ISDIR(buff.st_mode)) // must be a dir - && (!S_ISLNK(buff.st_mode)) // not a symlink - && ((buff.st_mode & 0777) == 0700) ) { // rwx for user, ------ for group and others - - if ( checkTrashSubdirs( trashDir_c ) ) - return trashDir; - } - kdDebug() << "Directory " << trashDir << " exists but didn't pass the security checks, can't use it" << endl; - // Exists, but not useable - return TQString::null; - } - if ( createIfNeeded && initTrashDirectory( trashDir_c ) ) { - return trashDir; - } - return TQString::null; -} - -int TrashImpl::idForTrashDirectory( const TQString& trashDir ) const -{ - // If this is too slow we can always use a reverse map... - TrashDirMap::ConstIterator it = m_trashDirectories.begin(); - for ( ; it != m_trashDirectories.end() ; ++it ) { - if ( it.data() == trashDir ) { - return it.key(); - } - } - return -1; -} - -bool TrashImpl::initTrashDirectory( const TQCString& trashDir_c ) const -{ - if ( ::mkdir( trashDir_c, 0700 ) != 0 ) - return false; - // This trash dir will be useable only if the directory is owned by user. - // In theory this is the case, but not on e.g. USB keys... - uid_t uid = getuid(); - KDE_struct_stat buff; - if ( KDE_lstat( trashDir_c, &buff ) != 0 ) - return false; // huh? - if ( (buff.st_uid == uid) // must be owned by user - && ((buff.st_mode & 0777) == 0700) ) { // rwx for user, --- for group and others - - return checkTrashSubdirs( trashDir_c ); - - } else { - kdDebug() << trashDir_c << " just created, by it doesn't have the right permissions, must be a FAT partition. Removing it again." << endl; - // Not good, e.g. USB key. Delete again. - // I'm paranoid, it would be better to find a solution that allows - // to trash directly onto the USB key, but I don't see how that would - // pass the security checks. It would also make the USB key appears as - // empty when it's in fact full... - ::rmdir( trashDir_c ); - return false; - } - return true; -} - -bool TrashImpl::checkTrashSubdirs( const TQCString& trashDir_c ) const -{ - // testDir currently works with a TQString - ## optimize - TQString trashDir = TQFile::decodeName( trashDir_c ); - const TQString info = trashDir + "/info"; - if ( testDir( info ) != 0 ) - return false; - const TQString files = trashDir + "/files"; - if ( testDir( files ) != 0 ) - return false; - return true; -} - -TQString TrashImpl::trashDirectoryPath( int trashId ) const -{ - // Never scanned for trash dirs? (This can happen after killing kio_trash - // and reusing a directory listing from the earlier instance.) - if ( !m_trashDirectoriesScanned ) - scanTrashDirectories(); - Q_ASSERT( m_trashDirectories.contains( trashId ) ); - return m_trashDirectories[trashId]; -} - -TQString TrashImpl::topDirectoryPath( int trashId ) const -{ - if ( !m_trashDirectoriesScanned ) - scanTrashDirectories(); - assert( trashId != 0 ); - Q_ASSERT( m_topDirectories.contains( trashId ) ); - return m_topDirectories[trashId]; -} - -// Helper method. Creates a URL with the format trash:/trashid-fileid or -// trash:/trashid-fileid/relativePath/To/File for a file inside a trashed directory. -KURL TrashImpl::makeURL( int trashId, const TQString& fileId, const TQString& relativePath ) -{ - KURL url; - url.setProtocol( "trash" ); - TQString path = "/"; - path += TQString::number( trashId ); - path += '-'; - path += fileId; - if ( !relativePath.isEmpty() ) { - path += '/'; - path += relativePath; - } - url.setPath( path ); - return url; -} - -// Helper method. Parses a trash URL with the URL scheme defined in makeURL. -// The trash:/ URL itself isn't parsed here, must be caught by the caller before hand. -bool TrashImpl::parseURL( const KURL& url, int& trashId, TQString& fileId, TQString& relativePath ) -{ - if ( url.protocol() != "trash" ) - return false; - const TQString path = url.path(); - int start = 0; - if ( path[0] == '/' ) // always true I hope - start = 1; - int slashPos = path.find( '-', 0 ); // don't match leading slash - if ( slashPos <= 0 ) - return false; - bool ok = false; - trashId = path.mid( start, slashPos - start ).toInt( &ok ); - Q_ASSERT( ok ); - if ( !ok ) - return false; - start = slashPos + 1; - slashPos = path.find( '/', start ); - if ( slashPos <= 0 ) { - fileId = path.mid( start ); - relativePath = TQString::null; - return true; - } - fileId = path.mid( start, slashPos - start ); - relativePath = path.mid( slashPos + 1 ); - return true; -} - -#include "trashimpl.moc" diff --git a/kioslave/trash/trashimpl.h b/kioslave/trash/trashimpl.h deleted file mode 100644 index 366f8a869..000000000 --- a/kioslave/trash/trashimpl.h +++ /dev/null @@ -1,182 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2004 David Faure <[email protected]> - - 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. -*/ - -#ifndef TRASHIMPL_H -#define TRASHIMPL_H - -#include <kio/jobclasses.h> -#include <ksimpleconfig.h> - -#include <tqstring.h> -#include <tqdatetime.h> -#include <tqmap.h> -#include <tqvaluelist.h> -#include <tqstrlist.h> -#include <assert.h> - -/** - * Implementation of all low-level operations done by kio_trash - * The structure of the trash directory follows the freedesktop.org standard <TODO URL> - */ -class TrashImpl : public TQObject -{ - Q_OBJECT -public: - TrashImpl(); - - /// Check the "home" trash directory - /// This MUST be called before doing anything else - bool init(); - - /// Create info for a file to be trashed - /// Returns trashId and fileId - /// The caller is then responsible for actually trashing the file - bool createInfo( const TQString& origPath, int& trashId, TQString& fileId ); - - /// Delete info file for a file to be trashed - /// Usually used for undoing what createInfo did if trashing failed - bool deleteInfo( int trashId, const TQString& fileId ); - - /// Moving a file or directory into the trash. The ids come from createInfo. - bool moveToTrash( const TQString& origPath, int trashId, const TQString& fileId ); - - /// Moving a file or directory out of the trash. The ids come from createInfo. - bool moveFromTrash( const TQString& origPath, int trashId, const TQString& fileId, const TQString& relativePath ); - - /// Copying a file or directory into the trash. The ids come from createInfo. - bool copyToTrash( const TQString& origPath, int trashId, const TQString& fileId ); - - /// Copying a file or directory out of the trash. The ids come from createInfo. - bool copyFromTrash( const TQString& origPath, int trashId, const TQString& fileId, const TQString& relativePath ); - - /// Create a top-level trashed directory - //bool mkdir( int trashId, const TQString& fileId, int permissions ); - - /// Get rid of a trashed file - bool del( int trashId, const TQString& fileId ); - - /// Empty trash, i.e. delete all trashed files - bool emptyTrash(); - - /// Return true if the trash is empty - bool isEmpty() const; - - struct TrashedFileInfo { - int trashId; // for the url - TQString fileId; // for the url - TQString physicalPath; // for stat'ing etc. - TQString origPath; // from info file - TQDateTime deletionDate; // from info file - }; - /// List trashed files - typedef TQValueList<TrashedFileInfo> TrashedFileInfoList; - TrashedFileInfoList list(); - - /// Return the info for a given trashed file - bool infoForFile( int trashId, const TQString& fileId, TrashedFileInfo& info ); - - /// Return the physicalPath for a given trashed file - helper method which - /// encapsulates the call to infoForFile. Don't use if you need more info from TrashedFileInfo. - TQString physicalPath( int trashId, const TQString& fileId, const TQString& relativePath ); - - /// Move data from the old trash system to the new one - void migrateOldTrash(); - - /// KIO error code - int lastErrorCode() const { return m_lastErrorCode; } - TQString lastErrorMessage() const { return m_lastErrorMessage; } - - TQStrList listDir( const TQString& physicalPath ); - - static KURL makeURL( int trashId, const TQString& fileId, const TQString& relativePath ); - static bool parseURL( const KURL& url, int& trashId, TQString& fileId, TQString& relativePath ); - - typedef TQMap<int, TQString> TrashDirMap; - /// @internal This method is for TestTrash only. Home trash is included (id 0). - TrashDirMap trashDirectories() const; - /// @internal This method is for TestTrash only. No entry with id 0. - TrashDirMap topDirectories() const; - -private: - /// Helper method. Moves a file or directory using the appropriate method. - bool move( const TQString& src, const TQString& dest ); - bool copy( const TQString& src, const TQString& dest ); - /// Helper method. Tries to call ::rename(src,dest) and does error handling. - bool directRename( const TQString& src, const TQString& dest ); - - void fileAdded(); - void fileRemoved(); - - // Warning, returns error code, not a bool - int testDir( const TQString& name ) const; - void error( int e, const TQString& s ); - - bool readInfoFile( const TQString& infoPath, TrashedFileInfo& info, int trashId ); - - TQString infoPath( int trashId, const TQString& fileId ) const; - TQString filesPath( int trashId, const TQString& fileId ) const; - - /// Find the trash dir to use for a given file to delete, based on original path - int findTrashDirectory( const TQString& origPath ); - - TQString trashDirectoryPath( int trashId ) const; - TQString topDirectoryPath( int trashId ) const; - - bool synchronousDel( const TQString& path, bool setLastErrorCode, bool isDir ); - - void scanTrashDirectories() const; - - int idForTrashDirectory( const TQString& trashDir ) const; - bool initTrashDirectory( const TQCString& trashDir_c ) const; - bool checkTrashSubdirs( const TQCString& trashDir_c ) const; - TQString trashForMountPoint( const TQString& topdir, bool createIfNeeded ) const; - static TQString makeRelativePath( const TQString& topdir, const TQString& path ); - -private slots: - void jobFinished(TDEIO::Job *job); - -private: - /// Last error code stored in class to simplify API. - /// Note that this means almost no method can be const. - int m_lastErrorCode; - TQString m_lastErrorMessage; - - enum { InitToBeDone, InitOK, InitError } m_initStatus; - - // A "trash directory" is a physical directory on disk, - // e.g. $HOME/.local/share/Trash/$uid or /mnt/foo/.Trash/$uid - // It has an id (number) and a path. - // The home trash has id 0. - mutable TrashDirMap m_trashDirectories; // id -> path of trash directory - mutable TrashDirMap m_topDirectories; // id -> $topdir of partition - mutable int m_lastId; - dev_t m_homeDevice; - mutable bool m_trashDirectoriesScanned; - int m_mibEnum; - - KSimpleConfig m_config; - - // We don't cache any data related to the trashed files. - // Another kioslave could change that behind our feet. - // If we want to start caching data - and avoiding some race conditions -, - // we should turn this class into a kded module and use DCOP to talk to it - // from the kioslave. -}; - -#endif |