Please review and apply. Brad
# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: [email protected]\ # y5gf78gg8ikjninq # target_branch: http://bzr.savannah.gnu.org/r/pdf/libgnupdf/branches\ # /trunk/ # testament_sha1: c3f32e22f4dfec978346a8b02342bce73053a2a2 # timestamp: 2009-06-24 20:21:51 +1000 # base_revision_id: [email protected] # # Begin patch === modified file 'AUTHORS' --- AUTHORS 2009-06-22 11:20:04 +0000 +++ AUTHORS 2009-06-23 03:16:51 +0000 @@ -82,7 +82,13 @@ m4/MANIFEST.wiki prmgt/MANIFEST.wiki src/MANIFEST.wiki + src/Makefile.am src/README + src/base/pdf-stm-f-ahex.c + src/base/pdf-stm-f-lzw.c + src/base/pdf-stm-f-lzw.h + src/base/pdf-stm-filter.c + src/base/pdf-stm-filter.h src/base/pdf-text.c src/base/pdf-time.c src/object/MANIFEST.wiki @@ -92,6 +98,7 @@ torture/unit/base/time/pdf-time-copy.c torture/unit/base/crypt/pdf-crypt-md-new.c torture/unit/base/crypt/pdf-crypt-md-read.c + torture/unit/base/stm/pdf-stm-write.c torture/unit/base/text/pdf-text-dup.c torture/unit/base/text/pdf-text-new-destroy.c torture/unit/base/text/pdf-text-new-from-host.c
=== modified file 'ChangeLog' --- ChangeLog 2009-06-22 11:20:04 +0000 +++ ChangeLog 2009-06-23 03:16:51 +0000 @@ -1,3 +1,18 @@ +2009-06-23 Brad Hards <[email protected]> + + * src/base/pdf-stm-f-lzw.c: initial port of LZW filter to new API + * src/base/pdf-stm-f-lzw.h: likewise + * src/base/pdf-stm-filter.c: likewise + * src/base/pdf-stm-filter.h: likewise + * src/Makefile.am: integrate pdf-stm-f-lzw.[c,h] back into build + system + * torture/unit/base/stm/pdf-stm-write.c: add test case from PDF + specification version 1.7. + + * src/base/pdf-stm-f-ahex.c (pdf_stm_f_ahexdec_dealloc_state): Use + pdf_stm_f_ahexdec_t instead of pdf_stm_f_ahexenc_t. Update variable + names to match. + 2009-06-22 Brad Hards <[email protected]> * src/base/pdf-text.c (pdf_text_dup): Protect against NULL arg. === modified file 'src/Makefile.am' --- src/Makefile.am 2009-05-20 15:54:43 +0000 +++ src/Makefile.am 2009-06-23 03:16:51 +0000 @@ -46,7 +46,8 @@ base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c \ base/pdf-stm-f-v2.h base/pdf-stm-f-v2.c \ base/pdf-stm-f-aesv2.h base/pdf-stm-f-aesv2.c \ - base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c + base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c \ + base/pdf-stm-f-lzw.h base/pdf-stm-f-lzw.c if ZLIB STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h @@ -115,7 +116,7 @@ libgnupdf_la_LDFLAGS = -no-undefined endif -AM_CFLAGS = -Wall -fno-strict-aliasing $(LIBGCRYPT_CFLAGS) +AM_CFLAGS = -Wall -fno-strict-aliasing -Wconversion $(LIBGCRYPT_CFLAGS) if USE_COVERAGE AM_CFLAGS += -fprofile-arcs -ftest-coverage endif === modified file 'src/base/pdf-stm-f-ahex.c' --- src/base/pdf-stm-f-ahex.c 2009-05-07 09:03:31 +0000 +++ src/base/pdf-stm-f-ahex.c 2009-06-22 22:03:57 +0000 @@ -308,10 +308,10 @@ pdf_status_t pdf_stm_f_ahexdec_dealloc_state (void *state) { - pdf_stm_f_ahexenc_t ahexenc_state; + pdf_stm_f_ahexdec_t ahexdec_state; - ahexenc_state = (pdf_stm_f_ahexenc_t) state; - pdf_dealloc (ahexenc_state); + ahexdec_state = (pdf_stm_f_ahexdec_t) state; + pdf_dealloc (ahexdec_state); return PDF_OK; } === modified file 'src/base/pdf-stm-f-lzw.c' --- src/base/pdf-stm-f-lzw.c 2009-01-11 21:37:29 +0000 +++ src/base/pdf-stm-f-lzw.c 2009-06-24 09:57:17 +0000 @@ -3,7 +3,7 @@ * File: pdf-stm-f-lzw.c * Date: Wed Aug 15 14:41:18 2007 * - * GNU PDF Library - LWZ encoder/decoder filter + * GNU PDF Library - LZW encoder/decoder filter * */ @@ -25,86 +25,114 @@ #include <string.h> #include <pdf-alloc.h> +#include <pdf-hash-helper.h> #include <pdf-stm-f-lzw.h> -#define MIN_BITSIZE 9 -#define MAX_BITSIZE 12 +#define NULL_INDEX ~0U + +#define MIN_BITSIZE 9 +#define MAX_BITSIZE 12 #define MAX_DICTSIZE (1 << MAX_BITSIZE) -#define MAX_COMPRESSION_FACTOR 1.5 - -#define NULL_INDEX ~0U - -enum { - LZW_RESET_CODE = 256, - LZW_EOD_CODE, - LZW_FIRST_CODE -} lzw_special_codes; - - - -/* -- LZW code output/input -- */ +static const int LZW_RESET_CODE = 256; +static const int LZW_EOD_CODE = 257; +static const int LZW_FIRST_CODE = 258; + +static const pdf_real_t MAX_COMPRESSION_FACTOR = 1.5; + +enum pdf_stm_f_lzw_mode_t { + PDF_STM_F_LZW_MODE_ENCODE, + PDF_STM_F_LZW_MODE_DECODE +}; /* - * Object to read and write codes of variable bitsize in a buffer. - * Warning: using both get and put functions may break the buffer. + * The strings are stored in a non balanced ordered binary tree. */ +typedef struct lzw_string_s +{ + unsigned prefix; /* Prefix string code */ + pdf_char_t suffix; /* Appended character */ + + unsigned first; /* First string with the same prefix. */ + unsigned left; /* Next string with smaller suffix and same prefix. */ + unsigned right; /* Next string with greater suffix and same prefix. */ +} lzw_string_t; + +typedef struct lzw_dict_s +{ + lzw_string_t table[MAX_DICTSIZE]; + unsigned int size; +} lzw_dict_t; + +struct pdf_stm_f_lzw_data_s +{ + enum pdf_stm_f_lzw_mode_t mode; /* encoding or decoding? */ + unsigned int early_change; +}; + +typedef struct pdf_stm_f_lzw_data_s *pdf_stm_f_lzw_data_t; + typedef struct lzw_buffer_s { - pdf_char_t* curp; - pdf_char_t* endp; - unsigned long valbuf; + pdf_buffer_t data; /* out for encode, in for decode */ + pdf_u32_t valbuf; unsigned valbits; unsigned bitsize; unsigned maxval; } lzw_buffer_t; static void -lzw_buffer_init (lzw_buffer_t* b, - pdf_char_t* ptr, - int size, - int bitsize) +lzw_buffer_init (lzw_buffer_t* buf, + pdf_buffer_t data, + unsigned int bitsize) { - b->curp = ptr; - b->endp = ptr + size; - b->valbuf = 0; - b->valbits = 0; - b->bitsize = bitsize; - b->maxval = (1 << bitsize) - 1; + buf->data = data; + buf->valbuf = 0; + buf->valbits = 0; + buf->bitsize = bitsize; + buf->maxval = (1U << bitsize) - 1; } static unsigned int lzw_buffer_get_code (lzw_buffer_t* b) { - unsigned long r; - + pdf_u32_t r; + pdf_buffer_t in = b->data; + while (b->valbits <= 24) { - if (b->curp > b->endp) + if (in->rp > in->wp) return NULL_INDEX; - b->valbuf |= (unsigned long) *b->curp++ << (24 - b->valbits); + b->valbuf |= (in->data[in->rp]) << (24 - b->valbits); + ++(in->rp); b->valbits += 8; } r = b->valbuf >> (32 - b->bitsize); b->valbuf <<= b->bitsize; b->valbits -= b->bitsize; - + return r; } -/* Once finished, call with 0 as code value to flush the buffer. */ static void lzw_buffer_put_code (lzw_buffer_t* b, unsigned int code) { - b->valbuf |= (unsigned long) code << (32 - b->bitsize - b->valbits); + pdf_buffer_t out = b->data; + + b->valbuf |= code << (32 - b->bitsize - b->valbits); b->valbits += b->bitsize; while (b->valbits >= 8) { - *b->curp++ = b->valbuf >> 24; + if (pdf_buffer_full_p(out)) + { + return; + } + out->data[out->wp] = (pdf_char_t)(b->valbuf >> 24); + ++(out->wp); b->valbuf <<= 8; b->valbits -= 8; } @@ -117,58 +145,38 @@ return PDF_ERROR; ++b->bitsize; - b->maxval = (1 << b->bitsize) - 1; + b->maxval = (1U << b->bitsize) - 1; return PDF_OK; } static void lzw_buffer_set_bitsize (lzw_buffer_t* b, - int newsize) + unsigned int newsize) { b->bitsize = newsize; - b->maxval = (1 << newsize) - 1; + b->maxval = (1U << newsize) - 1; } /* -- LZW dictionary handler -- */ -/* - * The strings are stored in a non balanced ordered binary tree. - */ -typedef struct lzw_string_s -{ - unsigned prefix; /* Prefix string code */ - pdf_char_t suffix; /* Appended character */ - - unsigned first; /* First string with the same prefix. */ - unsigned left; /* Next string with smaller suffix and same prefix. */ - unsigned right; /* Next string with greater suffix and same prefix. */ -} lzw_string_t; - static void lzw_string_init (lzw_string_t* s) { memset(s, 0xFF, sizeof(lzw_string_t)); } - -typedef struct lzw_dict_s -{ - lzw_string_t table[MAX_DICTSIZE]; - unsigned size; -} lzw_dict_t; - static void lzw_dict_init (lzw_dict_t* d) { int i; - + memset(d->table, 0xFF, sizeof(lzw_string_t) * MAX_DICTSIZE); for (i = 0; i < LZW_FIRST_CODE; i++) { - d->table[i].suffix = i; + d->table[i].suffix = (pdf_char_t) (i & 0xFF); } d->size = LZW_FIRST_CODE; @@ -176,11 +184,11 @@ static int lzw_dict_add (lzw_dict_t* d, - lzw_string_t* s) + lzw_string_t* s) { unsigned index; int must_add; - + if (s->prefix == NULL_INDEX) { s->prefix = s->suffix; @@ -264,170 +272,152 @@ } -/* -- The encoder -- */ - -static int -pdf_stm_f_lzw_encode (pdf_stm_f_lzw_data_t data, - pdf_char_t *in, - pdf_stm_pos_t in_size, - pdf_char_t **out, - pdf_stm_pos_t *out_size) -{ +pdf_status_t +pdf_stm_f_lzw_common_init (pdf_hash_t params, + void **state, + enum pdf_stm_f_lzw_mode_t mode) +{ + pdf_stm_f_lzw_data_t lzw_filter_state; + pdf_char_t *early_change_str; + + if (state == NULL) + { + return PDF_EBADDATA; + } + + lzw_filter_state = pdf_alloc (sizeof(struct pdf_stm_f_lzw_data_s)); + // check result of allocation + if (lzw_filter_state == NULL) + { + return PDF_ERROR; + } + + lzw_filter_state->mode = mode; + lzw_filter_state->early_change = 1; /* set default */ + + if (pdf_hash_key_p (params, "EarlyChange") == PDF_TRUE) + { + pdf_hash_get_string (params, "EarlyChange", &early_change_str); + if (early_change_str[0] == '0') + { + lzw_filter_state->early_change = 0; + } + } + + *state = lzw_filter_state; + + return PDF_OK; +} + + +pdf_status_t +pdf_stm_f_lzwenc_init (pdf_hash_t params, + void **state) +{ + return pdf_stm_f_lzw_common_init(params, state, PDF_STM_F_LZW_MODE_ENCODE); +} + + +pdf_status_t +pdf_stm_f_lzwdec_init (pdf_hash_t params, + void **state) +{ + return pdf_stm_f_lzw_common_init(params, state, PDF_STM_F_LZW_MODE_DECODE); +} + + +pdf_status_t +pdf_stm_f_lzwenc_apply (pdf_hash_t params, + void *state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p) +{ + pdf_stm_f_lzw_data_t data = (pdf_stm_f_lzw_data_t) state; lzw_buffer_t buffer; lzw_dict_t dict; lzw_string_t string; - - /* Allocate buffer with enough space. */ - *out_size = in_size * MAX_COMPRESSION_FACTOR; - if ((*out = (pdf_char_t *) pdf_alloc (*out_size)) == NULL) - { - *out_size = 0; - return PDF_ERROR; - } - - /* Do the actual encoding. */ - lzw_buffer_init(&buffer, *out, *out_size, MIN_BITSIZE); - lzw_dict_init(&dict); + + if (finish_p == PDF_TRUE) + { + return PDF_EEOF; + } + if (in->rp == in->wp) + { + return PDF_ENINPUT; + } + + lzw_buffer_init(&buffer, out, MIN_BITSIZE); + lzw_dict_init (&dict); lzw_string_init(&string); lzw_buffer_put_code(&buffer, LZW_RESET_CODE); - while (--in_size >= 0) + while (in->rp <= in->wp) { - string.suffix = *in++; - + string.suffix = in->data[in->rp]; + (in->rp)++; if (lzw_dict_add(&dict, &string)) - { - lzw_buffer_put_code(&buffer, string.prefix); - string.prefix = string.suffix; + { + lzw_buffer_put_code(&buffer, string.prefix); + string.prefix = string.suffix; - if (buffer.maxval - data->early_change == dict.size) - { - if (!lzw_buffer_inc_bitsize(&buffer)) - { - lzw_buffer_put_code(&buffer, LZW_RESET_CODE); - lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE); - lzw_dict_reset(&dict); - } - } - } + if (buffer.maxval - data->early_change == dict.size) + { + if (!lzw_buffer_inc_bitsize(&buffer)) + { + lzw_buffer_put_code(&buffer, LZW_RESET_CODE); + lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE); + lzw_dict_reset(&dict); + } + } + } + if (pdf_buffer_full_p(out)) + { + return PDF_ENOUTPUT; + } } - - lzw_buffer_put_code(&buffer, string.prefix); + if (buffer.maxval - data->early_change == dict.size) - lzw_buffer_inc_bitsize(&buffer); + { + lzw_buffer_inc_bitsize(&buffer); + } + lzw_buffer_put_code(&buffer, LZW_EOD_CODE); - lzw_buffer_put_code(&buffer, 0); - - /* Resize buffer to fit the data. */ - *out_size = (buffer.curp - *out); - if ((*out = pdf_realloc(*out, *out_size)) == NULL) - { - *out_size = 0; - return PDF_ERROR; - } - - return PDF_OK; -} - -/* -- The decoder -- */ - -/* Utility to write to the output. */ - -typedef struct lzw_writer_s -{ - pdf_char_t* buf; - pdf_char_t* cur; - int writen; - int allocated; -} lzw_writer_t; - -static int -lzw_writer_init (lzw_writer_t* s, - int size) -{ - if ((s->buf = pdf_alloc(size)) == NULL) - { - return PDF_ERROR; - } - - s->cur = s->buf; - s->writen = 0; - s->allocated = size; - - return PDF_OK; -} - -static int -lzw_writer_fit (lzw_writer_t* s) -{ - if ((s->buf = pdf_realloc(s->buf, s->writen)) == NULL) - { - return PDF_ERROR; - } - - s->cur = s->buf + s->writen; - s->allocated = s->writen; - - return PDF_OK; -} - -static int -lzw_writer_put (lzw_writer_t* s, - pdf_char_t* data, - unsigned size) -{ - if (s->allocated < s->writen + size) - { - s->allocated = s->allocated * 2 + 1; - if ((s->buf = pdf_realloc(s->buf, s->allocated)) == NULL) - { - return PDF_ERROR; - } - s->cur = s->buf + s->writen; - } - - memcpy(s->cur, data, size); - s->cur += size; - s->writen += size; - - return PDF_OK; -} - -static void -lzw_writer_destroy (lzw_writer_t* s) -{ - pdf_dealloc (s->buf); -} - -static int -pdf_stm_f_lzw_decode (pdf_stm_f_lzw_data_t data, - pdf_char_t *in, - pdf_stm_pos_t in_size, - pdf_char_t **out, - pdf_stm_pos_t *out_size) + + return PDF_ENINPUT; +} + +pdf_status_t +pdf_stm_f_lzwdec_apply (pdf_hash_t params, + void *state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p) { pdf_char_t dec_buf[MAX_DICTSIZE]; pdf_char_t* decoded; unsigned dec_size; - unsigned new_code; unsigned old_code; - + int lv = 0; + lzw_buffer_t buffer; lzw_dict_t dict; - lzw_writer_t writer; - - *out = NULL; - *out_size = 0; - - if (lzw_writer_init(&writer, in_size) == PDF_ERROR) - return PDF_ERROR; - - lzw_buffer_init(&buffer, in, in_size, MIN_BITSIZE); + + if (finish_p == PDF_TRUE) + { + return PDF_EEOF; + } + if (in->rp == in->wp) + { + return PDF_ENINPUT; + } + + lzw_buffer_init(&buffer, in, MIN_BITSIZE); lzw_dict_init(&dict); old_code = NULL_INDEX; - + do { lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE); lzw_dict_reset(&dict); @@ -435,123 +425,70 @@ do { new_code = lzw_buffer_get_code(&buffer); } while(new_code == LZW_RESET_CODE); - + if (new_code == NULL_INDEX) { - lzw_writer_destroy(&writer); - return PDF_ERROR; + return PDF_EEOF; } - + if (new_code != LZW_EOD_CODE) { - if (lzw_writer_put(&writer, (pdf_char_t*)&new_code, 1) == PDF_ERROR) - return PDF_ERROR; - - old_code = new_code; - new_code = lzw_buffer_get_code(&buffer); + if (pdf_buffer_full_p(out)) + { + return PDF_ENOUTPUT; + } + out->data[out->wp] = (pdf_char_t) (new_code & 0xFF); + ++(out->wp); + + old_code = new_code; + new_code = lzw_buffer_get_code(&buffer); } - + while (new_code != LZW_EOD_CODE && new_code != LZW_RESET_CODE) { - decoded = &(dec_buf[MAX_DICTSIZE-2]); - - if (new_code < dict.size) /* Is new code in the dict? */ - { - lzw_dict_decode(&dict, new_code, &decoded, &dec_size); - lzw_dict_fast_add(&dict, old_code, decoded[0]); - } - else - { - lzw_dict_decode(&dict, old_code, &decoded, &dec_size); + decoded = &(dec_buf[MAX_DICTSIZE-2]); + + if (new_code < dict.size) /* Is new code in the dict? */ + { + lzw_dict_decode(&dict, new_code, &decoded, &dec_size); + lzw_dict_fast_add(&dict, old_code, decoded[0]); + } + else + { + lzw_dict_decode(&dict, old_code, &decoded, &dec_size); lzw_dict_fast_add(&dict, old_code, decoded[0]); decoded[dec_size++] = decoded[0]; } - if (lzw_writer_put(&writer, decoded, dec_size) == PDF_ERROR) - return PDF_ERROR; - - if (dict.size == buffer.maxval - 1 - data->early_change) - if (!lzw_buffer_inc_bitsize(&buffer)); - /* break; We must wait for the reset code, don't reset yet. */ - - old_code = new_code; - new_code = lzw_buffer_get_code(&buffer); - + for (lv = 0; lv < dec_size; ++lv) + { + if (pdf_buffer_full_p(out)) + { + return PDF_ENOUTPUT; + } + out->data[out->wp] = decoded[lv]; + ++(out->wp); + } + + old_code = new_code; + new_code = lzw_buffer_get_code(&buffer); + if (new_code == NULL_INDEX) { - lzw_writer_destroy(&writer); - return PDF_ERROR; + return PDF_EEOF; } } } while (new_code != LZW_EOD_CODE); - - if (lzw_writer_fit(&writer) == PDF_ERROR) - return PDF_ERROR; - - *out = writer.buf; - *out_size = writer.writen; - - return PDF_OK; -} - - -/* -- PDF Filter functions --*/ - -int -pdf_stm_f_lzw_init (void **filter_data, - void *conf_data) -{ - pdf_stm_f_lzw_data_t *data; - pdf_stm_f_lzw_conf_t conf; - - data = (pdf_stm_f_lzw_data_t *) filter_data; - conf = (pdf_stm_f_lzw_conf_t) conf_data; - - /* Create the private data storage */ - *data = - (pdf_stm_f_lzw_data_t) pdf_alloc (sizeof(struct pdf_stm_f_lzw_data_s)); - (*data)->mode = conf->mode; - (*data)->early_change = conf->early_change; - - return PDF_OK; -} - -int -pdf_stm_f_lzw_apply (void *filter_data, - pdf_char_t *in, pdf_stm_pos_t in_size, - pdf_char_t **out, pdf_stm_pos_t *out_size) -{ - pdf_stm_f_lzw_data_t data; - - data = (pdf_stm_f_lzw_data_t) filter_data; - switch (data->mode) - { - case PDF_STM_F_LZW_MODE_ENCODE: - { - return pdf_stm_f_lzw_encode (data, in, in_size, out, out_size); - } - case PDF_STM_F_LZW_MODE_DECODE: - { - return pdf_stm_f_lzw_decode (data, in, in_size, out, out_size); - } - default: - { - return PDF_ERROR; - } - } - - /* Not reached */ -} - -int -pdf_stm_f_lzw_dealloc (void **filter_data) -{ - pdf_stm_f_lzw_data_t *data; - - data = (pdf_stm_f_lzw_data_t *) filter_data; - pdf_dealloc (*data); - - return PDF_OK; -} - + + return PDF_OK; +} + + +pdf_status_t +pdf_stm_f_lzw_dealloc_state (void *state) +{ + pdf_dealloc ((pdf_stm_f_lzw_data_t) state); + + return PDF_OK; +} /* End of pdf_stm_f_lzw.c */ === modified file 'src/base/pdf-stm-f-lzw.h' --- src/base/pdf-stm-f-lzw.h 2009-01-11 21:37:29 +0000 +++ src/base/pdf-stm-f-lzw.h 2009-06-22 23:47:24 +0000 @@ -27,54 +27,29 @@ #define PDF_STM_F_LZW_H #include <config.h> -#include <pdf-base.h> - -/* Configuration data */ - -/* BEGIN PUBLIC */ - -enum pdf_stm_f_lzw_mode_t -{ - PDF_STM_F_LZW_MODE_ENCODE, - PDF_STM_F_LZW_MODE_DECODE -}; - -/* END PUBLIC */ - -struct pdf_stm_f_lzw_conf_s -{ - int mode; - int early_change; /* An indication of when to increase the code - length. If the value of this entry is 0, code - length increases are postponed as long as - possible. If the value is 1, code length - increases occur one code early. This - parameter is included because LZW sample code - distributed by some vendors increases the - code length one code earlier than necessary. - - Default value: 1 */ -}; - -typedef struct pdf_stm_f_lzw_conf_s *pdf_stm_f_lzw_conf_t; - -/* Private data */ - -struct pdf_stm_f_lzw_data_s -{ - int mode; - int early_change; -}; - -typedef struct pdf_stm_f_lzw_data_s *pdf_stm_f_lzw_data_t; + +#include <pdf-types.h> +#include <pdf-hash.h> /* Filter API implementation */ -int pdf_stm_f_lzw_init (void **filter_data, void *conf_data); -int pdf_stm_f_lzw_apply (void *filter_data, - pdf_char_t *in, pdf_stm_pos_t in_size, - pdf_char_t **out, pdf_stm_pos_t *out_size); -int pdf_stm_f_lzw_dealloc (void **filter_data); +pdf_status_t pdf_stm_f_lzwenc_init (pdf_hash_t params, + void **state); +pdf_status_t pdf_stm_f_lzwenc_apply (pdf_hash_t params, + void *state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_lzwdec_init (pdf_hash_t params, + void **state); +pdf_status_t pdf_stm_f_lzwdec_apply (pdf_hash_t params, + void *state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_lzw_dealloc_state (void *state); #endif /* pdf_stm_f_lzw.h */ === modified file 'src/base/pdf-stm-filter.c' --- src/base/pdf-stm-filter.c 2009-05-19 13:26:02 +0000 +++ src/base/pdf-stm-filter.c 2009-06-23 10:31:09 +0000 @@ -72,7 +72,6 @@ /* Output buffer */ new->out = NULL; - /* Install the appropriate implementation */ switch (new->type) { @@ -180,6 +179,20 @@ break; } #endif /* HAVE_LIBJPEG */ + case PDF_STM_FILTER_LZW_ENC: + { + new->impl.init_fn = pdf_stm_f_lzwenc_init; + new->impl.apply_fn = pdf_stm_f_lzwenc_apply; + new->impl.dealloc_state_fn = pdf_stm_f_lzw_dealloc_state; + break; + } + case PDF_STM_FILTER_LZW_DEC: + { + new->impl.init_fn = pdf_stm_f_lzwdec_init; + new->impl.apply_fn = pdf_stm_f_lzwdec_apply; + new->impl.dealloc_state_fn = pdf_stm_f_lzw_dealloc_state; + break; + } default: { /* Shall not be reached, but makes the compiler happy */ === modified file 'src/base/pdf-stm-filter.h' --- src/base/pdf-stm-filter.h 2009-01-12 13:30:36 +0000 +++ src/base/pdf-stm-filter.h 2009-06-22 23:47:24 +0000 @@ -34,6 +34,7 @@ #include <pdf-stm-f-null.h> #include <pdf-stm-f-ahex.h> #include <pdf-stm-f-rl.h> +#include <pdf-stm-f-lzw.h> #include <pdf-stm-f-v2.h> #include <pdf-stm-f-aesv2.h> #include <pdf-stm-f-md5.h> @@ -74,7 +75,9 @@ PDF_STM_FILTER_AESV2_DEC, PDF_STM_FILTER_V2_ENC, PDF_STM_FILTER_V2_DEC, - PDF_STM_FILTER_MD5_ENC + PDF_STM_FILTER_MD5_ENC, + PDF_STM_FILTER_LZW_ENC, + PDF_STM_FILTER_LZW_DEC }; /* END PUBLIC */ === modified file 'torture/unit/base/stm/pdf-stm-write.c' --- torture/unit/base/stm/pdf-stm-write.c 2009-05-15 17:55:40 +0000 +++ torture/unit/base/stm/pdf-stm-write.c 2009-06-23 10:31:09 +0000 @@ -870,6 +870,110 @@ } END_TEST +/* + * Test: pdf_stm_write_015 + * Description: + * Create a memory-based writing stream and attach an LZW filter + * encoder to it. + * Success condition: + * The encoded data should be correct. + */ +START_TEST (pdf_stm_write_015) +{ + pdf_status_t ret; + pdf_hash_t params; + pdf_stm_t stm; + pdf_size_t buf_size, total; + pdf_size_t written = 0; + pdf_size_t flushed_bytes = 0; + pdf_char_t *buf = 0; + pdf_char_t *decoded = + "-----A---B"; + pdf_char_t *encoded = + "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01"; + + /* Writing stream */ + /* Create a memory buffer */ + buf_size = 100; + buf = pdf_alloc (buf_size); + fail_if(buf == NULL); + /* Create the stream */ + ret = pdf_stm_mem_new (buf, + buf_size, + 0, + PDF_STM_WRITE, + &stm); + fail_if(ret != PDF_OK); + /* Create the filter */ + pdf_hash_new (NULL, ¶ms); + fail_if (pdf_stm_install_filter (stm, PDF_STM_FILTER_LZW_ENC, params) != + PDF_OK); + written = 0; + ret = pdf_stm_write (stm, decoded, 10, &written); + fail_if (ret == PDF_ERROR); + fail_if(pdf_stm_flush (stm, PDF_TRUE, &flushed_bytes) == PDF_ERROR); + fail_if (memcmp (buf, encoded, 9) != 0); + /* Destroy the stream */ + pdf_hash_destroy (params); + pdf_stm_destroy (stm); + pdf_dealloc (buf); + +} +END_TEST + +/* + * Test: pdf_stm_write_015 + * Description: + * Create a memory-based writing stream and attach an LZW filter + * encoder to it. + * Success condition: + * The encoded data should be correct. + */ +START_TEST (pdf_stm_write_016) +{ + pdf_status_t ret; + pdf_hash_t params; + pdf_stm_t stm; + pdf_size_t buf_size, total; + pdf_size_t written = 0; + pdf_size_t flushed_bytes = 0; + pdf_char_t *buf = 0; + pdf_char_t *encoded = + "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01"; + pdf_char_t *decoded = + "-----A---B"; + + /* Writing stream */ + /* Create a memory buffer */ + buf_size = 100; + buf = pdf_alloc (buf_size); + fail_if(buf == NULL); + /* Create the stream */ + ret = pdf_stm_mem_new (buf, + buf_size, + 0, + PDF_STM_WRITE, + &stm); + fail_if(ret != PDF_OK); + /* Create the filter */ + pdf_hash_new (NULL, ¶ms); + fail_if (pdf_stm_install_filter (stm, PDF_STM_FILTER_LZW_DEC, params) != + PDF_OK); + written = 0; + ret = pdf_stm_write (stm, encoded, 9, &written); + fail_if (ret == PDF_ERROR); + fail_if(pdf_stm_flush (stm, PDF_TRUE, &flushed_bytes) == PDF_ERROR); + fail_if (memcmp (buf, decoded, 1) != 0); + fail_if (memcmp (buf, decoded, 9) != 0); + fail_if (memcmp (buf, decoded, 10) != 0); + /* Destroy the stream */ + pdf_hash_destroy (params); + pdf_stm_destroy (stm); + pdf_dealloc (buf); + +} +END_TEST + /* * Test case creation function @@ -896,6 +1000,8 @@ tcase_add_test(tc, pdf_stm_write_012); tcase_add_test(tc, pdf_stm_write_013); tcase_add_test(tc, pdf_stm_write_014); + tcase_add_test(tc, pdf_stm_write_015); + tcase_add_test(tc, pdf_stm_write_016); return tc; } # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWUfpc30AGqR/gH39LoB///// /+/f/r////9gJV6dO69VPN3z7Z899Zlvt84Fmdt313vbs9zu2esuXmANvrgDrQAK6NBXpvbpjPoZ Xop69cu9s42zIuxW1nQ3Hvd09CoqGhYyhSoRlQ66e28pXs6AAEoTRTEJlMhmk8NU9Jo08p6TTQ8i Gh6jRpoABoaGgaGgEkIAgIIEaKTyano0j0yj9UaZGh6g9QAABoAAZBqeQQVIxpNA0AAAAAGgAAAA AAAwSakJpNCk8JT9MTSj2qYTxRkeo9QyeptJoxAyABoAADQRRE1NBkE0CYAE0m0m0J6pg0p7UbUT yg9QyGgekA8p4UCpIpo0aBMgaQ0nqYU9oAink1Bo0Gan6U9T0h6gaGgAM1NidvYrOiFXoIABlMIg IRiOz+qK9U33d3t/gb/yauu17Jsi/3w6uSwqzqEVCDCqrsjENZGCACg3iaHTnjvY87YlkrZo+R8x qjkJthoztWzUKthLWNkizMoqqVkTFlfN615goyWyIVeKkBw6D/dOwKpF73Ee6pUJXYyFVVWDNX+0 kqK9Zdu7V33trtLZWNOjyS/a0X4YiuyqrsNHig7fgajjRuXp5aBUtKUqibYLeo/ljlIJGZFBTZPo 9IYKTdMwpEp7Ptp8VByVp4RMJNjAprh1+8pVNJDZhb5azOalaTMwaetXCAzHHB95AgktSonGCDdr 3ypro7jDFiY6StLU/5USaHVus5qMZnXfjF6aIZxUoEChLUYbFSpA4ycJEzp7OGhTYrRqwMN1D4jQ +M9+jOvHMt24ObFBg5K9NsL1Ka+HmN2/yM3STcBs1VSmRklhDCfLevr4RGvOjVnhPEUndvbKA8zT wGAWrAZQ3799guhxdEhxYEd9FNMBElMAvVF0pkuhAwYR1yWKbMM2rN8WzjSis5IEgmUIl4qzmhCS lPDspZUVJIaia1BloNFrwoCdEwrnEs6mBN0CmdA4jDhzjdTahOKTk/W7nb5R3paSK7ImbVDdjpp6 pwGolEh7vLE1UROWABS6EFGF74RYgF8kCjZSKpEZgzscEuHXhLUMLWTBqvupmilQUqCY0SFijWl1 yZJ4/E/37r1+SBWQUGTQlxVdKEQ3TiHmUY/YMRnEstXgC046KraPyMr97QMrDZuISHNUqeggow1M p3GgdKT4DVMP+n6Pgus0XXWs7O3TK46UcmEyky7eg3ejZ3//cuTr5ZtmVCsqsUlHxE65OUHnRVSI ALFAWCwUgKEESKEVSCgqoirJuJzdtQDtPiO0kA8XdfnvX6vkW8U0P9xolWXrnhFkfJxvxvtXWo9B pNqtH2Yrbd2pJgaNnzDrNTMuDZUJARSVGqg6uruHzMpoNbVZQxR4riZN/vhqrpF85rpfTRpLSJS0 Z5M93uUeKqzMv0S9OuvA0c7GSnG+tTFSnGKyzCcIOMcM7Y4bamLx2oy4dUrGC8vL2rSqil6oUygw akQnTC97QHFpTiksLTiS9qNRpVIBgEQaPeWuYiJvNrWGCXVjgGhNTioVos7spbFXZZSXdzKmTG22 MOoMK2qWNam2c2zVBnFBZmZYZSGhlVqMV2ae6zShhi7XxEfD3+xvvG7e/iQaSF4G6HCNp8GCu6XL 6izLdCPBJDWzFZI3xq1eiCBZMby0ySwY0l5MHOYGZLsav4p5Th+sqUMDuj3k9mJeZjQ8/tpSKPYB N54nhx5kbBDBA433zMyTUiZGS8LyCpGB5ok894ZbraMX1mJvnGenau3w6mRoH9NslQ1sWqdujpEz 6T9O0N4LtZt8OekthitoRM5O54BB4NOlRu2X6flS0ROchk87BH0dKSKnU/17nMFBhKggeY4y/Cdc i3Y4an/vwRsiPPQStVt5wh169e0RHwZVtMr09mX385q1nTumI44Rxx2bQzaCyj9DPnwaqPwOIhQD xj8sJTm+yWyGSNOLHOvTBf2adKSRfosvcxX1KVPZKRAqaeTcx5f10nfcUV2A43J8+UIgUuhSu86i q1CLHUEksV7SqlxOs3lj1zYOe0z2SgodyTuEDiIoooOnd1o8Np0m6/erv7aKqqvi9ITBt1CDHyQp 9Z7BLxG9Wybcggn7bUPJznkcyrCK0sOyxzsXkSPNkaZGYvzINGJEVYpsMTGof7wBvKCZOprmNoAu PHBsi4Oq1eNTLhQnQqiKuyE0h3NbwKw8Sezp0JTSVVZVParqdHzuHfypPdquSqKG+X05sNzfVv/P bO/nja+szXbTzre3K9yZMj9o+VCF+KbRhgYYYJ6EvU5h5yc5EhAKxADEPuRKl6r1T3rvqpmhRUVH kipPvUylHiFOdMCJmTyUA/jD4RYgHNCn2eMi+4JZAzEIODkQRAGWKPV04eXuUWj7ofyja9p+2ekd jlOzMObihAKpRpFNkih25GNM6IGu6UXJnmeGFpL3HmXkTMccVNC9NcurZ1trKprqf5ngdDsvuftw NwfMZIPpHw5gzsYMF/g9ufLkYCIDBO4xZ7MlpAnnUIggiA6Q8/29n9221jNqwZNJuFDUUNpyE1Sz LZQvrK0gXzFDzUzzPjzOgvfltPQmMc1+OWmxRoZ3t6zUXUo4PvHJKhH7J3BMFT/EnB0XP3/wMzM7 p05+2TVvZk2JdH7rVDBcuowX+W1dnAkLyiePiTv8OsEmWNL3CwdXLy9K710sVQM5Sbse2R0W4VWk DQRNr3FC8Lk1OgxLe4fZ54Eu41DWPel5v1lHbC0Sqp9DlRMgu1kbIl9U0k8zIQK2n8LxsHVufKPn TUtQZfat59XY18ro94rfau23lbWVLligLBaFVzadkkIWobmWYIIgjTz3FbKifkOXYa9h2UO8F+ET 2vMRCMQBAQwQg9h4+JImU4s+hmZGZlJmWZmUiwu4IOIl0i+VUXKw0kRJBbu8ywF52TmMqvpugJy9 kjaFtBWC0A1ilb6J00mYQvgK4SAaoF0MMugaJuzRsybmEFF3N0mUk1Q27d+kPamDgh6Cq2eJwNtY boeQ1vBJBkaQKrJzmk77s9xHaXanVl1mJ+IU0kkofXymk0G2mEIZiouShTOd9qoQ4lJII+2knilm ZFSoqlDNyVc0ZkyCyEMK56hg0ODB4lqhh369CImhylrXmJSIdFlcys6B3SxpIgyWEaPYbmGbBJUw qEjE4sE2ODMvCaOqNCidKfhnbmL9acy7i3uDJrWXXYLti/Ccxy1LHUjwN0dP12ANtpaeFZslrVCC rAjZm12gOGVsu7WZOMDslmHRKrShNaU5F7ZpETpWL6NXQVWI0KmTCQZrBhoZXGUkI+t0SEm5GD4S cJCUpkaMSZi8Y0QjkcdDVMayRcLMpO73W85KYUT1Ah3ZVQx5DbHJTjR8111tntXtjnyrxZsRrGEW HN9266E3UdNiCIOmCONKxD11SRQiK0qJzTceZuDJKnIyfk/GjEsjV10eRLgvWE7KWVM3ILFaBebS mSswQNJIIfsFHwQHbgV09XFTDcGCpa8xpM2WeXpNBDdz5PCRpoGxEV3Sdmd031ywtlTffY75tDAO A3DgIIMf29bJ1OLncVOdtUpnU4lSS26ScOrBZF8as7Kgcg5iAwaAK6ELXRkVxCfOiFbF4YzoAUkw ykzqx2XvHIJ6aJIzYmpKgZ9zlpX20T77z2EhkNuFtlIqYLkJKTWfNMEcI5KpKcCQaEJI6kvcbHBz iLggpYyaukjIuIOackyxUY88lDokiQnIQ3Q3HINsnjLoMrmXXBvl4mNgyO7aUU8SqMBQY5FA7BSu pJOeA5MhrqGY8Ek3XBwMhLc0sYHcweQ4UOSwdihc7HUmVKEyhU5D7ol8yg40mXhQ0YeEyXV3WJtr KZq3XWj0pJ5j1xic65jDIQwqXM2GykEWKYJyaYlYSdbrDohIPIdTXf0fXymQQOM46DoZNS5rOqZp v4RpQl4HA8xsssDGONVTYVlbGFG8d0nQriYGwyFC6+JtOhMR9BjQY7dhzUyO3FPIlqNVkwwGxetZ XK1NOc765Ipk5mhwZjM2vFOLWwcGddZzMW9pLG23QkSPYLWvT0GOGqyq7p26s/Z1yyhREyJqO8dX tFk5DFMRalcAu3nfJZDJIfNVdxbt4sFBVKpIqQMUmSV7xUTTNNSMWlA/Ue5EmSkWNqOTebaxHgMd m+mRY0Lbkj31JDBHJ5DK6yUokMyNehHA0G5MizP2NNUka6H2zJYsN0LliOScaScTINwzdJE+CCpI 5Jkj89JaEjuclDt57lxiZ9KQfmgGqLC4fnzHUHW0yktpUgow2NqNOvjEybkTu16PSC26MgyPbepy Zfh9NlA3coPX2noXUrGqQOuQbtrfQlM9kmvcUckFKyQgfqNZN0CY7Um15dSw+w4nmumDkl6bEiQp aIojSzkoO3N72scYLw0OMUSU/MbImHJj1NSRHHQv3NtpyqVuS4QicHBgwbDFdiDU0pNU8HF+jQ4q YuCngYsFl2p0OdwdTo6OLBQqbkHc2Jlz7QpCb6D0PUVxK1b+kN1biQ5CQIZzLJskMHhgM9psITVt FVWa2mzaCMauHBwKwi07YvGMYGHxeHhkTjHbqbH2UYxU6j+mMlCT6JJBnwggUqbjueBImQSyHQZ8 0hIKGR7xSOILWqWPEuTSXyoRn2lPM7mTQ557nOs6Egpm03U4KYNQmvFuWb29ZgzMVMzpWZmLQuH0 GAQeKQc69wZrcWYkxLRofVqPQeKxmbVnit7F2m9A8LvVcJJxe3JbDFNDkyktSTpLDWOSUqtla6ux CWDJU0fDZFQtUwkiEPQattLHcuLoaEzUrZsM9WfSUzQU5yfqSrQ0Km3fvXGLtoWGG1aOpwWOhycC tXNjgydDoFwSzxvs0NhZi2t5Zqm9NbY8e9obmTWydsieXX9HjDjHxnY8o1n1iG5Jx1lHWJUeGmmU EdHlQabzicpbtsVSqKPJVLaqUYrtt0bzWSHSJDY6yw+GO+nmaTaluCxqVPAsUJFOA3mmgmULkjDW NSh8glImy2KRgke6R1IJYIDSUmXQ4H4N2DPEYxa2LFzOk4NzizNDMyb1mTFXOlQvM4G89Y9fSmdQ 8qpk136NxmKbSobuq3BddFSJ93rBcjMsK/UqKQoEqFopE5r7DUGQJFS5tu6d2/pL5HfrW4Og4neH QUcHQcTwupsacVzQzGWSgsG5yTrpUi6Sz9jBSbaHU3MRsYzoYOSgT6BahBk9Ug6rqXLnU9hqWIOx ucmgxk4LyxUkymKhUsaDbtylnhNIvGoYqnMqfKeQMTx7Z+bd/Ajt55ixY1DzQpvokDCat/gCTyUV KAt1FTyItp5s2l4T4C/BrH2zbjvnTWkEkWT0VX5q+749cWRzWFedOTQ4Fjim3uT4JW+/Ww8bwMaz sueEb50LcD1ijDCazn0psAfanRc7w4iOCcujnLHO0bjObliBMpTTGAoVUtyZmGLNtKHEPRD6A/Xk mYMLAMAEGH5IMhQfzH4ow+RJi1wsQlBKKlQQulI5akJkOaDA3ojBF2IMpBRneghXliyHgjEjGDGI paFqjBKkEkyBPY64eT3gFAghOZOJJKpelBKZk2GWqQ3J0CORIUHHOZ1RN6DkgMYP4nQ9XxP1nFpb j6HS/gFTUazJEEAYLJFiHrT7/vw7S2d0KP9gjguUkIowT+HovLw5ByuVDUY6W9/UjnAwlfxVS60u +Ok0H4Kfpi1qU6FXXtMZxsLEspdwIWy+tgP4FskLrGDhMQv7yAPaXAkrCAdemOP7t0xbh3XfvMFz bzvhsruGCUXMYxrEziZCT7N9TiWy4bsEQyQsF8cjB/SVkIXLt5w79NdgyoVPHpG1VzTZ0uUTpkya Y2IWLr7t5fyeB5MgD/wQCcxC7jh+mRzNxqAxOT7jFda3OrQZV13LtyMSclyymw0AFsCwcQ5mTJ7E qhNSAKGkKSVEQb5q2Cwvj+ddJJMkVHB1vNeRHUuJCh2FDRkDNpXWI+l83nPd1/XFCqpV13MGweUy lo2y2MGIwkChHTpNKBMsPJn1xPjeDU7O+GvcGQJPBaGyCrQZhb71pC8XINyxVZRSg1NS0md9Ot4U n1wvaLUfaioK8R9BF0ly7Aq1URcphTM6n8a8lREv8hQUoZTLdEdI5HKg3NUPnVliAZcotjBDupsD jjlyyqhKwJEGAkOYTmAYW403E28+PTxfz1YM3k3MFUUW5rOK0UgyaCFBluGCEYYYJVEwEq4BnGlh NKwYkSRA4pKSghBokqAe5jYltKigqWcm6jMabjFwJI+yhi9nTfOnSSEfUe0+swQVNb7Wm/NJGKpI +LF352ti+xpU/OyYPO0LmltdDcycWp/MyYNDUu9P2+iZbHO1t7a6I+6pDOznFvbnBuWdDM+7Z40z uLS9bY3Nqlnrt2+XJY3uBecJyeLvlsgCl5kLzYSG+FDoEsi/E5DGfqZwPikJaHykDeqO53J9pIMz +ahaoYQyWZjPnuKN07ITfpi9ok0PN+K8XO/MQ1RlHlKZOrCSeFJN0n8Kal0Jw1fhwfBKI3ceGlzt 2+gyQS4qOfh0qdalyokIMm+rNA04SFKqJmpIS1gzlAC8KfU7zXrzp472SByw7fvtbyOL1PI0Mdzg 9b0sFPM1PE/E1O9rZOtrZmZg1trp9fewZ3qaWLSwje4Nre0s6znbIdi1T66t/3ZPU0Ol7fD0nO5N rJoV1MHW4ud5M/qn5HqaEwciYHZB3hZP5Jw84cBIwyEEoQMjBQDCgSiMqJUfw1DX4zj8ZxPULUyg pCoWysu+Kx+qF2YF8e21z73zx/clVPsEj1VAXxKh3+193vzIUT2PlfK0WXfIu8zCSXXdrl4cC72M D2vM857XtZlmt3rLsGh62xqbjmm31EViMVirOoVEGFTnu7Gh6j/J28nZlKZb2xxantaOS6+/Bjbg wcF41uyTZzAnc8T7aC7A/1wzkN6Z08As5IumYCCsUjywXCwlDeiixYUYKsYM67yXiM+SSCSPzwWD 1mrdQ0DmIEwDf0Kib0evP35Fb1ila2ZYLypdXKnjtYXT9Xgdfm2ru13PRlZo0fIyeaYO5pedg8qz xs7zsUzODzudzPqSnQFuVKFzqCWyS0PHc5MI1KByOdethJHjQTHBsczW1OtyqqUpVUqpO4nu/acH S62LU53FtUztiy7tHjKkk9mTv6urBGhzQ7n5T3/ltHzOu4pndT24Mye2plHN47E7T3MJ+ydzA6vT tPc+SId7pfI8EhmREbVJGkSN3CN0yWi3KmCemgYjS3oO2H26QocwSe2BifWyQ2lCWjGUktVabRKD TNxOcvXsbijQgJWXqZetL8czNMLXChvk9TgThYVYuKGDBFVggiFRGUGYFiHdvvJYCqIFwCgrDnHK NXPpWjCXCRqGIwFkMAphNUcq1tllXMa/e3Mp14esSUYMmxucGBi59Bc5OTBpQ+I6kjNr4odaUnhk oUICKEUJSVeNIeJUoJg7iSZBWFp3zwlydgliBeSBtuBEflI8xrNRe8nI5FIA5T0r9/5U9Hf5WCaR kDfVEhDlPDw1nUdJpFO3L5NjVQzkJWJ3JiCnVXJRKQ8RcPO1vdIXajI7GW12tzM8GCYp5Gdafm8T 5oo2Xo3cwXV6B0+q3WfyWAJCsHchteY5yEN71L5+3WGlGitpFCPzjx8zgPAQbzGWPZQkaoQBEJhN C1UoLApAh1V3tqdFjS5FRMoJQq3ElMwnEauosJFn+comgLFlModaRBCLLbIz3CM0R4ZTsjFRPsZQ jCaIwVT4QPWkQHpE+0kod14Fhq1UP5nQQrUg49Cmp6Gr0nJ7GDvelqYMGK7U0tT0tLS9LkmLWzlp D52R63M+mGCIUSK8C4tEkWpqbnh8zi7FkmnaZOLgu3MWDJrbkmok2mlUoWJRTUqJcbhkOBU3FBi7 3IbY86HGI4qHKdBUpV0jCfBhJtXpCREdlxU9ZeJQb8/hYXSMbopnyB6k4kS8Q5nOMDQaJnUOQecr VUhOESWEWAC/KnAPGO/dQfo+MaoSPwppu1bL91OUkMtwfPriDzHWUKDA0otJyK7qlw76olkiD/yw hTCSZqT8RGMQAyd2BLw9cZFOjEyGnjwIEGTJbsGRyHgqd48h3Z+R4Tryfp2gixyHDh1aUTsBLX/r 6zIRb2bn21uCvJ5q9KUSYE7lcOUVMxflEsuz8f2PlD3wGUO+pH7atQh+ZZHKqdGrFDZpeQevwGBY +MuUR3BPhHEXniBjiIgUJz+ivU5jnC0+2/OhI8J192d16BOQM1LIIxnGpD2NPal1pJgK3/PGuLxl NclVSooqJGd9J9zX06FU9k2Dukib7BmUmkMEssZnPEsnfFYTTE1kHizx5Ij2uVG+OH0j0CfqVPeL 71DqMx8kpp+N5X2DCLtoP023IGSkBtBeEWgwiUVKnrsXCwFNCUi/oXjqu0UhZUkUpDneWqxxz68J c0kAkJcoZhrGiKr8qcucAcibyZXYOY6/+vN7XUnTrkYEYMnxrlAgIIJP9+/zUPz9kY8Yp6m6sJVu ZRuCC0SIcGxeODhCO8SCCkKvylJVW4gTn+vzc1y7yn34er2Bv2CDHBiFTUbgxMIzNkfNHdF6jmQ2 p7Ke6NaNpkbDMmIdIZ0yqmcZFfdoDdH2C4BaMoTzDeaRSlyEf41oVK2p+QElB84eBIpcnqexUkY0 EzD4J0CeG+qUqGv31F4vEosewyi0iFvIJZXpVEvncQ5lRPIFQ7R531LxokSNMVQmuIVkd0fFLibF R+b9Pg/PMmCdKTWxhRcPFriUsi0kqpIcUoqLSTN6E8eVD2nzSGv97zDzylVBVCqUlIm7NI2T9+aE /GQ7m2N/Ji06vWpHCNOJKCwwNCx7kz0EU9+Mr5Uzom0vINorMdCwe2qmQ+jrHQFjSQkECSQbamY+ GA6ggTd8eygVfkbUOUXg3B4tIeV21NkUIYCjEJVLQ1eFrSxr5085xKhEBJPNDzQ8wSeY9eH7y544 aH1taKBi3ZQiiNWh8PnU3hZoUZZJZBowPCyyQjCHyiwEwfETLRD4WBYq1pFigoIlgQFWbtkRYCAi IIN1U+Q88B1d3UCUm4epUjZZHxVPIdlMCOKfm4UbzzFQ7SHfdxPIJCeg9+90nSnYNewkXeHzjxDl D1O9xysyEhG5G2itWAHhfChtqksAhcJCBARH7x9ICl6LQVkVb5QpJVo4Eih0uB90PoAx7jGKVF7v xMidNBBu0vUQEEHGHq/dNIPp5/zo1boC7oTuSgh0xQXTX2RHGTfF1cd9aKMFE4Dpdwf0kAb1swLC n0jnOJBwFz82OAJQbvGIA+YzFIXK9DLKAMMCWQzP7sLlrMkQJac4YxFIEZkvXxylZuzIM/EMUJQQ DdVBCcSLCoOioreGSMSuWDW+ivfo2zNSSfjqaZ7sd2hgOUCFcipVUqGQz96ltJekQIOPBlJhieB4 pTV7gKCO17VaBPFLhJwvPN1k+lYJywnW8gelq2B5LlocJ5ozjGUR3NQKKhFGIOwIALPxfIZAMDFF 8plL1QOoU4EWnLchQHezaWDxPkbA8pE5FeMekRbx3+jva8BhzjksQ8EsQ6OmYJpLinZep1YmLQpL pKQ3M8tGIJsXtAG65ZUutJ+wuJKEWpLdemwpcuTQNSipKmCBCgCsCXiUe+ZyUVFMqP4z+HyIyjYR pOywQsGQTrUEE09UmKokKo7OfnOI0IiXb5YkxwJQWAMCVMEoMmRxm6mYciYQY2lQqkCn1HOGjaoh mjUOE2SqqlZg2JvzMjgjBFy4/ASahECuWF1UFYJKKwUUIgQmFYqwJkkSQXISpvC3XGtBuAOVWgl5 xhTKO4LrNG/T7jzZkNoHiiJpHaM7TiQ1tzGIYKidJseSEqmGQtwalGWADLiPB78WYECDTcNRmeYs wMQz+tX4K7XmToA2B9KRzeA5w+uu8AQcdFfemfoVHaL9qJk/SIIP39x7z3vSiae0zhngODjkZVOf dZUosAgVDrlDFqwPkY4VN1O00PGESNw+BedQdKvxacYTmaSFk+wTAYJIORQgKti3LZDkUIdQ0ZUT pTfNqQczMDpTqqUCqQn1BvDXqDvULF6QC5m9PT4hgdo8ip6TKvPqHQqbEblTYbwAUhEOBU3jUmKu sAXKqen6BfcPiPur7uqQYItBdKkzaWEltS1xK2//F3JFOFCQR+lzfQ==
