bool CArchive7Zip::GetFile(unsigned fid, std::vector<boost::uint8_t>& buffer) { boost::mutex::scoped_lock lck(archiveLock); CHECK_FILE_ID(fid); // Get 7zip to decompress it size_t offset; size_t outSizeProcessed; SRes res; res = SzAr_Extract(&db, &lookStream.s, fileData[fid].fp, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res == SZ_OK) { buffer.resize(outSizeProcessed); memcpy(&buffer[0], (char*)outBuffer+offset, outSizeProcessed); return true; } else { return false; } }
BOOL main_unpack(CHAR *patch_file, struct MemoryStruct *patch, CHAR *grf) { CHAR mes[256]; CMemInStream memory_stream; CLookToRead lookStream; CSzArEx db; SRes res; ISzAlloc allocImp; ISzAlloc allocTempImp; memory_stream.buf = patch->memory; memory_stream.ptr = memory_stream.buf; memory_stream.size = patch->size; memory_stream.s.Read = &lzma_memory_read; memory_stream.s.Seek = &lzma_memory_seek; sprintf_s(mes, sizeof(mes), "Распаковка: %s...", patch_file); dialog_set_status(mes); LookToRead_CreateVTable(&lookStream, False); lookStream.realStream = &memory_stream.s; LookToRead_Init(&lookStream); allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; SzArEx_Init(&db); res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); if (res == SZ_OK) { UInt32 i; UInt32 blockIndex = 0xFFFFFFFF; Byte *outBuffer = 0; size_t outBufferSize = 0; void *grf_handle; // if we are working with grf we should // open grf-file first if (grf != NULL) { grf_handle = grf_load(grf, TRUE); if (grf_handle == NULL) grf_handle = grf_new(grf, TRUE); if (grf_handle == NULL) { SzArEx_Free(&db, &allocImp); sprintf_s(mes, sizeof(mes), "Невозможно ни открыть, ни создать GRF-файл: %s", grf); dialog_set_status(mes); return RES_FAIL; } } for (i = 0; i < db.db.NumFiles; i++) { BOOL res; size_t offset; size_t outSizeProcessed; CSzFileItem *f = db.db.Files + i; if (!f->IsDir) { res = SzAr_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res != SZ_OK) break; } res = (grf != NULL) ? main_target_grf(grf_handle, (WCHAR *)f->Name, f->IsDir, outBuffer + offset, outSizeProcessed) : main_target_fs((WCHAR *)f->Name, f->IsDir, outBuffer + offset, outSizeProcessed); if (res) { IAlloc_Free(&allocImp, outBuffer); SzArEx_Free(&db, &allocImp); return RES_FAIL; } } // if we're working with grf // close it if (grf != NULL) grf_free(grf_handle); IAlloc_Free(&allocImp, outBuffer); } SzArEx_Free(&db, &allocImp); if (res != SZ_OK) { if (res == SZ_ERROR_UNSUPPORTED) sprintf_s(mes, sizeof(mes), "Ошибка распаковки %s: Архив не поддерживается", patch_file); else if (res == SZ_ERROR_MEM) sprintf_s(mes, sizeof(mes), "Ошибка распаковки %s: Невозможно зарезервировать память", patch_file); else if (res == SZ_ERROR_CRC) sprintf_s(mes, sizeof(mes), "Ошибка распаковки %s: ошибка CRC", patch_file); else sprintf_s(mes, sizeof(mes), "Ошибка распаковки %s: ошибка #%d", patch_file, res); dialog_set_status(mes); return RES_FAIL; } return RES_OK; }
int auxio_load_archive(const char *filename, unsigned char **dataout, int *datasize, int *dataoffset, const char *filetoload, char *outname) { FILE *f; unsigned char idbuf[4]; int filesFound = 0; std::vector<char *> filelist; // list of files we can load in this archive // default case: outname is filename if (outname) { strcpy(outname, filename); } f = fopen(filename, "rb"); if (!f) { return 0; // no good } fread(idbuf, 4, 1, f); fclose(f); // printf("ID bytes %c %c %x %x\n", idbuf[0], idbuf[1], idbuf[2], idbuf[3]); if ((idbuf[0] == 'P') && (idbuf[1] == 'K') && (idbuf[2] == 0x03) && (idbuf[3] == 0x04)) { // it's zip unzFile zipArchive; char file_name[1024]; unz_file_info info; int nlen; int ret = 0; zipArchive = unzOpen(filename); if (!zipArchive) { return 0; } unzGoToFirstFile(zipArchive); for (;;) { if (unzGetCurrentFileInfo(zipArchive, &info, file_name, 1024, NULL, 0, NULL, 0) == UNZ_OK) { if (filetoload != NULL) { if (!strcasecmp(filetoload, file_name)) { int length; unsigned char *buffer; unzOpenCurrentFile(zipArchive); length = info.uncompressed_size; buffer = (unsigned char *)malloc(length); ret = unzReadCurrentFile(zipArchive, buffer, length); if (ret != length) { free(buffer); return 0; } unzCloseCurrentFile(zipArchive); unzClose(zipArchive); *datasize = length; *dataout = buffer; *dataoffset = 0; return 1; } } else { if (checkExtension(file_name)) { char *tmpstr; tmpstr = (char *)malloc(strlen(file_name)+1); strcpy(tmpstr, file_name); // add to the file list filelist.push_back(tmpstr); filesFound++; } } } else { break; } ret = unzGoToNextFile(zipArchive); if (ret == UNZ_END_OF_LIST_OF_FILE) { break; } if (ret != UNZ_OK) { unzClose(zipArchive); return 0; } } unzClose(zipArchive); } else if ((idbuf[0] == '7') && (idbuf[1] == 'z') && (idbuf[2] == 0xbc) && (idbuf[3] == 0xaf)) { // it's 7zip CFileInStream archiveStream; SRes res; CSzArEx db; /* 7z archive database structure */ ISzAlloc allocImp; /* memory functions for main pool */ ISzAlloc allocTempImp; /* memory functions for temporary pool */ archiveStream.File = fopen(filename, "rb"); if (!archiveStream.File) { return 0; } archiveStream.InStream.Read = SzFileReadImp; archiveStream.InStream.Seek = SzFileSeekImp; allocImp.Alloc = SzAlloc; allocImp.Free = SzFree; allocTempImp.Alloc = SzAllocTemp; allocTempImp.Free = SzFreeTemp; // init 7zip internals CrcGenerateTable(); SzArEx_Init(&db); res = SzArEx_Open(&db, &archiveStream.InStream, &allocImp, &allocTempImp); if (res == SZ_OK) { int i; for (i = 0; i < db.db.NumFiles; i++) { CSzFileItem *item = db.db.Files + i; if (!item->IsDirectory) { if (filetoload != NULL) { if (!strcasecmp(filetoload, item->Name)) { UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ size_t offset; size_t outSizeProcessed; res = SzAr_Extract(&db, &archiveStream.InStream, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp); if (res == SZ_OK) { SzArEx_Free(&db, &allocImp); fclose(archiveStream.File); *datasize = (int)outBufferSize; *dataout = (unsigned char *)outBuffer; *dataoffset = (int)offset; return 1; } else { std::cout << "Error extracting 7zip!\n"; } } } if (checkExtension(item->Name)) { char *tmpstr; tmpstr = (char *)malloc(strlen(item->Name)+1); strcpy(tmpstr, item->Name); // add to the file list filelist.push_back(tmpstr); filesFound++; } } } SzArEx_Free(&db, &allocImp); fclose(archiveStream.File); } } else if ((idbuf[0] == 'R') && (idbuf[1] == 'a') && (idbuf[2] == 'r') && (idbuf[3] == '!')) { // it's rar } // if we found any files and weren't forced to load them, handle accordingly if (filesFound) { // only 1 file found, just run it if (filesFound == 1) { char fname[512]; strcpy(fname, filelist[0]); free(filelist[0]); filelist.clear(); strcpy(outname, fname); return auxio_load_archive(filename, dataout, datasize, dataoffset, fname, NULL); } else // multiple files we can handle found, give the user a choice { int sel; char fname[512]; filepicker = create_archselect(); tree = lookup_widget(filepicker, "archtree"); gtk_tree_view_set_fixed_height_mode(GTK_TREE_VIEW (tree), FALSE); g_signal_connect(G_OBJECT(tree), "button_press_event", G_CALLBACK(check_list_double), NULL); // set up our tree store treestore = gtk_tree_store_new(1, G_TYPE_STRING); // attach the store to the tree gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(treestore)); // create a cell renderer using the stock text one renderer = gtk_cell_renderer_text_new(); // create a display column using the renderer column = gtk_tree_view_column_new_with_attributes ("NES file", renderer, "text", 0, NULL); // add the display column and renderer to the tree view gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column); // get the selection object too selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); // add the filenames for (int fn = 0; fn < filelist.size(); fn++) { gtk_tree_store_insert(treestore, &treeiters[fn], NULL, 999999); gtk_tree_store_set(treestore, &treeiters[fn], 0, filelist[fn], -1); } gtk_widget_show(filepicker); run_picker = true; cancelled = false; while (run_picker) { gtk_main_iteration_do(FALSE); } sel = find_current_selection(); gtk_widget_destroy(filepicker); // was something picked? if ((sel != -1) && (!cancelled)) { strcpy(fname, filelist[sel]); } // free all the temp filenames for (int fn = 0; fn < filelist.size(); fn++) { free(filelist[fn]); } // and wipe the vector filelist.clear(); if ((sel != -1) && (!cancelled)) { if (outname) { strcpy(outname, fname); } return auxio_load_archive(filename, dataout, datasize, dataoffset, fname, NULL); } } } return 0; }