Files
Yajbir Singh f1b860b25c
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++

/*
* (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