Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtSearch / hdecode.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *   COMPONENT_NAME: austext
25  *
26  *   FUNCTIONS: hc_decode
27  *              main
28  *
29  *   ORIGINS: 27
30  *
31  *
32  *   (C) COPYRIGHT International Business Machines Corp. 1990,1995
33  *   All Rights Reserved
34  *   Licensed Materials - Property of IBM
35  *   US Government Users Restricted Rights - Use, duplication or
36  *   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
37  */
38 /************************* HDECODE.C ***************************
39  * $XConsortium: hdecode.c /main/8 1996/11/21 19:50:15 drk $
40  * 1990.
41  * Decode function that reads in a Huffman Code bitstring and returns the
42  * original plaintext characters.  Intended use of Huffman Code is
43  * both compression and encryption of text lines in Opera System.
44  * Decode (decryption) is optimized for high speed, online use.
45  * 
46  * Global Arguments:
47  * 'hctree' is decode table in form of array of integers.  
48  *     Each integer pair forms a node in a huffman code tree.
49  *     See huffcode.c for full discussion of its organization.
50  *     If 'hctree' is NULL, the tree has not been linked into
51  *     current object module, and this function must read the
52  *     source file and create the tree at execution time.  
53  *     This flexibility allows internal use of decode function 
54  *     using different trees without having to recompile/relink.
55  *     The linked-in version is more secure for external customer use.
56  * 'hctree_name' is filename prefix for both encode (.huf) and 
57  *     encode (.c) source files.  If 'hctree' is NULL, this is
58  *     the file from which the tree will be built.
59  * 'hctree_id' is unique unix timestamp indicating when hctree was 
60  *     create.  It is compared with caller's (encoder's) passed stamp
61  *     to ensure encode/decode compatibility.
62  * 'hctree_root' is the integer index of the root node in hctree.
63  *     By luck, this is always the LAST node so it also gives an 
64  *     indication of the storage needed when the tree has to be 
65  *     allocated at execution time.
66  * 
67  * Passed Arguments:
68  * 'bitstring' is the address of the huffman encoded cyphertext.  
69  *     It begins on byte boundary, but may end in middle of
70  *     a byte depending on charcount.
71  * 'charbuf' is the output buffer where the plaintext characters 
72  *     will be assembled.
73  * 'charcount' is the number of plaintext bytes that were encoded into
74  *     the passed bitstring, and will be assembled into charbuf.
75  *
76  * $Log$
77  * Revision 2.3  1996/03/13  22:56:26  miker
78  * Changed char to UCHAR several places.
79  *
80  * Revision 2.2  1995/10/25  17:51:46  miker
81  * Added prolog.
82  *
83  * Revision 2.1  1995/09/22  20:50:00  miker
84  * Freeze DtSearch 0.1, AusText 2.1.8
85  *
86  * Revision 1.3  1995/09/05  18:02:21  miker
87  * Name changes for DtSearch.
88  */
89 #include "SearchP.h"
90 #include <errno.h>
91
92 #define X_INCLUDE_STRING_H
93 #define XOS_USE_NO_LOCKING
94 #include <X11/Xos_r.h>
95
96 #define HDEC_FBUFSZ     128
97 #define PROGNAME        "HDECODE"
98 #define MS_huff         30      /* message catalog set number */
99
100 extern char    *hctree_name;
101 extern time_t   hctree_id;
102 extern int      hctree_root;
103 extern int     *hctree;
104
105 /*---------------- TREENODE structure ---------------------*/
106 typedef struct {
107     int             branch0;
108     int             branch1;
109 }               TREENODE;
110
111 /************************************************/
112 /*                                              */
113 /*                 HC Decode                    */
114 /*                                              */
115 /************************************************/
116 void    hc_decode (
117                 UCHAR   *bitstring,     /* input: compressed data */
118                 UCHAR   *charbuf,       /* output: uncompressed data */
119                 int     charcount,      /* input: length uncompressed data */
120                 time_t  encode_id)
121 {  /* input: compression table to use */
122 #ifdef DEBUG_DECODE
123     static int      first_time = TRUE;
124 #endif
125     register int    bitreg;
126     int             i;
127     int             bitcount;
128     int             tree_index;
129     TREENODE       *tree_addr;
130
131 #ifdef EXTERNAL_TREE
132     char           *ptr;
133     char           *hdecode_filebuf;
134     FILE           *hdecode_file;
135     _Xstrtokparams  strtok_buf;
136 #endif
137
138 #ifdef EXTERNAL_TREE
139     /* Create hctree from external file? */
140     if (hctree == NULL) {
141         if ((hdecode_filebuf = malloc (HDEC_FBUFSZ)) == NULL) {
142             fprintf (aa_stderr, catgets(dtsearch_catd, MS_huff, 10,
143                 "%s Out of Memory.\n"),
144                 PROGNAME"076");
145             DtSearchExit (2);
146         }
147         if ((hdecode_file = fopen (hctree_name, "r")) == NULL) {
148             fprintf (aa_stderr, catgets(dtsearch_catd, MS_huff, 11,
149                 "%s Cannot open tree file '%s': %s\n"),
150                 PROGNAME"082", hctree_name, strerror (errno));
151             DtSearchExit (2);
152         }
153
154         /* read first few lines to load global variables */
155         for (i = 0; i < 3; i++)
156             fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file);
157         ptr = strchr (hdecode_filebuf, '=');
158         hctree_id = atol (ptr + 1);
159
160         fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file);
161         ptr = strchr (hdecode_filebuf, '=');
162         hctree_root = atoi (ptr + 1);
163
164         fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file);     /* throwaway */
165
166         /* allocate space for the hctree and read in the values */
167         if ((hctree = (int *) malloc (
168                 sizeof (int) * 2 * (hctree_root + 2))) == NULL) {
169             fprintf (aa_stderr, "\n" PROGNAME "100 Out of Memory.\7\n");
170             DtSearchExit (2);
171         }
172         for (i = 0; i <= hctree_root; i++) {
173             if ((fgets (hdecode_filebuf, HDEC_FBUFSZ, hdecode_file)) == NULL) {
174                 fprintf (aa_stderr, catgets(dtsearch_catd, MS_huff, 12,
175                     "%s Invalid format hctree '%s'.\n"),
176                     PROGNAME"106", hctree_name);
177                 DtSearchExit (2);
178             }
179             hctree[2 * i] = atoi (_XStrtok (hdecode_filebuf, " \t,", strtok_buf));
180             hctree[2 * i + 1] = atoi (_XStrtok (NULL, " \t,", strtok_buf));
181         }
182         free (hdecode_filebuf);
183         fclose (hdecode_file);
184     }   /* endif where hctree created from external file */
185 #endif  /* for EXTERNAL_TREE */
186
187 #ifdef DEBUG_DECODE
188     if (first_time) {
189         first_time = FALSE;
190         printf ("\n***** created hctree from '%s' ******\n"
191             "hctree_id = %ld\nhctree_root = %d\n",
192             hctree_name, hctree_id, hctree_root);
193     }
194 #endif
195
196
197     if (encode_id != hctree_id) {
198         fprintf (aa_stderr, catgets(dtsearch_catd, MS_huff, 13,
199             "%s Incompatible hctree_ids.\n"),
200             PROGNAME"118");
201         DtSearchExit (2);
202     }
203     tree_addr = (TREENODE *) hctree;
204     bitcount = 0;
205     while (charcount-- > 0) {   /****** MAIN OUTPUT CHARACTER LOOP ******/
206         tree_index = hctree_root;
207         while (tree_index >= 0) {       /****** TREE TRAVERSAL LOOP ******/
208             /* retrieve next bit */
209             if (bitcount <= 0) {        /* read next input char? */
210                 bitcount = 8;
211                 bitreg = *bitstring++;
212             }
213             bitreg <<= 1;
214             bitcount--;
215             if (bitreg & 0x0100)
216                 tree_index = tree_addr[tree_index].branch1;
217             else
218                 tree_index = tree_addr[tree_index].branch0;
219         }       /* end tree traversal loop */
220
221         /******** DECODE CHARACTER ********/
222         /* if literal code, retrieve next 8 bits as char itself */
223         if ((tree_index += 257) == 256) {
224             tree_index = 0;
225             for (i = 8; i > 0; i--) {
226                 if (bitcount <= 0) {    /* read next input char? */
227                     bitcount = 8;
228                     bitreg = *bitstring++;
229                 }
230                 bitreg <<= 1;
231                 bitcount--;
232                 tree_index <<= 1;
233                 if (bitreg & 0x0100)
234                     tree_index |= 1;
235             }   /* end 8-bit for loop */
236         }       /* endif to process literal coding */
237         *charbuf = tree_index;
238         charbuf++;
239     }   /* end main output character loop */
240
241     return;
242 }  /* end of function hc_decode */
243
244 #ifdef DEBUG_DECODE
245 /************************************************/
246 /*                                              */
247 /*                   Main                       */
248 /*                                              */
249 /************************************************/
250 void            main (int argc, char *argv[])
251 {
252 #define BITSTR_BUFSIZE  140
253     FILE           *instream;
254     FILE           *aa_stderr = stderr;
255     char            stringbuf[BITSTR_BUFSIZE + 2];
256     char            charbuf[9 * BITSTR_BUFSIZE];
257     char            fname_tree[80];
258     int             mychar;
259     int             oops;
260     int             i;
261     union {
262         INT             integer;
263         char            chars[2];
264     }               charcount;
265
266     if (argc <= 1) {
267         puts ("Usage:  hdecode [hucfile] cypherfile");
268         return;
269     }
270     if (argc >= 3) {
271         hctree = NULL;
272         append_ext (fname_tree, sizeof (fname_tree), argv[1], EXT_HDECODE);
273         hctree_name = fname_tree;
274         argv++;
275     }
276     if ((instream = fopen (argv[1], "rb")) == NULL) {
277         fprintf (aa_stderr, "Cannot open cypherfile '%s'.\n", argv[1]);
278         exit (2);
279     }
280 MAINLOOP:
281     /**************/
282     if ((mychar = fgetc (instream)) == EOF)
283         return;
284     charcount.chars[0] = mychar;
285     if ((mychar = fgetc (instream)) == EOF)
286         return;
287     charcount.chars[1] = mychar;
288     if (charcount.integer > sizeof (charbuf) - 2) {
289         oops = TRUE;
290         charcount.integer = sizeof (charbuf) - 2;
291     }
292     else
293         oops = FALSE;
294 /*    printf("\n\n***** charcount = %d %s*****\n",
295         charcount.integer, (oops) ? "(reduced)" : "");*/
296     for (i = 0; i < BITSTR_BUFSIZE; i++) {
297         if ((mychar = fgetc (instream)) == EOF) {
298             fprintf (aa_stderr, "\n" PROGNAME "202 Unexpected EOF '%s'.\n",
299                 argv[1]);
300             exit (2);
301         }
302         stringbuf[i] = mychar;
303     }
304     hc_decode (stringbuf, charbuf, charcount.integer, hctree_id);
305     for (i = 0; i < charcount.integer; i++)
306         putchar (charbuf[i]);
307     goto MAINLOOP;
308     /************/
309 }  /* end of function main */
310
311 #endif
312
313 /************************* HDECODE.C ***************************/