17#include <com/sun/star/uno/Sequence.hxx>
18#include <com/sun/star/security/XCertificate.hpp>
23#include <rtl/character.hxx>
24#include <rtl/strbuf.hxx>
25#include <rtl/string.hxx>
48 if (nPosition >= aSignatures.size())
50 SAL_WARN(
"vcl.filter",
"PDFDocument::RemoveSignature: invalid nPosition");
54 if (aSignatures.size() !=
m_aEOFs.size() - 1)
56 SAL_WARN(
"vcl.filter",
"PDFDocument::RemoveSignature: no 1:1 mapping between signatures "
57 "and incremental updates");
72 sal_Int32 nObject =
m_aXRef.size();
81 SAL_WARN(
"vcl.filter",
"PDFDocument::updateObject: invalid nObject");
95 return nWritten == nBytes;
114 const OString& rValue = pT->
GetValue();
115 static constexpr std::string_view aPrefix =
"Signature";
116 if (!rValue.startsWith(aPrefix))
119 nRet = std::max(nRet,
o3tl::toUInt32(rValue.subView(aPrefix.size())));
126 sal_uInt64& rLastByteRangeOffset,
127 sal_Int64& rContentOffset)
130 sal_Int32 nSignatureId =
m_aXRef.size();
134 m_aXRef[nSignatureId] = aSignatureEntry;
135 OStringBuffer aSigBuffer(OString::number(nSignatureId)
138 rContentOffset = aSignatureEntry.
GetOffset() + aSigBuffer.getLength();
142 aSigBuffer.append(aContentFiller +
">\n/Type/Sig/SubFilter");
144 aSigBuffer.append(
"/ETSI.CAdES.detached");
146 aSigBuffer.append(
"/adbe.pkcs7.detached");
156 + OString::number(rContentOffset - 1) +
" "
158 rLastByteRangeOffset = aSignatureEntry.
GetOffset() + aSigBuffer.getLength();
161 OStringBuffer aByteRangeFiller;
163 aSigBuffer.append(aByteRangeFiller
165 +
" /Filter/Adobe.PPKMS");
167 if (!rDescription.isEmpty())
169 aSigBuffer.append(
"/Reason<");
171 aSigBuffer.append(
">");
174 aSigBuffer.append(
" >>\nendobj\n\n");
184 std::vector<filter::PDFObjectElement*> aContentStreams;
193 if (!aPDFDocument.
Read(aPDFStream))
196 "PDFDocument::WriteAppearanceObject: failed to read the PDF document");
200 std::vector<filter::PDFObjectElement*> aPages = aPDFDocument.
GetPages();
203 SAL_WARN(
"vcl.filter",
"PDFDocument::WriteAppearanceObject: no pages");
210 SAL_WARN(
"vcl.filter",
"PDFDocument::WriteAppearanceObject: no page");
217 if (!pMediaBoxArray || pMediaBoxArray->GetElements().size() < 4)
220 "PDFDocument::WriteAppearanceObject: MediaBox is not an array of 4");
223 const std::vector<PDFElement*>& rMediaBoxElements = pMediaBoxArray->GetElements();
227 SAL_WARN(
"vcl.filter",
"PDFDocument::WriteAppearanceObject: MediaBox has no width");
230 rSignatureRectangle.
setWidth(pWidth->GetValue());
234 SAL_WARN(
"vcl.filter",
"PDFDocument::WriteAppearanceObject: MediaBox has no height");
237 rSignatureRectangle.
setHeight(pHeight->GetValue());
241 aContentStreams.push_back(pContentStream);
244 if (aContentStreams.empty())
246 SAL_WARN(
"vcl.filter",
"PDFDocument::WriteAppearanceObject: no content stream");
253 sal_Int32 nAppearanceId =
m_aXRef.size();
260 aEditBuffer.
WriteOString(
"<</Type/XObject\n/Subtype/Form\n");
263 if (!aContentStreams.empty())
265 assert(pPage &&
"aContentStreams is only filled if there was a pPage");
279 bool bCompressed =
false;
281 if (!aContentStreams.empty())
305 m_aXRef[nAppearanceId] = aAppearanceEntry;
308 return nAppearanceId;
312 sal_Int32 nAppearanceId,
319 sal_Int32 nAnnotId =
m_aXRef.size();
323 m_aXRef[nAnnotId] = aAnnotEntry;
357 if (pAnnotsReference)
363 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: invalid Annots reference");
370 m_aXRef[nAnnotsId].SetDirty(
true);
378 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: Page Annots is a reference to a non-array");
404 if (nFirstPageId >=
m_aXRef.size())
406 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: invalid first page obj id");
410 m_aXRef[nFirstPageId].SetDirty(
true);
431 sal_uInt64 nAnnotsEndOffset = pDictionary->
GetKeyOffset(
"Annots")
437 nAnnotsBeforeEndLength);
447 nAnnotsAfterEndLength);
464 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: found no trailer");
471 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: trailer has no root reference");
477 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: invalid catalog reference");
481 if (nCatalogId >=
m_aXRef.size())
483 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: invalid catalog obj id");
488 if (pAcroFormReference)
492 if (!pAcroFormObject)
494 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: invalid AcroForm reference");
501 m_aXRef[nAcroFormId].SetDirty(
true);
508 if (!pAcroFormObject->
Lookup(
"Fields"))
511 "PDFDocument::Sign: AcroForm object without required Fields key");
516 if (!pAcroFormDictionary)
518 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: AcroForm object has no dictionary");
523 sal_uInt64 nFieldsEndOffset = pAcroFormDictionary->
GetKeyOffset(
"Fields")
528 sal_uInt64 nFieldsBeforeEndLength = nFieldsEndOffset;
537 nFieldsBeforeEndLength);
548 sal_uInt64 nFieldsAfterEndLength = pStreamBuffer->
GetSize() - nFieldsEndOffset;
551 nFieldsAfterEndLength);
560 nFieldsAfterEndLength);
571 m_aXRef[nCatalogId].SetDirty(
true);
575 if (!pAcroFormDictionary)
588 auto it = pAcroFormDictionary->GetItems().find(
"Fields");
589 if (it == pAcroFormDictionary->GetItems().end())
591 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: AcroForm without required Fields key");
598 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: AcroForm Fields is not an array");
603 sal_uInt64 nFieldsEndOffset = pAcroFormDictionary->GetKeyOffset(
"Fields")
604 + pAcroFormDictionary->GetKeyValueLength(
"Fields") - 1;
609 nFieldsBeforeEndLength);
618 nFieldsAfterEndLength);
632 sal_Int32 nXRefStreamId =
m_aXRef.size();
636 m_aXRef[nXRefStreamId] = aXRefStreamEntry;
640 const size_t nOffsetLen = 3;
642 const size_t nLineLength = nOffsetLen + 3;
644 std::vector<unsigned char> aOrigLine(nLineLength);
646 std::vector<unsigned char> aPrevLine(nLineLength);
648 std::vector<unsigned char> aFilteredLine(nLineLength);
649 for (
const auto& rXRef :
m_aXRef)
659 aOrigLine[
nPos++] = 2;
662 unsigned char nType = 0;
678 for (
size_t i = 0;
i < nOffsetLen; ++
i)
680 size_t nByte = nOffsetLen -
i - 1;
683 unsigned char nCh = (rEntry.
GetOffset() & (0xff << (nByte * 8))) >> (nByte * 8);
684 aOrigLine[
nPos++] = nCh;
688 aOrigLine[
nPos++] = 0;
691 aFilteredLine[0] = aOrigLine[0];
692 for (
size_t i = 1;
i < nLineLength; ++
i)
695 aFilteredLine[
i] = aOrigLine[
i] - aPrevLine[
i];
697 aPrevLine[
i] = aOrigLine[
i];
700 aXRefStream.
WriteBytes(aFilteredLine.data(), aFilteredLine.size());
705 " 0 obj\n<</DecodeParms<</Columns 5/Predictor 12>>/Filter/FlateDecode");
711 const std::vector<PDFElement*>& rElements = pID->
GetElements();
713 for (
size_t i = 0;
i < rElements.size(); ++
i)
720 if ((
i + 1) < rElements.size())
728 for (
const auto& rXRef :
m_aXRef)
730 if (!rXRef.second.GetDirty())
756 aZCodec.
Compress(aXRefStream, aStream);
792 for (
const auto& rXRef :
m_aXRef)
794 size_t nObject = rXRef.first;
795 size_t nOffset = rXRef.second.GetOffset();
796 if (!rXRef.second.GetDirty())
801 OStringBuffer
aBuffer = OString::number(
static_cast<sal_Int32
>(nOffset));
802 while (
aBuffer.getLength() < 10)
831 const std::vector<PDFElement*>& rElements = pID->
GetElements();
833 for (
size_t i = 0;
i < rElements.size(); ++
i)
840 if ((
i + 1) < rElements.size())
858 const OUString& rDescription,
bool bAdES)
863 sal_uInt64 nSignatureLastByteRangeOffset = 0;
864 sal_Int64 nSignatureContentOffset = 0;
866 rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset);
871 std::vector<PDFObjectElement*> aPages =
GetPages();
874 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: found no pages");
885 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: failed to find page #" << nPage);
890 sal_Int32 nAnnotId =
WriteAnnotObject(rPage, nSignatureId, nAppearanceId, aSignatureRectangle);
894 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: failed to write the updated Page object");
901 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: failed to write the updated Catalog object");
916 sal_Int64 nLastByteRangeLength
920 OString aByteRangeBuffer = OString::number(nLastByteRangeLength) +
" ]";
924 css::uno::Sequence<sal_Int8> aDerEncoded = xCertificate->getEncoded();
925 if (!aDerEncoded.hasElements())
927 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: empty certificate");
932 sal_uInt64 nBufferSize1 = nSignatureContentOffset - 1;
933 std::unique_ptr<char[]> aBuffer1(
new char[nBufferSize1]);
937 sal_uInt64 nBufferSize2 = nLastByteRangeLength;
938 std::unique_ptr<char[]> aBuffer2(
new char[nBufferSize2]);
941 OStringBuffer aCMSHexBuffer;
945 if (!aSigning.
Sign(aCMSHexBuffer))
947 SAL_WARN(
"vcl.filter",
"PDFDocument::Sign: PDFWriter::Sign() failed");
963 return rStream.
good();
967 std::vector<std::unique_ptr<PDFElement>>& rElements,
974 bool bInXRef =
false;
976 bool bInStartXRef =
false;
982 bool bInObject =
false;
996 rElements.push_back(std::unique_ptr<PDFElement>(pComment));
998 if (!rElements.back()->Read(rStream))
1001 "PDFDocument::Tokenize: PDFCommentElement::Read() failed");
1024 if (!rElements.back()->Read(rStream))
1027 "PDFDocument::Tokenize: PDFDictionaryElement::Read() failed");
1037 if (!rElements.back()->Read(rStream))
1040 "PDFDocument::Tokenize: PDFEndDictionaryElement::Read() failed");
1048 rElements.push_back(std::unique_ptr<PDFElement>(pArr));
1061 if (!rElements.back()->Read(rStream))
1063 SAL_WARN(
"vcl.filter",
"PDFDocument::Tokenize: PDFArrayElement::Read() failed");
1080 if (!rElements.back()->Read(rStream))
1083 "PDFDocument::Tokenize: PDFEndArrayElement::Read() failed");
1091 rElements.push_back(std::unique_ptr<PDFElement>(pNameElement));
1093 if (!pNameElement->Read(rStream))
1095 SAL_WARN(
"vcl.filter",
"PDFDocument::Tokenize: PDFNameElement::Read() failed");
1100 && pNameElement->GetValue() ==
"ObjStm")
1103 pObjectKey = pNameElement;
1110 if (!rElements.back()->Read(rStream))
1113 "PDFDocument::Tokenize: PDFLiteralStringElement::Read() failed");
1120 if (rtl::isAsciiDigit(
static_cast<unsigned char>(
ch)) ||
ch ==
'-' ||
ch ==
'+'
1125 rElements.push_back(std::unique_ptr<PDFElement>(pNumberElement));
1127 if (!pNumberElement->Read(rStream))
1130 "PDFDocument::Tokenize: PDFNumberElement::Read() failed");
1135 bInStartXRef =
false;
1142 else if (bInObject && !nDepth &&
pObject)
1145 pObject->SetNumberElement(pNumberElement);
1147 else if (rtl::isAsciiAlpha(
static_cast<unsigned char>(
ch)))
1153 bool bObj = aKeyword ==
"obj";
1154 if (bObj || aKeyword ==
"R")
1159 SAL_WARN(
"vcl.filter",
"PDFDocument::Tokenize: expected at least two "
1160 "tokens before 'obj' or 'R' keyword");
1166 auto pGenerationNumber
1168 if (!pObjectNumber || !pGenerationNumber)
1170 SAL_WARN(
"vcl.filter",
"PDFDocument::Tokenize: missing object or "
1171 "generation number before 'obj' or 'R' keyword");
1178 pGenerationNumber->GetValue());
1179 rElements.push_back(std::unique_ptr<PDFElement>(
pObject));
1187 *pGenerationNumber);
1188 rElements.push_back(std::unique_ptr<PDFElement>(pReference));
1189 if (bInObject && nDepth > 0 &&
pObject)
1191 pObject->AddDictionaryReference(pReference);
1193 if (!rElements.back()->Read(rStream))
1196 "PDFDocument::Tokenize: PDFElement::Read() failed");
1200 else if (aKeyword ==
"stream")
1204 for (
size_t nElement = 0; nElement < rElements.size(); ++nElement)
1207 size_t nIndex = rElements.size() - nElement - 1;
1213 PDFElement* pLookup = pObj->Lookup(
"Length");
1218 nLength = pReference->LookupNumber(rStream);
1226 nLength = pNumber->GetValue();
1232 "PDFDocument::Tokenize: found no Length key for stream keyword");
1239 pObject->SetStream(pStreamElement);
1240 rElements.push_back(std::unique_ptr<PDFElement>(pStreamElement));
1241 if (!rElements.back()->Read(rStream))
1244 "PDFDocument::Tokenize: PDFStreamElement::Read() failed");
1248 else if (aKeyword ==
"endstream")
1251 if (!rElements.back()->Read(rStream))
1254 "PDFDocument::Tokenize: PDFEndStreamElement::Read() failed");
1258 else if (aKeyword ==
"endobj")
1261 if (!rElements.back()->Read(rStream))
1264 "PDFDocument::Tokenize: PDFEndObjectElement::Read() failed");
1277 pObjectStream =
nullptr;
1278 pObjectKey =
nullptr;
1282 else if (aKeyword ==
"true" || aKeyword ==
"false")
1283 rElements.push_back(std::unique_ptr<PDFElement>(
1285 else if (aKeyword ==
"null")
1286 rElements.push_back(std::unique_ptr<PDFElement>(
new PDFNullElement));
1287 else if (aKeyword ==
"xref")
1290 else if (bInXRef && (aKeyword ==
"f" || aKeyword ==
"n"))
1293 else if (aKeyword ==
"trailer")
1298 pTrailer->Read(rStream);
1305 rElements.push_back(std::unique_ptr<PDFElement>(pTrailer));
1307 else if (aKeyword ==
"startxref")
1309 bInStartXRef =
true;
1313 SAL_WARN(
"vcl.filter",
"PDFDocument::Tokenize: unexpected '"
1314 << aKeyword <<
"' keyword at byte position "
1321 auto uChar =
static_cast<unsigned char>(
ch);
1323 if (!rtl::isAsciiWhiteSpace(uChar) && uChar != 0)
1326 "PDFDocument::Tokenize: unexpected character with code "
1327 << sal_Int32(
ch) <<
" at byte position " << rStream.
Tell());
1331 "PDFDocument::Tokenize: unexpected null character at "
1332 << rStream.
Tell() <<
" - ignoring");
1356 return Read(aStandardizedStream);
1362 std::vector<sal_Int8> aHeader(5);
1364 rStream.
ReadBytes(aHeader.data(), aHeader.size());
1365 if (aHeader[0] !=
'%' || aHeader[1] !=
'P' || aHeader[2] !=
'D' || aHeader[3] !=
'F'
1366 || aHeader[4] !=
'-')
1368 SAL_WARN(
"vcl.filter",
"PDFDocument::Read: header mismatch");
1378 SAL_INFO(
"vcl.filter",
"PDFDocument::Read: nStartXRef is " << nStartXRef);
1379 if (nStartXRef == 0)
1381 SAL_WARN(
"vcl.filter",
"PDFDocument::Read: found no xref start offset");
1386 rStream.
Seek(nStartXRef);
1388 if (aKeyword.isEmpty())
1393 if (aKeyword !=
"xref")
1395 SAL_WARN(
"vcl.filter",
"PDFDocument::Read: xref is not the first keyword");
1401 SAL_WARN(
"vcl.filter",
"PDFDocument::Read: failed to tokenizer trailer after xref");
1444 while (rtl::isAsciiAlpha(
static_cast<unsigned char>(
ch)))
1449 return aBuf.toString();
1452 return aBuf.toString();
1458 std::vector<char>
aBuf(1024);
1461 rStream.
SeekRel(
static_cast<sal_Int64
>(-1) *
aBuf.size());
1465 size_t nBeforePeek = rStream.
Tell();
1467 rStream.
Seek(nBeforePeek);
1468 if (nSize !=
aBuf.size())
1470 OString aPrefix(
"startxref");
1472 auto itLastValid =
aBuf.end();
1473 auto it =
aBuf.begin();
1476 it = std::search(it,
aBuf.end(), aPrefix.getStr(), aPrefix.getStr() + aPrefix.getLength());
1477 if (it ==
aBuf.end())
1483 if (itLastValid ==
aBuf.end())
1485 SAL_WARN(
"vcl.filter",
"PDFDocument::FindStartXRef: found no startxref");
1489 rStream.
SeekRel(itLastValid -
aBuf.begin() + aPrefix.getLength());
1493 "PDFDocument::FindStartXRef: unexpected end of stream after startxref");
1499 if (!aNumber.
Read(rStream))
1509 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: failed to read object");
1515 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: no tokens found");
1530 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: no object token found");
1541 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: stream length is not provided");
1544 sal_uInt64
nLength = pNumber->GetValue();
1558 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: no stream token found");
1570 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: no Filter found");
1574 if (pFilter->GetValue() !=
"FlateDecode")
1577 "PDFDocument::ReadXRefStream: unexpected filter: " << pFilter->GetValue());
1585 const std::map<OString, PDFElement*>& rItems = pDecodeParams->GetItems();
1586 auto it = rItems.find(
"Columns");
1587 if (it != rItems.end())
1589 nColumns = pColumns->GetValue();
1590 it = rItems.find(
"Predictor");
1591 if (it != rItems.end())
1593 nPredictor = pPredictor->GetValue();
1603 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: decompression failed");
1609 std::vector<size_t> aFirstObjects;
1610 std::vector<size_t> aNumberOfObjects;
1616 aFirstObjects.push_back(0);
1617 aNumberOfObjects.push_back(pSize->GetValue());
1621 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: Index and Size not found");
1627 const std::vector<PDFElement*>& rIndexElements = pIndex->GetElements();
1628 size_t nFirstObject = 0;
1629 for (
size_t i = 0;
i < rIndexElements.size(); ++
i)
1637 "PDFDocument::ReadXRefStream: Index has no first object");
1640 nFirstObject = pFirstObject->GetValue();
1645 if (!pNumberOfObjects)
1648 "PDFDocument::ReadXRefStream: Index has no number of objects");
1651 aFirstObjects.push_back(nFirstObject);
1652 aNumberOfObjects.push_back(pNumberOfObjects->GetValue());
1657 const int nWSize = 3;
1659 if (!pW || pW->GetElements().size() < nWSize)
1661 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: W not found or has < 3 elements");
1666 int nLineLength = 1;
1667 for (
size_t i = 0;
i < nWSize; ++
i)
1672 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: W contains non-number");
1675 aW[
i] = pI->GetValue();
1676 nLineLength += aW[
i];
1679 if (nPredictor > 1 && nLineLength - 1 != nColumns)
1682 "PDFDocument::ReadXRefStream: /DecodeParms/Columns is inconsistent with /W");
1687 for (
size_t nSubSection = 0; nSubSection < aFirstObjects.size(); ++nSubSection)
1689 size_t nFirstObject = aFirstObjects[nSubSection];
1690 size_t nNumberOfObjects = aNumberOfObjects[nSubSection];
1693 std::vector<unsigned char> aOrigLine(nLineLength);
1695 std::vector<unsigned char> aFilteredLine(nLineLength);
1696 for (
size_t nEntry = 0; nEntry < nNumberOfObjects; ++nEntry)
1698 size_t nIndex = nFirstObject + nEntry;
1700 aStream.
ReadBytes(aOrigLine.data(), aOrigLine.size());
1701 if (nPredictor > 1 && aOrigLine[0] + 10 != nPredictor)
1703 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: in-stream predictor is "
1704 "inconsistent with /DecodeParms/Predictor for object #"
1709 for (
int i = 0;
i < nLineLength; ++
i)
1718 aFilteredLine[
i] = aFilteredLine[
i] + aOrigLine[
i];
1721 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: unexpected predictor: "
1732 for (;
nPos < nOffset + aW[0]; ++
nPos)
1734 unsigned char nCh = aFilteredLine[
nPos];
1739 size_t nStreamOffset = 0;
1741 for (;
nPos < nOffset + aW[1]; ++
nPos)
1743 unsigned char nCh = aFilteredLine[
nPos];
1744 nStreamOffset = (nStreamOffset << 8) + nCh;
1748 size_t nGenerationNumber = 0;
1750 for (;
nPos < nOffset + aW[2]; ++
nPos)
1752 unsigned char nCh = aFilteredLine[
nPos];
1753 nGenerationNumber = (nGenerationNumber << 8) + nCh;
1789 if (!aFirstObject.
Read(rStream))
1797 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRef: expected first object number >= 0");
1803 if (!aNumberOfEntries.
Read(rStream))
1805 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRef: failed to read number of entries");
1809 if (aNumberOfEntries.
GetValue() < 0)
1811 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRef: expected zero or more entries");
1815 size_t nSize = aNumberOfEntries.
GetValue();
1816 for (
size_t nEntry = 0; nEntry < nSize; ++nEntry)
1821 if (!aOffset.
Read(rStream))
1823 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRef: failed to read offset");
1829 if (!aGenerationNumber.
Read(rStream))
1831 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRef: failed to read generation number");
1837 if (aKeyword !=
"f" && aKeyword !=
"n")
1839 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRef: unexpected keyword");
1868 if (!rtl::isAsciiWhiteSpace(
static_cast<unsigned char>(
ch)))
1886 if (
ch !=
'\n' &&
ch !=
'\r')
1899 SAL_WARN(
"vcl.filter",
"PDFDocument::GetObjectOffset: wanted to look up index #"
1900 <<
nIndex <<
", but failed");
1904 return it->second.GetOffset();
1915 auto pKidsRef = pPages->
Lookup(
"Kids");
1922 SAL_WARN(
"vcl.filter",
"visitPages: pages has no kids");
1925 auto pObjWithKids = pRefKids->LookupObject();
1928 SAL_WARN(
"vcl.filter",
"visitPages: pages has no kids");
1932 pKids = pObjWithKids->GetArray();
1937 SAL_WARN(
"vcl.filter",
"visitPages: pages has no kids");
1943 for (
const auto& pKid : pKids->GetElements())
1956 SAL_WARN(
"vcl.filter",
"visitPages: loop in hierarchy");
1966 rRet.push_back(pKidObject);
1983 pTrailer = it->second;
1993 SAL_WARN(
"vcl.filter",
"PDFDocument::GetCatalog: trailer has no Root key");
2002 std::vector<PDFObjectElement*> aRet;
2007 SAL_WARN(
"vcl.filter",
"PDFDocument::GetPages: trailer has no catalog");
2015 <<
") has no pages");
2028 std::vector<PDFObjectElement*> aRet;
2030 std::vector<PDFObjectElement*> aPages =
GetPages();
2032 for (
const auto& pPage : aPages)
2037 PDFElement* pAnnotsElement = pPage->Lookup(
"Annots");
2048 pAnnots = pAnnotsObject->GetArray();
2056 for (
const auto& pAnnot : pAnnots->GetElements())
2067 if (!pFT || pFT->GetValue() !=
"Sig")
2070 aRet.push_back(pAnnotObject);
2087 if (encoded.size() < 2 || encoded[0] != 0xFE || encoded[1] != 0xFF || (encoded.size() & 1) != 0)
2091 OUStringBuffer buf(encoded.size() - 2);
2092 for (
size_t i = 2;
i < encoded.size();
i += 2)
2094 buf.append(
sal_Unicode((
static_cast<sal_uInt16
>(encoded[
i]) << 8) | encoded[
i + 1]));
2096 return buf.makeStringAndClear();
2112 if (
ch ==
'\n' ||
ch ==
'\r' || rStream.
eof())
2133 SAL_INFO(
"vcl.filter",
"PDFCommentElement::Read: m_aComment is '" <<
m_aComment <<
"'");
2155 if (!rtl::isAsciiDigit(
static_cast<unsigned char>(
ch)) &&
ch !=
'-' &&
ch !=
'+' &&
ch !=
'.')
2160 while (!rStream.
eof())
2162 if (!rtl::isAsciiDigit(
static_cast<unsigned char>(
ch)) &&
ch !=
'-' &&
ch !=
'+'
2169 SAL_INFO(
"vcl.filter",
"PDFNumberElement::Read: m_fValue is '" <<
m_fValue <<
"'");
2193 SAL_INFO(
"vcl.filter",
"PDFHexStringElement::Read: expected '<' as first character");
2199 while (!rStream.
eof())
2205 "PDFHexStringElement::Read: m_aValue length is " <<
m_aValue.getLength());
2224 SAL_INFO(
"vcl.filter",
"PDFHexStringElement::Read: expected '(' as first character");
2233 while (!rStream.
eof())
2235 if (
ch ==
'(' && nPrevCh !=
'\\')
2238 if (
ch ==
')' && nPrevCh !=
'\\')
2246 "PDFLiteralStringElement::Read: m_aValue is '" <<
m_aValue <<
"'");
2261 , m_pDictionaryElement(nullptr)
2276 aParser.
parse(
this);
2289 , m_fObjectValue(fObjectValue)
2290 , m_fGenerationValue(fGenerationValue)
2291 , m_pNumberElement(nullptr)
2292 , m_nDictionaryOffset(0)
2293 , m_nDictionaryLength(0)
2294 , m_pDictionaryElement(nullptr)
2297 , m_pArrayElement(nullptr)
2298 , m_pStreamElement(nullptr)
2313 const OString& rKey)
2315 auto it = rDictionary.find(rKey);
2316 if (it == rDictionary.end())
2329 "PDFDictionaryElement::LookupObject: no such key with reference value: "
2334 return pKey->LookupObject();
2351 aParser.
parse(
this);
2357 aParser.
parse(
this);
2375 SAL_WARN(
"vcl.filter",
"PDFObjectElement::LookupObject: no such key with reference value: "
2380 return pKey->LookupObject();
2498 SAL_WARN(
"vcl.filter",
"PDFObjectElement::ParseStoredObjects: no stream");
2503 if (!pType || pType->GetValue() !=
"ObjStm")
2506 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: missing unexpected type");
2509 "PDFDocument::ReadXRefStream: unexpected type: " << pType->GetValue());
2514 if (!pFilter || pFilter->GetValue() !=
"FlateDecode")
2517 SAL_WARN(
"vcl.filter",
"PDFDocument::ReadXRefStream: missing filter");
2520 "PDFDocument::ReadXRefStream: unexpected filter: " << pFilter->GetValue());
2527 SAL_WARN(
"vcl.filter",
"PDFObjectElement::ParseStoredObjects: no First");
2534 SAL_WARN(
"vcl.filter",
"PDFObjectElement::ParseStoredObjects: no N");
2537 size_t nN = pN->GetValue();
2542 SAL_WARN(
"vcl.filter",
"PDFObjectElement::ParseStoredObjects: no length");
2545 size_t nLength = pLength->GetValue();
2559 SAL_WARN(
"vcl.filter",
"PDFObjectElement::ParseStoredObjects: decompression failed");
2565 std::vector<size_t> aObjNums;
2566 std::vector<size_t> aOffsets;
2567 std::vector<size_t> aLengths;
2569 for (
size_t nObject = 0; nObject < nN; ++nObject)
2572 if (!aObjNum.
Read(aStream))
2575 "PDFObjectElement::ParseStoredObjects: failed to read object number");
2578 aObjNums.push_back(aObjNum.
GetValue());
2583 if (!aByteOffset.
Read(aStream))
2586 "PDFObjectElement::ParseStoredObjects: failed to read byte offset");
2589 aOffsets.push_back(pFirst->GetValue() + aByteOffset.
GetValue());
2591 if (aOffsets.size() > 1)
2592 aLengths.push_back(aOffsets.back() - aOffsets[aOffsets.size() - 2]);
2593 if (nObject + 1 == nN)
2594 aLengths.push_back(
nLength - aOffsets.back());
2600 for (
size_t nObject = 0; nObject < nN; ++nObject)
2602 size_t nObjNum = aObjNums[nObject];
2603 size_t nOffset = aOffsets[nObject];
2604 size_t nLen = aLengths[nObject];
2606 aStream.
Seek(nOffset);
2621 std::unique_ptr<SvMemoryStream> pStreamBuffer(
new SvMemoryStream());
2622 aStoredStream.
Seek(0);
2623 pStreamBuffer->WriteStream(aStoredStream);
2645 , m_fObjectValue(rObject.
GetValue())
2646 , m_fGenerationValue(rGeneration.
GetValue())
2647 , m_rObject(rObject)
2668 SAL_WARN(
"vcl.filter",
"PDFReferenceElement::LookupNumber: found no offset for object #"
2673 sal_uInt64 nOrigPos = rStream.
Tell();
2676 rStream.
Seek(nOffset);
2680 bool bRet = aNumber.
Read(rStream);
2684 "PDFReferenceElement::LookupNumber: offset points to not matching object");
2692 bool bRet = aNumber.
Read(rStream);
2696 "PDFReferenceElement::LookupNumber: offset points to not matching generation");
2704 if (aKeyword !=
"obj")
2707 "PDFReferenceElement::LookupNumber: offset doesn't point to an obj keyword");
2714 if (!aNumber.
Read(rStream))
2717 "PDFReferenceElement::LookupNumber: failed to read referenced number");
2734 return itIDObjects->second;
2736 SAL_WARN(
"vcl.filter",
"PDFDocument::LookupObject: can't find obj " << nObjectNumber);
2752 SAL_WARN(
"vcl.filter",
"PDFDictionaryElement::Read: unexpected character: " <<
ch);
2758 SAL_WARN(
"vcl.filter",
"PDFDictionaryElement::Read: unexpected end of file");
2765 SAL_WARN(
"vcl.filter",
"PDFDictionaryElement::Read: unexpected character: " <<
ch);
2771 SAL_INFO(
"vcl.filter",
"PDFDictionaryElement::Read: '<<'");
2787 SAL_WARN(
"vcl.filter",
"PDFEndDictionaryElement::Read: unexpected character: " <<
ch);
2793 SAL_WARN(
"vcl.filter",
"PDFEndDictionaryElement::Read: unexpected end of file");
2800 SAL_WARN(
"vcl.filter",
"PDFEndDictionaryElement::Read: unexpected character: " <<
ch);
2804 SAL_INFO(
"vcl.filter",
"PDFEndDictionaryElement::Read: '>>'");
2817 SAL_WARN(
"vcl.filter",
"PDFNameElement::Read: unexpected character: " <<
ch);
2824 SAL_WARN(
"vcl.filter",
"PDFNameElement::Read: unexpected end of file");
2831 while (!rStream.
eof())
2833 if (rtl::isAsciiWhiteSpace(
static_cast<unsigned char>(
ch)) ||
ch ==
'/' ||
ch ==
'['
2834 ||
ch ==
']' ||
ch ==
'<' ||
ch ==
'>' ||
ch ==
'(')
2838 SAL_INFO(
"vcl.filter",
"PDFNameElement::Read: m_aValue is '" <<
m_aValue <<
"'");
2862 std::vector<unsigned char> aBytes(
m_nLength);
2863 rStream.
ReadBytes(aBytes.data(), aBytes.size());
2866 return rStream.
good();
2888 SAL_WARN(
"vcl.filter",
"PDFArrayElement::Read: unexpected character: " <<
ch);
2892 SAL_INFO(
"vcl.filter",
"PDFArrayElement::Read: '['");
2916 SAL_WARN(
"vcl.filter",
"PDFEndArrayElement::Read: unexpected character: " <<
ch);
2920 SAL_INFO(
"vcl.filter",
"PDFEndArrayElement::Read: ']'");
2932 size_t nReturnIndex = 0;
2949 size_t nIndex = nStartIndex;
2960 sal_uInt64 nNameOffset = 0;
2961 std::vector<PDFNumberElement*> aNumbers;
2963 sal_uInt64 nDictionaryOffset = 0;
2976 if (!aNumbers.empty())
2978 if (pParsingDictionary)
2984 pParsingDictionary->insert(
aName, pNumber);
2985 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
2988 else if (pParsingArray)
2990 for (
auto& pNumber : aNumbers)
2991 pParsingArray->PushBack(pNumber);
2995 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3006 nDictionaryOffset = pCurrentDictionary->GetLocation();
3011 pParsingObject->SetDictionary(pCurrentDictionary);
3012 pParsingObject->SetDictionaryOffset(nDictionaryOffset);
3013 pParsingDictionary = pCurrentDictionary;
3015 else if (pParsingTrailer)
3017 pParsingTrailer->SetDictionary(pCurrentDictionary);
3018 pParsingDictionary = pCurrentDictionary;
3021 else if (!pCurrentDictionary->alreadyParsing())
3025 pParsingArray->PushBack(pCurrentDictionary);
3027 else if (pParsingDictionary)
3030 pParsingDictionary->insert(
aName, pCurrentDictionary);
3034 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3037 const size_t nNextElementIndex =
parse(pCurrentDictionary,
i, nCurrentDepth + 1);
3038 i = std::max(
i, nNextElementIndex - 1);
3041 else if (
auto pCurrentEndDictionary
3045 if (!aNumbers.empty())
3047 if (pParsingDictionary)
3053 pParsingDictionary->insert(
aName, pNumber);
3054 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3057 else if (pParsingArray)
3059 for (
auto& pNumber : aNumbers)
3060 pParsingArray->PushBack(pNumber);
3064 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3070 if (pParsingDictionary)
3072 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3073 sal_uInt64
nLength = pCurrentEndDictionary->GetLocation() - nNameOffset + 2;
3083 sal_uInt64 nDictionaryLength
3084 = pCurrentEndDictionary->GetLocation() - nDictionaryOffset;
3085 pParsingObject->SetDictionaryLength(nDictionaryLength);
3093 else if (
auto pCurrentArray =
dynamic_cast<PDFArrayElement*
>(pCurrentElement))
3096 if (!aNumbers.empty())
3098 if (pParsingDictionary)
3104 pParsingDictionary->insert(
aName, pNumber);
3105 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3108 else if (pParsingArray)
3110 for (
auto& pNumber : aNumbers)
3111 pParsingArray->PushBack(pNumber);
3115 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3126 pParsingObject->SetArray(pCurrentArray);
3127 pParsingArray = pCurrentArray;
3130 else if (!pCurrentArray->alreadyParsing())
3135 pParsingArray->PushBack(pCurrentArray);
3137 else if (pParsingDictionary)
3140 pParsingDictionary->insert(
aName, pCurrentArray);
3143 const size_t nNextElementIndex =
parse(pCurrentArray,
i, nCurrentDepth + 1);
3146 i = std::max(
i, nNextElementIndex - 1);
3152 if (!aNumbers.empty())
3154 if (pParsingDictionary)
3160 pParsingDictionary->insert(
aName, pNumber);
3161 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3164 else if (pParsingArray)
3166 for (
auto& pNumber : aNumbers)
3167 pParsingArray->PushBack(pNumber);
3171 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3184 if (pParsingDictionary)
3186 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3188 sal_uInt64
nLength = pCurrentEndArray->GetOffset() - nNameOffset + 1;
3194 else if (
auto pCurrentName =
dynamic_cast<PDFNameElement*
>(pCurrentElement))
3197 if (!aNumbers.empty())
3199 if (pParsingDictionary)
3205 pParsingDictionary->insert(
aName, pNumber);
3206 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3209 else if (pParsingArray)
3211 for (
auto& pNumber : aNumbers)
3212 pParsingArray->PushBack(pNumber);
3222 pParsingArray->PushBack(pCurrentName);
3224 else if (pParsingDictionary)
3227 if (
aName.isEmpty())
3229 aName = pCurrentName->GetValue();
3230 nNameOffset = pCurrentName->GetLocation();
3234 sal_uInt64 nKeyLength
3235 = pCurrentName->GetLocation() + pCurrentName->GetLength() - nNameOffset;
3236 pParsingDictionary->insert(
aName, pCurrentName);
3237 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3238 pParsingDictionary->SetKeyValueLength(
aName, nKeyLength);
3246 if (aNumbers.size() > 2)
3248 aNumbers.resize(aNumbers.size() - 2);
3251 for (
auto& pNumber : aNumbers)
3252 pParsingArray->PushBack(pNumber);
3259 pParsingArray->PushBack(pReference);
3261 else if (pParsingDictionary)
3263 sal_uInt64
nLength = pReference->GetOffset() - nNameOffset;
3264 pParsingDictionary->insert(
aName, pReference);
3265 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3271 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3278 if (!aNumbers.empty())
3282 for (
auto& pNumber : aNumbers)
3283 pParsingArray->PushBack(pNumber);
3290 pParsingArray->PushBack(pLiteralString);
3292 else if (pParsingDictionary)
3294 pParsingDictionary->insert(
aName, pLiteralString);
3295 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3300 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3306 if (!aNumbers.empty())
3310 for (
auto& pNumber : aNumbers)
3311 pParsingArray->PushBack(pNumber);
3318 pParsingArray->PushBack(pBoolean);
3320 else if (pParsingDictionary)
3322 pParsingDictionary->insert(
aName, pBoolean);
3323 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3328 SAL_INFO(
"vcl.filter",
"neither Dictionary nor Array available");
3334 if (!aNumbers.empty())
3338 for (
auto& pNumber : aNumbers)
3339 pParsingArray->PushBack(pNumber);
3346 pParsingArray->PushBack(pHexString);
3348 else if (pParsingDictionary)
3350 pParsingDictionary->insert(
aName, pHexString);
3351 pParsingDictionary->SetKeyOffset(
aName, nNameOffset);
3355 else if (
auto pNumberElement =
dynamic_cast<PDFNumberElement*
>(pCurrentElement))
3359 aNumbers.push_back(pNumberElement);
3373 SAL_INFO(
"vcl.filter",
"Unhandled element while parsing.");
3377 return nReturnIndex;
const sal_Int32 m_nLength
virtual sal_uInt64 TellEnd() override
SvStream & WriteNumberAsString(N n)
std::size_t WriteBytes(const void *pData, std::size_t nSize)
bool SetStreamSize(sal_uInt64 nSize)
SvStream & WriteOString(std::string_view rStr)
SvStream & ReadChar(char &rChar)
sal_uInt64 Seek(sal_uInt64 nPos)
std::size_t ReadBytes(void *pData, std::size_t nSize)
sal_uInt64 SeekRel(sal_Int64 nPos)
SvStream & WriteStream(SvStream &rStream)
tools::Long Decompress(SvStream &rIStm, SvStream &rOStm)
tools::Long EndCompression()
void BeginCompression(int nCompressLevel=ZCODEC_DEFAULT_COMPRESSION, bool gzLib=false)
void Compress(SvStream &rIStm, SvStream &rOStm)
void AddDataRange(const void *pData, sal_Int32 size)
bool Sign(OStringBuffer &rCMSHexBuffer)
Copies objects from one PDF file into another one.
static sal_Int32 copyPageStreams(std::vector< filter::PDFObjectElement * > &rContentStreams, SvMemoryStream &rStream, bool &rCompressed)
Copies page one or more page streams from rContentStreams into rStream.
void copyPageResources(filter::PDFObjectElement *pPage, OStringBuffer &rLine)
Copies resources of pPage into rLine.
static void AppendUnicodeTextString(const OUString &rString, OStringBuffer &rBuffer)
Write rString as a PDF hex string into rBuffer.
static OString GetDateTime()
Get current date/time in PDF D:YYYYMMDDHHMMSS form.
PDFObjectElement * m_pObject
The object that contains this array.
const std::vector< PDFElement * > & GetElements() const
bool Read(SvStream &rStream) override
void PushBack(PDFElement *pElement)
PDFArrayElement(PDFObjectElement *pObject)
std::vector< PDFElement * > m_aElements
Boolean object: a 'true' or a 'false'.
bool Read(SvStream &rStream) override
Dictionary object: a set key-value pairs.
static PDFElement * Lookup(const std::map< OString, PDFElement * > &rDictionary, const OString &rKey)
sal_uInt64 GetKeyOffset(const OString &rKey) const
std::map< OString, sal_uInt64 > m_aDictionaryKeyOffset
Position after the '/' token.
sal_uInt64 m_nLocation
Offset after the '<<' token.
bool Read(SvStream &rStream) override
std::map< OString, sal_uInt64 > m_aDictionaryKeyValueLength
Length of the dictionary key and value, till (before) the next token.
PDFElement * LookupElement(const OString &rDictionaryKey)
Looks up an element which is contained in this dictionary.
const std::map< OString, PDFElement * > & GetItems() const
void SetKeyValueLength(const OString &rKey, sal_uInt64 nLength)
void SetKeyOffset(const OString &rKey, sal_uInt64 nOffset)
sal_uInt64 GetKeyValueLength(const OString &rKey) const
PDFObjectElement * LookupObject(const OString &rDictionaryKey)
Looks up an object which is only referenced in this dictionary.
std::map< OString, PDFElement * > m_aItems
Key-value pairs when the dictionary is a nested value.
In-memory representation of an on-disk PDF document.
PDFObjectElement * m_pXRefStream
When m_pTrailer is nullptr, this can still have a dictionary.
static OUString DecodeHexStringUTF16BE(PDFHexStringElement const &rElement)
bool RemoveSignature(size_t nPosition)
Remove the nth signature from read document in the edit buffer.
PDFTrailerElement * m_pTrailer
sal_Int32 createObject() override
See vcl::PDFObjectContainer::createObject().
SvMemoryStream & GetEditBuffer()
Access to the input document, even after the input stream is gone.
bool writeBufferBytes(const void *pBuffer, sal_uInt64 nBytes) override
See vcl::PDFObjectContainer::writeBuffer().
std::vector< size_t > m_aEOFs
List of EOF offsets we know.
std::map< size_t, PDFObjectElement * > m_aOffsetObjects
Object offset <-> Object pointer map.
std::vector< size_t > m_aTrailerOffsets
Offsets of trailers, from latest to oldest.
bool WriteCatalogObject(sal_Int32 nAnnotId, PDFReferenceElement *&pRoot)
Write the updated Catalog object as part of signing.
void SetSignatureLine(std::vector< sal_Int8 > &&rSignatureLine)
bool Sign(const css::uno::Reference< css::security::XCertificate > &xCertificate, const OUString &rDescription, bool bAdES)
Sign the read document with xCertificate in the edit buffer.
void PushBackEOF(size_t nOffset)
Remember the end location of an EOF token.
bool Read(SvStream &rStream)
Read elements from the start of the stream till its end.
static size_t FindStartXRef(SvStream &rStream)
sal_uInt32 GetNextSignature()
Suggest a minimal, yet free signature ID to use for the next signature.
bool ReadWithPossibleFixup(SvStream &rStream)
Calls Read() first and if it fails it tries to fixup and then retry.
bool WritePageObject(PDFObjectElement &rFirstPage, sal_Int32 nAnnotId)
Write the updated Page object as part of signing.
static OString ReadKeyword(SvStream &rStream)
bool Tokenize(SvStream &rStream, TokenizeMode eMode, std::vector< std::unique_ptr< PDFElement > > &rElements, PDFObjectElement *pObjectElement)
Tokenize elements from current offset.
void ReadXRef(SvStream &rStream)
size_t GetObjectOffset(size_t nIndex) const
static void SkipWhitespace(SvStream &rStream)
PDFObjectElement * LookupObject(size_t nObjectNumber)
Look up object based on object number, possibly by parsing object streams.
static void SkipLineBreaks(SvStream &rStream)
Instead of all whitespace, just skip CR and NL characters.
PDFObjectElement * GetCatalog()
size_t m_nSignaturePage
0-based page number where m_aSignatureLine should be placed.
sal_Int32 WriteAnnotObject(PDFObjectElement const &rFirstPage, sal_Int32 nSignatureId, sal_Int32 nAppearanceId, const tools::Rectangle &rSignatureRectangle)
Write the annot object as part of signing.
bool updateObject(sal_Int32 n) override
See vcl::PDFObjectContainer::updateObject().
std::vector< PDFObjectElement * > GetSignatureWidgets()
Get a list of signatures embedded into this document.
sal_Int32 WriteAppearanceObject(tools::Rectangle &rSignatureRectangle)
Write the appearance object as part of signing.
void SetIDObject(size_t nID, PDFObjectElement *pObject)
Register an object (owned directly or indirectly by m_aElements) as a provider for a given ID.
bool Write(SvStream &rStream)
Serializes the contents of the edit buffer.
std::vector< PDFObjectElement * > GetPages()
const std::vector< std::unique_ptr< PDFElement > > & GetElements() const
void ReadXRefStream(SvStream &rStream)
SvMemoryStream m_aEditBuffer
All editing takes place in this buffer, if it happens.
void WriteXRef(sal_uInt64 nXRefOffset, PDFReferenceElement const *pRoot)
Write the updated cross-references as part of signing.
std::map< size_t, XRefEntry > m_aXRef
Object ID <-> object offset map.
std::vector< std::unique_ptr< PDFElement > > m_aElements
This vector owns all elements.
sal_Int32 WriteSignatureObject(const OUString &rDescription, bool bAdES, sal_uInt64 &rLastByteRangeOffset, sal_Int64 &rContentOffset)
Write the signature object as part of signing.
std::map< size_t, PDFObjectElement * > m_aIDObjects
Object ID <-> Object pointer map.
static std::vector< unsigned char > DecodeHexString(PDFHexStringElement const *pElement)
Decode a hex dump.
void SetSignaturePage(size_t nPage)
std::vector< size_t > m_aStartXRefs
List of xref offsets we know.
std::map< size_t, PDFTrailerElement * > m_aOffsetTrailers
Trailer offset <-> Trailer pointer map.
std::vector< sal_Int8 > m_aSignatureLine
Signature line in PDF format, to be consumed by the next Sign() invocation.
A byte range in a PDF file.
void setVisiting(bool bVisiting)
bool alreadyVisiting() const
void setParsing(bool bParsing)
sal_uInt64 GetOffset() const
bool Read(SvStream &rStream) override
sal_uInt64 m_nOffset
Location before the ']' token.
End of a dictionary: '>>'.
PDFEndDictionaryElement()
bool Read(SvStream &rStream) override
sal_uInt64 m_nLocation
Offset before the '>>' token.
sal_uInt64 GetLocation() const
End of an object: 'endobj' keyword.
bool Read(SvStream &rStream) override
End of a stream: 'endstream' keyword.
bool Read(SvStream &rStream) override
Hex string: in <AABB> form.
const OString & GetValue() const
bool Read(SvStream &rStream) override
Literal string: in (asdf) form.
bool Read(SvStream &rStream) override
const OString & GetValue() const
Name object: a key string.
bool Read(SvStream &rStream) override
sal_uInt64 m_nLocation
Offset after the '/' token.
sal_uInt64 GetLocation() const
const OString & GetValue() const
Null object: the 'null' singleton.
bool Read(SvStream &rStream) override
Numbering object: an integer or a real.
sal_uInt64 GetLocation() const
sal_uInt64 m_nLength
Input file token length.
sal_uInt64 GetLength() const
bool Read(SvStream &rStream) override
sal_uInt64 m_nOffset
Input file start location.
Indirect object: something with a unique ID.
PDFArrayElement * m_pArrayElement
The contained direct array, if any.
std::vector< std::unique_ptr< PDFElement > > m_aElements
Elements of an object in an object stream.
void SetNumberElement(PDFNumberElement *pNumberElement)
const std::vector< PDFReferenceElement * > & GetDictionaryReferences() const
void SetDictionaryLength(sal_uInt64 nDictionaryLength)
const std::map< OString, PDFElement * > & GetDictionaryItems()
Get access to the parsed key-value items from the object dictionary.
double GetObjectValue() const
sal_uInt64 m_nDictionaryOffset
Position after the '<<' token.
PDFElement * Lookup(const OString &rDictionaryKey)
void SetArrayOffset(sal_uInt64 nArrayOffset)
PDFNumberElement * m_pNumberElement
If set, the object contains this number element (outside any dictionary/array).
PDFStreamElement * GetStream() const
Access to the stream of the object, if it has any.
std::vector< std::unique_ptr< PDFObjectElement > > m_aStoredElements
Objects of an object stream.
void SetDictionary(PDFDictionaryElement *pDictionaryElement)
PDFDictionaryElement * m_pDictionaryElement
sal_uInt64 m_nDictionaryLength
Length of the dictionary buffer till (before) the '>>' token.
void SetStream(PDFStreamElement *pStreamElement)
bool Read(SvStream &rStream) override
void SetArrayLength(sal_uInt64 nArrayLength)
sal_uInt64 GetArrayOffset() const
sal_uInt64 GetDictionaryOffset()
double m_fGenerationValue
SvMemoryStream * GetStreamBuffer() const
void SetArray(PDFArrayElement *pArrayElement)
std::vector< PDFReferenceElement * > m_aDictionaryReferences
List of all reference elements inside this object's dictionary and nested dictionaries.
PDFArrayElement * GetArray()
std::vector< std::unique_ptr< PDFElement > > & GetStoredElements()
void SetStreamBuffer(std::unique_ptr< SvMemoryStream > &pStreamBuffer)
std::unique_ptr< SvMemoryStream > m_pStreamBuffer
Uncompressed buffer of an object in an object stream.
sal_uInt64 GetDictionaryLength()
PDFObjectElement(PDFDocument &rDoc, double fObjectValue, double fGenerationValue)
sal_uInt64 m_nArrayOffset
Position after the '[' token, if m_pArrayElement is set.
void AddDictionaryReference(PDFReferenceElement *pReference)
void ParseStoredObjects()
Parse objects stored in this object stream.
sal_uInt64 m_nArrayLength
Length of the array buffer till (before) the ']' token.
PDFNumberElement * GetNumberElement() const
sal_uInt64 GetArrayLength() const
PDFDocument & m_rDoc
The document owning this element.
PDFObjectElement * LookupObject(const OString &rDictionaryKey)
PDFDocument & GetDocument()
void SetDictionaryOffset(sal_uInt64 nDictionaryOffset)
PDFStreamElement * m_pStreamElement
The stream of this object, used when this is an object stream.
PDFDictionaryElement * GetDictionary()
const std::vector< std::unique_ptr< PDFElement > > & mrElements
size_t parse(PDFElement *pParsingElement, size_t nStartIndex=0, int nCurrentDepth=0)
Reference object: something with a unique ID.
sal_uInt64 GetOffset() const
sal_uInt64 m_nOffset
Location after the 'R' token.
int GetGenerationValue() const
PDFReferenceElement(PDFDocument &rDoc, PDFNumberElement &rObject, PDFNumberElement const &rGeneration)
int GetObjectValue() const
PDFNumberElement & GetObjectElement() const
double LookupNumber(SvStream &rStream) const
Assuming the reference points to a number object, return its value.
bool Read(SvStream &rStream) override
PDFNumberElement & m_rObject
The element providing the object number.
PDFObjectElement * LookupObject()
Lookup referenced object, without assuming anything about its contents.
Stream object: a byte array with a known length.
SvMemoryStream & GetMemory()
sal_uInt64 GetOffset() const
SvMemoryStream m_aMemory
The byte array itself.
bool Read(SvStream &rStream) override
PDFStreamElement(size_t nLength)
The trailer singleton is at the end of the doc.
sal_uInt64 GetLocation() const
PDFDictionaryElement * m_pDictionaryElement
sal_uInt64 m_nOffset
Location of the end of the trailer token.
PDFTrailerElement(PDFDocument &rDoc)
bool Read(SvStream &rStream) override
PDFElement * Lookup(const OString &rDictionaryKey)
An entry in a cross-reference stream.
void SetDirty(bool bDirty)
void SetOffset(sal_uInt64 nOffset)
XRefEntryType GetType() const
sal_uInt64 GetOffset() const
void SetType(XRefEntryType eType)
#define MAX_SIGNATURE_CONTENT_LENGTH
EmbeddedObjectRef * pObject
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill='\0')
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
double toDouble(std::u16string_view str)
sal_uInt32 toUInt32(std::u16string_view str, sal_Int16 radix=10)
std::vector< unsigned char > DecodeHexString(std::string_view rHex)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
@ COMPRESSED
xref stream "2".
@ FREE
xref "f" or xref stream "0".
@ NOT_COMPRESSED
xref "n" or xref stream "1".
static void visitPages(PDFObjectElement *pPages, std::vector< PDFObjectElement * > &rRet)
Visits the page tree recursively, looking for page objects.
@ STORED_OBJECT
Same as END_OF_OBJECT, but for object streams (no endobj keyword).
@ EOF_TOKEN
Till the first %EOF token.
@ END_OF_OBJECT
Till the end of the current object.
@ END_OF_STREAM
Full file.
bool convertToHighestSupported(SvStream &rInStream, SvStream &rOutStream)
Converts to highest supported format version (1.6).
#define STREAM_SEEK_TO_END
std::unique_ptr< char[]> aBuffer