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

c7z.cpp

/***************************************************************************
                          czip.cpp  -  description
                             -------------------
    begin                : Sat Dec 2 2000
    copyright            : (C) 2000 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 "c7z.h"

#include <kdebug.h>
#include <kstddirs.h>
#include <kmessagebox.h> 
#include <qdir.h>
#include <math.h>

C7z::C7z(){
  CArchive();
  
  connect(&processread,SIGNAL(receivedStdout(KProcess*, char*, int)),this,SLOT(haveSdtOut(KProcess*,char*,int)));
  connect(&processread,SIGNAL(processExited (KProcess*)),this,SLOT(endProcess(KProcess*)));
  connect(&processextract,SIGNAL(receivedStdout(KProcess*, char*, int)),this,SLOT(haveSdtOutExtract(KProcess*,char*,int)));
  connect(&processextract,SIGNAL(processExited (KProcess*)),this,SLOT(endProcess(KProcess*)));
  connect(&processextract, SIGNAL(receivedStderr(KProcess *, char *, int)),this, SLOT(haveSdtErrExtract(KProcess*,char*,int)));
  connect(&processadd,SIGNAL(receivedStdout(KProcess*, char*, int)),this,SLOT(haveSdtOutExtract(KProcess*,char*,int)));
  connect(&processadd,SIGNAL(processExited (KProcess*)),this,SLOT(endProcess(KProcess*)));

  connect(&processextract7z,SIGNAL(receivedStdout(KProcess*, char*, int)),this,SLOT(haveSdtOutExtract(KProcess*,char*,int)));
  connect(&processextract7z,SIGNAL(processExited (KProcess*)),this,SLOT(reconstructpath(KProcess*)));
  connect(&processextract7z, SIGNAL(receivedStderr(KProcess *, char *, int)),this, SLOT(haveSdtErrExtract(KProcess*,char*,int)));
  
  list->setColumnText(4, i18n("Packed"));
  list->setColumnText(5, i18n("Ratio"));
}

C7z::~C7z(){
archivePassword="";
}

/** this method will launch the right compressor
      to list the file contents
      It will then launch the right method to display
      the content in the listview */
00053 void C7z::displayArchiveContent(){

  initializeReadingArchive();
      
    processread << "7za";
      processread << "l" << archiveName;

    m_buffer[0]='\0';
    headerremoved=false;
    finished=false;
    processread.start(KProcess::NotifyOnExit, KProcess::AllOutput);
}

/** display in a listview the content of the current
zip archive. This method examines the stdout of
unarj to sort useful infos for the listview */
00069 void C7z::display7zArchiveContent( const char* line){
  CListViewItem* elementListe=NULL;
  QString ratio;
  char packedsize[30];
  char crc[20];
  char size[30];
  QString y, m, d;
  int iy;
  char year[7];
  char month[3];
  char day[3];
  char time[10];
  char sname[5000];
  QString path;
  QString name;
  int i;
kdDebug()<<QString("Read 7z:%1").arg(line)<<endl;
  sscanf(line, "%[0-9]-%[0-9]-%[0-9] %[0-9:] %[a-zA-Z.] %[0-9] %[0-9] %[^\n]", year, month, day, time, crc, size, packedsize, sname );
kdDebug()<<QString("Identified %1, %2, %3, %4, %5, %6, %7, %8").arg(year).arg(month).arg(day).arg(time).arg(crc).arg(size).arg(packedsize).arg(sname)<<endl;
  name=sname;
  i=name.findRev('/');
  if(i!=-1)
  {
    path=name.left(i+1);
    name=name.remove(0,i+1);
    if(name=="")name="..";
  }
  else
    path="";

  y=year;
  y.truncate(2);
  iy=y.toInt();
  m=month;
  m.truncate(2);
  d=day;
  d.truncate(2);

  int isize=QString(size).toInt();
  int ipackedsize=QString(packedsize).toInt();
  if(isize==0)
    ratio="";
  else
    ratio=ratio.sprintf("%.1f\%",(1-(float)ipackedsize/(float)isize)*100.0);
  elementListe=new CListViewItem(list,name,size,time,getLocalizedDate(QDate(iy,m.toInt(),d.toInt())), packedsize,ratio,path);

  setIcon(name, "", elementListe);
  elementListe->widthChanged();
}

/** we recive some informations through the standard
output of the process */
00121 void C7z::haveSdtOut(KProcess *, char *buffer, int length){
      //Has user canceled current action ?
      if(stopreadprocess)
            return;

      // This section is here only for testing. It has been taken from ark:
      //1997-1999: Rob Palmbos palm9744@kettering.edu
      //2000: Corel Corporation (author: Emily Ezust, emilye@corel.com)
      //and adapted to karchiveur
//    int passage;
  char c = buffer[length];
  buffer[length] = '\0';

  char line[1024] = "";
  char *tmpl = line;
  char *tmpb;


  //We copy m_buffer to tmpl
  for( tmpb = m_buffer; *tmpb != '\0'; tmpl++, tmpb++ )
    *tmpl = *tmpb;

  //We copy the fisrt string of buffer (till \n) to tmpl
  for( tmpb = buffer; *tmpb != '\n'; tmpl++, tmpb++ )
    *tmpl = *tmpb;

  tmpb++;
  *tmpl = '\0';

  if( *tmpb == '\0' )
    m_buffer[0]='\0';

  if( !strstr( line, "----" ) )
      {
      if( headerremoved && !finished )
      {
//    if((strncmp(line,"Archive: ",9)!=0)&&(strncmp(line," Length   Method",16)!=0))
                  display7zArchiveContent( line );
            }
      }
  else if(!headerremoved)
    headerremoved = true;
  else
    finished = true;

  bool stop = (*tmpb == '\0');

  while( !stop && !finished)
  {
      tmpl = line; *tmpl = '\0';

      for(; (*tmpb!='\n') && (*tmpb!='\0'); tmpl++, tmpb++)
                        *tmpl = *tmpb;

      if( *tmpb == '\n' )
                  {
                    *tmpl = '\n';
                    tmpl++;
                    *tmpl = '\0';
                    tmpb++;

      if( !strstr( line, "----" ) )
      {
            if( headerremoved && !finished )
            {
    //      if((strncmp(line,"Archive: ",9)!=0)&&(strncmp(line," Length   Method",16)!=0))
                  display7zArchiveContent( line );
            }
      }
      else if(!headerremoved)
        headerremoved = true;
      else
        finished = true;
/*          if((passage<1)&&(strncmp(line,"--------",8)!=0)&&(strncmp(line," Length   Method",16)!=0))
                  display7zArchiveContent( line );
            else
                  passage++;*/
                  }
      else if (*tmpb == '\0' )
                  {
                  *tmpl = '\0';
                    strcpy( m_buffer, line );
                  stop = true;
                  }
    }
  buffer[length] = c;
}

/** we recive some informations through the error
      * output of the process */
00211 void C7z::haveSdtErrExtract(KProcess *prc, char *buffer, int length){
  buffer[length]=0;

  if (strstr(buffer,"incorrect password")) {
    KMessageBox::error(NULL, i18n("An error occurred during extraction: \n The archive is password protected and the given password is wrong.\nPlease choose 'Archive->Set Password', change the password and try it again."));
    return;
  }
  CArchive::haveSdtErrExtract(prc, buffer, length);
}


/** we recive some informations through the standard
      * output of the process */
00224 void C7z::haveSdtOutExtract(KProcess *, char *, int ){
      counter++;
      if(counter%2==0)
            progressbar->setProgress(progressbar->progress()+ 1 );

}

/** The current process ended */
00232 void C7z::endProcess(KProcess*){
  kdDebug()<<("Process ENDED\n");

      emit(archiveReadEnded());
}

bool C7z::checkFiles7z(QString extractpath, int extractall)
{
  listfilestoextract.clear();
  listfilestoextract=checkFilesOnly(extractpath, extractall);
  progressbar->setTotalSteps(listfilestoextract.count());
  
  if(listfilestoextract.isEmpty())
    return false;
  
  processextract << listfilestoextract;
  return true;
}

void C7z::extractOneFile()
{
  
  processextract7z.clearArguments();
  processextract7z << "7za";
  processextract7z << "e";

  processextract7z << "-p";
  if(!archivePassword.isEmpty()) 
    processextract7z << archivePassword; 

  processextract7z << "-y";

  processextract7z << archiveName;
  processextract7z << "-o"+tmpdir;

  processextract7z << listfilestoextract.first();
  
  if(extractallfiles==EXTRACTONE_AND_BLOCK)
    processextract7z.start(KProcess::Block);
  else
    processextract7z.start(KProcess::NotifyOnExit);
}

void C7z::reconstructpath(KProcess*)
{
  QFileInfo processedfile;
  QDir dir;
  KProcess movejob;
  
  processedfile.setFile(listfilestoextract.first());
  dir.setPath(extractdirectory);
  dir.mkdir(extractdirectory+processedfile.dirPath());
  kdDebug()<<QString("mv %1 %2").arg(tmpdir+processedfile.fileName()).arg(extractdirectory+processedfile.dirPath())<<endl;
  movejob << "mv" << tmpdir+processedfile.fileName() << extractdirectory+processedfile.dirPath();
  movejob.start(KProcess::Block);
  listfilestoextract.remove(listfilestoextract.begin());
  if(listfilestoextract.isEmpty())
    emit(archiveReadEnded());
  else
    extractOneFile();
}

/** Upon the kind of archive, choose the right
      *uncompressor and extract all or some files
      *@toutextraire = 9: extract to karchiveur's temp directory (for viewing)
      *@toutextraire = 1: extract all selected files
      */
00299 void C7z::extractArchive(QString & extractpath, int extractall, QString &filetoextract){
  QStringList listsubdir;
//WARNING: Unix's 7z cannot extract directories in a simple way!!!
  errors.clear();
  counter=0;
  progressbar->reset();
  QString directory;
  directory.sprintf("karchivertmp.%d/", getpid());
  tmpdir = locateLocal( "tmp", directory );
  if(!tmpdir.endsWith("/"))
    tmpdir=tmpdir+"/";

  extractdirectory=extractpath;
  if(!extractdirectory.endsWith("/"))
    extractdirectory=extractdirectory+"/";
  extractallfiles=extractall;

  if((extractall!=EXTRACTONE)&&(extractall!=EXTRACTONE_AND_BLOCK)&&(!checkFiles7z(extractpath, extractall)))
  {
    endProcess(NULL);
    return;
  }
  else if((extractall==EXTRACTONE_AND_BLOCK)||(extractall==EXTRACTONE))
  {
    //We want to view (and so extract) only one file. So we just add this file to the tar or unzip
    //command. For gzip and bzip2 files, in any case, we extract one and only one file, so I put
    //it apart
    listfilestoextract.clear();
    listfilestoextract.append(filetoextract);
  }

  extractOneFile();
}

/** delete @param filestodelete from current archive */
00334 void C7z::removeFilesFromArchive( QStringList filestodelete ){
      processread.clearArguments();
      processread << "7za" << "d";
      processread << archiveName;
  for (QStringList::Iterator f = filestodelete.begin(); f!=filestodelete.end(); ++f )
      {
        processread << *f;
      }
  processread.start(KProcess::Block);
}

/** Add some files to the archive
@param filestoadd : list of files to add
@param removeoriginalfiles : remove or not those files from disk
@param action : 0=mode append and replace files, 1=mode update files
@param relativepath : if !NULL, include only filenames, without their base path */
00350 void C7z::addFilesToArchive( QStringList filestoadd, bool removeoriginalfiles, int action, QString relativepath){
      QString s;
 kdDebug()<<QString("C7z::addFilesToArchive %1, RelativePath=%2 comprrate %3").arg(archiveName).arg(relativepath).arg(compressrate)<<endl;
      if(relativepath!=NULL)
            QDir::setCurrent(relativepath);

      processadd.clearArguments();
      processadd << "7za";

    switch(action)
    {
            case 0:
                    //Mode add&replace
                    processadd << "a";
                    break;
            case 1:
                    //Mode update
                    processadd << "u";
                    break;
    }
  if(!archivePassword.isEmpty())
    processadd  << "-p" << archivePassword;
  
  processadd << QString("-mx=%1").arg((int)(round(compressrate/4.5)*4.5));//Valid arguments are 0, 5 or 9
    processadd << archiveName;
    for (QStringList::Iterator f = filestoadd.begin(); f!=filestoadd.end(); ++f )
    {
      s=*f;
      if(s.endsWith("/") )
        s.truncate(s.length()-1);
      if(s.startsWith("file:"))
        s.remove(0,5);
    kdDebug()<<QString("Appending %1 to 7z file").arg(s)<<endl;
    processadd << s;
    }
    processadd.start(KProcess::NotifyOnExit);
}

/** Create a 7zip archive
@param  nameofarchive: the name of the 7zip archive
@param param: list of files to add
@param relativepath: include only filenames, without their path */
00392 void C7z::createArchive(QString nameofarchive, QStringList filestoadd, QString relativepath) {
      QString str;

      archiveName=nameofarchive;
      kdDebug()<<QString("BeginCreation7z*%1*%2*").arg(nameofarchive).arg(relativepath)<<endl;
      addFilesToArchive(filestoadd, false, 0,relativepath);
}

/** Returns true if archive type supports passwords */
00401 bool C7z::supportPassword(){
 return true;
 
}

/** perform an integrity check...*/
00407 void C7z::testCurrentArchiveIntegrity()
{
  processextract.clearArguments();
  processextract << "7za" << "t" << archiveName;
  processextract.start(KProcess::NotifyOnExit,KProcess::AllOutput);
}


#include "c7z.moc"

Generated by  Doxygen 1.6.0   Back to index