2017-02-20 119 views
4

使用2016-W4 pdf,它有兩個大流,以及一堆其他對象和較小的流。我試圖泄漏流,以處理源數據,但我掙扎。我只能得到損壞的輸入和無效的校驗和錯誤。如何解壓/放縮PDF流

我已經編寫了一個測試腳本來幫助調試,並且已經從文件中拉出更小的流來測試。

下面是從原始的PDF 2流,其長度對象一起:

流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的內容我nto Vim內的新文件(不包括在stream之後和endstream之前的回車)

我都試過:

  • compress/flaterfc-1951) - (除去前2個字節(CMFFLG))
  • compress/zlibrfc-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 
} 

我確定我在某個地方做錯了什麼,我只是不太明白。

(PDF格式確實在查看器打開)

+1

你確定vim顯示你並複製了正確的字節嗎?您應該從十六進制編輯器獲取數據(例如,檢查[hecate](https://github.com/evanmiller/hecate))。 – icza

+0

@icza - 如果你想發佈作爲答案,我會給你信用=) – Justin

回答

1

二進制數據應該從不從文本編輯器中複製出/保存。可能會有這種情況發生,並且只是在火焰中添加油。

您最終從PDF中「挖出」的數據很可能與PDF中的實際數據不一致。您應該從十六進制編輯器中獲取數據(例如,嘗試使用hecate獲取新內容),或者編寫一個保存該文件的簡單應用程序(嚴格將該文件作爲二進制文件處理)。

提示#1:

顯示的二進制數據分佈在多條線上。二進制數據不包含回車符,這是一個文本控制。如果是這樣,那就意味着編輯確實將解釋爲文本,所以一些代碼/字符在其中「消耗」以開始新行。多個序列可被解釋爲相同的換行符(例如\n\r\n)。通過排除它們,您已經處於數據丟失狀態,通過包含它們,您可能已經有了不同的順序。如果數據被解釋並顯示爲文本,則可能會出現更多的問題,因爲控制字符更多,並且某些字符在顯示時可能不會顯示。

提示#2:

flateReaderFn時,解碼所述第二示例成功(完成沒有錯誤)。這意味着「你在咆哮着正確的樹」,但成功取決於實際數據是什麼以及它在文本編輯器中「扭曲」的程度。

1

好,表白時間...

我在試圖瞭解放氣,我完全忽略了Vim的WASN」事實如此趕上將流內容正確保存到新文件中。所以我花了很多時間閱讀RFC,並深入瞭解Go compress/...包的內部,假設問題出在我的代碼上。

在我發佈我的問題後不久,我嘗試閱讀PDF作爲一個整體,找到stream/endstream位置,並通過放氣推動。只要我看到內容在屏幕上滾動,我就意識到自己愚蠢的錯誤。

+1 @icza,這正是我的問題。

這樣做很好,因爲我對整個過程有了更好的理解,比起剛開始工作的時候更好。