// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "public/fpdf_ext.h"

#include "core/include/fxcrt/fx_xml.h"
#include "fpdfsdk/include/fsdk_define.h"

#ifdef PDF_ENABLE_XFA
#include "fpdfsdk/include/fpdfxfa/fpdfxfa_doc.h"
#endif  // PDF_ENABLE_XFA

#define FPDFSDK_UNSUPPORT_CALL 100

class CFSDK_UnsupportInfo_Adapter {
 public:
  CFSDK_UnsupportInfo_Adapter(UNSUPPORT_INFO* unsp_info) {
    m_unsp_info = unsp_info;
  }
  void ReportError(int nErrorType);

 private:
  UNSUPPORT_INFO* m_unsp_info;
};

void CFSDK_UnsupportInfo_Adapter::ReportError(int nErrorType) {
  if (m_unsp_info && m_unsp_info->FSDK_UnSupport_Handler) {
    m_unsp_info->FSDK_UnSupport_Handler(m_unsp_info, nErrorType);
  }
}

void FreeUnsupportInfo(void* pData) {
  CFSDK_UnsupportInfo_Adapter* pAdapter = (CFSDK_UnsupportInfo_Adapter*)pData;
  delete pAdapter;
}

FX_BOOL FPDF_UnSupportError(int nError) {
  CFSDK_UnsupportInfo_Adapter* pAdapter =
      (CFSDK_UnsupportInfo_Adapter*)CPDF_ModuleMgr::Get()->GetPrivateData(
          (void*)FPDFSDK_UNSUPPORT_CALL);

  if (!pAdapter)
    return FALSE;
  pAdapter->ReportError(nError);
  return TRUE;
}

DLLEXPORT FPDF_BOOL STDCALL
FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO* unsp_info) {
  if (!unsp_info || unsp_info->version != 1)
    return FALSE;
  CFSDK_UnsupportInfo_Adapter* pAdapter =
      new CFSDK_UnsupportInfo_Adapter(unsp_info);

  CPDF_ModuleMgr::Get()->SetPrivateData((void*)FPDFSDK_UNSUPPORT_CALL, pAdapter,
                                        &FreeUnsupportInfo);

  return TRUE;
}

void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot) {
  CFX_ByteString cbSubType = pPDFAnnot->GetSubType();
  if (cbSubType.Compare("3D") == 0) {
    FPDF_UnSupportError(FPDF_UNSP_ANNOT_3DANNOT);
  } else if (cbSubType.Compare("Screen") == 0) {
    const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
    CFX_ByteString cbString;
    if (pAnnotDict->KeyExist("IT"))
      cbString = pAnnotDict->GetStringBy("IT");
    if (cbString.Compare("Img") != 0)
      FPDF_UnSupportError(FPDF_UNSP_ANNOT_SCREEN_MEDIA);
  } else if (cbSubType.Compare("Movie") == 0) {
    FPDF_UnSupportError(FPDF_UNSP_ANNOT_MOVIE);
  } else if (cbSubType.Compare("Sound") == 0) {
    FPDF_UnSupportError(FPDF_UNSP_ANNOT_SOUND);
  } else if (cbSubType.Compare("RichMedia") == 0) {
    FPDF_UnSupportError(FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA);
  } else if (cbSubType.Compare("FileAttachment") == 0) {
    FPDF_UnSupportError(FPDF_UNSP_ANNOT_ATTACHMENT);
  } else if (cbSubType.Compare("Widget") == 0) {
    const CPDF_Dictionary* pAnnotDict = pPDFAnnot->GetAnnotDict();
    CFX_ByteString cbString;
    if (pAnnotDict->KeyExist("FT")) {
      cbString = pAnnotDict->GetStringBy("FT");
    }
    if (cbString.Compare("Sig") == 0) {
      FPDF_UnSupportError(FPDF_UNSP_ANNOT_SIG);
    }
  }
}

FX_BOOL CheckSharedForm(const CXML_Element* pElement, CFX_ByteString cbName) {
  int count = pElement->CountAttrs();
  int i = 0;
  for (i = 0; i < count; i++) {
    CFX_ByteString space, name;
    CFX_WideString value;
    pElement->GetAttrByIndex(i, space, name, value);
    if (space == "xmlns" && name == "adhocwf" &&
        value == L"http://ns.adobe.com/AcrobatAdhocWorkflow/1.0/") {
      CXML_Element* pVersion = pElement->GetElement("adhocwf", cbName);
      if (!pVersion)
        continue;
      CFX_WideString wsContent = pVersion->GetContent(0);  // == 1.1
      int nType = wsContent.GetInteger();
      switch (nType) {
        case 1:
          FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_ACROBAT);
          break;
        case 2:
          FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM);
          break;
        case 0:
          FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDFORM_EMAIL);
          break;
      }
    }
  }

  FX_DWORD nCount = pElement->CountChildren();
  for (i = 0; i < (int)nCount; i++) {
    CXML_Element::ChildType childType = pElement->GetChildType(i);
    if (childType == CXML_Element::Element) {
      CXML_Element* pChild = pElement->GetElement(i);
      if (CheckSharedForm(pChild, cbName))
        return TRUE;
    }
  }
  return FALSE;
}

void CheckUnSupportError(CPDF_Document* pDoc, FX_DWORD err_code) {
  // Security
  if (err_code == FPDF_ERR_SECURITY) {
    FPDF_UnSupportError(FPDF_UNSP_DOC_SECURITY);
    return;
  }
  if (!pDoc)
    return;

  // Portfolios and Packages
  CPDF_Dictionary* pRootDict = pDoc->GetRoot();
  if (pRootDict) {
    CFX_ByteString cbString;
    if (pRootDict->KeyExist("Collection")) {
      FPDF_UnSupportError(FPDF_UNSP_DOC_PORTABLECOLLECTION);
      return;
    }
    if (pRootDict->KeyExist("Names")) {
      CPDF_Dictionary* pNameDict = pRootDict->GetDictBy("Names");
      if (pNameDict && pNameDict->KeyExist("EmbeddedFiles")) {
        FPDF_UnSupportError(FPDF_UNSP_DOC_ATTACHMENT);
        return;
      }
      if (pNameDict && pNameDict->KeyExist("JavaScript")) {
        CPDF_Dictionary* pJSDict = pNameDict->GetDictBy("JavaScript");
        CPDF_Array* pArray = pJSDict ? pJSDict->GetArrayBy("Names") : NULL;
        if (pArray) {
          int nCount = pArray->GetCount();
          for (int i = 0; i < nCount; i++) {
            CFX_ByteString cbStr = pArray->GetStringAt(i);
            if (cbStr.Compare("com.adobe.acrobat.SharedReview.Register") == 0) {
              FPDF_UnSupportError(FPDF_UNSP_DOC_SHAREDREVIEW);
              return;
            }
          }
        }
      }
    }
  }

  // SharedForm
  CPDF_Metadata metaData(pDoc);
  const CXML_Element* pElement = metaData.GetRoot();
  if (pElement)
    CheckSharedForm(pElement, "workflowType");

#ifndef PDF_ENABLE_XFA
  // XFA Forms
  CPDF_InterForm* pInterForm = new CPDF_InterForm(pDoc, FALSE);
  if (pInterForm->HasXFAForm()) {
    FPDF_UnSupportError(FPDF_UNSP_DOC_XFAFORM);
  }
  delete pInterForm;
#endif  // PDF_ENABLE_XFA
}

DLLEXPORT int FPDFDoc_GetPageMode(FPDF_DOCUMENT document) {
  CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
  if (!pDoc)
    return PAGEMODE_UNKNOWN;

  CPDF_Dictionary* pRoot = pDoc->GetRoot();
  if (!pRoot)
    return PAGEMODE_UNKNOWN;

  CPDF_Object* pName = pRoot->GetElement("PageMode");
  if (!pName)
    return PAGEMODE_USENONE;

  CFX_ByteString strPageMode = pName->GetString();
  if (strPageMode.IsEmpty() || strPageMode.EqualNoCase("UseNone"))
    return PAGEMODE_USENONE;
  if (strPageMode.EqualNoCase("UseOutlines"))
    return PAGEMODE_USEOUTLINES;
  if (strPageMode.EqualNoCase("UseThumbs"))
    return PAGEMODE_USETHUMBS;
  if (strPageMode.EqualNoCase("FullScreen"))
    return PAGEMODE_FULLSCREEN;
  if (strPageMode.EqualNoCase("UseOC"))
    return PAGEMODE_USEOC;
  if (strPageMode.EqualNoCase("UseAttachments"))
    return PAGEMODE_USEATTACHMENTS;

  return PAGEMODE_UNKNOWN;
}
