mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-06-06 13:34:22 +02:00
Compare commits
No commits in common. "cad8f450ab0d267db33e47c6a171bb0c372a87d8" and "1e6bb710e30e64ae55edb32d248deb21c852ced2" have entirely different histories.
cad8f450ab
...
1e6bb710e3
35
doc/pdfio.3
35
doc/pdfio.3
@ -1,4 +1,4 @@
|
||||
.TH pdfio 3 "pdf read/write library" "2025-04-23" "pdf read/write library"
|
||||
.TH pdfio 3 "pdf read/write library" "2025-04-13" "pdf read/write library"
|
||||
.SH NAME
|
||||
pdfio \- pdf read/write library
|
||||
.SH Introduction
|
||||
@ -325,7 +325,7 @@ where the five arguments to the function are the filename ("myinputfile.pdf"), a
|
||||
}
|
||||
.fi
|
||||
.PP
|
||||
The error callback is called for both errors and warnings and accepts the pdfio_file_t pointer, a message string, and the callback pointer value. It returns true to continue processing the file or false to stop, for example:
|
||||
The error callback is called for both errors and warnings and accepts the pdfio_file_t pointer, a message string, and the callback pointer value, for example:
|
||||
.nf
|
||||
|
||||
bool
|
||||
@ -335,15 +335,12 @@ The error callback is called for both errors and warnings and accepts the pdfio_
|
||||
|
||||
fprintf(stderr, "%s: %s\\n", pdfioFileGetName(pdf), message);
|
||||
|
||||
// Return true for warning messages (continue) and false for errors (stop)
|
||||
return (!strncmp(message, "WARNING:", 8));
|
||||
// Return false to treat warnings as errors
|
||||
return (false);
|
||||
}
|
||||
.fi
|
||||
.PP
|
||||
The default error callback (NULL) does the equivalent of the above.
|
||||
.PP
|
||||
Note: Many errors are unrecoverable, so PDFio ignores the return value from the error callback and always stops processing the PDF file. Warning messages start with the prefix "WARNING:" while errors have no prefix.
|
||||
|
||||
.PP
|
||||
Each PDF file contains one or more pages. The pdfioFileGetNumPages function returns the number of pages in the file while the pdfioFileGetPage function gets the specified page in the PDF file:
|
||||
.nf
|
||||
@ -3913,9 +3910,8 @@ CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" siz
|
||||
of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||
.PP
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if \fBNULL\fR then the default error handler is used that
|
||||
writes error messages to \fBstderr\fR. The error handler callback should return
|
||||
\fBtrue\fR to continue writing the PDF file or \fBfalse\fR to stop.
|
||||
and its data pointer - if \fBNULL\fR the default error handler is used that
|
||||
writes error messages to \fBstderr\fR.
|
||||
.SS pdfioFileCreateArrayObj
|
||||
Create a new object in a PDF file containing an array.
|
||||
.PP
|
||||
@ -4156,9 +4152,8 @@ CropBox for pages in the PDF file - if \fBNULL\fR then a default "Universal" siz
|
||||
of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||
.PP
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if \fBNULL\fR then the default error handler is used that
|
||||
writes error messages to \fBstderr\fR. The error handler callback should return
|
||||
\fBtrue\fR to continue writing the PDF file or \fBfalse\fR to stop.
|
||||
and its data pointer - if \fBNULL\fR the default error handler is used that
|
||||
writes error messages to \fBstderr\fR.
|
||||
.PP
|
||||
.IP 5
|
||||
\fINote\fR: Files created using this API are slightly larger than those
|
||||
@ -4397,18 +4392,8 @@ cancel the open. If \fBNULL\fR is specified for the callback function and the
|
||||
PDF file requires a password, the open will always fail.
|
||||
.PP
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if \fBNULL\fR then the default error handler is used that
|
||||
writes error messages to \fBstderr\fR. The error handler callback should return
|
||||
\fBtrue\fR to continue reading the PDF file or \fBfalse\fR to stop.
|
||||
.PP
|
||||
.IP 5
|
||||
Note: Error messages starting with "WARNING:" are actually warning
|
||||
.IP 5
|
||||
messages - the callback should normally return \fBtrue\fR to allow PDFio to
|
||||
.IP 5
|
||||
try to resolve the issue. In addition, some errors are unrecoverable and
|
||||
.IP 5
|
||||
ignore the return value of the error callback.
|
||||
and its data pointer - if \fBNULL\fR the default error handler is used that
|
||||
writes error messages to \fBstderr\fR.
|
||||
.SS pdfioFileSetAuthor
|
||||
Set the author for a PDF file.
|
||||
.PP
|
||||
|
@ -732,7 +732,7 @@ password_cb(<span class="reserved">void</span> *data, <span class="reserved">con
|
||||
<span class="reserved">return</span> (<span class="string">"Password42"</span>);
|
||||
}
|
||||
</code></pre>
|
||||
<p>The error callback is called for both errors and warnings and accepts the <code>pdfio_file_t</code> pointer, a message string, and the callback pointer value. It returns <code>true</code> to continue processing the file or <code>false</code> to stop, for example:</p>
|
||||
<p>The error callback is called for both errors and warnings and accepts the <code>pdfio_file_t</code> pointer, a message string, and the callback pointer value, for example:</p>
|
||||
<pre><code class="language-c"><span class="reserved">bool</span>
|
||||
error_cb(pdfio_file_t *pdf, <span class="reserved">const</span> <span class="reserved">char</span> *message, <span class="reserved">void</span> *data)
|
||||
{
|
||||
@ -740,14 +740,11 @@ error_cb(pdfio_file_t *pdf, <span class="reserved">const</span> <span class="res
|
||||
|
||||
fprintf(stderr, <span class="string">"%s: %s\n"</span>, pdfioFileGetName(pdf), message);
|
||||
|
||||
<span class="comment">// Return true for warning messages (continue) and false for errors (stop)</span>
|
||||
<span class="reserved">return</span> (!strncmp(message, <span class="string">"WARNING:"</span>, <span class="number">8</span>));
|
||||
<span class="comment">// Return false to treat warnings as errors</span>
|
||||
<span class="reserved">return</span> (<span class="reserved">false</span>);
|
||||
}
|
||||
</code></pre>
|
||||
<p>The default error callback (<code>NULL</code>) does the equivalent of the above.</p>
|
||||
<blockquote>
|
||||
<p>Note: Many errors are unrecoverable, so PDFio ignores the return value from the error callback and always stops processing the PDF file. Warning messages start with the prefix "WARNING:" while errors have no prefix.</p>
|
||||
</blockquote>
|
||||
<p>Each PDF file contains one or more pages. The <a href="#pdfioFileGetNumPages"><code>pdfioFileGetNumPages</code></a> function returns the number of pages in the file while the <a href="#pdfioFileGetPage"><code>pdfioFileGetPage</code></a> function gets the specified page in the PDF file:</p>
|
||||
<pre><code class="language-c">pdfio_file_t *pdf; <span class="comment">// PDF file</span>
|
||||
size_t i; <span class="comment">// Looping var</span>
|
||||
@ -4132,9 +4129,8 @@ CropBox for pages in the PDF file - if <code>NULL</code> then a default "Un
|
||||
of 8.27x11in (the intersection of US Letter and ISO A4) is used.<br>
|
||||
<br>
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if <code>NULL</code> then the default error handler is used that
|
||||
writes error messages to <code>stderr</code>. The error handler callback should return
|
||||
<code>true</code> to continue writing the PDF file or <code>false</code> to stop.</p>
|
||||
and its data pointer - if <code>NULL</code> the default error handler is used that
|
||||
writes error messages to <code>stderr</code>.</p>
|
||||
<h3 class="function"><a id="pdfioFileCreateArrayObj">pdfioFileCreateArrayObj</a></h3>
|
||||
<p class="description">Create a new object in a PDF file containing an array.</p>
|
||||
<p class="code">
|
||||
@ -4438,9 +4434,8 @@ CropBox for pages in the PDF file - if <code>NULL</code> then a default "Un
|
||||
of 8.27x11in (the intersection of US Letter and ISO A4) is used.<br>
|
||||
<br>
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if <code>NULL</code> then the default error handler is used that
|
||||
writes error messages to <code>stderr</code>. The error handler callback should return
|
||||
<code>true</code> to continue writing the PDF file or <code>false</code> to stop.<br>
|
||||
and its data pointer - if <code>NULL</code> the default error handler is used that
|
||||
writes error messages to <code>stderr</code>.<br>
|
||||
<br>
|
||||
</p><blockquote>
|
||||
<em>Note</em>: Files created using this API are slightly larger than those
|
||||
@ -4777,15 +4772,8 @@ cancel the open. If <code>NULL</code> is specified for the callback function an
|
||||
PDF file requires a password, the open will always fail.<br>
|
||||
<br>
|
||||
The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
and its data pointer - if <code>NULL</code> then the default error handler is used that
|
||||
writes error messages to <code>stderr</code>. The error handler callback should return
|
||||
<code>true</code> to continue reading the PDF file or <code>false</code> to stop.<br>
|
||||
<br>
|
||||
</p><blockquote>
|
||||
Note: Error messages starting with "WARNING:" are actually warning
|
||||
messages - the callback should normally return <code>true</code> to allow PDFio to
|
||||
try to resolve the issue. In addition, some errors are unrecoverable and
|
||||
ignore the return value of the error callback.</blockquote>
|
||||
and its data pointer - if <code>NULL</code> the default error handler is used that
|
||||
writes error messages to <code>stderr</code>.</p>
|
||||
<h3 class="function"><a id="pdfioFileSetAuthor">pdfioFileSetAuthor</a></h3>
|
||||
<p class="description">Set the author for a PDF file.</p>
|
||||
<p class="code">
|
||||
|
12
doc/pdfio.md
12
doc/pdfio.md
@ -343,8 +343,8 @@ password_cb(void *data, const char *filename)
|
||||
```
|
||||
|
||||
The error callback is called for both errors and warnings and accepts the
|
||||
`pdfio_file_t` pointer, a message string, and the callback pointer value. It
|
||||
returns `true` to continue processing the file or `false` to stop, for example:
|
||||
`pdfio_file_t` pointer, a message string, and the callback pointer value, for
|
||||
example:
|
||||
|
||||
```c
|
||||
bool
|
||||
@ -354,17 +354,13 @@ error_cb(pdfio_file_t *pdf, const char *message, void *data)
|
||||
|
||||
fprintf(stderr, "%s: %s\n", pdfioFileGetName(pdf), message);
|
||||
|
||||
// Return true for warning messages (continue) and false for errors (stop)
|
||||
return (!strncmp(message, "WARNING:", 8));
|
||||
// Return false to treat warnings as errors
|
||||
return (false);
|
||||
}
|
||||
```
|
||||
|
||||
The default error callback (`NULL`) does the equivalent of the above.
|
||||
|
||||
> Note: Many errors are unrecoverable, so PDFio ignores the return value from
|
||||
> the error callback and always stops processing the PDF file. Warning messages
|
||||
> start with the prefix "WARNING:" while errors have no prefix.
|
||||
|
||||
Each PDF file contains one or more pages. The [`pdfioFileGetNumPages`](@@)
|
||||
function returns the number of pages in the file while the
|
||||
[`pdfioFileGetPage`](@@) function gets the specified page in the PDF file:
|
||||
|
@ -47,7 +47,7 @@ _pdfioFileConsume(pdfio_file_t *pdf, // I - PDF file
|
||||
// `false` to halt.
|
||||
//
|
||||
|
||||
bool // O - `false` to stop, `true` to continue
|
||||
bool // O - `false` to stop
|
||||
_pdfioFileDefaultError(
|
||||
pdfio_file_t *pdf, // I - PDF file
|
||||
const char *message, // I - Error message
|
||||
@ -57,7 +57,7 @@ _pdfioFileDefaultError(
|
||||
|
||||
fprintf(stderr, "%s: %s\n", pdf->filename, message);
|
||||
|
||||
return (!strncmp(message, "WARNING:", 8));
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
||||
@ -134,20 +134,19 @@ _pdfioFileGetChar(pdfio_file_t *pdf) // I - PDF file
|
||||
bool // O - `true` on success, `false` on error
|
||||
_pdfioFileGets(pdfio_file_t *pdf, // I - PDF file
|
||||
char *buffer, // I - Line buffer
|
||||
size_t bufsize, // I - Size of line buffer
|
||||
bool discard) // I - OK to discard excess line chars?
|
||||
size_t bufsize) // I - Size of line buffer
|
||||
{
|
||||
bool eol = false; // End of line?
|
||||
char *bufptr = buffer, // Pointer into buffer
|
||||
*bufend = buffer + bufsize - 1; // Pointer to end of buffer
|
||||
|
||||
|
||||
PDFIO_DEBUG("_pdfioFileGets(pdf=%p, buffer=%p, bufsize=%lu, discard=%s) bufpos=%ld, buffer=%p, bufptr=%p, bufend=%p, offset=%lu\n", pdf, buffer, (unsigned long)bufsize, discard ? "true" : "false", (long)pdf->bufpos, pdf->buffer, pdf->bufptr, pdf->bufend, (unsigned long)(pdf->bufpos + (pdf->bufptr - pdf->buffer)));
|
||||
PDFIO_DEBUG("_pdfioFileGets(pdf=%p, buffer=%p, bufsize=%lu) bufpos=%ld, buffer=%p, bufptr=%p, bufend=%p, offset=%lu\n", pdf, buffer, (unsigned long)bufsize, (long)pdf->bufpos, pdf->buffer, pdf->bufptr, pdf->bufend, (unsigned long)(pdf->bufpos + (pdf->bufptr - pdf->buffer)));
|
||||
|
||||
while (!eol)
|
||||
{
|
||||
// If there are characters ready in the buffer, use them...
|
||||
while (!eol && pdf->bufptr < pdf->bufend)
|
||||
while (!eol && pdf->bufptr < pdf->bufend && bufptr < bufend)
|
||||
{
|
||||
char ch = *(pdf->bufptr++); // Next character in buffer
|
||||
|
||||
@ -169,10 +168,8 @@ _pdfioFileGets(pdfio_file_t *pdf, // I - PDF file
|
||||
pdf->bufptr ++;
|
||||
}
|
||||
}
|
||||
else if (bufptr < bufend)
|
||||
else
|
||||
*bufptr++ = ch;
|
||||
else if (!discard)
|
||||
break;
|
||||
}
|
||||
|
||||
// Fill the read buffer as needed...
|
||||
|
@ -643,11 +643,9 @@ _pdfioDictRead(pdfio_file_t *pdf, // I - PDF file
|
||||
{
|
||||
// Issue 118: Discard duplicate key/value pairs, in the future this will
|
||||
// be a warning message...
|
||||
_pdfioFileError(pdf, "WARNING: Discarding value for duplicate dictionary key '%s'.", key + 1);
|
||||
_pdfioValueDelete(&value);
|
||||
if (_pdfioFileError(pdf, "WARNING: Discarding value for duplicate dictionary key '%s'.", key + 1))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
else if (!_pdfioDictSetValue(dict, pdfioStringCreate(pdf, key + 1), &value))
|
||||
break;
|
||||
|
309
pdfio-file.c
309
pdfio-file.c
@ -188,9 +188,8 @@ pdfioFileClose(pdfio_file_t *pdf) // I - PDF file
|
||||
// of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||
//
|
||||
// The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
// and its data pointer - if `NULL` then the default error handler is used that
|
||||
// writes error messages to `stderr`. The error handler callback should return
|
||||
// `true` to continue writing the PDF file or `false` to stop.
|
||||
// and its data pointer - if `NULL` the default error handler is used that
|
||||
// writes error messages to `stderr`.
|
||||
//
|
||||
|
||||
pdfio_file_t * // O - PDF file or `NULL` on error
|
||||
@ -427,9 +426,8 @@ _pdfioFileCreateObj(
|
||||
// of 8.27x11in (the intersection of US Letter and ISO A4) is used.
|
||||
//
|
||||
// The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
// and its data pointer - if `NULL` then the default error handler is used that
|
||||
// writes error messages to `stderr`. The error handler callback should return
|
||||
// `true` to continue writing the PDF file or `false` to stop.
|
||||
// and its data pointer - if `NULL` the default error handler is used that
|
||||
// writes error messages to `stderr`.
|
||||
//
|
||||
// > *Note*: Files created using this API are slightly larger than those
|
||||
// > created using the @link pdfioFileCreate@ function since stream lengths are
|
||||
@ -1021,14 +1019,8 @@ pdfioFileGetVersion(
|
||||
// PDF file requires a password, the open will always fail.
|
||||
//
|
||||
// The "error_cb" and "error_cbdata" arguments specify an error handler callback
|
||||
// and its data pointer - if `NULL` then the default error handler is used that
|
||||
// writes error messages to `stderr`. The error handler callback should return
|
||||
// `true` to continue reading the PDF file or `false` to stop.
|
||||
//
|
||||
// > Note: Error messages starting with "WARNING:" are actually warning
|
||||
// > messages - the callback should normally return `true` to allow PDFio to
|
||||
// > try to resolve the issue. In addition, some errors are unrecoverable and
|
||||
// > ignore the return value of the error callback.
|
||||
// and its data pointer - if `NULL` the default error handler is used that
|
||||
// writes error messages to `stderr`.
|
||||
//
|
||||
|
||||
pdfio_file_t * // O - PDF file
|
||||
@ -1089,7 +1081,7 @@ pdfioFileOpen(
|
||||
}
|
||||
|
||||
// Read the header from the first line...
|
||||
if (!_pdfioFileGets(pdf, line, sizeof(line), true))
|
||||
if (!_pdfioFileGets(pdf, line, sizeof(line)))
|
||||
goto error;
|
||||
|
||||
if ((strncmp(line, "%PDF-1.", 7) && strncmp(line, "%PDF-2.", 7)) || !isdigit(line[7] & 255))
|
||||
@ -1103,7 +1095,7 @@ pdfioFileOpen(
|
||||
pdf->version = strdup(line + 5);
|
||||
|
||||
// Grab the last 1k of the file to find the start of the xref table...
|
||||
if (_pdfioFileSeek(pdf, 1 - sizeof(line), SEEK_END) < 0)
|
||||
if (_pdfioFileSeek(pdf, -1024, SEEK_END) < 0)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to read startxref data.");
|
||||
goto error;
|
||||
@ -1115,34 +1107,26 @@ pdfioFileOpen(
|
||||
goto error;
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("pdfioOpen: Read %d bytes at end of file.\n", (int)bytes);
|
||||
|
||||
line[bytes] = '\0';
|
||||
end = line + bytes - 9;
|
||||
|
||||
for (ptr = line; ptr < end; ptr ++)
|
||||
{
|
||||
if (!strncmp(ptr, "startxref", 9) && !strstr(ptr + 9, "startxref") && strtol(ptr + 9, NULL, 10) > 0)
|
||||
if (!memcmp(ptr, "startxref", 9))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ptr >= end)
|
||||
{
|
||||
if (!_pdfioFileError(pdf, "WARNING: Unable to find start of cross-reference table, will attempt to rebuild."))
|
||||
goto error;
|
||||
|
||||
if (!repair_xref(pdf, password_cb, password_cbdata))
|
||||
goto error;
|
||||
_pdfioFileError(pdf, "Unable to find start of xref table.");
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
|
||||
xref_offset = (off_t)strtol(ptr + 9, NULL, 10);
|
||||
|
||||
if (!load_xref(pdf, xref_offset, password_cb, password_cbdata))
|
||||
{
|
||||
PDFIO_DEBUG("pdfioFileOpen: line=%p,ptr=%p(\"%s\")\n", line, ptr, ptr);
|
||||
|
||||
xref_offset = (off_t)strtol(ptr + 9, NULL, 10);
|
||||
|
||||
PDFIO_DEBUG("pdfioFileOpen: xref_offset=%lu\n", (unsigned long)xref_offset);
|
||||
|
||||
if (!load_xref(pdf, xref_offset, password_cb, password_cbdata))
|
||||
if (!repair_xref(pdf, password_cb, password_cbdata))
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -1771,10 +1755,7 @@ load_pages(pdfio_file_t *pdf, // I - PDF file
|
||||
}
|
||||
|
||||
if ((type = pdfioDictGetName(dict, "Type")) == NULL || (strcmp(type, "Pages") && strcmp(type, "Page")))
|
||||
{
|
||||
if (!_pdfioFileError(pdf, "WARNING: No Type value for pages object."))
|
||||
return (false);
|
||||
}
|
||||
return (false);
|
||||
|
||||
// If there is a Kids array, then this is a parent node and we have to look
|
||||
// at the child objects...
|
||||
@ -1841,32 +1822,31 @@ load_xref(
|
||||
int generation; // Generation number
|
||||
_pdfio_token_t tb; // Token buffer/stack
|
||||
off_t line_offset; // Offset to start of line
|
||||
pdfio_obj_t *pages_obj; // Pages object
|
||||
|
||||
|
||||
while (!done)
|
||||
{
|
||||
if (_pdfioFileSeek(pdf, xref_offset, SEEK_SET) != xref_offset)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to seek to %lu.\n", (unsigned long)xref_offset);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to seek to start of xref table.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
line_offset = _pdfioFileTell(pdf);
|
||||
|
||||
if (!_pdfioFileGets(pdf, line, sizeof(line), true))
|
||||
if (!_pdfioFileGets(pdf, line, sizeof(line)))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to read line at offset %lu.\n", (unsigned long)line_offset);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to read start of xref table.");
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
while (!line[0]);
|
||||
|
||||
PDFIO_DEBUG("load_xref: line_offset=%lu, line='%s'\n", (unsigned long)line_offset, line);
|
||||
|
||||
if (isdigit(line[0] & 255) && strlen(line) > 4 && (!strcmp(line + strlen(line) - 4, " obj") || ((ptr = strstr(line, " obj")) != NULL && (ptr[4] == '<' || isspace(ptr[4])))))
|
||||
if (isdigit(line[0] & 255) && strlen(line) > 4 && (!strcmp(line + strlen(line) - 4, " obj") || ((ptr = strstr(line, " obj")) != NULL && ptr[4] == '<')))
|
||||
{
|
||||
// Cross-reference stream
|
||||
pdfio_obj_t *obj; // Object
|
||||
@ -1888,14 +1868,14 @@ load_xref(
|
||||
|
||||
if ((number = strtoimax(line, &ptr, 10)) < 1)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to scan object number.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if ((generation = (int)strtol(ptr, &ptr, 10)) < 0 || (generation > 65535 && number != 0))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to scan generation number (%u).\n", (unsigned)generation);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
while (isspace(*ptr & 255))
|
||||
@ -1903,14 +1883,14 @@ load_xref(
|
||||
|
||||
if (strncmp(ptr, "obj", 3))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: No 'obj' after object number and generation (saw '%s').\n", ptr);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (_pdfioFileSeek(pdf, line_offset + (off_t)(ptr + 3 - line), SEEK_SET) < 0)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to seek to start of cross-reference object dictionary.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to seek to xref object %lu %u.", (unsigned long)number, (unsigned)generation);
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("load_xref: Loading object %lu %u.\n", (unsigned long)number, (unsigned)generation);
|
||||
@ -1925,21 +1905,21 @@ load_xref(
|
||||
|
||||
if (!_pdfioValueRead(pdf, obj, &tb, &trailer, 0))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to read cross-reference object dictionary.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to read cross-reference stream dictionary.");
|
||||
return (false);
|
||||
}
|
||||
else if (trailer.type != PDFIO_VALTYPE_DICT)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Expected dictionary for cross-reference object (type=%d).", trailer.type);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Cross-reference stream does not have a dictionary.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
obj->value = trailer;
|
||||
|
||||
if (!_pdfioTokenGet(&tb, line, sizeof(line)) || strcmp(line, "stream"))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: No stream token after dictionary (got '%s').\n", line);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to get stream after xref dictionary.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("load_xref: tb.bufptr=%p, tb.bufend=%p, tb.bufptr[0]=0x%02x, tb.bufptr[0]=0x%02x\n", tb.bufptr, tb.bufend, tb.bufptr[0], tb.bufptr[1]);
|
||||
@ -1957,8 +1937,8 @@ load_xref(
|
||||
|
||||
if ((w_array = pdfioDictGetArray(trailer.value.dict, "W")) == NULL)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Missing W array in cross-reference objection dictionary.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Cross-reference stream does not have required W key.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
w[0] = (size_t)pdfioArrayGetNumber(w_array, 0);
|
||||
@ -1968,18 +1948,16 @@ load_xref(
|
||||
w_2 = w[0];
|
||||
w_3 = w[0] + w[1];
|
||||
|
||||
PDFIO_DEBUG("W=[%u %u %u], w_total=%u\n", (unsigned)w[0], (unsigned)w[1], (unsigned)w[2], (unsigned)w_total);
|
||||
|
||||
if (pdfioArrayGetSize(w_array) > 3 || w[1] == 0 || w[2] > 4 || w[0] > sizeof(buffer) || w[1] > sizeof(buffer) || w[2] > sizeof(buffer) || w_total > sizeof(buffer))
|
||||
if (w[1] == 0 || w[2] > 4 || w[0] > sizeof(buffer) || w[1] > sizeof(buffer) || w[2] > sizeof(buffer) || w_total > sizeof(buffer))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Bad W array in cross-reference objection dictionary.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Cross-reference stream has invalid W key [%u %u %u].", (unsigned)w[0], (unsigned)w[1], (unsigned)w[2]);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if ((st = pdfioObjOpenStream(obj, true)) == NULL)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to open cross-reference stream.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to open cross-reference stream.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
for (index_n = 0; index_n < index_count; index_n += 2)
|
||||
@ -1999,20 +1977,7 @@ load_xref(
|
||||
{
|
||||
count --;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (w_total > 5)
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X%02X%02X%02X%02X...\n", (unsigned)number, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]);
|
||||
else if (w_total == 5)
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X%02X%02X%02X%02X\n", (unsigned)number, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]);
|
||||
else if (w_total == 4)
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X%02X%02X%02X\n", (unsigned)number, buffer[0], buffer[1], buffer[2], buffer[3]);
|
||||
else if (w_total == 3)
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X%02X%02X\n", (unsigned)number, buffer[0], buffer[1], buffer[2]);
|
||||
else if (w_total == 2)
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X%02X\n", (unsigned)number, buffer[0], buffer[1]);
|
||||
else
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X\n", (unsigned)number, buffer[0]);
|
||||
#endif // DEBUG
|
||||
PDFIO_DEBUG("load_xref: number=%u %02X%02X%02X%02X%02X\n", (unsigned)number, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]);
|
||||
|
||||
// Check whether this is an object definition...
|
||||
if (w[0] > 0)
|
||||
@ -2094,7 +2059,6 @@ load_xref(
|
||||
else
|
||||
{
|
||||
_pdfioFileError(pdf, "Too many object streams.");
|
||||
pdfioStreamClose(st);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
@ -2103,10 +2067,7 @@ load_xref(
|
||||
{
|
||||
// Add this object...
|
||||
if (!add_obj(pdf, (size_t)number, (unsigned short)generation, (off_t)offset))
|
||||
{
|
||||
pdfioStreamClose(st);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
number ++;
|
||||
@ -2154,7 +2115,7 @@ load_xref(
|
||||
// Offset of current line
|
||||
|
||||
PDFIO_DEBUG("load_xref: Reading xref table starting at offset %lu\n", (unsigned long)trailer_offset);
|
||||
while (_pdfioFileGets(pdf, line, sizeof(line), false))
|
||||
while (_pdfioFileGets(pdf, line, sizeof(line)))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: '%s' at offset %lu\n", line, (unsigned long)trailer_offset);
|
||||
|
||||
@ -2179,8 +2140,8 @@ load_xref(
|
||||
|
||||
if (sscanf(line, "%jd%jd", &number, &num_objects) != 2)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to scan START COUNT from line.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Malformed xref table section '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Read this group of objects...
|
||||
@ -2188,45 +2149,41 @@ load_xref(
|
||||
{
|
||||
// Read a line from the file and validate it...
|
||||
if (_pdfioFileRead(pdf, line, 20) != 20)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to read 20 byte xref record.\n");
|
||||
goto repair;
|
||||
}
|
||||
return (false);
|
||||
|
||||
line[20] = '\0';
|
||||
|
||||
if (strcmp(line + 18, "\r\n") && strcmp(line + 18, "\r\r") && strcmp(line + 18, " \n") && strcmp(line + 18, " \r"))
|
||||
if (strcmp(line + 18, "\r\n") && strcmp(line + 18, " \n") && strcmp(line + 18, " \r"))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Bad end-of-line <%02X%02X>\n", line[18], line[19]);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
line[18] = '\0';
|
||||
|
||||
// Parse the line
|
||||
if ((offset = strtoimax(line, &ptr, 10)) < 0)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to scan offset.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if ((generation = (int)strtol(ptr, &ptr, 10)) < 0 || (generation > 65535 && offset != 0))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to scan generation (%u).\n", (unsigned)generation);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (*ptr != ' ')
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Missing space before type.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
ptr ++;
|
||||
if (*ptr != 'f' && *ptr != 'n')
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Bad type '%c'.\n", *ptr);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Malformed xref table entry '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (*ptr == 'f')
|
||||
@ -2245,21 +2202,21 @@ load_xref(
|
||||
|
||||
if (strncmp(line, "trailer", 7))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: No trailer after xref table.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Missing trailer.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_pdfioTokenInit(&tb, pdf, (_pdfio_tconsume_cb_t)_pdfioFileConsume, (_pdfio_tpeek_cb_t)_pdfioFilePeek, pdf);
|
||||
|
||||
if (!_pdfioValueRead(pdf, NULL, &tb, &trailer, 0))
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Unable to read trailer dictionary.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Unable to read trailer dictionary.");
|
||||
return (false);
|
||||
}
|
||||
else if (trailer.type != PDFIO_VALTYPE_DICT)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Trailer not a dictionary (type=%d).\n", trailer.type);
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Trailer is not a dictionary.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("load_xref: Got trailer dict.\n");
|
||||
@ -2281,7 +2238,8 @@ load_xref(
|
||||
}
|
||||
else
|
||||
{
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Bad xref table header '%s'.", line);
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("load_xref: Contents of trailer dictionary:\n");
|
||||
@ -2310,31 +2268,13 @@ load_xref(
|
||||
|
||||
if ((pdf->root_obj = pdfioDictGetObj(pdf->trailer_dict, "Root")) == NULL)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Missing Root object.\n");
|
||||
goto repair;
|
||||
_pdfioFileError(pdf, "Missing Root object.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("load_xref: Root=%p(%lu)\n", pdf->root_obj, (unsigned long)pdf->root_obj->number);
|
||||
|
||||
if ((pages_obj = pdfioDictGetObj(pdfioObjGetDict(pdf->root_obj), "Pages")) == NULL)
|
||||
{
|
||||
PDFIO_DEBUG("load_xref: Missing Pages object.\n");
|
||||
goto repair;
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("load_xref: Pages=%p(%lu)\n", pdf->root_obj, (unsigned long)pdf->root_obj->number);
|
||||
|
||||
return (load_pages(pdf, pages_obj, 0));
|
||||
|
||||
// If we get here the cross-reference table is busted - try repairing if the
|
||||
// error callback says to proceed...
|
||||
|
||||
repair:
|
||||
|
||||
if (_pdfioFileError(pdf, "WARNING: Cross-reference is damaged, will attempt to rebuild."))
|
||||
return (repair_xref(pdf, password_cb, password_data));
|
||||
else
|
||||
return (false);
|
||||
return (load_pages(pdf, pdfioDictGetObj(pdfioObjGetDict(pdf->root_obj), "Pages"), 0));
|
||||
}
|
||||
|
||||
|
||||
@ -2348,7 +2288,7 @@ repair_xref(
|
||||
pdfio_password_cb_t password_cb, // I - Password callback or `NULL` for none
|
||||
void *password_data) // I - Password callback data, if any
|
||||
{
|
||||
char line[1024], // Line from file
|
||||
char line[16384], // Line from file
|
||||
*ptr; // Pointer into line
|
||||
off_t line_offset; // Offset in file
|
||||
intmax_t number; // Object number
|
||||
@ -2356,22 +2296,16 @@ repair_xref(
|
||||
size_t i; // Looping var
|
||||
size_t num_sobjs = 0; // Number of object streams
|
||||
pdfio_obj_t *sobjs[16384]; // Object streams to load
|
||||
pdfio_dict_t *backup_trailer = NULL; // Backup trailer dictionary
|
||||
pdfio_obj_t *pages_obj; // Pages object
|
||||
|
||||
|
||||
// Clear trailer data...
|
||||
pdf->trailer_dict = NULL;
|
||||
pdf->root_obj = NULL;
|
||||
pdf->info_obj = NULL;
|
||||
pdf->pages_obj = NULL;
|
||||
pdf->encrypt_obj = NULL;
|
||||
// Let caller know something is wrong...
|
||||
_pdfioFileError(pdf, "WARNING: Cross-reference table is damaged, attempting to rebuild.");
|
||||
|
||||
// Read from the beginning of the file, looking for objects...
|
||||
// Read from the beginning of the file, looking for
|
||||
if ((line_offset = _pdfioFileSeek(pdf, 0, SEEK_SET)) < 0)
|
||||
return (false);
|
||||
|
||||
while (_pdfioFileGets(pdf, line, sizeof(line), true))
|
||||
while (_pdfioFileGets(pdf, line, sizeof(line)))
|
||||
{
|
||||
// See if this is the start of an object...
|
||||
if (line[0] >= '1' && line[0] <= '9')
|
||||
@ -2388,75 +2322,43 @@ repair_xref(
|
||||
pdfio_obj_t *obj; // Object
|
||||
_pdfio_token_t tb; // Token buffer/stack
|
||||
|
||||
PDFIO_DEBUG("repair_xref: OBJECT %ld %d at offset %ld\n", (long)number, generation, (long)line_offset);
|
||||
PDFIO_DEBUG("OBJECT %ld %d at offset %ld\n", (long)number, generation, (long)line_offset);
|
||||
|
||||
if ((obj = pdfioFileFindObj(pdf, (size_t)number)) != NULL)
|
||||
{
|
||||
obj->offset = line_offset;
|
||||
}
|
||||
else if ((obj = add_obj(pdf, (size_t)number, (unsigned short)generation, line_offset)) == NULL)
|
||||
if ((obj = add_obj(pdf, (size_t)number, (unsigned short)generation, line_offset)) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Unable to allocate memory for object.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (ptr[3])
|
||||
{
|
||||
// Probably the start of the object dictionary, rewind the file so
|
||||
// we can read it...
|
||||
_pdfioFileSeek(pdf, line_offset + (ptr - line + 3), SEEK_SET);
|
||||
}
|
||||
|
||||
_pdfioTokenInit(&tb, pdf, (_pdfio_tconsume_cb_t)_pdfioFileConsume, (_pdfio_tpeek_cb_t)_pdfioFilePeek, pdf);
|
||||
|
||||
if (!_pdfioValueRead(pdf, obj, &tb, &obj->value, 0))
|
||||
{
|
||||
if (!_pdfioFileError(pdf, "WARNING: Unable to read object dictionary/value."))
|
||||
return (false);
|
||||
else
|
||||
continue;
|
||||
_pdfioFileError(pdf, "Unable to read cross-reference stream dictionary.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (_pdfioTokenGet(&tb, line, sizeof(line)))
|
||||
if (_pdfioTokenGet(&tb, line, sizeof(line)) && strcmp(line, "stream"))
|
||||
{
|
||||
const char *type = pdfioObjGetType(obj);
|
||||
// Object type
|
||||
|
||||
_pdfioTokenFlush(&tb);
|
||||
obj->stream_offset = _pdfioFileTell(pdf);
|
||||
|
||||
if (type && !strcmp(line, "stream"))
|
||||
{
|
||||
// Possible object or XRef stream...
|
||||
obj->stream_offset = _pdfioFileTell(pdf);
|
||||
|
||||
if (!strcmp(type, "ObjStm") && num_sobjs < (sizeof(sobjs) / sizeof(sobjs[0])))
|
||||
{
|
||||
PDFIO_DEBUG("repair_xref: Object stream...\n");
|
||||
sobjs[num_sobjs] = obj;
|
||||
num_sobjs ++;
|
||||
}
|
||||
|
||||
if (!strcmp(type, "XRef") && !pdf->trailer_dict)
|
||||
{
|
||||
// Save the trailer dictionary...
|
||||
PDFIO_DEBUG("repair_xref: XRef stream...\n");
|
||||
pdf->trailer_dict = pdfioObjGetDict(obj);
|
||||
pdf->encrypt_obj = pdfioDictGetObj(pdf->trailer_dict, "Encrypt");
|
||||
pdf->id_array = pdfioDictGetArray(pdf->trailer_dict, "ID");
|
||||
}
|
||||
}
|
||||
else if (type && !strcmp(line, "endobj"))
|
||||
if (type && !strcmp(type, "ObjStm") && num_sobjs < (sizeof(sobjs) / sizeof(sobjs[0])))
|
||||
{
|
||||
// Possible catalog or pages object...
|
||||
if (!strcmp(type, "Catalog"))
|
||||
{
|
||||
PDFIO_DEBUG("repair_xref: Catalog (root) object...\n");
|
||||
if (!backup_trailer)
|
||||
backup_trailer = pdfioDictCreate(pdf);
|
||||
|
||||
pdfioDictSetObj(backup_trailer, "Root", obj);
|
||||
}
|
||||
sobjs[num_sobjs] = obj;
|
||||
num_sobjs ++;
|
||||
}
|
||||
|
||||
if (type && !strcmp(type, "XRef") && !pdf->trailer_dict)
|
||||
{
|
||||
// Save the trailer dictionary...
|
||||
pdf->trailer_dict = pdfioObjGetDict(obj);
|
||||
pdf->encrypt_obj = pdfioDictGetObj(pdf->trailer_dict, "Encrypt");
|
||||
pdf->id_array = pdfioDictGetArray(pdf->trailer_dict, "ID");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2467,8 +2369,6 @@ repair_xref(
|
||||
_pdfio_token_t tb; // Token buffer/stack
|
||||
_pdfio_value_t trailer; // Trailer
|
||||
|
||||
PDFIO_DEBUG("repair_xref: line=\"%s\"\n", line);
|
||||
|
||||
if (line[7])
|
||||
{
|
||||
// Probably the start of the trailer dictionary, rewind the file so
|
||||
@ -2476,7 +2376,7 @@ repair_xref(
|
||||
_pdfioFileSeek(pdf, line_offset + 7, SEEK_SET);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("repair_xref: TRAILER at offset %ld\n", (long)line_offset);
|
||||
PDFIO_DEBUG("TRAILER at offset %ld\n", (long)line_offset);
|
||||
|
||||
_pdfioTokenInit(&tb, pdf, (_pdfio_tconsume_cb_t)_pdfioFileConsume, (_pdfio_tpeek_cb_t)_pdfioFilePeek, pdf);
|
||||
if (!_pdfioValueRead(pdf, NULL, &tb, &trailer, 0))
|
||||
@ -2492,12 +2392,10 @@ repair_xref(
|
||||
|
||||
_pdfioTokenFlush(&tb);
|
||||
|
||||
if (_pdfioDictGetValue(trailer.value.dict, "Root"))
|
||||
if (!pdf->trailer_dict)
|
||||
{
|
||||
// Save the trailer dictionary and grab the root (catalog) and info
|
||||
// objects...
|
||||
PDFIO_DEBUG("repair_xref: Using this trailer dictionary.\n");
|
||||
|
||||
pdf->trailer_dict = trailer.value.dict;
|
||||
pdf->encrypt_obj = pdfioDictGetObj(pdf->trailer_dict, "Encrypt");
|
||||
pdf->id_array = pdfioDictGetArray(pdf->trailer_dict, "ID");
|
||||
@ -2508,18 +2406,11 @@ repair_xref(
|
||||
line_offset = _pdfioFileTell(pdf);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("repair_xref: Stopped at line_offset=%lu\n", (unsigned long)line_offset);
|
||||
|
||||
if (!pdf->trailer_dict && backup_trailer)
|
||||
pdf->trailer_dict = backup_trailer;
|
||||
|
||||
// If the trailer contains an Encrypt key, try unlocking the file...
|
||||
if (pdf->encrypt_obj && !_pdfioCryptoUnlock(pdf, password_cb, password_data))
|
||||
return (false);
|
||||
|
||||
// Load any stream objects...
|
||||
PDFIO_DEBUG("repair_xref: Found %lu stream objects.\n", (unsigned long)num_sobjs);
|
||||
|
||||
for (i = 0; i < num_sobjs; i ++)
|
||||
{
|
||||
if (!load_obj_stream(sobjs[i]))
|
||||
@ -2538,16 +2429,8 @@ repair_xref(
|
||||
|
||||
PDFIO_DEBUG("repair_xref: Root=%p(%lu)\n", pdf->root_obj, (unsigned long)pdf->root_obj->number);
|
||||
|
||||
if ((pages_obj = pdfioDictGetObj(pdfioObjGetDict(pdf->root_obj), "Pages")) == NULL)
|
||||
{
|
||||
_pdfioFileError(pdf, "Missing Pages object.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
PDFIO_DEBUG("repair_xref: Pages=%p(%lu)\n", pages_obj, (unsigned long)pages_obj->number);
|
||||
|
||||
// Load pages...
|
||||
return (load_pages(pdf, pages_obj, 0));
|
||||
return (load_pages(pdf, pdfioDictGetObj(pdfioObjGetDict(pdf->root_obj), "Pages"), 0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,7 +141,6 @@ pdfioObjCreateStream(
|
||||
pdfio_obj_t *obj, // I - Object
|
||||
pdfio_filter_t filter) // I - Type of compression to apply
|
||||
{
|
||||
pdfio_stream_t *st; // Stream
|
||||
pdfio_obj_t *length_obj = NULL; // Length object, if any
|
||||
|
||||
|
||||
@ -195,13 +194,11 @@ pdfioObjCreateStream(
|
||||
if (!_pdfioFilePuts(obj->pdf, "stream\n"))
|
||||
return (NULL);
|
||||
|
||||
obj->stream_offset = _pdfioFileTell(obj->pdf);
|
||||
obj->stream_offset = _pdfioFileTell(obj->pdf);
|
||||
obj->pdf->current_obj = obj;
|
||||
|
||||
// Return the new stream...
|
||||
if ((st = _pdfioStreamCreate(obj, length_obj, 0, filter)) != NULL)
|
||||
obj->pdf->current_obj = obj;
|
||||
|
||||
return (st);
|
||||
return (_pdfioStreamCreate(obj, length_obj, 0, filter));
|
||||
}
|
||||
|
||||
|
||||
@ -537,9 +534,6 @@ pdfio_stream_t * // O - Stream or `NULL` on error
|
||||
pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object
|
||||
bool decode) // I - Decode/decompress data?
|
||||
{
|
||||
pdfio_stream_t *st; // Stream
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (!obj)
|
||||
return (NULL);
|
||||
@ -562,10 +556,9 @@ pdfioObjOpenStream(pdfio_obj_t *obj, // I - Object
|
||||
return (NULL);
|
||||
|
||||
// Open the stream...
|
||||
if ((st = _pdfioStreamOpen(obj, decode)) != NULL)
|
||||
obj->pdf->current_obj = obj;
|
||||
obj->pdf->current_obj = obj;
|
||||
|
||||
return (st);
|
||||
return (_pdfioStreamOpen(obj, decode));
|
||||
}
|
||||
|
||||
|
||||
|
@ -385,7 +385,7 @@ extern bool _pdfioFileError(pdfio_file_t *pdf, const char *format, ...) _PDFIO_
|
||||
extern pdfio_obj_t *_pdfioFileFindMappedObj(pdfio_file_t *pdf, pdfio_file_t *src_pdf, size_t src_number) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFileFlush(pdfio_file_t *pdf) _PDFIO_INTERNAL;
|
||||
extern int _pdfioFileGetChar(pdfio_file_t *pdf) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFileGets(pdfio_file_t *pdf, char *buffer, size_t bufsize, bool discard) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFileGets(pdfio_file_t *pdf, char *buffer, size_t bufsize) _PDFIO_INTERNAL;
|
||||
extern ssize_t _pdfioFilePeek(pdfio_file_t *pdf, void *buffer, size_t bytes) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFilePrintf(pdfio_file_t *pdf, const char *format, ...) _PDFIO_INTERNAL;
|
||||
extern bool _pdfioFilePuts(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
|
||||
|
@ -259,7 +259,7 @@ _pdfioStreamCreate(
|
||||
{
|
||||
colors = 1;
|
||||
}
|
||||
else if (colors < 0 || colors > 32)
|
||||
else if (colors < 0 || colors > 4)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unsupported Colors value %d.", colors);
|
||||
free(st);
|
||||
@ -532,7 +532,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
||||
{
|
||||
colors = 1;
|
||||
}
|
||||
else if (colors < 0 || colors > 32)
|
||||
else if (colors < 0 || colors > 4)
|
||||
{
|
||||
_pdfioFileError(st->pdf, "Unsupported Colors value %d.", colors);
|
||||
goto error;
|
||||
|
@ -18,22 +18,12 @@ if test $# = 0; then
|
||||
fi
|
||||
|
||||
for file in $(find "$@" -name \*.pdf -print); do
|
||||
# Don't worry about test files containing MIME garbage...
|
||||
(head -4 $file | grep -q Content-Type) && continue;
|
||||
|
||||
# Or test files containing MacBinary garbage...
|
||||
(file $file | grep -q MacBinary) && continue;
|
||||
|
||||
# Don't worry about test files that Xpdf can't handle...
|
||||
pdfinfo $file >/dev/null 2>&1 || continue;
|
||||
|
||||
# Run testpdfio to test loading the file...
|
||||
./testpdfio $file >$file.log 2>&1
|
||||
if test $? = 0; then
|
||||
# Passed
|
||||
rm -f $file.log
|
||||
else
|
||||
# Failed, preserve log and write filename to stdout...
|
||||
echo $file
|
||||
fi
|
||||
done
|
||||
|
@ -1333,7 +1333,7 @@ error_cb(pdfio_file_t *pdf, // I - PDF file
|
||||
testMessage("%s", message);
|
||||
|
||||
// Continue to catch more errors...
|
||||
return (true);
|
||||
return (false);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user