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

czip.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 "czip.h"

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

CZip::CZip(){
  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(&processcomment,SIGNAL(receivedStdout(KProcess*, char*, int)),this,SLOT(receivingComment(KProcess*,char*,int)));

  if(!viewbydirectories)
  {
    list->setColumnText(4, i18n("Packed"));
    list->setColumnText(5, i18n("Ratio"));
  }
  else
  {
    list->setColumnText(4, i18n("Owner"));
    list->setColumnText(5, i18n("Permissions"));
  }
}

CZip::~CZip(){
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 */
00056 void CZip::displayArchiveContent(){

  initializeReadingArchive();
  if(viewbydirectories)
  {
    zipfile=new KZip(archiveName);
    if( !zipfile->open(IO_ReadOnly) )
      errors.append("KZip Process failed to open file");
      
    CArchive::displayArchiveContent(zipfile->directory(),QString::null);
    endProcess(NULL);
  }
  else
  {
      FILE *flot;


    processread << "unzip";
      processread << "-lv" << archiveName;

      if(readArchiveWithStream)
      {
            processread.start(&flot,KProcess::AllOutput);
            displayZipArchiveContent(flot);
      }
      else
      {
            m_buffer[0]='\0';
            headerremoved=false;
            finished=false;
            processread.start(KProcess::NotifyOnExit, KProcess::AllOutput);
      }
  }
  
  readArchiveComments();
}

/** Retrieves the comments of this Zip archive */
00094 void CZip::readArchiveComments()
{
   kdDebug()<<QString("Starting process comment")<<endl;
   headercommentsremoved=false;
   processcomment.clearArguments();
   processcomment << "unzip" << "-z" << archiveName;
   processcomment.start(KProcess::DontCare, KProcess::Stdout);
}

void CZip::receivingComment(KProcess*, char* buffer, int length)
{
   buffer[length]='\0';
   QString str=buffer;
   kdDebug()<<QString("Process comment: got %1*").arg(str)<<endl;
   if(headercommentsremoved)
      archivecomments.append(buffer);
   else if(str.find("Archive:")!=-1)
   {
      headercommentsremoved=true;
      archivecomments.append(str.right(length-str.find(".zip\n")-4));
   }
}

/** 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 */
00120 void CZip::displayZipArchiveContent( FILE *flot ){
      CListViewItem* elementListe=NULL;
      char buffer[5000];
      char ratio[30];
      char packedsize[256];
      char crc[20];
      char size[30];
      QString date;
      QString y, m, d;
      char year[5];
      char month[2];
      char day[2];
      char time[7];
      char filename[5000];
      char methode[20];
      QString path;
      QString name;
      QString message;
      int i;

      do
            fgets( buffer, 5000, flot );
      while( !feof(flot) && (strstr( buffer, "----" )==NULL));
      fgets( buffer, 5000, flot );
      while( !feof(flot) && (strstr( buffer, "----" )==NULL))
      {
            sscanf(buffer, "  %[0-9]  %[a-zA-Z:]   %[0-9]  %[0-9%]  %[0-9]-%[0-9]-%[0-9]  %[0-9:]  %[a-zA-Z0-9]   %[^\n]",size, methode, packedsize, ratio, day, month, year, time, crc, filename );
            
                name=filename;
            i=name.findRev('/');
            if(i!=-1)
            {
                  path=name.left(i+1);
                  name=name.remove(0,i+1);
            if(name=="")name="..";
            }
            else
                  path="";

            y=year;
            m=month;
            m.truncate(2);
            d=day;
            date=y+"-"+m+"-"+d;

    elementListe=new CListViewItem(list,name,size,time,getLocalizedDate(QDate(y.toInt(),m.toInt(),d.toInt())), packedsize,ratio,path);

            setIcon(name, "", elementListe);
            elementListe->widthChanged();
            fgets( buffer, 5000, flot );
      }
      fclose( flot );
}

/*Overloaded method*/
void CZip::displayZipArchiveContent( const char* line){
  CListViewItem* elementListe=NULL;
  char ratio[30];
  char packedsize[256];
  char crc[20];
  char size[30];
  QString y, m, d;
  int iy;
  char year[5];
  char month[2];
  char day[2];
  char time[7];
  char sname[5000];
  char method[20];
  QString path;
  QString name;
  QString message;
  int i;

  sscanf(line, "  %[0-9]  %[a-zA-Z:]   %[0-9]  %[0-9%]  %[0-9]-%[0-9]-%[0-9]  %[0-9:]  %[a-zA-Z0-9]   %[^\n]",size, method, packedsize, ratio, day, month, year, time, crc, sname );
  
  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();
  if(iy<70) iy+=2000;//2k year bug, fix this before 2070...
  m=month;
  m.truncate(2);
  d=day;
  d.truncate(2);

  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 */
00224 void CZip::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))
                  displayZipArchiveContent( 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))
                  displayZipArchiveContent( line );
            }
      }
      else if(!headerremoved)
        headerremoved = true;
      else
        finished = true;
/*          if((passage<1)&&(strncmp(line,"--------",8)!=0)&&(strncmp(line," Length   Method",16)!=0))
                  displayZipArchiveContent( 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 */
00314 void CZip::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 */
00327 void CZip::haveSdtOutExtract(KProcess *, char *, int ){
      counter++;
      if(counter%2==0)
            progressbar->setProgress(progressbar->progress()+ 1 );

}

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

      emit(archiveReadEnded());
}

/** 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
      */
00346 void CZip::extractArchive(QString & extractpath, int extractall, QString &filetoextract){
  QStringList listsubdir;

  errors.clear();
  counter=0;
  progressbar->reset();

  processextract.clearArguments();
  processextract << "unzip";

  processextract << "-P";
  if(archivePassword.isEmpty()) 
    processextract << "''";
  else 
    processextract << archivePassword; 

  processextract << "-o"; //user select the files that have to be extracted in checkFiles(extractpath, extractall)

  processextract << archiveName;
  processextract << "-d"+extractpath;

  if((extractall!=EXTRACTONE)&&(extractall!=EXTRACTONE_AND_BLOCK)&&(!checkFiles(extractpath, extractall)))
  {
    endProcess(NULL);
    return;
  }
  else if(extractall==EXTRACTONE_AND_BLOCK)
  {
    //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
    processextract << filetoextract;
    if(processextract.start(KProcess::Block)==FALSE)
      kdDebug()<<("\n*PB PROCESS*\n");
  }
  else if(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
    processextract << filetoextract;
    if(processextract.start(KProcess::NotifyOnExit)==FALSE)
      kdDebug()<<("\n*PB PROCESS*\n");
  }
  else if(extractall!=EXTRACTONE_AND_BLOCK)
  {
          //We extract through the Stdout to have a progress indicator
    if(processextract.start(KProcess::NotifyOnExit,KProcess::AllOutput)==FALSE)
      kdDebug()<<("\n*PB PROCESS*\n");
  }
  counter=0;
}

/** delete @param filestodelete from current archive */
00400 void CZip::removeFilesFromArchive( QStringList filestodelete ){
      processread.clearArguments();
      processread << "zip" << "-dq";
      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 */
00416 void CZip::addFilesToArchive( QStringList filestoadd, bool removeoriginalfiles, int action, QString relativepath){
      QString s;
 kdDebug()<<QString("CZip::addFilesToArchive %1, RelativePath=%2 comprrate %3").arg(archiveName).arg(relativepath).arg(compressrate)<<endl;
      if(relativepath!=NULL)
            QDir::setCurrent(relativepath);

      processadd.clearArguments();
      processadd << "zip";
      if(removeoriginalfiles)
            processadd << "-m";
      if(recursivemode)
            processadd << "-r";

  if(!archivePassword.isEmpty())
    processadd  << "-P" << archivePassword;
  
    switch(action)
    {
            case UPDATE_FILES:
                    //Mode update
                    processadd << "-u";
                    break;
    }
    processadd << QString("-%1").arg(compressrate);
    processadd << "-q";
    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("AddZip:%1 (was %2)").arg(s).arg(f)<<endl;
    kdDebug()<<QString("Appending %1 to Zip file").arg(s)<<endl;
    processadd << s;
    }
    processadd.start(KProcess::NotifyOnExit);
}

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

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

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

/**Returns true if current archive can be repaired*/
00474 bool CZip::canRepairArchive(){
  return true;
}

/**Launches the repair process*/
00479 void CZip::repairCurrentArchive()
{
  errors.clear();
  
  repairedArchiveName=archiveName;
  QDir::setCurrent(QFileInfo(archiveName).dirPath(true));
  
  processextract.clearArguments();
  processextract << "zip" << "-FF" << archiveName;
  processextract.start(KProcess::NotifyOnExit,KProcess::AllOutput);
}

/** unzip don't dosplay any error when extracting some damaged archives, so
  * perform an integrity check...*/
00493 void CZip::testCurrentArchiveIntegrity()
{
  processextract.clearArguments();
  processextract << "zip" << "-T" << archiveName;
  processextract.start(KProcess::NotifyOnExit,KProcess::AllOutput);
}

#include "czip.moc"

Generated by  Doxygen 1.6.0   Back to index