Files
DocumentServer-v-9.2.0/core/OOXML/DocxFormat/IFileContainer.cpp
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

476 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "IFileContainer.h"
#include "Rels.h"
#include "FileFactory.h"
#include "ContentTypes.h"
#include "FileType.h"
#include "FileTypes.h"
#include "External/External.h"
#include "External/HyperLink.h"
#include "Media/Image.h"
#include "Media/OleObject.h"
#include "Media/ActiveX.h"
#include "../PPTXFormat/LegacyDiagramText.h"
#include "../XlsxFormat/FileFactory_Spreadsheet.h"
#include "../VsdxFormat/FileFactory_Draw.h"
namespace OOX
{
boost::unordered_map<std::wstring, size_t> IFileContainer::m_mapEnumeratedGlobal;
UnknowTypeFile IFileContainer::m_oUnknown(NULL);
IFileContainer::IFileContainer(OOX::Document* pMain) : m_pMainDocument(pMain)
{
m_bVisioPages = false;
m_bSpreadsheets = false;
m_lMaxRid = 0;
}
IFileContainer::~IFileContainer()
{
}
void IFileContainer::Read (const OOX::CPath& oRootPath, const OOX::CPath& oPath)
{
// Находим связи(рельсы) с данным файлом
m_pCurRels = new OOX::CRels(oPath);
if (m_pMainDocument)
{
smart_ptr<OOX::File> pFile = dynamic_cast<OOX::File*>(this);
pFile.AddRef();
m_pMainDocument->m_mapContent.insert(std::make_pair(oPath.GetPath(), pFile));
}
// Читаем все файлы по рельсам
Read( *m_pCurRels, oRootPath, oPath.GetDirectory() );
}
void IFileContainer::Read (const OOX::CRels& oRels, const OOX::CPath& oRootPath, const OOX::CPath& oPath)
{
for (size_t i = 0; i < oRels.m_arRelations.size(); ++i)
{
if (!oRels.m_arRelations[i]) continue;
std::wstring pathFile = oRels.m_arRelations[i]->IsExternal() ? oRels.m_arRelations[i]->Target().GetPath() :
(oPath / oRels.m_arRelations[i]->Target()).GetPath();
if (m_pMainDocument)
{
std::map<std::wstring, smart_ptr<OOX::File>>::iterator pFind = m_pMainDocument->m_mapContent.find(pathFile);
if (pFind != m_pMainDocument->m_mapContent.end())
{
Add(oRels.m_arRelations[i]->rId(), pFind->second);
continue;
}
}
smart_ptr<OOX::File> pFile;
if (m_bSpreadsheets)
pFile = OOX::Spreadsheet::CreateFile(oRootPath, oPath, oRels.m_arRelations[i], m_pMainDocument);
if (m_bVisioPages)
pFile = OOX::Draw::CreateFile(oRootPath, oPath, oRels.m_arRelations[i], m_pMainDocument);
if (pFile.IsInit() == false || pFile->type() == FileTypes::Unknown)
pFile = OOX::CreateFile(oRootPath, oPath, oRels.m_arRelations[i], m_pMainDocument);
if (oRels.m_arRelations[i]->IsExternal())
{
smart_ptr<OOX::Media> pMedia = pFile.smart_dynamic_cast<OOX::Media>();
if (pMedia.IsInit())
pMedia->set_filename(oRels.m_arRelations[i]->Target().GetPath(), true);
}
Add(oRels.m_arRelations[i]->rId(), pFile);
}
}
void IFileContainer::Write(const OOX::CPath& oFileName, const OOX::CPath& oDirectory, OOX::CContentTypes& oContent) const
{
OOX::CPath oCurrent = oFileName.GetDirectory();
OOX::CRels oRels;
Write( oRels, oCurrent, oDirectory, oContent );
oRels.Write( oFileName );
}
void IFileContainer::Write(OOX::CRels& oRels, const OOX::CPath& oCurrent, const OOX::CPath& oDir, OOX::CContentTypes& oContent) const
{
const OOX::File* pFileOwner = dynamic_cast<const OOX::File*>(this);
for (std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pPair = m_mapContainer.begin(); pPair != m_mapContainer.end(); ++pPair)
{
smart_ptr<OOX::File> pFile = pPair->second;
smart_ptr<OOX::External> pExt = pFile.smart_dynamic_cast<OOX::External>();
smart_ptr<OOX::Media> pMedia = pFile.smart_dynamic_cast<OOX::Media>();
bool bExternal = pExt.IsInit() || ((pMedia.IsInit()) && (pMedia->IsExternal()));
if ( !bExternal )
{
OOX::CPath oDefDir = pFile->DefaultDirectory();
OOX::CPath oName = pFile->DefaultFileName();
if (pFile->type() == OOX::Spreadsheet::FileTypes::PivotCacheDefinition &&
pFileOwner->type() == OOX::Spreadsheet::FileTypes::PivotTable)
{
oDefDir = L"../" + oDefDir;
}
if (false == pFile->m_sOutputFilename.empty())
oName.SetName(pFile->m_sOutputFilename, false);
boost::unordered_map<std::wstring, std::wstring>::const_iterator itFind = m_mNoWriteContainer.find(pPair->first);
if(m_mNoWriteContainer.end() == itFind)
{
OOX::CSystemUtility::CreateDirectories( oCurrent / oDefDir );
pFile->write( oCurrent / oDefDir / oName, oDir / oDefDir, oContent );
}
else if(itFind->second.length() > 0)
{
oDefDir = itFind->second;
}
if(true != pFile->m_bDoNotAddRels)
{
if (oDefDir.GetPath().length() > 0)//todooo перенести в CPath
oRels.Registration( pPair->first, pFile->type(), oDefDir / oName );
else
oRels.Registration( pPair->first, pFile->type(), oName );
}
}
else
{
if (pExt.IsInit())
{
oRels.Registration( pPair->first, pExt );
}
else if ((pMedia.IsInit()) && (pMedia->IsExternal()))
{
oRels.Registration( pPair->first, pMedia->type(), pMedia->filename().GetPath(), true);
}
}
}
}
void IFileContainer::Commit (const OOX::CPath& oPath)
{
std::map<std::wstring, size_t> mNamepair;
for (size_t i = 0; i < m_arContainer.size(); ++i)
{
smart_ptr<OOX::File> &pFile = m_arContainer[i];
smart_ptr<OOX::External> pExt = pFile.smart_dynamic_cast<OOX::External>();
smart_ptr<OOX::Media> pMedia = pFile.smart_dynamic_cast<OOX::Media>();
bool bExternal = pExt.IsInit() || ((pMedia.IsInit()) && (pMedia->IsExternal()));
if ( !bExternal )
if (!pExt.IsInit())
{
OOX::CPath oDefDir = pFile->DefaultDirectory();
OOX::CPath oName = pFile->DefaultFileName();
std::map<std::wstring, size_t>::const_iterator pNamePair = mNamepair.find( oName.m_strFilename );
if (pNamePair == mNamepair.end())
mNamepair [oName.m_strFilename] = 1;
else
oName = oName + pNamePair->first;
OOX::CSystemUtility::CreateDirectories( oPath / oDefDir );
smart_ptr<OOX::IFileBuilder> pFileBuilder = pFile.smart_dynamic_cast<OOX::IFileBuilder>();
if ( pFileBuilder.is_init() )
pFileBuilder->Commit( oPath / oDefDir / oName );
}
}
}
void IFileContainer::Finalize(const OOX::CPath& oFileName, const OOX::CPath& oDirectory, OOX::CContentTypes& oContent)
{
OOX::CPath oCurrent = oFileName.GetDirectory();
OOX::CRels oRels;
Finalize( oRels, oCurrent, oDirectory, oContent );
oRels.Write( oFileName );
}
void IFileContainer::Finalize(OOX::CRels& oRels, const OOX::CPath& oCurrent, const OOX::CPath& oDir, OOX::CContentTypes& oContent)
{
std::map<std::wstring, size_t> mNamepair;
for (std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pPair = m_mapContainer.begin(); pPair != m_mapContainer.end(); ++pPair)
{
smart_ptr<OOX::File> pFile = pPair->second;
smart_ptr<OOX::External> pExt = pFile.smart_dynamic_cast<OOX::External>();
smart_ptr<OOX::Media> pMedia = pFile.smart_dynamic_cast<OOX::Media>();
bool bExternal = pExt.IsInit() || ((pMedia.IsInit()) && (pMedia->IsExternal()));
if ( !bExternal )
{
OOX::CPath oDefDir = pFile->DefaultDirectory();
OOX::CPath oName = pFile->DefaultFileName();
std::map<std::wstring, size_t>::iterator pNamePair = mNamepair.find( oName.m_strFilename );
if ( pNamePair == mNamepair.end() )
mNamepair [oName.m_strFilename] = 1;
else
oName = oName + pNamePair->first;
boost::unordered_map<std::wstring, std::wstring>::const_iterator itFind = m_mNoWriteContainer.find(pPair->first);
if(m_mNoWriteContainer.end() == itFind)
{
OOX::CSystemUtility::CreateDirectories( oCurrent / oDefDir );
smart_ptr<OOX::IFileBuilder> pFileBuilder = pFile.smart_dynamic_cast<OOX::IFileBuilder>();
if ( pFileBuilder.is_init() )
{
pFileBuilder->Finalize( oCurrent / oDefDir / oName, oDir / oDefDir, oContent );
}
else
{
pFile->write( oCurrent / oDefDir / oName, oDir / oDefDir, oContent );
}
}
else if(itFind->second.length() > 0)
{
oDefDir = itFind->second;
}
oRels.Registration( pPair->first, pFile->type(), oDefDir / oName );
}
else
{
oRels.Registration( pPair->first, pExt );
}
}
}
const bool IFileContainer::IsExist(const RId& rId) const
{
std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pFind = m_mapContainer.find(rId.get());
return (pFind != m_mapContainer.end());
}
template<typename T>
const bool IFileContainer::IsExist() const
{
T oFile;
return IsExist( oFile.type() );
}
std::wstring IFileContainer::IsExistHyperlink(const std::wstring & href)
{
boost::unordered_map<std::wstring, std::wstring>::const_iterator pFind = m_mapHyperlinks.find(href);
if (pFind != m_mapHyperlinks.end())
{
return pFind->second;
}
return std::wstring();
}
const bool IFileContainer::IsExternal(const OOX::RId& rId) const
{
std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pFind = m_mapContainer.find(rId.get());
if (pFind != m_mapContainer.end())
{
smart_ptr<OOX::Media> mediaFile = pFind->second.smart_dynamic_cast<OOX::Media>();
if (mediaFile.IsInit())
{
return mediaFile->IsExternal();
}
else
{
return false;
}
}
return true;
}
const RId IFileContainer::Add(smart_ptr<OOX::File>& pFile)
{
const RId rId = GetMaxRId().next();
Add( rId, pFile );
return rId;
}
void IFileContainer::AssignOutputFilename(smart_ptr<OOX::File>& pFile)
{
bool bEnumerated = pFile->type().Enumerated();
bool bEnumeratedGlobal = pFile->type().EnumeratedGlobal();
if((true == bEnumeratedGlobal || true == bEnumerated) && pFile->m_sOutputFilename.empty())
{
int nIndex = 0;
if(true == bEnumeratedGlobal)
{
boost::unordered_map<std::wstring, size_t>::const_iterator pNamePair = m_mapEnumeratedGlobal.find (pFile->type().EnumerateType());
if (pNamePair != m_mapEnumeratedGlobal.end())
nIndex = pNamePair->second;
}
else
{
boost::unordered_map<std::wstring, size_t>::const_iterator pNamePair = m_mapAddNamePair.find (pFile->type().EnumerateType());
if (pNamePair != m_mapAddNamePair.end())
nIndex = pNamePair->second;
}
nIndex++;
if(true == bEnumeratedGlobal)
{
if(pFile.is<OOX::FileGlobalEnumerated>())
{
OOX::FileGlobalEnumerated& oFileGlobalEnumerated = pFile.as<OOX::FileGlobalEnumerated>();
oFileGlobalEnumerated.SetGlobalNumber(nIndex);
}
}
std::wstring sPath = pFile->DefaultFileName().GetPath();
size_t nDotIndex = sPath.rfind('.');
if(std::wstring::npos != nDotIndex && nDotIndex > 0)
{
std::wstring sDigit = std::to_wstring( nIndex);
sPath.insert(sPath.begin() + nDotIndex, sDigit.begin(), sDigit.end());
}
pFile->m_sOutputFilename = sPath;
if(true == bEnumeratedGlobal)
m_mapEnumeratedGlobal [pFile->type().EnumerateType()] = nIndex;
else
m_mapAddNamePair [pFile->type().EnumerateType()] = nIndex;
}
}
void IFileContainer::Add (const OOX::RId& rId, smart_ptr<OOX::File>& pFile)
{
AssignOutputFilename(pFile);
m_lMaxRid = (std::max)( m_lMaxRid, rId.getNumber() );
m_arContainer.push_back(pFile);
m_mapContainer [rId.get()] = pFile;
smart_ptr<OOX::HyperLink> oHyperlinkFile = pFile.smart_dynamic_cast<OOX::HyperLink>();
if (oHyperlinkFile.IsInit())
{
m_mapHyperlinks.insert(std::make_pair( oHyperlinkFile->Uri().GetPath(), rId.get() ));
}
}
const RId IFileContainer::AddNoWrite(const smart_ptr<OOX::File>& pFile, const std::wstring& oDefDir)
{
const RId rId = GetMaxRId().next();
AddNoWrite( rId, pFile, oDefDir );
return rId;
}
void IFileContainer::AddNoWrite (const OOX::RId& rId, const smart_ptr<OOX::File>& pFile, const std::wstring& oDefDir)
{
m_lMaxRid = (std::max)( m_lMaxRid, rId.getNumber() );
m_arContainer.push_back(pFile);
m_mapContainer [rId.get()] = pFile;
m_mNoWriteContainer[rId.get()] = oDefDir;
}
smart_ptr<OOX::File> IFileContainer::Find(const OOX::RId& rId) const
{
std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pPair = m_mapContainer.find(rId.get());
if ( pPair != m_mapContainer.end())
return pPair->second;
return smart_ptr<OOX::File>( (OOX::File*)new UnknowTypeFile(m_pMainDocument) );
}
smart_ptr<OOX::File> IFileContainer::Find(const FileType& oType) const
{
for (std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pPair = m_mapContainer.begin(); pPair != m_mapContainer.end(); ++pPair)
{
if (pPair->second->type() == oType)
return pPair->second;
}
return smart_ptr<OOX::File>( (OOX::File*)new UnknowTypeFile(m_pMainDocument) );
}
template<typename T>
T& IFileContainer::Find()
{
T oFile;
return dynamic_cast<T&>( Find( oFile.type() ) );
}
smart_ptr<OOX::File> IFileContainer::operator [](const OOX::RId rId)
{
std::map<std::wstring, smart_ptr<OOX::File>>::const_iterator pFind = m_mapContainer.find(rId.get());
if ( pFind != m_mapContainer.end())
return pFind->second;
return smart_ptr<OOX::File>( (OOX::File*)new UnknowTypeFile(m_pMainDocument) );
}
smart_ptr<OOX::File> IFileContainer::operator [](const FileType& oType)
{
return Find(oType);
}
const RId IFileContainer::GetMaxRId()
{
return RId( m_lMaxRid );
}
void IFileContainer::SetGlobalNumberByType(const std::wstring& sOverrideType, int val)
{
m_mapEnumeratedGlobal [sOverrideType] = val;
}
int IFileContainer::GetGlobalNumberByType(const std::wstring& sOverrideType)
{
boost::unordered_map<std::wstring, size_t>::const_iterator pNamePair = m_mapEnumeratedGlobal.find( sOverrideType );
int nRes = 0;
if(pNamePair != m_mapEnumeratedGlobal.end())
nRes = pNamePair->second;
return nRes;
}
} // namespace OOX