summaryrefslogtreecommitdiffstats
path: root/src/app/VFS/arc_vfs.cpp
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2025-08-28 22:44:34 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2025-08-31 23:30:34 +0900
commitf9abd9d505434c9244c03eac708e29a0ca042f6b (patch)
tree30a197ab4c413849188bc131ff859212e636c821 /src/app/VFS/arc_vfs.cpp
parent14d42d284de233f9937becf3fc9ee0dabede3b21 (diff)
downloadkrusader-r14.1.x.tar.gz
krusader-r14.1.x.zip
Restructure source foldersr14.1.x
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it> (cherry picked from commit 086012dcad8a976a0dabbb7cbc20c9cb612cdfa9)
Diffstat (limited to 'src/app/VFS/arc_vfs.cpp')
-rw-r--r--src/app/VFS/arc_vfs.cpp866
1 files changed, 866 insertions, 0 deletions
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"