cdesktopenv/cde/lib/DtSearch/hdecode.c

314 lines
9.8 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they 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 these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* COMPONENT_NAME: austext
*
* FUNCTIONS: hc_decode
* main
*
* ORIGINS: 27
*
*
* (C) COPYRIGHT International Business Machines Corp. 1990,1995
* All Rights Reserved
* Licensed Materials - Property of IBM
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/************************* HDECODE.C ***************************
* $XConsortium: hdecode.c /main/8 1996/11/21 19:50:15 drk $
* 1990.
* Decode function that reads in a Huffman Code bitstring and returns the
* original plaintext characters. Intended use of Huffman Code is
* both compression and encryption of text lines in Opera System.
* Decode (decryption) is optimized for high speed, online use.
*
* Global Arguments:
* 'hctree' is decode table in form of array of integers.
* Each integer pair forms a node in a huffman code tree.
* See huffcode.c for full discussion of its organization.
* If 'hctree' is NULL, the tree has not been linked into
* current object module, and this function must read the
* source file and create the tree at execution time.
* This flexibility allows internal use of decode function
* using different trees without having to recompile/relink.
* The linked-in version is more secure for external customer use.
* 'hctree_name' is filename prefix for both encode (.huf) and
* encode (.c) source files. If 'hctree' is NULL, this is
* the file from which the tree will be built.
* 'hctree_id' is unique unix timestamp indicating when hctree was
* create. It is compared with caller's (encoder's) passed stamp
* to ensure encode/decode compatibility.
* 'hctree_root' is the integer index of the root node in hctree.
* By luck, this is always the LAST node so it also gives an
* indication of the storage needed when the tree has to be
* allocated at execution time.
*
* Passed Arguments:
* 'bitstring' is the address of the huffman encoded cyphertext.
* It begins on byte boundary, but may end in middle of
* a byte depending on charcount.
* 'charbuf' is the output buffer where the plaintext characters
* will be assembled.
* 'charcount' is the number of plaintext bytes that were encoded into
* the passed bitstring, and will be assembled into charbuf.
*
* $Log$
* Revision 2.3 1996/03/13 22:56:26 miker
* Changed char to UCHAR several places.
*
* Revision 2.2 1995/10/25 17:51:46 miker
* Added prolog.
*
* Revision 2.1 1995/09/22 20:50:00 miker
* Freeze DtSearch 0.1, AusText 2.1.8
*
* Revision 1.3 1995/09/05 18:02:21 miker
* Name changes for DtSearch.
*/
#include "SearchP.h"
#include <errno.h>
#define X_INCLUDE_STRING_H
#define XOS_USE_NO_LOCKING
#include <X11/Xos_r.h>
#define HDEC_FBUFSZ 128
#define PROGNAME "HDECODE"
#define MS_huff 30 /* message catalog set number */
extern char *hctree_name;
extern time_t hctree_id;
extern int hctree_root;
extern int *hctree;
/*---------------- TREENODE structure ---------------------*/
typedef struct {
int branch0;
int branch1;
} TREENODE;
/************************************************/
/* */
/* HC Decode */
/* */
/************************************************/
void hc_decode (
UCHAR *bitstring, /* input: compressed data */
UCHAR *charbuf, /* output: uncompressed data */
int charcount, /* input: length uncompressed data */
time_t encode_id)
{ /* input: compression table to use */
#ifdef DEBUG_DECODE
static int first_time = TRUE;
#endif
int bitreg;
int i;
int bitcount;
int tree_index;
TREENODE *tree_addr;
#ifdef EXTERNAL_TREE
char *ptr;
char *hdecode_filebuf;
FILE *hdecode_file;
_Xstrtokparams strtok_buf;
#endif
#ifdef EXTERNAL_TREE
/* Create hctree from external file? */
if (hctree == NULL) {
if ((hdecode_filebuf = malloc (HDEC_FBUFSZ)) == NULL) {
fprintf (aa_stderr, CATGETS(dtsearch_catd, MS_huff, 10,
"%s Out of Memory.\n"),
PROGNAME"076");
DtSearchExit (2);
}
if ((hdecode_file = fopen (hctree_name, "r")) == NULL) {
fprintf (aa_stderr, CATGETS(dtsearch_catd, MS_huff, 11,
"%s Cannot open tree file '%s': %s\n"),
PROGNAME"082", hctree_name, strerror (errno));
DtSearchExit (2);
}
/* read first few lines to load global variables */
for (i = 0; i < 3; i++)
fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file);
ptr = strchr (hdecode_filebuf, '=');
hctree_id = atol (ptr + 1);
fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file);
ptr = strchr (hdecode_filebuf, '=');
hctree_root = atoi (ptr + 1);
fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file); /* throwaway */
/* allocate space for the hctree and read in the values */
if ((hctree = (int *) malloc (
sizeof (int) * 2 * (hctree_root + 2))) == NULL) {
fprintf (aa_stderr, "\n" PROGNAME "100 Out of Memory.\7\n");
DtSearchExit (2);
}
for (i = 0; i <= hctree_root; i++) {
if ((fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file)) == NULL) {
fprintf (aa_stderr, CATGETS(dtsearch_catd, MS_huff, 12,
"%s Invalid format hctree '%s'.\n"),
PROGNAME"106", hctree_name);
DtSearchExit (2);
}
hctree[2 * i] = atoi (_XStrtok (hdecode_filebuf, " \t,", strtok_buf));
hctree[2 * i + 1] = atoi (_XStrtok (NULL, " \t,", strtok_buf));
}
free (hdecode_filebuf);
fclose (hdecode_file);
} /* endif where hctree created from external file */
#endif /* for EXTERNAL_TREE */
#ifdef DEBUG_DECODE
if (first_time) {
first_time = FALSE;
printf ("\n***** created hctree from '%s' ******\n"
"hctree_id = %ld\nhctree_root = %d\n",
hctree_name, hctree_id, hctree_root);
}
#endif
if (encode_id != hctree_id) {
fprintf (aa_stderr, CATGETS(dtsearch_catd, MS_huff, 13,
"%s Incompatible hctree_ids.\n"),
PROGNAME"118");
DtSearchExit (2);
}
tree_addr = (TREENODE *) hctree;
bitcount = 0;
while (charcount-- > 0) { /****** MAIN OUTPUT CHARACTER LOOP ******/
tree_index = hctree_root;
while (tree_index >= 0) { /****** TREE TRAVERSAL LOOP ******/
/* retrieve next bit */
if (bitcount <= 0) { /* read next input char? */
bitcount = 8;
bitreg = *bitstring++;
}
bitreg <<= 1;
bitcount--;
if (bitreg & 0x0100)
tree_index = tree_addr[tree_index].branch1;
else
tree_index = tree_addr[tree_index].branch0;
} /* end tree traversal loop */
/******** DECODE CHARACTER ********/
/* if literal code, retrieve next 8 bits as char itself */
if ((tree_index += 257) == 256) {
tree_index = 0;
for (i = 8; i > 0; i--) {
if (bitcount <= 0) { /* read next input char? */
bitcount = 8;
bitreg = *bitstring++;
}
bitreg <<= 1;
bitcount--;
tree_index <<= 1;
if (bitreg & 0x0100)
tree_index |= 1;
} /* end 8-bit for loop */
} /* endif to process literal coding */
*charbuf = tree_index;
charbuf++;
} /* end main output character loop */
return;
} /* end of function hc_decode */
#ifdef DEBUG_DECODE
/************************************************/
/* */
/* Main */
/* */
/************************************************/
void main (int argc, char *argv[])
{
#define BITSTR_BUFSIZE 140
FILE *instream;
FILE *aa_stderr = stderr;
char stringbuf[BITSTR_BUFSIZE + 2];
char charbuf[9 * BITSTR_BUFSIZE];
char fname_tree[80];
int mychar;
int oops;
int i;
union {
INT integer;
char chars[2];
} charcount;
if (argc <= 1) {
puts ("Usage: hdecode [hucfile] cypherfile");
return;
}
if (argc >= 3) {
hctree = NULL;
append_ext (fname_tree, sizeof (fname_tree), argv[1], EXT_HDECODE);
hctree_name = fname_tree;
argv++;
}
if ((instream = fopen (argv[1], "rb")) == NULL) {
fprintf (aa_stderr, "Cannot open cypherfile '%s'.\n", argv[1]);
exit (2);
}
MAINLOOP:
/**************/
if ((mychar = fgetc (instream)) == EOF)
return;
charcount.chars[0] = mychar;
if ((mychar = fgetc (instream)) == EOF)
return;
charcount.chars[1] = mychar;
if (charcount.integer > sizeof (charbuf) - 2) {
oops = TRUE;
charcount.integer = sizeof (charbuf) - 2;
}
else
oops = FALSE;
/* printf("\n\n***** charcount = %d %s*****\n",
charcount.integer, (oops) ? "(reduced)" : "");*/
for (i = 0; i < BITSTR_BUFSIZE; i++) {
if ((mychar = fgetc (instream)) == EOF) {
fprintf (aa_stderr, "\n" PROGNAME "202 Unexpected EOF '%s'.\n",
argv[1]);
exit (2);
}
stringbuf[i] = mychar;
}
hc_decode (stringbuf, charbuf, charcount.integer, hctree_id);
for (i = 0; i < charcount.integer; i++)
putchar (charbuf[i]);
goto MAINLOOP;
/************/
} /* end of function main */
#endif
/************************* HDECODE.C ***************************/