1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/z_intrf.c,v 1.11 2011/06/18 04:44:51 william Exp $
19 */
20
21 #define _INCLUDE_FROM_Z_INTRF_C_
22
23 #include "tgifdefs.h"
24
25 #if (!defined(_NO_ZLIB) || defined(HAVE_LIBZ))
26 #include <zlib.h>
27 #endif /* (!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
28
29 #include "dialog.e"
30 #include "file.e"
31 #include "msg.e"
32 #include "setup.e"
33 #include "strtbl.e"
34 #include "util.e"
35 #include "z_intrf.e"
36
37 /* --------------------- Utility Functions --------------------- */
38
39 static
ByteStuff(buf_in,buf_len,buf_out,pn_buf_out)40 void ByteStuff(buf_in, buf_len, buf_out, pn_buf_out)
41 unsigned char *buf_in, *buf_out;
42 unsigned int buf_len, *pn_buf_out;
43 {
44 int i=0, count=0;
45
46 for (i=0; i < buf_len; i++, buf_in++) {
47 switch (*buf_in) {
48 case '\0':
49 *buf_out++ = ((unsigned char)0xff);
50 *buf_out++ = ((unsigned char)0x30);
51 count += 2;
52 break;
53 case ((unsigned char)0xff):
54 *buf_out++ = ((unsigned char)0xff);
55 *buf_out++ = ((unsigned char)0xff);
56 count += 2;
57 break;
58 default:
59 *buf_out++ = *buf_in;
60 count++;
61 break;
62 }
63 }
64 if (pn_buf_out != NULL) *pn_buf_out = count;
65 }
66
67 static
ByteUnStuff(buf_in,buf_len,buf_out,pn_buf_out,pn_has_left_over)68 int ByteUnStuff(buf_in, buf_len, buf_out, pn_buf_out, pn_has_left_over)
69 unsigned char *buf_in, *buf_out;
70 int buf_len, *pn_buf_out, *pn_has_left_over;
71 {
72 int i=0, count=0;
73
74 if (*pn_has_left_over) {
75 if (buf_len == 0) return TRUE;
76 switch (*buf_in) {
77 case ((unsigned char)0x30):
78 *buf_out++ = ((unsigned char)'\0');
79 count++;
80 buf_in++;
81 break;
82 case ((unsigned char)0xff):
83 *buf_out++ = ((unsigned char)0xff);
84 count++;
85 buf_in++;
86 break;
87 default: return FALSE;
88 }
89 *pn_has_left_over = FALSE;
90 }
91 for (i=count; i < buf_len; i++, buf_in++) {
92 if (*buf_in == ((unsigned char)0xff)) {
93 i++;
94 buf_in++;
95 if (i >= buf_len) {
96 *pn_has_left_over = TRUE;
97 if (pn_buf_out != NULL) *pn_buf_out = count;
98 return TRUE;
99 }
100 switch (*buf_in) {
101 case ((unsigned char)0x30):
102 *buf_out++ = ((unsigned char)'\0');
103 count++;
104 break;
105 case ((unsigned char)0xff):
106 *buf_out++ = ((unsigned char)0xff);
107 count++;
108 break;
109 default: return FALSE;
110 }
111 } else {
112 *buf_out++ = *buf_in;
113 count++;
114 }
115 }
116 if (pn_buf_out != NULL) *pn_buf_out = count;
117
118 return TRUE;
119 }
120
121 /* --------------------- HasZlibSupport() --------------------- */
122
HasZlibSupport()123 int HasZlibSupport()
124 {
125 #if (!defined(_NO_ZLIB) || defined(HAVE_LIBZ))
126 return TRUE;
127 #else /* ~(!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
128 return FALSE;
129 #endif /* (!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
130 }
131
132 /* --------------------- DeflateFile() --------------------- */
133
DeflateFile(fname,deflated_fname)134 int DeflateFile(fname, deflated_fname)
135 char *fname, *deflated_fname;
136 /* no byte stuffing */
137 {
138 #if (!defined(_NO_ZLIB) || defined(HAVE_LIBZ))
139 int level=Z_DEFAULT_COMPRESSION;
140 int ret=0, flush=0;
141 unsigned int block_sz=0x4000;
142 unsigned int have=0;
143 z_stream strm;
144 FILE *in_fp=NULL, *out_fp=NULL;
145 unsigned char in[0x4000], out[0x4000];
146 int bytes_left=0, input_size=0;
147 struct stat stat_buf;
148 ProgressInfo pi;
149
150 if ((in_fp=fopen(fname, "r")) == NULL) {
151 FailToOpenMessage(fname, "r", NULL);
152 return FALSE;
153 }
154 if (fstat(fileno(in_fp), &stat_buf) != 0) {
155 fclose(in_fp);
156 sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_FSTAT_ABORT_COPY), fname);
157 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
158 return FALSE;
159 }
160 bytes_left = input_size = stat_buf.st_size;
161 if ((out_fp=fopen(deflated_fname, "w")) == NULL) {
162 fclose(in_fp);
163 FailToOpenMessage(deflated_fname, "w", NULL);
164 return FALSE;
165 }
166 /* allocate deflate state */
167 memset(&strm, 0, sizeof(strm));
168 strm.zalloc = Z_NULL;
169 strm.zfree = Z_NULL;
170 strm.opaque = Z_NULL;
171 ret = deflateInit(&strm, level);
172 if (ret != Z_OK) {
173 ZlibError(ret, TRUE);
174 return FALSE;
175 }
176 BeginProgress(&pi, input_size);
177 do {
178 int bytes_to_read=min(block_sz, bytes_left);
179
180 strm.avail_in = fread(in, 1, bytes_to_read, in_fp);
181 if (ferror(in_fp)) {
182 (void)deflateEnd(&strm);
183 ZlibError(ret, TRUE);
184 return FALSE;
185 }
186 bytes_left -= bytes_to_read;
187
188 flush = (bytes_left == 0) ? Z_FINISH : Z_NO_FLUSH;
189 strm.next_in = in;
190
191 UpdateProgress(&pi, input_size-bytes_left);
192 /*
193 * run deflate() on input until output buffer not full, finish compression
194 * if all of in_fp has been read in or in_buf is exhausted
195 */
196 do {
197 strm.avail_out = block_sz;
198 strm.next_out = out;
199 ret = deflate(&strm, flush); /* no bad return value */
200 TgAssert(ret != Z_STREAM_ERROR,
201 "deflate() returns Z_STREAM_ERROR in DeflateFile()", NULL);
202 /* make sure that state is not clobbered */
203 have = block_sz - strm.avail_out;
204
205 if (fwrite(out, 1, have, out_fp) != have || ferror(out_fp)) {
206 (void)deflateEnd(&strm);
207 ZlibError(ret, TRUE);
208 return FALSE;
209 }
210 } while (strm.avail_out == 0);
211 TgAssert(strm.avail_in == 0,
212 "un-deflated data left in input buffer in DeflateFile()", NULL);
213 /* make sure that all input are used */
214
215 /* done when last data in file processed */
216 } while (flush != Z_FINISH);
217 EndProgress(&pi);
218
219 TgAssert(ret == Z_STREAM_END,
220 "end-of-stream not detected in DeflateFile()", NULL);
221 /* make sure that stream is complete */
222 deflateEnd(&strm);
223 fclose(in_fp);
224 fclose(out_fp);
225
226 return TRUE;
227 #else /* ~(!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
228 return FALSE;
229 #endif /* (!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
230 }
231
232 /* --------------------- DoDeflate() --------------------- */
233
DoDeflate(in_fp,in_buf,bytes_left,out_fp,use_def_compression,use_byte_stuffing,pn_rc)234 int DoDeflate(in_fp, in_buf, bytes_left, out_fp, use_def_compression, use_byte_stuffing, pn_rc)
235 /*
236 * This function is adapted from <URL:http://www.zlib.net/zpipe.c>
237 *
238 * zpipe.c - example of proper use of zlib's inflate() and deflate()
239 * Not copyrighted -- provided to the public domain
240 * Version 1.4 11 December 2005 Mark Adler
241 */
242 FILE *in_fp, *out_fp;
243 char *in_buf;
244 int bytes_left, use_byte_stuffing, *pn_rc;
245 int use_def_compression; /* always use Z_DEFAULT_COMPRESSION */
246 {
247 #if (!defined(_NO_ZLIB) || defined(HAVE_LIBZ))
248 int level=Z_DEFAULT_COMPRESSION;
249 int ret=0, flush=0;
250 unsigned int block_sz=0x4000;
251 unsigned int have=0;
252 z_stream strm;
253 unsigned char in[0x4000], out[0x4000];
254
255 TgAssert(in_fp == NULL || in_buf == NULL,
256 "in_fp and in_buf cannot be both NULL in DoDeflate()", NULL);
257 /* allocate deflate state */
258 memset(&strm, 0, sizeof(strm));
259 strm.zalloc = Z_NULL;
260 strm.zfree = Z_NULL;
261 strm.opaque = Z_NULL;
262 ret = deflateInit(&strm, level);
263 if (ret != Z_OK) {
264 if (pn_rc != NULL) *pn_rc = ret;
265 return FALSE;
266 }
267 if (in_fp != NULL) rewind(in_fp);
268 rewind(out_fp);
269 do {
270 int bytes_to_read=min(block_sz, bytes_left);
271
272 if (in_fp != NULL) {
273 strm.avail_in = fread(in, 1, bytes_to_read, in_fp);
274 if (ferror(in_fp)) {
275 (void)deflateEnd(&strm);
276 if (pn_rc != NULL) *pn_rc = Z_ERRNO;
277 return FALSE;
278 }
279 } else {
280 memcpy(in, in_buf, bytes_to_read);
281 strm.avail_in = bytes_to_read;
282 }
283 bytes_left -= bytes_to_read;
284
285 flush = (bytes_left == 0) ? Z_FINISH : Z_NO_FLUSH;
286 strm.next_in = in;
287
288 /*
289 * run deflate() on input until output buffer not full, finish compression
290 * if all of in_fp has been read in or in_buf is exhausted
291 */
292 do {
293 strm.avail_out = block_sz;
294 strm.next_out = out;
295 ret = deflate(&strm, flush); /* no bad return value */
296 TgAssert(ret != Z_STREAM_ERROR,
297 "deflate() returns Z_STREAM_ERROR in DoDeflate()", NULL);
298 /* make sure that state is not clobbered */
299 have = block_sz - strm.avail_out;
300
301 if (use_byte_stuffing) {
302 unsigned int have2=0;
303 unsigned char out2[0x8000];
304
305 have2 = 0;
306 ByteStuff(out, have, out2, &have2);
307 if (fwrite(out2, 1, have2, out_fp) != have2 || ferror(out_fp)) {
308 (void)deflateEnd(&strm);
309 if (pn_rc != NULL) *pn_rc = Z_ERRNO;
310 return FALSE;
311 }
312 } else {
313 if (fwrite(out, 1, have, out_fp) != have || ferror(out_fp)) {
314 (void)deflateEnd(&strm);
315 if (pn_rc != NULL) *pn_rc = Z_ERRNO;
316 return FALSE;
317 }
318 }
319 } while (strm.avail_out == 0);
320 TgAssert(strm.avail_in == 0,
321 "un-deflated data left in input buffer in DoDeflate()", NULL);
322 /* make sure that all input are used */
323
324 /* done when last data in file processed */
325 } while (flush != Z_FINISH);
326
327 TgAssert(ret == Z_STREAM_END,
328 "end-of-stream not detected in DoDeflate()", NULL);
329 /* make sure that stream is complete */
330 deflateEnd(&strm);
331
332 return TRUE;
333 #else /* ~(!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
334 return FALSE;
335 #endif /* (!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
336 }
337
338 /* --------------------- DoInflate() --------------------- */
339
DoInflate(in_buf,bytes_left,out_fp,use_byte_unstuffing,pn_rc)340 int DoInflate(in_buf, bytes_left, out_fp, use_byte_unstuffing, pn_rc)
341 /*
342 * This function is adapted from <URL:http://www.zlib.net/zpipe.c>
343 *
344 * zpipe.c - example of proper use of zlib's inflate() and deflate()
345 * Not copyrighted -- provided to the public domain
346 * Version 1.4 11 December 2005 Mark Adler
347 */
348 char *in_buf;
349 int bytes_left, use_byte_unstuffing, *pn_rc;
350 FILE *out_fp;
351 {
352 #if (!defined(_NO_ZLIB) || defined(HAVE_LIBZ))
353 int ret=0, has_left_over=FALSE;
354 unsigned int block_sz=0x4000;
355 unsigned int have=0;
356 z_stream strm;
357 unsigned char in[0x4000], out[0x4000];
358
359 /* allocate inflate state */
360 memset(&strm, 0, sizeof(strm));
361 strm.zalloc = Z_NULL;
362 strm.zfree = Z_NULL;
363 strm.opaque = Z_NULL;
364 strm.avail_in = 0;
365 strm.next_in = Z_NULL;
366 ret = inflateInit(&strm);
367 if (ret != Z_OK) {
368 if (pn_rc != NULL) *pn_rc = ret;
369 return FALSE;
370 }
371 rewind(out_fp);
372 /* decompress until deflate stream ends or end of file */
373 do {
374 int bytes_to_read=min(block_sz, bytes_left), bytes_to_read2=0;
375 unsigned char in2[0x4000];
376
377 if (bytes_to_read == 0) break;
378 memcpy(in, in_buf, bytes_to_read);
379
380 bytes_left -= bytes_to_read;
381 in_buf += bytes_to_read;
382
383 if (use_byte_unstuffing) {
384 if (!ByteUnStuff(in, bytes_to_read, in2, &bytes_to_read2,
385 &has_left_over)) {
386 (void)inflateEnd(&strm);
387 if (pn_rc != NULL) *pn_rc = Z_DATA_ERROR;
388 return FALSE;
389 }
390 strm.avail_in = bytes_to_read2;
391 strm.next_in = in2;
392 } else {
393 strm.avail_in = bytes_to_read;
394 strm.next_in = in;
395 }
396 /* run inflate() on input until output buffer not full */
397 do {
398 strm.avail_out = block_sz;
399 strm.next_out = out;
400 ret = inflate(&strm, Z_NO_FLUSH);
401 TgAssert(ret != Z_STREAM_ERROR,
402 "inflate() returns Z_STREAM_ERROR in DoInflate()", NULL);
403 /* make sure that state is not clobbered */
404 switch (ret) {
405 case Z_NEED_DICT:
406 ret = Z_DATA_ERROR; /* and fall through */
407 case Z_DATA_ERROR:
408 case Z_MEM_ERROR:
409 (void)inflateEnd(&strm);
410 if (pn_rc != NULL) *pn_rc = ret;
411 return FALSE;
412 }
413 have = block_sz - strm.avail_out;
414
415 if (fwrite(out, 1, have, out_fp) != have || ferror(out_fp)) {
416 (void)inflateEnd(&strm);
417 if (pn_rc != NULL) *pn_rc = Z_ERRNO;
418 return FALSE;
419 }
420 } while (strm.avail_out == 0);
421
422 /* done when inflate() says it's done */
423 } while (ret != Z_STREAM_END);
424
425 if (has_left_over) {
426 (void)inflateEnd(&strm);
427 if (pn_rc != NULL) *pn_rc = Z_DATA_ERROR;
428 return FALSE;
429 }
430 /* clean up and return */
431 inflateEnd(&strm);
432
433 if (ret == Z_STREAM_END) {
434 return TRUE;
435 }
436 if (pn_rc != NULL) *pn_rc = Z_DATA_ERROR;
437 return FALSE;
438 #else /* ~(!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
439 return FALSE;
440 #endif /* (!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
441 }
442
443 /* --------------------- InflateInit() --------------------- */
444
445 /* --------------------- ZlibError() --------------------- */
446
ZlibError(status,deflate)447 void ZlibError(status, deflate)
448 int status, deflate;
449 {
450 #if (!defined(_NO_ZLIB) || defined(HAVE_LIBZ))
451 char buf[MAXSTRING];
452
453 switch (status) {
454 case Z_ERRNO:
455 snprintf(buf, sizeof(buf), "%s-%s.",
456 "File I/O error during z",
457 deflate ? "compression" : "decompression");
458 break;
459 case Z_STREAM_ERROR:
460 snprintf(buf, sizeof(buf), "%s-%s.",
461 "Invalid compression level used for z",
462 deflate ? "compression" : "decompression");
463 break;
464 case Z_DATA_ERROR:
465 snprintf(buf, sizeof(buf), "%s-%s.",
466 "Corrupted data encountered during z",
467 deflate ? "compression" : "decompression");
468 break;
469 case Z_MEM_ERROR:
470 snprintf(buf, sizeof(buf), "%s-%s.", "Out of memory during z",
471 deflate ? "compression" : "decompression");
472 break;
473 case Z_VERSION_ERROR:
474 snprintf(buf, sizeof(buf), "%s-%s.", "Zlib version mismatch for z",
475 deflate ? "compression" : "decompression");
476 break;
477 }
478 if (deflate) {
479 snprintf(gszMsgBox, sizeof(gszMsgBox), "%s\n\n%s", buf,
480 "Continue without z-compression.");
481 } else {
482 UtilStrCpyN(gszMsgBox, sizeof(gszMsgBox), buf);
483 }
484 if (PRTGIF && !cmdLineOpenDisplay) {
485 fprintf(stderr, "%s\n", gszMsgBox);
486 } else {
487 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
488 }
489 #endif /* (!defined(_NO_ZLIB) || defined(HAVE_LIBZ)) */
490 }
491
492