/* * (c) Copyright Ascensio System SIA 2010-2017 * * 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 Lubanas st. 125a-25, Riga, Latvia, * EU, LV-1021. * * 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 "BinaryFileReaderWriter.h" #include "BinReaderWriterDefines.h" #include "../../Common/DocxFormat/Source/Base/Nullable.h" #include "../../Common/DocxFormat/Source/DocxFormat/WritingElement.h" #include "../../Common/DocxFormat/Source/DocxFormat/Media/OleObject.h" #include "../../Common/Base64.h" #include "./imagemanager.h" #include "./XmlWriter.h" #include "./FontPicker.h" #include "../../ASCOfficeDocxFile2/DocWrapper/DocxSerializer.h" #include "../../DesktopEditor/common/File.h" #include "../PPTXFormat/FileContainer.h" #define BYTE_SIZEOF sizeof(BYTE) #define UINT16_SIZEOF sizeof(_UINT16) #define UINT32_SIZEOF sizeof(_UINT32) #define DOUBLE_SIZEOF sizeof(double) #define CHAR_SIZEOF sizeof(CHAR) #define INT16_SIZEOF sizeof(_INT16) #define INT32_SIZEOF sizeof(_INT32) #define INT64_SIZEOF sizeof(_INT64) #define DOUBLE_MAIN 10000 #if defined(_WIN32) || defined (_WIN64) #include "../../Common/DocxFormat/Source/Base/unicode_util.h" #endif namespace NSBinPptxRW { template inline unsigned arraysize(const T (&v)[S]) { return S; } CCommonWriter::CCommonWriter() { m_pNativePicker = NULL; m_pFontPicker = NULL; m_bDeleteFontPicker = true; m_pImageManager = new NSShapeImageGen::CImageManager(); } CCommonWriter::~CCommonWriter() { m_pNativePicker = NULL; if(m_bDeleteFontPicker) RELEASEOBJECT(m_pFontPicker); RELEASEOBJECT(m_pImageManager); } void CCommonWriter::CreateFontPicker(COfficeFontPicker* pPicker) { if(m_bDeleteFontPicker) RELEASEOBJECT(m_pFontPicker); m_pNativePicker = NULL; if (pPicker != NULL) { m_pFontPicker = pPicker; m_bDeleteFontPicker = false; } else { m_pFontPicker = new COfficeFontPicker(); m_bDeleteFontPicker = true; } m_pNativePicker = m_pFontPicker->GetNativePicker(); } void CCommonWriter::CheckFontPicker() { if (NULL == m_pFontPicker) CreateFontPicker(NULL); } CImageManager2::CImageManager2() : m_mapImages(), m_lIndexNextImage(0), m_lIndexNextOle(0) { m_nDocumentType = XMLWRITER_DOC_TYPE_PPTX; m_pContentTypes = new OOX::CContentTypes(); } CImageManager2::~CImageManager2() { delete m_pContentTypes; } void CImageManager2::Clear() { m_mapImages.clear(); m_lIndexNextImage = 1; m_lIndexNextOle = 1; } void CImageManager2::SetDstMedia(const std::wstring& strDst) { m_strDstMedia = strDst; } std::wstring CImageManager2::GetDstMedia() { return m_strDstMedia; } void CImageManager2::SetDstEmbed(const std::wstring& strDst) { m_strDstEmbed = strDst; } std::wstring CImageManager2::GetDstEmbed() { return m_strDstEmbed; } int CImageManager2::IsDisplayedImage(const std::wstring& strInput) { int nRes = 0; //шаблон display[N]image.ext std::wstring sFind1 = _T("display"); int nIndex1 = (int)strInput.find(sFind1); if(-1 != nIndex1) { if(nIndex1 + sFind1.length() < strInput.length()) { wchar_t cRes = strInput[nIndex1 + sFind1.length()]; if('1' <= cRes && cRes <= '6') { int nImageIndex = nIndex1 + (int)sFind1.length() + 1; if(nImageIndex == (int)strInput.find(_T("image"), nImageIndex)) nRes = cRes - '0'; } } } return nRes; } _imageManager2Info CImageManager2::GenerateImage(const std::wstring& strInput, NSCommon::smart_ptr & oleFile, const std::wstring& oleData, std::wstring strBase64Image) { if (IsNeedDownload(strInput)) return DownloadImage(strInput); std::map::const_iterator pPair = m_mapImages.find ((_T("") == strBase64Image) ? strInput : strBase64Image); if (pPair != m_mapImages.end()) return pPair->second; std::wstring strExts = _T(".jpg"); int nIndexExt = (int)strInput.rfind(wchar_t('.')); if (-1 != nIndexExt) strExts = strInput.substr(nIndexExt); std::wstring strOleBin; std::wstring strImage = strInput; int nDisplayType = IsDisplayedImage(strInput); if (0 != nDisplayType) { OOX::CPath oPath = strInput; std::wstring strFolder = oPath.GetDirectory(); std::wstring strFileName = oPath.GetFilename(); strFileName.erase(strFileName.length() - 4, 4); if(0 != (nDisplayType & 1)) { std::wstring strVector = strFolder + strFileName + _T(".wmf"); if (OOX::CSystemUtility::IsFileExist(strVector)) { strImage = strVector; strExts = _T(".wmf"); } } if(0 != (nDisplayType & 2)) { std::wstring strVector = strFolder + strFileName + L".emf"; if (OOX::CSystemUtility::IsFileExist(strVector)) { m_pContentTypes->AddDefault(L"emf"); strImage = strVector; strExts = L".emf"; } } if(0 != (nDisplayType & 4)) { if (oleFile.IsInit()) { if (OOX::CSystemUtility::IsFileExist(oleFile->filename()) == false) { std::wstring strOle = strFolder + strFileName + oleFile->filename().GetExtention(); if (OOX::CSystemUtility::IsFileExist(strOle)) { m_pContentTypes->AddDefault(oleFile->filename().GetExtention(false)); strOleBin = strOle; } else { strOle = strFolder + strFileName + L".bin"; if (OOX::CSystemUtility::IsFileExist(strOle)) strOleBin = strOle; } } } } } else if (!strExts.empty()) { m_pContentTypes->AddDefault(strExts.substr(1)); } _imageManager2Info oImageManagerInfo = GenerateImageExec(strImage, strExts, strOleBin, oleData); if (!oImageManagerInfo.sFilepathOle.empty()) oleFile->set_filename(oImageManagerInfo.sFilepathOle); if (strBase64Image.empty()) m_mapImages[strInput] = oImageManagerInfo; else m_mapImages [strBase64Image] = oImageManagerInfo; return oImageManagerInfo; } bool CImageManager2::WriteOleData(const std::wstring& sFilePath, const std::wstring& sData) { bool bRes = false; //EncodingMode.unparsed https://github.com/tonyqus/npoi/blob/master/main/POIFS/FileSystem/Ole10Native.cs POLE::Storage oStorage(sFilePath.c_str()); if(oStorage.open(true, true)) { //CompObj Stream BYTE dataCompObj[] = {0x01,0x00,0xfe,0xff,0x03,0x0a,0x00,0x00,0xff,0xff,0xff,0xff,0x0c,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x0c,0x00,0x00,0x00,0x4f,0x4c,0x45,0x20,0x50,0x61,0x63,0x6b,0x61,0x67,0x65,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x61,0x63,0x6b,0x61,0x67,0x65,0x00,0xf4,0x39,0xb2,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; POLE::Stream oStream1(&oStorage, "\001CompObj", true, arraysize(dataCompObj)); oStream1.write(dataCompObj, arraysize(dataCompObj)); oStream1.flush(); //ObjInfo Stream BYTE dataObjInfo[] = {0x00,0x00,0x03,0x00,0x0d,0x00}; POLE::Stream oStream2(&oStorage, "\003ObjInfo", true, arraysize(dataObjInfo)); oStream2.write(dataObjInfo, arraysize(dataObjInfo)); oStream2.flush(); //Ole10Native Stream std::string sDataUtf8 = NSFile::CUtf8Converter::GetUtf8StringFromUnicode2(sData.c_str(), sData.size()); BYTE head[] = {0x00,0x00,0x00,0x00}; //LittleEndian unsigned char* aData = (unsigned char*)sDataUtf8.c_str(); _UINT32 nDataSize = (_UINT32)sDataUtf8.size(); memcpy(head, &nDataSize, sizeof(_UINT32)); POLE::Stream oStream(&oStorage, "\001Ole10Native", true, arraysize(head) + nDataSize); oStream.write(head, arraysize(head)); oStream.write(aData, nDataSize); oStream.flush(); oStorage.close(); bRes = true; } return bRes; } _imageManager2Info CImageManager2::GenerateImageExec(const std::wstring& strInput, const std::wstring& sExts, const std::wstring& strOleImage, const std::wstring& oleData) { OOX::CPath oPathOutput; _imageManager2Info oImageManagerInfo; std::wstring strExts = sExts; std::wstring strImage = L"image" + std::to_wstring(++m_lIndexNextImage); if ((_T(".jpg") == strExts) || (_T(".jpeg") == strExts) || (_T(".png") == strExts) || (_T(".emf") == strExts) || (_T(".wmf") == strExts)) { oPathOutput = m_strDstMedia + FILE_SEPARATOR_STR + strImage + strExts; if (oPathOutput.GetPath() != strInput) CDirectory::CopyFile(strInput, oPathOutput.GetPath()); } else { // content types!!! strExts = _T(".png"); oPathOutput = m_strDstMedia + FILE_SEPARATOR_STR + strImage + strExts; SaveImageAsPng(strInput, oPathOutput.GetPath()); } oImageManagerInfo.sFilepathImage = oPathOutput.GetPath(); if (!strOleImage.empty() || !oleData.empty() ) { std::wstring strExtsOle = L".bin"; int pos = (int)strOleImage.rfind(L"."); if (pos >= 0) strExtsOle = strOleImage.substr(pos); std::wstring strImageOle = L"oleObject" + std::to_wstring(++m_lIndexNextOle) + strExtsOle; OOX::CPath pathOutputOle = m_strDstEmbed + FILE_SEPARATOR_STR + strImageOle; std::wstring strOleImageOut = pathOutputOle.GetPath(); if(!oleData.empty()) { WriteOleData(strOleImageOut, oleData); } else { CDirectory::CopyFile(strOleImage, strOleImageOut); } oImageManagerInfo.sFilepathOle = strOleImageOut; } return oImageManagerInfo; } void CImageManager2::SaveImageAsPng(const std::wstring& strFileSrc, const std::wstring& strFileDst) { CBgraFrame oBgraFrame; if(oBgraFrame.OpenFile(strFileSrc)) oBgraFrame.SaveFile(strFileDst, _CXIMAGE_FORMAT_PNG); } void CImageManager2::SaveImageAsJPG(const std::wstring& strFileSrc, const std::wstring& strFileDst) { CBgraFrame oBgraFrame; if(oBgraFrame.OpenFile(strFileSrc)) oBgraFrame.SaveFile(strFileDst, _CXIMAGE_FORMAT_JPG); } bool CImageManager2::IsNeedDownload(const std::wstring& strFile) { size_t n1 = strFile.find(_T("www")); size_t n2 = strFile.find(_T("http")); size_t n3 = strFile.find(_T("ftp")); size_t n4 = strFile.find(_T("https://")); //если nI сранивать не с 0, то будут проблемы //потому что в инсталяции мы кладем файлы в /var/www... if (0 == n1 || 0 == n2 || 0 == n3 || 0 == n4) return true; return false; } _imageManager2Info CImageManager2::DownloadImage(const std::wstring& strUrl) { std::map::const_iterator pPair = m_mapImages.find (strUrl); if (pPair != m_mapImages.end()) return pPair->second; std::wstring strExts = _T(".jpg"); int nIndexExt = (int)strUrl.rfind(wchar_t('.')); if (-1 != nIndexExt) strExts = strUrl.substr(nIndexExt); std::wstring strImage; std::wstring strOleImage; int nDisplayType = IsDisplayedImage(strUrl); if(0 != nDisplayType) { std::wstring strInputMetafile = strUrl.substr(0, strUrl.length() - strExts.length()); std::wstring sDownloadRes; //todo if(0 != (nDisplayType & 4)) { strOleImage = DownloadImageExec(strInputMetafile + _T(".bin")); } if(0 != (nDisplayType & 1)) { strImage = DownloadImageExec(strInputMetafile + _T(".wmf")); strExts = _T(".wmf"); } else if(0 != (nDisplayType & 2)) { strImage = DownloadImageExec(strInputMetafile + _T(".emf")); strExts = _T(".emf"); } else { strImage = DownloadImageExec(strUrl); } } else { strImage = DownloadImageExec(strUrl); } if (!strExts.empty()) { m_pContentTypes->AddDefault(strExts.substr(1)); } _imageManager2Info oImageManagerInfo; if (!strImage.empty()) { oImageManagerInfo = GenerateImageExec(strImage, strExts, strOleImage, L""); CDirectory::DeleteFile(strImage); } if (!strOleImage.empty()) CDirectory::DeleteFile(strOleImage); m_mapImages[strUrl] = oImageManagerInfo; return oImageManagerInfo; } std::wstring CImageManager2::DownloadImageExec(const std::wstring& strFile) { #ifndef DISABLE_FILE_DOWNLOADER CFileDownloader oDownloader(strFile, false); if ( oDownloader.DownloadSync() ) { return oDownloader.GetFilePath(); } #endif return _T(""); } CBinaryFileWriter::CSeekTableEntry::CSeekTableEntry() { Type = 0; SeekPos = 0; } BYTE* CBinaryFileWriter::GetBuffer() { return m_pStreamData; } _UINT32 CBinaryFileWriter::GetPosition() { return m_lPosition; } void CBinaryFileWriter::SetPosition(const _UINT32& lPosition) { m_lPosition = lPosition; m_pStreamCur = m_pStreamData + m_lPosition; } void CBinaryFileWriter::Skip(const _UINT32& lSize) { CheckBufferSize(lSize); m_lPosition += lSize; m_pStreamCur = m_pStreamData + m_lPosition; } double CBinaryFileWriter::GetShapeHeight() { if (m_lCyCurShape == 0) return -1; return (double)m_lCyCurShape / 36000; //mm } double CBinaryFileWriter::GetShapeWidth() { if (m_lCyCurShape == 0) return -1; return (double)m_lCxCurShape / 36000; } double CBinaryFileWriter::GetShapeY() { return (double)m_lYCurShape / 36000; } double CBinaryFileWriter::GetShapeX() { return (double)m_lXCurShape / 36000; //mm } void CBinaryFileWriter::ClearCurShapePositionAndSizes() { m_lXCurShape = 0; m_lYCurShape = 0; m_lCxCurShape = 0; m_lCyCurShape = 0; } void CBinaryFileWriter::Clear() { m_lSize = 0; m_lPosition = 0; m_pStreamData = NULL; m_pStreamCur = NULL; m_lStackPosition = 0; memset(m_arStack, 0, MAX_STACK_SIZE * sizeof(_UINT32)); m_lCxCurShape = 0; m_lCyCurShape = 0; m_lXCurShape = 0; m_lYCurShape = 0; } void CBinaryFileWriter::SetMainDocument(BinDocxRW::CDocxSerializer* pMainDoc) { m_pMainDocument = pMainDoc; } void CBinaryFileWriter::ClearNoAttack() { m_lPosition = 0; m_pStreamCur = m_pStreamData; m_lStackPosition = 0; memset(m_arStack, 0, MAX_STACK_SIZE * sizeof(_UINT32)); } void CBinaryFileWriter::CheckBufferSize(_UINT32 lPlus) { if (NULL != m_pStreamData) { size_t nNewSize = m_lPosition + lPlus; if (nNewSize >= m_lSize) { while (nNewSize >= m_lSize) { m_lSize *= 2; } BYTE* pNew = new BYTE[m_lSize]; memcpy(pNew, m_pStreamData, m_lPosition); RELEASEARRAYOBJECTS(m_pStreamData); m_pStreamData = pNew; m_pStreamCur = m_pStreamData + m_lPosition; } } else { m_lSize = 1024 * 1024; // 1Mb m_pStreamData = new BYTE[m_lSize]; m_lPosition = 0; m_pStreamCur = m_pStreamData; CheckBufferSize(lPlus); } } void CBinaryFileWriter::WriteBYTE(const BYTE& lValue) { CheckBufferSize(BYTE_SIZEOF); *m_pStreamCur = lValue; m_lPosition += BYTE_SIZEOF; m_pStreamCur += BYTE_SIZEOF; } void CBinaryFileWriter::WriteSBYTE(const signed char& lValue) { CheckBufferSize(BYTE_SIZEOF); if (lValue < 0) *m_pStreamCur = (lValue + 256); else *m_pStreamCur = lValue; m_lPosition += BYTE_SIZEOF; m_pStreamCur += BYTE_SIZEOF; } void CBinaryFileWriter::WriteBOOL(const bool& bValue) { WriteBYTE((bValue == true) ? 1 : 0); } void CBinaryFileWriter::WriteUSHORT(const _UINT16& lValue) { CheckBufferSize(UINT16_SIZEOF); #ifdef _IOS memcpy(m_pStreamCur, &lValue, sizeof(_UINT16)); #else *((_UINT16*)m_pStreamCur) = lValue; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += UINT16_SIZEOF; m_pStreamCur += UINT16_SIZEOF; } void CBinaryFileWriter::WriteULONG(const _UINT32& lValue) { CheckBufferSize(UINT32_SIZEOF); #ifdef _IOS memcpy(m_pStreamCur, &lValue, sizeof(_UINT32)); #else *((_UINT32*)m_pStreamCur) = lValue; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += UINT32_SIZEOF; m_pStreamCur += UINT32_SIZEOF; } void CBinaryFileWriter::WriteLONG(const _INT32& lValue) { CheckBufferSize(INT32_SIZEOF); #ifdef _IOS memcpy(m_pStreamCur, &lValue, sizeof(_INT32)); #else *((_INT32*)m_pStreamCur) = lValue; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += INT32_SIZEOF; m_pStreamCur += INT32_SIZEOF; } void CBinaryFileWriter::WriteLONG64(const _INT64& lValue) { CheckBufferSize(INT64_SIZEOF); #ifdef _IOS memcpy(m_pStreamCur, &lValue, sizeof(_INT64)); #else *((_INT64*)m_pStreamCur) = lValue; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += INT64_SIZEOF; m_pStreamCur += INT64_SIZEOF; } void CBinaryFileWriter::WriteINT(const _INT32& lValue) { CheckBufferSize(INT32_SIZEOF); #ifdef _IOS memcpy(m_pStreamCur, &lValue, sizeof(_INT32)); #else *((_INT32*)m_pStreamCur) = lValue; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += INT32_SIZEOF; m_pStreamCur += INT32_SIZEOF; } void CBinaryFileWriter::WriteDouble64(const double& dValue) { _INT64 _val = (_INT64)(dValue * 100000); WriteLONG64(_val); } void CBinaryFileWriter::WriteDouble(const double& dValue) { _INT64 _val = (_INT64)(dValue * 100000); if (_val > 0x7fffffff) { WriteLONG(0x7fffffff); } else if ( _val < -0x7fffffff) { WriteLONG(-0x7fffffff); } else { WriteLONG((long)_val); } } void CBinaryFileWriter::WriteDoubleReal(const double& dValue) { CheckBufferSize(DOUBLE_SIZEOF); #ifdef _IOS memcpy(m_pStreamCur, &dValue, sizeof(double)); #else *((double*)m_pStreamCur) = dValue; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += DOUBLE_SIZEOF; m_pStreamCur += DOUBLE_SIZEOF; } void CBinaryFileWriter::WriteBYTEArray(const BYTE* pBuffer, size_t len) { CheckBufferSize((_UINT32)len); memcpy(m_pStreamCur, pBuffer, len); m_lPosition += (_UINT32)len; m_pStreamCur += len; } void CBinaryFileWriter::WriteStringA(std::string& sBuffer) { _UINT32 lSize = (_UINT32)sBuffer.length(); _UINT32 lSizeMem = lSize * sizeof(char); CheckBufferSize(UINT32_SIZEOF + lSizeMem); #ifdef _IOS memcpy(m_pStreamCur, &lSizeMem, sizeof(_UINT32)); #else *((_UINT32*)m_pStreamCur) = lSizeMem; // EXC_ARM_DA_ALIGN on ios #endif m_lPosition += UINT32_SIZEOF; m_pStreamCur += UINT32_SIZEOF; memcpy(m_pStreamCur, sBuffer.c_str(), lSizeMem); m_lPosition += lSizeMem; m_pStreamCur += lSizeMem; } void CBinaryFileWriter::WriteStringW(std::wstring& sBuffer) { _WriteStringWithLength(sBuffer.c_str(), (_UINT32)sBuffer.length(), true); } void CBinaryFileWriter::WriteStringW(const std::wstring& sBuffer) { _WriteStringWithLength(sBuffer.c_str(), (_UINT32)sBuffer.length(), true); } void CBinaryFileWriter::WriteStringW2(std::wstring& sBuffer) { _WriteStringWithLength(sBuffer.c_str(), (_UINT32)sBuffer.length(), false); } void CBinaryFileWriter::WriteStringW3(std::wstring& sBuffer) { _WriteString(sBuffer.c_str(), (_UINT32)sBuffer.length()); } void CBinaryFileWriter::WriteStringW3(const std::wstring& sBuffer) { _WriteString(sBuffer.c_str(), (_UINT32)sBuffer.length()); } void CBinaryFileWriter::WriteStringW4(const std::wstring& sBuffer) { _WriteString(sBuffer.c_str(), (_UINT32)sBuffer.length()); } CBinaryFileWriter::CBinaryFileWriter() { m_pMainDocument = NULL; m_pCommon = new CCommonWriter(); //m_pCommonRels = new NSCommon::smart_ptr(); m_pCurrentContainer = new NSCommon::smart_ptr(); m_pTheme = new NSCommon::smart_ptr(); m_pClrMap = new NSCommon::smart_ptr(); Clear(); } CBinaryFileWriter::~CBinaryFileWriter() { RELEASEARRAYOBJECTS (m_pStreamData); RELEASEOBJECT (m_pCommon); //RELEASEOBJECT (m_pCommonRels); RELEASEOBJECT (m_pCurrentContainer); RELEASEOBJECT (m_pTheme); RELEASEOBJECT (m_pClrMap); } void CBinaryFileWriter::StartRecord(_INT32 lType) { m_arStack[m_lStackPosition] = m_lPosition + 5; // sizeof(BYTE) + sizeof(_UINT32) m_lStackPosition++; WriteBYTE((BYTE)lType); WriteULONG(0); } void CBinaryFileWriter::EndRecord() { m_lStackPosition--; _UINT32 size_record = m_lPosition - m_arStack[m_lStackPosition]; (*(_UINT32*)(m_pStreamData + m_arStack[m_lStackPosition] - 4)) = size_record ; } void CBinaryFileWriter::StartMainRecord(_INT32 lType) { CSeekTableEntry oEntry; oEntry.Type = lType; oEntry.SeekPos = m_lPosition; m_arMainTables.push_back(oEntry); //StartRecord(lType); } void CBinaryFileWriter::WriteReserved(size_t lCount) { CheckBufferSize((_UINT32)lCount); memset(m_pStreamCur, 0, lCount); m_pStreamCur += lCount; m_lPosition += (_UINT32)lCount; } void CBinaryFileWriter::WriteMainPart() { BYTE* pData = m_pStreamData; size_t nCount = m_arMainTables.size(); for (size_t i = 0; i < nCount; i++) { *pData = (BYTE)m_arMainTables[i].Type; ++pData; #ifdef _IOS memcpy(pData, &m_arMainTables[i].SeekPos, sizeof(_INT32)); #else *((_INT32*)pData) = m_arMainTables[i].SeekPos; // EXC_ARM_DA_ALIGN on ios #endif pData += 4; } } void CBinaryFileWriter::WriteString1(int type, const std::wstring& val) { BYTE bType = (BYTE)type; WriteBYTE(bType); std::wstring* s = const_cast(&val); _WriteStringWithLength(s->c_str(), (_UINT32)s->length(), false); } void CBinaryFileWriter::WriteString2(int type, const NSCommon::nullable_string& val) { if (val.is_init()) WriteString1(type, *val); } void CBinaryFileWriter::WriteString(const std::wstring& val) { std::wstring* s = const_cast(&val); _WriteStringWithLength(s->c_str(), (_UINT32)s->length(), false); } void CBinaryFileWriter::WriteString1Data(int type, const WCHAR* pData, _UINT32 len) { BYTE bType = (BYTE)type; WriteBYTE(bType); _WriteStringWithLength(pData, len, false); } void CBinaryFileWriter::WriteBool1(int type, const bool& val) { BYTE bType = (BYTE)type; WriteBYTE(bType); WriteBYTE((val == true) ? 1 : 0); } void CBinaryFileWriter::WriteBool2(int type, const NSCommon::nullable_bool& val) { if (val.is_init()) WriteBool1(type, *val); } void CBinaryFileWriter::WriteInt1(int type, const int& val) { BYTE bType = (BYTE)type; WriteBYTE(bType); WriteINT(val); } void CBinaryFileWriter::WriteInt2(int type, const NSCommon::nullable_int& val) { if (val.is_init()) WriteInt1(type, *val); } void CBinaryFileWriter::WriteDouble1(int type, const double& val) { int _val = (int)(val * 10000); WriteInt1(type, _val); } void CBinaryFileWriter::WriteDouble2(int type, const NSCommon::nullable_double& val) { if (val.is_init()) WriteDouble1(type, *val); } void CBinaryFileWriter::WriteSize_t1(int type, const size_t& val) { BYTE bType = (BYTE)type; WriteBYTE(bType); _UINT32 ival = (_UINT32)val; WriteULONG(ival); } void CBinaryFileWriter::WriteSize_t2(int type, const NSCommon::nullable_sizet& val) { if (val.is_init()) WriteSize_t1(type, *val); } void CBinaryFileWriter::GetBase64File(const std::wstring& sFile, std::string& strDst64) { CFile oFile; HRESULT hr = oFile.OpenFile(sFile); if (S_OK != hr) { strDst64 = ""; return; } DWORD dwLen = (DWORD)oFile.GetFileSize(); BYTE* pBuffer = new BYTE[dwLen]; oFile.SetPosition(0); oFile.ReadFile(pBuffer, dwLen); int nBase64BufferLen = Base64::Base64EncodeGetRequiredLength((int)dwLen, Base64::B64_BASE64_FLAG_NOCRLF); BYTE *pbBase64Buffer = new BYTE[nBase64BufferLen + 1 + 64]; pbBase64Buffer[nBase64BufferLen] = '\0'; //if (true == Base64::Base64Encode(pBuffer, (int)dwLen, pbBase64Buffer, &nBase64BufferLen, Base64::B64_BASE64_FLAG_NOCRLF)) if (true == Base64_1::Base64Encode(pBuffer, (int)dwLen, pbBase64Buffer, &nBase64BufferLen)) { //strDst64.SetString(pbBase64Buffer, nBase64BufferLen); strDst64 = (char*)pbBase64Buffer; } RELEASEARRAYOBJECTS(pbBase64Buffer); RELEASEARRAYOBJECTS(pBuffer); oFile.CloseFile(); //DeleteFile(sFile); } void CBinaryFileWriter::WriteTheme64(_INT32 lIndex, const std::wstring& sFile) { GetBase64File(sFile, m_pCommon->m_oRels[lIndex].m_strImageBase64); } void CBinaryFileWriter::WriteLayoutTheme64(_INT32 lIndexTheme, _INT32 lIndexLayout, const std::wstring& sFile) { GetBase64File(sFile, m_pCommon->m_oRels[lIndexTheme].m_arLayoutImagesBase64[lIndexLayout]); } std::wstring CBinaryFileWriter::GetFolderForGenerateImages() { return m_strMainFolder + _T("\\extract_themes"); } // embedded fonts void CBinaryFileWriter::WriteEmbeddedFonts() { if (NULL == m_pCommon->m_pNativePicker) return; if (!m_pCommon->m_pNativePicker->m_bIsEmbeddedFonts) return; StartMainRecord(NSBinPptxRW::NSMainTables::FontsEmbedded); // добавим мега шрифт m_pCommon->m_pNativePicker->m_oEmbeddedFonts.CheckString(_T(".)abcdefghijklmnopqrstuvwxyz")); m_pCommon->m_pNativePicker->m_oEmbeddedFonts.CheckFont(_T("Wingdings 3"), m_pCommon->m_pNativePicker->m_pFontManager); m_pCommon->m_pNativePicker->m_oEmbeddedFonts.CheckFont(_T("Arial"), m_pCommon->m_pNativePicker->m_pFontManager); StartRecord(NSBinPptxRW::NSMainTables::FontsEmbedded); m_pCommon->m_pNativePicker->m_oEmbeddedFonts.WriteEmbeddedFonts(this); EndRecord(); } bool CBinaryFileWriter::GetSafearray(BYTE **ppArray, size_t& szCount) { if (NULL == ppArray) return false; _UINT32 lBinarySize = this->GetPosition(); if (0 == lBinarySize) return false; *ppArray = new BYTE [lBinarySize]; szCount = lBinarySize; memcpy(*ppArray, this->GetBuffer(), lBinarySize); return true; } _INT32 CBinaryFileWriter::_WriteString(const WCHAR* sBuffer, _UINT32 lCount) { _INT32 lSizeMem = 0; if (sizeof(wchar_t) == 4) { _INT32 lSizeMemMax = 4 * lCount + 2;//2 - for null terminator CheckBufferSize(lSizeMemMax); NSFile::CUtf8Converter::GetUtf16StringFromUnicode_4bytes(sBuffer, lCount, m_pStreamCur, lSizeMem); } else { lSizeMem = 2 * lCount; CheckBufferSize(lSizeMem); memcpy(m_pStreamCur, sBuffer, lSizeMem); } m_lPosition += lSizeMem; m_pStreamCur += lSizeMem; return lSizeMem; } void CBinaryFileWriter::_WriteStringWithLength(const WCHAR* sBuffer, _UINT32 lCount, bool bByte) { CheckBufferSize(UINT32_SIZEOF); //skip size m_lPosition += UINT32_SIZEOF; m_pStreamCur += UINT32_SIZEOF; //write string _INT32 lSizeMem = _WriteString(sBuffer, lCount); //back to size m_lPosition -= lSizeMem; m_pStreamCur -= lSizeMem; m_lPosition -= UINT32_SIZEOF; m_pStreamCur -= UINT32_SIZEOF; //write size if (bByte) { //byte WriteLONG(lSizeMem); } else { //length WriteLONG(lSizeMem / 2); } //skip string m_lPosition += lSizeMem; m_pStreamCur += lSizeMem; } CRelsGenerator::CRelsGenerator(CImageManager2* pManager) : m_lNextRelsID(1), m_mapImages() { m_pManager = pManager; m_pWriter = new CStringWriter(); } CRelsGenerator::~CRelsGenerator() { RELEASEOBJECT(m_pWriter); } void CRelsGenerator::Clear() { m_pWriter->ClearNoAttack(); m_lNextRelsID = 1; m_mapImages.clear(); m_mapLinks.clear(); } void CRelsGenerator::StartRels() { m_pWriter->WriteString(_T("")); m_pWriter->WriteString(_T("")); } void CRelsGenerator::StartTheme() { m_pWriter->WriteString(_T("")); m_pWriter->WriteString(_T("")); } void CRelsGenerator::StartMaster(int nIndexTheme, const _slideMasterInfo& oInfo) { m_pWriter->WriteString(_T("")); m_pWriter->WriteString(_T("")); int nCountLayouts = (int)oInfo.m_arLayouts.size(); for (int i = 0; i < nCountLayouts; ++i) { std::wstring str = L""; m_pWriter->WriteString(str); } std::wstring s = L""; m_pWriter->WriteString(s); } void CRelsGenerator::StartLayout(int nIndexTheme) { m_pWriter->WriteString(_T("")); m_pWriter->WriteString(_T("")); std::wstring str = L""; m_pWriter->WriteString(str); } void CRelsGenerator::StartSlide(int nIndexSlide, int nIndexLayout) { m_pWriter->WriteString(_T("")); m_pWriter->WriteString(_T("")); std::wstring str = L""; m_pWriter->WriteString(str); str = L""; m_pWriter->WriteString(str); } void CRelsGenerator::StartNote(int nIndexSlide) { m_pWriter->WriteString(L""); m_pWriter->WriteString(L""); std::wstring sNum = std::to_wstring(nIndexSlide + 1); std::wstring strNoteSlideRels = L""; m_pWriter->WriteString(strNoteSlideRels); m_pWriter->WriteString(L""); m_lNextRelsID = 3; } void CRelsGenerator::WriteMasters(int nCount) { for (int i = 0; i < nCount; ++i) { std::wstring strRels = L""; m_pWriter->WriteString(strRels); } } void CRelsGenerator::WriteThemes(int nCount) { for (int i = 0; i < nCount; ++i) { std::wstring strRels = L""; m_pWriter->WriteString(strRels); } } void CRelsGenerator::WriteSlides(int nCount) { for (int i = 0; i < nCount; ++i) { std::wstring strRels = L""; m_pWriter->WriteString(strRels); } } void CRelsGenerator::WriteSlideComments(int nComment) { std::wstring strRels = L""; m_pWriter->WriteString(strRels); } void CRelsGenerator::EndPresentationRels(const bool& bIsCommentsAuthors = false) { std::wstring strRels0 = L""; std::wstring strRels1 = L""; std::wstring strRels2 = L""; std::wstring strRels3 = L""; m_pWriter->WriteString(strRels0); m_pWriter->WriteString(strRels1); m_pWriter->WriteString(strRels2); m_pWriter->WriteString(strRels3); if (bIsCommentsAuthors) { std::wstring strRels4 = L""; m_pWriter->WriteString(strRels4); } } int CRelsGenerator::GetNextId() { return m_lNextRelsID; } void CRelsGenerator::CloseRels() { m_pWriter->WriteString(_T("")); } void CRelsGenerator::AddRels(const std::wstring& strRels) { m_pWriter->WriteString(strRels); } void CRelsGenerator::SaveRels(const std::wstring& strFile) { CFile oFile; oFile.CreateFile(strFile); std::wstring strMem = m_pWriter->GetData(); oFile.WriteStringUTF8(strMem); oFile.CloseFile(); } _relsGeneratorInfo CRelsGenerator::WriteImage(const std::wstring& strImage, smart_ptr & oleFile, const std::wstring& oleData, std::wstring strBase64Image = _T("")) { _imageManager2Info oImageManagerInfo = m_pManager->GenerateImage(strImage, oleFile, oleData, strBase64Image); std::wstring strImageRelsPath; if (m_pManager->m_nDocumentType == XMLWRITER_DOC_TYPE_DOCX) strImageRelsPath = L"media/"; else strImageRelsPath = L"../media/"; strImageRelsPath += OOX::CPath(oImageManagerInfo.sFilepathImage).GetFilename(); std::map::iterator pPair = m_mapImages.find(strImageRelsPath); if (m_mapImages.end() != pPair) { return pPair->second; } _relsGeneratorInfo oRelsGeneratorInfo; oRelsGeneratorInfo.nImageRId = m_lNextRelsID++; oRelsGeneratorInfo.sFilepathImage = oImageManagerInfo.sFilepathImage; std::wstring strRid = L"rId" + std::to_wstring(oRelsGeneratorInfo.nImageRId); m_pWriter->WriteString( L""); if( oleFile.IsInit() ) { std::wstring strOleRelsPath; oRelsGeneratorInfo.nOleRId = m_lNextRelsID++; oRelsGeneratorInfo.sFilepathOle = oleFile->filename().GetPath(); if (m_pManager->m_nDocumentType != XMLWRITER_DOC_TYPE_XLSX) { std::wstring strRid = L"rId" + std::to_wstring(oRelsGeneratorInfo.nOleRId); if (m_pManager->m_nDocumentType == XMLWRITER_DOC_TYPE_DOCX) strOleRelsPath = L"embeddings/"; else strOleRelsPath = L"../embeddings/"; strOleRelsPath += oleFile->filename().GetFilename(); if (oleFile->isMsPackage()) { m_pWriter->WriteString( L""); }else{ m_pWriter->WriteString( L""); } } } m_mapImages.insert(std::pair(strImageRelsPath, oRelsGeneratorInfo)); return oRelsGeneratorInfo; } int CRelsGenerator::WriteChart(int nChartNumber, _INT32 lDocType = XMLWRITER_DOC_TYPE_PPTX) { std::wstring strChart = L"charts/chart" + std::to_wstring(nChartNumber) + L".xml"; if (lDocType != XMLWRITER_DOC_TYPE_DOCX) { strChart = L"../" + strChart; } std::wstring strRid = L"rId" + std::to_wstring(m_lNextRelsID++); std::wstring strRels = L""; m_pWriter->WriteString(strRels); return m_lNextRelsID - 1; } int CRelsGenerator::WriteRels(const std::wstring& bsType, const std::wstring& bsTarget, const std::wstring& bsTargetMode) { std::wstring strRid = L"rId" + std::to_wstring(m_lNextRelsID++); std::wstring strType = _T("Type=\"") + bsType + _T("\" "); std::wstring strTarget = _T("Target=\"") + bsTarget + _T("\" "); std::wstring strTargetMode = bsTargetMode.empty() ? _T("") : (_T("TargetMode=\"") + bsTargetMode + _T("\"")); std::wstring strRels = _T(""); m_pWriter->WriteString(strRels); return m_lNextRelsID - 1; } int CRelsGenerator::WriteHyperlink(const std::wstring& strLink, const bool& bIsActionInit) { std::map::iterator pPair = m_mapLinks.find(strLink); if (m_mapLinks.end() != pPair) { return pPair->second; } m_mapLinks.insert(std::pair(strLink, m_lNextRelsID)); std::wstring strRid = L"rId" + std::to_wstring(m_lNextRelsID++); std::wstring sLink = XmlUtils::EncodeXmlString(strLink); bool bIsSlide = (0 == sLink.find(_T("slide"))); if (!bIsActionInit) bIsSlide = false; std::wstring strRels; if (!bIsSlide) { strRels = L""; } else { strRels = L""; } m_pWriter->WriteString(strRels); return m_lNextRelsID - 1; } CBinaryFileReader::CBinaryFileReader() { m_pMainDocument = NULL; m_lNextId = 0; m_lChartNumber = 1; m_nDocumentType = XMLWRITER_DOC_TYPE_PPTX; m_pRels = new CRelsGenerator(); m_nCurrentRelsStack = -1; } CBinaryFileReader::~CBinaryFileReader() { RELEASEOBJECT(m_pRels); size_t nCountStackRels = m_stackRels.size(); for (size_t i = 0; i < nCountStackRels; ++i) { CRelsGenerator* pCur = m_stackRels[i]; RELEASEOBJECT(pCur); } m_stackRels.clear(); } void CBinaryFileReader::SetMainDocument(BinDocxRW::CDocxSerializer* pMainDoc) { m_pMainDocument = pMainDoc; } void CBinaryFileReader::Init(BYTE* pData, _INT32 lStart, _INT32 lSize) { m_pData = pData; m_lSize = lSize + lStart; m_lPos = lStart; m_pDataCur = m_pData + m_lPos; } _INT32 CBinaryFileReader::GenerateNextId() { ++m_lNextId; return m_lNextId; } int CBinaryFileReader::Seek(LONG _pos) { if (_pos > m_lSize) return 1; m_lPos = _pos; m_pDataCur = m_pData + m_lPos; return 0; } int CBinaryFileReader::Skip(LONG _skip) { if (_skip < 0) return 1; return Seek(m_lPos + _skip); } bool CBinaryFileReader::Peek(LONG nSizeToRead = 0) { return !(m_lPos + nSizeToRead > m_lSize); } // 1 bytes BYTE CBinaryFileReader::GetUChar() { if (m_lPos >= m_lSize) return 0; BYTE res = *m_pDataCur; ++m_lPos; ++m_pDataCur; return res; } signed char CBinaryFileReader::GetChar() { if (m_lPos >= m_lSize) return 0; BYTE res = *m_pDataCur; if (res > 127) res -= 256; ++m_lPos; ++m_pDataCur; return res; } // 1 bytes BYTE CBinaryFileReader::GetUChar_TypeNode() { if (m_lPos >= m_lSize) return NSBinPptxRW::g_nodeAttributeEnd; BYTE res = *m_pDataCur; ++m_lPos; ++m_pDataCur; return res; } bool CBinaryFileReader::GetBool() { int res = GetUChar(); return (res == 1) ? true : false; } // 2 byte _UINT16 CBinaryFileReader::GetUShort() { if (m_lPos + 1 >= m_lSize) return 0; #ifdef _IOS _UINT16 res = 0; memcpy(&res, m_pDataCur, sizeof(_UINT16)); #else _UINT16 res = *((_UINT16*)m_pDataCur); // EXC_ARM_DA_ALIGN on ios #endif m_lPos += 2; m_pDataCur += 2; return res; } // 4 byte _UINT32 CBinaryFileReader::GetULong() { if (m_lPos + 3 >= m_lSize) return 0; #ifdef _IOS _UINT32 res = 0; memcpy(&res, m_pDataCur, sizeof(_UINT32)); #else _UINT32 res = *((_UINT32*)m_pDataCur); // EXC_ARM_DA_ALIGN on ios #endif m_lPos += 4; m_pDataCur += 4; return res; } _INT64 CBinaryFileReader::GetLong64() { if (m_lPos + 7 >= m_lSize) return 0; #ifdef _IOS _INT64 res = 0; memcpy(&res, m_pDataCur, sizeof(_INT64)); #else _INT64 res = *((_INT64*)m_pDataCur); // EXC_ARM_DA_ALIGN on ios #endif m_lPos += 8; m_pDataCur += 8; return res; } _INT32 CBinaryFileReader::GetLong() { return (_INT32)GetULong(); } double CBinaryFileReader::GetDouble() { return 1.0 * GetLong() / 100000; } double CBinaryFileReader::GetDouble64() { return 1.0 * GetLong64() / 100000; } // 8 byte double CBinaryFileReader::GetDoubleReal() { if (m_lPos + (int)DOUBLE_SIZEOF > m_lSize) return 0; #ifdef _IOS double res = 0.0; memcpy(&res, m_pDataCur, sizeof(double)); #else double res = *((double*)m_pDataCur); // EXC_ARM_DA_ALIGN on ios #endif m_lPos += DOUBLE_SIZEOF; m_pDataCur += DOUBLE_SIZEOF; return res; } //String std::wstring CBinaryFileReader::GetString(_INT32 len) { len *= 2; return GetString3(len); } std::string CBinaryFileReader::GetString1(_INT32 len) { if (len < 1 ) return ""; if (m_lPos + len > m_lSize) return ""; std::string res((CHAR*)m_pDataCur, len); m_lPos += len; m_pDataCur += len; return res; } std::wstring CBinaryFileReader::GetString2() { _INT32 len = GetLong(); return GetString(len); } std::wstring CBinaryFileReader::GetString3(_INT32 len)//len in byte for utf16 { if (len < 1 ) return _T(""); if (m_lPos + len > m_lSize) return _T(""); _UINT32 lSize = len >>1; //string in char if (sizeof(wchar_t) == 4) { std::wstring val = NSFile::CUtf8Converter::GetWStringFromUTF16((unsigned short*)m_pDataCur, lSize); std::wstring res(val.c_str(), val.length()); m_lPos += len; m_pDataCur += len; return res; } else { std::wstring res((WCHAR*)m_pDataCur, lSize); m_lPos += len; m_pDataCur += len; return res; } } std::wstring CBinaryFileReader::GetString4(_INT32 len)//len in byte for utf16 { if (len < 1) return _T(""); if (m_lPos + len > m_lSize) return _T(""); _UINT32 lSize = len >> 1; //string in char std::wstring res = NSFile::CUtf8Converter::GetWStringFromUTF16((unsigned short*)m_pDataCur, lSize); m_lPos += len; m_pDataCur += len; return res; } bool CBinaryFileReader::GetArray(BYTE **pBuffer, _INT32 len) { if (0 == len) return false; if (m_lPos + len > m_lSize) return false; *pBuffer = new BYTE [len]; memcpy(pBuffer, m_pDataCur, len); m_lPos += len; m_pDataCur += len; return true; } /*LPSAFEARRAY CBinaryFileReader::GetArray(_INT32 len) { if (0 == len) return NULL; if (m_lPos + len > m_lSize) return NULL; SAFEARRAY* pArray = SafeArrayCreateVector(VT_UI1, (_UINT32)len); BYTE* pDataD = (BYTE*)pArray->pvData; memcpy(pDataD, m_pDataCur, len); m_lPos += len; m_pDataCur += len; return pArray; } */ std::string CBinaryFileReader::GetString2A() { _INT32 len = GetULong(); return GetString1(len); } void CBinaryFileReader::SkipRecord() { _INT32 _len = GetULong(); Skip(_len); } LONG CBinaryFileReader::GetPos() { return m_lPos; } LONG CBinaryFileReader::GetSize() { return m_lSize; } BYTE* CBinaryFileReader::GetData() { return m_pData; } BYTE* CBinaryFileReader::GetPointer(int nSize = 0) { if (nSize < 0) return 0; if (m_lPos + nSize > m_lSize) return 0; BYTE* res = (BYTE*)m_pDataCur; m_lPos += nSize; m_pDataCur += nSize; return res; } }