aboutsummaryrefslogblamecommitdiffstats
path: root/src/pdf_get.c
blob: bde5bf2bac673dd571092e4eaead9b1ad7febd22 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
  
                                                 



                                      





                      














































































                                                           
                                             
































                                                          
                                             











                                           
                                             




















                                              

                                                                     








                                             










                                              

                                                                     








                                          
























                                               

                                                                             

                                                                 
                                                                 













































                                                                            

                                                                     





































                                                                      



                                                                            



                                                                                              
                                                                    










                                                            
/*
 * Copyright (c) 2020-2022, yzrh <yzrh@noema.org>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifdef __linux__

#define _GNU_SOURCE

#endif /* __linux__ */

#include <stdlib.h>
#include <string.h>

#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;
}