Ошибка в корневом объекте PDF
Этот корневой объект PDF приведет к сбою Adobe Reader. Другие программы для чтения PDF, такие как Foxit, Nuance, Evince, SumatraPDF, без проблем откроют файл PDF. Проблема заключается в /Dests, который регулирует косвенный объект (PDF-ссылка). Удаление /Dests << >> заставит Adobe Reader открыть файл, но при печати произойдет сбой. Все остальные читатели работают нормально без /Dests. Любые идеи, как исправить синтаксис в следующем примере корневого объекта?
17 0 obj
<<
/Type /Catalog
/Pages 2 0 R
/Outlines 15 0 R
/PageMode /UseOutlines
/Dests <<
/__WKANCHOR_2 8 0 R
/#8d#c2#ca#ebs#e4#60#00#9e#97l#b9#80#1b#cb#86sQR#83 9 0 R
>>
>>
endobj
3 ответа
Хорошо, нашел несколько свободных минут...
Итак, первое, что я заметил, это то, что * все остальные читатели действительно могут открыть файл (я тестировал только несколько). Но они выкладывают много предупреждений и сообщений об ошибках... (Попробуйте Ghostscript: gs virkerikke.pdf
или попробуй доказать...) есть хоть поврежденный xref
таблицы в формате PDF (или, по крайней мере, это одна из жалоб).
xpdf
жалуется:
[....]
Error: Invalid XRef entry
Error: Invalid XRef entry
Error: Invalid XRef entry
Error (157): Unterminated string
Error (159): End of file inside dictionary
gv
жалуется:
Warning: translation table syntax error: Unknown keysym name: apLineDel
Warning: ... found while parsing '<Key>apLineDel: GV_Page(page+5) '
Warning: String to TranslationTable conversion encountered errors
evince
жалуется:
[....]
Error: Invalid XRef entry
Error: Invalid XRef entry
Error: Invalid XRef entry
Error (157): Unterminated string
Error (159): End of file inside dictionary
Error (157): Unterminated string
Error (159): End of file inside dictionary
Error (157): Unterminated string
Error (159): End of file inside dictionary
[....]
Error (1918): Unterminated string
Error (1920): End of file inside dictionary
gs
жалуется:
**** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF.
mupdf
жалуется:
+ pdf/pdf_xref.c:60: pdf_read_start_xref(): cannot find startxref
| pdf/pdf_xref.c:477: pdf_load_xref(): cannot read startxref
\ pdf/pdf_xref.c:532: pdf_open_xref_with_stream(): trying to repair
warning: ignoring invalid character in hex string: '!'
warning: ignoring invalid character in hex string: 'O'
warning: ignoring invalid character in hex string: 'T'
warning: ignoring invalid character in hex string: 'Y'
[....]
qpdf --qdf
жалуется:
virkerikke.pdf (object 17 0, file position 2234): null character not allowed in name token
Хорошо, теперь открываем этот дерьмовый файл в текстовом редакторе, пытаясь восстановить его. Я обнаружил, что этот файл (размером 32746 байт) имеет некоторые серьезные синтаксические проблемы:
- Мусор после
%%EOF
: Есть полный и правильный синтаксис HTML-файл, приклеенный к PDF после его%%EOF
маркер с заголовком "Wkhtmltopdf - Teknisk regelverk". Его размер составляет 11878 байт. Удалите эту часть, и у вас будет "лучший" PDF-файл размером всего 20868 байт… хотя Acrobat/Adobe Reader по-прежнему не открывает его после сохранения отредактированного файла. - Недопустимый символ в имени токена: это находится внутри имени токена
/#8d#c2#ca#ebs#e4#60#00#9e#97l#b9#80#1b#cb#86sQR#83
, Похоже, 2 раза в этом файле. Уже в моих первых комментариях я говорил вам, что этот ключ не выглядит мне заслуживающим доверия, потому что он содержит очень мало символов ASCII, но содержит много двоичных байтов (используя их шестнадцатеричное представление. (Я упустил из виду, что он даже содержал#00
который является представлением PDF дляnul
символ... использование которого является недопустимым для токенов имен в PDF.) Замените этот токен имени на другой (фантазийный) один точно такой же длины (в обоих случаях). Я выбрал/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
, Сохраните отредактированный файл.
Теперь даже Acrobat/Adobe Reader s откроет этот восстановленный файл без жалоб. Кроме того, "другие читатели" теперь будут лучше работать с этим файлом, выдавая меньше предупреждений и теперь имея возможность идентифицировать некоторые метаданные (такие как дата создания и производитель == wkhtmltopdf), которые они не смогли получить для исходного файла.
/Dests
должен быть словарь (пары /Key value
) содержащие имена (ключи) и соответствующие пункты назначения (значения). /Dests
Ключевое слово впервые появилось в PDF 1.1.
В PDF 1.1 допускается, чтобы ключи были только именованным объектом. В PDF 1.2 ключи также могут быть байтовыми строками.
Итак, на какую версию PDF претендует ваш файл?
Из спецификации для PDF 1.7 ("ISO 32000-1"), описывающего значение /Dests
:
В PDF 1.1 соответствие между именованными объектами и адресатами должно определяться записью Dests в каталоге документов (см. 7.7.2, "Каталог документов"). Значением этой записи должен быть словарь, в котором каждый ключ является именем пункта назначения, а соответствующее значение представляет собой либо массив, определяющий пункт назначения с использованием синтаксиса, показанного в таблице 151, либо словарь с записью D, значение которой является таким массивом.,
Кажется, довольно просто. Переместите массив dests в его собственный объект.
Скорее, чем
17 0 obj
<<
/Type /Catalog
/Pages 2 0 R
/Outlines 15 0 R
/PageMode /UseOutlines
/Dests <<
/__WKANCHOR_2 8 0 R
/#8d#c2#ca#ebs#e4#60#00#9e#97l#b9#80#1b#cb#86sQR#83 9 0 R
>>
>>
endobj
вместо этого вы должны иметь:
17 0 obj
<<
/Type /Catalog
/Pages 2 0 R
/Outlines 15 0 R
/PageMode /UseOutlines
/Dests 1234 0 R
>>
endobj
1234 0 obj
<</__WKANCHOR_2 8 0 R/#8d#c2#ca#ebs#e4#60#00#9e#97l#b9#80#1b#cb#86sQR#83 9 0 R>>
endobj
Номер объекта будет чем-то псевдослучайным.
И как переместить массив dest из корня в его собственный объект будет полностью зависеть от того, какое программное обеспечение PDF вы используете. "Hex Editor" - вариант, но тогда вы закончите на SuperUser, а не на Stackru... технически. Я подозреваю, что вы можете получить Маллиган на этом. Я позволил бы этому скользить сам.