Compare commits

..

9 Commits

Author SHA1 Message Date
d18d3d1bdf Add FileID 2026-03-27 16:22:12 +03:00
920542cd78 Add const to link comparison 2026-03-27 16:21:58 +03:00
bd4d5ec1e9 Skip non-uri hyperlinks 2026-03-26 15:55:53 +03:00
b49997e615 From PdfLink to docx 2026-03-26 01:11:01 +03:00
d4b4fc04d9 Create PdfLink 2026-03-25 16:55:22 +03:00
78219fcba1 Add recording hyperlink for CShape 2026-03-23 20:12:25 +03:00
fa3ae4e2e2 Add recording hyperlinks 2026-03-23 20:11:40 +03:00
e69b1cf2d6 Add CLink for hyperlink 2026-03-23 20:09:11 +03:00
8870516a8a Fix bug 68012 2026-03-23 16:07:38 +03:00
44 changed files with 762 additions and 245 deletions

View File

@ -505,7 +505,13 @@ public:
}
if (m_nType == 0)
{
std::vector<CPdfLink*> arrLinks = ((CPdfFile*)m_pFile)->GetPdfLinks(nPageIndex);
// TODO Usage
for (int i = 0; i < arrLinks.size(); ++i)
RELEASEOBJECT(arrLinks[i]);
((CPdfFile*)m_pFile)->SetPageFonts(nPageIndex);
}
BYTE* res = oRes.GetBuffer();
oRes.ClearWithoutAttack();

View File

@ -141,3 +141,8 @@ void IOfficeDrawingFile::ConvertToRaster(int nPageIndex, const std::wstring& pat
pFrame->SaveFile(path, nImageType);
RELEASEOBJECT(pFrame);
}
std::vector<CPdfLink*> IOfficeDrawingFile::GetPdfLinks(int nPageIndex)
{
return std::vector<CPdfLink*>();
}

View File

@ -56,6 +56,20 @@ struct COfficeDrawingPageParams
}
};
struct CPdfLink
{
~CPdfLink() { RELEASEOBJECT(pNext); }
double pRect[4];
BYTE nType;
BYTE nKind;
unsigned int unPage;
unsigned int unKindFlag;
double pData[4];
std::string sData;
CPdfLink* pNext = NULL;
};
class GRAPHICS_DECL IOfficeDrawingFile
{
public:
@ -103,6 +117,8 @@ public:
virtual std::wstring GetInfo() = 0;
virtual unsigned char* GetStructure() = 0;
virtual unsigned char* GetLinks(int nPageIndex) = 0;
virtual std::vector<CPdfLink*> GetPdfLinks(int nPageIndex);
};
#endif // _OFFICE_DRAWING_FILE_H

View File

@ -116,8 +116,8 @@ namespace XmlUtils
void GetTextWithHHHH(bool bPreserve, wchar_t*& sBuffer, long& nSize, long& nLen);
std::wstring GetTextWithHHHH(bool bPreserve);
std::wstring GetOuterXml(bool bEncodingXml = true);
std::wstring GetInnerXml(bool bEncodingXml = true);
std::wstring GetOuterXml();
std::wstring GetInnerXml();
int GetAttributesCount();
bool MoveToFirstAttribute();

View File

@ -208,13 +208,13 @@ namespace XmlUtils
return m_pInternal->GetTextWithHHHH(bPreserve);
}
std::wstring CXmlLiteReader::GetOuterXml(bool bEncodingXml)
std::wstring CXmlLiteReader::GetOuterXml()
{
return m_pInternal->GetOuterXml(bEncodingXml);
return m_pInternal->GetOuterXml();
}
std::wstring CXmlLiteReader::GetInnerXml(bool bEncodingXml)
std::wstring CXmlLiteReader::GetInnerXml()
{
return m_pInternal->GetInnerXml(bEncodingXml);
return m_pInternal->GetInnerXml();
}
int CXmlLiteReader::GetAttributesCount()

View File

@ -635,13 +635,13 @@ namespace XmlUtils
GetTextWithHHHH(bPreserve, pUnicodes, nSize, nLen);
return std::wstring(pUnicodes, nLen);
}
inline std::wstring GetOuterXml(bool bEncodingXml = true)
inline std::wstring GetOuterXml()
{
return GetXml(false, bEncodingXml);
return GetXml(false);
}
inline std::wstring GetInnerXml(bool bEncodingXml = true)
inline std::wstring GetInnerXml()
{
return GetXml(true, bEncodingXml);
return GetXml(true);
}
inline int GetAttributesCount()
@ -700,7 +700,7 @@ namespace XmlUtils
}
private:
inline std::wstring GetXml(bool bInner, bool bEncodingXml = true)
inline std::wstring GetXml(bool bInner)
{
if (!IsValid())
return L"";
@ -730,7 +730,7 @@ namespace XmlUtils
eNodeType == XmlNodeType_Whitespace ||
eNodeType == XmlNodeType_SIGNIFICANT_WHITESPACE ||
eNodeType == XmlNodeType_CDATA)
(bEncodingXml)? oResult.WriteEncodeXmlString(GetText().c_str()): oResult.WriteString(GetText().c_str());
oResult.WriteEncodeXmlString(GetText().c_str());
else if (eNodeType == XmlNodeType_Element)
WriteElement(oResult);
else if (eNodeType == XmlNodeType_EndElement)

View File

@ -204,6 +204,30 @@ void CDocxRenderer::DrawPage(IOfficeDrawingFile* pFile, size_t nPage)
put_Width(dWidth);
put_Height(dHeight);
if (pFile->GetType() == OfficeDrawingFileType::odftPDF)
{
std::vector<CPdfLink*> arrLinks = pFile->GetPdfLinks(nPage);
for (int i = 0; i < arrLinks.size(); ++i)
{
LONG lType = arrLinks[i]->nType;
double x1, y1, x2, y2;
x1 = arrLinks[i]->pRect[0] / c_dMMToPix;
y1 = arrLinks[i]->pRect[1] / c_dMMToPix;
x2 = arrLinks[i]->pRect[2] / c_dMMToPix;
y2 = arrLinks[i]->pRect[3] / c_dMMToPix;
std::wstring wsData;
if (lType == 1 || lType == 9)
continue; // TODO: GoTo bookmarks or anchors
if (lType == 6)
wsData = NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)arrLinks[i]->sData.c_str(), arrLinks[i]->sData.size());
m_pInternal->m_oDocument.AddLink(lType, x1, y1, x2, y2, wsData);
RELEASEOBJECT(arrLinks[i]);
}
m_pInternal->m_oDocument.m_oImageManager.UpdateId(arrLinks.size());
}
pFile->DrawPageOnRenderer(this, nPage, nullptr);
m_pInternal->m_oDocument.m_bIsDisablePageCommand = false;

View File

@ -30,6 +30,7 @@ LIBS += \
HEADERS += \
src/logic/elements/BaseItem.h \
src/logic/elements/ContText.h \
src/logic/elements/Link.h \
src/logic/elements/Paragraph.h \
src/logic/elements/Shape.h \
src/logic/elements/Table.h \
@ -55,6 +56,7 @@ HEADERS += \
SOURCES += \
src/logic/elements/BaseItem.cpp \
src/logic/elements/ContText.cpp \
src/logic/elements/Link.cpp \
src/logic/elements/Paragraph.cpp \
src/logic/elements/Shape.cpp \
src/logic/elements/Table.cpp \

View File

@ -744,6 +744,18 @@ namespace NSDocxRenderer
m_oCurrentPage.m_lClipMode = lMode;
return S_OK;
}
HRESULT CDocument::AddLink(const LONG& lType, const double& x1, const double y1, const double& x2, const double& y2, const std::wstring& wsData)
{
CLink oLink;
UINT nId = m_oImageManager.GetId() + m_arLinks.size();
oLink.AddLink(nId, lType, wsData);
oLink.AddBBox(x1, y1, x2, y2);
m_arLinks.push_back(oLink);
m_oCurrentPage.AddLink(oLink);
return S_OK;
}
void CDocument::ApplyTransform(double d1, double d2, double d3, double d4, double d5, double d6)
{
@ -912,6 +924,17 @@ namespace NSDocxRenderer
oWriter.WriteString(L"\"/>");
}
for (const auto& pLink : m_arLinks)
{
oWriter.WriteString(L"<Relationship Id=\"rId");
oWriter.AddUInt(c_iStartingIdForLinks + pLink.m_nId);
oWriter.WriteString(L"\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink\" Target=\"");
oWriter.WriteString(pLink.m_wsData);
oWriter.WriteString(L"\" TargetMode=\"");
oWriter.WriteString(pLink.m_eType == eLinkType::ltUri ? L"External" : L"Internal");
oWriter.WriteString(L"\"/>");
}
oWriter.WriteString(L"</Relationships>");
NSFile::CFileBinary::SaveToFile(m_strTempDirectory + L"/word/_rels/document.xml.rels", oWriter.GetData());

View File

@ -44,6 +44,7 @@ namespace NSDocxRenderer
NSStringUtils::CStringBuilder m_oPageBuilder;
std::list<std::string> m_arXmlString;
std::list<CLink> m_arLinks;
public:
CDocument(IRenderer* pRenderer, NSFonts::IApplicationFonts* pFonts);
@ -178,6 +179,8 @@ namespace NSDocxRenderer
HRESULT get_ClipMode(LONG* plMode);
HRESULT put_ClipMode(LONG lMode);
HRESULT AddLink(const LONG& lType, const double& x1, const double y1, const double& x2, const double& y2, const std::wstring& wsData);
protected:
void ApplyTransform(double d1, double d2, double d3, double d4, double d5, double d6);
void ApplyTransform2(double dAngle, double dLeft, double dTop, double dWidth, double dHeight, DWORD lFlags);

View File

@ -273,6 +273,18 @@ namespace NSDocxRenderer
shape->m_oBrush.Color1 == c_iWhiteColor && !info)
return;
for (const auto& link : m_arLinks)
{
if (fabs(shape->m_dTop - link.m_dTop) <= c_dLINK_X_OFFSET_MM &&
fabs(shape->m_dLeft - link.m_dLeft) <= c_dLINK_X_OFFSET_MM &&
fabs(shape->m_dBot - link.m_dBottom) <= c_dLINK_X_OFFSET_MM &&
fabs(shape->m_dRight - link.m_dRight) <= c_dLINK_X_OFFSET_MM)
{
shape->m_bIsHyperlink = true;
shape->m_nRid = c_iStartingIdForLinks + link.m_nId;
}
}
if (!skip_shape)
{
shape->m_nOrder = ++m_nCurrentOrder;
@ -488,6 +500,10 @@ namespace NSDocxRenderer
{
m_arCompleteObjectsBinBase64.push_back(oBase64);
}
void CPage::AddLink(const CLink& oLink)
{
m_arLinks.push_back(oLink);
}
void CPage::ReorderShapesForPptx()
{
// переместим nullptr в конец и удалим

View File

@ -3,6 +3,7 @@
#include "elements/Paragraph.h"
#include "elements/Table.h"
#include "elements/Shape.h"
#include "elements/Link.h"
#include "managers/ImageManager.h"
#include "managers/FontStyleManager.h"
#include "managers/ParagraphStyleManager.h"
@ -91,6 +92,8 @@ namespace NSDocxRenderer
void AddCompleteXml(const std::wstring& oXml);
void AddCompleteBinBase64(const std::string& oBase64);
void AddLink(const CLink& pLink);
private:
using shape_ptr_t = std::shared_ptr<CShape>;
using cont_ptr_t = std::shared_ptr<CContText>;
@ -235,6 +238,8 @@ namespace NSDocxRenderer
std::vector<shape_ptr_t> m_arLuminosityShapes;
std::vector<shape_ptr_t> m_arOneColorGradientShape;
std::list<CLink> m_arLinks;
long m_lLastType = 0;
size_t m_nCurrentOrder = 0;

View File

@ -0,0 +1,31 @@
#include "Link.h"
namespace NSDocxRenderer
{
CLink::~CLink()
{
Clear();
}
void CLink::Clear()
{
m_nId = 0;
m_eType = eLinkType::ltNone;
m_wsData.clear();
}
void CLink::AddLink(BYTE nId, const LONG& lType, const std::wstring& wsData)
{
m_nId = nId;
m_eType = static_cast<eLinkType>(lType);
m_wsData = wsData;
}
void CLink::AddBBox(const double& x1, const double& y1, const double& x2, const double& y2)
{
m_dTop = y1;
m_dLeft = x1;
m_dBottom = y2;
m_dRight = x2;
}
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "BaseItem.h"
namespace NSDocxRenderer
{
enum class eLinkType
{
ltNone = 0,
ltGoTo = 1,
ltUri = 6,
ltNamed = 9,
};
class CLink : public CBaseItem
{
public:
CLink() = default;
virtual ~CLink();
void Clear();
void AddLink(BYTE nId, const LONG& type, const std::wstring& wsData);
void AddBBox(const double& x1, const double& y1, const double& x2, const double& y2);
public:
UINT m_nId{0};
eLinkType m_eType{eLinkType::ltNone};
double m_dTop{0.0};
double m_dLeft{0.0};
double m_dBottom{0.0};
double m_dRight{0.0};
std::wstring m_wsData{};
};
}

View File

@ -637,7 +637,14 @@ namespace NSDocxRenderer
break;
}
oWriter.AddUInt(m_nShapeId);
oWriter.WriteString(L"\"/>");
oWriter.WriteString(L"\">");
if (m_bIsHyperlink)
{
oWriter.WriteString(L"<a:hlinkClick xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\" r:id=\"rId");
oWriter.AddUInt(m_nRid);
oWriter.WriteString(L"\"/>");
}
oWriter.WriteString(L"</wp:docPr>");
oWriter.WriteString(L"<wp:cNvGraphicFramePr/>");
BuildSpecificProperties(oWriter);
oWriter.WriteString(L"</wp:anchor>");

View File

@ -46,11 +46,13 @@ namespace NSDocxRenderer
std::wstring m_strDstMedia {};
double m_dRotation {0.0};
int m_nRid {0};
bool m_bIsNoFill {true};
bool m_bIsNoStroke {true};
bool m_bIsBehindDoc {true};
bool m_bIsUseInTable{false};
bool m_bIsHyperlink {false};
std::shared_ptr<CImageInfo> m_pImageInfo{nullptr};
double m_dImageTop{};

View File

@ -132,10 +132,21 @@ namespace NSDocxRenderer
m_strDstMedia = L"";
m_lMaxSizeImage = 1200;
m_lNextIDImage = 0;
m_lFileID = 0;
m_mapImageData.clear();
}
void CImageManager::UpdateId(int idInc)
{
m_lNextIDImage += idInc;
}
int CImageManager::GetId() const
{
return m_lNextIDImage;
}
std::shared_ptr<CImageInfo> CImageManager::WriteImage(Aggplus::CImage* pImage, double& x, double& y, double& width, double& height)
{
if (height < 0)
@ -176,10 +187,11 @@ namespace NSDocxRenderer
return find->second;
++m_lNextIDImage;
++m_lFileID;
auto pInfo = std::make_shared<CImageInfo>();
pInfo->m_nId = m_lNextIDImage;
pInfo->m_eType = GetImageType(pImage);
pInfo->m_strFileName = L"image" + std::to_wstring(pInfo->m_nId);
pInfo->m_strFileName = L"image" + std::to_wstring(m_lFileID);
pInfo->m_strFileName += ((pInfo->m_eType == CImageInfo::itJPG) ? L".jpg" : L".png");
UINT format = (pInfo->m_eType == CImageInfo::itJPG) ? 3 : 4;

View File

@ -19,6 +19,9 @@ namespace NSDocxRenderer
~CImageManager() = default;
void Clear();
void UpdateId(int idInc);
int GetId() const;
std::shared_ptr<CImageInfo> WriteImage(Aggplus::CImage* pImage, double& x, double& y, double& width, double& height);
std::shared_ptr<CImageInfo> WriteImage(const std::wstring& strFile);
std::shared_ptr<CImageInfo> GenerateImageID(Aggplus::CImage* pImage);
@ -30,6 +33,7 @@ namespace NSDocxRenderer
std::shared_ptr<CImageInfo> GenerateImageID(const std::wstring& strFileName);
int m_lMaxSizeImage {1200};
int m_lNextIDImage {0};
int m_lFileID {0};
CCalculatorCRC32 m_oCRC;
};
}

View File

@ -46,6 +46,7 @@ const double c_dLINE_DISTANCE_MAX_MM = 50.0;
const double c_dSHAPE_TROUGH_MAX_MM = 80.0;
const double c_dLINE_SPLIT_DISTANCE_MM = 10.0;
const double c_dSHAPE_X_OFFSET_MM = 1.5;
const double c_dLINK_X_OFFSET_MM = 0.1;
const double c_dAVERAGE_SPACE_WIDTH_COEF = 0.9;
const double c_dSPACE_WIDTH_COEF = 0.4;
const double c_dMIN_ROTATION = 0.01;
@ -64,6 +65,7 @@ const double c_dSTANDART_FIRSTLINE_INDENT_MM = 12.5;
const uint32_t c_SPACE_SYM = 0x20;
const UINT c_iStartingIdForImages = 6;
const UINT c_iStartingIdForLinks = 6;
constexpr size_t c_nAntiZero = ~0;
const UINT c_iStandartRelativeHeight = 0x0400;

View File

@ -392,7 +392,6 @@ enum ElementType
typeMathSemantics,
typeMathAnnotation,
typeMathAnnotationXml,
typeMathSignatue,
typeMN,
typeMI,
typeMS,

View File

@ -37,7 +37,7 @@
namespace cpdoccore {
namespace common {
bool read_doc_element::read_sax( xml::sax * Reader, bool bOnlyText )
bool read_doc_element::read_sax( xml::sax * Reader )
{
const unsigned int currentDepth = Reader->depth();
@ -63,15 +63,7 @@ bool read_doc_element::read_sax( xml::sax * Reader, bool bOnlyText )
return false;
}
if(bOnlyText)
{
const std::wstring value = Reader->getXML();
if (false == value.empty())
{
add_text(value);
}
return true;
}
while (true)
{
nodeType = Reader->next(currentDepth);

View File

@ -57,7 +57,7 @@ namespace cpdoccore {
class read_doc_element
{
public:
bool read_sax( xml::sax * Reader, bool bOnlyText = false);
bool read_sax( xml::sax * Reader);
virtual ~read_doc_element() = 0;
virtual void add_child_element ( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name) = 0;

View File

@ -99,9 +99,7 @@ public:
virtual bool moveToAttrOwner() = 0;
virtual NodeType next(int Depth) = 0;
virtual std::wstring getXML() =0;
virtual ~sax() = 0;
};

View File

@ -70,8 +70,6 @@ public:
virtual bool moveToAttrOwner();
virtual NodeType next(int Depth);
virtual std::wstring getXML();
private:
smart_ptr< XmlUtils::CXmlLiteReader > xml_;
@ -226,11 +224,6 @@ NodeType saxXmlLiteReader::next(int Depth)
}
std::wstring saxXmlLiteReader::getXML()
{
return xml_->GetInnerXml(false);
}
sax_ptr create_sax_xmllite(const wchar_t * FileName)
{
return sax_ptr( new saxXmlLiteReader(FileName) );

View File

@ -322,7 +322,6 @@ SOURCES += \
../../Reader/Converter/xlsx_data_validation.cpp \
../../Reader/Converter/xlsx_utils.cpp \
../../Reader/Converter/xlsx_xf.cpp \
../../Reader/Converter/StarMath2OOXML/shakey.cpp \
../../Reader/Converter/StarMath2OOXML/cooxml2odf.cpp \
\
../../Writer/Format/office_document.cpp \
@ -723,7 +722,6 @@ HEADERS += \
../../Reader/Converter/xlsx_xf.h \
../../Reader/Converter/conversionelement.h \
../../Reader/Converter/ConvertOO2OOX.h \
../../Reader/Converter/StarMath2OOXML/shakey.h \
../../Reader/Converter/StarMath2OOXML/cooxml2odf.h \
\
../../Writer/Format/math_elementaries.h \
@ -831,3 +829,4 @@ HEADERS += \
../../Writer/Converter/VmlShapeTypes2Oox.h \
../../Writer/Converter/XlsxConverter.h \
../../Writer/Converter/PptxConverter.h \

View File

@ -3,7 +3,7 @@
namespace StarMath
{
//class OOXml2Odf
COOXml2Odf::COOXml2Odf():m_wsBaseColor(L""),m_wsHashAnnotation(L""),m_uiBaseSize(0),m_bStretchyAcc(false),m_bHeight(false)
COOXml2Odf::COOXml2Odf():m_wsBaseColor(L""),m_uiBaseSize(0),m_bStretchyAcc(false),m_bHeight(false)
{
m_pXmlWrite = new XmlUtils::CXmlWriter;
}
@ -21,7 +21,7 @@ namespace StarMath
if(pNode == nullptr)
{
m_pXmlWrite->WriteNodeBegin(L"annotation",false);
EndOdf(pNode);
EndOdf();
return;
}
else
@ -30,9 +30,8 @@ namespace StarMath
m_pXmlWrite->WriteNodeBegin(L"annotation",true);
m_pXmlWrite->WriteAttribute(L"encoding",L"StarMath 5.0");
m_pXmlWrite->WriteNodeEnd(L"w",true,false);
HashSM::RemovingSpaces(m_wsAnnotationStarMath);
m_pXmlWrite->WriteString(m_wsAnnotationStarMath);
EndOdf(pNode);
EndOdf();
}
void COOXml2Odf::NodeDefinition(OOX::WritingElement *pNode,const bool& bMatrix)
{
@ -707,16 +706,9 @@ namespace StarMath
else if(wsChr == L"\u2230") return L"lllint";
else return L"oper " + wsChr;
}
void COOXml2Odf::EndOdf(OOX::WritingElement *pNode)
void COOXml2Odf::EndOdf()
{
m_pXmlWrite->WriteNodeEnd(L"annotation",false,false);
m_pXmlWrite->WriteNodeBegin(L"signature",true);
m_pXmlWrite->WriteAttribute(L"encoding",L"OOXML");
m_pXmlWrite->WriteAttribute(L"alg",L"sha256");
m_pXmlWrite->WriteAttribute(L"shakey",HashSM::HashingAnnotation(m_wsAnnotationStarMath));
m_pXmlWrite->WriteNodeEnd(L"w",true,false);
m_pXmlWrite->WriteString(pNode->toXML());
m_pXmlWrite->WriteNodeEnd(L"signature",false,false);
m_pXmlWrite->WriteNodeEnd(L"semantics",false,false);
m_pXmlWrite->WriteNodeEnd(L"math",false,false);
}
@ -1871,10 +1863,6 @@ namespace StarMath
}
return wsText16;
}
std::wstring COOXml2Odf::GetHashAnnotation()
{
return m_wsHashAnnotation;
}
//class COneElement
COneElement::COneElement():m_stAttribute(nullptr),m_iStyle(0)
{}

View File

@ -37,8 +37,6 @@
#include "../../../../OOXML/Base/Unit.h"
#include "../../../../OOXML/Common/SimpleTypes_OMath.h"
#include "../../../../DesktopEditor/common/StringUTF32.h"
#include "../../../../../DesktopEditor/common/File.h"
#include "shakey.h"
#include "typeselements.h"
#include "fontType.h"
#include <vector>
@ -182,17 +180,16 @@ namespace StarMath
static bool ColorCheck(const std::wstring& wsColor,std::wstring& wsRecordColor);
void CheckVectorElementsForMf(std::vector<OOX::WritingElement*> arWrElement);
TFormulaSize GetFormulaSize();
void EndOdf(OOX::WritingElement* pNode);
void EndOdf();
std::wstring GetOdf();
std::wstring GetAnnotation();
std::wstring GetSemantic();
void SetBaseAttribute(std::wstring wsBaseColor = L"", unsigned int uiBaseSize = 0);
std::wstring GetHashAnnotation();
private:
XmlUtils::CXmlWriter* m_pXmlWrite;
std::wstring m_wsAnnotationStarMath,m_wsSemantic;
std::stack<StValuePr*> m_stAttribute;
std::wstring m_wsBaseColor,m_wsHashAnnotation;
std::wstring m_wsBaseColor;
unsigned int m_uiBaseSize;
TFormulaSize m_stSize;
bool m_bHeight;

View File

@ -1,72 +0,0 @@
#include "shakey.h"
#include "../../../../../DesktopEditor/common/File.h"
#include "../../../../../Common/3dParty/cryptopp/sha.h"
#include "../../../../../Common/3dParty/cryptopp/hex.h"
#include "../../../../../Common/3dParty/cryptopp/base64.h"
#include "../../../../../Common/3dParty/cryptopp/filters.h"
#include "../../../../../Common/3dParty/cryptopp/files.h"
namespace HashSM
{
std::wstring HashingAnnotation(std::wstring &wsAnnotation, const bool& bUnicodeConversionString)
{
RemovingSpaces(wsAnnotation);
std::wstring wsTempAnnotation = L"";
if(bUnicodeConversionString)
{
wsTempAnnotation = wsAnnotation;
wsAnnotation.clear();
for(wchar_t wcOneSymbol:wsTempAnnotation)
{
if(wcOneSymbol == L'"')
wsAnnotation += L"&quot;";
else
wsAnnotation += wcOneSymbol;
}
}
std::string sAnnotation = U_TO_UTF8(wsAnnotation),sResult;
std::wstring wsResult;
CryptoPP::SHA256 hash;
CryptoPP::StringSource oStringSourse(sAnnotation, true, new CryptoPP::HashFilter(hash,new CryptoPP::HexEncoder(new CryptoPP::StringSink(sResult))));
wsResult = UTF8_TO_U(sResult);
if( bUnicodeConversionString && !wsTempAnnotation.empty())
wsAnnotation = wsTempAnnotation;
return wsResult;
}
bool HashComparison(const std::wstring& wsHashFirst,const std::wstring& wsHashSecond)
{
if(wsHashFirst.empty() || wsHashSecond.empty() || wsHashFirst.length() != wsHashSecond.length())
return false;
std::string sFirstHash = U_TO_UTF8(wsHashFirst),sSecondHash = U_TO_UTF8(wsHashSecond);
const char* cFirst = sFirstHash.c_str();
const char* cSecond = sSecondHash.c_str();
size_t sizeLen = wsHashFirst.length();
for(size_t i = 0; i< sizeLen;i++)
{
if((cFirst[i]^cSecond[i]) != 0)
return false;
}
return true;
}
void RemovingSpaces(std::wstring &wsAnnotation)
{
if(!wsAnnotation.empty())
{
while(wsAnnotation.back() == L' ')
wsAnnotation.pop_back();
while(wsAnnotation[0] == L' ')
{
if(wsAnnotation.size() > 1)
{
wsAnnotation = wsAnnotation.substr(1,wsAnnotation.size());
}
}
}
}
}

View File

@ -1,12 +0,0 @@
#ifndef SHAKEY_H
#define SHAKEY_H
#include<string>
namespace HashSM
{
std::wstring HashingAnnotation(std::wstring & wsAnnotation, const bool &bUnicodeConversionString = false);
bool HashComparison(const std::wstring& wsHashFirst,const std::wstring& wsHashSecond);
void RemovingSpaces(std::wstring& wsAnnotation);
}
#endif // SHAKEY_H

View File

@ -41,17 +41,16 @@ namespace odf_reader {
bool create_element_and_read(xml::sax * Reader,
const std::wstring & Ns,
const std::wstring & Name,
office_element_ptr & _Element,
document_context * Context,
bool isRoot,
bool bOnlyText)
const std::wstring & Ns,
const std::wstring & Name,
office_element_ptr & _Element,
document_context * Context,
bool isRoot)
{
if (office_element_ptr elm = office_element_creator::get()->create(Ns, Name, Context, isRoot))
{
elm->afterCreate();
elm->read_sax( Reader, bOnlyText );
elm->read_sax( Reader );
elm->afterReadContent();
if (_Element) // элемент читается повторно

View File

@ -31,7 +31,7 @@
*/
#include "math_elements.h"
#include "../Converter/StarMath2OOXML/shakey.h"
// #include "../Converter/StarMath2OOXML/cconversionsmtoooxml.h"
#include "../Converter/StarMath2OOXML/conversionmathformula.h"
namespace cpdoccore {
@ -87,9 +87,7 @@ void math_semantics::add_child_element( xml::sax * Reader, const std::wstring &
{
CP_CREATE_ELEMENT(annotation_);
}
else if(CP_CHECK_NAME1(L"signature"))
create_element_and_read(Reader,Ns,Name,signature_,getContext(),false,true);
else
else
CP_CREATE_ELEMENT(content_);
}
@ -101,24 +99,15 @@ void math_semantics::oox_convert(oox::math_context & Context)
}
void math_semantics::oox_convert(oox::math_context &Context, int iTypeConversion)
{
math_signature* pSignature = dynamic_cast<math_signature*>(signature_.get());
math_annotation* annotation = dynamic_cast<math_annotation*>(annotation_.get());
math_annotation_xml* annotation_xml = dynamic_cast<math_annotation_xml*>(annotation_.get());
std::wstring annotation_text(L"");
std::wstring annotation_text;
if ((annotation) && (annotation->text_)) annotation_text = *annotation->text_;
else if ((annotation_xml) && (annotation_xml->text_)) annotation_text = *annotation_xml->text_;
bool result = false;
if(pSignature)
{
if(pSignature->text_ && pSignature->GetAlg() == L"sha256" && HashSM::HashComparison(pSignature->GetShaKey(),HashSM::HashingAnnotation(annotation_text,true)))
{
Context.output_stream() << *pSignature->text_;
result = true;
}
}
if (!annotation_text.empty() && !result)
bool result = false;
if (!annotation_text.empty())
{
result = true;
@ -206,46 +195,11 @@ void math_annotation_xml::add_child_element( xml::sax * Reader, const std::wstri
}
void math_annotation_xml::add_text(const std::wstring & Text)
{
text_->append(Text);
}
//----------------------------------------------------------------------------------------------------
const wchar_t * math_signature::ns = L"math";
const wchar_t * math_signature::name = L"signature";
//----------------------------------------------------------------------------------------------------
std::wstring math_signature::GetAlg() const
{
if(alg_)
return alg_.get();
return L"";
}
std::wstring math_signature::GetShaKey() const
{
if(shakey_)
return shakey_.get();
return L"";
}
void math_signature::add_attributes( const xml::attributes_wc_ptr & Attributes )
{
CP_APPLY_ATTR(L"encoding", encoding_);
CP_APPLY_ATTR(L"alg", alg_);
CP_APPLY_ATTR(L"shakey", shakey_);
}
void math_signature::add_child_element( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name)
{
CP_CREATE_ELEMENT(content_);
}
void math_signature::add_text(const std::wstring & Text)
{
text_ = Text;
}
//----------------------------------------------------------------------------------------------------
}
}

View File

@ -107,12 +107,12 @@ private:
office_element_ptr_array content_;
office_element_ptr annotation_;
office_element_ptr signature_;
};
CP_REGISTER_OFFICE_ELEMENT2(math_semantics);
CP_REGISTER_OFFICE_ELEMENT3(math_semantics);
//-------------------------------------------------------------------------------------------
class math_annotation : public office_math_element
{
public:
@ -159,33 +159,5 @@ private:
CP_REGISTER_OFFICE_ELEMENT2(math_annotation_xml);
CP_REGISTER_OFFICE_ELEMENT3(math_annotation_xml);
//--------------------------------------------------------------------
//-------------------------------------------------------------------------------------------
class math_signature : public office_math_element
{
public:
static const wchar_t * ns;
static const wchar_t * name;
static const xml::NodeType xml_type = xml::typeElement;
static const ElementType type = typeMathSignatue;
virtual void oox_convert(oox::math_context& Context) {}
_CP_OPT(std::wstring) text_;
std::wstring GetAlg() const;
std::wstring GetShaKey() const;
private:
virtual void add_attributes( const xml::attributes_wc_ptr & Attributes );
virtual void add_child_element( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name);
virtual void add_text(const std::wstring & Text);
office_element_ptr_array content_;
_CP_OPT(std::wstring) encoding_;
_CP_OPT(std::wstring) alg_;
_CP_OPT(std::wstring) shakey_;
};
CP_REGISTER_OFFICE_ELEMENT2(math_signature);
CP_REGISTER_OFFICE_ELEMENT3(math_signature);
}
}

View File

@ -137,8 +137,7 @@ bool create_element_and_read(xml::sax * Reader,
const std::wstring & Name,
office_element_ptr & _Element,
document_context * Context,
bool isRoot = false,
bool bOnlyText = false);
bool isRoot = false);
// Создать элемент и в случае успеха прочитать его содержимое из SAX, поместить в array
bool create_element_and_read(xml::sax * Reader,
@ -170,4 +169,4 @@ void not_applicable_element(const std::wstring & Current, const std::wstring & N
}
}
}

View File

@ -1020,7 +1020,7 @@ void OoxConverter::convert(PPTX::Logic::SpPr *oox_spPr, PPTX::Logic::ShapeStyle*
bool bLine = odf_context()->drawing_context()->isLineShape();
if (custGeom && !custGeom->cxnLst.empty() && !odf_context()->drawing_context()->isCustomClosed() && !odf_context()->drawing_context()->isNonPrimitive())
if (custGeom && !custGeom->cxnLst.empty() && !odf_context()->drawing_context()->isCustomClosed())
bLine = true;
odf_context()->drawing_context()->start_area_properties();

View File

@ -1265,11 +1265,6 @@ bool odf_drawing_context::isCustomClosed()
return impl_->current_drawing_state_.path_closed_;
}
bool odf_drawing_context::isNonPrimitive()
{
return (impl_->current_drawing_state_.oox_shape_->odf_type_name == L"non-primitive" || impl_->current_drawing_state_.oox_shape_->odf_type_name == L"ooxml-non-primitive");
}
bool odf_drawing_context::isLineShape()
{
if (impl_->current_level_.empty()) return false;

View File

@ -194,7 +194,6 @@ public:
bool isLineShape();
bool isCustomClosed();
bool isNonPrimitive();
void corrected_line_fill();

View File

@ -605,6 +605,12 @@ BYTE* CPdfFile::GetAPAnnots(int nRasterW, int nRasterH, int nBackgroundColor, in
return NULL;
return m_pInternal->pReader->GetAPAnnots(nRasterW, nRasterH, nBackgroundColor, nPageIndex, nAnnot, sView);
}
std::vector<CPdfLink*> CPdfFile::GetPdfLinks(int nPageIndex)
{
if (!m_pInternal->pReader)
return std::vector<CPdfLink*>();
return m_pInternal->pReader->GetPdfLinks(nPageIndex);
}
// ------------------------------------------------------------------------

View File

@ -136,6 +136,7 @@ public:
virtual std::wstring GetInfo();
virtual BYTE* GetStructure();
virtual BYTE* GetLinks(int nPageIndex);
std::vector<CPdfLink*> GetPdfLinks(int nPageIndex) override;
bool ValidMetaData();
// Захватывает полученную память malloc data

View File

@ -1124,7 +1124,6 @@ BYTE* CPdfReader::GetStructure()
}
BYTE* CPdfReader::GetLinks(int _nPageIndex)
{
// TODO Links должны стать частью Annots
PDFDoc* pDoc = NULL;
int nPageIndex = GetPageIndex(_nPageIndex, &pDoc);
if (nPageIndex < 0 || !pDoc || !pDoc->getCatalog())
@ -1257,6 +1256,64 @@ BYTE* CPdfReader::GetLinks(int _nPageIndex)
return oLinks.Serialize();
}
std::vector<CPdfLink*> CPdfReader::GetPdfLinks(int _nPageIndex)
{
std::vector<CPdfLink*> oRes;
if (m_vPDFContext.empty())
return oRes;
PDFDoc* pDoc = NULL;
PdfReader::CPdfFontList* pFontList = NULL;
int nStartRefID = 0;
int nPageIndex = GetPageIndex(_nPageIndex, &pDoc, &pFontList, &nStartRefID);
if (nPageIndex < 0 || !pDoc || !pFontList || !pDoc->getCatalog())
return oRes;
Page* pPage = pDoc->getCatalog()->getPage(nPageIndex);
if (!pPage)
return oRes;
Object oAnnots;
if (!pPage->getAnnots(&oAnnots)->isArray())
{
oAnnots.free();
return oRes;
}
for (int i = 0, nNum = oAnnots.arrayGetLength(); i < nNum; ++i)
{
Object oAnnot;
if (!oAnnots.arrayGet(i, &oAnnot)->isDict())
{
oAnnot.free();
continue;
}
Object oSubtype;
std::string sType;
if (oAnnot.dictLookup("Subtype", &oSubtype)->isName())
sType = oSubtype.getName();
oSubtype.free(); oAnnot.free();
Object oAnnotRef;
PdfReader::CAnnotLink* pAnnot = NULL;
oAnnots.arrayGetNF(i, &oAnnotRef);
if (sType == "Link")
pAnnot = new PdfReader::CAnnotLink(pDoc, &oAnnotRef, nPageIndex, nStartRefID);
CPdfLink* pLink = NULL;
if (pAnnot)
pLink = pAnnot->GetPdfLink();
if (pLink)
oRes.push_back(pLink);
RELEASEOBJECT(pAnnot);
}
oAnnots.free();
return oRes;
}
BYTE* CPdfReader::GetWidgets()
{
NSWasm::CData oRes;

View File

@ -126,6 +126,7 @@ public:
BYTE* GetButtonIcon(int nBackgroundColor, int nPageIndex, bool bBase64 = false, int nBWidget = -1, const char* sIView = NULL);
BYTE* StreamToCData(BYTE* pSteam, int nLength);
const std::map<std::wstring, std::wstring>& GetFonts() { return m_mFonts; }
std::vector<CPdfLink*> GetPdfLinks(int nPageIndex);
private:
void Clear();

View File

@ -533,6 +533,75 @@ CAnnot::CBorderType* getBorder(Object* oBorder, bool bBSorBorder)
return pBorderType;
}
//------------------------------------------------------------------------
// Action
//------------------------------------------------------------------------
void CActionGoTo::GetPdfLink(CPdfLink* pLink)
{
pLink->nType = 1;
pLink->unPage = unPage;
pLink->nKind = nKind;
switch (nKind)
{
case destXYZ:
case destFitH:
case destFitBH:
case destFitV:
case destFitBV:
{
pLink->unKindFlag = unKindFlag;
if (unKindFlag & (1 << 0))
pLink->pData[0] = pRect[0];
if (unKindFlag & (1 << 1))
pLink->pData[1] = pRect[1];
if (unKindFlag & (1 << 2))
pLink->pData[2] = pRect[2];
break;
}
case destFitR:
{
pLink->pData[0] = pRect[0];
pLink->pData[1] = pRect[1];
pLink->pData[2] = pRect[2];
pLink->pData[3] = pRect[3];
break;
}
case destFit:
case destFitB:
default:
break;
}
if (pNext)
{
pLink->pNext = new CPdfLink();
GetPdfLink(pLink->pNext);
}
}
void CActionURI::GetPdfLink(CPdfLink* pLink)
{
pLink->nType = 6;
pLink->sData = sURI;
if (pNext)
{
pLink->pNext = new CPdfLink();
GetPdfLink(pLink->pNext);
}
}
void CActionNamed::GetPdfLink(CPdfLink* pLink)
{
pLink->nType = 10;
pLink->sData = sNamed;
if (pNext)
{
pLink->pNext = new CPdfLink();
GetPdfLink(pLink->pNext);
}
}
//------------------------------------------------------------------------
// Widget
//------------------------------------------------------------------------
@ -1265,6 +1334,17 @@ CAnnotLink::~CAnnotLink()
RELEASEOBJECT(m_pAction);
RELEASEOBJECT(m_pPA);
}
CPdfLink* CAnnotLink::GetPdfLink()
{
CPdfLink* pRes = new CPdfLink();
pRes->pRect[0] = m_pRect[0];
pRes->pRect[1] = m_pRect[1];
pRes->pRect[2] = m_pRect[2];
pRes->pRect[3] = m_pRect[3];
if (m_pAction)
m_pAction->GetPdfLink(pRes);
return pRes;
}
//------------------------------------------------------------------------
// Screen

View File

@ -41,6 +41,7 @@
#include "../../DesktopEditor/graphics/pro/Fonts.h"
#include "../../DesktopEditor/graphics/pro/Graphics.h"
#include "../../DesktopEditor/graphics/pro/js/wasm/src/serialize.h"
#include "../../DesktopEditor/graphics/pro/officedrawingfile.h"
#include "RendererOutputDev.h"
@ -57,6 +58,7 @@ public:
virtual ~CAction() { RELEASEOBJECT(pNext); }
virtual void ToWASM(NSWasm::CData& oRes);
virtual void GetPdfLink(CPdfLink* pLink) {};
std::string sType;
CAction* pNext;
@ -70,18 +72,21 @@ struct CActionGoTo final : public CAction
double pRect[4];
BYTE nKind;
virtual void GetPdfLink(CPdfLink* pLink) override;
void ToWASM(NSWasm::CData& oRes) override;
};
struct CActionURI final : public CAction
{
std::string sURI;
virtual void GetPdfLink(CPdfLink* pLink) override;
void ToWASM(NSWasm::CData& oRes) override;
};
struct CActionNamed final : public CAction
{
std::string sNamed;
virtual void GetPdfLink(CPdfLink* pLink) override;
void ToWASM(NSWasm::CData& oRes) override;
};
struct CActionJavaScript final : public CAction
@ -347,6 +352,8 @@ public:
CAnnotLink(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID);
virtual ~CAnnotLink();
CPdfLink* GetPdfLink();
void ToWASM(NSWasm::CData& oRes) override;
private:

View File

@ -293,7 +293,7 @@ Object *ObjectStream::getObject(int objIdx, int objNum, Object *obj) {
XRef::XRef(BaseStream *strA, GBool repair) {
GFileOffset pos;
Object obj;
Object obj, root, rootType;
XRefPosSet *posSet;
int i;
@ -370,6 +370,17 @@ XRef::XRef(BaseStream *strA, GBool repair) {
if (obj.isRef()) {
rootNum = obj.getRefNum();
rootGen = obj.getRefGen();
fetch(rootNum, rootGen, &root);
if (!root.isDict() || !root.dictLookup("Type", &rootType)->isName("Catalog"))
{
root.free(); rootType.free();
errCode = errDamaged;
ok = gFalse;
return;
}
root.free(); rootType.free();
obj.free();
} else {
obj.free();
@ -972,6 +983,39 @@ GBool XRef::constructXRef() {
error(errSyntaxError, -1, "Couldn't find trailer dictionary");
return gFalse;
}
// validate the catalog object found by the initial xref scan
if (!quickCheckCatalog(str, entries[rootNum].offset + start)) {
error(errSyntaxWarning, -1, "invalid Catalog, trying repair scan");
// reset state before repair scan
rootNum = -1;
rootGen = -1;
gfree(entries);
entries = NULL;
size = 0;
last = -1;
for (int i = 0; i < xrefCacheSize; ++i) {
if (cache[i].num >= 0) {
cache[i].num = -1;
cache[i].obj.free();
}
}
for (int i = 0; i < objStrCacheLength; ++i) {
delete objStrs[i];
objStrs[i] = NULL;
}
objStrCacheLength = 0;
gfree(xrefTablePos);
xrefTablePos = NULL;
xrefTablePosLen = 0;
if (!trailerDict.isNone()) trailerDict.free();
return constructXRefRepair();
}
return gTrue;
}
@ -1016,6 +1060,316 @@ GBool XRef::saveTrailerDict(Dict *dict, GBool isXRefStream) {
return bRes;
}
// quick check: is the object at the given offset a /Type /Catalog dict?
GBool XRef::quickCheckCatalog(BaseStream *str, GFileOffset pos) {
if (pos < 0) return gFalse;
char buf[512];
str->setPos(pos);
int n = str->getBlock(buf, sizeof(buf) - 1);
if (n <= 0) return gFalse;
buf[n] = '\0';
// skip "N G obj"
char *p = strstr(buf, " obj");
if (!p) return gFalse;
p += 4;
// look for /Type key
char *t = strstr(p, "/Type");
if (!t || t - buf > 450) return gFalse;
t += 5;
// skip whitespace between /Type and its value
while (*t == ' ' || *t == '\t' || *t == '\r' || *t == '\n') ++t;
// value may be "/Catalog" or "/ Catalog" — skip the slash
if (*t == '/') ++t;
while (*t == ' ' || *t == '\t') ++t;
return strncmp(t, "Catalog", 7) == 0;
}
GFileOffset XRef::findValidCutoff(XRefTempEntry *tempEntries, int tempSize, std::vector<XRefTrailerCandidate> &candidates) {
for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) {
XRefTrailerCandidate &c = *it;
GFileOffset rootPos = c.rootObjPos;
if (rootPos < 0 && c.rootNum < tempSize && tempEntries[c.rootNum].used)
rootPos = tempEntries[c.rootNum].offset;
if (rootPos < 0) continue;
if (quickCheckCatalog(str, rootPos + start)) {
return (c.sectionEnd >= 0) ? c.sectionEnd : c.trailerPos;
}
}
return -1;
}
GBool XRef::constructXRefRepair() {
int tempSize = 0;
XRefTempEntry *tempEntries = NULL;
auto ensureTemp = [&](int num) {
if (num >= tempSize) {
int newSize = num + 256;
tempEntries = (XRefTempEntry *)greallocn(
tempEntries, newSize, sizeof(XRefTempEntry));
for (int i = tempSize; i < newSize; ++i) {
tempEntries[i].offset = -1;
tempEntries[i].gen = 0;
tempEntries[i].used = gFalse;
}
tempSize = newSize;
}
};
std::vector<XRefTrailerCandidate> candidates;
int tmpStreamEndsSize = 0;
int tmpStreamEndsLen = 0;
GFileOffset *tmpStreamEnds = NULL;
// ---------- PASS 1 ----------
{
char buf[4096 + 1];
str->reset();
GFileOffset bufPos = start;
char *p = buf;
char *end = buf;
GBool startOfLine = gTrue;
GBool eof = gFalse;
GFileOffset sectionStart = start;
while (1) {
if (end - p < 256 && !eof) {
memmove(buf, p, end - p);
bufPos += p - buf;
p = buf + (end - p);
int n = (int)(buf + 4096 - p);
int m = str->getBlock(p, n);
end = p + m;
*end = '\0';
p = buf;
eof = m < n;
}
if (p == end && eof) break;
GFileOffset curPos = (GFileOffset)(bufPos + (p - buf));
// %%EOF — close current section
if (startOfLine && p[0] == '%' && !strncmp(p, "%%EOF", 5)) {
for (auto &c : candidates)
if (c.sectionEnd < 0 && c.sectionStart == sectionStart)
c.sectionEnd = curPos;
sectionStart = curPos + 5;
p += 5;
startOfLine = gFalse;
continue;
}
if (startOfLine && !strncmp(p, "endstream", 9)) {
if (tmpStreamEndsLen == tmpStreamEndsSize) {
tmpStreamEndsSize += 64;
tmpStreamEnds = (GFileOffset *)greallocn(
tmpStreamEnds, tmpStreamEndsSize, sizeof(GFileOffset));
}
tmpStreamEnds[tmpStreamEndsLen++] = curPos;
p += 9;
startOfLine = gFalse;
continue;
}
if (startOfLine && !strncmp(p, "trailer", 7)) {
GFileOffset tPos = (GFileOffset)(bufPos + (p + 7 - buf));
Object tDict, obj;
obj.initNull();
Parser *parser = new Parser(
NULL,
new Lexer(NULL, str->makeSubStream(tPos, gFalse, 0, &obj)),
gFalse);
parser->getObj(&tDict);
if (tDict.isDict()) {
Object rootRef;
tDict.getDict()->lookupNF("Root", &rootRef);
if (rootRef.isRef()) {
int rNum = rootRef.getRefNum();
ensureTemp(rNum);
XRefTrailerCandidate c;
c.trailerPos = tPos;
c.sectionStart = sectionStart;
c.sectionEnd = -1;
c.rootNum = rNum;
c.rootGen = rootRef.getRefGen();
// rootObjPos — берём то что уже видели к этому моменту
c.rootObjPos = tempEntries[rNum].used
? tempEntries[rNum].offset
: -1;
candidates.push_back(c);
}
rootRef.free();
}
tDict.free();
delete parser;
p += 7;
startOfLine = gFalse;
continue;
}
// N G obj — write to tempEntries only
if (startOfLine && *p >= '0' && *p <= '9') {
char *q = p;
int num = 0, gen = 0;
do { num = num * 10 + (*q - '0'); ++q; }
while (*q >= '0' && *q <= '9' && num < 100000000);
if (*q == '\t' || *q == '\x0c' || *q == ' ') {
do { ++q; } while (*q == '\t' || *q == '\x0c' || *q == ' ');
if (*q >= '0' && *q <= '9') {
do { gen = gen * 10 + (*q - '0'); ++q; }
while (*q >= '0' && *q <= '9' && gen < 100000000);
if ((*q == '\t' || *q == '\x0c' || *q == ' ') &&
!strncmp(q + 1, "obj", 3)) {
ensureTemp(num);
// will be overwritten — pass 2 is bounded by cutoff
tempEntries[num].offset = curPos - start;
tempEntries[num].gen = gen;
tempEntries[num].used = gTrue;
}
}
}
while (*p && *p != '\n' && *p != '\r') ++p;
startOfLine = gFalse;
continue;
}
startOfLine = (*p == '\n' || *p == '\r');
++p;
}
} // end of pass 1
// ---------- VALIDATION ----------
GFileOffset cutoffPos = findValidCutoff(tempEntries, tempSize, candidates);
gfree(tempEntries);
gfree(tmpStreamEnds);
if (cutoffPos < 0) {
error(errSyntaxWarning, -1, "no valid Catalog found, scanning entire file");
cutoffPos = str->getPos();
}
// ---------- PASS 2 ----------
// identical to original constructXRef, but stops at curPos >= cutoffPos
int streamObjNumsSize = 0;
int streamObjNumsLen = 0;
int *streamObjNums = NULL;
int lastObjNum = -1;
rootNum = -1;
gfree(streamEnds);
streamEnds = NULL;
streamEndsLen = 0;
int streamEndsSize = 0;
{
char buf[4096 + 1];
str->reset();
GFileOffset bufPos = start;
char *p = buf;
char *end = buf;
GBool startOfLine = gTrue;
GBool eof = gFalse;
while (1) {
if (end - p < 256 && !eof) {
memmove(buf, p, end - p);
bufPos += p - buf;
p = buf + (end - p);
int n = (int)(buf + 4096 - p);
int m = str->getBlock(p, n);
end = p + m;
*end = '\0';
p = buf;
eof = m < n;
}
if (p == end && eof) break;
GFileOffset curPos = (GFileOffset)(bufPos + (p - buf));
if (curPos - start >= cutoffPos)
break;
if (startOfLine && !strncmp(p, "trailer", 7)) {
constructTrailerDict((GFileOffset)(bufPos + (p + 7 - buf)));
p += 7;
startOfLine = gFalse;
} else if (startOfLine && !strncmp(p, "endstream", 9)) {
if (streamEndsLen == streamEndsSize) {
streamEndsSize += 64;
streamEnds = (GFileOffset *)greallocn(
streamEnds, streamEndsSize, sizeof(GFileOffset));
}
streamEnds[streamEndsLen++] = curPos;
p += 9;
startOfLine = gFalse;
} else if (startOfLine && *p >= '0' && *p <= '9') {
p = constructObjectEntry(p, (GFileOffset)(bufPos + (p - buf)),
&lastObjNum);
startOfLine = gFalse;
} else if (p[0] == '>' && p[1] == '>') {
p += 2;
startOfLine = gFalse;
while (*p == '\t' || *p == '\n' || *p == '\x0c' ||
*p == '\r' || *p == ' ') {
startOfLine = (*p == '\n' || *p == '\r');
++p;
}
if (!strncmp(p, "stream", 6)) {
if (lastObjNum >= 0) {
if (streamObjNumsLen == streamObjNumsSize) {
streamObjNumsSize += 64;
streamObjNums = (int *)greallocn(
streamObjNums, streamObjNumsSize, sizeof(int));
}
streamObjNums[streamObjNumsLen++] = lastObjNum;
}
p += 6;
startOfLine = gFalse;
}
} else {
startOfLine = (*p == '\n' || *p == '\r');
++p;
}
}
} // end of pass 2
GBool bRoot = gFalse;
for (int i = 0; i < streamObjNumsLen; ++i) {
Object obj;
fetch(streamObjNums[i], entries[streamObjNums[i]].gen, &obj);
if (obj.isStream()) {
Dict *dict = obj.streamGetDict();
Object type;
dict->lookup("Type", &type);
if (type.isName("XRef") && !bRoot) {
bRoot = saveTrailerDict(dict, gTrue);
} else if (type.isName("ObjStm")) {
constructObjectStreamEntries(&obj, streamObjNums[i]);
}
type.free();
}
obj.free();
}
gfree(streamObjNums);
if (rootNum < 0) {
error(errSyntaxError, -1, "Couldn't find trailer dictionary");
return gFalse;
}
return gTrue;
}
// Look for an object header ("nnn ggg obj") at [p]. The first
// character at *[p] is a digit. [pos] is the position of *[p].
char *XRef::constructObjectEntry(char *p, GFileOffset pos, int *objNum) {

View File

@ -10,6 +10,7 @@
#define XREF_H
#include <aconf.h>
#include <vector>
#ifdef USE_GCC_PRAGMAS
#pragma interface
@ -50,6 +51,21 @@ struct XRefCacheEntry {
Object obj;
};
struct XRefTempEntry {
GFileOffset offset;
int gen;
GBool used;
};
struct XRefTrailerCandidate {
GFileOffset trailerPos;
GFileOffset sectionStart;
GFileOffset sectionEnd;
GFileOffset rootObjPos; // Root object offset at the time the trailer was encountered
int rootNum;
int rootGen;
};
#define xrefCacheSize 16
#define objStrCacheSize 128
@ -179,6 +195,9 @@ private:
void constructObjectStreamEntries(Object *objStr, int objStrObjNum);
GBool constructXRefEntry(int num, int gen, GFileOffset pos,
XRefEntryType type);
GBool constructXRefRepair();
GFileOffset findValidCutoff(XRefTempEntry *tempEntries, int tempSize, std::vector<XRefTrailerCandidate> &candidates);
static GBool quickCheckCatalog(BaseStream *str, GFileOffset pos);
GBool getObjectStreamObject(int objStrNum, int objIdx,
int objNum, Object *obj);
ObjectStream *getObjectStream(int objStrNum);