ref: d53ab5a9d654df525f522afb43c6afeb6c1b6d4b
parent: 778b53afed3f8cd0caa85d81a3f1fd0a3a35c446
author: giles <giles@ded80894-8fb9-0310-811b-c03f3676ab4d>
date: Mon Jul 15 16:01:01 EDT 2002
Add a '--hash' cmdline option to print the SHA-1 hash of the decoded document. Useful for regression testing. We currently use the openssl/ libcrypto implemention; there's provision for fallback to a local version but I've not written one yet. It should probably just be the default once provided. git-svn-id: http://svn.ghostscript.com/jbig2dec/trunk@138 ded80894-8fb9-0310-811b-c03f3676ab4d
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
AM_INIT_AUTOMAKE([AC_PACKAGE_NAME], [AC_PACKAGE_VERSION])
AM_CONFIG_HEADER(config.h)
-AC_REVISION([$Revision: 1.8 $])
+AC_REVISION([$Revision: 1.9 $])
# Checks for programs.
AC_PROG_CC
@@ -96,6 +96,27 @@
AC_FUNC_MEMCMP
AC_CHECK_FUNCS([memset strdup])
+dnl use our included md5 if we can't find one
+AC_CHECK_HEADER([openssl/md5.h], [
+ AC_CHECK_LIB(crypto, MD5_Init, [
+ AC_DEFINE(HAVE_OPENSSL_MD5,,[Define to use of the
+ MD5_*() routines from OpenSSL rather than the included ones])
+ LIBS="$LIBS -lcrypto"
+ ], [
+ AC_LIBOBJ([md5])
+ ])
+],,[ ])
+
+dnl use our included SHA-1 if we can't find one
+AC_CHECK_HEADER([openssl/sha.h], [
+ AC_CHECK_LIB(crypto, SHA1_Init, [
+ AC_DEFINE(HAVE_OPENSSL_SHA1,,[Define to use of the
+ SHA1_*() routines from OpenSSL rather than the included ones])
+ ], [
+ AC_LIBOBJ([sha1])
+ ])
+],,[ ])
+
dnl use our included getopt if the system doesn't have getopt_long()
AC_CHECK_FUNC(getopt_long,
[AC_DEFINE(HAVE_GETOPT_LONG,,[Define if the local libc includes getopt_long()])],
--- a/jbig2dec.c
+++ b/jbig2dec.c
@@ -8,7 +8,7 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
- $Id: jbig2dec.c,v 1.31 2002/07/13 00:32:13 giles Exp $
+ $Id: jbig2dec.c,v 1.32 2002/07/15 20:01:01 giles Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -22,10 +22,13 @@
#endif
#include <stdio.h>
-# include <stdlib.h>
-# include <stddef.h>
-# include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include "jbig2.h"
+#include "jbig2_image.h"
+
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#else
@@ -32,8 +35,9 @@
# include "getopt.h"
#endif
-#include "jbig2.h"
-#include "jbig2_image.h"
+#ifdef HAVE_OPENSSL_SHA1
+# include <openssl/sha.h>
+#endif
typedef enum {
usage,dump,render
@@ -41,38 +45,67 @@
typedef struct {
jbig2dec_mode mode;
- int verbose;
+ int verbose, hash;
+#ifdef HAVE_OPENSSL_SHA1
+ SHA_CTX *hash_ctx;
+#endif
char *output_file;
} jbig2dec_params_t;
+/* page hashing functions */
+static void
+hash_init(jbig2dec_params_t *params)
+{
+#ifdef HAVE_OPENSSL_SHA1
+ params->hash_ctx = malloc(sizeof(SHA_CTX));
+ if (params->hash == NULL) {
+ fprintf(stderr, "unable to allocate hash state\n");
+ params->hash = 0;
+ return;
+ } else {
+ SHA1_Init(params->hash_ctx);
+ }
+#endif /* HAVE_OPENSSL_SHA1 */
+}
-static int
-print_usage (void)
+static void
+hash_image(jbig2dec_params_t *params, Jbig2Image *image)
{
- fprintf(stderr,
- "Usage: jbig2dec [options] <file.jbig2>\n"
- " or jbig2dec [options] <global_stream> <page_stream>\n"
- "\n"
- " When invoked with a single file, it attempts to parse it as\n"
- " a normal jbig2 file. Invoked with two files, it treats the\n"
- " first as the global segments, and the second as the segment\n"
- " stream for a particular page. This is useful for examining\n"
- " embedded streams.\n"
- "\n"
- " available options:\n"
- " -h --help this usage summary\n"
- " -q --quiet suppress diagnostic output\n"
- " -d --dump print the structure of the jbig2 file\n"
- " rather than explicitly decoding\n"
- " -o <file> send decoded output to <file>\n"
- " Defaults to the the input with a different\n"
- " extension. Pass '-' for stdout.\n"
- "\n"
- );
-
- return 1;
+ int N = image->stride * image->height;
+#ifdef HAVE_OPENSSL_SHA1
+ SHA1_Update(params->hash_ctx, image->data, N);
+#endif
}
+static void
+hash_print(jbig2dec_params_t *params, FILE *out)
+{
+#ifdef HAVE_OPENSSL_SHA1
+ char md[SHA_DIGEST_LENGTH];
+ char digest[2*SHA_DIGEST_LENGTH + 1];
+ int i;
+
+ SHA1_Final(md, params->hash_ctx);
+ for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+ snprintf(&(digest[2*i]), 3, "%02x", md[i]);
+ }
+ fprintf(out, "%s", digest);
+#else
+ fprintf(out, "sorry, hash function unimplemented");
+#endif
+}
+
+static void
+hash_free(jbig2dec_params_t *params)
+{
+#ifdef HAVE_OPENSSL_SHA1
+ // FIXME: need to check for SHA1 finalization?
+ free(params->hash_ctx);
+ params->hash_ctx = NULL;
+#endif
+}
+
+
static int
parse_options(int argc, char *argv[], jbig2dec_params_t *params)
{
@@ -80,6 +113,7 @@
{"quiet", 0, NULL, 'q'},
{"help", 0, NULL, 'h'},
{"dump", 0, NULL, 'd'},
+ {"hash", 0, NULL, 'm'},
{"output", 1, NULL, 'o'},
{NULL, 0, NULL, 0}
};
@@ -108,6 +142,9 @@
case 'd':
params->mode=dump;
break;
+ case 'm':
+ params->hash = 1;
+ break;
case 'o':
params->output_file = strdup(optarg);
break;
@@ -117,10 +154,36 @@
break;
}
}
- fprintf(stderr, "final option index %d out of %d\n", optind, argc);
return (optind);
}
+static int
+print_usage (void)
+{
+ fprintf(stderr,
+ "Usage: jbig2dec [options] <file.jbig2>\n"
+ " or jbig2dec [options] <global_stream> <page_stream>\n"
+ "\n"
+ " When invoked with a single file, it attempts to parse it as\n"
+ " a normal jbig2 file. Invoked with two files, it treats the\n"
+ " first as the global segments, and the second as the segment\n"
+ " stream for a particular page. This is useful for examining\n"
+ " embedded streams.\n"
+ "\n"
+ " available options:\n"
+ " -h --help this usage summary\n"
+ " -q --quiet suppress diagnostic output\n"
+ " -d --dump print the structure of the jbig2 file\n"
+ " rather than explicitly decoding\n"
+ " --hash print a hash of the decode document\n"
+ " -o <file> send decoded output to <file>\n"
+ " Defaults to the the input with a different\n"
+ " extension. Pass '-' for stdout.\n"
+ "\n"
+ );
+
+ return 1;
+}
static int
error_callback(void *error_callback_data, const char *buf, Jbig2Severity severity,
@@ -197,7 +260,7 @@
static int
write_page_image(jbig2dec_params_t *params, Jbig2Image *image)
{
- if (!strcmp(params->output_file, "-"))
+ if (!strncmp(params->output_file, "-", 2))
{
fprintf(stderr, "writing decoded page to stdout\n");
#ifdef HAVE_LIBPNG
@@ -219,6 +282,24 @@
return 0;
}
+static int
+write_document_hash(jbig2dec_params_t *params)
+{
+ FILE *out;
+
+ if (!strncmp(params->output_file, "-", 2)) {
+ out = stderr;
+ } else {
+ out = stdout;
+ }
+
+ fprintf(out, "Hash of decoded document: ");
+ hash_print(params, out);
+ fprintf(out, "\n");
+
+ return 0;
+}
+
int
main (int argc, char **argv)
{
@@ -225,11 +306,19 @@
FILE *f = NULL, *f_page = NULL;
Jbig2Ctx *ctx;
uint8_t buf[4096];
- jbig2dec_params_t params = {render,1,NULL};
+ jbig2dec_params_t params;
int filearg;
+
+ // set defaults
+ params.mode = render;
+ params.verbose = 1;
+ params.hash = 0;
+ params.output_file = NULL;
filearg = parse_options(argc, argv, ¶ms);
+ if (params.hash) hash_init(¶ms);
+
switch (params.mode) {
case usage:
print_usage();
@@ -310,7 +399,7 @@
// retrieve and output the returned pages
{
Jbig2Image *image;
-
+
/* work around broken CVision embedded streams */
if (f_page != NULL)
jbig2_complete_page(ctx);
@@ -327,13 +416,17 @@
/* retrieve and write out all the completed pages */
while ((image = jbig2_page_out(ctx)) != NULL) {
write_page_image(¶ms, image);
+ if (params.hash) hash_image(¶ms, image);
jbig2_release_page(ctx, image);
}
+ if (params.hash) write_document_hash(¶ms);
}
jbig2_ctx_free(ctx);
} /* end params.mode switch */
+
+ if (params.hash) hash_free(¶ms);
// fin
return 0;