xref: /aosp_15_r20/external/pdfium/core/fpdfdoc/cpdf_metadata.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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)25 bool 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)75 CPDF_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() const82 std::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