From: "A.Appleyard" To: DJGPP AT SUN DOT SOE DOT CLARKSON DOT EDU Date: Tue, 24 Oct 1995 15:21:30 BST Subject: An apparent fault in GZIP In DJGPP\SRC\GZIP-124\ I have the source (but not the compiled form) of an unzipper. It seems to claim to be able to be able to unzip any zipped file that has only one file in. The file DJGPP\SRC\GZIP-124\UNLZW.C "decompress files in LZW format" is the file to unzip files that have been shrunk. Here follows a program that I just wrote that successfully unzips a PKZIP file that contains one file, which must have been packed by shrinking. But its algorithm varies in various places from DJGPP\SRC\GZIP-124\UNLZW.C, which may be able to handle ordinary LZW'ing, but therefore won't be able to PKZIP's version:- #include #include #define pk __attribute__((packed)) typedef unsigned long ul; typedef unsigned short us; typedef unsigned char byte; /*-----*/ class fileheader{public: ul signature pk; byte version pk; byte opsystem pk; us gp pk; us compmethod pk; us time pk; us date pk; ul crc32 pk; ul compsize pk; ul uncompsize pk; us fnleng pk; us extraleng pk;}; class centralfileheader : public fileheader {public: us fcommleng pk; us filediskno pk; us intattr pk; ul extattr pk; ul localoffset pk;}; /*-----*/ class bits{public: int addr,mask; inline bits(void*i){addr=(int)i;}; inline void operator=(void*i){addr=(int)i;}; inline int operator[](int i){return (*(long*)(addr+(i>>3))>>(i&7))&mask;};}; /*-----*/ main(){int i,j,k,l,fs,fhs=sizeof(fileheader),ptr; fileheader*fh; char file[0x100000],*p,sw[256],inname[256],outname[256]; printf("pkzip file to unshrink from?"); gets(inname); printf("text file to unshrink into?"); gets(outname); FILE*Z=fopen(inname,"rb"); fs=fread(file,1,0x100000,Z); FILE*Y=fopen(outname,"wb"); fh=(fileheader*)file; ptr=sizeof(fileheader)+fh->fnleng+fh->extraleng; { /* unshrink */ bits F(file+ptr); F.mask=0x1ff; int N=9,c,q,inbit=0,n=0,i=0,j,k,l,m,p=-1,pc=0; us a[0x10000],b[0x10000]; char w[256],pn[0x10000]; for(i=0;i<0x10000;i++) a[i]=b[i]=pn[i]=0; q=256; for(c=-1,i=0;(inbit>>3)compsize;i++) { p=c; X: k=inbit; c=F[inbit]; inbit+=N; if(c==256) {c=F[inbit]; inbit+=N; if(c==1) {N++; F.mask=(F.mask<<1)|1;} /* Here UNLZW.C rounds `inbit' up to the next code boundary which is also */ /* a byte boundary, but this program (and therefore PKZIP) do not. */ else if(c==2) {pc++; for(m=256;m<0x10000;m++) b[a[m]]|=0x8000; for(m=0;m<0x10000;m++) if(b[m]&0x8000) b[m]&=0x7fff; else a[m]=b[m]=0; for(q=257;b[q];q++) if(q>=0x10000) break /* MOAN */;} /* Here UNLZW.C zeros all the arrays a and b, and returns N to 9 */ /* I and PKZIP merely remove all code entries that no other code entry is */ /* pointing to. */ goto X;} for(l=0,j=c;j>255;j=j==q?p:a[j]) w[l++]=b[j]; w[l++]=j; a[q]=p; b[q]=j; if(c==q) w[0]=j; pn[q]=pc; for(q++;b[q];q++) if(q>=0x10000) break /* MOAN */; for(j=l-1;j>=0;j--) putc(w[j],Y);}} fclose(Y); fclose(Z);}