1 // Copyright 2016 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fpdfdoc/cpdf_metadata.h" 8 9 #include <memory> 10 #include <utility> 11 12 #include "core/fpdfapi/parser/cpdf_stream.h" 13 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 14 #include "core/fxcrt/cfx_read_only_span_stream.h" 15 #include "core/fxcrt/fx_codepage.h" 16 #include "core/fxcrt/xml/cfx_xmldocument.h" 17 #include "core/fxcrt/xml/cfx_xmlelement.h" 18 #include "core/fxcrt/xml/cfx_xmlparser.h" 19 #include "third_party/base/check.h" 20 21 namespace { 22 23 constexpr int kMaxMetaDataDepth = 128; 24 CheckForSharedFormInternal(int depth,CFX_XMLElement * element,std::vector<UnsupportedFeature> * unsupported)25bool CheckForSharedFormInternal(int depth, 26 CFX_XMLElement* element, 27 std::vector<UnsupportedFeature>* unsupported) { 28 if (depth >= kMaxMetaDataDepth) { 29 return false; 30 } 31 32 WideString attr = 33 element->GetAttribute(WideString::FromASCII("xmlns:adhocwf")); 34 if (attr.EqualsASCII("http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/")) { 35 for (const auto* child = element->GetFirstChild(); child; 36 child = child->GetNextSibling()) { 37 if (child->GetType() != CFX_XMLNode::Type::kElement) 38 continue; 39 40 const auto* child_elem = static_cast<const CFX_XMLElement*>(child); 41 if (!child_elem->GetName().EqualsASCII("adhocwf:workflowType")) 42 continue; 43 44 switch (child_elem->GetTextData().GetInteger()) { 45 case 0: 46 unsupported->push_back(UnsupportedFeature::kDocumentSharedFormEmail); 47 break; 48 case 1: 49 unsupported->push_back( 50 UnsupportedFeature::kDocumentSharedFormAcrobat); 51 break; 52 case 2: 53 unsupported->push_back( 54 UnsupportedFeature::kDocumentSharedFormFilesystem); 55 break; 56 } 57 // We only care about the first one we find. 58 break; 59 } 60 } 61 62 for (auto* child = element->GetFirstChild(); child; 63 child = child->GetNextSibling()) { 64 CFX_XMLElement* xml_element = ToXMLElement(child); 65 if (xml_element && 66 !CheckForSharedFormInternal(depth + 1, xml_element, unsupported)) { 67 return false; 68 } 69 } 70 return true; 71 } 72 73 } // namespace 74 CPDF_Metadata(RetainPtr<const CPDF_Stream> pStream)75CPDF_Metadata::CPDF_Metadata(RetainPtr<const CPDF_Stream> pStream) 76 : stream_(std::move(pStream)) { 77 DCHECK(stream_); 78 } 79 80 CPDF_Metadata::~CPDF_Metadata() = default; 81 CheckForSharedForm() const82std::vector<UnsupportedFeature> CPDF_Metadata::CheckForSharedForm() const { 83 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(stream_); 84 pAcc->LoadAllDataFiltered(); 85 86 auto stream = pdfium::MakeRetain<CFX_ReadOnlySpanStream>(pAcc->GetSpan()); 87 CFX_XMLParser parser(stream); 88 std::unique_ptr<CFX_XMLDocument> doc = parser.Parse(); 89 if (!doc) 90 return {}; 91 92 std::vector<UnsupportedFeature> unsupported; 93 CheckForSharedFormInternal(/*depth=*/0, doc->GetRoot(), &unsupported); 94 return unsupported; 95 } 96