summaryrefslogtreecommitdiffstats
path: root/src/app/VFS
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/VFS')
-rw-r--r--src/app/VFS/Makefile.am19
-rw-r--r--src/app/VFS/arc_vfs.cpp866
-rw-r--r--src/app/VFS/arc_vfs.h131
-rw-r--r--src/app/VFS/ftp_vfs.cpp297
-rw-r--r--src/app/VFS/ftp_vfs.h80
-rw-r--r--src/app/VFS/krarchandler.cpp785
-rw-r--r--src/app/VFS/krarchandler.h151
-rw-r--r--src/app/VFS/krdirwatch.cpp124
-rw-r--r--src/app/VFS/krdirwatch.h80
-rw-r--r--src/app/VFS/krpermhandler.cpp355
-rw-r--r--src/app/VFS/krpermhandler.h89
-rw-r--r--src/app/VFS/krquery.cpp653
-rw-r--r--src/app/VFS/krquery.h209
-rw-r--r--src/app/VFS/krvfshandler.cpp71
-rw-r--r--src/app/VFS/krvfshandler.h40
-rw-r--r--src/app/VFS/normal_vfs.cpp437
-rw-r--r--src/app/VFS/normal_vfs.h93
-rw-r--r--src/app/VFS/preservingcopyjob.cpp319
-rw-r--r--src/app/VFS/preservingcopyjob.h85
-rw-r--r--src/app/VFS/temp_vfs.cpp136
-rw-r--r--src/app/VFS/temp_vfs.h60
-rw-r--r--src/app/VFS/vfile.cpp311
-rw-r--r--src/app/VFS/vfile.h167
-rw-r--r--src/app/VFS/vfs.cpp393
-rw-r--r--src/app/VFS/vfs.h187
-rw-r--r--src/app/VFS/virt_vfs.cpp341
-rw-r--r--src/app/VFS/virt_vfs.h77
-rw-r--r--src/app/VFS/virtualcopyjob.cpp316
-rw-r--r--src/app/VFS/virtualcopyjob.h126
29 files changed, 6998 insertions, 0 deletions
diff --git a/src/app/VFS/Makefile.am b/src/app/VFS/Makefile.am
new file mode 100644
index 0000000..63ef663
--- /dev/null
+++ b/src/app/VFS/Makefile.am
@@ -0,0 +1,19 @@
+noinst_LIBRARIES = libVFS.a
+
+INCLUDES = $(all_includes)
+
+libVFS_a_METASOURCES = AUTO
+
+libVFS_a_SOURCES = \
+ krvfshandler.cpp \
+ virt_vfs.cpp \
+ vfs.cpp \
+ vfile.cpp \
+ temp_vfs.cpp \
+ normal_vfs.cpp \
+ krpermhandler.cpp \
+ krdirwatch.cpp \
+ krarchandler.cpp \
+ preservingcopyjob.cpp \
+ virtualcopyjob.cpp \
+ ftp_vfs.cpp krquery.cpp
diff --git a/src/app/VFS/arc_vfs.cpp b/src/app/VFS/arc_vfs.cpp
new file mode 100644
index 0000000..4af6c74
--- /dev/null
+++ b/src/app/VFS/arc_vfs.cpp
@@ -0,0 +1,866 @@
+/***************************************************************************
+ arc_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <time.h>
+// TQt includes
+#include <tqregexp.h>
+#include <tqdir.h>
+#include <tqdatetime.h>
+#include <tqfileinfo.h>
+// TDE includes
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+#include <kprocess.h>
+#include <tdeio/jobclasses.h>
+#include <tqprogressdialog.h>
+#include <tdeglobalsettings.h>
+#include <kmimetype.h>
+#include <kcursor.h>
+#include <klargefile.h>
+// krusader includes
+#include "arc_vfs.h"
+#include "krpermhandler.h"
+#include "krarchandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../Dialogs/krdialogs.h"
+
+#define MAX_FILES 500
+
+//constructor
+arc_vfs::arc_vfs(TQString origin,TQString type,TQObject* panel,bool write):
+ vfs(panel),arcFile(origin),changed(false),prefix(""),ignoreLines(0){
+
+ if ( type == "tarz" ) type = "-tgz";
+
+ // set the cursor to busy mode
+ if (!quietMode) krApp->setCursor(KCursor::waitCursor());
+
+ // set the writable attribute
+ isWritable = KRpermHandler::fileWriteable(origin);
+ isWritable = ( write && isWritable );
+
+ vfs_type = vfs::ERROR;
+
+ // create the temp dir..
+ tmpDir = krApp->getTempDir();
+ if( tmpDir.isEmpty() ){
+ error = true;
+ return;
+ }
+
+ TQString password = TQString();
+ krConfig->setGroup("Archives");
+ // fill the command options
+ if( type == "gzip" ){
+ cmd = KrServices::fullPathName ( "gzip" );
+ listCmd = "-l";
+ delCmd = "";
+ addCmd = KrServices::fullPathName ( "gzip" ) + " -c";
+ getCmd = "-dc";
+ ignoreLines = -1;
+ isWritable = false;
+ }
+ if(type == "zip2"){
+ cmd = KrServices::fullPathName( "bzip2" );
+ listCmd = "";
+ delCmd = "";
+ addCmd = KrServices::fullPathName( "bzip2" )+ " -c";
+ getCmd = "-dc";
+ ignoreLines = -1;
+ isWritable = false;
+ }
+ if(type == "-tar"){
+ cmd = KrServices::fullPathName( "tar" );
+ listCmd = " -tvf";
+ delCmd = cmd+" --delete -vf";
+ addCmd = cmd+" -uvf";
+ getCmd = " -xvf";
+ }
+ if(type == "-tgz"){
+ cmd = KrServices::fullPathName( "tar" );
+ listCmd = " -tzvf";
+ delCmd = "";
+ addCmd = cmd+" -uvzf";
+ getCmd = " -xzvf";
+ isWritable = false;
+ }
+ if(type == "-tbz"){
+ cmd = KrServices::fullPathName( "tar" );
+ listCmd = " -tjvf";
+ delCmd = "";
+ addCmd = cmd+" -uvjf";
+ getCmd = " -xjvf";
+ isWritable = false;
+ }
+ if(type == "-zip"){
+ password = KRarcHandler::getPassword(arcFile,type);
+ cmd = KrServices::fullPathName( "unzip" );
+ listCmd = "-ZTs ";
+ TQString zipcmd = KrServices::fullPathName( "zip" );
+ delCmd = zipcmd+" -d";
+ addCmd = zipcmd+" -ry";
+ getCmd = " -o";
+ if( !password.isEmpty() ){
+ //listCmd = listCmd + " -P "+password;
+ delCmd = delCmd + " -P "+password;
+ addCmd = addCmd + " -P "+password;
+ getCmd = getCmd + " -P "+password;
+ }
+ ignoreLines = 1;
+ }
+ // "-rpm" is used only to list the rpm - to extract files use "+rpm"
+ if(type == "-rpm"){
+ //rpm can't handle files with " " in them so replace " " with "\ "
+ arcFile.replace(TQRegExp(" "),"\\ ");
+
+ cmd = KrServices::fullPathName( "rpm" );
+ listCmd = " --dump -lpq ";
+ delCmd = "";
+ addCmd = "";
+ getCmd = "";
+ isWritable = false;
+ }
+ if( type == "+rpm" ){
+ // extract the cpio archive from the rpm
+ KShellProcess rpm;
+ rpm << "rpm2cpio"<<"\""+arcFile+"\""+" > "+tmpDir+"/contents.cpio";
+ rpm.start(TDEProcess::Block);
+ arcFile = tmpDir+"/contents.cpio";
+ }
+ if(type == "cpio" || type == "+rpm" ){
+ cmd = KrServices::fullPathName( "cpio" );
+ listCmd = "-tvF ";
+ delCmd = "";
+ addCmd = "";
+ getCmd = " --force-local --no-absolute-filenames -ivdF";
+ isWritable = false;
+ }
+ if(type == "-rar"){
+ bool doRar = krConfig->readBoolEntry("Do Rar",_DoRar);
+ cmd = KrServices::fullPathName( "unrar" );
+ listCmd = " -c- v ";
+ delCmd = "";
+ addCmd = (doRar ? TQString(KrServices::fullPathName( "rar" ) + " -r a ") : TQString("")) ;
+ getCmd = " x -y ";
+ ignoreLines = 8;
+ isWritable = (doRar && isWritable );
+ }
+
+ getDirs();
+ // set the cursor to normal mode
+ if (!quietMode) krApp->setCursor(KCursor::arrowCursor());
+}
+
+// return the working dir
+TQString arc_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1) != "/") path = "/"+path;
+ TQDir().mkdir(tmpDir+path);
+ return tmpDir+path;
+}
+
+arc_vfs::~arc_vfs(){
+ // set the cursor to busy mode
+ if (!quietMode) krApp->setCursor(KCursor::waitCursor());
+ // don't touch messed-up archives
+ if(!error) repack();
+ // delete the temp dir
+ KShellProcess proc;
+ proc<<"rm"<<"-rf"<<tmpDir;
+ proc.start(TDEProcess::Block);
+
+ // set the cursor to normal mode
+ if (!quietMode) krApp->setCursor(KCursor::arrowCursor());
+}
+
+bool arc_vfs::getDirs(){
+ if( !listCmd.isEmpty() ){
+ // write the temp file
+ KShellProcess proc;
+ proc << cmd << listCmd << "\""+arcFile+"\"" <<" > " << tmpDir+"/tempfilelist";
+ proc.start(TDEProcess::Block);
+ if( !proc.normalExit() || !proc.exitStatus() == 0 ){
+ if (!quietMode) KMessageBox::error(krApp, i18n("<qt>Can't read <b>%1</b>. Archive "
+ "might be corrupted!</qt>").arg(arcFile.mid(arcFile.findRev('/')+1)));
+ error = true;
+ return false;
+ }
+
+ // clear the dir list
+ dirList.clear();
+
+ // prepare the first dir entry - the "" entry
+ arc_dir *tempdir = new arc_dir("");
+ vfs_filesP = &(tempdir->entries);
+ dirList.append(tempdir);
+
+ // parse the temp file
+ TQFile temp(tmpDir+"/tempfilelist");
+ temp.open(IO_ReadOnly);
+ char buf[1000];
+ TQString line;
+ if(vfs_type == "gzip" || vfs_type == "-zip" )
+ temp.readLine(line,10000); // skip the first line - it's garbage
+ if( vfs_type == "-rar" ){
+ while(temp.readLine(line,10000) != -1)
+ if ( line.contains("----------") ) break;
+ }
+ while(temp.readLine(buf,1000) != -1){
+ line = TQString::fromLocal8Bit(buf);
+ if ( line.contains("----------") ) break;
+ parseLine(line.stripWhiteSpace(),&temp);
+
+ }
+ temp.close();
+ TQDir().remove(tmpDir+"/tempfilelist");
+ }
+ else { // bzip2
+ // clear the dir list
+ dirList.clear();
+
+ // prepare the first dir entry - the "" entry
+ arc_dir *tempdir = new arc_dir("");
+ vfs_filesP = &(tempdir->entries);
+ dirList.append(tempdir);
+
+ parseLine("",0);
+ }
+ return true;
+}
+
+
+// copy a file to the vfs (physical)
+void arc_vfs::vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir, PreserveMode /*pmode*/ ){
+ if ( addCmd.isEmpty() ) return;
+
+ // get the path inside the archive
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ path = path+"/";
+ if(dir != "" ) dir = "/"+dir;
+ if(path.left(1) != "/") path = "/"+path;
+
+ // make sure the destination exist
+ for( int i=0; i >= 0 ; i= TQString(tmpDir+path+dir).find('/',i+1) ){
+ TQDir().mkdir(TQString(tmpDir+path+dir).left(i));
+ }
+
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+dir);
+
+ TDEIO::Job* job = new TDEIO::CopyJob(*fileUrls,dest,mode,false,true);
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+ if(mode == TDEIO::CopyJob::Move) // notify the other panel
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),toNotify,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+}
+
+
+// remove a file from the vfs (physical)
+void arc_vfs::vfs_delFiles(TQStringList *fileNames){
+ if ( delCmd.isEmpty() ) return;
+ // if we move to trash - just extract files and move them to trash -
+ // the repack() will delete them for us
+ krConfig->setGroup("General");
+ if( krConfig->readBoolEntry("Move To Trash",_MoveToTrash) ) {
+ KURL::List* filesUrls = vfs_getFiles(fileNames); // extract
+ changed = true;
+
+ TDEIO::Job *job = new TDEIO::CopyJob(*filesUrls,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+ }
+ // else we have to delete the files from both the archive and the temp dir
+ else {
+ // change dir to the temp dir
+ TQString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ TQStringList files;
+ TDEIO::filesize_t totalSizeVal = 0;
+ unsigned long totalFilesVal = 0;
+
+ // names -> urls
+ for(TQStringList::Iterator name = fileNames->begin(); name != fileNames->end(); ++name )
+ processName(*name,&files,&totalSizeVal,&totalFilesVal);
+
+
+ KShellProcess proc1 , proc2;
+ krApp->startWaiting(i18n("Deleting Files..."),files.count()+ignoreLines);
+ connect(&proc1,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,char*,int)) );
+
+ proc1 << delCmd << "\""+arcFile+"\"";
+ proc2 << "rm -rf";
+ for(unsigned int i =0; i < files.count(); ){
+ proc1 << (prefix+*files.at(i));
+ proc2 << tmpDir+"/"+(*files.at(i));
+ extFiles.remove(*files.at(i++));
+ if ( i%MAX_FILES==0 || i==files.count() ){
+ proc1.start(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ proc2.start();
+ while( proc1.isRunning() || proc2.isRunning() ) tqApp->processEvents(); // busy wait - need to find something better...
+ proc1.clearArguments() ; proc2.clearArguments();
+ proc1 << delCmd << "\""+arcFile+"\"";
+ proc2 << "rm -rf";
+ }
+ }
+ krApp->stopWait();
+
+ changed = true;
+ chdir (save.local8Bit());
+ vfs_refresh(vfs_origin);
+ }
+}
+
+// return a path to the file
+TQString arc_vfs::vfs_getFile(TQString name){
+ // get the current file path
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ TQStringList temp(name);
+ vfs_getFiles(&temp);
+
+ return tmpDir+"/"+path+name;
+}
+
+KURL::List* arc_vfs::vfs_getFiles(TQStringList* names){
+ KURL url;
+ KURL::List* urls = new KURL::List();
+
+ // get the current file path
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ // change dir to the temp dir
+ TQString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+ // names -> urls
+ TQStringList files;
+ TDEIO::filesize_t totalSize = 0;
+ unsigned long totalFiles = 0;
+ for(TQStringList::Iterator name = names->begin(); name != names->end(); ++name ){
+ processName(*name,&files,&totalSize,&totalFiles);
+ url.setPath(tmpDir+"/"+path+(*name));
+ urls->append(url);
+ }
+ // check the urls for unpacked files and directories
+ for(TQStringList::Iterator file = files.begin(); file != files.end(); ++file ){
+ if ( (*file).right(1)=="/" ){
+ TQDir(tmpDir).mkdir(*file);
+ if( vfs_type == "-rar" ) file = files.remove(file--);
+ }
+ // don't unpack the same file twice
+ else if( extFiles.contains(*file) ){
+ file = files.remove(file--);
+ }
+ }
+ // unpack ( if needed )
+ if ( files.count() > 0 ){
+ krApp->startWaiting(i18n("Unpacking Files"),files.count()+ignoreLines);
+ KShellProcess proc;
+ connect(&proc,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,char*,int)) );
+
+ proc << cmd << getCmd << "\""+arcFile+"\"";
+ if( vfs_type == "gzip" || vfs_type == "zip2" ) proc << ">";
+ for(unsigned int i=0 ; i < files.count() ; ){
+ proc << (prefix+*files.at(i++));
+ if ( i%MAX_FILES==0 || i==files.count() ){
+ proc.start(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ while( proc.isRunning() ) tqApp->processEvents();
+ proc.clearArguments();
+ proc << cmd << getCmd << "\""+arcFile+"\"";
+ }
+ }
+ getExtFiles(); // this will update the extFiles list.
+ krApp->stopWait();
+ }
+ // restore dir
+ chdir(save.local8Bit());
+
+ return urls;
+}
+
+// make dir
+void arc_vfs::vfs_mkdir(TQString name){
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ TQDir(tmpDir).mkdir(path+name);
+ changed = true; //rescan the archive
+ vfs_refresh(vfs_origin);
+}
+
+// rename file
+void arc_vfs::vfs_rename(TQString fileName,TQString newName){
+ KURL::List temp;
+ temp.append(vfs_getFile(fileName));
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ TQDir(tmpDir).mkdir(path);
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+"/"+newName);
+
+ TDEIO::Job* job = new TDEIO::CopyJob(temp,dest,TDEIO::CopyJob::Move,false,false);
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+}
+
+bool arc_vfs::vfs_refresh(TQString origin){
+ if ( error ) return false;
+
+ if ( changed || origin == vfs_origin ){
+ repack(); // repack dirs only if needed
+ if ( !getDirs() ){
+ if (!quietMode) emit startUpdate();
+ return true;
+ }
+ changed = false;
+ }
+
+ vfs_origin = origin;
+ // get the directory...
+ TQString path = origin.right((origin.length()-origin.findRev('\\'))-1);
+ if(path.left(1) =="/") path.remove(0,1);
+
+ vfs_filesP = findDir(path);
+
+ if (!quietMode) emit startUpdate();
+ return true;
+}
+
+// service functions
+TQString arc_vfs::nextWord(TQString &s,char d) {
+ s=s.stripWhiteSpace();
+ int j=s.find(d,0);
+ TQString temp=s.left(j); // find the leftmost word.
+ s.remove(0,j);
+ return temp;
+}
+
+void arc_vfs::getFilesToPack(TQStringList* filesToPack,TQString dir_name){
+ bool newDir = false;
+ vfileDict *vfs_filesP_backup = vfs_filesP; // save vfs_filesP
+
+ // init all the diffrent lists (and list pointers);
+ vfs_filesP=findDir(dir_name);
+ if ( vfs_filesP == 0) newDir = true;
+ if(dir_name != "") dir_name = dir_name+"/";
+
+ DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
+ if(!dir) return ;
+
+ struct dirent* dirEnt;
+ TQString name;
+ KDE_struct_stat stat_p;
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = dirEnt->d_name;
+ if ( name == ".." || name == "." ) continue;
+ if( KDE_lstat(tmpDir.local8Bit()+"/"+dir_name.local8Bit()+name.local8Bit(),&stat_p) ) continue;
+ extFile temp(dir_name+name,stat_p.st_mtime,stat_p.st_size);
+ // add to the list file that are diffrent than the ones packed
+ if( S_ISDIR(stat_p.st_mode) ){ // recurse on all sub dirs
+ if( !findDir(dir_name+name) ){
+ // add to the list only new && empty dirs
+ if( newDir && TQDir(dir_name+name).entryList(TQDir::All | TQDir::AccessMask).count() <= 2 )
+ filesToPack->append( dir_name+name);
+ }
+ getFilesToPack(filesToPack,dir_name+name);
+ continue;
+ }
+
+ // if the file don't exist add it to the archive and to the extFiles
+ if( newDir || !extFiles.contains( dir_name+name ) ){
+ filesToPack->append( dir_name+name );
+ extFiles.append( temp );
+ } // else if the file exist but was modified - repack it;
+ else if( !extFiles.contains( temp ) ){
+ filesToPack->append( dir_name+name );
+ extFiles.remove( dir_name+name );
+ extFiles.append( temp );
+ }
+ }
+ vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
+}
+
+void arc_vfs::getFilesToDelete(TQStringList* filesToDelete,TQString){
+ // sync the extFiles - and find out which files were deleted
+ TQString file;
+ for(unsigned int i=0 ; i<extFiles.count(); ){
+ file = tmpDir+"/"+(*extFiles.at(i)).url;
+ if( !KRpermHandler::fileExist(file) ){
+ filesToDelete->append( (*extFiles.at(i)).url );
+ extFiles.remove(extFiles.at(i));
+ }
+ else ++i;
+ }
+}
+
+void arc_vfs::getExtFiles(TQString dir_name){
+ DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
+ if(!dir){
+ kdWarning() << "faild to opendir(): " << tmpDir.local8Bit()+"/"+dir_name.local8Bit() << endl;
+ return ;
+ }
+
+ if( dir_name != "") dir_name = dir_name+"/";
+
+ struct dirent* dirEnt;
+ TQString name;
+ KDE_struct_stat stat_p;
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = dirEnt->d_name;
+ if ( name == ".." || name == "." ) continue;
+ if( KDE_lstat(tmpDir.local8Bit()+"/"+dir_name.local8Bit()+name.local8Bit(),&stat_p) ) continue;
+ extFile temp(dir_name+name,stat_p.st_mtime,stat_p.st_size);
+ // recurse on all sub dirs
+ if( S_ISDIR(stat_p.st_mode) ){
+ getExtFiles(dir_name+name);
+ }
+ // if the file is not in extFiles - it is newly extracted.
+ // note: getFilesToPack() updates time + size !
+ else if( !extFiles.contains( dir_name+name ) ){
+ extFiles.append( temp );
+ }
+ }
+}
+
+void arc_vfs::repack(){
+ TQString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ // delete from the archive files that were unpacked and deleted
+ if( vfs_isWritable() ){
+ TQStringList filesToDelete;
+ getFilesToDelete(&filesToDelete);
+ if( !filesToDelete.isEmpty() ){
+ KShellProcess delProc;
+ krApp->startWaiting(i18n("Deleting Files..."),filesToDelete.count()+ignoreLines);
+ connect(&delProc,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,char*,int)) );
+
+ delProc << delCmd << "\""+arcFile+"\"";
+ for( unsigned int i=0 ; i < filesToDelete.count() ;){
+ delProc << (*filesToDelete.at(i++));
+ if( i%MAX_FILES==0 || i==filesToDelete.count() ){
+ delProc.start(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ while( delProc.isRunning() ) tqApp->processEvents();
+ delProc.clearArguments();
+ delProc << delCmd << "\""+arcFile+"\"";
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+
+ // finaly repack tmpDir
+ if( vfs_isWritable() || vfs_type=="gzip" || vfs_type=="zip2" ){
+ TQStringList filesToPack;
+ getFilesToPack(&filesToPack);
+ if( !filesToPack.isEmpty() ){
+ KShellProcess addProc;
+ krApp->startWaiting(i18n("Repacking..."),filesToPack.count()+ignoreLines);
+ connect(&addProc,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ krApp, TQ_SLOT(incProgress(TDEProcess*,char*,int)) );
+
+ if( vfs_type=="gzip" || vfs_type=="zip2" ){
+ addProc << addCmd << *filesToPack.at(0)<< ">" << "\""+arcFile+"\"";
+ addProc.start(TDEProcess::NotifyOnExit);
+ while( addProc.isRunning() ) tqApp->processEvents();
+ }
+ else {
+ addProc << addCmd << "\""+arcFile+"\"";
+ for( unsigned int i=0 ; i<filesToPack.count(); ){
+ addProc << "\""+prefix+(*filesToPack.at(i++))+"\"";
+ if( i%MAX_FILES==0 || i==filesToPack.count() ){
+ addProc.start(TDEProcess::NotifyOnExit,TDEProcess::AllOutput);
+ while( addProc.isRunning() ) tqApp->processEvents(); // busy wait - need to find something better...
+ addProc.clearArguments();
+ addProc << addCmd << "\""+arcFile+"\"";
+ }
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+ chdir(save.local8Bit());
+}
+
+vfileDict* arc_vfs::findDir(TQString name){
+ for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
+ if(temp->name == name) return &(temp->entries);
+ }
+ return 0;
+}
+
+arc_vfs::arc_dir* arc_vfs::findArcDir(TQString name){
+for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
+ if(temp->name == name) return temp;
+ }
+ return 0;
+}
+
+TQString arc_vfs::changeDir(TQString name){
+ if(name.left(2) == "./") {
+ prefix = "./";
+ name.remove(0,2);
+ }
+
+ if(!name.contains('/')){
+ vfs_filesP = findDir("");
+ return name;
+ }
+ // seperate the path from the name
+ TQString path = name.left(name.findRev('/'));
+ name = name.mid(name.findRev('/')+1);
+ // see if the path exists
+ if ((vfs_filesP=findDir(path)) == 0){
+ //create a new dir entry
+ TQString Pname = path.mid(path.findRev('/')+1);
+ if(Pname.isEmpty()) return name;
+ TQString tempName = arcFile;
+ TQFileInfo qfi(tempName.replace(TQRegExp("\\"),""));
+ vfile* vf=new vfile(Pname,0,"drwxr-xr-x",qfi.lastModified().toTime_t(),false,
+ qfi.owner(),qfi.group(),"inode/directory","",0 );
+ // add dirs if needed
+ changeDir(path);
+
+ vfile* vf2 = vfs_search(Pname);
+ if(vf2 != 0) vfs_removeFromList(vf2);
+ vfs_addToList(vf);
+
+ // add a new arc_dir
+ dirList.append(new arc_dir(path));
+ vfs_filesP = findDir(path);
+ }
+ return name;
+}
+
+// calculate space
+void arc_vfs::vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs,bool* stop){
+ if ( *stop ) return;
+ vfile* vf = vfs_search(name);
+
+ // get the path inside the archive
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ path = path+"/";
+ if(path.left(1) == "/") path.remove(0,1);
+
+ if( !vf->vfile_isDir() ){ // single files are simple :)
+ ++(*totalFiles);
+ (*totalSize) += vf->vfile_getSize();
+ }
+ else { // handle directories : (
+ ++(*totalDirs);
+
+ TQString origin_backup = vfs_origin; // backup the vfs origin
+ vfs_origin = vfs_origin+"/"+name;
+ vfileDict* vfs_filesP_backup = vfs_filesP; // backup the vfs_filesP
+ vfs_filesP = findDir(path+name);
+
+ // process all the files in the directory.
+ for( vf = vfs_getFirstFile(); vf != 0; vf = vfs_getNextFile() ){
+ if (*stop) return;
+ vfs_calcSpace(vf->vfile_getName(),totalSize,totalFiles,totalDirs,stop);
+ }
+
+ vfs_origin = origin_backup; // restore origin
+ vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
+ }
+}
+
+void arc_vfs::processName(const TQString& name, TQStringList *urls,TDEIO::filesize_t *totalSize,unsigned long *totalFiles ){
+ vfile* vf = vfs_search(name);
+ if ( vf == 0 ) return;
+
+ // get the path inside the archive
+ TQString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ path = path+"/";
+ if(path.left(1) == "/") path.remove(0,1);
+
+ if( !vf->vfile_isDir() || vf->vfile_isSymLink() ){ // single files are simple :)
+ ++(*totalFiles);
+ (*totalSize) += vf->vfile_getSize();
+ urls->append(path+name);
+ } else { // handle directories : (
+ urls->append(path+name+"/");
+ TQString origin_backup = vfs_origin; // backup the vfs origin
+ vfs_origin = vfs_origin+"/"+name;
+ vfileDict* vfs_filesP_backup = vfs_filesP; // backup the vfs_filesP
+ vfs_filesP = findDir(path+name);
+
+ // process all the files in the directory.
+ for( vf = vfs_getFirstFile(); vf != 0; vf = vfs_getNextFile() )
+ processName(vf->vfile_getName(),urls,totalSize,totalFiles);
+
+ vfs_origin = origin_backup; // restore origin
+ vfs_filesP = vfs_filesP_backup; // restore vfs_filesP
+ }
+}
+
+void arc_vfs::parseLine(TQString line, TQFile* temp){
+ TQString name;
+ TDEIO::filesize_t size = 0;
+ TQString perm;
+ TQFileInfo qfi(arcFile);
+ time_t mtime = qfi.lastModified().toTime_t();
+ bool link = false;
+ uid_t owner = getuid();
+ gid_t group = getgid();
+ TQString dest = "";
+ mode_t mode = 0;
+
+
+ // parse gziped files
+ if(vfs_type == "gzip"){
+ KDE_struct_stat stat_p;
+ KDE_stat(arcFile.local8Bit(),&stat_p);
+
+ nextWord(line);
+ size = nextWord(line).toLong();
+ nextWord(line);
+ name = nextWord(line,'\n');
+ if(name.contains('/')) name = name.mid(name.findRev('/')+1,name.length());
+ perm = KRpermHandler::mode2TQString(stat_p.st_mode) ;
+ owner = KRpermHandler::user2uid(qfi.owner());
+ group = KRpermHandler::group2gid(qfi.group());
+ mode = stat_p.st_mode;
+ }
+
+ // parse bzip2ed files
+ if( vfs_type == "zip2" ){
+ KDE_struct_stat stat_p;
+ KDE_stat(arcFile.local8Bit(),&stat_p);
+
+ name = qfi.fileName();
+ name = name.left(name.findRev('.'));
+ //long size = qfi.size();
+ perm = KRpermHandler::mode2TQString(stat_p.st_mode) ;
+ owner = KRpermHandler::user2uid(qfi.owner());
+ group = KRpermHandler::group2gid(qfi.group());
+ mode = stat_p.st_mode;
+ }
+
+ // parse tar files
+ if(vfs_type == "-tar" || vfs_type == "-tbz" || vfs_type == "-tgz" ){
+ perm = nextWord(line);
+ TQString temp = nextWord(line);
+ owner = temp.left(temp.findRev('/')).toInt();
+ group = temp.mid(temp.find('/')+1,temp.length()).toInt();
+ size = nextWord(line).toLong();
+ temp = nextWord(line);
+ name = nextWord(line,'\n');
+ if (name.startsWith("/")) // fix full-paths problem in tar (thanks to Heiner!)
+ name.remove(0, 1);
+ if( name.contains(" -> ") ){
+ link = true;
+ dest = name.mid(name.find(" -> ")+4);
+ name = name.left(name.find(" -> "));
+ }
+ }
+
+ // parse zipped files
+ if(vfs_type == "-zip"){
+ perm = nextWord(line);
+ if(perm.length() != 10)
+ perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ if (nextWord(line).contains("file")) return;
+ nextWord(line);
+ size = nextWord(line).toLong();
+ nextWord(line);nextWord(line);
+ TQString temp = nextWord(line);
+ name = nextWord(line,'\n');
+ }
+
+ // parse cpio packages
+ if(vfs_type == "cpio" || vfs_type == "+rpm"){
+ perm = nextWord(line);
+ nextWord(line);nextWord(line);nextWord(line);
+ size = nextWord(line).toLong();
+ nextWord(line);nextWord(line);nextWord(line);
+ TQString tempName = arcFile;
+ TQFileInfo qfi(tempName.replace(TQRegExp("\\"),""));
+ name = nextWord(line,'\n');
+ if ( name.left(1) == "/" ) name.remove(0,1);
+ if( name.contains(" -> ") ){
+ link = true;
+ dest = name.mid(name.find(" -> ")+4);
+ name = name.left(name.find(" -> "));
+ }
+ }
+ // parse rared files
+ if(vfs_type == "-rar"){
+ name = nextWord(line,'\n');
+ temp->readLine(line,10000);
+ size = nextWord(line).toLong();
+ nextWord(line);
+ nextWord(line);
+ perm = nextWord(line);
+ if(perm.length() != 10)
+ perm = (perm.at(1)=='D')? "drwxr-xr-x" : "-rw-r--r--" ;
+ }
+ // parse rpm packages
+ if(vfs_type == "-rpm"){
+ name = nextWord(line);
+ if ( name.left(1) == "/" ) name.remove(0,1);
+ size = nextWord(line).toLong();
+ mtime = nextWord(line).toLong();
+ nextWord(line);
+ perm = KRpermHandler::mode2TQString(nextWord(line).toLong());
+ perm = (perm.at(0)=='d')? "drwxr-xr-x" : "-rw-r--r--" ;
+ }
+
+ if ( perm[0]=='d' && name.right(1) != "/" ) name = name+"/";
+ name = changeDir(name);
+ if(name.length() < 1) return;
+
+
+ TQString mime = KMimeType::findByURL( "/"+name,0,true,true)->name();
+ vfile* vf=new vfile(name,size,perm,mtime,link,owner,group,mime,dest,mode);
+ vfile* vf2 = vfs_search(name);
+ if(vf2 != 0) vfs_removeFromList(vf2);
+ vfs_addToList(vf);
+}
+
+#include "arc_vfs.moc"
diff --git a/src/app/VFS/arc_vfs.h b/src/app/VFS/arc_vfs.h
new file mode 100644
index 0000000..bb7dd0c
--- /dev/null
+++ b/src/app/VFS/arc_vfs.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+ arc_vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef ARC_VFS_H
+#define ARC_VFS_H
+
+#include <sys/types.h>
+#include "vfs.h"
+#include <tqvaluestack.h>
+#include <kprocess.h>
+#include <tqfile.h>
+#include <tqprogressdialog.h>
+
+class arc_vfs : public vfs {
+ TQ_OBJECT
+
+ class arc_dir;
+ class extFile;
+public:
+ arc_vfs(TQString origin,TQString type,TQObject* panel,bool write);
+ ~arc_vfs();
+
+ // copy a file to the vfs (physical)
+ void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify=0,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ // remove a file from the vfs (physical)
+ void vfs_delFiles(TQStringList *fileNames);
+ // return a path to the file
+ TQString vfs_getFile(TQString name);
+ KURL::List* vfs_getFiles(TQStringList* names);
+ // make dir
+ void vfs_mkdir(TQString name);
+ // rename file
+ void vfs_rename(TQString fileName,TQString newName);
+ // calculate space
+ void vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool* stop);
+ // return the working dir
+ TQString vfs_workingDir();
+
+public slots:
+ // actually reads files and stats
+ bool vfs_refresh(TQString origin);
+ void repack();
+
+protected:
+ TQString tmpDir; // the temp directory tha archive is using
+ TQString arcFile; // the archive file URL
+ bool changed; // true if repack changed the archive
+ TQPtrList<arc_dir> dirList;
+ TQValueList<extFile> extFiles; // the name, time & size of files unpacked from this archive
+
+ void processName(const TQString& name,TQStringList *urls,TDEIO::filesize_t *totalSize,unsigned long *totalFiles );
+ bool getDirs(); // fill the dir list
+ vfileDict* findDir(TQString name);
+ arc_dir* findArcDir(TQString name);
+ void getFilesToPack (TQStringList* filesToPack,TQString dir_name = "");
+ void getFilesToDelete(TQStringList* filesToDelete,TQString dir_name = "");
+ void getExtFiles( TQString dir_name="" );
+ TQString nextWord( TQString &s, char d=' ' );
+ TQString changeDir(TQString name);
+
+ void parseLine(TQString line,TQFile* temp);
+
+ TQString prefix;
+ TQString cmd; // the archiver main command
+ TQString listCmd; // the file listing option
+ TQString delCmd; // the delete option
+ TQString addCmd; // the add files option
+ TQString getCmd; // the extract files option
+
+ // the interl progress bar variale
+ int ignoreLines; // no of lines to ignore on stdout
+
+private:
+ class arc_dir{
+ public:
+ arc_dir(TQString _name){
+ name = _name;
+ entries.setAutoDelete(true);
+ }
+ TQString name; // the name of the dir
+ vfileDict entries; // the file and dir in this dir
+ };
+
+ class extFile{
+ public:
+ extFile(): url(""),time(0),size(0){}
+ extFile(TQString u): url(u),time(0),size(0){}
+ extFile(TQString u,time_t t,off_t s): url(u),time(t),size(s){}
+ bool operator==(const extFile& ef) const{
+ if( url != ef.url ) return false;
+ if( size*ef.size && size!=ef.size )return false;
+ if( time*ef.time && time!=ef.time )return false;
+ return true;
+ }
+ TQString url;
+ time_t time;
+ off_t size;
+ };
+
+
+
+};
+
+#endif
diff --git a/src/app/VFS/ftp_vfs.cpp b/src/app/VFS/ftp_vfs.cpp
new file mode 100644
index 0000000..2da0665
--- /dev/null
+++ b/src/app/VFS/ftp_vfs.cpp
@@ -0,0 +1,297 @@
+/***************************************************************************
+ ftp_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+// Sys includes
+#include <time.h>
+#include <sys/param.h>
+#include <unistd.h>
+#ifdef BSD
+#include <sys/types.h>
+#endif
+// TQt includes
+#include <tqdir.h>
+#include <tqregexp.h>
+#include <tqtimer.h>
+#include <tqeventloop.h>
+// TDE includes
+#include <tdeio/jobclasses.h>
+#include <tdelocale.h>
+#include <tdeio/job.h>
+#include <tdemessagebox.h>
+#include <kprotocolinfo.h>
+#include <kdebug.h>
+// Krusader includes
+#include "ftp_vfs.h"
+#include "krpermhandler.h"
+#include "../Dialogs/krdialogs.h"
+#include "../Dialogs/krprogress.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+
+ftp_vfs::ftp_vfs( TQObject* panel ) : vfs( panel ), busy( false ) {
+ // set the writable attribute
+ isWritable = true;
+ vfs_type = FTP;
+}
+
+ftp_vfs::~ftp_vfs() {
+ busy = false;
+}
+
+void ftp_vfs::slotAddFiles( TDEIO::Job *, const TDEIO::UDSEntryList& entries ) {
+ int rwx = -1;
+
+ TQString prot = vfs_origin.protocol();
+ if( prot == "krarc" || prot == "tar" || prot == "zip" )
+ rwx = PERM_ALL;
+
+ TDEIO::UDSEntryListConstIterator it = entries.begin();
+ TDEIO::UDSEntryListConstIterator end = entries.end();
+
+ // as long as u can find files - add them to the vfs
+ for ( ; it != end; ++it ) {
+ KFileItem kfi( *it, vfs_origin, true, true );
+ vfile *temp;
+
+ // get file statistics
+ TQString name = kfi.text();
+ // ignore un-needed entries
+ if ( name.isEmpty() || name == "." || name == ".." ) continue;
+
+ TDEIO::filesize_t size = kfi.size();
+ time_t mtime = kfi.time( TDEIO::UDS_MODIFICATION_TIME );
+ bool symLink = kfi.isLink();
+ mode_t mode = kfi.mode() | kfi.permissions();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+ // set the mimetype
+ TQString mime = kfi.mimetype();
+ TQString symDest = "";
+ if ( symLink ) {
+ symDest = kfi.linkDest();
+ if ( kfi.isDir() ) perm[ 0 ] = 'd';
+ }
+
+ // create a new virtual file object
+ if ( kfi.user().isEmpty() )
+ temp = new vfile( name, size, perm, mtime, symLink, getuid(), getgid(), mime, symDest, mode, rwx );
+ else {
+ TQString currentUser = vfs_origin.user();
+ if ( currentUser.contains( "@" ) ) /* remove the FTP proxy tags from the username */
+ currentUser.truncate( currentUser.find( '@' ) );
+ if ( currentUser.isEmpty() ) {
+ if( vfs_origin.host().isEmpty() )
+ currentUser = KRpermHandler::uid2user( getuid() );
+ else {
+ currentUser = ""; // empty, but not TQString()
+ }
+ }
+#if KDE_IS_VERSION(3,5,0)
+ temp = new vfile( name, size, perm, mtime, symLink,
+ kfi.user(), kfi.group(), currentUser,
+ mime, symDest, mode, rwx, kfi.ACL().asString(),
+ kfi.defaultACL().asString() );
+#else
+ temp = new vfile( name, size, perm, mtime, symLink, kfi.user(), kfi.group(), currentUser, mime, symDest, mode, rwx );
+#endif
+ }
+
+#if KDE_IS_VERSION(3,4,0)
+ if( !kfi.localPath().isEmpty() ){
+ temp->vfile_setUrl( kfi.localPath() );
+ } else {
+ temp->vfile_setUrl( kfi.url() );
+ }
+#else
+ temp->vfile_setUrl( kfi.url() );
+#endif
+ temp->vfile_setIcon( kfi.iconName() );
+ foundVfile( temp );
+ }
+}
+
+void ftp_vfs::slotPermanentRedirection( TDEIO::Job*, const KURL&, const KURL& newUrl ) {
+ vfs_origin = newUrl;
+ vfs_origin.adjustPath(-1);
+}
+
+void ftp_vfs::slotRedirection( TDEIO::Job *, const KURL &url ) {
+ // update the origin
+ vfs_origin = url;
+ vfs_origin.adjustPath(-1);
+}
+
+void ftp_vfs::slotListResult( TDEIO::Job *job ) {
+ if ( job && job->error() ) {
+ // we failed to refresh
+ listError = true;
+ // display error message
+ if ( !quietMode ) job->showErrorDialog( krApp );
+ }
+ busy = false;
+}
+
+bool ftp_vfs::populateVfsList( const KURL& origin, bool showHidden ) {
+ TQString errorMsg = TQString();
+ if ( !origin.isValid() )
+ errorMsg = i18n( "Malformed URL:\n%1" ).arg( origin.url() );
+ if ( !KProtocolInfo::supportsListing( origin ) ) {
+ if( origin.protocol() == "ftp" && KProtocolInfo::supportsReading( origin ) )
+ errorMsg = i18n( "Krusader doesn't support FTP access via HTTP.\nIf it is not the case, please check and change the Proxy settings in kcontrol." );
+ else
+ errorMsg = i18n( "Protocol not supported by Krusader:\n%1" ).arg( origin.url() );
+ }
+
+ if ( !errorMsg.isEmpty() ) {
+ if ( !quietMode ) KMessageBox::sorry( krApp, errorMsg );
+ return false;
+ }
+
+ busy = true;
+
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+
+ //TQTimer::singleShot( 0,this,TQ_SLOT(startLister()) );
+ listError = false;
+ // Open the directory marked by origin
+ krConfig->setGroup( "Look&Feel" );
+ //vfs_origin.adjustPath(+1);
+ TDEIO::Job *job = TDEIO::listDir( vfs_origin, false, showHidden );
+ connect( job, TQ_SIGNAL( entries( TDEIO::Job*, const TDEIO::UDSEntryList& ) ),
+ this, TQ_SLOT( slotAddFiles( TDEIO::Job*, const TDEIO::UDSEntryList& ) ) );
+ connect( job, TQ_SIGNAL( redirection( TDEIO::Job*, const KURL& ) ),
+ this, TQ_SLOT( slotRedirection( TDEIO::Job*, const KURL& ) ) );
+ connect( job, TQ_SIGNAL( permanentRedirection( TDEIO::Job*, const KURL&, const KURL& ) ),
+ this, TQ_SLOT( slotPermanentRedirection( TDEIO::Job*, const KURL&, const KURL& ) ) );
+
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQ_SLOT( slotListResult( TDEIO::Job* ) ) );
+
+ job->setWindow( krApp );
+
+ if ( !quietMode ) {
+ emit startJob( job );
+ //new KrProgress(job); ==> disabled because of in-panel refresh
+ }
+
+ while ( busy && vfs_processEvents());
+
+ if ( listError ) return false;
+
+ return true;
+}
+
+
+// copy a file to the vfs (physical)
+void ftp_vfs::vfs_addFiles( KURL::List *fileUrls, TDEIO::CopyJob::CopyMode mode, TQObject* toNotify, TQString dir, PreserveMode /*pmode*/ ) {
+ KURL destUrl = vfs_origin;
+
+ if ( dir != "" ) {
+ destUrl.addPath( dir );
+ destUrl.cleanPath(); // removes the '..', '.' and extra slashes from the URL.
+
+ if ( destUrl.protocol() == "tar" || destUrl.protocol() == "zip" || destUrl.protocol() == "krarc" ) {
+ if ( TQDir( destUrl.path( -1 ) ).exists() )
+ destUrl.setProtocol( "file" ); // if we get out from the archive change the protocol
+ }
+ }
+
+ TDEIO::Job* job = new TDEIO::CopyJob( *fileUrls, destUrl, mode, false, true );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+ if ( mode == TDEIO::CopyJob::Move ) // notify the other panel
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), toNotify, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+// remove a file from the vfs (physical)
+void ftp_vfs::vfs_delFiles( TQStringList *fileNames ) {
+ KURL::List filesUrls;
+ KURL url;
+
+ // names -> urls
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ TQString filename = ( *fileNames ) [ i ];
+ url = vfs_origin;
+ url.addPath( filename );
+ filesUrls.append( url );
+ }
+ TDEIO::Job *job = new TDEIO::DeleteJob( filesUrls, false, true );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+
+KURL::List* ftp_vfs::vfs_getFiles( TQStringList* names ) {
+ KURL url;
+ KURL::List* urls = new KURL::List();
+ for ( TQStringList::Iterator name = names->begin(); name != names->end(); ++name ) {
+ url = vfs_getFile( *name );
+ urls->append( url );
+ }
+ return urls;
+}
+
+
+// return a path to the file
+KURL ftp_vfs::vfs_getFile( const TQString& name ) {
+ vfile * vf = vfs_search( name );
+ if ( !vf ) return KURL(); // empty
+
+ KURL url = vf->vfile_getUrl();
+ if ( vf->vfile_isDir() ) url.adjustPath( + 1 );
+ return url;
+}
+
+void ftp_vfs::vfs_mkdir( const TQString& name ) {
+ KURL url = vfs_origin;
+ url.addPath( name );
+
+ TDEIO::SimpleJob* job = TDEIO::mkdir( url );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+void ftp_vfs::vfs_rename( const TQString& fileName, const TQString& newName ) {
+ KURL::List fileUrls;
+ KURL oldUrl = vfs_origin;
+ oldUrl.addPath( fileName ) ;
+
+ fileUrls.append( oldUrl );
+
+ KURL newUrl = vfs_origin;
+ newUrl.addPath( newName );
+
+ TDEIO::Job *job = new TDEIO::CopyJob( fileUrls, newUrl, TDEIO::CopyJob::Move, true, true );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+TQString ftp_vfs::vfs_workingDir() {
+ return vfs_origin.url( -1 );
+}
+
+#include "ftp_vfs.moc"
diff --git a/src/app/VFS/ftp_vfs.h b/src/app/VFS/ftp_vfs.h
new file mode 100644
index 0000000..486efc9
--- /dev/null
+++ b/src/app/VFS/ftp_vfs.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ ftp_vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ A vfs class that handels "ftp/samba" directory enteris
+ inherits: vfs
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef FTP_VFS
+#define FTP_VFS
+
+// TDE includes
+#include <kdirlister.h>
+// Krusader includes
+#include "vfs.h"
+
+class ftp_vfs : public vfs{
+ TQ_OBJECT
+
+public:
+ // the constructor simply uses the inherited constructor
+ ftp_vfs(TQObject* panel);
+ ~ftp_vfs();
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(TQStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(TQStringList* names);
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const TQString& name);
+ /// Create a new directory
+ virtual void vfs_mkdir(const TQString& name);
+ /// Rename file
+ virtual void vfs_rename(const TQString& fileName,const TQString& newName);
+ /// Return the VFS working dir
+ TQString vfs_workingDir();
+
+public slots:
+ /// Handles new files from the dir lister
+ void slotAddFiles(TDEIO::Job * job, const TDEIO::UDSEntryList& entries);
+ /// Redirection signal handlers
+ void slotRedirection(TDEIO::Job *, const KURL &url);
+ void slotPermanentRedirection(TDEIO::Job*,const KURL&,const KURL& newUrl);
+ /// Called when the dir listing job is finished (for better or worst)
+ void slotListResult(TDEIO::Job *job);
+ /// Active the dir listing job
+ bool populateVfsList(const KURL& origin, bool showHidden);
+
+protected:
+ KURL origin_backup; //< used to backup the old URL when refreshing to a new one,
+ bool busy;
+ bool listError;
+};
+
+#endif
diff --git a/src/app/VFS/krarchandler.cpp b/src/app/VFS/krarchandler.cpp
new file mode 100644
index 0000000..faba80b
--- /dev/null
+++ b/src/app/VFS/krarchandler.cpp
@@ -0,0 +1,785 @@
+/***************************************************************************
+ krarchandler.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+// TQt includes
+#include <tqtextstream.h>
+// TDE includes
+#include <kprocess.h>
+#include <tdetempfile.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdeio/passdlg.h>
+#include <tqfile.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <tdeio/global.h>
+// Krusader includes
+#include "krarchandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../krservices.h"
+#include "../Dialogs/krpleasewait.h"
+
+static TQStringList arcProtocols = TQStringList::split(";", "tar;bzip;bzip2;gzip;krarc;zip;xz");
+
+TDEWallet::Wallet * KRarcHandler::wallet = 0;
+
+TQStringList KRarcHandler::supportedPackers() {
+ TQStringList packers;
+
+ // we will simply try to find the packers here..
+ if ( KrServices::cmdExist( "tar" ) ) packers.append( "tar" );
+ if ( KrServices::cmdExist( "gzip" ) ) packers.append( "gzip" );
+ if ( KrServices::cmdExist( "bzip2" ) ) packers.append( "bzip2" );
+ if ( KrServices::cmdExist( "unzip" ) ) packers.append( "unzip" );
+ if ( KrServices::cmdExist( "zip" ) ) packers.append( "zip" );
+ if ( KrServices::cmdExist( "lha" ) ) packers.append( "lha" );
+ if ( KrServices::cmdExist( "cpio" ) ) packers.append( "cpio" );
+ if ( KrServices::cmdExist( "unrar" ) ) packers.append( "unrar" );
+ if ( KrServices::cmdExist( "rar" ) ) packers.append( "rar" );
+ if ( KrServices::cmdExist( "arj" ) ) packers.append( "arj" );
+ if ( KrServices::cmdExist( "unarj" ) ) packers.append( "unarj" );
+ if ( KrServices::cmdExist( "unace" ) ) packers.append( "unace" );
+ if ( KrServices::cmdExist( "dpkg" ) ) packers.append( "dpkg" );
+ if ( KrServices::cmdExist( "7z" ) || KrServices::cmdExist( "7za" ) ) packers.append( "7z" );
+ if ( KrServices::cmdExist( "rpm" ) && KrServices::cmdExist( "rpm2cpio" ) ) packers.append( "rpm" );
+ if ( KrServices::cmdExist( "xz" ) ) packers.append( "xz" );
+ // kdDebug() << "Supported Packers:" << endl;
+ //TQStringList::Iterator it;
+ //for( it = packers.begin(); it != packers.end(); ++it )
+ // kdDebug() << *it << endl;
+
+ return packers;
+ }
+
+bool KRarcHandler::arcSupported( TQString type ) {
+ // lst will contain the supported unpacker list...
+ krConfig->setGroup( "Archives" );
+ TQStringList lst = krConfig->readListEntry( "Supported Packers" );
+
+ if ( type == "-zip" && lst.contains( "unzip" ) )
+ return true;
+ else if ( type == "-tar" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "-tbz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "-tgz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "-txz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "tarz" && lst.contains( "tar" ) )
+ return true;
+ else if ( type == "gzip" && lst.contains( "gzip" ) )
+ return true;
+ else if ( type == "zip2" && lst.contains( "bzip2" ) )
+ return true;
+ else if ( type == "-lha" && lst.contains( "lha" ) )
+ return true;
+ else if ( type == "-ace" && lst.contains( "unace" ) )
+ return true;
+ else if ( type == "-rpm" && lst.contains( "cpio" ) )
+ return true;
+ else if ( type == "cpio" && lst.contains( "cpio" ) )
+ return true;
+ else if ( type == "-rar" && ( lst.contains( "unrar" ) || lst.contains( "rar" ) ) )
+ return true;
+ else if ( type == "-arj" && ( lst.contains( "unarj" ) || lst.contains( "arj" ) ) )
+ return true;
+ else if ( type == "-deb" && ( lst.contains( "dpkg" ) && lst.contains( "tar" ) ) )
+ return true;
+ else if ( type == "-7z" && lst.contains( "7z" ) )
+ return true;
+ else if ( type == "-xz" && lst.contains( "xz" ) )
+ return true;
+ // not supported : (
+ return false;
+ }
+
+bool KRarcHandler::arcHandled( TQString type ) {
+ // first check if supported
+ if ( !arcSupported( type ) ) return false;
+
+ krConfig->setGroup( "Archives" );
+ if ( ( type == "-tgz" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) ||
+ ( type == "tarz" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) ||
+ ( type == "-tar" && krConfig->readBoolEntry( "Do Tar" , _DoTar ) ) ||
+ ( type == "-tbz" && krConfig->readBoolEntry( "Do BZip2", _DoBZip2 ) ) ||
+ ( type == "-txz" && krConfig->readBoolEntry( "Do Xz" , _DoXz ) ) ||
+ ( type == "gzip" && krConfig->readBoolEntry( "Do GZip" , _DoGZip ) ) ||
+ ( type == "zip2" && krConfig->readBoolEntry( "Do BZip2", _DoBZip2 ) ) ||
+ ( type == "-zip" && krConfig->readBoolEntry( "Do UnZip", _DoUnZip ) ) ||
+ ( type == "-lha" && krConfig->readBoolEntry( "Do Lha" , _DoUnZip ) ) ||
+ ( type == "-rar" && krConfig->readBoolEntry( "Do UnRar", _DoUnRar ) ) ||
+ ( type == "-arj" && krConfig->readBoolEntry( "Do UnArj", _DoUnarj ) ) ||
+ ( type == "-ace" && krConfig->readBoolEntry( "Do UnAce", _DoUnAce ) ) ||
+ ( type == "cpio" && krConfig->readBoolEntry( "Do RPM" , _DoRPM ) ) ||
+ ( type == "-rpm" && krConfig->readBoolEntry( "Do RPM" , _DoRPM ) ) ||
+ ( type == "-deb" && krConfig->readBoolEntry( "Do DEB" , _DoDEB ) ) ||
+ ( type == "-7z" && krConfig->readBoolEntry( "Do 7z" , _Do7z ) ) ||
+ ( type == "-xz" && krConfig->readBoolEntry( "Do Xz" , _DoXz ) ) )
+ return true;
+ else
+ return false;
+ }
+
+
+long KRarcHandler::arcFileCount( TQString archive, TQString type, TQString password ) {
+ int divideWith = 1;
+
+ // first check if supported
+ if ( !arcSupported( type ) ) return 0;
+
+ // bzip, gzip and xz archives contain only one file
+ if ( type == "zip2" || type == "gzip" || type == "-xz") return 1L;
+
+ // set the right lister to do the job
+ TQString lister;
+
+ if ( type == "-zip" ) lister = KrServices::fullPathName( "unzip" ) + " -ZTs";
+ else if ( type == "-tar" ) lister = KrServices::fullPathName( "tar" ) + " -tvf";
+ else if ( type == "-tgz" ) lister = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "tarz" ) lister = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "-tbz" ) lister = KrServices::fullPathName( "tar" ) + " -tjvf";
+ else if ( type == "-txz" ) lister = KrServices::fullPathName( "tar" ) + " -tJvf";
+ else if ( type == "-lha" ) lister = KrServices::fullPathName( "lha" ) + " l";
+ else if ( type == "-rar" ) lister = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " l -v";
+ else if ( type == "-ace" ) lister = KrServices::fullPathName( "unace" ) + " l";
+ else if ( type == "-arj" ) { if( KrServices::cmdExist( "arj" ) )
+ lister = KrServices::fullPathName( "arj" ) + " v -y -v",
+ divideWith = 4;
+ else
+ lister = KrServices::fullPathName( "unarj" ) + " l";
+ }
+ else if ( type == "-rpm" ) lister = KrServices::fullPathName( "rpm" ) + " --dump -lpq";
+ else if ( type == "-deb" ) lister = KrServices::fullPathName( "dpkg" ) + " -c";
+ else if ( type == "-7z" ) lister = KrServices::fullPathName( "7z" ) + " -y l";
+ else if ( type == "-xz" ) lister = KrServices::fullPathName( "xz" ) + " -l";
+ else return 0L;
+
+ if ( !password.isNull() ) {
+ if ( type == "-arj" )
+ lister += " -g'" + password + "'";
+ if ( type == "-ace" || type == "-rar" || type == "-7z" )
+ lister += " -p'" + password + "'";
+ }
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Counting files in archive" ), 0, true );
+
+ // count the number of files in the archive
+ long count = 1;
+ KTempFile tmpFile( /*"tmp"*/ TQString(), "krusader-unpack" ); // commented out as it created files in the current dir!
+ KrShellProcess list;
+ list << lister << KrServices::quote( archive ) << ">" << tmpFile.name() ;
+ if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ list<< "<" << "/dev/ptmx";
+ list.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( list.isRunning() ) {
+ usleep( 1000 );
+ tqApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ list.kill();
+ }
+ ; // busy wait - need to find something better...
+
+ krApp->stopWait();
+
+ if( !list.normalExit() || !checkStatus( type, list.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to list the content of the archive (%1)!" ).arg( archive ),
+ list.getErrorMsg(), i18n("Error" ) );
+ return 0;
+ }
+
+ TQTextStream *stream = tmpFile.textStream();
+ while ( stream && stream->readLine() != TQString() ) ++count;
+ tmpFile.unlink();
+
+ //make sure you call stopWait after this function return...
+ //krApp->stopWait();
+
+ return count / divideWith;
+ }
+
+bool KRarcHandler::unpack( TQString archive, TQString type, TQString password, TQString dest ) {
+ krConfig->setGroup( "Archives" );
+ if ( krConfig->readBoolEntry( "Test Before Unpack", _TestBeforeUnpack ) ) {
+ // test first - or be sorry later...
+ if ( type != "-rpm" && type != "-deb" && !test( archive, type, password, 0 ) ) {
+ KMessageBox::error( krApp, i18n( "Failed to unpack" ) + " \"" + archive + "\" !" );
+ return false;
+ }
+ }
+
+ // count the files in the archive
+ long count = arcFileCount( archive, type, password );
+ if ( count == 0 ) return false; // not supported
+ if ( count == 1 ) count = 0 ;
+
+ // choose the right packer for the job
+ TQString packer, cpioName = TQString();
+
+ // set the right packer to do the job
+ if ( type == "-zip" ) packer = KrServices::fullPathName( "unzip" ) + " -o" ;
+ else if ( type == "-tar" ) packer = KrServices::fullPathName( "tar" ) + " -xvf";
+ else if ( type == "-tgz" ) packer = KrServices::fullPathName( "tar" ) + " -xvzf";
+ else if ( type == "tarz" ) packer = KrServices::fullPathName( "tar" ) + " -xvzf";
+ else if ( type == "-tbz" ) packer = KrServices::fullPathName( "tar" ) + " -xjvf";
+ else if ( type == "-txz" ) packer = KrServices::fullPathName( "tar" ) + " -xJvf";
+ else if ( type == "gzip" ) packer = KrServices::fullPathName( "gzip" ) + " -cd";
+ else if ( type == "zip2" ) packer = KrServices::fullPathName( "bzip2" ) + " -cdk";
+ else if ( type == "-lha" ) packer = KrServices::fullPathName( "lha" ) + " xf";
+ else if ( type == "-rar" ) packer = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " -y x";
+ else if ( type == "-ace" ) packer = KrServices::fullPathName( "unace" ) + " x";
+ else if ( type == "-arj" ) packer = KrServices::cmdExist( "arj" ) ?
+ KrServices::fullPathName( "arj" ) + " -y -v x" :
+ KrServices::fullPathName( "unarj" ) + " x";
+ else if ( type == "-7z" ) packer = KrServices::fullPathName( "7z" ) + " -y x";
+ else if ( type == "-xz" ) packer = KrServices::fullPathName( "xz" ) + " -cdk";
+ else if ( type == "-rpm" ) {
+ TQString tempDir = locateLocal("tmp",TQString());
+
+ cpioName = tempDir+"/contents.cpio";
+
+ KrShellProcess cpio;
+ cpio << KrServices::fullPathName( "rpm2cpio" ) << " " + KrServices::quote( archive ) << " > " << cpioName;
+ cpio.start(TDEProcess::Block, TDEProcess::AllOutput );
+ if( !cpio.normalExit() || !checkStatus( "cpio", cpio.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to convert rpm (%1) to cpio!" ).arg( archive ),
+ cpio.getErrorMsg(), i18n("Error" ) );
+ return 0;
+ }
+
+ archive = cpioName;
+ packer = KrServices::fullPathName( "cpio" ) + " --force-local --no-absolute-filenames -iuvdF";
+ }
+ else if ( type == "-deb" ) {
+ TQString tempDir = locateLocal("tmp",TQString());
+
+ cpioName = tempDir+"/contents.tar";
+
+ KrShellProcess dpkg;
+ dpkg << KrServices::fullPathName( "dpkg" ) << " --fsys-tarfile " + KrServices::quote( archive ) << " > " << cpioName;
+ dpkg.start(TDEProcess::Block, TDEProcess::AllOutput );
+ if( !dpkg.normalExit() || !checkStatus( "-deb", dpkg.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to convert deb (%1) to tar!" ).arg( archive ),
+ dpkg.getErrorMsg(), i18n("Error" ) );
+ return 0;
+ }
+
+ archive = cpioName;
+ packer = KrServices::fullPathName( "tar" ) + " xvf ";
+ }
+ else return false;
+
+ if ( !password.isNull() ) {
+ if ( type == "-zip" )
+ packer += " -P '" + password + "'";
+ if ( type == "-arj" )
+ packer += " -g'" + password + "'";
+ if ( type == "-ace" || type == "-rar" || type == "-7z" )
+ packer += " -p'" + password + "'";
+ }
+
+ // unpack the files
+ KrShellProcess proc;
+ proc << packer << " " + KrServices::quote( archive );
+ if( type == "zip2" || type=="gzip" ){
+ TQString arcname = archive.mid(archive.findRev("/")+1);
+ if( arcname.contains(".") ) arcname = arcname.left(arcname.findRev("."));
+ proc << ">" << KrServices::quote( dest+"/"+arcname );
+ }
+ if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+
+ TQString save = getcwd( 0, 0 );
+ chdir( dest.local8Bit() );
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Unpacking File(s)" ), count, true );
+ if ( count != 0 ) {
+ connect( &proc, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+ if( type == "-rpm" )
+ connect( &proc, TQ_SIGNAL( receivedStderr( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+ }
+
+ // start the unpacking process
+ proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ tqApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+ chdir( save.local8Bit() );
+
+ if( !cpioName.isEmpty() )
+ TQFile( cpioName ).remove(); /* remove the cpio file */
+
+ // check the return value
+ if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to unpack %1!" ).arg( archive ),
+ krApp->wasWaitingCancelled() ? i18n( "User cancelled." ) :
+ proc.getErrorMsg(), i18n("Error" ) );
+ return false;
+ }
+ return true; // SUCCESS
+ }
+
+bool KRarcHandler::test( TQString archive, TQString type, TQString password, long count ) {
+ // choose the right packer for the job
+ TQString packer;
+
+ // set the right packer to do the job
+ if ( type == "-zip" ) packer = KrServices::fullPathName( "unzip" ) + " -t";
+ else if ( type == "-tar" ) packer = KrServices::fullPathName( "tar" ) + " -tvf";
+ else if ( type == "-tgz" ) packer = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "tarz" ) packer = KrServices::fullPathName( "tar" ) + " -tvzf";
+ else if ( type == "-tbz" ) packer = KrServices::fullPathName( "tar" ) + " -tjvf";
+ else if ( type == "-txz" ) packer = KrServices::fullPathName( "tar" ) + " -tJvf";
+ else if ( type == "gzip" ) packer = KrServices::fullPathName( "gzip" ) + " -tv";
+ else if ( type == "zip2" ) packer = KrServices::fullPathName( "bzip2" ) + " -tv";
+ else if ( type == "-rar" ) packer = KrServices::fullPathName( KrServices::cmdExist( "rar" ) ? "rar" : "unrar" ) + " t";
+ else if ( type == "-ace" ) packer = KrServices::fullPathName( "unace" ) + " t";
+ else if ( type == "-lha" ) packer = KrServices::fullPathName( "lha" ) + " t";
+ else if ( type == "-arj" ) packer = KrServices::fullPathName( KrServices::cmdExist( "arj" ) ? "arj" : "unarj" ) + " t";
+ else if ( type == "cpio" ) packer = KrServices::fullPathName( "cpio" ) + " --only-verify-crc -tvF" ;
+ else if ( type == "-7z" ) packer = KrServices::fullPathName( "7z" ) + " -y t";
+ else if ( type == "-xz" ) packer = KrServices::fullPathName( "xz" ) + " -tv";
+ else return false;
+
+ if ( !password.isNull() ) {
+ if ( type == "-zip" )
+ packer += " -P '" + password + "'";
+ if ( type == "-arj" )
+ packer += " -g'" + password + "'";
+ if ( type == "-ace" || type == "-rar" || type == "-7z" )
+ packer += " -p'" + password + "'";
+ }
+
+ // unpack the files
+ KrShellProcess proc;
+ proc << packer << KrServices::quote( archive );
+
+ if( type == "-ace" && TQFile( "/dev/ptmx" ).exists() ) // Don't remove, unace crashes if missing!!!
+ proc << "<" << "/dev/ptmx";
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Testing Archive" ), count, true );
+ if ( count != 0 ) connect( &proc, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+
+ // start the unpacking process
+ proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ tqApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+
+ // check the return value
+ if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) )
+ return false;
+
+ return true; // SUCCESS
+ }
+
+bool KRarcHandler::pack( TQStringList fileNames, TQString type, TQString dest, long count, TQMap<TQString,TQString> extraProps ) {
+ // set the right packer to do the job
+ TQString packer;
+
+ if ( type == "zip" ) { packer = KrServices::fullPathName( "zip" ) + " -ry"; type = "-zip"; }
+ else if ( type == "tar" ) { packer = KrServices::fullPathName( "tar" ) + " -cvf"; type = "-tar"; }
+ else if ( type == "tar.gz" ) { packer = KrServices::fullPathName( "tar" ) + " -cvzf"; type = "-tgz"; }
+ else if ( type == "tar.bz2" ) { packer = KrServices::fullPathName( "tar" ) + " -cvjf"; type = "-tbz"; }
+ else if ( type == "tar.xz" ) { packer = KrServices::fullPathName( "tar" ) + " -cvJf"; type = "-txz"; }
+ else if ( type == "rar" ) { packer = KrServices::fullPathName( "rar" ) + " -r a"; type = "-rar"; }
+ else if ( type == "lha" ) { packer = KrServices::fullPathName( "lha" ) + " a"; type = "-lha"; }
+ else if ( type == "arj" ) { packer = KrServices::fullPathName( "arj" ) + " -r -y a"; type = "-arj"; }
+ else if ( type == "7z" ) { packer = KrServices::fullPathName( "7z" ) + " -y a"; type = "-7z"; }
+ else if ( type == "xz" ) { packer = KrServices::fullPathName( "xz" ) + " -z"; type = "-xz"; }
+ else return false;
+
+ TQString password = TQString();
+
+ if( extraProps.count( "Password" ) > 0 ) {
+ password = extraProps[ "Password" ];
+
+ if ( !password.isNull() ) {
+ if ( type == "-zip" )
+ packer += " -P '" + password + "'";
+ else if ( type == "-arj" )
+ packer += " -g'" + password + "'";
+ else if ( type == "-ace" || type == "-7z" )
+ packer += " -p'" + password + "'";
+ else if ( type == "-rar" ) {
+ if( extraProps.count( "EncryptHeaders" ) > 0 )
+ packer += " -hp'" + password + "'";
+ else
+ packer += " -p'" + password + "'";
+ }
+ else
+ password = TQString();
+ }
+ }
+
+ if( extraProps.count( "VolumeSize" ) > 0 ) {
+ TQString sizeStr = extraProps[ "VolumeSize" ];
+ TDEIO::filesize_t size = sizeStr.toLongLong();
+
+ if( size >= 10000 ) {
+ if( type == "-arj" || type == "-rar" )
+ packer += TQString( " -v%1b" ).arg( sizeStr );
+ }
+ }
+
+ if( extraProps.count( "CompressionLevel" ) > 0 ) {
+ int level = extraProps[ "CompressionLevel" ].toInt() - 1;
+ if ( level < 0 )
+ level = 0;
+ if ( level > 8 )
+ level = 8;
+
+ if( type == "-rar" ) {
+ static const int rarLevels[] = { 0, 1, 2, 2, 3, 3, 4, 4, 5 };
+ packer += TQString( " -m%1" ).arg( rarLevels[ level ] );
+ }
+ else if( type == "-arj" ) {
+ static const int arjLevels[] = { 0, 4, 4, 3, 3, 2, 2, 1, 1 };
+ packer += TQString( " -m%1" ).arg( arjLevels[ level ] );
+ }
+ else if( type == "-zip" ) {
+ static const int zipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += TQString( " -%1" ).arg( zipLevels[ level ] );
+ }
+ else if( type == "-7z" ) {
+ static const int sevenZipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += TQString( " -mx%1" ).arg( sevenZipLevels[ level ] );
+ }
+ else if( type == "-xz" ) {
+ static const int xzLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 };
+ packer += TQString( " -%1" ).arg( xzLevels[ level ] );
+ }
+ }
+
+ if( extraProps.count( "CommandLineSwitches" ) > 0 )
+ packer += TQString( " %1" ).arg( extraProps[ "CommandLineSwitches" ] );
+
+ // prepare to pack
+ KrShellProcess proc;
+ proc << packer << KrServices::quote( dest );
+
+ for ( TQStringList::Iterator file = fileNames.begin(); file != fileNames.end(); ++file ) {
+ proc << KrServices::quote( *file );
+ }
+
+ // tell the user to wait
+ krApp->startWaiting( i18n( "Packing File(s)" ), count, true );
+ if ( count != 0 )
+ connect( &proc, TQ_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
+ krApp, TQ_SLOT( incProgress( TDEProcess*, char*, int ) ) );
+
+ // start the packing process
+ proc.start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput );
+ while ( proc.isRunning() ) {
+ usleep( 1000 );
+ tqApp->processEvents();
+ if( krApp->wasWaitingCancelled() )
+ proc.kill();
+ }
+ ; // busy wait - need to find something better...
+ krApp->stopWait();
+
+ // check the return value
+ if ( !proc.normalExit() || !checkStatus( type, proc.exitStatus() ) ) {
+ KMessageBox::detailedError (krApp, i18n( "Failed to pack %1!" ).arg( dest ),
+ krApp->wasWaitingCancelled() ? i18n( "User cancelled." ) : proc.getErrorMsg(),
+ i18n("Error" ) );
+ return false;
+ }
+
+ krConfig->setGroup( "Archives" );
+ if ( krConfig->readBoolEntry( "Test Archives", _TestArchives ) &&
+ !test( dest, type, password, count ) ) {
+ KMessageBox::error( krApp, i18n( "Failed to pack: " ) + dest, i18n( "Error" ) );
+ return false;
+ }
+ return true; // SUCCESS
+ }
+
+TQString KRarcHandler::getPassword( TQString path ) {
+ TQString password;
+
+ TQString key = "krarc-" + path;
+
+ if( !TDEWallet::Wallet::keyDoesNotExist(TDEWallet::Wallet::NetworkWallet(), TDEWallet::Wallet::PasswordFolder(), key ) ) {
+ if( !TDEWallet::Wallet::isOpen( TDEWallet::Wallet::NetworkWallet() ) && wallet != 0 ) {
+ delete wallet;
+ wallet = 0;
+ }
+ if( wallet == 0 )
+ wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet() );
+ if ( wallet && wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) ) {
+ wallet->setFolder( TDEWallet::Wallet::PasswordFolder() );
+ TQMap<TQString,TQString> map;
+ if ( wallet->readMap( key, map ) == 0 ) {
+ TQMap<TQString, TQString>::ConstIterator it = map.find( "password" );
+ if ( it != map.end() )
+ password = it.data();
+ }
+ }
+ }
+
+ bool keep = true;
+ TQString user = "archive";
+ TDEIO::PasswordDialog passDlg( i18n("This archive is encrypted, please supply the password:"),
+ user, true );
+ passDlg.setPassword( password );
+ if (passDlg.exec() == TDEIO::PasswordDialog::Accepted) {
+ password = passDlg.password();
+ if ( keep ) {
+ if( !TDEWallet::Wallet::isOpen( TDEWallet::Wallet::NetworkWallet() ) && wallet != 0 ) {
+ delete wallet;
+ wallet = 0;
+ }
+ if ( !wallet )
+ wallet = TDEWallet::Wallet::openWallet( TDEWallet::Wallet::NetworkWallet() );
+ if ( wallet ) {
+ bool ok = true;
+ if ( !wallet->hasFolder( TDEWallet::Wallet::PasswordFolder() ) )
+ ok = wallet->createFolder( TDEWallet::Wallet::PasswordFolder() );
+ if ( ok ) {
+ wallet->setFolder( TDEWallet::Wallet::PasswordFolder() );
+ TQMap<TQString,TQString> map;
+ map.insert( "login", "archive" );
+ map.insert( "password", password );
+ wallet->writeMap( key, map );
+ }
+ }
+ }
+ return password;
+ }
+
+ return "";
+}
+
+bool KRarcHandler::isArchive(const KURL& url) {
+ TQString protocol = url.protocol();
+ if (arcProtocols.find(protocol) != arcProtocols.end())
+ return true;
+ else return false;
+}
+
+TQString KRarcHandler::getType( bool &encrypted, TQString fileName, TQString mime, bool checkEncrypted ) {
+ TQString result = detectArchive( encrypted, fileName, checkEncrypted );
+ if( result.isNull() )
+ result = mime;
+ else
+ result = "-" + result;
+
+ if (result.endsWith("-7z"))
+ {
+ result = "-7z";
+ }
+ if (result.endsWith("-xz"))
+ {
+ result = "-xz";
+ }
+
+ return result.right( 4 );
+}
+
+
+bool KRarcHandler::checkStatus( TQString type, int exitCode ) {
+ if( type == "-zip" || type == "-rar" || type == "-7z" )
+ return exitCode == 0 || exitCode == 1;
+ else if( type == "-ace" || type == "zip2" || type == "-lha" || type == "-rpm" || type == "cpio" ||
+ type == "-tar" || type == "tarz" || type == "-tbz" || type == "-tgz" || type == "-arj" ||
+ type == "-deb" || type == "-txz" || type == "-xz")
+ return exitCode == 0;
+ else if (type == "gzip" || type == "-xz")
+ return exitCode == 0 || exitCode == 2;
+ else
+ return exitCode == 0;
+}
+
+struct AutoDetectParams {
+ TQString type;
+ int location;
+ TQString detectionString;
+};
+
+TQString KRarcHandler::detectArchive( bool &encrypted, TQString fileName, bool checkEncrypted ) {
+ static AutoDetectParams autoDetectParams[] = {{"zip", 0, "PK\x03\x04"},
+ {"rar", 0, "Rar!\x1a" },
+ {"arj", 0, "\x60\xea" },
+ {"rpm", 0, "\xed\xab\xee\xdb"},
+ {"ace", 7, "**ACE**" },
+ {"bzip2",0, "\x42\x5a\x68\x39\x31" },
+ {"gzip", 0, "\x1f\x8b"},
+ {"deb", 0, "!<arch>\ndebian-binary " },
+ {"7z", 0, "7z\xbc\xaf\x27\x1c" },
+ {"xz", 0, "\xfd" "7zXZ\x00" } };
+ static int autoDetectElems = sizeof( autoDetectParams ) / sizeof( AutoDetectParams );
+
+ encrypted = false;
+
+ TQFile arcFile( fileName );
+ if ( arcFile.open( IO_ReadOnly ) ) {
+ char buffer[ 1024 ];
+ long sizeMax = arcFile.readBlock( buffer, sizeof( buffer ) );
+ arcFile.close();
+
+ for( int i=0; i < autoDetectElems; i++ ) {
+ TQString detectionString = autoDetectParams[ i ].detectionString;
+ int location = autoDetectParams[ i ].location;
+
+ int endPtr = detectionString.length() + location;
+ if( endPtr > sizeMax )
+ continue;
+
+ unsigned int j=0;
+ for(; j != detectionString.length(); j++ ) {
+ if( detectionString[ j ] == '?' )
+ continue;
+ if( buffer[ location + j ] != detectionString[ j ] )
+ break;
+ }
+
+ if( j == detectionString.length() ) {
+ TQString type = autoDetectParams[ i ].type;
+ if( type == "bzip2" || type == "gzip" ) {
+ KTar tapeArchive( fileName );
+ if( tapeArchive.open( IO_ReadOnly ) ) {
+ tapeArchive.close();
+ if( type == "bzip2" )
+ type = "tbz";
+ else
+ type = "tgz";
+ }
+ }
+ else if( type == "zip" )
+ encrypted = (buffer[6] & 1);
+ else if( type == "arj" ) {
+ if( sizeMax > 4 ) {
+ long headerSize = ((unsigned char *)buffer)[ 2 ] + 256*((unsigned char *)buffer)[ 3 ];
+ long fileHeader = headerSize + 10;
+ if( fileHeader + 9 < sizeMax && buffer[ fileHeader ] == (char)0x60 && buffer[ fileHeader + 1 ] == (char)0xea )
+ encrypted = (buffer[ fileHeader + 8 ] & 1 );
+ }
+ }
+ else if( type == "rar" ) {
+ if( sizeMax > 13 && buffer[ 9 ] == (char)0x73 ) {
+ if( buffer[ 10 ] & 0x80 ) { // the header is encrypted?
+ encrypted = true;
+ } else {
+ long offset = 7;
+ long mainHeaderSize = ((unsigned char *)buffer)[ offset+5 ] + 256*((unsigned char *)buffer)[ offset+6 ];
+ offset += mainHeaderSize;
+ while( offset + 10 < sizeMax ) {
+ long headerSize = ((unsigned char *)buffer)[ offset+5 ] + 256*((unsigned char *)buffer)[ offset+6 ];
+ bool isDir = (buffer[ offset+7 ] == '\0' ) && (buffer[ offset+8 ] == '\0' ) &&
+ (buffer[ offset+9 ] == '\0' ) && (buffer[ offset+10 ] == '\0' );
+
+ if( buffer[ offset + 2 ] != (char)0x74 )
+ break;
+ if( !isDir ) {
+ encrypted = ( buffer[ offset + 3 ] & 4 ) != 0;
+ break;
+ }
+ offset += headerSize;
+ }
+ }
+ }
+ }
+ else if( type == "ace" ) {
+ long offset = 0;
+ long mainHeaderSize = ((unsigned char *)buffer)[ offset+2 ] + 256*((unsigned char *)buffer)[ offset+3 ] + 4;
+ offset += mainHeaderSize;
+ while( offset + 10 < sizeMax ) {
+ long headerSize = ((unsigned char *)buffer)[ offset+2 ] + 256*((unsigned char *)buffer)[ offset+3 ] + 4;
+ bool isDir = (buffer[ offset+11 ] == '\0' ) && (buffer[ offset+12 ] == '\0' ) &&
+ (buffer[ offset+13 ] == '\0' ) && (buffer[ offset+14 ] == '\0' );
+
+ if( buffer[ offset + 4 ] != (char)0x01 )
+ break;
+ if( !isDir ) {
+ encrypted = ( buffer[ offset + 6 ] & 64 ) != 0;
+ break;
+ }
+ offset += headerSize;
+ }
+ }
+ else if( type == "7z" ) {
+ if( checkEncrypted ) { // encryption check is expensive
+ // check only if it's necessary
+ Kr7zEncryptionChecker proc;
+ proc << KrServices::fullPathName( "7z" ) << " -y t";
+ proc << KrServices::quote( fileName );
+ proc.start(TDEProcess::Block,TDEProcess::AllOutput);
+ encrypted = proc.isEncrypted();
+ }
+ }
+ else if( type == "xz" && (fileName.endsWith(".tar.xz") || fileName.endsWith(".txz")) )
+ type = "txz";
+ return type;
+ }
+ }
+
+ if( sizeMax >= 512 ) {
+ /* checking if it's a tar file */
+ unsigned checksum = 32*8;
+ char chksum[ 9 ];
+ for( int i=0; i != 512; i++ )
+ checksum += ((unsigned char *)buffer)[ i ];
+ for( int i=148; i != 156; i++ )
+ checksum -= ((unsigned char *)buffer)[ i ];
+ sprintf( chksum, "0%o", checksum );
+ if( !memcmp( buffer + 148, chksum, strlen( chksum ) ) ) {
+ int k = strlen( chksum );
+ for(; k < 8; k++ )
+ if( buffer[148+k] != 0 && buffer[148+k] != 32 )
+ break;
+ if( k==8 )
+ return "tar";
+ }
+ }
+ }
+
+ return TQString();
+}
+
+#include "krarchandler.moc"
+
diff --git a/src/app/VFS/krarchandler.h b/src/app/VFS/krarchandler.h
new file mode 100644
index 0000000..506162a
--- /dev/null
+++ b/src/app/VFS/krarchandler.h
@@ -0,0 +1,151 @@
+/***************************************************************************
+ krarchandler.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description: this class will supply static archive handling functions.
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRARCHANDLER_H
+#define KRARCHANDLER_H
+
+#include <tqstringlist.h>
+#include <tqobject.h>
+#include <kprocess.h>
+#include <kurl.h>
+#include <tdewallet.h>
+
+class KRarcHandler: public TQObject {
+ TQ_OBJECT
+
+public:
+ // return the number of files in the archive
+ static long arcFileCount(TQString archive, TQString type, TQString password);
+ // unpack an archive to destination directory
+ static bool unpack(TQString archive, TQString type, TQString password, TQString dest );
+ // pack an archive to destination directory
+ static bool pack(TQStringList fileNames, TQString type, TQString dest, long count, TQMap<TQString,TQString> extraProps );
+ // test an archive
+ static bool test(TQString archive, TQString type, TQString password, long count = 0L );
+ // true - if the right unpacker exist in the system
+ static bool arcSupported(TQString type);
+ // true - if supported and the user want us to handle this kind of archive
+ static bool arcHandled(TQString type);
+ // return the a list of supported packers
+ static TQStringList supportedPackers();
+ // true - if the url is an archive (ie: tar:/home/test/file.tar.bz2)
+ static bool isArchive(const KURL& url);
+ // used to determine the type of the archive
+ static TQString getType( bool &encrypted, TQString fileName, TQString mime, bool checkEncrypted = true );
+ // queries the password from the user
+ static TQString getPassword( TQString path );
+ // detects the archive type
+ static TQString detectArchive( bool &encrypted, TQString fileName, bool checkEncrypted = true );
+private:
+ // checks if the returned status is correct
+ static bool checkStatus( TQString type, int exitCode );
+
+ static TDEWallet::Wallet * wallet;
+};
+
+class KrShellProcess : public KShellProcess {
+ TQ_OBJECT
+
+public:
+ KrShellProcess() : KShellProcess(), errorMsg( TQString() ), outputMsg( TQString() ) {
+ connect(this,TQ_SIGNAL(receivedStderr(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedErrorMsg(TDEProcess*,char*,int)) );
+ connect(this,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ this,TQ_SLOT(receivedOutputMsg(TDEProcess*,char*,int)) );
+ }
+
+ TQString getErrorMsg() {
+ if( errorMsg.stripWhiteSpace().isEmpty() )
+ return outputMsg.right( 500 );
+ else
+ return errorMsg.right( 500 );
+ }
+
+public slots:
+ void receivedErrorMsg(TDEProcess*, char *buf, int len) {
+ errorMsg += TQString::fromLocal8Bit( buf, len );
+ if( errorMsg.length() > 500 )
+ errorMsg = errorMsg.right( 500 );
+ receivedOutputMsg( 0, buf, len );
+ }
+
+ void receivedOutputMsg(TDEProcess*, char *buf, int len) {
+ outputMsg += TQString::fromLocal8Bit( buf, len );
+ if( outputMsg.length() > 500 )
+ outputMsg = outputMsg.right( 500 );
+ }
+
+private:
+ TQString errorMsg;
+ TQString outputMsg;
+};
+
+class Kr7zEncryptionChecker : public KrShellProcess {
+ TQ_OBJECT
+
+
+public:
+ Kr7zEncryptionChecker() : KrShellProcess(), encrypted( false ), lastData() {
+ connect(this,TQ_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
+ this,TQ_SLOT(processStdout(TDEProcess*,char*,int)) );
+ }
+
+public slots:
+ void processStdout( TDEProcess *proc,char *buf,int len ) {
+ TQByteArray d(len);
+ d.setRawData(buf,len);
+ TQString data = TQString( d );
+ d.resetRawData(buf,len);
+
+ TQString checkable = lastData + data;
+
+ TQStringList lines = TQStringList::split( '\n', checkable );
+ lastData = lines[ lines.count() - 1 ];
+ for( unsigned i=0; i != lines.count(); i++ ) {
+ TQString line = lines[ i ].stripWhiteSpace().lower();
+ int ndx = line.find( "testing" );
+ if( ndx >=0 )
+ line.truncate( ndx );
+ if( line.isEmpty() )
+ continue;
+
+ if( line.contains( "password" ) && line.contains( "enter" ) ) {
+ encrypted = true;
+ proc->kill();
+ }
+ }
+ }
+
+ bool isEncrypted() { return encrypted; }
+private:
+ bool encrypted;
+ TQString lastData;
+};
+
+#endif
diff --git a/src/app/VFS/krdirwatch.cpp b/src/app/VFS/krdirwatch.cpp
new file mode 100644
index 0000000..fe4e2de
--- /dev/null
+++ b/src/app/VFS/krdirwatch.cpp
@@ -0,0 +1,124 @@
+/***************************************************************************
+ krdirwatch.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u rc e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "krdirwatch.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <kdebug.h>
+#include "krpermhandler.h"
+#include "tqstringlist.h"
+#include <tqdir.h>
+
+KRdirWatch::KRdirWatch(int msec,bool dirOnly):
+ delay(msec),t(this), changed(false) {
+ if(dirOnly) dir.setFilter( TQDir::Dirs | TQDir::Hidden | TQDir::NoSymLinks );
+ watched.setAutoDelete(true);
+ connect(&t,TQ_SIGNAL(timeout()),this, TQ_SLOT(checkDirs()));
+ startScan();
+}
+
+KRdirWatch::~KRdirWatch(){
+ clearList();
+ stopScan();
+}
+
+void KRdirWatch::removeDir(TQString path){
+ t.stop();
+ for ( it = watched.first(); it != 0; )
+ if (it->path == path) watched.remove();
+ else it = watched.next();
+ if (!stopped) startScan();
+}
+
+void KRdirWatch::addDir(TQString path, bool checkPermissions){
+ t.stop();
+
+ krDirEntry* temp = new krDirEntry;
+ if (!dir.cd(path)){ // if it's not a dir or don't exist - don't add it
+ //kdDebug() << "KRDirWatch: can't watch " + path +", (don't exist)" << endl;
+ return;
+ }
+ if( checkPermissions ) {
+ // if we can't read it - don't bother
+ if (getgid() != 0 && !KRpermHandler::fileReadable(path) ){
+ //kdDebug() << "KRDirWatch: can't watch " + path +", (not readable)" << endl;
+ return;
+ }
+ if (!KRpermHandler::fileWriteable(path) ){ // read-only directorys can't be changed
+ //kdDebug() << "KRDirWatch: not watching " + path +", (read-only directory)" << endl;
+ return;
+ }
+ }
+ qfi.setFile(path);
+
+ temp->path = dir.path();
+ temp->count = dir.entryList(TQDir::All | TQDir::AccessMask).count();
+ temp->lastModified = qfi.lastModified();
+
+ watched.append(temp);
+ if (!stopped) startScan();
+}
+
+// here we do the actual checking
+void KRdirWatch::checkDirs(){
+ t.stop();
+
+ TQString path;
+ unsigned long count;
+ TQDateTime dt;
+
+ for ( it = watched.first(); it != 0; it = watched.next() ){
+ path = it->path;
+ qfi.setFile(path);
+ if (!dir.cd(path)){
+ clearList();
+ emit dirty();
+ return;
+ }
+ dt = qfi.lastModified();
+ count = dir.entryList(TQDir::All | TQDir::AccessMask).count();
+ // check for changes
+ if(it->lastModified!=dt || it->count!=count){
+ changed = true;
+ it->lastModified=dt;
+ it->count=count;
+ startScan();
+ return;
+ }
+ if(changed){
+ changed = false;
+ clearList();
+ emit dirty();
+ return;
+ }
+ }
+ if (!stopped) startScan();
+}
+
+#include "krdirwatch.moc"
diff --git a/src/app/VFS/krdirwatch.h b/src/app/VFS/krdirwatch.h
new file mode 100644
index 0000000..e99618b
--- /dev/null
+++ b/src/app/VFS/krdirwatch.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ krdirwatch.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KRDIRWATCH_H
+#define KRDIRWATCH_H
+
+#include <tqobject.h>
+#include <tqstring.h>
+#include <tqptrlist.h>
+#include <tqtimer.h>
+#include <tqdatetime.h>
+#include <tqdir.h>
+
+
+typedef struct krDirEntry_s{
+ TQString path;
+ unsigned long count; // number of files
+ TQDateTime lastModified;
+} krDirEntry ;
+
+class KRdirWatch : public TQObject {
+ TQ_OBJECT
+
+public:
+ KRdirWatch(int msec = 250 , bool dirOnly = false );
+ ~KRdirWatch();
+ void addDir(TQString path,bool checkPermissions = true );
+ void removeDir(TQString path);
+
+ inline void clearList(){watched.clear();}
+ inline void startScan(){t.start(delay);stopped=false;}
+ inline void stopScan() {t.stop(); stopped=true;}
+
+public slots:
+ void checkDirs(); // here we do the actual checking
+
+signals:
+ void dirty();
+
+protected:
+ int delay; // time in msec between updates
+ TQPtrList<krDirEntry> watched;
+ TQTimer t;
+ TQDir dir;
+ TQFileInfo qfi;
+ krDirEntry* it;
+ bool changed; // true if something happend to the watched dirs
+ bool stopped; // true if the watcher is stopped
+};
+
+#endif
diff --git a/src/app/VFS/krpermhandler.cpp b/src/app/VFS/krpermhandler.cpp
new file mode 100644
index 0000000..aa955aa
--- /dev/null
+++ b/src/app/VFS/krpermhandler.cpp
@@ -0,0 +1,355 @@
+/***************************************************************************
+ krpermhandler.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+---------------------------------------------------------------------------
+ Description
+***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+***************************************************************************
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+***************************************************************************/
+
+
+// System includes
+#include <unistd.h>
+#include <math.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <time.h>
+#include <tdelocale.h>
+#include <tdeglobal.h>
+#include <klargefile.h>
+// TQt includes
+#include <tqdatetime.h>
+#include <tqdir.h>
+// krusader includes
+#include <tdeversion.h>
+#include "krpermhandler.h"
+#include "../resources.h"
+
+TQDict<uid_t> *KRpermHandler::passwdCache = 0L;
+TQDict<gid_t> *KRpermHandler::groupCache = 0L;
+TQIntDict<char> *KRpermHandler::currentGroups = 0L;
+TQIntDict<TQString> *KRpermHandler::uidCache = 0L;
+TQIntDict<TQString> *KRpermHandler::gidCache = 0L;
+
+char KRpermHandler::writeable( TQString perm, gid_t gid, uid_t uid, int rwx ) {
+ if( rwx != -1 )
+ return ( rwx & W_OK ) ? ALLOWED_PERM : NO_PERM;
+ // root override
+ if ( getuid() == 0 )
+ return ALLOWED_PERM;
+ // first check other permissions.
+ if ( perm[ 8 ] != '-' ) return ALLOWED_PERM;
+ // now check group permission
+ if ( ( perm[ 5 ] != '-' ) && ( currentGroups->find( gid ) ) )
+ return ALLOWED_PERM;
+ // the last chance - user permissions
+ if ( ( perm[ 2 ] != '-' ) && ( uid == getuid() ) )
+ return ALLOWED_PERM;
+ // sorry !
+ return NO_PERM;
+}
+
+char KRpermHandler::readable( TQString perm, gid_t gid, uid_t uid, int rwx ) {
+ if( rwx != -1 )
+ return ( rwx & R_OK ) ? ALLOWED_PERM : NO_PERM;
+ // root override
+ if ( getuid() == 0 )
+ return ALLOWED_PERM;
+ // first check other permissions.
+ if ( perm[ 7 ] != '-' ) return ALLOWED_PERM;
+ // now check group permission
+ if ( ( perm[ 4 ] != '-' ) && ( currentGroups->find( gid ) ) )
+ return ALLOWED_PERM;
+ // the last chance - user permissions
+ if ( ( perm[ 1 ] != '-' ) && ( uid == getuid() ) )
+ return ALLOWED_PERM;
+ // sorry !
+ return NO_PERM;
+}
+
+char KRpermHandler::executable( TQString perm, gid_t gid, uid_t uid, int rwx ) {
+ if( rwx != -1 )
+ return ( rwx & X_OK ) ? ALLOWED_PERM : NO_PERM;
+ // first check other permissions.
+ if ( perm[ 9 ] != '-' ) return ALLOWED_PERM;
+ // now check group permission
+ if ( ( perm[ 6 ] != '-' ) && ( currentGroups->find( gid ) ) )
+ return ALLOWED_PERM;
+ // the last chance - user permissions
+ if ( ( perm[ 3 ] != '-' ) && ( uid == getuid() ) )
+ return ALLOWED_PERM;
+ // sorry !
+ return NO_PERM;
+}
+
+bool KRpermHandler::fileWriteable( TQString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ TQString perm = mode2TQString( m );
+ return writeable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+bool KRpermHandler::fileReadable( TQString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ TQString perm = mode2TQString( m );
+ return readable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+bool KRpermHandler::fileExecutable( TQString localFile ) {
+ KDE_struct_stat stat_p;
+ if ( KDE_stat( localFile.local8Bit(), &stat_p ) == -1 ) return false;
+ mode_t m = stat_p.st_mode;
+ TQString perm = mode2TQString( m );
+ return executable( perm, stat_p.st_gid, stat_p.st_uid );
+}
+
+TQString KRpermHandler::mode2TQString( mode_t m ) {
+ char perm[ 11 ];
+ for( int i=0; i != 10; i++ )
+ perm[ i ] = '-';
+ perm[ 10 ] = 0;
+
+ if ( S_ISLNK( m ) ) perm[ 0 ] = 'l'; // check for symLink
+ if ( S_ISDIR( m ) ) perm[ 0 ] = 'd'; // check for directory
+
+ //ReadUser = 0400, WriteUser = 0200, ExeUser = 0100, Suid = 04000
+ if ( m & 0400 ) perm[ 1 ] = 'r';
+ if ( m & 0200 ) perm[ 2 ] = 'w';
+ if ( m & 0100 ) perm[ 3 ] = 'x';
+ if ( m & 04000 ) perm[ 3 ] = 's';
+ //ReadGroup = 0040, WriteGroup = 0020, ExeGroup = 0010, Gid = 02000
+ if ( m & 0040 ) perm[ 4 ] = 'r';
+ if ( m & 0020 ) perm[ 5 ] = 'w';
+ if ( m & 0010 ) perm[ 6 ] = 'x';
+ if ( m & 02000 ) perm[ 6 ] = 's';
+ //ReadOther = 0004, WriteOther = 0002, ExeOther = 0001, Sticky = 01000
+ if ( m & 0004 ) perm[ 7 ] = 'r';
+ if ( m & 0002 ) perm[ 8 ] = 'w';
+ if ( m & 0001 ) perm[ 9 ] = 'x';
+ if ( m & 01000 ) perm[ 9 ] = 't';
+
+ return TQString( perm );
+}
+
+void KRpermHandler::init() {
+ // set the umask to 022
+ //umask( 022 );
+
+ // 50 groups should be enough
+ gid_t groupList[ 50 ];
+ int groupNo = getgroups( 50, groupList );
+
+ // init the groups and user caches
+ passwdCache = new TQDict<uid_t>( 317 );
+ groupCache = new TQDict<gid_t>( 317 );
+ currentGroups = new TQIntDict<char>( 317 );
+ uidCache = new TQIntDict<TQString>( 317 );
+ gidCache = new TQIntDict<TQString>( 317 );
+
+
+ passwdCache->setAutoDelete( true );
+ groupCache->setAutoDelete( true );
+ currentGroups->setAutoDelete( true );
+ uidCache->setAutoDelete( true );
+ gidCache->setAutoDelete( true );
+
+ // fill the UID cache
+ struct passwd *pass;
+ uid_t* uid_temp;
+ while ( ( pass = getpwent() ) != 0L ) {
+ uid_temp = new uid_t( pass->pw_uid );
+ passwdCache->insert( pass->pw_name, uid_temp );
+ uidCache->insert( pass->pw_uid, new TQString( pass->pw_name ) );
+ }
+ delete pass;
+ endpwent();
+
+ // fill the GID cache
+ struct group *gr;
+ gid_t* gid_temp;
+ while ( ( gr = getgrent() ) != 0L ) {
+ gid_temp = new gid_t( gr->gr_gid );
+ groupCache->insert( gr->gr_name, gid_temp );
+ gidCache->insert( gr->gr_gid, new TQString( gr->gr_name ) );
+ }
+ delete gr;
+ endgrent();
+
+ // fill the groups for the current user
+ char * t = new char( 1 );
+ for ( int i = 0; i < groupNo; ++i ) {
+ currentGroups->insert( groupList[ i ], t );
+ }
+ // just to be sure add the effective gid...
+ currentGroups->insert( getegid(), t );
+}
+
+char KRpermHandler::ftpWriteable ( TQString fileOwner, TQString userName, TQString perm ) {
+ // first check other permissions.
+ if ( perm[ 8 ] != '-' ) return ALLOWED_PERM;
+ // can't check group permission !
+ // so check the user permissions
+ if ( ( perm[ 2 ] != '-' ) && ( fileOwner == userName ) )
+ return ALLOWED_PERM;
+ if ( ( perm[ 2 ] != '-' ) && ( userName.isEmpty() ) )
+ return UNKNOWN_PERM;
+ if ( perm[ 5 ] != '-' ) return UNKNOWN_PERM;
+ return NO_PERM;
+}
+
+char KRpermHandler::ftpReadable ( TQString fileOwner, TQString userName, TQString perm ) {
+ // first check other permissions.
+ if ( perm[ 7 ] != '-' ) return ALLOWED_PERM;
+ // can't check group permission !
+ // so check the user permissions
+ if ( ( perm[ 1 ] != '-' ) && ( fileOwner == userName ) )
+ return ALLOWED_PERM;
+ if ( ( perm[ 1 ] != '-' ) && ( userName.isEmpty() ) )
+ return UNKNOWN_PERM;
+ if ( perm[ 4 ] != '-' ) return UNKNOWN_PERM;
+ return NO_PERM;
+}
+
+char KRpermHandler::ftpExecutable( TQString fileOwner, TQString userName, TQString perm ) {
+ // first check other permissions.
+ if ( perm[ 9 ] != '-' ) return ALLOWED_PERM;
+ // can't check group permission !
+ // so check the user permissions
+ if ( ( perm[ 3 ] != '-' ) && ( fileOwner == userName ) )
+ return ALLOWED_PERM;
+ if ( ( perm[ 3 ] != '-' ) && ( userName.isEmpty() ) )
+ return UNKNOWN_PERM;
+ if ( perm[ 6 ] != '-' ) return UNKNOWN_PERM;
+ return NO_PERM;
+}
+
+bool KRpermHandler::dirExist( TQString path ) {
+ DIR * dir = opendir( path.local8Bit() );
+ if ( !dir ) return false;
+ closedir( dir ); // bug fix Karai Csaba (ckarai)
+ return true;
+}
+
+bool KRpermHandler::fileExist( TQString fullPath ) {
+ if ( fullPath.right( 1 ) == "/" ) fullPath = fullPath.left( fullPath.length() - 1 ) ;
+ if ( fullPath.left( 1 ) != "/" ) return fileExist( "/", fullPath );
+ return fileExist( fullPath.left( fullPath.findRev( "/" ) ) ,
+ fullPath.mid( fullPath.findRev( "/" ) + 1 ) );
+}
+
+bool KRpermHandler::fileExist( TQString path, TQString name ) {
+ if ( TQDir( path ).exists( name ) ) return true;
+ DIR* dir = opendir( path.local8Bit() );
+ if ( !dir ) return false;
+ struct dirent* dirEnt;
+ while ( ( dirEnt = readdir( dir ) ) ) {
+ if ( dirEnt->d_name == name ) {
+ closedir( dir );
+ return true;
+ }
+ }
+ closedir( dir );
+ return false;
+}
+
+TQString KRpermHandler::parseSize( TDEIO::filesize_t val ) {
+#if (TDE_VERSION_MAJOR >= 3) && (TDE_VERSION_MINOR >= 5)
+ return TDEGlobal::locale()->formatNumber(TQString::number(val), false, 0);
+#else
+ return TDEGlobal::locale()->formatNumber(val);
+#endif
+
+#if 0
+ TQString temp;
+ temp.sprintf( "%llu", val );
+ if ( temp.length() <= 3 ) return temp;
+ unsigned int i = temp.length() % 3;
+ if ( i == 0 ) i = 3;
+ TQString size = temp.left( i ) + ",";
+ while ( i + 3 < temp.length() ) {
+ size = size + temp.mid( i, 3 ) + ",";
+ i += 3;
+ }
+ size = size + temp.right( 3 );
+
+ return size;
+#endif
+}
+
+TQString KRpermHandler::date2qstring( TQString date ) {
+ TQString temp;
+ int year;
+
+ year = date[ 6 ].digitValue() * 10 + date[ 7 ].digitValue();
+ year > 80 ? year += 1900 : year += 2000;
+
+ temp.sprintf( "%d", year );
+ temp = temp + date[ 3 ] + date[ 4 ] + date[ 0 ] + date[ 1 ] + date[ 9 ] + date[ 10 ] + date[ 12 ] + date[ 13 ];
+
+ return temp;
+}
+
+time_t KRpermHandler::TQString2time( TQString date ) {
+ struct tm t;
+ t.tm_sec = 0;
+ t.tm_min = ( TQString( date[ 12 ] ) + TQString( date[ 13 ] ) ).toInt();
+ t.tm_hour = ( TQString( date[ 9 ] ) + TQString( date[ 10 ] ) ).toInt();
+ t.tm_mday = ( TQString( date[ 0 ] ) + TQString( date[ 1 ] ) ).toInt();
+ t.tm_mon = ( TQString( date[ 3 ] ) + TQString( date[ 4 ] ) ).toInt() - 1;
+ t.tm_year = ( TQString( date[ 6 ] ) + TQString( date[ 7 ] ) ).toInt();
+ if ( t.tm_year < 70 ) t.tm_year += 100;
+ t.tm_isdst = -1; // daylight saving time information isn't availble
+
+ return mktime( &t );
+}
+
+gid_t KRpermHandler::group2gid( TQString group ) {
+ gid_t * gid = groupCache->find( group );
+ if ( gid ) return * gid;
+ return getgid();
+}
+uid_t KRpermHandler::user2uid ( TQString user ) {
+ uid_t * uid = passwdCache->find( user );
+ if ( uid ) return * uid;
+ return getuid();
+}
+
+TQString KRpermHandler::gid2group( gid_t groupId ) {
+ TQString * group = gidCache->find( groupId );
+ if ( group ) return * group;
+ return TQString( "???" );
+}
+
+TQString KRpermHandler::uid2user ( uid_t userId ) {
+ TQString * user = uidCache->find( userId );
+ if ( user ) return * user;
+ return TQString( "???" );
+}
+
diff --git a/src/app/VFS/krpermhandler.h b/src/app/VFS/krpermhandler.h
new file mode 100644
index 0000000..02a2928
--- /dev/null
+++ b/src/app/VFS/krpermhandler.h
@@ -0,0 +1,89 @@
+/***************************************************************************
+ krpermhandler.h
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#ifndef KRPERMHANDLER_H
+#define KRPERMHANDLER_H
+
+#include <tqstring.h>
+#include <tqfileinfo.h>
+#include <sys/types.h>
+#include <tqdict.h>
+#include <tqintdict.h>
+#include <tdeio/global.h>
+
+#define NO_PERM 0
+#define UNKNOWN_PERM 1
+#define ALLOWED_PERM 2
+
+class KRpermHandler {
+public:
+ KRpermHandler(){}
+ ~KRpermHandler(){}
+
+ static void init();
+
+ static gid_t group2gid(TQString group);
+ static uid_t user2uid (TQString user);
+
+ static TQString gid2group(gid_t groupId);
+ static TQString uid2user (uid_t userId);
+
+ static char writeable (TQString perm, gid_t gid, uid_t uid, int rwx=-1);
+ static char readable (TQString perm, gid_t gid, uid_t uid, int rwx=-1);
+ static char executable(TQString perm, gid_t gid, uid_t uid, int rwx=-1);
+
+ static bool fileWriteable (TQString localFile);
+ static bool fileReadable (TQString localFile);
+ static bool fileExecutable(TQString localFile);
+
+ static char ftpWriteable ( TQString fileOwner, TQString userName, TQString perm );
+ static char ftpReadable ( TQString fileOwner, TQString userName, TQString perm );
+ static char ftpExecutable( TQString fileOwner, TQString userName, TQString perm );
+
+ static bool dirExist (TQString path);
+ static bool fileExist(TQString fullPath);
+ static bool fileExist(TQString Path, TQString name);
+
+ static TQString mode2TQString(mode_t m);
+ static TQString parseSize(TDEIO::filesize_t val);
+ static TQString date2qstring(TQString date);
+ static time_t TQString2time(TQString date);
+
+private:
+ // cache for passwd and group entries
+ static TQDict<uid_t> *passwdCache;
+ static TQDict<gid_t> *groupCache;
+ static TQIntDict<char> *currentGroups;
+ static TQIntDict<TQString> *uidCache;
+ static TQIntDict<TQString> *gidCache;
+};
+
+#endif
diff --git a/src/app/VFS/krquery.cpp b/src/app/VFS/krquery.cpp
new file mode 100644
index 0000000..7ceeca9
--- /dev/null
+++ b/src/app/VFS/krquery.cpp
@@ -0,0 +1,653 @@
+/***************************************************************************
+ krquery.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#include "krquery.h"
+#include "../krusader.h"
+#include "../resources.h"
+#include "vfs.h"
+#include "krarchandler.h"
+#include "krpermhandler.h"
+
+#include <tqtextstream.h>
+#include <tqtextcodec.h>
+#include <tqregexp.h>
+#include <klargefile.h>
+#include <tdelocale.h>
+#include <kmimetype.h>
+#include <tqfile.h>
+#include <kurlcompletion.h>
+#include <tdeio/job.h>
+#include <tdefileitem.h>
+
+#define STATUS_SEND_DELAY 250
+#define MAX_LINE_LEN 500
+
+// set the defaults
+KRQuery::KRQuery(): TQObject(), matchesCaseSensitive(true), bNull( true ),
+ contain(TQString()),containCaseSensetive(true),
+ containWholeWord(false),containOnRemote(false),
+ minSize(0),maxSize(0),newerThen(0),olderThen(0),
+ owner(TQString()),group(TQString()),perm(TQString()),
+ type(TQString()),inArchive(false),recurse(true),
+ followLinksP(true), receivedBuffer( 0 ), processEventsConnected(0) {}
+
+// set the defaults
+KRQuery::KRQuery( const TQString &name, bool matchCase ) : TQObject(),
+ bNull( true ),contain(TQString()),containCaseSensetive(true),
+ containWholeWord(false), containOnRemote(false),
+ minSize(0),maxSize(0),newerThen(0),olderThen(0),
+ owner(TQString()),group(TQString()),perm(TQString()),
+ type(TQString()),inArchive(false),recurse(true),
+ followLinksP(true), receivedBuffer( 0 ), processEventsConnected(0) {
+ setNameFilter( name, matchCase );
+}
+
+KRQuery::KRQuery( const KRQuery & that ) : TQObject(), receivedBuffer( 0 ), processEventsConnected(0) {
+ *this = that;
+}
+
+KRQuery::~KRQuery() {
+ if( receivedBuffer )
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+}
+
+KRQuery& KRQuery::operator=(const KRQuery &old) {
+ matches = old.matches;
+ excludes = old.excludes;
+ includedDirs = old.includedDirs;
+ excludedDirs = old.excludedDirs;
+ matchesCaseSensitive = old.matchesCaseSensitive;
+ bNull = old.bNull;
+ contain = old.contain;
+ containCaseSensetive = old.containCaseSensetive;
+ containWholeWord = old.containWholeWord;
+ containOnRemote = old.containOnRemote;
+ minSize = old.minSize;
+ maxSize = old.maxSize;
+ newerThen = old.newerThen;
+ olderThen = old.olderThen;
+ owner = old.owner;
+ group = old.group;
+ perm = old.perm;
+ type = old.type;
+ customType = old.customType;
+ inArchive = old.inArchive;
+ recurse = old.recurse;
+ followLinksP = old.followLinksP;
+ whereToSearch = old.whereToSearch;
+ whereNotToSearch = old.whereNotToSearch;
+ origFilter = old.origFilter;
+
+ return *this;
+}
+
+void KRQuery::connectNotify ( const char * signal ) {
+ TQString signalString = TQString( signal ).replace( " ", "" );
+ TQString processString = TQString( TQ_SIGNAL( processEvents( bool & ) ) ).replace( " ", "" );
+ if( signalString == processString )
+ processEventsConnected++;
+}
+
+void KRQuery::disconnectNotify ( const char * signal ) {
+ TQString signalString = TQString( signal ).replace( " ", "" );
+ TQString processString = TQString( TQ_SIGNAL( processEvents( bool & ) ) ).replace( " ", "" );
+ if( signalString == processString )
+ processEventsConnected--;
+}
+
+bool KRQuery::checkPerm( TQString filePerm ) const
+{
+ for ( int i = 0; i < 9; ++i )
+ if ( perm[ i ] != '?' && perm[ i ] != filePerm[ i + 1 ] ) return false;
+ return true;
+}
+
+bool KRQuery::checkType( TQString mime ) const
+{
+ if ( type == mime ) return true;
+ if ( type == i18n( "Archives" ) ) return KRarcHandler::arcSupported( mime.right( 4 ) );
+ if ( type == i18n( "Directories" ) ) return mime.contains( "directory" );
+ if ( type == i18n( "Image Files" ) ) return mime.contains( "image/" );
+ if ( type == i18n( "Text Files" ) ) return mime.contains( "text/" );
+ if ( type == i18n( "Video Files" ) ) return mime.contains( "video/" );
+ if ( type == i18n( "Audio Files" ) ) return mime.contains( "audio/" );
+ if ( type == i18n( "Custom" ) ) return customType.contains( mime );
+ return false;
+}
+
+bool KRQuery::match( const TQString & name ) const {
+ return matchCommon( name, matches, excludes );
+}
+
+bool KRQuery::matchDirName( const TQString & name ) const {
+ return matchCommon( name, includedDirs, excludedDirs );
+}
+
+bool KRQuery::matchCommon( const TQString &nameIn, const TQStringList &matchList, const TQStringList &excludeList ) const
+{
+ if( excludeList.count() == 0 && matchList.count() == 0 ) /* true if there's no match condition */
+ return true;
+
+ TQString name( nameIn );
+ int ndx = nameIn.findRev( '/' ); // virtual filenames may contain '/'
+ if( ndx != -1 ) // but the end of the filename is OK
+ name = nameIn.mid( ndx + 1 );
+
+ unsigned int len;
+ for ( unsigned int i = 0; i < excludeList.count(); ++i )
+ {
+ TQRegExp( *excludeList.at( i ), matchesCaseSensitive, true ).match( name, 0, ( int* ) & len );
+ if ( len == name.length() ) return false;
+ }
+
+ if( matchList.count() == 0 )
+ return true;
+
+ for ( unsigned int i = 0; i < matchList.count(); ++i )
+ {
+ TQRegExp( *matchList.at( i ), matchesCaseSensitive, true ).match( name, 0, ( int* ) & len );
+ if ( len == name.length() ) return true;
+ }
+ return false;
+}
+
+bool KRQuery::match( vfile *vf ) const
+{
+ if( vf->vfile_isDir() && !matchDirName( vf->vfile_getName() ) ) return false;
+ // see if the name matches
+ if ( !match( vf->vfile_getName() ) ) return false;
+ // checking the mime
+ if( !type.isEmpty() && !checkType( vf->vfile_getMime( true ) ) ) return false;
+ // check that the size fit
+ TDEIO::filesize_t size = vf->vfile_getSize();
+ if ( minSize && size < minSize ) return false;
+ if ( maxSize && size > maxSize ) return false;
+ // check the time frame
+ time_t mtime = vf->vfile_getTime_t();
+ if ( olderThen && mtime > olderThen ) return false;
+ if ( newerThen && mtime < newerThen ) return false;
+ // check owner name
+ if ( !owner.isEmpty() && vf->vfile_getOwner() != owner ) return false;
+ // check group name
+ if ( !group.isEmpty() && vf->vfile_getGroup() != group ) return false;
+ //check permission
+ if ( !perm.isEmpty() && !checkPerm( vf->vfile_getPerm() ) ) return false;
+
+ if ( !contain.isEmpty() )
+ {
+ if( (totalBytes = vf->vfile_getSize()) == 0 )
+ totalBytes++; // sanity
+ receivedBytes = 0;
+ if( receivedBuffer ) {
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+ }
+ fileName = vf->vfile_getName();
+ timer.start();
+
+ if( vf->vfile_getUrl().isLocalFile() )
+ {
+ if( !containsContent( vf->vfile_getUrl().path() ) ) return false;
+ }
+ else
+ {
+ if( containOnRemote ) {
+ if( processEventsConnected == 0 ) return false;
+ if( !containsContent( vf->vfile_getUrl() ) ) return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool KRQuery::match( KFileItem *kfi ) const {
+ mode_t mode = kfi->mode() | kfi->permissions();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+ if ( kfi->isDir() )
+ perm[ 0 ] = 'd';
+
+ vfile temp( kfi->text(), kfi->size(), perm, kfi->time( TDEIO::UDS_MODIFICATION_TIME ),
+ kfi->isLink(), kfi->user(), kfi->group(), kfi->user(),
+ kfi->mimetype(), kfi->linkDest(), mode );
+
+ return match( &temp );
+}
+
+// takes the string and adds BOLD to it, so that when it is displayed,
+// the grepped text will be bold
+void fixFoundTextForDisplay(TQString& haystack, int start, int length) {
+ TQString before = haystack.left( start );
+ TQString text = haystack.mid( start, length );
+ TQString after = haystack.mid( start + length );
+
+ before.replace( '&', "&amp;" );
+ before.replace( '<', "&lt;" );
+ before.replace( '>', "&gt;" );
+
+ text.replace( '&', "&amp;" );
+ text.replace( '<', "&lt;" );
+ text.replace( '>', "&gt;" );
+
+ after.replace( '&', "&amp;" );
+ after.replace( '<', "&lt;" );
+ after.replace( '>', "&gt;" );
+
+ haystack = ("<qt>"+before+"<b>"+text+"</b>"+after+"</qt>" );
+}
+
+bool KRQuery::checkBuffer( const char *buf, int len ) const {
+ if( len == 0 ) { // last block?
+ if( receivedBuffer ) {
+ bool result = checkLines( receivedBuffer, receivedBufferLen );
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+ return result;
+ }
+ return false;
+ }
+
+ int after = len;
+ while( buf[ after-1 ] != '\n' && buf[ after-1 ] != 0 ) {
+ after--;
+ if( after <= 0 || after <= len - MAX_LINE_LEN ) {
+ after = len; // if there's no <ENTER> in MAX_LINE_LEN, we break the line
+ break; // breaking the line causes problems at Unicode characters
+ }
+ }
+
+ if( receivedBuffer ) {
+ int previous = 0;
+ while( previous < after && previous < MAX_LINE_LEN && buf[previous] != '\n' && buf[previous] != 0 )
+ previous++;
+
+ char * str = new char[ receivedBufferLen + previous ];
+ memcpy( str, receivedBuffer, receivedBufferLen );
+ delete []receivedBuffer;
+ receivedBuffer = 0;
+ memcpy( str + receivedBufferLen, buf, previous );
+
+ if( checkLines( str, receivedBufferLen+previous ) ) {
+ delete []str;
+ return true;
+ }
+ delete []str;
+
+ if( after > previous && checkLines( buf+previous, after-previous ) )
+ return true;
+
+ } else if( checkLines( buf, after ) )
+ return true;
+
+ if( after < len ) {
+ receivedBufferLen = len-after;
+ receivedBuffer = new char [ receivedBufferLen ];
+ memcpy( receivedBuffer, buf+after, receivedBufferLen );
+ }
+ return false;
+}
+
+bool KRQuery::checkLines( const char * buf, int len ) const
+{
+ TQStringList list;
+
+ int start = 0;
+ int k = 0;
+ while( k < len )
+ {
+ if( buf[ k ] == 0 || buf[ k ] == '\n' )
+ {
+ if( k != start )
+ {
+ TQString line = TQTextCodec::codecForLocale()->toUnicode( buf + start, k - start );
+ if( !line.isEmpty() )
+ list << line;
+ }
+ start = k + 1;
+ }
+ k++;
+ }
+ if( start != k )
+ {
+ TQString line = TQTextCodec::codecForLocale()->toUnicode( buf + start, k - start );
+ if( !line.isEmpty() )
+ list << line;
+ }
+
+ for( unsigned int i=0; i != list.count(); i++ ) {
+ TQString line = list[ i ];
+
+ int ndx = 0;
+ if ( line.isNull() ) return false;
+ if ( containWholeWord )
+ {
+ while ( ( ndx = line.find( contain, ndx, containCaseSensetive ) ) != -1 )
+ {
+ TQChar before = line.at( ndx - 1 );
+ TQChar after = line.at( ndx + contain.length() );
+
+ if ( !before.isLetterOrNumber() && !after.isLetterOrNumber() &&
+ after != '_' && before != '_' ) {
+ lastSuccessfulGrep = line;
+ fixFoundTextForDisplay(lastSuccessfulGrep, ndx, contain.length());
+ return true;
+ }
+ ndx++;
+ }
+ }
+ else if ( (ndx = line.find( contain, 0, containCaseSensetive )) != -1 ) {
+ lastSuccessfulGrep = line;
+ fixFoundTextForDisplay(lastSuccessfulGrep, ndx, contain.length());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool KRQuery::containsContent( TQString file ) const
+{
+ TQFile qf( file );
+ if( !qf.open( IO_ReadOnly ) )
+ return false;
+
+ char buffer[ 1440 ]; // 2k buffer
+
+ while ( !qf.atEnd() )
+ {
+ int bytes = qf.readBlock( buffer, sizeof( buffer ) );
+ if( bytes <= 0 )
+ break;
+
+ receivedBytes += bytes;
+
+ if( checkBuffer( buffer, bytes ) )
+ return true;
+
+ if( checkTimer() ) {
+ bool stopped = false;
+ emit ((KRQuery *)this)->processEvents( stopped );
+ if( stopped )
+ return false;
+ }
+ }
+ if( checkBuffer( buffer, 0 ) )
+ return true;
+
+ lastSuccessfulGrep = TQString(); // nothing was found
+ return false;
+}
+
+bool KRQuery::containsContent( KURL url ) const
+{
+ TDEIO::TransferJob *contentReader = TDEIO::get( url, false, false );
+ connect(contentReader, TQ_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQ_SLOT(containsContentData(TDEIO::Job *, const TQByteArray &)));
+ connect(contentReader, TQ_SIGNAL( result( TDEIO::Job* ) ),
+ this, TQ_SLOT(containsContentFinished( TDEIO::Job* ) ) );
+
+ busy = true;
+ containsContentResult = false;
+ bool stopped = false;
+
+ while( busy && !stopped ) {
+ checkTimer();
+ emit ((KRQuery *)this)->processEvents( stopped );
+ }
+
+ if( busy ) {
+ contentReader->kill();
+ busy = false;
+ }
+
+ return containsContentResult;
+}
+
+void KRQuery::containsContentData(TDEIO::Job *job, const TQByteArray &array) {
+ receivedBytes += array.size();
+ if( checkBuffer( array.data(), array.size() ) ) {
+ containsContentResult = true;
+ containsContentFinished( job );
+ job->kill();
+ return;
+ }
+ checkTimer();
+}
+
+void KRQuery::containsContentFinished( TDEIO::Job * ) {
+ busy = false;
+}
+
+bool KRQuery::checkTimer() const {
+ if( timer.elapsed() >= STATUS_SEND_DELAY ) {
+ int pcnt = (int)(100.*(double)receivedBytes/(double)totalBytes + .5);
+ TQString message = i18n( "Searching content of '%1' (%2%)" )
+ .arg( fileName ).arg( pcnt );
+ timer.start();
+ emit ((KRQuery *)this)->status( message );
+ return true;
+ }
+ return false;
+}
+
+TQStringList KRQuery::split( TQString str )
+{
+ TQStringList list;
+ unsigned splitNdx = 0;
+ unsigned startNdx = 0;
+ bool quotation = false;
+
+ while( splitNdx < str.length() )
+ {
+ if( str[ splitNdx ] == '"' )
+ quotation = !quotation;
+
+ if( !quotation && str[ splitNdx ] == ' ')
+ {
+ TQString section = str.mid( startNdx, splitNdx - startNdx );
+ startNdx = splitNdx+1;
+ if( section.startsWith( "\"" ) && section.endsWith( "\"" ) && section.length() >=2 )
+ section = section.mid( 1, section.length()-2 );
+ if( !section.isEmpty() )
+ list.append( section );
+ }
+ splitNdx++;
+ }
+
+ if( startNdx < splitNdx )
+ {
+ TQString section = str.mid( startNdx, splitNdx - startNdx );
+ if( section.startsWith( "\"" ) && section.endsWith( "\"" ) && section.length() >=2 )
+ section = section.mid( 1, section.length()-2 );
+ if( !section.isEmpty() )
+ list.append( section );
+ }
+
+ return list;
+}
+
+void KRQuery::setNameFilter( const TQString &text, bool cs )
+{
+ bNull = false;
+ matchesCaseSensitive = cs;
+ origFilter = text;
+
+ TQString matchText = text;
+ TQString excludeText;
+
+ unsigned excludeNdx = 0;
+ bool quotationMark = 0;
+ while( excludeNdx < matchText.length() )
+ {
+ if( matchText[ excludeNdx ] == '"' )
+ quotationMark = !quotationMark;
+ if( !quotationMark )
+ {
+ if( matchText[ excludeNdx ] == '|' )
+ break;
+ }
+ excludeNdx++;
+ }
+
+ if( excludeNdx < matchText.length() )
+ {
+ excludeText = matchText.mid( excludeNdx + 1 ).stripWhiteSpace();
+ matchText.truncate( excludeNdx );
+ matchText = matchText.stripWhiteSpace();
+ if( matchText.isEmpty() )
+ matchText = "*";
+ }
+
+ unsigned i;
+
+ matches = split( matchText );
+ includedDirs.clear();
+
+ for( i=0; i < matches.count(); ) {
+ if( matches[ i ].endsWith( "/" ) ) {
+ includedDirs.push_back( matches[ i ].left( matches[ i ].length() - 1 ) );
+ matches.remove( matches.at( i ) );
+ continue;
+ }
+
+ if( !matches[ i ].contains( "*" ) && !matches[ i ].contains( "?" ) )
+ matches[ i ] = "*" + matches[ i ] + "*";
+
+ i++;
+ }
+
+ excludes = split( excludeText );
+ excludedDirs.clear();
+
+ for( i=0; i < excludes.count(); ) {
+ if( excludes[ i ].endsWith( "/" ) ) {
+ excludedDirs.push_back( excludes[ i ].left( excludes[ i ].length() - 1 ) );
+ excludes.remove( excludes.at( i ) );
+ continue;
+ }
+
+ if( !excludes[ i ].contains( "*" ) && !excludes[ i ].contains( "?" ) )
+ excludes[ i ] = "*" + excludes[ i ] + "*";
+
+ i++;
+ }
+}
+
+void KRQuery::setContent( const TQString &content, bool cs, bool wholeWord, bool remoteSearch )
+{
+ bNull = false;
+ contain = content;
+ containCaseSensetive = cs;
+ containWholeWord = wholeWord;
+ containOnRemote = remoteSearch;
+}
+
+void KRQuery::setMinimumFileSize( TDEIO::filesize_t minimumSize )
+{
+ bNull = false;
+ minSize = minimumSize;
+}
+
+void KRQuery::setMaximumFileSize( TDEIO::filesize_t maximumSize )
+{
+ bNull = false;
+ maxSize = maximumSize;
+}
+
+void KRQuery::setNewerThan( time_t time )
+{
+ bNull = false;
+ newerThen = time;
+}
+
+void KRQuery::setOlderThan( time_t time )
+{
+ bNull = false;
+ olderThen = time;
+}
+
+void KRQuery::setOwner( const TQString &ownerIn )
+{
+ bNull = false;
+ owner = ownerIn;
+}
+
+void KRQuery::setGroup( const TQString &groupIn )
+{
+ bNull = false;
+ group = groupIn;
+}
+
+void KRQuery::setPermissions( const TQString &permIn )
+{
+ bNull = false;
+ perm = permIn;
+}
+
+void KRQuery::setMimeType( const TQString &typeIn, TQStringList customList )
+{
+ bNull = false;
+ type = typeIn;
+ customType = customList;
+}
+
+bool KRQuery::isExcluded( const KURL &url )
+{
+ for ( unsigned int i = 0; i < whereNotToSearch.count(); ++i )
+ if( whereNotToSearch [ i ].isParentOf( url ) || url.equals( whereNotToSearch [ i ], true ) )
+ return true;
+
+ if( !matchDirName( url.fileName() ) )
+ return true;
+
+ return false;
+}
+
+void KRQuery::setSearchInDirs( const KURL::List &urls ) {
+ whereToSearch.clear();
+ for( unsigned int i = 0; i < urls.count(); ++i ) {
+ TQString url = urls[ i ].url();
+ KURL completed = vfs::fromPathOrURL( KURLCompletion::replacedPath( url, true, true ) );
+ whereToSearch.append( completed );
+ }
+}
+
+void KRQuery::setDontSearchInDirs( const KURL::List &urls ) {
+ whereNotToSearch.clear();
+ for( unsigned int i = 0; i < urls.count(); ++i ) {
+ TQString url = urls[ i ].url();
+ KURL completed = vfs::fromPathOrURL( KURLCompletion::replacedPath( url, true, true ) );
+ whereNotToSearch.append( completed );
+ }
+}
+
+#include "krquery.moc"
diff --git a/src/app/VFS/krquery.h b/src/app/VFS/krquery.h
new file mode 100644
index 0000000..6481782
--- /dev/null
+++ b/src/app/VFS/krquery.h
@@ -0,0 +1,209 @@
+/***************************************************************************
+ krquery.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef KRQUERY_H
+#define KRQUERY_H
+
+#include <tqstringlist.h>
+#include <tqdatetime.h>
+#include <time.h>
+#include <kurl.h>
+#include <tdeio/jobclasses.h>
+#include "vfile.h"
+
+class KFileItem;
+
+class KRQuery : public TQObject {
+ TQ_OBJECT
+
+
+public:
+ // null query
+ KRQuery();
+ // query only with name filter
+ KRQuery( const TQString &name, bool matchCase = true );
+ // copy constructor
+ KRQuery( const KRQuery & );
+ // let operator
+ KRQuery& operator=(const KRQuery &);
+ // destructor
+ virtual ~KRQuery();
+
+ // matching a file with the query
+ bool match( vfile *file ) const;// checks if the given vfile object matches the conditions
+ // matching a TDEIO file with the query
+ bool match( KFileItem *file ) const;// checks if the given vfile object matches the conditions
+ // matching a name with the query
+ bool match( const TQString &name ) const;// matching the filename only
+ // matching the name of the directory
+ bool matchDirName( const TQString &name ) const;
+
+ // sets the text for name filtering
+ void setNameFilter( const TQString &text, bool cs=true );
+ // returns the current filter mask
+ const TQString& nameFilter() const { return origFilter; }
+ // returns whether the filter is case sensitive
+ bool isCaseSensitive() { return matchesCaseSensitive; }
+
+ // returns if the filter is null (was cancelled)
+ bool isNull() {return bNull;};
+
+ // sets the content part of the query
+ void setContent( const TQString &content, bool cs=true, bool wholeWord=false, bool remoteSearch=false );
+
+ // sets the minimum file size limit
+ void setMinimumFileSize( TDEIO::filesize_t );
+ // sets the maximum file size limit
+ void setMaximumFileSize( TDEIO::filesize_t );
+
+ // sets the time the file newer than
+ void setNewerThan( time_t time );
+ // sets the time the file older than
+ void setOlderThan( time_t time );
+
+ // sets the owner
+ void setOwner( const TQString &ownerIn );
+ // sets the group
+ void setGroup( const TQString &groupIn );
+ // sets the permissions
+ void setPermissions( const TQString &permIn );
+
+ // sets the mimetype for the query
+ // type, must be one of the following:
+ // 1. a valid mime type name
+ // 2. one of: i18n("Archives"), i18n("Directories"), i18n("Image Files")
+ // i18n("Text Files"), i18n("Video Files"), i18n("Audio Files")
+ // 3. i18n("Custom") in which case you must supply a list of valid mime-types
+ // in the member TQStringList customType
+ void setMimeType( const TQString &typeIn, TQStringList customList = TQStringList() );
+ // true if setMimeType was called
+ bool hasMimeType() { return type.isEmpty(); }
+
+ // sets the search in archive flag
+ void setSearchInArchives( bool flag ) { inArchive = flag; }
+ // gets the search in archive flag
+ bool searchInArchives() { return inArchive; }
+ // sets the recursive flag
+ void setRecursive( bool flag ) { recurse = flag; }
+ // gets the recursive flag
+ bool isRecursive() { return recurse; }
+ // sets whether to follow symbolic links
+ void setFollowLinks( bool flag ) { followLinksP = flag; }
+ // gets whether to follow symbolic links
+ bool followLinks() { return followLinksP; }
+
+ // sets the folders where the searcher will search
+ void setSearchInDirs( const KURL::List &urls );
+ // gets the folders where the searcher searches
+ const KURL::List & searchInDirs() { return whereToSearch; }
+ // sets the folders where search is not permitted
+ void setDontSearchInDirs( const KURL::List &urls );
+ // gets the folders where search is not permitted
+ const KURL::List & dontSearchInDirs() { return whereNotToSearch; }
+ // checks if a URL is excluded
+ bool isExcluded( const KURL &url );
+ // gives whether we search for content
+ bool isContentSearched() const { return !contain.isEmpty(); }
+
+ const TQString& foundText() const { return lastSuccessfulGrep; }
+
+protected:
+ // important to know whether the event processor is connected
+ virtual void connectNotify ( const char * signal );
+ // important to know whether the event processor is connected
+ virtual void disconnectNotify ( const char * signal );
+
+protected:
+ TQStringList matches; // what to search
+ TQStringList excludes; // what to exclude
+ TQStringList includedDirs; // what dirs to include
+ TQStringList excludedDirs; // what dirs to exclude
+ bool matchesCaseSensitive;
+
+ bool bNull; // flag if the query is null
+
+ TQString contain; // file must contain this string
+ bool containCaseSensetive;
+ bool containWholeWord;
+ bool containOnRemote;
+
+ TDEIO::filesize_t minSize;
+ TDEIO::filesize_t maxSize;
+
+ time_t newerThen;
+ time_t olderThen;
+
+ TQString owner;
+ TQString group;
+ TQString perm;
+
+ TQString type;
+ TQStringList customType;
+
+ bool inArchive; // if true- search in archive.
+ bool recurse; // if true recurse ob sub-dirs...
+ bool followLinksP;
+
+ KURL::List whereToSearch; // directorys to search
+ KURL::List whereNotToSearch; // directorys NOT to search
+
+signals:
+ void status( const TQString &name );
+ void processEvents( bool & stopped );
+
+private:
+ bool matchCommon( const TQString &, const TQStringList &, const TQStringList & ) const;
+ bool checkPerm(TQString perm) const;
+ bool checkType(TQString mime) const;
+ bool containsContent( TQString file ) const;
+ bool containsContent( KURL url ) const;
+ bool checkBuffer( const char *buffer, int len ) const;
+ bool checkLines( const char *buffer, int len ) const;
+ bool checkTimer() const;
+ TQStringList split( TQString );
+
+private slots:
+ void containsContentData(TDEIO::Job *, const TQByteArray &);
+ void containsContentFinished(TDEIO::Job*);
+
+private:
+ TQString origFilter;
+ mutable bool busy;
+ mutable bool containsContentResult;
+ mutable char * receivedBuffer;
+ mutable int receivedBufferLen;
+ mutable TQString lastSuccessfulGrep;
+ mutable TQString fileName;
+ mutable TDEIO::filesize_t receivedBytes;
+ mutable TDEIO::filesize_t totalBytes;
+ mutable int processEventsConnected;
+ mutable TQTime timer;
+};
+
+#endif
diff --git a/src/app/VFS/krvfshandler.cpp b/src/app/VFS/krvfshandler.cpp
new file mode 100644
index 0000000..553c55d
--- /dev/null
+++ b/src/app/VFS/krvfshandler.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+ krvfshandler.cpp - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "krvfshandler.h"
+#include "normal_vfs.h"
+#include "temp_vfs.h"
+#include "ftp_vfs.h"
+#include "virt_vfs.h"
+
+#include <tqdir.h>
+
+#include <kdebug.h>
+
+
+KrVfsHandler::KrVfsHandler(){
+}
+KrVfsHandler::~KrVfsHandler(){
+}
+
+vfs::VFS_TYPE KrVfsHandler::getVfsType(const KURL& url){
+ TQString protocol = url.protocol();
+
+ if( ( protocol == "krarc" || protocol == "tar" || protocol == "zip" ) &&
+ TQDir(url.path(-1)).exists() )
+ return vfs::NORMAL;
+
+ if( url.isLocalFile() ){
+ return vfs::NORMAL;
+ }
+ else{
+ if(url.protocol() == "virt") return vfs::VIRT;
+ else return vfs::FTP;
+ }
+ return vfs::ERROR;
+}
+
+vfs* KrVfsHandler::getVfs(const KURL& url,TQObject* parent,vfs* oldVfs){
+ vfs::VFS_TYPE newType,oldType = vfs::ERROR;
+
+ if(oldVfs) oldType = oldVfs->vfs_getType();
+ newType = getVfsType(url);
+
+
+ vfs* newVfs = oldVfs;
+
+ if( oldType != newType ){
+ switch( newType ){
+ case (vfs::NORMAL) : newVfs = new normal_vfs(parent); break;
+ case (vfs::FTP ) : newVfs = new ftp_vfs(parent) ; break;
+ case (vfs::TEMP ) : newVfs = 0/*new temp_vfs(parent)*/ ; break;
+ case (vfs::VIRT ) : newVfs = new virt_vfs(parent) ; break;
+ case (vfs::ERROR ) : newVfs = 0 ; break;
+ }
+ }
+
+ return newVfs;
+}
diff --git a/src/app/VFS/krvfshandler.h b/src/app/VFS/krvfshandler.h
new file mode 100644
index 0000000..b061b53
--- /dev/null
+++ b/src/app/VFS/krvfshandler.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ krvfshandler.h - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRVFSHANDLER_H
+#define KRVFSHANDLER_H
+
+#include <tqobject.h>
+
+#include <kurl.h>
+
+#include "vfs.h"
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class KrVfsHandler : public TQObject {
+public:
+ KrVfsHandler();
+ ~KrVfsHandler();
+
+ static vfs::VFS_TYPE getVfsType(const KURL& url);
+ static vfs* getVfs(const KURL& url,TQObject* parent=0,vfs* oldVfs=0);
+};
+
+#endif
diff --git a/src/app/VFS/normal_vfs.cpp b/src/app/VFS/normal_vfs.cpp
new file mode 100644
index 0000000..f81ab9a
--- /dev/null
+++ b/src/app/VFS/normal_vfs.cpp
@@ -0,0 +1,437 @@
+/***************************************************************************
+ normal_vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+// TQt includes
+#include <tqdir.h>
+#include <tqtimer.h>
+// TDE includes
+#include <tdemessagebox.h>
+#include <kmimetype.h>
+#include <tdeio/jobclasses.h>
+#include <tdelocale.h>
+#include <tdeglobalsettings.h>
+#include <kdebug.h>
+#include <klargefile.h>
+#include <tdefileitem.h>
+// Krusader includes
+#include "normal_vfs.h"
+#include "../Dialogs/krdialogs.h"
+#include "../MountMan/kmountman.h"
+#include "krpermhandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../resources.h"
+#include "../krslots.h"
+
+// header files for ACL
+#if KDE_IS_VERSION(3,5,0)
+#ifdef HAVE_POSIX_ACL
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+#endif
+
+normal_vfs::normal_vfs(TQObject* panel):vfs(panel), watcher(0) {
+ vfs_type=NORMAL;
+}
+
+bool normal_vfs::populateVfsList(const KURL& origin, bool showHidden){
+ TQString path = origin.path(-1);
+
+ // set the writable attribute to true, if that's not the case - the TDEIO job
+ // will give the warnings and errors
+ isWritable = true;
+
+ if( watcher ) delete watcher; //stop watching the old dir
+ watcher = 0;
+
+ // set the origin...
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ vfs_origin.setProtocol("file"); // do not remove !
+ vfs_origin.cleanPath(-1);
+
+ // check that the new origin exists
+ if ( !TQDir(path).exists() )
+ {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Directory %1 does not exist!").arg( path ), i18n("Error"));
+ return false;
+ }
+
+ krConfig->setGroup("Advanced");
+ if (krConfig->readBoolEntry("AutoMount",_AutoMount)) krMtMan.autoMount(path);
+
+ DIR* dir = opendir(path.local8Bit());
+ if(!dir)
+ {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Can't open the %1 directory!").arg( path ), i18n("Error"));
+ return false;
+ }
+
+ // change directory to the new directory
+ TQString save = getcwd( 0, 0 );
+ if (chdir(path.local8Bit()) != 0) {
+ if( !quietMode ) KMessageBox::error(krApp, i18n("Access denied to")+path, i18n("Error"));
+ closedir(dir);
+ return false;
+ }
+
+ struct dirent* dirEnt;
+ TQString name;
+
+ while( (dirEnt=readdir(dir)) != NULL ){
+ name = TQString::fromLocal8Bit(dirEnt->d_name);
+
+ // show hidden files ?
+ if ( !showHidden && name.left(1) == "." ) continue ;
+ // we dont need the ".",".." enteries
+ if (name=="." || name == "..") continue;
+
+ vfile* temp = vfileFromName(name);
+ foundVfile(temp);
+ }
+ // clean up
+ closedir(dir);
+ chdir( save.local8Bit() );
+
+ if( panelConnected )
+ {
+ watcher = new KDirWatch();
+ // connect the watcher
+ connect(watcher,TQ_SIGNAL(dirty(const TQString&)),this,TQ_SLOT(vfs_slotDirty(const TQString&)));
+ connect(watcher,TQ_SIGNAL(created(const TQString&)),this, TQ_SLOT(vfs_slotCreated(const TQString&)));
+ connect(watcher,TQ_SIGNAL(deleted(const TQString&)),this, TQ_SLOT(vfs_slotDeleted(const TQString&)));
+ watcher->addDir(vfs_getOrigin().path(-1),true); //start watching the new dir
+ watcher->startScan(true);
+ }
+
+ return true;
+}
+
+// copy a file to the vfs (physical)
+void normal_vfs::vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir, PreserveMode pmode ){
+ //if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ KURL dest;
+ dest.setPath(vfs_workingDir()+"/"+dir);
+
+ TDEIO::Job* job = PreservingCopyJob::createCopyJob( pmode, *fileUrls,dest,mode,false,true );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh()) );
+ if(mode == TDEIO::CopyJob::Move) // notify the other panel
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),toNotify,TQ_SLOT(vfs_refresh(TDEIO::Job*)) );
+ else
+ job->setAutoErrorHandlingEnabled( true );
+}
+
+// remove a file from the vfs (physical)
+void normal_vfs::vfs_delFiles(TQStringList *fileNames){
+ KURL::List filesUrls;
+ KURL url;
+ TQDir local( vfs_workingDir() );
+ vfile* vf;
+
+// if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ // names -> urls
+ for(uint i=0 ; i<fileNames->count(); ++i){
+ TQString filename = (*fileNames)[i];
+ vf = vfs_search(filename);
+ url.setPath( vfs_workingDir()+"/"+filename);
+ filesUrls.append(url);
+ }
+ TDEIO::Job *job;
+
+ // delete of move to trash ?
+ krConfig->setGroup("General");
+ if( krConfig->readBoolEntry("Move To Trash",_MoveToTrash) ){
+#if KDE_IS_VERSION(3,4,0)
+ job = TDEIO::trash(filesUrls, true );
+#else
+ job = new TDEIO::CopyJob(filesUrls,TDEGlobalSettings::trashPath(),TDEIO::CopyJob::Move,false,true );
+#endif
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),SLOTS,TQ_SLOT(changeTrashIcon()));
+ }
+ else
+ job = new TDEIO::DeleteJob(filesUrls, false, true);
+
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+}
+
+// return a path to the file
+KURL normal_vfs::vfs_getFile(const TQString& name){
+ TQString url;
+ if ( vfs_workingDir() == "/" ) url = "/"+name;
+ else url = vfs_workingDir()+"/"+name;
+
+ return vfs::fromPathOrURL(url);
+}
+
+KURL::List* normal_vfs::vfs_getFiles(TQStringList* names){
+ KURL::List* urls = new KURL::List();
+ for(TQStringList::Iterator name = names->begin(); name != names->end(); ++name){
+ urls->append( vfs_getFile(*name) );
+ }
+ return urls;
+}
+
+void normal_vfs::vfs_mkdir(const TQString& name){
+ if (!TQDir(vfs_workingDir()).mkdir(name))
+ if (!quietMode) KMessageBox::sorry(krApp,i18n("Can't create a directory. Check your permissions."));
+ vfs::vfs_refresh();
+}
+
+void normal_vfs::vfs_rename(const TQString& fileName,const TQString& newName){
+ KURL::List fileUrls;
+ KURL url , dest;
+
+ //if( watcher ) watcher->stopScan(); // we will refresh manually this time...
+ if( watcher ) {
+ delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher
+ watcher = 0;
+ }
+
+ url.setPath( vfs_workingDir()+"/"+fileName );
+ fileUrls.append(url);
+ dest.setPath(vfs_workingDir()+"/"+newName);
+
+ TDEIO::Job *job = new TDEIO::CopyJob(fileUrls,dest,TDEIO::CopyJob::Move,true,false );
+ connect(job,TQ_SIGNAL(result(TDEIO::Job*)),this,TQ_SLOT(vfs_refresh(TDEIO::Job*)));
+}
+
+vfile* normal_vfs::vfileFromName(const TQString& name){
+ TQString path = vfs_workingDir()+"/"+name;
+ TQCString fileName = path.local8Bit();
+
+ KDE_struct_stat stat_p;
+ KDE_lstat(fileName.data(),&stat_p);
+ TDEIO::filesize_t size = stat_p.st_size;
+ TQString perm = KRpermHandler::mode2TQString(stat_p.st_mode);
+ bool symLink= S_ISLNK(stat_p.st_mode);
+ if( S_ISDIR(stat_p.st_mode) ) perm[0] = 'd';
+
+ KURL mimeUrl = fromPathOrURL(path);
+ TQString mime=TQString();
+
+ char symDest[256];
+ bzero(symDest,256);
+ if( S_ISLNK(stat_p.st_mode) ){ // who the link is pointing to ?
+ int endOfName=0;
+ endOfName=readlink(fileName.data(),symDest,256);
+ if ( endOfName != -1 ){
+ if ( TQDir(TQString::fromLocal8Bit( symDest ) ).exists() ) perm[0] = 'd';
+ if ( !TQDir(vfs_workingDir()).exists( TQString::fromLocal8Bit ( symDest ) ) ) mime = "Broken Link !";
+ }
+ else krOut << "Failed to read link: "<< path<<endl;
+ }
+
+ int rwx = 0;
+ if( ::access( fileName.data(), R_OK ) == 0 )
+ rwx |= R_OK;
+ if( ::access( fileName.data(), W_OK ) == 0 )
+ rwx |= W_OK;
+ if( ::access( fileName.data(), X_OK ) == 0 )
+ rwx |= X_OK;
+
+ // create a new virtual file object
+ vfile* temp=new vfile(name,size,perm,stat_p.st_mtime,symLink,stat_p.st_uid,
+ stat_p.st_gid,mime,TQString::fromLocal8Bit( symDest ),stat_p.st_mode, rwx);
+ temp->vfile_setUrl( mimeUrl );
+ return temp;
+}
+
+void normal_vfs::getACL( vfile *file, TQString &acl, TQString &defAcl )
+{
+ acl = defAcl = TQString();
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ TQCString fileName = file->vfile_getUrl().path( -1 ).local8Bit();
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ if ( acl_extended_file( fileName.data() ) )
+ {
+#endif
+ acl = getACL( fileName.data(), ACL_TYPE_ACCESS );
+ if( file->vfile_isDir() )
+ defAcl = getACL( fileName.data(), ACL_TYPE_DEFAULT );
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ }
+#endif
+#endif
+}
+
+TQString normal_vfs::getACL( const TQString & path, int type )
+{
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ acl_t acl = 0;
+ // do we have an acl for the file, and/or a default acl for the dir, if it is one?
+ if ( ( acl = acl_get_file( path.ascii(), type ) ) != 0 )
+ {
+ bool aclExtended = false;
+
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ aclExtended = acl_equiv_mode( acl, 0 );
+#else
+ acl_entry_t entry;
+ int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
+ while ( ret == 1 ) {
+ acl_tag_t currentTag;
+ acl_get_tag_type( entry, &currentTag );
+ if ( currentTag != ACL_USER_OBJ &&
+ currentTag != ACL_GROUP_OBJ &&
+ currentTag != ACL_OTHER )
+ {
+ aclExtended = true;
+ break;
+ }
+ ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
+ }
+#endif
+
+ if ( !aclExtended )
+ {
+ acl_free( acl );
+ acl = 0;
+ }
+ }
+
+ if( acl == 0 )
+ return TQString();
+
+ char *aclString = acl_to_text( acl, 0 );
+ TQString ret = TQString::fromLatin1( aclString );
+ acl_free( (void*)aclString );
+ acl_free( acl );
+
+ return ret;
+#else
+ return TQString();
+#endif
+}
+
+void normal_vfs::vfs_slotRefresh()
+{
+ krConfig->setGroup("Advanced");
+ int maxRefreshFrequency = krConfig->readNumEntry("Max Refresh Frequency", 1000);
+ vfs_refresh();
+ disconnect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ refreshTimer.start( maxRefreshFrequency, true );
+}
+
+bool normal_vfs::burstRefresh(const TQString& path ){
+ if( path == vfs_getOrigin().path(-1) ) {
+ if( !refreshTimer.isActive() ) {
+ // the directory itself is dirty - full refresh is needed
+ TQTimer::singleShot(0, this, TQ_SLOT( vfs_slotRefresh() ) ); // safety: dirty signal comes from KDirWatch!
+ return true;
+ }
+ disconnect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ connect( &refreshTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( vfs_slotRefresh() ) );
+ postponedRefreshURL = fromPathOrURL(path);
+ return true;
+ }
+ return false;
+}
+
+void normal_vfs::vfs_slotDirty(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+ KURL url = fromPathOrURL(path);
+ TQString name = url.fileName();
+
+ // do we have it already ?
+ if( !vfs_search(name ) ) return vfs_slotCreated(path);
+
+ // we have an updated file..
+ removeFromList(name);
+ vfile* vf = vfileFromName(name);
+ addToList(vf);
+ emit updatedVfile(vf);
+}
+
+void normal_vfs::vfs_slotCreated(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ TQString name = url.fileName();
+ // if it's in the CVS - it's an update not new file
+ if( vfs_search(name) )
+ return vfs_slotDirty(path);
+
+ vfile* vf = vfileFromName(name);
+ addToList(vf);
+ emit addedVfile(vf);
+}
+
+void normal_vfs::vfs_slotDeleted(const TQString& path){
+ if( disableRefresh ){
+ postponedRefreshURL = fromPathOrURL(path);
+ return;
+ }
+
+ if( burstRefresh( path ) )
+ return;
+
+
+ KURL url = fromPathOrURL(path);
+ TQString name = url.fileName();
+
+ // if it's not in the CVS - do nothing
+ if( vfs_search(name) ){
+ emit deletedVfile(name);
+ removeFromList(name);
+ }
+}
+
+#include "normal_vfs.moc"
diff --git a/src/app/VFS/normal_vfs.h b/src/app/VFS/normal_vfs.h
new file mode 100644
index 0000000..0df0ea6
--- /dev/null
+++ b/src/app/VFS/normal_vfs.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+ normal_vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef NORMAL_VFS
+#define NORMAL_VFS
+
+// TQt includes
+#include <tqstring.h>
+// TDE includes
+#include <tdefileitem.h>
+#include <kdirwatch.h>
+#include <kurl.h>
+// Krusader includes
+#include "vfs.h"
+
+/**
+ * The normal_vfs class is Kruasder implemention for local directories.
+ * As this is the most common case, we try to make it as fast and efficent as possible.
+ */
+class normal_vfs : public vfs{
+ TQ_OBJECT
+
+public:
+ // the constructor simply uses the inherited constructor
+ normal_vfs(TQObject* panel);
+ ~normal_vfs(){if( watcher ) delete watcher;}
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(TQStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(TQStringList* names);
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const TQString& name);
+ /// Create a new directory
+ virtual void vfs_mkdir(const TQString& name);
+ /// Rename file
+ virtual void vfs_rename(const TQString& fileName,const TQString& newName);
+
+ /// return the VFS working dir
+ virtual TQString vfs_workingDir() { return vfs_origin.path(-1); }
+
+ /// Get ACL permissions
+ static void getACL( vfile *file, TQString &acl, TQString &defAcl );
+
+public slots:
+ void vfs_slotRefresh();
+ void vfs_slotDirty(const TQString& path);
+ void vfs_slotCreated(const TQString& path);
+ void vfs_slotDeleted(const TQString& path);
+
+protected:
+ /// Re-reads files and stats and fills the vfile list
+ virtual bool populateVfsList(const KURL& origin, bool showHidden);
+
+ TQTimer refreshTimer; //< Timer to exclude sudden refreshes
+ KDirWatch *watcher; //< The internal dir watcher - use to detect changes in directories
+ vfile* vfileFromName(const TQString& name);
+
+private:
+ bool burstRefresh( const TQString &path );
+ static TQString getACL( const TQString & path, int type );
+};
+
+#endif
diff --git a/src/app/VFS/preservingcopyjob.cpp b/src/app/VFS/preservingcopyjob.cpp
new file mode 100644
index 0000000..04c3195
--- /dev/null
+++ b/src/app/VFS/preservingcopyjob.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+ preservingcopyjob.cpp - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "preservingcopyjob.h"
+#include "../defaults.h"
+#include "../krusader.h"
+#include <utime.h>
+#include <klargefile.h>
+#include <tdeio/job.h>
+#include <tdeio/jobclasses.h>
+#include <tdefileitem.h>
+#include <tqfile.h>
+#include <pwd.h>
+#include <grp.h>
+
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+#include <sys/acl.h>
+#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
+#include <acl/libacl.h>
+#endif
+#endif
+
+Attributes::Attributes()
+{
+ time = (time_t)-1;
+ uid = (uid_t)-1;
+ gid = (gid_t)-1;
+ mode = (mode_t)-1;
+ acl = TQString();
+}
+
+Attributes::Attributes( time_t tIn, uid_t uIn, gid_t gIn, mode_t modeIn, const TQString & aclIn )
+{
+ time = tIn, uid = uIn, gid = gIn, mode = modeIn, acl = aclIn;
+}
+
+Attributes::Attributes( time_t tIn, TQString user, TQString group, mode_t modeIn, const TQString & aclIn )
+{
+ time = tIn;
+ uid = (uid_t)-1;
+ struct passwd* pw = getpwnam(TQFile::encodeName( user ));
+ if ( pw != 0L )
+ uid = pw->pw_uid;
+ gid = (gid_t)-1;
+ struct group* g = getgrnam(TQFile::encodeName( group ));
+ if ( g != 0L )
+ gid = g->gr_gid;
+ mode = modeIn;
+ acl = aclIn;
+}
+
+PreservingCopyJob::PreservingCopyJob( const KURL::List& src, const KURL& dest, CopyMode mode,
+ bool asMethod, bool showProgressInfo ) : TDEIO::CopyJob( src, dest, mode, asMethod, showProgressInfo )
+{
+ if( dest.isLocalFile() )
+ {
+ connect( this, TQ_SIGNAL( aboutToCreate (TDEIO::Job *, const TQValueList< TDEIO::CopyInfo > &) ),
+ this, TQ_SLOT( slotAboutToCreate (TDEIO::Job *, const TQValueList< TDEIO::CopyInfo > &) ) );
+ connect( this, TQ_SIGNAL( copyingDone( TDEIO::Job *, const KURL &, const KURL &, bool, bool) ),
+ this, TQ_SLOT( slotCopyingDone( TDEIO::Job *, const KURL &, const KURL &, bool, bool) ) );
+ connect( this, TQ_SIGNAL( result( TDEIO::Job * ) ),
+ this, TQ_SLOT( slotFinished() ) );
+ }
+}
+
+void PreservingCopyJob::slotAboutToCreate( TDEIO::Job */*job*/, const TQValueList< TDEIO::CopyInfo > &files )
+{
+ for ( TQValueList< TDEIO::CopyInfo >::ConstIterator it = files.begin(); it != files.end(); ++it ) {
+
+ if( (*it).uSource.isLocalFile() ) {
+ KDE_struct_stat stat_p;
+ KDE_lstat( (*it).uSource.path(-1).local8Bit(),&stat_p); /* getting the date information */
+
+ TQString aclStr;
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ acl_t acl = acl_get_file( (*it).uSource.path(-1).local8Bit(), ACL_TYPE_ACCESS );
+
+ bool aclExtended = false;
+ if( acl )
+ {
+#if HAVE_NON_POSIX_ACL_EXTENSIONS
+ aclExtended = acl_equiv_mode( acl, 0 );
+#else
+ acl_entry_t entry;
+ int ret = acl_get_entry( acl, ACL_FIRST_ENTRY, &entry );
+ while ( ret == 1 ) {
+ acl_tag_t currentTag;
+ acl_get_tag_type( entry, &currentTag );
+ if ( currentTag != ACL_USER_OBJ &&
+ currentTag != ACL_GROUP_OBJ &&
+ currentTag != ACL_OTHER )
+ {
+ aclExtended = true;
+ break;
+ }
+ ret = acl_get_entry( acl, ACL_NEXT_ENTRY, &entry );
+ }
+#endif
+ }
+
+
+ if ( acl && !aclExtended ) {
+ acl_free( acl );
+ acl = NULL;
+ }
+ if( acl )
+ {
+ char *aclString = acl_to_text( acl, 0 );
+ aclStr = TQString::fromLatin1( aclString );
+ acl_free( (void*)aclString );
+ acl_free( acl );
+ }
+#endif
+ fileAttributes[ (*it).uSource ] = Attributes( stat_p.st_mtime, stat_p.st_uid, stat_p.st_gid, stat_p.st_mode & 07777, aclStr );
+ }
+ else {
+ time_t mtime = (*it).mtime;
+
+ if( mtime != 0 && mtime != ((time_t) -1 ) ) /* is it correct? */
+ fileAttributes[ (*it).uSource ].time = mtime;
+
+ int permissions = (*it).permissions;
+ fileAttributes[ (*it).uSource ].mode = permissions;
+ }
+ }
+}
+
+void PreservingCopyJob::slotResult( Job *job ) {
+ if( !job->error() ) {
+ if( job->inherits( "TDEIO::StatJob" ) ) { /* Unfortunately TDEIO forgets to set times when the file is in the */
+ KURL url = ((TDEIO::SimpleJob *)job)->url(); /* base directory. That's why we capture every StatJob and set the */
+ /* time manually. */
+ TDEIO::UDSEntry entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ KFileItem kfi(entry, url );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ fileAttributes[ url ] = Attributes( kfi.time( TDEIO::UDS_MODIFICATION_TIME ), kfi.user(), kfi.group(), kfi.mode(), kfi.ACL().asString() );
+#else
+ fileAttributes[ url ] = Attributes( kfi.time( TDEIO::UDS_MODIFICATION_TIME ), kfi.user(), kfi.group(), kfi.mode(), TQString() );
+#endif
+ }
+ }
+
+ CopyJob::slotResult( job );
+
+ for( unsigned j=0; j != subjobs.count(); j++ ) {
+ if( subjobs.at( j )->inherits( "TDEIO::ListJob" ) ) {
+ disconnect( subjobs.at( j ), TQ_SIGNAL( entries (TDEIO::Job *, const TDEIO::UDSEntryList &) ),
+ this, TQ_SLOT( slotListEntries (TDEIO::Job *, const TDEIO::UDSEntryList &) ) );
+ connect( subjobs.at( j ), TQ_SIGNAL( entries (TDEIO::Job *, const TDEIO::UDSEntryList &) ),
+ this, TQ_SLOT( slotListEntries (TDEIO::Job *, const TDEIO::UDSEntryList &) ) );
+ }
+ }
+}
+
+void PreservingCopyJob::slotListEntries(TDEIO::Job *job, const TDEIO::UDSEntryList &list) {
+ TDEIO::UDSEntryListConstIterator it = list.begin();
+ TDEIO::UDSEntryListConstIterator end = list.end();
+ for (; it != end; ++it) {
+ KURL url = ((TDEIO::SimpleJob *)job)->url();
+ TQString relName, user, group;
+ time_t mtime = (time_t)-1;
+ mode_t mode = 0755;
+ TQString acl;
+
+ TDEIO::UDSEntry::ConstIterator it2 = (*it).begin();
+ for( ; it2 != (*it).end(); it2++ ) {
+ switch ((*it2).m_uds) {
+ case TDEIO::UDS_NAME:
+ if( relName.isEmpty() )
+ relName = (*it2).m_str;
+ break;
+ case TDEIO::UDS_URL:
+ relName = KURL((*it2).m_str).fileName();
+ break;
+ case TDEIO::UDS_MODIFICATION_TIME:
+ mtime = (time_t)((*it2).m_long);
+ break;
+ case TDEIO::UDS_USER:
+ user = (*it2).m_str;
+ break;
+ case TDEIO::UDS_GROUP:
+ group = (*it2).m_str;
+ break;
+ case TDEIO::UDS_ACCESS:
+ mode = (*it2).m_long;
+ break;
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ case TDEIO::UDS_ACL_STRING:
+ acl = (*it2).m_str;
+ break;
+#endif
+ }
+ }
+ url.addPath( relName );
+
+ fileAttributes[ url ] = Attributes( mtime, user, group, mode, acl );
+ }
+}
+
+void PreservingCopyJob::slotCopyingDone( TDEIO::Job *, const KURL &from, const KURL &to, bool postpone, bool)
+{
+ if( postpone ) { // the directories are stamped at the last step, so if it's a directory, we postpone
+ unsigned i=0;
+ TQString path = to.path( -1 );
+
+ for( ; i != directoriesToStamp.count(); i++ ) // sort the URL-s to avoid parent time stamp modification
+ if( path >= directoriesToStamp[ i ].path( -1 ) )
+ break;
+
+ directoriesToStamp.insert( directoriesToStamp.at( i ), to );
+ originalDirectories.insert( originalDirectories.at( i ), from );
+ }
+ else if( fileAttributes.count( from ) ) {
+ Attributes attrs = fileAttributes[ from ];
+ fileAttributes.remove( from );
+
+ time_t mtime = attrs.time;
+
+ if( to.isLocalFile() )
+ {
+ if( mtime != 0 && mtime != ((time_t) -1 ) )
+ {
+ struct utimbuf timestamp;
+
+ timestamp.actime = time( 0 );
+ timestamp.modtime = mtime;
+
+ utime( (const char *)( to.path( -1 ).local8Bit() ), &timestamp );
+ }
+
+ if( attrs.uid != (uid_t)-1 )
+ chown( (const char *)( to.path( -1 ).local8Bit() ), attrs.uid, (gid_t)-1 );
+ if( attrs.gid != (gid_t)-1 )
+ chown( (const char *)( to.path( -1 ).local8Bit() ), (uid_t)-1, attrs.gid );
+
+ if( attrs.mode != (mode_t) -1 )
+ chmod( (const char *)( to.path( -1 ).local8Bit() ), attrs.mode );
+
+#if KDE_IS_VERSION(3,5,0) && defined( HAVE_POSIX_ACL )
+ if( !attrs.acl.isNull() )
+ {
+ acl_t acl = acl_from_text( attrs.acl.latin1() );
+ if( acl && !acl_valid( acl ) )
+ acl_set_file( to.path( -1 ).local8Bit(), ACL_TYPE_ACCESS, acl );
+ if( acl )
+ acl_free( acl );
+ }
+#endif
+ }
+ }
+}
+
+void PreservingCopyJob::slotFinished() {
+ for( unsigned i=0; i != directoriesToStamp.count(); i++ ) {
+ KURL from = originalDirectories[ i ];
+ KURL to = directoriesToStamp[ i ];
+
+ slotCopyingDone( 0, from, to, false, false );
+ }
+}
+
+TDEIO::CopyJob * PreservingCopyJob::createCopyJob( PreserveMode pmode, const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo )
+{
+ if( ! dest.isLocalFile() )
+ pmode = PM_NONE;
+ if( mode == TDEIO::CopyJob::Link )
+ pmode = PM_NONE;
+
+ switch( pmode )
+ {
+ case PM_PRESERVE_ATTR:
+ return new PreservingCopyJob( src, dest, mode, asMethod, showProgressInfo );
+ case PM_DEFAULT:
+ {
+ TQString group = krConfig->group();
+ krConfig->setGroup( "Advanced" );
+ bool preserve = krConfig->readBoolEntry( "PreserveAttributes", _PreserveAttributes );
+ krConfig->setGroup( group );
+ if( preserve )
+ return new PreservingCopyJob( src, dest, mode, asMethod, showProgressInfo );
+ else
+ return new TDEIO::CopyJob( src, dest, mode, asMethod, showProgressInfo );
+ }
+ case PM_NONE:
+ default:
+ return new TDEIO::CopyJob( src, dest, mode, asMethod, showProgressInfo );
+ }
+}
+
+#include "preservingcopyjob.moc"
diff --git a/src/app/VFS/preservingcopyjob.h b/src/app/VFS/preservingcopyjob.h
new file mode 100644
index 0000000..e51783b
--- /dev/null
+++ b/src/app/VFS/preservingcopyjob.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ preservingcopyjob.h - description
+ -------------------
+ copyright : (C) 2005 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __PRESERVING_COPY_JOB_H__
+#define __PRESERVING_COPY_JOB_H__
+
+#include "config.h"
+#include <time.h>
+#include <tdeio/jobclasses.h>
+#include <tqmap.h>
+#include <tqvaluelist.h>
+
+typedef enum {
+ PM_NONE = 0,
+ PM_PRESERVE_ATTR = 1,
+ PM_DEFAULT = 2
+} PreserveMode;
+
+
+class Attributes {
+public:
+ Attributes();
+ Attributes( time_t tIn, uid_t uIn, gid_t gIn, mode_t modeIn, const TQString & aclIn );
+ Attributes( time_t tIn, TQString user, TQString group, mode_t modeIn, const TQString & aclIn );
+
+ time_t time;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+ TQString acl;
+};
+
+class PreservingCopyJob : public TDEIO::CopyJob
+{
+ TQ_OBJECT
+
+
+public:
+
+ PreservingCopyJob( const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo );
+
+ static TDEIO::CopyJob *createCopyJob( PreserveMode pmode, const KURL::List& src, const KURL& dest, CopyMode mode, bool asMethod, bool showProgressInfo );
+
+public slots:
+ void slotAboutToCreate (TDEIO::Job *, const TQValueList< TDEIO::CopyInfo > &);
+ void slotCopyingDone( TDEIO::Job *, const KURL &, const KURL &, bool, bool);
+ void slotFinished();
+ virtual void slotResult( Job *job );
+ void slotListEntries(TDEIO::Job *job, const TDEIO::UDSEntryList &list);
+
+private:
+ TQMap<KURL, Attributes> fileAttributes;
+ TQMap<TDEIO::Job *, KURL> pendingJobs;
+ TQValueList<KURL> directoriesToStamp;
+ TQValueList<KURL> originalDirectories;
+};
+
+#endif /* __PRESERVING_COPY_JOB_H__ */
diff --git a/src/app/VFS/temp_vfs.cpp b/src/app/VFS/temp_vfs.cpp
new file mode 100644
index 0000000..4dc8185
--- /dev/null
+++ b/src/app/VFS/temp_vfs.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ temp_vfs.cpp
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// TQt includes
+#include <tqdir.h>
+// TDE includes
+#include <tdemessagebox.h>
+#include <kprocess.h>
+// Krusader includes
+#include "temp_vfs.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "../VFS/krarchandler.h"
+#include "../resources.h"
+#include "../krservices.h"
+
+temp_vfs::temp_vfs( TQString origin, TQString type, TQWidget* panel, bool ):
+ normal_vfs(panel){
+ vfs_type=TEMP;
+ // first we need to create a temp diretory
+ tmpDir = krApp->getTempDir();
+ // then we must get the files from the origin to the tmp dir
+ if( type == "-arj" || type == "-ace" ) handleAceArj(origin,type);
+ else if( type == "-rpm" ) handleRpm(origin);
+ else if( type == "-iso" ) handleIso(origin);
+ else{
+ if (!quietMode) KMessageBox::error(krApp,"Unknown temp_vfs type.");
+ return;
+ }
+}
+
+temp_vfs::~temp_vfs(){
+ if( tmpvfs_type == ISO ){
+ // unmount the ISO image
+ KShellProcess umount;
+ umount << "umount -f" << tmpDir;
+ umount.start(TDEProcess::Block);
+ }
+ // delete the temp dir
+ KShellProcess proc;
+ proc << "rm -rf" << tmpDir;
+ proc.start(TDEProcess::DontCare);
+}
+
+// return the working dir
+TQString temp_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ TQString path = vfs_origin.path(-1);
+ path = path.mid(path.findRev('\\')+1);
+ if(path.left(1) != "/") path = "/"+path;
+ TQDir().mkdir(tmpDir+path);
+ return tmpDir+path;
+}
+
+bool temp_vfs::vfs_refresh(const KURL& origin){
+ KURL backup = vfs_origin;
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ // get the directory...
+ TQString path = origin.path(-1).mid(origin.path(-1).findRev('\\')+1);
+ if(path.left(1) =="/") path.remove(0,1);
+ if ( !normal_vfs::vfs_refresh(tmpDir+"/"+path) ){
+ vfs_origin = backup;
+ vfs_origin.adjustPath(-1);
+ return false;
+ }
+ return true;
+}
+
+void temp_vfs::handleAceArj(TQString origin, TQString type){
+ if (type == "-ace") {
+ tmpvfs_type = ACE;
+ }
+ else if (type == "-arj") {
+ tmpvfs_type = ARJ;
+ }
+
+ // for ace and arj we just unpack to the tmpDir
+ if( !KRarcHandler::arcHandled(type) ){
+ if (!quietMode) KMessageBox::error(krApp,"This archive type is NOT supported");
+ return;
+ }
+ else if( !KRarcHandler::unpack(origin,type, TQString(), tmpDir) ){
+ return;
+ }
+}
+
+void temp_vfs::handleRpm(TQString origin){
+ // then extract the cpio archive from the rpm
+ KShellProcess rpm;
+ rpm << "rpm2cpio"<<"\""+origin+"\""+" > "+tmpDir+"/contents.cpio";
+ rpm.start(TDEProcess::Block);
+ // and write a nice header
+ rpm.clearArguments();
+ rpm << "rpm -qip"<<"\""+origin+"\""+" > "+tmpDir+"/header.txt";
+ rpm.start(TDEProcess::Block);
+ // and a file list
+ rpm.clearArguments();
+ rpm << "rpm -lpq"<<"\""+origin+"\""+" > "+tmpDir+"/filelist.txt";
+ rpm.start(TDEProcess::Block);
+ tmpvfs_type = RPM;
+}
+
+void temp_vfs::handleIso(TQString origin){
+ // mount the ISO image
+ KShellProcess mount;
+ mount << KrServices::fullPathName( "mount" ) << "-o loop" << origin << tmpDir;
+ mount.start(TDEProcess::Block);
+ tmpvfs_type = ISO;
+}
diff --git a/src/app/VFS/temp_vfs.h b/src/app/VFS/temp_vfs.h
new file mode 100644
index 0000000..d35169b
--- /dev/null
+++ b/src/app/VFS/temp_vfs.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ temp_vfs.h
+ -------------------
+ copyright : (C) 2001 by Shie Erlich & Rafi Yanai
+ email : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#ifndef TEMP_VFS_H
+#define TEMP_VFS_H
+
+#include "normal_vfs.h"
+
+class temp_vfs : public normal_vfs {
+public:
+ enum TMPVFS_TYPE{ERROR=0,ACE,ARJ,RPM,ISO};
+
+ temp_vfs( TQString origin, TQString type, TQWidget* panel, bool writeable);
+ ~temp_vfs();
+ TQString vfs_workingDir();
+ bool vfs_isWritable() { return false; } // temp vfs is not writable !
+
+public slots:
+ // actually reads files and stats
+ bool vfs_refresh(const KURL& origin);
+
+protected:
+ void handleAceArj(TQString origin, TQString type);
+ void handleRpm(TQString origin);
+ void handleIso(TQString origin);
+ TMPVFS_TYPE tmpvfs_type; //< the tmp vfs type.
+ TQString tmpDir;
+
+};
+
+#endif
diff --git a/src/app/VFS/vfile.cpp b/src/app/VFS/vfile.cpp
new file mode 100644
index 0000000..c333f45
--- /dev/null
+++ b/src/app/VFS/vfile.cpp
@@ -0,0 +1,311 @@
+/***************************************************************************
+ vfile.cpp
+ -------------------
+ copyright : (C) 2000 by Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+// System includes
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+// TQt includes
+#include <tqdatetime.h>
+// TDE includes
+#include <kmimetype.h>
+#include <tdeversion.h>
+// Krusader includes
+#include "vfile.h"
+#include "krpermhandler.h"
+#include "normal_vfs.h"
+
+#include <kdebug.h>
+
+vfile::vfile(const TQString& name, // useful construtor
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const uid_t owner,
+ const gid_t group,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx)
+{
+ vfile_name=name;
+ vfile_size=size;
+ vfile_owner=TQString();
+ vfile_ownerId=owner;
+ vfile_group=TQString();
+ vfile_groupId=group;
+ vfile_userName=TQString();
+ vfile_perm=perm;
+ vfile_time_t=mtime;
+ vfile_symLink=symLink;
+ vfile_mimeType=mime;
+ vfile_symDest=symDest;
+ vfile_mode=mode;
+ vfile_isdir = ( perm[ 0 ] == 'd' );
+ if (vfile_isDir() && !vfile_symLink )
+ vfile_size = 0;
+ vfile_rwx = rwx;
+ vfile_acl_loaded = false;
+}
+
+vfile::vfile(const TQString& name, // useful construtor
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const TQString& owner,
+ const TQString& group,
+ const TQString& userName,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx,
+ const TQString& aclString,
+ const TQString& aclDfltString ){
+ vfile_name=name;
+ vfile_size=size;
+ vfile_owner=owner;
+ vfile_group=group;
+ vfile_userName=userName;
+ vfile_ownerId=KRpermHandler::user2uid(owner) ;
+ vfile_groupId=KRpermHandler::group2gid(group);
+ vfile_perm=perm;
+ vfile_time_t=mtime;
+ vfile_symLink=symLink;
+ vfile_mimeType=mime;
+ vfile_symDest=symDest;
+ vfile_mode=mode;
+ vfile_isdir = ( perm[ 0 ] == 'd' );
+ if ( vfile_isDir() && !vfile_symLink )
+ vfile_size = 0;
+ vfile_acl = aclString;
+ vfile_def_acl = aclDfltString;
+ vfile_has_acl = !aclString.isNull() || !aclDfltString.isNull();
+ vfile_acl_loaded = true;
+ vfile_rwx = rwx;
+}
+
+char vfile::vfile_isReadable() const {
+ if( vfile_rwx == PERM_ALL )
+ return ALLOWED_PERM;
+ else if( vfile_userName.isNull() )
+ return KRpermHandler::readable(vfile_perm,vfile_groupId,vfile_ownerId,vfile_rwx);
+ else
+ return KRpermHandler::ftpReadable(vfile_owner, vfile_userName, vfile_perm);
+}
+
+char vfile::vfile_isWriteable() const {
+ if( vfile_rwx == PERM_ALL )
+ return ALLOWED_PERM;
+ else if( vfile_userName.isNull() )
+ return KRpermHandler::writeable(vfile_perm,vfile_groupId,vfile_ownerId,vfile_rwx);
+ else
+ return KRpermHandler::ftpWriteable(vfile_owner, vfile_userName, vfile_perm);
+}
+
+char vfile::vfile_isExecutable() const {
+ if( vfile_rwx == PERM_ALL )
+ {
+ if(( vfile_mode & 0111 ) || vfile_isdir )
+ return ALLOWED_PERM;
+ else
+ return NO_PERM;
+ }
+ else if( vfile_userName.isNull() )
+ return KRpermHandler::executable(vfile_perm,vfile_groupId,vfile_ownerId,vfile_rwx);
+ else
+ return KRpermHandler::ftpExecutable(vfile_owner, vfile_userName, vfile_perm);
+}
+
+const TQString& vfile::vfile_getMime(bool fast){
+ if( vfile_mimeType == TQString() ){ // mimetype == "" is OK so don't check mimetype.empty() !
+ vfile_mimeType = KMimeType::findByURL( vfile_getUrl(),vfile_getMode(),vfile_getUrl().isLocalFile(),fast)->name();
+ if( vfile_mimeType.contains("directory") ) vfile_perm[0] = 'd', vfile_isdir = true;
+ }
+ return vfile_mimeType;
+}
+
+const TQString& vfile::vfile_getOwner(){
+ if( vfile_owner.isEmpty() )
+ vfile_owner=KRpermHandler::uid2user(vfile_getUid());
+ return vfile_owner;
+}
+
+const TQString& vfile::vfile_getGroup(){
+ if( vfile_group.isEmpty() )
+ vfile_group=KRpermHandler::gid2group(vfile_getGid());
+ return vfile_group;
+}
+
+const TQString& vfile::vfile_getACL(){
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ return vfile_acl;
+}
+
+const TQString& vfile::vfile_getDefaultACL(){
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ return vfile_def_acl;
+}
+
+void vfile::vfile_loadACL()
+{
+ if( vfile_url.isLocalFile() )
+ {
+ normal_vfs::getACL( this, vfile_acl, vfile_def_acl );
+ vfile_has_acl = !vfile_acl.isNull() || !vfile_def_acl.isNull();
+ }
+ vfile_acl_loaded = true;
+}
+
+const TDEIO::UDSEntry vfile::vfile_getEntry() {
+ TDEIO::UDSEntry entry;
+ TDEIO::UDSAtom atom;
+
+ atom.m_uds = TDEIO::UDS_NAME;
+ atom.m_str = vfile_getName();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_SIZE;
+ atom.m_long = vfile_getSize();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_MODIFICATION_TIME;
+ atom.m_long = vfile_getTime_t();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_USER;
+ atom.m_str = vfile_getOwner();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_GROUP;
+ atom.m_str = vfile_getGroup();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_MIME_TYPE;
+ atom.m_str = vfile_getMime();
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_FILE_TYPE;
+ atom.m_long = vfile_getMode() & S_IFMT;
+ entry.append(atom);
+
+ atom.m_uds = TDEIO::UDS_ACCESS;
+ atom.m_long = vfile_getMode() & 07777; // keep permissions only
+ entry.append( atom );
+
+ atom.m_uds = TDEIO::UDS_MIME_TYPE;
+ atom.m_str = vfile_getMime();
+ entry.append(atom);
+
+ if( vfile_isSymLink() ){
+ atom.m_uds = TDEIO::UDS_LINK_DEST;
+ atom.m_str = vfile_getSymDest();
+ entry.append(atom);
+ }
+
+#if KDE_IS_VERSION(3,5,0)
+ if( !vfile_acl_loaded )
+ vfile_loadACL();
+ if( vfile_has_acl ) {
+ atom.m_uds = TDEIO::UDS_EXTENDED_ACL;
+ atom.m_long = 1;
+ entry.append( atom );
+
+ if( !vfile_acl.isNull() )
+ {
+ atom.m_uds = TDEIO::UDS_ACL_STRING;
+ atom.m_str = vfile_acl;
+ entry.append(atom);
+ }
+
+ if( !vfile_def_acl.isNull() )
+ {
+ atom.m_uds = TDEIO::UDS_DEFAULT_ACL_STRING;
+ atom.m_str = vfile_acl;
+ entry.append(atom);
+ }
+ }
+#endif
+
+ return entry;
+}
+
+bool vfile::operator==(const vfile& vf) const{
+ bool equal;
+
+ if( !vfile_acl_loaded )
+ const_cast<vfile *>( this )->vfile_loadACL();
+ if( !vf.vfile_acl_loaded )
+ const_cast<vfile *>( &vf )->vfile_loadACL();
+
+ equal = (vfile_name == vf.vfile_getName() ) &&
+ (vfile_size == vf.vfile_getSize() ) &&
+ (vfile_perm == vf.vfile_getPerm() ) &&
+ (vfile_time_t == vf.vfile_getTime_t() ) &&
+ (vfile_ownerId == vf.vfile_getUid() ) &&
+ (vfile_groupId == vf.vfile_getGid() ) &&
+ (vfile_has_acl == vf.vfile_has_acl ) &&
+ (!vfile_has_acl ||
+ (vfile_acl == vf.vfile_acl ) &&
+ (vfile_def_acl == vf.vfile_def_acl ) );;
+
+ return equal;
+}
+
+vfile& vfile::operator= (const vfile& vf){
+ vfile_name = vf.vfile_name ;
+ vfile_size = vf.vfile_size ;
+ vfile_mode = vf.vfile_mode ;
+ vfile_ownerId = vf.vfile_ownerId ;
+ vfile_groupId = vf.vfile_groupId ;
+ vfile_owner = vf.vfile_owner ;
+ vfile_group = vf.vfile_group ;
+ vfile_userName = vf.vfile_userName ;
+ vfile_perm = vf.vfile_perm ;
+ vfile_time_t = vf.vfile_time_t ;
+ vfile_symLink = vf.vfile_symLink ;
+ vfile_mimeType = vf.vfile_mimeType ;
+ vfile_symDest = vf.vfile_symDest ;
+ vfile_url = vf.vfile_url ;
+ vfile_isdir = vf.vfile_isdir ;
+ vfile_has_acl = vf.vfile_has_acl ;
+ vfile_acl = vf.vfile_acl ;
+ vfile_def_acl = vf.vfile_def_acl ;
+ vfile_rwx = vf.vfile_rwx ;
+ vfile_acl_loaded = vf.vfile_acl_loaded;
+
+ return (*this);
+}
+
+#include "vfile.moc"
diff --git a/src/app/VFS/vfile.h b/src/app/VFS/vfile.h
new file mode 100644
index 0000000..b2fc9e8
--- /dev/null
+++ b/src/app/VFS/vfile.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+ vfile.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef VFILE_H
+#define VFILE_H
+
+// TQt includes
+#include <tqstring.h>
+#include <tqobject.h>
+// System includes
+#include <sys/types.h>
+// TDE includes
+#include <tdeio/global.h>
+#include <kmimetype.h>
+
+#define PERM_ALL -2
+
+/**
+ * The Virtual File class handles all the details of maintaining a single
+ * file component within the virtual file system (vfs). a vfile object
+ * contains the nessecery details about a file and member functions which
+ * allow the object to give out the needed details about the file.
+ */
+class vfile : public TQObject{
+ TQ_OBJECT
+
+
+public:
+ vfile(){}
+
+ /**
+ * Use this constructor when you know the following files properties: \n
+ * file name, file size, file permissions,is the file a link,owner uid & group uid.
+ */
+ vfile(const TQString& name,
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const uid_t owner,
+ const gid_t group,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx = -1 );
+
+ vfile(const TQString& name,
+ const TDEIO::filesize_t size,
+ const TQString& perm,
+ const time_t mtime,
+ const bool symLink,
+ const TQString& owner,
+ const TQString& group,
+ const TQString& userName,
+ const TQString& mime,
+ const TQString& symDest,
+ const mode_t mode,
+ const int rwx = -1,
+ const TQString& aclString = TQString(),
+ const TQString& aclDfltString = TQString() );
+
+ bool operator==(const vfile& vf) const;
+ vfile& operator= (const vfile& vf);
+ inline bool operator!=(const vfile& vf){ return !((*this)==vf); }
+
+ // following functions give-out file details
+ inline const TQString& vfile_getName() const { return vfile_name; }
+ inline TDEIO::filesize_t vfile_getSize() const { return vfile_size; }
+ inline const TQString& vfile_getPerm() const { return vfile_perm; }
+ inline bool vfile_isDir() const { return vfile_isdir; }
+ inline bool vfile_isSymLink() const { return vfile_symLink; }
+ inline const TQString& vfile_getSymDest() const { return vfile_symDest; }
+ inline mode_t vfile_getMode() const { return vfile_mode; }
+ inline uid_t vfile_getUid() const { return vfile_ownerId; }
+ inline gid_t vfile_getGid() const { return vfile_groupId; }
+ inline time_t vfile_getTime_t() const { return vfile_time_t; }
+ inline const KURL& vfile_getUrl() const { return vfile_url; }
+
+ const TQString& vfile_getMime(bool fast=false);
+ const TQString& vfile_getOwner();
+ const TQString& vfile_getGroup();
+ const TQString& vfile_getACL();
+ const TQString& vfile_getDefaultACL();
+ const TDEIO::UDSEntry vfile_getEntry(); //< return the UDSEntry from the vfile
+ char vfile_isReadable() const;
+ char vfile_isWriteable() const;
+ char vfile_isExecutable() const;
+ /**
+ * Set the file size.
+ * used ONLY when calculating a directory's space, needs to change the
+ * displayed size of the viewitem and thus the vfile. For INTERNAL USE !
+ */
+ inline void vfile_setSize(TDEIO::filesize_t size) {vfile_size = size;}
+ inline void vfile_setUrl(const KURL& url) {vfile_url = url; }
+
+ inline void vfile_setIcon(const TQString& icn) {vfile_icon = icn; }
+ inline TQString vfile_getIcon();
+
+ virtual ~vfile(){}
+
+private:
+ void vfile_loadACL();
+
+protected:
+ // the file information list
+ TQString vfile_name; //< file name
+ TDEIO::filesize_t vfile_size; //< file size
+ mode_t vfile_mode; //< file mode
+ uid_t vfile_ownerId; //< file owner id
+ gid_t vfile_groupId; //< file group id
+ TQString vfile_owner; //< file owner name
+ TQString vfile_group; //< file group name
+ TQString vfile_userName; //< the current username
+ TQString vfile_perm; //< file permissions string
+ time_t vfile_time_t; //< file modification in time_t format
+ bool vfile_symLink; //< true if the file is a symlink
+ TQString vfile_mimeType; //< file mimetype
+ TQString vfile_symDest; //< if it's a sym link - its detination
+ KURL vfile_url; //< file URL - empty by default
+ TQString vfile_icon; //< the name of the icon file
+ bool vfile_isdir; //< flag, if it's a directory
+ int vfile_rwx; //< flag, showing read, write, execute properties
+ bool vfile_acl_loaded;//<flag, indicates that ACL permissions already loaded
+ bool vfile_has_acl; //< flag, indicates ACL permissions
+ TQString vfile_acl; //< ACL permission string
+ TQString vfile_def_acl; //< ACL default string
+};
+
+
+TQString vfile::vfile_getIcon(){
+ if( vfile_icon.isEmpty() ){
+ TQString mime = this->vfile_getMime();
+ if ( mime == "Broken Link !" )
+ vfile_icon = "file_broken";
+ else {
+ vfile_icon = KMimeType::mimeType( mime ) ->icon( TQString(), true );
+ }
+ }
+ return vfile_icon;
+}
+
+#endif
diff --git a/src/app/VFS/vfs.cpp b/src/app/VFS/vfs.cpp
new file mode 100644
index 0000000..e6804e6
--- /dev/null
+++ b/src/app/VFS/vfs.cpp
@@ -0,0 +1,393 @@
+/***************************************************************************
+ vfs.cpp
+ -------------------
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ------------------------------------------------------------------------
+ the vfs class is an extendable class which by itself does (almost)
+ nothing. other VFSs like the normal_vfs inherits from this class and
+ make it possible to use a consistent API for all types of VFSs.
+
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+#include <tqeventloop.h>
+#include <tdeapplication.h>
+#include <klargefile.h>
+#include <tqdir.h>
+#include "vfs.h"
+#include "../krusader.h"
+#include "../defaults.h"
+
+vfs::vfs(TQObject* panel, bool quiet): vfs_busy(false), quietMode(quiet),disableRefresh(false),postponedRefreshURL(),
+ invalidated(true),panelConnected(false),vfs_tempFilesP(0),vfileIterator(0),deletePossible( true ),
+ deleteRequested( false ) {
+
+
+ setVfsFilesP( new vfileDict() );
+ if ( panel ){
+ panelConnected = true;
+ connect(this,TQ_SIGNAL(startUpdate()),panel,TQ_SLOT(slotStartUpdate()));
+ connect(this,TQ_SIGNAL(incrementalRefreshFinished( const KURL& )),panel,TQ_SLOT(slotGetStats( const KURL& )));
+ }
+ else quietMode = true;
+}
+
+vfs::~vfs() {
+ if( !deletePossible )
+ fprintf( stderr, "INTERNAL ERROR: trying to delete vfs while it is used! This may cause crash. Hoping the best...\n" );
+ clear(); // please don't remove this line. This informs the view about deleting the references
+ delete vfs_filesP;
+}
+
+TDEIO::filesize_t vfs::vfs_totalSize(){
+ TDEIO::filesize_t temp=0;
+ class vfile* vf=vfs_getFirstFile();
+
+ while (vf!=0){
+ if ( (vf->vfile_getName() != ".") && ( vf->vfile_getName() != "..")
+ && !(vf->vfile_isDir()) )
+ temp+=vf->vfile_getSize();
+ vf=vfs_getNextFile();
+ }
+ return temp;
+}
+
+bool vfs::vfs_refresh(TDEIO::Job* job){
+ if(job && job->error()){
+ job->showErrorDialog(krApp);
+ }
+ return vfs_refresh(vfs_origin);
+}
+
+KURL vfs::fromPathOrURL( const TQString &originIn )
+{
+ TQString password, loginName, origin = originIn;
+ bool bugfix = false;
+
+ if ( originIn.contains( ":/" ) && !originIn.startsWith( "/" ) )
+ {
+ // breakdown the url;
+ /* FIXME: untill KDE fixes the bug we have to check for
+ passwords and users with @ in them... */
+ bugfix = origin.find("@") != origin.findRev("@");
+ if(bugfix){
+ if(origin.find(":") != origin.findRev(":", origin.findRev("@") )){
+ int passStart = origin.find( ":",origin.find(":")+1 )+1;
+ int passLen = origin.findRev("@")-passStart;
+ password = origin.mid(passStart,passLen);
+ origin = origin.remove(passStart-1,passLen+1);
+ }
+ if(origin.find("@") != origin.findRev("@")){
+ int usrStart = origin.find( "/" )+1;
+ if(origin.at(usrStart) == '/') ++usrStart;
+ int usrLen = origin.findRev("@")-usrStart;
+ loginName = origin.mid(usrStart,usrLen);
+ origin = origin.remove(usrStart,usrLen+1);
+ }
+ }
+ }
+ KURL url = KURL::fromPathOrURL( origin );
+ if(loginName.isEmpty()) loginName = url.user();
+ if(password.isEmpty()) password = url.pass();
+ if(bugfix){
+ url.setPass(password);
+ url.setUser(loginName);
+ }
+
+ return url;
+}
+
+TQString vfs::pathOrURL( const KURL &originIn, int trailingSlash )
+{
+ if( originIn.isLocalFile() )
+ return originIn.path( trailingSlash );
+ return originIn.prettyURL( trailingSlash );
+}
+
+void vfs::setVfsFilesP(vfileDict* dict){
+ vfs_filesP=dict;
+ vfs_tempFilesP = new vfileDict();
+ vfs_tempFilesP->setAutoDelete( true );
+ dict->setAutoDelete(true);
+ if( vfileIterator ) delete vfileIterator;
+ vfileIterator = new TQDictIterator<vfile>(*dict);
+}
+
+bool vfs::vfs_refresh(){
+ if( vfs_busy )
+ return false;
+
+ if( invalidated ) // invalidated fs requires total refresh
+ return vfs_refresh( vfs_getOrigin() );
+
+ if( disableRefresh )
+ {
+ postponedRefreshURL = vfs_getOrigin();
+ return false;
+ }
+
+ vfs_busy = true;
+ // and populate it
+ krConfig->setGroup("Advanced");
+ int maxIncrementalRefreshFileNr = krConfig->readNumEntry("Max Incremental Refresh File Nr", 50);
+ krConfig->setGroup("Look&Feel");
+ bool showHidden = krConfig->readBoolEntry("Show Hidden",_ShowHidden);
+ bool res = populateVfsList(vfs_getOrigin(),showHidden);
+
+ TQString name;
+ if( res ){
+ // check if the maximum incremental refresh number is achieved
+ int diff = vfs_filesP->count() - vfs_tempFilesP->count();
+ if( diff < 0 )
+ diff = -diff;
+ if( diff >= maxIncrementalRefreshFileNr )
+ {
+ // total filesystem refresh is cheaper than incremental refresh for many files
+ clear();
+ delete vfs_filesP;
+ setVfsFilesP( vfs_tempFilesP );
+ vfs_busy = false;
+
+ emit startUpdate();
+ return true;
+ }
+
+ // compare the two list emiting signals when needed;;
+ for( vfile* vf = vfs_getFirstFile(); vf ; ){
+ name = vf->vfile_getName();
+ vfile* newVf = (*vfs_tempFilesP)[name];
+ if( !newVf ){
+ // the file was deleted..
+ emit deletedVfile(name);
+ vfs_filesP->remove(name);
+ // the remove() advance our iterator !
+ vf = vfileIterator->current();
+ } else {
+ if( *vf != *newVf ){
+ // the file was changed..
+ *vf = *newVf;
+ emit updatedVfile(vf);
+ }
+ vf=vfs_getNextFile();
+ }
+ vfs_tempFilesP->remove(name);
+ }
+ // everything thats left is a new file
+ TQDictIterator<vfile> it(*vfs_tempFilesP);
+ for(vfile* vf=it.toFirst(); vf; vf=(++it)){
+ // sanity checking
+ if( !vf || (*vfs_filesP)[vf->vfile_getName()] ) continue;
+
+ vfile* newVf = new vfile();
+ *newVf = *vf;
+ vfs_filesP->insert(newVf->vfile_getName(),newVf);
+ emit addedVfile(newVf);
+ }
+ }
+
+ // delete the temporary vfiles
+ vfs_tempFilesP->clear();
+ vfs_busy = false;
+
+ emit incrementalRefreshFinished( vfs_origin );
+
+ return res;
+}
+
+bool vfs::vfs_refresh(const KURL& origin){
+ if( vfs_busy )
+ return false;
+
+ if( disableRefresh )
+ {
+ postponedRefreshURL = origin;
+ return true;
+ }
+
+ if( !invalidated && origin.equals(vfs_getOrigin(),true) ) return vfs_refresh();
+
+ vfs_busy = true;
+
+ krConfig->setGroup("Look&Feel");
+ bool showHidden = krConfig->readBoolEntry("Show Hidden",_ShowHidden);
+
+ vfs_tempFilesP->clear();
+ // and re-populate it
+ if (!populateVfsList(origin,showHidden) )
+ {
+ vfs_busy = false;
+ return false;
+ }
+
+ clear();
+ delete vfs_filesP;
+ setVfsFilesP( vfs_tempFilesP );
+ vfs_busy = false;
+
+ emit startUpdate();
+
+ invalidated = false;
+ return true;
+}
+
+void vfs::vfs_enableRefresh(bool enable){
+ if (vfs_type != NORMAL) return;
+ if (disableRefresh == !enable) return; // if gets called twice by mistake
+ disableRefresh = quietMode = !enable;
+ if( enable && !postponedRefreshURL.isEmpty() ) vfs_refresh( postponedRefreshURL );
+ postponedRefreshURL = KURL();
+}
+
+void vfs::clear()
+{
+ emit cleared();
+ vfs_filesP->clear();
+}
+
+bool vfs::vfs_processEvents() {
+ if( deleteRequested )
+ return false;
+ deletePossible = false;
+ tqApp->eventLoop() ->processEvents( TQEventLoop::AllEvents | TQEventLoop::WaitForMore );
+ deletePossible = true;
+ if( deleteRequested ) {
+ emit deleteAllowed();
+ return false;
+ }
+ return true;
+}
+
+void vfs::vfs_requestDelete() {
+ if( deletePossible )
+ emit deleteAllowed();
+ deleteRequested = true;
+}
+
+/// to be implemented
+#if KDE_IS_VERSION(3,3,0)
+#include <kdirsize.h>
+void vfs::slotKdsResult( TDEIO::Job* job){
+ if( job && !job->error() ){
+ KDirSize* kds = static_cast<KDirSize*>(job);
+ *kds_totalSize += kds->totalSize();
+ *kds_totalFiles += kds->totalFiles();
+ *kds_totalDirs += kds->totalSubdirs();
+ }
+ *kds_busy = true;
+}
+
+void vfs::vfs_calcSpace( TQString name , TDEIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ calculateURLSize( vfs_getFile( name ), totalSize, totalFiles, totalDirs, stop );
+}
+
+void vfs::calculateURLSize( KURL url, TDEIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ if ( stop && *stop ) return ;
+ kds_busy = stop;
+ kds_totalSize = totalSize ;
+ kds_totalFiles = totalFiles;
+ kds_totalDirs = totalDirs;
+
+ if( url.isLocalFile() ) {
+ vfs_calcSpaceLocal( url.path(-1), totalSize, totalFiles, totalDirs, stop );
+ return;
+ } else {
+ stat_busy = true;
+ TDEIO::StatJob* statJob = TDEIO::stat( url, false );
+ connect( statJob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResultArrived( TDEIO::Job* ) ) );
+ while ( !(*stop) && stat_busy ) {usleep(1000);}
+ if( entry.isEmpty() ) return; // statJob failed
+ KFileItem kfi(entry, url, true );
+ if( kfi.isFile() || kfi.isLink() ) {
+ *totalFiles++;
+ *totalSize += kfi.size();
+ return;
+ }
+ }
+
+ KDirSize* kds = KDirSize::dirSizeJob( url );
+ connect( kds, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotKdsResult( TDEIO::Job* ) ) );
+ while ( !(*stop) ){
+ // we are in a sepetate thread - so sleeping is OK
+ usleep(1000);
+ }
+}
+
+void vfs::vfs_calcSpaceLocal(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool* stop){
+ if ( *stop ) return;
+ if (!name.contains("/")) name = vfs_workingDir()+"/"+name;
+ if (name == "/proc") return;
+
+ KDE_struct_stat stat_p; // KDE lstat is necessary as TQFileInfo and KFileItem
+ KDE_lstat(name.local8Bit(),&stat_p); // reports wrong size for a symbolic link
+
+ if( S_ISLNK(stat_p.st_mode) || !S_ISDIR(stat_p.st_mode) ) { // single files are easy : )
+ ++(*totalFiles);
+ (*totalSize) += stat_p.st_size;
+ }
+ else{ // handle directories
+ // avoid a nasty crash on un-readable dirs
+ bool readable = ::access( name.local8Bit(), R_OK | X_OK ) == 0;
+ if( !readable )
+ return;
+
+ TQDir dir(name);
+ if ( !dir.exists() ) return;
+
+ ++(*totalDirs);
+ dir.setFilter(TQDir::All | TQDir::System | TQDir::Hidden);
+ dir.setSorting(TQDir::Name | TQDir::DirsFirst);
+
+ // recurse on all the files in the directory
+ TQFileInfoList* fileList = const_cast<TQFileInfoList*>(dir.entryInfoList());
+ for (TQFileInfo* qfiP = fileList->first(); qfiP != 0; qfiP = fileList->next()){
+ if ( *stop ) return;
+ if (qfiP->fileName() != "." && qfiP->fileName() != "..")
+ vfs_calcSpaceLocal(name+"/"+qfiP->fileName(),totalSize,totalFiles,totalDirs,stop);
+ }
+ }
+}
+
+
+void vfs::slotStatResultArrived( TDEIO::Job* job ) {
+ if( !job || job->error() ) entry = TDEIO::UDSEntry();
+ else entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ stat_busy = false;
+}
+
+#else
+void vfs::slotKdsResult(TDEIO::Job *job){/* empty */}
+void vfs::vfs_calcSpace( TQString /*name*/ , TDEIO::filesize_t* /*totalSize*/, unsigned long* /*totalFiles*/, unsigned long* /*totalDirs*/, bool* /*stop*/ ) {/* empty*/}
+#endif
+
+TQValueList<vfile*> vfs::vfs_search(const KRQuery& filter) {
+ TQValueList<vfile*> result;
+ for ( vfile *vf = vfs_getFirstFile(); vf != 0 ; vf = vfs_getNextFile() )
+ if (filter.match(vf))
+ result.append(vf);
+ return result;
+}
+
+#include "vfs.moc"
diff --git a/src/app/VFS/vfs.h b/src/app/VFS/vfs.h
new file mode 100644
index 0000000..9253de0
--- /dev/null
+++ b/src/app/VFS/vfs.h
@@ -0,0 +1,187 @@
+/***************************************************************************
+ vfs.h
+ -------------------
+ begin : Thu May 4 2000
+ copyright : (C) 2000 by Shie Erlich & Rafi Yanai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef VFS_H
+#define VFS_H
+
+// TQt includes
+#include <tqstring.h>
+#include <tqvaluelist.h>
+#include <tqobject.h>
+#include <tqdict.h>
+// TDE includes
+#include <kurl.h>
+#include <tdeio/jobclasses.h>
+// Krusader includes
+#include "vfile.h"
+#include "preservingcopyjob.h"
+#include "krquery.h"
+
+/**
+ * The vfs class is an extendable class which by itself does (almost)
+ * nothing. other VFSs like the normal_vfs inherits from this class and
+ * make it possible to use a consistent API for all types of VFSs.
+ */
+class vfs: public TQObject{
+ TQ_OBJECT
+
+public:
+ typedef TQDict<vfile> vfileDict;
+ enum VFS_TYPE{ERROR=0,NORMAL,FTP,TEMP,VIRT};
+
+ /**
+ * Creates a vfs.
+ * @param panel the panel father. the VFS will connect it's signals to this object.
+ * @param quiet if true, the VFS will not display error messages
+ */
+ vfs(TQObject* panel, bool quiet=false);
+ virtual ~vfs();
+
+ /// Copy a file to the vfs (physical).
+ virtual void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT)=0;
+ /// Remove a file from the vfs (physical)
+ virtual void vfs_delFiles(TQStringList *fileNames)=0;
+ /// Return a list of URLs for multiple files
+ virtual KURL::List* vfs_getFiles(TQStringList* names)=0;
+ /// Return a URL to a single file
+ virtual KURL vfs_getFile(const TQString& name)=0;
+ /// Create a new directory
+ virtual void vfs_mkdir(const TQString& name)=0;
+ /// Rename file
+ virtual void vfs_rename(const TQString& fileName,const TQString& newName)=0;
+ /// Calculate the amount of space occupied by a file or directory (recursive).
+ virtual void vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+ /// Calculate the amount of space occupied by a local file or directory (recursive).
+ virtual void vfs_calcSpaceLocal(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ /// Return the VFS working dir
+ virtual TQString vfs_workingDir()=0;
+ /// Return true if the VFS url is writable
+ virtual bool vfs_isWritable() { return isWritable; }
+ /// Return vfile* or 0 if not found
+ inline vfile* vfs_search(const TQString& name){ return (*vfs_filesP)[name]; }
+ /// Return an empty vfile* list if not found
+ TQValueList<vfile*> vfs_search(const KRQuery& filter);
+ /// The total size of all the files in the VFS,
+ TDEIO::filesize_t vfs_totalSize();
+ /// The number of files in the VFS
+ inline unsigned long vfs_noOfFiles() { return vfs_filesP->count(); }
+ /// Returns the VFS url.
+ inline KURL vfs_getOrigin() { return vfs_origin; }
+ /// Return the VFS type.
+ inline VFS_TYPE vfs_getType() { return vfs_type; }
+ /// Returns true if vfs is busy
+ inline bool vfs_isBusy() { return vfs_busy; }
+ /// Return the first file in the VFS and set the internal iterator to the beginning of the list.
+ inline vfile* vfs_getFirstFile(){ return (vfileIterator ? vfileIterator->toFirst() : 0); }
+ /// Return the the next file in the list and advance the iterator.
+ inline vfile* vfs_getNextFile() { return (vfileIterator ? ++(*vfileIterator) : 0); }
+ /// returns true if the vfs can be deleted without crash
+ virtual bool vfs_canDelete() { return deletePossible; }
+ /// process the application events
+ virtual bool vfs_processEvents();
+ /// process the application events
+ virtual void vfs_requestDelete();
+ /// process the application events
+ virtual bool vfs_isDeleting() { return deleteRequested; }
+ // KDE FTP proxy bug correction
+ static KURL fromPathOrURL( const TQString &originIn );
+ static TQString pathOrURL( const KURL &originIn, int trailingSlash = 0 );
+
+
+public slots:
+ /// Re-reads files and stats and fills the vfile list
+ bool vfs_refresh(const KURL& origin);
+ /// Used to refresh the VFS when a job finishs. it calls the refresh() slot
+ /// or display a error message if the job fails
+ bool vfs_refresh(TDEIO::Job* job);
+ bool vfs_refresh();
+ void vfs_setQuiet(bool beQuiet){ quietMode=beQuiet; }
+ void vfs_enableRefresh(bool enable);
+ void vfs_invalidate() { invalidated = true; }
+
+signals:
+ void startUpdate(); //< emitted when the VFS starts to refresh its list of vfiles.
+ void startJob(TDEIO::Job* job);
+ void incrementalRefreshFinished( const KURL& ); //< emitted when the incremental refresh was finished
+ void addedVfile(vfile* vf);
+ void deletedVfile(const TQString& name);
+ void updatedVfile(vfile* vf);
+ void cleared();
+ void deleteAllowed();
+
+protected:
+ /// Feel the vfs dictionary with vfiles, must be implemented for each vfs
+ virtual bool populateVfsList(const KURL& origin, bool showHidden) = 0;
+ /// Called by populateVfsList for each file
+ void foundVfile( vfile *vf ) { vfs_tempFilesP->insert(vf->vfile_getName(),vf); }
+ /// Set the vfile list pointer
+ void setVfsFilesP(vfileDict* dict);
+ /// clear and delete all current vfiles
+ inline void clear();
+ /// Add a new vfile to the list.
+ inline void addToList(vfile *data){ vfs_filesP->insert(data->vfile_getName(),data); }
+ /// Deletes a vfile from the list.
+ inline void removeFromList(TQString name){ vfs_filesP->remove(name); }
+
+ /// Deletes a vfile from the list.
+ void calculateURLSize(KURL url,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ VFS_TYPE vfs_type; //< the vfs type.
+ KURL vfs_origin; //< the path or file the VFS originates from.
+ bool vfs_busy; //< true if vfs is busy with refreshing
+ bool quietMode; //< if true the vfs won't display error messages or emit signals
+ bool disableRefresh; //< true if refresh is disabled
+ bool isWritable; //< true if it's writable
+ KURL postponedRefreshURL; //< true if vfs_refresh() was called when refresh is disabled.
+ bool invalidated; //< the content of the cache is invalidated
+ bool panelConnected; //< indicates that there's a panel connected. Important for disabling the dir watcher
+
+protected slots:
+ /// The slot for the KDirSize job
+ void slotKdsResult(TDEIO::Job *job);
+ void slotStatResultArrived(TDEIO::Job *job);
+
+private:
+ vfileDict* vfs_filesP; //< Point to a lists of virtual files (vfile).
+ vfileDict* vfs_tempFilesP;//< Temporary files are stored here
+ TQDictIterator<vfile>* vfileIterator; //< Point to a dictionary of virtual files (vfile).
+
+ // used in the calcSpace function
+ bool* kds_busy;
+ bool stat_busy;
+ bool deletePossible;
+ bool deleteRequested;
+ TDEIO::UDSEntry entry;
+ TDEIO::filesize_t* kds_totalSize;
+ unsigned long* kds_totalFiles;
+ unsigned long* kds_totalDirs;
+};
+
+#endif
diff --git a/src/app/VFS/virt_vfs.cpp b/src/app/VFS/virt_vfs.cpp
new file mode 100644
index 0000000..3c70231
--- /dev/null
+++ b/src/app/VFS/virt_vfs.cpp
@@ -0,0 +1,341 @@
+/***************************************************************************
+ virt_vfs.cpp - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <time.h>
+
+#include <tdefileitem.h>
+#include <tdeglobalsettings.h>
+#include <kurl.h>
+#include <tdemessagebox.h>
+#include <tdelocale.h>
+#include <kdirsize.h>
+#include <kstandarddirs.h>
+
+#include "krpermhandler.h"
+#include "../krusader.h"
+#include "../defaults.h"
+#include "virt_vfs.h"
+
+#define VIRT_VFS_DB "virt_vfs.db"
+
+TQDict<KURL::List> virt_vfs::virtVfsDict;
+TDEConfig* virt_vfs::virt_vfs_db=0;
+
+virt_vfs::virt_vfs( TQObject* panel, bool quiet ) : vfs( panel, quiet ) {
+ // set the writable attribute
+ isWritable = true;
+
+ virtVfsDict.setAutoDelete( true );
+ if ( virtVfsDict.isEmpty() ) {
+ restore();
+ }
+
+ vfs_type = VIRT;
+}
+
+virt_vfs::~virt_vfs() {}
+
+bool virt_vfs::populateVfsList( const KURL& origin, bool /*showHidden*/ ) {
+ vfs_origin = origin;
+ vfs_origin.adjustPath(-1);
+ path = origin.path( -1 ).mid( 1 );
+ if ( path.isEmpty() ) path = "/";
+
+ KURL::List* urlList = virtVfsDict[ path ];
+ if ( !urlList ) {
+ urlList = new KURL::List();
+ virtVfsDict.insert( path, urlList );
+ virtVfsDict[ "/" ] ->append( KURL::fromPathOrURL( "virt:/" + path ) );
+ }
+
+ if ( urlList->isEmpty() ) return true;
+ KURL::List::iterator it;
+ for ( it = urlList->begin() ; it != urlList->end() ; /*++it*/ ) {
+ KURL url = *it;
+ // translate url->vfile and remove urls that no longer exist from the list
+ vfile* vf = stat(url);
+ if ( !vf ) {
+ it = urlList->remove( it );
+ // the iterator is advanced automaticly
+ continue;
+ }
+ foundVfile( vf );
+ ++it;
+ }
+ save();
+ return true;
+}
+
+void virt_vfs::vfs_addFiles( KURL::List *fileUrls, TDEIO::CopyJob::CopyMode /*mode*/, TQObject* /*toNotify*/, TQString /*dir*/, PreserveMode /*pmode*/ ) {
+ if ( path == "/" ) {
+ if ( !quietMode )
+ KMessageBox::error( krApp, i18n( "You can't copy files directly to the 'virt:/' directory.\nYou can create a sub directory and copy your files into it." ), i18n( "Error" ) );
+ return ;
+ }
+
+ KURL::List* urlList = virtVfsDict[ path ];
+ for( unsigned i=0; i != fileUrls->count(); i++ ) {
+ if( !urlList->contains( (*fileUrls)[ i ] ) )
+ urlList->push_back( (*fileUrls)[ i ] );
+ }
+
+ vfs_refresh();
+}
+
+void virt_vfs::vfs_delFiles( TQStringList *fileNames ) {
+ if ( path == "/" ) {
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ TQString filename = ( *fileNames ) [ i ];
+ virtVfsDict[ "/" ] ->remove( TQString("virt:/")+filename );
+ virtVfsDict.remove( filename );
+ }
+ vfs_refresh();
+ return ;
+ }
+
+ KURL::List filesUrls;
+ KURL url;
+
+ // names -> urls
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ TQString filename = ( *fileNames ) [ i ];
+ filesUrls.append( vfs_getFile( filename ) );
+ }
+ TDEIO::Job *job;
+
+ // delete of move to trash ?
+ krConfig->setGroup( "General" );
+ if ( krConfig->readBoolEntry( "Move To Trash", _MoveToTrash ) ) {
+#if KDE_IS_VERSION(3,4,0)
+ job = TDEIO::trash( filesUrls, true );
+#else
+ job = new TDEIO::CopyJob( filesUrls, TDEGlobalSettings::trashPath(), TDEIO::CopyJob::Move, false, true );
+#endif
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), krApp, TQ_SLOT( changeTrashIcon() ) );
+ } else
+ job = new TDEIO::DeleteJob( filesUrls, false, true );
+
+ // refresh will remove the deleted files...
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+void virt_vfs::vfs_removeFiles( TQStringList *fileNames ) {
+ if ( path == "/" )
+ return;
+
+ // removing the URLs from the collection
+ for ( uint i = 0 ; i < fileNames->count(); ++i ) {
+ KURL::List* urlList = virtVfsDict[ path ];
+ if( urlList )
+ urlList->remove( vfs_getFile( ( *fileNames ) [ i ] ) );
+ }
+
+ vfs_refresh();
+}
+
+KURL::List* virt_vfs::vfs_getFiles( TQStringList* names ) {
+ KURL url;
+ KURL::List* urls = new KURL::List();
+ for ( TQStringList::Iterator name = names->begin(); name != names->end(); ++name ) {
+ url = vfs_getFile( *name );
+ urls->append( url );
+ }
+ return urls;
+}
+
+KURL virt_vfs::vfs_getFile( const TQString& name ) {
+ vfile * vf = vfs_search( name );
+ if ( !vf ) return KURL(); // empty
+
+ KURL url = vf->vfile_getUrl();
+ if ( vf->vfile_isDir() ) url.adjustPath( + 1 );
+ return url;
+}
+
+void virt_vfs::vfs_mkdir( const TQString& name ) {
+ if ( path != "/" ) {
+ if ( !quietMode )
+ KMessageBox::error( krApp, i18n( "Creating new directories is allowed only in the 'virt:/' directory." ), i18n( "Error" ) );
+ return ;
+ }
+ KURL::List* temp = new KURL::List();
+ virtVfsDict.insert( name, temp );
+ virtVfsDict[ "/" ] ->append( TQString( "virt:/" )+name );
+
+ vfs_refresh();
+}
+
+void virt_vfs::vfs_rename( const TQString& fileName, const TQString& newName ) {
+ KURL::List fileUrls;
+ KURL url , dest;
+
+ vfile* vf = vfs_search( fileName );
+ if ( !vf ) return ; // not found
+
+ if ( path == "/" ) {
+ virtVfsDict[ "/" ] ->append( TQString( "virt:/" ) + newName );
+ virtVfsDict[ "/" ] ->remove( TQString( "virt:/" ) + fileName );
+ virtVfsDict.insert( newName, virtVfsDict.take( fileName ) );
+ vfs_refresh();
+ return ;
+ }
+
+ url = vf->vfile_getUrl();
+ fileUrls.append( url );
+
+ dest = fromPathOrURL( newName );
+ // add the new url to the list
+ // the the list is refreshed only existing files remain -
+ // so we don't have to worry if the job was successful
+ virtVfsDict[ path ] ->append( dest );
+
+ TDEIO::Job *job = new TDEIO::CopyJob( fileUrls, dest, TDEIO::CopyJob::Move, true, false );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( vfs_refresh( TDEIO::Job* ) ) );
+}
+
+void virt_vfs::slotStatResult( TDEIO::Job* job ) {
+ if( !job || job->error() ) entry = TDEIO::UDSEntry();
+ else entry = static_cast<TDEIO::StatJob*>(job)->statResult();
+ busy = false;
+}
+
+vfile* virt_vfs::stat( const KURL& url ) {
+ if( url.protocol() == "virt" ){
+ TQString path = url.path().mid(1);
+ if( path.isEmpty() ) path = "/";
+ vfile * temp = new vfile( path, 0, "drwxr-xr-x", time( 0 ), false, getuid(), getgid(), "inode/directory", "", 0 );
+ temp->vfile_setUrl( url );
+ return temp;
+ }
+ KFileItem* kfi;
+ if ( url.isLocalFile() ) {
+ kfi = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, url, true );
+ }
+ else {
+ busy = true;
+ TDEIO::StatJob* statJob = TDEIO::stat( url, false );
+ connect( statJob, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::Job* ) ) );
+ while ( busy && vfs_processEvents() );
+ if( entry.isEmpty() ) return 0; // statJob failed
+
+ kfi = new KFileItem(entry, url, true );
+ }
+
+ if ( !kfi->time( TDEIO::UDS_MODIFICATION_TIME ) ){
+ delete kfi;
+ return 0; // file not found
+ }
+
+ vfile *temp;
+
+ // get file statistics
+ TQString name;
+ if( url.isLocalFile() )
+ name = url.path();
+ else
+ name = url.prettyURL();
+
+ TDEIO::filesize_t size = kfi->size();
+ time_t mtime = kfi->time( TDEIO::UDS_MODIFICATION_TIME );
+ bool symLink = kfi->isLink();
+ mode_t mode = kfi->mode() | kfi->permissions();
+ TQString perm = KRpermHandler::mode2TQString( mode );
+// set the mimetype
+ TQString mime = TQString();
+ TQString symDest = "";
+ if ( symLink ) {
+ symDest = kfi->linkDest();
+ if ( kfi->isDir() ) perm[ 0 ] = 'd';
+ }
+
+ // create a new virtual file object
+ if ( kfi->user().isEmpty() )
+ temp = new vfile( name, size, perm, mtime, symLink, getuid(), getgid(), mime, symDest, mode );
+ else {
+ TQString currentUser = url.user();
+ if ( currentUser.contains( "@" ) ) /* remove the FTP proxy tags from the username */
+ currentUser.truncate( currentUser.find( '@' ) );
+ if ( currentUser.isEmpty() )
+ currentUser = KRpermHandler::uid2user( getuid() );
+ temp = new vfile( name, size, perm, mtime, symLink, kfi->user(), kfi->group(), currentUser, mime, symDest, mode );
+ }
+
+ temp->vfile_setUrl( kfi->url() );
+ delete kfi;
+ return temp;
+}
+
+TDEConfig* virt_vfs::getVirtDB(){
+ if( !virt_vfs_db ){
+ virt_vfs_db = new TDEConfig(VIRT_VFS_DB,false,"data");
+ }
+ return virt_vfs_db;
+}
+
+bool virt_vfs::save(){
+ TDEConfig* db = getVirtDB();
+
+ db->setGroup("virt_db");
+ TQDictIterator<KURL::List> it( virtVfsDict ); // See TQDictIterator
+ for( ; it.current(); ++it ){
+ KURL::List::iterator url;
+ TQStringList entry;
+ for ( url = it.current()->begin() ; url != it.current()->end() ; ++url ) {
+ entry.append( (*url).prettyURL() );
+ }
+ db->writeEntry(it.currentKey(),entry);
+ }
+
+ db->sync();
+
+ return true;
+}
+
+bool virt_vfs::restore(){
+ TDEConfig* db = getVirtDB();
+ db->setGroup("virt_db");
+
+ TQMap<TQString, TQString> map = db->entryMap("virt_db");
+ TQMap<TQString, TQString>::Iterator it;
+ KURL::List* urlList;
+ for ( it = map.begin(); it != map.end(); ++it ) {
+ urlList = new KURL::List( db->readListEntry(it.key()) );
+ virtVfsDict.insert( it.key(),urlList );
+ }
+
+ if( !virtVfsDict["/" ]){
+ urlList = new KURL::List();
+ virtVfsDict.insert( "/", urlList );
+ }
+
+ return true;
+}
+
+void virt_vfs::vfs_calcSpace( TQString name , TDEIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop ) {
+ if ( stop && *stop ) return ;
+ if( path == "/" ) {
+ KURL::List* urlList = virtVfsDict[ name ];
+ if ( urlList )
+ for( unsigned i=0; (i != urlList->size()) && !(*stop); i++ )
+ calculateURLSize( (*urlList)[ i ], totalSize, totalFiles, totalDirs, stop );
+ return;
+ }
+ return vfs::vfs_calcSpace( name, totalSize, totalFiles, totalDirs, stop );
+}
+
+#include "virt_vfs.moc"
diff --git a/src/app/VFS/virt_vfs.h b/src/app/VFS/virt_vfs.h
new file mode 100644
index 0000000..6663e21
--- /dev/null
+++ b/src/app/VFS/virt_vfs.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ virt_vfs.h - description
+ -------------------
+ begin : Fri Dec 5 2003
+ copyright : (C) 2003 by Shie Erlich & Rafi Yanai
+ email :
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef VIRT_VFS_H
+#define VIRT_VFS_H
+
+#include <tdeconfig.h>
+
+#include "vfs.h"
+
+/**
+ *@author Shie Erlich & Rafi Yanai
+ */
+
+class virt_vfs : public vfs {
+TQ_OBJECT
+
+public:
+ virt_vfs(TQObject* panel, bool quiet=false);
+ ~virt_vfs();
+
+ /// Copy a file to the vfs (physical).
+ void vfs_addFiles(KURL::List *fileUrls,TDEIO::CopyJob::CopyMode mode,TQObject* toNotify,TQString dir = "", PreserveMode pmode = PM_DEFAULT );
+ /// Remove a file from the vfs (physical)
+ void vfs_delFiles(TQStringList *fileNames);
+ /// Remove a file from the collection (only its link, not the file)
+ void vfs_removeFiles(TQStringList *fileNames);
+ /// Return a list of URLs for multiple files
+ KURL::List* vfs_getFiles(TQStringList* names);
+ /// Return a URL to a single file
+ KURL vfs_getFile(const TQString& name);
+ /// Create a new directory
+ void vfs_mkdir(const TQString& name);
+ /// Rename file
+ void vfs_rename(const TQString& fileName,const TQString& newName);
+ /// Calculate the amount of space occupied by a file or directory (recursive).
+ virtual void vfs_calcSpace(TQString name ,TDEIO::filesize_t *totalSize,unsigned long *totalFiles,unsigned long *totalDirs, bool * stop);
+
+ /// Return the VFS working dir
+ TQString vfs_workingDir(){ return TQString(); }
+
+protected slots:
+ void slotStatResult(TDEIO::Job *job);
+
+protected:
+ /// Save the dictionary to file
+ bool save();
+ /// Restore the dictionary from file
+ bool restore();
+ /// return the URLs DB
+ TDEConfig* getVirtDB();
+
+ bool populateVfsList(const KURL& origin, bool showHidden);
+ vfile* stat(const KURL& url);
+
+ static TQDict<KURL::List> virtVfsDict;
+ static TDEConfig* virt_vfs_db;
+ bool busy;
+ TQString path;
+ TDEIO::UDSEntry entry;
+};
+
+#endif
diff --git a/src/app/VFS/virtualcopyjob.cpp b/src/app/VFS/virtualcopyjob.cpp
new file mode 100644
index 0000000..15be7fa
--- /dev/null
+++ b/src/app/VFS/virtualcopyjob.cpp
@@ -0,0 +1,316 @@
+/***************************************************************************
+ virtualcopyjob.cpp - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ S o u r c e F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "virtualcopyjob.h"
+#include "vfs.h"
+#include "vfile.h"
+#include "../krusader.h"
+#include <tdeio/observer.h>
+#include <tdeio/global.h>
+#include <tdeio/jobclasses.h>
+#include <kdirsize.h>
+
+#define REPORT_TIMEOUT 200
+
+VirtualCopyJob::VirtualCopyJob( const TQStringList *names, vfs * vfs, const KURL& dest, const KURL& baseURL,
+ PreserveMode pmode, TDEIO::CopyJob::CopyMode mode, bool asMethod, bool showProgressInfo ) :
+ TDEIO::Job( showProgressInfo ), m_totalSize( 0 ), m_totalFiles( 0 ), m_totalSubdirs( 0 ),
+ m_processedSize( 0 ), m_processedFiles( 0 ), m_processedSubdirs( 0 ), m_tempSize( 0 ), m_tempFiles( 0 ),
+ m_tempSubdirs( 0 ), m_dirsToGetSize(), m_filesToCopy(), m_size(), m_filenum(), m_subdirs(), m_baseURL( baseURL ),
+ m_dest( dest ), m_pmode( pmode ), m_mode( mode ), m_asMethod( asMethod ), m_showProgressInfo( showProgressInfo ),
+ m_state( ST_STARTING ), m_reportTimer(), m_current(), m_currentDir(), m_dirStack() {
+
+ m_filesToCopy.setAutoDelete( true );
+ m_dest.adjustPath( 1 );
+
+ vfile * file = vfs->vfs_getFirstFile();
+ while( file ) {
+ if( names->contains( file->vfile_getName() ) ) {
+ TQString relativeDir = KURL::relativeURL( baseURL, file->vfile_getUrl().upURL() );
+
+ KURL::List *list = m_filesToCopy.find( relativeDir );
+ if( list == 0 ) {
+ list = new KURL::List();
+ m_filesToCopy.insert( relativeDir, list );
+ // initialize the dir content
+ m_size[ relativeDir ] = 0;
+ m_filenum[ relativeDir ] = 0;
+ m_subdirs[ relativeDir ] = 0;
+ }
+
+ if( !list->contains( file->vfile_getUrl() ) ) {
+ if( file->vfile_isDir() ) {
+ m_dirsToGetSize.append( file->vfile_getUrl() );
+ m_totalSubdirs++;
+ m_subdirs[ relativeDir ]++;
+ } else {
+ m_totalFiles++;
+ m_filenum[ relativeDir ]++;
+ m_totalSize += file->vfile_getSize();
+ m_size[ relativeDir ] += file->vfile_getSize();
+ }
+ list->append( file->vfile_getUrl() );
+ }
+ }
+ file = vfs->vfs_getNextFile();
+ }
+
+ if ( showProgressInfo ) {
+ connect( this, TQ_SIGNAL( totalFiles( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotTotalFiles( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( totalDirs( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotTotalDirs( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( processedFiles( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotProcessedFiles( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( processedDirs( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotProcessedDirs( TDEIO::Job*, unsigned long ) ) );
+ connect( this, TQ_SIGNAL( percent( TDEIO::Job*, unsigned long ) ),
+ Observer::self(), TQ_SLOT( slotPercent( TDEIO::Job*, unsigned long ) ) );
+ }
+
+ TQTimer::singleShot( 0, this, TQ_SLOT( slotStart() ) );
+}
+
+void VirtualCopyJob::slotStart() {
+ if( m_showProgressInfo ) {
+ if( m_mode == TDEIO::CopyJob::Move )
+ Observer::self()->slotMoving( this, m_baseURL, m_dest );
+ else
+ Observer::self()->slotCopying( this, m_baseURL, m_dest );
+ }
+
+ connect(&m_reportTimer,TQ_SIGNAL(timeout()),this,TQ_SLOT(slotReport()));
+ m_reportTimer.start(REPORT_TIMEOUT,false);
+
+ statNextDir();
+}
+
+void VirtualCopyJob::slotReport() {
+ switch( m_state ) {
+ case ST_CREATING_DIRECTORY:
+ if( m_showProgressInfo ) {
+ Observer::self()->slotCreatingDir( this, m_current );
+ Observer::self()->slotProcessedDirs( this, m_processedSubdirs );
+ emit processedDirs( this, m_processedSubdirs );
+ }
+ break;
+ case ST_CALCULATING_TOTAL_SIZE:
+ emit totalSize( this, m_totalSize );
+ emit totalDirs( this, m_totalSubdirs );
+ emit totalFiles( this, m_totalFiles );
+ break;
+ case ST_COPYING:
+ {
+ emit processedDirs( this, m_processedSubdirs + m_tempSubdirs );
+ emit processedFiles( this, m_processedFiles + m_tempFiles );
+ setProcessedSize( m_processedSize + m_tempSize );
+ emit processedSize( this, m_processedSize + m_tempSize );
+ double percDbl = ((double)( m_processedSize + m_tempSize )/(double)m_totalSize) * 100. + 0.5;
+ unsigned long perc = (long)percDbl;
+ if( perc > 100 )
+ perc = 100;
+ emit percent( this, perc );
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void VirtualCopyJob::statNextDir() {
+ m_state = ST_CALCULATING_TOTAL_SIZE;
+
+ if( m_dirsToGetSize.count() == 0 ) {
+ slotReport(); // report the total size values
+ createNextDir();
+ return;
+ }
+ KURL dirToCheck = m_dirsToGetSize.first();
+ m_dirsToGetSize.pop_front();
+
+ m_currentDir = KURL::relativeURL( m_baseURL, dirToCheck.upURL() );
+
+ KDirSize* kds = KDirSize::dirSizeJob( dirToCheck );
+ connect( kds, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotKdsResult( TDEIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotKdsResult( TDEIO::Job * job ) {
+ KDirSize* kds = static_cast<KDirSize*>(job);
+ m_totalSize += kds->totalSize();
+ m_totalFiles += kds->totalFiles();
+ m_totalSubdirs += kds->totalSubdirs();
+
+ m_size[ m_currentDir ] += kds->totalSize();
+ m_filenum[ m_currentDir ] += kds->totalFiles();
+ m_subdirs[ m_currentDir ] += kds->totalSubdirs();
+ statNextDir();
+}
+
+void VirtualCopyJob::createNextDir() {
+ m_state = ST_CREATING_DIRECTORY;
+
+ if( m_filesToCopy.count() == 0 ) {
+ emitResult();
+ return;
+ }
+
+ TQDictIterator<KURL::List> diter( m_filesToCopy );
+
+ m_currentDir = diter.currentKey();
+ m_current = m_dest;
+ if( m_currentDir != "./" && !m_currentDir.isEmpty() )
+ m_current.addPath( m_currentDir );
+
+ TDEIO::Job *job = TDEIO::stat( m_current );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotStatResult( TDEIO::Job *job ) {
+ KURL url = (static_cast<TDEIO::SimpleJob*>(job) )->url();
+
+ if ( job && job->error() ) {
+ if( job->error() == TDEIO::ERR_DOES_NOT_EXIST && !url.equals( url.upURL(),true ) ) {
+ m_dirStack.push_back( url.fileName() );
+ TDEIO::Job *job = TDEIO::stat( url.upURL() );
+ connect( job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotStatResult( TDEIO::Job* ) ) );
+ return;
+ }
+ job->showErrorDialog( krApp );
+ directoryFinished( m_currentDir );
+ createNextDir();
+ return;
+ }
+
+ if( m_dirStack.count() ) {
+ url.adjustPath( 1 );
+ url.addPath( m_dirStack.last() );
+ m_dirStack.pop_back();
+
+ TDEIO::Job *mkdir_job = TDEIO::mkdir( url );
+ connect( mkdir_job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotMkdirResult( TDEIO::Job* ) ) );
+ }
+ else
+ copyCurrentDir();
+}
+
+void VirtualCopyJob::slotMkdirResult( TDEIO::Job *job ) {
+ KURL url = (static_cast<TDEIO::SimpleJob*>(job) )->url();
+
+ if ( job && job->error() ) {
+ job->showErrorDialog( krApp );
+ directoryFinished( m_currentDir );
+ createNextDir();
+ return;
+ }
+
+ if( m_dirStack.count() ) {
+ url.adjustPath( 1 );
+ url.addPath( m_dirStack.last() );
+ m_dirStack.pop_back();
+
+ TDEIO::Job *mkdir_job = TDEIO::mkdir( url );
+ connect( mkdir_job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotMkdirResult( TDEIO::Job* ) ) );
+ }
+ else
+ copyCurrentDir();
+}
+
+void VirtualCopyJob::copyCurrentDir() {
+ m_state = ST_COPYING;
+
+ TDEIO::CopyJob * copy_job = PreservingCopyJob::createCopyJob( m_pmode, *m_filesToCopy[ m_currentDir ], m_current,
+ m_mode, m_asMethod, false );
+
+ connect( copy_job, TQ_SIGNAL( copying(TDEIO::Job *, const KURL &, const KURL &) ),
+ this, TQ_SLOT( slotCopying(TDEIO::Job *, const KURL &, const KURL &) ) );
+ connect( copy_job, TQ_SIGNAL( moving(TDEIO::Job *, const KURL &, const KURL &) ),
+ this, TQ_SLOT( slotMoving(TDEIO::Job *, const KURL &, const KURL &) ) );
+ connect( copy_job, TQ_SIGNAL( creatingDir(TDEIO::Job *, const KURL &) ),
+ this, TQ_SLOT( slotCreatingDir(TDEIO::Job *, const KURL &) ) );
+ connect( copy_job, TQ_SIGNAL( processedFiles (TDEIO::Job *, unsigned long) ),
+ this, TQ_SLOT( slotProcessedFiles (TDEIO::Job *, unsigned long) ) );
+ connect( copy_job, TQ_SIGNAL( processedDirs (TDEIO::Job *, unsigned long) ),
+ this, TQ_SLOT( slotProcessedDirs (TDEIO::Job *, unsigned long) ) );
+ connect( copy_job, TQ_SIGNAL( processedSize (TDEIO::Job *, TDEIO::filesize_t) ),
+ this, TQ_SLOT( slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t) ) );
+ connect( copy_job, TQ_SIGNAL( result( TDEIO::Job* ) ), this, TQ_SLOT( slotCopyResult( TDEIO::Job* ) ) );
+}
+
+void VirtualCopyJob::slotCopyResult( TDEIO::Job *job ) {
+ if ( job && job->error() ) {
+ job->showErrorDialog( krApp );
+ }
+
+ directoryFinished( m_currentDir );
+ createNextDir();
+}
+
+void VirtualCopyJob::directoryFinished( const TQString &name ) {
+ m_filesToCopy.remove( name );
+
+ m_processedSize += m_size[ name ];
+ m_processedFiles += m_filenum[ name ];
+ m_processedSubdirs += m_subdirs[ name ];
+
+ m_tempSize = m_tempFiles = m_tempSubdirs = 0;
+
+ m_size.remove( name );
+ m_filenum.remove( name );
+ m_subdirs.remove( name );
+}
+
+void VirtualCopyJob::slotCopying(TDEIO::Job *, const KURL &from, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotCopying( this, from, to );
+}
+
+void VirtualCopyJob::slotMoving(TDEIO::Job *, const KURL &from, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotMoving( this, from, to );
+}
+
+void VirtualCopyJob::slotCreatingDir(TDEIO::Job *, const KURL &to) {
+ if( m_showProgressInfo )
+ Observer::self()->slotCreatingDir( this, to );
+}
+
+void VirtualCopyJob::slotProcessedFiles (TDEIO::Job *, unsigned long filenum) {
+ m_tempFiles = filenum;
+}
+
+void VirtualCopyJob::slotProcessedDirs (TDEIO::Job *, unsigned long subdirs) {
+ m_tempSubdirs = subdirs;
+}
+
+void VirtualCopyJob::slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t size) {
+ m_tempSize = size;
+}
+
+#include "virtualcopyjob.moc"
diff --git a/src/app/VFS/virtualcopyjob.h b/src/app/VFS/virtualcopyjob.h
new file mode 100644
index 0000000..c9600ad
--- /dev/null
+++ b/src/app/VFS/virtualcopyjob.h
@@ -0,0 +1,126 @@
+/***************************************************************************
+ virtualcopyjob.h - description
+ -------------------
+ copyright : (C) 2006 + by Csaba Karai
+ e-mail : krusader@users.sourceforge.net
+ web site : http://krusader.sourceforge.net
+ ---------------------------------------------------------------------------
+ Description
+ ***************************************************************************
+
+ A
+
+ db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b.
+ 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D
+ 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY'
+ 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b
+ 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88.
+ YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD
+
+ H e a d e r F i l e
+
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef __VIRTUAL_COPY_JOB_H__
+#define __VIRTUAL_COPY_JOB_H__
+
+#include <tdeio/job.h>
+#include "preservingcopyjob.h"
+#include <tqvaluelist.h>
+#include <tqtimer.h>
+#include <tqdict.h>
+#include <tqmap.h>
+
+class vfs;
+
+typedef enum {
+ ST_STARTING = 0,
+ ST_CALCULATING_TOTAL_SIZE = 1,
+ ST_CREATING_DIRECTORY = 2,
+ ST_COPYING = 3
+} State;
+
+class VirtualCopyJob : public TDEIO::Job
+{
+ TQ_OBJECT
+
+
+public:
+ VirtualCopyJob( const TQStringList *names, vfs * vfs, const KURL& dest, const KURL& baseURL,
+ PreserveMode pmode, TDEIO::CopyJob::CopyMode mode, bool asMethod, bool showProgressInfo );
+
+protected:
+ void statNextDir();
+ void createNextDir();
+ void copyCurrentDir();
+ void directoryFinished( const TQString & );
+
+protected slots:
+ void slotStart();
+ void slotReport();
+
+ void slotKdsResult( TDEIO::Job * );
+ void slotStatResult( TDEIO::Job * );
+ void slotMkdirResult( TDEIO::Job * );
+ void slotCopyResult( TDEIO::Job * );
+
+ void slotCopying(TDEIO::Job *, const KURL &, const KURL &);
+ void slotMoving(TDEIO::Job *, const KURL &, const KURL &);
+ void slotCreatingDir(TDEIO::Job *, const KURL &);
+
+ void slotProcessedFiles (TDEIO::Job *, unsigned long);
+ void slotProcessedDirs (TDEIO::Job *, unsigned long);
+ void slotProcessedSize (TDEIO::Job *, TDEIO::filesize_t);
+
+signals:
+ void totalFiles( TDEIO::Job *job, unsigned long files );
+ void totalDirs( TDEIO::Job *job, unsigned long dirs );
+ void processedFiles( TDEIO::Job *job, unsigned long files );
+ void processedDirs( TDEIO::Job *job, unsigned long dirs );
+
+private:
+ TDEIO::filesize_t m_totalSize;
+ unsigned long m_totalFiles;
+ unsigned long m_totalSubdirs;
+
+ TDEIO::filesize_t m_processedSize;
+ unsigned long m_processedFiles;
+ unsigned long m_processedSubdirs;
+
+ TDEIO::filesize_t m_tempSize;
+ unsigned long m_tempFiles;
+ unsigned long m_tempSubdirs;
+
+ TQValueList<KURL> m_dirsToGetSize;
+
+ TQDict<KURL::List> m_filesToCopy;
+
+ TQMap<TQString,int> m_size;
+ TQMap<TQString,int> m_filenum;
+ TQMap<TQString,int> m_subdirs;
+
+ KURL m_baseURL;
+ KURL m_dest;
+ PreserveMode m_pmode;
+ TDEIO::CopyJob::CopyMode m_mode;
+ bool m_asMethod;
+ bool m_showProgressInfo;
+
+ State m_state;
+
+ TQTimer m_reportTimer;
+
+ KURL m_current;
+ TQString m_currentDir;
+
+ TQStringList m_dirStack;
+};
+
+#endif /* __VIRTUAL_COPY_JOB_H__ */