Back to index

scribus-ng  1.3.4.dfsg+svn20071115
fileunzip.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008  *   Copyright (C) 2004 by Riku Leino                                      *
00009  *   tsoots@gmail.com                                                      *
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  *   This program is distributed in the hope that it will be useful,       *
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00019  *   GNU General Public License for more details.                          *
00020  *                                                                         *
00021  *   You should have received a copy of the GNU General Public License     *
00022  *   along with this program; if not, write to the                         *
00023  *   Free Software Foundation, Inc.,                                       *
00024  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00025  ***************************************************************************/
00026 
00027 #include "scconfig.h"
00028 #include "fileunzip.h"
00029 
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <errno.h>
00033 #include <fcntl.h>
00034 
00035 #ifdef HAVE_SYS_TYPES_H
00036 #include <sys/types.h>
00037 #endif
00038 #ifdef HAVE_SYS_STAT_H
00039 #include <sys/stat.h>
00040 #endif
00041 
00042 #ifdef HAVE_UNISTD_H
00043 # include <unistd.h>
00044 #endif
00045 
00046 #ifndef _MSC_VER
00047 #include <utime.h>
00048 #else
00049 #include <direct.h>
00050 #include <time.h>
00051 #include <sys/utime.h>
00052 #endif
00053 
00054 #include <iostream>
00055 #include "unzip.h"
00056 #include <qdir.h>
00057 
00058 #include "scpaths.h"
00059 
00060 #define CASESENSITIVITY (0)
00061 #define WRITEBUFFERSIZE (8192)
00062 #define MAXFILENAME (256)
00063 
00064 int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password);
00065 int do_extract_onefile(unzFile uf, const QString& filename, int opt_extract_without_path, int opt_overwrite, const char* password);
00066 FILE*    openfile(const QString& filename, const QString& mode);
00067 unzFile  unzOpenFile(const QString& filename);
00068 int mymkdir(const QString& dirname);
00069 int makedir (const QString& newdir);
00070 void change_file_date(const QString& filename, uLong dosdate, tm_unz tmu_date);
00071 
00072 #if defined(_WIN32) && defined(HAVE_UNICODE)
00073 zlib_filefunc_def file_api;
00074 static voidpf ZCALLBACK fopen_filefunc_unicode(voidpf opaque, const char *filename, int mode);
00075 #define utimbuf _utimbuf
00076 #endif
00077 
00078 FileUnzip::FileUnzip(QString zipFilePath)
00079 {
00080        zipFile = zipFilePath;
00081 }
00082 
00083 QString FileUnzip::getFile(QString name)
00084 {
00085        QString pwd = QDir::currentDirPath();
00086        QString outDir = ScPaths::getTempFileDir();
00087        QFile f(outDir);
00088        QFileInfo fi(f);
00089        if (!fi.isWritable())
00090               outDir = ScPaths::getApplicationDataDir();
00091        QDir::setCurrent(outDir);
00092        unzFile uf = unzOpenFile(zipFile);
00093        int ret = do_extract_onefile(uf,name, 0, 1, NULL);
00094        unzCloseCurrentFile(uf);
00095        QDir::setCurrent(pwd);
00096        if (ret != 0)
00097               return NULL;
00098        else
00099               return outDir + name;
00100 }
00101 
00102 FileUnzip::~FileUnzip()
00103 {
00104 
00105 }
00106 
00107 FILE* openfile(const QString& filename, const QString& mode)
00108 {
00109        FILE* fout = NULL;
00110 #if defined(_WIN32) && defined(HAVE_UNICODE)
00111        fout = _wfopen((const wchar_t*) filename.ucs2(), (const wchar_t*) mode.ucs2());
00112 #else
00113        QCString fname = filename.local8Bit();
00114        QCString fmode  = mode.local8Bit();
00115     fout = fopen(fname.data(), fmode.data());
00116 #endif
00117        return fout;
00118 }
00119 
00120 unzFile unzOpenFile(const QString& filename)
00121 {
00122        unzFile unz;
00123 #if defined(_WIN32) && defined(HAVE_UNICODE)
00124        fill_fopen_filefunc(&file_api);
00125        file_api.zopen_file = fopen_filefunc_unicode;
00126        unz = unzOpen2((const char*)filename.ucs2(), &file_api); 
00127 #else
00128        QCString fname(filename.local8Bit());
00129        unz = unzOpen(fname.data()); 
00130 #endif
00131        return unz;
00132 }
00133 
00134 #if defined(_WIN32) && defined(HAVE_UNICODE)
00135 static voidpf ZCALLBACK fopen_filefunc_unicode(voidpf opaque, const char *filename, int mode)
00136 {
00137        FILE* file = NULL;
00138        const wchar_t* mode_fopen = NULL;
00139        if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
00140               mode_fopen = L"rb";
00141        else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
00142               mode_fopen = L"r+b";
00143        else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
00144               mode_fopen = L"wb";
00145        if (!((filename == NULL) || (mode_fopen == NULL)))
00146               file = _wfopen((const wchar_t *)filename, mode_fopen);
00147        return file;
00148 }
00149 #endif
00150 
00151 int mymkdir(const QString& dirname)
00152 {
00153     int ret=0;
00154 #if defined(_WIN32) && defined(HAVE_UNICODE)
00155        ret = _wmkdir((const wchar_t*) dirname.ucs2());
00156 #elif defined(_WIN32)
00157        QCString cdir = dirname.local8Bit();
00158     ret = _mkdir(cdir.data());
00159 #else
00160        QCString cdir = dirname.local8Bit();
00161     ret = mkdir (cdir.data(), 0775);
00162 #endif
00163     return ret;
00164 }
00165 
00166 int makedir (const QString& newdir)
00167 {
00168        QChar p;
00169        QString buffer;
00170        int len = newdir.length();
00171        
00172        if (len <= 0)
00173               return 0;
00174        buffer = newdir;
00175 
00176        if (buffer.endsWith("/") || buffer.endsWith("\\"))
00177               buffer.left(len - 1);
00178 
00179        if (mymkdir(buffer) == 0)
00180               return 1;
00181 
00182        uint cIndex = 1;
00183        p = buffer[1];
00184        while (1)
00185        {
00186               QString tmpBuf;
00187               while(!p.isNull() && p != '\\' && p != '/')
00188                      p = buffer[cIndex++];
00189               tmpBuf = buffer.left(cIndex - 1);
00190               if ((mymkdir(tmpBuf) == -1) && (errno == ENOENT))
00191                      return 0;
00192               if (p.isNull())
00193                      break;
00194               p = buffer[++cIndex];
00195        }
00196        return 1;
00197 }
00198 
00199 int do_extract_onefile(unzFile uf, const QString& filename, int opt_extract_without_path, int opt_overwrite, const char* password)
00200 {
00201 //    int err = UNZ_OK;
00202        QCString fname = filename.local8Bit();
00203     if (unzLocateFile(uf,fname.data(),CASESENSITIVITY)!=UNZ_OK)
00204         return 2;
00205 
00206     if (do_extract_currentfile(uf,&opt_extract_without_path,
00207                                       &opt_overwrite,
00208                                       password) == UNZ_OK)
00209         return 0;
00210     else
00211         return 1;
00212 }
00213 
00214 int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int*, const char* password)
00215 {
00216        char  fn_inzip[256];
00217        QString filename_inzip;
00218        QString filename_withoutpath;
00219        int err=UNZ_OK;
00220        FILE *fout=NULL;
00221        void* buf;
00222        uInt size_buf;
00223 
00224        unz_file_info file_info;
00225        //uLong ratio=0;
00226        err = unzGetCurrentFileInfo(uf,&file_info,fn_inzip,sizeof(fn_inzip),NULL,0,NULL,0);
00227 
00228        if (err!=UNZ_OK)
00229               return err;
00230 
00231        size_buf = WRITEBUFFERSIZE;
00232        buf = (void*)malloc(size_buf);
00233        if (buf==NULL)
00234               return UNZ_INTERNALERROR;
00235 
00236        QChar p;
00237 //     uint cIndex = 0;
00238        filename_inzip = QString::fromLocal8Bit(fn_inzip); 
00239        filename_withoutpath = filename_inzip;
00240        for (uint i = 0; i < filename_inzip.length(); i++)
00241        {
00242               p = filename_inzip[i];
00243               if( (p == '/') || (p =='\\'))
00244                      filename_withoutpath = filename_inzip.mid(i+1);
00245        }
00246 
00247        if (filename_withoutpath.isEmpty())
00248        {
00249               if ((*popt_extract_without_path)==0)
00250                      mymkdir(filename_inzip);
00251        }
00252        else
00253     {
00254               QString write_filename;
00255               int skip=0;
00256 
00257               if ((*popt_extract_without_path)==0)
00258                      write_filename = filename_inzip;
00259               else
00260                      write_filename = filename_withoutpath;
00261               
00262               err = unzOpenCurrentFilePassword(uf,password);
00263 
00264               if ((skip==0) && (err==UNZ_OK))
00265               {
00266                      fout = openfile(write_filename, "wb");
00267             /* some zipfile don't contain directory alone before file */
00268                      if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
00269                                                         (filename_withoutpath != filename_inzip))
00270                      {
00271                             uint len = filename_inzip.length() - filename_withoutpath.length() - 1;
00272                             QString write_dir = filename_inzip.left(len);
00273                             makedir(write_dir);
00274                             fout = openfile(write_filename, "wb");
00275                      }
00276               }
00277 
00278               if (fout!=NULL)
00279               {
00280                      do
00281                      {
00282                             err = unzReadCurrentFile(uf,buf,size_buf);
00283                             if (err<0)
00284                                    break;
00285                             if (err>0)
00286                                    if (fwrite(buf,err,1,fout)!=1)
00287                                    {
00288                                           err=UNZ_ERRNO;
00289                                           break;
00290                                    }
00291                      }
00292                      while (err>0);
00293                      if (fout)
00294                             fclose(fout);
00295 
00296                      if (err==0)
00297                             change_file_date(write_filename,file_info.dosDate,
00298                                                                file_info.tmu_date);
00299               }
00300 
00301               if (err==UNZ_OK)
00302                      err = unzCloseCurrentFile (uf);
00303               else
00304                      unzCloseCurrentFile(uf); /* don't lose the error */
00305        }
00306 
00307        free(buf);
00308        return err;
00309 }
00310 
00311 /* change_file_date : change the date/time of a file
00312     filename : the filename of the file where date/time must be modified
00313     dosdate : the new date at the MSDos format (4 bytes)
00314     tmu_date : the SAME new date at the tm_unz format */
00315 void change_file_date(const QString& filename, uLong, tm_unz tmu_date)
00316 {
00317        struct utimbuf ut;
00318        struct tm newdate;
00319        newdate.tm_sec = tmu_date.tm_sec;
00320        newdate.tm_min=tmu_date.tm_min;
00321        newdate.tm_hour=tmu_date.tm_hour;
00322        newdate.tm_mday=tmu_date.tm_mday;
00323        newdate.tm_mon=tmu_date.tm_mon;
00324        if (tmu_date.tm_year > 1900)
00325               newdate.tm_year=tmu_date.tm_year - 1900;
00326        else
00327               newdate.tm_year=tmu_date.tm_year ;
00328        newdate.tm_isdst=-1;
00329 
00330        ut.actime=ut.modtime=mktime(&newdate);
00331 #if defined(_WIN32) && defined(HAVE_UNICODE)
00332        _wutime((const wchar_t*) filename.ucs2(), &ut);
00333 #else
00334        QCString fname = filename.local8Bit();
00335        utime(fname.data(), &ut);
00336 #endif
00337 }