summaryrefslogtreecommitdiffstats
path: root/krusader/VFS/arc_vfs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'krusader/VFS/arc_vfs.cpp')
-rwxr-xr-xkrusader/VFS/arc_vfs.cpp866
1 files changed, 866 insertions, 0 deletions
diff --git a/krusader/VFS/arc_vfs.cpp b/krusader/VFS/arc_vfs.cpp
new file mode 100755
index 0000000..97e32df
--- /dev/null
+++ b/krusader/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>
+// QT includes
+#include <qregexp.h>
+#include <qdir.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+// KDE includes
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kprocess.h>
+#include <kio/jobclasses.h>
+#include <qprogressdialog.h>
+#include <kglobalsettings.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(QString origin,QString type,QObject* 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;
+ }
+
+ QString password = QString::null;
+ 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 ";
+ QString 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(QRegExp(" "),"\\ ");
+
+ 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(KProcess::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 ? QString(KrServices::fullPathName( "rar" ) + " -r a ") : QString("")) ;
+ 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
+QString arc_vfs::vfs_workingDir(){
+ // get the path inside the archive
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1) != "/") path = "/"+path;
+ QDir().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(KProcess::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(KProcess::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
+ QFile temp(tmpDir+"/tempfilelist");
+ temp.open(IO_ReadOnly);
+ char buf[1000];
+ QString 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 = QString::fromLocal8Bit(buf);
+ if ( line.contains("----------") ) break;
+ parseLine(line.stripWhiteSpace(),&temp);
+
+ }
+ temp.close();
+ QDir().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,KIO::CopyJob::CopyMode mode,QObject* toNotify,QString dir, PreserveMode /*pmode*/ ){
+ if ( addCmd.isEmpty() ) return;
+
+ // get the path inside the archive
+ QString 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= QString(tmpDir+path+dir).find('/',i+1) ){
+ QDir().mkdir(QString(tmpDir+path+dir).left(i));
+ }
+
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+dir);
+
+ KIO::Job* job = new KIO::CopyJob(*fileUrls,dest,mode,false,true);
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)) );
+ if(mode == KIO::CopyJob::Move) // notify the other panel
+ connect(job,SIGNAL(result(KIO::Job*)),toNotify,SLOT(vfs_refresh(KIO::Job*)) );
+}
+
+
+// remove a file from the vfs (physical)
+void arc_vfs::vfs_delFiles(QStringList *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;
+
+ KIO::Job *job = new KIO::CopyJob(*filesUrls,KGlobalSettings::trashPath(),KIO::CopyJob::Move,false,true );
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)));
+ }
+ // else we have to delete the files from both the archive and the temp dir
+ else {
+ // change dir to the temp dir
+ QString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ QStringList files;
+ KIO::filesize_t totalSizeVal = 0;
+ unsigned long totalFilesVal = 0;
+
+ // names -> urls
+ for(QStringList::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,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,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(KProcess::NotifyOnExit,KProcess::AllOutput);
+ proc2.start();
+ while( proc1.isRunning() || proc2.isRunning() ) qApp->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
+QString arc_vfs::vfs_getFile(QString name){
+ // get the current file path
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ QStringList temp(name);
+ vfs_getFiles(&temp);
+
+ return tmpDir+"/"+path+name;
+}
+
+KURL::List* arc_vfs::vfs_getFiles(QStringList* names){
+ KURL url;
+ KURL::List* urls = new KURL::List();
+
+ // get the current file path
+ QString 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
+ QString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+ // names -> urls
+ QStringList files;
+ KIO::filesize_t totalSize = 0;
+ unsigned long totalFiles = 0;
+ for(QStringList::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(QStringList::Iterator file = files.begin(); file != files.end(); ++file ){
+ if ( (*file).right(1)=="/" ){
+ QDir(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,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,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(KProcess::NotifyOnExit,KProcess::AllOutput);
+ while( proc.isRunning() ) qApp->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(QString name){
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ QDir(tmpDir).mkdir(path+name);
+ changed = true; //rescan the archive
+ vfs_refresh(vfs_origin);
+}
+
+// rename file
+void arc_vfs::vfs_rename(QString fileName,QString newName){
+ KURL::List temp;
+ temp.append(vfs_getFile(fileName));
+ QString path = vfs_origin.right((vfs_origin.length()-vfs_origin.findRev('\\'))-1);
+ if(path.left(1)=="/") path.remove(0,1);
+ if(path != "") path = path+"/";
+
+ QDir(tmpDir).mkdir(path);
+ changed = true; //rescan the archive
+
+ KURL dest;
+ dest.setPath(tmpDir+path+"/"+newName);
+
+ KIO::Job* job = new KIO::CopyJob(temp,dest,KIO::CopyJob::Move,false,false);
+ connect(job,SIGNAL(result(KIO::Job*)),this,SLOT(vfs_refresh(KIO::Job*)) );
+}
+
+bool arc_vfs::vfs_refresh(QString 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...
+ QString 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
+QString arc_vfs::nextWord(QString &s,char d) {
+ s=s.stripWhiteSpace();
+ int j=s.find(d,0);
+ QString temp=s.left(j); // find the leftmost word.
+ s.remove(0,j);
+ return temp;
+}
+
+void arc_vfs::getFilesToPack(QStringList* filesToPack,QString 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+"/";
+
+ register DIR* dir = opendir(tmpDir.local8Bit()+"/"+dir_name.local8Bit());
+ if(!dir) return ;
+
+ register struct dirent* dirEnt;
+ QString 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 && QDir(dir_name+name).entryList(QDir::All | QDir::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(QStringList* filesToDelete,QString){
+ // sync the extFiles - and find out which files were deleted
+ QString 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(QString dir_name){
+ register 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+"/";
+
+ register struct dirent* dirEnt;
+ QString 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(){
+ QString save = getcwd(0,0);
+ chdir(tmpDir.local8Bit());
+
+ // delete from the archive files that were unpacked and deleted
+ if( vfs_isWritable() ){
+ QStringList filesToDelete;
+ getFilesToDelete(&filesToDelete);
+ if( !filesToDelete.isEmpty() ){
+ KShellProcess delProc;
+ krApp->startWaiting(i18n("Deleting Files..."),filesToDelete.count()+ignoreLines);
+ connect(&delProc,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,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(KProcess::NotifyOnExit,KProcess::AllOutput);
+ while( delProc.isRunning() ) qApp->processEvents();
+ delProc.clearArguments();
+ delProc << delCmd << "\""+arcFile+"\"";
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+
+ // finaly repack tmpDir
+ if( vfs_isWritable() || vfs_type=="gzip" || vfs_type=="zip2" ){
+ QStringList filesToPack;
+ getFilesToPack(&filesToPack);
+ if( !filesToPack.isEmpty() ){
+ KShellProcess addProc;
+ krApp->startWaiting(i18n("Repacking..."),filesToPack.count()+ignoreLines);
+ connect(&addProc,SIGNAL(receivedStdout(KProcess*,char*,int)),
+ krApp, SLOT(incProgress(KProcess*,char*,int)) );
+
+ if( vfs_type=="gzip" || vfs_type=="zip2" ){
+ addProc << addCmd << *filesToPack.at(0)<< ">" << "\""+arcFile+"\"";
+ addProc.start(KProcess::NotifyOnExit);
+ while( addProc.isRunning() ) qApp->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(KProcess::NotifyOnExit,KProcess::AllOutput);
+ while( addProc.isRunning() ) qApp->processEvents(); // busy wait - need to find something better...
+ addProc.clearArguments();
+ addProc << addCmd << "\""+arcFile+"\"";
+ }
+ }
+ }
+ krApp->stopWait();
+ }
+ }
+ chdir(save.local8Bit());
+}
+
+vfileDict* arc_vfs::findDir(QString 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(QString name){
+for(arc_dir* temp = dirList.first();temp != 0 ; temp = dirList.next()){
+ if(temp->name == name) return temp;
+ }
+ return 0;
+}
+
+QString arc_vfs::changeDir(QString name){
+ if(name.left(2) == "./") {
+ prefix = "./";
+ name.remove(0,2);
+ }
+
+ if(!name.contains('/')){
+ vfs_filesP = findDir("");
+ return name;
+ }
+ // seperate the path from the name
+ QString 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
+ QString Pname = path.mid(path.findRev('/')+1);
+ if(Pname.isEmpty()) return name;
+ QString tempName = arcFile;
+ QFileInfo qfi(tempName.replace(QRegExp("\\"),""));
+ 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(QString name ,KIO::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
+ QString 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);
+
+ QString 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 QString& name, QStringList *urls,KIO::filesize_t *totalSize,unsigned long *totalFiles ){
+ vfile* vf = vfs_search(name);
+ if ( vf == 0 ) return;
+
+ // get the path inside the archive
+ QString 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+"/");
+ QString 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(QString line, QFile* temp){
+ QString name;
+ KIO::filesize_t size = 0;
+ QString perm;
+ QFileInfo qfi(arcFile);
+ time_t mtime = qfi.lastModified().toTime_t();
+ bool link = false;
+ uid_t owner = getuid();
+ gid_t group = getgid();
+ QString 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::mode2QString(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::mode2QString(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);
+ QString 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);
+ QString 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);
+ QString tempName = arcFile;
+ QFileInfo qfi(tempName.replace(QRegExp("\\"),""));
+ 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::mode2QString(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;
+
+
+ QString 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"