Files
FileManager/unzipLIBUtils.cpp
2025-12-15 00:18:06 -08:00

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;
}