From 3f3b45cc74b0499912409f766a595945dbbfc4c5 Mon Sep 17 00:00:00 2001 From: John Abd-El-Malek Date: Fri, 23 May 2014 17:28:10 -0700 Subject: Convert all line endings to LF. --- core/src/fpdfapi/fpdf_parser/filters_int.h | 238 +- .../src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp | 1066 ++++---- .../fpdfapi/fpdf_parser/fpdf_parser_document.cpp | 796 +++--- .../fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp | 1914 +++++++------- core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp | 448 ++-- .../fpdfapi/fpdf_parser/fpdf_parser_filters.cpp | 1818 ++++++------- .../fpdfapi/fpdf_parser/fpdf_parser_objects.cpp | 2688 ++++++++++---------- .../fpdfapi/fpdf_parser/fpdf_parser_utility.cpp | 906 +++---- 8 files changed, 4937 insertions(+), 4937 deletions(-) (limited to 'core/src/fpdfapi/fpdf_parser') diff --git a/core/src/fpdfapi/fpdf_parser/filters_int.h b/core/src/fpdfapi/fpdf_parser/filters_int.h index fa7d7db76e..d1dedc482c 100644 --- a/core/src/fpdfapi/fpdf_parser/filters_int.h +++ b/core/src/fpdfapi/fpdf_parser/filters_int.h @@ -1,119 +1,119 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -class CPDF_DecryptFilter : public CFX_DataFilter -{ -public: - CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum); - virtual ~CPDF_DecryptFilter(); - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf); - CPDF_CryptoHandler* m_pCryptoHandler; - FX_LPVOID m_pContext; - FX_DWORD m_ObjNum, m_GenNum; -}; -class CPDF_FlateFilter : public CFX_DataFilter -{ -public: - CPDF_FlateFilter(); - virtual ~CPDF_FlateFilter(); - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - void* m_pContext; - FX_BYTE m_DestBuffer[FPDF_FILTER_BUFFER_SIZE]; -}; -class CPDF_LzwFilter : public CFX_DataFilter -{ -public: - CPDF_LzwFilter(FX_BOOL bEarlyChange); - virtual ~CPDF_LzwFilter() {} - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - FX_BOOL m_bEarlyChange; - FX_DWORD m_CodeArray[5021]; - FX_DWORD m_nCodes; - FX_DWORD m_CodeLen; - FX_DWORD m_OldCode; - FX_BYTE m_LastChar; - FX_DWORD m_nLeftBits, m_LeftBits; - FX_BYTE m_DecodeStack[4000]; - FX_DWORD m_StackLen; - void AddCode(FX_DWORD prefix_code, FX_BYTE append_char); - void DecodeString(FX_DWORD code); -}; -class CPDF_PredictorFilter : public CFX_DataFilter -{ -public: - CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols); - virtual ~CPDF_PredictorFilter(); - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - FX_BOOL m_bTiff; - FX_DWORD m_Pitch, m_Bpp; - FX_LPBYTE m_pRefLine, m_pCurLine; - FX_DWORD m_iLine, m_LineInSize; -}; -class CPDF_AsciiHexFilter : public CFX_DataFilter -{ -public: - CPDF_AsciiHexFilter(); - virtual ~CPDF_AsciiHexFilter() {} - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - int m_State; - int m_FirstDigit; -}; -class CPDF_Ascii85Filter : public CFX_DataFilter -{ -public: - CPDF_Ascii85Filter(); - virtual ~CPDF_Ascii85Filter() {} - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - int m_State; - int m_CharCount; - FX_DWORD m_CurDWord; -}; -class CPDF_RunLenFilter : public CFX_DataFilter -{ -public: - CPDF_RunLenFilter(); - virtual ~CPDF_RunLenFilter() {} - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - int m_State; - FX_DWORD m_Count; -}; -class CPDF_JpegFilter : public CFX_DataFilter -{ -public: - CPDF_JpegFilter(); - virtual ~CPDF_JpegFilter(); - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} - void* m_pContext; - CFX_BinaryBuf m_InputBuf; - FX_LPBYTE m_pScanline; - int m_Pitch, m_Height, m_Width, m_nComps, m_iLine; - FX_BOOL m_bGotHeader; -}; -class CPDF_FaxFilter : public CFX_DataFilter -{ -public: - CPDF_FaxFilter(); - virtual ~CPDF_FaxFilter(); - FX_BOOL Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns); - virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); - virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf); - int m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack; - int m_nRows, m_nColumns, m_Pitch, m_iRow; - FX_LPBYTE m_pScanlineBuf, m_pRefBuf; - CFX_BinaryBuf m_InputBuf; - int m_InputBitPos; - void ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish, - CFX_BinaryBuf& dest_buf); - FX_BOOL ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos); -}; +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +class CPDF_DecryptFilter : public CFX_DataFilter +{ +public: + CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum); + virtual ~CPDF_DecryptFilter(); + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf); + CPDF_CryptoHandler* m_pCryptoHandler; + FX_LPVOID m_pContext; + FX_DWORD m_ObjNum, m_GenNum; +}; +class CPDF_FlateFilter : public CFX_DataFilter +{ +public: + CPDF_FlateFilter(); + virtual ~CPDF_FlateFilter(); + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + void* m_pContext; + FX_BYTE m_DestBuffer[FPDF_FILTER_BUFFER_SIZE]; +}; +class CPDF_LzwFilter : public CFX_DataFilter +{ +public: + CPDF_LzwFilter(FX_BOOL bEarlyChange); + virtual ~CPDF_LzwFilter() {} + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + FX_BOOL m_bEarlyChange; + FX_DWORD m_CodeArray[5021]; + FX_DWORD m_nCodes; + FX_DWORD m_CodeLen; + FX_DWORD m_OldCode; + FX_BYTE m_LastChar; + FX_DWORD m_nLeftBits, m_LeftBits; + FX_BYTE m_DecodeStack[4000]; + FX_DWORD m_StackLen; + void AddCode(FX_DWORD prefix_code, FX_BYTE append_char); + void DecodeString(FX_DWORD code); +}; +class CPDF_PredictorFilter : public CFX_DataFilter +{ +public: + CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols); + virtual ~CPDF_PredictorFilter(); + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + FX_BOOL m_bTiff; + FX_DWORD m_Pitch, m_Bpp; + FX_LPBYTE m_pRefLine, m_pCurLine; + FX_DWORD m_iLine, m_LineInSize; +}; +class CPDF_AsciiHexFilter : public CFX_DataFilter +{ +public: + CPDF_AsciiHexFilter(); + virtual ~CPDF_AsciiHexFilter() {} + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + int m_State; + int m_FirstDigit; +}; +class CPDF_Ascii85Filter : public CFX_DataFilter +{ +public: + CPDF_Ascii85Filter(); + virtual ~CPDF_Ascii85Filter() {} + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + int m_State; + int m_CharCount; + FX_DWORD m_CurDWord; +}; +class CPDF_RunLenFilter : public CFX_DataFilter +{ +public: + CPDF_RunLenFilter(); + virtual ~CPDF_RunLenFilter() {} + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + int m_State; + FX_DWORD m_Count; +}; +class CPDF_JpegFilter : public CFX_DataFilter +{ +public: + CPDF_JpegFilter(); + virtual ~CPDF_JpegFilter(); + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf) {} + void* m_pContext; + CFX_BinaryBuf m_InputBuf; + FX_LPBYTE m_pScanline; + int m_Pitch, m_Height, m_Width, m_nComps, m_iLine; + FX_BOOL m_bGotHeader; +}; +class CPDF_FaxFilter : public CFX_DataFilter +{ +public: + CPDF_FaxFilter(); + virtual ~CPDF_FaxFilter(); + FX_BOOL Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns); + virtual void v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf); + virtual void v_FilterFinish(CFX_BinaryBuf& dest_buf); + int m_Encoding, m_bEndOfLine, m_bByteAlign, m_bBlack; + int m_nRows, m_nColumns, m_Pitch, m_iRow; + FX_LPBYTE m_pScanlineBuf, m_pRefBuf; + CFX_BinaryBuf m_InputBuf; + int m_InputBitPos; + void ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish, + CFX_BinaryBuf& dest_buf); + FX_BOOL ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos); +}; diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp index 74e81d40fd..dfc26bc197 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_decode.cpp @@ -1,533 +1,533 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fpdfapi/fpdf_parser.h" -#include "../../../include/fpdfapi/fpdf_module.h" -#include "../../../include/fxcodec/fx_codec.h" -#include -#define _STREAM_MAX_SIZE_ 20 * 1024 * 1024 -FX_DWORD _A85Decode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - dest_size = 0; - dest_buf = NULL; - if (src_size == 0) { - return 0; - } - FX_DWORD orig_size = dest_size; - FX_DWORD zcount = 0; - FX_DWORD pos = 0; - while (pos < src_size) { - FX_BYTE ch = src_buf[pos]; - if (ch < '!' && ch != '\n' && ch != '\r' && ch != ' ' && ch != '\t') { - break; - } - if (ch == 'z') { - zcount ++; - } else if (ch > 'u') { - break; - } - pos ++; - } - if (pos == 0) { - return 0; - } - if (zcount > UINT_MAX / 4) { - return (FX_DWORD) - 1; - } - if (zcount * 4 > UINT_MAX - (pos - zcount)) { - return (FX_DWORD) - 1; - } - dest_buf = FX_Alloc(FX_BYTE, zcount * 4 + (pos - zcount)); - if (dest_buf == NULL) { - return (FX_DWORD) - 1; - } - int state = 0, res = 0; - pos = dest_size = 0; - while (pos < src_size) { - FX_BYTE ch = src_buf[pos++]; - if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') { - continue; - } - if (ch == 'z') { - FXSYS_memset32(dest_buf + dest_size, 0, 4); - state = 0; - res = 0; - dest_size += 4; - } else { - if (ch < '!' || ch > 'u') { - break; - } - res = res * 85 + ch - 33; - state ++; - if (state == 5) { - for (int i = 0; i < 4; i ++) { - dest_buf[dest_size++] = (FX_BYTE)(res >> (3 - i) * 8); - } - state = 0; - res = 0; - } - } - } - if (state) { - int i; - for (i = state; i < 5; i ++) { - res = res * 85 + 84; - } - for (i = 0; i < state - 1; i ++) { - dest_buf[dest_size++] = (FX_BYTE)(res >> (3 - i) * 8); - } - } - if (pos < src_size && src_buf[pos] == '>') { - pos ++; - } - return pos; -} -FX_DWORD _HexDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - FX_DWORD orig_size = dest_size; - FX_DWORD i; - for (i = 0; i < src_size; i ++) - if (src_buf[i] == '>') { - break; - } - dest_buf = FX_Alloc( FX_BYTE, i / 2 + 1); - dest_size = 0; - FX_BOOL bFirstDigit = TRUE; - for (i = 0; i < src_size; i ++) { - FX_BYTE ch = src_buf[i]; - if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r') { - continue; - } - int digit; - if (ch <= '9' && ch >= '0') { - digit = ch - '0'; - } else if (ch <= 'f' && ch >= 'a') { - digit = ch - 'a' + 10; - } else if (ch <= 'F' && ch >= 'A') { - digit = ch - 'A' + 10; - } else if (ch == '>') { - i ++; - break; - } else { - continue; - } - if (bFirstDigit) { - dest_buf[dest_size] = digit * 16; - } else { - dest_buf[dest_size ++] += digit; - } - bFirstDigit = !bFirstDigit; - } - if (!bFirstDigit) { - dest_size ++; - } - return i; -} -FX_DWORD RunLengthDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - FX_DWORD orig_size = dest_size; - FX_DWORD i = 0; - FX_DWORD old; - dest_size = 0; - while (i < src_size) { - if (src_buf[i] < 128) { - old = dest_size; - dest_size += src_buf[i] + 1; - if (dest_size < old) { - return (FX_DWORD) - 1; - } - i += src_buf[i] + 2; - } else if (src_buf[i] > 128) { - old = dest_size; - dest_size += 257 - src_buf[i]; - if (dest_size < old) { - return (FX_DWORD) - 1; - } - i += 2; - } else { - break; - } - } - if (dest_size >= _STREAM_MAX_SIZE_) { - return -1; - } - dest_buf = FX_Alloc( FX_BYTE, dest_size); - if (!dest_buf) { - return -1; - } - i = 0; - int dest_count = 0; - while (i < src_size) { - if (src_buf[i] < 128) { - FX_DWORD copy_len = src_buf[i] + 1; - FX_DWORD buf_left = src_size - i - 1; - if (buf_left < copy_len) { - FX_DWORD delta = copy_len - buf_left; - copy_len = buf_left; - FXSYS_memset8(dest_buf + dest_count + copy_len, '\0', delta); - } - FXSYS_memcpy32(dest_buf + dest_count, src_buf + i + 1, copy_len); - dest_count += src_buf[i] + 1; - i += src_buf[i] + 2; - } else if (src_buf[i] > 128) { - int fill = 0; - if (i < src_size - 1) { - fill = src_buf[i + 1]; - } - FXSYS_memset8(dest_buf + dest_count, fill, 257 - src_buf[i]); - dest_count += 257 - src_buf[i]; - i += 2; - } else { - break; - } - } - FX_DWORD ret = i + 1; - if (ret > src_size) { - ret = src_size; - } - return ret; -} -ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, - const CPDF_Dictionary* pParams) -{ - int K = 0; - FX_BOOL EndOfLine = FALSE; - FX_BOOL ByteAlign = FALSE; - FX_BOOL BlackIs1 = FALSE; - FX_BOOL Columns = 1728; - FX_BOOL Rows = 0; - if (pParams) { - K = pParams->GetInteger(FX_BSTRC("K")); - EndOfLine = pParams->GetInteger(FX_BSTRC("EndOfLine")); - ByteAlign = pParams->GetInteger(FX_BSTRC("EncodedByteAlign")); - BlackIs1 = pParams->GetInteger(FX_BSTRC("BlackIs1")); - Columns = pParams->GetInteger(FX_BSTRC("Columns"), 1728); - Rows = pParams->GetInteger(FX_BSTRC("Rows")); - if (Rows > USHRT_MAX) { - Rows = 0; - } - if (Columns <= 0 || Rows < 0 || Columns > USHRT_MAX || Rows > USHRT_MAX) { - return NULL; - } - } - return CPDF_ModuleMgr::Get()->GetFaxModule()->CreateDecoder(src_buf, src_size, width, height, - K, EndOfLine, ByteAlign, BlackIs1, Columns, Rows); -} -static FX_BOOL CheckFlateDecodeParams(int Colors, int BitsPerComponent, int Columns) -{ - if (Columns < 0) { - return FALSE; - } - int check = Columns; - if (Colors < 0 || (check > 0 && Colors > INT_MAX / check)) { - return FALSE; - } - check *= Colors; - if (BitsPerComponent < 0 || - (check > 0 && BitsPerComponent > INT_MAX / check)) { - return FALSE; - } - check *= BitsPerComponent; - if (check > INT_MAX - 7) { - return FALSE; - } - return TRUE; -} -ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, - int nComps, int bpc, const CPDF_Dictionary* pParams) -{ - int predictor = 0; - FX_BOOL bEarlyChange = TRUE; - int Colors = 0, BitsPerComponent = 0, Columns = 0; - if (pParams) { - predictor = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("Predictor")); - bEarlyChange = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("EarlyChange"), 1); - Colors = pParams->GetInteger(FX_BSTRC("Colors"), 1); - BitsPerComponent = pParams->GetInteger(FX_BSTRC("BitsPerComponent"), 8); - Columns = pParams->GetInteger(FX_BSTRC("Columns"), 1); - if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns)) { - return NULL; - } - } - return CPDF_ModuleMgr::Get()->GetFlateModule()->CreateDecoder(src_buf, src_size, width, height, - nComps, bpc, predictor, Colors, BitsPerComponent, Columns); -} -FX_DWORD FPDFAPI_FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, CPDF_Dictionary* pParams, - FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - int predictor = 0; - FX_BOOL bEarlyChange = TRUE; - int Colors = 0, BitsPerComponent = 0, Columns = 0; - if (pParams) { - predictor = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("Predictor")); - bEarlyChange = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("EarlyChange"), 1); - Colors = pParams->GetInteger(FX_BSTRC("Colors"), 1); - BitsPerComponent = pParams->GetInteger(FX_BSTRC("BitsPerComponent"), 8); - Columns = pParams->GetInteger(FX_BSTRC("Columns"), 1); - if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns)) { - return (FX_DWORD) - 1; - } - } - return CPDF_ModuleMgr::Get()->GetFlateModule()->FlateOrLZWDecode(bLZW, src_buf, src_size, - bEarlyChange, predictor, Colors, BitsPerComponent, Columns, estimated_size, - dest_buf, dest_size); -} -FX_BOOL PDF_DataDecode(FX_LPCBYTE src_buf, FX_DWORD src_size, const CPDF_Dictionary* pDict, - FX_LPBYTE& dest_buf, FX_DWORD& dest_size, CFX_ByteString& ImageEncoding, - CPDF_Dictionary*& pImageParms, FX_DWORD last_estimated_size, FX_BOOL bImageAcc) - -{ - CPDF_Object* pDecoder = pDict->GetElementValue(FX_BSTRC("Filter")); - if (pDecoder == NULL || (pDecoder->GetType() != PDFOBJ_ARRAY && pDecoder->GetType() != PDFOBJ_NAME)) { - return FALSE; - } - CPDF_Object* pParams = pDict->GetElementValue(FX_BSTRC("DecodeParms")); - CFX_ByteStringArray DecoderList; - CFX_PtrArray ParamList; - if (pDecoder->GetType() == PDFOBJ_ARRAY) { - if (pParams && pParams->GetType() != PDFOBJ_ARRAY) { - pParams = NULL; - } - CPDF_Array* pDecoders = (CPDF_Array*)pDecoder; - for (FX_DWORD i = 0; i < pDecoders->GetCount(); i ++) { - CFX_ByteStringC str = pDecoders->GetConstString(i); - DecoderList.Add(str); - if (pParams) { - ParamList.Add(((CPDF_Array*)pParams)->GetDict(i)); - } else { - ParamList.Add(NULL); - } - } - } else { - DecoderList.Add(pDecoder->GetConstString()); - ParamList.Add(pParams->GetDict()); - } - FX_LPBYTE last_buf = (FX_LPBYTE)src_buf; - FX_DWORD last_size = src_size; - for (int i = 0; i < DecoderList.GetSize(); i ++) { - int estimated_size = i == DecoderList.GetSize() - 1 ? last_estimated_size : 0; - CFX_ByteString decoder = DecoderList[i]; - CPDF_Dictionary* pParam = (CPDF_Dictionary*)ParamList[i]; - FX_LPBYTE new_buf = NULL; - FX_DWORD new_size = (FX_DWORD) - 1; - int offset = -1; - if (decoder == FX_BSTRC("FlateDecode") || decoder == FX_BSTRC("Fl")) { - if (bImageAcc && i == DecoderList.GetSize() - 1) { - ImageEncoding = FX_BSTRC("FlateDecode"); - dest_buf = (FX_LPBYTE)last_buf; - dest_size = last_size; - pImageParms = pParam; - return TRUE; - } else { - offset = FPDFAPI_FlateOrLZWDecode(FALSE, last_buf, last_size, pParam, estimated_size, new_buf, new_size); - } - } else if (decoder == FX_BSTRC("LZWDecode") || decoder == FX_BSTRC("LZW")) { - offset = FPDFAPI_FlateOrLZWDecode(TRUE, last_buf, last_size, pParam, estimated_size, new_buf, new_size); - } else if (decoder == FX_BSTRC("ASCII85Decode") || decoder == FX_BSTRC("A85")) { - offset = _A85Decode(last_buf, last_size, new_buf, new_size); - } else if (decoder == FX_BSTRC("ASCIIHexDecode") || decoder == FX_BSTRC("AHx")) { - offset = _HexDecode(last_buf, last_size, new_buf, new_size); - } else if (decoder == FX_BSTRC("RunLengthDecode") || decoder == FX_BSTRC("RL")) { - if (bImageAcc && i == DecoderList.GetSize() - 1) { - ImageEncoding = FX_BSTRC("RunLengthDecode"); - dest_buf = (FX_LPBYTE)last_buf; - dest_size = last_size; - pImageParms = pParam; - return TRUE; - } - offset = RunLengthDecode(last_buf, last_size, new_buf, new_size); - } else { - if (decoder == FX_BSTRC("DCT")) { - decoder = "DCTDecode"; - } else if (decoder == FX_BSTRC("CCF")) { - decoder = "CCITTFaxDecode"; - } else if (decoder == FX_BSTRC("Crypt")) { - continue; - } - ImageEncoding = decoder; - pImageParms = pParam; - dest_buf = (FX_LPBYTE)last_buf; - dest_size = last_size; - return TRUE; - } - if (last_buf != src_buf) { - FX_Free(last_buf); - } - if (offset == -1) { - return FALSE; - } - last_buf = new_buf; - last_size = new_size; - } - ImageEncoding = ""; - pImageParms = NULL; - dest_buf = last_buf; - dest_size = last_size; - return TRUE; -} -extern const FX_WORD PDFDocEncoding[256] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, - 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, - 0x0014, 0x0015, 0x0016, 0x0017, 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, - 0x02da, 0x02dc, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, - 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, - 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, - 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, - 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062, 0x0063, - 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, - 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000, 0x2022, 0x2020, - 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, - 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, - 0x0152, 0x0160, 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, - 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, - 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3, - 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, - 0x00be, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, - 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0, 0x00d1, - 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, - 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, - 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, - 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, - 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff -}; -CFX_WideString PDF_DecodeText(FX_LPCBYTE src_data, FX_DWORD src_len, CFX_CharMap* pCharMap) -{ - CFX_WideString result; - if (src_len >= 2 && ((src_data[0] == 0xfe && src_data[1] == 0xff) || (src_data[0] == 0xff && src_data[1] == 0xfe))) { - FX_BOOL bBE = src_data[0] == 0xfe; - int max_chars = (src_len - 2) / 2; - if (!max_chars) { - return result; - } - if (src_data[0] == 0xff) { - bBE = !src_data[2]; - } - FX_LPWSTR dest_buf = result.GetBuffer(max_chars); - FX_LPCBYTE uni_str = src_data + 2; - int dest_pos = 0; - for (int i = 0; i < max_chars * 2; i += 2) { - FX_WORD unicode = bBE ? (uni_str[i] << 8 | uni_str[i + 1]) : (uni_str[i + 1] << 8 | uni_str[i]); - if (unicode == 0x1b) { - i += 2; - while (i < max_chars * 2) { - FX_WORD unicode = bBE ? (uni_str[i] << 8 | uni_str[i + 1]) : (uni_str[i + 1] << 8 | uni_str[i]); - i += 2; - if (unicode == 0x1b) { - break; - } - } - } else { - dest_buf[dest_pos++] = unicode; - } - } - result.ReleaseBuffer(dest_pos); - } else if (pCharMap == NULL) { - FX_LPWSTR dest_buf = result.GetBuffer(src_len); - for (FX_DWORD i = 0; i < src_len; i ++) { - dest_buf[i] = PDFDocEncoding[src_data[i]]; - } - result.ReleaseBuffer(src_len); - } else { - return (*pCharMap->m_GetWideString)(pCharMap, CFX_ByteString((FX_LPCSTR)src_data, src_len)); - } - return result; -} -CFX_WideString PDF_DecodeText(const CFX_ByteString& bstr, CFX_CharMap* pCharMap) -{ - return PDF_DecodeText((FX_LPCBYTE)(FX_LPCSTR)bstr, bstr.GetLength(), pCharMap); -} -CFX_ByteString PDF_EncodeText(FX_LPCWSTR pString, int len, CFX_CharMap* pCharMap) -{ - if (len == -1) { - len = (FX_STRSIZE)FXSYS_wcslen(pString); - } - CFX_ByteString result; - if (pCharMap == NULL) { - FX_LPSTR dest_buf1 = result.GetBuffer(len); - int i; - for (i = 0; i < len; i ++) { - int code; - for (code = 0; code < 256; code ++) - if (PDFDocEncoding[code] == pString[i]) { - break; - } - if (code == 256) { - break; - } - dest_buf1[i] = code; - } - result.ReleaseBuffer(i); - if (i == len) { - return result; - } - } - FX_LPBYTE dest_buf2 = (FX_LPBYTE)result.GetBuffer(len * 2 + 2); - dest_buf2[0] = 0xfe; - dest_buf2[1] = 0xff; - dest_buf2 += 2; - for (int i = 0; i < len; i ++) { - *dest_buf2++ = pString[i] >> 8; - *dest_buf2++ = (FX_BYTE)pString[i]; - } - result.ReleaseBuffer(len * 2 + 2); - return result; -} -CFX_ByteString PDF_EncodeString(const CFX_ByteString& src, FX_BOOL bHex) -{ - CFX_ByteTextBuf result; - int srclen = src.GetLength(); - if (bHex) { - result.AppendChar('<'); - for (int i = 0; i < srclen; i ++) { - result.AppendChar("0123456789ABCDEF"[src[i] / 16]); - result.AppendChar("0123456789ABCDEF"[src[i] % 16]); - } - result.AppendChar('>'); - return result.GetByteString(); - } - result.AppendChar('('); - for (int i = 0; i < srclen; i ++) { - FX_BYTE ch = src[i]; - if (ch == ')' || ch == '\\' || ch == '(') { - result.AppendChar('\\'); - } else if (ch == 0x0a) { - result << FX_BSTRC("\\n"); - continue; - } else if (ch == 0x0d) { - result << FX_BSTRC("\\r"); - continue; - } - result.AppendChar(ch); - } - result.AppendChar(')'); - return result.GetByteString(); -} -void FlateEncode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); - if (pEncoders) { - pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf, dest_size); - } -} -void FlateEncode(FX_LPCBYTE src_buf, FX_DWORD src_size, int predictor, int Colors, int BitsPerComponent, int Columns, - FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); - if (pEncoders) { - pEncoders->GetFlateModule()->Encode(src_buf, src_size, predictor, Colors, BitsPerComponent, Columns, dest_buf, dest_size); - } -} -FX_DWORD FlateDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) -{ - CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); - if (pEncoders) { - return pEncoders->GetFlateModule()->FlateOrLZWDecode(FALSE, src_buf, src_size, FALSE, 0, 0, 0, 0, 0, dest_buf, dest_size); - } - return 0; -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fpdfapi/fpdf_parser.h" +#include "../../../include/fpdfapi/fpdf_module.h" +#include "../../../include/fxcodec/fx_codec.h" +#include +#define _STREAM_MAX_SIZE_ 20 * 1024 * 1024 +FX_DWORD _A85Decode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + dest_size = 0; + dest_buf = NULL; + if (src_size == 0) { + return 0; + } + FX_DWORD orig_size = dest_size; + FX_DWORD zcount = 0; + FX_DWORD pos = 0; + while (pos < src_size) { + FX_BYTE ch = src_buf[pos]; + if (ch < '!' && ch != '\n' && ch != '\r' && ch != ' ' && ch != '\t') { + break; + } + if (ch == 'z') { + zcount ++; + } else if (ch > 'u') { + break; + } + pos ++; + } + if (pos == 0) { + return 0; + } + if (zcount > UINT_MAX / 4) { + return (FX_DWORD) - 1; + } + if (zcount * 4 > UINT_MAX - (pos - zcount)) { + return (FX_DWORD) - 1; + } + dest_buf = FX_Alloc(FX_BYTE, zcount * 4 + (pos - zcount)); + if (dest_buf == NULL) { + return (FX_DWORD) - 1; + } + int state = 0, res = 0; + pos = dest_size = 0; + while (pos < src_size) { + FX_BYTE ch = src_buf[pos++]; + if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') { + continue; + } + if (ch == 'z') { + FXSYS_memset32(dest_buf + dest_size, 0, 4); + state = 0; + res = 0; + dest_size += 4; + } else { + if (ch < '!' || ch > 'u') { + break; + } + res = res * 85 + ch - 33; + state ++; + if (state == 5) { + for (int i = 0; i < 4; i ++) { + dest_buf[dest_size++] = (FX_BYTE)(res >> (3 - i) * 8); + } + state = 0; + res = 0; + } + } + } + if (state) { + int i; + for (i = state; i < 5; i ++) { + res = res * 85 + 84; + } + for (i = 0; i < state - 1; i ++) { + dest_buf[dest_size++] = (FX_BYTE)(res >> (3 - i) * 8); + } + } + if (pos < src_size && src_buf[pos] == '>') { + pos ++; + } + return pos; +} +FX_DWORD _HexDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + FX_DWORD orig_size = dest_size; + FX_DWORD i; + for (i = 0; i < src_size; i ++) + if (src_buf[i] == '>') { + break; + } + dest_buf = FX_Alloc( FX_BYTE, i / 2 + 1); + dest_size = 0; + FX_BOOL bFirstDigit = TRUE; + for (i = 0; i < src_size; i ++) { + FX_BYTE ch = src_buf[i]; + if (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r') { + continue; + } + int digit; + if (ch <= '9' && ch >= '0') { + digit = ch - '0'; + } else if (ch <= 'f' && ch >= 'a') { + digit = ch - 'a' + 10; + } else if (ch <= 'F' && ch >= 'A') { + digit = ch - 'A' + 10; + } else if (ch == '>') { + i ++; + break; + } else { + continue; + } + if (bFirstDigit) { + dest_buf[dest_size] = digit * 16; + } else { + dest_buf[dest_size ++] += digit; + } + bFirstDigit = !bFirstDigit; + } + if (!bFirstDigit) { + dest_size ++; + } + return i; +} +FX_DWORD RunLengthDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + FX_DWORD orig_size = dest_size; + FX_DWORD i = 0; + FX_DWORD old; + dest_size = 0; + while (i < src_size) { + if (src_buf[i] < 128) { + old = dest_size; + dest_size += src_buf[i] + 1; + if (dest_size < old) { + return (FX_DWORD) - 1; + } + i += src_buf[i] + 2; + } else if (src_buf[i] > 128) { + old = dest_size; + dest_size += 257 - src_buf[i]; + if (dest_size < old) { + return (FX_DWORD) - 1; + } + i += 2; + } else { + break; + } + } + if (dest_size >= _STREAM_MAX_SIZE_) { + return -1; + } + dest_buf = FX_Alloc( FX_BYTE, dest_size); + if (!dest_buf) { + return -1; + } + i = 0; + int dest_count = 0; + while (i < src_size) { + if (src_buf[i] < 128) { + FX_DWORD copy_len = src_buf[i] + 1; + FX_DWORD buf_left = src_size - i - 1; + if (buf_left < copy_len) { + FX_DWORD delta = copy_len - buf_left; + copy_len = buf_left; + FXSYS_memset8(dest_buf + dest_count + copy_len, '\0', delta); + } + FXSYS_memcpy32(dest_buf + dest_count, src_buf + i + 1, copy_len); + dest_count += src_buf[i] + 1; + i += src_buf[i] + 2; + } else if (src_buf[i] > 128) { + int fill = 0; + if (i < src_size - 1) { + fill = src_buf[i + 1]; + } + FXSYS_memset8(dest_buf + dest_count, fill, 257 - src_buf[i]); + dest_count += 257 - src_buf[i]; + i += 2; + } else { + break; + } + } + FX_DWORD ret = i + 1; + if (ret > src_size) { + ret = src_size; + } + return ret; +} +ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, + const CPDF_Dictionary* pParams) +{ + int K = 0; + FX_BOOL EndOfLine = FALSE; + FX_BOOL ByteAlign = FALSE; + FX_BOOL BlackIs1 = FALSE; + FX_BOOL Columns = 1728; + FX_BOOL Rows = 0; + if (pParams) { + K = pParams->GetInteger(FX_BSTRC("K")); + EndOfLine = pParams->GetInteger(FX_BSTRC("EndOfLine")); + ByteAlign = pParams->GetInteger(FX_BSTRC("EncodedByteAlign")); + BlackIs1 = pParams->GetInteger(FX_BSTRC("BlackIs1")); + Columns = pParams->GetInteger(FX_BSTRC("Columns"), 1728); + Rows = pParams->GetInteger(FX_BSTRC("Rows")); + if (Rows > USHRT_MAX) { + Rows = 0; + } + if (Columns <= 0 || Rows < 0 || Columns > USHRT_MAX || Rows > USHRT_MAX) { + return NULL; + } + } + return CPDF_ModuleMgr::Get()->GetFaxModule()->CreateDecoder(src_buf, src_size, width, height, + K, EndOfLine, ByteAlign, BlackIs1, Columns, Rows); +} +static FX_BOOL CheckFlateDecodeParams(int Colors, int BitsPerComponent, int Columns) +{ + if (Columns < 0) { + return FALSE; + } + int check = Columns; + if (Colors < 0 || (check > 0 && Colors > INT_MAX / check)) { + return FALSE; + } + check *= Colors; + if (BitsPerComponent < 0 || + (check > 0 && BitsPerComponent > INT_MAX / check)) { + return FALSE; + } + check *= BitsPerComponent; + if (check > INT_MAX - 7) { + return FALSE; + } + return TRUE; +} +ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size, int width, int height, + int nComps, int bpc, const CPDF_Dictionary* pParams) +{ + int predictor = 0; + FX_BOOL bEarlyChange = TRUE; + int Colors = 0, BitsPerComponent = 0, Columns = 0; + if (pParams) { + predictor = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("Predictor")); + bEarlyChange = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("EarlyChange"), 1); + Colors = pParams->GetInteger(FX_BSTRC("Colors"), 1); + BitsPerComponent = pParams->GetInteger(FX_BSTRC("BitsPerComponent"), 8); + Columns = pParams->GetInteger(FX_BSTRC("Columns"), 1); + if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns)) { + return NULL; + } + } + return CPDF_ModuleMgr::Get()->GetFlateModule()->CreateDecoder(src_buf, src_size, width, height, + nComps, bpc, predictor, Colors, BitsPerComponent, Columns); +} +FX_DWORD FPDFAPI_FlateOrLZWDecode(FX_BOOL bLZW, const FX_BYTE* src_buf, FX_DWORD src_size, CPDF_Dictionary* pParams, + FX_DWORD estimated_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + int predictor = 0; + FX_BOOL bEarlyChange = TRUE; + int Colors = 0, BitsPerComponent = 0, Columns = 0; + if (pParams) { + predictor = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("Predictor")); + bEarlyChange = ((CPDF_Dictionary*)pParams)->GetInteger(FX_BSTRC("EarlyChange"), 1); + Colors = pParams->GetInteger(FX_BSTRC("Colors"), 1); + BitsPerComponent = pParams->GetInteger(FX_BSTRC("BitsPerComponent"), 8); + Columns = pParams->GetInteger(FX_BSTRC("Columns"), 1); + if (!CheckFlateDecodeParams(Colors, BitsPerComponent, Columns)) { + return (FX_DWORD) - 1; + } + } + return CPDF_ModuleMgr::Get()->GetFlateModule()->FlateOrLZWDecode(bLZW, src_buf, src_size, + bEarlyChange, predictor, Colors, BitsPerComponent, Columns, estimated_size, + dest_buf, dest_size); +} +FX_BOOL PDF_DataDecode(FX_LPCBYTE src_buf, FX_DWORD src_size, const CPDF_Dictionary* pDict, + FX_LPBYTE& dest_buf, FX_DWORD& dest_size, CFX_ByteString& ImageEncoding, + CPDF_Dictionary*& pImageParms, FX_DWORD last_estimated_size, FX_BOOL bImageAcc) + +{ + CPDF_Object* pDecoder = pDict->GetElementValue(FX_BSTRC("Filter")); + if (pDecoder == NULL || (pDecoder->GetType() != PDFOBJ_ARRAY && pDecoder->GetType() != PDFOBJ_NAME)) { + return FALSE; + } + CPDF_Object* pParams = pDict->GetElementValue(FX_BSTRC("DecodeParms")); + CFX_ByteStringArray DecoderList; + CFX_PtrArray ParamList; + if (pDecoder->GetType() == PDFOBJ_ARRAY) { + if (pParams && pParams->GetType() != PDFOBJ_ARRAY) { + pParams = NULL; + } + CPDF_Array* pDecoders = (CPDF_Array*)pDecoder; + for (FX_DWORD i = 0; i < pDecoders->GetCount(); i ++) { + CFX_ByteStringC str = pDecoders->GetConstString(i); + DecoderList.Add(str); + if (pParams) { + ParamList.Add(((CPDF_Array*)pParams)->GetDict(i)); + } else { + ParamList.Add(NULL); + } + } + } else { + DecoderList.Add(pDecoder->GetConstString()); + ParamList.Add(pParams->GetDict()); + } + FX_LPBYTE last_buf = (FX_LPBYTE)src_buf; + FX_DWORD last_size = src_size; + for (int i = 0; i < DecoderList.GetSize(); i ++) { + int estimated_size = i == DecoderList.GetSize() - 1 ? last_estimated_size : 0; + CFX_ByteString decoder = DecoderList[i]; + CPDF_Dictionary* pParam = (CPDF_Dictionary*)ParamList[i]; + FX_LPBYTE new_buf = NULL; + FX_DWORD new_size = (FX_DWORD) - 1; + int offset = -1; + if (decoder == FX_BSTRC("FlateDecode") || decoder == FX_BSTRC("Fl")) { + if (bImageAcc && i == DecoderList.GetSize() - 1) { + ImageEncoding = FX_BSTRC("FlateDecode"); + dest_buf = (FX_LPBYTE)last_buf; + dest_size = last_size; + pImageParms = pParam; + return TRUE; + } else { + offset = FPDFAPI_FlateOrLZWDecode(FALSE, last_buf, last_size, pParam, estimated_size, new_buf, new_size); + } + } else if (decoder == FX_BSTRC("LZWDecode") || decoder == FX_BSTRC("LZW")) { + offset = FPDFAPI_FlateOrLZWDecode(TRUE, last_buf, last_size, pParam, estimated_size, new_buf, new_size); + } else if (decoder == FX_BSTRC("ASCII85Decode") || decoder == FX_BSTRC("A85")) { + offset = _A85Decode(last_buf, last_size, new_buf, new_size); + } else if (decoder == FX_BSTRC("ASCIIHexDecode") || decoder == FX_BSTRC("AHx")) { + offset = _HexDecode(last_buf, last_size, new_buf, new_size); + } else if (decoder == FX_BSTRC("RunLengthDecode") || decoder == FX_BSTRC("RL")) { + if (bImageAcc && i == DecoderList.GetSize() - 1) { + ImageEncoding = FX_BSTRC("RunLengthDecode"); + dest_buf = (FX_LPBYTE)last_buf; + dest_size = last_size; + pImageParms = pParam; + return TRUE; + } + offset = RunLengthDecode(last_buf, last_size, new_buf, new_size); + } else { + if (decoder == FX_BSTRC("DCT")) { + decoder = "DCTDecode"; + } else if (decoder == FX_BSTRC("CCF")) { + decoder = "CCITTFaxDecode"; + } else if (decoder == FX_BSTRC("Crypt")) { + continue; + } + ImageEncoding = decoder; + pImageParms = pParam; + dest_buf = (FX_LPBYTE)last_buf; + dest_size = last_size; + return TRUE; + } + if (last_buf != src_buf) { + FX_Free(last_buf); + } + if (offset == -1) { + return FALSE; + } + last_buf = new_buf; + last_size = new_size; + } + ImageEncoding = ""; + pImageParms = NULL; + dest_buf = last_buf; + dest_size = last_size; + return TRUE; +} +extern const FX_WORD PDFDocEncoding[256] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013, + 0x0014, 0x0015, 0x0016, 0x0017, 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, + 0x02da, 0x02dc, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, + 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, + 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, + 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, + 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062, 0x0063, + 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, + 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000, 0x2022, 0x2020, + 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, 0x2039, 0x203a, 0x2212, 0x2030, + 0x201e, 0x201c, 0x201d, 0x2018, 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, + 0x0152, 0x0160, 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, + 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, + 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3, + 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, + 0x00be, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0, 0x00d1, + 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, + 0x00dc, 0x00dd, 0x00de, 0x00df, 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, + 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, + 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; +CFX_WideString PDF_DecodeText(FX_LPCBYTE src_data, FX_DWORD src_len, CFX_CharMap* pCharMap) +{ + CFX_WideString result; + if (src_len >= 2 && ((src_data[0] == 0xfe && src_data[1] == 0xff) || (src_data[0] == 0xff && src_data[1] == 0xfe))) { + FX_BOOL bBE = src_data[0] == 0xfe; + int max_chars = (src_len - 2) / 2; + if (!max_chars) { + return result; + } + if (src_data[0] == 0xff) { + bBE = !src_data[2]; + } + FX_LPWSTR dest_buf = result.GetBuffer(max_chars); + FX_LPCBYTE uni_str = src_data + 2; + int dest_pos = 0; + for (int i = 0; i < max_chars * 2; i += 2) { + FX_WORD unicode = bBE ? (uni_str[i] << 8 | uni_str[i + 1]) : (uni_str[i + 1] << 8 | uni_str[i]); + if (unicode == 0x1b) { + i += 2; + while (i < max_chars * 2) { + FX_WORD unicode = bBE ? (uni_str[i] << 8 | uni_str[i + 1]) : (uni_str[i + 1] << 8 | uni_str[i]); + i += 2; + if (unicode == 0x1b) { + break; + } + } + } else { + dest_buf[dest_pos++] = unicode; + } + } + result.ReleaseBuffer(dest_pos); + } else if (pCharMap == NULL) { + FX_LPWSTR dest_buf = result.GetBuffer(src_len); + for (FX_DWORD i = 0; i < src_len; i ++) { + dest_buf[i] = PDFDocEncoding[src_data[i]]; + } + result.ReleaseBuffer(src_len); + } else { + return (*pCharMap->m_GetWideString)(pCharMap, CFX_ByteString((FX_LPCSTR)src_data, src_len)); + } + return result; +} +CFX_WideString PDF_DecodeText(const CFX_ByteString& bstr, CFX_CharMap* pCharMap) +{ + return PDF_DecodeText((FX_LPCBYTE)(FX_LPCSTR)bstr, bstr.GetLength(), pCharMap); +} +CFX_ByteString PDF_EncodeText(FX_LPCWSTR pString, int len, CFX_CharMap* pCharMap) +{ + if (len == -1) { + len = (FX_STRSIZE)FXSYS_wcslen(pString); + } + CFX_ByteString result; + if (pCharMap == NULL) { + FX_LPSTR dest_buf1 = result.GetBuffer(len); + int i; + for (i = 0; i < len; i ++) { + int code; + for (code = 0; code < 256; code ++) + if (PDFDocEncoding[code] == pString[i]) { + break; + } + if (code == 256) { + break; + } + dest_buf1[i] = code; + } + result.ReleaseBuffer(i); + if (i == len) { + return result; + } + } + FX_LPBYTE dest_buf2 = (FX_LPBYTE)result.GetBuffer(len * 2 + 2); + dest_buf2[0] = 0xfe; + dest_buf2[1] = 0xff; + dest_buf2 += 2; + for (int i = 0; i < len; i ++) { + *dest_buf2++ = pString[i] >> 8; + *dest_buf2++ = (FX_BYTE)pString[i]; + } + result.ReleaseBuffer(len * 2 + 2); + return result; +} +CFX_ByteString PDF_EncodeString(const CFX_ByteString& src, FX_BOOL bHex) +{ + CFX_ByteTextBuf result; + int srclen = src.GetLength(); + if (bHex) { + result.AppendChar('<'); + for (int i = 0; i < srclen; i ++) { + result.AppendChar("0123456789ABCDEF"[src[i] / 16]); + result.AppendChar("0123456789ABCDEF"[src[i] % 16]); + } + result.AppendChar('>'); + return result.GetByteString(); + } + result.AppendChar('('); + for (int i = 0; i < srclen; i ++) { + FX_BYTE ch = src[i]; + if (ch == ')' || ch == '\\' || ch == '(') { + result.AppendChar('\\'); + } else if (ch == 0x0a) { + result << FX_BSTRC("\\n"); + continue; + } else if (ch == 0x0d) { + result << FX_BSTRC("\\r"); + continue; + } + result.AppendChar(ch); + } + result.AppendChar(')'); + return result.GetByteString(); +} +void FlateEncode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); + if (pEncoders) { + pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf, dest_size); + } +} +void FlateEncode(FX_LPCBYTE src_buf, FX_DWORD src_size, int predictor, int Colors, int BitsPerComponent, int Columns, + FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); + if (pEncoders) { + pEncoders->GetFlateModule()->Encode(src_buf, src_size, predictor, Colors, BitsPerComponent, Columns, dest_buf, dest_size); + } +} +FX_DWORD FlateDecode(const FX_BYTE* src_buf, FX_DWORD src_size, FX_LPBYTE& dest_buf, FX_DWORD& dest_size) +{ + CCodec_ModuleMgr* pEncoders = CPDF_ModuleMgr::Get()->GetCodecModule(); + if (pEncoders) { + return pEncoders->GetFlateModule()->FlateOrLZWDecode(FALSE, src_buf, src_size, FALSE, 0, 0, 0, 0, 0, dest_buf, dest_size); + } + return 0; +} diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp index 068a60679a..a4982040bf 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp @@ -1,398 +1,398 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fpdfapi/fpdf_parser.h" -#include "../../../include/fpdfapi/fpdf_module.h" -extern FX_LPVOID PDFPreviewInitCache(CPDF_Document* pDoc); -extern void PDFPreviewClearCache(FX_LPVOID pCache); -CPDF_Document::CPDF_Document(IPDF_DocParser* pParser) : CPDF_IndirectObjects(pParser) -{ - ASSERT(pParser != NULL); - m_pRootDict = NULL; - m_pInfoDict = NULL; - m_bLinearized = FALSE; - m_dwFirstPageNo = 0; - m_dwFirstPageObjNum = 0; - m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); - m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); -} -CPDF_DocPageData* CPDF_Document::GetValidatePageData() -{ - if (m_pDocPage) { - return m_pDocPage; - } - m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); - return m_pDocPage; -} -CPDF_DocRenderData* CPDF_Document::GetValidateRenderData() -{ - if (m_pDocRender) { - return m_pDocRender; - } - m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); - return m_pDocRender; -} -void CPDF_Document::LoadDoc() -{ - m_LastObjNum = m_pParser->GetLastObjNum(); - CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum()); - if (pRootObj == NULL) { - return; - } - m_pRootDict = pRootObj->GetDict(); - if (m_pRootDict == NULL) { - return; - } - CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum()); - if (pInfoObj) { - m_pInfoDict = pInfoObj->GetDict(); - } - CPDF_Array* pIDArray = m_pParser->GetIDArray(); - if (pIDArray) { - m_ID1 = pIDArray->GetString(0); - m_ID2 = pIDArray->GetString(1); - } - m_PageList.SetSize(_GetPageCount()); -} -void CPDF_Document::LoadAsynDoc(CPDF_Dictionary *pLinearized) -{ - m_bLinearized = TRUE; - m_LastObjNum = m_pParser->GetLastObjNum(); - m_pRootDict = GetIndirectObject(m_pParser->GetRootObjNum())->GetDict(); - if (m_pRootDict == NULL) { - return; - } - m_pInfoDict = GetIndirectObject(m_pParser->GetInfoObjNum())->GetDict(); - CPDF_Array* pIDArray = m_pParser->GetIDArray(); - if (pIDArray) { - m_ID1 = pIDArray->GetString(0); - m_ID2 = pIDArray->GetString(1); - } - FX_DWORD dwPageCount = 0; - CPDF_Object *pCount = pLinearized->GetElement(FX_BSTRC("N")); - if (pCount && pCount->GetType() == PDFOBJ_NUMBER) { - dwPageCount = pCount->GetInteger(); - } - m_PageList.SetSize(dwPageCount); - CPDF_Object *pNo = pLinearized->GetElement(FX_BSTRC("P")); - if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { - m_dwFirstPageNo = pNo->GetInteger(); - } - CPDF_Object *pObjNum = pLinearized->GetElement(FX_BSTRC("O")); - if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) { - m_dwFirstPageObjNum = pObjNum->GetInteger(); - } -} -void CPDF_Document::LoadPages() -{ - m_PageList.SetSize(_GetPageCount()); -} -extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*); -CPDF_Document::~CPDF_Document() -{ - if (m_pDocRender) { - CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender); - } - if (m_pDocPage) { - CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this); - CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this); - } -} -#define FX_MAX_PAGE_LEVEL 1024 -CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level) -{ - CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); - if (pKidList == NULL) { - if (nPagesToGo == 0) { - return pPages; - } - return NULL; - } - if (level >= FX_MAX_PAGE_LEVEL) { - return NULL; - } - int nKids = pKidList->GetCount(); - for (int i = 0; i < nKids; i ++) { - CPDF_Dictionary* pKid = pKidList->GetDict(i); - if (pKid == NULL) { - nPagesToGo --; - continue; - } - if (pKid == pPages) { - continue; - } - if (!pKid->KeyExist(FX_BSTRC("Kids"))) { - if (nPagesToGo == 0) { - return pKid; - } - m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum()); - nPagesToGo --; - } else { - int nPages = pKid->GetInteger(FX_BSTRC("Count")); - if (nPagesToGo < nPages) { - return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1); - } - nPagesToGo -= nPages; - } - } - return NULL; -} -CPDF_Dictionary* CPDF_Document::GetPage(int iPage) -{ - if (iPage < 0 || iPage >= m_PageList.GetSize()) { - return NULL; - } - if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) { - CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum); - if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) { - return (CPDF_Dictionary*)pObj; - } - } - int objnum = m_PageList.GetAt(iPage); - if (objnum) { - CPDF_Object* pObj = GetIndirectObject(objnum); - ASSERT(pObj->GetType() == PDFOBJ_DICTIONARY); - return (CPDF_Dictionary*)pObj; - } - CPDF_Dictionary* pRoot = GetRoot(); - if (pRoot == NULL) { - return NULL; - } - CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); - if (pPages == NULL) { - return NULL; - } - CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0); - if (pPage == NULL) { - return NULL; - } - m_PageList.SetAt(iPage, pPage->GetObjNum()); - return pPage; -} -int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level) -{ - if (pNode->KeyExist(FX_BSTRC("Kids"))) { - CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids")); - if (pKidList == NULL) { - return -1; - } - if (level >= FX_MAX_PAGE_LEVEL) { - return -1; - } - FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count")); - if (count <= skip_count) { - skip_count -= count; - index += count; - return -1; - } - if (count && count == pKidList->GetCount()) { - for (FX_DWORD i = 0; i < count; i ++) { - CPDF_Reference* pKid = (CPDF_Reference*)pKidList->GetElement(i); - if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) { - if (pKid->GetRefObjNum() == objnum) { - m_PageList.SetAt(index + i, objnum); - return index + i; - } - } - } - } - for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { - CPDF_Dictionary* pKid = pKidList->GetDict(i); - if (pKid == NULL) { - continue; - } - if (pKid == pNode) { - continue; - } - int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1); - if (found_index >= 0) { - return found_index; - } - } - } else { - if (objnum == pNode->GetObjNum()) { - return index; - } - if (skip_count) { - skip_count--; - } - index ++; - } - return -1; -} -int CPDF_Document::GetPageIndex(FX_DWORD objnum) -{ - FX_DWORD nPages = m_PageList.GetSize(); - FX_DWORD skip_count = 0; - FX_BOOL bSkipped = FALSE; - for (FX_DWORD i = 0; i < nPages; i ++) { - FX_DWORD objnum1 = m_PageList.GetAt(i); - if (objnum1 == objnum) { - return i; - } - if (!bSkipped && objnum1 == 0) { - skip_count = i; - bSkipped = TRUE; - } - } - CPDF_Dictionary* pRoot = GetRoot(); - if (pRoot == NULL) { - return -1; - } - CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); - if (pPages == NULL) { - return -1; - } - int index = 0; - return _FindPageIndex(pPages, skip_count, objnum, index); -} -int CPDF_Document::GetPageCount() const -{ - return m_PageList.GetSize(); -} -static int _CountPages(CPDF_Dictionary* pPages, int level) -{ - if (level > 128) { - return 0; - } - int count = pPages->GetInteger(FX_BSTRC("Count")); - if (count > 0 && count < FPDF_PAGE_MAX_NUM) { - return count; - } - CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); - if (pKidList == NULL) { - return 0; - } - count = 0; - for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { - CPDF_Dictionary* pKid = pKidList->GetDict(i); - if (pKid == NULL) { - continue; - } - if (!pKid->KeyExist(FX_BSTRC("Kids"))) { - count ++; - } else { - count += _CountPages(pKid, level + 1); - } - } - pPages->SetAtInteger(FX_BSTRC("Count"), count); - return count; -} -int CPDF_Document::_GetPageCount() const -{ - CPDF_Dictionary* pRoot = GetRoot(); - if (pRoot == NULL) { - return 0; - } - CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); - if (pPages == NULL) { - return 0; - } - if (!pPages->KeyExist(FX_BSTRC("Kids"))) { - return 1; - } - return _CountPages(pPages, 0); -} -static FX_BOOL _EnumPages(CPDF_Dictionary* pPages, IPDF_EnumPageHandler* pHandler) -{ - CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); - if (pKidList == NULL) { - return pHandler->EnumPage(pPages); - } - for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { - CPDF_Dictionary* pKid = pKidList->GetDict(i); - if (pKid == NULL) { - continue; - } - if (!pKid->KeyExist(FX_BSTRC("Kids"))) { - if (!pHandler->EnumPage(pKid)) { - return FALSE; - } - } else { - return _EnumPages(pKid, pHandler); - } - } - return TRUE; -} -void CPDF_Document::EnumPages(IPDF_EnumPageHandler* pHandler) -{ - CPDF_Dictionary* pRoot = GetRoot(); - if (pRoot == NULL) { - return; - } - CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); - if (pPages == NULL) { - return; - } - _EnumPages(pPages, pHandler); -} -FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict) -{ - for (int i = 0; i < m_PageList.GetSize(); i ++) { - CPDF_Dictionary* pPageDict = GetPage(i); - if (pPageDict == pThisPageDict) { - continue; - } - CPDF_Object* pContents = pPageDict->GetElement(FX_BSTRC("Contents")); - if (pContents == NULL) { - continue; - } - if (pContents->GetDirectType() == PDFOBJ_ARRAY) { - CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect(); - for (FX_DWORD j = 0; j < pArray->GetCount(); j ++) { - CPDF_Reference* pRef = (CPDF_Reference*)pArray->GetElement(j); - if (pRef->GetRefObjNum() == objnum) { - return TRUE; - } - } - } else if (pContents->GetObjNum() == objnum) { - return TRUE; - } - } - return FALSE; -} -FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const -{ - if (m_pParser == NULL) { - return (FX_DWORD) - 1; - } - return m_pParser->GetPermissions(bCheckRevision); -} -FX_BOOL CPDF_Document::IsOwner() const -{ - if (m_pParser == NULL) { - return TRUE; - } - return m_pParser->IsOwner(); -} -FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const -{ - { - CPDF_Object* pObj; - if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj)) { - bForm = pObj->GetType() == PDFOBJ_STREAM && - ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form"); - return TRUE; - } - } - if (m_pParser == NULL) { - bForm = FALSE; - return TRUE; - } - return m_pParser->IsFormStream(objnum, bForm); -} -void CPDF_Document::ClearPageData() -{ - if (m_pDocPage) { - CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this); - } -} -void CPDF_Document::ClearRenderData() -{ - if (m_pDocRender) { - CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender); - } -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fpdfapi/fpdf_parser.h" +#include "../../../include/fpdfapi/fpdf_module.h" +extern FX_LPVOID PDFPreviewInitCache(CPDF_Document* pDoc); +extern void PDFPreviewClearCache(FX_LPVOID pCache); +CPDF_Document::CPDF_Document(IPDF_DocParser* pParser) : CPDF_IndirectObjects(pParser) +{ + ASSERT(pParser != NULL); + m_pRootDict = NULL; + m_pInfoDict = NULL; + m_bLinearized = FALSE; + m_dwFirstPageNo = 0; + m_dwFirstPageObjNum = 0; + m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); + m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); +} +CPDF_DocPageData* CPDF_Document::GetValidatePageData() +{ + if (m_pDocPage) { + return m_pDocPage; + } + m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); + return m_pDocPage; +} +CPDF_DocRenderData* CPDF_Document::GetValidateRenderData() +{ + if (m_pDocRender) { + return m_pDocRender; + } + m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); + return m_pDocRender; +} +void CPDF_Document::LoadDoc() +{ + m_LastObjNum = m_pParser->GetLastObjNum(); + CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum()); + if (pRootObj == NULL) { + return; + } + m_pRootDict = pRootObj->GetDict(); + if (m_pRootDict == NULL) { + return; + } + CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum()); + if (pInfoObj) { + m_pInfoDict = pInfoObj->GetDict(); + } + CPDF_Array* pIDArray = m_pParser->GetIDArray(); + if (pIDArray) { + m_ID1 = pIDArray->GetString(0); + m_ID2 = pIDArray->GetString(1); + } + m_PageList.SetSize(_GetPageCount()); +} +void CPDF_Document::LoadAsynDoc(CPDF_Dictionary *pLinearized) +{ + m_bLinearized = TRUE; + m_LastObjNum = m_pParser->GetLastObjNum(); + m_pRootDict = GetIndirectObject(m_pParser->GetRootObjNum())->GetDict(); + if (m_pRootDict == NULL) { + return; + } + m_pInfoDict = GetIndirectObject(m_pParser->GetInfoObjNum())->GetDict(); + CPDF_Array* pIDArray = m_pParser->GetIDArray(); + if (pIDArray) { + m_ID1 = pIDArray->GetString(0); + m_ID2 = pIDArray->GetString(1); + } + FX_DWORD dwPageCount = 0; + CPDF_Object *pCount = pLinearized->GetElement(FX_BSTRC("N")); + if (pCount && pCount->GetType() == PDFOBJ_NUMBER) { + dwPageCount = pCount->GetInteger(); + } + m_PageList.SetSize(dwPageCount); + CPDF_Object *pNo = pLinearized->GetElement(FX_BSTRC("P")); + if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { + m_dwFirstPageNo = pNo->GetInteger(); + } + CPDF_Object *pObjNum = pLinearized->GetElement(FX_BSTRC("O")); + if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) { + m_dwFirstPageObjNum = pObjNum->GetInteger(); + } +} +void CPDF_Document::LoadPages() +{ + m_PageList.SetSize(_GetPageCount()); +} +extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*); +CPDF_Document::~CPDF_Document() +{ + if (m_pDocRender) { + CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender); + } + if (m_pDocPage) { + CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this); + CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this); + } +} +#define FX_MAX_PAGE_LEVEL 1024 +CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level) +{ + CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); + if (pKidList == NULL) { + if (nPagesToGo == 0) { + return pPages; + } + return NULL; + } + if (level >= FX_MAX_PAGE_LEVEL) { + return NULL; + } + int nKids = pKidList->GetCount(); + for (int i = 0; i < nKids; i ++) { + CPDF_Dictionary* pKid = pKidList->GetDict(i); + if (pKid == NULL) { + nPagesToGo --; + continue; + } + if (pKid == pPages) { + continue; + } + if (!pKid->KeyExist(FX_BSTRC("Kids"))) { + if (nPagesToGo == 0) { + return pKid; + } + m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum()); + nPagesToGo --; + } else { + int nPages = pKid->GetInteger(FX_BSTRC("Count")); + if (nPagesToGo < nPages) { + return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1); + } + nPagesToGo -= nPages; + } + } + return NULL; +} +CPDF_Dictionary* CPDF_Document::GetPage(int iPage) +{ + if (iPage < 0 || iPage >= m_PageList.GetSize()) { + return NULL; + } + if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) { + CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum); + if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) { + return (CPDF_Dictionary*)pObj; + } + } + int objnum = m_PageList.GetAt(iPage); + if (objnum) { + CPDF_Object* pObj = GetIndirectObject(objnum); + ASSERT(pObj->GetType() == PDFOBJ_DICTIONARY); + return (CPDF_Dictionary*)pObj; + } + CPDF_Dictionary* pRoot = GetRoot(); + if (pRoot == NULL) { + return NULL; + } + CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); + if (pPages == NULL) { + return NULL; + } + CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0); + if (pPage == NULL) { + return NULL; + } + m_PageList.SetAt(iPage, pPage->GetObjNum()); + return pPage; +} +int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level) +{ + if (pNode->KeyExist(FX_BSTRC("Kids"))) { + CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids")); + if (pKidList == NULL) { + return -1; + } + if (level >= FX_MAX_PAGE_LEVEL) { + return -1; + } + FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count")); + if (count <= skip_count) { + skip_count -= count; + index += count; + return -1; + } + if (count && count == pKidList->GetCount()) { + for (FX_DWORD i = 0; i < count; i ++) { + CPDF_Reference* pKid = (CPDF_Reference*)pKidList->GetElement(i); + if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) { + if (pKid->GetRefObjNum() == objnum) { + m_PageList.SetAt(index + i, objnum); + return index + i; + } + } + } + } + for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { + CPDF_Dictionary* pKid = pKidList->GetDict(i); + if (pKid == NULL) { + continue; + } + if (pKid == pNode) { + continue; + } + int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1); + if (found_index >= 0) { + return found_index; + } + } + } else { + if (objnum == pNode->GetObjNum()) { + return index; + } + if (skip_count) { + skip_count--; + } + index ++; + } + return -1; +} +int CPDF_Document::GetPageIndex(FX_DWORD objnum) +{ + FX_DWORD nPages = m_PageList.GetSize(); + FX_DWORD skip_count = 0; + FX_BOOL bSkipped = FALSE; + for (FX_DWORD i = 0; i < nPages; i ++) { + FX_DWORD objnum1 = m_PageList.GetAt(i); + if (objnum1 == objnum) { + return i; + } + if (!bSkipped && objnum1 == 0) { + skip_count = i; + bSkipped = TRUE; + } + } + CPDF_Dictionary* pRoot = GetRoot(); + if (pRoot == NULL) { + return -1; + } + CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); + if (pPages == NULL) { + return -1; + } + int index = 0; + return _FindPageIndex(pPages, skip_count, objnum, index); +} +int CPDF_Document::GetPageCount() const +{ + return m_PageList.GetSize(); +} +static int _CountPages(CPDF_Dictionary* pPages, int level) +{ + if (level > 128) { + return 0; + } + int count = pPages->GetInteger(FX_BSTRC("Count")); + if (count > 0 && count < FPDF_PAGE_MAX_NUM) { + return count; + } + CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); + if (pKidList == NULL) { + return 0; + } + count = 0; + for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { + CPDF_Dictionary* pKid = pKidList->GetDict(i); + if (pKid == NULL) { + continue; + } + if (!pKid->KeyExist(FX_BSTRC("Kids"))) { + count ++; + } else { + count += _CountPages(pKid, level + 1); + } + } + pPages->SetAtInteger(FX_BSTRC("Count"), count); + return count; +} +int CPDF_Document::_GetPageCount() const +{ + CPDF_Dictionary* pRoot = GetRoot(); + if (pRoot == NULL) { + return 0; + } + CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); + if (pPages == NULL) { + return 0; + } + if (!pPages->KeyExist(FX_BSTRC("Kids"))) { + return 1; + } + return _CountPages(pPages, 0); +} +static FX_BOOL _EnumPages(CPDF_Dictionary* pPages, IPDF_EnumPageHandler* pHandler) +{ + CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); + if (pKidList == NULL) { + return pHandler->EnumPage(pPages); + } + for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { + CPDF_Dictionary* pKid = pKidList->GetDict(i); + if (pKid == NULL) { + continue; + } + if (!pKid->KeyExist(FX_BSTRC("Kids"))) { + if (!pHandler->EnumPage(pKid)) { + return FALSE; + } + } else { + return _EnumPages(pKid, pHandler); + } + } + return TRUE; +} +void CPDF_Document::EnumPages(IPDF_EnumPageHandler* pHandler) +{ + CPDF_Dictionary* pRoot = GetRoot(); + if (pRoot == NULL) { + return; + } + CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); + if (pPages == NULL) { + return; + } + _EnumPages(pPages, pHandler); +} +FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict) +{ + for (int i = 0; i < m_PageList.GetSize(); i ++) { + CPDF_Dictionary* pPageDict = GetPage(i); + if (pPageDict == pThisPageDict) { + continue; + } + CPDF_Object* pContents = pPageDict->GetElement(FX_BSTRC("Contents")); + if (pContents == NULL) { + continue; + } + if (pContents->GetDirectType() == PDFOBJ_ARRAY) { + CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect(); + for (FX_DWORD j = 0; j < pArray->GetCount(); j ++) { + CPDF_Reference* pRef = (CPDF_Reference*)pArray->GetElement(j); + if (pRef->GetRefObjNum() == objnum) { + return TRUE; + } + } + } else if (pContents->GetObjNum() == objnum) { + return TRUE; + } + } + return FALSE; +} +FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const +{ + if (m_pParser == NULL) { + return (FX_DWORD) - 1; + } + return m_pParser->GetPermissions(bCheckRevision); +} +FX_BOOL CPDF_Document::IsOwner() const +{ + if (m_pParser == NULL) { + return TRUE; + } + return m_pParser->IsOwner(); +} +FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const +{ + { + CPDF_Object* pObj; + if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj)) { + bForm = pObj->GetType() == PDFOBJ_STREAM && + ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form"); + return TRUE; + } + } + if (m_pParser == NULL) { + bForm = FALSE; + return TRUE; + } + return m_pParser->IsFormStream(objnum, bForm); +} +void CPDF_Document::ClearPageData() +{ + if (m_pDocPage) { + CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this); + } +} +void CPDF_Document::ClearRenderData() +{ + if (m_pDocRender) { + CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender); + } +} diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp index d1f1a24488..fadcd38b1b 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_encrypt.cpp @@ -1,957 +1,957 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include "../../../include/fpdfapi/fpdf_parser.h" -#include "../../../include/fdrm/fx_crypt.h" -const FX_BYTE defpasscode[32] = { - 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, - 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, - 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, - 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a -}; -void CalcEncryptKey(CPDF_Dictionary* pEncrypt, FX_LPCBYTE password, FX_DWORD pass_size, - FX_LPBYTE key, int keylen, FX_BOOL bIgnoreMeta, CPDF_Array* pIdArray) -{ - int revision = pEncrypt->GetInteger(FX_BSTRC("R")); - FX_BYTE passcode[32]; - for (FX_DWORD i = 0; i < 32; i ++) { - passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size]; - } - FX_BYTE md5[100]; - CRYPT_MD5Start(md5); - CRYPT_MD5Update(md5, passcode, 32); - CFX_ByteString okey = pEncrypt->GetString(FX_BSTRC("O")); - CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)okey, okey.GetLength()); - FX_DWORD perm = pEncrypt->GetInteger(FX_BSTRC("P")); - CRYPT_MD5Update(md5, (FX_LPBYTE)&perm, 4); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetString(0); - CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); - } - if (!bIgnoreMeta && revision >= 3 && !pEncrypt->GetInteger(FX_BSTRC("EncryptMetadata"), 1)) { - FX_DWORD tag = (FX_DWORD) - 1; - CRYPT_MD5Update(md5, (FX_LPBYTE)&tag, 4); - } - FX_BYTE digest[16]; - CRYPT_MD5Finish(md5, digest); - FX_DWORD copy_len = keylen; - if (copy_len > sizeof(digest)) { - copy_len = sizeof(digest); - } - if (revision >= 3) { - for (int i = 0; i < 50; i ++) { - CRYPT_MD5Generate(digest, copy_len, digest); - } - } - FXSYS_memset32(key, 0, keylen); - FXSYS_memcpy32(key, digest, copy_len); -} -CPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler() -{ - return FX_NEW CPDF_StandardCryptoHandler; -} -typedef struct _PDF_CRYPTOITEM : public CFX_Object { - FX_INT32 m_Cipher; - FX_INT32 m_KeyLen; - FX_BOOL m_bChecked; - CPDF_StandardCryptoHandler* m_pCryptoHandler; -} PDF_CRYPTOITEM; -CPDF_StandardSecurityHandler::CPDF_StandardSecurityHandler() -{ - m_Version = 0; - m_Revision = 0; - m_pParser = NULL; - m_pEncryptDict = NULL; - m_bOwner = FALSE; - m_Permissions = 0; - m_Cipher = FXCIPHER_NONE; - m_KeyLen = 0; -} -CPDF_StandardSecurityHandler::~CPDF_StandardSecurityHandler() -{ -} -FX_BOOL CPDF_StandardSecurityHandler::OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict) -{ - m_pParser = pParser; - if (!LoadDict(pEncryptDict)) { - return FALSE; - } - if (m_Cipher == FXCIPHER_NONE) { - return TRUE; - } - return CheckSecurity(m_KeyLen); -} -FX_BOOL CPDF_StandardSecurityHandler::CheckSecurity(FX_INT32 key_len) -{ - CFX_ByteString password = m_pParser->GetPassword(); - if (CheckPassword(password, password.GetLength(), TRUE, m_EncryptKey, key_len)) { - if (password.IsEmpty()) { - if (!CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len)) { - return FALSE; - } - } - m_bOwner = TRUE; - return TRUE; - } - return CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len); -} -FX_DWORD CPDF_StandardSecurityHandler::GetPermissions() -{ - return m_Permissions; -} -static FX_BOOL _LoadCryptInfo(CPDF_Dictionary* pEncryptDict, FX_BSTR name, int& cipher, int& keylen) -{ - int Version = pEncryptDict->GetInteger(FX_BSTRC("V")); - int Revision = pEncryptDict->GetInteger(FX_BSTRC("R")); - cipher = FXCIPHER_RC4; - keylen = 0; - if (Version >= 4) { - CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDict(FX_BSTRC("CF")); - if (pCryptFilters == NULL) { - return FALSE; - } - if (name == FX_BSTRC("Identity")) { - cipher = FXCIPHER_NONE; - } else { - CPDF_Dictionary* pDefFilter = pCryptFilters->GetDict(name); - if (pDefFilter == NULL) { - return FALSE; - } - int nKeyBits = 0; - if (Version == 4) { - nKeyBits = pDefFilter->GetInteger(FX_BSTRC("Length"), 0); - if (nKeyBits == 0) { - nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 128); - } - } else { - nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 256); - } - if (nKeyBits < 40) { - nKeyBits *= 8; - } - keylen = nKeyBits / 8; - CFX_ByteString cipher_name = pDefFilter->GetString(FX_BSTRC("CFM")); - if (cipher_name == FX_BSTRC("AESV2") || cipher_name == FX_BSTRC("AESV3")) { - cipher = FXCIPHER_AES; - } - } - } else { - keylen = Version > 1 ? pEncryptDict->GetInteger(FX_BSTRC("Length"), 40) / 8 : 5; - } - if (keylen > 32 || keylen < 0) { - return FALSE; - } - return TRUE; -} -FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) -{ - m_pEncryptDict = pEncryptDict; - m_bOwner = FALSE; - m_Version = pEncryptDict->GetInteger(FX_BSTRC("V")); - m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R")); - m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1); - if (m_Version < 4) { - return _LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen); - } - CFX_ByteString stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF")); - CFX_ByteString strf_name = pEncryptDict->GetString(FX_BSTRC("StrF")); - if (stmf_name != strf_name) { - return FALSE; - } - if (!_LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen)) { - return FALSE; - } - return TRUE; -} -FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, FX_DWORD type, int& cipher, int& key_len) -{ - m_pEncryptDict = pEncryptDict; - m_bOwner = FALSE; - m_Version = pEncryptDict->GetInteger(FX_BSTRC("V")); - m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R")); - m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1); - CFX_ByteString strf_name, stmf_name; - if (m_Version >= 4) { - stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF")); - strf_name = pEncryptDict->GetString(FX_BSTRC("StrF")); - if (stmf_name != strf_name) { - return FALSE; - } - } - if (!_LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len)) { - return FALSE; - } - m_Cipher = cipher; - m_KeyLen = key_len; - return TRUE; - return TRUE; -} -FX_BOOL CPDF_StandardSecurityHandler::GetCryptInfo(int& cipher, FX_LPCBYTE& buffer, int& keylen) -{ - cipher = m_Cipher; - buffer = m_EncryptKey; - keylen = m_KeyLen; - return TRUE; -} -#define FX_GET_32WORD(n,b,i) \ - { \ - (n) = (FX_DWORD)(( (FX_UINT64) (b)[(i)] << 24 ) \ - | ( (FX_UINT64) (b)[(i) + 1] << 16 ) \ - | ( (FX_UINT64) (b)[(i) + 2] << 8 ) \ - | ( (FX_UINT64) (b)[(i) + 3] )); \ - } -int BigOrder64BitsMod3(FX_LPBYTE data) -{ - FX_UINT64 ret = 0; - for (int i = 0; i < 4; ++i) { - FX_DWORD value; - FX_GET_32WORD(value, data, 4 * i); - ret <<= 32; - ret |= value; - ret %= 3; - } - return (int)ret; -} -void Revision6_Hash(FX_LPCBYTE password, FX_DWORD size, FX_LPCBYTE salt, FX_LPCBYTE vector, FX_LPBYTE hash) -{ - int iBlockSize = 32; - FX_BYTE sha[128]; - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, salt, 8); - if (vector) { - CRYPT_SHA256Update(sha, vector, 48); - } - FX_BYTE digest[32]; - CRYPT_SHA256Finish(sha, digest); - CFX_ByteTextBuf buf; - FX_LPBYTE input = digest; - FX_LPBYTE key = input; - FX_LPBYTE iv = input + 16; - FX_LPBYTE E = buf.GetBuffer(); - int iBufLen = buf.GetLength(); - CFX_ByteTextBuf interDigest; - int i = 0; - FX_LPBYTE aes = FX_Alloc(FX_BYTE, 2048); - while (i < 64 || i < E[iBufLen - 1] + 32) { - int iRoundSize = size + iBlockSize; - if (vector) { - iRoundSize += 48; - } - iBufLen = iRoundSize * 64; - buf.EstimateSize(iBufLen); - E = buf.GetBuffer(); - CFX_ByteTextBuf content; - for (int j = 0; j < 64; ++j) { - content.AppendBlock(password, size); - content.AppendBlock(input, iBlockSize); - if (vector) { - content.AppendBlock(vector, 48); - } - } - CRYPT_AESSetKey(aes, 16, key, 16, TRUE); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen); - int iHash = 0; - switch (BigOrder64BitsMod3(E)) { - case 0: - iHash = 0; - iBlockSize = 32; - break; - case 1: - iHash = 1; - iBlockSize = 48; - break; - default: - iHash = 2; - iBlockSize = 64; - break; - } - interDigest.EstimateSize(iBlockSize); - input = interDigest.GetBuffer(); - if (iHash == 0) { - CRYPT_SHA256Generate(E, iBufLen, input); - } else if (iHash == 1) { - CRYPT_SHA384Generate(E, iBufLen, input); - } else if (iHash == 2) { - CRYPT_SHA512Generate(E, iBufLen, input); - } - key = input; - iv = input + 16; - ++i; - } - FX_Free(aes); - if (hash) { - FXSYS_memcpy32(hash, input, 32); - } -} -FX_BOOL CPDF_StandardSecurityHandler::AES256_CheckPassword(FX_LPCBYTE password, FX_DWORD size, - FX_BOOL bOwner, FX_LPBYTE key) -{ - CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O")); - if (okey.GetLength() < 48) { - return FALSE; - } - CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U")); - if (ukey.GetLength() < 48) { - return FALSE; - } - FX_LPCBYTE pkey = bOwner ? (FX_LPCBYTE)okey : (FX_LPCBYTE)ukey; - FX_BYTE sha[128]; - FX_BYTE digest[32]; - if (m_Revision >= 6) { - Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 32, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, pkey + 32, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey, 48); - } - CRYPT_SHA256Finish(sha, digest); - } - if (FXSYS_memcmp32(digest, pkey, 32) != 0) { - return FALSE; - } - if (key == NULL) { - return TRUE; - } - if (m_Revision >= 6) { - Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 40, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, pkey + 40, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey, 48); - } - CRYPT_SHA256Finish(sha, digest); - } - CFX_ByteString ekey = m_pEncryptDict->GetString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE")); - if (ekey.GetLength() < 32) { - return FALSE; - } - FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048); - CRYPT_AESSetKey(aes, 16, digest, 32, FALSE); - FX_BYTE iv[16]; - FXSYS_memset32(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESDecrypt(aes, key, ekey, 32); - CRYPT_AESSetKey(aes, 16, key, 32, FALSE); - CRYPT_AESSetIV(aes, iv); - CFX_ByteString perms = m_pEncryptDict->GetString(FX_BSTRC("Perms")); - if (perms.IsEmpty()) { - return FALSE; - } - FX_BYTE perms_buf[16]; - FXSYS_memset32(perms_buf, 0, sizeof(perms_buf)); - FX_DWORD copy_len = sizeof(perms_buf); - if (copy_len > (FX_DWORD)perms.GetLength()) { - copy_len = perms.GetLength(); - } - FXSYS_memcpy32(perms_buf, (FX_LPCBYTE)perms, copy_len); - FX_BYTE buf[16]; - CRYPT_AESDecrypt(aes, buf, perms_buf, 16); - FX_Free(aes); - if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') { - return FALSE; - } - if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) { - return FALSE; - } - if ((buf[8] == 'T' && !IsMetadataEncrypted()) || (buf[8] == 'F' && IsMetadataEncrypted())) { - return FALSE; - } - return TRUE; -} -int CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD pass_size, FX_BOOL bOwner, FX_LPBYTE key) -{ - return CheckPassword(password, pass_size, bOwner, key, m_KeyLen); -} -int CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPBYTE key, FX_INT32 key_len) -{ - if (m_Revision >= 5) { - return AES256_CheckPassword(password, size, bOwner, key); - } - FX_BYTE keybuf[32]; - if (key == NULL) { - key = keybuf; - } - if (bOwner) { - return CheckOwnerPassword(password, size, key, key_len); - } - return CheckUserPassword(password, size, FALSE, key, key_len) || CheckUserPassword(password, size, TRUE, key, key_len); -} -FX_BOOL CPDF_StandardSecurityHandler::CheckUserPassword(FX_LPCBYTE password, FX_DWORD pass_size, - FX_BOOL bIgnoreEncryptMeta, FX_LPBYTE key, FX_INT32 key_len) -{ - CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, bIgnoreEncryptMeta, - m_pParser->GetIDArray()); - CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U")); - if (ukey.GetLength() < 16) { - return FALSE; - } - FX_BYTE ukeybuf[32]; - if (m_Revision == 2) { - FXSYS_memcpy32(ukeybuf, defpasscode, 32); - CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len); - } else { - FX_BYTE test[32], tmpkey[32]; - FX_DWORD copy_len = sizeof(test); - if (copy_len > (FX_DWORD)ukey.GetLength()) { - copy_len = ukey.GetLength(); - } - FXSYS_memset32(test, 0, sizeof(test)); - FXSYS_memcpy32(test, (FX_LPCSTR)ukey, copy_len); - for (int i = 19; i >= 0; i --) { - for (int j = 0; j < key_len; j ++) { - tmpkey[j] = key[j] ^ i; - } - CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len); - } - FX_BYTE md5[100]; - CRYPT_MD5Start(md5); - CRYPT_MD5Update(md5, defpasscode, 32); - CPDF_Array* pIdArray = m_pParser->GetIDArray(); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetString(0); - CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); - } - CRYPT_MD5Finish(md5, ukeybuf); - return FXSYS_memcmp32(test, ukeybuf, 16) == 0; - } - if (FXSYS_memcmp32((FX_LPVOID)(FX_LPCSTR)ukey, ukeybuf, 16) == 0) { - return TRUE; - } - return FALSE; -} -CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size) -{ - return GetUserPassword(owner_pass, pass_size, m_KeyLen); -} -CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size, FX_INT32 key_len) -{ - CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O")); - FX_BYTE passcode[32]; - FX_DWORD i; - for (i = 0; i < 32; i ++) { - passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size]; - } - FX_BYTE digest[16]; - CRYPT_MD5Generate(passcode, 32, digest); - if (m_Revision >= 3) { - for (int i = 0; i < 50; i ++) { - CRYPT_MD5Generate(digest, 16, digest); - } - } - FX_BYTE enckey[32]; - FXSYS_memset32(enckey, 0, sizeof(enckey)); - FX_DWORD copy_len = key_len; - if (copy_len > sizeof(digest)) { - copy_len = sizeof(digest); - } - FXSYS_memcpy32(enckey, digest, copy_len); - int okeylen = okey.GetLength(); - if (okeylen > 32) { - okeylen = 32; - } - FX_BYTE okeybuf[64]; - FXSYS_memcpy32(okeybuf, (FX_LPCSTR)okey, okeylen); - if (m_Revision == 2) { - CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len); - } else { - for (int i = 19; i >= 0; i --) { - FX_BYTE tempkey[32]; - for (int j = 0; j < m_KeyLen; j ++) { - tempkey[j] = enckey[j] ^ i; - } - CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len); - } - } - int len = 32; - while (len && defpasscode[len - 1] == okeybuf[len - 1]) { - len --; - } - return CFX_ByteString(okeybuf, len); -} -FX_BOOL CPDF_StandardSecurityHandler::CheckOwnerPassword(FX_LPCBYTE password, FX_DWORD pass_size, - FX_LPBYTE key, FX_INT32 key_len) -{ - CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len); - if (CheckUserPassword(user_pass, user_pass.GetLength(), FALSE, key, key_len)) { - return TRUE; - } - return CheckUserPassword(user_pass, user_pass.GetLength(), TRUE, key, key_len); -} -FX_BOOL CPDF_StandardSecurityHandler::IsMetadataEncrypted() -{ - return m_pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE); -} -CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler() -{ - return FX_NEW CPDF_StandardSecurityHandler; -} -void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, - FX_LPCBYTE user_pass, FX_DWORD user_size, - FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_BOOL bDefault, FX_DWORD type) -{ - int cipher = 0, key_len = 0; - if (!LoadDict(pEncryptDict, type, cipher, key_len)) { - return; - } - if (bDefault && (owner_pass == NULL || owner_size == 0)) { - owner_pass = user_pass; - owner_size = user_size; - } - if (m_Revision >= 5) { - int t = (int)time(NULL); - FX_BYTE sha[128]; - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, (FX_BYTE*)&t, sizeof t); - CRYPT_SHA256Update(sha, m_EncryptKey, 32); - CRYPT_SHA256Update(sha, (FX_BYTE*)"there", 5); - CRYPT_SHA256Finish(sha, m_EncryptKey); - AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey); - if (bDefault) { - AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey); - AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE), m_EncryptKey); - } - return; - } - if (bDefault) { - FX_BYTE passcode[32]; - FX_DWORD i; - for (i = 0; i < 32; i ++) { - passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; - } - FX_BYTE digest[16]; - CRYPT_MD5Generate(passcode, 32, digest); - if (m_Revision >= 3) { - for (int i = 0; i < 50; i ++) { - CRYPT_MD5Generate(digest, 16, digest); - } - } - FX_BYTE enckey[32]; - FXSYS_memcpy32(enckey, digest, key_len); - for (i = 0; i < 32; i ++) { - passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; - } - CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); - FX_BYTE tempkey[32]; - if (m_Revision >= 3) { - for (i = 1; i <= 19; i ++) { - for (int j = 0; j < key_len; j ++) { - tempkey[j] = enckey[j] ^ (FX_BYTE)i; - } - CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); - } - } - pEncryptDict->SetAtString(FX_BSTRC("O"), CFX_ByteString(passcode, 32)); - } - CalcEncryptKey(m_pEncryptDict, (FX_LPBYTE)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray); - if (m_Revision < 3) { - FX_BYTE tempbuf[32]; - FXSYS_memcpy32(tempbuf, defpasscode, 32); - CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); - pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(tempbuf, 32)); - } else { - FX_BYTE md5[100]; - CRYPT_MD5Start(md5); - CRYPT_MD5Update(md5, defpasscode, 32); - if (pIdArray) { - CFX_ByteString id = pIdArray->GetString(0); - CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); - } - FX_BYTE digest[32]; - CRYPT_MD5Finish(md5, digest); - CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len); - FX_BYTE tempkey[32]; - for (int i = 1; i <= 19; i ++) { - for (int j = 0; j < key_len; j ++) { - tempkey[j] = m_EncryptKey[j] ^ (FX_BYTE)i; - } - CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); - } - CRYPT_MD5Generate(digest, 16, digest + 16); - pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(digest, 32)); - } -} -void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, - FX_LPCBYTE user_pass, FX_DWORD user_size, - FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_DWORD type) -{ - OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, TRUE, type); -} -void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, FX_LPCBYTE user_pass, FX_DWORD user_size, FX_DWORD type) -{ - OnCreate(pEncryptDict, pIdArray, user_pass, user_size, NULL, 0, FALSE, type); -} -void CPDF_StandardSecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPCBYTE key) -{ - FX_BYTE sha[128]; - CRYPT_SHA1Start(sha); - CRYPT_SHA1Update(sha, key, 32); - CRYPT_SHA1Update(sha, (FX_BYTE*)"hello", 5); - FX_BYTE digest[20]; - CRYPT_SHA1Finish(sha, digest); - CFX_ByteString ukey = pEncryptDict->GetString(FX_BSTRC("U")); - FX_BYTE digest1[48]; - if (m_Revision >= 6) { - Revision6_Hash(password, size, digest, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, digest, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey, ukey.GetLength()); - } - CRYPT_SHA256Finish(sha, digest1); - } - FXSYS_memcpy32(digest1 + 32, digest, 16); - pEncryptDict->SetAtString(bOwner ? FX_BSTRC("O") : FX_BSTRC("U"), CFX_ByteString(digest1, 48)); - if (m_Revision >= 6) { - Revision6_Hash(password, size, digest + 8, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1); - } else { - CRYPT_SHA256Start(sha); - CRYPT_SHA256Update(sha, password, size); - CRYPT_SHA256Update(sha, digest + 8, 8); - if (bOwner) { - CRYPT_SHA256Update(sha, ukey, ukey.GetLength()); - } - CRYPT_SHA256Finish(sha, digest1); - } - FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048); - CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE); - FX_BYTE iv[16]; - FXSYS_memset32(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, digest1, key, 32); - FX_Free(aes); - pEncryptDict->SetAtString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"), CFX_ByteString(digest1, 32)); -} -void CPDF_StandardSecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, FX_DWORD permissions, - FX_BOOL bEncryptMetadata, FX_LPCBYTE key) -{ - FX_BYTE buf[16]; - buf[0] = (FX_BYTE)permissions; - buf[1] = (FX_BYTE)(permissions >> 8); - buf[2] = (FX_BYTE)(permissions >> 16); - buf[3] = (FX_BYTE)(permissions >> 24); - buf[4] = 0xff; - buf[5] = 0xff; - buf[6] = 0xff; - buf[7] = 0xff; - buf[8] = bEncryptMetadata ? 'T' : 'F'; - buf[9] = 'a'; - buf[10] = 'd'; - buf[11] = 'b'; - FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048); - CRYPT_AESSetKey(aes, 16, key, 32, TRUE); - FX_BYTE iv[16], buf1[16]; - FXSYS_memset32(iv, 0, 16); - CRYPT_AESSetIV(aes, iv); - CRYPT_AESEncrypt(aes, buf1, buf, 16); - FX_Free(aes); - pEncryptDict->SetAtString(FX_BSTRC("Perms"), CFX_ByteString(buf1, 16)); -} -void CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size, - FX_LPBYTE dest_buf, FX_DWORD& dest_size) -{ - if (m_Cipher == FXCIPHER_NONE) { - FXSYS_memcpy32(dest_buf, src_buf, src_size); - return; - } - FX_BYTE realkey[16]; - int realkeylen = 16; - if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) { - FX_BYTE key1[32]; - FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen); - key1[m_KeyLen + 0] = (FX_BYTE)objnum; - key1[m_KeyLen + 1] = (FX_BYTE)(objnum >> 8); - key1[m_KeyLen + 2] = (FX_BYTE)(objnum >> 16); - key1[m_KeyLen + 3] = (FX_BYTE)gennum; - key1[m_KeyLen + 4] = (FX_BYTE)(gennum >> 8); - FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3); - FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2); - if (m_Cipher == FXCIPHER_AES) { - FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4); - } - CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); - realkeylen = m_KeyLen + 5; - if (realkeylen > 16) { - realkeylen = 16; - } - } - if (m_Cipher == FXCIPHER_AES) { - CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen, bEncrypt); - if (bEncrypt) { - FX_BYTE iv[16]; - for (int i = 0; i < 16; i ++) { - iv[i] = (FX_BYTE)rand(); - } - CRYPT_AESSetIV(m_pAESContext, iv); - FXSYS_memcpy32(dest_buf, iv, 16); - int nblocks = src_size / 16; - CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); - FX_BYTE padding[16]; - FXSYS_memcpy32(padding, src_buf + nblocks * 16, src_size % 16); - FXSYS_memset8(padding + src_size % 16, 16 - src_size % 16, 16 - src_size % 16); - CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, 16); - dest_size = 32 + nblocks * 16; - } else { - CRYPT_AESSetIV(m_pAESContext, src_buf); - CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); - dest_size = src_size - 16; - dest_size -= dest_buf[dest_size - 1]; - } - } else { - ASSERT(dest_size == src_size); - if (dest_buf != src_buf) { - FXSYS_memcpy32(dest_buf, src_buf, src_size); - } - CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); - } -} -typedef struct _AESCryptContext { - FX_BYTE m_Context[2048]; - FX_BOOL m_bIV; - FX_BYTE m_Block[16]; - FX_DWORD m_BlockOffset; -} AESCryptContext; -FX_LPVOID CPDF_StandardCryptoHandler::CryptStart(FX_DWORD objnum, FX_DWORD gennum, FX_BOOL bEncrypt) -{ - if (m_Cipher == FXCIPHER_NONE) { - return this; - } - if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) { - AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); - pContext->m_bIV = TRUE; - pContext->m_BlockOffset = 0; - CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); - if (bEncrypt) { - for (int i = 0; i < 16; i ++) { - pContext->m_Block[i] = (FX_BYTE)rand(); - } - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); - } - return pContext; - } - FX_BYTE key1[48]; - FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen); - FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3); - FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2); - if (m_Cipher == FXCIPHER_AES) { - FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4); - } - FX_BYTE realkey[16]; - CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); - int realkeylen = m_KeyLen + 5; - if (realkeylen > 16) { - realkeylen = 16; - } - if (m_Cipher == FXCIPHER_AES) { - AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); - pContext->m_bIV = TRUE; - pContext->m_BlockOffset = 0; - CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); - if (bEncrypt) { - for (int i = 0; i < 16; i ++) { - pContext->m_Block[i] = (FX_BYTE)rand(); - } - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); - } - return pContext; - } - void* pContext = FX_Alloc(FX_BYTE, 1040); - CRYPT_ArcFourSetup(pContext, realkey, realkeylen); - return pContext; -} -FX_BOOL CPDF_StandardCryptoHandler::CryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt) -{ - if (!context) { - return FALSE; - } - if (m_Cipher == FXCIPHER_NONE) { - dest_buf.AppendBlock(src_buf, src_size); - return TRUE; - } - if (m_Cipher == FXCIPHER_RC4) { - int old_size = dest_buf.GetSize(); - dest_buf.AppendBlock(src_buf, src_size); - CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size); - return TRUE; - } - AESCryptContext* pContext = (AESCryptContext*)context; - if (pContext->m_bIV && bEncrypt) { - dest_buf.AppendBlock(pContext->m_Block, 16); - pContext->m_bIV = FALSE; - } - FX_DWORD src_off = 0; - FX_DWORD src_left = src_size; - while (1) { - FX_DWORD copy_size = 16 - pContext->m_BlockOffset; - if (copy_size > src_left) { - copy_size = src_left; - } - FXSYS_memcpy32(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, copy_size); - src_off += copy_size; - src_left -= copy_size; - pContext->m_BlockOffset += copy_size; - if (pContext->m_BlockOffset == 16) { - if (!bEncrypt && pContext->m_bIV) { - CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); - pContext->m_bIV = FALSE; - pContext->m_BlockOffset = 0; - } else if (src_off < src_size) { - FX_BYTE block_buf[16]; - if (bEncrypt) { - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - } else { - CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - } - dest_buf.AppendBlock(block_buf, 16); - pContext->m_BlockOffset = 0; - } - } - if (!src_left) { - break; - } - } - return TRUE; -} -FX_BOOL CPDF_StandardCryptoHandler::CryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt) -{ - if (!context) { - return FALSE; - } - if (m_Cipher == FXCIPHER_NONE) { - return TRUE; - } - if (m_Cipher == FXCIPHER_RC4) { - FX_Free(context); - return TRUE; - } - AESCryptContext* pContext = (AESCryptContext*)context; - if (bEncrypt) { - FX_BYTE block_buf[16]; - if (pContext->m_BlockOffset == 16) { - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - dest_buf.AppendBlock(block_buf, 16); - pContext->m_BlockOffset = 0; - } - FXSYS_memset8(pContext->m_Block + pContext->m_BlockOffset, (FX_BYTE)(16 - pContext->m_BlockOffset), 16 - pContext->m_BlockOffset); - CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - dest_buf.AppendBlock(block_buf, 16); - } else if (pContext->m_BlockOffset == 16) { - FX_BYTE block_buf[16]; - CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); - if (block_buf[15] <= 16) { - dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); - } - } - FX_Free(pContext); - return TRUE; -} -FX_LPVOID CPDF_StandardCryptoHandler::DecryptStart(FX_DWORD objnum, FX_DWORD gennum) -{ - return CryptStart(objnum, gennum, FALSE); -} -FX_DWORD CPDF_StandardCryptoHandler::DecryptGetSize(FX_DWORD src_size) -{ - return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; -} -FX_BOOL CPDF_StandardCryptoHandler::Init(CPDF_Dictionary* pEncryptDict, CPDF_SecurityHandler* pSecurityHandler) -{ - FX_LPCBYTE key; - if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) { - return FALSE; - } - if (m_KeyLen > 32 || m_KeyLen < 0) { - return FALSE; - } - if (m_Cipher != FXCIPHER_NONE) { - FXSYS_memcpy32(m_EncryptKey, key, m_KeyLen); - } - if (m_Cipher == FXCIPHER_AES) { - m_pAESContext = FX_Alloc(FX_BYTE, 2048); - } - return TRUE; -} -FX_BOOL CPDF_StandardCryptoHandler::Init(int cipher, FX_LPCBYTE key, int keylen) -{ - if (cipher == FXCIPHER_AES) { - switch(keylen) { - case 16: - case 24: - case 32: - break; - default: - return FALSE; - } - } else if (cipher == FXCIPHER_AES2) { - if (keylen != 32) { - return FALSE; - } - } else if (cipher == FXCIPHER_RC4) { - if (keylen < 5 || keylen > 16) { - return FALSE; - } - } else { - if (keylen > 32) { - keylen = 32; - } - } - m_Cipher = cipher; - m_KeyLen = keylen; - FXSYS_memcpy32(m_EncryptKey, key, keylen); - if (m_Cipher == FXCIPHER_AES) { - m_pAESContext = FX_Alloc(FX_BYTE, 2048); - } - return TRUE; -} -FX_BOOL CPDF_StandardCryptoHandler::DecryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size, - CFX_BinaryBuf& dest_buf) -{ - return CryptStream(context, src_buf, src_size, dest_buf, FALSE); -} -FX_BOOL CPDF_StandardCryptoHandler::DecryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf) -{ - return CryptFinish(context, dest_buf, FALSE); -} -FX_DWORD CPDF_StandardCryptoHandler::EncryptGetSize(FX_DWORD objnum, FX_DWORD version, FX_LPCBYTE src_buf, FX_DWORD src_size) -{ - if (m_Cipher == FXCIPHER_AES) { - return src_size + 32; - } - return src_size; -} -FX_BOOL CPDF_StandardCryptoHandler::EncryptContent(FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size, - FX_LPBYTE dest_buf, FX_DWORD& dest_size) -{ - CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size); - return TRUE; -} -void CPDF_CryptoHandler::Decrypt(FX_DWORD objnum, FX_DWORD gennum, CFX_ByteString& str) -{ - CFX_BinaryBuf dest_buf; - FX_LPVOID context = DecryptStart(objnum, gennum); - DecryptStream(context, (FX_LPCBYTE)str, str.GetLength(), dest_buf); - DecryptFinish(context, dest_buf); - str = dest_buf; -} -CPDF_StandardCryptoHandler::CPDF_StandardCryptoHandler() -{ - m_pAESContext = NULL; - m_Cipher = FXCIPHER_NONE; - m_KeyLen = 0; -} -CPDF_StandardCryptoHandler::~CPDF_StandardCryptoHandler() -{ - if (m_pAESContext) { - FX_Free(m_pAESContext); - } -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include +#include "../../../include/fpdfapi/fpdf_parser.h" +#include "../../../include/fdrm/fx_crypt.h" +const FX_BYTE defpasscode[32] = { + 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, + 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, + 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, + 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a +}; +void CalcEncryptKey(CPDF_Dictionary* pEncrypt, FX_LPCBYTE password, FX_DWORD pass_size, + FX_LPBYTE key, int keylen, FX_BOOL bIgnoreMeta, CPDF_Array* pIdArray) +{ + int revision = pEncrypt->GetInteger(FX_BSTRC("R")); + FX_BYTE passcode[32]; + for (FX_DWORD i = 0; i < 32; i ++) { + passcode[i] = i < pass_size ? password[i] : defpasscode[i - pass_size]; + } + FX_BYTE md5[100]; + CRYPT_MD5Start(md5); + CRYPT_MD5Update(md5, passcode, 32); + CFX_ByteString okey = pEncrypt->GetString(FX_BSTRC("O")); + CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)okey, okey.GetLength()); + FX_DWORD perm = pEncrypt->GetInteger(FX_BSTRC("P")); + CRYPT_MD5Update(md5, (FX_LPBYTE)&perm, 4); + if (pIdArray) { + CFX_ByteString id = pIdArray->GetString(0); + CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); + } + if (!bIgnoreMeta && revision >= 3 && !pEncrypt->GetInteger(FX_BSTRC("EncryptMetadata"), 1)) { + FX_DWORD tag = (FX_DWORD) - 1; + CRYPT_MD5Update(md5, (FX_LPBYTE)&tag, 4); + } + FX_BYTE digest[16]; + CRYPT_MD5Finish(md5, digest); + FX_DWORD copy_len = keylen; + if (copy_len > sizeof(digest)) { + copy_len = sizeof(digest); + } + if (revision >= 3) { + for (int i = 0; i < 50; i ++) { + CRYPT_MD5Generate(digest, copy_len, digest); + } + } + FXSYS_memset32(key, 0, keylen); + FXSYS_memcpy32(key, digest, copy_len); +} +CPDF_CryptoHandler* CPDF_StandardSecurityHandler::CreateCryptoHandler() +{ + return FX_NEW CPDF_StandardCryptoHandler; +} +typedef struct _PDF_CRYPTOITEM : public CFX_Object { + FX_INT32 m_Cipher; + FX_INT32 m_KeyLen; + FX_BOOL m_bChecked; + CPDF_StandardCryptoHandler* m_pCryptoHandler; +} PDF_CRYPTOITEM; +CPDF_StandardSecurityHandler::CPDF_StandardSecurityHandler() +{ + m_Version = 0; + m_Revision = 0; + m_pParser = NULL; + m_pEncryptDict = NULL; + m_bOwner = FALSE; + m_Permissions = 0; + m_Cipher = FXCIPHER_NONE; + m_KeyLen = 0; +} +CPDF_StandardSecurityHandler::~CPDF_StandardSecurityHandler() +{ +} +FX_BOOL CPDF_StandardSecurityHandler::OnInit(CPDF_Parser* pParser, CPDF_Dictionary* pEncryptDict) +{ + m_pParser = pParser; + if (!LoadDict(pEncryptDict)) { + return FALSE; + } + if (m_Cipher == FXCIPHER_NONE) { + return TRUE; + } + return CheckSecurity(m_KeyLen); +} +FX_BOOL CPDF_StandardSecurityHandler::CheckSecurity(FX_INT32 key_len) +{ + CFX_ByteString password = m_pParser->GetPassword(); + if (CheckPassword(password, password.GetLength(), TRUE, m_EncryptKey, key_len)) { + if (password.IsEmpty()) { + if (!CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len)) { + return FALSE; + } + } + m_bOwner = TRUE; + return TRUE; + } + return CheckPassword(password, password.GetLength(), FALSE, m_EncryptKey, key_len); +} +FX_DWORD CPDF_StandardSecurityHandler::GetPermissions() +{ + return m_Permissions; +} +static FX_BOOL _LoadCryptInfo(CPDF_Dictionary* pEncryptDict, FX_BSTR name, int& cipher, int& keylen) +{ + int Version = pEncryptDict->GetInteger(FX_BSTRC("V")); + int Revision = pEncryptDict->GetInteger(FX_BSTRC("R")); + cipher = FXCIPHER_RC4; + keylen = 0; + if (Version >= 4) { + CPDF_Dictionary* pCryptFilters = pEncryptDict->GetDict(FX_BSTRC("CF")); + if (pCryptFilters == NULL) { + return FALSE; + } + if (name == FX_BSTRC("Identity")) { + cipher = FXCIPHER_NONE; + } else { + CPDF_Dictionary* pDefFilter = pCryptFilters->GetDict(name); + if (pDefFilter == NULL) { + return FALSE; + } + int nKeyBits = 0; + if (Version == 4) { + nKeyBits = pDefFilter->GetInteger(FX_BSTRC("Length"), 0); + if (nKeyBits == 0) { + nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 128); + } + } else { + nKeyBits = pEncryptDict->GetInteger(FX_BSTRC("Length"), 256); + } + if (nKeyBits < 40) { + nKeyBits *= 8; + } + keylen = nKeyBits / 8; + CFX_ByteString cipher_name = pDefFilter->GetString(FX_BSTRC("CFM")); + if (cipher_name == FX_BSTRC("AESV2") || cipher_name == FX_BSTRC("AESV3")) { + cipher = FXCIPHER_AES; + } + } + } else { + keylen = Version > 1 ? pEncryptDict->GetInteger(FX_BSTRC("Length"), 40) / 8 : 5; + } + if (keylen > 32 || keylen < 0) { + return FALSE; + } + return TRUE; +} +FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict) +{ + m_pEncryptDict = pEncryptDict; + m_bOwner = FALSE; + m_Version = pEncryptDict->GetInteger(FX_BSTRC("V")); + m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R")); + m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1); + if (m_Version < 4) { + return _LoadCryptInfo(pEncryptDict, CFX_ByteString(), m_Cipher, m_KeyLen); + } + CFX_ByteString stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF")); + CFX_ByteString strf_name = pEncryptDict->GetString(FX_BSTRC("StrF")); + if (stmf_name != strf_name) { + return FALSE; + } + if (!_LoadCryptInfo(pEncryptDict, strf_name, m_Cipher, m_KeyLen)) { + return FALSE; + } + return TRUE; +} +FX_BOOL CPDF_StandardSecurityHandler::LoadDict(CPDF_Dictionary* pEncryptDict, FX_DWORD type, int& cipher, int& key_len) +{ + m_pEncryptDict = pEncryptDict; + m_bOwner = FALSE; + m_Version = pEncryptDict->GetInteger(FX_BSTRC("V")); + m_Revision = pEncryptDict->GetInteger(FX_BSTRC("R")); + m_Permissions = pEncryptDict->GetInteger(FX_BSTRC("P"), -1); + CFX_ByteString strf_name, stmf_name; + if (m_Version >= 4) { + stmf_name = pEncryptDict->GetString(FX_BSTRC("StmF")); + strf_name = pEncryptDict->GetString(FX_BSTRC("StrF")); + if (stmf_name != strf_name) { + return FALSE; + } + } + if (!_LoadCryptInfo(pEncryptDict, strf_name, cipher, key_len)) { + return FALSE; + } + m_Cipher = cipher; + m_KeyLen = key_len; + return TRUE; + return TRUE; +} +FX_BOOL CPDF_StandardSecurityHandler::GetCryptInfo(int& cipher, FX_LPCBYTE& buffer, int& keylen) +{ + cipher = m_Cipher; + buffer = m_EncryptKey; + keylen = m_KeyLen; + return TRUE; +} +#define FX_GET_32WORD(n,b,i) \ + { \ + (n) = (FX_DWORD)(( (FX_UINT64) (b)[(i)] << 24 ) \ + | ( (FX_UINT64) (b)[(i) + 1] << 16 ) \ + | ( (FX_UINT64) (b)[(i) + 2] << 8 ) \ + | ( (FX_UINT64) (b)[(i) + 3] )); \ + } +int BigOrder64BitsMod3(FX_LPBYTE data) +{ + FX_UINT64 ret = 0; + for (int i = 0; i < 4; ++i) { + FX_DWORD value; + FX_GET_32WORD(value, data, 4 * i); + ret <<= 32; + ret |= value; + ret %= 3; + } + return (int)ret; +} +void Revision6_Hash(FX_LPCBYTE password, FX_DWORD size, FX_LPCBYTE salt, FX_LPCBYTE vector, FX_LPBYTE hash) +{ + int iBlockSize = 32; + FX_BYTE sha[128]; + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, salt, 8); + if (vector) { + CRYPT_SHA256Update(sha, vector, 48); + } + FX_BYTE digest[32]; + CRYPT_SHA256Finish(sha, digest); + CFX_ByteTextBuf buf; + FX_LPBYTE input = digest; + FX_LPBYTE key = input; + FX_LPBYTE iv = input + 16; + FX_LPBYTE E = buf.GetBuffer(); + int iBufLen = buf.GetLength(); + CFX_ByteTextBuf interDigest; + int i = 0; + FX_LPBYTE aes = FX_Alloc(FX_BYTE, 2048); + while (i < 64 || i < E[iBufLen - 1] + 32) { + int iRoundSize = size + iBlockSize; + if (vector) { + iRoundSize += 48; + } + iBufLen = iRoundSize * 64; + buf.EstimateSize(iBufLen); + E = buf.GetBuffer(); + CFX_ByteTextBuf content; + for (int j = 0; j < 64; ++j) { + content.AppendBlock(password, size); + content.AppendBlock(input, iBlockSize); + if (vector) { + content.AppendBlock(vector, 48); + } + } + CRYPT_AESSetKey(aes, 16, key, 16, TRUE); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESEncrypt(aes, E, content.GetBuffer(), iBufLen); + int iHash = 0; + switch (BigOrder64BitsMod3(E)) { + case 0: + iHash = 0; + iBlockSize = 32; + break; + case 1: + iHash = 1; + iBlockSize = 48; + break; + default: + iHash = 2; + iBlockSize = 64; + break; + } + interDigest.EstimateSize(iBlockSize); + input = interDigest.GetBuffer(); + if (iHash == 0) { + CRYPT_SHA256Generate(E, iBufLen, input); + } else if (iHash == 1) { + CRYPT_SHA384Generate(E, iBufLen, input); + } else if (iHash == 2) { + CRYPT_SHA512Generate(E, iBufLen, input); + } + key = input; + iv = input + 16; + ++i; + } + FX_Free(aes); + if (hash) { + FXSYS_memcpy32(hash, input, 32); + } +} +FX_BOOL CPDF_StandardSecurityHandler::AES256_CheckPassword(FX_LPCBYTE password, FX_DWORD size, + FX_BOOL bOwner, FX_LPBYTE key) +{ + CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O")); + if (okey.GetLength() < 48) { + return FALSE; + } + CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U")); + if (ukey.GetLength() < 48) { + return FALSE; + } + FX_LPCBYTE pkey = bOwner ? (FX_LPCBYTE)okey : (FX_LPCBYTE)ukey; + FX_BYTE sha[128]; + FX_BYTE digest[32]; + if (m_Revision >= 6) { + Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 32, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, pkey + 32, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey, 48); + } + CRYPT_SHA256Finish(sha, digest); + } + if (FXSYS_memcmp32(digest, pkey, 32) != 0) { + return FALSE; + } + if (key == NULL) { + return TRUE; + } + if (m_Revision >= 6) { + Revision6_Hash(password, size, (FX_LPCBYTE)pkey + 40, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, pkey + 40, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey, 48); + } + CRYPT_SHA256Finish(sha, digest); + } + CFX_ByteString ekey = m_pEncryptDict->GetString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE")); + if (ekey.GetLength() < 32) { + return FALSE; + } + FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048); + CRYPT_AESSetKey(aes, 16, digest, 32, FALSE); + FX_BYTE iv[16]; + FXSYS_memset32(iv, 0, 16); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESDecrypt(aes, key, ekey, 32); + CRYPT_AESSetKey(aes, 16, key, 32, FALSE); + CRYPT_AESSetIV(aes, iv); + CFX_ByteString perms = m_pEncryptDict->GetString(FX_BSTRC("Perms")); + if (perms.IsEmpty()) { + return FALSE; + } + FX_BYTE perms_buf[16]; + FXSYS_memset32(perms_buf, 0, sizeof(perms_buf)); + FX_DWORD copy_len = sizeof(perms_buf); + if (copy_len > (FX_DWORD)perms.GetLength()) { + copy_len = perms.GetLength(); + } + FXSYS_memcpy32(perms_buf, (FX_LPCBYTE)perms, copy_len); + FX_BYTE buf[16]; + CRYPT_AESDecrypt(aes, buf, perms_buf, 16); + FX_Free(aes); + if (buf[9] != 'a' || buf[10] != 'd' || buf[11] != 'b') { + return FALSE; + } + if (FXDWORD_GET_LSBFIRST(buf) != m_Permissions) { + return FALSE; + } + if ((buf[8] == 'T' && !IsMetadataEncrypted()) || (buf[8] == 'F' && IsMetadataEncrypted())) { + return FALSE; + } + return TRUE; +} +int CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD pass_size, FX_BOOL bOwner, FX_LPBYTE key) +{ + return CheckPassword(password, pass_size, bOwner, key, m_KeyLen); +} +int CPDF_StandardSecurityHandler::CheckPassword(FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPBYTE key, FX_INT32 key_len) +{ + if (m_Revision >= 5) { + return AES256_CheckPassword(password, size, bOwner, key); + } + FX_BYTE keybuf[32]; + if (key == NULL) { + key = keybuf; + } + if (bOwner) { + return CheckOwnerPassword(password, size, key, key_len); + } + return CheckUserPassword(password, size, FALSE, key, key_len) || CheckUserPassword(password, size, TRUE, key, key_len); +} +FX_BOOL CPDF_StandardSecurityHandler::CheckUserPassword(FX_LPCBYTE password, FX_DWORD pass_size, + FX_BOOL bIgnoreEncryptMeta, FX_LPBYTE key, FX_INT32 key_len) +{ + CalcEncryptKey(m_pEncryptDict, password, pass_size, key, key_len, bIgnoreEncryptMeta, + m_pParser->GetIDArray()); + CFX_ByteString ukey = m_pEncryptDict->GetString(FX_BSTRC("U")); + if (ukey.GetLength() < 16) { + return FALSE; + } + FX_BYTE ukeybuf[32]; + if (m_Revision == 2) { + FXSYS_memcpy32(ukeybuf, defpasscode, 32); + CRYPT_ArcFourCryptBlock(ukeybuf, 32, key, key_len); + } else { + FX_BYTE test[32], tmpkey[32]; + FX_DWORD copy_len = sizeof(test); + if (copy_len > (FX_DWORD)ukey.GetLength()) { + copy_len = ukey.GetLength(); + } + FXSYS_memset32(test, 0, sizeof(test)); + FXSYS_memcpy32(test, (FX_LPCSTR)ukey, copy_len); + for (int i = 19; i >= 0; i --) { + for (int j = 0; j < key_len; j ++) { + tmpkey[j] = key[j] ^ i; + } + CRYPT_ArcFourCryptBlock(test, 32, tmpkey, key_len); + } + FX_BYTE md5[100]; + CRYPT_MD5Start(md5); + CRYPT_MD5Update(md5, defpasscode, 32); + CPDF_Array* pIdArray = m_pParser->GetIDArray(); + if (pIdArray) { + CFX_ByteString id = pIdArray->GetString(0); + CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); + } + CRYPT_MD5Finish(md5, ukeybuf); + return FXSYS_memcmp32(test, ukeybuf, 16) == 0; + } + if (FXSYS_memcmp32((FX_LPVOID)(FX_LPCSTR)ukey, ukeybuf, 16) == 0) { + return TRUE; + } + return FALSE; +} +CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size) +{ + return GetUserPassword(owner_pass, pass_size, m_KeyLen); +} +CFX_ByteString CPDF_StandardSecurityHandler::GetUserPassword(FX_LPCBYTE owner_pass, FX_DWORD pass_size, FX_INT32 key_len) +{ + CFX_ByteString okey = m_pEncryptDict->GetString(FX_BSTRC("O")); + FX_BYTE passcode[32]; + FX_DWORD i; + for (i = 0; i < 32; i ++) { + passcode[i] = i < pass_size ? owner_pass[i] : defpasscode[i - pass_size]; + } + FX_BYTE digest[16]; + CRYPT_MD5Generate(passcode, 32, digest); + if (m_Revision >= 3) { + for (int i = 0; i < 50; i ++) { + CRYPT_MD5Generate(digest, 16, digest); + } + } + FX_BYTE enckey[32]; + FXSYS_memset32(enckey, 0, sizeof(enckey)); + FX_DWORD copy_len = key_len; + if (copy_len > sizeof(digest)) { + copy_len = sizeof(digest); + } + FXSYS_memcpy32(enckey, digest, copy_len); + int okeylen = okey.GetLength(); + if (okeylen > 32) { + okeylen = 32; + } + FX_BYTE okeybuf[64]; + FXSYS_memcpy32(okeybuf, (FX_LPCSTR)okey, okeylen); + if (m_Revision == 2) { + CRYPT_ArcFourCryptBlock(okeybuf, okeylen, enckey, key_len); + } else { + for (int i = 19; i >= 0; i --) { + FX_BYTE tempkey[32]; + for (int j = 0; j < m_KeyLen; j ++) { + tempkey[j] = enckey[j] ^ i; + } + CRYPT_ArcFourCryptBlock(okeybuf, okeylen, tempkey, key_len); + } + } + int len = 32; + while (len && defpasscode[len - 1] == okeybuf[len - 1]) { + len --; + } + return CFX_ByteString(okeybuf, len); +} +FX_BOOL CPDF_StandardSecurityHandler::CheckOwnerPassword(FX_LPCBYTE password, FX_DWORD pass_size, + FX_LPBYTE key, FX_INT32 key_len) +{ + CFX_ByteString user_pass = GetUserPassword(password, pass_size, key_len); + if (CheckUserPassword(user_pass, user_pass.GetLength(), FALSE, key, key_len)) { + return TRUE; + } + return CheckUserPassword(user_pass, user_pass.GetLength(), TRUE, key, key_len); +} +FX_BOOL CPDF_StandardSecurityHandler::IsMetadataEncrypted() +{ + return m_pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE); +} +CPDF_SecurityHandler* FPDF_CreateStandardSecurityHandler() +{ + return FX_NEW CPDF_StandardSecurityHandler; +} +void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, + FX_LPCBYTE user_pass, FX_DWORD user_size, + FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_BOOL bDefault, FX_DWORD type) +{ + int cipher = 0, key_len = 0; + if (!LoadDict(pEncryptDict, type, cipher, key_len)) { + return; + } + if (bDefault && (owner_pass == NULL || owner_size == 0)) { + owner_pass = user_pass; + owner_size = user_size; + } + if (m_Revision >= 5) { + int t = (int)time(NULL); + FX_BYTE sha[128]; + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, (FX_BYTE*)&t, sizeof t); + CRYPT_SHA256Update(sha, m_EncryptKey, 32); + CRYPT_SHA256Update(sha, (FX_BYTE*)"there", 5); + CRYPT_SHA256Finish(sha, m_EncryptKey); + AES256_SetPassword(pEncryptDict, user_pass, user_size, FALSE, m_EncryptKey); + if (bDefault) { + AES256_SetPassword(pEncryptDict, owner_pass, owner_size, TRUE, m_EncryptKey); + AES256_SetPerms(pEncryptDict, m_Permissions, pEncryptDict->GetBoolean(FX_BSTRC("EncryptMetadata"), TRUE), m_EncryptKey); + } + return; + } + if (bDefault) { + FX_BYTE passcode[32]; + FX_DWORD i; + for (i = 0; i < 32; i ++) { + passcode[i] = i < owner_size ? owner_pass[i] : defpasscode[i - owner_size]; + } + FX_BYTE digest[16]; + CRYPT_MD5Generate(passcode, 32, digest); + if (m_Revision >= 3) { + for (int i = 0; i < 50; i ++) { + CRYPT_MD5Generate(digest, 16, digest); + } + } + FX_BYTE enckey[32]; + FXSYS_memcpy32(enckey, digest, key_len); + for (i = 0; i < 32; i ++) { + passcode[i] = i < user_size ? user_pass[i] : defpasscode[i - user_size]; + } + CRYPT_ArcFourCryptBlock(passcode, 32, enckey, key_len); + FX_BYTE tempkey[32]; + if (m_Revision >= 3) { + for (i = 1; i <= 19; i ++) { + for (int j = 0; j < key_len; j ++) { + tempkey[j] = enckey[j] ^ (FX_BYTE)i; + } + CRYPT_ArcFourCryptBlock(passcode, 32, tempkey, key_len); + } + } + pEncryptDict->SetAtString(FX_BSTRC("O"), CFX_ByteString(passcode, 32)); + } + CalcEncryptKey(m_pEncryptDict, (FX_LPBYTE)user_pass, user_size, m_EncryptKey, key_len, FALSE, pIdArray); + if (m_Revision < 3) { + FX_BYTE tempbuf[32]; + FXSYS_memcpy32(tempbuf, defpasscode, 32); + CRYPT_ArcFourCryptBlock(tempbuf, 32, m_EncryptKey, key_len); + pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(tempbuf, 32)); + } else { + FX_BYTE md5[100]; + CRYPT_MD5Start(md5); + CRYPT_MD5Update(md5, defpasscode, 32); + if (pIdArray) { + CFX_ByteString id = pIdArray->GetString(0); + CRYPT_MD5Update(md5, (FX_LPBYTE)(FX_LPCSTR)id, id.GetLength()); + } + FX_BYTE digest[32]; + CRYPT_MD5Finish(md5, digest); + CRYPT_ArcFourCryptBlock(digest, 16, m_EncryptKey, key_len); + FX_BYTE tempkey[32]; + for (int i = 1; i <= 19; i ++) { + for (int j = 0; j < key_len; j ++) { + tempkey[j] = m_EncryptKey[j] ^ (FX_BYTE)i; + } + CRYPT_ArcFourCryptBlock(digest, 16, tempkey, key_len); + } + CRYPT_MD5Generate(digest, 16, digest + 16); + pEncryptDict->SetAtString(FX_BSTRC("U"), CFX_ByteString(digest, 32)); + } +} +void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, + FX_LPCBYTE user_pass, FX_DWORD user_size, + FX_LPCBYTE owner_pass, FX_DWORD owner_size, FX_DWORD type) +{ + OnCreate(pEncryptDict, pIdArray, user_pass, user_size, owner_pass, owner_size, TRUE, type); +} +void CPDF_StandardSecurityHandler::OnCreate(CPDF_Dictionary* pEncryptDict, CPDF_Array* pIdArray, FX_LPCBYTE user_pass, FX_DWORD user_size, FX_DWORD type) +{ + OnCreate(pEncryptDict, pIdArray, user_pass, user_size, NULL, 0, FALSE, type); +} +void CPDF_StandardSecurityHandler::AES256_SetPassword(CPDF_Dictionary* pEncryptDict, FX_LPCBYTE password, FX_DWORD size, FX_BOOL bOwner, FX_LPCBYTE key) +{ + FX_BYTE sha[128]; + CRYPT_SHA1Start(sha); + CRYPT_SHA1Update(sha, key, 32); + CRYPT_SHA1Update(sha, (FX_BYTE*)"hello", 5); + FX_BYTE digest[20]; + CRYPT_SHA1Finish(sha, digest); + CFX_ByteString ukey = pEncryptDict->GetString(FX_BSTRC("U")); + FX_BYTE digest1[48]; + if (m_Revision >= 6) { + Revision6_Hash(password, size, digest, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, digest, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey, ukey.GetLength()); + } + CRYPT_SHA256Finish(sha, digest1); + } + FXSYS_memcpy32(digest1 + 32, digest, 16); + pEncryptDict->SetAtString(bOwner ? FX_BSTRC("O") : FX_BSTRC("U"), CFX_ByteString(digest1, 48)); + if (m_Revision >= 6) { + Revision6_Hash(password, size, digest + 8, (bOwner ? (FX_LPCBYTE)ukey : NULL), digest1); + } else { + CRYPT_SHA256Start(sha); + CRYPT_SHA256Update(sha, password, size); + CRYPT_SHA256Update(sha, digest + 8, 8); + if (bOwner) { + CRYPT_SHA256Update(sha, ukey, ukey.GetLength()); + } + CRYPT_SHA256Finish(sha, digest1); + } + FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048); + CRYPT_AESSetKey(aes, 16, digest1, 32, TRUE); + FX_BYTE iv[16]; + FXSYS_memset32(iv, 0, 16); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESEncrypt(aes, digest1, key, 32); + FX_Free(aes); + pEncryptDict->SetAtString(bOwner ? FX_BSTRC("OE") : FX_BSTRC("UE"), CFX_ByteString(digest1, 32)); +} +void CPDF_StandardSecurityHandler::AES256_SetPerms(CPDF_Dictionary* pEncryptDict, FX_DWORD permissions, + FX_BOOL bEncryptMetadata, FX_LPCBYTE key) +{ + FX_BYTE buf[16]; + buf[0] = (FX_BYTE)permissions; + buf[1] = (FX_BYTE)(permissions >> 8); + buf[2] = (FX_BYTE)(permissions >> 16); + buf[3] = (FX_BYTE)(permissions >> 24); + buf[4] = 0xff; + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + buf[8] = bEncryptMetadata ? 'T' : 'F'; + buf[9] = 'a'; + buf[10] = 'd'; + buf[11] = 'b'; + FX_BYTE* aes = FX_Alloc(FX_BYTE, 2048); + CRYPT_AESSetKey(aes, 16, key, 32, TRUE); + FX_BYTE iv[16], buf1[16]; + FXSYS_memset32(iv, 0, 16); + CRYPT_AESSetIV(aes, iv); + CRYPT_AESEncrypt(aes, buf1, buf, 16); + FX_Free(aes); + pEncryptDict->SetAtString(FX_BSTRC("Perms"), CFX_ByteString(buf1, 16)); +} +void CPDF_StandardCryptoHandler::CryptBlock(FX_BOOL bEncrypt, FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size, + FX_LPBYTE dest_buf, FX_DWORD& dest_size) +{ + if (m_Cipher == FXCIPHER_NONE) { + FXSYS_memcpy32(dest_buf, src_buf, src_size); + return; + } + FX_BYTE realkey[16]; + int realkeylen = 16; + if (m_Cipher != FXCIPHER_AES || m_KeyLen != 32) { + FX_BYTE key1[32]; + FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen); + key1[m_KeyLen + 0] = (FX_BYTE)objnum; + key1[m_KeyLen + 1] = (FX_BYTE)(objnum >> 8); + key1[m_KeyLen + 2] = (FX_BYTE)(objnum >> 16); + key1[m_KeyLen + 3] = (FX_BYTE)gennum; + key1[m_KeyLen + 4] = (FX_BYTE)(gennum >> 8); + FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3); + FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2); + if (m_Cipher == FXCIPHER_AES) { + FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4); + } + CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); + realkeylen = m_KeyLen + 5; + if (realkeylen > 16) { + realkeylen = 16; + } + } + if (m_Cipher == FXCIPHER_AES) { + CRYPT_AESSetKey(m_pAESContext, 16, m_KeyLen == 32 ? m_EncryptKey : realkey, m_KeyLen, bEncrypt); + if (bEncrypt) { + FX_BYTE iv[16]; + for (int i = 0; i < 16; i ++) { + iv[i] = (FX_BYTE)rand(); + } + CRYPT_AESSetIV(m_pAESContext, iv); + FXSYS_memcpy32(dest_buf, iv, 16); + int nblocks = src_size / 16; + CRYPT_AESEncrypt(m_pAESContext, dest_buf + 16, src_buf, nblocks * 16); + FX_BYTE padding[16]; + FXSYS_memcpy32(padding, src_buf + nblocks * 16, src_size % 16); + FXSYS_memset8(padding + src_size % 16, 16 - src_size % 16, 16 - src_size % 16); + CRYPT_AESEncrypt(m_pAESContext, dest_buf + nblocks * 16 + 16, padding, 16); + dest_size = 32 + nblocks * 16; + } else { + CRYPT_AESSetIV(m_pAESContext, src_buf); + CRYPT_AESDecrypt(m_pAESContext, dest_buf, src_buf + 16, src_size - 16); + dest_size = src_size - 16; + dest_size -= dest_buf[dest_size - 1]; + } + } else { + ASSERT(dest_size == src_size); + if (dest_buf != src_buf) { + FXSYS_memcpy32(dest_buf, src_buf, src_size); + } + CRYPT_ArcFourCryptBlock(dest_buf, dest_size, realkey, realkeylen); + } +} +typedef struct _AESCryptContext { + FX_BYTE m_Context[2048]; + FX_BOOL m_bIV; + FX_BYTE m_Block[16]; + FX_DWORD m_BlockOffset; +} AESCryptContext; +FX_LPVOID CPDF_StandardCryptoHandler::CryptStart(FX_DWORD objnum, FX_DWORD gennum, FX_BOOL bEncrypt) +{ + if (m_Cipher == FXCIPHER_NONE) { + return this; + } + if (m_Cipher == FXCIPHER_AES && m_KeyLen == 32) { + AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); + pContext->m_bIV = TRUE; + pContext->m_BlockOffset = 0; + CRYPT_AESSetKey(pContext->m_Context, 16, m_EncryptKey, 32, bEncrypt); + if (bEncrypt) { + for (int i = 0; i < 16; i ++) { + pContext->m_Block[i] = (FX_BYTE)rand(); + } + CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + } + return pContext; + } + FX_BYTE key1[48]; + FXSYS_memcpy32(key1, m_EncryptKey, m_KeyLen); + FXSYS_memcpy32(key1 + m_KeyLen, &objnum, 3); + FXSYS_memcpy32(key1 + m_KeyLen + 3, &gennum, 2); + if (m_Cipher == FXCIPHER_AES) { + FXSYS_memcpy32(key1 + m_KeyLen + 5, "sAlT", 4); + } + FX_BYTE realkey[16]; + CRYPT_MD5Generate(key1, m_Cipher == FXCIPHER_AES ? m_KeyLen + 9 : m_KeyLen + 5, realkey); + int realkeylen = m_KeyLen + 5; + if (realkeylen > 16) { + realkeylen = 16; + } + if (m_Cipher == FXCIPHER_AES) { + AESCryptContext* pContext = FX_Alloc(AESCryptContext, 1); + pContext->m_bIV = TRUE; + pContext->m_BlockOffset = 0; + CRYPT_AESSetKey(pContext->m_Context, 16, realkey, 16, bEncrypt); + if (bEncrypt) { + for (int i = 0; i < 16; i ++) { + pContext->m_Block[i] = (FX_BYTE)rand(); + } + CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + } + return pContext; + } + void* pContext = FX_Alloc(FX_BYTE, 1040); + CRYPT_ArcFourSetup(pContext, realkey, realkeylen); + return pContext; +} +FX_BOOL CPDF_StandardCryptoHandler::CryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt) +{ + if (!context) { + return FALSE; + } + if (m_Cipher == FXCIPHER_NONE) { + dest_buf.AppendBlock(src_buf, src_size); + return TRUE; + } + if (m_Cipher == FXCIPHER_RC4) { + int old_size = dest_buf.GetSize(); + dest_buf.AppendBlock(src_buf, src_size); + CRYPT_ArcFourCrypt(context, dest_buf.GetBuffer() + old_size, src_size); + return TRUE; + } + AESCryptContext* pContext = (AESCryptContext*)context; + if (pContext->m_bIV && bEncrypt) { + dest_buf.AppendBlock(pContext->m_Block, 16); + pContext->m_bIV = FALSE; + } + FX_DWORD src_off = 0; + FX_DWORD src_left = src_size; + while (1) { + FX_DWORD copy_size = 16 - pContext->m_BlockOffset; + if (copy_size > src_left) { + copy_size = src_left; + } + FXSYS_memcpy32(pContext->m_Block + pContext->m_BlockOffset, src_buf + src_off, copy_size); + src_off += copy_size; + src_left -= copy_size; + pContext->m_BlockOffset += copy_size; + if (pContext->m_BlockOffset == 16) { + if (!bEncrypt && pContext->m_bIV) { + CRYPT_AESSetIV(pContext->m_Context, pContext->m_Block); + pContext->m_bIV = FALSE; + pContext->m_BlockOffset = 0; + } else if (src_off < src_size) { + FX_BYTE block_buf[16]; + if (bEncrypt) { + CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + } else { + CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + } + dest_buf.AppendBlock(block_buf, 16); + pContext->m_BlockOffset = 0; + } + } + if (!src_left) { + break; + } + } + return TRUE; +} +FX_BOOL CPDF_StandardCryptoHandler::CryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf, FX_BOOL bEncrypt) +{ + if (!context) { + return FALSE; + } + if (m_Cipher == FXCIPHER_NONE) { + return TRUE; + } + if (m_Cipher == FXCIPHER_RC4) { + FX_Free(context); + return TRUE; + } + AESCryptContext* pContext = (AESCryptContext*)context; + if (bEncrypt) { + FX_BYTE block_buf[16]; + if (pContext->m_BlockOffset == 16) { + CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + dest_buf.AppendBlock(block_buf, 16); + pContext->m_BlockOffset = 0; + } + FXSYS_memset8(pContext->m_Block + pContext->m_BlockOffset, (FX_BYTE)(16 - pContext->m_BlockOffset), 16 - pContext->m_BlockOffset); + CRYPT_AESEncrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + dest_buf.AppendBlock(block_buf, 16); + } else if (pContext->m_BlockOffset == 16) { + FX_BYTE block_buf[16]; + CRYPT_AESDecrypt(pContext->m_Context, block_buf, pContext->m_Block, 16); + if (block_buf[15] <= 16) { + dest_buf.AppendBlock(block_buf, 16 - block_buf[15]); + } + } + FX_Free(pContext); + return TRUE; +} +FX_LPVOID CPDF_StandardCryptoHandler::DecryptStart(FX_DWORD objnum, FX_DWORD gennum) +{ + return CryptStart(objnum, gennum, FALSE); +} +FX_DWORD CPDF_StandardCryptoHandler::DecryptGetSize(FX_DWORD src_size) +{ + return m_Cipher == FXCIPHER_AES ? src_size - 16 : src_size; +} +FX_BOOL CPDF_StandardCryptoHandler::Init(CPDF_Dictionary* pEncryptDict, CPDF_SecurityHandler* pSecurityHandler) +{ + FX_LPCBYTE key; + if (!pSecurityHandler->GetCryptInfo(m_Cipher, key, m_KeyLen)) { + return FALSE; + } + if (m_KeyLen > 32 || m_KeyLen < 0) { + return FALSE; + } + if (m_Cipher != FXCIPHER_NONE) { + FXSYS_memcpy32(m_EncryptKey, key, m_KeyLen); + } + if (m_Cipher == FXCIPHER_AES) { + m_pAESContext = FX_Alloc(FX_BYTE, 2048); + } + return TRUE; +} +FX_BOOL CPDF_StandardCryptoHandler::Init(int cipher, FX_LPCBYTE key, int keylen) +{ + if (cipher == FXCIPHER_AES) { + switch(keylen) { + case 16: + case 24: + case 32: + break; + default: + return FALSE; + } + } else if (cipher == FXCIPHER_AES2) { + if (keylen != 32) { + return FALSE; + } + } else if (cipher == FXCIPHER_RC4) { + if (keylen < 5 || keylen > 16) { + return FALSE; + } + } else { + if (keylen > 32) { + keylen = 32; + } + } + m_Cipher = cipher; + m_KeyLen = keylen; + FXSYS_memcpy32(m_EncryptKey, key, keylen); + if (m_Cipher == FXCIPHER_AES) { + m_pAESContext = FX_Alloc(FX_BYTE, 2048); + } + return TRUE; +} +FX_BOOL CPDF_StandardCryptoHandler::DecryptStream(FX_LPVOID context, FX_LPCBYTE src_buf, FX_DWORD src_size, + CFX_BinaryBuf& dest_buf) +{ + return CryptStream(context, src_buf, src_size, dest_buf, FALSE); +} +FX_BOOL CPDF_StandardCryptoHandler::DecryptFinish(FX_LPVOID context, CFX_BinaryBuf& dest_buf) +{ + return CryptFinish(context, dest_buf, FALSE); +} +FX_DWORD CPDF_StandardCryptoHandler::EncryptGetSize(FX_DWORD objnum, FX_DWORD version, FX_LPCBYTE src_buf, FX_DWORD src_size) +{ + if (m_Cipher == FXCIPHER_AES) { + return src_size + 32; + } + return src_size; +} +FX_BOOL CPDF_StandardCryptoHandler::EncryptContent(FX_DWORD objnum, FX_DWORD gennum, FX_LPCBYTE src_buf, FX_DWORD src_size, + FX_LPBYTE dest_buf, FX_DWORD& dest_size) +{ + CryptBlock(TRUE, objnum, gennum, src_buf, src_size, dest_buf, dest_size); + return TRUE; +} +void CPDF_CryptoHandler::Decrypt(FX_DWORD objnum, FX_DWORD gennum, CFX_ByteString& str) +{ + CFX_BinaryBuf dest_buf; + FX_LPVOID context = DecryptStart(objnum, gennum); + DecryptStream(context, (FX_LPCBYTE)str, str.GetLength(), dest_buf); + DecryptFinish(context, dest_buf); + str = dest_buf; +} +CPDF_StandardCryptoHandler::CPDF_StandardCryptoHandler() +{ + m_pAESContext = NULL; + m_Cipher = FXCIPHER_NONE; + m_KeyLen = 0; +} +CPDF_StandardCryptoHandler::~CPDF_StandardCryptoHandler() +{ + if (m_pAESContext) { + FX_Free(m_pAESContext); + } +} diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp index 22f9aa713f..36cc9db754 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_fdf.cpp @@ -1,224 +1,224 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fpdfapi/fpdf_serial.h" -CFDF_Document::CFDF_Document() : CPDF_IndirectObjects(NULL) -{ - m_pRootDict = NULL; - m_pFile = NULL; - m_bOwnFile = FALSE; -} -CFDF_Document::~CFDF_Document() -{ - if (m_bOwnFile && m_pFile) { - m_pFile->Release(); - } -} -CFDF_Document* CFDF_Document::CreateNewDoc() -{ - CFDF_Document* pDoc = FX_NEW CFDF_Document; - pDoc->m_pRootDict = FX_NEW CPDF_Dictionary; - pDoc->AddIndirectObject(pDoc->m_pRootDict); - CPDF_Dictionary* pFDFDict = FX_NEW CPDF_Dictionary; - pDoc->m_pRootDict->SetAt(FX_BSTRC("FDF"), pFDFDict); - return pDoc; -} -CFDF_Document* CFDF_Document::ParseFile(FX_LPCSTR file_path) -{ - return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE); -} -CFDF_Document* CFDF_Document::ParseFile(FX_LPCWSTR file_path) -{ - return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE); -} -CFDF_Document* CFDF_Document::ParseFile(IFX_FileRead *pFile, FX_BOOL bOwnFile) -{ - if (!pFile) { - return NULL; - } - CFDF_Document* pDoc = FX_NEW CFDF_Document; - pDoc->ParseStream(pFile, bOwnFile); - if (pDoc->m_pRootDict == NULL) { - delete pDoc; - return NULL; - } - return pDoc; -} -CFDF_Document* CFDF_Document::ParseMemory(FX_LPCBYTE pData, FX_DWORD size) -{ - return CFDF_Document::ParseFile(FX_CreateMemoryStream((FX_LPBYTE)pData, size), TRUE); -} -void CFDF_Document::ParseStream(IFX_FileRead *pFile, FX_BOOL bOwnFile) -{ - m_pFile = pFile; - m_bOwnFile = bOwnFile; - CPDF_SyntaxParser parser; - parser.InitParser(m_pFile, 0); - while (1) { - FX_BOOL bNumber; - CFX_ByteString word = parser.GetNextWord(bNumber); - if (bNumber) { - FX_DWORD objnum = FXSYS_atoi(word); - word = parser.GetNextWord(bNumber); - if (!bNumber) { - break; - } - word = parser.GetNextWord(bNumber); - if (word != FX_BSTRC("obj")) { - break; - } - CPDF_Object* pObj = parser.GetObject(this, objnum, 0, FALSE); - if (pObj == NULL) { - break; - } - InsertIndirectObject(objnum, pObj); - word = parser.GetNextWord(bNumber); - if (word != FX_BSTRC("endobj")) { - break; - } - } else { - if (word != FX_BSTRC("trailer")) { - break; - } - CPDF_Dictionary* pMainDict = (CPDF_Dictionary*)parser.GetObject(this, 0, 0, 0); - if (pMainDict == NULL || pMainDict->GetType() != PDFOBJ_DICTIONARY) { - break; - } - m_pRootDict = pMainDict->GetDict(FX_BSTRC("Root")); - pMainDict->Release(); - break; - } - } -} -FX_BOOL CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const -{ - if (m_pRootDict == NULL) { - return FALSE; - } - buf << FX_BSTRC("%FDF-1.2\r\n"); - FX_POSITION pos = m_IndirectObjs.GetStartPosition(); - while(pos) { - size_t objnum; - CPDF_Object* pObj; - m_IndirectObjs.GetNextAssoc(pos, (FX_LPVOID&)objnum, (FX_LPVOID&)pObj); - buf << (FX_DWORD)objnum << FX_BSTRC(" 0 obj\r\n") << pObj << FX_BSTRC("\r\nendobj\r\n\r\n"); - } - buf << FX_BSTRC("trailer\r\n<GetObjNum() << FX_BSTRC(" 0 R>>\r\n%%EOF\r\n"); - return TRUE; -} -CFX_WideString CFDF_Document::GetWin32Path() const -{ - CPDF_Object* pFileSpec = m_pRootDict->GetDict(FX_BSTRC("FDF"))->GetElementValue(FX_BSTRC("F")); - if (pFileSpec == NULL) { - return CFX_WideString(); - } - if (pFileSpec->GetType() == PDFOBJ_STRING) { - return FPDF_FileSpec_GetWin32Path(m_pRootDict->GetDict(FX_BSTRC("FDF"))); - } - return FPDF_FileSpec_GetWin32Path(pFileSpec); -} -FX_BOOL CFDF_Document::WriteFile(FX_LPCSTR file_path) const -{ - IFX_FileWrite *pFile = FX_CreateFileWrite(file_path); - if (!pFile) { - return FALSE; - } - FX_BOOL bRet = WriteFile(pFile); - pFile->Release(); - return bRet; -} -FX_BOOL CFDF_Document::WriteFile(FX_LPCWSTR file_path) const -{ - IFX_FileWrite *pFile = FX_CreateFileWrite(file_path); - if (!pFile) { - return FALSE; - } - FX_BOOL bRet = WriteFile(pFile); - pFile->Release(); - return bRet; -} -FX_BOOL CFDF_Document::WriteFile(IFX_FileWrite *pFile) const -{ - CFX_ByteTextBuf buf; - WriteBuf(buf); - FX_BOOL bRet = pFile->WriteBlock(buf.GetBuffer(), buf.GetSize()); - if (bRet) { - pFile->Flush(); - } - return bRet; -} -static CFX_WideString ChangeSlash(FX_LPCWSTR str) -{ - CFX_WideString result; - while (*str) { - if (*str == '\\') { - result += '/'; - } else if (*str == '/') { - result += '\\'; - } else { - result += *str; - } - str ++; - } - return result; -} -void FPDF_FileSpec_SetWin32Path(CPDF_Object* pFileSpec, const CFX_WideString& filepath) -{ - CFX_WideString result; - if (filepath.GetLength() > 1 && filepath[1] == ':') { - result = L"/"; - result += filepath[0]; - if (filepath[2] != '\\') { - result += '/'; - } - result += ChangeSlash((FX_LPCWSTR)filepath + 2); - } else if (filepath.GetLength() > 1 && filepath[0] == '\\' && filepath[1] == '\\') { - result = ChangeSlash((FX_LPCWSTR)filepath + 1); - } else { - result = ChangeSlash(filepath); - } - if (pFileSpec->GetType() == PDFOBJ_STRING) { - pFileSpec->SetString(CFX_ByteString::FromUnicode(result)); - } else if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) { - ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(result)); - ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(result)); - ((CPDF_Dictionary*)pFileSpec)->RemoveAt(FX_BSTRC("FS")); - } -} -CFX_WideString FPDF_FileSpec_GetWin32Path(const CPDF_Object* pFileSpec) -{ - CFX_WideString wsFileName; - if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) { - CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFileSpec; - wsFileName = pDict->GetUnicodeText(FX_BSTRC("UF")); - if (wsFileName.IsEmpty()) { - wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F"))); - } - if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) { - return wsFileName; - } - if (wsFileName.IsEmpty() && pDict->KeyExist(FX_BSTRC("DOS"))) { - wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS"))); - } - } else { - wsFileName = CFX_WideString::FromLocal(pFileSpec->GetString()); - } - if (wsFileName[0] != '/') { - return ChangeSlash(wsFileName); - } - if (wsFileName[2] == '/') { - CFX_WideString result; - result += wsFileName[1]; - result += ':'; - result += ChangeSlash(((FX_LPCWSTR)wsFileName) + 2); - return result; - } else { - CFX_WideString result; - result += '\\'; - result += ChangeSlash(wsFileName); - return result; - } -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fpdfapi/fpdf_serial.h" +CFDF_Document::CFDF_Document() : CPDF_IndirectObjects(NULL) +{ + m_pRootDict = NULL; + m_pFile = NULL; + m_bOwnFile = FALSE; +} +CFDF_Document::~CFDF_Document() +{ + if (m_bOwnFile && m_pFile) { + m_pFile->Release(); + } +} +CFDF_Document* CFDF_Document::CreateNewDoc() +{ + CFDF_Document* pDoc = FX_NEW CFDF_Document; + pDoc->m_pRootDict = FX_NEW CPDF_Dictionary; + pDoc->AddIndirectObject(pDoc->m_pRootDict); + CPDF_Dictionary* pFDFDict = FX_NEW CPDF_Dictionary; + pDoc->m_pRootDict->SetAt(FX_BSTRC("FDF"), pFDFDict); + return pDoc; +} +CFDF_Document* CFDF_Document::ParseFile(FX_LPCSTR file_path) +{ + return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE); +} +CFDF_Document* CFDF_Document::ParseFile(FX_LPCWSTR file_path) +{ + return CFDF_Document::ParseFile(FX_CreateFileRead(file_path), TRUE); +} +CFDF_Document* CFDF_Document::ParseFile(IFX_FileRead *pFile, FX_BOOL bOwnFile) +{ + if (!pFile) { + return NULL; + } + CFDF_Document* pDoc = FX_NEW CFDF_Document; + pDoc->ParseStream(pFile, bOwnFile); + if (pDoc->m_pRootDict == NULL) { + delete pDoc; + return NULL; + } + return pDoc; +} +CFDF_Document* CFDF_Document::ParseMemory(FX_LPCBYTE pData, FX_DWORD size) +{ + return CFDF_Document::ParseFile(FX_CreateMemoryStream((FX_LPBYTE)pData, size), TRUE); +} +void CFDF_Document::ParseStream(IFX_FileRead *pFile, FX_BOOL bOwnFile) +{ + m_pFile = pFile; + m_bOwnFile = bOwnFile; + CPDF_SyntaxParser parser; + parser.InitParser(m_pFile, 0); + while (1) { + FX_BOOL bNumber; + CFX_ByteString word = parser.GetNextWord(bNumber); + if (bNumber) { + FX_DWORD objnum = FXSYS_atoi(word); + word = parser.GetNextWord(bNumber); + if (!bNumber) { + break; + } + word = parser.GetNextWord(bNumber); + if (word != FX_BSTRC("obj")) { + break; + } + CPDF_Object* pObj = parser.GetObject(this, objnum, 0, FALSE); + if (pObj == NULL) { + break; + } + InsertIndirectObject(objnum, pObj); + word = parser.GetNextWord(bNumber); + if (word != FX_BSTRC("endobj")) { + break; + } + } else { + if (word != FX_BSTRC("trailer")) { + break; + } + CPDF_Dictionary* pMainDict = (CPDF_Dictionary*)parser.GetObject(this, 0, 0, 0); + if (pMainDict == NULL || pMainDict->GetType() != PDFOBJ_DICTIONARY) { + break; + } + m_pRootDict = pMainDict->GetDict(FX_BSTRC("Root")); + pMainDict->Release(); + break; + } + } +} +FX_BOOL CFDF_Document::WriteBuf(CFX_ByteTextBuf& buf) const +{ + if (m_pRootDict == NULL) { + return FALSE; + } + buf << FX_BSTRC("%FDF-1.2\r\n"); + FX_POSITION pos = m_IndirectObjs.GetStartPosition(); + while(pos) { + size_t objnum; + CPDF_Object* pObj; + m_IndirectObjs.GetNextAssoc(pos, (FX_LPVOID&)objnum, (FX_LPVOID&)pObj); + buf << (FX_DWORD)objnum << FX_BSTRC(" 0 obj\r\n") << pObj << FX_BSTRC("\r\nendobj\r\n\r\n"); + } + buf << FX_BSTRC("trailer\r\n<GetObjNum() << FX_BSTRC(" 0 R>>\r\n%%EOF\r\n"); + return TRUE; +} +CFX_WideString CFDF_Document::GetWin32Path() const +{ + CPDF_Object* pFileSpec = m_pRootDict->GetDict(FX_BSTRC("FDF"))->GetElementValue(FX_BSTRC("F")); + if (pFileSpec == NULL) { + return CFX_WideString(); + } + if (pFileSpec->GetType() == PDFOBJ_STRING) { + return FPDF_FileSpec_GetWin32Path(m_pRootDict->GetDict(FX_BSTRC("FDF"))); + } + return FPDF_FileSpec_GetWin32Path(pFileSpec); +} +FX_BOOL CFDF_Document::WriteFile(FX_LPCSTR file_path) const +{ + IFX_FileWrite *pFile = FX_CreateFileWrite(file_path); + if (!pFile) { + return FALSE; + } + FX_BOOL bRet = WriteFile(pFile); + pFile->Release(); + return bRet; +} +FX_BOOL CFDF_Document::WriteFile(FX_LPCWSTR file_path) const +{ + IFX_FileWrite *pFile = FX_CreateFileWrite(file_path); + if (!pFile) { + return FALSE; + } + FX_BOOL bRet = WriteFile(pFile); + pFile->Release(); + return bRet; +} +FX_BOOL CFDF_Document::WriteFile(IFX_FileWrite *pFile) const +{ + CFX_ByteTextBuf buf; + WriteBuf(buf); + FX_BOOL bRet = pFile->WriteBlock(buf.GetBuffer(), buf.GetSize()); + if (bRet) { + pFile->Flush(); + } + return bRet; +} +static CFX_WideString ChangeSlash(FX_LPCWSTR str) +{ + CFX_WideString result; + while (*str) { + if (*str == '\\') { + result += '/'; + } else if (*str == '/') { + result += '\\'; + } else { + result += *str; + } + str ++; + } + return result; +} +void FPDF_FileSpec_SetWin32Path(CPDF_Object* pFileSpec, const CFX_WideString& filepath) +{ + CFX_WideString result; + if (filepath.GetLength() > 1 && filepath[1] == ':') { + result = L"/"; + result += filepath[0]; + if (filepath[2] != '\\') { + result += '/'; + } + result += ChangeSlash((FX_LPCWSTR)filepath + 2); + } else if (filepath.GetLength() > 1 && filepath[0] == '\\' && filepath[1] == '\\') { + result = ChangeSlash((FX_LPCWSTR)filepath + 1); + } else { + result = ChangeSlash(filepath); + } + if (pFileSpec->GetType() == PDFOBJ_STRING) { + pFileSpec->SetString(CFX_ByteString::FromUnicode(result)); + } else if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) { + ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(result)); + ((CPDF_Dictionary*)pFileSpec)->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(result)); + ((CPDF_Dictionary*)pFileSpec)->RemoveAt(FX_BSTRC("FS")); + } +} +CFX_WideString FPDF_FileSpec_GetWin32Path(const CPDF_Object* pFileSpec) +{ + CFX_WideString wsFileName; + if (pFileSpec->GetType() == PDFOBJ_DICTIONARY) { + CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFileSpec; + wsFileName = pDict->GetUnicodeText(FX_BSTRC("UF")); + if (wsFileName.IsEmpty()) { + wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F"))); + } + if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) { + return wsFileName; + } + if (wsFileName.IsEmpty() && pDict->KeyExist(FX_BSTRC("DOS"))) { + wsFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS"))); + } + } else { + wsFileName = CFX_WideString::FromLocal(pFileSpec->GetString()); + } + if (wsFileName[0] != '/') { + return ChangeSlash(wsFileName); + } + if (wsFileName[2] == '/') { + CFX_WideString result; + result += wsFileName[1]; + result += ':'; + result += ChangeSlash(((FX_LPCWSTR)wsFileName) + 2); + return result; + } else { + CFX_WideString result; + result += '\\'; + result += ChangeSlash(wsFileName); + return result; + } +} diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_filters.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_filters.cpp index 76a79f69cb..1e4e1570df 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_filters.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_filters.cpp @@ -1,909 +1,909 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../fx_zlib.h" -#include "../../../include/fpdfapi/fpdf_parser.h" -#include "../../../include/fxcodec/fx_codec.h" -#include "../../../include/fpdfapi/fpdf_module.h" -#include "filters_int.h" -CFX_DataFilter::CFX_DataFilter() -{ - m_bEOF = FALSE; - m_pDestFilter = NULL; - m_SrcPos = 0; -} -CFX_DataFilter::~CFX_DataFilter() -{ - if (m_pDestFilter) { - delete m_pDestFilter; - } -} -void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter) -{ - if (m_pDestFilter) { - m_pDestFilter->SetDestFilter(pFilter); - } else { - m_pDestFilter = pFilter; - } -} -void CFX_DataFilter::FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - if (m_bEOF) { - return; - } - m_SrcPos += src_size; - if (m_pDestFilter) { - CFX_BinaryBuf temp_buf; - temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE); - v_FilterIn(src_buf, src_size, temp_buf); - m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf); - } else { - v_FilterIn(src_buf, src_size, dest_buf); - } -} -void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf) -{ - if (m_pDestFilter) { - CFX_BinaryBuf temp_buf; - v_FilterFinish(temp_buf); - if (temp_buf.GetSize()) { - m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf); - } - m_pDestFilter->FilterFinish(dest_buf); - } else { - v_FilterFinish(dest_buf); - } - m_bEOF = TRUE; -} -void CFX_DataFilter::ReportEOF(FX_DWORD left_input) -{ - if (m_bEOF) { - return; - } - m_bEOF = TRUE; - m_SrcPos -= left_input; -} -CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width, int height) -{ - FX_DWORD id = name.GetID(); - switch (id) { - case FXBSTR_ID('F', 'l', 'a', 't'): - case FXBSTR_ID('F', 'l', 0, 0): - case FXBSTR_ID('L', 'Z', 'W', 'D'): - case FXBSTR_ID('L', 'Z', 'W', 0): { - CFX_DataFilter* pFilter; - if (id == FXBSTR_ID('L', 'Z', 'W', 'D') || id == FXBSTR_ID('L', 'Z', 'W', 0)) { - pFilter = FX_NEW CPDF_LzwFilter(pParam->GetInteger("EarlyChange", 1)); - } else { - pFilter = FX_NEW CPDF_FlateFilter; - } - if (pParam->GetInteger("Predictor", 1) > 1) { - CFX_DataFilter* pPredictor = FX_NEW CPDF_PredictorFilter(pParam->GetInteger(FX_BSTRC("Predictor"), 1), - pParam->GetInteger(FX_BSTRC("Colors"), 1), pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8), - pParam->GetInteger(FX_BSTRC("Columns"), 1)); - pFilter->SetDestFilter(pPredictor); - } - return pFilter; - } - case FXBSTR_ID('A', 'S', 'C', 'I'): - if (name == "ASCIIHexDecode") { - return FX_NEW CPDF_AsciiHexFilter; - } - return FX_NEW CPDF_Ascii85Filter; - case FXBSTR_ID('A', 'H', 'x', 0): - return FX_NEW CPDF_AsciiHexFilter; - case FXBSTR_ID('A', '8', '5', 0): - return FX_NEW CPDF_Ascii85Filter; - case FXBSTR_ID('R', 'u', 'n', 'L'): - return FX_NEW CPDF_RunLenFilter; - case FXBSTR_ID('C', 'C', 'I', 'T'): { - int Encoding = 0; - int bEndOfLine = FALSE; - int bByteAlign = FALSE; - int bBlack = FALSE; - int nRows = 0; - int nColumns = 1728; - if (pParam) { - Encoding = pParam->GetInteger(FX_BSTRC("K")); - bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine")); - bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign")); - bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1")); - nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728); - nRows = pParam->GetInteger(FX_BSTRC("Rows")); - } - if (nColumns == 0) { - nColumns = width; - } - if (nRows == 0) { - nRows = height; - } - CPDF_FaxFilter* pFilter = FX_NEW CPDF_FaxFilter(); - pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows, nColumns); - return pFilter; - } - case FXBSTR_ID('D', 'C', 'T', 'D'): - return FX_NEW CPDF_JpegFilter; - default: - return NULL; - } -} -CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict) -{ - CPDF_Object* pDecoder = pDict->GetElementValue("Filter"); - if (pDecoder == NULL) { - return NULL; - } - CFX_DataFilter* pFirstFilter = NULL; - int width = pDict->GetInteger(FX_BSTRC("Width")), height = pDict->GetInteger(FX_BSTRC("Height")); - CPDF_Object* pParams = pDict->GetElementValue("DecodeParms"); - if (pDecoder->GetType() == PDFOBJ_ARRAY) { - if (pParams && pParams->GetType() != PDFOBJ_ARRAY) { - pParams = NULL; - } - for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i ++) { - CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i); - CPDF_Dictionary* pParam = NULL; - if (pParams) { - pParam = ((CPDF_Array*)pParams)->GetDict(i); - } - CFX_DataFilter* pDestFilter = FPDF_CreateFilter(name, pParam, width, height); - if (pDestFilter) { - if (pFirstFilter == NULL) { - pFirstFilter = pDestFilter; - } else { - pFirstFilter->SetDestFilter(pDestFilter); - } - } - } - } else { - if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) { - pParams = NULL; - } - pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(), (CPDF_Dictionary*)pParams, width, height); - } - return pFirstFilter; -} -CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const -{ - CFX_DataFilter* pFirstFilter = NULL; - if (m_pCryptoHandler) { - pFirstFilter = FX_NEW CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum); - } - if (!bRaw) { - CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict); - if (pFilter) { - if (pFirstFilter == NULL) { - pFirstFilter = pFilter; - } else { - pFirstFilter->SetDestFilter(pFilter); - } - } - } - CPDF_StreamFilter* pStreamFilter = FX_NEW CPDF_StreamFilter; - pStreamFilter->m_pStream = this; - pStreamFilter->m_pFilter = pFirstFilter; - pStreamFilter->m_pBuffer = NULL; - pStreamFilter->m_SrcOffset = 0; - return pStreamFilter; -} -CPDF_StreamFilter::~CPDF_StreamFilter() -{ - if (m_pFilter) { - delete m_pFilter; - } - if (m_pBuffer) { - delete m_pBuffer; - } -} -#define FPDF_FILTER_BUFFER_IN_SIZE FPDF_FILTER_BUFFER_SIZE -FX_DWORD CPDF_StreamFilter::ReadBlock(FX_LPBYTE buffer, FX_DWORD buf_size) -{ - if (m_pFilter == NULL) { - FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset; - if (read_size == 0) { - return 0; - } - if (read_size > buf_size) { - read_size = buf_size; - } - m_pStream->ReadRawData(m_SrcOffset, buffer, read_size); - m_SrcOffset += read_size; - return read_size; - } - FX_DWORD read_size = 0; - if (m_pBuffer) { - read_size = ReadLeftOver(buffer, buf_size); - if (read_size == buf_size) { - return read_size; - } - buffer += read_size; - buf_size -= read_size; - } - ASSERT(m_pBuffer == NULL); - if (m_pFilter->IsEOF()) { - return read_size; - } - m_pBuffer = FX_NEW CFX_BinaryBuf; - m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE); - m_BufOffset = 0; - while (1) { - int src_size = m_pStream->GetRawSize() - m_SrcOffset; - if (src_size == 0) { - m_pFilter->FilterFinish(*m_pBuffer); - break; - } - if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) { - src_size = FPDF_FILTER_BUFFER_IN_SIZE; - } - if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) { - return 0; - } - m_SrcOffset += src_size; - m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer); - if (m_pBuffer->GetSize() >= (int)buf_size) { - break; - } - } - return read_size + ReadLeftOver(buffer, buf_size); -} -FX_DWORD CPDF_StreamFilter::ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size) -{ - FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset; - if (read_size > buf_size) { - read_size = buf_size; - } - FXSYS_memcpy32(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size); - m_BufOffset += read_size; - if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) { - delete m_pBuffer; - m_pBuffer = NULL; - } - return read_size; -} -CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum) -{ - m_pCryptoHandler = pCryptoHandler; - m_pContext = NULL; - m_ObjNum = objnum; - m_GenNum = gennum; -} -CPDF_DecryptFilter::~CPDF_DecryptFilter() -{ - CFX_BinaryBuf buf; - if (m_pContext) { - m_pCryptoHandler->DecryptFinish(m_pContext, buf); - } -} -void CPDF_DecryptFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - if (m_pContext == NULL) { - m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum); - } - m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf); -} -void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf) -{ - m_bEOF = TRUE; - if (m_pContext == NULL) { - return; - } - m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf); - m_pContext = NULL; -} -extern "C" { - static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size) - { - return FX_Alloc(FX_BYTE, items * size); - } - static void my_free_func (void* opaque, void* address) - { - FX_Free(address); - } - void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int), - void (*free_func)(void*, void*)); - void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size); - int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size); - int FPDFAPI_FlateGetAvailIn(void* context); - int FPDFAPI_FlateGetAvailOut(void* context); - void FPDFAPI_FlateEnd(void* context); -} -CPDF_FlateFilter::CPDF_FlateFilter() -{ - m_pContext = NULL; -} -CPDF_FlateFilter::~CPDF_FlateFilter() -{ - if (m_pContext) { - FPDFAPI_FlateEnd(m_pContext); - } -} -void CPDF_FlateFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - if (m_pContext == NULL) { - m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func); - } - FPDFAPI_FlateInput(m_pContext, src_buf, src_size); - while (1) { - int ret = FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE); - int out_size = FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext); - dest_buf.AppendBlock(m_DestBuffer, out_size); - if (ret == Z_BUF_ERROR) { - break; - } - if (ret != Z_OK) { - ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext)); - break; - } - } -} -CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange) -{ - m_bEarlyChange = bEarlyChange ? 1 : 0; - m_CodeLen = 9; - m_nCodes = 0; - m_nLeftBits = 0; - m_LeftBits = 0; - m_OldCode = (FX_DWORD) - 1; -} -void CPDF_LzwFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - for (FX_DWORD i = 0; i < src_size; i ++) { - if (m_nLeftBits + 8 < m_CodeLen) { - m_nLeftBits += 8; - m_LeftBits = (m_LeftBits << 8) | src_buf[i]; - continue; - } - FX_DWORD new_bits = m_CodeLen - m_nLeftBits; - FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits)); - m_nLeftBits = 8 - new_bits; - m_LeftBits = src_buf[i] % (1 << m_nLeftBits); - if (code < 256) { - dest_buf.AppendByte((FX_BYTE)code); - m_LastChar = (FX_BYTE)code; - if (m_OldCode != -1) { - AddCode(m_OldCode, m_LastChar); - } - m_OldCode = code; - } else if (code == 256) { - m_CodeLen = 9; - m_nCodes = 0; - m_OldCode = (FX_DWORD) - 1; - } else if (code == 257) { - ReportEOF(src_size - i - 1); - return; - } else { - if (m_OldCode == -1) { - ReportEOF(src_size - i - 1); - return; - } - m_StackLen = 0; - if (code >= m_nCodes + 258) { - if (m_StackLen < sizeof(m_DecodeStack)) { - m_DecodeStack[m_StackLen++] = m_LastChar; - } - DecodeString(m_OldCode); - } else { - DecodeString(code); - } - dest_buf.AppendBlock(NULL, m_StackLen); - FX_LPBYTE pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen; - for (FX_DWORD cc = 0; cc < m_StackLen; cc ++) { - pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1]; - } - m_LastChar = m_DecodeStack[m_StackLen - 1]; - if (m_OldCode < 256) { - AddCode(m_OldCode, m_LastChar); - } else if (m_OldCode - 258 >= m_nCodes) { - ReportEOF(src_size - i - 1); - return; - } else { - AddCode(m_OldCode, m_LastChar); - } - m_OldCode = code; - } - } -} -void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, FX_BYTE append_char) -{ - if (m_nCodes + m_bEarlyChange == 4094) { - return; - } - m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char; - if (m_nCodes + m_bEarlyChange == 512 - 258) { - m_CodeLen = 10; - } else if (m_nCodes + m_bEarlyChange == 1024 - 258) { - m_CodeLen = 11; - } else if (m_nCodes + m_bEarlyChange == 2048 - 258) { - m_CodeLen = 12; - } -} -void CPDF_LzwFilter::DecodeString(FX_DWORD code) -{ - while (1) { - int index = code - 258; - if (index < 0 || index >= (int)m_nCodes) { - break; - } - FX_DWORD data = m_CodeArray[index]; - if (m_StackLen >= sizeof(m_DecodeStack)) { - return; - } - m_DecodeStack[m_StackLen++] = (FX_BYTE)data; - code = data >> 16; - } - if (m_StackLen >= sizeof(m_DecodeStack)) { - return; - } - m_DecodeStack[m_StackLen++] = (FX_BYTE)code; -} -CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols) -{ - m_bTiff = predictor < 10; - m_pRefLine = NULL; - m_pCurLine = NULL; - m_iLine = 0; - m_LineInSize = 0; - m_Bpp = (colors * bpc + 7) / 8; - m_Pitch = (colors * bpc * cols + 7) / 8; - if (!m_bTiff) { - m_Pitch ++; - } -} -CPDF_PredictorFilter::~CPDF_PredictorFilter() -{ - if (m_pCurLine) { - FX_Free(m_pCurLine); - } - if (m_pRefLine) { - FX_Free(m_pRefLine); - } -} -static FX_BYTE PaethPredictor(int a, int b, int c) -{ - int p = a + b - c; - int pa = FXSYS_abs(p - a); - int pb = FXSYS_abs(p - b); - int pc = FXSYS_abs(p - c); - if (pa <= pb && pa <= pc) { - return (FX_BYTE)a; - } - if (pb <= pc) { - return (FX_BYTE)b; - } - return (FX_BYTE)c; -} -static void PNG_PredictorLine(FX_LPBYTE cur_buf, FX_LPBYTE ref_buf, int pitch, int Bpp) -{ - FX_BYTE tag = cur_buf[0]; - if (tag == 0) { - return; - } - cur_buf ++; - if (ref_buf) { - ref_buf ++; - } - for (int byte = 0; byte < pitch; byte ++) { - FX_BYTE raw_byte = cur_buf[byte]; - switch (tag) { - case 1: { - FX_BYTE left = 0; - if (byte >= Bpp) { - left = cur_buf[byte - Bpp]; - } - cur_buf[byte] = raw_byte + left; - break; - } - case 2: { - FX_BYTE up = 0; - if (ref_buf) { - up = ref_buf[byte]; - } - cur_buf[byte] = raw_byte + up; - break; - } - case 3: { - FX_BYTE left = 0; - if (byte >= Bpp) { - left = cur_buf[byte - Bpp]; - } - FX_BYTE up = 0; - if (ref_buf) { - up = ref_buf[byte]; - } - cur_buf[byte] = raw_byte + (up + left) / 2; - break; - } - case 4: { - FX_BYTE left = 0; - if (byte >= Bpp) { - left = cur_buf[byte - Bpp]; - } - FX_BYTE up = 0; - if (ref_buf) { - up = ref_buf[byte]; - } - FX_BYTE upper_left = 0; - if (byte >= Bpp && ref_buf) { - upper_left = ref_buf[byte - Bpp]; - } - cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left); - break; - } - } - } -} -void CPDF_PredictorFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - if (m_pCurLine == NULL) { - m_pCurLine = FX_Alloc(FX_BYTE, m_Pitch); - if (!m_bTiff) { - m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch); - } - } - while (1) { - FX_DWORD read_size = m_Pitch - m_LineInSize; - if (read_size > src_size) { - read_size = src_size; - } - FXSYS_memcpy32(m_pCurLine + m_LineInSize, src_buf, read_size); - m_LineInSize += read_size; - if (m_LineInSize < m_Pitch) { - break; - } - src_buf += read_size; - src_size -= read_size; - if (m_bTiff) { - for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte ++) { - m_pCurLine[byte] += m_pCurLine[byte - m_Bpp]; - } - dest_buf.AppendBlock(m_pCurLine, m_Pitch); - } else { - PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1, m_Bpp); - dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1); - m_iLine ++; - FX_LPBYTE temp = m_pCurLine; - m_pCurLine = m_pRefLine; - m_pRefLine = temp; - } - m_LineInSize = 0; - } -} -CPDF_Ascii85Filter::CPDF_Ascii85Filter() -{ - m_State = 0; - m_CharCount = 0; -} -extern const FX_LPCSTR _PDF_CharType; -void CPDF_Ascii85Filter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - for (FX_DWORD i = 0; i < src_size; i ++) { - FX_BYTE byte = src_buf[i]; - if (_PDF_CharType[byte] == 'W') { - continue; - } - switch (m_State) { - case 0: - if (byte >= '!' && byte <= 'u') { - int digit = byte - '!'; - m_CurDWord = digit; - m_CharCount = 1; - m_State = 1; - } else if (byte == 'z') { - int zero = 0; - dest_buf.AppendBlock(&zero, 4); - } else if (byte == '~') { - m_State = 2; - } - break; - case 1: { - if (byte >= '!' && byte <= 'u') { - int digit = byte - '!'; - m_CurDWord = m_CurDWord * 85 + digit; - m_CharCount ++; - if (m_CharCount == 5) { - for (int i = 0; i < 4; i ++) { - dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8)); - } - m_State = 0; - } - } else if (byte == '~') { - if (m_CharCount > 1) { - int i; - for (i = m_CharCount; i < 5; i ++) { - m_CurDWord = m_CurDWord * 85 + 84; - } - for (i = 0; i < m_CharCount - 1; i ++) { - dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8)); - } - } - m_State = 2; - } - break; - } - case 2: - if (byte == '>') { - ReportEOF(src_size - i - 1); - return; - } - break; - } - } -} -CPDF_AsciiHexFilter::CPDF_AsciiHexFilter() -{ - m_State = 0; -} -void CPDF_AsciiHexFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - for (FX_DWORD i = 0; i < src_size; i ++) { - FX_BYTE byte = src_buf[i]; - if (_PDF_CharType[byte] == 'W') { - continue; - } - int digit; - if (byte >= '0' && byte <= '9') { - digit = byte - '0'; - } else if (byte >= 'a' && byte <= 'f') { - digit = byte - 'a' + 10; - } else if (byte >= 'A' && byte <= 'F') { - digit = byte - 'A' + 10; - } else { - if (m_State) { - dest_buf.AppendByte(m_FirstDigit * 16); - } - ReportEOF(src_size - i - 1); - return; - } - if (m_State == 0) { - m_FirstDigit = digit; - m_State ++; - } else { - dest_buf.AppendByte(m_FirstDigit * 16 + digit); - m_State --; - } - } -} -CPDF_RunLenFilter::CPDF_RunLenFilter() -{ - m_State = 0; - m_Count = 0; -} -void CPDF_RunLenFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - for (FX_DWORD i = 0; i < src_size; i ++) { - FX_BYTE byte = src_buf[i]; - switch (m_State) { - case 0: - if (byte < 128) { - m_State = 1; - m_Count = byte + 1; - } else if (byte == 128) { - ReportEOF(src_size - i - 1); - return; - } else { - m_State = 2; - m_Count = 257 - byte; - } - break; - case 1: - dest_buf.AppendByte(byte); - m_Count --; - if (m_Count == 0) { - m_State = 0; - } - break; - case 2: { - dest_buf.AppendBlock(NULL, m_Count); - FXSYS_memset8(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte, m_Count); - m_State = 0; - break; - } - } - } -} -CPDF_JpegFilter::CPDF_JpegFilter() -{ - m_pContext = NULL; - m_bGotHeader = FALSE; - m_pScanline = NULL; - m_iLine = 0; -} -CPDF_JpegFilter::~CPDF_JpegFilter() -{ - if (m_pScanline) { - FX_Free(m_pScanline); - } - if (m_pContext) { - CPDF_ModuleMgr::Get()->GetJpegModule()->Finish(m_pContext); - } -} -void CPDF_JpegFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - if (m_pContext == NULL) { - m_pContext = CPDF_ModuleMgr::Get()->GetJpegModule()->Start(); - } - FX_LPCBYTE jpeg_src_buf; - FX_DWORD jpeg_src_size; - CFX_BinaryBuf temp_buf; - if (m_InputBuf.GetSize()) { - temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size); - temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize()); - m_InputBuf.Clear(); - temp_buf.AppendBlock(src_buf, src_size); - jpeg_src_buf = temp_buf.GetBuffer(); - jpeg_src_size = temp_buf.GetSize(); - } else { - jpeg_src_buf = src_buf; - jpeg_src_size = src_size; - } - CPDF_ModuleMgr::Get()->GetJpegModule()->Input(m_pContext, jpeg_src_buf, jpeg_src_size); - if (!m_bGotHeader) { - int ret = CPDF_ModuleMgr::Get()->GetJpegModule()->ReadHeader(m_pContext, &m_Width, &m_Height, &m_nComps); - int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext); - if (ret == 1) { - ReportEOF(left_size); - return; - } - if (ret == 2) { - m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size); - return; - } - CPDF_ModuleMgr::Get()->GetJpegModule()->StartScanline(m_pContext, 1); - m_bGotHeader = TRUE; - m_Pitch = m_Width * m_nComps; - } - if (m_pScanline == NULL) { - m_pScanline = FX_Alloc(FX_BYTE, m_Pitch + 4); - } - while (1) { - if (!CPDF_ModuleMgr::Get()->GetJpegModule()->ReadScanline(m_pContext, m_pScanline)) { - int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext); - m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size); - break; - } - dest_buf.AppendBlock(m_pScanline, m_Pitch); - m_iLine ++; - if (m_iLine == m_Height) { - ReportEOF(CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext)); - return; - } - } -} -CPDF_FaxFilter::CPDF_FaxFilter() -{ - m_Encoding = 0; - m_bEndOfLine = FALSE; - m_bByteAlign = FALSE; - m_bBlack = FALSE; - m_nRows = 0; - m_nColumns = 0; - m_Pitch = 0; - m_pScanlineBuf = NULL; - m_pRefBuf = NULL; - m_iRow = 0; - m_InputBitPos = 0; -} -CPDF_FaxFilter::~CPDF_FaxFilter() -{ - if (m_pScanlineBuf) { - FX_Free(m_pScanlineBuf); - } - if (m_pRefBuf) { - FX_Free(m_pRefBuf); - } -} -FX_BOOL CPDF_FaxFilter::Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns) -{ - m_Encoding = Encoding; - m_bEndOfLine = bEndOfLine; - m_bByteAlign = bByteAlign; - m_bBlack = bBlack; - m_nRows = nRows; - m_nColumns = nColumns; - m_Pitch = (m_nColumns + 7) / 8; - m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch); - m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch); - FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch); - FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch); - m_iRow = 0; - m_InputBitPos = 0; - return TRUE; -} -void CPDF_FaxFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) -{ - FX_LPCBYTE fax_src_buf; - FX_DWORD fax_src_size; - CFX_BinaryBuf temp_buf; - int bitpos; - if (m_InputBuf.GetSize()) { - temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size); - temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize()); - m_InputBuf.Clear(); - temp_buf.AppendBlock(src_buf, src_size); - fax_src_buf = temp_buf.GetBuffer(); - fax_src_size = temp_buf.GetSize(); - bitpos = m_InputBitPos; - } else { - fax_src_buf = src_buf; - fax_src_size = src_size; - bitpos = 0; - } - ProcessData(fax_src_buf, fax_src_size, bitpos, FALSE, dest_buf); - int left_bits = fax_src_size * 8 - bitpos; - m_InputBuf.AppendBlock(fax_src_buf + bitpos / 8, (left_bits + 7) / 8); - m_InputBitPos = bitpos % 8; -} -void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf) -{ - ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE, dest_buf); -} -FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos); -FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns); -FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns); -void CPDF_FaxFilter::ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish, - CFX_BinaryBuf& dest_buf) -{ - int bitsize = src_size * 8; - while (1) { - if ((bitsize < bitpos + 256) && !bFinish) { - return; - } - int start_bitpos = bitpos; - FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch); - if (!ReadLine(src_buf, bitsize, bitpos)) { - bitpos = start_bitpos; - return; - } - if (m_Encoding) { - FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch); - } - if (m_bBlack) { - for (int i = 0; i < m_Pitch; i ++) { - m_pScanlineBuf[i] = ~m_pScanlineBuf[i]; - } - } - dest_buf.AppendBlock(m_pScanlineBuf, m_Pitch); - m_iRow ++; - if (m_iRow == m_nRows) { - ReportEOF(src_size - (bitpos + 7) / 8); - return; - } - } -} -FX_BOOL CPDF_FaxFilter::ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos) -{ - if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) { - return FALSE; - } - FX_BOOL ret; - if (m_Encoding < 0) { - ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns); - } else if (m_Encoding == 0) { - ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns); - } else { - if (bitpos == bitsize) { - return FALSE; - } - FX_BOOL bNext1D = src_buf[bitpos / 8] & (1 << (7 - bitpos % 8)); - bitpos ++; - if (bNext1D) { - ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns); - } else { - ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns); - } - } - if (!ret) { - return FALSE; - } - if (m_bEndOfLine) - if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) { - return FALSE; - } - if (m_bByteAlign) { - bitpos = (bitpos + 7) / 8 * 8; - } - return TRUE; -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../fx_zlib.h" +#include "../../../include/fpdfapi/fpdf_parser.h" +#include "../../../include/fxcodec/fx_codec.h" +#include "../../../include/fpdfapi/fpdf_module.h" +#include "filters_int.h" +CFX_DataFilter::CFX_DataFilter() +{ + m_bEOF = FALSE; + m_pDestFilter = NULL; + m_SrcPos = 0; +} +CFX_DataFilter::~CFX_DataFilter() +{ + if (m_pDestFilter) { + delete m_pDestFilter; + } +} +void CFX_DataFilter::SetDestFilter(CFX_DataFilter* pFilter) +{ + if (m_pDestFilter) { + m_pDestFilter->SetDestFilter(pFilter); + } else { + m_pDestFilter = pFilter; + } +} +void CFX_DataFilter::FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + if (m_bEOF) { + return; + } + m_SrcPos += src_size; + if (m_pDestFilter) { + CFX_BinaryBuf temp_buf; + temp_buf.EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE); + v_FilterIn(src_buf, src_size, temp_buf); + m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf); + } else { + v_FilterIn(src_buf, src_size, dest_buf); + } +} +void CFX_DataFilter::FilterFinish(CFX_BinaryBuf& dest_buf) +{ + if (m_pDestFilter) { + CFX_BinaryBuf temp_buf; + v_FilterFinish(temp_buf); + if (temp_buf.GetSize()) { + m_pDestFilter->FilterIn(temp_buf.GetBuffer(), temp_buf.GetSize(), dest_buf); + } + m_pDestFilter->FilterFinish(dest_buf); + } else { + v_FilterFinish(dest_buf); + } + m_bEOF = TRUE; +} +void CFX_DataFilter::ReportEOF(FX_DWORD left_input) +{ + if (m_bEOF) { + return; + } + m_bEOF = TRUE; + m_SrcPos -= left_input; +} +CFX_DataFilter* FPDF_CreateFilter(FX_BSTR name, const CPDF_Dictionary* pParam, int width, int height) +{ + FX_DWORD id = name.GetID(); + switch (id) { + case FXBSTR_ID('F', 'l', 'a', 't'): + case FXBSTR_ID('F', 'l', 0, 0): + case FXBSTR_ID('L', 'Z', 'W', 'D'): + case FXBSTR_ID('L', 'Z', 'W', 0): { + CFX_DataFilter* pFilter; + if (id == FXBSTR_ID('L', 'Z', 'W', 'D') || id == FXBSTR_ID('L', 'Z', 'W', 0)) { + pFilter = FX_NEW CPDF_LzwFilter(pParam->GetInteger("EarlyChange", 1)); + } else { + pFilter = FX_NEW CPDF_FlateFilter; + } + if (pParam->GetInteger("Predictor", 1) > 1) { + CFX_DataFilter* pPredictor = FX_NEW CPDF_PredictorFilter(pParam->GetInteger(FX_BSTRC("Predictor"), 1), + pParam->GetInteger(FX_BSTRC("Colors"), 1), pParam->GetInteger(FX_BSTRC("BitsPerComponent"), 8), + pParam->GetInteger(FX_BSTRC("Columns"), 1)); + pFilter->SetDestFilter(pPredictor); + } + return pFilter; + } + case FXBSTR_ID('A', 'S', 'C', 'I'): + if (name == "ASCIIHexDecode") { + return FX_NEW CPDF_AsciiHexFilter; + } + return FX_NEW CPDF_Ascii85Filter; + case FXBSTR_ID('A', 'H', 'x', 0): + return FX_NEW CPDF_AsciiHexFilter; + case FXBSTR_ID('A', '8', '5', 0): + return FX_NEW CPDF_Ascii85Filter; + case FXBSTR_ID('R', 'u', 'n', 'L'): + return FX_NEW CPDF_RunLenFilter; + case FXBSTR_ID('C', 'C', 'I', 'T'): { + int Encoding = 0; + int bEndOfLine = FALSE; + int bByteAlign = FALSE; + int bBlack = FALSE; + int nRows = 0; + int nColumns = 1728; + if (pParam) { + Encoding = pParam->GetInteger(FX_BSTRC("K")); + bEndOfLine = pParam->GetInteger(FX_BSTRC("EndOfLine")); + bByteAlign = pParam->GetInteger(FX_BSTRC("EncodedByteAlign")); + bBlack = pParam->GetInteger(FX_BSTRC("BlackIs1")); + nColumns = pParam->GetInteger(FX_BSTRC("Columns"), 1728); + nRows = pParam->GetInteger(FX_BSTRC("Rows")); + } + if (nColumns == 0) { + nColumns = width; + } + if (nRows == 0) { + nRows = height; + } + CPDF_FaxFilter* pFilter = FX_NEW CPDF_FaxFilter(); + pFilter->Initialize(Encoding, bEndOfLine, bByteAlign, bBlack, nRows, nColumns); + return pFilter; + } + case FXBSTR_ID('D', 'C', 'T', 'D'): + return FX_NEW CPDF_JpegFilter; + default: + return NULL; + } +} +CFX_DataFilter* _FPDF_CreateFilterFromDict(CPDF_Dictionary* pDict) +{ + CPDF_Object* pDecoder = pDict->GetElementValue("Filter"); + if (pDecoder == NULL) { + return NULL; + } + CFX_DataFilter* pFirstFilter = NULL; + int width = pDict->GetInteger(FX_BSTRC("Width")), height = pDict->GetInteger(FX_BSTRC("Height")); + CPDF_Object* pParams = pDict->GetElementValue("DecodeParms"); + if (pDecoder->GetType() == PDFOBJ_ARRAY) { + if (pParams && pParams->GetType() != PDFOBJ_ARRAY) { + pParams = NULL; + } + for (FX_DWORD i = 0; i < ((CPDF_Array*)pDecoder)->GetCount(); i ++) { + CFX_ByteString name = ((CPDF_Array*)pDecoder)->GetString(i); + CPDF_Dictionary* pParam = NULL; + if (pParams) { + pParam = ((CPDF_Array*)pParams)->GetDict(i); + } + CFX_DataFilter* pDestFilter = FPDF_CreateFilter(name, pParam, width, height); + if (pDestFilter) { + if (pFirstFilter == NULL) { + pFirstFilter = pDestFilter; + } else { + pFirstFilter->SetDestFilter(pDestFilter); + } + } + } + } else { + if (pParams && pParams->GetType() != PDFOBJ_DICTIONARY) { + pParams = NULL; + } + pFirstFilter = FPDF_CreateFilter(pDecoder->GetString(), (CPDF_Dictionary*)pParams, width, height); + } + return pFirstFilter; +} +CPDF_StreamFilter* CPDF_Stream::GetStreamFilter(FX_BOOL bRaw) const +{ + CFX_DataFilter* pFirstFilter = NULL; + if (m_pCryptoHandler) { + pFirstFilter = FX_NEW CPDF_DecryptFilter(m_pCryptoHandler, m_ObjNum, m_GenNum); + } + if (!bRaw) { + CFX_DataFilter* pFilter = _FPDF_CreateFilterFromDict(m_pDict); + if (pFilter) { + if (pFirstFilter == NULL) { + pFirstFilter = pFilter; + } else { + pFirstFilter->SetDestFilter(pFilter); + } + } + } + CPDF_StreamFilter* pStreamFilter = FX_NEW CPDF_StreamFilter; + pStreamFilter->m_pStream = this; + pStreamFilter->m_pFilter = pFirstFilter; + pStreamFilter->m_pBuffer = NULL; + pStreamFilter->m_SrcOffset = 0; + return pStreamFilter; +} +CPDF_StreamFilter::~CPDF_StreamFilter() +{ + if (m_pFilter) { + delete m_pFilter; + } + if (m_pBuffer) { + delete m_pBuffer; + } +} +#define FPDF_FILTER_BUFFER_IN_SIZE FPDF_FILTER_BUFFER_SIZE +FX_DWORD CPDF_StreamFilter::ReadBlock(FX_LPBYTE buffer, FX_DWORD buf_size) +{ + if (m_pFilter == NULL) { + FX_DWORD read_size = m_pStream->GetRawSize() - m_SrcOffset; + if (read_size == 0) { + return 0; + } + if (read_size > buf_size) { + read_size = buf_size; + } + m_pStream->ReadRawData(m_SrcOffset, buffer, read_size); + m_SrcOffset += read_size; + return read_size; + } + FX_DWORD read_size = 0; + if (m_pBuffer) { + read_size = ReadLeftOver(buffer, buf_size); + if (read_size == buf_size) { + return read_size; + } + buffer += read_size; + buf_size -= read_size; + } + ASSERT(m_pBuffer == NULL); + if (m_pFilter->IsEOF()) { + return read_size; + } + m_pBuffer = FX_NEW CFX_BinaryBuf; + m_pBuffer->EstimateSize(FPDF_FILTER_BUFFER_SIZE, FPDF_FILTER_BUFFER_SIZE); + m_BufOffset = 0; + while (1) { + int src_size = m_pStream->GetRawSize() - m_SrcOffset; + if (src_size == 0) { + m_pFilter->FilterFinish(*m_pBuffer); + break; + } + if (src_size > FPDF_FILTER_BUFFER_IN_SIZE) { + src_size = FPDF_FILTER_BUFFER_IN_SIZE; + } + if (!m_pStream->ReadRawData(m_SrcOffset, m_SrcBuffer, src_size)) { + return 0; + } + m_SrcOffset += src_size; + m_pFilter->FilterIn(m_SrcBuffer, src_size, *m_pBuffer); + if (m_pBuffer->GetSize() >= (int)buf_size) { + break; + } + } + return read_size + ReadLeftOver(buffer, buf_size); +} +FX_DWORD CPDF_StreamFilter::ReadLeftOver(FX_LPBYTE buffer, FX_DWORD buf_size) +{ + FX_DWORD read_size = m_pBuffer->GetSize() - m_BufOffset; + if (read_size > buf_size) { + read_size = buf_size; + } + FXSYS_memcpy32(buffer, m_pBuffer->GetBuffer() + m_BufOffset, read_size); + m_BufOffset += read_size; + if (m_BufOffset == (FX_DWORD)m_pBuffer->GetSize()) { + delete m_pBuffer; + m_pBuffer = NULL; + } + return read_size; +} +CPDF_DecryptFilter::CPDF_DecryptFilter(CPDF_CryptoHandler* pCryptoHandler, FX_DWORD objnum, FX_DWORD gennum) +{ + m_pCryptoHandler = pCryptoHandler; + m_pContext = NULL; + m_ObjNum = objnum; + m_GenNum = gennum; +} +CPDF_DecryptFilter::~CPDF_DecryptFilter() +{ + CFX_BinaryBuf buf; + if (m_pContext) { + m_pCryptoHandler->DecryptFinish(m_pContext, buf); + } +} +void CPDF_DecryptFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + if (m_pContext == NULL) { + m_pContext = m_pCryptoHandler->DecryptStart(m_ObjNum, m_GenNum); + } + m_pCryptoHandler->DecryptStream(m_pContext, src_buf, src_size, dest_buf); +} +void CPDF_DecryptFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf) +{ + m_bEOF = TRUE; + if (m_pContext == NULL) { + return; + } + m_pCryptoHandler->DecryptFinish(m_pContext, dest_buf); + m_pContext = NULL; +} +extern "C" { + static void* my_alloc_func (void* opaque, unsigned int items, unsigned int size) + { + return FX_Alloc(FX_BYTE, items * size); + } + static void my_free_func (void* opaque, void* address) + { + FX_Free(address); + } + void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int), + void (*free_func)(void*, void*)); + void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigned int src_size); + int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int dest_size); + int FPDFAPI_FlateGetAvailIn(void* context); + int FPDFAPI_FlateGetAvailOut(void* context); + void FPDFAPI_FlateEnd(void* context); +} +CPDF_FlateFilter::CPDF_FlateFilter() +{ + m_pContext = NULL; +} +CPDF_FlateFilter::~CPDF_FlateFilter() +{ + if (m_pContext) { + FPDFAPI_FlateEnd(m_pContext); + } +} +void CPDF_FlateFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + if (m_pContext == NULL) { + m_pContext = FPDFAPI_FlateInit(my_alloc_func, my_free_func); + } + FPDFAPI_FlateInput(m_pContext, src_buf, src_size); + while (1) { + int ret = FPDFAPI_FlateOutput(m_pContext, m_DestBuffer, FPDF_FILTER_BUFFER_SIZE); + int out_size = FPDF_FILTER_BUFFER_SIZE - FPDFAPI_FlateGetAvailOut(m_pContext); + dest_buf.AppendBlock(m_DestBuffer, out_size); + if (ret == Z_BUF_ERROR) { + break; + } + if (ret != Z_OK) { + ReportEOF(FPDFAPI_FlateGetAvailIn(m_pContext)); + break; + } + } +} +CPDF_LzwFilter::CPDF_LzwFilter(FX_BOOL bEarlyChange) +{ + m_bEarlyChange = bEarlyChange ? 1 : 0; + m_CodeLen = 9; + m_nCodes = 0; + m_nLeftBits = 0; + m_LeftBits = 0; + m_OldCode = (FX_DWORD) - 1; +} +void CPDF_LzwFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + for (FX_DWORD i = 0; i < src_size; i ++) { + if (m_nLeftBits + 8 < m_CodeLen) { + m_nLeftBits += 8; + m_LeftBits = (m_LeftBits << 8) | src_buf[i]; + continue; + } + FX_DWORD new_bits = m_CodeLen - m_nLeftBits; + FX_DWORD code = (m_LeftBits << new_bits) | (src_buf[i] >> (8 - new_bits)); + m_nLeftBits = 8 - new_bits; + m_LeftBits = src_buf[i] % (1 << m_nLeftBits); + if (code < 256) { + dest_buf.AppendByte((FX_BYTE)code); + m_LastChar = (FX_BYTE)code; + if (m_OldCode != -1) { + AddCode(m_OldCode, m_LastChar); + } + m_OldCode = code; + } else if (code == 256) { + m_CodeLen = 9; + m_nCodes = 0; + m_OldCode = (FX_DWORD) - 1; + } else if (code == 257) { + ReportEOF(src_size - i - 1); + return; + } else { + if (m_OldCode == -1) { + ReportEOF(src_size - i - 1); + return; + } + m_StackLen = 0; + if (code >= m_nCodes + 258) { + if (m_StackLen < sizeof(m_DecodeStack)) { + m_DecodeStack[m_StackLen++] = m_LastChar; + } + DecodeString(m_OldCode); + } else { + DecodeString(code); + } + dest_buf.AppendBlock(NULL, m_StackLen); + FX_LPBYTE pOutput = dest_buf.GetBuffer() + dest_buf.GetSize() - m_StackLen; + for (FX_DWORD cc = 0; cc < m_StackLen; cc ++) { + pOutput[cc] = m_DecodeStack[m_StackLen - cc - 1]; + } + m_LastChar = m_DecodeStack[m_StackLen - 1]; + if (m_OldCode < 256) { + AddCode(m_OldCode, m_LastChar); + } else if (m_OldCode - 258 >= m_nCodes) { + ReportEOF(src_size - i - 1); + return; + } else { + AddCode(m_OldCode, m_LastChar); + } + m_OldCode = code; + } + } +} +void CPDF_LzwFilter::AddCode(FX_DWORD prefix_code, FX_BYTE append_char) +{ + if (m_nCodes + m_bEarlyChange == 4094) { + return; + } + m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char; + if (m_nCodes + m_bEarlyChange == 512 - 258) { + m_CodeLen = 10; + } else if (m_nCodes + m_bEarlyChange == 1024 - 258) { + m_CodeLen = 11; + } else if (m_nCodes + m_bEarlyChange == 2048 - 258) { + m_CodeLen = 12; + } +} +void CPDF_LzwFilter::DecodeString(FX_DWORD code) +{ + while (1) { + int index = code - 258; + if (index < 0 || index >= (int)m_nCodes) { + break; + } + FX_DWORD data = m_CodeArray[index]; + if (m_StackLen >= sizeof(m_DecodeStack)) { + return; + } + m_DecodeStack[m_StackLen++] = (FX_BYTE)data; + code = data >> 16; + } + if (m_StackLen >= sizeof(m_DecodeStack)) { + return; + } + m_DecodeStack[m_StackLen++] = (FX_BYTE)code; +} +CPDF_PredictorFilter::CPDF_PredictorFilter(int predictor, int colors, int bpc, int cols) +{ + m_bTiff = predictor < 10; + m_pRefLine = NULL; + m_pCurLine = NULL; + m_iLine = 0; + m_LineInSize = 0; + m_Bpp = (colors * bpc + 7) / 8; + m_Pitch = (colors * bpc * cols + 7) / 8; + if (!m_bTiff) { + m_Pitch ++; + } +} +CPDF_PredictorFilter::~CPDF_PredictorFilter() +{ + if (m_pCurLine) { + FX_Free(m_pCurLine); + } + if (m_pRefLine) { + FX_Free(m_pRefLine); + } +} +static FX_BYTE PaethPredictor(int a, int b, int c) +{ + int p = a + b - c; + int pa = FXSYS_abs(p - a); + int pb = FXSYS_abs(p - b); + int pc = FXSYS_abs(p - c); + if (pa <= pb && pa <= pc) { + return (FX_BYTE)a; + } + if (pb <= pc) { + return (FX_BYTE)b; + } + return (FX_BYTE)c; +} +static void PNG_PredictorLine(FX_LPBYTE cur_buf, FX_LPBYTE ref_buf, int pitch, int Bpp) +{ + FX_BYTE tag = cur_buf[0]; + if (tag == 0) { + return; + } + cur_buf ++; + if (ref_buf) { + ref_buf ++; + } + for (int byte = 0; byte < pitch; byte ++) { + FX_BYTE raw_byte = cur_buf[byte]; + switch (tag) { + case 1: { + FX_BYTE left = 0; + if (byte >= Bpp) { + left = cur_buf[byte - Bpp]; + } + cur_buf[byte] = raw_byte + left; + break; + } + case 2: { + FX_BYTE up = 0; + if (ref_buf) { + up = ref_buf[byte]; + } + cur_buf[byte] = raw_byte + up; + break; + } + case 3: { + FX_BYTE left = 0; + if (byte >= Bpp) { + left = cur_buf[byte - Bpp]; + } + FX_BYTE up = 0; + if (ref_buf) { + up = ref_buf[byte]; + } + cur_buf[byte] = raw_byte + (up + left) / 2; + break; + } + case 4: { + FX_BYTE left = 0; + if (byte >= Bpp) { + left = cur_buf[byte - Bpp]; + } + FX_BYTE up = 0; + if (ref_buf) { + up = ref_buf[byte]; + } + FX_BYTE upper_left = 0; + if (byte >= Bpp && ref_buf) { + upper_left = ref_buf[byte - Bpp]; + } + cur_buf[byte] = raw_byte + PaethPredictor(left, up, upper_left); + break; + } + } + } +} +void CPDF_PredictorFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + if (m_pCurLine == NULL) { + m_pCurLine = FX_Alloc(FX_BYTE, m_Pitch); + if (!m_bTiff) { + m_pRefLine = FX_Alloc(FX_BYTE, m_Pitch); + } + } + while (1) { + FX_DWORD read_size = m_Pitch - m_LineInSize; + if (read_size > src_size) { + read_size = src_size; + } + FXSYS_memcpy32(m_pCurLine + m_LineInSize, src_buf, read_size); + m_LineInSize += read_size; + if (m_LineInSize < m_Pitch) { + break; + } + src_buf += read_size; + src_size -= read_size; + if (m_bTiff) { + for (FX_DWORD byte = m_Bpp; byte < m_Pitch; byte ++) { + m_pCurLine[byte] += m_pCurLine[byte - m_Bpp]; + } + dest_buf.AppendBlock(m_pCurLine, m_Pitch); + } else { + PNG_PredictorLine(m_pCurLine, m_iLine ? m_pRefLine : NULL, m_Pitch - 1, m_Bpp); + dest_buf.AppendBlock(m_pCurLine + 1, m_Pitch - 1); + m_iLine ++; + FX_LPBYTE temp = m_pCurLine; + m_pCurLine = m_pRefLine; + m_pRefLine = temp; + } + m_LineInSize = 0; + } +} +CPDF_Ascii85Filter::CPDF_Ascii85Filter() +{ + m_State = 0; + m_CharCount = 0; +} +extern const FX_LPCSTR _PDF_CharType; +void CPDF_Ascii85Filter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + for (FX_DWORD i = 0; i < src_size; i ++) { + FX_BYTE byte = src_buf[i]; + if (_PDF_CharType[byte] == 'W') { + continue; + } + switch (m_State) { + case 0: + if (byte >= '!' && byte <= 'u') { + int digit = byte - '!'; + m_CurDWord = digit; + m_CharCount = 1; + m_State = 1; + } else if (byte == 'z') { + int zero = 0; + dest_buf.AppendBlock(&zero, 4); + } else if (byte == '~') { + m_State = 2; + } + break; + case 1: { + if (byte >= '!' && byte <= 'u') { + int digit = byte - '!'; + m_CurDWord = m_CurDWord * 85 + digit; + m_CharCount ++; + if (m_CharCount == 5) { + for (int i = 0; i < 4; i ++) { + dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8)); + } + m_State = 0; + } + } else if (byte == '~') { + if (m_CharCount > 1) { + int i; + for (i = m_CharCount; i < 5; i ++) { + m_CurDWord = m_CurDWord * 85 + 84; + } + for (i = 0; i < m_CharCount - 1; i ++) { + dest_buf.AppendByte((FX_BYTE)(m_CurDWord >> (3 - i) * 8)); + } + } + m_State = 2; + } + break; + } + case 2: + if (byte == '>') { + ReportEOF(src_size - i - 1); + return; + } + break; + } + } +} +CPDF_AsciiHexFilter::CPDF_AsciiHexFilter() +{ + m_State = 0; +} +void CPDF_AsciiHexFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + for (FX_DWORD i = 0; i < src_size; i ++) { + FX_BYTE byte = src_buf[i]; + if (_PDF_CharType[byte] == 'W') { + continue; + } + int digit; + if (byte >= '0' && byte <= '9') { + digit = byte - '0'; + } else if (byte >= 'a' && byte <= 'f') { + digit = byte - 'a' + 10; + } else if (byte >= 'A' && byte <= 'F') { + digit = byte - 'A' + 10; + } else { + if (m_State) { + dest_buf.AppendByte(m_FirstDigit * 16); + } + ReportEOF(src_size - i - 1); + return; + } + if (m_State == 0) { + m_FirstDigit = digit; + m_State ++; + } else { + dest_buf.AppendByte(m_FirstDigit * 16 + digit); + m_State --; + } + } +} +CPDF_RunLenFilter::CPDF_RunLenFilter() +{ + m_State = 0; + m_Count = 0; +} +void CPDF_RunLenFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + for (FX_DWORD i = 0; i < src_size; i ++) { + FX_BYTE byte = src_buf[i]; + switch (m_State) { + case 0: + if (byte < 128) { + m_State = 1; + m_Count = byte + 1; + } else if (byte == 128) { + ReportEOF(src_size - i - 1); + return; + } else { + m_State = 2; + m_Count = 257 - byte; + } + break; + case 1: + dest_buf.AppendByte(byte); + m_Count --; + if (m_Count == 0) { + m_State = 0; + } + break; + case 2: { + dest_buf.AppendBlock(NULL, m_Count); + FXSYS_memset8(dest_buf.GetBuffer() + dest_buf.GetSize() - m_Count, byte, m_Count); + m_State = 0; + break; + } + } + } +} +CPDF_JpegFilter::CPDF_JpegFilter() +{ + m_pContext = NULL; + m_bGotHeader = FALSE; + m_pScanline = NULL; + m_iLine = 0; +} +CPDF_JpegFilter::~CPDF_JpegFilter() +{ + if (m_pScanline) { + FX_Free(m_pScanline); + } + if (m_pContext) { + CPDF_ModuleMgr::Get()->GetJpegModule()->Finish(m_pContext); + } +} +void CPDF_JpegFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + if (m_pContext == NULL) { + m_pContext = CPDF_ModuleMgr::Get()->GetJpegModule()->Start(); + } + FX_LPCBYTE jpeg_src_buf; + FX_DWORD jpeg_src_size; + CFX_BinaryBuf temp_buf; + if (m_InputBuf.GetSize()) { + temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size); + temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize()); + m_InputBuf.Clear(); + temp_buf.AppendBlock(src_buf, src_size); + jpeg_src_buf = temp_buf.GetBuffer(); + jpeg_src_size = temp_buf.GetSize(); + } else { + jpeg_src_buf = src_buf; + jpeg_src_size = src_size; + } + CPDF_ModuleMgr::Get()->GetJpegModule()->Input(m_pContext, jpeg_src_buf, jpeg_src_size); + if (!m_bGotHeader) { + int ret = CPDF_ModuleMgr::Get()->GetJpegModule()->ReadHeader(m_pContext, &m_Width, &m_Height, &m_nComps); + int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext); + if (ret == 1) { + ReportEOF(left_size); + return; + } + if (ret == 2) { + m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size); + return; + } + CPDF_ModuleMgr::Get()->GetJpegModule()->StartScanline(m_pContext, 1); + m_bGotHeader = TRUE; + m_Pitch = m_Width * m_nComps; + } + if (m_pScanline == NULL) { + m_pScanline = FX_Alloc(FX_BYTE, m_Pitch + 4); + } + while (1) { + if (!CPDF_ModuleMgr::Get()->GetJpegModule()->ReadScanline(m_pContext, m_pScanline)) { + int left_size = CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext); + m_InputBuf.AppendBlock(jpeg_src_buf + jpeg_src_size - left_size, left_size); + break; + } + dest_buf.AppendBlock(m_pScanline, m_Pitch); + m_iLine ++; + if (m_iLine == m_Height) { + ReportEOF(CPDF_ModuleMgr::Get()->GetJpegModule()->GetAvailInput(m_pContext)); + return; + } + } +} +CPDF_FaxFilter::CPDF_FaxFilter() +{ + m_Encoding = 0; + m_bEndOfLine = FALSE; + m_bByteAlign = FALSE; + m_bBlack = FALSE; + m_nRows = 0; + m_nColumns = 0; + m_Pitch = 0; + m_pScanlineBuf = NULL; + m_pRefBuf = NULL; + m_iRow = 0; + m_InputBitPos = 0; +} +CPDF_FaxFilter::~CPDF_FaxFilter() +{ + if (m_pScanlineBuf) { + FX_Free(m_pScanlineBuf); + } + if (m_pRefBuf) { + FX_Free(m_pRefBuf); + } +} +FX_BOOL CPDF_FaxFilter::Initialize(int Encoding, int bEndOfLine, int bByteAlign, int bBlack, int nRows, int nColumns) +{ + m_Encoding = Encoding; + m_bEndOfLine = bEndOfLine; + m_bByteAlign = bByteAlign; + m_bBlack = bBlack; + m_nRows = nRows; + m_nColumns = nColumns; + m_Pitch = (m_nColumns + 7) / 8; + m_pScanlineBuf = FX_Alloc(FX_BYTE, m_Pitch); + m_pRefBuf = FX_Alloc(FX_BYTE, m_Pitch); + FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch); + FXSYS_memset8(m_pRefBuf, 0xff, m_Pitch); + m_iRow = 0; + m_InputBitPos = 0; + return TRUE; +} +void CPDF_FaxFilter::v_FilterIn(FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_BinaryBuf& dest_buf) +{ + FX_LPCBYTE fax_src_buf; + FX_DWORD fax_src_size; + CFX_BinaryBuf temp_buf; + int bitpos; + if (m_InputBuf.GetSize()) { + temp_buf.EstimateSize(m_InputBuf.GetSize() + src_size); + temp_buf.AppendBlock(m_InputBuf.GetBuffer(), m_InputBuf.GetSize()); + m_InputBuf.Clear(); + temp_buf.AppendBlock(src_buf, src_size); + fax_src_buf = temp_buf.GetBuffer(); + fax_src_size = temp_buf.GetSize(); + bitpos = m_InputBitPos; + } else { + fax_src_buf = src_buf; + fax_src_size = src_size; + bitpos = 0; + } + ProcessData(fax_src_buf, fax_src_size, bitpos, FALSE, dest_buf); + int left_bits = fax_src_size * 8 - bitpos; + m_InputBuf.AppendBlock(fax_src_buf + bitpos / 8, (left_bits + 7) / 8); + m_InputBitPos = bitpos % 8; +} +void CPDF_FaxFilter::v_FilterFinish(CFX_BinaryBuf& dest_buf) +{ + ProcessData(m_InputBuf.GetBuffer(), m_InputBuf.GetSize(), m_InputBitPos, TRUE, dest_buf); +} +FX_BOOL _FaxSkipEOL(const FX_BYTE* src_buf, int bitsize, int& bitpos); +FX_BOOL _FaxG4GetRow(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, const FX_BYTE* ref_buf, int columns); +FX_BOOL _FaxGet1DLine(const FX_BYTE* src_buf, int bitsize, int& bitpos, FX_LPBYTE dest_buf, int columns); +void CPDF_FaxFilter::ProcessData(FX_LPCBYTE src_buf, FX_DWORD src_size, int& bitpos, FX_BOOL bFinish, + CFX_BinaryBuf& dest_buf) +{ + int bitsize = src_size * 8; + while (1) { + if ((bitsize < bitpos + 256) && !bFinish) { + return; + } + int start_bitpos = bitpos; + FXSYS_memset8(m_pScanlineBuf, 0xff, m_Pitch); + if (!ReadLine(src_buf, bitsize, bitpos)) { + bitpos = start_bitpos; + return; + } + if (m_Encoding) { + FXSYS_memcpy32(m_pRefBuf, m_pScanlineBuf, m_Pitch); + } + if (m_bBlack) { + for (int i = 0; i < m_Pitch; i ++) { + m_pScanlineBuf[i] = ~m_pScanlineBuf[i]; + } + } + dest_buf.AppendBlock(m_pScanlineBuf, m_Pitch); + m_iRow ++; + if (m_iRow == m_nRows) { + ReportEOF(src_size - (bitpos + 7) / 8); + return; + } + } +} +FX_BOOL CPDF_FaxFilter::ReadLine(FX_LPCBYTE src_buf, int bitsize, int& bitpos) +{ + if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) { + return FALSE; + } + FX_BOOL ret; + if (m_Encoding < 0) { + ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns); + } else if (m_Encoding == 0) { + ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns); + } else { + if (bitpos == bitsize) { + return FALSE; + } + FX_BOOL bNext1D = src_buf[bitpos / 8] & (1 << (7 - bitpos % 8)); + bitpos ++; + if (bNext1D) { + ret = _FaxGet1DLine(src_buf, bitsize, bitpos, m_pScanlineBuf, m_nColumns); + } else { + ret = _FaxG4GetRow(src_buf, bitsize, bitpos, m_pScanlineBuf, m_pRefBuf, m_nColumns); + } + } + if (!ret) { + return FALSE; + } + if (m_bEndOfLine) + if (!_FaxSkipEOL(src_buf, bitsize, bitpos)) { + return FALSE; + } + if (m_bByteAlign) { + bitpos = (bitpos + 7) / 8 * 8; + } + return TRUE; +} diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp index 53cf892d7e..bd8b157bfa 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_objects.cpp @@ -1,1344 +1,1344 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fpdfapi/fpdf_parser.h" -void CPDF_Object::Release() -{ - if (this == NULL) { - return; - } - if (m_ObjNum) { - return; - } - Destroy(); -} -void CPDF_Object::Destroy() -{ - switch (m_Type) { - case PDFOBJ_STRING: - delete (CPDF_String*)this; - break; - case PDFOBJ_NAME: - delete (CPDF_Name*)this; - break; - case PDFOBJ_ARRAY: - delete (CPDF_Array*)this; - break; - case PDFOBJ_DICTIONARY: - delete (CPDF_Dictionary*)this; - break; - case PDFOBJ_STREAM: - delete (CPDF_Stream*)this; - break; - default: - delete this; - } -} -CFX_ByteString CPDF_Object::GetString() const -{ - if (this == NULL) { - return CFX_ByteString(); - } - switch (m_Type) { - case PDFOBJ_BOOLEAN: - return ((CPDF_Boolean*)this)->m_bValue ? "true" : "false"; - case PDFOBJ_NUMBER: - return ((CPDF_Number*)this)->GetString(); - case PDFOBJ_STRING: - return ((CPDF_String*)this)->m_String; - case PDFOBJ_NAME: - return ((CPDF_Name*)this)->m_Name; - case PDFOBJ_REFERENCE: { - CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; - if (pRef->m_pObjList == NULL) { - break; - } - CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); - if (pObj == NULL) { - return CFX_ByteString(); - } - return pObj->GetString(); - } - } - return CFX_ByteString(); -} -CFX_ByteStringC CPDF_Object::GetConstString() const -{ - if (this == NULL) { - return CFX_ByteStringC(); - } - switch (m_Type) { - case PDFOBJ_STRING: - return CFX_ByteStringC((FX_LPCBYTE)((CPDF_String*)this)->m_String, ((CPDF_String*)this)->m_String.GetLength()); - case PDFOBJ_NAME: - return CFX_ByteStringC((FX_LPCBYTE)((CPDF_Name*)this)->m_Name, ((CPDF_Name*)this)->m_Name.GetLength()); - case PDFOBJ_REFERENCE: { - CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; - if (pRef->m_pObjList == NULL) { - break; - } - CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); - if (pObj == NULL) { - return CFX_ByteStringC(); - } - return pObj->GetConstString(); - } - } - return CFX_ByteStringC(); -} -FX_FLOAT CPDF_Object::GetNumber() const -{ - if (this == NULL) { - return 0; - } - switch (m_Type) { - case PDFOBJ_NUMBER: - return ((CPDF_Number*)this)->GetNumber(); - case PDFOBJ_REFERENCE: { - CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; - if (pRef->m_pObjList == NULL) { - break; - } - CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); - if (pObj == NULL) { - return 0; - } - return pObj->GetNumber(); - } - } - return 0; -} -FX_FLOAT CPDF_Object::GetNumber16() const -{ - return GetNumber(); -} -int CPDF_Object::GetInteger() const -{ - if (this == NULL) { - return 0; - } - switch (m_Type) { - case PDFOBJ_BOOLEAN: - return ((CPDF_Boolean*)this)->m_bValue; - case PDFOBJ_NUMBER: - return ((CPDF_Number*)this)->GetInteger(); - case PDFOBJ_REFERENCE: { - CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; - PARSE_CONTEXT context; - FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT)); - if (pRef->m_pObjList == NULL) { - return 0; - } - CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum, &context); - if (pObj == NULL) { - return 0; - } - return pObj->GetInteger(); - } - } - return 0; -} -CPDF_Dictionary* CPDF_Object::GetDict() const -{ - if (this == NULL) { - return NULL; - } - switch (m_Type) { - case PDFOBJ_DICTIONARY: - return (CPDF_Dictionary*)this; - case PDFOBJ_STREAM: - return ((CPDF_Stream*)this)->GetDict(); - case PDFOBJ_REFERENCE: { - CPDF_Reference* pRef = (CPDF_Reference*)this; - if (pRef->m_pObjList == NULL) { - break; - } - CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); - if (pObj == NULL) { - return NULL; - } - return pObj->GetDict(); - } - } - return NULL; -} -CPDF_Array* CPDF_Object::GetArray() const -{ - if (this == NULL) { - return NULL; - } - if (m_Type == PDFOBJ_ARRAY) { - return (CPDF_Array*)this; - } - return NULL; -} -void CPDF_Object::SetString(const CFX_ByteString& str) -{ - ASSERT(this != NULL); - switch (m_Type) { - case PDFOBJ_BOOLEAN: - ((CPDF_Boolean*)this)->m_bValue = str == FX_BSTRC("true") ? 1 : 0; - return; - case PDFOBJ_NUMBER: - ((CPDF_Number*)this)->SetString(str); - return; - case PDFOBJ_STRING: - ((CPDF_String*)this)->m_String = str; - return; - case PDFOBJ_NAME: - ((CPDF_Name*)this)->m_Name = str; - return; - } - ASSERT(FALSE); -} -int CPDF_Object::GetDirectType() const -{ - if (m_Type != PDFOBJ_REFERENCE) { - return m_Type; - } - CPDF_Reference* pRef = (CPDF_Reference*)this; - return pRef->m_pObjList->GetIndirectType(pRef->m_RefObjNum); -} -FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const -{ - if (this == pOther) { - return TRUE; - } - if (this == NULL || pOther == NULL) { - return FALSE; - } - if (pOther->m_Type != m_Type) { - if (m_Type == PDFOBJ_REFERENCE) { - return GetDirect()->IsIdentical(pOther); - } else if (pOther->m_Type == PDFOBJ_REFERENCE) { - return IsIdentical(pOther->GetDirect()); - } - return FALSE; - } - switch (m_Type) { - case PDFOBJ_BOOLEAN: - return (((CPDF_Boolean*)this)->Identical((CPDF_Boolean*)pOther)); - case PDFOBJ_NUMBER: - return (((CPDF_Number*)this)->Identical((CPDF_Number*)pOther)); - case PDFOBJ_STRING: - return (((CPDF_String*)this)->Identical((CPDF_String*)pOther)); - case PDFOBJ_NAME: - return (((CPDF_Name*)this)->Identical((CPDF_Name*)pOther)); - case PDFOBJ_ARRAY: - return (((CPDF_Array*)this)->Identical((CPDF_Array*)pOther)); - case PDFOBJ_DICTIONARY: - return (((CPDF_Dictionary*)this)->Identical((CPDF_Dictionary*)pOther)); - case PDFOBJ_NULL: - return TRUE; - case PDFOBJ_STREAM: - return (((CPDF_Stream*)this)->Identical((CPDF_Stream*)pOther)); - case PDFOBJ_REFERENCE: - return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther)); - } - return FALSE; -} -CPDF_Object* CPDF_Object::GetDirect() const -{ - if (this == NULL) { - return NULL; - } - if (m_Type != PDFOBJ_REFERENCE) { - return (CPDF_Object*)this; - } - CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; - if (pRef->m_pObjList == NULL) { - return NULL; - } - return pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); -} -CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const -{ - CFX_MapPtrToPtr visited; - return CloneInternal(bDirect, &visited); -} -CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const -{ - if (this == NULL) { - return NULL; - } - switch (m_Type) { - case PDFOBJ_BOOLEAN: - return FX_NEW CPDF_Boolean(((CPDF_Boolean*)this)->m_bValue); - case PDFOBJ_NUMBER: - return FX_NEW CPDF_Number(((CPDF_Number*)this)->m_bInteger, &((CPDF_Number*)this)->m_Integer); - case PDFOBJ_STRING: - return FX_NEW CPDF_String(((CPDF_String*)this)->m_String, ((CPDF_String*)this)->IsHex()); - case PDFOBJ_NAME: - return FX_NEW CPDF_Name(((CPDF_Name*)this)->m_Name); - case PDFOBJ_ARRAY: { - CPDF_Array* pCopy = FX_NEW CPDF_Array(); - CPDF_Array* pThis = (CPDF_Array*)this; - int n = pThis->GetCount(); - for (int i = 0; i < n; i ++) { - CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i); - pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited)); - } - return pCopy; - } - case PDFOBJ_DICTIONARY: { - CPDF_Dictionary* pCopy = FX_NEW CPDF_Dictionary(); - CPDF_Dictionary* pThis = (CPDF_Dictionary*)this; - FX_POSITION pos = pThis->m_Map.GetStartPosition(); - while (pos) { - CFX_ByteString key; - CPDF_Object* value; - pThis->m_Map.GetNextAssoc(pos, key, (void*&)value); - pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited)); - } - return pCopy; - } - case PDFOBJ_NULL: { - return FX_NEW CPDF_Null; - } - case PDFOBJ_STREAM: { - CPDF_Stream* pThis = (CPDF_Stream*)this; - CPDF_StreamAcc acc; - acc.LoadAllData(pThis, TRUE); - FX_DWORD streamSize = acc.GetSize(); - CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, (CPDF_Dictionary*)((CPDF_Object*)pThis->GetDict())->CloneInternal(bDirect, visited)); - return pObj; - } - case PDFOBJ_REFERENCE: { - CPDF_Reference* pRef = (CPDF_Reference*)this; - FX_DWORD obj_num = pRef->m_RefObjNum; - if (bDirect && !visited->GetValueAt((void*)(FX_UINTPTR)obj_num)) { - visited->SetAt((void*)(FX_UINTPTR)obj_num, (void*)1); - CPDF_Object* ret = pRef->GetDirect()->CloneInternal(TRUE, visited); - return ret; - } else { - return FX_NEW CPDF_Reference(pRef->m_pObjList, obj_num); - } - } - } - return NULL; -} -CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const -{ - if (this == NULL) { - return NULL; - } - if (m_ObjNum) { - return FX_NEW CPDF_Reference(pDoc, m_ObjNum); - } - return Clone(); -} -CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const -{ - if (this == NULL) { - return CFX_WideString(); - } - if (m_Type == PDFOBJ_STRING) { - return PDF_DecodeText(((CPDF_String*)this)->m_String, pCharMap); - } else if (m_Type == PDFOBJ_STREAM) { - CPDF_StreamAcc stream; - stream.LoadAllData((CPDF_Stream*)this, FALSE); - CFX_WideString result = PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap); - return result; - } else if (m_Type == PDFOBJ_NAME) { - return PDF_DecodeText(((CPDF_Name*)this)->m_Name, pCharMap); - } - return CFX_WideString(); -} -void CPDF_Object::SetUnicodeText(FX_LPCWSTR pUnicodes, int len) -{ - if (this == NULL) { - return; - } - if (m_Type == PDFOBJ_STRING) { - ((CPDF_String*)this)->m_String = PDF_EncodeText(pUnicodes, len); - } else if (m_Type == PDFOBJ_STREAM) { - CFX_ByteString result = PDF_EncodeText(pUnicodes, len); - ((CPDF_Stream*)this)->SetData((FX_LPBYTE)(FX_LPCSTR)result, result.GetLength(), FALSE, FALSE); - } -} -CPDF_Number::CPDF_Number(int value) -{ - m_Type = PDFOBJ_NUMBER; - m_bInteger = TRUE; - m_Integer = value; -} -CPDF_Number::CPDF_Number(FX_FLOAT value) -{ - m_Type = PDFOBJ_NUMBER; - m_bInteger = FALSE; - m_Float = value; -} -CPDF_Number::CPDF_Number(FX_BOOL bInteger, void* pData) -{ - m_Type = PDFOBJ_NUMBER; - m_bInteger = bInteger; - m_Integer = *(int*)pData; -} -extern void FX_atonum(FX_BSTR, FX_BOOL&, void*); -CPDF_Number::CPDF_Number(FX_BSTR str) -{ - m_Type = PDFOBJ_NUMBER; - FX_atonum(str, m_bInteger, &m_Integer); -} -void CPDF_Number::SetString(FX_BSTR str) -{ - FX_atonum(str, m_bInteger, &m_Integer); -} -FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const -{ - return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer; -} -CFX_ByteString CPDF_Number::GetString() const -{ - return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED) : CFX_ByteString::FormatFloat(m_Float); -} -void CPDF_Number::SetNumber(FX_FLOAT value) -{ - m_bInteger = FALSE; - m_Float = value; -} -CPDF_String::CPDF_String(const CFX_WideString& str) -{ - m_Type = PDFOBJ_STRING; - m_String = PDF_EncodeText(str, str.GetLength()); - m_bHex = FALSE; -} -CPDF_Array::~CPDF_Array() -{ - int size = m_Objects.GetSize(); - CPDF_Object** pList = (CPDF_Object**)m_Objects.GetData(); - for (int i = 0; i < size; i ++) { - pList[i]->Release(); - } -} -CFX_FloatRect CPDF_Array::GetRect() -{ - CFX_FloatRect rect; - if (this == NULL || m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 4) { - return rect; - } - rect.left = GetNumber(0); - rect.bottom = GetNumber(1); - rect.right = GetNumber(2); - rect.top = GetNumber(3); - return rect; -} -CFX_AffineMatrix CPDF_Array::GetMatrix() -{ - CFX_AffineMatrix matrix; - if (this == NULL || m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 6) { - return matrix; - } - matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3), GetNumber(4), GetNumber(5)); - return matrix; -} -CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const -{ - if (this == NULL) { - return NULL; - } - if (i >= (FX_DWORD)m_Objects.GetSize()) { - return NULL; - } - return (CPDF_Object*)m_Objects.GetAt(i); -} -CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const -{ - if (this == NULL) { - return NULL; - } - if (i >= (FX_DWORD)m_Objects.GetSize()) { - return NULL; - } - return ((CPDF_Object*)m_Objects.GetAt(i))->GetDirect(); -} -CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const -{ - if (this && i < (FX_DWORD)m_Objects.GetSize()) { - CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); - return p->GetString(); - } - return CFX_ByteString(); -} -CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const -{ - if (this && i < (FX_DWORD)m_Objects.GetSize()) { - CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); - return p->GetConstString(); - } - return CFX_ByteStringC(); -} -int CPDF_Array::GetInteger(FX_DWORD i) const -{ - if (this == NULL || i >= (FX_DWORD)m_Objects.GetSize()) { - return 0; - } - CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); - return p->GetInteger(); -} -FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const -{ - if (this == NULL || i >= (FX_DWORD)m_Objects.GetSize()) { - return 0; - } - CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); - return p->GetNumber(); -} -CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const -{ - CPDF_Object* p = GetElementValue(i); - if (p == NULL) { - return NULL; - } else if (p->GetType() == PDFOBJ_DICTIONARY) { - return (CPDF_Dictionary*)p; - } else if (p->GetType() == PDFOBJ_STREAM) { - return ((CPDF_Stream*)p)->GetDict(); - } - return NULL; -} -CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const -{ - CPDF_Object* p = GetElementValue(i); - if (p == NULL || p->GetType() != PDFOBJ_STREAM) { - return NULL; - } - return (CPDF_Stream*)p; -} -CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const -{ - CPDF_Object* p = GetElementValue(i); - if (p == NULL || p->GetType() != PDFOBJ_ARRAY) { - return NULL; - } - return (CPDF_Array*)p; -} -void CPDF_Array::RemoveAt(FX_DWORD i) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - if (i >= (FX_DWORD)m_Objects.GetSize()) { - return; - } - CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); - p->Release(); - m_Objects.RemoveAt(i); -} -void CPDF_Array::SetAt(FX_DWORD i, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - ASSERT(i < (FX_DWORD)m_Objects.GetSize()); - if (i >= (FX_DWORD)m_Objects.GetSize()) { - return; - } - CPDF_Object* pOld = (CPDF_Object*)m_Objects.GetAt(i); - pOld->Release(); - if (pObj->GetObjNum()) { - ASSERT(pObjs != NULL); - pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); - } - m_Objects.SetAt(i, pObj); -} -void CPDF_Array::InsertAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) -{ - ASSERT(pObj != NULL); - if (pObj->GetObjNum()) { - ASSERT(pObjs != NULL); - pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); - } - m_Objects.InsertAt(index, pObj); -} -void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) -{ - ASSERT(pObj != NULL); - if (pObj->GetObjNum()) { - ASSERT(pObjs != NULL); - pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); - } - m_Objects.Add(pObj); -} -void CPDF_Array::AddName(const CFX_ByteString& str) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - Add(FX_NEW CPDF_Name(str)); -} -void CPDF_Array::AddString(const CFX_ByteString& str) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - Add(FX_NEW CPDF_String(str)); -} -void CPDF_Array::AddInteger(int i) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - Add(FX_NEW CPDF_Number(i)); -} -void CPDF_Array::AddNumber(FX_FLOAT f) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - CPDF_Number* pNumber = FX_NEW CPDF_Number; - pNumber->SetNumber(f); - Add(pNumber); -} -void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); - Add(FX_NEW CPDF_Reference(pDoc, objnum)); -} -FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const -{ - if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) { - return FALSE; - } - for (int i = 0; i < m_Objects.GetSize(); i ++) - if (!((CPDF_Object*)m_Objects[i])->IsIdentical((CPDF_Object*)pOther->m_Objects[i])) { - return FALSE; - } - return TRUE; -} -CPDF_Dictionary::~CPDF_Dictionary() -{ - FX_POSITION pos = m_Map.GetStartPosition(); - while (pos) { - FX_LPVOID value = m_Map.GetNextValue(pos); - ((CPDF_Object*)value)->Release(); - } -} -FX_POSITION CPDF_Dictionary::GetStartPos() const -{ - return m_Map.GetStartPosition(); -} -CPDF_Object* CPDF_Dictionary::GetNextElement(FX_POSITION& pos, CFX_ByteString& key) const -{ - if (pos == NULL) { - return NULL; - } - CPDF_Object* p; - m_Map.GetNextAssoc(pos, key, (FX_LPVOID&)p); - return p; -} -CPDF_Object* CPDF_Dictionary::GetElement(FX_BSTR key) const -{ - if (this == NULL) { - return NULL; - } - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - return p; -} -CPDF_Object* CPDF_Dictionary::GetElementValue(FX_BSTR key) const -{ - if (this == NULL) { - return NULL; - } - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - return p->GetDirect(); -} -CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetString(); - } - } - return CFX_ByteString(); -} -CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetConstString(); - } - } - return CFX_ByteStringC(); -} -CFX_WideString CPDF_Dictionary::GetUnicodeText(FX_BSTR key, CFX_CharMap* pCharMap) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - if(p->GetType() == PDFOBJ_REFERENCE) { - p = ((CPDF_Reference*)p)->GetDirect(); - return p->GetUnicodeText(pCharMap); - } else { - return p->GetUnicodeText(pCharMap); - } - } - } - return CFX_WideString(); -} -CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key, FX_BSTR def) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetString(); - } - } - return CFX_ByteString(def); -} -CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key, FX_BSTR def) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetConstString(); - } - } - return CFX_ByteStringC(def); -} -int CPDF_Dictionary::GetInteger(FX_BSTR key) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetInteger(); - } - } - return 0; -} -int CPDF_Dictionary::GetInteger(FX_BSTR key, int def) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetInteger(); - } - } - return def; -} -FX_FLOAT CPDF_Dictionary::GetNumber(FX_BSTR key) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p) { - return p->GetNumber(); - } - } - return 0; -} -FX_BOOL CPDF_Dictionary::GetBoolean(FX_BSTR key, FX_BOOL bDefault) const -{ - if (this) { - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p && p->GetType() == PDFOBJ_BOOLEAN) { - return p->GetInteger(); - } - } - return bDefault; -} -CPDF_Dictionary* CPDF_Dictionary::GetDict(FX_BSTR key) const -{ - CPDF_Object* p = GetElementValue(key); - if (p == NULL) { - return NULL; - } else if (p->GetType() == PDFOBJ_DICTIONARY) { - return (CPDF_Dictionary*)p; - } else if (p->GetType() == PDFOBJ_STREAM) { - return ((CPDF_Stream*)p)->GetDict(); - } - return NULL; -} -CPDF_Array* CPDF_Dictionary::GetArray(FX_BSTR key) const -{ - CPDF_Object* p = GetElementValue(key); - if (p == NULL || p->GetType() != PDFOBJ_ARRAY) { - return NULL; - } - return (CPDF_Array*)p; -} -CPDF_Stream* CPDF_Dictionary::GetStream(FX_BSTR key) const -{ - CPDF_Object* p = GetElementValue(key); - if (p == NULL || p->GetType() != PDFOBJ_STREAM) { - return NULL; - } - return (CPDF_Stream*)p; -} -CFX_FloatRect CPDF_Dictionary::GetRect(FX_BSTR key) const -{ - CFX_FloatRect rect; - CPDF_Array* pArray = GetArray(key); - if (pArray) { - rect = pArray->GetRect(); - } - return rect; -} -CFX_AffineMatrix CPDF_Dictionary::GetMatrix(FX_BSTR key) const -{ - CFX_AffineMatrix matrix; - CPDF_Array* pArray = GetArray(key); - if (pArray) { - matrix = pArray->GetMatrix(); - } - return matrix; -} -FX_BOOL CPDF_Dictionary::KeyExist(FX_BSTR key) const -{ - if (this == NULL) { - return FALSE; - } - FX_LPVOID value; - return m_Map.Lookup(key, value); -} -void CPDF_Dictionary::SetAt(FX_BSTR key, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p == pObj) { - return; - } - if (p) { - p->Release(); - } - if (pObj) { - if (pObj->GetObjNum()) { - ASSERT(pObjs != NULL); - pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); - } - m_Map.SetAt(key, pObj); - } else { - m_Map.RemoveKey(key); - } -} -void CPDF_Dictionary::AddValue(FX_BSTR key, CPDF_Object* pObj) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); - m_Map.AddValue(key, pObj); -} -void CPDF_Dictionary::RemoveAt(FX_BSTR key) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); - CPDF_Object* p = NULL; - m_Map.Lookup(key, (void*&)p); - if (p == NULL) { - return; - } - p->Release(); - m_Map.RemoveKey(key); -} -void CPDF_Dictionary::ReplaceKey(FX_BSTR oldkey, FX_BSTR newkey) -{ - ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); - CPDF_Object* p = NULL; - m_Map.Lookup(oldkey, (void*&)p); - if (p == NULL) { - return; - } - m_Map.RemoveKey(oldkey); - m_Map.SetAt(newkey, p); -} -FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const -{ - if (this == NULL) { - if (pOther == NULL) { - return TRUE; - } - return FALSE; - } - if (pOther == NULL) { - return FALSE; - } - if (m_Map.GetCount() != pOther->m_Map.GetCount()) { - return FALSE; - } - FX_POSITION pos = m_Map.GetStartPosition(); - while (pos) { - CFX_ByteString key; - FX_LPVOID value; - m_Map.GetNextAssoc(pos, key, value); - if (!((CPDF_Object*)value)->IsIdentical(pOther->GetElement(key))) { - return FALSE; - } - } - return TRUE; -} -void CPDF_Dictionary::SetAtInteger(FX_BSTR key, int i) -{ - SetAt(key, FX_NEW CPDF_Number(i)); -} -void CPDF_Dictionary::SetAtName(FX_BSTR key, const CFX_ByteString& name) -{ - SetAt(key, FX_NEW CPDF_Name(name)); -} -void CPDF_Dictionary::SetAtString(FX_BSTR key, const CFX_ByteString& str) -{ - SetAt(key, FX_NEW CPDF_String(str)); -} -void CPDF_Dictionary::SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum) -{ - SetAt(key, FX_NEW CPDF_Reference(pDoc, objnum)); -} -void CPDF_Dictionary::AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum) -{ - AddValue(key, FX_NEW CPDF_Reference(pDoc, objnum)); -} -void CPDF_Dictionary::SetAtNumber(FX_BSTR key, FX_FLOAT f) -{ - CPDF_Number* pNumber = FX_NEW CPDF_Number; - pNumber->SetNumber(f); - SetAt(key, pNumber); -} -void CPDF_Dictionary::SetAtBoolean(FX_BSTR key, FX_BOOL bValue) -{ - SetAt(key, FX_NEW CPDF_Boolean(bValue)); -} -void CPDF_Dictionary::SetAtRect(FX_BSTR key, const CFX_FloatRect& rect) -{ - CPDF_Array* pArray = FX_NEW CPDF_Array; - pArray->AddNumber(rect.left); - pArray->AddNumber(rect.bottom); - pArray->AddNumber(rect.right); - pArray->AddNumber(rect.top); - SetAt(key, pArray); -} -void CPDF_Dictionary::SetAtMatrix(FX_BSTR key, const CFX_AffineMatrix& matrix) -{ - CPDF_Array* pArray = FX_NEW CPDF_Array; - pArray->AddNumber16(matrix.a); - pArray->AddNumber16(matrix.b); - pArray->AddNumber16(matrix.c); - pArray->AddNumber16(matrix.d); - pArray->AddNumber(matrix.e); - pArray->AddNumber(matrix.f); - SetAt(key, pArray); -} -CPDF_Stream::CPDF_Stream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict) -{ - m_Type = PDFOBJ_STREAM; - m_pDict = pDict; - m_dwSize = size; - m_GenNum = (FX_DWORD) - 1; - m_pDataBuf = pData; - m_pCryptoHandler = NULL; -} -CPDF_Stream::~CPDF_Stream() -{ - if (m_GenNum == (FX_DWORD) - 1 && m_pDataBuf != NULL) { - FX_Free(m_pDataBuf); - } - if (m_pDict) { - m_pDict->Release(); - } -} -void CPDF_Stream::InitStream(CPDF_Dictionary* pDict) -{ - if (pDict) { - if (m_pDict) { - m_pDict->Release(); - } - m_pDict = pDict; - } - if (m_GenNum == (FX_DWORD) - 1) { - if (m_pDataBuf) { - FX_Free(m_pDataBuf); - } - } - m_GenNum = 0; - m_pFile = NULL; - m_pCryptoHandler = NULL; - m_FileOffset = 0; -} -void CPDF_Stream::InitStream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict) -{ - InitStream(pDict); - m_GenNum = (FX_DWORD) - 1; - m_pDataBuf = FX_Alloc(FX_BYTE, size); - if (pData) { - FXSYS_memcpy32(m_pDataBuf, pData, size); - } - m_dwSize = size; - if (m_pDict) { - m_pDict->SetAtInteger(FX_BSTRC("Length"), size); - } -} -void CPDF_Stream::SetData(FX_LPCBYTE pData, FX_DWORD size, FX_BOOL bCompressed, FX_BOOL bKeepBuf) -{ - if (m_GenNum == (FX_DWORD) - 1) { - if (m_pDataBuf) { - FX_Free(m_pDataBuf); - } - } else { - m_GenNum = (FX_DWORD) - 1; - m_pCryptoHandler = NULL; - } - if (bKeepBuf) { - m_pDataBuf = (FX_LPBYTE)pData; - } else { - m_pDataBuf = FX_Alloc(FX_BYTE, size); - if (pData) { - FXSYS_memcpy32(m_pDataBuf, pData, size); - } - } - m_dwSize = size; - if (m_pDict == NULL) { - m_pDict = FX_NEW CPDF_Dictionary; - } - m_pDict->SetAtInteger(FX_BSTRC("Length"), size); - if (!bCompressed) { - m_pDict->RemoveAt(FX_BSTRC("Filter")); - m_pDict->RemoveAt(FX_BSTRC("DecodeParms")); - } -} -FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset, FX_LPBYTE buf, FX_DWORD size) const -{ - if ((m_GenNum != (FX_DWORD) - 1) && m_pFile) { - return m_pFile->ReadBlock(buf, m_FileOffset + offset, size); - } - if (m_pDataBuf) { - FXSYS_memcpy32(buf, m_pDataBuf + offset, size); - } - return TRUE; -} -void CPDF_Stream::InitStream(IFX_FileRead *pFile, CPDF_Dictionary* pDict) -{ - InitStream(pDict); - m_pFile = pFile; - m_dwSize = (FX_DWORD)pFile->GetSize(); - if (m_pDict) { - m_pDict->SetAtInteger(FX_BSTRC("Length"), m_dwSize); - } -} -FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const -{ - if (!m_pDict->Identical(pOther->m_pDict)) { - return FALSE; - } - if (m_dwSize != pOther->m_dwSize) { - return FALSE; - } - if (m_GenNum != (FX_DWORD) - 1 && pOther->m_GenNum != (FX_DWORD) - 1) { - if (m_pFile == pOther->m_pFile && m_pFile == NULL) { - return TRUE; - } - if (!m_pFile || !pOther->m_pFile) { - return FALSE; - } - FX_BYTE srcBuf[1024]; - FX_BYTE destBuf[1024]; - FX_DWORD size = m_dwSize; - FX_DWORD srcOffset = m_FileOffset; - FX_DWORD destOffset = pOther->m_FileOffset; - if (m_pFile == pOther->m_pFile && srcOffset == destOffset) { - return TRUE; - } - while (size > 0) { - FX_DWORD actualSize = size > 1024 ? 1024 : size; - m_pFile->ReadBlock(srcBuf, srcOffset, actualSize); - pOther->m_pFile->ReadBlock(destBuf, destOffset, actualSize); - if (FXSYS_memcmp32(srcBuf, destBuf, actualSize) != 0) { - return FALSE; - } - size -= actualSize; - srcOffset += actualSize; - destOffset += actualSize; - } - return TRUE; - } - if (m_GenNum != (FX_DWORD) - 1 || pOther->m_GenNum != (FX_DWORD) - 1) { - IFX_FileRead* pFile = NULL; - FX_LPBYTE pBuf = NULL; - FX_DWORD offset = 0; - if (m_GenNum != (FX_DWORD) - 1) { - pFile = m_pFile; - pBuf = pOther->m_pDataBuf; - offset = m_FileOffset; - } - if (pOther->m_GenNum != (FX_DWORD) - 1) { - pFile = pOther->m_pFile; - pBuf = m_pDataBuf; - offset = pOther->m_FileOffset; - } - if (NULL == pBuf) { - return FALSE; - } - FX_BYTE srcBuf[1024]; - FX_DWORD size = m_dwSize; - while (size > 0) { - FX_DWORD actualSize = size > 1024 ? 1024 : size; - m_pFile->ReadBlock(srcBuf, offset, actualSize); - if (FXSYS_memcmp32(srcBuf, pBuf, actualSize) != 0) { - return FALSE; - } - pBuf += actualSize; - size -= actualSize; - offset += actualSize; - } - return TRUE; - } - return FXSYS_memcmp32(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0; -} -CPDF_Stream* CPDF_Stream::Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const -{ - CPDF_Dictionary *pCloneDict = (CPDF_Dictionary*)m_pDict->Clone(bDirect); - IFX_FileStream *pFS = NULL; - if (lpfCallback) { - pFS = lpfCallback((CPDF_Stream*)this, pUserData); - } - if (!pFS) { - CPDF_StreamAcc acc; - acc.LoadAllData(this, TRUE); - FX_DWORD streamSize = acc.GetSize(); - CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, pCloneDict); - return pObj; - } - CPDF_Stream* pObj = FX_NEW CPDF_Stream(NULL, 0, NULL); - CPDF_StreamFilter *pSF = GetStreamFilter(TRUE); - if (pSF) { - FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, 4096); - FX_DWORD dwRead; - do { - dwRead = pSF->ReadBlock(pBuf, 4096); - if (dwRead) { - pFS->WriteBlock(pBuf, dwRead); - } - } while (dwRead == 4096); - pFS->Flush(); - FX_Free(pBuf); - delete pSF; - } - pObj->InitStream((IFX_FileRead*)pFS, pCloneDict); - return pObj; -} -extern FX_BOOL PDF_DataDecode(FX_LPCBYTE src_buf, FX_DWORD src_size, const CPDF_Dictionary* pDict, - FX_LPBYTE& dest_buf, FX_DWORD& dest_size, CFX_ByteString& ImageEncoding, - CPDF_Dictionary*& pImageParms, FX_DWORD estimated_size, FX_BOOL bImageAcc); -CPDF_StreamAcc::CPDF_StreamAcc() -{ - m_bNewBuf = FALSE; - m_pData = NULL; - m_dwSize = 0; - m_pImageParam = NULL; - m_pStream = NULL; - m_pSrcData = NULL; -} -void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, FX_BOOL bRawAccess, FX_DWORD estimated_size, - FX_BOOL bImageAcc) -{ - if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) { - return; - } - m_pStream = pStream; - if (pStream->IsMemoryBased() && - (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) { - m_dwSize = pStream->m_dwSize; - m_pData = (FX_LPBYTE)pStream->m_pDataBuf; - return; - } - FX_LPBYTE pSrcData; - FX_DWORD dwSrcSize = pStream->m_dwSize; - if (dwSrcSize == 0) { - return; - } - if (!pStream->IsMemoryBased()) { - pSrcData = m_pSrcData = FX_Alloc(FX_BYTE, dwSrcSize); - if (!pSrcData || !pStream->ReadRawData(0, pSrcData, dwSrcSize)) { - return; - } - } else { - pSrcData = pStream->m_pDataBuf; - } - FX_LPBYTE pDecryptedData; - FX_DWORD dwDecryptedSize; - if (pStream->m_pCryptoHandler) { - CFX_BinaryBuf dest_buf; - dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize)); - FX_LPVOID context = pStream->m_pCryptoHandler->DecryptStart(pStream->GetObjNum(), pStream->m_GenNum); - pStream->m_pCryptoHandler->DecryptStream(context, pSrcData, dwSrcSize, dest_buf); - pStream->m_pCryptoHandler->DecryptFinish(context, dest_buf); - pDecryptedData = dest_buf.GetBuffer(); - dwDecryptedSize = dest_buf.GetSize(); - dest_buf.DetachBuffer(); - } else { - pDecryptedData = pSrcData; - dwDecryptedSize = dwSrcSize; - } - if (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess) { - m_pData = pDecryptedData; - m_dwSize = dwDecryptedSize; - } else { - FX_BOOL bRet = PDF_DataDecode(pDecryptedData, dwDecryptedSize, m_pStream->GetDict(), - m_pData, m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc); - if (!bRet) { - m_pData = pDecryptedData; - m_dwSize = dwDecryptedSize; - } - } - if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) { - FX_Free(pSrcData); - } - if (pDecryptedData != pSrcData && pDecryptedData != m_pData) { - FX_Free(pDecryptedData); - } - m_pSrcData = NULL; - m_bNewBuf = m_pData != pStream->m_pDataBuf; -} -CPDF_StreamAcc::~CPDF_StreamAcc() -{ - if (m_bNewBuf && m_pData) { - FX_Free(m_pData); - } - if (m_pSrcData) { - FX_Free(m_pSrcData); - } -} -FX_LPCBYTE CPDF_StreamAcc::GetData() const -{ - if (m_bNewBuf) { - return m_pData; - } - if (!m_pStream) { - return NULL; - } - return m_pStream->m_pDataBuf; -} -FX_DWORD CPDF_StreamAcc::GetSize() const -{ - if (m_bNewBuf) { - return m_dwSize; - } - if (!m_pStream) { - return 0; - } - return m_pStream->m_dwSize; -} -FX_LPBYTE CPDF_StreamAcc::DetachData() -{ - if (m_bNewBuf) { - FX_LPBYTE p = m_pData; - m_pData = NULL; - m_dwSize = 0; - return p; - } - FX_LPBYTE p = FX_Alloc(FX_BYTE, m_dwSize); - if (p == NULL) { - return NULL; - } - FXSYS_memcpy32(p, m_pData, m_dwSize); - return p; -} -void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) -{ - m_pObjList = pDoc; - m_RefObjNum = objnum; -} -CPDF_IndirectObjects::CPDF_IndirectObjects(IPDF_DocParser* pParser) -{ - m_pParser = pParser; - m_IndirectObjs.InitHashTable(1013); - if (pParser) { - m_LastObjNum = m_pParser->GetLastObjNum(); - } else { - m_LastObjNum = 0; - } -} -CPDF_IndirectObjects::~CPDF_IndirectObjects() -{ - FX_POSITION pos = m_IndirectObjs.GetStartPosition(); - while (pos) { - FX_LPVOID key, value; - m_IndirectObjs.GetNextAssoc(pos, key, value); - ((CPDF_Object*)value)->Destroy(); - } -} -CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(FX_DWORD objnum, struct PARSE_CONTEXT* pContext) -{ - if (objnum == 0) { - return NULL; - } - FX_LPVOID value; - { - if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { - if (((CPDF_Object*)value)->GetObjNum() == -1) { - return NULL; - } - return (CPDF_Object*)value; - } - } - CPDF_Object* pObj = NULL; - if (m_pParser) { - pObj = m_pParser->ParseIndirectObject(this, objnum, pContext); - } - if (pObj == NULL) { - return NULL; - } - pObj->m_ObjNum = objnum; - if (m_LastObjNum < objnum) { - m_LastObjNum = objnum; - } - if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { - if (value) { - ((CPDF_Object *)value)->Destroy(); - } - } - m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj); - return pObj; -} -int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum) -{ - FX_LPVOID value; - if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { - return ((CPDF_Object*)value)->GetType(); - } - if (m_pParser) { - PARSE_CONTEXT context; - FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT)); - context.m_Flags = PDFPARSE_TYPEONLY; - return (int)(FX_UINTPTR)m_pParser->ParseIndirectObject(this, objnum, &context); - } - return 0; -} -FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj) -{ - if (pObj->m_ObjNum) { - return pObj->m_ObjNum; - } - m_LastObjNum ++; - m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)m_LastObjNum, pObj); - pObj->m_ObjNum = m_LastObjNum; - return m_LastObjNum; -} -void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum) -{ - FX_LPVOID value; - if (!m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { - return; - } - if (((CPDF_Object*)value)->GetObjNum() == -1) { - return; - } - ((CPDF_Object*)value)->Destroy(); - m_IndirectObjs.RemoveKey((FX_LPVOID)(FX_UINTPTR)objnum); -} -void CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj) -{ - if (objnum == 0 || pObj == NULL) { - return; - } - FX_LPVOID value; - if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { - ((CPDF_Object*)value)->Destroy(); - } - pObj->m_ObjNum = objnum; - m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj); - if (m_LastObjNum < objnum) { - m_LastObjNum = objnum; - } -} -FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const -{ - return m_LastObjNum; -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fpdfapi/fpdf_parser.h" +void CPDF_Object::Release() +{ + if (this == NULL) { + return; + } + if (m_ObjNum) { + return; + } + Destroy(); +} +void CPDF_Object::Destroy() +{ + switch (m_Type) { + case PDFOBJ_STRING: + delete (CPDF_String*)this; + break; + case PDFOBJ_NAME: + delete (CPDF_Name*)this; + break; + case PDFOBJ_ARRAY: + delete (CPDF_Array*)this; + break; + case PDFOBJ_DICTIONARY: + delete (CPDF_Dictionary*)this; + break; + case PDFOBJ_STREAM: + delete (CPDF_Stream*)this; + break; + default: + delete this; + } +} +CFX_ByteString CPDF_Object::GetString() const +{ + if (this == NULL) { + return CFX_ByteString(); + } + switch (m_Type) { + case PDFOBJ_BOOLEAN: + return ((CPDF_Boolean*)this)->m_bValue ? "true" : "false"; + case PDFOBJ_NUMBER: + return ((CPDF_Number*)this)->GetString(); + case PDFOBJ_STRING: + return ((CPDF_String*)this)->m_String; + case PDFOBJ_NAME: + return ((CPDF_Name*)this)->m_Name; + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; + if (pRef->m_pObjList == NULL) { + break; + } + CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); + if (pObj == NULL) { + return CFX_ByteString(); + } + return pObj->GetString(); + } + } + return CFX_ByteString(); +} +CFX_ByteStringC CPDF_Object::GetConstString() const +{ + if (this == NULL) { + return CFX_ByteStringC(); + } + switch (m_Type) { + case PDFOBJ_STRING: + return CFX_ByteStringC((FX_LPCBYTE)((CPDF_String*)this)->m_String, ((CPDF_String*)this)->m_String.GetLength()); + case PDFOBJ_NAME: + return CFX_ByteStringC((FX_LPCBYTE)((CPDF_Name*)this)->m_Name, ((CPDF_Name*)this)->m_Name.GetLength()); + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; + if (pRef->m_pObjList == NULL) { + break; + } + CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); + if (pObj == NULL) { + return CFX_ByteStringC(); + } + return pObj->GetConstString(); + } + } + return CFX_ByteStringC(); +} +FX_FLOAT CPDF_Object::GetNumber() const +{ + if (this == NULL) { + return 0; + } + switch (m_Type) { + case PDFOBJ_NUMBER: + return ((CPDF_Number*)this)->GetNumber(); + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; + if (pRef->m_pObjList == NULL) { + break; + } + CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); + if (pObj == NULL) { + return 0; + } + return pObj->GetNumber(); + } + } + return 0; +} +FX_FLOAT CPDF_Object::GetNumber16() const +{ + return GetNumber(); +} +int CPDF_Object::GetInteger() const +{ + if (this == NULL) { + return 0; + } + switch (m_Type) { + case PDFOBJ_BOOLEAN: + return ((CPDF_Boolean*)this)->m_bValue; + case PDFOBJ_NUMBER: + return ((CPDF_Number*)this)->GetInteger(); + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; + PARSE_CONTEXT context; + FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT)); + if (pRef->m_pObjList == NULL) { + return 0; + } + CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum, &context); + if (pObj == NULL) { + return 0; + } + return pObj->GetInteger(); + } + } + return 0; +} +CPDF_Dictionary* CPDF_Object::GetDict() const +{ + if (this == NULL) { + return NULL; + } + switch (m_Type) { + case PDFOBJ_DICTIONARY: + return (CPDF_Dictionary*)this; + case PDFOBJ_STREAM: + return ((CPDF_Stream*)this)->GetDict(); + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)this; + if (pRef->m_pObjList == NULL) { + break; + } + CPDF_Object* pObj = pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); + if (pObj == NULL) { + return NULL; + } + return pObj->GetDict(); + } + } + return NULL; +} +CPDF_Array* CPDF_Object::GetArray() const +{ + if (this == NULL) { + return NULL; + } + if (m_Type == PDFOBJ_ARRAY) { + return (CPDF_Array*)this; + } + return NULL; +} +void CPDF_Object::SetString(const CFX_ByteString& str) +{ + ASSERT(this != NULL); + switch (m_Type) { + case PDFOBJ_BOOLEAN: + ((CPDF_Boolean*)this)->m_bValue = str == FX_BSTRC("true") ? 1 : 0; + return; + case PDFOBJ_NUMBER: + ((CPDF_Number*)this)->SetString(str); + return; + case PDFOBJ_STRING: + ((CPDF_String*)this)->m_String = str; + return; + case PDFOBJ_NAME: + ((CPDF_Name*)this)->m_Name = str; + return; + } + ASSERT(FALSE); +} +int CPDF_Object::GetDirectType() const +{ + if (m_Type != PDFOBJ_REFERENCE) { + return m_Type; + } + CPDF_Reference* pRef = (CPDF_Reference*)this; + return pRef->m_pObjList->GetIndirectType(pRef->m_RefObjNum); +} +FX_BOOL CPDF_Object::IsIdentical(CPDF_Object* pOther) const +{ + if (this == pOther) { + return TRUE; + } + if (this == NULL || pOther == NULL) { + return FALSE; + } + if (pOther->m_Type != m_Type) { + if (m_Type == PDFOBJ_REFERENCE) { + return GetDirect()->IsIdentical(pOther); + } else if (pOther->m_Type == PDFOBJ_REFERENCE) { + return IsIdentical(pOther->GetDirect()); + } + return FALSE; + } + switch (m_Type) { + case PDFOBJ_BOOLEAN: + return (((CPDF_Boolean*)this)->Identical((CPDF_Boolean*)pOther)); + case PDFOBJ_NUMBER: + return (((CPDF_Number*)this)->Identical((CPDF_Number*)pOther)); + case PDFOBJ_STRING: + return (((CPDF_String*)this)->Identical((CPDF_String*)pOther)); + case PDFOBJ_NAME: + return (((CPDF_Name*)this)->Identical((CPDF_Name*)pOther)); + case PDFOBJ_ARRAY: + return (((CPDF_Array*)this)->Identical((CPDF_Array*)pOther)); + case PDFOBJ_DICTIONARY: + return (((CPDF_Dictionary*)this)->Identical((CPDF_Dictionary*)pOther)); + case PDFOBJ_NULL: + return TRUE; + case PDFOBJ_STREAM: + return (((CPDF_Stream*)this)->Identical((CPDF_Stream*)pOther)); + case PDFOBJ_REFERENCE: + return (((CPDF_Reference*)this)->Identical((CPDF_Reference*)pOther)); + } + return FALSE; +} +CPDF_Object* CPDF_Object::GetDirect() const +{ + if (this == NULL) { + return NULL; + } + if (m_Type != PDFOBJ_REFERENCE) { + return (CPDF_Object*)this; + } + CPDF_Reference* pRef = (CPDF_Reference*)(FX_LPVOID)this; + if (pRef->m_pObjList == NULL) { + return NULL; + } + return pRef->m_pObjList->GetIndirectObject(pRef->m_RefObjNum); +} +CPDF_Object* CPDF_Object::Clone(FX_BOOL bDirect) const +{ + CFX_MapPtrToPtr visited; + return CloneInternal(bDirect, &visited); +} +CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const +{ + if (this == NULL) { + return NULL; + } + switch (m_Type) { + case PDFOBJ_BOOLEAN: + return FX_NEW CPDF_Boolean(((CPDF_Boolean*)this)->m_bValue); + case PDFOBJ_NUMBER: + return FX_NEW CPDF_Number(((CPDF_Number*)this)->m_bInteger, &((CPDF_Number*)this)->m_Integer); + case PDFOBJ_STRING: + return FX_NEW CPDF_String(((CPDF_String*)this)->m_String, ((CPDF_String*)this)->IsHex()); + case PDFOBJ_NAME: + return FX_NEW CPDF_Name(((CPDF_Name*)this)->m_Name); + case PDFOBJ_ARRAY: { + CPDF_Array* pCopy = FX_NEW CPDF_Array(); + CPDF_Array* pThis = (CPDF_Array*)this; + int n = pThis->GetCount(); + for (int i = 0; i < n; i ++) { + CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i); + pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited)); + } + return pCopy; + } + case PDFOBJ_DICTIONARY: { + CPDF_Dictionary* pCopy = FX_NEW CPDF_Dictionary(); + CPDF_Dictionary* pThis = (CPDF_Dictionary*)this; + FX_POSITION pos = pThis->m_Map.GetStartPosition(); + while (pos) { + CFX_ByteString key; + CPDF_Object* value; + pThis->m_Map.GetNextAssoc(pos, key, (void*&)value); + pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited)); + } + return pCopy; + } + case PDFOBJ_NULL: { + return FX_NEW CPDF_Null; + } + case PDFOBJ_STREAM: { + CPDF_Stream* pThis = (CPDF_Stream*)this; + CPDF_StreamAcc acc; + acc.LoadAllData(pThis, TRUE); + FX_DWORD streamSize = acc.GetSize(); + CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, (CPDF_Dictionary*)((CPDF_Object*)pThis->GetDict())->CloneInternal(bDirect, visited)); + return pObj; + } + case PDFOBJ_REFERENCE: { + CPDF_Reference* pRef = (CPDF_Reference*)this; + FX_DWORD obj_num = pRef->m_RefObjNum; + if (bDirect && !visited->GetValueAt((void*)(FX_UINTPTR)obj_num)) { + visited->SetAt((void*)(FX_UINTPTR)obj_num, (void*)1); + CPDF_Object* ret = pRef->GetDirect()->CloneInternal(TRUE, visited); + return ret; + } else { + return FX_NEW CPDF_Reference(pRef->m_pObjList, obj_num); + } + } + } + return NULL; +} +CPDF_Object* CPDF_Object::CloneRef(CPDF_IndirectObjects* pDoc) const +{ + if (this == NULL) { + return NULL; + } + if (m_ObjNum) { + return FX_NEW CPDF_Reference(pDoc, m_ObjNum); + } + return Clone(); +} +CFX_WideString CPDF_Object::GetUnicodeText(CFX_CharMap* pCharMap) const +{ + if (this == NULL) { + return CFX_WideString(); + } + if (m_Type == PDFOBJ_STRING) { + return PDF_DecodeText(((CPDF_String*)this)->m_String, pCharMap); + } else if (m_Type == PDFOBJ_STREAM) { + CPDF_StreamAcc stream; + stream.LoadAllData((CPDF_Stream*)this, FALSE); + CFX_WideString result = PDF_DecodeText(stream.GetData(), stream.GetSize(), pCharMap); + return result; + } else if (m_Type == PDFOBJ_NAME) { + return PDF_DecodeText(((CPDF_Name*)this)->m_Name, pCharMap); + } + return CFX_WideString(); +} +void CPDF_Object::SetUnicodeText(FX_LPCWSTR pUnicodes, int len) +{ + if (this == NULL) { + return; + } + if (m_Type == PDFOBJ_STRING) { + ((CPDF_String*)this)->m_String = PDF_EncodeText(pUnicodes, len); + } else if (m_Type == PDFOBJ_STREAM) { + CFX_ByteString result = PDF_EncodeText(pUnicodes, len); + ((CPDF_Stream*)this)->SetData((FX_LPBYTE)(FX_LPCSTR)result, result.GetLength(), FALSE, FALSE); + } +} +CPDF_Number::CPDF_Number(int value) +{ + m_Type = PDFOBJ_NUMBER; + m_bInteger = TRUE; + m_Integer = value; +} +CPDF_Number::CPDF_Number(FX_FLOAT value) +{ + m_Type = PDFOBJ_NUMBER; + m_bInteger = FALSE; + m_Float = value; +} +CPDF_Number::CPDF_Number(FX_BOOL bInteger, void* pData) +{ + m_Type = PDFOBJ_NUMBER; + m_bInteger = bInteger; + m_Integer = *(int*)pData; +} +extern void FX_atonum(FX_BSTR, FX_BOOL&, void*); +CPDF_Number::CPDF_Number(FX_BSTR str) +{ + m_Type = PDFOBJ_NUMBER; + FX_atonum(str, m_bInteger, &m_Integer); +} +void CPDF_Number::SetString(FX_BSTR str) +{ + FX_atonum(str, m_bInteger, &m_Integer); +} +FX_BOOL CPDF_Number::Identical(CPDF_Number* pOther) const +{ + return m_bInteger == pOther->m_bInteger && m_Integer == pOther->m_Integer; +} +CFX_ByteString CPDF_Number::GetString() const +{ + return m_bInteger ? CFX_ByteString::FormatInteger(m_Integer, FXFORMAT_SIGNED) : CFX_ByteString::FormatFloat(m_Float); +} +void CPDF_Number::SetNumber(FX_FLOAT value) +{ + m_bInteger = FALSE; + m_Float = value; +} +CPDF_String::CPDF_String(const CFX_WideString& str) +{ + m_Type = PDFOBJ_STRING; + m_String = PDF_EncodeText(str, str.GetLength()); + m_bHex = FALSE; +} +CPDF_Array::~CPDF_Array() +{ + int size = m_Objects.GetSize(); + CPDF_Object** pList = (CPDF_Object**)m_Objects.GetData(); + for (int i = 0; i < size; i ++) { + pList[i]->Release(); + } +} +CFX_FloatRect CPDF_Array::GetRect() +{ + CFX_FloatRect rect; + if (this == NULL || m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 4) { + return rect; + } + rect.left = GetNumber(0); + rect.bottom = GetNumber(1); + rect.right = GetNumber(2); + rect.top = GetNumber(3); + return rect; +} +CFX_AffineMatrix CPDF_Array::GetMatrix() +{ + CFX_AffineMatrix matrix; + if (this == NULL || m_Type != PDFOBJ_ARRAY || m_Objects.GetSize() != 6) { + return matrix; + } + matrix.Set(GetNumber(0), GetNumber(1), GetNumber(2), GetNumber(3), GetNumber(4), GetNumber(5)); + return matrix; +} +CPDF_Object* CPDF_Array::GetElement(FX_DWORD i) const +{ + if (this == NULL) { + return NULL; + } + if (i >= (FX_DWORD)m_Objects.GetSize()) { + return NULL; + } + return (CPDF_Object*)m_Objects.GetAt(i); +} +CPDF_Object* CPDF_Array::GetElementValue(FX_DWORD i) const +{ + if (this == NULL) { + return NULL; + } + if (i >= (FX_DWORD)m_Objects.GetSize()) { + return NULL; + } + return ((CPDF_Object*)m_Objects.GetAt(i))->GetDirect(); +} +CFX_ByteString CPDF_Array::GetString(FX_DWORD i) const +{ + if (this && i < (FX_DWORD)m_Objects.GetSize()) { + CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); + return p->GetString(); + } + return CFX_ByteString(); +} +CFX_ByteStringC CPDF_Array::GetConstString(FX_DWORD i) const +{ + if (this && i < (FX_DWORD)m_Objects.GetSize()) { + CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); + return p->GetConstString(); + } + return CFX_ByteStringC(); +} +int CPDF_Array::GetInteger(FX_DWORD i) const +{ + if (this == NULL || i >= (FX_DWORD)m_Objects.GetSize()) { + return 0; + } + CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); + return p->GetInteger(); +} +FX_FLOAT CPDF_Array::GetNumber(FX_DWORD i) const +{ + if (this == NULL || i >= (FX_DWORD)m_Objects.GetSize()) { + return 0; + } + CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); + return p->GetNumber(); +} +CPDF_Dictionary* CPDF_Array::GetDict(FX_DWORD i) const +{ + CPDF_Object* p = GetElementValue(i); + if (p == NULL) { + return NULL; + } else if (p->GetType() == PDFOBJ_DICTIONARY) { + return (CPDF_Dictionary*)p; + } else if (p->GetType() == PDFOBJ_STREAM) { + return ((CPDF_Stream*)p)->GetDict(); + } + return NULL; +} +CPDF_Stream* CPDF_Array::GetStream(FX_DWORD i) const +{ + CPDF_Object* p = GetElementValue(i); + if (p == NULL || p->GetType() != PDFOBJ_STREAM) { + return NULL; + } + return (CPDF_Stream*)p; +} +CPDF_Array* CPDF_Array::GetArray(FX_DWORD i) const +{ + CPDF_Object* p = GetElementValue(i); + if (p == NULL || p->GetType() != PDFOBJ_ARRAY) { + return NULL; + } + return (CPDF_Array*)p; +} +void CPDF_Array::RemoveAt(FX_DWORD i) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + if (i >= (FX_DWORD)m_Objects.GetSize()) { + return; + } + CPDF_Object* p = (CPDF_Object*)m_Objects.GetAt(i); + p->Release(); + m_Objects.RemoveAt(i); +} +void CPDF_Array::SetAt(FX_DWORD i, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + ASSERT(i < (FX_DWORD)m_Objects.GetSize()); + if (i >= (FX_DWORD)m_Objects.GetSize()) { + return; + } + CPDF_Object* pOld = (CPDF_Object*)m_Objects.GetAt(i); + pOld->Release(); + if (pObj->GetObjNum()) { + ASSERT(pObjs != NULL); + pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); + } + m_Objects.SetAt(i, pObj); +} +void CPDF_Array::InsertAt(FX_DWORD index, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) +{ + ASSERT(pObj != NULL); + if (pObj->GetObjNum()) { + ASSERT(pObjs != NULL); + pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); + } + m_Objects.InsertAt(index, pObj); +} +void CPDF_Array::Add(CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) +{ + ASSERT(pObj != NULL); + if (pObj->GetObjNum()) { + ASSERT(pObjs != NULL); + pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); + } + m_Objects.Add(pObj); +} +void CPDF_Array::AddName(const CFX_ByteString& str) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + Add(FX_NEW CPDF_Name(str)); +} +void CPDF_Array::AddString(const CFX_ByteString& str) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + Add(FX_NEW CPDF_String(str)); +} +void CPDF_Array::AddInteger(int i) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + Add(FX_NEW CPDF_Number(i)); +} +void CPDF_Array::AddNumber(FX_FLOAT f) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + CPDF_Number* pNumber = FX_NEW CPDF_Number; + pNumber->SetNumber(f); + Add(pNumber); +} +void CPDF_Array::AddReference(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_ARRAY); + Add(FX_NEW CPDF_Reference(pDoc, objnum)); +} +FX_BOOL CPDF_Array::Identical(CPDF_Array* pOther) const +{ + if (m_Objects.GetSize() != pOther->m_Objects.GetSize()) { + return FALSE; + } + for (int i = 0; i < m_Objects.GetSize(); i ++) + if (!((CPDF_Object*)m_Objects[i])->IsIdentical((CPDF_Object*)pOther->m_Objects[i])) { + return FALSE; + } + return TRUE; +} +CPDF_Dictionary::~CPDF_Dictionary() +{ + FX_POSITION pos = m_Map.GetStartPosition(); + while (pos) { + FX_LPVOID value = m_Map.GetNextValue(pos); + ((CPDF_Object*)value)->Release(); + } +} +FX_POSITION CPDF_Dictionary::GetStartPos() const +{ + return m_Map.GetStartPosition(); +} +CPDF_Object* CPDF_Dictionary::GetNextElement(FX_POSITION& pos, CFX_ByteString& key) const +{ + if (pos == NULL) { + return NULL; + } + CPDF_Object* p; + m_Map.GetNextAssoc(pos, key, (FX_LPVOID&)p); + return p; +} +CPDF_Object* CPDF_Dictionary::GetElement(FX_BSTR key) const +{ + if (this == NULL) { + return NULL; + } + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + return p; +} +CPDF_Object* CPDF_Dictionary::GetElementValue(FX_BSTR key) const +{ + if (this == NULL) { + return NULL; + } + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + return p->GetDirect(); +} +CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetString(); + } + } + return CFX_ByteString(); +} +CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetConstString(); + } + } + return CFX_ByteStringC(); +} +CFX_WideString CPDF_Dictionary::GetUnicodeText(FX_BSTR key, CFX_CharMap* pCharMap) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + if(p->GetType() == PDFOBJ_REFERENCE) { + p = ((CPDF_Reference*)p)->GetDirect(); + return p->GetUnicodeText(pCharMap); + } else { + return p->GetUnicodeText(pCharMap); + } + } + } + return CFX_WideString(); +} +CFX_ByteString CPDF_Dictionary::GetString(FX_BSTR key, FX_BSTR def) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetString(); + } + } + return CFX_ByteString(def); +} +CFX_ByteStringC CPDF_Dictionary::GetConstString(FX_BSTR key, FX_BSTR def) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetConstString(); + } + } + return CFX_ByteStringC(def); +} +int CPDF_Dictionary::GetInteger(FX_BSTR key) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetInteger(); + } + } + return 0; +} +int CPDF_Dictionary::GetInteger(FX_BSTR key, int def) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetInteger(); + } + } + return def; +} +FX_FLOAT CPDF_Dictionary::GetNumber(FX_BSTR key) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p) { + return p->GetNumber(); + } + } + return 0; +} +FX_BOOL CPDF_Dictionary::GetBoolean(FX_BSTR key, FX_BOOL bDefault) const +{ + if (this) { + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p && p->GetType() == PDFOBJ_BOOLEAN) { + return p->GetInteger(); + } + } + return bDefault; +} +CPDF_Dictionary* CPDF_Dictionary::GetDict(FX_BSTR key) const +{ + CPDF_Object* p = GetElementValue(key); + if (p == NULL) { + return NULL; + } else if (p->GetType() == PDFOBJ_DICTIONARY) { + return (CPDF_Dictionary*)p; + } else if (p->GetType() == PDFOBJ_STREAM) { + return ((CPDF_Stream*)p)->GetDict(); + } + return NULL; +} +CPDF_Array* CPDF_Dictionary::GetArray(FX_BSTR key) const +{ + CPDF_Object* p = GetElementValue(key); + if (p == NULL || p->GetType() != PDFOBJ_ARRAY) { + return NULL; + } + return (CPDF_Array*)p; +} +CPDF_Stream* CPDF_Dictionary::GetStream(FX_BSTR key) const +{ + CPDF_Object* p = GetElementValue(key); + if (p == NULL || p->GetType() != PDFOBJ_STREAM) { + return NULL; + } + return (CPDF_Stream*)p; +} +CFX_FloatRect CPDF_Dictionary::GetRect(FX_BSTR key) const +{ + CFX_FloatRect rect; + CPDF_Array* pArray = GetArray(key); + if (pArray) { + rect = pArray->GetRect(); + } + return rect; +} +CFX_AffineMatrix CPDF_Dictionary::GetMatrix(FX_BSTR key) const +{ + CFX_AffineMatrix matrix; + CPDF_Array* pArray = GetArray(key); + if (pArray) { + matrix = pArray->GetMatrix(); + } + return matrix; +} +FX_BOOL CPDF_Dictionary::KeyExist(FX_BSTR key) const +{ + if (this == NULL) { + return FALSE; + } + FX_LPVOID value; + return m_Map.Lookup(key, value); +} +void CPDF_Dictionary::SetAt(FX_BSTR key, CPDF_Object* pObj, CPDF_IndirectObjects* pObjs) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p == pObj) { + return; + } + if (p) { + p->Release(); + } + if (pObj) { + if (pObj->GetObjNum()) { + ASSERT(pObjs != NULL); + pObj = CPDF_Reference::Create(pObjs, pObj->GetObjNum()); + } + m_Map.SetAt(key, pObj); + } else { + m_Map.RemoveKey(key); + } +} +void CPDF_Dictionary::AddValue(FX_BSTR key, CPDF_Object* pObj) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); + m_Map.AddValue(key, pObj); +} +void CPDF_Dictionary::RemoveAt(FX_BSTR key) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); + CPDF_Object* p = NULL; + m_Map.Lookup(key, (void*&)p); + if (p == NULL) { + return; + } + p->Release(); + m_Map.RemoveKey(key); +} +void CPDF_Dictionary::ReplaceKey(FX_BSTR oldkey, FX_BSTR newkey) +{ + ASSERT(this != NULL && m_Type == PDFOBJ_DICTIONARY); + CPDF_Object* p = NULL; + m_Map.Lookup(oldkey, (void*&)p); + if (p == NULL) { + return; + } + m_Map.RemoveKey(oldkey); + m_Map.SetAt(newkey, p); +} +FX_BOOL CPDF_Dictionary::Identical(CPDF_Dictionary* pOther) const +{ + if (this == NULL) { + if (pOther == NULL) { + return TRUE; + } + return FALSE; + } + if (pOther == NULL) { + return FALSE; + } + if (m_Map.GetCount() != pOther->m_Map.GetCount()) { + return FALSE; + } + FX_POSITION pos = m_Map.GetStartPosition(); + while (pos) { + CFX_ByteString key; + FX_LPVOID value; + m_Map.GetNextAssoc(pos, key, value); + if (!((CPDF_Object*)value)->IsIdentical(pOther->GetElement(key))) { + return FALSE; + } + } + return TRUE; +} +void CPDF_Dictionary::SetAtInteger(FX_BSTR key, int i) +{ + SetAt(key, FX_NEW CPDF_Number(i)); +} +void CPDF_Dictionary::SetAtName(FX_BSTR key, const CFX_ByteString& name) +{ + SetAt(key, FX_NEW CPDF_Name(name)); +} +void CPDF_Dictionary::SetAtString(FX_BSTR key, const CFX_ByteString& str) +{ + SetAt(key, FX_NEW CPDF_String(str)); +} +void CPDF_Dictionary::SetAtReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum) +{ + SetAt(key, FX_NEW CPDF_Reference(pDoc, objnum)); +} +void CPDF_Dictionary::AddReference(FX_BSTR key, CPDF_IndirectObjects* pDoc, FX_DWORD objnum) +{ + AddValue(key, FX_NEW CPDF_Reference(pDoc, objnum)); +} +void CPDF_Dictionary::SetAtNumber(FX_BSTR key, FX_FLOAT f) +{ + CPDF_Number* pNumber = FX_NEW CPDF_Number; + pNumber->SetNumber(f); + SetAt(key, pNumber); +} +void CPDF_Dictionary::SetAtBoolean(FX_BSTR key, FX_BOOL bValue) +{ + SetAt(key, FX_NEW CPDF_Boolean(bValue)); +} +void CPDF_Dictionary::SetAtRect(FX_BSTR key, const CFX_FloatRect& rect) +{ + CPDF_Array* pArray = FX_NEW CPDF_Array; + pArray->AddNumber(rect.left); + pArray->AddNumber(rect.bottom); + pArray->AddNumber(rect.right); + pArray->AddNumber(rect.top); + SetAt(key, pArray); +} +void CPDF_Dictionary::SetAtMatrix(FX_BSTR key, const CFX_AffineMatrix& matrix) +{ + CPDF_Array* pArray = FX_NEW CPDF_Array; + pArray->AddNumber16(matrix.a); + pArray->AddNumber16(matrix.b); + pArray->AddNumber16(matrix.c); + pArray->AddNumber16(matrix.d); + pArray->AddNumber(matrix.e); + pArray->AddNumber(matrix.f); + SetAt(key, pArray); +} +CPDF_Stream::CPDF_Stream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict) +{ + m_Type = PDFOBJ_STREAM; + m_pDict = pDict; + m_dwSize = size; + m_GenNum = (FX_DWORD) - 1; + m_pDataBuf = pData; + m_pCryptoHandler = NULL; +} +CPDF_Stream::~CPDF_Stream() +{ + if (m_GenNum == (FX_DWORD) - 1 && m_pDataBuf != NULL) { + FX_Free(m_pDataBuf); + } + if (m_pDict) { + m_pDict->Release(); + } +} +void CPDF_Stream::InitStream(CPDF_Dictionary* pDict) +{ + if (pDict) { + if (m_pDict) { + m_pDict->Release(); + } + m_pDict = pDict; + } + if (m_GenNum == (FX_DWORD) - 1) { + if (m_pDataBuf) { + FX_Free(m_pDataBuf); + } + } + m_GenNum = 0; + m_pFile = NULL; + m_pCryptoHandler = NULL; + m_FileOffset = 0; +} +void CPDF_Stream::InitStream(FX_LPBYTE pData, FX_DWORD size, CPDF_Dictionary* pDict) +{ + InitStream(pDict); + m_GenNum = (FX_DWORD) - 1; + m_pDataBuf = FX_Alloc(FX_BYTE, size); + if (pData) { + FXSYS_memcpy32(m_pDataBuf, pData, size); + } + m_dwSize = size; + if (m_pDict) { + m_pDict->SetAtInteger(FX_BSTRC("Length"), size); + } +} +void CPDF_Stream::SetData(FX_LPCBYTE pData, FX_DWORD size, FX_BOOL bCompressed, FX_BOOL bKeepBuf) +{ + if (m_GenNum == (FX_DWORD) - 1) { + if (m_pDataBuf) { + FX_Free(m_pDataBuf); + } + } else { + m_GenNum = (FX_DWORD) - 1; + m_pCryptoHandler = NULL; + } + if (bKeepBuf) { + m_pDataBuf = (FX_LPBYTE)pData; + } else { + m_pDataBuf = FX_Alloc(FX_BYTE, size); + if (pData) { + FXSYS_memcpy32(m_pDataBuf, pData, size); + } + } + m_dwSize = size; + if (m_pDict == NULL) { + m_pDict = FX_NEW CPDF_Dictionary; + } + m_pDict->SetAtInteger(FX_BSTRC("Length"), size); + if (!bCompressed) { + m_pDict->RemoveAt(FX_BSTRC("Filter")); + m_pDict->RemoveAt(FX_BSTRC("DecodeParms")); + } +} +FX_BOOL CPDF_Stream::ReadRawData(FX_FILESIZE offset, FX_LPBYTE buf, FX_DWORD size) const +{ + if ((m_GenNum != (FX_DWORD) - 1) && m_pFile) { + return m_pFile->ReadBlock(buf, m_FileOffset + offset, size); + } + if (m_pDataBuf) { + FXSYS_memcpy32(buf, m_pDataBuf + offset, size); + } + return TRUE; +} +void CPDF_Stream::InitStream(IFX_FileRead *pFile, CPDF_Dictionary* pDict) +{ + InitStream(pDict); + m_pFile = pFile; + m_dwSize = (FX_DWORD)pFile->GetSize(); + if (m_pDict) { + m_pDict->SetAtInteger(FX_BSTRC("Length"), m_dwSize); + } +} +FX_BOOL CPDF_Stream::Identical(CPDF_Stream* pOther) const +{ + if (!m_pDict->Identical(pOther->m_pDict)) { + return FALSE; + } + if (m_dwSize != pOther->m_dwSize) { + return FALSE; + } + if (m_GenNum != (FX_DWORD) - 1 && pOther->m_GenNum != (FX_DWORD) - 1) { + if (m_pFile == pOther->m_pFile && m_pFile == NULL) { + return TRUE; + } + if (!m_pFile || !pOther->m_pFile) { + return FALSE; + } + FX_BYTE srcBuf[1024]; + FX_BYTE destBuf[1024]; + FX_DWORD size = m_dwSize; + FX_DWORD srcOffset = m_FileOffset; + FX_DWORD destOffset = pOther->m_FileOffset; + if (m_pFile == pOther->m_pFile && srcOffset == destOffset) { + return TRUE; + } + while (size > 0) { + FX_DWORD actualSize = size > 1024 ? 1024 : size; + m_pFile->ReadBlock(srcBuf, srcOffset, actualSize); + pOther->m_pFile->ReadBlock(destBuf, destOffset, actualSize); + if (FXSYS_memcmp32(srcBuf, destBuf, actualSize) != 0) { + return FALSE; + } + size -= actualSize; + srcOffset += actualSize; + destOffset += actualSize; + } + return TRUE; + } + if (m_GenNum != (FX_DWORD) - 1 || pOther->m_GenNum != (FX_DWORD) - 1) { + IFX_FileRead* pFile = NULL; + FX_LPBYTE pBuf = NULL; + FX_DWORD offset = 0; + if (m_GenNum != (FX_DWORD) - 1) { + pFile = m_pFile; + pBuf = pOther->m_pDataBuf; + offset = m_FileOffset; + } + if (pOther->m_GenNum != (FX_DWORD) - 1) { + pFile = pOther->m_pFile; + pBuf = m_pDataBuf; + offset = pOther->m_FileOffset; + } + if (NULL == pBuf) { + return FALSE; + } + FX_BYTE srcBuf[1024]; + FX_DWORD size = m_dwSize; + while (size > 0) { + FX_DWORD actualSize = size > 1024 ? 1024 : size; + m_pFile->ReadBlock(srcBuf, offset, actualSize); + if (FXSYS_memcmp32(srcBuf, pBuf, actualSize) != 0) { + return FALSE; + } + pBuf += actualSize; + size -= actualSize; + offset += actualSize; + } + return TRUE; + } + return FXSYS_memcmp32(m_pDataBuf, pOther->m_pDataBuf, m_dwSize) == 0; +} +CPDF_Stream* CPDF_Stream::Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const +{ + CPDF_Dictionary *pCloneDict = (CPDF_Dictionary*)m_pDict->Clone(bDirect); + IFX_FileStream *pFS = NULL; + if (lpfCallback) { + pFS = lpfCallback((CPDF_Stream*)this, pUserData); + } + if (!pFS) { + CPDF_StreamAcc acc; + acc.LoadAllData(this, TRUE); + FX_DWORD streamSize = acc.GetSize(); + CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, pCloneDict); + return pObj; + } + CPDF_Stream* pObj = FX_NEW CPDF_Stream(NULL, 0, NULL); + CPDF_StreamFilter *pSF = GetStreamFilter(TRUE); + if (pSF) { + FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, 4096); + FX_DWORD dwRead; + do { + dwRead = pSF->ReadBlock(pBuf, 4096); + if (dwRead) { + pFS->WriteBlock(pBuf, dwRead); + } + } while (dwRead == 4096); + pFS->Flush(); + FX_Free(pBuf); + delete pSF; + } + pObj->InitStream((IFX_FileRead*)pFS, pCloneDict); + return pObj; +} +extern FX_BOOL PDF_DataDecode(FX_LPCBYTE src_buf, FX_DWORD src_size, const CPDF_Dictionary* pDict, + FX_LPBYTE& dest_buf, FX_DWORD& dest_size, CFX_ByteString& ImageEncoding, + CPDF_Dictionary*& pImageParms, FX_DWORD estimated_size, FX_BOOL bImageAcc); +CPDF_StreamAcc::CPDF_StreamAcc() +{ + m_bNewBuf = FALSE; + m_pData = NULL; + m_dwSize = 0; + m_pImageParam = NULL; + m_pStream = NULL; + m_pSrcData = NULL; +} +void CPDF_StreamAcc::LoadAllData(const CPDF_Stream* pStream, FX_BOOL bRawAccess, FX_DWORD estimated_size, + FX_BOOL bImageAcc) +{ + if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM) { + return; + } + m_pStream = pStream; + if (pStream->IsMemoryBased() && + (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess)) { + m_dwSize = pStream->m_dwSize; + m_pData = (FX_LPBYTE)pStream->m_pDataBuf; + return; + } + FX_LPBYTE pSrcData; + FX_DWORD dwSrcSize = pStream->m_dwSize; + if (dwSrcSize == 0) { + return; + } + if (!pStream->IsMemoryBased()) { + pSrcData = m_pSrcData = FX_Alloc(FX_BYTE, dwSrcSize); + if (!pSrcData || !pStream->ReadRawData(0, pSrcData, dwSrcSize)) { + return; + } + } else { + pSrcData = pStream->m_pDataBuf; + } + FX_LPBYTE pDecryptedData; + FX_DWORD dwDecryptedSize; + if (pStream->m_pCryptoHandler) { + CFX_BinaryBuf dest_buf; + dest_buf.EstimateSize(pStream->m_pCryptoHandler->DecryptGetSize(dwSrcSize)); + FX_LPVOID context = pStream->m_pCryptoHandler->DecryptStart(pStream->GetObjNum(), pStream->m_GenNum); + pStream->m_pCryptoHandler->DecryptStream(context, pSrcData, dwSrcSize, dest_buf); + pStream->m_pCryptoHandler->DecryptFinish(context, dest_buf); + pDecryptedData = dest_buf.GetBuffer(); + dwDecryptedSize = dest_buf.GetSize(); + dest_buf.DetachBuffer(); + } else { + pDecryptedData = pSrcData; + dwDecryptedSize = dwSrcSize; + } + if (!pStream->GetDict()->KeyExist(FX_BSTRC("Filter")) || bRawAccess) { + m_pData = pDecryptedData; + m_dwSize = dwDecryptedSize; + } else { + FX_BOOL bRet = PDF_DataDecode(pDecryptedData, dwDecryptedSize, m_pStream->GetDict(), + m_pData, m_dwSize, m_ImageDecoder, m_pImageParam, estimated_size, bImageAcc); + if (!bRet) { + m_pData = pDecryptedData; + m_dwSize = dwDecryptedSize; + } + } + if (pSrcData != pStream->m_pDataBuf && pSrcData != m_pData) { + FX_Free(pSrcData); + } + if (pDecryptedData != pSrcData && pDecryptedData != m_pData) { + FX_Free(pDecryptedData); + } + m_pSrcData = NULL; + m_bNewBuf = m_pData != pStream->m_pDataBuf; +} +CPDF_StreamAcc::~CPDF_StreamAcc() +{ + if (m_bNewBuf && m_pData) { + FX_Free(m_pData); + } + if (m_pSrcData) { + FX_Free(m_pSrcData); + } +} +FX_LPCBYTE CPDF_StreamAcc::GetData() const +{ + if (m_bNewBuf) { + return m_pData; + } + if (!m_pStream) { + return NULL; + } + return m_pStream->m_pDataBuf; +} +FX_DWORD CPDF_StreamAcc::GetSize() const +{ + if (m_bNewBuf) { + return m_dwSize; + } + if (!m_pStream) { + return 0; + } + return m_pStream->m_dwSize; +} +FX_LPBYTE CPDF_StreamAcc::DetachData() +{ + if (m_bNewBuf) { + FX_LPBYTE p = m_pData; + m_pData = NULL; + m_dwSize = 0; + return p; + } + FX_LPBYTE p = FX_Alloc(FX_BYTE, m_dwSize); + if (p == NULL) { + return NULL; + } + FXSYS_memcpy32(p, m_pData, m_dwSize); + return p; +} +void CPDF_Reference::SetRef(CPDF_IndirectObjects* pDoc, FX_DWORD objnum) +{ + m_pObjList = pDoc; + m_RefObjNum = objnum; +} +CPDF_IndirectObjects::CPDF_IndirectObjects(IPDF_DocParser* pParser) +{ + m_pParser = pParser; + m_IndirectObjs.InitHashTable(1013); + if (pParser) { + m_LastObjNum = m_pParser->GetLastObjNum(); + } else { + m_LastObjNum = 0; + } +} +CPDF_IndirectObjects::~CPDF_IndirectObjects() +{ + FX_POSITION pos = m_IndirectObjs.GetStartPosition(); + while (pos) { + FX_LPVOID key, value; + m_IndirectObjs.GetNextAssoc(pos, key, value); + ((CPDF_Object*)value)->Destroy(); + } +} +CPDF_Object* CPDF_IndirectObjects::GetIndirectObject(FX_DWORD objnum, struct PARSE_CONTEXT* pContext) +{ + if (objnum == 0) { + return NULL; + } + FX_LPVOID value; + { + if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { + if (((CPDF_Object*)value)->GetObjNum() == -1) { + return NULL; + } + return (CPDF_Object*)value; + } + } + CPDF_Object* pObj = NULL; + if (m_pParser) { + pObj = m_pParser->ParseIndirectObject(this, objnum, pContext); + } + if (pObj == NULL) { + return NULL; + } + pObj->m_ObjNum = objnum; + if (m_LastObjNum < objnum) { + m_LastObjNum = objnum; + } + if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { + if (value) { + ((CPDF_Object *)value)->Destroy(); + } + } + m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj); + return pObj; +} +int CPDF_IndirectObjects::GetIndirectType(FX_DWORD objnum) +{ + FX_LPVOID value; + if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { + return ((CPDF_Object*)value)->GetType(); + } + if (m_pParser) { + PARSE_CONTEXT context; + FXSYS_memset32(&context, 0, sizeof(PARSE_CONTEXT)); + context.m_Flags = PDFPARSE_TYPEONLY; + return (int)(FX_UINTPTR)m_pParser->ParseIndirectObject(this, objnum, &context); + } + return 0; +} +FX_DWORD CPDF_IndirectObjects::AddIndirectObject(CPDF_Object* pObj) +{ + if (pObj->m_ObjNum) { + return pObj->m_ObjNum; + } + m_LastObjNum ++; + m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)m_LastObjNum, pObj); + pObj->m_ObjNum = m_LastObjNum; + return m_LastObjNum; +} +void CPDF_IndirectObjects::ReleaseIndirectObject(FX_DWORD objnum) +{ + FX_LPVOID value; + if (!m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { + return; + } + if (((CPDF_Object*)value)->GetObjNum() == -1) { + return; + } + ((CPDF_Object*)value)->Destroy(); + m_IndirectObjs.RemoveKey((FX_LPVOID)(FX_UINTPTR)objnum); +} +void CPDF_IndirectObjects::InsertIndirectObject(FX_DWORD objnum, CPDF_Object* pObj) +{ + if (objnum == 0 || pObj == NULL) { + return; + } + FX_LPVOID value; + if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, value)) { + ((CPDF_Object*)value)->Destroy(); + } + pObj->m_ObjNum = objnum; + m_IndirectObjs.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pObj); + if (m_LastObjNum < objnum) { + m_LastObjNum = objnum; + } +} +FX_DWORD CPDF_IndirectObjects::GetLastObjNum() const +{ + return m_LastObjNum; +} diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.cpp index cc3d29c9ed..7559bcee91 100644 --- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.cpp +++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_utility.cpp @@ -1,453 +1,453 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fpdfapi/fpdf_parser.h" -extern const FX_LPCSTR _PDF_CharType = - "WRRRRRRRRWWRWWRRRRRRRRRRRRRRRRRR" - "WRRRRDRRDDRNRNNDNNNNNNNNNNRRDRDR" - "RRRRRRRRRRRRRRRRRRRRRRRRRRRDRDRR" - "RRRRRRRRRRRRRRRRRRRRRRRRRRRDRDRR" - "WRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR" - "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR" - "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR" - "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRW"; -#ifndef MAX_PATH -#define MAX_PATH 4096 -#endif -CPDF_SimpleParser::CPDF_SimpleParser(FX_LPCBYTE pData, FX_DWORD dwSize) -{ - m_pData = pData; - m_dwSize = dwSize; - m_dwCurPos = 0; -} -CPDF_SimpleParser::CPDF_SimpleParser(FX_BSTR str) -{ - m_pData = str; - m_dwSize = str.GetLength(); - m_dwCurPos = 0; -} -void CPDF_SimpleParser::ParseWord(FX_LPCBYTE& pStart, FX_DWORD& dwSize, int& type) -{ - pStart = NULL; - dwSize = 0; - type = PDFWORD_EOF; - FX_BYTE ch; - char chartype; - while (1) { - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - chartype = _PDF_CharType[ch]; - while (chartype == 'W') { - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - chartype = _PDF_CharType[ch]; - } - if (ch != '%') { - break; - } - while (1) { - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - if (ch == '\r' || ch == '\n') { - break; - } - } - chartype = _PDF_CharType[ch]; - } - FX_DWORD start_pos = m_dwCurPos - 1; - pStart = m_pData + start_pos; - if (chartype == 'D') { - if (ch == '/') { - while (1) { - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - chartype = _PDF_CharType[ch]; - if (chartype != 'R' && chartype != 'N') { - m_dwCurPos --; - dwSize = m_dwCurPos - start_pos; - type = PDFWORD_NAME; - return; - } - } - } else { - type = PDFWORD_DELIMITER; - dwSize = 1; - if (ch == '<') { - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - if (ch == '<') { - dwSize = 2; - } else { - m_dwCurPos --; - } - } else if (ch == '>') { - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - if (ch == '>') { - dwSize = 2; - } else { - m_dwCurPos --; - } - } - } - return; - } - type = PDFWORD_NUMBER; - dwSize = 1; - while (1) { - if (chartype != 'N') { - type = PDFWORD_TEXT; - } - if (m_dwSize <= m_dwCurPos) { - return; - } - ch = m_pData[m_dwCurPos++]; - chartype = _PDF_CharType[ch]; - if (chartype == 'D' || chartype == 'W') { - m_dwCurPos --; - break; - } - dwSize ++; - } -} -CFX_ByteStringC CPDF_SimpleParser::GetWord() -{ - FX_LPCBYTE pStart; - FX_DWORD dwSize; - int type; - ParseWord(pStart, dwSize, type); - if (dwSize == 1 && pStart[0] == '<') { - while (m_dwCurPos < m_dwSize && m_pData[m_dwCurPos] != '>') { - m_dwCurPos ++; - } - if (m_dwCurPos < m_dwSize) { - m_dwCurPos ++; - } - return CFX_ByteStringC(pStart, (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); - } else if (dwSize == 1 && pStart[0] == '(') { - int level = 1; - while (m_dwCurPos < m_dwSize) { - if (m_pData[m_dwCurPos] == ')') { - level --; - if (level == 0) { - break; - } - } - if (m_pData[m_dwCurPos] == '\\') { - if (m_dwSize <= m_dwCurPos) { - break; - } - m_dwCurPos ++; - } else if (m_pData[m_dwCurPos] == '(') { - level ++; - } - if (m_dwSize <= m_dwCurPos) { - break; - } - m_dwCurPos ++; - } - if (m_dwCurPos < m_dwSize) { - m_dwCurPos ++; - } - return CFX_ByteStringC(pStart, (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); - } - return CFX_ByteStringC(pStart, dwSize); -} -FX_BOOL CPDF_SimpleParser::SearchToken(FX_BSTR token) -{ - int token_len = token.GetLength(); - while (m_dwCurPos < m_dwSize - token_len) { - if (FXSYS_memcmp32(m_pData + m_dwCurPos, token, token_len) == 0) { - break; - } - m_dwCurPos ++; - } - if (m_dwCurPos == m_dwSize - token_len) { - return FALSE; - } - m_dwCurPos += token_len; - return TRUE; -} -FX_BOOL CPDF_SimpleParser::SkipWord(FX_BSTR token) -{ - while (1) { - CFX_ByteStringC word = GetWord(); - if (word.IsEmpty()) { - return FALSE; - } - if (word == token) { - return TRUE; - } - } - return FALSE; -} -FX_BOOL CPDF_SimpleParser::FindTagPair(FX_BSTR start_token, FX_BSTR end_token, - FX_DWORD& start_pos, FX_DWORD& end_pos) -{ - if (!start_token.IsEmpty()) { - if (!SkipWord(start_token)) { - return FALSE; - } - start_pos = m_dwCurPos; - } - while (1) { - end_pos = m_dwCurPos; - CFX_ByteStringC word = GetWord(); - if (word.IsEmpty()) { - return FALSE; - } - if (word == end_token) { - return TRUE; - } - } - return FALSE; -} -FX_BOOL CPDF_SimpleParser::FindTagParam(FX_BSTR token, int nParams) -{ - nParams ++; - FX_DWORD* pBuf = FX_Alloc(FX_DWORD, nParams); - int buf_index = 0; - int buf_count = 0; - while (1) { - pBuf[buf_index++] = m_dwCurPos; - if (buf_index == nParams) { - buf_index = 0; - } - buf_count ++; - if (buf_count > nParams) { - buf_count = nParams; - } - CFX_ByteStringC word = GetWord(); - if (word.IsEmpty()) { - FX_Free(pBuf); - return FALSE; - } - if (word == token) { - if (buf_count < nParams) { - continue; - } - m_dwCurPos = pBuf[buf_index]; - FX_Free(pBuf); - return TRUE; - } - } - return FALSE; -} -static int _hex2dec(char ch) -{ - if (ch >= '0' && ch <= '9') { - return ch - '0'; - } - if (ch >= 'a' && ch <= 'f') { - return ch - 'a' + 10; - } - if (ch >= 'A' && ch <= 'F') { - return ch - 'A' + 10; - } - return 0; -} -CFX_ByteString PDF_NameDecode(FX_BSTR bstr) -{ - int size = bstr.GetLength(); - FX_LPCSTR pSrc = bstr.GetCStr(); - if (FXSYS_memchr(pSrc, '#', size) == NULL) { - return bstr; - } - CFX_ByteString result; - FX_LPSTR pDestStart = result.GetBuffer(size); - FX_LPSTR pDest = pDestStart; - for (int i = 0; i < size; i ++) { - if (pSrc[i] == '#' && i < size - 2) { - *pDest ++ = _hex2dec(pSrc[i + 1]) * 16 + _hex2dec(pSrc[i + 2]); - i += 2; - } else { - *pDest ++ = pSrc[i]; - } - } - result.ReleaseBuffer((FX_STRSIZE)(pDest - pDestStart)); - return result; -} -CFX_ByteString PDF_NameDecode(const CFX_ByteString& orig) -{ - if (FXSYS_memchr((FX_LPCSTR)orig, '#', orig.GetLength()) == NULL) { - return orig; - } - return PDF_NameDecode(CFX_ByteStringC(orig)); -} -CFX_ByteString PDF_NameEncode(const CFX_ByteString& orig) -{ - FX_LPBYTE src_buf = (FX_LPBYTE)(FX_LPCSTR)orig; - int src_len = orig.GetLength(); - int dest_len = 0; - int i; - for (i = 0; i < src_len; i ++) { - FX_BYTE ch = src_buf[i]; - if (ch >= 0x80 || _PDF_CharType[ch] == 'W' || ch == '#' || - _PDF_CharType[ch] == 'D') { - dest_len += 3; - } else { - dest_len ++; - } - } - if (dest_len == src_len) { - return orig; - } - CFX_ByteString res; - FX_LPSTR dest_buf = res.GetBuffer(dest_len); - dest_len = 0; - for (i = 0; i < src_len; i ++) { - FX_BYTE ch = src_buf[i]; - if (ch >= 0x80 || _PDF_CharType[ch] == 'W' || ch == '#' || - _PDF_CharType[ch] == 'D') { - dest_buf[dest_len++] = '#'; - dest_buf[dest_len++] = "0123456789ABCDEF"[ch / 16]; - dest_buf[dest_len++] = "0123456789ABCDEF"[ch % 16]; - } else { - dest_buf[dest_len++] = ch; - } - } - dest_buf[dest_len] = 0; - res.ReleaseBuffer(); - return res; -} -CFX_ByteTextBuf& operator << (CFX_ByteTextBuf& buf, const CPDF_Object* pObj) -{ - if (pObj == NULL) { - buf << FX_BSTRC(" null"); - return buf; - } - switch (pObj->GetType()) { - case PDFOBJ_NULL: - buf << FX_BSTRC(" null"); - break; - case PDFOBJ_BOOLEAN: - case PDFOBJ_NUMBER: - buf << " " << pObj->GetString(); - break; - case PDFOBJ_STRING: { - CFX_ByteString str = pObj->GetString(); - FX_BOOL bHex = ((CPDF_String*)pObj)->IsHex(); - buf << PDF_EncodeString(str, bHex); - break; - } - case PDFOBJ_NAME: { - CFX_ByteString str = pObj->GetString(); - buf << FX_BSTRC("/") << PDF_NameEncode(str); - break; - } - case PDFOBJ_REFERENCE: { - CPDF_Reference* p = (CPDF_Reference*)pObj; - buf << " " << p->GetRefObjNum() << FX_BSTRC(" 0 R "); - break; - } - case PDFOBJ_ARRAY: { - CPDF_Array* p = (CPDF_Array*)pObj; - buf << FX_BSTRC("["); - for (FX_DWORD i = 0; i < p->GetCount(); i ++) { - CPDF_Object* pElement = p->GetElement(i); - if (pElement->GetObjNum()) { - buf << " " << pElement->GetObjNum() << FX_BSTRC(" 0 R"); - } else { - buf << pElement; - } - } - buf << FX_BSTRC("]"); - break; - } - case PDFOBJ_DICTIONARY: { - CPDF_Dictionary* p = (CPDF_Dictionary*)pObj; - buf << FX_BSTRC("<<"); - FX_POSITION pos = p->GetStartPos(); - while (pos) { - CFX_ByteString key; - CPDF_Object* pValue = p->GetNextElement(pos, key); - buf << FX_BSTRC("/") << PDF_NameEncode(key); - if (pValue->GetObjNum()) { - buf << " " << pValue->GetObjNum() << FX_BSTRC(" 0 R "); - } else { - buf << pValue; - } - } - buf << FX_BSTRC(">>"); - break; - } - case PDFOBJ_STREAM: { - CPDF_Stream* p = (CPDF_Stream*)pObj; - buf << p->GetDict() << FX_BSTRC("stream\r\n"); - CPDF_StreamAcc acc; - acc.LoadAllData(p, TRUE); - buf.AppendBlock(acc.GetData(), acc.GetSize()); - buf << FX_BSTRC("\r\nendstream"); - break; - } - default: - ASSERT(FALSE); - break; - } - return buf; -} -FX_FLOAT PDF_ClipFloat(FX_FLOAT f) -{ - if (f < 0) { - return 0; - } - if (f > 1.0f) { - return 1.0f; - } - return f; -} -static CPDF_Object* SearchNumberNode(CPDF_Dictionary* pNode, int num) -{ - CPDF_Array* pLimits = pNode->GetArray("Limits"); - if (pLimits && (num < pLimits->GetInteger(0) || num > pLimits->GetInteger(1))) { - return NULL; - } - CPDF_Array* pNumbers = pNode->GetArray("Nums"); - if (pNumbers) { - FX_DWORD dwCount = pNumbers->GetCount() / 2; - for (FX_DWORD i = 0; i < dwCount; i ++) { - int index = pNumbers->GetInteger(i * 2); - if (num == index) { - return pNumbers->GetElementValue(i * 2 + 1); - } - if (index > num) { - break; - } - } - return NULL; - } - CPDF_Array* pKids = pNode->GetArray("Kids"); - if (pKids == NULL) { - return NULL; - } - for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) { - CPDF_Dictionary* pKid = pKids->GetDict(i); - if (pKid == NULL) { - continue; - } - CPDF_Object* pFound = SearchNumberNode(pKid, num); - if (pFound) { - return pFound; - } - } - return NULL; -} -CPDF_Object* CPDF_NumberTree::LookupValue(int num) -{ - return SearchNumberNode(m_pRoot, num); -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fpdfapi/fpdf_parser.h" +extern const FX_LPCSTR _PDF_CharType = + "WRRRRRRRRWWRWWRRRRRRRRRRRRRRRRRR" + "WRRRRDRRDDRNRNNDNNNNNNNNNNRRDRDR" + "RRRRRRRRRRRRRRRRRRRRRRRRRRRDRDRR" + "RRRRRRRRRRRRRRRRRRRRRRRRRRRDRDRR" + "WRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR" + "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR" + "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR" + "RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRW"; +#ifndef MAX_PATH +#define MAX_PATH 4096 +#endif +CPDF_SimpleParser::CPDF_SimpleParser(FX_LPCBYTE pData, FX_DWORD dwSize) +{ + m_pData = pData; + m_dwSize = dwSize; + m_dwCurPos = 0; +} +CPDF_SimpleParser::CPDF_SimpleParser(FX_BSTR str) +{ + m_pData = str; + m_dwSize = str.GetLength(); + m_dwCurPos = 0; +} +void CPDF_SimpleParser::ParseWord(FX_LPCBYTE& pStart, FX_DWORD& dwSize, int& type) +{ + pStart = NULL; + dwSize = 0; + type = PDFWORD_EOF; + FX_BYTE ch; + char chartype; + while (1) { + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + chartype = _PDF_CharType[ch]; + while (chartype == 'W') { + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + chartype = _PDF_CharType[ch]; + } + if (ch != '%') { + break; + } + while (1) { + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + if (ch == '\r' || ch == '\n') { + break; + } + } + chartype = _PDF_CharType[ch]; + } + FX_DWORD start_pos = m_dwCurPos - 1; + pStart = m_pData + start_pos; + if (chartype == 'D') { + if (ch == '/') { + while (1) { + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + chartype = _PDF_CharType[ch]; + if (chartype != 'R' && chartype != 'N') { + m_dwCurPos --; + dwSize = m_dwCurPos - start_pos; + type = PDFWORD_NAME; + return; + } + } + } else { + type = PDFWORD_DELIMITER; + dwSize = 1; + if (ch == '<') { + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + if (ch == '<') { + dwSize = 2; + } else { + m_dwCurPos --; + } + } else if (ch == '>') { + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + if (ch == '>') { + dwSize = 2; + } else { + m_dwCurPos --; + } + } + } + return; + } + type = PDFWORD_NUMBER; + dwSize = 1; + while (1) { + if (chartype != 'N') { + type = PDFWORD_TEXT; + } + if (m_dwSize <= m_dwCurPos) { + return; + } + ch = m_pData[m_dwCurPos++]; + chartype = _PDF_CharType[ch]; + if (chartype == 'D' || chartype == 'W') { + m_dwCurPos --; + break; + } + dwSize ++; + } +} +CFX_ByteStringC CPDF_SimpleParser::GetWord() +{ + FX_LPCBYTE pStart; + FX_DWORD dwSize; + int type; + ParseWord(pStart, dwSize, type); + if (dwSize == 1 && pStart[0] == '<') { + while (m_dwCurPos < m_dwSize && m_pData[m_dwCurPos] != '>') { + m_dwCurPos ++; + } + if (m_dwCurPos < m_dwSize) { + m_dwCurPos ++; + } + return CFX_ByteStringC(pStart, (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); + } else if (dwSize == 1 && pStart[0] == '(') { + int level = 1; + while (m_dwCurPos < m_dwSize) { + if (m_pData[m_dwCurPos] == ')') { + level --; + if (level == 0) { + break; + } + } + if (m_pData[m_dwCurPos] == '\\') { + if (m_dwSize <= m_dwCurPos) { + break; + } + m_dwCurPos ++; + } else if (m_pData[m_dwCurPos] == '(') { + level ++; + } + if (m_dwSize <= m_dwCurPos) { + break; + } + m_dwCurPos ++; + } + if (m_dwCurPos < m_dwSize) { + m_dwCurPos ++; + } + return CFX_ByteStringC(pStart, (FX_STRSIZE)(m_dwCurPos - (pStart - m_pData))); + } + return CFX_ByteStringC(pStart, dwSize); +} +FX_BOOL CPDF_SimpleParser::SearchToken(FX_BSTR token) +{ + int token_len = token.GetLength(); + while (m_dwCurPos < m_dwSize - token_len) { + if (FXSYS_memcmp32(m_pData + m_dwCurPos, token, token_len) == 0) { + break; + } + m_dwCurPos ++; + } + if (m_dwCurPos == m_dwSize - token_len) { + return FALSE; + } + m_dwCurPos += token_len; + return TRUE; +} +FX_BOOL CPDF_SimpleParser::SkipWord(FX_BSTR token) +{ + while (1) { + CFX_ByteStringC word = GetWord(); + if (word.IsEmpty()) { + return FALSE; + } + if (word == token) { + return TRUE; + } + } + return FALSE; +} +FX_BOOL CPDF_SimpleParser::FindTagPair(FX_BSTR start_token, FX_BSTR end_token, + FX_DWORD& start_pos, FX_DWORD& end_pos) +{ + if (!start_token.IsEmpty()) { + if (!SkipWord(start_token)) { + return FALSE; + } + start_pos = m_dwCurPos; + } + while (1) { + end_pos = m_dwCurPos; + CFX_ByteStringC word = GetWord(); + if (word.IsEmpty()) { + return FALSE; + } + if (word == end_token) { + return TRUE; + } + } + return FALSE; +} +FX_BOOL CPDF_SimpleParser::FindTagParam(FX_BSTR token, int nParams) +{ + nParams ++; + FX_DWORD* pBuf = FX_Alloc(FX_DWORD, nParams); + int buf_index = 0; + int buf_count = 0; + while (1) { + pBuf[buf_index++] = m_dwCurPos; + if (buf_index == nParams) { + buf_index = 0; + } + buf_count ++; + if (buf_count > nParams) { + buf_count = nParams; + } + CFX_ByteStringC word = GetWord(); + if (word.IsEmpty()) { + FX_Free(pBuf); + return FALSE; + } + if (word == token) { + if (buf_count < nParams) { + continue; + } + m_dwCurPos = pBuf[buf_index]; + FX_Free(pBuf); + return TRUE; + } + } + return FALSE; +} +static int _hex2dec(char ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } + if (ch >= 'A' && ch <= 'F') { + return ch - 'A' + 10; + } + return 0; +} +CFX_ByteString PDF_NameDecode(FX_BSTR bstr) +{ + int size = bstr.GetLength(); + FX_LPCSTR pSrc = bstr.GetCStr(); + if (FXSYS_memchr(pSrc, '#', size) == NULL) { + return bstr; + } + CFX_ByteString result; + FX_LPSTR pDestStart = result.GetBuffer(size); + FX_LPSTR pDest = pDestStart; + for (int i = 0; i < size; i ++) { + if (pSrc[i] == '#' && i < size - 2) { + *pDest ++ = _hex2dec(pSrc[i + 1]) * 16 + _hex2dec(pSrc[i + 2]); + i += 2; + } else { + *pDest ++ = pSrc[i]; + } + } + result.ReleaseBuffer((FX_STRSIZE)(pDest - pDestStart)); + return result; +} +CFX_ByteString PDF_NameDecode(const CFX_ByteString& orig) +{ + if (FXSYS_memchr((FX_LPCSTR)orig, '#', orig.GetLength()) == NULL) { + return orig; + } + return PDF_NameDecode(CFX_ByteStringC(orig)); +} +CFX_ByteString PDF_NameEncode(const CFX_ByteString& orig) +{ + FX_LPBYTE src_buf = (FX_LPBYTE)(FX_LPCSTR)orig; + int src_len = orig.GetLength(); + int dest_len = 0; + int i; + for (i = 0; i < src_len; i ++) { + FX_BYTE ch = src_buf[i]; + if (ch >= 0x80 || _PDF_CharType[ch] == 'W' || ch == '#' || + _PDF_CharType[ch] == 'D') { + dest_len += 3; + } else { + dest_len ++; + } + } + if (dest_len == src_len) { + return orig; + } + CFX_ByteString res; + FX_LPSTR dest_buf = res.GetBuffer(dest_len); + dest_len = 0; + for (i = 0; i < src_len; i ++) { + FX_BYTE ch = src_buf[i]; + if (ch >= 0x80 || _PDF_CharType[ch] == 'W' || ch == '#' || + _PDF_CharType[ch] == 'D') { + dest_buf[dest_len++] = '#'; + dest_buf[dest_len++] = "0123456789ABCDEF"[ch / 16]; + dest_buf[dest_len++] = "0123456789ABCDEF"[ch % 16]; + } else { + dest_buf[dest_len++] = ch; + } + } + dest_buf[dest_len] = 0; + res.ReleaseBuffer(); + return res; +} +CFX_ByteTextBuf& operator << (CFX_ByteTextBuf& buf, const CPDF_Object* pObj) +{ + if (pObj == NULL) { + buf << FX_BSTRC(" null"); + return buf; + } + switch (pObj->GetType()) { + case PDFOBJ_NULL: + buf << FX_BSTRC(" null"); + break; + case PDFOBJ_BOOLEAN: + case PDFOBJ_NUMBER: + buf << " " << pObj->GetString(); + break; + case PDFOBJ_STRING: { + CFX_ByteString str = pObj->GetString(); + FX_BOOL bHex = ((CPDF_String*)pObj)->IsHex(); + buf << PDF_EncodeString(str, bHex); + break; + } + case PDFOBJ_NAME: { + CFX_ByteString str = pObj->GetString(); + buf << FX_BSTRC("/") << PDF_NameEncode(str); + break; + } + case PDFOBJ_REFERENCE: { + CPDF_Reference* p = (CPDF_Reference*)pObj; + buf << " " << p->GetRefObjNum() << FX_BSTRC(" 0 R "); + break; + } + case PDFOBJ_ARRAY: { + CPDF_Array* p = (CPDF_Array*)pObj; + buf << FX_BSTRC("["); + for (FX_DWORD i = 0; i < p->GetCount(); i ++) { + CPDF_Object* pElement = p->GetElement(i); + if (pElement->GetObjNum()) { + buf << " " << pElement->GetObjNum() << FX_BSTRC(" 0 R"); + } else { + buf << pElement; + } + } + buf << FX_BSTRC("]"); + break; + } + case PDFOBJ_DICTIONARY: { + CPDF_Dictionary* p = (CPDF_Dictionary*)pObj; + buf << FX_BSTRC("<<"); + FX_POSITION pos = p->GetStartPos(); + while (pos) { + CFX_ByteString key; + CPDF_Object* pValue = p->GetNextElement(pos, key); + buf << FX_BSTRC("/") << PDF_NameEncode(key); + if (pValue->GetObjNum()) { + buf << " " << pValue->GetObjNum() << FX_BSTRC(" 0 R "); + } else { + buf << pValue; + } + } + buf << FX_BSTRC(">>"); + break; + } + case PDFOBJ_STREAM: { + CPDF_Stream* p = (CPDF_Stream*)pObj; + buf << p->GetDict() << FX_BSTRC("stream\r\n"); + CPDF_StreamAcc acc; + acc.LoadAllData(p, TRUE); + buf.AppendBlock(acc.GetData(), acc.GetSize()); + buf << FX_BSTRC("\r\nendstream"); + break; + } + default: + ASSERT(FALSE); + break; + } + return buf; +} +FX_FLOAT PDF_ClipFloat(FX_FLOAT f) +{ + if (f < 0) { + return 0; + } + if (f > 1.0f) { + return 1.0f; + } + return f; +} +static CPDF_Object* SearchNumberNode(CPDF_Dictionary* pNode, int num) +{ + CPDF_Array* pLimits = pNode->GetArray("Limits"); + if (pLimits && (num < pLimits->GetInteger(0) || num > pLimits->GetInteger(1))) { + return NULL; + } + CPDF_Array* pNumbers = pNode->GetArray("Nums"); + if (pNumbers) { + FX_DWORD dwCount = pNumbers->GetCount() / 2; + for (FX_DWORD i = 0; i < dwCount; i ++) { + int index = pNumbers->GetInteger(i * 2); + if (num == index) { + return pNumbers->GetElementValue(i * 2 + 1); + } + if (index > num) { + break; + } + } + return NULL; + } + CPDF_Array* pKids = pNode->GetArray("Kids"); + if (pKids == NULL) { + return NULL; + } + for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) { + CPDF_Dictionary* pKid = pKids->GetDict(i); + if (pKid == NULL) { + continue; + } + CPDF_Object* pFound = SearchNumberNode(pKid, num); + if (pFound) { + return pFound; + } + } + return NULL; +} +CPDF_Object* CPDF_NumberTree::LookupValue(int num) +{ + return SearchNumberNode(m_pRoot, num); +} -- cgit v1.2.3