Automatically detect and handle "bad Mac" archives.

This commit is contained in:
Andy McFadden 2007-02-19 22:37:59 +00:00
parent 8aab8caff1
commit 56379e1db4
9 changed files with 45 additions and 9 deletions

View File

@ -97,6 +97,7 @@ Nu_NuArchiveNew(NuArchive** ppArchive)
/* bug: this can't be set by application! */ /* bug: this can't be set by application! */
(*ppArchive)->valJunkSkipMax = kDefaultJunkSkipMax; (*ppArchive)->valJunkSkipMax = kDefaultJunkSkipMax;
(*ppArchive)->valIgnoreLZW2Len = false; (*ppArchive)->valIgnoreLZW2Len = false;
(*ppArchive)->valHandleBadMac = false;
(*ppArchive)->messageHandlerFunc = gNuGlobalErrorMessageHandler; (*ppArchive)->messageHandlerFunc = gNuGlobalErrorMessageHandler;

View File

@ -1,3 +1,9 @@
2007/02/19 fadden
- Auto-detect and handle "bad Mac" archives.
2006/12/02 fadden
- Check for overrun when unpacking RLE.
2006/02/18 ***** v2.1.1 shipped ***** 2006/02/18 ***** v2.1.1 shipped *****
2006/02/18 fadden 2006/02/18 fadden

View File

@ -52,7 +52,7 @@ static const char* gMonths[] = {
/* file_sys_id values */ /* file_sys_id values */
static const char* gFileSysIDs[] = { static const char* gFileSysIDs[] = {
"Reserved/unknown ($00)", "ProDOS/SOS", "DOS 3.3", "DOS 3.2", "Reserved/unknown ($00)", "ProDOS/SOS", "DOS 3.3", "DOS 3.2",
"Apple II Pascal", "Macintosh (MFS)", "Macintosh (HFS)", "Apple II Pascal", "Macintosh (HFS)", "Macintosh (MFS)",
"LISA file system", "Apple CP/M", "Reserved 0x09", "MS-DOS", "LISA file system", "Apple CP/M", "Reserved 0x09", "MS-DOS",
"High-Sierra", "ISO 9660", "AppleShare" "High-Sierra", "ISO 9660", "AppleShare"
}; };

View File

@ -838,9 +838,10 @@ Nu_LZCPutcCRC(LZCState* pLzcState, char c)
{ {
NuError err; NuError err;
err = Nu_FunnelWrite(pLzcState->pArchive, pLzcState->pFunnel, &c, 1); err = Nu_FunnelWrite(pLzcState->pArchive, pLzcState->pFunnel,
(uchar*) &c, 1);
if (pLzcState->doCalcCRC) if (pLzcState->doCalcCRC)
pLzcState->crc = Nu_CalcCRC16(pLzcState->crc, &c, 1); pLzcState->crc = Nu_CalcCRC16(pLzcState->crc, (uchar*) &c, 1);
return err; return err;
} }

View File

@ -1073,6 +1073,9 @@ bail:
* is cleared explicitly. * is cleared explicitly.
* *
* Reads from lzwState->dataPtr, writes to lzwState->lzwOutBuf. * Reads from lzwState->dataPtr, writes to lzwState->lzwOutBuf.
*
* In some cases, "expectedInputUsed" will be -1 to indicate that the
* value is not known.
*/ */
static NuError static NuError
Nu_ExpandLZW2(LZWExpandState* lzwState, uint expectedLen, Nu_ExpandLZW2(LZWExpandState* lzwState, uint expectedLen,
@ -1486,9 +1489,8 @@ Nu_ExpandLZW(NuArchive* pArchive, const NuRecord* pRecord,
if (!isType2) { if (!isType2) {
err = Nu_ExpandLZW1(lzwState, rleLen); err = Nu_ExpandLZW1(lzwState, rleLen);
} else { } else {
if (pArchive->valIgnoreLZW2Len) { if (pRecord->isBadMac || pArchive->valIgnoreLZW2Len) {
/* some badly-formed archives need this -- not sure /* might be big-endian, might be okay; just ignore it */
what's creating them, possibly a Mac program */
lzwLen = (unsigned int) -1; lzwLen = (unsigned int) -1;
} else if (lzwState->dataInBuffer < lzwLen) { } else if (lzwState->dataInBuffer < lzwLen) {
/* rare -- GSHK will do this if you don't let it finish */ /* rare -- GSHK will do this if you don't let it finish */

View File

@ -32,8 +32,8 @@ extern "C" {
* fixes. Unless, of course, your code depends upon that fix. * fixes. Unless, of course, your code depends upon that fix.
*/ */
#define kNuVersionMajor 2 #define kNuVersionMajor 2
#define kNuVersionMinor 1 #define kNuVersionMinor 2
#define kNuVersionBug 1 #define kNuVersionBug 0
/* /*
@ -270,7 +270,8 @@ typedef enum NuValueID {
kNuValueMaskDataless = 11, kNuValueMaskDataless = 11,
kNuValueStripHighASCII = 12, kNuValueStripHighASCII = 12,
kNuValueJunkSkipMax = 13, kNuValueJunkSkipMax = 13,
kNuValueIgnoreLZW2Len = 14 kNuValueIgnoreLZW2Len = 14,
kNuValueHandleBadMac = 15
} NuValueID; } NuValueID;
typedef unsigned long NuValue; typedef unsigned long NuValue;
@ -461,6 +462,7 @@ typedef struct NuRecord {
unsigned long recHeaderLength; /* size of rec hdr, incl thread hdrs */ unsigned long recHeaderLength; /* size of rec hdr, incl thread hdrs */
unsigned long totalCompLength; /* total len of data in archive file */ unsigned long totalCompLength; /* total len of data in archive file */
long fakeThreads; /* used by "MaskDataless" */ long fakeThreads; /* used by "MaskDataless" */
int isBadMac; /* malformed "bad mac" header */
long fileOffset; /* file offset of record header */ long fileOffset; /* file offset of record header */

View File

@ -157,6 +157,7 @@ struct NuArchive {
NuValue valStripHighASCII; /* during EOL conv, strip hi bit? */ NuValue valStripHighASCII; /* during EOL conv, strip hi bit? */
NuValue valJunkSkipMax; /* scan this far for header */ NuValue valJunkSkipMax; /* scan this far for header */
NuValue valIgnoreLZW2Len; /* don't verify LZW/II len field */ NuValue valIgnoreLZW2Len; /* don't verify LZW/II len field */
NuValue valHandleBadMac; /* handle "bad Mac" archives */
/* callback functions */ /* callback functions */
NuCallback selectionFilterFunc; NuCallback selectionFilterFunc;

View File

@ -43,6 +43,7 @@ Nu_InitRecordContents(NuArchive* pArchive, NuRecord* pRecord)
pRecord->pThreadMods = nil; pRecord->pThreadMods = nil;
pRecord->dirtyHeader = false; pRecord->dirtyHeader = false;
pRecord->dropRecFilename = false; pRecord->dropRecFilename = false;
pRecord->isBadMac = false;
return kNuErrNone; return kNuErrNone;
} }
@ -1075,6 +1076,17 @@ Nu_ReadRecordHeader(NuArchive* pArchive, NuRecord* pRecord)
err = Nu_ComputeThreadData(pArchive, pRecord); err = Nu_ComputeThreadData(pArchive, pRecord);
BailError(err); BailError(err);
/* check for "bad Mac" archives */
if (pArchive->valHandleBadMac) {
if (pRecord->recFileSysInfo == '?' &&
pRecord->recFileSysID == kNuFileSysMacMFS)
{
DBUG(("--- using 'bad mac' handling\n"));
pRecord->isBadMac = true;
pRecord->recFileSysInfo = ':';
}
}
bail: bail:
if (err != kNuErrNone) if (err != kNuErrNone)
(void)Nu_FreeRecordContents(pArchive, pRecord); (void)Nu_FreeRecordContents(pArchive, pRecord);

View File

@ -65,6 +65,9 @@ Nu_GetValue(NuArchive* pArchive, NuValueID ident, NuValue* pValue)
case kNuValueIgnoreLZW2Len: case kNuValueIgnoreLZW2Len:
*pValue = pArchive->valIgnoreLZW2Len; *pValue = pArchive->valIgnoreLZW2Len;
break; break;
case kNuValueHandleBadMac:
*pValue = pArchive->valHandleBadMac;
break;
default: default:
err = kNuErrInvalidArg; err = kNuErrInvalidArg;
Nu_ReportError(NU_BLOB, err, "Unknown ValueID %d requested", ident); Nu_ReportError(NU_BLOB, err, "Unknown ValueID %d requested", ident);
@ -197,6 +200,14 @@ Nu_SetValue(NuArchive* pArchive, NuValueID ident, NuValue value)
} }
pArchive->valIgnoreLZW2Len = value; pArchive->valIgnoreLZW2Len = value;
break; break;
case kNuValueHandleBadMac:
if (value != true && value != false) {
Nu_ReportError(NU_BLOB, err,
"Invalid kNuValueHandleBadMac value %ld", value);
goto bail;
}
pArchive->valHandleBadMac = value;
break;
default: default:
Nu_ReportError(NU_BLOB, err, "Unknown ValueID %d requested", ident); Nu_ReportError(NU_BLOB, err, "Unknown ValueID %d requested", ident);
goto bail; goto bail;