|
How to extract zip file to specific folder path?
|
|
|
|
|
Trying to complie in RAD XE 15, have lots of these errors in Messages:
[BCC32 Error] unzip.cpp(nnn): E2015 Ambiguity between 'Byte' and 'System::Byte'
|
|
|
|
|
I used stdafx.h in the both xzip and xunzip, zip runs perfect but unzip will throw an exception in get first item information. when I remove it and set file configuration as not use precompiled , problem does not reproduce any more. why?
|
|
|
|
|
I am not able to zip or unzip contents more than 2GB.
Is there anway to create a zip with contents for upto 4gb and then unzip the same.
Any help is appreciated.
Thanks,
Seetharam
|
|
|
|
|
|
XUnzip.cpp
FILETIME timet2filetime(time_t timer)
{
struct tm *tm = gmtime(&timer); <<< here
...
gmtime() returns 0, and thereby to process crash
My patch:
struct tm *tm = gmtime(&timer);
if (tm == NULL)
{
time(&timer);
tm = gmtime(&timer);
}
|
|
|
|
|
I create this zip file also by this libary.But why it's successful unzip when only file(s) but failed when contain sub-folder?
urgency!
740176597@qq.com.
|
|
|
|
|
You need to check ZIPENTRY.name for a slash at the end of the item name. If it's found that means you faced a directory. Just skip such item and go to the next one.
Regards.
|
|
|
|
|
Test sample code:
HZIP hz = CreateZip(L"E:\\haha.zip", 0, ZIP_FILENAME);
ZipAdd(hz, L"test.cc", L"e:\\test.cc", 0, ZIP_FILENAME);
AddFolderContent(hz, L"e:\\", L"tmp");
CloseZip(hz);
1. Add Folder UNICODE bug:
In the original version of ZipAdd for adding folder, the unicode(wchar_t) string get no chance to convert to ansi string. Changed version:
char szDest[MAX_PATH * 2];
memset(szDest, 0, sizeof(szDest));
#ifdef _UNICODE
int nActualChars = WideCharToMultiByte(CP_ACP,
0,
(LPCWSTR)dstzn,
-1,
szDest,
MAX_PATH * 2 - 2,
NULL,
NULL);
if (nActualChars == 0)
return ZR_ARGS;
#else
strcpy(szDest, dstzn);
#endif
if (flags == ZIP_FILENAME) {
lasterrorZ = zip->Add(szDest, src, len, flags);
} else {
if (flags == ZIP_FOLDER) {
lasterrorZ = zip->Add(szDest, src, len, flags);
} else {
lasterrorZ = zip->Add((char *)dstzn, src, len, flags);
}
}
2. Add Folder does not add any files bug.
After found a file, the source file parameter call to ZipAdd is wrong, it should not be the relative path but absolute path. Changed version:
else {
TCHAR RelativePathNewFileFound[MAX_PATH] = { 0 };
_tcscpy(RelativePathNewFileFound, DirToAdd);
_tcscat(RelativePathNewFileFound, _T("\\"));
_tcscat(RelativePathNewFileFound, FindFileData.cFileName);
TCHAR AbsoluteSourceFile[MAX_PATH] = { 0 };
PathAppend(AbsoluteSourceFile, AbsolutePath);
PathAppend(AbsoluteSourceFile, RelativePathNewFileFound);
TRACE_IF(LOG_FOLDER_ADD, L"add file %s to the zip file\n", AbsoluteSourceFile);
if (ZipAdd(hZip, RelativePathNewFileFound, AbsoluteSourceFile, 0, ZIP_FILENAME) != ZR_OK) {
return FALSE;
}
}
3. Another minor bug in AddFolderContent is, the while loop should changed to do-while loop, for the FindFirstFile already returned the first valid file. Also, we need to FindClose the find handle if ZipAdd failed.
So the whole code:
BOOL AddFolderContent(HZIP hZip, TCHAR* AbsolutePath, TCHAR* DirToAdd)
{
TRACE_IF(LOG_FOLDER_ADD, L"add folder %s %s to zip file\n", AbsolutePath, DirToAdd);
HANDLE hFind; WIN32_FIND_DATA FindFileData;
TCHAR PathToSearchInto[MAX_PATH] = { 0 };
if (NULL != DirToAdd) {
ZipAdd(hZip, DirToAdd, 0, 0, ZIP_FOLDER);
}
_tcscpy(PathToSearchInto, AbsolutePath);
_tcscat(PathToSearchInto, _T("\\"));
_tcscat(PathToSearchInto, DirToAdd);
_tcscat(PathToSearchInto, _T("\\*"));
hFind = FindFirstFile(PathToSearchInto, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) {
return FALSE;
}
do {
if ((_tcscmp(FindFileData.cFileName, _T(".")) == 0) ||
(_tcscmp(FindFileData.cFileName, _T("..")) == 0))
continue;
if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
TCHAR RelativePathNewDirFound[MAX_PATH] = { 0 };
_tcscat(RelativePathNewDirFound, DirToAdd);
_tcscat(RelativePathNewDirFound, _T("\\"));
_tcscat(RelativePathNewDirFound, FindFileData.cFileName);
if (AddFolderContent(hZip, AbsolutePath, RelativePathNewDirFound) == FALSE) {
FindClose(hFind);
return FALSE;
}
}
else {
TCHAR RelativePathNewFileFound[MAX_PATH] = { 0 };
_tcscpy(RelativePathNewFileFound, DirToAdd);
_tcscat(RelativePathNewFileFound, _T("\\"));
_tcscat(RelativePathNewFileFound, FindFileData.cFileName);
TCHAR AbsoluteSourceFile[MAX_PATH] = { 0 };
PathAppend(AbsoluteSourceFile, AbsolutePath);
PathAppend(AbsoluteSourceFile, RelativePathNewFileFound);
TRACE_IF(LOG_FOLDER_ADD, L"add file %s to the zip file\n", AbsoluteSourceFile);
if (ZipAdd(hZip, RelativePathNewFileFound, AbsoluteSourceFile, 0, ZIP_FILENAME) != ZR_OK) {
FindClose(hFind);
return FALSE;
}
}
} while (FindNextFile(hFind, &FindFileData));
bool hasError = false;
if (GetLastError() != ERROR_NO_MORE_FILES) {
hasError = true;
}
FindClose(hFind); return !hasError;
}
|
|
|
|
|
Hi, I want to use the XUnzip files in a commercial product but this is part of a closed system where the user, for example can only use a browser window. In the background I need to unzip some files and this is done with the help of a console application. The user can never access this command line tool directly but an admin user can. So how to display the Info-Zip licence? It is in the documentation of the command line tool and there is even a command line switch which is showing the license but a non-admin user cannot see this.
Can I use the XUnzip files this way or do I have to show the license even to a normal user?
|
|
|
|
|
Hello everyone,
first of all: thanks for this piece of code, it is really helpful and easy to use.
I unzipped a file containing subfolders. I noticed, that the function
void EnsureDirectory(const TCHAR *rootdir, const TCHAR *dir)
creates the subfolder structure in the current working directory as well as in the target folder. Those temporary directories are not cleaned up afterwards.
As a quick fix, I removed the
CreateDirectory(cd,NULL) call.
My tests still run, everything gets extracted correctly.
Does anyone have a similar experience? Did I forget something?
[Edit]
My tests run, because I didn't expect the Unzip-function to create subfolders. I do this before I call Unzip, that's why it works.
However, rootdir is set to
GetCurrentDirectory(MAX_PATH,rootdir);
when opening the zipfile. It is used in
TUnzip::Unzip(...)
As a bugfix I removed the EnsureDirectoryMethod and create the subfolder structure before I call Unzip on an item.
Best regards,
Markus
P.S.
Environment: Windows7, VS2010 SP1
modified 14-Mar-13 3:49am.
|
|
|
|
|
Hello,
I'm having a similar problem with function UnzipItem.
When the destination is a absolute path and the archive has a subfolder it creates the subfolder in the working dir instead of the destination path and the extraction fails silently.
Must find a way to set rootdir in:
ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags){...}
TUnzip *unz = han->unz;
strcpy(unz->rootdir, "c:/destinationPath/");
lasterrorU = unz->Unzip(index,dst,len,flags);
|
|
|
|
|
really useful,many thanks.
|
|
|
|
|
I've tried everything I can think of but I cannot get the logic to accept anything other than a lliteral as in "some file name" as input for a file to be added to a just created zip file. I have the full path and file name in a CString object and have tried several ways of specifying including (void *)&MyCString for the 3rd parameter of the ZipAdd() function but it always fails. Any idea?
oh well. Shortly after I posted the above I found the solution to my problem:
CString wcString = "Whatever the full path and file name happen to be";
Then:
wcString.GetBuffer() <-- as the 3rd paramter to ZipAdd() works.
Mike - typical white guy.
"Political correctness is a doctrine, fostered by a delusional, illogical minority, and rabidly promoted by an unscrupulous mainstream media, which holds forth the proposition that it is entirely possible to pick up a piece of sh*t by the clean end."
Thomas Mann - "Tolerance becomes a crime when applied to evil."
As American as: hot dogs, apple and Sarah Palin.
modified 21-Jan-13 13:52pm.
|
|
|
|
|
Hi guys,
Thanks for the code. I've tried it and has found and fixed 2 bugs:
1. In BOOL AddFolderContent(HZIP hZip, TCHAR* AbsolutePath, TCHAR* DirToAdd) (it didn't work):
I've fixed as follows:
//Duan fixed bug
CString stPath;
stPath = AbsolutePath;
stPath += RelativePathNewFileFound;
if (ZipAdd(hZip, RelativePathNewFileFound, /*RelativePathNewFileFound*/(TCHAR*)((LPCTSTR)stPath), 0, ZIP_FILENAME) != ZR_OK)
{
return FALSE;
}
2. Bug for Unicode mode for adding a folder in a zip: In ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len, DWORD flags)
I've fixed as follows:
//Duan added || flags == ZIP_FOLDER
if (flags == ZIP_FILENAME || flags == ZIP_FOLDER)
{
char szDest[MAX_PATH*2];
memset(szDest, 0, sizeof(szDest));
#ifdef _UNICODE
// need to convert Unicode dest to ANSI
int nActualChars = WideCharToMultiByte(CP_ACP, // code page
0, // performance and mapping flags
(LPCWSTR) dstzn, // wide-character string
-1, // number of chars in string
szDest, // buffer for new string
MAX_PATH*2-2, // size of buffer
NULL, // default for unmappable chars
NULL); // set when default char used
if (nActualChars == 0)
return ZR_ARGS;
#else
strcpy(szDest, dstzn);
#endif
lasterrorZ = zip->Add(szDest, src, len, flags);
}
else
{
lasterrorZ = zip->Add((char *)dstzn, src, len, flags);
}
Best Regards,
Duan.
|
|
|
|
|
Windows system using this code find subdirectory file didn't work
FindZipItem(hz, _T("toolbar\\bk.bmp"), true, &i, &ze)
change code,work well
int unzLocateFile (unzFile file, const TCHAR *szFileName, int iCaseSensitivity)
{
unz_s* s;
int err;
uLong num_fileSaved;
uLong pos_in_central_dirSaved;
if (file==NULL)
return UNZ_PARAMERROR;
if (_tcslen(szFileName)>=UNZ_MAXFILENAMEINZIP)
return UNZ_PARAMERROR;
char szFileNameA[MAX_PATH];
#ifdef _UNICODE
GetAnsiFileName(szFileName, szFileNameA, MAX_PATH-1);
#else
strcpy(szFileNameA, szFileName);
#endif
int iLen=strlen(szFileNameA);
for (int i=0;i<iLen;i++)
{
if (szFileNameA[i]=='\\')
{
szFileNameA[i]='/';
}
}
s=(unz_s*)file;
if (!s->current_file_ok)
return UNZ_END_OF_LIST_OF_FILE;
num_fileSaved = s->num_file;
pos_in_central_dirSaved = s->pos_in_central_dir;
err = unzGoToFirstFile(file);
while (err == UNZ_OK)
{
char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
unzGetCurrentFileInfo(file,NULL,
szCurrentFileName,sizeof(szCurrentFileName)-1,
NULL,0,NULL,0);
TRACE(_T("%s\t%s"),szCurrentFileName,szFileNameA);
if (unzStringFileNameCompare(szCurrentFileName,szFileNameA,iCaseSensitivity)==0)
return UNZ_OK;
err = unzGoToNextFile(file);
}
s->num_file = num_fileSaved ;
s->pos_in_central_dir = pos_in_central_dirSaved ;
return err;
}
modified 9-Apr-12 7:33am.
|
|
|
|
|
I found a small bug where the file date and time is not correctly set in unzipped file.
Some zip files do not set the date/time of their contained files at all.
So DOS date / time members are zero.
ZRESULT TUnzip::Get(int index,ZIPENTRY *ze)
{ .
.
WORD dostime = (WORD)(ufi.dosDate&0xFFFF);
WORD dosdate = (WORD)((ufi.dosDate>>16)&0xFFFF);
FILETIME ft;
DosDateTimeToFileTime(dosdate,dostime,&ft);
ze->atime=ft; ze->ctime=ft; ze->mtime=ft;
.
.
.
}
DosDateTimeToFileTime fails if dostime and and dosdate is zero.
since ft is not initialized, some random values are inside.
Better:
Initialize ft with current date time.
ZRESULT TUnzip::Get(int index,ZIPENTRY *ze)
{ .
.
WORD dostime = (WORD)(ufi.dosDate&0xFFFF);
WORD dosdate = (WORD)((ufi.dosDate>>16)&0xFFFF);
FILETIME ft;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
DosDateTimeToFileTime(dosdate,dostime,&ft);
ze->atime=ft; ze->ctime=ft; ze->mtime=ft;
.
.
.
}
but anyway: Thanks for sharing the code!
With best regards,
Frank Kobs
Palette CAD GmbH
|
|
|
|
|
UnzipItem may create wrongly read-only files.
I'm calling the function like this:
zr = UnzipItem(hz, index, targetname, 0, ZIP_FILENAME);
The problem occurs when working with zip files, that have not been created with XZip.
For example, I have created zip files with
- Windows-7 Context menu 'Send To' 'Compressed (zipped) Folder'
- Java
- Total Commander 7.56a
- 7-Zip 9.20
In all cases UnzipItem creates wrongly read-only files.
The problem is located in TUnzip::Get when evaluating the so called upper half of the attribute value, which is called standard unix attr in the comment.
In the line, that initializes bool uwritable , what does this comment // ***hd*** mean? Does it mean Hans Dietrich?
I have temporary solved this issue for my use case by commenting out the evaluation of
uwritable<br /> , but I guess this won't work, if I would handle zip files that have been created on a unix machine.
Please advice, any comments are welcome.
I've already posted this issue in 2003, the problem still exist in the latest Version 1.3.
http://www.codeproject.com/Messages/681420/Problem-in-TUnzip-Get-gt-creates-sometimes-read-on.aspx[^]
Thomas Haase
|
|
|
|
|
Generally I don't like to hide warnings by using a global pragma. But I know, this is my personal preference.
But I would like to discuss an alternative solution.
In the past we had solved the related issue by by using _stricmp and _tzset instead of stricmp and tzset .
Are there any arguments against this alternative solution?
Thomas Haase
|
|
|
|
|
There has been a lot of fixes and enhancements posted over the years. Is there an updated version that includes all of these fixes?
|
|
|
|
|
Yes! Version 1.4 would be very welcome!
Thomas Haase
|
|
|
|
|
Where is the 1.4 edition ? thank you
|
|
|
|
|
Bug
The current version of the library when building with _UNICODE defined and using
ZipAdd(zipFile, L"HelloWorld.txt", buffer, sizeof(buffer), ZIP_MEMORY) results in a bug that only the 1st character 'H' of the filename "HelloWorld.txt" gets stored in the zip archive because the cast to (char*)dstzn produces "H\0" as the filename rather than "HelloWorld.txt\0". Reason being the wchar_t is 2 bytes and since 'H' 0x48 is stored as 2 bytes with the 1st byte being NUL 0x00 and the 2nd byte being 'H' 0x48 and in little endian it is stored in RAM as "H\0" 0x48 0x00 hence the cast to (char*) produces a null terminated string "H\0".
The buggy code is in XZip.cpp ZipAdd(...)
if (flags == ZIP_FILENAME)
{
char szDest[MAX_PATH*2];
memset(szDest, 0, sizeof(szDest));
#ifdef _UNICODE
int nActualChars = WideCharToMultiByte(CP_ACP,
0,
(LPCWSTR) dstzn,
-1,
szDest,
MAX_PATH*2-2,
NULL,
NULL);
if (nActualChars == 0)
return ZR_ARGS;
#else
strcpy(szDest, dstzn);
#endif
lasterrorZ = zip->Add(szDest, src, len, flags);
}
else
{
lasterrorZ = zip->Add((char *)dstzn, src, len, flags);
}
Solution
To fix the bug the code should be simplified to this in XZip.cpp ZipAdd(...)
1. Check for invalid dstzn parameter
if (hz == 0)
{
lasterrorZ = ZR_ARGS;
return ZR_ARGS;
}
if (dstzn == NULL)
{
lasterrorZ = ZR_ARGS;
return ZR_ARGS;
}
TZipHandleData *han = (TZipHandleData*)hz;
2. Remove the if/else to always convert the filename regardless of the value of the flags parameter
TZip *zip = han->zip;
char szDest[MAX_PATH*2];
memset(szDest, 0, sizeof(szDest));
#ifdef _UNICODE
int nActualChars = WideCharToMultiByte(CP_ACP,
0,
(LPCWSTR) dstzn,
-1,
szDest,
MAX_PATH*2-2,
NULL,
NULL);
if (nActualChars == 0)
return ZR_ARGS;
#else
strcpy(szDest, dstzn);
#endif
lasterrorZ = zip->Add(szDest, src, len, flags);
return lasterrorZ;
modified 19-Oct-11 16:35pm.
|
|
|
|
|
Hi there:
Tried to use CreateZip with ZIP_FOLDER, but always have an error returned.
I was trying to pack several folders with files underneath into a zip file under an assigned directory.
Can anyone shed a light on how to do that?
Thanks and regards,
Ke
|
|
|
|
|
The problem might be a unicode issue. The ZipAdd function is only handling unicode properly for files and not folders. Solution:
ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len, DWORD flags)
{
...
FROM:
if ( flags == ZIP_FILENAME )
{
TO:
if ( dstzn )
{
...
}
modified on Tuesday, August 23, 2011 8:03 PM
|
|
|
|
|