// 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 "../../../include/fpdfapi/fpdf_parser.h" #include "../../../include/fpdfapi/fpdf_module.h" CPDF_Document::CPDF_Document(CPDF_Parser* pParser) : CPDF_IndirectObjects(pParser) { ASSERT(pParser != NULL); m_pRootDict = NULL; m_pInfoDict = NULL; m_bLinearized = FALSE; m_dwFirstPageNo = 0; m_dwFirstPageObjNum = 0; m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); } CPDF_DocPageData* CPDF_Document::GetValidatePageData() { if (m_pDocPage) { return m_pDocPage; } m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); return m_pDocPage; } CPDF_DocRenderData* CPDF_Document::GetValidateRenderData() { if (m_pDocRender) { return m_pDocRender; } m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); return m_pDocRender; } void CPDF_Document::LoadDoc() { m_LastObjNum = m_pParser->GetLastObjNum(); CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum()); if (pRootObj == NULL) { return; } m_pRootDict = pRootObj->GetDict(); if (m_pRootDict == NULL) { return; } CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum()); if (pInfoObj) { m_pInfoDict = pInfoObj->GetDict(); } CPDF_Array* pIDArray = m_pParser->GetIDArray(); if (pIDArray) { m_ID1 = pIDArray->GetString(0); m_ID2 = pIDArray->GetString(1); } m_PageList.SetSize(_GetPageCount()); } void CPDF_Document::LoadAsynDoc(CPDF_Dictionary* pLinearized) { m_bLinearized = TRUE; m_LastObjNum = m_pParser->GetLastObjNum(); CPDF_Object* indirectObj = GetIndirectObject(m_pParser->GetRootObjNum()); m_pRootDict = indirectObj ? indirectObj->GetDict() : NULL; if (m_pRootDict == NULL) { return; } indirectObj = GetIndirectObject(m_pParser->GetInfoObjNum()); m_pInfoDict = indirectObj ? indirectObj->GetDict() : NULL; CPDF_Array* pIDArray = m_pParser->GetIDArray(); if (pIDArray) { m_ID1 = pIDArray->GetString(0); m_ID2 = pIDArray->GetString(1); } FX_DWORD dwPageCount = 0; CPDF_Object* pCount = pLinearized->GetElement(FX_BSTRC("N")); if (pCount && pCount->GetType() == PDFOBJ_NUMBER) { dwPageCount = pCount->GetInteger(); } m_PageList.SetSize(dwPageCount); CPDF_Object* pNo = pLinearized->GetElement(FX_BSTRC("P")); if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { m_dwFirstPageNo = pNo->GetInteger(); } CPDF_Object* pObjNum = pLinearized->GetElement(FX_BSTRC("O")); if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) { m_dwFirstPageObjNum = pObjNum->GetInteger(); } } void CPDF_Document::LoadPages() { m_PageList.SetSize(_GetPageCount()); } CPDF_Document::~CPDF_Document() { if (m_pDocPage) { CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this); CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this); } if (m_pDocRender) { CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender); } } #define FX_MAX_PAGE_LEVEL 1024 CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level) { CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); if (pKidList == NULL) { if (nPagesToGo == 0) { return pPages; } return NULL; } if (level >= FX_MAX_PAGE_LEVEL) { return NULL; } int nKids = pKidList->GetCount(); for (int i = 0; i < nKids; i++) { CPDF_Dictionary* pKid = pKidList->GetDict(i); if (pKid == NULL) { nPagesToGo--; continue; } if (pKid == pPages) { continue; } if (!pKid->KeyExist(FX_BSTRC("Kids"))) { if (nPagesToGo == 0) { return pKid; } m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum()); nPagesToGo--; } else { int nPages = pKid->GetInteger(FX_BSTRC("Count")); if (nPagesToGo < nPages) { return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1); } nPagesToGo -= nPages; } } return NULL; } CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { if (iPage < 0 || iPage >= m_PageList.GetSize()) return nullptr; if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) { CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum); if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) { return static_cast(pObj); } } int objnum = m_PageList.GetAt(iPage); if (objnum) { CPDF_Object* pObj = GetIndirectObject(objnum); if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) { return static_cast(pObj); } } CPDF_Dictionary* pRoot = GetRoot(); if (!pRoot) return nullptr; CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); if (!pPages) return nullptr; CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0); if (!pPage) return nullptr; m_PageList.SetAt(iPage, pPage->GetObjNum()); return pPage; } int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level) { if (pNode->KeyExist(FX_BSTRC("Kids"))) { CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids")); if (pKidList == NULL) { return -1; } if (level >= FX_MAX_PAGE_LEVEL) { return -1; } FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count")); if (count <= skip_count) { skip_count -= count; index += count; return -1; } if (count && count == pKidList->GetCount()) { for (FX_DWORD i = 0; i < count; i++) { CPDF_Object* pKid = pKidList->GetElement(i); if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) { if (((CPDF_Reference*)pKid)->GetRefObjNum() == objnum) { m_PageList.SetAt(index + i, objnum); return index + i; } } } } for (FX_DWORD i = 0; i < pKidList->GetCount(); i++) { CPDF_Dictionary* pKid = pKidList->GetDict(i); if (pKid == NULL) { continue; } if (pKid == pNode) { continue; } int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1); if (found_index >= 0) { return found_index; } } } else { if (objnum == pNode->GetObjNum()) { return index; } if (skip_count) { skip_count--; } index++; } return -1; } int CPDF_Document::GetPageIndex(FX_DWORD objnum) { FX_DWORD nPages = m_PageList.GetSize(); FX_DWORD skip_count = 0; FX_BOOL bSkipped = FALSE; for (FX_DWORD i = 0; i < nPages; i++) { FX_DWORD objnum1 = m_PageList.GetAt(i); if (objnum1 == objnum) { return i; } if (!bSkipped && objnum1 == 0) { skip_count = i; bSkipped = TRUE; } } CPDF_Dictionary* pRoot = GetRoot(); if (pRoot == NULL) { return -1; } CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); if (pPages == NULL) { return -1; } int index = 0; return _FindPageIndex(pPages, skip_count, objnum, index); } int CPDF_Document::GetPageCount() const { return m_PageList.GetSize(); } static int _CountPages(CPDF_Dictionary* pPages, int level) { if (level > 128) { return 0; } int count = pPages->GetInteger(FX_BSTRC("Count")); if (count > 0 && count < FPDF_PAGE_MAX_NUM) { return count; } CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); if (pKidList == NULL) { return 0; } count = 0; for (FX_DWORD i = 0; i < pKidList->GetCount(); i++) { CPDF_Dictionary* pKid = pKidList->GetDict(i); if (pKid == NULL) { continue; } if (!pKid->KeyExist(FX_BSTRC("Kids"))) { count++; } else { count += _CountPages(pKid, level + 1); } } pPages->SetAtInteger(FX_BSTRC("Count"), count); return count; } int CPDF_Document::_GetPageCount() const { CPDF_Dictionary* pRoot = GetRoot(); if (pRoot == NULL) { return 0; } CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); if (pPages == NULL) { return 0; } if (!pPages->KeyExist(FX_BSTRC("Kids"))) { return 1; } return _CountPages(pPages, 0); } FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict) { for (int i = 0; i < m_PageList.GetSize(); i++) { CPDF_Dictionary* pPageDict = GetPage(i); if (pPageDict == pThisPageDict) { continue; } CPDF_Object* pContents = pPageDict ? pPageDict->GetElement(FX_BSTRC("Contents")) : NULL; if (pContents == NULL) { continue; } if (pContents->GetDirectType() == PDFOBJ_ARRAY) { CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect(); for (FX_DWORD j = 0; j < pArray->GetCount(); j++) { CPDF_Object* pRef = pArray->GetElement(j); if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { continue; } if (((CPDF_Reference*)pRef)->GetRefObjNum() == objnum) { return TRUE; } } } else if (pContents->GetObjNum() == objnum) { return TRUE; } } return FALSE; } FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const { if (m_pParser == NULL) { return (FX_DWORD)-1; } return m_pParser->GetPermissions(bCheckRevision); } FX_BOOL CPDF_Document::IsOwner() const { if (m_pParser == NULL) { return TRUE; } return m_pParser->IsOwner(); } FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const { { CPDF_Object* pObj; if (m_IndirectObjs.Lookup((void*)(uintptr_t)objnum, (void*&)pObj)) { bForm = pObj->GetType() == PDFOBJ_STREAM && ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form"); return TRUE; } } if (m_pParser == NULL) { bForm = FALSE; return TRUE; } return m_pParser->IsFormStream(objnum, bForm); } void CPDF_Document::ClearPageData() { if (m_pDocPage) { CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this); } } void CPDF_Document::ClearRenderData() { if (m_pDocRender) { CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender); } }