static int ExtractCurrentFile (unzFile uf, void* buffer, const size_t bufferSize, const char* outPath, const bool skipPaths, const bool overwrite, const char* password) { char filenameInZip[256]; char* filenameWithoutPath; char* fullPath; char* p; FILE *fout; unz_file_info64 fileInfo; if (unzGetCurrentFileInfo64(uf, &fileInfo, filenameInZip, sizeof(filenameInZip), NULL, 0, NULL, 0) != UNZ_OK) { return TRI_ERROR_INTERNAL; } p = filenameWithoutPath = filenameInZip; // get the file name without any path prefix while (*p != '\0') { if (*p == '/' || *p == '\\') { filenameWithoutPath = p + 1; } p++; } // found a directory if (*filenameWithoutPath == '\0') { if (! skipPaths) { fullPath = TRI_Concatenate2File(outPath, filenameInZip); TRI_CreateRecursiveDirectory(fullPath); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); } } // found a file else { const char* writeFilename; if (! skipPaths) { writeFilename = filenameInZip; } else { writeFilename = filenameWithoutPath; } if (unzOpenCurrentFilePassword(uf, password) != UNZ_OK) { return TRI_ERROR_INTERNAL; } // prefix the name from the zip file with the path specified fullPath = TRI_Concatenate2File(outPath, writeFilename); if (! overwrite && TRI_ExistsFile(fullPath)) { return TRI_ERROR_INTERNAL; } // try to write the outfile fout = fopen(fullPath, "wb"); // cannot write to outfile. this may be due to the target directory missing if (fout == NULL && ! skipPaths && filenameWithoutPath != (char*) filenameInZip) { char* d; char c = *(filenameWithoutPath - 1); *(filenameWithoutPath - 1) = '\0'; // create target directory recursively d = TRI_Concatenate2File(outPath, filenameInZip); TRI_CreateRecursiveDirectory(d); TRI_Free(TRI_CORE_MEM_ZONE, d); *(filenameWithoutPath - 1) = c; // try again fout = fopen(fullPath, "wb"); } TRI_Free(TRI_CORE_MEM_ZONE, fullPath); if (fout == NULL) { return TRI_ERROR_CANNOT_WRITE_FILE; } while (true) { int result = unzReadCurrentFile(uf, buffer, bufferSize); if (result < 0) { fclose(fout); return TRI_ERROR_INTERNAL; } if (result > 0) { if (fwrite(buffer, result, 1, fout) != 1) { fclose(fout); return TRI_set_errno(TRI_ERROR_SYS_ERROR); } } else { assert(result == 0); break; } } fclose(fout); } unzCloseCurrentFile(uf); return TRI_ERROR_NO_ERROR; }
static int ExtractCurrentFile(unzFile uf, void* buffer, size_t const bufferSize, char const* outPath, bool const skipPaths, bool const overwrite, char const* password, std::string& errorMessage) { char filenameInZip[256]; char* filenameWithoutPath; char* fullPath; char* p; unz_file_info64 fileInfo; long systemError; int err; // cppcheck-suppress * FILE* fout; filenameInZip[0] = '\0'; err = unzGetCurrentFileInfo64(uf, &fileInfo, filenameInZip, sizeof(filenameInZip), NULL, 0, NULL, 0); if (err != UNZ_OK) { errorMessage = std::string("Failed to get file info for ") + filenameInZip + ": " + std::to_string(err); return TRI_ERROR_INTERNAL; } // adjust file name p = filenameInZip; while (*p != '\0') { #ifdef WIN32 if (*p == '/') { *p = '\\'; } #else if (*p == '\\') { *p = '/'; } #endif ++p; } p = filenameWithoutPath = filenameInZip; // get the file name without any path prefix while (*p != '\0') { if (*p == '/' || *p == '\\' || *p == ':') { filenameWithoutPath = p + 1; } p++; } // found a directory if (*filenameWithoutPath == '\0') { if (!skipPaths) { fullPath = TRI_Concatenate2File(outPath, filenameInZip); int res = TRI_CreateRecursiveDirectory(fullPath, systemError, errorMessage); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_CORE_MEM_ZONE, fullPath); return res; } TRI_Free(TRI_CORE_MEM_ZONE, fullPath); } } // found a file else { char const* writeFilename; if (!skipPaths) { writeFilename = filenameInZip; } else { writeFilename = filenameWithoutPath; } err = unzOpenCurrentFilePassword(uf, password); if (err != UNZ_OK) { errorMessage = "failed to authenticate the password in the zip: " + std::to_string(err); return TRI_ERROR_INTERNAL; } // prefix the name from the zip file with the path specified fullPath = TRI_Concatenate2File(outPath, writeFilename); if (!overwrite && TRI_ExistsFile(fullPath)) { TRI_Free(TRI_CORE_MEM_ZONE, fullPath); errorMessage = std::string("not allowed to overwrite file ") + fullPath; return TRI_ERROR_CANNOT_OVERWRITE_FILE; } // try to write the outfile fout = fopen(fullPath, "wb"); // cannot write to outfile. this may be due to the target directory missing if (fout == nullptr && !skipPaths && filenameWithoutPath != (char*)filenameInZip) { char c = *(filenameWithoutPath - 1); *(filenameWithoutPath - 1) = '\0'; // create target directory recursively char* d = TRI_Concatenate2File(outPath, filenameInZip); int res = TRI_CreateRecursiveDirectory(d, systemError, errorMessage); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_CORE_MEM_ZONE, d); return res; } TRI_Free(TRI_CORE_MEM_ZONE, d); *(filenameWithoutPath - 1) = c; // try again fout = fopen(fullPath, "wb"); } else if (fout == nullptr) { // try to create the target directory recursively char* d = TRI_Concatenate2File(outPath, filenameInZip); // strip filename so we only have the directory name char* dir = TRI_Dirname(d); int res = TRI_CreateRecursiveDirectory(dir, systemError, errorMessage); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_CORE_MEM_ZONE, d); TRI_Free(TRI_CORE_MEM_ZONE, dir); return res; } TRI_Free(TRI_CORE_MEM_ZONE, d); TRI_Free(TRI_CORE_MEM_ZONE, dir); // try again fout = fopen(fullPath, "wb"); } if (fout == NULL) { errorMessage = std::string("failed to open file for writing: ") + fullPath + " - " + strerror(errno); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); return TRI_ERROR_CANNOT_WRITE_FILE; } while (true) { int result = unzReadCurrentFile(uf, buffer, (unsigned int)bufferSize); if (result < 0) { errorMessage = std::string("failed to write file ") + fullPath + " - " + strerror(errno); fclose(fout); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); return TRI_ERROR_CANNOT_WRITE_FILE; } if (result > 0) { if (fwrite(buffer, result, 1, fout) != 1) { errorMessage = std::string("failed to write file ") + fullPath + " - " + strerror(errno); TRI_Free(TRI_CORE_MEM_ZONE, fullPath); fclose(fout); return TRI_set_errno(TRI_ERROR_SYS_ERROR); } } else { TRI_ASSERT(result == 0); break; } } TRI_Free(TRI_CORE_MEM_ZONE, fullPath); fclose(fout); } unzCloseCurrentFile(uf); return TRI_ERROR_NO_ERROR; }