From 2597722d7aa1be523058bc8449120d32768f44b3 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Tue, 28 Aug 2012 17:34:23 +0200 Subject: Add fz_open_document_with_stream function. Use a "magic" string for filetype detection: filename or mime-type. --- cbz/mucbz.c | 5 ++--- cbz/mucbz.h | 2 +- fitz/doc_document.c | 58 ++++++++++++++++++++++++++++++++++++++-------------- fitz/fitz.h | 10 +++++++++ pdf/mupdf-internal.h | 2 +- pdf/mupdf.h | 2 +- pdf/pdf_xref.c | 9 ++++---- pdf/pdf_xref_aux.c | 4 ++-- xps/muxps.h | 2 +- xps/xps_zip.c | 5 ++--- 10 files changed, 67 insertions(+), 32 deletions(-) diff --git a/cbz/mucbz.c b/cbz/mucbz.c index df6be18f..8dc08798 100644 --- a/cbz/mucbz.c +++ b/cbz/mucbz.c @@ -285,9 +285,8 @@ cbz_read_zip_dir(cbz_document *doc) } cbz_document * -cbz_open_document_with_stream(fz_stream *file) +cbz_open_document_with_stream(fz_context *ctx, fz_stream *file) { - fz_context *ctx = file->ctx; cbz_document *doc; doc = fz_malloc_struct(ctx, cbz_document); @@ -323,7 +322,7 @@ cbz_open_document(fz_context *ctx, char *filename) fz_throw(ctx, "cannot open file '%s': %s", filename, strerror(errno)); fz_try(ctx) { - doc = cbz_open_document_with_stream(file); + doc = cbz_open_document_with_stream(ctx, file); } fz_always(ctx) { fz_close(file); } fz_catch(ctx) { diff --git a/cbz/mucbz.h b/cbz/mucbz.h index 080423bf..05288eb3 100644 --- a/cbz/mucbz.h +++ b/cbz/mucbz.h @@ -30,7 +30,7 @@ cbz_document *cbz_open_document(fz_context *ctx, char *filename); fz_open_file_w or fz_open_fd for opening a stream, and fz_close for closing an open stream. */ -cbz_document *cbz_open_document_with_stream(fz_stream *file); +cbz_document *cbz_open_document_with_stream(fz_context *ctx, fz_stream *file); /* cbz_close_document: Closes and frees an opened document. diff --git a/fitz/doc_document.c b/fitz/doc_document.c index 1233aeb9..eb50285b 100644 --- a/fitz/doc_document.c +++ b/fitz/doc_document.c @@ -5,6 +5,11 @@ extern struct pdf_document *pdf_open_document(fz_context *ctx, char *filename); extern struct xps_document *xps_open_document(fz_context *ctx, char *filename); extern struct cbz_document *cbz_open_document(fz_context *ctx, char *filename); +extern struct pdf_document *pdf_open_document_with_stream(fz_context *ctx, fz_stream *file); +extern struct xps_document *xps_open_document_with_stream(fz_context *ctx, fz_stream *file); +extern struct cbz_document *cbz_open_document_with_stream(fz_context *ctx, fz_stream *file); + + static inline int fz_tolower(int c) { if (c >= 'A' && c <= 'Z') @@ -23,26 +28,49 @@ static inline int fz_strcasecmp(char *a, char *b) return fz_tolower(*a) - fz_tolower(*b); } +fz_document * +fz_open_document_with_stream(fz_context *ctx, char *magic, fz_stream *stream) +{ + char *ext = strrchr(magic, '.'); + + if (ext) + { + if (!fz_strcasecmp(ext, ".xps") || !fz_strcasecmp(ext, ".rels")) + return (fz_document*) xps_open_document_with_stream(ctx, stream); + if (!fz_strcasecmp(ext, ".cbz") || !fz_strcasecmp(ext, ".zip")) + return (fz_document*) cbz_open_document_with_stream(ctx, stream); + if (!fz_strcasecmp(ext, ".pdf")) + return (fz_document*) pdf_open_document_with_stream(ctx, stream); + } + + if (!strcmp(magic, "cbz") || !strcmp(magic, "application/x-cbz")) + return (fz_document*) cbz_open_document_with_stream(ctx, stream); + if (!strcmp(magic, "xps") || !strcmp(magic, "application/vnd.ms-xpsdocument")) + return (fz_document*) xps_open_document_with_stream(ctx, stream); + if (!strcmp(magic, "pdf") || !strcmp(magic, "application/pdf")) + return (fz_document*) pdf_open_document_with_stream(ctx, stream); + + /* last guess: pdf */ + return (fz_document*) pdf_open_document_with_stream(ctx, stream); +} + fz_document * fz_open_document(fz_context *ctx, char *filename) { char *ext = strrchr(filename, '.'); - if (ext && (!fz_strcasecmp(ext, ".xps") || !fz_strcasecmp(ext, ".rels"))) - return (fz_document*) xps_open_document(ctx, filename); - if (ext && !fz_strcasecmp(ext, ".cbz")) - return (fz_document*) cbz_open_document(ctx, filename); -#if 0 - /* We used to only open pdf files if they ended in .pdf. For now, - * until we move to detecting filetypes by their content, we disable - * this code, and assume that any file that hasn't matched an - * extension already, is a PDF. */ - if (ext && !fz_strcasecmp(ext, ".pdf")) - return (fz_document*) pdf_open_document(ctx, filename); - fz_throw(ctx, "unknown document type: '%s'", filename); - return NULL; -#else + + if (ext) + { + if (!fz_strcasecmp(ext, ".xps") || !fz_strcasecmp(ext, ".rels")) + return (fz_document*) xps_open_document(ctx, filename); + if (!fz_strcasecmp(ext, ".cbz") || !fz_strcasecmp(ext, ".zip")) + return (fz_document*) cbz_open_document(ctx, filename); + if (!fz_strcasecmp(ext, ".pdf")) + return (fz_document*) pdf_open_document(ctx, filename); + } + + /* last guess: pdf */ return (fz_document*) pdf_open_document(ctx, filename); -#endif } void diff --git a/fitz/fitz.h b/fitz/fitz.h index b4e7cee4..96cd69a8 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -2142,6 +2142,16 @@ typedef struct fz_page_s fz_page; */ fz_document *fz_open_document(fz_context *ctx, char *filename); +/* + fz_open_document_with_stream: Open a PDF, XPS or CBZ document. + + Open a document using the specified stream object rather than + opening a file on disk. + + magic: a string used to detect document type; either a file name or mime-type. +*/ +fz_document *fz_open_document_with_stream(fz_context *ctx, char *magic, fz_stream *stream); + /* fz_close_document: Close and free an open document. diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h index efd9e109..1aca4aa2 100644 --- a/pdf/mupdf-internal.h +++ b/pdf/mupdf-internal.h @@ -206,7 +206,7 @@ struct pdf_document_s }; pdf_document *pdf_open_document_no_run(fz_context *ctx, const char *filename); -pdf_document *pdf_open_document_no_run_with_stream(fz_stream *file); +pdf_document *pdf_open_document_no_run_with_stream(fz_context *ctx, fz_stream *file); void pdf_cache_object(pdf_document *doc, int num, int gen); diff --git a/pdf/mupdf.h b/pdf/mupdf.h index 6ebe4437..8e536777 100644 --- a/pdf/mupdf.h +++ b/pdf/mupdf.h @@ -167,7 +167,7 @@ pdf_document *pdf_open_document(fz_context *ctx, const char *filename); fz_open_file_w or fz_open_fd for opening a stream, and fz_close for closing an open stream. */ -pdf_document *pdf_open_document_with_stream(fz_stream *file); +pdf_document *pdf_open_document_with_stream(fz_context *ctx, fz_stream *file); /* pdf_close_document: Closes and frees an opened PDF document. diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c index 050a6f53..37cc2081 100644 --- a/pdf/pdf_xref.c +++ b/pdf/pdf_xref.c @@ -1307,9 +1307,8 @@ static int pdf_meta_shim(fz_document *doc, int key, void *ptr, int size) } static pdf_document * -pdf_new_document(fz_stream *file) +pdf_new_document(fz_context *ctx, fz_stream *file) { - fz_context *ctx = file->ctx; pdf_document *doc = fz_malloc_struct(ctx, pdf_document); doc->super.close = pdf_close_document_shim; @@ -1332,9 +1331,9 @@ pdf_new_document(fz_stream *file) } pdf_document * -pdf_open_document_no_run_with_stream(fz_stream *file) +pdf_open_document_no_run_with_stream(fz_context *ctx, fz_stream *file) { - pdf_document *doc = pdf_new_document(file); + pdf_document *doc = pdf_new_document(ctx, file); pdf_init_document(doc); return doc; } @@ -1350,7 +1349,7 @@ pdf_open_document_no_run(fz_context *ctx, const char *filename) fz_try(ctx) { file = fz_open_file(ctx, filename); - doc = pdf_new_document(file); + doc = pdf_new_document(ctx, file); pdf_init_document(doc); } fz_always(ctx) diff --git a/pdf/pdf_xref_aux.c b/pdf/pdf_xref_aux.c index 907e6f17..bf2fe19b 100644 --- a/pdf/pdf_xref_aux.c +++ b/pdf/pdf_xref_aux.c @@ -15,9 +15,9 @@ static void pdf_run_page_shim(fz_document *doc, fz_page *page, fz_device *dev, f } pdf_document * -pdf_open_document_with_stream(fz_stream *file) +pdf_open_document_with_stream(fz_context *ctx, fz_stream *file) { - pdf_document *doc = pdf_open_document_no_run_with_stream(file); + pdf_document *doc = pdf_open_document_no_run_with_stream(ctx, file); doc->super.run_page = pdf_run_page_shim; return doc; } diff --git a/xps/muxps.h b/xps/muxps.h index 128ed35f..8ec577af 100644 --- a/xps/muxps.h +++ b/xps/muxps.h @@ -45,7 +45,7 @@ xps_document *xps_open_document(fz_context *ctx, char *filename); fz_open_file_w or fz_open_fd for opening a stream, and fz_close for closing an open stream. */ -xps_document *xps_open_document_with_stream(fz_stream *file); +xps_document *xps_open_document_with_stream(fz_context *ctx, fz_stream *file); /* xps_close_document: Closes and frees an opened document. diff --git a/xps/xps_zip.c b/xps/xps_zip.c index 099bbf46..e0d1eae9 100644 --- a/xps/xps_zip.c +++ b/xps/xps_zip.c @@ -576,9 +576,8 @@ xps_open_document_with_directory(fz_context *ctx, char *directory) } xps_document * -xps_open_document_with_stream(fz_stream *file) +xps_open_document_with_stream(fz_context *ctx, fz_stream *file) { - fz_context *ctx = file->ctx; xps_document *doc; doc = fz_malloc_struct(ctx, xps_document); @@ -624,7 +623,7 @@ xps_open_document(fz_context *ctx, char *filename) fz_try(ctx) { - doc = xps_open_document_with_stream(file); + doc = xps_open_document_with_stream(ctx, file); } fz_always(ctx) { -- cgit v1.2.3 From d2aefcfff6ef57fadcce87e61f844efe85f73d58 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Thu, 16 Aug 2012 15:18:44 +0200 Subject: Handle missing clear codes in LZW. Previously if the lookup table was full and no clear code appeared the decoder would try to add more entries to the table. However the table is of fixed size (4096 entries) so it would write outside the table. Fix this by detecting when the lookup table is full and a clear code ought to appear. At this point the decoder will now treat and process any code as a clear code. For valid documents this will never happen, for invalid documents this means risking that succeeding codes may be misinterpreted and that the decoded data will be incorrect, this case should be handled by the consumer of the data though. Fixes bug 693306. --- fitz/filt_lzwd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fitz/filt_lzwd.c b/fitz/filt_lzwd.c index 3ee4d34c..b1aa4421 100644 --- a/fitz/filt_lzwd.c +++ b/fitz/filt_lzwd.c @@ -80,6 +80,12 @@ read_lzwd(fz_stream *stm, unsigned char *buf, int len) break; } + if (next_code >= NUM_CODES && code != LZW_CLEAR) + { + fz_warn(stm->ctx, "missing clear code in lzw decode"); + code = LZW_CLEAR; + } + if (code == LZW_CLEAR) { code_bits = MIN_BITS; @@ -112,7 +118,7 @@ read_lzwd(fz_stream *stm, unsigned char *buf, int len) { code_bits ++; if (code_bits > MAX_BITS) - code_bits = MAX_BITS; /* FIXME */ + code_bits = MAX_BITS; } old_code = code; -- cgit v1.2.3