2017-02-20 12 views
4

Работа с 2016-W4 pdf, который имеет 2 больших потока (страница 1 & 2), а также множество других объектов и небольших потоков. Я пытаюсь сдуть поток (ы), работать с исходными данными, но боюсь. Я могу получить только коррумпированные данные и неверные ошибки контрольных сумм.Как распаковать/сдуть PDF-поток

Я написал тестовый скрипт, чтобы помочь отлаживать и вытащил из потока файлы меньшего размера из файла для тестирования.

Здесь 2 потоков из исходного PDF, наряду с их объектами Длина:

поток 1:

149 0 obj 
<< /Length 150 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /FormType 
1 /BBox [0 0 8 8] /Resources 151 0 R >> 
stream 
x+TT(T0B ,JUWÈS0Ð37±402V(NFJSþ¶ 
« 
endstream 
endobj 
150 0 obj 
42 
endobj 

поток 2

142 0 obj 
<< /Length 143 0 R /Filter /FlateDecode /Type /XObject /Subtype /Form /FormType 
1 /BBox [0 0 0 0] /Resources 144 0 R >> 
stream 
x+Tçã 
endstream 
endobj 
143 0 obj 
11 
endobj 

Я скопировал только содержимое stream i nto новых файлов в пределах Vim (за исключением возвратов каретки после stream и до endstream).

Я попытался как:

  • compress/flate(rfc-1951) - (удаление первые 2 байта (CMF, FLG))
  • compress/zlib(rfc-1950)

Я преобразовал потоки в []byte для ниже:

package main 

import (
    "bytes" 
    "compress/flate" 
    "compress/gzip" 
    "compress/zlib" 
    "fmt" 
    "io" 
    "os" 
) 

var (
    flateReaderFn = func(r io.Reader) (io.ReadCloser, error) { return flate.NewReader(r), nil } 
    zlibReaderFn = func(r io.Reader) (io.ReadCloser, error) { return zlib.NewReader(r) } 
) 

func deflate(b []byte, skip, length int, newReader func(io.Reader) (io.ReadCloser, error)) { 
    // rfc-1950 
    // -------- 
    // First 2 bytes 
    // [120, 1] - CMF, FLG 
    // 
    // CMF: 120 
    //  0111 1000 
    //  ↑ ↑ 
    //  | CM(8) = deflate compression method 
    //  CINFO(7) = 32k LZ77 window size 
    // 
    // FLG: 1 
    //  0001 ← FCHECK 
    //   (CMF*256 + FLG) % 31 == 0 
    //    120 * 256 + 1 = 30721 
    //        30721 % 31 == 0 

    stream := bytes.NewReader(b[skip:length]) 
    r, err := newReader(stream) 
    if err != nil { 
     fmt.Println("\nfailed to create reader,", err) 
     return 
    } 

    n, err := io.Copy(os.Stdout, r) 
    if err != nil { 
     if n > 0 { 
      fmt.Print("\n") 
     } 
     fmt.Println("\nfailed to write contents from reader,", err) 
     return 
    } 
    fmt.Printf("%d bytes written\n", n) 
    r.Close() 
} 

func main() { 
    //readerFn, skip := flateReaderFn, 2 // compress/flate RFC-1951, ignore first 2 bytes 
    readerFn, skip := zlibReaderFn, 0 // compress/zlib RFC-1950, ignore nothing 

    //                        ⤹ This is where the error occurs: `flate: corrupt input before offset 19`. 
    stream1 := []byte{120, 1, 43, 84, 8, 84, 40, 84, 48, 0, 66, 11, 32, 44, 74, 85, 8, 87, 195, 136, 83, 48, 195, 144, 51, 55, 194, 177, 52, 48, 50, 86, 40, 78, 70, 194, 150, 74, 83, 8, 4, 0, 195, 190, 194, 182, 10, 194, 171, 10} 
    stream2 := []byte{120, 1, 43, 84, 8, 4, 0, 1, 195, 167, 0, 195, 163, 10} 

    fmt.Println("----------------------------------------\nStream 1:") 
    deflate(stream1, skip, 42, readerFn) // flate: corrupt input before offset 19 

    fmt.Println("----------------------------------------\nStream 2:") 
    deflate(stream2, skip, 11, readerFn) // invalid checksum 
} 

Я уверен, что я что-то делаю что-то не так, я просто не могу это увидеть.

(ФПВ делает открытым в зрителя)

+1

Вы уверены, что vim отобразили и скопировали правильные байты? Вы должны взять данные из шестнадцатеричного редактора (например, проверить [hecate] (https://github.com/evanmiller/hecate)). – icza

+0

@icza - Если вы хотите опубликовать это как ответ, я дам вам кредит =) – Justin

ответ

1

Двоичные данные должны никогда не быть скопированы из/сохранены из текстовых редакторов. Бывают случаи, когда это удастся, и это просто добавляет масло к пламени.

Ваши данные, которые вы в конечном итоге «вычеркнули» из PDF, скорее всего, не идентичны фактическим данным, которые является в PDF. Вы должны взять данные из шестнадцатеричного редактора (например, попробуйте hecate для чего-то нового) или написать простое приложение, которое сохраняет его (что строго обрабатывает файл как двоичный).

Подсказка # 1:

двоичные данные отображаются распределены по нескольким линиям. Двоичные данные не содержат возврат каретки, это текстовый элемент управления. Если это так, значит, редактор сделал интерпретировать его как текст, а значит, некоторые коды/символы, где «потреблялось», чтобы начать новую строку. Несколько последовательностей могут быть интерпретированы как одна и та же новая строка (например, \n, \r\n). Исключая их, вы уже потеряли данные, включив их, возможно, у вас уже есть другая последовательность. И если данные были интерпретированы и отображены как текст, может возникнуть больше проблем, так как есть больше управляющих символов, и некоторые символы могут не отображаться при отображении.

Подсказка # 2:

Когда flateReaderFn используется, декодирование 2-й пример преуспевает (завершает без ошибок). Это означает, что «вы лаяли по правильному дереву», но успех зависит от того, каковы фактические данные и в какой степени он «искажен» текстовым редактором.

1

Хорошо, время исповеди ...

я так догнали в попытке понять выкачать, что я совершенно упускается из виду тот факт, что Vim WASN» t правильно сохраняет содержимое потока в новых файлах. Поэтому я потратил немало времени на чтение RFC и на то, чтобы разобраться с внутренними пакетами Go compress/..., предполагая, что проблема связана с моим кодом.

Вскоре после того, как я разместил свой вопрос, я пробовал читать PDF в целом, находя местоположения и нажав на него с помощью дефлята. Как только я увидел, что контент прокручивается по экрану, я понял свою тупую ошибку.

+1 @icza, это была именно моя проблема.

В конце концов это было хорошо, так как у меня есть гораздо лучшее понимание всего процесса, чем если бы он только что сработал, первый раз.

Смежные вопросы