Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: PDF driver
4 : * Purpose: GDALDataset driver for PDF dataset.
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : *
9 : * Support for open-source PDFium library
10 : *
11 : * Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
12 : * Author: Martin Mikita <martin.mikita@klokantech.com>, xmikit00 @ FIT VUT Brno
13 : *
14 : ******************************************************************************
15 : * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
16 : *
17 : * SPDX-License-Identifier: MIT
18 : ****************************************************************************/
19 :
20 : #include "gdal_pdf.h"
21 :
22 : #include <limits>
23 : #include <type_traits>
24 : #include <vector>
25 : #include "pdfobject.h"
26 :
27 : /************************************************************************/
28 : /* ROUND_IF_CLOSE() */
29 : /************************************************************************/
30 :
31 4556 : double ROUND_IF_CLOSE(double x, double eps)
32 : {
33 4556 : if (eps == 0.0)
34 3323 : eps = fabs(x) < 1 ? 1e-10 : 1e-8;
35 4556 : const double dfRounded = std::round(x);
36 4556 : if (fabs(x - dfRounded) < eps)
37 3546 : return dfRounded;
38 : else
39 1010 : return x;
40 : }
41 :
42 : /************************************************************************/
43 : /* GDALPDFGetPDFString() */
44 : /************************************************************************/
45 :
46 631 : static CPLString GDALPDFGetPDFString(const char *pszStr)
47 : {
48 631 : const GByte *pabyData = reinterpret_cast<const GByte *>(pszStr);
49 : GByte ch;
50 20934 : for (size_t i = 0; (ch = pabyData[i]) != '\0'; i++)
51 : {
52 20311 : if (ch < 32 || ch > 127 || ch == '(' || ch == ')' || ch == '\\' ||
53 20303 : ch == '%' || ch == '#')
54 : break;
55 : }
56 631 : CPLString osStr;
57 631 : if (ch == 0)
58 : {
59 623 : osStr = "(";
60 623 : osStr += pszStr;
61 623 : osStr += ")";
62 623 : return osStr;
63 : }
64 :
65 8 : wchar_t *pwszDest = CPLRecodeToWChar(pszStr, CPL_ENC_UTF8, CPL_ENC_UCS2);
66 8 : osStr = "<FEFF";
67 480 : for (size_t i = 0; pwszDest[i] != 0; i++)
68 : {
69 : #ifndef _WIN32
70 472 : if (pwszDest[i] >= 0x10000 /* && pwszDest[i] <= 0x10FFFF */)
71 : {
72 : /* Generate UTF-16 surrogate pairs (on Windows, CPLRecodeToWChar
73 : * does it for us) */
74 0 : int nHeadSurrogate = ((pwszDest[i] - 0x10000) >> 10) | 0xd800;
75 0 : int nTrailSurrogate = ((pwszDest[i] - 0x10000) & 0x3ff) | 0xdc00;
76 0 : osStr += CPLSPrintf("%02X", (nHeadSurrogate >> 8) & 0xff);
77 0 : osStr += CPLSPrintf("%02X", (nHeadSurrogate) & 0xff);
78 0 : osStr += CPLSPrintf("%02X", (nTrailSurrogate >> 8) & 0xff);
79 0 : osStr += CPLSPrintf("%02X", (nTrailSurrogate) & 0xff);
80 : }
81 : else
82 : #endif
83 : {
84 : osStr +=
85 472 : CPLSPrintf("%02X", static_cast<int>(pwszDest[i] >> 8) & 0xff);
86 472 : osStr += CPLSPrintf("%02X", static_cast<int>(pwszDest[i]) & 0xff);
87 : }
88 : }
89 8 : osStr += ">";
90 8 : CPLFree(pwszDest);
91 8 : return osStr;
92 : }
93 :
94 : #if defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
95 :
96 : /************************************************************************/
97 : /* GDALPDFGetUTF8StringFromBytes() */
98 : /************************************************************************/
99 :
100 436 : static std::string GDALPDFGetUTF8StringFromBytes(const GByte *pabySrc,
101 : size_t nLen)
102 : {
103 436 : const bool bLEUnicodeMarker =
104 436 : nLen >= 2 && pabySrc[0] == 0xFE && pabySrc[1] == 0xFF;
105 436 : const bool bBEUnicodeMarker =
106 436 : nLen >= 2 && pabySrc[0] == 0xFF && pabySrc[1] == 0xFE;
107 436 : if (!bLEUnicodeMarker && !bBEUnicodeMarker)
108 : {
109 0 : std::string osStr;
110 : try
111 : {
112 0 : osStr.reserve(nLen);
113 : }
114 0 : catch (const std::exception &e)
115 : {
116 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
117 0 : "GDALPDFGetUTF8StringFromBytes(): %s", e.what());
118 0 : return osStr;
119 : }
120 0 : osStr.assign(reinterpret_cast<const char *>(pabySrc), nLen);
121 0 : const char *pszStr = osStr.c_str();
122 0 : if (CPLIsUTF8(pszStr, -1))
123 0 : return osStr;
124 : else
125 : {
126 0 : char *pszUTF8 = CPLRecode(pszStr, CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
127 0 : std::string osRet = pszUTF8;
128 0 : CPLFree(pszUTF8);
129 0 : return osRet;
130 : }
131 : }
132 :
133 : /* This is UTF-16 content */
134 436 : pabySrc += 2;
135 436 : nLen = (nLen - 2) / 2;
136 872 : std::wstring awszSource;
137 436 : awszSource.resize(nLen + 1);
138 436 : size_t j = 0;
139 6541 : for (size_t i = 0; i < nLen; i++, j++)
140 : {
141 6105 : if (!bBEUnicodeMarker)
142 5105 : awszSource[j] = (pabySrc[2 * i] << 8) + pabySrc[2 * i + 1];
143 : else
144 1000 : awszSource[j] = (pabySrc[2 * i + 1] << 8) + pabySrc[2 * i];
145 : #ifndef _WIN32
146 : /* Is there a surrogate pair ? See http://en.wikipedia.org/wiki/UTF-16
147 : */
148 : /* On Windows, CPLRecodeFromWChar does this for us, because wchar_t is
149 : * only */
150 : /* 2 bytes wide, whereas on Unix it is 32bits */
151 6105 : if (awszSource[j] >= 0xD800 && awszSource[j] <= 0xDBFF && i + 1 < nLen)
152 : {
153 : /* should be in the range 0xDC00... 0xDFFF */
154 : wchar_t nTrailSurrogate;
155 0 : if (!bBEUnicodeMarker)
156 0 : nTrailSurrogate =
157 0 : (pabySrc[2 * (i + 1)] << 8) + pabySrc[2 * (i + 1) + 1];
158 : else
159 0 : nTrailSurrogate =
160 0 : (pabySrc[2 * (i + 1) + 1] << 8) + pabySrc[2 * (i + 1)];
161 0 : if (nTrailSurrogate >= 0xDC00 && nTrailSurrogate <= 0xDFFF)
162 : {
163 0 : awszSource[j] = ((awszSource[j] - 0xD800) << 10) +
164 0 : (nTrailSurrogate - 0xDC00) + 0x10000;
165 0 : i++;
166 : }
167 : }
168 : #endif
169 : }
170 436 : awszSource[j] = 0;
171 :
172 : char *pszUTF8 =
173 436 : CPLRecodeFromWChar(awszSource.data(), CPL_ENC_UCS2, CPL_ENC_UTF8);
174 436 : awszSource.clear();
175 872 : std::string osStrUTF8(pszUTF8);
176 436 : CPLFree(pszUTF8);
177 436 : return osStrUTF8;
178 : }
179 :
180 : #endif // defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
181 :
182 : /************************************************************************/
183 : /* GDALPDFGetPDFName() */
184 : /************************************************************************/
185 :
186 2147 : static std::string GDALPDFGetPDFName(const std::string &osStr)
187 : {
188 2147 : std::string osRet;
189 18209 : for (const char ch : osStr)
190 : {
191 16062 : if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
192 12 : (ch >= '0' && ch <= '9') || ch == '-'))
193 0 : osRet += '_';
194 : else
195 16062 : osRet += ch;
196 : }
197 2147 : return osRet;
198 : }
199 :
200 : /************************************************************************/
201 : /* ==================================================================== */
202 : /* GDALPDFObject */
203 : /* ==================================================================== */
204 : /************************************************************************/
205 :
206 : /************************************************************************/
207 : /* ~GDALPDFObject() */
208 : /************************************************************************/
209 :
210 26516 : GDALPDFObject::~GDALPDFObject()
211 : {
212 26516 : }
213 :
214 : /************************************************************************/
215 : /* LookupObject() */
216 : /************************************************************************/
217 :
218 1234 : GDALPDFObject *GDALPDFObject::LookupObject(const char *pszPath)
219 : {
220 1234 : if (GetType() != PDFObjectType_Dictionary)
221 0 : return nullptr;
222 1234 : return GetDictionary()->LookupObject(pszPath);
223 : }
224 :
225 : /************************************************************************/
226 : /* GetTypeName() */
227 : /************************************************************************/
228 :
229 70 : const char *GDALPDFObject::GetTypeName()
230 : {
231 70 : switch (GetType())
232 : {
233 0 : case PDFObjectType_Unknown:
234 0 : return GetTypeNameNative();
235 0 : case PDFObjectType_Null:
236 0 : return "null";
237 0 : case PDFObjectType_Bool:
238 0 : return "bool";
239 0 : case PDFObjectType_Int:
240 0 : return "int";
241 0 : case PDFObjectType_Real:
242 0 : return "real";
243 0 : case PDFObjectType_String:
244 0 : return "string";
245 0 : case PDFObjectType_Name:
246 0 : return "name";
247 3 : case PDFObjectType_Array:
248 3 : return "array";
249 67 : case PDFObjectType_Dictionary:
250 67 : return "dictionary";
251 0 : default:
252 0 : return GetTypeNameNative();
253 : }
254 : }
255 :
256 : /************************************************************************/
257 : /* Serialize() */
258 : /************************************************************************/
259 :
260 10768 : void GDALPDFObject::Serialize(CPLString &osStr, bool bEmitRef)
261 : {
262 10768 : auto nRefNum = GetRefNum();
263 10768 : if (bEmitRef && nRefNum.toBool())
264 : {
265 2088 : int nRefGen = GetRefGen();
266 2088 : osStr.append(CPLSPrintf("%d %d R", nRefNum.toInt(), nRefGen));
267 2088 : return;
268 : }
269 :
270 8680 : switch (GetType())
271 : {
272 12 : case PDFObjectType_Null:
273 12 : osStr.append("null");
274 12 : return;
275 23 : case PDFObjectType_Bool:
276 23 : osStr.append(GetBool() ? "true" : "false");
277 23 : return;
278 2453 : case PDFObjectType_Int:
279 2453 : osStr.append(CPLSPrintf("%d", GetInt()));
280 2453 : return;
281 1653 : case PDFObjectType_Real:
282 : {
283 : char szReal[512];
284 1653 : double dfRealNonRounded = GetReal();
285 1653 : double dfReal = ROUND_IF_CLOSE(dfRealNonRounded);
286 1653 : if (dfReal >=
287 1653 : static_cast<double>(std::numeric_limits<GIntBig>::min()) &&
288 : dfReal <=
289 3306 : static_cast<double>(std::numeric_limits<GIntBig>::max()) &&
290 1653 : dfReal == static_cast<double>(static_cast<GIntBig>(dfReal)))
291 : {
292 1225 : snprintf(szReal, sizeof(szReal), CPL_FRMT_GIB,
293 : static_cast<GIntBig>(dfReal));
294 : }
295 428 : else if (CanRepresentRealAsString())
296 : {
297 : /* Used for OGC BP numeric values */
298 0 : CPLsnprintf(szReal, sizeof(szReal), "(%.*g)", GetPrecision(),
299 : dfReal);
300 : }
301 : else
302 : {
303 428 : CPLsnprintf(szReal, sizeof(szReal), "%.*f", GetPrecision(),
304 : dfReal);
305 :
306 : /* Remove non significant trailing zeroes */
307 428 : char *pszDot = strchr(szReal, '.');
308 428 : if (pszDot)
309 : {
310 428 : int iDot = static_cast<int>(pszDot - szReal);
311 428 : int nLen = static_cast<int>(strlen(szReal));
312 2174 : for (int i = nLen - 1; i > iDot; i--)
313 : {
314 2174 : if (szReal[i] == '0')
315 1746 : szReal[i] = '\0';
316 : else
317 428 : break;
318 : }
319 : }
320 : }
321 1653 : osStr.append(szReal);
322 1653 : return;
323 : }
324 631 : case PDFObjectType_String:
325 631 : osStr.append(GDALPDFGetPDFString(GetString().c_str()));
326 631 : return;
327 2147 : case PDFObjectType_Name:
328 2147 : osStr.append("/");
329 2147 : osStr.append(GDALPDFGetPDFName(GetName()));
330 2147 : return;
331 839 : case PDFObjectType_Array:
332 839 : GetArray()->Serialize(osStr);
333 839 : return;
334 922 : case PDFObjectType_Dictionary:
335 922 : GetDictionary()->Serialize(osStr);
336 922 : return;
337 0 : case PDFObjectType_Unknown:
338 : default:
339 0 : CPLError(CE_Warning, CPLE_AppDefined,
340 : "Serializing unknown object !");
341 0 : return;
342 : }
343 : }
344 :
345 : /************************************************************************/
346 : /* Clone() */
347 : /************************************************************************/
348 :
349 158 : GDALPDFObjectRW *GDALPDFObject::Clone()
350 : {
351 158 : auto nRefNum = GetRefNum();
352 158 : if (nRefNum.toBool())
353 : {
354 63 : int nRefGen = GetRefGen();
355 63 : return GDALPDFObjectRW::CreateIndirect(nRefNum, nRefGen);
356 : }
357 :
358 95 : switch (GetType())
359 : {
360 0 : case PDFObjectType_Null:
361 0 : return GDALPDFObjectRW::CreateNull();
362 0 : case PDFObjectType_Bool:
363 0 : return GDALPDFObjectRW::CreateBool(GetBool());
364 54 : case PDFObjectType_Int:
365 54 : return GDALPDFObjectRW::CreateInt(GetInt());
366 4 : case PDFObjectType_Real:
367 4 : return GDALPDFObjectRW::CreateReal(GetReal());
368 0 : case PDFObjectType_String:
369 0 : return GDALPDFObjectRW::CreateString(GetString().c_str());
370 15 : case PDFObjectType_Name:
371 15 : return GDALPDFObjectRW::CreateName(GetName().c_str());
372 22 : case PDFObjectType_Array:
373 22 : return GDALPDFObjectRW::CreateArray(GetArray()->Clone());
374 0 : case PDFObjectType_Dictionary:
375 0 : return GDALPDFObjectRW::CreateDictionary(GetDictionary()->Clone());
376 0 : case PDFObjectType_Unknown:
377 : default:
378 0 : CPLError(CE_Warning, CPLE_AppDefined, "Cloning unknown object !");
379 0 : return nullptr;
380 : }
381 : }
382 :
383 : /************************************************************************/
384 : /* ==================================================================== */
385 : /* GDALPDFDictionary */
386 : /* ==================================================================== */
387 : /************************************************************************/
388 :
389 : /************************************************************************/
390 : /* ~GDALPDFDictionary() */
391 : /************************************************************************/
392 :
393 6965 : GDALPDFDictionary::~GDALPDFDictionary()
394 : {
395 6965 : }
396 :
397 : /************************************************************************/
398 : /* LookupObject() */
399 : /************************************************************************/
400 :
401 1716 : GDALPDFObject *GDALPDFDictionary::LookupObject(const char *pszPath)
402 : {
403 1716 : GDALPDFObject *poCurObj = nullptr;
404 1716 : char **papszTokens = CSLTokenizeString2(pszPath, ".", 0);
405 4113 : for (int i = 0; papszTokens[i] != nullptr; i++)
406 : {
407 3093 : int iElt = -1;
408 3093 : char *pszBracket = strchr(papszTokens[i], '[');
409 3093 : if (pszBracket != nullptr)
410 : {
411 0 : iElt = atoi(pszBracket + 1);
412 0 : *pszBracket = '\0';
413 : }
414 :
415 3093 : if (i == 0)
416 : {
417 1716 : poCurObj = Get(papszTokens[i]);
418 : }
419 : else
420 : {
421 1377 : if (poCurObj->GetType() != PDFObjectType_Dictionary)
422 : {
423 0 : poCurObj = nullptr;
424 0 : break;
425 : }
426 1377 : poCurObj = poCurObj->GetDictionary()->Get(papszTokens[i]);
427 : }
428 :
429 3093 : if (poCurObj == nullptr)
430 : {
431 696 : poCurObj = nullptr;
432 696 : break;
433 : }
434 :
435 2397 : if (iElt >= 0)
436 : {
437 0 : if (poCurObj->GetType() != PDFObjectType_Array)
438 : {
439 0 : poCurObj = nullptr;
440 0 : break;
441 : }
442 0 : poCurObj = poCurObj->GetArray()->Get(iElt);
443 : }
444 : }
445 1716 : CSLDestroy(papszTokens);
446 1716 : return poCurObj;
447 : }
448 :
449 : /************************************************************************/
450 : /* Serialize() */
451 : /************************************************************************/
452 :
453 2204 : void GDALPDFDictionary::Serialize(CPLString &osStr)
454 : {
455 2204 : osStr.append("<< ");
456 9359 : for (const auto &oIter : GetValues())
457 : {
458 7155 : const char *pszKey = oIter.first.c_str();
459 7155 : GDALPDFObject *poObj = oIter.second;
460 7155 : osStr.append("/");
461 7155 : osStr.append(pszKey);
462 7155 : osStr.append(" ");
463 7155 : poObj->Serialize(osStr);
464 7155 : osStr.append(" ");
465 : }
466 2204 : osStr.append(">>");
467 2204 : }
468 :
469 : /************************************************************************/
470 : /* Clone() */
471 : /************************************************************************/
472 :
473 15 : GDALPDFDictionaryRW *GDALPDFDictionary::Clone()
474 : {
475 15 : GDALPDFDictionaryRW *poDict = new GDALPDFDictionaryRW();
476 115 : for (const auto &oIter : GetValues())
477 : {
478 100 : const char *pszKey = oIter.first.c_str();
479 100 : GDALPDFObject *poObj = oIter.second;
480 100 : poDict->Add(pszKey, poObj->Clone());
481 : }
482 15 : return poDict;
483 : }
484 :
485 : /************************************************************************/
486 : /* ==================================================================== */
487 : /* GDALPDFArray */
488 : /* ==================================================================== */
489 : /************************************************************************/
490 :
491 : /************************************************************************/
492 : /* ~GDALPDFArray() */
493 : /************************************************************************/
494 :
495 2225 : GDALPDFArray::~GDALPDFArray()
496 : {
497 2225 : }
498 :
499 : /************************************************************************/
500 : /* Serialize() */
501 : /************************************************************************/
502 :
503 914 : void GDALPDFArray::Serialize(CPLString &osStr)
504 : {
505 914 : int nLength = GetLength();
506 : int i;
507 :
508 914 : osStr.append("[ ");
509 4059 : for (i = 0; i < nLength; i++)
510 : {
511 3145 : Get(i)->Serialize(osStr);
512 3145 : osStr.append(" ");
513 : }
514 914 : osStr.append("]");
515 914 : }
516 :
517 : /************************************************************************/
518 : /* Clone() */
519 : /************************************************************************/
520 :
521 22 : GDALPDFArrayRW *GDALPDFArray::Clone()
522 : {
523 22 : GDALPDFArrayRW *poArray = new GDALPDFArrayRW();
524 22 : int nLength = GetLength();
525 : int i;
526 80 : for (i = 0; i < nLength; i++)
527 : {
528 58 : poArray->Add(Get(i)->Clone());
529 : }
530 22 : return poArray;
531 : }
532 :
533 : /************************************************************************/
534 : /* ==================================================================== */
535 : /* GDALPDFStream */
536 : /* ==================================================================== */
537 : /************************************************************************/
538 :
539 : /************************************************************************/
540 : /* ~GDALPDFStream() */
541 : /************************************************************************/
542 :
543 : GDALPDFStream::~GDALPDFStream() = default;
544 :
545 : /************************************************************************/
546 : /* ==================================================================== */
547 : /* GDALPDFObjectRW */
548 : /* ==================================================================== */
549 : /************************************************************************/
550 :
551 : /************************************************************************/
552 : /* GDALPDFObjectRW() */
553 : /************************************************************************/
554 :
555 10851 : GDALPDFObjectRW::GDALPDFObjectRW(GDALPDFObjectType eType) : m_eType(eType)
556 : {
557 10851 : }
558 :
559 : /************************************************************************/
560 : /* ~GDALPDFObjectRW() */
561 : /************************************************************************/
562 :
563 21702 : GDALPDFObjectRW::~GDALPDFObjectRW()
564 : {
565 10851 : delete m_poDict;
566 10851 : delete m_poArray;
567 21702 : }
568 :
569 : /************************************************************************/
570 : /* CreateIndirect() */
571 : /************************************************************************/
572 :
573 2125 : GDALPDFObjectRW *GDALPDFObjectRW::CreateIndirect(const GDALPDFObjectNum &nNum,
574 : int nGen)
575 : {
576 2125 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Unknown);
577 2125 : poObj->m_nNum = nNum;
578 2125 : poObj->m_nGen = nGen;
579 2125 : return poObj;
580 : }
581 :
582 : /************************************************************************/
583 : /* CreateNull() */
584 : /************************************************************************/
585 :
586 12 : GDALPDFObjectRW *GDALPDFObjectRW::CreateNull()
587 : {
588 12 : return new GDALPDFObjectRW(PDFObjectType_Null);
589 : }
590 :
591 : /************************************************************************/
592 : /* CreateBool() */
593 : /************************************************************************/
594 :
595 23 : GDALPDFObjectRW *GDALPDFObjectRW::CreateBool(int bVal)
596 : {
597 23 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Bool);
598 23 : poObj->m_nVal = bVal;
599 23 : return poObj;
600 : }
601 :
602 : /************************************************************************/
603 : /* CreateInt() */
604 : /************************************************************************/
605 :
606 2477 : GDALPDFObjectRW *GDALPDFObjectRW::CreateInt(int nVal)
607 : {
608 2477 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Int);
609 2477 : poObj->m_nVal = nVal;
610 2477 : return poObj;
611 : }
612 :
613 : /************************************************************************/
614 : /* CreateReal() */
615 : /************************************************************************/
616 :
617 1591 : GDALPDFObjectRW *GDALPDFObjectRW::CreateReal(double dfVal,
618 : int bCanRepresentRealAsString)
619 : {
620 1591 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Real);
621 1591 : poObj->m_dfVal = dfVal;
622 1591 : poObj->m_bCanRepresentRealAsString = bCanRepresentRealAsString;
623 1591 : return poObj;
624 : }
625 :
626 : /************************************************************************/
627 : /* CreateRealWithPrecision() */
628 : /************************************************************************/
629 :
630 64 : GDALPDFObjectRW *GDALPDFObjectRW::CreateRealWithPrecision(double dfVal,
631 : int nPrecision)
632 : {
633 64 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Real);
634 64 : poObj->m_dfVal = dfVal;
635 64 : poObj->m_nPrecision = nPrecision;
636 64 : return poObj;
637 : }
638 :
639 : /************************************************************************/
640 : /* CreateString() */
641 : /************************************************************************/
642 :
643 631 : GDALPDFObjectRW *GDALPDFObjectRW::CreateString(const char *pszStr)
644 : {
645 631 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_String);
646 631 : poObj->m_osVal = pszStr;
647 631 : return poObj;
648 : }
649 :
650 : /************************************************************************/
651 : /* CreateName() */
652 : /************************************************************************/
653 :
654 2149 : GDALPDFObjectRW *GDALPDFObjectRW::CreateName(const char *pszName)
655 : {
656 2149 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Name);
657 2149 : poObj->m_osVal = pszName;
658 2149 : return poObj;
659 : }
660 :
661 : /************************************************************************/
662 : /* CreateDictionary() */
663 : /************************************************************************/
664 :
665 923 : GDALPDFObjectRW *GDALPDFObjectRW::CreateDictionary(GDALPDFDictionaryRW *poDict)
666 : {
667 923 : CPLAssert(poDict);
668 923 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Dictionary);
669 923 : poObj->m_poDict = poDict;
670 923 : return poObj;
671 : }
672 :
673 : /************************************************************************/
674 : /* CreateArray() */
675 : /************************************************************************/
676 :
677 856 : GDALPDFObjectRW *GDALPDFObjectRW::CreateArray(GDALPDFArrayRW *poArray)
678 : {
679 856 : CPLAssert(poArray);
680 856 : GDALPDFObjectRW *poObj = new GDALPDFObjectRW(PDFObjectType_Array);
681 856 : poObj->m_poArray = poArray;
682 856 : return poObj;
683 : }
684 :
685 : /************************************************************************/
686 : /* GetTypeNameNative() */
687 : /************************************************************************/
688 :
689 0 : const char *GDALPDFObjectRW::GetTypeNameNative()
690 : {
691 0 : CPLError(CE_Failure, CPLE_AppDefined, "Should not go here");
692 0 : return "";
693 : }
694 :
695 : /************************************************************************/
696 : /* GetType() */
697 : /************************************************************************/
698 :
699 8664 : GDALPDFObjectType GDALPDFObjectRW::GetType()
700 : {
701 8664 : return m_eType;
702 : }
703 :
704 : /************************************************************************/
705 : /* GetBool() */
706 : /************************************************************************/
707 :
708 23 : int GDALPDFObjectRW::GetBool()
709 : {
710 23 : if (m_eType == PDFObjectType_Bool)
711 23 : return m_nVal;
712 :
713 0 : return FALSE;
714 : }
715 :
716 : /************************************************************************/
717 : /* GetInt() */
718 : /************************************************************************/
719 :
720 2445 : int GDALPDFObjectRW::GetInt()
721 : {
722 2445 : if (m_eType == PDFObjectType_Int)
723 2445 : return m_nVal;
724 :
725 0 : return 0;
726 : }
727 :
728 : /************************************************************************/
729 : /* GetReal() */
730 : /************************************************************************/
731 :
732 1653 : double GDALPDFObjectRW::GetReal()
733 : {
734 1653 : return m_dfVal;
735 : }
736 :
737 : /************************************************************************/
738 : /* GetString() */
739 : /************************************************************************/
740 :
741 631 : const CPLString &GDALPDFObjectRW::GetString()
742 : {
743 631 : return m_osVal;
744 : }
745 :
746 : /************************************************************************/
747 : /* GetName() */
748 : /************************************************************************/
749 :
750 2139 : const CPLString &GDALPDFObjectRW::GetName()
751 : {
752 2139 : return m_osVal;
753 : }
754 :
755 : /************************************************************************/
756 : /* GetDictionary() */
757 : /************************************************************************/
758 :
759 922 : GDALPDFDictionary *GDALPDFObjectRW::GetDictionary()
760 : {
761 922 : return m_poDict;
762 : }
763 :
764 : /************************************************************************/
765 : /* GetArray() */
766 : /************************************************************************/
767 :
768 839 : GDALPDFArray *GDALPDFObjectRW::GetArray()
769 : {
770 839 : return m_poArray;
771 : }
772 :
773 : /************************************************************************/
774 : /* GetStream() */
775 : /************************************************************************/
776 :
777 0 : GDALPDFStream *GDALPDFObjectRW::GetStream()
778 : {
779 0 : return nullptr;
780 : }
781 :
782 : /************************************************************************/
783 : /* GetRefNum() */
784 : /************************************************************************/
785 :
786 10754 : GDALPDFObjectNum GDALPDFObjectRW::GetRefNum()
787 : {
788 10754 : return m_nNum;
789 : }
790 :
791 : /************************************************************************/
792 : /* GetRefGen() */
793 : /************************************************************************/
794 :
795 2090 : int GDALPDFObjectRW::GetRefGen()
796 : {
797 2090 : return m_nGen;
798 : }
799 :
800 : /************************************************************************/
801 : /* ==================================================================== */
802 : /* GDALPDFDictionaryRW */
803 : /* ==================================================================== */
804 : /************************************************************************/
805 :
806 : /************************************************************************/
807 : /* GDALPDFDictionaryRW() */
808 : /************************************************************************/
809 :
810 : GDALPDFDictionaryRW::GDALPDFDictionaryRW() = default;
811 :
812 : /************************************************************************/
813 : /* ~GDALPDFDictionaryRW() */
814 : /************************************************************************/
815 :
816 3150 : GDALPDFDictionaryRW::~GDALPDFDictionaryRW()
817 : {
818 2212 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
819 2212 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
820 9422 : for (; oIter != oEnd; ++oIter)
821 7210 : delete oIter->second;
822 3150 : }
823 :
824 : /************************************************************************/
825 : /* Get() */
826 : /************************************************************************/
827 :
828 3 : GDALPDFObject *GDALPDFDictionaryRW::Get(const char *pszKey)
829 : {
830 3 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
831 3 : if (oIter != m_map.end())
832 2 : return oIter->second;
833 1 : return nullptr;
834 : }
835 :
836 : /************************************************************************/
837 : /* GetValues() */
838 : /************************************************************************/
839 :
840 2204 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryRW::GetValues()
841 : {
842 2204 : return m_map;
843 : }
844 :
845 : /************************************************************************/
846 : /* Add() */
847 : /************************************************************************/
848 :
849 7216 : GDALPDFDictionaryRW &GDALPDFDictionaryRW::Add(const char *pszKey,
850 : GDALPDFObject *poVal)
851 : {
852 7216 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
853 7216 : if (oIter != m_map.end())
854 : {
855 0 : delete oIter->second;
856 0 : oIter->second = poVal;
857 : }
858 : else
859 7216 : m_map[pszKey] = poVal;
860 :
861 7216 : return *this;
862 : }
863 :
864 : /************************************************************************/
865 : /* Remove() */
866 : /************************************************************************/
867 :
868 15 : GDALPDFDictionaryRW &GDALPDFDictionaryRW::Remove(const char *pszKey)
869 : {
870 15 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
871 15 : if (oIter != m_map.end())
872 : {
873 6 : delete oIter->second;
874 6 : m_map.erase(pszKey);
875 : }
876 :
877 15 : return *this;
878 : }
879 :
880 : /************************************************************************/
881 : /* ==================================================================== */
882 : /* GDALPDFArrayRW */
883 : /* ==================================================================== */
884 : /************************************************************************/
885 :
886 : /************************************************************************/
887 : /* GDALPDFArrayRW() */
888 : /************************************************************************/
889 :
890 931 : GDALPDFArrayRW::GDALPDFArrayRW()
891 : {
892 931 : }
893 :
894 : /************************************************************************/
895 : /* ~GDALPDFArrayRW() */
896 : /************************************************************************/
897 :
898 1787 : GDALPDFArrayRW::~GDALPDFArrayRW()
899 : {
900 4114 : for (size_t i = 0; i < m_array.size(); i++)
901 3183 : delete m_array[i];
902 1787 : }
903 :
904 : /************************************************************************/
905 : /* GetLength() */
906 : /************************************************************************/
907 :
908 4060 : int GDALPDFArrayRW::GetLength()
909 : {
910 4060 : return static_cast<int>(m_array.size());
911 : }
912 :
913 : /************************************************************************/
914 : /* Get() */
915 : /************************************************************************/
916 :
917 3145 : GDALPDFObject *GDALPDFArrayRW::Get(int nIndex)
918 : {
919 3145 : if (nIndex < 0 || nIndex >= GetLength())
920 0 : return nullptr;
921 3145 : return m_array[nIndex];
922 : }
923 :
924 : /************************************************************************/
925 : /* Add() */
926 : /************************************************************************/
927 :
928 3183 : GDALPDFArrayRW &GDALPDFArrayRW::Add(GDALPDFObject *poObj)
929 : {
930 3183 : m_array.push_back(poObj);
931 3183 : return *this;
932 : }
933 :
934 : /************************************************************************/
935 : /* Add() */
936 : /************************************************************************/
937 :
938 0 : GDALPDFArrayRW &GDALPDFArrayRW::Add(double *padfVal, int nCount,
939 : int bCanRepresentRealAsString)
940 : {
941 0 : for (int i = 0; i < nCount; i++)
942 0 : m_array.push_back(
943 0 : GDALPDFObjectRW::CreateReal(padfVal[i], bCanRepresentRealAsString));
944 0 : return *this;
945 : }
946 :
947 : #ifdef HAVE_POPPLER
948 :
949 : /************************************************************************/
950 : /* ==================================================================== */
951 : /* GDALPDFDictionaryPoppler */
952 : /* ==================================================================== */
953 : /************************************************************************/
954 :
955 : class GDALPDFDictionaryPoppler final : public GDALPDFDictionary
956 : {
957 : private:
958 : Dict *m_poDict;
959 : std::map<CPLString, GDALPDFObject *> m_map{};
960 :
961 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFDictionaryPoppler)
962 :
963 : public:
964 4753 : GDALPDFDictionaryPoppler(Dict *poDict) : m_poDict(poDict)
965 : {
966 4753 : }
967 :
968 : ~GDALPDFDictionaryPoppler() override;
969 :
970 : GDALPDFObject *Get(const char *pszKey) override;
971 : std::map<CPLString, GDALPDFObject *> &GetValues() override;
972 : };
973 :
974 : /************************************************************************/
975 : /* ==================================================================== */
976 : /* GDALPDFArrayPoppler */
977 : /* ==================================================================== */
978 : /************************************************************************/
979 :
980 : class GDALPDFArrayPoppler final : public GDALPDFArray
981 : {
982 : private:
983 : const Array *m_poArray;
984 : std::vector<std::unique_ptr<GDALPDFObject>> m_v{};
985 :
986 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayPoppler)
987 :
988 : public:
989 1294 : GDALPDFArrayPoppler(const Array *poArray) : m_poArray(poArray)
990 : {
991 1294 : }
992 :
993 : int GetLength() override;
994 : GDALPDFObject *Get(int nIndex) override;
995 : };
996 :
997 : /************************************************************************/
998 : /* ==================================================================== */
999 : /* GDALPDFStreamPoppler */
1000 : /* ==================================================================== */
1001 : /************************************************************************/
1002 :
1003 : class GDALPDFStreamPoppler final : public GDALPDFStream
1004 : {
1005 : private:
1006 : int64_t m_nLength = -1;
1007 : Stream *m_poStream;
1008 : int64_t m_nRawLength = -1;
1009 :
1010 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFStreamPoppler)
1011 :
1012 : public:
1013 458 : GDALPDFStreamPoppler(Stream *poStream) : m_poStream(poStream)
1014 : {
1015 458 : }
1016 :
1017 : int64_t GetLength(int64_t nMaxSize = 0) override;
1018 : char *GetBytes() override;
1019 :
1020 : int64_t GetRawLength() override;
1021 : char *GetRawBytes() override;
1022 : };
1023 :
1024 : /************************************************************************/
1025 : /* ==================================================================== */
1026 : /* GDALPDFObjectPoppler */
1027 : /* ==================================================================== */
1028 : /************************************************************************/
1029 :
1030 : /************************************************************************/
1031 : /* ~GDALPDFObjectPoppler() */
1032 : /************************************************************************/
1033 :
1034 31111 : GDALPDFObjectPoppler::~GDALPDFObjectPoppler()
1035 : {
1036 15665 : delete m_poToDestroy;
1037 15665 : delete m_poDict;
1038 15665 : delete m_poArray;
1039 15665 : delete m_poStream;
1040 31111 : }
1041 :
1042 : /************************************************************************/
1043 : /* GetType() */
1044 : /************************************************************************/
1045 :
1046 61246 : GDALPDFObjectType GDALPDFObjectPoppler::GetType()
1047 : {
1048 61246 : switch (m_poConst->getType())
1049 : {
1050 180 : case objNull:
1051 180 : return PDFObjectType_Null;
1052 0 : case objBool:
1053 0 : return PDFObjectType_Bool;
1054 17162 : case objInt:
1055 17162 : return PDFObjectType_Int;
1056 4876 : case objReal:
1057 4876 : return PDFObjectType_Real;
1058 2741 : case objString:
1059 2741 : return PDFObjectType_String;
1060 6671 : case objName:
1061 6671 : return PDFObjectType_Name;
1062 13343 : case objArray:
1063 13343 : return PDFObjectType_Array;
1064 12050 : case objDict:
1065 12050 : return PDFObjectType_Dictionary;
1066 4223 : case objStream:
1067 4223 : return PDFObjectType_Dictionary;
1068 0 : default:
1069 0 : return PDFObjectType_Unknown;
1070 : }
1071 : }
1072 :
1073 : /************************************************************************/
1074 : /* GetTypeNameNative() */
1075 : /************************************************************************/
1076 :
1077 0 : const char *GDALPDFObjectPoppler::GetTypeNameNative()
1078 : {
1079 0 : return m_poConst->getTypeName();
1080 : }
1081 :
1082 : /************************************************************************/
1083 : /* GetBool() */
1084 : /************************************************************************/
1085 :
1086 0 : int GDALPDFObjectPoppler::GetBool()
1087 : {
1088 0 : if (GetType() == PDFObjectType_Bool)
1089 0 : return m_poConst->getBool();
1090 : else
1091 0 : return 0;
1092 : }
1093 :
1094 : /************************************************************************/
1095 : /* GetInt() */
1096 : /************************************************************************/
1097 :
1098 5484 : int GDALPDFObjectPoppler::GetInt()
1099 : {
1100 5484 : if (GetType() == PDFObjectType_Int)
1101 5484 : return m_poConst->getInt();
1102 : else
1103 0 : return 0;
1104 : }
1105 :
1106 : /************************************************************************/
1107 : /* GetReal() */
1108 : /************************************************************************/
1109 :
1110 1214 : double GDALPDFObjectPoppler::GetReal()
1111 : {
1112 1214 : if (GetType() == PDFObjectType_Real)
1113 1214 : return m_poConst->getReal();
1114 : else
1115 0 : return 0.0;
1116 : }
1117 :
1118 : /************************************************************************/
1119 : /* GetString() */
1120 : /************************************************************************/
1121 :
1122 1397 : const std::string &GDALPDFObjectPoppler::GetString()
1123 : {
1124 1397 : if (GetType() == PDFObjectType_String)
1125 : {
1126 : const std::string &osStdStr = *(
1127 1397 : [](auto &&obj) -> const std::string *
1128 : {
1129 : if constexpr (std::is_same_v<decltype(obj),
1130 : const std::string &>)
1131 : {
1132 : // Since Poppler 26.04
1133 : return &obj;
1134 : }
1135 : else
1136 : {
1137 : static_assert(
1138 : std::is_same_v<decltype(obj), const GooString *&&>);
1139 : static_assert(std::is_same_v<decltype(obj->toStr()),
1140 : const std::string &>);
1141 1397 : return &(obj->toStr());
1142 : }
1143 1397 : }(m_poConst->getString()));
1144 : const bool bLEUnicodeMarker =
1145 1743 : osStdStr.size() >= 2 && static_cast<uint8_t>(osStdStr[0]) == 0xFE &&
1146 346 : static_cast<uint8_t>(osStdStr[1]) == 0xFF;
1147 : const bool bBEUnicodeMarker =
1148 1487 : osStdStr.size() >= 2 && static_cast<uint8_t>(osStdStr[0]) == 0xFF &&
1149 90 : static_cast<uint8_t>(osStdStr[1]) == 0xFE;
1150 1397 : if (!bLEUnicodeMarker && !bBEUnicodeMarker)
1151 : {
1152 961 : if (CPLIsUTF8(osStdStr.c_str(), -1))
1153 : {
1154 961 : return osStdStr;
1155 : }
1156 : else
1157 : {
1158 : char *pszUTF8 =
1159 0 : CPLRecode(osStdStr.data(), CPL_ENC_ISO8859_1, CPL_ENC_UTF8);
1160 0 : osStr = pszUTF8;
1161 0 : CPLFree(pszUTF8);
1162 0 : return osStr;
1163 : }
1164 : }
1165 1308 : return (osStr = GDALPDFGetUTF8StringFromBytes(
1166 436 : reinterpret_cast<const GByte *>(osStdStr.data()),
1167 436 : osStdStr.size()));
1168 : }
1169 : else
1170 0 : return (osStr = "");
1171 : }
1172 :
1173 : /************************************************************************/
1174 : /* GetName() */
1175 : /************************************************************************/
1176 :
1177 2942 : const std::string &GDALPDFObjectPoppler::GetName()
1178 : {
1179 2942 : if (GetType() == PDFObjectType_Name)
1180 2942 : return (osStr = m_poConst->getName());
1181 : else
1182 0 : return (osStr = "");
1183 : }
1184 :
1185 : /************************************************************************/
1186 : /* GetDictionary() */
1187 : /************************************************************************/
1188 :
1189 7559 : GDALPDFDictionary *GDALPDFObjectPoppler::GetDictionary()
1190 : {
1191 7559 : if (GetType() != PDFObjectType_Dictionary)
1192 0 : return nullptr;
1193 :
1194 7559 : if (m_poDict)
1195 2806 : return m_poDict;
1196 :
1197 4753 : Dict *poDict = (m_poConst->getType() == objStream)
1198 4753 : ? m_poConst->getStream()->getDict()
1199 3686 : : m_poConst->getDict();
1200 4753 : if (poDict == nullptr)
1201 0 : return nullptr;
1202 4753 : m_poDict = new GDALPDFDictionaryPoppler(poDict);
1203 4753 : return m_poDict;
1204 : }
1205 :
1206 : /************************************************************************/
1207 : /* GetArray() */
1208 : /************************************************************************/
1209 :
1210 6652 : GDALPDFArray *GDALPDFObjectPoppler::GetArray()
1211 : {
1212 6652 : if (GetType() != PDFObjectType_Array)
1213 0 : return nullptr;
1214 :
1215 6652 : if (m_poArray)
1216 5421 : return m_poArray;
1217 :
1218 1231 : Array *poArray = m_poConst->getArray();
1219 1231 : if (poArray == nullptr)
1220 0 : return nullptr;
1221 1231 : m_poArray = new GDALPDFArrayPoppler(poArray);
1222 1231 : return m_poArray;
1223 : }
1224 :
1225 : /************************************************************************/
1226 : /* GetStream() */
1227 : /************************************************************************/
1228 :
1229 605 : GDALPDFStream *GDALPDFObjectPoppler::GetStream()
1230 : {
1231 605 : if (m_poConst->getType() != objStream)
1232 14 : return nullptr;
1233 :
1234 591 : if (m_poStream)
1235 133 : return m_poStream;
1236 458 : m_poStream = new GDALPDFStreamPoppler(m_poConst->getStream());
1237 458 : return m_poStream;
1238 : }
1239 :
1240 : /************************************************************************/
1241 : /* SetRefNumAndGen() */
1242 : /************************************************************************/
1243 :
1244 15227 : void GDALPDFObjectPoppler::SetRefNumAndGen(const GDALPDFObjectNum &nNum,
1245 : int nGen)
1246 : {
1247 15227 : m_nRefNum = nNum;
1248 15227 : m_nRefGen = nGen;
1249 15227 : }
1250 :
1251 : /************************************************************************/
1252 : /* GetRefNum() */
1253 : /************************************************************************/
1254 :
1255 2640 : GDALPDFObjectNum GDALPDFObjectPoppler::GetRefNum()
1256 : {
1257 2640 : return m_nRefNum;
1258 : }
1259 :
1260 : /************************************************************************/
1261 : /* GetRefGen() */
1262 : /************************************************************************/
1263 :
1264 1660 : int GDALPDFObjectPoppler::GetRefGen()
1265 : {
1266 1660 : return m_nRefGen;
1267 : }
1268 :
1269 : /************************************************************************/
1270 : /* ==================================================================== */
1271 : /* GDALPDFDictionaryPoppler */
1272 : /* ==================================================================== */
1273 : /************************************************************************/
1274 :
1275 : /************************************************************************/
1276 : /* ~GDALPDFDictionaryPoppler() */
1277 : /************************************************************************/
1278 :
1279 9506 : GDALPDFDictionaryPoppler::~GDALPDFDictionaryPoppler()
1280 : {
1281 4753 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
1282 4753 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
1283 14260 : for (; oIter != oEnd; ++oIter)
1284 9507 : delete oIter->second;
1285 9506 : }
1286 :
1287 : /************************************************************************/
1288 : /* Get() */
1289 : /************************************************************************/
1290 :
1291 14347 : GDALPDFObject *GDALPDFDictionaryPoppler::Get(const char *pszKey)
1292 : {
1293 14347 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
1294 14347 : if (oIter != m_map.end())
1295 2439 : return oIter->second;
1296 :
1297 11908 : auto &&o(m_poDict->lookupNF(pszKey));
1298 11908 : if (!o.isNull())
1299 : {
1300 9507 : GDALPDFObjectNum nRefNum;
1301 9507 : int nRefGen = 0;
1302 9507 : if (o.isRef())
1303 : {
1304 3023 : nRefNum = o.getRefNum();
1305 3023 : nRefGen = o.getRefGen();
1306 3023 : Object o2(m_poDict->lookup(pszKey));
1307 3023 : if (!o2.isNull())
1308 : {
1309 : GDALPDFObjectPoppler *poObj =
1310 3023 : new GDALPDFObjectPoppler(new Object(std::move(o2)), TRUE);
1311 3023 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1312 3023 : m_map[pszKey] = poObj;
1313 3023 : return poObj;
1314 : }
1315 : }
1316 : else
1317 : {
1318 : GDALPDFObjectPoppler *poObj =
1319 6484 : new GDALPDFObjectPoppler(new Object(o.copy()), TRUE);
1320 6484 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1321 6484 : m_map[pszKey] = poObj;
1322 6484 : return poObj;
1323 : }
1324 : }
1325 2401 : return nullptr;
1326 : }
1327 :
1328 : /************************************************************************/
1329 : /* GetValues() */
1330 : /************************************************************************/
1331 :
1332 478 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryPoppler::GetValues()
1333 : {
1334 478 : int i = 0;
1335 478 : int nLength = m_poDict->getLength();
1336 2350 : for (i = 0; i < nLength; i++)
1337 : {
1338 1872 : const char *pszKey = m_poDict->getKey(i);
1339 1872 : Get(pszKey);
1340 : }
1341 478 : return m_map;
1342 : }
1343 :
1344 : /************************************************************************/
1345 : /* ==================================================================== */
1346 : /* GDALPDFArrayPoppler */
1347 : /* ==================================================================== */
1348 : /************************************************************************/
1349 :
1350 : /************************************************************************/
1351 : /* GDALPDFCreateArray() */
1352 : /************************************************************************/
1353 :
1354 63 : GDALPDFArray *GDALPDFCreateArray(const Array *array)
1355 : {
1356 63 : return new GDALPDFArrayPoppler(array);
1357 : }
1358 :
1359 : /************************************************************************/
1360 : /* GetLength() */
1361 : /************************************************************************/
1362 :
1363 9487 : int GDALPDFArrayPoppler::GetLength()
1364 : {
1365 9487 : return m_poArray->getLength();
1366 : }
1367 :
1368 : /************************************************************************/
1369 : /* Get() */
1370 : /************************************************************************/
1371 :
1372 6383 : GDALPDFObject *GDALPDFArrayPoppler::Get(int nIndex)
1373 : {
1374 6383 : if (nIndex < 0 || nIndex >= GetLength())
1375 0 : return nullptr;
1376 :
1377 6383 : if (m_v.empty())
1378 1259 : m_v.resize(GetLength());
1379 :
1380 6383 : if (m_v[nIndex] != nullptr)
1381 882 : return m_v[nIndex].get();
1382 :
1383 5501 : auto &&o(m_poArray->getNF(nIndex));
1384 5501 : if (!o.isNull())
1385 : {
1386 5501 : GDALPDFObjectNum nRefNum;
1387 5501 : int nRefGen = 0;
1388 5501 : if (o.isRef())
1389 : {
1390 872 : nRefNum = o.getRefNum();
1391 872 : nRefGen = o.getRefGen();
1392 872 : Object o2(m_poArray->get(nIndex));
1393 872 : if (!o2.isNull())
1394 : {
1395 : auto poObj = std::make_unique<GDALPDFObjectPoppler>(
1396 1744 : new Object(std::move(o2)), TRUE);
1397 872 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1398 872 : m_v[nIndex] = std::move(poObj);
1399 872 : return m_v[nIndex].get();
1400 : }
1401 : }
1402 : else
1403 : {
1404 : auto poObj = std::make_unique<GDALPDFObjectPoppler>(
1405 9258 : new Object(o.copy()), TRUE);
1406 4629 : poObj->SetRefNumAndGen(nRefNum, nRefGen);
1407 4629 : m_v[nIndex] = std::move(poObj);
1408 4629 : return m_v[nIndex].get();
1409 : }
1410 : }
1411 0 : return nullptr;
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* ==================================================================== */
1416 : /* GDALPDFStreamPoppler */
1417 : /* ==================================================================== */
1418 : /************************************************************************/
1419 :
1420 : /************************************************************************/
1421 : /* GetLength() */
1422 : /************************************************************************/
1423 :
1424 556 : int64_t GDALPDFStreamPoppler::GetLength(int64_t nMaxSize)
1425 : {
1426 556 : if (m_nLength >= 0)
1427 292 : return m_nLength;
1428 :
1429 : #if POPPLER_MAJOR_VERSION > 25
1430 : if (!m_poStream->rewind())
1431 : return 0;
1432 : #elif POPPLER_MAJOR_VERSION == 25 && POPPLER_MINOR_VERSION >= 2
1433 : if (!m_poStream->reset())
1434 : return 0;
1435 : #else
1436 264 : m_poStream->reset();
1437 : #endif
1438 264 : m_nLength = 0;
1439 : unsigned char readBuf[4096];
1440 : int readChars;
1441 528 : while ((readChars = m_poStream->doGetChars(4096, readBuf)) != 0)
1442 : {
1443 264 : m_nLength += readChars;
1444 264 : if (nMaxSize != 0 && m_nLength > nMaxSize)
1445 : {
1446 0 : m_nLength = -1;
1447 0 : return std::numeric_limits<int64_t>::max();
1448 : }
1449 : }
1450 264 : return m_nLength;
1451 : }
1452 :
1453 : /************************************************************************/
1454 : /* GooStringToCharStart() */
1455 : /************************************************************************/
1456 :
1457 530 : static char *GooStringToCharStart(GooString &gstr)
1458 : {
1459 : #if POPPLER_MAJOR_VERSION > 25 || \
1460 : (POPPLER_MAJOR_VERSION == 25 && POPPLER_MINOR_VERSION >= 10)
1461 : const auto nLength = gstr.size();
1462 : #else
1463 530 : const auto nLength = gstr.getLength();
1464 : #endif
1465 530 : if (nLength)
1466 : {
1467 528 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLength + 1));
1468 528 : if (pszContent)
1469 : {
1470 528 : const char *srcStr = gstr.c_str();
1471 528 : memcpy(pszContent, srcStr, nLength);
1472 528 : pszContent[nLength] = '\0';
1473 : }
1474 528 : return pszContent;
1475 : }
1476 2 : return nullptr;
1477 : }
1478 :
1479 : /************************************************************************/
1480 : /* GetBytes() */
1481 : /************************************************************************/
1482 :
1483 528 : char *GDALPDFStreamPoppler::GetBytes()
1484 : {
1485 1056 : GooString gstr;
1486 : try
1487 : {
1488 528 : m_poStream->fillGooString(&gstr);
1489 : }
1490 0 : catch (const std::exception &e)
1491 : {
1492 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
1493 0 : "GDALPDFStreamPoppler::GetBytes(): %s", e.what());
1494 0 : return nullptr;
1495 : }
1496 528 : m_nLength = static_cast<int64_t>(gstr.toStr().size());
1497 528 : return GooStringToCharStart(gstr);
1498 : }
1499 :
1500 : /************************************************************************/
1501 : /* GetRawLength() */
1502 : /************************************************************************/
1503 :
1504 63 : int64_t GDALPDFStreamPoppler::GetRawLength()
1505 : {
1506 63 : if (m_nRawLength >= 0)
1507 2 : return m_nRawLength;
1508 :
1509 61 : auto undecodeStream = m_poStream->getUndecodedStream();
1510 : #if POPPLER_MAJOR_VERSION > 25
1511 : if (!undecodeStream->rewind())
1512 : return 0;
1513 : #elif POPPLER_MAJOR_VERSION == 25 && POPPLER_MINOR_VERSION >= 2
1514 : if (!undecodeStream->reset())
1515 : return 0;
1516 : #else
1517 61 : undecodeStream->reset();
1518 : #endif
1519 61 : m_nRawLength = 0;
1520 25531 : while (undecodeStream->getChar() != EOF)
1521 25470 : m_nRawLength++;
1522 61 : return m_nRawLength;
1523 : }
1524 :
1525 : /************************************************************************/
1526 : /* GetRawBytes() */
1527 : /************************************************************************/
1528 :
1529 2 : char *GDALPDFStreamPoppler::GetRawBytes()
1530 : {
1531 4 : GooString gstr;
1532 2 : auto undecodeStream = m_poStream->getUndecodedStream();
1533 : try
1534 : {
1535 2 : undecodeStream->fillGooString(&gstr);
1536 : }
1537 0 : catch (const std::exception &e)
1538 : {
1539 0 : CPLError(CE_Failure, CPLE_OutOfMemory,
1540 0 : "GDALPDFStreamPoppler::GetRawBytes(): %s", e.what());
1541 0 : return nullptr;
1542 : }
1543 : #if POPPLER_MAJOR_VERSION > 25 || \
1544 : (POPPLER_MAJOR_VERSION == 25 && POPPLER_MINOR_VERSION >= 10)
1545 : m_nRawLength = gstr.size();
1546 : #else
1547 2 : m_nRawLength = gstr.getLength();
1548 : #endif
1549 2 : return GooStringToCharStart(gstr);
1550 : }
1551 :
1552 : #endif // HAVE_POPPLER
1553 :
1554 : #ifdef HAVE_PODOFO
1555 :
1556 : /************************************************************************/
1557 : /* ==================================================================== */
1558 : /* GDALPDFDictionaryPodofo */
1559 : /* ==================================================================== */
1560 : /************************************************************************/
1561 :
1562 : class GDALPDFDictionaryPodofo final : public GDALPDFDictionary
1563 : {
1564 : private:
1565 : const PoDoFo::PdfDictionary *m_poDict;
1566 : const PoDoFo::PdfVecObjects &m_poObjects;
1567 : std::map<CPLString, GDALPDFObject *> m_map{};
1568 :
1569 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFDictionaryPodofo)
1570 :
1571 : public:
1572 : GDALPDFDictionaryPodofo(const PoDoFo::PdfDictionary *poDict,
1573 : const PoDoFo::PdfVecObjects &poObjects)
1574 : : m_poDict(poDict), m_poObjects(poObjects)
1575 : {
1576 : }
1577 :
1578 : ~GDALPDFDictionaryPodofo() override;
1579 :
1580 : GDALPDFObject *Get(const char *pszKey) override;
1581 : std::map<CPLString, GDALPDFObject *> &GetValues() override;
1582 : };
1583 :
1584 : /************************************************************************/
1585 : /* ==================================================================== */
1586 : /* GDALPDFArrayPodofo */
1587 : /* ==================================================================== */
1588 : /************************************************************************/
1589 :
1590 : class GDALPDFArrayPodofo final : public GDALPDFArray
1591 : {
1592 : private:
1593 : const PoDoFo::PdfArray *m_poArray;
1594 : const PoDoFo::PdfVecObjects &m_poObjects;
1595 : std::vector<std::unique_ptr<GDALPDFObject>> m_v{};
1596 :
1597 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayPodofo)
1598 :
1599 : public:
1600 : GDALPDFArrayPodofo(const PoDoFo::PdfArray *poArray,
1601 : const PoDoFo::PdfVecObjects &poObjects)
1602 : : m_poArray(poArray), m_poObjects(poObjects)
1603 : {
1604 : }
1605 :
1606 : int GetLength() override;
1607 : GDALPDFObject *Get(int nIndex) override;
1608 : };
1609 :
1610 : /************************************************************************/
1611 : /* ==================================================================== */
1612 : /* GDALPDFStreamPodofo */
1613 : /* ==================================================================== */
1614 : /************************************************************************/
1615 :
1616 : class GDALPDFStreamPodofo final : public GDALPDFStream
1617 : {
1618 : private:
1619 : #if PODOFO_VERSION_MAJOR > 0 || \
1620 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1621 : const PoDoFo::PdfObjectStream *m_pStream;
1622 : #else
1623 : const PoDoFo::PdfStream *m_pStream;
1624 : #endif
1625 :
1626 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFStreamPodofo)
1627 :
1628 : public:
1629 : GDALPDFStreamPodofo(
1630 : #if PODOFO_VERSION_MAJOR > 0 || \
1631 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1632 : const PoDoFo::PdfObjectStream *
1633 : #else
1634 : const PoDoFo::PdfStream *
1635 : #endif
1636 : pStream)
1637 : : m_pStream(pStream)
1638 : {
1639 : }
1640 :
1641 : int64_t GetLength(int64_t nMaxSize = 0) override;
1642 : char *GetBytes() override;
1643 :
1644 : int64_t GetRawLength() override;
1645 : char *GetRawBytes() override;
1646 : };
1647 :
1648 : /************************************************************************/
1649 : /* ==================================================================== */
1650 : /* GDALPDFObjectPodofo */
1651 : /* ==================================================================== */
1652 : /************************************************************************/
1653 :
1654 : /************************************************************************/
1655 : /* GDALPDFObjectPodofo() */
1656 : /************************************************************************/
1657 :
1658 : GDALPDFObjectPodofo::GDALPDFObjectPodofo(const PoDoFo::PdfObject *po,
1659 : const PoDoFo::PdfVecObjects &poObjects)
1660 : : m_po(po), m_poObjects(poObjects)
1661 : {
1662 : try
1663 : {
1664 : #if PODOFO_VERSION_MAJOR > 0 || \
1665 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1666 : if (m_po->GetDataType() == PoDoFo::PdfDataType::Reference)
1667 : {
1668 : PoDoFo::PdfObject *poObj =
1669 : m_poObjects.GetObject(m_po->GetReference());
1670 : if (poObj)
1671 : m_po = poObj;
1672 : }
1673 : #else
1674 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Reference)
1675 : {
1676 : PoDoFo::PdfObject *poObj =
1677 : m_poObjects.GetObject(m_po->GetReference());
1678 : if (poObj)
1679 : m_po = poObj;
1680 : }
1681 : #endif
1682 : }
1683 : catch (PoDoFo::PdfError &oError)
1684 : {
1685 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s",
1686 : oError.what());
1687 : }
1688 : }
1689 :
1690 : /************************************************************************/
1691 : /* ~GDALPDFObjectPodofo() */
1692 : /************************************************************************/
1693 :
1694 : GDALPDFObjectPodofo::~GDALPDFObjectPodofo()
1695 : {
1696 : delete m_poDict;
1697 : delete m_poArray;
1698 : delete m_poStream;
1699 : }
1700 :
1701 : /************************************************************************/
1702 : /* GetType() */
1703 : /************************************************************************/
1704 :
1705 : GDALPDFObjectType GDALPDFObjectPodofo::GetType()
1706 : {
1707 : try
1708 : {
1709 : switch (m_po->GetDataType())
1710 : {
1711 : #if PODOFO_VERSION_MAJOR > 0 || \
1712 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1713 : case PoDoFo::PdfDataType::Null:
1714 : return PDFObjectType_Null;
1715 : case PoDoFo::PdfDataType::Bool:
1716 : return PDFObjectType_Bool;
1717 : case PoDoFo::PdfDataType::Number:
1718 : return PDFObjectType_Int;
1719 : case PoDoFo::PdfDataType::Real:
1720 : return PDFObjectType_Real;
1721 : case PoDoFo::PdfDataType::String:
1722 : return PDFObjectType_String;
1723 : case PoDoFo::PdfDataType::Name:
1724 : return PDFObjectType_Name;
1725 : case PoDoFo::PdfDataType::Array:
1726 : return PDFObjectType_Array;
1727 : case PoDoFo::PdfDataType::Dictionary:
1728 : return PDFObjectType_Dictionary;
1729 : default:
1730 : return PDFObjectType_Unknown;
1731 : #else
1732 : case PoDoFo::ePdfDataType_Null:
1733 : return PDFObjectType_Null;
1734 : case PoDoFo::ePdfDataType_Bool:
1735 : return PDFObjectType_Bool;
1736 : case PoDoFo::ePdfDataType_Number:
1737 : return PDFObjectType_Int;
1738 : case PoDoFo::ePdfDataType_Real:
1739 : return PDFObjectType_Real;
1740 : case PoDoFo::ePdfDataType_HexString:
1741 : return PDFObjectType_String;
1742 : case PoDoFo::ePdfDataType_String:
1743 : return PDFObjectType_String;
1744 : case PoDoFo::ePdfDataType_Name:
1745 : return PDFObjectType_Name;
1746 : case PoDoFo::ePdfDataType_Array:
1747 : return PDFObjectType_Array;
1748 : case PoDoFo::ePdfDataType_Dictionary:
1749 : return PDFObjectType_Dictionary;
1750 : default:
1751 : return PDFObjectType_Unknown;
1752 : #endif
1753 : }
1754 : }
1755 : catch (PoDoFo::PdfError &oError)
1756 : {
1757 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s",
1758 : oError.what());
1759 : return PDFObjectType_Unknown;
1760 : }
1761 : }
1762 :
1763 : /************************************************************************/
1764 : /* GetTypeNameNative() */
1765 : /************************************************************************/
1766 :
1767 : const char *GDALPDFObjectPodofo::GetTypeNameNative()
1768 : {
1769 : try
1770 : {
1771 : osStr = m_po->GetDataTypeString();
1772 : return osStr.c_str();
1773 : }
1774 : catch (PoDoFo::PdfError &oError)
1775 : {
1776 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid PDF : %s",
1777 : oError.what());
1778 : return "unknown";
1779 : }
1780 : }
1781 :
1782 : /************************************************************************/
1783 : /* GetBool() */
1784 : /************************************************************************/
1785 :
1786 : int GDALPDFObjectPodofo::GetBool()
1787 : {
1788 : #if PODOFO_VERSION_MAJOR > 0 || \
1789 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1790 : if (m_po->GetDataType() == PoDoFo::PdfDataType::Bool)
1791 : #else
1792 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Bool)
1793 : #endif
1794 : return m_po->GetBool();
1795 : else
1796 : return 0;
1797 : }
1798 :
1799 : /************************************************************************/
1800 : /* GetInt() */
1801 : /************************************************************************/
1802 :
1803 : int GDALPDFObjectPodofo::GetInt()
1804 : {
1805 : #if PODOFO_VERSION_MAJOR > 0 || \
1806 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1807 : if (m_po->GetDataType() == PoDoFo::PdfDataType::Number)
1808 : #else
1809 : if (m_po->GetDataType() == PoDoFo::ePdfDataType_Number)
1810 : #endif
1811 : return static_cast<int>(m_po->GetNumber());
1812 : else
1813 : return 0;
1814 : }
1815 :
1816 : /************************************************************************/
1817 : /* GetReal() */
1818 : /************************************************************************/
1819 :
1820 : double GDALPDFObjectPodofo::GetReal()
1821 : {
1822 : if (GetType() == PDFObjectType_Real)
1823 : return m_po->GetReal();
1824 : else
1825 : return 0.0;
1826 : }
1827 :
1828 : /************************************************************************/
1829 : /* GetString() */
1830 : /************************************************************************/
1831 :
1832 : const std::string &GDALPDFObjectPodofo::GetString()
1833 : {
1834 : if (GetType() == PDFObjectType_String)
1835 : #if PODOFO_VERSION_MAJOR > 0 || \
1836 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1837 : return (osStr = m_po->GetString().GetString());
1838 : #else
1839 : return (osStr = m_po->GetString().GetStringUtf8());
1840 : #endif
1841 : else
1842 : return (osStr = "");
1843 : }
1844 :
1845 : /************************************************************************/
1846 : /* GetName() */
1847 : /************************************************************************/
1848 :
1849 : const std::string &GDALPDFObjectPodofo::GetName()
1850 : {
1851 : if (GetType() == PDFObjectType_Name)
1852 : #if PODOFO_VERSION_MAJOR > 0 || \
1853 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1854 : return (osStr = m_po->GetName().GetString());
1855 : #else
1856 : return (osStr = m_po->GetName().GetName());
1857 : #endif
1858 : else
1859 : return (osStr = "");
1860 : }
1861 :
1862 : /************************************************************************/
1863 : /* GetDictionary() */
1864 : /************************************************************************/
1865 :
1866 : GDALPDFDictionary *GDALPDFObjectPodofo::GetDictionary()
1867 : {
1868 : if (GetType() != PDFObjectType_Dictionary)
1869 : return nullptr;
1870 :
1871 : if (m_poDict)
1872 : return m_poDict;
1873 :
1874 : m_poDict = new GDALPDFDictionaryPodofo(&m_po->GetDictionary(), m_poObjects);
1875 : return m_poDict;
1876 : }
1877 :
1878 : /************************************************************************/
1879 : /* GetArray() */
1880 : /************************************************************************/
1881 :
1882 : GDALPDFArray *GDALPDFObjectPodofo::GetArray()
1883 : {
1884 : if (GetType() != PDFObjectType_Array)
1885 : return nullptr;
1886 :
1887 : if (m_poArray)
1888 : return m_poArray;
1889 :
1890 : m_poArray = new GDALPDFArrayPodofo(&m_po->GetArray(), m_poObjects);
1891 : return m_poArray;
1892 : }
1893 :
1894 : /************************************************************************/
1895 : /* GetStream() */
1896 : /************************************************************************/
1897 :
1898 : GDALPDFStream *GDALPDFObjectPodofo::GetStream()
1899 : {
1900 : try
1901 : {
1902 : if (!m_po->HasStream())
1903 : return nullptr;
1904 : }
1905 : catch (PoDoFo::PdfError &oError)
1906 : {
1907 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid object : %s",
1908 : oError.what());
1909 : return nullptr;
1910 : }
1911 : catch (...)
1912 : {
1913 : CPLError(CE_Failure, CPLE_AppDefined, "Invalid object");
1914 : return nullptr;
1915 : }
1916 :
1917 : if (m_poStream == nullptr)
1918 : m_poStream = new GDALPDFStreamPodofo(m_po->GetStream());
1919 : return m_poStream;
1920 : }
1921 :
1922 : /************************************************************************/
1923 : /* GetRefNum() */
1924 : /************************************************************************/
1925 :
1926 : GDALPDFObjectNum GDALPDFObjectPodofo::GetRefNum()
1927 : {
1928 : #if PODOFO_VERSION_MAJOR > 0 || \
1929 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1930 : return GDALPDFObjectNum(m_po->GetIndirectReference().ObjectNumber());
1931 : #else
1932 : return GDALPDFObjectNum(m_po->Reference().ObjectNumber());
1933 : #endif
1934 : }
1935 :
1936 : /************************************************************************/
1937 : /* GetRefGen() */
1938 : /************************************************************************/
1939 :
1940 : int GDALPDFObjectPodofo::GetRefGen()
1941 : {
1942 : #if PODOFO_VERSION_MAJOR > 0 || \
1943 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
1944 : return m_po->GetIndirectReference().GenerationNumber();
1945 : #else
1946 : return m_po->Reference().GenerationNumber();
1947 : #endif
1948 : }
1949 :
1950 : /************************************************************************/
1951 : /* ==================================================================== */
1952 : /* GDALPDFDictionaryPodofo */
1953 : /* ==================================================================== */
1954 : /************************************************************************/
1955 :
1956 : /************************************************************************/
1957 : /* ~GDALPDFDictionaryPodofo() */
1958 : /************************************************************************/
1959 :
1960 : GDALPDFDictionaryPodofo::~GDALPDFDictionaryPodofo()
1961 : {
1962 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
1963 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
1964 : for (; oIter != oEnd; ++oIter)
1965 : delete oIter->second;
1966 : }
1967 :
1968 : /************************************************************************/
1969 : /* Get() */
1970 : /************************************************************************/
1971 :
1972 : GDALPDFObject *GDALPDFDictionaryPodofo::Get(const char *pszKey)
1973 : {
1974 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
1975 : if (oIter != m_map.end())
1976 : return oIter->second;
1977 :
1978 : const PoDoFo::PdfObject *poVal = m_poDict->GetKey(PoDoFo::PdfName(pszKey));
1979 : if (poVal)
1980 : {
1981 : GDALPDFObjectPodofo *poObj =
1982 : new GDALPDFObjectPodofo(poVal, m_poObjects);
1983 : m_map[pszKey] = poObj;
1984 : return poObj;
1985 : }
1986 : else
1987 : {
1988 : return nullptr;
1989 : }
1990 : }
1991 :
1992 : /************************************************************************/
1993 : /* GetValues() */
1994 : /************************************************************************/
1995 :
1996 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryPodofo::GetValues()
1997 : {
1998 : #if PODOFO_VERSION_MAJOR > 0 || \
1999 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2000 : for (const auto &oIter : *m_poDict)
2001 : {
2002 : const std::string osTmp(oIter.first.GetString());
2003 : Get(osTmp.c_str());
2004 : }
2005 : #else
2006 : for (const auto &oIter : m_poDict->GetKeys())
2007 : {
2008 : Get(oIter.first.GetName().c_str());
2009 : }
2010 : #endif
2011 : return m_map;
2012 : }
2013 :
2014 : /************************************************************************/
2015 : /* ==================================================================== */
2016 : /* GDALPDFArrayPodofo */
2017 : /* ==================================================================== */
2018 : /************************************************************************/
2019 :
2020 : /************************************************************************/
2021 : /* GetLength() */
2022 : /************************************************************************/
2023 :
2024 : int GDALPDFArrayPodofo::GetLength()
2025 : {
2026 : return static_cast<int>(m_poArray->GetSize());
2027 : }
2028 :
2029 : /************************************************************************/
2030 : /* Get() */
2031 : /************************************************************************/
2032 :
2033 : GDALPDFObject *GDALPDFArrayPodofo::Get(int nIndex)
2034 : {
2035 : if (nIndex < 0 || nIndex >= GetLength())
2036 : return nullptr;
2037 :
2038 : if (m_v.empty())
2039 : m_v.resize(GetLength());
2040 :
2041 : if (m_v[nIndex] != nullptr)
2042 : return m_v[nIndex].get();
2043 :
2044 : const PoDoFo::PdfObject &oVal = (*m_poArray)[nIndex];
2045 : m_v[nIndex] = std::make_unique<GDALPDFObjectPodofo>(&oVal, m_poObjects);
2046 : return m_v[nIndex].get();
2047 : }
2048 :
2049 : /************************************************************************/
2050 : /* ==================================================================== */
2051 : /* GDALPDFStreamPodofo */
2052 : /* ==================================================================== */
2053 : /************************************************************************/
2054 :
2055 : /************************************************************************/
2056 : /* GetLength() */
2057 : /************************************************************************/
2058 :
2059 : int64_t GDALPDFStreamPodofo::GetLength(int64_t /* nMaxSize */)
2060 : {
2061 : #if PODOFO_VERSION_MAJOR > 0 || \
2062 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2063 : PoDoFo::charbuff str;
2064 : try
2065 : {
2066 : m_pStream->CopyToSafe(str);
2067 : }
2068 : catch (PoDoFo::PdfError &e)
2069 : {
2070 : CPLError(CE_Failure, CPLE_AppDefined, "CopyToSafe() failed: %s",
2071 : e.what());
2072 : return 0;
2073 : }
2074 : return static_cast<int64_t>(str.size());
2075 : #else
2076 : char *pBuffer = nullptr;
2077 : PoDoFo::pdf_long nLen = 0;
2078 : try
2079 : {
2080 : m_pStream->GetFilteredCopy(&pBuffer, &nLen);
2081 : PoDoFo::podofo_free(pBuffer);
2082 : return static_cast<int64_t>(nLen);
2083 : }
2084 : catch (PoDoFo::PdfError &e)
2085 : {
2086 : }
2087 : return 0;
2088 : #endif
2089 : }
2090 :
2091 : /************************************************************************/
2092 : /* GetBytes() */
2093 : /************************************************************************/
2094 :
2095 : char *GDALPDFStreamPodofo::GetBytes()
2096 : {
2097 : #if PODOFO_VERSION_MAJOR > 0 || \
2098 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2099 : PoDoFo::charbuff str;
2100 : try
2101 : {
2102 : m_pStream->CopyToSafe(str);
2103 : }
2104 : catch (PoDoFo::PdfError &e)
2105 : {
2106 : CPLError(CE_Failure, CPLE_AppDefined, "CopyToSafe() failed: %s",
2107 : e.what());
2108 : return nullptr;
2109 : }
2110 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(str.size() + 1));
2111 : if (!pszContent)
2112 : {
2113 : return nullptr;
2114 : }
2115 : memcpy(pszContent, str.data(), str.size());
2116 : pszContent[str.size()] = '\0';
2117 : return pszContent;
2118 : #else
2119 : char *pBuffer = nullptr;
2120 : PoDoFo::pdf_long nLen = 0;
2121 : try
2122 : {
2123 : m_pStream->GetFilteredCopy(&pBuffer, &nLen);
2124 : }
2125 : catch (PoDoFo::PdfError &e)
2126 : {
2127 : return nullptr;
2128 : }
2129 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLen + 1));
2130 : if (!pszContent)
2131 : {
2132 : PoDoFo::podofo_free(pBuffer);
2133 : return nullptr;
2134 : }
2135 : memcpy(pszContent, pBuffer, nLen);
2136 : PoDoFo::podofo_free(pBuffer);
2137 : pszContent[nLen] = '\0';
2138 : return pszContent;
2139 : #endif
2140 : }
2141 :
2142 : /************************************************************************/
2143 : /* GetRawLength() */
2144 : /************************************************************************/
2145 :
2146 : int64_t GDALPDFStreamPodofo::GetRawLength()
2147 : {
2148 : try
2149 : {
2150 : auto nLen = m_pStream->GetLength();
2151 : return static_cast<int64_t>(nLen);
2152 : }
2153 : catch (PoDoFo::PdfError &e)
2154 : {
2155 : }
2156 : return 0;
2157 : }
2158 :
2159 : /************************************************************************/
2160 : /* GetRawBytes() */
2161 : /************************************************************************/
2162 :
2163 : char *GDALPDFStreamPodofo::GetRawBytes()
2164 : {
2165 : #if PODOFO_VERSION_MAJOR > 0 || \
2166 : (PODOFO_VERSION_MAJOR == 0 && PODOFO_VERSION_MINOR >= 10)
2167 : PoDoFo::charbuff str;
2168 : try
2169 : {
2170 : PoDoFo::StringStreamDevice stream(str);
2171 : #ifdef USE_HACK_BECAUSE_PdfInputStream_constructor_is_not_exported_in_podofo_0_11
2172 : auto *poNonConstStream =
2173 : const_cast<PoDoFo::PdfObjectStream *>(m_pStream);
2174 : auto inputStream = poNonConstStream->GetProvider().GetInputStream(
2175 : poNonConstStream->GetParent());
2176 : inputStream->CopyTo(stream);
2177 : #else
2178 : // Should work but fails to link because PdfInputStream destructor
2179 : // is not exported
2180 : auto inputStream = m_pStream->GetInputStream(/*raw=*/true);
2181 : inputStream.CopyTo(stream);
2182 : #endif
2183 : stream.Flush();
2184 : }
2185 : catch (PoDoFo::PdfError &e)
2186 : {
2187 : CPLError(CE_Failure, CPLE_AppDefined, "CopyToSafe() failed: %s",
2188 : e.what());
2189 : return nullptr;
2190 : }
2191 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(str.size() + 1));
2192 : if (!pszContent)
2193 : {
2194 : return nullptr;
2195 : }
2196 : memcpy(pszContent, str.data(), str.size());
2197 : pszContent[str.size()] = '\0';
2198 : return pszContent;
2199 : #else
2200 : char *pBuffer = nullptr;
2201 : PoDoFo::pdf_long nLen = 0;
2202 : try
2203 : {
2204 : m_pStream->GetCopy(&pBuffer, &nLen);
2205 : }
2206 : catch (PoDoFo::PdfError &e)
2207 : {
2208 : return nullptr;
2209 : }
2210 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLen + 1));
2211 : if (!pszContent)
2212 : {
2213 : PoDoFo::podofo_free(pBuffer);
2214 : return nullptr;
2215 : }
2216 : memcpy(pszContent, pBuffer, nLen);
2217 : PoDoFo::podofo_free(pBuffer);
2218 : pszContent[nLen] = '\0';
2219 : return pszContent;
2220 : #endif
2221 : }
2222 :
2223 : #endif // HAVE_PODOFO
2224 :
2225 : #ifdef HAVE_PDFIUM
2226 :
2227 : /************************************************************************/
2228 : /* ==================================================================== */
2229 : /* GDALPDFDictionaryPdfium */
2230 : /* ==================================================================== */
2231 : /************************************************************************/
2232 :
2233 : class GDALPDFDictionaryPdfium final : public GDALPDFDictionary
2234 : {
2235 : private:
2236 : RetainPtr<const CPDF_Dictionary> m_poDict;
2237 : std::map<CPLString, GDALPDFObject *> m_map{};
2238 :
2239 : public:
2240 : GDALPDFDictionaryPdfium(RetainPtr<const CPDF_Dictionary> poDict)
2241 : : m_poDict(std::move(poDict))
2242 : {
2243 : }
2244 :
2245 : ~GDALPDFDictionaryPdfium() override;
2246 :
2247 : GDALPDFObject *Get(const char *pszKey) override;
2248 : std::map<CPLString, GDALPDFObject *> &GetValues() override;
2249 : };
2250 :
2251 : /************************************************************************/
2252 : /* ==================================================================== */
2253 : /* GDALPDFArrayPdfium */
2254 : /* ==================================================================== */
2255 : /************************************************************************/
2256 :
2257 : class GDALPDFArrayPdfium final : public GDALPDFArray
2258 : {
2259 : private:
2260 : const CPDF_Array *m_poArray;
2261 : std::vector<std::unique_ptr<GDALPDFObject>> m_v{};
2262 :
2263 : CPL_DISALLOW_COPY_ASSIGN(GDALPDFArrayPdfium)
2264 :
2265 : public:
2266 : GDALPDFArrayPdfium(const CPDF_Array *poArray) : m_poArray(poArray)
2267 : {
2268 : }
2269 :
2270 : int GetLength() override;
2271 : GDALPDFObject *Get(int nIndex) override;
2272 : };
2273 :
2274 : /************************************************************************/
2275 : /* ==================================================================== */
2276 : /* GDALPDFStreamPdfium */
2277 : /* ==================================================================== */
2278 : /************************************************************************/
2279 :
2280 : class GDALPDFStreamPdfium final : public GDALPDFStream
2281 : {
2282 : private:
2283 : RetainPtr<const CPDF_Stream> m_pStream;
2284 : int64_t m_nSize = 0;
2285 : std::unique_ptr<uint8_t, VSIFreeReleaser> m_pData = nullptr;
2286 : int64_t m_nRawSize = 0;
2287 : std::unique_ptr<uint8_t, VSIFreeReleaser> m_pRawData = nullptr;
2288 :
2289 : void Decompress();
2290 : void FillRaw();
2291 :
2292 : public:
2293 : GDALPDFStreamPdfium(RetainPtr<const CPDF_Stream> pStream)
2294 : : m_pStream(std::move(pStream))
2295 : {
2296 : }
2297 :
2298 : int64_t GetLength(int64_t nMaxSize = 0) override;
2299 : char *GetBytes() override;
2300 :
2301 : int64_t GetRawLength() override;
2302 : char *GetRawBytes() override;
2303 : };
2304 :
2305 : /************************************************************************/
2306 : /* ==================================================================== */
2307 : /* GDALPDFObjectPdfium */
2308 : /* ==================================================================== */
2309 : /************************************************************************/
2310 :
2311 : /************************************************************************/
2312 : /* GDALPDFObjectPdfium() */
2313 : /************************************************************************/
2314 :
2315 : GDALPDFObjectPdfium::GDALPDFObjectPdfium(RetainPtr<const CPDF_Object> obj)
2316 : : m_obj(std::move(obj))
2317 : {
2318 : CPLAssert(m_obj != nullptr);
2319 : }
2320 :
2321 : /************************************************************************/
2322 : /* ~GDALPDFObjectPdfium() */
2323 : /************************************************************************/
2324 :
2325 : GDALPDFObjectPdfium::~GDALPDFObjectPdfium()
2326 : {
2327 : delete m_poDict;
2328 : delete m_poArray;
2329 : delete m_poStream;
2330 : }
2331 :
2332 : /************************************************************************/
2333 : /* Build() */
2334 : /************************************************************************/
2335 :
2336 : GDALPDFObjectPdfium *
2337 : GDALPDFObjectPdfium::Build(RetainPtr<const CPDF_Object> obj)
2338 : {
2339 : if (obj == nullptr)
2340 : return nullptr;
2341 : if (obj->GetType() == CPDF_Object::Type::kReference)
2342 : {
2343 : obj = obj->GetDirect();
2344 : if (obj == nullptr)
2345 : {
2346 : CPLError(CE_Failure, CPLE_AppDefined,
2347 : "Cannot resolve indirect object");
2348 : return nullptr;
2349 : }
2350 : }
2351 : return new GDALPDFObjectPdfium(std::move(obj));
2352 : }
2353 :
2354 : /************************************************************************/
2355 : /* GetType() */
2356 : /************************************************************************/
2357 :
2358 : GDALPDFObjectType GDALPDFObjectPdfium::GetType()
2359 : {
2360 : switch (m_obj->GetType())
2361 : {
2362 : case CPDF_Object::Type::kNullobj:
2363 : return PDFObjectType_Null;
2364 : case CPDF_Object::Type::kBoolean:
2365 : return PDFObjectType_Bool;
2366 : case CPDF_Object::Type::kNumber:
2367 : return (cpl::down_cast<const CPDF_Number *>(m_obj.Get()))
2368 : ->IsInteger()
2369 : ? PDFObjectType_Int
2370 : : PDFObjectType_Real;
2371 : case CPDF_Object::Type::kString:
2372 : return PDFObjectType_String;
2373 : case CPDF_Object::Type::kName:
2374 : return PDFObjectType_Name;
2375 : case CPDF_Object::Type::kArray:
2376 : return PDFObjectType_Array;
2377 : case CPDF_Object::Type::kDictionary:
2378 : return PDFObjectType_Dictionary;
2379 : case CPDF_Object::Type::kStream:
2380 : return PDFObjectType_Dictionary;
2381 : case CPDF_Object::Type::kReference:
2382 : // unresolved reference
2383 : return PDFObjectType_Unknown;
2384 : default:
2385 : CPLAssert(false);
2386 : return PDFObjectType_Unknown;
2387 : }
2388 : }
2389 :
2390 : /************************************************************************/
2391 : /* GetTypeNameNative() */
2392 : /************************************************************************/
2393 :
2394 : const char *GDALPDFObjectPdfium::GetTypeNameNative()
2395 : {
2396 : if (m_obj->GetType() == CPDF_Object::Type::kStream)
2397 : return "stream";
2398 : else
2399 : return "";
2400 : }
2401 :
2402 : /************************************************************************/
2403 : /* GetBool() */
2404 : /************************************************************************/
2405 :
2406 : int GDALPDFObjectPdfium::GetBool()
2407 : {
2408 : return m_obj->GetInteger();
2409 : }
2410 :
2411 : /************************************************************************/
2412 : /* GetInt() */
2413 : /************************************************************************/
2414 :
2415 : int GDALPDFObjectPdfium::GetInt()
2416 : {
2417 : return m_obj->GetInteger();
2418 : }
2419 :
2420 : /************************************************************************/
2421 : /* CPLRoundToMoreLikelyDouble() */
2422 : /************************************************************************/
2423 :
2424 : // We try to compensate for rounding errors when converting the number
2425 : // in the PDF expressed as a string (e.g 297.84) to float32 by pdfium :
2426 : // 297.8399963378906 Which is technically correct per the PDF spec, but in
2427 : // practice poppler or podofo use double and Geospatial PDF are often encoded
2428 : // with double precision.
2429 :
2430 : static double CPLRoundToMoreLikelyDouble(float f)
2431 : {
2432 : if (std::round(f) == f)
2433 : return f;
2434 :
2435 : char szBuffer[80];
2436 : CPLsnprintf(szBuffer, 80, "%f\n", f);
2437 : double d = f;
2438 : char *pszDot = strchr(szBuffer, '.');
2439 : if (pszDot == nullptr)
2440 : return d;
2441 : pszDot++;
2442 : if (pszDot[0] == 0 || pszDot[1] == 0)
2443 : return d;
2444 : if (STARTS_WITH(pszDot + 2, "99"))
2445 : {
2446 : pszDot[2] = 0;
2447 : double d2 = CPLAtof(szBuffer) + 0.01;
2448 : float f2 = static_cast<float>(d2);
2449 : if (f == f2 || nextafterf(f, f + 1.0f) == f2 ||
2450 : nextafterf(f, f - 1.0f) == f2)
2451 : d = d2;
2452 : }
2453 : else if (STARTS_WITH(pszDot + 2, "00"))
2454 : {
2455 : pszDot[2] = 0;
2456 : double d2 = CPLAtof(szBuffer);
2457 : float f2 = static_cast<float>(d2);
2458 : if (f == f2 || nextafterf(f, f + 1.0f) == f2 ||
2459 : nextafterf(f, f - 1.0f) == f2)
2460 : d = d2;
2461 : }
2462 : return d;
2463 : }
2464 :
2465 : /************************************************************************/
2466 : /* GetReal() */
2467 : /************************************************************************/
2468 :
2469 : double GDALPDFObjectPdfium::GetReal()
2470 : {
2471 : return CPLRoundToMoreLikelyDouble(m_obj->GetNumber());
2472 : }
2473 :
2474 : /************************************************************************/
2475 : /* GetString() */
2476 : /************************************************************************/
2477 :
2478 : const std::string &GDALPDFObjectPdfium::GetString()
2479 : {
2480 : if (GetType() == PDFObjectType_String)
2481 : {
2482 : const auto bs = m_obj->GetString();
2483 : // If empty string, code crashes
2484 : if (bs.IsEmpty())
2485 : return (osStr = "");
2486 : return (osStr = GDALPDFGetUTF8StringFromBytes(
2487 : reinterpret_cast<const GByte *>(bs.c_str()),
2488 : static_cast<int>(bs.GetLength())));
2489 : }
2490 : else
2491 : return (osStr = "");
2492 : }
2493 :
2494 : /************************************************************************/
2495 : /* GetName() */
2496 : /************************************************************************/
2497 :
2498 : const std::string &GDALPDFObjectPdfium::GetName()
2499 : {
2500 : if (GetType() == PDFObjectType_Name)
2501 : return (osStr = m_obj->GetString().c_str());
2502 : else
2503 : return (osStr = "");
2504 : }
2505 :
2506 : /************************************************************************/
2507 : /* GetDictionary() */
2508 : /************************************************************************/
2509 :
2510 : GDALPDFDictionary *GDALPDFObjectPdfium::GetDictionary()
2511 : {
2512 : if (GetType() != PDFObjectType_Dictionary)
2513 : return nullptr;
2514 :
2515 : if (m_poDict)
2516 : return m_poDict;
2517 :
2518 : m_poDict = new GDALPDFDictionaryPdfium(m_obj->GetDict());
2519 : return m_poDict;
2520 : }
2521 :
2522 : /************************************************************************/
2523 : /* GetArray() */
2524 : /************************************************************************/
2525 :
2526 : GDALPDFArray *GDALPDFObjectPdfium::GetArray()
2527 : {
2528 : if (GetType() != PDFObjectType_Array)
2529 : return nullptr;
2530 :
2531 : if (m_poArray)
2532 : return m_poArray;
2533 :
2534 : m_poArray =
2535 : new GDALPDFArrayPdfium(cpl::down_cast<const CPDF_Array *>(m_obj.Get()));
2536 : return m_poArray;
2537 : }
2538 :
2539 : /************************************************************************/
2540 : /* GetStream() */
2541 : /************************************************************************/
2542 :
2543 : GDALPDFStream *GDALPDFObjectPdfium::GetStream()
2544 : {
2545 : if (m_obj->GetType() != CPDF_Object::Type::kStream)
2546 : return nullptr;
2547 :
2548 : if (m_poStream)
2549 : return m_poStream;
2550 : auto pStream = pdfium::WrapRetain(m_obj->AsStream());
2551 : if (pStream)
2552 : {
2553 : m_poStream = new GDALPDFStreamPdfium(std::move(pStream));
2554 : return m_poStream;
2555 : }
2556 : else
2557 : return nullptr;
2558 : }
2559 :
2560 : /************************************************************************/
2561 : /* GetRefNum() */
2562 : /************************************************************************/
2563 :
2564 : GDALPDFObjectNum GDALPDFObjectPdfium::GetRefNum()
2565 : {
2566 : return GDALPDFObjectNum(m_obj->GetObjNum());
2567 : }
2568 :
2569 : /************************************************************************/
2570 : /* GetRefGen() */
2571 : /************************************************************************/
2572 :
2573 : int GDALPDFObjectPdfium::GetRefGen()
2574 : {
2575 : return m_obj->GetGenNum();
2576 : }
2577 :
2578 : /************************************************************************/
2579 : /* ==================================================================== */
2580 : /* GDALPDFDictionaryPdfium */
2581 : /* ==================================================================== */
2582 : /************************************************************************/
2583 :
2584 : /************************************************************************/
2585 : /* ~GDALPDFDictionaryPdfium() */
2586 : /************************************************************************/
2587 :
2588 : GDALPDFDictionaryPdfium::~GDALPDFDictionaryPdfium()
2589 : {
2590 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.begin();
2591 : std::map<CPLString, GDALPDFObject *>::iterator oEnd = m_map.end();
2592 : for (; oIter != oEnd; ++oIter)
2593 : delete oIter->second;
2594 : }
2595 :
2596 : /************************************************************************/
2597 : /* Get() */
2598 : /************************************************************************/
2599 :
2600 : GDALPDFObject *GDALPDFDictionaryPdfium::Get(const char *pszKey)
2601 : {
2602 : std::map<CPLString, GDALPDFObject *>::iterator oIter = m_map.find(pszKey);
2603 : if (oIter != m_map.end())
2604 : return oIter->second;
2605 :
2606 : ByteStringView pdfiumKey(pszKey);
2607 : GDALPDFObjectPdfium *poObj =
2608 : GDALPDFObjectPdfium::Build(m_poDict->GetObjectFor(pdfiumKey));
2609 : if (poObj)
2610 : {
2611 : m_map[pszKey] = poObj;
2612 : return poObj;
2613 : }
2614 : else
2615 : {
2616 : return nullptr;
2617 : }
2618 : }
2619 :
2620 : /************************************************************************/
2621 : /* GetValues() */
2622 : /************************************************************************/
2623 :
2624 : std::map<CPLString, GDALPDFObject *> &GDALPDFDictionaryPdfium::GetValues()
2625 : {
2626 : CPDF_DictionaryLocker dictIterator(m_poDict);
2627 : for (const auto &iter : dictIterator)
2628 : {
2629 : // No object for this key
2630 : if (!iter.second)
2631 : continue;
2632 :
2633 : const char *pszKey = iter.first.c_str();
2634 : // Objects exists in the map
2635 : if (m_map.find(pszKey) != m_map.end())
2636 : continue;
2637 : GDALPDFObjectPdfium *poObj = GDALPDFObjectPdfium::Build(iter.second);
2638 : if (poObj == nullptr)
2639 : continue;
2640 : m_map[pszKey] = poObj;
2641 : }
2642 :
2643 : return m_map;
2644 : }
2645 :
2646 : /************************************************************************/
2647 : /* ==================================================================== */
2648 : /* GDALPDFArrayPdfium */
2649 : /* ==================================================================== */
2650 : /************************************************************************/
2651 :
2652 : /************************************************************************/
2653 : /* GetLength() */
2654 : /************************************************************************/
2655 :
2656 : int GDALPDFArrayPdfium::GetLength()
2657 : {
2658 : return static_cast<int>(m_poArray->size());
2659 : }
2660 :
2661 : /************************************************************************/
2662 : /* Get() */
2663 : /************************************************************************/
2664 :
2665 : GDALPDFObject *GDALPDFArrayPdfium::Get(int nIndex)
2666 : {
2667 : if (nIndex < 0 || nIndex >= GetLength())
2668 : return nullptr;
2669 :
2670 : if (m_v.empty())
2671 : m_v.resize(GetLength());
2672 :
2673 : if (m_v[nIndex] != nullptr)
2674 : return m_v[nIndex].get();
2675 :
2676 : auto poObj = std::unique_ptr<GDALPDFObjectPdfium>(
2677 : GDALPDFObjectPdfium::Build(m_poArray->GetObjectAt(nIndex)));
2678 : if (poObj == nullptr)
2679 : return nullptr;
2680 : m_v[nIndex] = std::move(poObj);
2681 : return m_v[nIndex].get();
2682 : }
2683 :
2684 : /************************************************************************/
2685 : /* ==================================================================== */
2686 : /* GDALPDFStreamPdfium */
2687 : /* ==================================================================== */
2688 : /************************************************************************/
2689 :
2690 : void GDALPDFStreamPdfium::Decompress()
2691 : {
2692 : if (m_pData != nullptr)
2693 : return;
2694 : auto acc(pdfium::MakeRetain<CPDF_StreamAcc>(m_pStream));
2695 : acc->LoadAllDataFiltered();
2696 : m_nSize = static_cast<int64_t>(acc->GetSize());
2697 : m_pData.reset();
2698 : const auto nSize = static_cast<size_t>(m_nSize);
2699 : if (static_cast<int64_t>(nSize) != m_nSize)
2700 : {
2701 : m_nSize = 0;
2702 : }
2703 : if (m_nSize)
2704 : {
2705 : m_pData.reset(static_cast<uint8_t *>(VSI_MALLOC_VERBOSE(nSize)));
2706 : if (!m_pData)
2707 : m_nSize = 0;
2708 : else
2709 : memcpy(&m_pData.get()[0], acc->DetachData().data(), nSize);
2710 : }
2711 : }
2712 :
2713 : /************************************************************************/
2714 : /* GetLength() */
2715 : /************************************************************************/
2716 :
2717 : int64_t GDALPDFStreamPdfium::GetLength(int64_t /* nMaxSize */)
2718 : {
2719 : Decompress();
2720 : return m_nSize;
2721 : }
2722 :
2723 : /************************************************************************/
2724 : /* GetBytes() */
2725 : /************************************************************************/
2726 :
2727 : char *GDALPDFStreamPdfium::GetBytes()
2728 : {
2729 : size_t nLength = static_cast<size_t>(GetLength());
2730 : if (nLength == 0)
2731 : return nullptr;
2732 : char *pszContent = static_cast<char *>(VSI_MALLOC_VERBOSE(nLength + 1));
2733 : if (!pszContent)
2734 : return nullptr;
2735 : memcpy(pszContent, m_pData.get(), nLength);
2736 : pszContent[nLength] = '\0';
2737 : return pszContent;
2738 : }
2739 :
2740 : /************************************************************************/
2741 : /* FillRaw() */
2742 : /************************************************************************/
2743 :
2744 : void GDALPDFStreamPdfium::FillRaw()
2745 : {
2746 : if (m_pRawData != nullptr)
2747 : return;
2748 : auto acc(pdfium::MakeRetain<CPDF_StreamAcc>(m_pStream));
2749 : acc->LoadAllDataRaw();
2750 : m_nRawSize = static_cast<int64_t>(acc->GetSize());
2751 : m_pRawData.reset();
2752 : const auto nSize = static_cast<size_t>(m_nRawSize);
2753 : if (static_cast<int64_t>(nSize) != m_nRawSize)
2754 : {
2755 : m_nRawSize = 0;
2756 : }
2757 : if (m_nRawSize)
2758 : {
2759 : m_pRawData.reset(
2760 : static_cast<uint8_t *>(VSI_MALLOC_VERBOSE(m_nRawSize)));
2761 : if (!m_pRawData)
2762 : m_nRawSize = 0;
2763 : else
2764 : memcpy(&m_pRawData.get()[0], acc->DetachData().data(), m_nRawSize);
2765 : }
2766 : }
2767 :
2768 : /************************************************************************/
2769 : /* GetRawLength() */
2770 : /************************************************************************/
2771 :
2772 : int64_t GDALPDFStreamPdfium::GetRawLength()
2773 : {
2774 : FillRaw();
2775 : return m_nRawSize;
2776 : }
2777 :
2778 : /************************************************************************/
2779 : /* GetRawBytes() */
2780 : /************************************************************************/
2781 :
2782 : char *GDALPDFStreamPdfium::GetRawBytes()
2783 : {
2784 : size_t nLength = static_cast<size_t>(GetRawLength());
2785 : if (nLength == 0)
2786 : return nullptr;
2787 : char *pszContent =
2788 : static_cast<char *>(VSI_MALLOC_VERBOSE(sizeof(char) * (nLength + 1)));
2789 : if (!pszContent)
2790 : return nullptr;
2791 : memcpy(pszContent, m_pRawData.get(), nLength);
2792 : pszContent[nLength] = '\0';
2793 : return pszContent;
2794 : }
2795 :
2796 : #endif // HAVE_PDFIUM
|