summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cos_object.c127
-rw-r--r--src/cos_object.h38
-rw-r--r--src/nspdferror.h1
-rw-r--r--src/xref.c64
4 files changed, 182 insertions, 48 deletions
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,
@@ -145,6 +206,26 @@ cos_get_int(struct pdf_doc *doc,
}
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,
struct cos_object **value_out)
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 <filename>\n", argv[0]);
+ return 1;
+ }
+
res = new_pdf_doc(&doc);
if (res != NSPDFERROR_OK) {
printf("failed to read file\n");