1// Copyright 2014 PDFium Authors. All rights reserved.
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 "public/fpdf_ext.h"
8
9#include "core/include/fxcrt/fx_xml.h"
10#include "fpdfsdk/include/fsdk_define.h"
11
12#ifdef PDF_ENABLE_XFA
13#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h"
14#endif  // PDF_ENABLE_XFA
15
16#define FPDFSDK_UNSUPPORT_CALL 100
17
18class CFSDK_UnsupportInfo_Adapter {
19 public:
20  CFSDK_UnsupportInfo_Adapter(UNSUPPORT_INFO* unsp_info) {
21    m_unsp_info = unsp_info;
22  }
23  void ReportError(int nErrorType);
24
25 private:
26  UNSUPPORT_INFO* m_unsp_info;
27};
28
29void CFSDK_UnsupportInfo_Adapter::ReportError(int nErrorType) {
30  if (m_unsp_info && m_unsp_info->FSDK_UnSupport_Handler) {
31    m_unsp_info->FSDK_UnSupport_Handler(m_unsp_info, nErrorType);
32  }
33}
34
35void FreeUnsupportInfo(void* pData) {
36  CFSDK_UnsupportInfo_Adapter* pAdapter = (CFSDK_UnsupportInfo_Adapter*)pData;
37  delete pAdapter;
38}
39
40FX_BOOL FPDF_UnSupportError(int nError) {
41  CFSDK_UnsupportInfo_Adapter* pAdapter =
42      (CFSDK_UnsupportInfo_Adapter*)CPDF_ModuleMgr::Get()->GetPrivateData(
43          (void*)FPDFSDK_UNSUPPORT_CALL);
44
45  if (!pAdapter)
46    return FALSE;
47  pAdapter->ReportError(nError);
48  return TRUE;
49}
50
51DLLEXPORT FPDF_BOOL STDCALL
52FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info) {
53  if (!unsp_info || unsp_info->version != 1)
54    return FALSE;
55  CFSDK_UnsupportInfo_Adapter* pAdapter =
56      new CFSDK_UnsupportInfo_Adapter(unsp_info);
57
58  CPDF_ModuleMgr::Get()->SetPrivateData((void*)FPDFSDK_UNSUPPORT_CALL, pAdapter,
59                                        &FreeUnsupportInfo);
60
61  return TRUE;
62}
63
64void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot) {
65  CFX_ByteString cbSubType = pPDFAnnot->GetSubType();
66  if (cbSubType.Compare("3D") == 0) {
67    FPDF_UnSupportError(FPDF_UNSP_ANNOT_3DANNOT);
68  } else if (cbSubType.Compare("Screen") == 0) {
69    const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
70    CFX_ByteString cbString;
71    if (pAnnotDict->KeyExist("IT"))
72      cbString = pAnnotDict->GetString("IT");
73    if (cbString.Compare("Img") != 0)
74      FPDF_UnSupportError(FPDF_UNSP_ANNOT_SCREEN_MEDIA);
75  } else if (cbSubType.Compare("Movie") == 0) {
76    FPDF_UnSupportError(FPDF_UNSP_ANNOT_MOVIE);
77  } else if (cbSubType.Compare("Sound") == 0) {
78    FPDF_UnSupportError(FPDF_UNSP_ANNOT_SOUND);
79  } else if (cbSubType.Compare("RichMedia") == 0) {
80    FPDF_UnSupportError(FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA);
81  } else if (cbSubType.Compare("FileAttachment") == 0) {
82    FPDF_UnSupportError(FPDF_UNSP_ANNOT_ATTACHMENT);
83  } else if (cbSubType.Compare("Widget") == 0) {
84    const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
85    CFX_ByteString cbString;
86    if (pAnnotDict->KeyExist("FT")) {
87      cbString = pAnnotDict->GetString("FT");
88    }
89    if (cbString.Compare("Sig") == 0) {
90      FPDF_UnSupportError(FPDF_UNSP_ANNOT_SIG);
91    }
92  }
93}
94
95FX_BOOL CheckSharedForm(const CXML_Element* pElement, CFX_ByteString cbName) {
96  int count = pElement->CountAttrs();
97  int i = 0;
98  for (i = 0; i < count; i++) {
99    CFX_ByteString space, name;
100    CFX_WideString value;
101    pElement->GetAttrByIndex(i, space, name, value);
102    if (space == "xmlns" && name == "adhocwf" &&
103        value == L"http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/") {
104      CXML_Element* pVersion = pElement->GetElement("adhocwf", cbName);
105      if (!pVersion)
106        continue;
107      CFX_WideString wsContent = pVersion->GetContent(0);  // == 1.1
108      int nType = wsContent.GetInteger();
109      switch (nType) {
110        case 1:
111          FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_ACROBAT);
112          break;
113        case 2:
114          FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM);
115          break;
116        case 0:
117          FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_EMAIL);
118          break;
119      }
120    }
121  }
122
123  FX_DWORD nCount = pElement->CountChildren();
124  for (i = 0; i < (int)nCount; i++) {
125    CXML_Element::ChildType childType = pElement->GetChildType(i);
126    if (childType == CXML_Element::Element) {
127      CXML_Element* pChild = pElement->GetElement(i);
128      if (CheckSharedForm(pChild, cbName))
129        return TRUE;
130    }
131  }
132  return FALSE;
133}
134
135void CheckUnSupportError(CPDF_Document* pDoc, FX_DWORD err_code) {
136  // Security
137  if (err_code == FPDF_ERR_SECURITY) {
138    FPDF_UnSupportError(FPDF_UNSP_DOC_SECURITY);
139    return;
140  }
141  if (!pDoc)
142    return;
143
144  // Portfolios and Packages
145  CPDF_Dictionary* pRootDict = pDoc->GetRoot();
146  if (pRootDict) {
147    CFX_ByteString cbString;
148    if (pRootDict->KeyExist("Collection")) {
149      FPDF_UnSupportError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
150      return;
151    }
152    if (pRootDict->KeyExist("Names")) {
153      CPDF_Dictionary* pNameDict = pRootDict->GetDict("Names");
154      if (pNameDict && pNameDict->KeyExist("EmbeddedFiles")) {
155        FPDF_UnSupportError(FPDF_UNSP_DOC_ATTACHMENT);
156        return;
157      }
158      if (pNameDict && pNameDict->KeyExist("JavaScript")) {
159        CPDF_Dictionary* pJSDict = pNameDict->GetDict("JavaScript");
160        CPDF_Array* pArray = pJSDict ? pJSDict->GetArray("Names") : NULL;
161        if (pArray) {
162          int nCount = pArray->GetCount();
163          for (int i = 0; i < nCount; i++) {
164            CFX_ByteString cbStr = pArray->GetString(i);
165            if (cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0) {
166              FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDREVIEW);
167              return;
168            }
169          }
170        }
171      }
172    }
173  }
174
175  // SharedForm
176  CPDF_Metadata metaData(pDoc);
177  const CXML_Element* pElement = metaData.GetRoot();
178  if (pElement)
179    CheckSharedForm(pElement, "workflowType");
180
181#ifndef PDF_ENABLE_XFA
182  // XFA Forms
183  CPDF_InterForm* pInterForm = new CPDF_InterForm(pDoc, FALSE);
184  if (pInterForm->HasXFAForm()) {
185    FPDF_UnSupportError(FPDF_UNSP_DOC_XFAFORM);
186  }
187  delete pInterForm;
188#endif  // PDF_ENABLE_XFA
189}
190
191DLLEXPORT int FPDFDoc_GetPageMode(FPDF_DOCUMENT document) {
192  CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
193  if (!pDoc)
194    return PAGEMODE_UNKNOWN;
195
196  CPDF_Dictionary* pRoot = pDoc->GetRoot();
197  if (!pRoot)
198    return PAGEMODE_UNKNOWN;
199
200  CPDF_Object* pName = pRoot->GetElement("PageMode");
201  if (!pName)
202    return PAGEMODE_USENONE;
203
204  CFX_ByteString strPageMode = pName->GetString();
205  if (strPageMode.IsEmpty() || strPageMode.EqualNoCase("UseNone"))
206    return PAGEMODE_USENONE;
207  if (strPageMode.EqualNoCase("UseOutlines"))
208    return PAGEMODE_USEOUTLINES;
209  if (strPageMode.EqualNoCase("UseThumbs"))
210    return PAGEMODE_USETHUMBS;
211  if (strPageMode.EqualNoCase("FullScreen"))
212    return PAGEMODE_FULLSCREEN;
213  if (strPageMode.EqualNoCase("UseOC"))
214    return PAGEMODE_USEOC;
215  if (strPageMode.EqualNoCase("UseAttachments"))
216    return PAGEMODE_USEATTACHMENTS;
217
218  return PAGEMODE_UNKNOWN;
219}
220