Compare commits

..

13 Commits

Author SHA1 Message Date
5b4c6363bb OdfFormat - fix layouts 2017-05-13 16:05:23 +03:00
2026d064ef DocFormatReader - fix shape freeforms 2017-05-13 16:04:54 +03:00
42257ca447 verify ooxml file. developing... 2017-05-12 18:59:57 +03:00
6f2fdcd971 verify ooxml file. developing... 2017-05-12 18:25:18 +03:00
9b4b7a26fd verify ooxml file. developing... 2017-05-12 18:04:13 +03:00
4d688b3922 . 2017-05-12 13:46:13 +03:00
be8d427e26 . 2017-05-12 13:17:26 +03:00
7e0749ddda partly fix bug #18056 2017-05-12 11:33:04 +03:00
9f2324d208 verify ooxml file. developing... 2017-05-12 11:24:04 +03:00
6e258b85d7 . 2017-05-11 19:02:56 +03:00
24e55018a0 . 2017-05-11 18:43:24 +03:00
2352ae5d88 PptFormatReader - fix line shape ends 2017-05-11 18:08:46 +03:00
2cba43e6f3 . 2017-05-11 17:56:47 +03:00
35 changed files with 1638 additions and 704 deletions

View File

@ -35,11 +35,23 @@
namespace DocFileFormat
{
struct _guides
{
unsigned char type;
unsigned char param_type1;
unsigned char param_type2;
unsigned char param_type3;
WORD param1;
WORD param2;
WORD param3;
};
class PathParser
{
public:
PathParser (const unsigned char* pSegmentInfo, unsigned int pSegmentInfoSize, const unsigned char* pVertices, unsigned int pVerticesSize)
PathParser (const unsigned char* pSegmentInfo, unsigned int pSegmentInfoSize, const unsigned char* pVertices, unsigned int pVerticesSize, std::vector<_guides> & guides)
{
if ((pSegmentInfo != NULL) && (pSegmentInfoSize > 0))
{
@ -105,31 +117,40 @@ namespace DocFileFormat
unsigned short nElemsAlloc = FormatUtils::BytesToUInt16(pVertices, 2, pVerticesSize);
unsigned short cb = FormatUtils::BytesToUInt16(pVertices, 4, pVerticesSize);
if (0xfff0 == cb)
{
cb = 4;
for (unsigned short i = 0; i < nElems; ++i)
for (unsigned short i = 0; i < nElems; ++i)
{
POINT point;
if (0xfff0 == cb)
{
POINT point;
cb = 4;
point.x = FormatUtils::BytesToInt16(pVertices + 6, (i * cb), pVerticesSize);
point.y = FormatUtils::BytesToInt16(pVertices + 6, (i * cb) + (cb / 2), pVerticesSize);
m_arPoints.push_back(point);
}
}
else
{
for (unsigned short i = 0; i < nElems; ++i)
else
{
POINT point;
point.x = FormatUtils::BytesToInt32(pVertices + 6, (i * cb), pVerticesSize);
point.y = FormatUtils::BytesToInt32(pVertices + 6, (i * cb) + (cb / 2), pVerticesSize);
m_arPoints.push_back(point);
}
LONG lMinF = (LONG)0x80000000;
if (lMinF <= point.x)
{
int index = (DWORD)point.x - 0x80000000;
if (index >= 0 && index < guides.size())
{
point.x = guides[index].param3;
}
}
if (lMinF <= point.y)
{
int index = (DWORD)point.y - 0x80000000;
if (index >= 0 && index < guides.size())
{
point.y = guides[index].param3;
}
}
m_arPoints.push_back(point);
}
}
}

View File

@ -106,21 +106,20 @@ namespace DocFileFormat
return new ShapeContainer( _reader, bodySize, typeCode, version, instance );
}
std::list<OptionEntry> ExtractOptions() const
std::vector<OptionEntryPtr> ExtractOptions() const
{
std::list<OptionEntry> ret;
std::vector<OptionEntryPtr> ret;
//build the list of all option entries of this shape
for ( std::vector<Record*>::const_iterator iter = this->Children.begin(); iter != this->Children.end(); iter++ )
{
ShapeOptions* opt = dynamic_cast<ShapeOptions*>( *iter );
if ( opt != NULL )
if ( opt == NULL ) continue;
for ( size_t i = 0; i < opt->Options.size(); i++)
{
for ( std::vector<OptionEntry>::iterator oeIter = opt->Options.begin(); oeIter != opt->Options.end(); oeIter++ )
{
ret.push_back( *oeIter );
}
ret.push_back( opt->Options[i]);
}
}

View File

@ -568,18 +568,19 @@ namespace DocFileFormat
struct OptionEntry
{
OptionEntry() : pid(PropertyId_left), fBid(false), fComplex(false), op(0), opComplex(NULL)
OptionEntry() : pid(PropertyId_left), fBid(false), fComplex(false), op(0)
{
}
PropertyId pid;
bool fBid;
bool fComplex;
unsigned int op;
unsigned char* opComplex;
std::shared_ptr<unsigned char> opComplex;
};
typedef std::shared_ptr<OptionEntry> OptionEntryPtr;
class ShapeOptions: public Record
{
public:
@ -587,8 +588,8 @@ namespace DocFileFormat
static const unsigned short TYPE_CODE_0xF121 = 0xF121;
static const unsigned short TYPE_CODE_0xF122 = 0xF122;
std::vector<OptionEntry> Options;
std::map<PropertyId, OptionEntry> OptionsByID;
std::vector<OptionEntryPtr> Options;
std::map<PropertyId, OptionEntryPtr> OptionsByID;
ShapeOptions() : Record()
{
@ -596,8 +597,8 @@ namespace DocFileFormat
virtual ~ShapeOptions()
{
for (std::vector<OptionEntry>::iterator iter = Options.begin(); iter != Options.end(); ++iter)
RELEASEARRAYOBJECTS( iter->opComplex );
//for (std::vector<OptionEntry>::iterator iter = Options.begin(); iter != Options.end(); ++iter)
// RELEASEARRAYOBJECTS( iter->opComplex );
}
ShapeOptions (IBinaryReader* _reader, unsigned int size, unsigned int typeCode, unsigned int version, unsigned int instance) : Record (_reader, size, typeCode, version, instance)
@ -606,16 +607,16 @@ namespace DocFileFormat
//instance is the count of properties stored in this record
OptionEntry entry;
//parse the flags and the simple values
for (unsigned int i = 0; i < instance; ++i)
{
OptionEntryPtr entry = std::shared_ptr<OptionEntry>(new OptionEntry());
unsigned short flag = Reader->ReadUInt16();
entry.pid = (PropertyId)FormatUtils::BitmaskToInt (flag, 0x3FFF);
entry.fBid = FormatUtils::BitmaskToBool (flag, 0x4000);
entry.fComplex = FormatUtils::BitmaskToBool (flag, 0x8000);
entry.op = Reader->ReadUInt32();
entry->pid = (PropertyId)FormatUtils::BitmaskToInt (flag, 0x3FFF);
entry->fBid = FormatUtils::BitmaskToBool (flag, 0x4000);
entry->fComplex = FormatUtils::BitmaskToBool (flag, 0x8000);
entry->op = Reader->ReadUInt32();
Options.push_back( entry );
}
@ -625,21 +626,12 @@ namespace DocFileFormat
//of the OptionEntry arry, sorted by pid
for (unsigned int i = 0; i < instance; ++i)
{
if (Options[i].fComplex)
{
int read_size = (int)Options[i].op + 6 ; //????
//todooo !!!! проверить все остальные !! тут размер в зависимости от типа Complex!!!
switch(Options[i].pid)
{
case PropertyId::gtextUNICODE:
case PropertyId::gtextFont:
read_size = (int)Options[i].op;
break;
}
Options[i].opComplex = Reader->ReadBytes( read_size, true );
if (Options[i]->fComplex && Options[i]->op > 0)
{
Options[i]->opComplex = std::shared_ptr<unsigned char>(Reader->ReadBytes( Options[i]->op, true ));
}
OptionsByID.insert(std::pair<PropertyId, OptionEntry>(Options[i].pid, Options[i]));
OptionsByID.insert(std::make_pair(Options[i]->pid, Options[i]));
}
Reader->Seek(( pos + size ), 0/*STREAM_SEEK_SET*/);

View File

@ -241,7 +241,7 @@ namespace DocFileFormat
std::wstring strHeight = FormatUtils::DoubleToWideString( height.ToPoints() );
std::wstring strStyle;
std::list<OptionEntry> options;
std::vector<OptionEntryPtr> options;
PictureFrameType type;
if ((pict->shapeContainer || pict->blipStoreEntry) && pict->shapeContainer->Children.size() > 0)
@ -282,9 +282,9 @@ namespace DocFileFormat
}
//todooo oбъединить с shape_mapping
std::list<OptionEntry>::iterator end = options.end();
for (std::list<OptionEntry>::iterator iter = options.begin(); iter != end; ++iter)
for (size_t i = 0; i < options.size(); i++)
{
OptionEntryPtr & iter = options[i];
switch ( iter->pid )
{
case wzEquationXML:
@ -292,7 +292,7 @@ namespace DocFileFormat
m_isEquation = true;
m_isEmbedded = true;
m_embeddedData = std::string((char*)iter->opComplex, iter->op);
m_embeddedData = std::string((char*)iter->opComplex.get(), iter->op);
if (ParseEmbeddedEquation( m_embeddedData, m_equationXml))
{
@ -303,7 +303,7 @@ namespace DocFileFormat
{
//встроенная неведомая хуйня
m_isEmbedded = true;
m_embeddedData = std::string((char*)iter->opComplex, iter->op);
m_embeddedData = std::string((char*)iter->opComplex.get(), iter->op);
//if (ParseEmbeddedBlob( m_embeddedData, m_blobXml)) // todoooo
//{

View File

@ -143,8 +143,9 @@ namespace DocFileFormat
ShapeContainer* groupShape = static_cast<ShapeContainer*>(container->Children[0]);
GroupShapeRecord* gsr = static_cast<GroupShapeRecord*>(groupShape->Children[0]);
Shape* shape = static_cast<Shape*>(groupShape->Children[1]);
std::list<OptionEntry> options = groupShape->ExtractOptions();
ChildAnchor* anchor = groupShape->FirstChildWithType<ChildAnchor>();
ChildAnchor* anchor = groupShape->FirstChildWithType<ChildAnchor>();
std::vector<OptionEntryPtr> options = groupShape->ExtractOptions();
m_shapeId = GetShapeID(shape);
@ -155,14 +156,13 @@ namespace DocFileFormat
m_pXmlWriter->WriteAttribute( L"coordsize", ( FormatUtils::IntToWideString(gsr->rcgBounds.size.cx) + L"," + FormatUtils::IntToWideString(gsr->rcgBounds.size.cy)));
// Write wrap coords
std::list<OptionEntry>::const_iterator end = options.end();
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
for (size_t i = 0; i < options.size(); i++)
{
switch (iter->pid)
switch (options[i]->pid)
{
case pWrapPolygonVertices:
case pWrapPolygonVertices:
{
std::wstring wrapCoords = getWrapCoords(*iter);
std::wstring wrapCoords = GetWrapCoords(options[i]);
if (wrapCoords.length())
m_pXmlWriter->WriteAttribute(L"wrapcoords", wrapCoords);
}
@ -226,9 +226,9 @@ namespace DocFileFormat
bool freeform = true;
std::wstring sShapeId;
std::list<OptionEntry> options = pContainer->ExtractOptions();
ChildAnchor* pAnchor = pContainer->FirstChildWithType<ChildAnchor>();
ClientAnchor* clientAnchor = pContainer->FirstChildWithType<ClientAnchor>();
std::vector<OptionEntryPtr> options = pContainer->ExtractOptions();
ChildAnchor* pAnchor = pContainer->FirstChildWithType<ChildAnchor>();
ClientAnchor* clientAnchor = pContainer->FirstChildWithType<ClientAnchor>();
WriteBeginShapeNode (pShape);
@ -294,13 +294,17 @@ namespace DocFileFormat
std::wstring sTextboxStyle;
std::wstring adjValues[8];
ShadowStyleBooleanProperties shadowBoolean(0);
std::vector<std::wstring> arrInscribe;
OptionEntryPtr opSegmentInfo;
OptionEntryPtr opVerticles;
OptionEntryPtr opInscribe;
OptionEntryPtr opConnectAngles;
OptionEntryPtr opConnectLocs;
std::list<OptionEntry>::const_iterator end = options.end();
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
for (size_t i = 0; i < options.size(); i++)
{
OptionEntryPtr & iter = options[i];
switch (iter->pid)
{
//BOOLEANS
@ -335,19 +339,16 @@ namespace DocFileFormat
}
}
break;
case protectionBooleans:
{
ProtectionBooleanProperties booleans(iter->op);
}
break;
case diagramBooleans:
{
DiagramBooleanProperties booleans(iter->op);
}
break;
case groupShapeBooleans:
{
GroupShapeBooleanProperties booleans(iter->op);
@ -357,56 +358,80 @@ namespace DocFileFormat
}
}
break;
// GEOMETRY
// GEOMETRY
case shapePath :
{
bHavePath = true;
}break;
case pVertices:
{
opVerticles = iter;
}break;
case pSegmentInfo:
{
opSegmentInfo = iter;
}break;
case pGuides:
{
GetGuides(iter);
}break;
case pConnectionSites:
{
opConnectLocs = iter;
}break;
case pConnectionSitesDir:
{
opConnectAngles = iter;
}break;
case pInscribe:
{
opInscribe = iter;
}break;
case adjustValue:
{
adjValues[0] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,1);
m_nAdjValues[0] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues,1);
}
break;
case adjust2Value:
{
adjValues[1] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,2);
m_nAdjValues[1] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 2);
}
break;
case adjust3Value:
{
adjValues[2] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,3);
m_nAdjValues[2] = (int)iter->op;
nAdjValues =(std::max)(nAdjValues, 3);
}break;
case adjust4Value:
{
adjValues[3] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,4);
m_nAdjValues[3] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 4);
}break;
case adjust5Value:
{
adjValues[4] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,5);
m_nAdjValues[4] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 5);
}break;
case adjust6Value:
{
adjValues[5] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,6);
m_nAdjValues[5] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 6);
}break;
case adjust7Value:
{
adjValues[6] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,7);
m_nAdjValues[6] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 7);
}break;
case adjust8Value:
{
adjValues[7] = FormatUtils::IntToWideString( (int)iter->op );
nAdjValues = (std::max)(nAdjValues,8);
m_nAdjValues[7] = (int)iter->op;
nAdjValues = (std::max)(nAdjValues, 8);
}break;
case pWrapPolygonVertices:
{
std::wstring wrapCoords = getWrapCoords(*iter);
std::wstring wrapCoords = GetWrapCoords(iter);
if (!wrapCoords.empty())
{
@ -421,13 +446,6 @@ namespace DocFileFormat
{
yCoord = iter->op;
}break;
case pGuides:
{
}break;
case pInscribe:
{
arrInscribe = GetTextRectangles(*iter);
}break;
// OUTLINE
case lineColor:
{
@ -497,7 +515,7 @@ namespace DocFileFormat
}break;
case fillShadeColors:
{
appendValueAttribute(&m_fill, L"colors", getFillColorString( iter->opComplex, iter->op ));
appendValueAttribute(&m_fill, L"colors", getFillColorString( iter->opComplex.get(), iter->op ));
}break;
case fillFocus:
{
@ -602,7 +620,7 @@ namespace DocFileFormat
case pibName:
{
std::wstring name;
FormatUtils::GetSTLCollectionFromBytes<std::wstring>(&name, iter->opComplex, iter->op, ENCODING_UTF16);
FormatUtils::GetSTLCollectionFromBytes<std::wstring>(&name, iter->opComplex.get(), iter->op, ENCODING_UTF16);
if (!name.empty())
appendValueAttribute(&m_imagedata, L"o:title", FormatUtils::XmlEncode(name));
}break;
@ -676,10 +694,10 @@ namespace DocFileFormat
hasTextbox = true;
nLTxID = (((iter->op) >> 16) & 0xFFFF);
}break;
case dxTextLeft: {ndxTextLeft = (int)iter->op;break;}
case dyTextTop: {ndyTextTop = (int)iter->op;break;}
case dxTextRight: {ndxTextRight = (int)iter->op;break;}
case dyTextBottom: {ndyTextBottom = (int)iter->op;break;}
case dxTextLeft: {ndxTextLeft = (int)iter->op; break;}
case dyTextTop: {ndyTextTop = (int)iter->op; break;}
case dxTextRight: {ndxTextRight = (int)iter->op; break;}
case dyTextBottom: {ndyTextBottom = (int)iter->op; break;}
case txflTextFlow:
{
switch(iter->op)
@ -700,7 +718,7 @@ namespace DocFileFormat
// Word Art
case gtextUNICODE:
{
std::wstring text = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)iter->opComplex, (iter->op)/2);
std::wstring text = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)iter->opComplex.get(), (iter->op)/2);
text = FormatUtils::XmlEncode(text);
@ -713,7 +731,7 @@ namespace DocFileFormat
}break;
case gtextFont:
{
std::wstring font = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)iter->opComplex, (iter->op)/2);
std::wstring font = NSStringExt::CConverter::GetUnicodeFromUTF16((unsigned short*)iter->opComplex.get(), (iter->op)/2);
int i = font.size();
while (i > 0)
{
@ -764,31 +782,31 @@ namespace DocFileFormat
appendStyleProperty(&m_textPathStyle, L"font-weight", L"bold");
}
}break;
// PATH
case shapePath :
{
bHavePath = true;
std::wstring path = ParsePath(options);
if (false == path.empty())
m_pXmlWriter->WriteAttribute (L"path", path);
}break;
default:
default:
{
int val = iter->op;
}break;
}
}
if (false == bHavePath) // фигура может быть задана только наборами вершин и индексов
if (opVerticles && opSegmentInfo)
{
std::wstring path = ParsePath(options);
const unsigned char* pVP = opVerticles->opComplex.get();
unsigned int nVP = opVerticles->op;
const unsigned char* pSI = opSegmentInfo->opComplex.get();
unsigned int nSI = opSegmentInfo->op;
PathParser oParser (pSI, nSI, pVP, nVP, m_arrGuides);
std::wstring path = oParser.GetVmlPath();
if (false == path.empty())
m_pXmlWriter->WriteAttribute (L"path", path);
}
if (freeform && (xCoord == 0 || yCoord == 0 ))
{
xCoord = 21600;
yCoord = 21600;
}
if ( !filled )
{
m_pXmlWriter->WriteAttribute( L"filled", L"f" );
@ -804,10 +822,10 @@ namespace DocFileFormat
m_pXmlWriter->WriteAttribute(L"o:allowincell", L"f");
}
if ( ( xCoord > 0 ) && ( yCoord > 0 ) )
if ( xCoord > 0 && yCoord > 0 )
{
m_pXmlWriter->WriteAttribute( L"coordsize", ( FormatUtils::IntToWideString( xCoord ) + L"," + FormatUtils::IntToWideString( yCoord ) ));
}
}
int nCode = 0;
if (pShape->GetShapeType())
@ -819,17 +837,17 @@ namespace DocFileFormat
{
if (nAdjValues)
{
m_pXmlWriter->WriteAttribute(L"arcsize", adjValues[0]);
m_pXmlWriter->WriteAttribute(L"arcsize", m_nAdjValues[0]);
}
}
else
{
if (nAdjValues)
if (nAdjValues > 0)
{
std::wstring adjTag = adjValues[0];
std::wstring adjTag = std::to_wstring(m_nAdjValues[0]);
for (int i = 1; i < nAdjValues; ++i)
adjTag += std::wstring(L",") + adjValues[i];
adjTag += L"," + std::to_wstring(m_nAdjValues[i]);
m_pXmlWriter->WriteAttribute(L"adj", adjTag);
}
@ -982,10 +1000,24 @@ namespace DocFileFormat
}
if (freeform)
{
if (arrInscribe.size())
if (opInscribe || opConnectAngles || opConnectLocs)
{
std::vector<std::wstring> arrInscribe = GetTextRectangles(opInscribe);
std::wstring strConnectAngles = GetConnectAngles(opConnectAngles);
std::wstring strConnectLocs = GetConnectLocs(opConnectLocs);
m_pXmlWriter->WriteNodeBegin(L"v:path", true);
m_pXmlWriter->WriteAttribute(L"textboxrect", arrInscribe[0]);
if (!arrInscribe.empty())
m_pXmlWriter->WriteAttribute(L"textboxrect", arrInscribe[0]);
if (!strConnectAngles.empty() || !strConnectLocs.empty())
{
m_pXmlWriter->WriteAttribute(L"o:connecttype", L"custom");
if (!strConnectLocs.empty())
m_pXmlWriter->WriteAttribute(L"o:connectlocs", strConnectLocs);
if (!strConnectAngles.empty())
m_pXmlWriter->WriteAttribute(L"o:connectangles", strConnectAngles);
}
m_pXmlWriter->WriteNodeEnd(L"", true);
}
}
@ -1182,11 +1214,13 @@ namespace DocFileFormat
}
/// Build the VML wrapcoords string for a given pWrapPolygonVertices
std::wstring VMLShapeMapping::getWrapCoords(const OptionEntry& pWrapPolygonVertices) const
std::wstring VMLShapeMapping::GetWrapCoords(const OptionEntryPtr& pWrapPolygonVertices) const
{
if (!pWrapPolygonVertices) return L"";
std::wstring coords;
MemoryStream oStream(pWrapPolygonVertices.opComplex, pWrapPolygonVertices.op);
MemoryStream oStream(pWrapPolygonVertices->opComplex.get(), pWrapPolygonVertices->op);
std::list<int> arrVertices;
unsigned short nElems = oStream.ReadUInt16();
@ -1498,7 +1532,7 @@ namespace DocFileFormat
}
}
void VMLShapeMapping::AppendOptionsToStyle (std::wstring* oStyle, const std::list<OptionEntry>& options, int zIndex) const
void VMLShapeMapping::AppendOptionsToStyle (std::wstring* oStyle, const std::vector<OptionEntryPtr>& options, int zIndex) const
{
bool bRelH = false;
bool bRelV = false;
@ -1508,9 +1542,9 @@ namespace DocFileFormat
bool bZIndex = false;
std::list<OptionEntry>::const_iterator end = options.end();
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
for (size_t i = 0; i < options.size(); i++)
{
const OptionEntryPtr & iter = options[i];
switch (iter->pid)
{
// POSITIONING
@ -1616,15 +1650,16 @@ namespace DocFileFormat
}
//
std::wstring VMLShapeMapping::buildStyle (const Shape* shape, const ChildAnchor* anchor, const std::list<OptionEntry>& options, int zIndex) const
std::wstring VMLShapeMapping::buildStyle (const Shape* shape, const ChildAnchor* anchor, const std::vector<OptionEntryPtr>& options, int zIndex) const
{
std::wstring style;
// Check if some properties are set that cause the dimensions to be twisted
bool twistDimensions = false;
std::list<OptionEntry>::const_iterator end = options.end();
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
for (size_t i = 0; i < options.size(); i++)
{
const OptionEntryPtr & iter = options[i];
if (geometryTextBooleanProperties == iter->pid)
{
GeometryTextBooleanProperties props(iter->op);
@ -1860,61 +1895,210 @@ namespace DocFileFormat
return wrapType;
}
std::wstring VMLShapeMapping::ParsePath (const std::list<OptionEntry>& options) const
std::wstring VMLShapeMapping::GetConnectAngles(const OptionEntryPtr& opAngles) const
{
const unsigned char* pVP = NULL;
unsigned int nVP = 0;
const unsigned char* pSI = NULL;
unsigned int nSI = 0;
if (!opAngles) return L"";
if (!opAngles->opComplex) return L"";
std::list<OptionEntry>::const_iterator end = options.end();
for (std::list<OptionEntry>::const_iterator iter = options.begin(); iter != end; ++iter)
MemoryStream reader(opAngles->opComplex.get(), opAngles->op);
unsigned short nElems = reader.ReadUInt16();
unsigned short nElemsAlloc = reader.ReadUInt16();
unsigned short nElemSize = reader.ReadUInt16();
bool bTruncated = false;
if (0xFFF0 == nElemSize)
{
nElemSize = 4;
bTruncated = true;
}
long dwSize = nElems * nElemSize;
if (opAngles->op - 6 != (dwSize))
{
bool b = false;
}
if (nElemSize < 1) return L"";
int count = dwSize / nElemSize;
std::wstring angles;
for (int i = 0; i < count; ++i)
{
if (iter->pid == pVertices)
{
pVP = iter->opComplex;
nVP = iter->op;
}
if (iter->pid == pSegmentInfo)
{
pSI = iter->opComplex;
nSI = iter->op;
}
DWORD v = reader.ReadUInt32();
double val = (double)((WORD)(v >> 16) + ((WORD)(v) / 65536.0));
angles += std::to_wstring((int)val) + (i < (count - 1) ? L"," : L"");
}
return angles;
}
int VMLShapeMapping::UpdateFromGuides(const int val) const
{
int new_val = val;
LONG lMinF = (LONG)0x80000000;
if (lMinF <= val)
{
int index = (DWORD)val - 0x80000000;
if (index >= 0 && index < m_arrGuides.size())
{
new_val = m_arrGuides[index].param3;
}
PathParser oParser (pSI, nSI, pVP, nVP);
return oParser.GetVmlPath();
}
return new_val;
}
void VMLShapeMapping::GetGuides( const OptionEntryPtr& opGuides )
{
if (!opGuides) return;
if (!opGuides->opComplex) return;
MemoryStream reader(opGuides->opComplex.get(), opGuides->op);
unsigned short nElems = reader.ReadUInt16();
unsigned short nElemsAlloc = reader.ReadUInt16();
unsigned short nElemSize = reader.ReadUInt16();
bool bTruncated = false;
if (0xFFF0 == nElemSize)
{
nElemSize = 4;
bTruncated = true;
}
long dwSize = nElems * nElemSize;
if (opGuides->op - 6 != (dwSize))
{
bool b = false;
}
int count = dwSize / nElemSize; //1x (int or short)
for (int i = 0; i < count; ++i)
{
_guides g;
WORD flags = reader.ReadUInt16();
g.type = flags & 0x1FFF;
g.param_type1 = (unsigned char)(flags & 0x04);
g.param_type2 = (unsigned char)(flags & 0x02);
g.param_type3 = (unsigned char)(flags & 0x01);
g.param1 = reader.ReadUInt16();
g.param2 = reader.ReadUInt16();
g.param3 = reader.ReadUInt16();
m_arrGuides.push_back(g);
}
}
//
std::vector<std::wstring> VMLShapeMapping::GetTextRectangles(const OptionEntry& inscribe) const
std::wstring VMLShapeMapping::GetConnectLocs( const OptionEntryPtr& opLocs ) const
{
MemoryStream reader(inscribe.opComplex, inscribe.op + 6);
if (!opLocs) return L"";
if (!opLocs->opComplex) return L"";
unsigned short elems = reader.ReadUInt16();
unsigned short allocElems = reader.ReadUInt16();
unsigned short cb = reader.ReadUInt16();
MemoryStream reader(opLocs->opComplex.get(), opLocs->op);
unsigned short nElems = reader.ReadUInt16();
unsigned short nElemsAlloc = reader.ReadUInt16();
unsigned short nElemSize = reader.ReadUInt16();
bool bTruncated = false;
if (0xFFF0 == nElemSize)
{
nElemSize = 4;
bTruncated = true;
}
long dwSize = nElems * nElemSize;
if (opLocs->op - 6 != (dwSize))
{
bool b = false;
}
int count = dwSize / nElemSize; //2x (int or short)
std::wstring locs;
for (int i = 0; i < count; ++i)
{
POINT pt;
if (bTruncated)
{
pt.x = reader.ReadInt16();
pt.y = reader.ReadInt16();
}
else
{
pt.x = reader.ReadInt32();
pt.y = reader.ReadInt32();
}
pt.x = UpdateFromGuides(pt.x);
pt.y = UpdateFromGuides(pt.y);
locs += std::to_wstring(pt.x) + L"," + std::to_wstring(pt.y) + (i < (count - 1) ? L";" : L"");
}
return locs;
}
std::vector<std::wstring> VMLShapeMapping::GetTextRectangles( const OptionEntryPtr& opInscribe ) const
{
std::vector<std::wstring> rectangles;
if (!opInscribe) return rectangles;
if (!opInscribe->opComplex) return rectangles;
if (16 != cb) return rectangles; // TODO: доделать
MemoryStream reader(opInscribe->opComplex.get(), opInscribe->op);
int count = (inscribe.op) / 16;
unsigned short nElems = reader.ReadUInt16();
unsigned short nElemsAlloc = reader.ReadUInt16();
unsigned short nElemSize = reader.ReadUInt16();
bool bTruncated = false;
if (0xFFF0 == nElemSize)
{
nElemSize = 4;
bTruncated = true;
}
long dwSize = nElems * nElemSize;
if (opInscribe->op - 6 != (dwSize))
{
bool b = false;
}
int count = dwSize / nElemSize; //4x (int or short)
for (int i = 0; i < count; ++i)
{
RECT rc;
rc.top = reader.ReadInt32();
rc.left = reader.ReadInt32();
rc.right = reader.ReadInt32();
rc.bottom = reader.ReadInt32();
if (bTruncated)
{
rc.top = reader.ReadInt16();
rc.left = reader.ReadInt16();
rc.right = reader.ReadInt16();
rc.bottom = reader.ReadInt16();
}
else
{
rc.top = reader.ReadInt32();
rc.left = reader.ReadInt32();
rc.right = reader.ReadInt32();
rc.bottom = reader.ReadInt32();
}
rc.top = UpdateFromGuides(rc.top);
rc.left = UpdateFromGuides(rc.left);
rc.right = UpdateFromGuides(rc.right);
rc.bottom = UpdateFromGuides(rc.bottom);
std::wstringstream sstream;
sstream << boost::wformat(L"%d,%d,%d,%d") % rc.top % rc.left % rc.right % rc.bottom;
rectangles.push_back(sstream.str());
rectangles.push_back( std::to_wstring(rc.top) + L"," + std::to_wstring(rc.left) + L"," +
std::to_wstring(rc.right) + L"," + std::to_wstring(rc.bottom));
}
return rectangles;

View File

@ -77,17 +77,10 @@ namespace DocFileFormat
void WritePrimitiveProps(DrawingPrimitive * primitive, bool root);
// Converts a group of shapes
void WriteGroup(const GroupContainer* pContainer);
// Converts a single shape
void WriteShape (const ShapeContainer* pContainer);
/// Generates a string id for the given shape
std::wstring GenShapeId(const Shape* pShape) const;
/// Build the VML wrapcoords string for a given pWrapPolygonVertices
std::wstring getWrapCoords( const OptionEntry& pWrapPolygonVertices ) const;
/// Copies the picture from the binary stream to the zip archive
/// and creates the relationships for the image.
bool copyPicture( const BlipStoreEntry* bse );
std::wstring GetTargetExt( Global::BlipType _type ) const;
@ -98,21 +91,22 @@ namespace DocFileFormat
std::wstring getTextboxAnchor( unsigned int anchor ) const;
void AppendOptionsToStyle( std::wstring* style, const std::list<OptionEntry>& options, int zIndex ) const;
std::wstring buildStyle ( const Shape* shape, const ChildAnchor* anchor, const std::vector<OptionEntryPtr>& options, int zIndex ) const;
void AppendOptionsToStyle ( std::wstring* style, const std::vector<OptionEntryPtr>& options, int zIndex ) const;
std::wstring buildStyle ( const Shape* shape, const ChildAnchor* anchor, const std::list<OptionEntry>& options, int zIndex ) const;
int UpdateFromGuides(const int val) const;
std::wstring getLineStyle ( unsigned int p ) const;
std::wstring getArrowStyle ( unsigned int op ) const;
std::wstring getArrowLength ( unsigned int op ) const;
std::wstring getArrowWidth ( unsigned int op ) const;
std::wstring getFillMethod ( unsigned int p ) const;
std::wstring getFillColorString( const unsigned char* p, unsigned int size ) const;
/// Returns the OpenXML fill type of a fill effect
std::wstring getFillType ( unsigned int p ) const;
std::wstring getShadowType ( unsigned int p ) const;
/// Returns the OpenXML wrap type of the shape
std::wstring getWrapType (const Spa* pSpa) const;
std::wstring ParsePath (const std::list<OptionEntry>& options) const;
void WriteBeginShapeNode (const Shape* pShape);
void WriteEndShapeNode (const Shape* pShape);
@ -121,9 +115,15 @@ namespace DocFileFormat
std::wstring GetLineFrom (const ChildAnchor* pAnchor) const;
std::wstring GetLineTo (const ChildAnchor* pAnchor) const;
std::vector<std::wstring> GetTextRectangles(const OptionEntry& inscribe) const;
std::wstring GetWrapCoords ( const OptionEntryPtr& pOpt ) const;
std::vector<std::wstring> GetTextRectangles ( const OptionEntryPtr& pOpt ) const;
std::wstring GetConnectAngles ( const OptionEntryPtr& pOpt ) const;
std::wstring GetConnectLocs ( const OptionEntryPtr& pOpt ) const;
void GetGuides ( const OptionEntryPtr& pOpt );
private:
int m_nAdjValues[8];
std::vector<_guides> m_arrGuides;
bool m_isInlineShape;
Spa* m_pSpa;
IMapping* m_pCaller;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="OdfFileReaderTest"
ProjectGUID="{C2882DDD-07E6-4314-AD4B-48F43F38D722}"
RootNamespace="ASCOfficeOdfFileTest"

View File

@ -155,8 +155,11 @@ void pptx_serialize_shape(std::wostream & strm, _pptx_drawing & val)
odf_reader::GetProperty(val.additional,L"no_rect",bNoRect);
if (!bNoRect)
{
val.serialize_xfrm(CP_XML_STREAM(), L"a", true);
{
if (val.cx != 0 || val.cy != 0) //layout
{
val.serialize_xfrm(CP_XML_STREAM(), L"a", true);
}
val.serialize_shape(CP_XML_STREAM());
oox_serialize_ln(CP_XML_STREAM(), val.additional);

View File

@ -352,7 +352,7 @@ void PptxConverter::convert_slides()
current_slide = slide->Master.operator->();
if (bShowLayoutMasterSp && bShowMasterSp)
convert_slide(&slide->Master->cSld, current_txStyles, false, true);
convert_slide(&slide->Master->cSld, current_txStyles, false, true, 2);
else
convert(slide->Master->cSld.bg.GetPointer());
@ -360,7 +360,7 @@ void PptxConverter::convert_slides()
current_clrMap = slide->Layout->clrMapOvr->overrideClrMapping.GetPointer();
current_slide = slide->Layout.operator->();
convert_slide(&slide->Layout->cSld, current_txStyles, true, bShowLayoutMasterSp);
convert_slide(&slide->Layout->cSld, current_txStyles, true, bShowLayoutMasterSp, 3);
if (!presentation->notesMasterIdLst.empty())
{
@ -407,7 +407,7 @@ void PptxConverter::convert_slides()
odp_context->current_slide().set_master_page (master_style_name);
odp_context->current_slide().set_layout_page (layout_style_name);
convert_slide (slide->cSld.GetPointer(), current_txStyles, true, bShowMasterSp);
convert_slide (slide->cSld.GetPointer(), current_txStyles, true, bShowMasterSp, 1);
convert (slide->comments.operator->());
convert (slide->Note.operator->());
@ -439,7 +439,7 @@ void PptxConverter::convert(PPTX::NotesMaster *oox_notes)
odf_context()->page_layout_context()->set_page_size(width, height);
}
convert_slide(&oox_notes->cSld, NULL, true, true);
convert_slide(&oox_notes->cSld, NULL, true, true, 2);
odp_context->end_note();
@ -472,7 +472,7 @@ void PptxConverter::convert(PPTX::NotesSlide *oox_notes)
if (oox_notes->clrMapOvr.IsInit() && oox_notes->clrMapOvr->overrideClrMapping.IsInit())
current_clrMap = oox_notes->clrMapOvr->overrideClrMapping.GetPointer();
convert_slide(&oox_notes->cSld, NULL, true, true);
convert_slide(&oox_notes->cSld, NULL, true, true, 1);
odp_context->end_note();
@ -1021,7 +1021,7 @@ void PptxConverter::convert(PPTX::Logic::Bg *oox_background)
odp_context->end_drawings();
}
void PptxConverter::convert_slide(PPTX::Logic::CSld *oox_slide, PPTX::Logic::TxStyles* txStyles, bool bPlaceholders, bool bFillUp)
void PptxConverter::convert_slide(PPTX::Logic::CSld *oox_slide, PPTX::Logic::TxStyles* txStyles, bool bPlaceholders, bool bFillUp, int type)
{
if (oox_slide == NULL) return;
@ -1051,6 +1051,9 @@ void PptxConverter::convert_slide(PPTX::Logic::CSld *oox_slide, PPTX::Logic::TxS
{
int ph_type = pShape->nvSpPr.nvPr.ph->type->GetBYTECode();
if (type == 3 && (ph_type == 5 || ph_type == 6 || ph_type == 7 || ph_type == 12))
continue;
odf_context()->drawing_context()->set_placeholder_type(ph_type);
}
else

View File

@ -108,7 +108,7 @@ namespace Oox2Odf
void convert(OOX::WritingElement *oox_unknown);
void convert_slide (PPTX::Logic::CSld *oox_slide, PPTX::Logic::TxStyles* txStyles, bool bPlaceholders, bool bFillUp);
void convert_slide (PPTX::Logic::CSld *oox_slide, PPTX::Logic::TxStyles* txStyles, bool bPlaceholders, bool bFillUp, int type);
void convert_layout (PPTX::Logic::CSld *oox_slide);
void convert (PPTX::Comments *oox_comments);
void convert (PPTX::NotesSlide *oox_notes);

View File

@ -293,21 +293,79 @@ NSPresentationEditor::CShapeWriter::CShapeWriter()
m_pImageElement = NULL;
m_pShapeElement = NULL;
}
std::wstring NSPresentationEditor::CShapeWriter::ConvertLine(CPen & pen)
std::wstring NSPresentationEditor::CShapeWriter::ConvertLine(CPen & pen)
{
NSPresentationEditor::CStringWriter line_writer;
std::wstring str = std::to_wstring( (int)(pen.Size * 36000));
line_writer.WriteString(L"<a:ln w=\"" + str + L"\">");
std::wstring strL;
switch(pen.LineStyle)
{
case 1: strL = L" cmpd=\"dbl\""; break;
case 2: strL = L" cmpd=\"thickThin\""; break;
case 3: strL = L" cmpd=\"thinThick\""; break;
case 4: strL = L" cmpd=\"tri\""; break;
}
line_writer.WriteString(L"<a:ln w=\"" + std::to_wstring((int)(pen.Size * 36000)) + L"\"" + strL + L">");
line_writer.WriteString(L"<a:solidFill>");
line_writer.WriteString(ConvertColor(pen.Color, pen.Alpha));
line_writer.WriteString(L"</a:solidFill>");
line_writer.WriteString(L"<a:round/><a:headEnd/><a:tailEnd/></a:ln>");
switch(pen.DashStyle)
{
case 1: line_writer.WriteString(L"<a:prstDash val=\"sysDash\"/>"); break;
case 2: line_writer.WriteString(L"<a:prstDash val=\"sysDot\"/>"); break;
case 3: line_writer.WriteString(L"<a:prstDash val=\"sysDashDot\"/>"); break;
case 4: line_writer.WriteString(L"<a:prstDash val=\"sysDashDotDot\"/>"); break;
case 5: line_writer.WriteString(L"<a:prstDash val=\"dot\"/>"); break;
case 6: line_writer.WriteString(L"<a:prstDash val=\"dash\"/>"); break;
case 7: line_writer.WriteString(L"<a:prstDash val=\"lgDash\"/>"); break;
case 8: line_writer.WriteString(L"<a:prstDash val=\"dashDot\"/>"); break;
case 9: line_writer.WriteString(L"<a:prstDash val=\"lgDashDot\"/>"); break;
case 10:line_writer.WriteString(L"<a:prstDash val=\"lgDashDotDot\"/>"); break;
}
switch(pen.LineJoin)
{
case 0: line_writer.WriteString(L"<a:bevel/>"); break;
case 1: line_writer.WriteString(L"<a:miter/>"); break;
case 2: line_writer.WriteString(L"<a:round/>"); break;
}
line_writer.WriteString(L"<a:headEnd" + ConvertLineEnd(pen.LineStartCap, pen.LineStartLength, pen.LineStartWidth) + L"/>");
line_writer.WriteString(L"<a:tailEnd" + ConvertLineEnd(pen.LineEndCap, pen.LineEndLength, pen.LineEndWidth) + L"/>");
line_writer.WriteString(L"</a:ln>");
return line_writer.GetData();
}
std::wstring NSPresentationEditor::CShapeWriter::ConvertLineEnd(unsigned char cap, unsigned char length, unsigned char width)
{
if (cap < 1) return L"";
std::wstring sResult;
switch(cap)
{
case 1: sResult += L" type=\"triangle\""; break;
case 2: sResult += L" type=\"stealth\""; break;
case 3: sResult += L" type=\"diamond\""; break;
case 4: sResult += L" type=\"oval\""; break;
case 5: sResult += L" type=\"arrow\""; break;
}
switch(length)
{
case 0: sResult += L" len=\"sm\""; break;
case 1: sResult += L" len=\"med\""; break;
case 2: sResult += L" len=\"lg\""; break;
}
switch(width)
{
case 0: sResult += L" w=\"sm\""; break;
case 1: sResult += L" w=\"med\""; break;
case 2: sResult += L" w=\"lg\""; break;
}
return sResult;
}
std::wstring NSPresentationEditor::CShapeWriter::ConvertBrush(CBrush & brush)
{
NSPresentationEditor::CStringWriter brush_writer;
@ -1168,7 +1226,8 @@ std::wstring NSPresentationEditor::CShapeWriter::ConvertShape()
}
m_oWriter.WriteString(std::wstring(L">"));
m_oWriter.WriteString(L"<a:off x=\"" + std::to_wstring((int)m_pShapeElement->m_rcBoundsOriginal.left) + L"\" y=\"" + std::to_wstring((int)m_pShapeElement->m_rcBoundsOriginal.top) + L"\"/>");
m_oWriter.WriteString(L"<a:off x=\"" + std::to_wstring((int)m_pShapeElement->m_rcBoundsOriginal.left) +
L"\" y=\"" + std::to_wstring((int)m_pShapeElement->m_rcBoundsOriginal.top) + L"\"/>");
int width = m_pShapeElement->m_rcBoundsOriginal.right - m_pShapeElement->m_rcBoundsOriginal.left;
int height = m_pShapeElement->m_rcBoundsOriginal.bottom - m_pShapeElement->m_rcBoundsOriginal.top;

View File

@ -213,6 +213,7 @@ namespace NSPresentationEditor
std::wstring ConvertShadow (CShadow & shadow);
std::wstring ConvertBrush (CBrush & brush);
static std::wstring ConvertColor (CColor & color, long alpha);
std::wstring ConvertLineEnd(unsigned char cap, unsigned char length, unsigned char width);
// тип рендерера-----------------------------------------------------------------------------
virtual HRESULT get_Type(LONG* lType) ;
//-------- Функции для работы со страницей --------------------------------------------------

View File

@ -401,48 +401,47 @@ static std::string GetRecordName(DWORD dwType)
case RECORD_TYPE_ROUNDTRIPNOTESMASTERTEXTSTYLES12 : { strName = ("RoundTripNotesMasterTextStyles12"); break; }
case RECORD_TYPE_ROUNDTRIPCUSTOMTABLESTYLES12 : { strName = ("RoundTripCustomTableStyles12"); break; }
//records greater then 0xF000 belong to with Microsoft Office Drawing format also known as Escher
case RECORD_TYPE_ESCHER_DGG_CONTAINER : { strName = ("Escher_DrawingGroupContainer"); break; }
case RECORD_TYPE_ESCHER_DGG : { strName = ("Escher_DrawingGroupRecord"); break; }
case RECORD_TYPE_ESCHER_CLSID : { strName = ("Escher_CLSID_Record"); break; }
case RECORD_TYPE_ESCHER_OPT : { strName = ("Escher_OPT"); break; }
case RECORD_TYPE_ESCHER_BSTORE_CONTAINER : { strName = ("Escher_BlipStoreContainer"); break; }
case RECORD_TYPE_ESCHER_BSE : { strName = ("Escher_BlipStoreEntry"); break; }
case RECORD_TYPE_ESCHER_BLIP_START : { strName = ("Escher_BlipStart"); break; }
case RECORD_TYPE_ESCHER_BLIP_END : { strName = ("Escher_BlipEnd"); break; }
case RECORD_TYPE_ESCHER_DG_CONTAINER : { strName = ("Escher_DrawingContainer"); break; }
case RECORD_TYPE_ESCHER_DG : { strName = ("Escher_DrawingRecord"); break; }
case RECORD_TYPE_ESCHER_REGROUPITEMS : { strName = ("Escher_RegGroupItems"); break; }
case RECORD_TYPE_ESCHER_COLORSCHEME : { strName = ("Escher_ColorSheme"); break; }
case RECORD_TYPE_ESCHER_SPGR_CONTAINER : { strName = ("Escher_GroupShapeContainer"); break; }
case RECORD_TYPE_ESCHER_SP_CONTAINER : { strName = ("Escher_ShapeContainer"); break; }
case RECORD_TYPE_ESCHER_SPGR : { strName = ("Escher_GroupShapeRecord"); break; }
case RECORD_TYPE_ESCHER_SP : { strName = ("Escher_ShapeRecord"); break; }
case RECORD_TYPE_ESCHER_TEXTBOX : { strName = ("Escher_TextBox"); break; }
case RECORD_TYPE_ESCHER_CLIENTTEXTBOX : { strName = ("Escher_ClientTextBox"); break; }
case RECORD_TYPE_ESCHER_ANCHOR : { strName = ("Escher_Anchor"); break; }
case RECORD_TYPE_ESCHER_CHILDANCHOR : { strName = ("Escher_ChildAnchor"); break; }
case RECORD_TYPE_ESCHER_CLIENTANCHOR : { strName = ("Escher_ClientAnchor"); break; }
case RECORD_TYPE_ESCHER_CLIENTDATA : { strName = ("Escher_ClientData"); break; }
case RECORD_TYPE_ESCHER_SOLVERCONTAINER : { strName = ("Escher_SolverContainer"); break; }
case RECORD_TYPE_ESCHER_CONNECTORRULE : { strName = ("Escher_ConnectorRule"); break; }
case RECORD_TYPE_ESCHER_ALIGNRULE : { strName = ("Escher_AlignRule"); break; }
case RECORD_TYPE_ESCHER_ARCRULE : { strName = ("Escher_ArcRule"); break; }
case RECORD_TYPE_ESCHER_CLIENTRULE : { strName = ("Escher_ClientRule"); break; }
case RECORD_TYPE_ESCHER_CALLOUTRULE : { strName = ("Escher_CallOutRule"); break; }
case RECORD_TYPE_ESCHER_SELECTION : { strName = ("Escher_Selection"); break; }
case RECORD_TYPE_ESCHER_COLORMRU : { strName = ("Escher_ColorMRU"); break; }
case RECORD_TYPE_ESCHER_DELETEDPSPL : { strName = ("Escher_DeletedPSPL"); break; }
case RECORD_TYPE_ESCHER_SPLITMENUCOLORS : { strName = ("Escher_SplitMenuColors"); break; }
case RECORD_TYPE_ESCHER_OLEOBJECT : { strName = ("Escher_OleObject"); break; }
case RECORD_TYPE_ESCHER_SECONDARY_OPT : { strName = ("Escher_SecondaryOPT"); break; }
case RECORD_TYPE_ESCHER_TETRIARY_OPT : { strName = ("Escher_TetriaryOPT"); break; }
case RECORD_TYPE_ESCHER_DGG_CONTAINER : { strName = ("DrawingGroupContainer"); break; }
case RECORD_TYPE_ESCHER_DGG : { strName = ("DrawingGroupRecord"); break; }
case RECORD_TYPE_ESCHER_CLSID : { strName = ("CLSID_Record"); break; }
case RECORD_TYPE_ESCHER_OPT : { strName = ("OPT"); break; }
case RECORD_TYPE_ESCHER_BSTORE_CONTAINER : { strName = ("BlipStoreContainer"); break; }
case RECORD_TYPE_ESCHER_BSE : { strName = ("BlipStoreEntry"); break; }
case RECORD_TYPE_ESCHER_BLIP_START : { strName = ("BlipStart"); break; }
case RECORD_TYPE_ESCHER_BLIP_END : { strName = ("BlipEnd"); break; }
case RECORD_TYPE_ESCHER_DG_CONTAINER : { strName = ("DrawingContainer"); break; }
case RECORD_TYPE_ESCHER_DG : { strName = ("DrawingRecord"); break; }
case RECORD_TYPE_ESCHER_REGROUPITEMS : { strName = ("RegGroupItems"); break; }
case RECORD_TYPE_ESCHER_COLORSCHEME : { strName = ("ColorSheme"); break; }
case RECORD_TYPE_ESCHER_SPGR_CONTAINER : { strName = ("GroupShapeContainer"); break; }
case RECORD_TYPE_ESCHER_SP_CONTAINER : { strName = ("ShapeContainer"); break; }
case RECORD_TYPE_ESCHER_SPGR : { strName = ("GroupShapeRecord"); break; }
case RECORD_TYPE_ESCHER_SP : { strName = ("ShapeRecord"); break; }
case RECORD_TYPE_ESCHER_TEXTBOX : { strName = ("TextBox"); break; }
case RECORD_TYPE_ESCHER_CLIENTTEXTBOX : { strName = ("ClientTextBox"); break; }
case RECORD_TYPE_ESCHER_ANCHOR : { strName = ("Anchor"); break; }
case RECORD_TYPE_ESCHER_CHILDANCHOR : { strName = ("ChildAnchor"); break; }
case RECORD_TYPE_ESCHER_CLIENTANCHOR : { strName = ("ClientAnchor"); break; }
case RECORD_TYPE_ESCHER_CLIENTDATA : { strName = ("ClientData"); break; }
case RECORD_TYPE_ESCHER_SOLVERCONTAINER : { strName = ("SolverContainer"); break; }
case RECORD_TYPE_ESCHER_CONNECTORRULE : { strName = ("ConnectorRule"); break; }
case RECORD_TYPE_ESCHER_ALIGNRULE : { strName = ("AlignRule"); break; }
case RECORD_TYPE_ESCHER_ARCRULE : { strName = ("ArcRule"); break; }
case RECORD_TYPE_ESCHER_CLIENTRULE : { strName = ("ClientRule"); break; }
case RECORD_TYPE_ESCHER_CALLOUTRULE : { strName = ("CallOutRule"); break; }
case RECORD_TYPE_ESCHER_SELECTION : { strName = ("Selection"); break; }
case RECORD_TYPE_ESCHER_COLORMRU : { strName = ("ColorMRU"); break; }
case RECORD_TYPE_ESCHER_DELETEDPSPL : { strName = ("DeletedPSPL"); break; }
case RECORD_TYPE_ESCHER_SPLITMENUCOLORS : { strName = ("SplitMenuColors"); break; }
case RECORD_TYPE_ESCHER_OLEOBJECT : { strName = ("OleObject"); break; }
case RECORD_TYPE_ESCHER_SECONDARY_OPT : { strName = ("SecondaryOPT"); break; }
case RECORD_TYPE_ESCHER_TETRIARY_OPT : { strName = ("TetriaryOPT"); break; }
default: break;
};
if ((dwType > RECORD_TYPE_ESCHER_BLIP_START) && (dwType < RECORD_TYPE_ESCHER_BLIP_END))
{
strName = ("Escher_Blip");
strName = ("Blip");
}
return strName;

View File

@ -575,212 +575,134 @@ public:
}
// line --------------------------------------------------------
case lineBoolean: //Line Style Boolean Properties
{
bool bNoLineDrawDash = GETBIT(pProperty->m_lValue, 0);
bool bLineFillShape = GETBIT(pProperty->m_lValue, 1);
bool bHitTestLine = GETBIT(pProperty->m_lValue, 2);
bool bLine = GETBIT(pProperty->m_lValue, 3);
bool bArrowheadsOK = GETBIT(pProperty->m_lValue, 4);
bool bInsetPenOK = GETBIT(pProperty->m_lValue, 5);
bool bInsetPen = GETBIT(pProperty->m_lValue, 6);
bool bLineOpaqueBackColor = GETBIT(pProperty->m_lValue, 9);
{
bool bNoLineDrawDash = GETBIT(pProperty->m_lValue, 0);
bool bLineFillShape = GETBIT(pProperty->m_lValue, 1);
bool bHitTestLine = GETBIT(pProperty->m_lValue, 2);
bool bLine = GETBIT(pProperty->m_lValue, 3);
bool bArrowheadsOK = GETBIT(pProperty->m_lValue, 4);
bool bInsetPenOK = GETBIT(pProperty->m_lValue, 5);
bool bInsetPen = GETBIT(pProperty->m_lValue, 6);
bool bLineOpaqueBackColor = GETBIT(pProperty->m_lValue, 9);
bool bUsefNoLineDrawDash = GETBIT(pProperty->m_lValue, 16);
bool bUsefLineFillShape = GETBIT(pProperty->m_lValue, 17);
bool bUsefHitTestLine = GETBIT(pProperty->m_lValue, 18);
bool bUsefLine = GETBIT(pProperty->m_lValue, 19);
bool bUsefArrowheadsOK = GETBIT(pProperty->m_lValue, 20);
bool bUsefInsetPenOK = GETBIT(pProperty->m_lValue, 21);
bool bUsefInsetPen = GETBIT(pProperty->m_lValue, 22);
bool bUsefLineOpaqueBackColor = GETBIT(pProperty->m_lValue, 25);
bool bUsefNoLineDrawDash = GETBIT(pProperty->m_lValue, 16);
bool bUsefLineFillShape = GETBIT(pProperty->m_lValue, 17);
bool bUsefHitTestLine = GETBIT(pProperty->m_lValue, 18);
bool bUsefLine = GETBIT(pProperty->m_lValue, 19);
bool bUsefArrowheadsOK = GETBIT(pProperty->m_lValue, 20);
bool bUsefInsetPenOK = GETBIT(pProperty->m_lValue, 21);
bool bUsefInsetPen = GETBIT(pProperty->m_lValue, 22);
bool bUsefLineOpaqueBackColor = GETBIT(pProperty->m_lValue, 25);
if (bUsefLine)
pElement->m_bLine = bLine;
}break;
case lineStyle:
if (bUsefLine)
pElement->m_bLine = bLine;
}break;
case lineDashStyle://from Complex
{
pElement->m_bLine = true;
}break;
{
pElement->m_bLine = true;
}break;
case lineColor:
{
SColorAtom oAtom;
oAtom.FromValue(pProperty->m_lValue);
if (oAtom.bSysIndex)
pElement->m_oPen.Color = CorrectSysColor(pProperty->m_lValue, pElement, pTheme);
else
oAtom.ToColor(&pElement->m_oPen.Color);
break;
}
{
SColorAtom oAtom;
oAtom.FromValue(pProperty->m_lValue);
if (oAtom.bSysIndex)
pElement->m_oPen.Color = CorrectSysColor(pProperty->m_lValue, pElement, pTheme);
else
oAtom.ToColor(&pElement->m_oPen.Color);
}break;
case lineOpacity:
{
pElement->m_oPen.Alpha = (BYTE)(std::min)(255, (int)CDirectory::NormFixedPoint(pProperty->m_lValue, 255));
break;
}
{
pElement->m_oPen.Alpha = (BYTE)(std::min)(255, (int)CDirectory::NormFixedPoint(pProperty->m_lValue, 255));
}break;
case lineBackColor:
{
SColorAtom oAtom;
oAtom.FromValue(pProperty->m_lValue);
if (oAtom.bSysIndex)
pElement->m_oPen.Color2 = CorrectSysColor(pProperty->m_lValue, pElement, pTheme);
else
oAtom.ToColor(&pElement->m_oPen.Color2);
{
SColorAtom oAtom;
oAtom.FromValue(pProperty->m_lValue);
if (oAtom.bSysIndex)
pElement->m_oPen.Color2 = CorrectSysColor(pProperty->m_lValue, pElement, pTheme);
else
oAtom.ToColor(&pElement->m_oPen.Color2);
}break;
}break;
case lineWidth:
{
pElement->m_oPen.Size = (double)pProperty->m_lValue / EMU_MM;
pElement->m_bLine = true;
break;
}
{
pElement->m_oPen.Size = (double)pProperty->m_lValue / EMU_MM;
pElement->m_bLine = true;
}break;
case lineStyle:
{
pElement->m_bLine = true;
pElement->m_oPen.LineStyle = pProperty->m_lValue;
}break;
case lineDashing:
{
BYTE nDashStyle = 0;
switch (pProperty->m_lValue)
{
case 0:
{
nDashStyle = 0; // solid
}break;
case 1:
case 6:
case 7:
{
nDashStyle = 1; // dash
}break;
case 2:
case 5:
{
nDashStyle = 2; // dot
}break;
case 3:
case 8:
case 9:
{
nDashStyle = 3; // dashdot
}break;
case 4:
case 10:
{
nDashStyle = 4;// dashdotdot
}break;
default:
break;
};
pElement->m_bLine = true;
pElement->m_oPen.DashStyle = nDashStyle;
break;
}
{
pElement->m_bLine = true;
pElement->m_oPen.DashStyle = pProperty->m_lValue;
}break;
case lineJoinStyle:
{
BYTE nLineJoin = 2;
switch (pProperty->m_lValue)
{
case 0:
{
nLineJoin = 1; // bevel
}break;
case 1:
{
nLineJoin = 1; // Miter
}break;
case 2:
{
nLineJoin = 2; // round
}break;
default:
break;
};
pElement->m_oPen.LineJoin = nLineJoin;
break;
}
{
pElement->m_oPen.LineJoin = pProperty->m_lValue;
}break;
case lineStartArrowLength:
{
pElement->m_oPen.LineStartLength = pProperty->m_lValue;
}break;
case lineEndArrowLength:
{
pElement->m_oPen.LineEndLength = pProperty->m_lValue;
}break;
case lineStartArrowWidth:
{
pElement->m_oPen.LineStartWidth = pProperty->m_lValue;
}break;
case lineEndArrowWidth:
{
pElement->m_oPen.LineEndWidth = pProperty->m_lValue;
}break;
case lineStartArrowhead:
{
BYTE nStartCap = 0;
switch (pProperty->m_lValue)
{
case 1:
case 2:
case 5:
{
nStartCap = 0x14;
}break;
case 3:
case 4:
{
nStartCap = 2;
}break;
default:
break;
};
pElement->m_oPen.LineStartCap = nStartCap;
break;
}
{
pElement->m_oPen.LineStartCap = pProperty->m_lValue;
}break;
case lineEndArrowhead:
{
BYTE nEndCap = 0;
switch (pProperty->m_lValue)
{
case 1:
case 2:
case 5:
{
nEndCap = 0x14;
}break;
case 3:
case 4:
{
nEndCap = 2;
}break;
default:
break;
};
pElement->m_oPen.LineEndCap = nEndCap;
break;
}
{
pElement->m_oPen.LineEndCap = pProperty->m_lValue;
}break;
case shadowType:
{
pElement->m_oShadow.Type = pProperty->m_lValue;
}break;
{
pElement->m_oShadow.Type = pProperty->m_lValue;
}break;
case shadowOriginX://in emu, relative from center shape
{
pElement->m_oShadow.OriginX = FixedPointToDouble(pProperty->m_lValue);
}break;
{
pElement->m_oShadow.OriginX = FixedPointToDouble(pProperty->m_lValue);
}break;
case shadowOriginY:
{
pElement->m_oShadow.OriginY = FixedPointToDouble(pProperty->m_lValue);
}break;
{
pElement->m_oShadow.OriginY = FixedPointToDouble(pProperty->m_lValue);
}break;
case shadowColor:
{
SColorAtom oAtom;
oAtom.FromValue(pProperty->m_lValue);
{
SColorAtom oAtom;
oAtom.FromValue(pProperty->m_lValue);
if (oAtom.bSysIndex)
pElement->m_oShadow.Color = CorrectSysColor(pProperty->m_lValue, pElement, pTheme);
else
oAtom.ToColor(&pElement->m_oShadow.Color);
if (oAtom.bSysIndex)
pElement->m_oShadow.Color = CorrectSysColor(pProperty->m_lValue, pElement, pTheme);
else
oAtom.ToColor(&pElement->m_oShadow.Color);
}break;
}break;
case shadowWeight:
{
}break;
case shadowOpacity:
{
pElement->m_oShadow.Alpha = (BYTE)(std::min)(255, (int)CDirectory::NormFixedPoint(pProperty->m_lValue, 255));
}break;
{
pElement->m_oShadow.Alpha = (BYTE)(std::min)(255, (int)CDirectory::NormFixedPoint(pProperty->m_lValue, 255));
}break;
case shadowHighlight:
{
//оттенок двойной тени
}break;
{
//оттенок двойной тени
}break;
case shadowOffsetX:
{
pElement->m_oShadow.DistanceX = ((int)pProperty->m_lValue) / EMU_MM;
@ -949,65 +871,80 @@ public:
switch (pProperty->m_ePID)
{
// здесь просто применяем проперти...
// geometry ----------------------------------------------------
// top, left, right, bottom logic
case NSOfficeDrawing::metroBlob:
{
//альтернатива в формате oox
//NSFile::CFileBinary f;
//f.CreateFileW(L"d:\\test.zip");
//f.WriteFile(pProperty->m_pOptions, pProperty->m_lValue);
//f.CloseFile();
}break;
{
//альтернатива в формате oox
//NSFile::CFileBinary f;
//f.CreateFileW(L"d:\\test.zip");
//f.WriteFile(pProperty->m_pOptions, pProperty->m_lValue);
//f.CloseFile();
}break;
case NSOfficeDrawing::geoRight:
{
if (0 < pProperty->m_lValue)
pParentShape->m_dWidthLogic = (double)(pProperty->m_lValue);
}break;
{
if (0 < pProperty->m_lValue)
pParentShape->m_dWidthLogic = (double)(pProperty->m_lValue);
}break;
case NSOfficeDrawing::geoBottom:
{
if (0 < pProperty->m_lValue)
pParentShape->m_dHeightLogic = (double)(pProperty->m_lValue);
}break;
// shapePath
{
if (0 < pProperty->m_lValue)
pParentShape->m_dHeightLogic = (double)(pProperty->m_lValue);
}break;
case NSOfficeDrawing::shapePath:
{
pShape->m_oCustomVML.SetPath((RulesType)pProperty->m_lValue);
pShape->m_bCustomShape = true;
}break;
// segmentsInfo
{
pShape->m_oCustomVML.SetPath((RulesType)pProperty->m_lValue);
pShape->m_bCustomShape = true;
}break;
case NSOfficeDrawing::pSegmentInfo:
{
if (pProperty->m_bComplex)
{
if (pProperty->m_bComplex)
{
pShape->m_oCustomVML.LoadSegments(pProperty);
pShape->m_bCustomShape = true;
}
}break;
// verticesInfo
pShape->m_oCustomVML.LoadSegments(pProperty);
pShape->m_bCustomShape = true;
}
}break;
case NSOfficeDrawing::pVertices:
{
if (pProperty->m_bComplex)
{
if (pProperty->m_bComplex)
{
pShape->m_oCustomVML.LoadVertices(pProperty);
pShape->m_bCustomShape = true;
}
}break;
pShape->m_oCustomVML.LoadVertices(pProperty);
pShape->m_bCustomShape = true;
}
}break;
case NSOfficeDrawing::pConnectionSites:
{
if (pProperty->m_bComplex)
{
pShape->m_oCustomVML.LoadConnectionSites(pProperty);
}
}break;
case NSOfficeDrawing::pConnectionSitesDir:
{
if (pProperty->m_bComplex)
{
pShape->m_oCustomVML.LoadConnectionSitesDir(pProperty);
}
}break;
case NSOfficeDrawing::pGuides:
{
if (pProperty->m_bComplex/* && pShape->m_eType != sptNotchedCircularArrow*/)
{//Тікбұрышты үшбұрыштарды.ppt - slide 25
pShape->m_oCustomVML.LoadGuides(pProperty);
}
}break;
case NSOfficeDrawing::pInscribe:
{
if (pProperty->m_bComplex)
{
if (pProperty->m_bComplex && pShape->m_eType != sptNotchedCircularArrow)
{//Тікбұрышты үшбұрыштарды.ppt - slide 25
pShape->m_oCustomVML.LoadGuides(pProperty);
}
}break;
pShape->m_oCustomVML.LoadInscribe(pProperty);
}
}break;
case NSOfficeDrawing::pAdjustHandles:
{
if (pProperty->m_bComplex)
{
if (pProperty->m_bComplex)
{
pShape->m_oCustomVML.LoadAHs(pProperty);
}
}break;
pShape->m_oCustomVML.LoadAHs(pProperty);
}
}break;
case NSOfficeDrawing::adjustValue:
case NSOfficeDrawing::adjust2Value:
case NSOfficeDrawing::adjust3Value:

View File

@ -1026,6 +1026,26 @@
RelativePath="..\..\..\ASCOfficePPTXFile\Editor\Drawing\XmlWriter.h"
>
</File>
<Filter
Name="ppt shapes"
>
<File
RelativePath="..\..\..\ASCOfficePPTXFile\Editor\Drawing\Shapes\BaseShape\PPTShape\customgeomshape.h"
>
</File>
<File
RelativePath="..\..\..\ASCOfficePPTXFile\Editor\Drawing\Shapes\BaseShape\PPTShape\elementsettings.h"
>
</File>
<File
RelativePath="..\..\..\ASCOfficePPTXFile\Editor\Drawing\Shapes\BaseShape\PPTShape\formula.h"
>
</File>
<File
RelativePath="..\..\..\ASCOfficePPTXFile\Editor\Drawing\Shapes\BaseShape\PPTShape\PPTShape.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="OOXWriter"

View File

@ -478,10 +478,17 @@ namespace NSPresentationEditor
long Alpha;
double Size;
BYTE DashStyle;
BYTE LineStartCap;
BYTE LineEndCap;
BYTE LineJoin;
unsigned char DashStyle;
unsigned char LineStyle;
unsigned char LineJoin;
unsigned char LineEndCap;
unsigned char LineEndLength;
unsigned char LineEndWidth;
unsigned char LineStartCap;
unsigned char LineStartLength;
unsigned char LineStartWidth;
double* DashPattern;
long Count;
@ -492,9 +499,8 @@ namespace NSPresentationEditor
double MiterLimit;
CColor Color2; //backLine
public:
void GetDashPattern(double* arrDashPattern, long& nCount) const
void GetDashPattern(double* arrDashPattern, long& nCount) const
{
if (nCount == Count)
{
@ -579,10 +585,16 @@ namespace NSPresentationEditor
Alpha = 255;
Size = 0.26458;
DashStyle = 0;
LineStartCap = 0;
LineEndCap = 0;
LineJoin = 0;
LineStyle = 0; //single(Simple)
DashStyle = 0; //Solid
LineJoin = 2; //round
LineStartCap = 0;
LineEndCap = 0;
LineEndLength = 1; //med
LineStartLength = 1;
LineEndWidth = 1;
LineStartWidth = 1;
DashPattern = NULL;
Count = 0;

View File

@ -488,6 +488,9 @@ namespace NSCustomVML
std::vector<CSegment> m_arSegments;
std::vector<CGuide> m_arGuides;
std::vector<LONG>* m_pAdjustValues;
std::vector<Aggplus::POINT> m_arConnectionSites;
std::vector<Aggplus::RECT> m_arInscribe;
std::vector<double> m_arConnectionSitesDir;
bool m_bIsVerticesPresent;
bool m_bIsPathPresent;
@ -496,7 +499,7 @@ namespace NSCustomVML
CPen m_oPen;
public:
CCustomVML() : m_arVertices(), m_arSegments(), m_arGuides(), m_pAdjustValues(NULL)
CCustomVML() : m_pAdjustValues(NULL)
{
m_ePath = rtCurveTo/*rtLineTo*/;
@ -579,6 +582,63 @@ namespace NSCustomVML
m_arVertices.push_back(oPoint);
}
}
void LoadConnectionSitesDir(CProperty* pProperty)
{
NSOfficeDrawing::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue);
m_arConnectionSitesDir.clear();
WORD lCount = (WORD)(pProperty->m_lValue / 4);
for (WORD lIndex = 0; lIndex < lCount; ++lIndex)
{
DWORD v = oReader.ReadLONG();
double val = (double)((WORD)(v >> 16) + ((WORD)(v) / 65536.0));
m_arConnectionSitesDir.push_back(val);
}
}
void LoadConnectionSites(CProperty* pProperty)
{
NSOfficeDrawing::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue);
m_arConnectionSites.clear();
WORD lCount = (WORD)(pProperty->m_lValue / 8);
if (pProperty->m_bIsTruncated)
{
lCount = (WORD)(pProperty->m_lValue / 4);
}
for (WORD lIndex = 0; lIndex < lCount; ++lIndex)
{
Aggplus::POINT oPoint;
if (pProperty->m_bIsTruncated)
{
oPoint.x = (short)oReader.ReadWORD();
oPoint.y = (short)oReader.ReadWORD();
}
else
{
oPoint.x = oReader.ReadLONG();
oPoint.y = oReader.ReadLONG();
}
LONG lMinF = (LONG)0x80000000;
LONG lMaxF = (LONG)0x8000007F;
if (lMinF <= oPoint.x)
{
int nGuideIndex = (DWORD)oPoint.x - 0x80000000;
bool b = false;
}
if (lMinF <= oPoint.y)
{
int nGuideIndex = (DWORD)oPoint.y - 0x80000000;
bool b = false;
}
m_arConnectionSites.push_back(oPoint);
}
}
void LoadVertices(CProperty* pProperty)
{
NSOfficeDrawing::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue);
@ -704,8 +764,38 @@ namespace NSCustomVML
oInfo.Read(oReader);
m_arGuides.push_back(oInfo);
}
}
void LoadInscribe(CProperty* pProperty)
{
NSOfficeDrawing::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue);
m_arInscribe.clear();
WORD lCount = (WORD)(pProperty->m_lValue / 16);
if (pProperty->m_bIsTruncated)
{
lCount = (WORD)(pProperty->m_lValue / 8);
}
for (WORD lIndex = 0; lIndex < lCount; ++lIndex)
{
Aggplus::RECT oRect;
if (pProperty->m_bIsTruncated)
{
oRect.left = (short)oReader.ReadWORD();
oRect.right = (short)oReader.ReadWORD();
oRect.top = (short)oReader.ReadWORD();
oRect.bottom = (short)oReader.ReadWORD();
}
else
{
oRect.left = (short)oReader.ReadLONG();
oRect.right = (short)oReader.ReadLONG();
oRect.top = (short)oReader.ReadLONG();
oRect.bottom = (short)oReader.ReadLONG();
}
m_arInscribe.push_back(oRect);
}
}
void LoadAdjusts(LONG lIndex, LONG lValue)
{
if (NULL == m_pAdjustValues)

View File

@ -47,10 +47,10 @@ CPPTShape* CPPTShape::CreateByType(PPTShapes::ShapeType type)
CPPTShape* pShape = NULL;
switch (type)
{
// msosptNotchedCircularArrow 0x00000064 A value that SHOULD NOT be used.
// msosptNotchedCircularArrow 0x00000064 A value that SHOULD NOT be used.
// msosptHostControl 0x000000C9 A value that SHOULD NOT be used.
case sptNotchedCircularArrow:
//case sptNotchedCircularArrow:
case sptHostControl:
{ pShape = new CPPTShape(); pShape->m_eType = type; break; }
case 0: { pShape = new CRectangleType(); break; }

View File

@ -45,6 +45,12 @@
#pragma comment(lib,"Shell32.lib")
#pragma comment(lib,"Advapi32.lib")
#if defined(_WIN64)
#pragma comment(lib, "../../build/bin/icu/win_64/icuuc.lib")
#elif defined (_WIN32)
#pragma comment(lib, "../../build/bin/icu/win_32/icuuc.lib")
#endif
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = S_OK;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="XlsFormatTest"
ProjectGUID="{C2882DDD-07E6-4314-AD4B-48F43F38D722}"
RootNamespace="ASCOfficeOdfFileTest"
@ -367,14 +367,6 @@
</FileConfiguration>
</File>
</Filter>
<File
RelativePath="..\..\build\bin\icu\win_32\icudt.lib"
>
</File>
<File
RelativePath="..\..\build\bin\icu\win_32\icuuc.lib"
>
</File>
</Files>
<Globals>
</Globals>

View File

@ -312,7 +312,7 @@ namespace NSCustomShapesConvert
if (lMaxF > m_arVertices[nIndex].x ) nGuideIndex_x = (DWORD)m_arVertices[nIndex].x - (DWORD)lMinF;
if (lMaxF > m_arVertices[nIndex].y ) nGuideIndex_y = (DWORD)m_arVertices[nIndex].y - (DWORD)lMinF;
if (nGuideIndex_x >= 0 )
if (nGuideIndex_x >= 0 && nGuideIndex_x < m_arGuides.size())
{
strPath += std::to_wstring(m_arGuides[nGuideIndex_x].m_param_value1) + L",";
}
@ -320,7 +320,7 @@ namespace NSCustomShapesConvert
{
strPath += std::to_wstring(m_arVertices[nIndex].x) + L",";
}
if (nGuideIndex_y >= 0)
if (nGuideIndex_y >= 0 && nGuideIndex_y < m_arGuides.size())
{
strPath += std::to_wstring(m_arGuides[nGuideIndex_y].m_param_value1) + L",";
}
@ -388,7 +388,7 @@ namespace NSCustomShapesConvert
if (lMaxF > m_arVertices[nV].x ) nGuideIndex_x = (DWORD)m_arVertices[nV].x - (DWORD)lMinF;
if (lMaxF > m_arVertices[nV].y ) nGuideIndex_y = (DWORD)m_arVertices[nV].y - (DWORD)lMinF;
if (nGuideIndex_x >= 0 )
if (nGuideIndex_x >= 0 && nGuideIndex_x < m_arGuides.size() )
{
strPath += std::to_wstring(m_arGuides[nGuideIndex_x].m_param_value1) + L",";
}
@ -396,7 +396,7 @@ namespace NSCustomShapesConvert
{
strPath += std::to_wstring(m_arVertices[nV].x) + L",";
}
if (nGuideIndex_y >= 0)
if (nGuideIndex_y >= 0 && nGuideIndex_y < m_arGuides.size())
{
strPath += std::to_wstring(m_arGuides[nGuideIndex_y].m_param_value1) + L",";
}

View File

@ -251,6 +251,19 @@ namespace oox
case msosptRectangle : return L"rect";
case msosptEllipse : return L"ellipse";
case msosptLine : return L"line";
case msosptActionButtonBlank : return L"actionButtonBlank";
case msosptActionButtonHome : return L"actionButtonHome";
case msosptActionButtonHelp : return L"actionButtonHelp";
case msosptActionButtonInformation : return L"actionButtonInformation";
case msosptActionButtonForwardNext : return L"actionButtonForwardNext";
case msosptActionButtonBackPrevious : return L"actionButtonBackPrevious";
case msosptActionButtonEnd : return L"actionButtonEnd";
case msosptActionButtonBeginning : return L"actionButtonBeginning";
case msosptActionButtonReturn : return L"actionButtonReturn";
case msosptActionButtonDocument : return L"actionButtonDocument";
case msosptActionButtonSound : return L"actionButtonSound";
case msosptActionButtonMovie : return L"actionButtonMovie";
case msosptLeftArrow : return L"leftArrow";
}
return L"";
}

View File

@ -326,7 +326,7 @@ private:
if (differenceInLength < 0)
differenceInLength = -differenceInLength;
for (int i = number1.size() - 1; i >= 0; --i)
for (int i = (int)(number1.size()) - 1; i >= 0; --i)
{
add[i] = ((carry-'0')+(number1[i]-'0')+(number2[i]-'0')) + '0';
@ -364,7 +364,7 @@ private:
if (differenceInLength < 0)
differenceInLength = -differenceInLength;
for (int i = number1.length() - 1; i >= 0; --i)
for (int i = (int)(number1.length()) - 1; i >= 0; --i)
{
if (number1[i] < number2[i])
{
@ -386,13 +386,13 @@ private:
n1.swap(n2);
std::string res = "0";
for (int i = n1.length() - 1; i >= 0; --i)
for (int i = (int)(n1.length()) - 1; i >= 0; --i)
{
std::string temp = n2;
int currentDigit = n1[i] - '0';
int carry = 0;
for (int j = temp.length() - 1; j >= 0; --j)
for (int j = (int)(temp.length()) - 1; j >= 0; --j)
{
temp[j] = ((temp[j]-'0') * currentDigit) + carry;

View File

@ -11,6 +11,19 @@ TEMPLATE = lib
CONFIG += staticlib
QMAKE_CXXFLAGS += -Wall -g
DEFINES += \
LIBXML_READER_ENABLED \
LIBXML_PUSH_ENABLED \
LIBXML_HTML_ENABLED \
LIBXML_XPATH_ENABLED \
LIBXML_OUTPUT_ENABLED \
LIBXML_C14N_ENABLED \
LIBXML_SAX1_ENABLED \
LIBXML_TREE_ENABLED \
LIBXML_XPTR_ENABLED \
IN_LIBXML \
LIBXML_STATIC
CORE_ROOT_DIR = $$PWD/../../../..
PWD_ROOT_DIR = $$PWD
include(../../../../Common/base.pri)

View File

@ -305,6 +305,19 @@ namespace XmlUtils
strValues.push_back (NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)p->second.c_str(), (long)p->second.length()));
}
}
template<typename T>
void ReadAllAttributesA(T& strNames, T& strValues)
{
if (!IsValid())
return;
std::map<std::string, std::string>::iterator p;
for (p = m_pBase->m_attributes.begin(); p != m_pBase->m_attributes.end(); ++p)
{
strNames.push_back(p->first);
strValues.push_back(p->second);
}
}
template <typename T>
void ReadNodeValueBase(const wchar_t* bsName, T& value)
{

View File

@ -3,6 +3,7 @@
#include "./XmlCanonicalizator.h"
#include "./XmlSignerBase.h"
#include "./XmlTransform.h"
class COOXMLSigner
{
@ -23,167 +24,6 @@ public:
std::wstring m_guid;
public:
class COOXMLRelationship
{
public:
std::wstring rid;
std::wstring type;
std::wstring target;
std::wstring target_mode;
public:
COOXMLRelationship()
{
}
COOXMLRelationship(XmlUtils::CXmlNode& node)
{
rid = node.GetAttribute("Id");
type = node.GetAttribute("Type");
target = node.GetAttribute("Target");
CheckTargetMode();
}
std::wstring GetXml()
{
NSStringUtils::CStringBuilder builder;
builder.WriteString(L"<Relationship Id=\"");
builder.WriteEncodeXmlString(rid);
builder.WriteString(L"\" Type=\"");
builder.WriteEncodeXmlString(type);
builder.WriteString(L"\" Target=\"");
builder.WriteEncodeXmlString(target);
builder.WriteString(L"\" TargetMode=\"");
builder.WriteEncodeXmlString(target_mode);
builder.WriteString(L"\" />");
return builder.GetData();
}
static bool Compare(const COOXMLRelationship& i, const COOXMLRelationship& j)
{
return i.rid < j.rid;
}
protected:
void CheckTargetMode()
{
if (0 == target.find(L"http") || 0 == target.find(L"www") || 0 == target.find(L"ftp"))
target_mode = L"External";
else
target_mode = L"Internal";
}
};
class COOXMLRelationships
{
public:
std::vector<COOXMLRelationship> rels;
public:
COOXMLRelationships()
{
}
COOXMLRelationships(std::wstring& file)
{
XmlUtils::CXmlNode oNode;
if (!oNode.FromXmlFile(file))
return;
XmlUtils::CXmlNodes oNodes;
if (!oNode.GetNodes(L"Relationship", oNodes))
return;
int nCount = oNodes.GetCount();
for (int i = 0; i < nCount; ++i)
{
XmlUtils::CXmlNode oRel;
oNodes.GetAt(i, oRel);
rels.push_back(COOXMLRelationship(oRel));
}
}
std::wstring GetXml()
{
NSStringUtils::CStringBuilder builder;
builder.WriteString(L"<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">");
// sort by rId
std::sort(rels.begin(), rels.end(), COOXMLRelationship::Compare);
for (std::vector<COOXMLRelationship>::iterator i = rels.begin(); i != rels.end(); i++)
builder.WriteString(i->GetXml());
builder.WriteString(L"</Relationships>");
return builder.GetData();
}
std::wstring GetTransforms()
{
NSStringUtils::CStringBuilder builder;
builder.WriteString(L"<Transforms><Transform Algorithm=\"http://schemas.openxmlformats.org/package/2006/RelationshipTransform\">");
for (std::vector<COOXMLRelationship>::iterator i = rels.begin(); i != rels.end(); i++)
{
builder.WriteString(L"<mdssi:RelationshipReference xmlns:mdssi=\"http://schemas.openxmlformats.org/package/2006/digital-signature\" SourceId=\"");
builder.WriteEncodeXmlString(i->rid);
builder.WriteString(L"\" />");
}
builder.WriteString(L"</Transform><Transform Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/></Transforms>");
return builder.GetData();
}
void CheckOriginSigs(std::wstring& file)
{
int rId = 0;
std::vector<COOXMLRelationship>::iterator i = rels.begin();
while (i != rels.end())
{
if (0 == i->target.find(L"_xmlsignatures/"))
return;
std::wstring rid = i->rid;
rid = rid.substr(3);
int nTemp = std::stoi(rid);
if (nTemp > rId)
rId = nTemp;
i++;
}
std::string sXmlA;
NSFile::CFileBinary::ReadAllTextUtf8A(file, sXmlA);
std::string::size_type pos = sXmlA.rfind("</Relationships>");
if (pos == std::string::npos)
return;
rId++;
std::string sRet = sXmlA.substr(0, pos);
sRet += ("<Relationship Id=\"rId" + std::to_string(rId) + "\" \
Type=\"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin\" Target=\"_xmlsignatures/origin.sigs\"/>\
</Relationships>");
NSFile::CFileBinary::Remove(file);
NSFile::CFileBinary oFile;
oFile.CreateFileW(file);
oFile.WriteFile((BYTE*)sRet.c_str(), (DWORD)sRet.length());
oFile.CloseFile();
}
};
public:
COOXMLSigner(const std::wstring& sFolder, ICertificate* pContext)
{
@ -204,7 +44,7 @@ public:
std::wstring sXml = L"<Reference URI=\"" + file + L"?ContentType=" + content_type + L"\">";
sXml += L"<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/>";
sXml += L"<DigestValue>";
sXml += UTF8_TO_U(m_certificate->GetHash(m_sFolder + file));
sXml += UTF8_TO_U(m_certificate->GetHash(m_sFolder + file, OOXML_HASH_ALG_SHA1));
sXml += L"</DigestValue>";
sXml += L"</Reference>";
return sXml;
@ -214,7 +54,7 @@ public:
{
std::string sXmlSigned = U_TO_UTF8(xml);
sXmlSigned = CXmlCanonicalizator::Execute(sXmlSigned, XML_C14N_1_0);
return m_certificate->GetHash(sXmlSigned);
return m_certificate->GetHash(sXmlSigned, OOXML_HASH_ALG_SHA1);
}
std::string GetReferenceMain(const std::wstring& xml, const std::wstring& id, const bool& isCannon = true)
@ -259,7 +99,7 @@ public:
std::wstring GetRelsReference(const std::wstring& file)
{
COOXMLRelationships oRels(m_sFolder + file);
COOXMLRelationships oRels(m_sFolder + file, true);
if (L"/_rels/.rels" == file)
{
@ -651,7 +491,7 @@ Type=\"http://schemas.openxmlformats.org/package/2006/relationships/digital-sign
m_signed_info.WriteString("<Reference Type=\"http://uri.etsi.org/01903#SignedProperties\" URI=\"#idSignedProperties\">");
m_signed_info.WriteString("<Transforms><Transform Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/></Transforms>");
m_signed_info.WriteString("<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>");
m_signed_info.WriteString(m_certificate->GetHash(sXmlTmp));
m_signed_info.WriteString(m_certificate->GetHash(sXmlTmp, OOXML_HASH_ALG_SHA1));
m_signed_info.WriteString("</DigestValue></Reference>");
return (L"<Object><xd:QualifyingProperties xmlns:xd=\"http://uri.etsi.org/01903/v1.3.2#\" Target=\"#idPackageSignature\">\

View File

@ -0,0 +1,248 @@
#ifndef _XML_OOXMLVERIFIER_H_
#define _XML_OOXMLVERIFIER_H_
#include "./XmlCanonicalizator.h"
#include "./XmlTransform.h"
#include "./XmlCertificate.h"
#define OOXML_SIGNATURE_VALID 0
#define OOXML_SIGNATURE_INVALID 1
#define OOXML_SIGNATURE_NOTSUPPORTED 2
#define OOXML_SIGNATURE_BAD 3
class COOXMLSignature
{
private:
int m_valid;
std::string m_guid;
ICertificate* m_cert;
std::string m_sImageValidBase64;
std::string m_sImageInvalidBase64;
private:
XmlUtils::CXmlNode m_node; // signature file
class CXmlStackNamespaces
{
public:
std::wstring m_namespaces;
XmlUtils::CXmlNode m_node;
public:
CXmlStackNamespaces(const CXmlStackNamespaces& src)
{
m_namespaces = src.m_namespaces;
m_node = src.m_node;
}
CXmlStackNamespaces()
{
}
CXmlStackNamespaces(const XmlUtils::CXmlNode& node)
{
m_node = node;
}
CXmlStackNamespaces& operator=(const CXmlStackNamespaces& src)
{
m_namespaces = src.m_namespaces;
m_node = src.m_node;
return *this;
}
CXmlStackNamespaces GetById(const std::string& id)
{
return GetByIdRec(*this, id);
}
CXmlStackNamespaces GetByIdRec(CXmlStackNamespaces& stack, const std::string& id)
{
if (stack.m_node.GetAttributeA("Id") == id)
return stack;
CXmlStackNamespaces ret = stack;
std::vector<std::wstring> _names;
std::vector<std::wstring> _values;
ret.m_node.ReadAllAttributes(_names, _values);
NSStringUtils::CStringBuilder oBuilder;
oBuilder.WriteString(L" ");
for (std::vector<std::wstring>::iterator i = _names.begin(), j = _values.begin(); i != _names.end(); i++, j++)
{
if (i->find(L"xmlns") == 0)
{
oBuilder.WriteString(*i);
oBuilder.WriteString(L"=\"");
oBuilder.WriteEncodeXmlString(*j);
oBuilder.WriteString(L"\"");
}
}
if (oBuilder.GetCurSize() != 1)
ret.m_namespaces += oBuilder.GetData();
XmlUtils::CXmlNodes oNodes;
if (stack.m_node.GetChilds(oNodes))
{
int nCount = oNodes.GetCount();
for (int i = 0; i < nCount; i++)
{
oNodes.GetAt(i, ret.m_node);
CXmlStackNamespaces _retRecursion = ret.GetByIdRec(ret, id);
if (_retRecursion.m_node.IsValid())
return _retRecursion;
}
}
return CXmlStackNamespaces();
}
std::string GetXml()
{
std::wstring sXml = m_node.GetXml();
if (!m_namespaces.empty())
{
std::wstring sName = m_node.GetName();
std::wstring sXmlFind = L"<" + sName + L" ";
if (0 == sXml.find(sXmlFind))
sXml.replace(0, sXmlFind.length(), L"<" + sName + L" " + m_namespaces + L" ");
}
return U_TO_UTF8(sXml);
}
};
public:
COOXMLSignature()
{
m_valid = OOXML_SIGNATURE_INVALID;
m_guid = "";
m_cert = NULL;
}
~COOXMLSignature()
{
RELEASEOBJECT(m_cert);
}
public:
int GetValid()
{
return m_valid;
}
std::string GetGuid()
{
return m_guid;
}
ICertificate* GetCertificate()
{
return m_cert;
}
std::string GetImageValidBase64()
{
return m_sImageValidBase64;
}
std::string GetImageInvalidBase64()
{
return m_sImageInvalidBase64;
}
public:
void Check()
{
// 1) get cert
XmlUtils::CXmlNode oNodeCert = m_node.ReadNode(L"KeyInfo").ReadNode(L"X509Data").ReadNode(L"X509Certificate");
if (!oNodeCert.IsValid())
{
m_valid = OOXML_SIGNATURE_NOTSUPPORTED;
return;
}
m_cert = new CCertificate();
if (!m_cert->LoadFromBase64Data(U_TO_UTF8(oNodeCert.GetText())))
{
m_valid = OOXML_SIGNATURE_NOTSUPPORTED;
return;
}
// 2) Objects
XmlUtils::CXmlNodes nodesReferences;
m_node.ReadNode(L"SignedInfo").GetNodes(L"Reference", nodesReferences);
CXmlStackNamespaces stack(m_node);
int nCount = nodesReferences.GetCount();
for (int i = 0; i < nCount; i++)
{
XmlUtils::CXmlNode nodeRef;
nodesReferences.GetAt(i, nodeRef);
std::string sId = nodeRef.GetAttributeA("URI");
if (0 == sId.find("#"))
sId = sId.substr(1);
CXmlStackNamespaces _stack = stack.GetById(sId);
std::string sTmp = _stack.GetXml();
XML_UNUSED(sTmp);
}
}
friend class COOXMLVerifier;
};
class COOXMLVerifier
{
public:
std::wstring m_sFolder;
std::vector<COOXMLSignature*> m_arSignatures;
public:
COOXMLVerifier(const std::wstring& sFolder)
{
m_sFolder = sFolder;
if (!NSFile::CFileBinary::Exists(m_sFolder + L"/_xmlsignatures/origin.sigs"))
return;
XmlUtils::CXmlNode oContentTypes;
if (!oContentTypes.FromXmlFile(m_sFolder + L"/[Content_Types].xml"))
return;
XmlUtils::CXmlNodes oOverrides = oContentTypes.GetNodes(L"Override");
int nCount = oOverrides.GetCount();
for (int i = 0; i < nCount; i++)
{
XmlUtils::CXmlNode node;
oOverrides.GetAt(i, node);
if (node.GetAttributeA("ContentType") != "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml")
continue;
std::wstring sFile = m_sFolder + node.GetAttribute("PartName");
XmlUtils::CXmlNode nodeSig;
if (!nodeSig.FromXmlFile(sFile))
continue;
if (nodeSig.GetName() != L"Signature")
continue;
COOXMLSignature* pSignature = new COOXMLSignature();
pSignature->m_node = nodeSig;
pSignature->Check();
m_arSignatures.push_back(pSignature);
}
}
~COOXMLVerifier()
{
for (std::vector<COOXMLSignature*>::iterator i = m_arSignatures.begin(); i != m_arSignatures.end(); i++)
{
COOXMLSignature* v = *i;
RELEASEOBJECT(v);
}
m_arSignatures.clear();
}
};
#endif //_XML_OOXMLVERIFIER_H_

View File

@ -8,6 +8,10 @@
#include "../../xml/include/xmlutils.h"
#include "../../xml/libxml2/include/libxml/c14n.h"
#ifndef XML_UNUSED
#define XML_UNUSED( arg ) ( (arg) = (arg) )
#endif
class CXmlCanonicalizator
{
private:
@ -33,11 +37,14 @@ private:
static int buffer_xmlBufferIOClose(CXmlBuffer* buf)
{
XML_UNUSED(buf);
return 0;
}
static int buffer_xmlC14NIsVisibleCallback(void * user_data, xmlNodePtr node, xmlNodePtr parent)
{
XML_UNUSED(user_data);
XML_UNUSED(parent);
if (node->type == XML_TEXT_NODE)
{
const char* cur = (char*)node->content;
@ -53,7 +60,7 @@ private:
}
public:
static std::string Execute(const std::string& sXml, int mode)
static std::string Execute(const std::string& sXml, int mode = XML_C14N_1_0, bool withComments = false)
{
xmlDocPtr xmlDoc = xmlParseMemory((char*)sXml.c_str(), (int)sXml.length());
@ -63,21 +70,18 @@ public:
&bufferC14N,
NULL);
xmlC14NExecute(xmlDoc, buffer_xmlC14NIsVisibleCallback, NULL, mode, NULL, 0, _buffer);
xmlC14NExecute(xmlDoc, buffer_xmlC14NIsVisibleCallback, NULL, mode, NULL, withComments ? 1 : 0, _buffer);
xmlOutputBufferClose(_buffer);
return bufferC14N.builder.GetData();
}
static std::string Execute(const std::wstring& sXmlFile, int mode)
static std::string Execute(const std::wstring& sXmlFile, int mode = XML_C14N_1_0, bool withComments = false)
{
std::string sXml;
NSFile::CFileBinary::ReadAllTextUtf8A(sXmlFile, sXml);
xmlDocPtr xmlDoc = xmlParseMemory((char*)sXml.c_str(), (int)sXml.length());
return Execute(sXml, mode);
return Execute(sXml, mode, withComments);
}
};

View File

@ -0,0 +1,17 @@
#ifndef _XMLSIGNER_CERTIFICATE_H_
#define _XMLSIGNER_CERTIFICATE_H_
#ifdef WIN32
#include "XmlSigner_mscrypto.h"
#define CCertificate CCertificate_mscrypto
#endif
#if defined(_LINUX) && !defined(_MAC)
#endif
#ifdef _MAC
#endif
#endif // _XMLSIGNER_CERTIFICATE_H_

View File

@ -0,0 +1,199 @@
#ifndef _XML_RELS_H_
#define _XML_RELS_H_
#include "./XmlCanonicalizator.h"
class COOXMLRelationship
{
public:
std::wstring rid;
std::wstring type;
std::wstring target;
std::wstring target_mode;
public:
COOXMLRelationship()
{
}
COOXMLRelationship(XmlUtils::CXmlNode& node)
{
rid = node.GetAttribute("Id");
type = node.GetAttribute("Type");
target = node.GetAttribute("Target");
CheckTargetMode();
}
std::wstring GetXml()
{
NSStringUtils::CStringBuilder builder;
builder.WriteString(L"<Relationship Id=\"");
builder.WriteEncodeXmlString(rid);
builder.WriteString(L"\" Type=\"");
builder.WriteEncodeXmlString(type);
builder.WriteString(L"\" Target=\"");
builder.WriteEncodeXmlString(target);
builder.WriteString(L"\" TargetMode=\"");
builder.WriteEncodeXmlString(target_mode);
builder.WriteString(L"\" />");
return builder.GetData();
}
static bool Compare(const COOXMLRelationship& i, const COOXMLRelationship& j)
{
return i.rid < j.rid;
}
protected:
void CheckTargetMode()
{
if (0 == target.find(L"http") || 0 == target.find(L"www") || 0 == target.find(L"ftp"))
target_mode = L"External";
else
target_mode = L"Internal";
}
};
class COOXMLRelationships
{
public:
std::vector<COOXMLRelationship> rels;
public:
COOXMLRelationships()
{
}
COOXMLRelationships(const std::string& xml, std::map<std::wstring, bool>* check_need = NULL)
{
XmlUtils::CXmlNode oNode;
if (!oNode.FromXmlStringA(xml))
return;
FromXmlNode(oNode, check_need);
}
COOXMLRelationships(const std::wstring& xml, const bool& is_file, std::map<std::wstring, bool>* check_need = NULL)
{
XmlUtils::CXmlNode oNode;
if (!is_file)
{
if (!oNode.FromXmlString(xml))
return;
}
else
{
if (!oNode.FromXmlFile(xml))
return;
}
FromXmlNode(oNode, check_need);
}
void FromXmlNode(XmlUtils::CXmlNode& oNode, std::map<std::wstring, bool>* check_need = NULL)
{
XmlUtils::CXmlNodes oNodes;
if (!oNode.GetNodes(L"Relationship", oNodes))
return;
int nCount = oNodes.GetCount();
for (int i = 0; i < nCount; ++i)
{
XmlUtils::CXmlNode oRel;
oNodes.GetAt(i, oRel);
if (NULL == check_need)
{
rels.push_back(COOXMLRelationship(oRel));
}
else
{
std::wstring sRid = oRel.GetAttribute("Id");
if (check_need->find(sRid) != check_need->end())
rels.push_back(COOXMLRelationship(oRel));
}
}
}
std::wstring GetXml()
{
NSStringUtils::CStringBuilder builder;
builder.WriteString(L"<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">");
// sort by rId
std::sort(rels.begin(), rels.end(), COOXMLRelationship::Compare);
for (std::vector<COOXMLRelationship>::iterator i = rels.begin(); i != rels.end(); i++)
builder.WriteString(i->GetXml());
builder.WriteString(L"</Relationships>");
return builder.GetData();
}
std::wstring GetTransforms()
{
NSStringUtils::CStringBuilder builder;
builder.WriteString(L"<Transforms><Transform Algorithm=\"http://schemas.openxmlformats.org/package/2006/RelationshipTransform\">");
for (std::vector<COOXMLRelationship>::iterator i = rels.begin(); i != rels.end(); i++)
{
builder.WriteString(L"<mdssi:RelationshipReference xmlns:mdssi=\"http://schemas.openxmlformats.org/package/2006/digital-signature\" SourceId=\"");
builder.WriteEncodeXmlString(i->rid);
builder.WriteString(L"\" />");
}
builder.WriteString(L"</Transform><Transform Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/></Transforms>");
return builder.GetData();
}
void CheckOriginSigs(std::wstring& file)
{
int rId = 0;
std::vector<COOXMLRelationship>::iterator i = rels.begin();
while (i != rels.end())
{
if (0 == i->target.find(L"_xmlsignatures/"))
return;
std::wstring rid = i->rid;
rid = rid.substr(3);
int nTemp = std::stoi(rid);
if (nTemp > rId)
rId = nTemp;
i++;
}
std::string sXmlA;
NSFile::CFileBinary::ReadAllTextUtf8A(file, sXmlA);
std::string::size_type pos = sXmlA.rfind("</Relationships>");
if (pos == std::string::npos)
return;
rId++;
std::string sRet = sXmlA.substr(0, pos);
sRet += ("<Relationship Id=\"rId" + std::to_string(rId) + "\" \
Type=\"http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin\" Target=\"_xmlsignatures/origin.sigs\"/>\
</Relationships>");
NSFile::CFileBinary::Remove(file);
NSFile::CFileBinary oFile;
oFile.CreateFileW(file);
oFile.WriteFile((BYTE*)sRet.c_str(), (DWORD)sRet.length());
oFile.CloseFile();
}
};
#endif //_XML_RELS_H_

View File

@ -8,6 +8,9 @@
#include <vector>
#include <map>
#define OOXML_HASH_ALG_SHA1 0
#define OOXML_HASH_ALG_INVALID 1
class ICertificate
{
public:
@ -27,14 +30,26 @@ public:
virtual std::string GetCertificateHash() = 0;
public:
virtual std::string Sign(std::string sXml) = 0;
virtual std::string GetHash(unsigned char* pData, unsigned int nSize) = 0;
virtual std::string GetHash(std::string& sXml) = 0;
virtual std::string GetHash(std::wstring& sXmlFile) = 0;
virtual bool Verify(std::string& sXml, std::string& sXmlSignature) = 0;
virtual std::string Sign(std::string sXml) = 0;
virtual std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg) = 0;
virtual std::string GetHash(std::string& sXml, int nAlg) = 0;
virtual std::string GetHash(std::wstring& sXmlFile, int nAlg) = 0;
virtual bool Verify(std::string& sXml, std::string& sXmlSignature, int nAlg) = 0;
virtual bool LoadFromBase64Data(const std::string& data) = 0;
virtual int ShowCertificate() = 0;
public:
virtual bool ShowSelectDialog() = 0;
static int GetOOXMLHashAlg(const std::string& sAlg)
{
if ("http://www.w3.org/2000/09/xmldsig#rsa-sha1" == sAlg ||
"http://www.w3.org/2000/09/xmldsig#sha1" == sAlg)
return OOXML_HASH_ALG_SHA1;
return OOXML_HASH_ALG_INVALID;
}
};
#endif // _XMLSIGNER_BASE_H_

View File

@ -14,27 +14,40 @@ public:
HCERTSTORE m_store;
PCCERT_CONTEXT m_context;
protected:
BYTE* m_rawData;
int m_rawDataLen;
public:
CCertificate_mscrypto() : ICertificate()
{
m_store = NULL;
m_context = NULL;
m_rawData = NULL;
m_rawDataLen = 0;
}
CCertificate_mscrypto(PCCERT_CONTEXT ctx) : ICertificate()
{
m_store = NULL;
m_context = ctx;
m_rawData = NULL;
m_rawDataLen = 0;
}
virtual ~CCertificate_mscrypto()
{
if (m_store != NULL)
if (m_store != NULL || m_rawData != NULL)
{
if (NULL != m_context)
CertFreeCertificateContext(m_context);
CertCloseStore(m_store, 0);
RELEASEARRAYOBJECTS(m_rawData);
}
if (m_store != NULL)
CertCloseStore(m_store, 0);
}
public:
@ -80,7 +93,7 @@ public:
virtual std::string GetCertificateHash()
{
return GetHash(m_context->pbCertEncoded, (unsigned int)m_context->cbCertEncoded);
return GetHash(m_context->pbCertEncoded, (unsigned int)m_context->cbCertEncoded, OOXML_HASH_ALG_SHA1);
}
public:
@ -153,8 +166,11 @@ public:
return sReturn;
}
virtual std::string GetHash(unsigned char* pData, unsigned int nSize)
virtual std::string GetHash(unsigned char* pData, unsigned int nSize, int nAlg)
{
if (nAlg == OOXML_HASH_ALG_INVALID)
return "";
BOOL bResult = TRUE;
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
@ -168,7 +184,7 @@ public:
if (!bResult)
return "";
bResult = CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash);
bResult = CryptCreateHash(hCryptProv, GetHashId(nAlg), 0, 0, &hHash);
if (!bResult)
{
CryptReleaseContext(hCryptProv, 0);
@ -218,12 +234,12 @@ public:
return sReturn;
}
virtual std::string GetHash(std::string& sXml)
virtual std::string GetHash(std::string& sXml, int nAlg)
{
return GetHash((BYTE*)sXml.c_str(), (DWORD)sXml.length());
return GetHash((BYTE*)sXml.c_str(), (DWORD)sXml.length(), nAlg);
}
virtual std::string GetHash(std::wstring& sXmlFile)
virtual std::string GetHash(std::wstring& sXmlFile, int nAlg)
{
BYTE* pFileData = NULL;
DWORD dwFileDataLen = 0;
@ -232,13 +248,13 @@ public:
if (0 == dwFileDataLen)
return "";
std::string sReturn = GetHash(pFileData, dwFileDataLen);
std::string sReturn = GetHash(pFileData, dwFileDataLen, nAlg);
RELEASEARRAYOBJECTS(pFileData);
return sReturn;
}
virtual bool Verify(std::string& sXml, std::string& sXmlSignature)
virtual bool Verify(std::string& sXml, std::string& sXmlSignature, int nAlg)
{
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
@ -250,7 +266,7 @@ public:
if (!bResult)
return FALSE;
bResult = CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash);
bResult = CryptCreateHash(hCryptProv, GetHashId(nAlg), 0, 0, &hHash);
if (!bResult)
{
@ -286,6 +302,28 @@ public:
return bResultRet && bResult;
}
virtual bool LoadFromBase64Data(const std::string& data)
{
RELEASEARRAYOBJECTS(m_rawData);
if (!NSFile::CBase64Converter::Decode(data.c_str(), (int)data.length(), m_rawData, m_rawDataLen))
return false;
m_context = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, m_rawData, m_rawDataLen);
if (!m_context)
{
RELEASEARRAYOBJECTS(m_rawData);
m_rawDataLen = 0;
return false;
}
return true;
}
virtual int ShowCertificate()
{
return (int)CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, m_context, NULL, NULL, 0, NULL);
}
public:
virtual bool ShowSelectDialog()
{
@ -309,6 +347,17 @@ private:
for(BYTE* p = dst + size - 1; p >= dst; ++src, --p)
(*p) = (*src);
}
ALG_ID GetHashId(int nAlg)
{
switch (nAlg)
{
case OOXML_HASH_ALG_SHA1:
return CALG_SHA1;
default:
return CALG_SHA1;
}
}
};
#endif // _XMLSIGNER_MSCRYPTO_H_

View File

@ -0,0 +1,186 @@
#ifndef _XML_TRANSFORM_H_
#define _XML_TRANSFORM_H_
#include "./XmlRels.h"
class IXmlTransform
{
protected:
std::string m_algorithm;
public:
IXmlTransform()
{
m_algorithm = "";
}
virtual ~IXmlTransform()
{
}
public:
virtual std::string Transform(const std::string& sXml) = 0;
virtual void LoadFromXml(XmlUtils::CXmlNode& node) = 0;
static IXmlTransform* GetFromType(const std::string& alg);
};
class CXmlTransformRelationship : public IXmlTransform
{
protected:
std::map<std::wstring, bool> m_arIds;
public:
CXmlTransformRelationship() : IXmlTransform()
{
m_algorithm = "http://schemas.openxmlformats.org/package/2006/RelationshipTransform";
}
virtual std::string Transform(const std::string& xml)
{
COOXMLRelationships _rels(xml, &m_arIds);
return U_TO_UTF8(_rels.GetXml());
}
virtual void LoadFromXml(XmlUtils::CXmlNode& node)
{
XmlUtils::CXmlNodes oNodesIds;
node.GetChilds(oNodesIds);
int nCount = oNodesIds.GetCount();
for (int i = 0; i < nCount; ++i)
{
XmlUtils::CXmlNode _node;
oNodesIds.GetAt(i, _node);
std::wstring sType = _node.GetAttribute("SourceId");
if (!sType.empty())
m_arIds.insert(std::pair<std::wstring, bool>(sType, true));
}
}
};
class CXmlTransformC14N : public IXmlTransform
{
protected:
int m_mode;
bool m_comments;
public:
CXmlTransformC14N() : IXmlTransform()
{
m_mode = -1;
m_comments = false;
}
bool CheckC14NTransform(const std::string& alg)
{
m_mode = -1;
if ("http://www.w3.org/TR/2001/REC-xml-c14n-20010315" == alg)
{
m_mode = XML_C14N_1_0;
m_comments = false;
}
else if ("http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" == alg)
{
m_mode = XML_C14N_1_0;
m_comments = true;
}
else if ("http://www.w3.org/2006/12/xml-c14n11" == alg)
{
m_mode = XML_C14N_1_1;
m_comments = false;
}
else if ("http://www.w3.org/2006/12/xml-c14n11#WithComments" == alg)
{
m_mode = XML_C14N_1_1;
m_comments = true;
}
else if ("http://www.w3.org/2001/10/xml-exc-c14n#" == alg)
{
m_mode = XML_C14N_EXCLUSIVE_1_0;
m_comments = false;
}
else if ("http://www.w3.org/2001/10/xml-exc-c14n#WithComments" == alg)
{
m_mode = XML_C14N_EXCLUSIVE_1_0;
m_comments = true;
}
return (-1 != m_mode) ? true : false;
}
virtual std::string Transform(const std::string& xml)
{
// TODO
return xml;
}
virtual void LoadFromXml(XmlUtils::CXmlNode& node)
{
// none
XML_UNUSED(node);
}
};
IXmlTransform* IXmlTransform::GetFromType(const std::string& alg)
{
if (true)
{
CXmlTransformRelationship* transform = new CXmlTransformRelationship();
if (transform->m_algorithm == alg)
return transform;
RELEASEOBJECT(transform);
}
if (true)
{
CXmlTransformC14N* transform = new CXmlTransformC14N();
if (transform->CheckC14NTransform(alg))
return transform;
RELEASEOBJECT(transform);
}
return NULL;
}
class CXmlTransforms
{
protected:
std::vector<IXmlTransform*> m_transforms;
bool m_valid;
public:
CXmlTransforms(XmlUtils::CXmlNode& node)
{
m_valid = true;
XmlUtils::CXmlNodes oNodes = node.GetNodes(L"Transform");
int nCount = oNodes.GetCount();
for (int i = 0; i < nCount; ++i)
{
XmlUtils::CXmlNode nodeTransform;
oNodes.GetAt(i, nodeTransform);
IXmlTransform* pTransform = IXmlTransform::GetFromType(nodeTransform.GetAttributeA("Algorithm"));
if (NULL == pTransform)
{
m_valid = false;
return;
}
pTransform->LoadFromXml(nodeTransform);
m_transforms.push_back(pTransform);
}
}
~CXmlTransforms()
{
for (std::vector<IXmlTransform*>::iterator i = m_transforms.begin(); i != m_transforms.end(); i++)
{
IXmlTransform* t = *i;
RELEASEOBJECT(t);
}
m_transforms.clear();
}
};
#endif //_XML_TRANSFORM_H_

View File

@ -6,7 +6,9 @@ TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
DEFINES += UNICODE
DEFINES -= \
UNICODE \
_UNICODE
CORE_ROOT_DIR = $$PWD/../../../..
PWD_ROOT_DIR = $$PWD

View File

@ -1,6 +1,6 @@
#include "../../src/XmlCanonicalizator.h"
#include "../../src/XmlSigner_mscrypto.h"
#include "../../src/XmlCertificate.h"
#include "../../src/OOXMLSigner.h"
#include "../../src/OOXMLVerifier.h"
#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "cryptui.lib")
@ -12,17 +12,34 @@ void main(void)
//std::wstring sSignId = L"{39B6B9C7-60AD-45A2-9F61-40C74A24042E}";
std::wstring sFolderOOXML = L"D:\\555";
std::wstring sSignId = L"{9792D33F-AB37-4E5B-A465-481B9465818B}";
CCertificate_mscrypto oCertificate;
if (!oCertificate.ShowSelectDialog())
return;
if (false)
{
std::wstring sSignId = L"{9792D33F-AB37-4E5B-A465-481B9465818B}";
COOXMLSigner oOOXMLSigner(sFolderOOXML, &oCertificate);
CCertificate oCertificate;
if (!oCertificate.ShowSelectDialog())
return;
oOOXMLSigner.SetGuid(sSignId);
oOOXMLSigner.SetImageValid(NSFile::GetProcessDirectory() + L"/../../../resources/valid.png");
oOOXMLSigner.SetImageInvalid(NSFile::GetProcessDirectory() + L"/../../../resources/invalid.png");
COOXMLSigner oOOXMLSigner(sFolderOOXML, &oCertificate);
oOOXMLSigner.Sign();
oOOXMLSigner.SetGuid(sSignId);
oOOXMLSigner.SetImageValid(NSFile::GetProcessDirectory() + L"/../../../resources/valid.png");
oOOXMLSigner.SetImageInvalid(NSFile::GetProcessDirectory() + L"/../../../resources/invalid.png");
oOOXMLSigner.Sign();
}
else
{
COOXMLVerifier oVerifier(sFolderOOXML);
size_t nCount = oVerifier.m_arSignatures.size();
for (std::vector<COOXMLSignature*>::iterator i = oVerifier.m_arSignatures.begin(); i != oVerifier.m_arSignatures.end(); i++)
{
COOXMLSignature* pSign = *i;
XML_UNUSED(pSign);
}
XML_UNUSED(nCount);
}
}