/* * CiderPress * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. * See the file LICENSE for distribution terms. */ /* * NuFX archive support. */ #ifndef APP_NUFXARCHIVE_H #define APP_NUFXARCHIVE_H #include "GenericArchive.h" #include "../nufxlib/NufxLib.h" // ideally this wouldn't be here, only in .cpp /* * One file in an NuFX archive. */ class NufxEntry : public GenericEntry { public: NufxEntry(NuArchive* pArchive) : fpArchive(pArchive) {} virtual ~NufxEntry(void) {} NuRecordIdx GetRecordIdx(void) const { return fRecordIdx; } void SetRecordIdx(NuRecordIdx idx) { fRecordIdx = idx; } virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, CString* pErrMsg) const override; virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, CString* pErrMsg) const override; virtual long GetSelectionSerial(void) const override { return fRecordIdx; } virtual bool GetFeatureFlag(Feature feature) const override { if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || feature == kFeatureHasSimpleAccess) { return false; } else { return true; } } /* * Analyzes the contents of a record to determine if it's a disk, file, * or "other". Computes the total compressed and uncompressed lengths * of all data threads. Fills out several GenericEntry fields. */ void AnalyzeRecord(const NuRecord* pRecord); friend class NufxArchive; private: /* * Find info for the thread we're about to extract. * * Given the NuRecordIdx stored in the object, find the thread whose * ThreadID matches "which". Copies the NuThread structure into * "*pThread". * * On entry *pErrMsg must be an empty string. On failure, it will * contain an error message describing the problem. */ void FindThreadInfo(int which, NuThread* pThread, CString* pErrMsg) const; NuRecordIdx fRecordIdx; // unique record index NuArchive* fpArchive; }; /* * A generic archive plus NuFX-specific goodies. */ class NufxArchive : public GenericArchive { public: NufxArchive(void) : fpArchive(NULL), fIsReadOnly(false), fProgressAsRecompress(false), fNumAdded(-1), fpMsgWnd(NULL), fpAddOpts(NULL) {} virtual ~NufxArchive(void) { (void) Close(); } /* * Perform one-time initialization of the NufxLib library. * * Returns with an error if the NufxLib version is off. Major version must * match (since it indicates an interface change), minor version must be * >= what we expect (in case we're relying on recent behavior changes). * * Returns 0 on success, nonzero on error. */ static CString AppInit(void); /* * Finish instantiating a NufxArchive object by opening an existing file. */ virtual OpenResult Open(const WCHAR* filename, bool readOnly, CString* pErrMsg) override; /* * Finish instantiating a NufxArchive object by creating a new archive. * * Returns an error string on failure, or "" on success. */ virtual CString New(const WCHAR* filename, const void* options) override; virtual CString Flush(void) override { return ""; } virtual CString Reload(void) override; virtual bool IsReadOnly(void) const override { return fIsReadOnly; }; virtual bool IsModified(void) const override { return false; } virtual CString GetDescription() const override { return L"NuFX"; } virtual bool BulkAdd(ActionProgressDialog* pActionProgress, const AddFilesDialog* pAddOpts) override; virtual bool AddDisk(ActionProgressDialog* pActionProgress, const AddFilesDialog* pAddOpts) override; virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, const WCHAR* newName) override { ASSERT(false); return false; } virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) override; virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) override; virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) override; virtual CString TestPathName(const GenericEntry* pGenericEntry, const CString& basePath, const CString& newName, char newFssep) const override; virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, const WCHAR* newName) override { ASSERT(false); return false; } virtual CString TestVolumeName(const DiskFS* pDiskFS, const WCHAR* newName) const override { ASSERT(false); return L"!"; } virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, const RecompressOptionsDialog* pRecompOpts) override; virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) override; virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, CString* pStr) override; virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, const CString& str) override; virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) override; virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, const FileProps* pProps) override; virtual void PreferencesChanged(void) override; virtual long GetCapability(Capability cap) override; // try not to use this NuArchive* GetNuArchivePointer(void) const { return fpArchive; } // determine whether a particular type of compression is supported static bool IsCompressionSupported(NuThreadFormat format); // convert from DateTime format to time_t static time_t DateTimeToSeconds(const NuDateTime* pDateTime); private: virtual CString Close(void) { if (fpArchive != NULL) { LOGI("Closing archive (aborting any un-flushed changes)"); NuAbort(fpArchive); NuClose(fpArchive); fpArchive = NULL; } return L""; } // recompress one thread bool RecompressThread(NufxEntry* pEntry, int threadKind, const RecompressOptionsDialog* pRecompOpts, long* pSizeInMemory, CString* pErrMsg); virtual void XferPrepare(const XferFileOptions* pXferOpts) override; virtual CString XferFile(LocalFileDetails* pDetails, uint8_t** pDataBuf, long dataLen, uint8_t** pRsrcBuf, long rsrcLen) override; virtual void XferAbort(CWnd* pMsgWnd) override; virtual void XferFinish(CWnd* pMsgWnd) override; virtual ArchiveKind GetArchiveKind(void) override { return kArchiveNuFX; } // prepare to add files void AddPrep(CWnd* pWnd, const AddFilesDialog* pAddOpts); /* * Reset some things after we finish adding files. We don't necessarily * want these to stay in effect for other operations, e.g. extracting. */ void AddFinish(void); virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, LocalFileDetails* pDetails) override; /* * Error handler callback for "bulk" adds. */ static NuResult BulkAddErrorHandler(NuArchive* pArchive, void* vErrorStatus); /* * Decide whether or not to replace an existing file (during extract) * or record (during add). */ NuResult HandleReplaceExisting(const NuErrorStatus* pErrorStatus); /* * A file that used to be there isn't anymore. * * This should be exceedingly rare. */ NuResult HandleAddNotFound(const NuErrorStatus* pErrorStatus); /* * Load the contents of an archive into the GenericEntry/NufxEntry list. */ NuError LoadContents(void); /* * Reload the contents of the archive, showing an error message if the * reload fails. */ NuError InternalReload(CWnd* pMsgWnd); /* * Static callback function. Used for scanning the contents of an archive. */ static NuResult ContentFunc(NuArchive* pArchive, void* vpRecord); /* * Set some standard callbacks and feature flags. */ NuError SetCallbacks(void); // handle progress update messages static NuResult ProgressUpdater(NuArchive* pArchive, void* vpProgress); // handle error and debug messages from NufxLib. static NuResult NufxErrorMsgHandler(NuArchive* pArchive, void* vErrorMessage); // handle a DataSource resource release request; used for memory allocated // with new[] static NuResult ArrayDeleteHandler(NuArchive* pArchive, void* ptr); NuArchive* fpArchive; bool fIsReadOnly; bool fProgressAsRecompress; // tweak progress updater /* state while adding files */ int fNumAdded; CWnd* fpMsgWnd; const AddFilesDialog* fpAddOpts; }; #endif /*APP_NUFXARCHIVE_H*/