home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* */
- /* Copyright 1989, Doug Boone. FidoNet 119/5 */
- /* (916) 893-9019 Data */
- /* (916) 891-0748 voice */
- /* P.O. Box 5108, Chico, CA. 95928 */
- /* */
- /* This program is not for sale. It is for the free use with Opus systems. */
- /* You may not sell it in ANY way. If you have an access charge to your */
- /* Bulletin Board, consider this to be like Opus, you can ONLY make it */
- /* available for download in an open area, where non-members can get access */
- /* */
- /* If you need to modify this source code, please send me a copy of the */
- /* changes you've made so that everyone can share in the updates. */
- /* */
- /* "Don't rip me off!" -- Tom Jennings, FidoNet's founder */
- /* */
- /*--------------------------------------------------------------------------*/
- /*--------------------------------------------------------------------------*/
- /* This is basically UNZIP.C by Samuel H. Smith. There have been several */
- /* modifications to meet the needs of FVIEW, as opposed to a stand-alone */
- /* program. Who can judge when source code has been so modified as to no */
- /* longer belongs to the original person? So you better respect his copy- */
- /* right. I still want to do more work on this thing. There's an AWFUL */
- /* amount of global data here. */
- /* */
- /* Copyright 1989, Doug Boone */
- /*--------------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <io.h>
- #ifndef TURBOC
- #include <sys\types.h>
- #include <malloc.h>
- #endif
- #include <sys\stat.h>
- #include <fcntl.h>
- #include <string.h>
- #include "archdr.h"
- #include "unzip.h"
-
- extern void unpack(int,int,long); /* In Arc_View.C */
-
- int unzip(char *,char *);
- int loadup(void);
- int read_bytes(unsigned *);
- int load_bits(int);
- void flushout(void);
- void load_follower(void);
- void reduced(void);
- void clear_part(void);
- void shrunk(void);
- int get_file(char *);
- void do_header(char *);
-
-
- /* Main entry point for this module */
-
- int unzip(char *in_name,char *out_name)
- {
-
- bits_left = 0;
- bitbuf = 0;
- inpos = 0;
- outpos = 0;
- zipeof = 0;
- insize = INBUF_SIZE;
- outsize = OUTBUF_SIZE;
- outcnt = 0L;
-
-
- if ((infile = open(in_name,O_RDONLY|O_BINARY)) < 1) {
- free(inbuf);
- free(outbuf);
- return(1);
- }
-
- do_header(out_name);
-
- return(0);
- }
-
- int loadup(void)
- {
-
- if (packed <= 0)
- return inpos = 0;
-
- if (packed < insize)
- insize = (int) packed;
-
- inpos = read(infile, inbuf, insize);
-
- packed -= inpos;
- inptr = inbuf;
- return inpos--;
- }
-
- int read_bytes(unsigned *x)
- {
- if (inpos-- == 0)
- if (loadup() == 0)
- return 0;
- *x = *inptr++;
- return 8;
- }
-
-
- int load_bits(register int bits)
- {
-
- unsigned temp;
- register int result = bitbuf;
- int sbits = bits_left;
-
- bits -= bits_left;
-
- bits_left = read_bytes(&bitbuf);
- bits_left += read_bytes(&temp);
- bitbuf |= (temp << 8);
- if (bits_left == 0)
- zipeof = 1;
-
- result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
- bitbuf >>= bits;
- bits_left -= bits;
- return result;
- }
-
- void flushout(void)
- {
- write(outfile, outbuf, outpos);
- outcnt += (long) outpos;
- outpos = 0;
- outptr = outbuf;
- }
-
- void load_follower(void)
- {
- register int x;
- register int i;
-
- for (x = 255; x >= 0; x--) {
- if (6 <= bits_left) {
- Slen[x] = (byte)(bitbuf & mask_bits[6]);
- bitbuf >>= 6;
- bits_left -= 6;
- }
- else
- Slen[x] = (byte) load_bits(6);
-
- for (i = 0; i < Slen[x]; i++) {
- if (8 <= bits_left) {
- followers[x][i] = (byte)(bitbuf & mask_bits[8]);
- bitbuf >>= 8; bits_left -= 8;
- }
- else
- followers[x][i] = (byte) load_bits(8);
- } /* end of for(Slen[x]) loop */
- } /* end of for(x) loop */
- }
-
-
-
- void reduced(void)
- {
- int lchar;
- int i;
- int ix;
- int nchar;
- int ExState;
- int V;
- int Len;
- int offset;
- int follower;
- int bitsneeded;
- int factor;
- long op;
-
- factor = method - 1;
- ExState = 0;
- lchar = 0;
- load_follower();
-
- while ((unpacked > (outpos+outcnt)) && (!zipeof)) {
- if (Slen[lchar] == 0) {
- if (8 <= bits_left) {
- nchar = (int)(bitbuf & mask_bits[8]);
- bitbuf >>= 8;
- bits_left -= 8;
- }
- else
- nchar = load_bits(8);
- }
- else {
- if (1 <= bits_left) {
- nchar = (int)(bitbuf & mask_bits[1]);
- bitbuf >>= 1;
- bits_left -= 1;
- }
- else
- nchar = load_bits(1);
-
- if (nchar != 0) {
- if (8 <= bits_left) {
- nchar = (int)(bitbuf & mask_bits[8]);
- bitbuf >>= 8;
- bits_left -= 8;
- }
- else
- nchar = load_bits(8);
- }
- else {
- bitsneeded = B_table[Slen[lchar]];
- if (bitsneeded <= bits_left) {
- follower = (int)(bitbuf & mask_bits[bitsneeded]);
- bitbuf >>= bitsneeded;
- bits_left -= bitsneeded;
- }
- else
- follower = load_bits(bitsneeded);
- nchar = followers[lchar][follower];
- }
- } /* This one is questionable! */
-
- switch (ExState) {
-
- case 0:
- if (nchar != DLE ) {
- *outptr++ = (byte) nchar;
- if (++outpos >= outsize)
- flushout();
- }
- else
- ExState = 1;
- break;
-
- case 1:
- if (nchar != 0) {
- V = nchar;
- Len = V & L_table[factor];
- if (Len == L_table[factor])
- ExState = 2;
- else
- ExState = 3;
- }
- else {
- *outptr++ = DLE;
- if (++outpos >= outsize)
- flushout();
- ExState = 0;
- }
- break;
-
- case 2:
- Len += nchar;
- ExState = 3;
- break;
-
- case 3: i = Len + 3;
- offset = (((V >> D_shift[factor]) &
- D_mask[factor]) << 8) + nchar + 1;
- op = outcnt + outpos - offset;
-
- while ((op < 0L) && (i > 0)) {
- *outptr++=0;
- if (++outpos >= outsize)
- flushout();
- op++;
- i--;
- } /* End of while((op<0L && (i>0)) */
-
- ix = (int) (op % outsize );
- if ( (((long)(ix + i)) < outsize ) &&
- ((outpos+i) < outsize ) ) {
- memcpy(outptr,&outbuf[ix],i);
- outptr += i;
- outpos += i;
- }
- else {
- while (i--) {
- *outptr++=outbuf[ix];
- if (++outpos==outsize )
- flushout();
- if (((long)++ix) >= outsize )
- ix = 0;
- }
- }
-
- ExState = 0;
- break; /* End of case 3 */
- } /* End of Switch statement */
-
- lchar = nchar;
- } /* End of WHILE loop */
- return;
- }
-
-
- void clear_part(void)
- {
- register int pr;
- register int cd;
-
- for (cd = FIRST ; cd < free_ent; cd++)
- prefix[cd] |= 0x8000;
-
- for (cd = FIRST ; cd < free_ent; cd++) {
- pr = prefix[cd] & 0x7fff;
- if (pr >= FIRST )
- prefix[pr] &= 0x7fff;
- }
-
-
- for (cd = FIRST ; cd < free_ent; cd++)
- if ((prefix[cd] & 0x8000) != 0)
- prefix[cd] = -1;
-
-
- cd = FIRST ;
- while ((cd < maxcodemax) && (prefix[cd] != -1))
- cd++;
- free_ent = cd;
- }
-
- void shrunk(void)
- {
-
- register int code;
- register int stackp;
- int finchar;
- int oldcode;
- int incode;
-
- maxcodemax = 1 << MAX_BITS ;
- codesize = INIT_BITS ;
- maxcode = (1 << codesize) - 1;
- free_ent = FIRST ;
- offset = 0;
-
- for (code = maxcodemax; code > 255; code--)
- prefix[code] = -1;
-
- for (code = 255; code >= 0; code--) {
- prefix[code] = 0;
- suffix[code] = (byte) code;
- }
-
- if (codesize <= bits_left) {
- oldcode = (int)(bitbuf & mask_bits[codesize]);
- bitbuf >>= codesize;
- bits_left -= codesize;
- }
- else
- oldcode = load_bits(codesize);
-
- if (zipeof)
- return;
- finchar = oldcode;
-
- *outptr++ = (byte) finchar;
- if (++outpos==outsize )
- flushout();
-
- stackp = HSIZE ;
-
- while (!zipeof) {
- if (codesize <= bits_left) {
- code = (int)(bitbuf & mask_bits[codesize]);
- bitbuf >>= codesize;
- bits_left -= codesize;
- }
- else
- code = load_bits(codesize);
-
- if (zipeof)
- return;
-
- while (code == CLEAR ) {
- if (codesize <= bits_left) {
- code = (int)(bitbuf & mask_bits[codesize]);
- bitbuf >>= codesize;
- bits_left -= codesize;
- }
- else
- code = load_bits(codesize);
- /*}*/
- switch (code) {
-
- case 1:
- codesize++;
- if (codesize == MAX_BITS )
- maxcode = maxcodemax;
- else
- maxcode = (1 << codesize) - 1;
- break;
-
- case 2:
- clear_part();
- break;
- } /* End of switch(code) */
-
-
- if (codesize <= bits_left) {
- code = (int)(bitbuf & mask_bits[codesize]);
- bitbuf >>= codesize;
- bits_left -= codesize;
- }
- else
- code = load_bits(codesize);
-
- if (zipeof)
- return;
- } /* End of while(code == CLEAR) */
-
- incode = code;
- if (prefix[code] == -1) {
- stack[--stackp] = (byte) finchar;
- code = oldcode;
- }
-
-
- while (code >= FIRST ) {
- stack[--stackp] = suffix[code];
- code = prefix[code];
- }
-
- finchar = suffix[code];
- stack[--stackp] = (byte) finchar;
-
- if ((HSIZE -stackp+outpos) < outsize ) {
- memcpy(outptr,&stack[stackp],HSIZE -stackp);
- outptr += HSIZE -stackp;
- outpos += HSIZE -stackp;
- stackp = HSIZE ;
- }
-
- else while (stackp < HSIZE ) {
- *outptr++=stack[stackp++];
- if (++outpos==outsize )
- flushout();
- }
-
- code = free_ent;
- if (code < maxcodemax) {
- prefix[code] = oldcode;
- suffix[code] = (byte) finchar;
-
- do
- code++;
- while ((code < maxcodemax) && (prefix[code] != -1));
-
- free_ent = code;
- }
-
- oldcode = incode;
- } /* End of while(!zipeof) */
-
- }
-
-
- int get_file(char *dearc)
- {
-
- if ((outfile = open(dearc,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE)) < 1 ) {
- fprintf(Log_fp,"Can't create output: %s\n", dearc);
- return 1;
- }
-
- write(outfile, "?", 1);
- lseek(outfile, 0L,SEEK_SET);
-
- switch (method) {
-
- case 0: unpack(infile,outfile,outsize);
- break;
-
- case 1:
- inbuf = (byte *) malloc(insize);
- outbuf = (byte *) malloc(outsize);
-
- inptr = inbuf;
- outptr = outbuf;
-
- if ((inbuf == 0L ) || (outbuf == 0L )) {
- fprintf(Log_fp,"Can't allocate buffers!\n");
- return(1);
- }
- shrunk();
- break;
-
- case 2:
- case 3:
- case 4:
- case 5:
- inbuf = (byte *) malloc(insize);
- outbuf = (byte *) malloc(outsize);
-
- inptr = inbuf;
- outptr = outbuf;
-
- if ((inbuf == 0L ) || (outbuf == 0L )) {
- fprintf(Log_fp,"Can't allocate buffers!\n");
- return(1);
- }
- reduced();
- break;
-
- default:
- fprintf(Log_fp,"Unknown compression method.\n");
- }
- if (outpos > 0)
- write(outfile, outbuf, (int) outpos);
- close(outfile);
- return(0);
- }
-
-
- void do_header(char *dearc)
- {
- struct ID_Hdr *ID;
- struct Local_Hdr *local;
- char *mbrname;
- int check;
- char *test;
-
- if ((test = strrchr(dearc,'\\')) == 0L )
- test = dearc;
- else
- test++;
-
- ID = (struct ID_Hdr *) malloc(sizeof(struct ID_Hdr));
- local = (struct Local_Hdr *) malloc(sizeof(struct Local_Hdr));
- mbrname = (char *) malloc(80);
-
- do {
- check = read(infile,(void *)ID,sizeof(struct ID_Hdr));
- if (ID->Head_Type == LOCAL_HEADER) {
- if ((check = read(infile,(void *)local,sizeof(struct Local_Hdr))) != -1) {
- memset(mbrname,EOS,80);
- check = read(infile,mbrname,local->name_length);
- lseek(infile,((long)local->Xfield_length),SEEK_CUR);
-
- if (stricmp(test,mbrname) == 0) {
- packed = local->size_now;
- method = local->compression;
- unpacked = local->real_size;
- get_file(dearc);
- zipeof = 1;
- }
- else
- lseek(infile,local->size_now,SEEK_CUR);
-
- } /* End of one entry */
- } /* End of grabbing local directory entries */
- else
- check = -1;
- } while(check >0 && !zipeof); /* End of file */
- free(local);
- free(mbrname);
- free(ID);
- close(infile);
- free(inbuf);
- free(outbuf);
- return;
- }
-
-
-