Files
core/RtfFile/Format/RtfOle.cpp
2026-04-02 08:10:57 +03:00

273 lines
8.7 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 "RtfOle.h"
#include "../OOXml/Writer/OOXWriter.h"
#include "../OOXml/Writer/OOXRelsWriter.h"
#include "RtfDocument.h"
#include "../../Common/OfficeFileFormatChecker.h"
RtfOle::RtfOle()
{
SetDefault();
}
RtfOle::~RtfOle()
{
SetDefault();
}
int RtfOle::GetType( )
{
return TYPE_RTF_OLE;
}
bool RtfOle::IsValid()
{
return PROP_DEF != m_nWidth && PROP_DEF != m_nHeight && L"" != m_sOleFilename;
/*&& ::GetFileAttributes( m_sOleFilename ) != DWORD( -1 )*/
}
std::wstring RtfOle::RenderToOOX(RenderParameter oRenderParameter)
{
if( false == IsValid() ) return L"";
std::wstring sResult;
RtfDocument* poRtfDocument = static_cast<RtfDocument*> (oRenderParameter.poDocument);
OOXWriter* poOOXWriter = static_cast<OOXWriter*> (oRenderParameter.poWriter);
if( RENDER_TO_OOX_PARAM_OLE_ONLY == oRenderParameter.nType )
{
sResult += RenderToOOXOnlyOle(oRenderParameter);
}
else
{
RtfCharProperty * pCharProps = &m_oCharProperty;
//------------------------------------------
// todooo common part with RtfChar
bool bInsert = false;
bool bDelete = false;
if (pCharProps->m_nRevised != PROP_DEF)
{
bInsert = true;
std::wstring sAuthor = poRtfDocument->m_oRevisionTable.GetAuthor(pCharProps->m_nRevauth);
std::wstring sDate(RtfUtility::convertDateTime(pCharProps->m_nRevdttm).c_str());
sResult += L"<w:ins w:date=\"" + sDate + L"\" w:author=\"" + XmlUtils::EncodeXmlString(sAuthor) + L"\" w:id=\"" + std::to_wstring(poOOXWriter->m_nCurTrackChangesId++).c_str() + L"\">";
pCharProps->m_nRevised = PROP_DEF;
}
if (pCharProps->m_nDeleted != PROP_DEF)
{
bDelete = true;
std::wstring sAuthor = poRtfDocument->m_oRevisionTable.GetAuthor(pCharProps->m_nRevauthDel);
std::wstring sDate(RtfUtility::convertDateTime(pCharProps->m_nRevdttmDel).c_str());
sResult += L"<w:del w:date=\"" + sDate + L"\" w:author=\"" + XmlUtils::EncodeXmlString(sAuthor) + L"\" w:id=\"" + std::to_wstring(poOOXWriter->m_nCurTrackChangesId++).c_str() + L"\">";
pCharProps->m_nDeleted = PROP_DEF;
}
//----------
sResult += L"<w:r>";
std::wstring sCharProp = pCharProps->RenderToOOX(oRenderParameter);
if (!sCharProp .empty())
{
sResult += L"<w:rPr>";
sResult += sCharProp;
sResult += L"</w:rPr>";
}
sResult += L"<w:object w:dxaOrig=\"" + std::to_wstring(m_nWidth) +
L"\" w:dyaOrig=\"" + std::to_wstring(m_nHeight) + L"\">";
RenderParameter oNewRenderParameter = oRenderParameter;
oNewRenderParameter.nType = RENDER_TO_OOX_PARAM_SHAPE_CHILD;
if (m_oResultShape)
{
m_oResultShape->m_bIsOle = true;
sResult += m_oResultShape->RenderToOOX(oNewRenderParameter);
oNewRenderParameter.nValue = m_oResultShape->m_nID;
}
sResult += RenderToOOXOnlyOle(oNewRenderParameter);
sResult += L"</w:object>";
sResult += L"</w:r>";
if (bDelete)sResult += L"</w:del>";
if (bInsert)sResult += L"</w:ins>";
}
return sResult;
}
std::wstring RtfOle::RenderToOOXOnlyOle(RenderParameter oRenderParameter)
{
std::wstring sResult;
OOXWriter * poOOXWriter = static_cast<OOXWriter*> (oRenderParameter.poWriter);
OOXRelsWriter * poRelsWriter = static_cast<OOXRelsWriter*> (oRenderParameter.poRels);
RtfDocument * poDocument = static_cast<RtfDocument*> (oRenderParameter.poDocument);
sResult += L"<o:OLEObject";
switch ( m_eOleType )
{
case ot_link: sResult += L" Type=\"Link\""; break;
default: sResult += L" Type=\"Embed\""; break;
}
sResult += L" ProgID=\"" + m_sOleClass + L"\"";
sResult += L" ShapeID=\"_x0000_s" + std::to_wstring(poDocument->GetShapeId( oRenderParameter.nValue )) + L"\"";
sResult += L" DrawAspect=\"Content\"";
sResult += L" ObjectID=\"" + poDocument->m_oIdGenerator.Generate_OleId() + L"\"";
std::wstring sExtension = L"bin";
std::wstring sMime = L"application/vnd.openxmlformats-officedocument.oleObject";
std::wstring sRelsType = L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
COfficeFileFormatChecker checker;
if (checker.isOfficeFile(m_sOleFilename))
{
switch (checker.nFileType)
{
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLS:
{
sExtension = L"xls";
sMime = L"application/vnd.ms-excel";
}break;
case AVS_OFFICESTUDIO_FILE_SPREADSHEET_XLSX:
{
sExtension = L"xlsx";
sMime = L"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
sRelsType = L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
}break;
case AVS_OFFICESTUDIO_FILE_DOCUMENT_DOC:
case AVS_OFFICESTUDIO_FILE_DOCUMENT_DOC_FLAT:
{
sExtension = L"doc";
sMime = L"application/msword";
}break;
case AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX:
{
sExtension = L"docx";
sMime = L"application/vnd.openxmlformats-officedocument.wordprocessingml.document";
sRelsType = L"http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
}break;
}
}
std::wstring sFilenameRels;
sFilenameRels += L"oleObject" + std::to_wstring(poDocument->m_oIdGenerator.Generate_OleIndex()) + L".";
sFilenameRels += sExtension;
std::wstring sFilenameFull = poOOXWriter->m_sTargetFolder + FILE_SEPARATOR_STR + L"word" + FILE_SEPARATOR_STR + L"embeddings";
NSDirectory::CreateDirectory( sFilenameFull );
sFilenameFull += FILE_SEPARATOR_STR + sFilenameRels;
sFilenameRels = L"embeddings/" + sFilenameRels;
Utils::CopyDirOrFile( m_sOleFilename, sFilenameFull );
poOOXWriter->m_oContentTypes.AddExtension( sMime, sExtension);
std::wstring srId = poRelsWriter->AddRelationship( sRelsType, sFilenameRels);
sResult += L" r:id=\"" + srId + L"\"";
sResult += L"/>";
return sResult;
}
std::wstring RtfOle::RenderToRtf(RenderParameter oRenderParameter)
{
if( !IsValid() ) return L"";
std::wstring sResult;
sResult += m_oCharProperty.RenderToRtf( oRenderParameter );
sResult += L"{\\object";
if( PROP_DEF != m_eOleType )
{
switch( m_eOleType )
{
case ot_emb: sResult += L"\\objemb"; break;
case ot_link: sResult += L"\\objlink"; break;
}
}
//sResult += L"\\f13";
sResult += L"\\objsetsize";
RENDER_RTF_INT( m_nWidth, sResult, L"objw" );
RENDER_RTF_INT( m_nHeight, sResult, L"objh" );
if( !m_sOleClass.empty() )
sResult += L"{\\*\\objclass " + m_sOleClass + L"}";
if( !m_sOleFilename.empty() )
{
std::wstring str = RtfUtility::RtfInternalEncoder::Encode( m_sOleFilename );
sResult += L"{\\*\\objdata " + str + L"}";
}
//-------------------------------------
if( NULL != m_oResultShape )
{
std::wstring str = m_oResultShape->RenderToRtf( oRenderParameter );
sResult += L"{\\result {\\pard\\plain" + str + L"}}";
}
//else if( NULL != m_oResultPicture )
//{
// std::wstring str = m_oResultPicture->RenderToRtf( oRenderParameter );
// sResult += L"{\\result {\\*\\shppict" + str + L"}}";
//}
sResult += L"}";
return sResult;
}
void RtfOle::SetFilename( std::wstring sFilename )
{
m_sOleFilename = sFilename;
}
void RtfOle::SetDefault()
{
m_eOleType = ot_none;
m_nShapeId = PROP_DEF;
m_nWidth = PROP_DEF;
m_nHeight = PROP_DEF;
Utils::RemoveDirOrFile( m_sOleFilename );
m_sOleFilename = L"";
m_oCharProperty.SetDefault();
}