You've already forked FileManager
mirror of
https://github.com/Team-Resurgent/FileManager.git
synced 2026-04-30 10:38:50 -07:00
205 lines
5.6 KiB
C++
205 lines
5.6 KiB
C++
#include "unzipLIBUtils.h"
|
|
|
|
char* unZipBuffer = NULL;
|
|
|
|
// unzipLIB filesystem callbacks
|
|
void* ZipFile_Open(const char* filename, int32_t* size) {
|
|
FILE* f = fopen(filename, "rb");
|
|
fseek(f, 0L, SEEK_END);
|
|
*size = ftell(f);
|
|
rewind(f);
|
|
return (void*)f;
|
|
}
|
|
|
|
void ZipFile_Close(void* p) {
|
|
ZIPFILE* pzf = (ZIPFILE*)p;
|
|
FILE* f = (FILE*)pzf->fHandle;
|
|
|
|
if (f) {
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
int32_t ZipFile_Read(void* p, uint8_t* buffer, int32_t length) {
|
|
ZIPFILE* pzf = (ZIPFILE*)p;
|
|
FILE* f = (FILE*)pzf->fHandle;
|
|
return fread(buffer, 1, length, f);
|
|
}
|
|
|
|
int32_t ZipFile_Seek(void* p, int32_t position, int iType) {
|
|
ZIPFILE* pzf = (ZIPFILE*)p;
|
|
FILE* f = (FILE*)pzf->fHandle;
|
|
long l = 0;
|
|
|
|
if (iType == SEEK_SET) {
|
|
return fseek(f, position, SEEK_SET);
|
|
}
|
|
else if (iType == SEEK_END) {
|
|
return fseek(f, position + pzf->iSize, SEEK_END);
|
|
}
|
|
else { // SEEK_CUR
|
|
l = ftell(f);
|
|
}
|
|
|
|
return fseek(f, l + position, SEEK_CUR);
|
|
}
|
|
|
|
// ExtractCurrentFileWithProgress & helper functions
|
|
char* strrepl(char* Str, size_t BufSiz, char* OldStr, char* NewStr) {
|
|
int OldLen, NewLen;
|
|
char* p, * q;
|
|
|
|
if (NULL == (p = strstr(Str, OldStr))) {
|
|
return Str;
|
|
}
|
|
|
|
OldLen = strlen(OldStr);
|
|
NewLen = strlen(NewStr);
|
|
|
|
if ((strlen(Str) + NewLen - OldLen + 1) > BufSiz) {
|
|
return NULL;
|
|
}
|
|
|
|
memmove(q = p + NewLen, p + OldLen, strlen(p + OldLen) + 1);
|
|
memcpy(p, NewStr, NewLen);
|
|
return q;
|
|
}
|
|
|
|
char* strreplall(char* Str, size_t BufSiz, char* OldStr, char* NewStr) {
|
|
char* ret;
|
|
size_t i;
|
|
|
|
for (i = 0; i < BufSiz; i++) {
|
|
ret = strrepl(Str, BufSiz, OldStr, NewStr);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ExtractCurrentFileWithProgress(UNZIP* zip, const char* dst, bool overwrite) {
|
|
char pathSep[2];
|
|
|
|
// Check if the destination folder ends with an '\\'
|
|
if (*(dst + strlen(dst) - 1) == '\\') *pathSep = '\0';
|
|
else strcpy(pathSep, "\\");
|
|
|
|
char buf[512];
|
|
unz_file_info fi;
|
|
int rc;
|
|
|
|
// Get information about the current file
|
|
rc = zip->getFileInfo(&fi, buf, 512, NULL, 0, NULL, 0);
|
|
if (rc != UNZ_OK) return rc;
|
|
|
|
// Substitute '/' with '\'
|
|
strreplall(buf, 512, "/", "\\");
|
|
|
|
char fileName_InZip[512];
|
|
|
|
// Don't include the drive letter (if present) and the leading '\' (if present)
|
|
if (buf[1] == ':' && buf[2] == '\\') strcpy(fileName_InZip, (buf + 3));
|
|
else if (buf[1] == ':') strcpy(fileName_InZip, (buf + 2));
|
|
else if (buf[0] == '\\') strcpy(fileName_InZip, (buf + 1));
|
|
else strcpy(fileName_InZip, buf);
|
|
|
|
char* fileName_WithOutPath;
|
|
char* pos;
|
|
|
|
pos = (char*)fileName_WithOutPath = (char*)fileName_InZip;
|
|
|
|
// Find filename part (without the path)
|
|
while ((*pos) != '\0') {
|
|
if (((*pos) == '/') || ((*pos) == '\\')) fileName_WithOutPath = (char*)(pos + 1);
|
|
pos++;
|
|
}
|
|
|
|
// Is this a folder?
|
|
if ((*fileName_WithOutPath) == '\0') {
|
|
sprintf(buf, "%s%s%s", dst, pathSep, fileName_InZip);
|
|
strreplall(buf, 512, "/", "\\");
|
|
CreateDirectory(buf, NULL);
|
|
return UNZ_OK;
|
|
}
|
|
|
|
// Do we have a buffer?
|
|
if (unZipBuffer == NULL) {
|
|
if ((unZipBuffer = (char*)malloc(65536)) == NULL) return UNZ_INTERNALERROR;
|
|
}
|
|
|
|
char* writeFileName = fileName_InZip;
|
|
|
|
// Open the current file
|
|
if ((rc = zip->openCurrentFile()) != UNZ_OK) return rc;
|
|
|
|
// Compose file name
|
|
sprintf(buf, "%s%s%s", dst, pathSep, writeFileName);
|
|
|
|
HANDLE file;
|
|
bool skip = false;
|
|
|
|
// Check if file exists?
|
|
if (!overwrite && rc == UNZ_OK) {
|
|
file = CreateFile(buf, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (file != (HANDLE)INVALID_HANDLE_VALUE) {
|
|
CloseHandle(file);
|
|
skip = true;
|
|
}
|
|
}
|
|
|
|
char hold;
|
|
|
|
//Create the file and directories
|
|
if (!skip && rc == UNZ_OK) {
|
|
file = CreateFile(buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (file == (HANDLE)INVALID_HANDLE_VALUE) {
|
|
if (fileName_WithOutPath != (char*)fileName_InZip) {
|
|
hold = *(fileName_WithOutPath - 1);
|
|
*(fileName_WithOutPath - 1) = '\0';
|
|
sprintf(buf, "%s%s%s", overwrite, pathSep, writeFileName);
|
|
CreateDirectory(buf, NULL);
|
|
*(fileName_WithOutPath - 1) = hold;
|
|
sprintf(buf, "%s%s%s", overwrite, pathSep, writeFileName);
|
|
file = CreateFile(buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
}
|
|
}
|
|
|
|
if (file == (HANDLE)INVALID_HANDLE_VALUE) return UNZ_ERRNO;
|
|
}
|
|
|
|
DWORD bytesWritten = 0;
|
|
|
|
// Read and write the current file
|
|
if (file != (HANDLE)INVALID_HANDLE_VALUE) {
|
|
do {
|
|
if ((rc = zip->readCurrentFile((uint8_t*)unZipBuffer, 65536)) < 0) break;
|
|
|
|
if (rc > 0) {
|
|
if (!WriteFile(file, unZipBuffer, (DWORD)rc, &bytesWritten, NULL)) {
|
|
rc = UNZ_ERRNO;
|
|
break;
|
|
}
|
|
else {
|
|
if (CopyProgress::g_copyProgFn) {
|
|
if (!CopyProgress::g_copyProgFn(-(LONGLONG)bytesWritten, NULL, NULL, CopyProgress::g_copyProgUser)) {
|
|
break; // canceled
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while (rc > 0);
|
|
|
|
CloseHandle(file);
|
|
}
|
|
|
|
// Close current file (don't lose the error)
|
|
if (rc == UNZ_OK) rc = zip->closeCurrentFile();
|
|
else zip->closeCurrentFile();
|
|
|
|
return rc;
|
|
}
|
|
|
|
void FreeUnZipBuffer() {
|
|
free(unZipBuffer);
|
|
unZipBuffer = NULL;
|
|
} |