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