Logo Search packages:      
Sourcecode: karchiver version File versions  Download package

carchiveoperation.cpp

/***************************************************************************
                          carchiveoperation.cpp  -  description
                             -------------------
    begin                : Tue Nov 15 17:03:53 CET 2005
    copyright            : (C) 2005 by Eric Coquelle
    email                : coquelle@caramail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "carchiveoperation.h"
#include "cchoixfichier.h"
#include "cfileinfo.h"
#include "cfiledialog.h"
#include "caddfiles.h"
#include "cmail.h"
#include "ctar.h"
#include "ctargz.h"
#include "ctarbz2.h"
#include "carj.h"
#include "clha.h"
#include "crar.h"
#include "czip.h"
#include "cgz.h"
#include "cbz2.h"
#include "cgpg.h"
#include "c7z.h"
#include "car.h"
#include "csit.h"
#include "cscript.h"
#include "cutt.h"

#include <kdebug.h>
#include <kmessagebox.h>
#include <kinputdialog.h>
#include <kfileitem.h>
#include <kopenwith.h>
#include <kurl.h>
#include <kio/netaccess.h>


CArchiveOperation::CArchiveOperation(CArchive* archive_obj, QProgressBar* progress_bar, QString temp_dir )
{
  tempdir=temp_dir;
  archiveobj=archive_obj;
  progressbar=progress_bar;
  kindofCompressor=UNKNOWN;
  errormsgnocompressor=i18n("Compressor not available");
}

CArchiveOperation::CArchiveOperation( QObject * parent , const char * name ): QObject(parent, name)
{
}

CArchiveOperation::~CArchiveOperation()
{
}

/**Erases karchiver's temp dir content*/
00067 void CArchiveOperation::eraseTempDir()
{
  KProcess process;
  process.clearArguments();
  process << "rm" << "-fR" <<tempdir;
  process.start(KProcess::Block);

  process.clearArguments();
  process << "mkdir" << tempdir;
  process.start(KProcess::Block);
}

QString CArchiveOperation::getArchiveName()
{
  return newarchivename;
}

/** Check if @param archivename is a valid archive. Returns either an error message,
  * or QString::NULL if everything is OK. Set also kindofCompressor*/
00086 QString CArchiveOperation::checkCanIdentifyArchive(QString& archivename)
{
    CArchiveChoice identifyArchive;
    identifyArchive.setArchiveName(archivename);

    if(identifyArchive.findKindOfCompressor()==UNKNOWN)
    {
        return i18n("Unknown archive type");
    }
    else if(!identifyArchive.isCurrentCompressorAvaible())
    {
        return errormsgnocompressor;
    }
    
    kindofCompressor=identifyArchive.getKindOfCompressor();
    
    return NULL;
}

/** Creates the adequate CArchive-child object */
00106 CArchive* CArchiveOperation::createsArchiveObject(CArchive* objarchive, int archivetype)
{
  switch(archivetype)
  {
    case TAR:
      extension=".tar";
      objarchive=new CTar();
      break;
    case TARGZ:
      extension=".tar.gz";
      objarchive=new CTarGz();
      break;
    case TARBZ2:
      extension=".tar.bz2";
      objarchive=new CTarBz2();
      break;
    case ZIP:
      extension=".zip";
      objarchive=new CZip();
      break;
    case GZIP:
      extension=".gz";
      objarchive=new CGz();
      break;
    case BZIP2:
      extension=".bz2";
      objarchive=new CBz2();
      break;
    case RAR:
      extension=".rar";
      objarchive=new CRar();
      break;
    case LHA:
      extension=".lha";
      objarchive=new CLha();
      break;
    case ARJ:
      extension=".arj";
      objarchive=new CArj();
      break;
    case SEVENZ:
      extension=".7z";
      objarchive=new C7z();
      break;
    case AR:
      extension=".deb";
      objarchive=new CAr();
      break;
    case SIT:
      extension=".sit";
      objarchive=new CSit();
      break;
    case HQX:
      extension=".hqx";
      objarchive=new CHqx();
      break;
    default:
    case UNKNOWN:
      objarchive=NULL;;
      break;
  }

  return objarchive;
}




//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationConversion class
  * convert the current archive in @param newname
  * First check if everything is OK with convertCurrentArchive()
  */
00179 CArchiveOperationConversion::CArchiveOperationConversion(QString temp_dir, CArchive* archive_obj, QProgressBar* progress_bar) : CArchiveOperation( archive_obj, progress_bar, temp_dir)
{
}

CArchiveOperationConversion::~CArchiveOperationConversion()
{
}

/** convert current archive type into another one named @param newname */
00188 void CArchiveOperationConversion::convertCurrentArchive(QString newname)
{
  QString tmp=NULL;
  int size=0;
  QString errormessage;
  QString oldarchivename;
  CCheckFiles checkfile;
  QFileInfo fileinfo(newname);
  QString filename;
  QDateTime date=QDateTime::currentDateTime();
  
  eraseTempDir();
  newarchivename=newname;
  
  if(archiveobj==NULL)
  {
    emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
    return;
  }
  errormessage=checkCanIdentifyArchive(newarchivename);
  if(!errormessage.isNull())
  {
    emit operationEnded(CANNOT_PERFORM_OPERATION, errormessage);
    return;
  }
  
  checkfile.setExtractPath(fileinfo.dirPath(true));
  filename=fileinfo.fileName();
  checkfile.addFile(filename, size, date );
  if(!checkfile.canSafelyExtract())
  {
      checkfile.exec();
      if(checkfile.getFiles().isEmpty())
      {
        emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Cannot write there"));
        return;
      }
  }

  progressbar->reset();
  progressbar->setTotalSteps ( archiveobj->countFiles() );
  connect(archiveobj, SIGNAL(archiveReadEnded()), SLOT(doArchiveConversion()));
  archiveobj->extractArchive(tempdir,EXTRACT_ALL_FILES,tmp);
}

/** Convert an archive to a new one*/
00234 void CArchiveOperationConversion::doArchiveConversion()
{
  QString archivedirectory;
  CFileInfo fileinfo;
  CArchiveChoice archivemanager;
  
  fileinfo.setFile(newarchivename);

  archivedirectory=fileinfo.dirPath(true)+"/";
  
  kdDebug()<<QString("Conversion in dir %1, new type=%2").arg(archivedirectory).arg(archivemanager.getKindOfCompressor())<<endl;
  
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(doArchiveConversion()));
  doArchiveConversion(kindofCompressor, archivedirectory);
}

/** Convert an archive to type, and store it in the directory repconv. If @param  previousarchivename is provided, the new archivename will be reconstructed from it, with the proper extension (@param newarchivetype)*/
00251 void CArchiveOperationConversion::doArchiveConversion(int newarchivetype, const QString & targetdirectory, QString previousarchivename)
{
  QDir directory(tempdir);
  QStringList extractedfileslist;
  QStringList filesofnewarchive;
  //QString extension;
  KProcess process;
  
  extractedfileslist=directory.entryList();
  for (QStringList::Iterator f = extractedfileslist.begin(); f!=extractedfileslist.end(); ++f )
  {
    if( !(*f).startsWith(".") && !(*f).startsWith("..") )
      filesofnewarchive.append(*f);
  }

  if( ((newarchivetype==GZIP)||(newarchivetype==BZIP2)) && filesofnewarchive.count() !=1 )
  {
        emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Gzip and Bzip2 archives can only contain one file!"));
        return;
  }
  
  if( (archiveobj=createsArchiveObject(archiveobj, newarchivetype)) == NULL )
  {
    emit operationEnded( CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor") );
    return;
  }
  /*
  switch(newarchivetype)
  {
    case TAR:
      extension=".tar";
      archiveobj=new CTar();
      break;
    case TARGZ:
      extension=".tar.gz";
      archiveobj=new CTarGz();
      break;
    case TARBZ2:
      extension=".tar.bz2";
      archiveobj=new CTarBz2();
      break;
    case ZIP:
      extension=".zip";
      archiveobj=new CZip();
      break;
    case GZIP:
      extension=".gz";
      archiveobj=new CGz();
      break;
    case BZIP2:
      extension=".bz2";
      archiveobj=new CBz2();
      break;
    case RAR:
      extension=".rar";
      archiveobj=new CRar();
      break;
    case LHA:
      extension=".lha";
      archiveobj=new CLha();
      break;
    case ARJ:
      extension=".arj";
      archiveobj=new CArj();
      break;
    case SEVENZ:
      extension=".7z";
      archiveobj=new C7z();
      break;
    case AR:
      extension=".deb";
      archiveobj=new CAr();
      break;
    case SIT:
      extension=".sit";
      archiveobj=new CSit();
      break;
    case HQX:
      extension=".hqx";
      archiveobj=new CHqx();
      break;
    default:
    case UNKNOWN:
      emit operationEnded( CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor") );
      return;
      break;
  }*/

  if(!previousarchivename.isNull())
  {
    QFileInfo info(previousarchivename);
    newarchivename=targetdirectory+(targetdirectory.endsWith("/")?"":"/")+info.baseName(true);
    if(newarchivename.lower().endsWith("tar"))
      newarchivename=newarchivename.left(newarchivename.length()-4);
    newarchivename=newarchivename+extension;
  }
  kdDebug()<<QString("Analysis of:%1, future type:%2,target dir:%3*").arg(newarchivename).arg(newarchivetype).arg(targetdirectory)<<endl;
  
  connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(conversionDone()));
  archiveobj->createArchive(newarchivename,filesofnewarchive,tempdir);
  
}

void CArchiveOperationConversion::conversionDone()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(conversionDone()));
  emit(operationEnded(CONVERSION_ACHIEVED,i18n("Conversion achieved")));
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationDisplay class
  * displays the content of @param archivename
  * First check if the required compressor is available with canDisplayArchive()
  * Then create a CArchive child and display the archive with displayArchiveContent()
  */
00368 CArchiveOperationDisplay::CArchiveOperationDisplay(QString archivename, bool readwithstream, bool viewbydirs, CArchive* archive_obj, QProgressBar* progress_bar) : CArchiveOperation(archive_obj, progress_bar)
{
  newarchivename=archivename;
  readarchivewithstream=readwithstream;
  viewbydirectories=viewbydirs;
  kindofCompressor=-1;
}

/** Try to identify an archive named newarchivename. Returns a localized error message
  (to be displayed in the statusbar) in case of problem, otherwise returns NULL. Stores the detected
  archive type in kindofCompressor */
00379 QString CArchiveOperationDisplay::canDisplayArchive()
{
  CGPG crypt;
  QString errormessage;

  if(newarchivename.isEmpty())
    return QString("NoArchiveNameProvided");
  
  errormessage=checkCanIdentifyArchive(newarchivename);
  
  if(kindofCompressor==CRYPTED)
  {
    //This is a pgp encrypted archive
    kdDebug() << QString("Will decrypt %1").arg(newarchivename) << endl;
    crypt.setArchiveToProcess( newarchivename );
    crypt.decryptArchive();
    newarchivename=newarchivename.remove(newarchivename.length(),4); //remove .gpg extension
    errormessage=checkCanIdentifyArchive(newarchivename);
  }
  if(!QFileInfo(newarchivename).isReadable())
    errormessage=i18n("Cannot read file");

  if(!errormessage.isEmpty())
    return errormessage;
  
  return NULL;
}

/** Creates the adequate CArchive object, and launches the display process */
00408 void CArchiveOperationDisplay::displayArchiveContent()
{
  if(archiveobj!=NULL)
    delete archiveobj;
  kdDebug()<<QString("CArchiveOperationDisplay::displayArchiveContent of %1  Type=%2").arg(newarchivename).arg(kindofCompressor)<<endl;
  
  /*switch(kindofCompressor)
  {
    case TARGZ:
      archiveobj=new CTarGz();
      break;
    case TARBZ2:
      archiveobj=new CTarBz2();
      break;
    case TAR:
      archiveobj=new CTar();
      break;
    case ZIP:
      archiveobj=new CZip();
      break;
    case ARJ:
      archiveobj=new CArj();
      break;
    case LHA:
      archiveobj=new CLha();
      break;
    case RAR:
      archiveobj=new CRar();
      break;
    case GZIP:
      archiveobj=new CGz();
      break;
    case BZIP2:
      archiveobj=new CBz2();
      break;
    case SEVENZ:
      archiveobj=new C7z();
      break;
    case AR:
      archiveobj=new CAr();
      break;
    default:
    case SIT:
      archiveobj=new CSit();
      break;
    case HQX:
      archiveobj=new CHqx();
      break;
    case UNKNOWN:
      emit operationEnded( CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor") );
      return;
      break;
  }*/
  if( (archiveobj=createsArchiveObject(archiveobj, kindofCompressor)) == NULL )
  {
    emit operationEnded( CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor") );
    return;
  }
  connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotDisplayProcessEnded()));

  archiveobj->setReadArchiveWithStream(readarchivewithstream);
  archiveobj->setArchiveName(newarchivename);
  archiveobj->setDisplayArchiveByDirectories(viewbydirectories);
  archiveobj->displayArchiveContent();
}

00474 void CArchiveOperationDisplay::slotDisplayProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotDisplayProcessEnded()));
  if(!archiveobj->getErrors().isEmpty())
    KMessageBox::informationList(0,i18n("Some errors occurred while opening archive:"),archiveobj->getErrors());
  emit(operationEnded(DISPLAY_ACHIEVED,i18n("Ready")));
}





//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationExtract class
  * extracts the content of current archive
  * using extractCurrentArchive();
  */
00491 CArchiveOperationExtract::CArchiveOperationExtract( CArchive* archive_obj, QProgressBar* progress_bar ) : CArchiveOperation(archive_obj, progress_bar)
{
}

/** Extract current archive. Extract in @param extractpath all or some files depending
  * on @param kindofextraction */
00497 void CArchiveOperationExtract::extractCurrentArchive(int kindofextraction, QString extractpath)
{
    QString tmp=NULL;
    if(archiveobj==NULL)
    {
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
      return;
    }

    connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
    archiveobj->extractArchive(extractpath,kindofextraction,tmp);
}

/** Extract current archive. Promt for Extract dir and other options...*/
00511 void CArchiveOperationExtract::extractCurrentArchive()
{
    QString tmp=NULL;
    if(archiveobj==NULL)
    {
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
      return;
    }

    if(extractdlg.exec())
    {
      int kindofextraction=extractdlg.extractAll();
      archiveobj->setRegExp(QRegExp(extractdlg.getRegExp()));
      connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
      archiveobj->extractArchive(extractdlg.getLastExtractPath(),kindofextraction,tmp);
    }
    else
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("Canceled")));
}

void CArchiveOperationExtract::slotExtractProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
  if(!archiveobj->getErrors().isEmpty())
    KMessageBox::informationList(0,i18n("Some errors occurred while extracting this archive:"),archiveobj->getErrors());
  if(extractdlg.viewExtractedDirectoryInKonqueror())
  {
    KProcess process;

    process.clearArguments();
    process<<"konqueror";
    process<<extractdlg.getLastExtractPath();
    process.start(KProcess::DontCare);
  }
  emit(operationEnded(EXTRACT_ACHIEVED,i18n("Ready")));
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationMail class
  * mail all or anly some files from current archive
  */
00554 CArchiveOperationMail::CArchiveOperationMail( CArchive* archive_obj, QProgressBar* progress_bar, QString tmpdir ) : CArchiveOperationExtract(archive_obj, progress_bar)
{
  tempdir=tmpdir;
}

/** Mail some or all files from current archive. Promt which operation to perform in a dialog...*/
00560 void CArchiveOperationMail::mailCurrentArchive()
{
    Mail_dialog mail;
    int mailoperation;
    filestomail.clear();

    if(archiveobj==NULL)
    {
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
      return;
    }

    if(mail.exec())
    {
      mailoperation=mail.getKindofFilesToMail();
      connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
      
      if(mailoperation==Mail_dialog::MAIL_CURRENT_ARCHIVE)
      {
        //Mail current archive
        filestomail.append(archiveobj->getArchiveName());
        tempdir="";
        slotExtractProcessEnded();
      }
      else if(mailoperation==Mail_dialog::MAIL_SELECTED_FILES)
      {
        extractCurrentArchive( EXTRACT_SELECTED_FILES, tempdir);
        filestomail=archiveobj->getAllFiles(true);
      }
      else if(mailoperation==Mail_dialog::MAIL_ALL_FILES)
      {
        extractCurrentArchive( EXTRACT_ALL_FILES, tempdir);
        filestomail=archiveobj->getAllFiles();
      }
      else
      {
        emit(operationEnded(CANNOT_PERFORM_OPERATION, "Invalid operation"));
        return;
      }
    }
    else
    {
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("Canceled") ));
      return;
    }
}

void CArchiveOperationMail::slotExtractProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));

    adress = KInputDialog::getText( i18n("Karchiver - Mail archive"),  i18n("Enter the email address of the recipient"), "someone@example.com" );
    
    CProcessus proc;  
    proc.clearArguments();
    proc << "kmail";
    
    for(QStringList::Iterator it=filestomail.begin(); it!=filestomail.end(); ++it)
      proc  << "--attach" << KURL::encode_string(tempdir + *it);
    
    proc << adress;
    proc.start(KProcess::DontCare);
  
  if(!archiveobj->getErrors().isEmpty())
    KMessageBox::informationList(0,i18n("Some errors occurred while extracting this archive:"),archiveobj->getErrors());
  
  emit(operationEnded(EXTRACT_ACHIEVED,i18n("Ready")));
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationView class
  * displays the selected file(s) with the adequate software
  */
00635 CArchiveOperationViewFiles::CArchiveOperationViewFiles( CArchive* archive_obj, QProgressBar* progress_bar, QString temp_dir ): CArchiveOperation(archive_obj, progress_bar)
{
  tempdir=temp_dir;
  connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesExtracted()));
}

/** display the file designed by the listentry @param currentItem using its associated program */
00642 void CArchiveOperationViewFiles::displayFile(QListViewItem* currentItem)
{
  QString fullinternalfilename;
    
  if(archiveobj==NULL)
  {
    disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesExtracted()));
    emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
    return;
  }
  if(currentItem==0)
  {
    disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesExtracted()));
    emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First select a file")));
    return;
  }
  eraseTempDir();
  
  fullinternalfilename=currentItem->text(6);//the directory
  if(fullinternalfilename.startsWith("/"))
    fullinternalfilename=fullinternalfilename.remove(0,1);
  fullinternalfilename+=currentItem->text(0);//dir+itemname
kdDebug()<<QString("Prepare viewing of %1 in %2").arg(fullinternalfilename).arg(tempdir)<<endl;
  archiveobj->extractArchive(tempdir, EXTRACTONE_AND_BLOCK,fullinternalfilename);
}

/** display the selected files using their associated program */
00669 void CArchiveOperationViewFiles::displaySelectedFiles()
{
  QString str=NULL;
  
  if(archiveobj==NULL)
  {
    disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesExtracted()));
    emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
    return;
  }
  eraseTempDir();
  
  archiveobj->extractArchive(tempdir, EXTRACT_SELECTED_FILES,str);
}

void CArchiveOperationViewFiles::slotFilesExtracted()
{
  QStringList listoffilestoview;
  KFileOpenWithHandler* owh;
  QDir d(tempdir);
  listoffilestoview=getAllFiles(d);
  kdDebug()<<QString("Will view %1 files in %2").arg(listoffilestoview.count()).arg(tempdir)<<endl;
  for ( QStringList::Iterator it = listoffilestoview.begin(); it != listoffilestoview.end(); ++it )
  {
    kdDebug()<<QString("Viewing of %1").arg(*it)<<endl;
    KFileItem fi(0,0,KURL(*it));
    if(fi.isFile())
    {
      owh=new KFileOpenWithHandler();
      fi.run();
    }
  }
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesExtracted()));
  emit(operationEnded(VIEW_FILES_ACHIEVED, i18n("Ready")));
}

/** Get recursively all files contained in the directory @param d */
00706 QStringList CArchiveOperationViewFiles::getAllFiles(QDir d)
{
  QStringList listoffilestoview;
  QStringList filesandsubdirs;
  QString basedir=d.path()+"/";
  filesandsubdirs=d.entryList(QDir::Dirs);
  
  for ( QStringList::Iterator it = filesandsubdirs.begin(); it != filesandsubdirs.end(); ++it ) {
    kdDebug()<<QString("Looking in %1").arg(basedir + *it)<<endl;
    if((*it!=".")&&(*it!=".."))
      listoffilestoview+=getAllFiles(QDir(basedir + *it));
  }
  filesandsubdirs=d.entryList(QDir::Files);
  for ( QStringList::Iterator it = filesandsubdirs.begin(); it != filesandsubdirs.end(); ++it ) {
    kdDebug()<<QString("Appending %1").arg(basedir + *it)<<endl;
      listoffilestoview.append(basedir + *it);
  }
  return listoffilestoview;
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationExtractMultiFiles class
  * extract a list of archives
  */
00732 CArchiveOperationExtractMultiFiles::CArchiveOperationExtractMultiFiles( CArchive* archive_obj, QProgressBar* progress_bar  ) : CArchiveOperationExtract(archive_obj, progress_bar)
{
  displayobj=NULL;
}

/** Extract the archives @param archives to the directory @param extractdir.
      If @param promptdir is true, ignore pervious parameter and show the extract dialog,
        to let the user choosing the right extract dir
        If @param promptdir == false && if @param  chooseExtractDirFromArchive == true && the
        archive's files are not contained in a top subdir, create this topsubdir when extracting
        to avoid many files spreading everywhere... */
00743 void CArchiveOperationExtractMultiFiles::extractMultiFiles( QStringList archives, bool promptdir, QCString extractdir, bool chooseExtractDirFromArchive ){
   
  KURL url;
  QFileInfo fileinfo;
  
  for ( QStringList::Iterator it=archives.begin(); it!=archives.end(); ++it)
   {
     url=KURL(*it);
     fileinfo.setFile(url.directory(false, false)+url.fileName());
     if( fileinfo.exists() && fileinfo.isReadable() )
      archivesqueue.append(fileinfo.absFilePath());
     else
      kdDebug()<<QString("CArchiveOperationExtractMultiFiles::extractMultiFiles : Cannot read %1").arg(fileinfo.absFilePath())<<endl;
   }
   m_promptdir=promptdir;
   m_extractdir=extractdir;
   m_chooseExtractDirFromArchive=chooseExtractDirFromArchive;
   
   extractMultiFiles();
}

void CArchiveOperationExtractMultiFiles::extractMultiFiles()
{
  newarchivename= *archivesqueue.begin();
  archivesqueue.remove(*archivesqueue.begin());
  kdDebug()<<QString("CArchiveOperationExtractMultiFiles::extractMultiFiles - Processing %1").arg(newarchivename)<<endl;
  if(displayobj!=NULL)
    delete displayobj;
  
  displayobj=new CArchiveOperationDisplay( newarchivename, false, true, archiveobj,  progressbar);
  connect(displayobj, SIGNAL(operationEnded(int, QString)), this, SLOT(slotArchiveDisplayed(int, QString)));
  QString pb=displayobj->canDisplayArchive();
  if(pb==NULL)
    displayobj->displayArchiveContent();
  else
  {
    kdDebug()<<QString("extractMultiFiles: pb in display=%1").arg(pb)<<endl;
    slotArchiveExtracted();
    return;
  }
}

/**The archive is displayed (usefull to perform CArchive::checkFiles(). Check is everything 
   * is OK, and extract the archive. @param value = display erros/success message*/
00787 void CArchiveOperationExtractMultiFiles::slotArchiveDisplayed(int value, QString)
{
  QString tmp=NULL;
  KArchive *archive=NULL;
  QString extractdir=m_extractdir;
  
  if(value==CANNOT_PERFORM_OPERATION)
  {
    slotArchiveExtracted();//skip to the next file to extract
    return;
  }
  archiveobj=displayobj->getArchiveObject();
  const int kindofCompressor=displayobj->getKindofCompressor();
  connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotArchiveExtracted()));
  
  delete displayobj;
  displayobj=NULL;
  
  if(m_promptdir)
  {
    if(extractdlg.exec())
      archiveobj->extractArchive(extractdlg.getLastExtractPath(),extractdlg.extractAll(),tmp);
    else
    {
      slotArchiveExtracted();
      disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotArchiveExtracted()));
      return;
    }
  }
  else
  {
    if(m_chooseExtractDirFromArchive)
    {
      //Special feature: if the / of the archives doesn't contain a top-dir but many files,
      //let's create a top-directory
      if((kindofCompressor==TAR)||(kindofCompressor==TARGZ)||(kindofCompressor==TARBZ2))
        archive=new KTar(newarchivename);
      else if(kindofCompressor==ZIP)
        archive=new KZip(newarchivename);
  
      if(extractdir.isEmpty())
      {
         QFileInfo f(newarchivename);
         extractdir=f.dirPath();
      }
      if((archive!=NULL)&&(archive->open(IO_ReadOnly)))
      {
        CFileInfo fileInfo(newarchivename);
        QString archive_base_name=fileInfo.baseName();
        QDir dir(extractdir);
        const KArchiveDirectory*  archive_tar_dir=archive->directory();
        const QStringList  archive_tar_entries=archive_tar_dir->entries();
        if(archive_tar_entries.count()>1)
        {
          dir.mkdir(archive_base_name);
          extractdir+="/"+archive_base_name+"/";
        }
      }
    }
    archiveobj->extractArchive(extractdir,EXTRACT_ALL_FILES,tmp);
  }
}

void CArchiveOperationExtractMultiFiles::slotArchiveExtracted()
{
  kdDebug()<<QString("CArchiveOperationExtractMultiFiles::slotArchiveExtracted Remaining %1 files").arg(archivesqueue.count())<<endl;
  if(archivesqueue.count()==0)
    emit(operationEnded(MULTI_EXTRACTION_ACHIEVED, i18n("Done")));
  else
  {
    CArchive::list->clear();
    extractMultiFiles();
  }
}




//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationSfx class
  * extracts the content of current archive to @param temp_dir + "Data/"
  * and create the sfx module using makeSfxArchive();
  */
00870 CArchiveOperationSfx::CArchiveOperationSfx(CArchive* archive_obj, QProgressBar* progress_bar, QString temp_dir ) : CArchiveOperation( archive_obj, progress_bar, temp_dir)
{
  tempdirsfx=tempdir+"Data/";
}

/** Creates an sfx archive */
00876 void CArchiveOperationSfx::makeSfxArchive(QString namesfxarchive=QString::null, int type=UNIVERSAL_SFX)
{
  if( archiveobj== NULL )
  {
    emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Please first open an archive"));
    return;
  }
  
  newarchivename=namesfxarchive;
  sfxtype=type;
  
  extractAllFiles();
}

/** Extract current archive in tempdirsfx */
00891 void CArchiveOperationSfx::extractAllFiles()
{
  QString tmp=NULL;
  //We will extract the archive to a temp folder, so let's clean it
  eraseTempDir();

  progressbar->reset();
  progressbar->setTotalSteps ( archiveobj->countFiles() );
  
  connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
  archiveobj->extractArchive(tempdirsfx,0,tmp);
}

00904 void CArchiveOperationSfx::slotExtractProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));

   switch(sfxtype)
   {
      case SEVENZ_SFX:
         make7zSfx();
         break;
      default:
      case UNIVERSAL_SFX:
         makeUniversalSfx();
         break;
   }
}

/** Create an Universal Sfx archive from the files extracted in tempdirsfx */
00921 void CArchiveOperationSfx::makeUniversalSfx()
{
  archiveobj->getAllFiles();
  QString baserep;
  QString file;
  CFileInfo fileinfo;
  QString sfxmodulepath;
  QStringList filestoadd;
  QStringList fileswithpathtoadd;
  
  if(newarchivename.isEmpty())
    newarchivename=KFileDialog::getSaveFileName(QDir::homeDirPath(), QString::null, 0L, i18n("Please give a name to your SelfExtracting archive"));
  
  sfxmodulepath=KGlobal::dirs()->findResource("data", "karchiver/KArchiverSfxModule.jar");
  
  if(newarchivename.isEmpty()||sfxmodulepath.isNull())
  {
    emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Sfx module not found"));
    return;
  }

  KProcess proc;
  newarchivename+=".jar";
  proc << "cp" << "--force" << sfxmodulepath << newarchivename;
  proc.start(KProcess::Block);
  
  //Add extracted files to karchiver's Sfx java module
  filestoadd=archiveobj->getAllFiles();
  for (QStringList::Iterator fp = filestoadd.begin(); fp!=filestoadd.end(); ++fp )
  {
    file=*fp;
    if(file.startsWith("/"))
      file=file.remove(0,1);
    fileswithpathtoadd.append("Data/"+file);
  }

  sfx_archiveobj=new CZip();
  connect(sfx_archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
  sfx_archiveobj->setArchiveName(newarchivename);
  sfx_archiveobj->addFilesToArchive( fileswithpathtoadd, false, ADD_AND_REPLACE_FILES, tempdir);
}

void CArchiveOperationSfx::slotFilesAdded()
{
  disconnect(sfx_archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
  emit operationEnded(SFX_ARCHIVE_CREATED, i18n("Your Sfx archive")+"\n"+sfx_archiveobj->getArchiveName()+"\n"+i18n("is ready"));
  delete sfx_archiveobj;
}

/** Create the 7z Sfx archive from the files extracted in tempdirsfx */
00971 void CArchiveOperationSfx::make7zSfx()
{
  archiveobj->getAllFiles();
  QString baserep;
  QString file;
  CFileInfo fileinfo;
  QString sfxmodulepath;
  QStringList filestoadd;
  QStringList fileswithpathtoadd;
  
  if(newarchivename.isEmpty())
    newarchivename=KFileDialog::getSaveFileName(QDir::homeDirPath(), QString::null, 0L, i18n("Please give a name to your SelfExtracting archive"));
  
  sfxmodulepath=KGlobal::dirs()->findResource("data", "karchiver/SevenzSfxModule.sfx");
  
  if(newarchivename.isEmpty()||sfxmodulepath.isNull())
  {
    emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Sfx module not found"));
    return;
  }

  exearchivename=newarchivename+".exe";
  newarchivename=tempdir+QFileInfo(newarchivename).baseName()+".7z";
  
  //Creates a .7z archive and then append it to the sfx module
  filestoadd=archiveobj->getAllFiles();
  for (QStringList::Iterator fp = filestoadd.begin(); fp!=filestoadd.end(); ++fp )
  {
    file=*fp;
    if(file.startsWith("/"))
      file=file.remove(0,1);
    fileswithpathtoadd.append(file);
  }

  sfx_archiveobj=new C7z();
  connect(sfx_archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slot7zSfxReady()));
  sfx_archiveobj->setArchiveName(newarchivename);
  sfx_archiveobj->addFilesToArchive( fileswithpathtoadd, false, ADD_AND_REPLACE_FILES, tempdirsfx);
}

void CArchiveOperationSfx::slot7zSfxReady()
{
  disconnect(sfx_archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slot7zSfxReady()));
  
  KProcess proc;
  QString sfxmodulepath=KGlobal::dirs()->findResource("data", "karchiver/SevenzSfxModule.sfx");
  
  proc << "cp" << "--force" << sfxmodulepath << exearchivename;
  proc.start(KProcess::Block);
  
  cat();
  
  proc.clearArguments();
  proc << "rm" << "-f" << newarchivename;
  proc.start(KProcess::Block);
  
  emit operationEnded(SFX_ARCHIVE_CREATED, i18n("Your Sfx archive")+"\n"+exearchivename+"\n"+i18n("is ready"));
  delete sfx_archiveobj;
}

/** Catenates an archive to its sfx module */
01032 void CArchiveOperationSfx::cat()
{
  int j;
  
  QFile filesfx(exearchivename);
  filesfx.open(IO_WriteOnly | IO_Append);
  
  QFile filearchive(newarchivename);
  filearchive.open(IO_ReadOnly);

  const int size=filearchive.size();
  const int sizebuffer=100000;
  char  data[sizebuffer];
  const int fullsizeblock = size / sizebuffer;
  const int partialblock = size % sizebuffer;

  for (j = 1; j <= fullsizeblock; j++)
  {
    filearchive.readBlock(data, sizebuffer);
    filesfx.writeBlock(data, sizebuffer);
  }
  filearchive.readBlock(data, partialblock);
  filesfx.writeBlock(data, partialblock);
  
  filearchive.close();
  filesfx.close();
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationTest class
  * extracts the content of current archive to @param temp_dir
  * and look for any errors using testArchive();
  */
01067 CArchiveOperationTest::CArchiveOperationTest( CArchive* archive_obj, QProgressBar* progress_bar, QString temp_dir ) : CArchiveOperationSfx(archive_obj, progress_bar, temp_dir)
{
  tempdirsfx=tempdir;
}

void CArchiveOperationTest::testArchive()
{
  extractAllFiles();//just extract to the temp dir...
}

01077 void CArchiveOperationTest::slotExtractProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
  connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotIntegrityProcessEnded()));
  archiveobj->testCurrentArchiveIntegrity();
}

void CArchiveOperationTest::slotIntegrityProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotIntegrityProcessEnded()));
  if(!archiveobj->getErrors().isEmpty())
  {
    if( KMessageBox::questionYesNoList(0,i18n("Some errors occurred while testing this archive. Would you like to repair this archive ?"),archiveobj->getErrors()) == KMessageBox::Yes )
    {
      if(archiveobj->canRepairArchive())
      {
        connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(archiveRepaired()));
        archiveobj->repairCurrentArchive();
      }
      else
      {
        KMessageBox::error(0, i18n("This compressor cannot repair damaged archives"), i18n("Not possible"));
        emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("This compressor cannot repair damaged archives"));
      }
    }
    else
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("Some errors occurred while extracting this archive:")));
  }
  else
  {
    KMessageBox::information(0, i18n("None errors found in this archive"), i18n("Everything is OK."));
    emit(operationEnded(TEST_ACHIEVED, i18n("Ready")));
  }
}

void CArchiveOperationTest::archiveRepaired()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(archiveRepaired()));
  
  KMessageBox::informationList(0, i18n("<qt>The archive <i>%1</i> has been repaired.<br>During the reparation, the following errors occured:</qt>").arg(archiveobj->getRepairedArchiveName()), archiveobj->getErrors(), i18n("Repair of archives"));
  
  emit operationEnded(TEST_ACHIEVED, i18n("Archive repaired"));
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationScanForVirus class
 * extracts the content of current archive to @param temp_dir
 * and launches KlamAV using scanArchive();
 */
01128 CArchiveOperationScanForVirus::CArchiveOperationScanForVirus( CArchive* archive_obj, QProgressBar* progress_bar, QString temp_dir ) : CArchiveOperationSfx(archive_obj, progress_bar, temp_dir)
{
  tempdirsfx=tempdir;
  scanprogramm="klamav";
  scanprogrammargument="--scanthis";
  connect(&processav, SIGNAL(processExited(KProcess*)),this,SLOT(slotScanProcessEnded(KProcess*)));
}

void CArchiveOperationScanForVirus::scanArchive()
{
  if(KStandardDirs::findExe(scanprogramm)==NULL)
    emit(operationEnded(SCAN_ACHIEVED, i18n("Cannot find the anti-virus scanner: ")+scanprogramm));
  else
    extractAllFiles();//just extract to the temp dir...
}

01144 void CArchiveOperationScanForVirus::slotExtractProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
  
  processav.clearArguments();
  processav << scanprogramm << scanprogrammargument << tempdirsfx;
  processav.start(KProcess::NotifyOnExit);
}

void CArchiveOperationScanForVirus::slotScanProcessEnded(KProcess*)
{
  kdDebug()<<QString("Finished")<<endl;
  QString str=i18n("Finished. Please look at the output of %1 for the results of the scan").arg(scanprogramm);
  kdDebug()<<QString("Sending message %1").arg(str)<<endl;
  emit(operationEnded(SCAN_ACHIEVED, str));
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationWizard class
 * extracts the content of current archive to @param temp_dir
 * and launches KArchiver's wizards;
 */
01168 CArchiveOperationWizard::CArchiveOperationWizard( CArchive* archive_obj, QProgressBar* progress_bar, QString temp_dir ) : CArchiveOperationSfx(archive_obj, progress_bar, temp_dir)
{
  tempdirsfx=tempdir;
}

void CArchiveOperationWizard::launchWizard(QListViewItem* current)
{
  currentItem=current;
  extractAllFiles();//just extract to the temp dir...
}

01179 QString CArchiveOperationWizard::getCommonDirectory(QDir d)
{
  QString commondirectory;
  QStringList filesandsubdirs;
  QString basedir=d.path()+"/";
  
  filesandsubdirs=d.entryList(QDir::Files);
  if(filesandsubdirs.count()!=0)
    return d.absPath();
    
  
  filesandsubdirs=d.entryList(QDir::Dirs);
  if(filesandsubdirs.count()!=3) ///A directory + . + ..
    return d.absPath();
  for ( QStringList::Iterator it = filesandsubdirs.begin(); it != filesandsubdirs.end(); ++it ) {
    kdDebug()<<QString("Looking in %1").arg(basedir + *it)<<endl;
    if((*it!=".")&&(*it!=".."))
      commondirectory=getCommonDirectory(QDir(basedir + *it));
  }
  return commondirectory;
}

01201 void CArchiveOperationWizard::slotExtractProcessEnded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotExtractProcessEnded()));
  
   progressbar->reset();

   QString namefichselect;
   QString basedir;
   QString repbasetmp;
   int typescript;

  QString str;
  QString fullinternalfilename;
  QString patchname;
  QString patchpath;
  CScript objetscript;
  
  patchpath=currentItem->text(6);//the directory
  if(patchpath.startsWith("/"))
    patchpath=patchpath.remove(0,1);
  fullinternalfilename+=currentItem->text(0);//dir+itemname
  patchname=currentItem->text(0);
  
   basedir=getCommonDirectory(QDir(tempdir));
   kdDebug()<<QString("Common directory=%1").arg(basedir)<<endl;


   ///Launches the Wizard dialog
   typescript=objetscript.startWizard(patchname,basedir,archiveobj->getArchiveName());
   kdDebug()<<QString("EndingWizard: typescript= %1").arg(typescript)<<endl;
   
   ///Process user choice
   if(typescript==CScript::WIZ_CONVERSION)
   {
         //User has chosen to convert the archive
         archiveoperation=new CArchiveOperationConversion(tempdir, archiveobj, progressbar);
         connect(archiveoperation, SIGNAL(operationEnded(int, QString)), this, SLOT(slotMessageArchiveOperation(int , QString )));
         archiveoperation->doArchiveConversion(objetscript.getTypeConversion(),objetscript.getDirectoryConversion(), archiveobj->getArchiveName());
   }
   else if(typescript==CScript::WIZ_UNCUTT)
   {
      //User has chosen to split/unsplit archive
      if(objetscript.getDirectoryCutt()!=NULL)
      {
        archiveoperation = new CArchiveOperationSplit( archiveobj,  progressbar );
        connect(archiveoperation, SIGNAL(operationEnded(int, QString)), this, SLOT(slotMessageArchiveOperation(int , QString )));
        archiveoperation->doCuttUnCutt(objetscript.getDirectoryCutt());
      }
   }
   else if(typescript==CScript::WIZ_SFX)
   {
      //User has chosen to create a Sfx archive
      //slotStatusMsg(i18n("Make a Self-extract archive..."));
   
      archiveoperation=new CArchiveOperationSfx(archiveobj, progressbar, tempdir);
      connect(archiveoperation, SIGNAL(operationEnded(int, QString)), this, SLOT(slotMessageArchiveOperation(int , QString )));
      archiveoperation->makeSfxArchive(objetscript.getSfxArchiveName(), objetscript.getSfxArchiveType());
   }
   else
    emit(operationEnded(WIZARD_ACHIEVED, str));

}

void CArchiveOperationWizard::slotMessageArchiveOperation(int type, QString message)
{
  emit(operationEnded(type, message));
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationSplit class
  * Split current archive in a series of files whose maximum size is blocksize
  * Also performs the opposite oeration to reconstruct the archive
  */
01276 CArchiveOperationSplit::CArchiveOperationSplit( CArchive* archive_obj, QProgressBar* progress_bar ) : CArchiveOperation(archive_obj, progress_bar)
{
}

/** unsplit the archive @param name
  * or split current archive into the directory @param name in block of size @param blocksize*/
01282 void CArchiveOperationSplit::doCuttUnCutt(QString name, int blocksize)
{
  kdDebug()<<QString("Splitting %1, blocksize=%2").arg(name).arg(blocksize)<<endl;

  cuttFichier objCutt;
  QString str;
  QFileInfo cutt(name);

  if(cutt.extension(false)=="01")
  {
    objCutt.Begin(name,cuttFichier::UNSPLIT, cutt.dirPath(true));
    emit operationEnded(UNSPLIT_ACHIEVED, cutt.dirPath(true)+"/"+cutt.baseName(true));
  }
  else
  {
    if(!name.endsWith("/"))
            name+="/";
    objCutt.Begin(archiveobj->getArchiveName(),cuttFichier::SPLIT, name, blocksize);
  
    emit operationEnded(SPLIT_ACHIEVED, i18n("Archive split in %1.01...").arg(archiveobj->getArchiveName()));
  }
}



//////////////////////////////////////////////////////////////////////////////////////
/**The CArchiveOperationAdd class
  * add some files to an existing archive
  */
01311 CArchiveOperationAdd::CArchiveOperationAdd( CArchive* archive_obj, QProgressBar* progress_bar ) : CArchiveOperation(archive_obj, progress_bar)
{
}

/** Add files @param files to the archive @param archivename.*/
01316 void CArchiveOperationAdd::addFilesToThisArchive(QString& archivename, QStringList files, bool removefiles, int actionfiles, QString relativepath)
{
   QString m_relpath=relativepath;
    kdDebug()<<QString("Target archive: %1, added files in %2").arg(archivename).arg(m_relpath)<<endl;
    if(archiveobj!=NULL)
      delete archiveobj;
    kdDebug()<<QString("Target archive: %1, added files in %2").arg(archivename).arg(m_relpath)<<endl;
    
    /*switch(kindofCompressor)
    {
      case TAR:
        archiveobj=new CTar();
        break;
      case TARGZ:
        archiveobj=new CTarGz();
        break;
      case TARBZ2:
        archiveobj=new CTarBz2();
        break;
      case ZIP:
        archiveobj=new CZip();
        break;
      case GZIP:
        archiveobj=new CGz();
        break;
      case BZIP2:
        archiveobj=new CBz2();
        break;
      case RAR:
        archiveobj=new CRar();
        break;
      case LHA:
        archiveobj=new CLha();
        break;
      case ARJ:
        archiveobj=new CArj();
        break;
      case SEVENZ:
        archiveobj=new C7z();
        break;
      case AR:
        archiveobj=new CAr();
        break;
      case SIT:
        archiveobj=new CSit();
        break;
      case HQX:
        archiveobj=new CHqx();
        break;
      default:
      case UNKNOWN:
        archiveobj=NULL;
        emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor"));
        return;
        break;
    }*/
    if( (archiveobj=createsArchiveObject(archiveobj, kindofCompressor)) == NULL )
    {
      emit operationEnded( CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor") );
      return;
    }

    kdDebug()<<QString("Target archive: %1, added files in %2").arg(archivename).arg(m_relpath)<<endl;
    archiveobj->setArchiveName(archivename);
    kdDebug()<<QString("Target archive: %1, added files in %2").arg(archivename).arg(m_relpath)<<endl;
    connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAddedToAnotherArchive()));
    archiveobj->addFilesToArchive(files,removefiles,actionfiles, m_relpath);
}

/** Add files @param files to the current archive */
01386 void CArchiveOperationAdd::addFilesToCurrentArchive(QStringList files, bool removefiles, int actionfiles, QString relativepath)
{
    if(archiveobj==NULL)
    {
      emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!"));
      return;
    }
    
    connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
    archiveobj->addFilesToArchive(files,removefiles,actionfiles, relativepath);
}

/**Add files to current archives. Launches a dialog box to get the files to add*/
01399 void CArchiveOperationAdd::addFilesToCurrentArchive()
{
    int actionfiles;
    bool removefiles;
    QStringList filestoadd;

    if(archiveobj==NULL)
    {
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("First open an archive!")));
      return;
    }
    else if(!QFileInfo(archiveobj->getArchiveName()).isWritable())
    {
      emit(operationEnded(CANNOT_PERFORM_OPERATION, i18n("This is a read-only archive!")));
      return;
    }
    else if(addfilestoarchive.exec()!=0)
    {
        emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("No file to be added"));
        return;
    }
    
    filestoadd=addfilestoarchive.getFiles();
    actionfiles=addfilestoarchive.getAction();
    removefiles=addfilestoarchive.hasToRemoveFiles();

    progressbar->reset();
    progressbar->setTotalSteps ( addfilestoarchive.getFiles().count() );    
    
    connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
    archiveobj->addFilesToArchive(filestoadd,removefiles,actionfiles, NULL);
}

void CArchiveOperationAdd::slotFilesAdded()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
  emit operationEnded(ADD_FILES_ACHIEVED, i18n("Ready"));
}

void CArchiveOperationAdd::slotFilesAddedToAnotherArchive()
{
  kdDebug()<<QString("CArchiveOperationAdd::slotFilesAddedToAnotherArchive")<<endl;
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
  emit operationEnded(ADD_FILES_ANOTHER_ARCHIVE_ACHIEVED, i18n("Ready")); //We need to update KArchiverApp::archiveobj as a new one has been created, and reopen the file
}



//////////////////////////////////////////////////////////////////////////////////////
/** The CArchiveOperationCreate class
  * creates a new archive and add some files to it
  */
01451 CArchiveOperationCreate::CArchiveOperationCreate( CArchive* archive_obj, QProgressBar* progress_bar ) : CArchiveOperationAdd(archive_obj, progress_bar)
{
}

void CArchiveOperationCreate::createNewArchive()
{
    QString archivename;
    QString errormessage;
     
    CFileDialog newarchive(i18n("Create archive"),"*",0,"dlg_create_archive",false);
    archivename=newarchive.getSaveFileName();
    
    errormessage  = checkCanCreateNewArchive(archivename);
    errormessage += checkCanIdentifyArchive(archivename);
    
    if( errormessage.isNull() )
    {
      addfilestoarchive.setUpdateAvailable(false);
      if(addfilestoarchive.exec()!=0)
      {
          emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("None files selected!"));
          return;
      }
      
      progressbar->reset();
      progressbar->setTotalSteps ( addfilestoarchive.getFiles().count() );    
  
      addFilesToNewArchive( archivename, addfilestoarchive.getFiles());
    }
    else
      emit operationEnded(CANNOT_PERFORM_OPERATION, errormessage);
}

QString CArchiveOperationCreate::checkCanCreateNewArchive(QString& archivename)
{
    QFileInfo fileinfo;
    QDir dir;

    if(archivename.isEmpty())
    {
      return i18n("Please enter a valid archive name");
    }
    //various checkings
    fileinfo.setFile(archivename);
    if(fileinfo.exists())
    {
      return i18n("This file already exists");
    }
    dir=fileinfo.dir(true);
    if(!dir.exists())
      dir.mkdir(dir.absPath());
      
    return NULL;
}
    
void CArchiveOperationCreate::addFilesToNewArchive(QString& archivename, QStringList files, QString relativepath)
{
    if(archiveobj!=NULL)
      delete archiveobj;
    
    /*switch(kindofCompressor)
    {
      case TAR:
        archiveobj=new CTar();
        break;
      case TARGZ:
        archiveobj=new CTarGz();
        break;
      case TARBZ2:
        archiveobj=new CTarBz2();
        break;
      case ZIP:
        archiveobj=new CZip();
        break;
      case GZIP:
        archiveobj=new CGz();
        break;
      case BZIP2:
        archiveobj=new CBz2();
        break;
      case RAR:
        archiveobj=new CRar();
        break;
      case LHA:
        archiveobj=new CLha();
        break;
      case ARJ:
        archiveobj=new CArj();
        break;
      case SEVENZ:
        archiveobj=new C7z();
        break;
      case AR:
        archiveobj=new CAr();
        break;
      case SIT:
        archiveobj=new CSit();
        break;
      case HQX:
        archiveobj=new CHqx();
        break;
      default:
      case UNKNOWN:
        archiveobj=NULL;
        emit operationEnded(CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor"));
        return;
        break;
    }*/
    if( (archiveobj=createsArchiveObject(archiveobj, kindofCompressor)) == NULL )
    {
      emit operationEnded( CANNOT_PERFORM_OPERATION, i18n("Unsupported compressor") );
      return;
    }


    connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotArchiveCreated()));
    archiveobj->createArchive(archivename, files, relativepath);
}

void CArchiveOperationCreate::slotArchiveCreated()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotArchiveCreated()));
  emit operationEnded(ARCHIVE_CREATION_ACHIEVED, i18n("Ready"));
}



CArchiveOperationProcessInputFiles::CArchiveOperationProcessInputFiles( CArchive* archive_obj, QProgressBar* progress_bar, QString perferedarchiveextension, bool hastoincludewholepath, int action_addfiles) : CArchiveOperationCreate(archive_obj, progress_bar)
{
  preferedArchiveType=perferedarchiveextension;
  includewholepath=hastoincludewholepath;
  actionaddfiles=action_addfiles;
}

void CArchiveOperationProcessInputFiles::createArchiveFromCommandLine( QStringList files, QString preferedtype  ){
  idmessageok=CREATE_ARCHIVE_CMD_LINE_ACHIEVED;
  idmessageerror=CREATE_ARCHIVE_CMD_LINE_ACHIEVED;
  processInputFiles( files, preferedtype );
}

void CArchiveOperationProcessInputFiles::processPastedFiles( QStringList files, bool view_bydirs ){
  idmessageok=PASTE_FILES_ACHIEVED;
  idmessageerror=CANNOT_PERFORM_OPERATION;
  viewbydirs=view_bydirs;
  kdDebug()<<QString("In CArchiveOperationProcessInputFiles::processPastedFiles")<<endl;
  processInputFiles( files );
}

/** Automaticaly create a compressed file containing @param files
  * @param preferedtype is an archive extension (.zip...) that indicated
  * which type of archive should be created. If @param preferedtype is Null,
  * use KArchiver's default archive type
If there is a single file or directory, create an archive
named files.tar.gz. Otherwise, prompt the user for a name */
void CArchiveOperationProcessInputFiles::processInputFiles( QStringList files, QString preferedtype  ){
  QStringList strlistWithoutPath;   //Contains the names WITHOUT their path of dropped files
  QStringList strlistWithPath;      //Contains the names WITH their path of dropped files
  QString commonpath;
  QStringList pathlist;
  CAddFiles dlgTypeAction;
  QString archivename;
  QFileInfo fileinfo;
  QString entryname;
  QString errormessage;

  strlistWithoutPath.clear();
  strlistWithPath.clear();
  pathlist.clear();

  for( QStringList::Iterator it=files.begin(); it!=files.end(); ++it)
  {
      kdDebug()<<QString("processInputFiles: adding %1*").arg(*it)<<endl;
      entryname=openRemoteFile(KURL((*it)));
      if(entryname!=NULL)
      {
        strlistWithPath.append(entryname);
        //Let's keep only the filename
        fileinfo.setFile(entryname);
         
        pathlist.append(fileinfo.dirPath(true)+"/");
        kdDebug()<<QString("Appended %1, path=%2").arg(entryname).arg(fileinfo.dirPath(true)+"/")<<endl;
      }
  }
  
  
  //Get the common parent directory of all the files
  commonpath=*pathlist.begin();
  int minnumberofsubdirs=(*pathlist.begin()).contains("/");
  int numberofsubdirs;
  for ( QStringList::Iterator it=pathlist.begin(); it!=pathlist.end(); ++it)
  {
    numberofsubdirs=(*it).contains("/");
    if( numberofsubdirs < minnumberofsubdirs )
    {
      minnumberofsubdirs=numberofsubdirs;
      commonpath=*it;
    }
  }
  
  const int commonpathlength=commonpath.length();
  for ( QStringList::Iterator it=strlistWithPath.begin(); it!=strlistWithPath.end(); ++it)
  {
    entryname=*it;
    strlistWithoutPath.append( entryname.remove(0,commonpathlength) );
  }

  if(preferedtype.isNull())
    preferedtype=preferedArchiveType;
  if(!preferedtype.startsWith("."))
    preferedtype="."+preferedtype;
    
  if(archiveobj==NULL)
    dlgTypeAction.canAddToCurrentArchive(false);//None archive loaded=>disable some radio buttons

  //Drop of one file onto an empty window
  if((strlistWithPath.count()==1) && (archiveobj==NULL))
  {
     newarchivename=archivename=strlistWithPath.first();
     errormessage=checkCanIdentifyArchive(archivename);
     if(errormessage.isNull())
     {
        //We have dropped an archive, so open it!
        if( canProcessDisplayArchive( archivename ) )
          return;
     }
     else if(errormessage == errormsgnocompressor)
     {
      //The dropped file is an archive, but the required compressor is not installed
      KMessageBox::error(0, errormsgnocompressor);
     }
     else
     {
       //We have dropped one file; so create archivename from it.
       newarchivename=archivename+=preferedtype;
       kdDebug()<<QString("Will create an archive from this file: %1").arg(archivename)<<endl;
       errormessage  = checkCanCreateNewArchive(archivename);
       errormessage += checkCanIdentifyArchive(archivename);
       if(errormessage.isNull())
       {
            if(includewholepath)
              addFilesToNewArchive( archivename, strlistWithPath );
            else
              addFilesToNewArchive( archivename, strlistWithoutPath, commonpath );
            return;
       }
       else
       {
        emit operationEnded(idmessageerror, archivename);
        return;
       }
     }
  }
  
  //Ask what to do...
  if(!dlgTypeAction.exec())
  {
      emit operationEnded(idmessageerror, i18n("Operation canceled"));
      return;
  }
  switch(dlgTypeAction.getAddFilesChoice())
  {
    case CAddFiles::ADD_TO_CURRENT_ARCHIVE:
    {
      ///Add to current archive
      connect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
      if(includewholepath)
        archiveobj->addFilesToArchive(strlistWithPath, false, actionaddfiles, NULL);
      else
        archiveobj->addFilesToArchive(strlistWithoutPath, false, actionaddfiles, commonpath);
      break;
    }
    case CAddFiles::ADD_TO_ANOTHER_ARCHIVE:
    {
      ///Add to another archive
      newarchivename=archivename=dlgTypeAction.getOtherArchiveName();
       kdDebug()<<QString("CArchiveOperationProcessInputFiles::processInputFiles Add files to this archive:%1").arg(archivename)<<endl;
       
      errormessage = checkCanIdentifyArchive( archivename );
      
      if( errormessage.isNull() )
      {
        progressbar->reset();
        progressbar->setTotalSteps ( strlistWithPath.count() );
    
        if(includewholepath)
          addFilesToThisArchive( archivename, strlistWithPath );
        else
         {
            kdDebug()<<QString("Adding files without path, basedir=%1").arg(commonpath)<<endl;
            addFilesToThisArchive( archivename, strlistWithoutPath, false, ADD_AND_REPLACE_FILES, commonpath );
         }
      }
      else
      {
        KMessageBox::error(0, i18n("Cannot perform operation, exiting") + "\n" + errormessage, errormessage);
        emit operationEnded(idmessageerror, errormessage);
      }
      break;
    }
    case CAddFiles::CREATE_NEW_ARCHIVE_AND_ADD:
    {
      //Create a new archive
      newarchivename=archivename=dlgTypeAction.getNewArchiveName();
      kdDebug()<<QString("CArchiveOperationProcessInputFiles::processInputFiles Add to this new archive:%1").arg(archivename)<<endl;
      errormessage = checkCanCreateNewArchive( archivename );
      errormessage+=checkCanIdentifyArchive( archivename );
      
      if( errormessage.isNull() )
      {
        progressbar->reset();
        progressbar->setTotalSteps ( strlistWithPath.count() );
    
        if(includewholepath)
          addFilesToNewArchive( archivename, strlistWithPath );
        else
          addFilesToNewArchive( archivename, strlistWithoutPath, commonpath );
      }
      else
      {
        KMessageBox::error(0, i18n("Cannot perform operation, exiting") + "\n" + errormessage, errormessage);
        emit operationEnded(idmessageerror, errormessage);
      }
      break;
    }
    case CAddFiles::OPEN_THIS_ARCHIVE:
    {
      //Open current archive
      if( canProcessDisplayArchive(archivename) )
        return;
      else
        emit operationEnded(idmessageerror, i18n("Cannot perform operation, exiting"));
      break;
    }
    default:
    case CAddFiles::INVALID:
      emit operationEnded(idmessageerror, i18n("Cannot perform operation, exiting"));
      return;
      break;
  }
}

/** User has selected to open @param archivename. Try to lauch the adequate process. Otherwise, return false*/
bool CArchiveOperationProcessInputFiles::canProcessDisplayArchive(QString& archivename)
{
kdDebug()<<QString("Trying to display %1").arg(archivename)<<endl;
    if(archiveobj!=NULL)
    {
      //An archive is already loaded, so try to open this one in a new window
      emit operationEnded(OPEN_ARCHIVE_IN_NEW_WINDOW, archivename);
      return true;
    }
    else
    {
      archiveoperationdisplay = new CArchiveOperationDisplay( archivename, false, viewbydirs, archiveobj, progressbar );
kdDebug()<<QString("CanDisplayArchive=%1").arg(archiveoperationdisplay->canDisplayArchive())<<endl;
      if( archiveoperationdisplay->canDisplayArchive().isNull() )
      {
        //Open this archive in present empty window
        connect(archiveoperationdisplay, SIGNAL(operationEnded(int, QString)), this, SLOT(slotArchiveDisplayed(int, QString)));
        archiveoperationdisplay->displayArchiveContent();
        return true;
      }
      else
        delete archiveoperationdisplay;//Cannot handle this archive, so treat it as a regular file...
    }
    return false;
}

void CArchiveOperationProcessInputFiles::slotArchiveDisplayed(int message, QString error)
{
  disconnect(archiveoperationdisplay, SIGNAL(operationEnded(int, QString)), this, SLOT(slotArchiveDisplayed(int, QString)));
  delete archiveoperationdisplay;
  if(message == DISPLAY_ACHIEVED)
  {
    archiveobj=archiveoperationdisplay->getArchiveObject();
    archiveobj->setArchiveName(archiveoperationdisplay->getArchiveName());
    emit operationEnded(DISPLAY_ACHIEVED, i18n("Ready"));
  }
  else
    emit operationEnded(CANNOT_PERFORM_OPERATION, error);
}

void CArchiveOperationProcessInputFiles::slotArchiveCreated()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotArchiveCreated()));
  if(idmessageok!=CREATE_ARCHIVE_CMD_LINE_ACHIEVED)
    idmessageok=ADD_FILES_ANOTHER_ARCHIVE_ACHIEVED;
  emit operationEnded(idmessageok, newarchivename);
}

void CArchiveOperationProcessInputFiles::slotFilesAddedToAnotherArchive()
{
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAddedToAnotherArchive()));
  if(idmessageok!=CREATE_ARCHIVE_CMD_LINE_ACHIEVED)
    idmessageok=ADD_FILES_ANOTHER_ARCHIVE_ACHIEVED;
  emit operationEnded(idmessageok, newarchivename);
}

void CArchiveOperationProcessInputFiles::slotFilesAdded()
{
  kdDebug()<<QString("In CArchiveOperationProcessInputFiles::slotFilesAdded")<<endl;
  disconnect(archiveobj, SIGNAL(archiveReadEnded()), this, SLOT(slotFilesAdded()));
  emit operationEnded(ADD_FILES_ACHIEVED, i18n("Ready"));
}

/** Download a net file and returns its local filename*/
QString CArchiveOperationProcessInputFiles::openRemoteFile( const KURL& url){
  QString localfile;

  if(url.isLocalFile())
  {
    if( url.prettyURL().startsWith("file://") )
      return url.prettyURL().remove(0,7);
    else
      return url.prettyURL();
  }
  localfile=QDir::homeDirPath();
  localfile+="/";
  localfile+=url.fileName(true);
  kdDebug()<<QString("local file:%1*%2*").arg(localfile).arg(url.prettyURL())<<endl;
  if ( !url.isValid() )
  {
      kdDebug()<<QString("Bad URL!")<<endl;
      return NULL;
  }

  if (KIO::NetAccess::download(url, localfile, 0) == false)
  {
    kdDebug()<<QString("Cannot download file %1").arg(url.prettyURL())<<endl;
    return NULL;
  }

  return localfile;
}

#include "carchiveoperation.moc"

Generated by  Doxygen 1.6.0   Back to index