mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 14:00:32 +08:00
PptFile поправлен под iOs git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@62409 954022d7-b5bf-4e40-9824-e11837661b57
472 lines
11 KiB
C++
472 lines
11 KiB
C++
#pragma once
|
|
|
|
#include "../../../Common/DocxFormat/Source/SystemUtility/FileSystem/Directory.h"
|
|
|
|
#include "PPTDocumentInfo.h"
|
|
|
|
#define CURRENT_USER_STREAM "Current User"
|
|
#define DOCUMENT_STREAM "PowerPoint Document"
|
|
#define PICTURE_STREAM "Pictures"
|
|
#define HEADER_STREAM "Header"
|
|
|
|
#define PP97_DUALSTORAGE "PP97_DUALSTORAGE"
|
|
|
|
class CPPTFileReader
|
|
{
|
|
public:
|
|
CPPTFileReader(POLE::Storage *pStg, CStringW strTemp):
|
|
m_pPowerPointStg(pStg),
|
|
m_bIsPPTFile(false),
|
|
m_pDocStream(NULL),
|
|
m_pPictureStream(NULL),
|
|
m_lImagesCount(0),
|
|
m_strMemoryForder(strTemp),
|
|
m_oDocumentInfo()
|
|
{
|
|
m_bDualStorage = false;
|
|
|
|
POLE::Stream *pStm = new POLE::Stream( m_pPowerPointStg, CURRENT_USER_STREAM);
|
|
if (pStm == NULL) return;
|
|
|
|
if ( ReadCurrentUser(pStm))
|
|
m_bIsPPTFile = TRUE;
|
|
else
|
|
{
|
|
RELEASEOBJECT(pStm);
|
|
|
|
std::string stream_name = std::string(PP97_DUALSTORAGE) + std::string("/") + std::string(CURRENT_USER_STREAM);
|
|
pStm = new POLE::Stream( m_pPowerPointStg, stream_name);
|
|
if (pStm == NULL) return;
|
|
|
|
m_bDualStorage = true;
|
|
if ( ReadCurrentUser(pStm))
|
|
m_bIsPPTFile = TRUE;
|
|
}
|
|
|
|
RELEASEOBJECT(pStm);
|
|
|
|
if (0 == m_strMemoryForder.GetLength())
|
|
{
|
|
m_strMemoryForder = FileSystem::Directory::GetTempPath();
|
|
}
|
|
|
|
m_strMemoryForder = FileSystem::Directory::CreateDirectoryWithUniqueName(m_strMemoryForder);
|
|
|
|
}
|
|
~CPPTFileReader()
|
|
{
|
|
RELEASEOBJECT(m_pDocStream);
|
|
RELEASEOBJECT(m_pPictureStream);
|
|
|
|
RELEASEOBJECT(m_pPowerPointStg);
|
|
|
|
FileSystem::Directory::DeleteDirectory(m_strMemoryForder);
|
|
}
|
|
|
|
bool IsPowerPoint()
|
|
{
|
|
return m_bIsPPTFile;
|
|
}
|
|
|
|
void ReadPersistDirectory()
|
|
{
|
|
// íóæíî âûçûâàòü ÐÎÂÍÎ îäèí ðàç...
|
|
m_oDocumentInfo.ReadFromStream(&m_oCurrentUser, GetDocStream(), (CStringW)m_strMemoryForder);
|
|
}
|
|
|
|
void ReadSlideList()
|
|
{
|
|
// ýòîò ìåòîä ÷èòàåò êàðòèíêè.
|
|
// ñíà÷àëà íóæíî çàïîëíèòü m_arLoadImageFlags
|
|
//std::vector<CRecordBlipStoreEntry*> oArrayBSE;
|
|
//m_oDocumentInfo.m_arUsers[0]->m_oDocument.GetRecordsByType(&oArrayBSE, true, false);
|
|
|
|
// ÷èòàåì êàðòèíêè...
|
|
bool bRes = SavePictures();
|
|
|
|
|
|
if (m_oDocumentInfo.m_arUsers.size() > 0)
|
|
{
|
|
|
|
DWORD nPID = m_oDocumentInfo.m_arUsers[0]->m_oUser.m_nDocumentRef;
|
|
std::map<DWORD, DWORD>::iterator pPair = m_oDocumentInfo.m_arUsers[0]->m_mapOffsetInPIDs.find(nPID);
|
|
|
|
if (pPair == m_oDocumentInfo.m_arUsers[0]->m_mapOffsetInPIDs.end()) return;
|
|
|
|
DWORD offset = pPair->second;
|
|
StreamUtils::StreamSeek((long)offset, GetDocStream());
|
|
}
|
|
|
|
if (PPT_DUMP_LOG)
|
|
{
|
|
ParseForSlideLists();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
bool ReadCurrentUser(POLE::Stream *pStm)
|
|
{
|
|
SRecordHeader oHeader;
|
|
bool isPP = false;
|
|
|
|
if( oHeader.ReadFromStream(pStm))
|
|
{
|
|
m_oCurrentUser.ReadFromStream(oHeader, pStm);
|
|
|
|
isPP = (m_oCurrentUser.m_nSize == 0x00000014 && (m_oCurrentUser.m_nToken == NO_ENCRYPT) &&
|
|
(m_oCurrentUser.m_nLenUserName <= 255));
|
|
}
|
|
|
|
return isPP;
|
|
}
|
|
|
|
POLE::Stream* GetDocStream()
|
|
{
|
|
if (m_pDocStream == NULL)
|
|
{
|
|
if (!m_bIsPPTFile)
|
|
return NULL;
|
|
|
|
std::string stream_name;
|
|
|
|
if (m_bDualStorage) stream_name = std::string(PP97_DUALSTORAGE) + std::string("/");
|
|
|
|
m_pDocStream = new POLE::Stream(m_pPowerPointStg, stream_name + DOCUMENT_STREAM);
|
|
}
|
|
return m_pDocStream;
|
|
}
|
|
POLE::Stream* GetPictureStream()
|
|
{
|
|
if (m_pPictureStream == NULL)
|
|
{
|
|
if (!m_bIsPPTFile)
|
|
return NULL;
|
|
|
|
std::string stream_name;
|
|
|
|
if (m_bDualStorage) stream_name = std::string(PP97_DUALSTORAGE) + std::string("/");
|
|
|
|
m_pPictureStream = new POLE::Stream(m_pPowerPointStg, stream_name + PICTURE_STREAM);
|
|
}
|
|
return m_pPictureStream;
|
|
}
|
|
|
|
|
|
DWORD ParseForSlideLists()
|
|
{
|
|
POLE::Stream *pStm = GetDocStream();
|
|
|
|
SRecordHeader oHeader;
|
|
//DWORD nRd = 0;
|
|
|
|
XmlUtils::CXmlWriter oWriter;
|
|
oWriter.WriteNodeBegin(_T("PPTFile"));
|
|
|
|
while (TRUE)
|
|
{
|
|
/////////////////////////////////////////////
|
|
|
|
// çäåñü ñîçäàåì xml
|
|
|
|
if ( oHeader.ReadFromStream(pStm) == false )
|
|
break;
|
|
|
|
oHeader.ToXmlWriter(&oWriter, pStm);
|
|
}
|
|
|
|
oWriter.WriteNodeEnd(_T("PPTFile"));
|
|
|
|
CDirectory::SaveToFile(_T("C:\\PPT.xml"), oWriter.GetXmlString());
|
|
//oWriter.SaveToFile(_T("C:\\PPT.xml"));
|
|
return 0;
|
|
}
|
|
|
|
bool SavePictures()
|
|
{
|
|
POLE::Stream* pStream = GetPictureStream();
|
|
|
|
if (NULL == pStream)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SRecordHeader oHeader;
|
|
ULONG nRd = 0;
|
|
m_lImagesCount = 0;
|
|
|
|
// óäàëåíèå êàðòèíîê ïðè çàâåðøåíèè ïðîãðàììû
|
|
|
|
while (TRUE)
|
|
{
|
|
/*if (m_lImagesCount < m_oDocumentInfo.m_arEmptyPictures.GetCount())
|
|
{
|
|
if (m_oDocumentInfo.m_arEmptyPictures[m_lImagesCount])
|
|
{
|
|
++m_lImagesCount;
|
|
continue;
|
|
}
|
|
}*/
|
|
|
|
CMetaFileBuffer oMetaFile;
|
|
|
|
if (oHeader.ReadFromStream(pStream) == false )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ((oHeader.RecVersion != PSFLAG_CONTAINER) && ((oHeader.RecVersion & 0x0F) != 0x0F))
|
|
{
|
|
long lOffset = 0;
|
|
|
|
switch (oHeader.RecType)
|
|
{
|
|
case RECORD_TYPE_ESCHER_BLIP_EMF:
|
|
{
|
|
if (0x03D4 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 16;
|
|
}
|
|
else if (0x03D5 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 32;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
lOffset += 34;
|
|
|
|
oMetaFile.m_bIsValid = TRUE;
|
|
|
|
CMetaHeader oMetaHeader;
|
|
oMetaHeader.FromStream(pStream);
|
|
|
|
Gdiplus::ENHMETAHEADER3 oEmfHeader;
|
|
oMetaHeader.ToEMFHeader(&oEmfHeader);
|
|
|
|
//LONG lLenHeader = 88;
|
|
//BYTE* pMetaHeader = new BYTE[lLenHeader];
|
|
//memcpy(pMetaHeader, (void*)(&oEmfHeader), lLenHeader);
|
|
//oMetaFile.SetHeader(pMetaHeader, lLenHeader);
|
|
|
|
oMetaFile.SetHeader(NULL, 0);
|
|
|
|
BYTE* pData = new BYTE[oHeader.RecLen - lOffset];
|
|
pStream->read(pData, oHeader.RecLen - lOffset);
|
|
|
|
oMetaFile.SetData(pData, oMetaHeader.cbSave,
|
|
oMetaHeader.cbSize, 0 == oMetaHeader.compression);
|
|
|
|
if (0 == oMetaHeader.compression)
|
|
{
|
|
RELEASEARRAYOBJECTS(pData);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case RECORD_TYPE_ESCHER_BLIP_WMF:
|
|
{
|
|
if (0x0216 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 16;
|
|
}
|
|
else if (0x0217 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 32;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
|
|
lOffset += 34;
|
|
|
|
oMetaFile.m_bIsValid = TRUE;
|
|
|
|
CMetaHeader oMetaHeader;
|
|
oMetaHeader.FromStream(pStream);
|
|
Gdiplus::WmfPlaceableFileHeader oWmfHeader;
|
|
oMetaHeader.ToWMFHeader(&oWmfHeader);
|
|
|
|
LONG lLenHeader = 22;
|
|
BYTE* pMetaHeader = new BYTE[lLenHeader];
|
|
memcpy(pMetaHeader, (void*)(&oWmfHeader), lLenHeader);
|
|
|
|
oMetaFile.SetHeader(pMetaHeader, lLenHeader);
|
|
|
|
BYTE* pData = new BYTE[oHeader.RecLen - lOffset];
|
|
pStream->read(pData, oHeader.RecLen - lOffset);
|
|
|
|
oMetaFile.SetData(pData, oMetaHeader.cbSave,
|
|
oMetaHeader.cbSize, 0 == oMetaHeader.compression);
|
|
|
|
if (0 == oMetaHeader.compression)
|
|
{
|
|
RELEASEARRAYOBJECTS(pData);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case RECORD_TYPE_ESCHER_BLIP_PICT:
|
|
{
|
|
if (0x0542 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 16;
|
|
}
|
|
else if (0x0543 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 32;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
lOffset += 34;
|
|
|
|
oMetaFile.m_bIsValid = TRUE;
|
|
|
|
CMetaHeader oMetaHeader;
|
|
oMetaHeader.FromStream(pStream);
|
|
Gdiplus::WmfPlaceableFileHeader oWmfHeader;
|
|
oMetaHeader.ToWMFHeader(&oWmfHeader);
|
|
|
|
LONG lLenHeader = 22;
|
|
BYTE* pMetaHeader = new BYTE[lLenHeader];
|
|
memcpy(pMetaHeader, (void*)(&oWmfHeader), lLenHeader);
|
|
|
|
oMetaFile.SetHeader(pMetaHeader, lLenHeader);
|
|
|
|
BYTE* pData = new BYTE[oHeader.RecLen - lOffset];
|
|
pStream->read(pData, oHeader.RecLen - lOffset);
|
|
|
|
oMetaFile.SetData(pData, oMetaHeader.cbSave,
|
|
oMetaHeader.cbSize, 0 == oMetaHeader.compression);
|
|
|
|
if (0 == oMetaHeader.compression)
|
|
{
|
|
RELEASEARRAYOBJECTS(pData);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case RECORD_TYPE_ESCHER_BLIP_JPEG:
|
|
{
|
|
if (0x046A == oHeader.RecInstance || 0x06E2 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 17;
|
|
}
|
|
else if (0x046B == oHeader.RecInstance || 0x06E3 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 33;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
break;
|
|
}
|
|
case RECORD_TYPE_ESCHER_BLIP_PNG:
|
|
{
|
|
if (0x06E0 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 17;
|
|
}
|
|
else if (0x06E1 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 33;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
break;
|
|
}
|
|
case RECORD_TYPE_ESCHER_BLIP_DIB:
|
|
{
|
|
if (0x07A8 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 17;
|
|
}
|
|
else if (0x07A9 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 33;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
break;
|
|
}
|
|
case RECORD_TYPE_ESCHER_BLIP_TIFF:
|
|
{
|
|
if (0x06E4 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 17;
|
|
}
|
|
else if (0x06E5 == oHeader.RecInstance)
|
|
{
|
|
lOffset = 33;
|
|
}
|
|
StreamUtils::StreamSkip(lOffset, pStream);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
};
|
|
|
|
if (oMetaFile.m_bIsValid)
|
|
{
|
|
CString strFile = CDirectory::ToString(++m_lImagesCount) + _T(".jpg");
|
|
|
|
CFile fileMeta;
|
|
HRESULT hr = fileMeta.CreateFile((CString)m_strMemoryForder + FILE_SEPARATOR_STR + strFile);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
oMetaFile.ToFile(&fileMeta);
|
|
fileMeta.CloseFile();
|
|
}
|
|
continue;
|
|
}
|
|
|
|
BYTE* pImage = new BYTE[oHeader.RecLen - lOffset];
|
|
//StreamUtils::StreamSkip(lOffset, pStream);
|
|
|
|
pStream->read(pImage, oHeader.RecLen - lOffset);
|
|
|
|
CString strFile = CDirectory::ToString(++m_lImagesCount) + _T(".jpg");
|
|
|
|
CFile fileJpeg;
|
|
HRESULT hr = fileJpeg.CreateFile((CString)m_strMemoryForder+ FILE_SEPARATOR_STR + strFile);
|
|
if (hr == S_OK)
|
|
{
|
|
if (RECORD_TYPE_ESCHER_BLIP_DIB == oHeader.RecType)
|
|
{
|
|
WORD vtType = 0x4D42;
|
|
fileJpeg.WriteFile((void*)&vtType, 2);
|
|
DWORD dwLen = oHeader.RecLen - lOffset;
|
|
fileJpeg.WriteFile((void*)&dwLen, 4);
|
|
DWORD dwRes = 0;
|
|
fileJpeg.WriteFile((void*)&dwRes, 4);
|
|
DWORD dwOffset = 2;
|
|
fileJpeg.WriteFile((void*)&dwOffset, 4);
|
|
}
|
|
fileJpeg.WriteFile((void*)pImage, oHeader.RecLen - lOffset);
|
|
fileJpeg.CloseFile();
|
|
}
|
|
|
|
delete[] pImage;
|
|
}
|
|
else
|
|
{
|
|
// ýòîãî áûòü íå äîëæíî...
|
|
continue;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
private:
|
|
bool m_bDualStorage;
|
|
CRecordCurrentUserAtom m_oCurrentUser;
|
|
POLE::Stream * m_pDocStream;
|
|
POLE::Stream * m_pPictureStream;
|
|
POLE::Storage* m_pPowerPointStg;
|
|
bool m_bIsPPTFile;
|
|
|
|
public:
|
|
// äëÿ êàðòèíîê
|
|
CStringW m_strMemoryForder;
|
|
|
|
std::vector<bool> m_arLoadImageFlags;
|
|
DWORD m_lImagesCount;
|
|
|
|
public:
|
|
CPPTDocumentInfo m_oDocumentInfo;
|
|
};
|