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! */
(*ppArchive)->valJunkSkipMax = kDefaultJunkSkipMax;
(*ppArchive)->valIgnoreLZW2Len = false;
(*ppArchive)->valHandleBadMac = false;
(*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 fadden

View File

@ -52,7 +52,7 @@ static const char* gMonths[] = {
/* file_sys_id values */
static const char* gFileSysIDs[] = {
"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",
"High-Sierra", "ISO 9660", "AppleShare"
};

View File

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

View File

@ -1073,6 +1073,9 @@ bail:
* is cleared explicitly.
*
* 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
Nu_ExpandLZW2(LZWExpandState* lzwState, uint expectedLen,
@ -1486,9 +1489,8 @@ Nu_ExpandLZW(NuArchive* pArchive, const NuRecord* pRecord,
if (!isType2) {
err = Nu_ExpandLZW1(lzwState, rleLen);
} else {
if (pArchive->valIgnoreLZW2Len) {
/* some badly-formed archives need this -- not sure
what's creating them, possibly a Mac program */
if (pRecord->isBadMac || pArchive->valIgnoreLZW2Len) {
/* might be big-endian, might be okay; just ignore it */
lzwLen = (unsigned int) -1;
} else if (lzwState->dataInBuffer < lzwLen) {
/* 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.
*/
#define kNuVersionMajor 2
#define kNuVersionMinor 1
#define kNuVersionBug 1
#define kNuVersionMinor 2
#define kNuVersionBug 0
/*
@ -270,7 +270,8 @@ typedef enum NuValueID {
kNuValueMaskDataless = 11,
kNuValueStripHighASCII = 12,
kNuValueJunkSkipMax = 13,
kNuValueIgnoreLZW2Len = 14
kNuValueIgnoreLZW2Len = 14,
kNuValueHandleBadMac = 15
} NuValueID;
typedef unsigned long NuValue;
@ -461,6 +462,7 @@ typedef struct NuRecord {
unsigned long recHeaderLength; /* size of rec hdr, incl thread hdrs */
unsigned long totalCompLength; /* total len of data in archive file */
long fakeThreads; /* used by "MaskDataless" */
int isBadMac; /* malformed "bad mac" 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 valJunkSkipMax; /* scan this far for header */
NuValue valIgnoreLZW2Len; /* don't verify LZW/II len field */
NuValue valHandleBadMac; /* handle "bad Mac" archives */
/* callback functions */
NuCallback selectionFilterFunc;

View File

@ -43,6 +43,7 @@ Nu_InitRecordContents(NuArchive* pArchive, NuRecord* pRecord)
pRecord->pThreadMods = nil;
pRecord->dirtyHeader = false;
pRecord->dropRecFilename = false;
pRecord->isBadMac = false;
return kNuErrNone;
}
@ -1075,6 +1076,17 @@ Nu_ReadRecordHeader(NuArchive* pArchive, NuRecord* pRecord)
err = Nu_ComputeThreadData(pArchive, pRecord);
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:
if (err != kNuErrNone)
(void)Nu_FreeRecordContents(pArchive, pRecord);

View File

@ -65,6 +65,9 @@ Nu_GetValue(NuArchive* pArchive, NuValueID ident, NuValue* pValue)
case kNuValueIgnoreLZW2Len:
*pValue = pArchive->valIgnoreLZW2Len;
break;
case kNuValueHandleBadMac:
*pValue = pArchive->valHandleBadMac;
break;
default:
err = kNuErrInvalidArg;
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;
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:
Nu_ReportError(NU_BLOB, err, "Unknown ValueID %d requested", ident);
goto bail;