OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
6 | |
7 #include "core/fpdfapi/fpdf_parser/fpdf_parser_utility.h" | |
8 | |
9 #include "core/fpdfapi/fpdf_parser/cpdf_array.h" | |
10 #include "core/fpdfapi/fpdf_parser/cpdf_dictionary.h" | |
11 #include "core/fpdfapi/fpdf_parser/cpdf_number.h" | |
12 #include "core/fpdfapi/fpdf_parser/cpdf_reference.h" | |
13 #include "core/fpdfapi/fpdf_parser/cpdf_stream.h" | |
14 #include "core/fpdfapi/fpdf_parser/cpdf_stream_acc.h" | |
15 #include "core/fpdfapi/fpdf_parser/cpdf_string.h" | |
16 #include "core/fpdfapi/fpdf_parser/fpdf_parser_decode.h" | |
17 #include "core/fxcrt/fx_ext.h" | |
18 | |
19 // Indexed by 8-bit character code, contains either: | |
20 // 'W' - for whitespace: NUL, TAB, CR, LF, FF, SPACE, 0x80, 0xff | |
21 // 'N' - for numeric: 0123456789+-. | |
22 // 'D' - for delimiter: %()/<>[]{} | |
23 // 'R' - otherwise. | |
24 const char PDF_CharType[256] = { | |
25 // NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO | |
26 // SI | |
27 'W', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'W', 'W', 'R', 'W', 'W', 'R', | |
28 'R', | |
29 | |
30 // DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS | |
31 // US | |
32 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
33 'R', | |
34 | |
35 // SP ! " # $ % & ยด ( ) * + , - . | |
36 // / | |
37 'W', 'R', 'R', 'R', 'R', 'D', 'R', 'R', 'D', 'D', 'R', 'N', 'R', 'N', 'N', | |
38 'D', | |
39 | |
40 // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? | |
41 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'R', 'R', 'D', 'R', 'D', | |
42 'R', | |
43 | |
44 // @ A B C D E F G H I J K L M N O | |
45 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
46 'R', | |
47 | |
48 // P Q R S T U V W X Y Z [ \ ] ^ _ | |
49 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'D', 'R', 'D', 'R', | |
50 'R', | |
51 | |
52 // ` a b c d e f g h i j k l m n o | |
53 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
54 'R', | |
55 | |
56 // p q r s t u v w x y z { | } ~ | |
57 // DEL | |
58 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'D', 'R', 'D', 'R', | |
59 'R', | |
60 | |
61 'W', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
62 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
63 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
64 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
65 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
66 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
67 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
68 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', | |
69 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'W'}; | |
70 | |
71 int32_t GetHeaderOffset(IFX_FileRead* pFile) { | |
72 const size_t kBufSize = 4; | |
73 uint8_t buf[kBufSize]; | |
74 for (int32_t offset = 0; offset <= 1024; ++offset) { | |
75 if (!pFile->ReadBlock(buf, offset, kBufSize)) | |
76 return -1; | |
77 | |
78 if (memcmp(buf, "%PDF", 4) == 0) | |
79 return offset; | |
80 } | |
81 return -1; | |
82 } | |
83 | |
84 int32_t GetDirectInteger(CPDF_Dictionary* pDict, const CFX_ByteString& key) { | |
85 CPDF_Number* pObj = ToNumber(pDict->GetObjectFor(key)); | |
86 return pObj ? pObj->GetInteger() : 0; | |
87 } | |
88 | |
89 CFX_ByteString PDF_NameDecode(const CFX_ByteStringC& bstr) { | |
90 if (bstr.Find('#') == -1) | |
91 return CFX_ByteString(bstr); | |
92 | |
93 int size = bstr.GetLength(); | |
94 CFX_ByteString result; | |
95 FX_CHAR* pDestStart = result.GetBuffer(size); | |
96 FX_CHAR* pDest = pDestStart; | |
97 for (int i = 0; i < size; i++) { | |
98 if (bstr[i] == '#' && i < size - 2) { | |
99 *pDest++ = | |
100 FXSYS_toHexDigit(bstr[i + 1]) * 16 + FXSYS_toHexDigit(bstr[i + 2]); | |
101 i += 2; | |
102 } else { | |
103 *pDest++ = bstr[i]; | |
104 } | |
105 } | |
106 result.ReleaseBuffer((FX_STRSIZE)(pDest - pDestStart)); | |
107 return result; | |
108 } | |
109 | |
110 CFX_ByteString PDF_NameDecode(const CFX_ByteString& orig) { | |
111 if (orig.Find('#') == -1) | |
112 return orig; | |
113 return PDF_NameDecode(orig.AsStringC()); | |
114 } | |
115 | |
116 CFX_ByteString PDF_NameEncode(const CFX_ByteString& orig) { | |
117 uint8_t* src_buf = (uint8_t*)orig.c_str(); | |
118 int src_len = orig.GetLength(); | |
119 int dest_len = 0; | |
120 int i; | |
121 for (i = 0; i < src_len; i++) { | |
122 uint8_t ch = src_buf[i]; | |
123 if (ch >= 0x80 || PDFCharIsWhitespace(ch) || ch == '#' || | |
124 PDFCharIsDelimiter(ch)) { | |
125 dest_len += 3; | |
126 } else { | |
127 dest_len++; | |
128 } | |
129 } | |
130 if (dest_len == src_len) | |
131 return orig; | |
132 | |
133 CFX_ByteString res; | |
134 FX_CHAR* dest_buf = res.GetBuffer(dest_len); | |
135 dest_len = 0; | |
136 for (i = 0; i < src_len; i++) { | |
137 uint8_t ch = src_buf[i]; | |
138 if (ch >= 0x80 || PDFCharIsWhitespace(ch) || ch == '#' || | |
139 PDFCharIsDelimiter(ch)) { | |
140 dest_buf[dest_len++] = '#'; | |
141 dest_buf[dest_len++] = "0123456789ABCDEF"[ch / 16]; | |
142 dest_buf[dest_len++] = "0123456789ABCDEF"[ch % 16]; | |
143 } else { | |
144 dest_buf[dest_len++] = ch; | |
145 } | |
146 } | |
147 dest_buf[dest_len] = 0; | |
148 res.ReleaseBuffer(); | |
149 return res; | |
150 } | |
151 | |
152 CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& buf, const CPDF_Object* pObj) { | |
153 if (!pObj) { | |
154 buf << " null"; | |
155 return buf; | |
156 } | |
157 switch (pObj->GetType()) { | |
158 case CPDF_Object::NULLOBJ: | |
159 buf << " null"; | |
160 break; | |
161 case CPDF_Object::BOOLEAN: | |
162 case CPDF_Object::NUMBER: | |
163 buf << " " << pObj->GetString(); | |
164 break; | |
165 case CPDF_Object::STRING: | |
166 buf << PDF_EncodeString(pObj->GetString(), pObj->AsString()->IsHex()); | |
167 break; | |
168 case CPDF_Object::NAME: { | |
169 CFX_ByteString str = pObj->GetString(); | |
170 buf << "/" << PDF_NameEncode(str); | |
171 break; | |
172 } | |
173 case CPDF_Object::REFERENCE: { | |
174 buf << " " << pObj->AsReference()->GetRefObjNum() << " 0 R "; | |
175 break; | |
176 } | |
177 case CPDF_Object::ARRAY: { | |
178 const CPDF_Array* p = pObj->AsArray(); | |
179 buf << "["; | |
180 for (size_t i = 0; i < p->GetCount(); i++) { | |
181 CPDF_Object* pElement = p->GetObjectAt(i); | |
182 if (pElement && pElement->GetObjNum()) { | |
183 buf << " " << pElement->GetObjNum() << " 0 R"; | |
184 } else { | |
185 buf << pElement; | |
186 } | |
187 } | |
188 buf << "]"; | |
189 break; | |
190 } | |
191 case CPDF_Object::DICTIONARY: { | |
192 const CPDF_Dictionary* p = pObj->AsDictionary(); | |
193 buf << "<<"; | |
194 for (const auto& it : *p) { | |
195 const CFX_ByteString& key = it.first; | |
196 CPDF_Object* pValue = it.second; | |
197 buf << "/" << PDF_NameEncode(key); | |
198 if (pValue && pValue->GetObjNum()) { | |
199 buf << " " << pValue->GetObjNum() << " 0 R "; | |
200 } else { | |
201 buf << pValue; | |
202 } | |
203 } | |
204 buf << ">>"; | |
205 break; | |
206 } | |
207 case CPDF_Object::STREAM: { | |
208 const CPDF_Stream* p = pObj->AsStream(); | |
209 buf << p->GetDict() << "stream\r\n"; | |
210 CPDF_StreamAcc acc; | |
211 acc.LoadAllData(p, TRUE); | |
212 buf.AppendBlock(acc.GetData(), acc.GetSize()); | |
213 buf << "\r\nendstream"; | |
214 break; | |
215 } | |
216 default: | |
217 ASSERT(FALSE); | |
218 break; | |
219 } | |
220 return buf; | |
221 } | |
OLD | NEW |