/* * Copyright (c) 2020-2022, yzrh * * SPDX-License-Identifier: Apache-2.0 */ #ifdef __linux__ #define _GNU_SOURCE #endif /* __linux__ */ #include #include #include "pdf.h" static int _id_in(int id, int *ids) { for (int i = 1; i <= ids[0]; i++) if (ids[i] == id) return 1; return 0; } int pdf_get_obj(pdf_object_t **pdf, int id, pdf_object_t **obj) { if (*pdf == NULL || id <= 0) return 1; pdf_object_t *ptr = *pdf; while (ptr->next != NULL) { if (ptr->next->id == id) { *obj = ptr->next; return 0; } ptr = ptr->next; } return 1; } int pdf_get_count(pdf_object_t **pdf) { if (*pdf == NULL) return 1; int count = 0; pdf_object_t *ptr = (*pdf)->next; while (ptr != NULL) { count++; ptr = ptr->next; } return count; } int pdf_get_size(pdf_object_t **pdf) { if (*pdf == NULL) return 1; int size = 0; pdf_object_t *ptr = (*pdf)->next; while (ptr != NULL) { size += ptr->size; ptr = ptr->next; } return size; } int pdf_get_free_id(pdf_object_t **pdf) { if (*pdf == NULL) return 1; int free_id = 0; pdf_object_t *ptr; int id = 0; for (int i = 1; i < 100000000; i++) { ptr = (*pdf)->next; while (ptr != NULL) { if (ptr->id == i) { id = i; break; } ptr = ptr->next; } if (i != id) { free_id = i; break; } } return free_id; } int pdf_get_free_ids(pdf_object_t **pdf, int **ids, int count) { if (*pdf == NULL || *ids != NULL || count <= 0) return 1; *ids = malloc(count * sizeof(int)); if (*ids == NULL) return 1; int pos = 0; int id = 0; pdf_object_t *ptr; for (int i = 1; i < 100000000; i++) { ptr = (*pdf)->next; while (ptr != NULL) { if (ptr->id == i) { id = i; break; } ptr = ptr->next; } if (i != id) { (*ids)[pos] = i; if (pos == count - 1) return 0; pos++; } } return 1; } int pdf_get_catalog_id(pdf_object_t **pdf) { if (*pdf == NULL) return 1; int catalog_id = 0; pdf_object_t *ptr = (*pdf)->next; while (ptr != NULL) { if (ptr->dictionary != NULL && memmem(ptr->dictionary, ptr->dictionary_size, "/Catalog", 8) != NULL) catalog_id = ptr->id; ptr = ptr->next; } return catalog_id; } int pdf_get_xref_id(pdf_object_t **pdf) { if (*pdf == NULL) return 1; int xref_id = 0; pdf_object_t *ptr = (*pdf)->next; while (ptr != NULL) { if (ptr->dictionary != NULL && memmem(ptr->dictionary, ptr->dictionary_size, "/XRef", 5) != NULL) xref_id = ptr->id; ptr = ptr->next; } return xref_id; } int pdf_get_parent_id(pdf_object_t **pdf, int **id) { if (*pdf == NULL || *id != NULL) return 1; int id_size = 1; *id = malloc(sizeof(int)); if (*id == NULL) return 1; (*id)[0] = 0; pdf_object_t *ptr = (*pdf)->next; char *head; char *tail; char str[8]; int str_val; int *ret; while (ptr != NULL) { if (ptr->dictionary != NULL && (head = memmem(ptr->dictionary, ptr->dictionary_size, "/Parent ", 8)) != NULL && (tail = strchr(head + 8, ' ')) != NULL) { memset(str, 0, 8); memcpy(str, head + 8, (tail - head) - 8); str_val = atoi(str); if (!_id_in(str_val, *id)) { ret = realloc(*id, ++id_size * sizeof(int)); if (ret == NULL) return 1; else *id = ret; (*id)[0]++; (*id)[id_size - 1] = str_val; } } ptr = ptr->next; } return 0; } int pdf_get_kid_id(pdf_object_t **pdf, int id, int **kid) { if (*pdf == NULL || *kid != NULL) return 1; int kid_size = 1; *kid = malloc(sizeof(int)); if (*kid == NULL) return 1; pdf_object_t *ptr = (*pdf)->next; char str[32]; int *ret; snprintf(str, 32, "/Parent %d 0 R", id); while (ptr != NULL) { if (ptr->id == id) { (*kid)[0] = 0; return 1; } if (ptr->dictionary != NULL && memmem(ptr->dictionary, ptr->dictionary_size, str, strlen(str)) != NULL) { ret = realloc(*kid, ++kid_size * sizeof(int)); if (ret == NULL) return 1; else *kid = ret; (*kid)[kid_size - 1] = ptr->id; } ptr = ptr->next; } (*kid)[0] = kid_size - 1; return 0; } int pdf_get_kid_count(pdf_object_t **pdf, int id) { if (*pdf == NULL || id <= 0) return 1; int count = 0; pdf_object_t *ptr = (*pdf)->next; char id_str[32]; char *pos; char str[8]; int str_val; snprintf(id_str, 32, "/Parent %d 0 R", id); while (ptr != NULL) { if (ptr->dictionary != NULL && memmem(ptr->dictionary, ptr->dictionary_size, id_str, strlen(id_str)) != NULL && (pos = memmem(ptr->dictionary, ptr->dictionary_size, "/Count ", 7)) != NULL) { for (int i = 8; i >= 0; i--) { if (i + 7 <= ptr->dictionary_size - (pos - ptr->dictionary) && pos[i + 7] >= '0' && pos[i + 7] <= '9') { memset(str, 0, 8); memcpy(str, pos + 7, i + 1); str_val = atoi(str); count += str_val; break; } } } ptr = ptr->next; } return count; }