From 7da4a1d7b029ab640a9ae2b95e745d29c998a7b0 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 26 Dec 2017 00:07:34 +0000 Subject: add more data acessors --- src/cos_object.c | 127 +++++++++++++++++++++++++++++++++++++++++++++---------- src/cos_object.h | 38 +++++++++++++++-- src/nspdferror.h | 1 + src/xref.c | 64 ++++++++++++++++++---------- 4 files changed, 182 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/cos_object.c b/src/cos_object.c index 5ec41a9..a5bd738 100644 --- a/src/cos_object.c +++ b/src/cos_object.c @@ -71,35 +71,14 @@ nspdferror cos_free_object(struct cos_object *cos_obj) return NSPDFERROR_OK; } -nspdferror -cos_dictionary_get_value(struct cos_object *dict, - const char *key, - struct cos_object **value_out) -{ - struct cos_dictionary_entry *entry; - if (dict->type != COS_TYPE_DICTIONARY) { - return NSPDFERROR_TYPE; - } - - entry = dict->u.dictionary; - while (entry != NULL) { - if (strcmp(entry->key->u.n, key) == 0) { - *value_out = entry->value; - return NSPDFERROR_OK; - } - entry = entry->next; - } - return NSPDFERROR_NOTFOUND; -} - -/** +/* * extracts a value for a key in a dictionary. * * this finds and returns a value for a given key removing it from a dictionary */ nspdferror -cos_dictionary_extract_value(struct cos_object *dict, +cos_extract_dictionary_value(struct cos_object *dict, const char *key, struct cos_object **value_out) { @@ -126,6 +105,88 @@ cos_dictionary_extract_value(struct cos_object *dict, return NSPDFERROR_NOTFOUND; } + +/* + * get a value for a key from a dictionary + */ +nspdferror +cos_get_dictionary_value(struct pdf_doc *doc, + struct cos_object *dict, + const char *key, + struct cos_object **value_out) +{ + nspdferror res; + struct cos_dictionary_entry *entry; + + res = xref_get_referenced(doc, &dict); + if (res == NSPDFERROR_OK) { + if (dict->type != COS_TYPE_DICTIONARY) { + res = NSPDFERROR_TYPE; + } else { + res = NSPDFERROR_NOTFOUND; + + entry = dict->u.dictionary; + while (entry != NULL) { + if (strcmp(entry->key->u.n, key) == 0) { + *value_out = entry->value; + res = NSPDFERROR_OK; + break; + } + entry = entry->next; + } + } + } + return res; +} + +nspdferror +cos_get_dictionary_int(struct pdf_doc *doc, + struct cos_object *dict, + const char *key, + int64_t *value_out) +{ + nspdferror res; + struct cos_object *dict_value; + + res = cos_get_dictionary_value(doc, dict, key, &dict_value); + if (res != NSPDFERROR_OK) { + return res; + } + return cos_get_int(doc, dict_value, value_out); +} + +nspdferror +cos_get_dictionary_name(struct pdf_doc *doc, + struct cos_object *dict, + const char *key, + const char **value_out) +{ + nspdferror res; + struct cos_object *dict_value; + + res = cos_get_dictionary_value(doc, dict, key, &dict_value); + if (res != NSPDFERROR_OK) { + return res; + } + return cos_get_name(doc, dict_value, value_out); +} + +nspdferror +cos_get_dictionary_dictionary(struct pdf_doc *doc, + struct cos_object *dict, + const char *key, + struct cos_object **value_out) +{ + nspdferror res; + struct cos_object *dict_value; + + res = cos_get_dictionary_value(doc, dict, key, &dict_value); + if (res != NSPDFERROR_OK) { + return res; + } + return cos_get_dictionary(doc, dict_value, value_out); +} + nspdferror cos_get_int(struct pdf_doc *doc, struct cos_object *cobj, @@ -144,6 +205,26 @@ cos_get_int(struct pdf_doc *doc, return res; } +nspdferror +cos_get_name(struct pdf_doc *doc, + struct cos_object *cobj, + const char **value_out) +{ + nspdferror res; + + res = xref_get_referenced(doc, &cobj); + if (res == NSPDFERROR_OK) { + if (cobj->type != COS_TYPE_NAME) { + res = NSPDFERROR_TYPE; + } else { + *value_out = cobj->u.n; + } + } + return res; +} + + + nspdferror cos_get_dictionary(struct pdf_doc *doc, struct cos_object *cobj, diff --git a/src/cos_object.h b/src/cos_object.h index 8d1449d..2ded7ec 100644 --- a/src/cos_object.h +++ b/src/cos_object.h @@ -92,13 +92,45 @@ nspdferror cos_decode_object(struct pdf_doc *doc, uint64_t *offset_out, struct c nspdferror cos_free_object(struct cos_object *cos_obj); -nspdferror cos_dictionary_get_value(struct cos_object *dict, const char *key, struct cos_object **value_out); +/** + * extract a value for a key from a dictionary + * + * This retrieves the value of a given key in a dictionary and removes it from + * the dictionary. + * + * \param dict The dictionary + * \param key The key to lookup + * \param value_out The value object associated with the key + * \return NSPDFERROR_OK and value_out updated on success. + * NSPDFERROR_TYPE if the object passed in \p dict is not a dictionary. + * NSPDFERROR_NOTFOUND if the key is not present in the dictionary. + */ +nspdferror cos_extract_dictionary_value(struct cos_object *dict, const char *key, struct cos_object **value_out); + +/** + * get a value for a key from a dictionary + * + * \param dict The dictionary + * \param key The key to lookup + * \param value_out The value object associated with the key + * \return NSPDFERROR_OK and value_out updated on success. + * NSPDFERROR_TYPE if the object passed in \p dict is not a dictionary. + * NSPDFERROR_NOTFOUND if the key is not present in the dictionary. + */ +nspdferror cos_get_dictionary_value(struct pdf_doc *doc, struct cos_object *dict, const char *key, struct cos_object **value_out); + + +nspdferror cos_get_dictionary_int(struct pdf_doc *doc, struct cos_object *dict, const char *key, int64_t *value_out); + -nspdferror cos_dictionary_extract_value(struct cos_object *dict, const char *key, struct cos_object **value_out); +nspdferror cos_get_dictionary_name(struct pdf_doc *doc, struct cos_object *dict, const char *key, const char **value_out); +nspdferror cos_get_dictionary_dictionary(struct pdf_doc *doc, struct cos_object *dict, const char *key, struct cos_object **value_out); nspdferror cos_get_int(struct pdf_doc *doc, struct cos_object *cobj, int64_t *value_out); -nspdferror cos_get_dictionary(struct pdf_doc *doc, struct cos_object *cobj, struct cos_object **value_out); + +nspdferror cos_get_name(struct pdf_doc *doc, struct cos_object *cobj, const char **value_out); +nspdferror cos_get_dictionary(struct pdf_doc *doc, struct cos_object *cobj, struct cos_object **value_out); diff --git a/src/nspdferror.h b/src/nspdferror.h index c6042eb..3e26813 100644 --- a/src/nspdferror.h +++ b/src/nspdferror.h @@ -6,4 +6,5 @@ typedef enum { NSPDFERROR_RANGE, /**< value outside type range */ NSPDFERROR_TYPE, /**< wrong type error */ NSPDFERROR_NOTFOUND, /**< key not found */ + NSPDFERROR_FORMAT, /**< objects do not cornform to expected format */ } nspdferror; diff --git a/src/xref.c b/src/xref.c index b1748be..8239f45 100644 --- a/src/xref.c +++ b/src/xref.c @@ -365,7 +365,6 @@ nspdferror decode_xref_trailer(struct pdf_doc *doc, uint64_t xref_offset) uint64_t offset; /* the current data offset */ uint64_t startxref; /* the value of the startxref field */ struct cos_object *trailer; /* the current trailer */ - struct cos_object *cobj_prev; int64_t prev; offset = xref_offset; @@ -394,22 +393,15 @@ nspdferror decode_xref_trailer(struct pdf_doc *doc, uint64_t xref_offset) if (doc->xref_table == NULL) { /* extract Size from trailer and create xref table large enough */ - struct cos_object *cobj_size; int64_t size; - res = cos_dictionary_get_value(trailer, "Size", &cobj_size); + res = cos_get_dictionary_int(doc, trailer, "Size", &size); if (res != NSPDFERROR_OK) { - printf("trailer has no Size value\n"); + printf("trailer has no integer Size value\n"); goto decode_xref_trailer_failed; } - res = cos_get_int(doc, cobj_size, &size); - if (res != NSPDFERROR_OK) { - printf("trailer Size not int\n"); - goto decode_xref_trailer_failed; - } - - res = cos_dictionary_extract_value(trailer, "Root", &doc->root); + res = cos_extract_dictionary_value(trailer, "Root", &doc->root); if (res != NSPDFERROR_OK) { printf("no Root!\n"); goto decode_xref_trailer_failed; @@ -422,17 +414,17 @@ nspdferror decode_xref_trailer(struct pdf_doc *doc, uint64_t xref_offset) } doc->xref_size = size; - res = cos_dictionary_extract_value(trailer, "Encrypt", &doc->encrypt); + res = cos_extract_dictionary_value(trailer, "Encrypt", &doc->encrypt); if ((res != NSPDFERROR_OK) && (res != NSPDFERROR_NOTFOUND)) { goto decode_xref_trailer_failed; } - res = cos_dictionary_extract_value(trailer, "Info", &doc->info); + res = cos_extract_dictionary_value(trailer, "Info", &doc->info); if ((res != NSPDFERROR_OK) && (res != NSPDFERROR_NOTFOUND)) { goto decode_xref_trailer_failed; } - res = cos_dictionary_extract_value(trailer, "ID", &doc->id); + res = cos_extract_dictionary_value(trailer, "ID", &doc->id); if ((res != NSPDFERROR_OK) && (res != NSPDFERROR_NOTFOUND)) { goto decode_xref_trailer_failed; } @@ -440,14 +432,8 @@ nspdferror decode_xref_trailer(struct pdf_doc *doc, uint64_t xref_offset) } /* check for prev ID key in trailer and recurse call if present */ - res = cos_dictionary_get_value(trailer, "Prev", &cobj_prev); + res = cos_get_dictionary_int(doc, trailer, "Prev", &prev); if (res == NSPDFERROR_OK) { - res = cos_get_int(doc, cobj_prev, &prev); - if (res != NSPDFERROR_OK) { - printf("trailer Prev not int\n"); - goto decode_xref_trailer_failed; - } - res = decode_xref_trailer(doc, prev); if (res != NSPDFERROR_OK) { goto decode_xref_trailer_failed; @@ -517,9 +503,38 @@ nspdferror decode_catalog(struct pdf_doc *doc) { nspdferror res; struct cos_object *catalog; + const char *type; + struct cos_object *pages; res = cos_get_dictionary(doc, doc->root, &catalog); - + if (res != NSPDFERROR_OK) { + return res; + } + + // Type = Catalog + res = cos_get_dictionary_name(doc, catalog, "Type", &type); + if (res != NSPDFERROR_OK) { + return res; + } + if (strcmp(type, "Catalog") != 0) { + return NSPDFERROR_FORMAT; + } + + // Pages + res = cos_get_dictionary_dictionary(doc, catalog, "Pages", &pages); + if (res != NSPDFERROR_OK) { + return res; + } + + // Type = Pages + res = cos_get_dictionary_name(doc, pages, "Type", &type); + if (res != NSPDFERROR_OK) { + return res; + } + if (strcmp(type, "Pages") != 0) { + return NSPDFERROR_FORMAT; + } + return res; } @@ -539,6 +554,11 @@ int main(int argc, char **argv) struct pdf_doc *doc; int res; + if (argc < 2) { + fprintf(stderr, "Usage %s \n", argv[0]); + return 1; + } + res = new_pdf_doc(&doc); if (res != NSPDFERROR_OK) { printf("failed to read file\n"); -- cgit v1.2.3