HANDLE ComicBookRAR::openRar(RAROpenArchiveDataEx *flags, RARHeaderDataEx *header, wxUint8 mode) { HANDLE rarFile; memset(flags, 0, sizeof(*flags)); #ifdef wxUSE_UNICODE #ifdef __WXOSX__ const char *filenameData = filename.fn_str().data(); flags->ArcName = new char[strlen(filenameData) + 1]; strcpy(flags->ArcName, filenameData); #else flags->ArcNameW = new wchar_t[filename.Length() + 1]; wcscpy(flags->ArcNameW, filename.c_str()); #endif #else // ASCII flags->ArcName = new char[filename.Length() + 1]; strcpy(flags->ArcName, filename.c_str()); #endif flags->CmtBuf = NULL; flags->OpenMode = mode; rarFile = RAROpenArchiveEx(flags); if (flags->OpenResult != 0) { closeRar(rarFile, flags); throw ArchiveException(filename, OpenArchiveError(flags->OpenResult)); } header->CmtBuf = NULL; return rarFile; }
bool ComicBookRAR::TestPassword() { HANDLE rarFile; int RHCode = 0, PFCode = 0; struct RARHeaderDataEx header; struct RAROpenArchiveDataEx flags; bool passwordCorrect = true; if (Pages.size() == 0) // nothing in the archive to open return true; wxString page = Pages.at(0)->Filename; // test using the first page rarFile = openRar(&flags, &header, RAR_OM_EXTRACT); if (password) RARSetPassword(rarFile, password); while ((RHCode = RARReadHeaderEx(rarFile, &header)) == 0) { if (page.Cmp(header.FileNameW) == 0) { break; } else { if ((PFCode = RARProcessFile(rarFile, RAR_SKIP, NULL, NULL)) != 0) { closeRar(rarFile, &flags); throw ArchiveException(filename, ProcessFileError(PFCode, page)); } } } if (RHCode != 0) { closeRar(rarFile, &flags); throw new ArchiveException(filename, OpenArchiveError(RHCode)); } RARSetCallback(rarFile, TestPasswordCallbackProc, (long) &passwordCorrect); PFCode = RARProcessFile(rarFile, RAR_TEST, NULL, NULL); closeRar(rarFile, &flags); // If the password is wrong, RARProcessFile will return ERAR_BAD_DATA. Of // course, it will also return ERAR_BAD_DATA when the first file in the archive // is corrupted. How does one tell the difference? if (PFCode == ERAR_BAD_DATA) return false; return passwordCorrect; }
HANDLE ComicBookRAR::openRar(RAROpenArchiveDataEx *flags, RARHeaderDataEx *header, wxUint8 mode) { HANDLE rarFile; memset(flags, 0, sizeof(*flags)); flags->ArcNameW = const_cast<wchar_t*>(filename.wc_str()); flags->CmtBuf = NULL; flags->OpenMode = mode; rarFile = RAROpenArchiveEx(flags); if (flags->OpenResult != 0) { closeRar(rarFile, flags); throw ArchiveException(filename, OpenArchiveError(flags->OpenResult)); } header->CmtBuf = NULL; return rarFile; }
wxInputStream * ComicBookRAR::ExtractStream(wxUint32 pageindex) { HANDLE rarFile; int RHCode = 0, PFCode = 0; struct RARHeaderDataEx header; struct RAROpenArchiveDataEx flags; wxString page = Filenames->Item(pageindex); size_t length = 0; rarFile = openRar(&flags, &header, RAR_OM_EXTRACT); if (password) RARSetPassword(rarFile, password); while ((RHCode = RARReadHeaderEx(rarFile, &header)) == 0) { #ifdef wxUSE_UNICODE if (page.IsSameAs(wxString(header.FileNameW))) { #else // ASCII if (page.IsSameAs(header.FileName)) { #endif length = header.UnpSize; break; } else { if ((PFCode = RARProcessFile(rarFile, RAR_SKIP, NULL, NULL)) != 0) { closeRar(rarFile, &flags); throw ArchiveException(filename, ProcessFileError(PFCode, page)); } } } if (length == 0) { // archived file not found closeRar(rarFile, &flags); throw new ArchiveException(filename, page + wxT(" not found in this archive.")); } if (RHCode) { closeRar(rarFile, &flags); throw new ArchiveException(filename, OpenArchiveError(PFCode)); } wxUint8 *buffer = new wxUint8[length]; wxUint8 *callBackBuffer = buffer; RARSetCallback(rarFile, CallbackProc, (long) &callBackBuffer); PFCode = RARProcessFile(rarFile, RAR_TEST, NULL, NULL); closeRar(rarFile, &flags); if (PFCode != 0) throw new ArchiveException(filename, ProcessFileError(PFCode, page)); return new wxMemoryInputStream(buffer, length); } bool ComicBookRAR::TestPassword() { HANDLE rarFile; int RHCode = 0, PFCode = 0; struct RARHeaderDataEx header; struct RAROpenArchiveDataEx flags; bool passwordCorrect = true; wxString page = Filenames->Item(0); // test using the first page rarFile = openRar(&flags, &header, RAR_OM_EXTRACT); if (password) RARSetPassword(rarFile, password); while ((RHCode = RARReadHeaderEx(rarFile, &header)) == 0) { #ifdef wxUSE_UNICODE if (page.IsSameAs(wxString(header.FileNameW))) { #else // ASCII if (page.IsSameAs(header.FileName)) { #endif break; } else { if ((PFCode = RARProcessFile(rarFile, RAR_SKIP, NULL, NULL)) != 0) { closeRar(rarFile, &flags); throw ArchiveException(filename, ProcessFileError(PFCode, page)); } } } if (RHCode != 0) { closeRar(rarFile, &flags); throw new ArchiveException(filename, OpenArchiveError(RHCode)); } RARSetCallback(rarFile, TestPasswordCallbackProc, (long) &passwordCorrect); PFCode = RARProcessFile(rarFile, RAR_TEST, NULL, NULL); closeRar(rarFile, &flags); // If the password is wrong, RARProcessFile will return ERAR_BAD_DATA. Of // course, it will also return ERAR_BAD_DATA when the first file in the archive // is corrupted. How does one tell the difference? if (PFCode == ERAR_BAD_DATA) return false; return passwordCorrect; } wxString ComicBookRAR::OpenArchiveError(int Error) { wxString prefix = wxT("Could not open ") + filename; switch(Error) { case ERAR_NO_MEMORY: return wxString(prefix + wxT(": out of memory")); case ERAR_EOPEN: return prefix; case ERAR_BAD_ARCHIVE: return wxString(prefix + wxT(": it is not a valid RAR archive")); case ERAR_BAD_DATA: return wxString(prefix + wxT(": archive header broken")); case ERAR_UNKNOWN: return wxString(prefix + wxT(": unknown error")); default: return prefix; } }