tdf#154285 Check upper bound of arguments in SbRtl_Minute function
[LibreOffice.git] / vcl / source / filter / ipdf / pdfcompat.cxx
blob2710b97a788c2e3ea844741ed5e18a4998838adf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <pdf/pdfcompat.hxx>
12 #include <o3tl/string_view.hxx>
13 #include <tools/solar.h>
14 #include <vcl/filter/PDFiumLibrary.hxx>
15 #include <sal/log.hxx>
17 namespace vcl::pdf
19 /// Decide if PDF data is old enough to be compatible.
20 bool isCompatible(SvStream& rInStream, sal_uInt64 nPos, sal_uInt64 nSize)
22 if (nSize < 8)
23 return false;
25 // %PDF-x.y
26 sal_uInt8 aFirstBytes[8];
27 rInStream.Seek(nPos);
28 sal_uLong nRead = rInStream.ReadBytes(aFirstBytes, 8);
29 if (nRead < 8)
30 return false;
32 if (aFirstBytes[0] != '%' || aFirstBytes[1] != 'P' || aFirstBytes[2] != 'D'
33 || aFirstBytes[3] != 'F' || aFirstBytes[4] != '-')
34 return false;
36 sal_Int32 nMajor = o3tl::toInt32(std::string_view(reinterpret_cast<char*>(&aFirstBytes[5]), 1));
37 sal_Int32 nMinor = o3tl::toInt32(std::string_view(reinterpret_cast<char*>(&aFirstBytes[7]), 1));
38 return !(nMajor > 1 || (nMajor == 1 && nMinor > 6));
41 /// Converts to highest supported format version (1.6).
42 /// Usually used to deal with missing referenced objects in source
43 /// pdf stream.
44 bool convertToHighestSupported(SvStream& rInStream, SvStream& rOutStream)
46 sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN;
47 sal_uInt64 nSize = STREAM_SEEK_TO_END;
48 rInStream.Seek(nPos);
49 // Convert to PDF-1.6.
50 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
51 if (!pPdfium)
52 return false;
54 // Read input into a buffer.
55 SvMemoryStream aInBuffer;
56 aInBuffer.WriteStream(rInStream, nSize);
58 SvMemoryStream aSaved;
60 // Load the buffer using pdfium.
61 std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
62 = pPdfium->openDocument(aInBuffer.GetData(), aInBuffer.GetSize(), OString());
63 if (!pPdfDocument)
64 return false;
66 // 16 means PDF-1.6.
67 if (!pPdfDocument->saveWithVersion(aSaved, 16))
68 return false;
71 aSaved.Seek(STREAM_SEEK_TO_BEGIN);
72 rOutStream.WriteStream(aSaved);
74 return rOutStream.good();
77 /// Takes care of transparently downgrading the version of the PDF stream in
78 /// case it's too new for our PDF export.
79 bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream)
81 sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN;
82 sal_uInt64 nSize = STREAM_SEEK_TO_END;
83 bool bCompatible = isCompatible(rInStream, nPos, nSize);
84 rInStream.Seek(nPos);
85 if (bCompatible)
86 // Not converting.
87 rOutStream.WriteStream(rInStream, nSize);
88 else
89 convertToHighestSupported(rInStream, rOutStream);
91 return rOutStream.good();
94 BinaryDataContainer createBinaryDataContainer(SvStream& rStream)
96 // Save the original PDF stream for later use.
97 SvMemoryStream aMemoryStream;
98 if (!getCompatibleStream(rStream, aMemoryStream))
99 return {};
101 const sal_uInt64 nStreamLength = aMemoryStream.TellEnd();
103 aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
104 BinaryDataContainer aPdfData(aMemoryStream, nStreamLength);
105 if (aMemoryStream.GetError())
106 return {};
108 return aPdfData;
111 } // end vcl::filter::ipdf namespace
113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */