mupdf
Loading...
Searching...
No Matches
xref.h
Go to the documentation of this file.
1// Copyright (C) 2004-2026 Artifex Software, Inc.
2//
3// This file is part of MuPDF.
4//
5// MuPDF is free software: you can redistribute it and/or modify it under the
6// terms of the GNU Affero General Public License as published by the Free
7// Software Foundation, either version 3 of the License, or (at your option)
8// any later version.
9//
10// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13// details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17//
18// Alternative licensing terms are available from the licensor.
19// For commercial licensing, see <https://www.artifex.com/> or contact
20// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21// CA 94129, USA, for further information.
22
23#ifndef MUPDF_PDF_XREF_H
24#define MUPDF_PDF_XREF_H
25
26#include "mupdf/pdf/document.h"
27
28/*
29 Allocate a slot in the xref table and return a fresh unused object number.
30*/
32
33/*
34 Remove object from xref table, marking the slot as free.
35*/
36void pdf_delete_object(fz_context *ctx, pdf_document *doc, int num);
37
38/*
39 Replace object in xref table with the passed in object.
40*/
41void pdf_update_object(fz_context *ctx, pdf_document *doc, int num, pdf_obj *obj);
42
43/*
44 Replace stream contents for object in xref table with the passed in buffer.
45
46 The buffer contents must match the /Filter setting if 'compressed' is true.
47 If 'compressed' is false, the /Filter and /DecodeParms entries are deleted.
48 The /Length entry is updated.
49*/
50void pdf_update_stream(fz_context *ctx, pdf_document *doc, pdf_obj *ref, fz_buffer *buf, int compressed);
51
52/*
53 Return true if 'obj' is an indirect reference to an object that is held
54 by the "local" xref section.
55*/
57
60pdf_obj *pdf_add_stream(fz_context *ctx, pdf_document *doc, fz_buffer *buf, pdf_obj *obj, int compressed);
61
64
65typedef struct
66{
67 char type; /* 0=unset (f)ree i(n)use (o)bjstm */
68 unsigned char marked; /* marked to keep alive with pdf_mark_xref */
69 unsigned short gen; /* generation / objstm index */
70 int num; /* original object number (for decryption after renumbering) */
71 int64_t ofs; /* file offset / objstm object number */
72 int64_t stm_ofs; /* on-disk stream */
73 fz_buffer *stm_buf; /* in-memory stream (for updated objects) */
74 pdf_obj *obj; /* stored/cached object */
76
84
96
105
107
109
119
129
130/*
131 Load raw (compressed but decrypted) contents of a stream into buf.
132*/
135
136/*
137 Load uncompressed contents of a stream into buf.
138*/
141
142/*
143 Open a stream for reading the raw (compressed but decrypted) data.
144*/
147
148/*
149 Open a stream for reading uncompressed data.
150 Put the opened file in doc->stream.
151 Using doc->file while a stream is open is a Bad idea.
152*/
155
156/*
157 Construct a filter to decode a stream, without
158 constraining to stream length, and without decryption.
159*/
162void pdf_load_compressed_inline_image(fz_context *ctx, pdf_document *doc, pdf_obj *dict, size_t length, fz_stream *cstm, int indexed, fz_compressed_image *image);
163fz_stream *pdf_open_stream_with_offset(fz_context *ctx, pdf_document *doc, int num, pdf_obj *dict, int64_t stm_ofs);
165fz_buffer *pdf_load_image_stream(fz_context *ctx, pdf_document *doc, int num, fz_compression_params *params, int *truncated, size_t worst_case);
166
172
174
175/*
176 Used while reading the individual xref sections from a file.
177*/
179
180/*
181 Used after loading a document to access entries.
182
183 This will never throw anything, or return NULL if it is
184 only asked to return objects in range within a 'solid'
185 xref.
186
187 This may "solidify" the xref (so can cause allocations).
188*/
190
191/*
192 Map a function across all xref entries in a document.
193*/
194void pdf_xref_entry_map(fz_context *ctx, pdf_document *doc, void (*fn)(fz_context *, pdf_xref_entry *, int i, pdf_document *doc, void *), void *arg);
195
196
197/*
198 Used after loading a document to access entries.
199
200 This will never throw anything, or return NULL if it is
201 only asked to return objects in range within a 'solid'
202 xref.
203
204 This will never "solidify" the xref, so no entry may be found
205 (NULL will be returned) for free entries.
206
207 Called with a valid i, this will never try/catch or throw.
208*/
211void pdf_replace_xref(fz_context *ctx, pdf_document *doc, pdf_xref_entry *entries, int n);
214
215/*
216 Ensure that an object has been cloned into the incremental xref section.
217*/
225
227
228/*
229 Ensure that the current populating xref has a single subsection
230 that covers the entire range.
231*/
236
237int pdf_repair_obj(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf, int64_t *stmofsp, int64_t *stmlenp, pdf_obj **encrypt, pdf_obj **id, pdf_obj **page, int64_t *tmpofs, pdf_obj **root);
238
240
241/*
242 Return the number of versions that there
243 are in a file. i.e. 1 + the number of updates that
244 the file on disc has been through. i.e. internal
245 unsaved changes to the file (such as appearance streams)
246 are ignored. Also, the initial write of a linearized
247 file (which appears as a base file write + an incremental
248 update) is treated as a single version.
249*/
252int pdf_validate_changes(fz_context *ctx, pdf_document *doc, int version);
254
256int pdf_is_field_locked(fz_context *ctx, pdf_locked_fields *locked, const char *name);
260
261/*
262 Check the entire history of the document, and return the number of
263 the last version that checked out OK.
264 i.e. 0 = "the entire history checks out OK".
265 n = "none of the history checked out OK".
266*/
268
269/*
270 Find which version of a document the current version of obj
271 was defined in.
272
273 version = 0 = latest, 1 = previous update etc, allowing for
274 the first incremental update in a linearized file being ignored.
275*/
277
278/*
279 Return the number of updates ago when a signature field
280 became invalid, not counting any unsaved changes.
281
282 Thus:
283 -1 => Has changed in the current unsaved changes.
284 0 => still valid.
285 1 => became invalid on the last save
286 n => became invalid n saves ago
287*/
291
292/* Local xrefs - designed for holding stuff that shouldn't be written
293 * back into the actual document, such as synthesized appearance
294 * streams. */
296
299
300/* Debug call to dump the incremental/local xrefs to the
301 * debug channel. */
303
304#endif
struct pdf_annot pdf_annot
Definition annot.h:32
struct fz_compressed_image fz_compressed_image
Definition image.h:42
struct pdf_obj pdf_obj
Definition object.h:44
Definition buffer.h:41
Definition compressed-buffer.h:93
Definition compressed-buffer.h:37
Definition context.h:886
Definition stream.h:320
Definition document.h:463
Definition document.h:48
Definition form.h:230
Definition document.h:433
Definition xref.h:66
unsigned short gen
Definition xref.h:69
unsigned char marked
Definition xref.h:68
char type
Definition xref.h:67
fz_buffer * stm_buf
Definition xref.h:73
int64_t stm_ofs
Definition xref.h:72
pdf_obj * obj
Definition xref.h:74
int num
Definition xref.h:70
int64_t ofs
Definition xref.h:71
Definition xref.h:78
int start
Definition xref.h:81
int len
Definition xref.h:80
struct pdf_xref_subsec * next
Definition xref.h:79
pdf_xref_entry * table
Definition xref.h:82
Definition xref.h:86
pdf_unsaved_sig * unsaved_sigs
Definition xref.h:92
pdf_obj * trailer
Definition xref.h:90
int num_subsecs
Definition xref.h:88
pdf_xref_subsec * subsec
Definition xref.h:89
int64_t end_ofs
Definition xref.h:94
int num_objects
Definition xref.h:87
pdf_unsaved_sig ** unsaved_sigs_end
Definition xref.h:93
pdf_obj * pre_repair_trailer
Definition xref.h:91
int pdf_version(fz_context *ctx, pdf_document *doc)
fz_buffer * pdf_load_stream(fz_context *ctx, pdf_obj *ref)
int pdf_count_objects(fz_context *ctx, pdf_document *doc)
pdf_obj * pdf_add_stream(fz_context *ctx, pdf_document *doc, fz_buffer *buf, pdf_obj *obj, int compressed)
void pdf_debug_doc_changes(fz_context *ctx, pdf_document *doc)
pdf_obj * pdf_metadata(fz_context *ctx, pdf_document *doc)
fz_stream * pdf_open_raw_stream(fz_context *ctx, pdf_obj *ref)
fz_buffer * pdf_load_raw_stream(fz_context *ctx, pdf_obj *ref)
pdf_xref_entry * pdf_get_incremental_xref_entry(fz_context *ctx, pdf_document *doc, int i)
pdf_obj * pdf_add_new_array(fz_context *ctx, pdf_document *doc, int initial)
void pdf_set_trailer(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
int pdf_object_exists(fz_context *ctx, pdf_document *doc, int num)
void pdf_drop_locked_fields(fz_context *ctx, pdf_locked_fields *locked)
fz_stream * pdf_open_contents_stream(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
void pdf_clear_xref(fz_context *ctx, pdf_document *doc)
fz_buffer * pdf_load_raw_stream_number(fz_context *ctx, pdf_document *doc, int num)
int pdf_count_versions(fz_context *ctx, pdf_document *doc)
int pdf_xref_is_incremental(fz_context *ctx, pdf_document *doc, int num)
int pdf_find_version_for_obj(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
pdf_obj * pdf_resolve_indirect(fz_context *ctx, pdf_obj *ref)
void pdf_set_populating_xref_trailer(fz_context *ctx, pdf_document *doc, pdf_obj *trailer)
void pdf_delete_object(fz_context *ctx, pdf_document *doc, int num)
void pdf_ensure_solid_xref(fz_context *ctx, pdf_document *doc, int num)
void pdf_load_compressed_inline_image(fz_context *ctx, pdf_document *doc, pdf_obj *dict, size_t length, fz_stream *cstm, int indexed, fz_compressed_image *image)
int pdf_repair_obj(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf, int64_t *stmofsp, int64_t *stmlenp, pdf_obj **encrypt, pdf_obj **id, pdf_obj **page, int64_t *tmpofs, pdf_obj **root)
fz_buffer * pdf_load_stream_number(fz_context *ctx, pdf_document *doc, int num)
pdf_obj * pdf_add_object(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
pdf_xref * pdf_new_local_xref(fz_context *ctx, pdf_document *doc)
void pdf_update_stream(fz_context *ctx, pdf_document *doc, pdf_obj *ref, fz_buffer *buf, int compressed)
void pdf_xref_remove_unsaved_signature(fz_context *ctx, pdf_document *doc, pdf_obj *field)
void pdf_replace_xref(fz_context *ctx, pdf_document *doc, pdf_xref_entry *entries, int n)
pdf_obj * pdf_load_object(fz_context *ctx, pdf_document *doc, int num)
int pdf_validate_changes(fz_context *ctx, pdf_document *doc, int version)
pdf_xref_entry * pdf_get_xref_entry_no_change(fz_context *ctx, pdf_document *doc, int i)
int pdf_is_local_object(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
void pdf_clear_xref_to_mark(fz_context *ctx, pdf_document *doc)
pdf_xref_entry * pdf_get_xref_entry(fz_context *ctx, pdf_document *doc, int i)
void pdf_repair_xref(fz_context *ctx, pdf_document *doc)
struct pdf_locked_fields pdf_locked_fields
Definition xref.h:255
pdf_xref_entry * pdf_get_xref_entry_no_null(fz_context *ctx, pdf_document *doc, int i)
pdf_obj * pdf_resolve_indirect_chain(fz_context *ctx, pdf_obj *ref)
void pdf_update_object(fz_context *ctx, pdf_document *doc, int num, pdf_obj *obj)
int pdf_count_unsaved_versions(fz_context *ctx, pdf_document *doc)
pdf_obj * pdf_progressive_advance(fz_context *ctx, pdf_document *doc, int pagenum)
int pdf_validate_signature(fz_context *ctx, pdf_document *doc, pdf_obj *field)
pdf_xref_entry * pdf_get_populating_xref_entry(fz_context *ctx, pdf_document *doc, int i)
fz_stream * pdf_open_stream(fz_context *ctx, pdf_obj *ref)
pdf_obj * pdf_add_object_drop(fz_context *ctx, pdf_document *doc, pdf_obj *obj)
int pdf_obj_is_incremental(fz_context *ctx, pdf_obj *obj)
pdf_obj * pdf_trailer(fz_context *ctx, pdf_document *doc)
pdf_locked_fields * pdf_find_locked_fields_for_sig(fz_context *ctx, pdf_document *doc, pdf_obj *sig)
int pdf_xref_obj_is_unsaved_signature(pdf_document *doc, pdf_obj *obj)
int pdf_create_object(fz_context *ctx, pdf_document *doc)
fz_stream * pdf_open_raw_stream_number(fz_context *ctx, pdf_document *doc, int num)
int pdf_xref_len(fz_context *ctx, pdf_document *doc)
pdf_xref_entry * pdf_cache_object(fz_context *ctx, pdf_document *doc, int num)
fz_buffer * pdf_load_image_stream(fz_context *ctx, pdf_document *doc, int num, fz_compression_params *params, int *truncated, size_t worst_case)
int pdf_was_pure_xfa(fz_context *ctx, pdf_document *doc)
void pdf_drop_local_xref_and_resources(fz_context *ctx, pdf_document *doc)
pdf_obj * pdf_load_unencrypted_object(fz_context *ctx, pdf_document *doc, int num)
int pdf_doc_was_linearized(fz_context *ctx, pdf_document *doc)
void pdf_forget_xref(fz_context *ctx, pdf_document *doc)
void pdf_mark_xref(fz_context *ctx, pdf_document *doc)
int pdf_is_field_locked(fz_context *ctx, pdf_locked_fields *locked, const char *name)
int pdf_validate_change_history(fz_context *ctx, pdf_document *doc)
pdf_obj * pdf_add_new_dict(fz_context *ctx, pdf_document *doc, int initial)
fz_compressed_buffer * pdf_load_compressed_stream(fz_context *ctx, pdf_document *doc, int num, size_t worst_case)
fz_stream * pdf_open_inline_stream(fz_context *ctx, pdf_document *doc, pdf_obj *stmobj, size_t length, fz_stream *chain, fz_compression_params *params)
void pdf_xref_store_unsaved_signature(fz_context *ctx, pdf_document *doc, pdf_obj *field, pdf_pkcs7_signer *signer)
fz_stream * pdf_open_stream_with_offset(fz_context *ctx, pdf_document *doc, int num, pdf_obj *dict, int64_t stm_ofs)
pdf_locked_fields * pdf_find_locked_fields(fz_context *ctx, pdf_document *doc, int version)
int pdf_xref_ensure_incremental_object(fz_context *ctx, pdf_document *doc, int num)
int pdf_validate_signature_widget(fz_context *ctx, pdf_annot *widget)
void pdf_drop_local_xref(fz_context *ctx, pdf_xref *xref)
void pdf_xref_entry_map(fz_context *ctx, pdf_document *doc, void(*fn)(fz_context *, pdf_xref_entry *, int i, pdf_document *doc, void *), void *arg)
fz_stream * pdf_open_stream_number(fz_context *ctx, pdf_document *doc, int num)
void pdf_xref_ensure_local_object(fz_context *ctx, pdf_document *doc, int num)