614 lines
17 KiB
C
614 lines
17 KiB
C
/*
|
|
* $Id$
|
|
*/
|
|
|
|
/*
|
|
* Harbour Project source code:
|
|
* Low level zip functions for Zlib dll Call
|
|
*
|
|
* Copyright 2000 Luiz Rafael Culik <culik@sl.conex.net>
|
|
* www - http://www.harbour-project.org
|
|
*
|
|
* 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, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this software; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
|
|
*
|
|
* As a special exception, the Harbour Project gives permission for
|
|
* additional uses of the text contained in its release of Harbour.
|
|
*
|
|
* The exception is that, if you link the Harbour libraries with other
|
|
* files to produce an executable, this does not by itself cause the
|
|
* resulting executable to be covered by the GNU General Public License.
|
|
* Your use of that executable is in no way restricted on account of
|
|
* linking the Harbour library code into it.
|
|
*
|
|
* This exception does not however invalidate any other reasons why
|
|
* the executable file might be covered by the GNU General Public License.
|
|
*
|
|
* This exception applies only to the code released by the Harbour
|
|
* Project under the name Harbour. If you copy code from other
|
|
* Harbour Project or Free Software Foundation releases into a copy of
|
|
* Harbour, as the General Public License permits, the exception does
|
|
* not apply to the code that you add in this way. To avoid misleading
|
|
* anyone as to the status of such modified files, you must delete
|
|
* this exception notice from them.
|
|
*
|
|
* If you write modifications of your own for Harbour, it is your choice
|
|
* whether to permit this exception to apply to your modifications.
|
|
* If you do not wish that, delete this exception notice.
|
|
*
|
|
*/
|
|
|
|
#include <hbsetup.h>
|
|
|
|
#include "hbzip.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
|
|
#if defined(HB_OS_UNIX) || defined(HARBOUR_GCC_OS2) || defined(__DJGPP__)
|
|
# include <unistd.h>
|
|
# include <utime.h>
|
|
# include <sys/types.h>
|
|
# include <sys/stat.h>
|
|
#else
|
|
# include <direct.h>
|
|
# include <io.h>
|
|
#endif
|
|
#include "unzip.h"
|
|
#define CASESENSITIVITY (0)
|
|
#define WRITEBUFFERSIZE (8192)
|
|
extern int err;
|
|
extern int Size_Buf;
|
|
uLong uiCounter;
|
|
char szTempTime[80];
|
|
unzFile szUnzipFile=NULL;
|
|
void hb_____GetTime(unz_file_info file_info) ;
|
|
void hb____ChangeFileDate(char *filename,uLong dosdate,tm_unz tmu_date)
|
|
{
|
|
#if defined(HB_OS_WIN_32)
|
|
HANDLE hFile;
|
|
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
|
|
HB_SYMBOL_UNUSED(tmu_date);
|
|
hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
|
|
0,NULL,OPEN_EXISTING,0,NULL);
|
|
GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
|
|
DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
|
|
LocalFileTimeToFileTime(&ftLocal,&ftm);
|
|
SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
|
|
CloseHandle(hFile);
|
|
#elif defined(HB_OS_UNIX) || defined(HARBOUR_GCC_OS2) || defined(__DJGPP__)
|
|
struct utimbuf ut;
|
|
struct tm newdate;
|
|
newdate.tm_sec = tmu_date.tm_sec;
|
|
newdate.tm_min=tmu_date.tm_min;
|
|
newdate.tm_hour=tmu_date.tm_hour;
|
|
newdate.tm_mday=tmu_date.tm_mday;
|
|
newdate.tm_mon=tmu_date.tm_mon;
|
|
if (tmu_date.tm_year > 1900)
|
|
newdate.tm_year=tmu_date.tm_year - 1900;
|
|
else
|
|
newdate.tm_year=tmu_date.tm_year ;
|
|
newdate.tm_isdst=-1;
|
|
ut.actime=ut.modtime=mktime(&newdate);
|
|
utime(filename,&ut);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/* mymkdir and change_file_date are not 100 % portable
|
|
As I don't know well Unix, I wait feedback for the unix portion */
|
|
int hb___MakeDir(char *szNewDirectory)
|
|
{
|
|
char *szBuffer ;
|
|
char *szTemp;
|
|
int uiLen = strlen(szNewDirectory);
|
|
|
|
if (uiLen <= 0)
|
|
return 0;
|
|
|
|
szBuffer = (void*)hb_xalloc(uiLen+1);
|
|
strcpy(szBuffer,szNewDirectory);
|
|
|
|
if (szBuffer[uiLen-1] == '/') {
|
|
szBuffer[uiLen-1] = '\0';
|
|
}
|
|
|
|
if (hb_fsMkDir(szBuffer))
|
|
{
|
|
|
|
hb_xfree((void*) szBuffer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
szTemp = szBuffer+1;
|
|
while (1)
|
|
{
|
|
char szHold;
|
|
int iResult;
|
|
while(*szTemp && *szTemp != '\\' && *szTemp != '/')
|
|
szTemp++;
|
|
szHold = *szTemp;
|
|
*szTemp = 0;
|
|
|
|
iResult=hb_fsMkDir(szBuffer);
|
|
if (( iResult== -1) && (errno == ENOENT))
|
|
{
|
|
|
|
hb_xfree((void*) szBuffer);
|
|
|
|
|
|
return 0;
|
|
}
|
|
if (szHold == 0)
|
|
break;
|
|
*szTemp++ = szHold;
|
|
}
|
|
|
|
hb_xfree((void*) szBuffer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int hb___ExtractOneFile(unzFile szUnzipFile,const char* filename,BOOL opt_extract_without_path,BOOL opt_overwrite,PHB_ITEM pBlock)
|
|
{
|
|
err = UNZ_OK;
|
|
if (unzLocateFile(szUnzipFile,filename,CASESENSITIVITY)!=UNZ_OK)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
if (hb___ExtractCurrentFile(szUnzipFile,opt_extract_without_path,
|
|
opt_overwrite,pBlock) == UNZ_OK)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
int hb___Extract(unzFile szUnzipFile,BOOL bExtractPath,BOOL opt_overwrite,PHB_ITEM pBlock)
|
|
{
|
|
unz_global_info szGlobalUnzipInfo;
|
|
|
|
err = unzGetGlobalInfo (szUnzipFile,&szGlobalUnzipInfo);
|
|
|
|
if (err!=UNZ_OK) {
|
|
/* printf("error %d with zipfile in unzGetGlobalInfo \n",err);*/
|
|
}
|
|
for (uiCounter=1;uiCounter<=(uLong)szGlobalUnzipInfo.number_entry;uiCounter++)
|
|
{
|
|
|
|
if (hb___ExtractCurrentFile(szUnzipFile,bExtractPath,
|
|
opt_overwrite, pBlock) != UNZ_OK)
|
|
{
|
|
break;
|
|
}
|
|
if (uiCounter+1<=szGlobalUnzipInfo.number_entry)
|
|
{
|
|
err = unzGoToNextFile(szUnzipFile);
|
|
if (err!=UNZ_OK)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
BOOL hb___unZipFiles(char *szFile,PHB_ITEM pBlock,BOOL bExtractPath)
|
|
{
|
|
const char *szZipFileName=NULL;
|
|
const char *szFilename_to_Extract=NULL;
|
|
|
|
BOOL opt_do_extract=1;
|
|
|
|
int opt_overwrite=0;
|
|
char szFilename_Try[512];
|
|
/* unzFile szUnzipFile=NULL;*/
|
|
|
|
if (szZipFileName == NULL)
|
|
{
|
|
szZipFileName = szFile;
|
|
}
|
|
|
|
if (szZipFileName!=NULL)
|
|
{
|
|
strcpy(szFilename_Try,szZipFileName);
|
|
szUnzipFile = unzOpen(szZipFileName);
|
|
if (szUnzipFile==NULL)
|
|
{
|
|
strcat(szFilename_Try,".zip");
|
|
szUnzipFile = unzOpen(szFilename_Try);
|
|
}
|
|
}
|
|
|
|
if (szUnzipFile==NULL)
|
|
{
|
|
|
|
return -1;
|
|
}
|
|
|
|
if (opt_do_extract)
|
|
{
|
|
if (szFilename_to_Extract == NULL)
|
|
return hb___Extract(szUnzipFile,bExtractPath,opt_overwrite,pBlock);
|
|
else
|
|
return hb___ExtractOneFile(szUnzipFile,szFilename_to_Extract,
|
|
bExtractPath,opt_overwrite,pBlock);
|
|
}
|
|
unzCloseCurrentFile(szUnzipFile);
|
|
|
|
return 1; /* to avoid warning */
|
|
}
|
|
|
|
int hb___ExtractCurrentFile(unzFile szUnzipFile,BOOL popt_extract_without_path,BOOL popt_overwrite,PHB_ITEM pBlock)
|
|
{
|
|
char filename_inzip[256];
|
|
char* filename_withoutpath;
|
|
char* p;
|
|
char NewFileToWrite[256];
|
|
FHANDLE nFileHandle;
|
|
BYTE * szBuffer;
|
|
|
|
|
|
unz_file_info file_info;
|
|
|
|
err=UNZ_OK;
|
|
err = unzGetCurrentFileInfo(szUnzipFile,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
|
|
|
|
if (err!=UNZ_OK)
|
|
{
|
|
return err;
|
|
}
|
|
|
|
Size_Buf = WRITEBUFFERSIZE;
|
|
|
|
szBuffer = (void*) hb_xalloc(Size_Buf);
|
|
if (szBuffer==NULL)
|
|
{
|
|
return UNZ_INTERNALERROR;
|
|
}
|
|
strcpy(NewFileToWrite,filename_inzip);
|
|
p = filename_withoutpath = filename_inzip;
|
|
while ((*p) != '\0')
|
|
{
|
|
if (((*p)=='/') || ((*p)=='\\'))
|
|
filename_withoutpath = p+1;
|
|
p++;
|
|
}
|
|
|
|
if ((*filename_withoutpath)=='\0')
|
|
{
|
|
if (popt_extract_without_path)
|
|
{
|
|
|
|
hb_fsMkDir(filename_inzip);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
char* write_filename;
|
|
int skip=0;
|
|
|
|
if ((popt_extract_without_path)) {
|
|
|
|
write_filename = filename_inzip;
|
|
|
|
}
|
|
else {
|
|
|
|
write_filename = filename_withoutpath;
|
|
|
|
}
|
|
if(pBlock !=NULL){
|
|
|
|
PHB_ITEM pFileName=hb_itemPutC(NULL, (char *)write_filename);
|
|
PHB_ITEM pFilePos=hb_itemPutNI(NULL,uiCounter);
|
|
hb_vmEvalBlockV( pBlock, 2, pFileName, pFilePos );
|
|
hb_itemRelease(pFileName);
|
|
hb_itemRelease(pFilePos);
|
|
}
|
|
|
|
|
|
err = unzOpenCurrentFile(szUnzipFile);
|
|
if (err!=UNZ_OK)
|
|
{
|
|
}
|
|
|
|
|
|
if ((skip==0) && (err==UNZ_OK))
|
|
{
|
|
|
|
nFileHandle=(FHANDLE) hb_fsCreate((char *) write_filename,FC_NORMAL);
|
|
|
|
|
|
/* some zipfile don't contain directory alone before file */
|
|
if ((nFileHandle==-1) && ((popt_extract_without_path)) &&
|
|
(filename_withoutpath!=(char*)filename_inzip))
|
|
{
|
|
char c=*(filename_withoutpath-1);
|
|
*(filename_withoutpath-1)='\0';
|
|
hb___MakeDir((char *)write_filename);
|
|
*(filename_withoutpath-1)=c;
|
|
|
|
nFileHandle=hb_fsCreate((char *)write_filename,FC_NORMAL);
|
|
}
|
|
|
|
}
|
|
|
|
if (nFileHandle!=NULL)
|
|
{
|
|
|
|
do
|
|
{
|
|
err = unzReadCurrentFile(szUnzipFile,szBuffer,Size_Buf);
|
|
if (err<0)
|
|
{
|
|
|
|
break;
|
|
}
|
|
if (err>0)
|
|
|
|
if (hb_fsWrite(nFileHandle,szBuffer,err)==0)
|
|
{
|
|
|
|
err=UNZ_ERRNO;
|
|
break;
|
|
}
|
|
}
|
|
while (err>0);
|
|
|
|
hb_fsClose(nFileHandle);
|
|
if (err==0)
|
|
hb____ChangeFileDate(write_filename,file_info.dosDate,
|
|
file_info.tmu_date);
|
|
}
|
|
|
|
if (err==UNZ_OK)
|
|
{
|
|
err = unzCloseCurrentFile (szUnzipFile);
|
|
if (err!=UNZ_OK)
|
|
{
|
|
|
|
}
|
|
}
|
|
else
|
|
unzCloseCurrentFile(szUnzipFile); /* don't lose the error */
|
|
}
|
|
|
|
hb_xfree((void*)szBuffer);
|
|
return err;
|
|
}
|
|
|
|
|
|
int hb___GetNumbersofFilestoUnzip(char *szFile)
|
|
{
|
|
/*int iNumbersOfFiles;*/
|
|
|
|
const char *szZipFileName=NULL;
|
|
char szFilename_Try[512];
|
|
unz_global_info szGlobalUnzipInfo;
|
|
szZipFileName = szFile;
|
|
/* if (szZipFileName == NULL)
|
|
{
|
|
szZipFileName = szFile;
|
|
}
|
|
*/
|
|
if (szZipFileName!=NULL)
|
|
{
|
|
strcpy(szFilename_Try,szZipFileName);
|
|
szUnzipFile = unzOpen(szZipFileName);
|
|
if (szUnzipFile==NULL)
|
|
{
|
|
strcat(szFilename_Try,".zip");
|
|
szUnzipFile = unzOpen(szFilename_Try);
|
|
}
|
|
}
|
|
|
|
if (szUnzipFile==NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
err = unzGetGlobalInfo (szUnzipFile,&szGlobalUnzipInfo);
|
|
/* if (err==ZIP_OK) {
|
|
iNumbersOfFiles=szGlobalUnzipInfo.number_entry;
|
|
}
|
|
*/
|
|
unzCloseCurrentFile(szUnzipFile);
|
|
|
|
/* return iNumbersOfFiles; to avoid warning */
|
|
return szGlobalUnzipInfo.number_entry;
|
|
}
|
|
|
|
|
|
PHB_ITEM hb___GetFilesNamesFromZip(char *szFile,BOOL iMode)
|
|
{
|
|
const char *szZipFileName=NULL;
|
|
char szFilename_Try[_POSIX_PATH_MAX];
|
|
char szFileNameinZip[_POSIX_PATH_MAX];
|
|
int iNumbersOfFiles;
|
|
|
|
PHB_ITEM pItem=NULL;
|
|
PHB_ITEM pArray=NULL;
|
|
|
|
int uiCount;
|
|
unz_global_info szGlobalUnzipInfo;
|
|
if (szZipFileName == NULL)
|
|
{
|
|
szZipFileName = szFile;
|
|
}
|
|
|
|
if (szZipFileName!=NULL)
|
|
{
|
|
strcpy(szFilename_Try,szZipFileName);
|
|
szUnzipFile = unzOpen(szZipFileName);
|
|
if (szUnzipFile==NULL)
|
|
{
|
|
strcat(szFilename_Try,".zip");
|
|
szUnzipFile = unzOpen(szFilename_Try);
|
|
}
|
|
}
|
|
|
|
if (szUnzipFile==NULL)
|
|
{
|
|
exit(1);
|
|
}
|
|
err = unzGetGlobalInfo (szUnzipFile,&szGlobalUnzipInfo);
|
|
if (err==ZIP_OK) {
|
|
iNumbersOfFiles=(uLong)szGlobalUnzipInfo.number_entry;
|
|
pArray=hb_itemArrayNew( iNumbersOfFiles );
|
|
}
|
|
for(uiCount=0;uiCount<iNumbersOfFiles;uiCount++) {
|
|
unz_file_info file_info;
|
|
err = unzGetCurrentFileInfo(szUnzipFile,&file_info,szFileNameinZip,sizeof(szFileNameinZip),NULL,0,NULL,0);
|
|
if (err!=UNZ_OK)
|
|
{
|
|
break;
|
|
}
|
|
if (iMode)
|
|
{
|
|
|
|
PHB_ITEM pTempArray=hb_itemArrayNew(8);
|
|
char szTime[8];
|
|
char *szMethod;
|
|
char szCRC[8];
|
|
int iRatio=0;
|
|
int iLen;
|
|
int iCount=0;
|
|
int iiCount=0;
|
|
|
|
pItem=hb_itemPutC(NULL,szFileNameinZip);
|
|
hb_itemArrayPut(pTempArray,filePos,pItem);
|
|
hb_itemRelease(pItem);
|
|
|
|
if (file_info.uncompressed_size>0) {
|
|
|
|
pItem=hb_itemPutNL(NULL,file_info.uncompressed_size);
|
|
hb_itemArrayPut(pTempArray,Lenght,pItem);
|
|
hb_itemRelease(pItem);
|
|
pItem=hb_itemPutNL(NULL,file_info.compressed_size);
|
|
hb_itemArrayPut(pTempArray,Size,pItem);
|
|
hb_itemRelease(pItem);
|
|
iRatio=100-((file_info.compressed_size*100)/file_info.uncompressed_size);
|
|
if (iRatio <0){
|
|
iRatio=0;
|
|
}
|
|
pItem=hb_itemPutNL(NULL,iRatio);
|
|
hb_itemArrayPut(pTempArray,Ratio,pItem);
|
|
hb_itemRelease(pItem);
|
|
}
|
|
else {
|
|
pItem=hb_itemPutNL(NULL,file_info.uncompressed_size);
|
|
hb_itemArrayPut(pTempArray,Lenght,pItem);
|
|
hb_itemRelease(pItem);
|
|
pItem=hb_itemPutNL(NULL,file_info.compressed_size);
|
|
hb_itemArrayPut(pTempArray,Size,pItem);
|
|
hb_itemRelease(pItem);
|
|
iRatio=0;
|
|
pItem=hb_itemPutNL(NULL,iRatio);
|
|
hb_itemArrayPut(pTempArray,Ratio,pItem);
|
|
hb_itemRelease(pItem);
|
|
}
|
|
|
|
if (file_info.compression_method==0) {
|
|
szMethod="Stored";
|
|
}
|
|
if (file_info.compression_method==Z_DEFLATED) {
|
|
uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
|
|
if (iLevel==0) {
|
|
szMethod="Defl:N";
|
|
}
|
|
else if (iLevel==1) {
|
|
szMethod="Defl:X";
|
|
}
|
|
else if ((iLevel==2) || (iLevel==3)) {
|
|
szMethod="Defl:F";
|
|
}
|
|
else {
|
|
szMethod="Unknow";
|
|
}
|
|
|
|
pItem=hb_itemPutC(NULL,szMethod);
|
|
hb_itemArrayPut(pTempArray,Method,pItem);
|
|
hb_itemRelease(pItem);
|
|
}
|
|
sprintf(szCRC,"%8.8lx\n",(uLong)file_info.crc);
|
|
|
|
pItem=hb_itemPutCL(NULL,szCRC,8);
|
|
hb_itemArrayPut(pTempArray,Crc32,pItem);
|
|
hb_itemRelease(pItem);
|
|
pItem=hb_itemPutD(NULL, (long)file_info.tmu_date.tm_year ,(long)file_info.tmu_date.tm_mon + 1,(long)file_info.tmu_date.tm_mday);
|
|
hb_itemArrayPut(pTempArray,Date,pItem);
|
|
hb_itemRelease(pItem);
|
|
hb_____GetTime(file_info);
|
|
iLen=strlen(szTempTime);
|
|
|
|
for(iCount=10;iCount<19;iCount++) {
|
|
if( (iCount>10) && (iCount<19)) {
|
|
szTime[iiCount]=szTempTime[iCount];
|
|
iiCount++;
|
|
}
|
|
}
|
|
pItem=hb_itemPutCL(NULL,szTime,8);
|
|
hb_itemArrayPut(pTempArray,Time,pItem);
|
|
hb_itemRelease(pItem);
|
|
hb_itemArrayPut(pArray,uiCount+1,pTempArray);
|
|
hb_itemRelease(pTempArray);
|
|
}
|
|
else {
|
|
|
|
pItem=hb_itemPutC(NULL,szFileNameinZip);
|
|
hb_itemArrayPut(pArray,uiCount+1,pItem);
|
|
hb_itemRelease(pItem);
|
|
|
|
}
|
|
if ((uiCount+1)<iNumbersOfFiles) {
|
|
err = unzGoToNextFile(szUnzipFile);
|
|
if (err!=UNZ_OK) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
unzCloseCurrentFile(szUnzipFile);
|
|
|
|
hb_itemReturn(pArray);
|
|
|
|
}
|
|
void hb_____GetTime(unz_file_info file_info)
|
|
{
|
|
struct tm t;
|
|
t.tm_sec = file_info.tmu_date.tm_sec;
|
|
t.tm_min = file_info.tmu_date.tm_min;
|
|
t.tm_hour = file_info.tmu_date.tm_hour;
|
|
t.tm_mday = file_info.tmu_date.tm_mday;
|
|
t.tm_mon = file_info.tmu_date.tm_mon;
|
|
t.tm_year = file_info.tmu_date.tm_year;
|
|
t.tm_wday = 4;
|
|
t.tm_yday = 0;
|
|
t.tm_isdst = 0;
|
|
strcpy(szTempTime, asctime(&t));
|
|
|
|
}
|