mirror of
https://github.com/MacPaw/XADMaster.git
synced 2025-08-29 03:23:48 +02:00
584 lines
13 KiB
C
Executable file
584 lines
13 KiB
C
Executable file
#ifndef XADMASTER_LHF_C
|
|
#define XADMASTER_LHF_C
|
|
|
|
/* $Id: LhF.c,v 1.7 2005/06/23 14:54:41 stoecker Exp $
|
|
LhF file archiver client
|
|
|
|
XAD library system for archive handling
|
|
Copyright (C) 1998 and later by Dirk Stöcker <soft@dstoecker.de>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
|
|
#include "../unix/xadClient.h"
|
|
|
|
#ifndef XADMASTERVERSION
|
|
#define XADMASTERVERSION 8
|
|
#endif
|
|
|
|
XADCLIENTVERSTR("LhF 1.1 (22.2.2004)")
|
|
|
|
#define LHF_VERSION 1
|
|
#define LHF_REVISION 1
|
|
|
|
struct LhFData {
|
|
xadUINT8 Comment;
|
|
xadUINT8 Protection;
|
|
xadUINT16 NameSize;
|
|
xadUINT32 CrunchSize;
|
|
xadUINT32 Size;
|
|
xadUINT32 Date;
|
|
};
|
|
|
|
XADGETINFO(LhF)
|
|
{
|
|
xadINT32 err, num = 1, i;
|
|
xadUINT32 data[2];
|
|
struct LhFData ld;
|
|
struct xadFileInfo *fi = 0, *fi2;
|
|
|
|
if((err = xadHookAccess(XADM XADAC_READ, 8, data, ai)))
|
|
return err;
|
|
while(!err && ai->xai_InPos < ai->xai_InSize && ai->xai_InPos < data[1])
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, sizeof(struct LhFData), &ld, ai)))
|
|
{
|
|
if((fi2 = (struct xadFileInfo *) xadAllocObject(XADM XADOBJ_FILEINFO,
|
|
XAD_OBJNAMESIZE, ld.NameSize+1, TAG_DONE)))
|
|
{
|
|
if(!(err = xadHookAccess(XADM XADAC_READ, ld.NameSize, fi2->xfi_FileName, ai)))
|
|
{
|
|
struct xadDate xd;
|
|
if(ld.Comment)
|
|
{
|
|
xadSTRPTR a;
|
|
|
|
for(a = fi2->xfi_FileName; *a; ++a)
|
|
;
|
|
fi2->xfi_Comment = ++a;
|
|
}
|
|
fi2->xfi_DataPos = ai->xai_InPos;
|
|
fi2->xfi_EntryNumber = num++;
|
|
if(ld.Size == 0xFFFFFFFF)
|
|
fi2->xfi_Flags |= XADFIF_DIRECTORY;
|
|
else if(!ld.Size)
|
|
{
|
|
fi2->xfi_Size = fi2->xfi_CrunchSize = ld.CrunchSize;
|
|
fi2->xfi_PrivateInfo = (xadPTR) 1;
|
|
}
|
|
else
|
|
{
|
|
fi2->xfi_Size = ld.Size;
|
|
fi2->xfi_CrunchSize = ld.CrunchSize;
|
|
}
|
|
fi2->xfi_Protection = ld.Protection;
|
|
fi2->xfi_Flags |= XADFIF_SEEKDATAPOS;
|
|
i = ld.Date;
|
|
xd.xd_Second = i&63; i >>= 6;
|
|
xd.xd_Minute = i&63; i >>= 6;
|
|
xd.xd_Hour = i&31; i >>= 5;
|
|
xd.xd_Day = (1 + i)&31; i >>= 5;
|
|
xd.xd_Month = i&15; i >>= 4;
|
|
xd.xd_Year = 1976 + i;
|
|
xd.xd_Micros = 0;
|
|
xadConvertDates(XADM XAD_DATEXADDATE, &xd, XAD_GETDATEXADDATE,
|
|
&fi2->xfi_Date, TAG_DONE);
|
|
err = xadHookAccess(XADM XADAC_INPUTSEEK, ld.CrunchSize, 0, ai);
|
|
}
|
|
|
|
if(!err)
|
|
{
|
|
if(fi)
|
|
fi->xfi_Next = fi2;
|
|
else
|
|
ai->xai_FileInfo = fi2;
|
|
fi = fi2;
|
|
}
|
|
else
|
|
xadFreeObjectA(XADM fi2, 0);
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
}
|
|
if(err)
|
|
{
|
|
ai->xai_Flags |= XADAIF_FILECORRUPT;
|
|
ai->xai_LastError = err;
|
|
}
|
|
|
|
return fi ? 0 : XADERR_ILLEGALDATA;
|
|
}
|
|
|
|
XADRECOGDATA(LhF)
|
|
{
|
|
if(((xadUINT32 *)data)[0] == 0x4C684600)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#define LHFWINDOWSIZE 0x8000
|
|
|
|
struct LhFDecrunch {
|
|
xadINT16 backstack[20];
|
|
xadINT16 stackdata[256];
|
|
xadINT32 leftwinsize;
|
|
xadSTRPTR windowpos;
|
|
xadSTRPTR sourcebuf;
|
|
xadUINT32 sourcelen;
|
|
xadINT16 data0[16];
|
|
xadINT8 data1[20];
|
|
xadINT8 data2[2560];
|
|
xadINT16 data3[4098];
|
|
|
|
xadINT32 numbits;
|
|
xadUINT32 bitbuf;
|
|
xadUINT16 err;
|
|
struct xadArchiveInfo *ai;
|
|
struct xadMasterBase *xadMasterBase;
|
|
xadUINT8 inbuffer[LHFWINDOWSIZE];
|
|
xadINT8 outbuffer[256*2+LHFWINDOWSIZE+6];
|
|
};
|
|
|
|
static xadUINT16 LHFgetc(struct LhFDecrunch *lhd)
|
|
{
|
|
xadUINT16 a;
|
|
if(lhd->sourcelen < 2 || lhd->err)
|
|
return 0;
|
|
if(lhd->sourcebuf == (xadSTRPTR) lhd->inbuffer + LHFWINDOWSIZE)
|
|
{
|
|
xadUINT32 i;
|
|
struct xadMasterBase *xadMasterBase = lhd->xadMasterBase;
|
|
|
|
if((i = lhd->sourcelen) > LHFWINDOWSIZE)
|
|
i = LHFWINDOWSIZE;
|
|
|
|
if((lhd->err = xadHookAccess(XADM XADAC_READ, i, lhd->inbuffer, lhd->ai)))
|
|
return 0;
|
|
lhd->sourcebuf = (xadSTRPTR) lhd->inbuffer;
|
|
}
|
|
|
|
lhd->sourcelen -= 2;
|
|
a = *(lhd->sourcebuf++) << 8;
|
|
a += *(lhd->sourcebuf++);
|
|
|
|
return a;
|
|
}
|
|
|
|
/* Neue Bytes von rechts herein, Daten links abgreifen */
|
|
static xadUINT16 LHFgetbits(struct LhFDecrunch *lhd, xadUINT32 bits)
|
|
{
|
|
xadUINT16 r;
|
|
|
|
r = lhd->bitbuf >> (32-bits);
|
|
lhd->numbits += bits;
|
|
if(lhd->numbits < 0)
|
|
lhd->bitbuf <<= bits;
|
|
else
|
|
{
|
|
bits -= lhd->numbits;
|
|
lhd->bitbuf <<= bits;
|
|
lhd->bitbuf |= LHFgetc(lhd);
|
|
lhd->bitbuf <<= lhd->numbits;
|
|
lhd->numbits -= 16;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
static xadINT32 LHFflush(struct LhFDecrunch *lhd)
|
|
{
|
|
xadINT32 i, j, err;
|
|
struct xadMasterBase *xadMasterBase = lhd->xadMasterBase;
|
|
|
|
lhd->leftwinsize = LHFWINDOWSIZE-1;
|
|
j = LHFWINDOWSIZE;
|
|
|
|
if((i = ((uintptr_t)lhd->windowpos - (uintptr_t)(lhd->outbuffer+256)) - j) < 0)
|
|
j += i;
|
|
lhd->windowpos -= j;
|
|
|
|
if((err = xadHookAccess(XADM XADAC_WRITE, (xadUINT32) j, lhd->outbuffer+256, lhd->ai)) && !lhd->err)
|
|
lhd->err = err;
|
|
|
|
if(i >= 0) /* copy the overworked buffer back */
|
|
{
|
|
lhd->leftwinsize -= i;
|
|
i += 256 - 1;
|
|
do
|
|
{
|
|
lhd->outbuffer[i] = lhd->outbuffer[LHFWINDOWSIZE+i];
|
|
} while(i--);
|
|
}
|
|
return lhd->err;
|
|
}
|
|
|
|
static xadINT32 LHFsub1(struct LhFDecrunch *lhd, xadINT16 *p, xadINT8 *q, xadINT16 rounds, xadINT16 maxbits)
|
|
{
|
|
xadINT16 data[32], *r = data+16, *s = data, *t = lhd->data0, *u;
|
|
xadINT16 i = 0, j = 0, k = 0, l = maxbits-1, m, n, o;
|
|
|
|
m = (1<<l);
|
|
n = (m<<1);
|
|
do
|
|
{
|
|
*(s++) = m;
|
|
m >>= 1;
|
|
*(r++) = k;
|
|
o = *(t++);
|
|
o = (o<<l)|(o>>(16-l));
|
|
k += o;
|
|
if(k < 0)
|
|
return XADERR_ILLEGALDATA;
|
|
} while(l--);
|
|
if(k > n)
|
|
return XADERR_ILLEGALDATA;
|
|
else if(k != n)
|
|
{
|
|
u = p + n;
|
|
n -= k;
|
|
l += (n&1) + (n>>1);
|
|
do
|
|
{
|
|
*(--u) = m;
|
|
*(--u) = 0;
|
|
} while(l--);
|
|
o = 16 - maxbits;
|
|
k = (k<<o)|(k>>(16-o));
|
|
l += o;
|
|
m |= (1<<l);
|
|
do
|
|
{
|
|
*(s++) = m;
|
|
m >>= 1;
|
|
*(r++) = k;
|
|
o = *(t++);
|
|
o = (o<<l)|(o>>(16-l));
|
|
k += o;
|
|
} while(k < 0 && l--);
|
|
if(k)
|
|
return XADERR_ILLEGALDATA;
|
|
}
|
|
t = p;
|
|
do
|
|
{
|
|
if((k = *(q++)) > 0)
|
|
{
|
|
s = data+15+k;
|
|
o = *s;
|
|
m = *(s-16);
|
|
*s += m;
|
|
k -= maxbits;
|
|
if(k <= 0 && m--)
|
|
{
|
|
s = p+o;
|
|
do
|
|
{
|
|
*(s++) = i;
|
|
} while(m--);
|
|
}
|
|
else
|
|
{
|
|
s = p + (((xadUINT16) o) >> (16-maxbits));
|
|
o <<= maxbits;
|
|
do
|
|
{
|
|
if(!(m = *s))
|
|
{
|
|
do
|
|
{
|
|
j -= 4;
|
|
*s = j;
|
|
*(--t) = m;
|
|
*(--t) = 0;
|
|
s = t;
|
|
if(o & 0x8000)
|
|
++s;
|
|
o <<= 1;
|
|
} while(--k > 0);
|
|
*(s) = i;
|
|
}
|
|
else
|
|
{
|
|
s = p + (m/2);
|
|
if(o & 0x8000)
|
|
++s;
|
|
o <<= 1;
|
|
--k;
|
|
}
|
|
} while(k > 0);
|
|
*s = i;
|
|
}
|
|
}
|
|
++i;
|
|
} while(rounds--);
|
|
return 0;
|
|
}
|
|
|
|
static xadINT32 LHFsub2(struct LhFDecrunch *lhd, xadINT16 bits, xadINT16 maxbits)
|
|
{
|
|
xadINT16 i, j, k, l;
|
|
xadINT8 *d = lhd->data1;
|
|
|
|
memset(lhd->data0, 0, 32);
|
|
if(!(i = LHFgetbits(lhd, (xadUINT32) bits)))
|
|
{
|
|
if((i = LHFgetbits(lhd, (xadUINT32)bits)) >= maxbits)
|
|
return XADERR_ILLEGALDATA;
|
|
lhd->data1[i] = 0;
|
|
for(bits = 0; bits < 256; ++bits)
|
|
lhd->stackdata[i] = i;
|
|
return 0;
|
|
}
|
|
else if(i >= maxbits)
|
|
return XADERR_ILLEGALDATA;
|
|
|
|
l = i;
|
|
do
|
|
{
|
|
if((k = LHFgetbits(lhd, 3)) == 7)
|
|
{
|
|
j = k;
|
|
do
|
|
{
|
|
k = LHFgetbits(lhd, 1);
|
|
j += k;
|
|
} while(k);
|
|
k = j;
|
|
}
|
|
*d = k;
|
|
if(*(d++) > 0)
|
|
++lhd->data0[k-1];
|
|
} while(i--);
|
|
|
|
return LHFsub1(lhd, lhd->stackdata, lhd->data1, l, 8);
|
|
}
|
|
|
|
static xadINT32 DecrunchLhF(struct LhFDecrunch *lhd)
|
|
{
|
|
xadINT32 i, j, k, l, m, n;
|
|
xadINT8 *p;
|
|
|
|
lhd->numbits = -16; /* init getbits */
|
|
lhd->bitbuf = LHFgetc(lhd) << 16;
|
|
lhd->bitbuf += LHFgetc(lhd); /* end init */
|
|
|
|
// lhd->windowpos = lhd->outbuffer + 254;
|
|
// *(lhd->windowpos++) = 0;
|
|
// *(lhd->windowpos++) = 0;
|
|
lhd->windowpos = (xadSTRPTR) lhd->outbuffer + 256;
|
|
lhd->leftwinsize = LHFWINDOWSIZE-1;
|
|
do
|
|
{
|
|
if(!(i = LHFgetbits(lhd, 16)))
|
|
return XADERR_ILLEGALDATA;
|
|
if((j = LHFgetbits(lhd, 9)))
|
|
{
|
|
if(LHFsub2(lhd, 5, 20))
|
|
return XADERR_ILLEGALDATA;
|
|
memset(lhd->data0, 0, 32);
|
|
|
|
p = lhd->data2;
|
|
do
|
|
{
|
|
k = lhd->bitbuf >> 24;
|
|
if((k = lhd->stackdata[k]) < 0)
|
|
{
|
|
l = lhd->bitbuf >> 16;
|
|
do
|
|
{
|
|
if(l & 0x80)
|
|
k += 2;
|
|
l <<= 1;
|
|
} while((k = lhd->stackdata[k>>1]) < 0);
|
|
}
|
|
|
|
LHFgetbits(lhd, (xadUINT32) lhd->data1[k]);
|
|
k -= 3;
|
|
if(k < 0)
|
|
{
|
|
l = 0;
|
|
k += 2;
|
|
if(!k)
|
|
k = LHFgetbits(lhd, 2) + 3;
|
|
else if(k > 0)
|
|
k = LHFgetbits(lhd, 7) + 7;
|
|
else
|
|
{
|
|
k = LHFgetbits(lhd, 3) + 3;
|
|
l = *(p-1);
|
|
lhd->data0[l-1] += k--;
|
|
}
|
|
do
|
|
{
|
|
*(p++) = l;
|
|
} while(k--);
|
|
}
|
|
else
|
|
{
|
|
*p = k;
|
|
if(*(p++) > 0)
|
|
++lhd->data0[k-1];
|
|
}
|
|
} while(j--);
|
|
while(!*(--p))
|
|
;
|
|
n = p-lhd->data2;
|
|
if((k = LHFsub1(lhd, lhd->data3, lhd->data2, n, 12)))
|
|
return k;
|
|
}
|
|
else
|
|
{
|
|
xadUINT16 temp;
|
|
n = LHFgetbits(lhd, 9);
|
|
lhd->data2[n] = 0;
|
|
for(temp = 0; temp < 0x1000; ++temp)
|
|
lhd->data3[temp] = n;
|
|
}
|
|
if(n >= 256 && (k = LHFsub2(lhd, 4, 16)))
|
|
return k;
|
|
|
|
--i;
|
|
do
|
|
{
|
|
do
|
|
{
|
|
if((k = lhd->data3[lhd->bitbuf>>20]) < 0)
|
|
{
|
|
l = lhd->bitbuf >> 16;
|
|
if(l & (1<<3))
|
|
k += 2;
|
|
if((k = lhd->data3[k>>1]) < 0)
|
|
{
|
|
if(l & (1<<2))
|
|
k += 2;
|
|
if((k = lhd->data3[k>>1]) < 0)
|
|
{
|
|
if(l & (1<<1))
|
|
k += 2;
|
|
if((k = lhd->data3[k>>1]) < 0)
|
|
{
|
|
if(l & (1<<0))
|
|
k += 2;
|
|
k = lhd->data3[k>>1];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LHFgetbits(lhd, (xadUINT32) lhd->data2[k]);
|
|
k -= 256;
|
|
if(k >= 0)
|
|
{
|
|
if((l = lhd->stackdata[lhd->bitbuf >> 24]) < 0)
|
|
{
|
|
m = lhd->bitbuf >> 16;
|
|
do
|
|
{
|
|
m <<= 1;
|
|
if(m & 0x100)
|
|
l = lhd->stackdata[(l/2)+1];
|
|
else
|
|
{
|
|
do
|
|
{
|
|
m <<= 1;
|
|
l = lhd->stackdata[l/2];
|
|
} while(l < 0 && !(m & 0x100));
|
|
}
|
|
} while(l < 0);
|
|
}
|
|
m = lhd->data1[l];
|
|
LHFgetbits(lhd, (xadUINT32) m);
|
|
m = l;
|
|
if(--m > 0)
|
|
l = LHFgetbits(lhd, (xadUINT32) m) + (1<<m);
|
|
p = (xadINT8 *) lhd->windowpos-l-1;
|
|
l = 256 - k;
|
|
if(p < lhd->outbuffer)
|
|
p += LHFWINDOWSIZE;
|
|
while(l++ < 257+2)
|
|
*(lhd->windowpos++) = *(p++);
|
|
k += 3;
|
|
lhd->leftwinsize -= k;
|
|
}
|
|
else
|
|
{
|
|
*(lhd->windowpos++) = k;
|
|
--lhd->leftwinsize;
|
|
}
|
|
} while(i-- && lhd->leftwinsize >= 0);
|
|
if(lhd->leftwinsize < 0 && LHFflush(lhd))
|
|
return lhd->err;
|
|
} while(i >= 0);
|
|
} while(LHFgetbits(lhd, 1));
|
|
return LHFflush(lhd);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
XADUNARCHIVE(LhF)
|
|
{
|
|
xadINT32 err;
|
|
struct xadFileInfo *fi;
|
|
|
|
fi = ai->xai_CurFile;
|
|
|
|
if(fi->xfi_PrivateInfo)
|
|
err = xadHookAccess(XADM XADAC_COPY, fi->xfi_Size, 0, ai);
|
|
else
|
|
{
|
|
struct LhFDecrunch *d;
|
|
|
|
if((d = (struct LhFDecrunch *) xadAllocVec(XADM sizeof(struct LhFDecrunch), XADMEMF_CLEAR)))
|
|
{
|
|
d->ai = ai;
|
|
d->xadMasterBase = xadMasterBase;
|
|
d->sourcelen = (xadUINT32)fi->xfi_CrunchSize;
|
|
d->sourcebuf = (xadSTRPTR) d->inbuffer+LHFWINDOWSIZE;
|
|
err = DecrunchLhF(d);
|
|
xadFreeObjectA(XADM d, 0);
|
|
}
|
|
else
|
|
err = XADERR_NOMEMORY;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
XADFIRSTCLIENT(LhF) {
|
|
XADNEXTCLIENT,
|
|
XADCLIENT_VERSION,
|
|
XADMASTERVERSION,
|
|
LHF_VERSION,
|
|
LHF_REVISION,
|
|
8,
|
|
XADCF_FILEARCHIVER|XADCF_FREEFILEINFO,
|
|
XADCID_LHF,
|
|
"LhF",
|
|
XADRECOGDATAP(LhF),
|
|
XADGETINFOP(LhF),
|
|
XADUNARCHIVEP(LhF),
|
|
NULL
|
|
};
|
|
|
|
#undef XADNEXTCLIENT
|
|
#define XADNEXTCLIENT XADNEXTCLIENTNAME(LhF)
|
|
|
|
#endif /* XADMASTER_LHF_C */
|