Commit 29c989e7 authored by Elen.Subbotina's avatar Elen.Subbotina Committed by Alexander Trofimov

чтение xls файлов

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@58816 954022d7-b5bf-4e40-9824-e11837661b57
parent 1c811dde

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -345,6 +345,27 @@ ASCOfficeXlsFile/ASCWorksheetConverter/Documents/Сводная[!!-~]табли
ASCOfficeXlsFile/ASCWorksheetConverter/source/Streams_binaries/DocumentSummaryInformation.bin svn_mime_002dtype=application%2Foctet-stream
ASCOfficeXlsFile/ASCWorksheetConverter/source/Streams_binaries/SummaryInformation.bin svn_mime_002dtype=application%2Foctet-stream
ASCOfficeXlsFile/ASCWorksheetConverter/source/XLS_logic/Biff_structures/ODRAW svnc_bugtraq_003anumber=true
/ASCOfficeXlsFile2 svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/Converter svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/Serializer svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Auxiliary svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Auxiliary/nullable svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Binary svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Crypt svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Crypt/rtl svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Document svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Document/msxml svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/FormatFactory svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logging svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_records svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_structures/ODRAW svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic/Biff_unions svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic/SummaryInformationStream svnc_tsvn_003alogminsize=5
ASCOfficeXlsFile2/source/XlsFormat/Logic/SummaryInformationStream/Structures svnc_tsvn_003alogminsize=5
Common/ASCDocxFormat/Lib/Debug/Common.lib svn_mime_002dtype=application%2Foctet-stream
Common/ASCDocxFormat/Lib/Debug/DocxFormat.lib svn_mime_002dtype=application%2Foctet-stream
Common/ASCDocxFormat/Lib/Debug/Utility.lib svn_mime_002dtype=application%2Foctet-stream
......
// ASCOfficeXlsFile2.cpp : Implementation of DLL Exports.
#include "stdafx.h"
#include "resource.h"
// The module attribute causes DllMain, DllRegisterServer and DllUnregisterServer to be automatically implemented for you
[ module(dll, uuid = "{BA5347EE-D187-4D72-AB18-CB0057EF4397}",
name = "ASCOfficeXlsFile2",
helpstring = "ASCOfficeXlsFile2 1.0 Type Library",
resource_name = "IDR_ASCOFFICEXLSFILE2") ]
class CASCOfficeXlsFile2Module
{
public:
// Override CAtlDllModuleT members
};
//Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
LANGUAGE 25, 1
#pragma code_page(1251)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "TODO: <Company name>"
VALUE "FileDescription", "TODO: <File description>"
VALUE "FileVersion", "1.0.0.1"
VALUE "LegalCopyright", "TODO: (c) <Company name>. All rights reserved."
VALUE "InternalName", "ASCOfficeXlsFile2.dll"
VALUE "OriginalFilename", "ASCOfficeXlsFile2.dll"
VALUE "ProductName", "TODO: <Product name>"
VALUE "ProductVersion", "1.0.0.1"
VALUE "OLESelfRegister", ""
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1252
END
END
#endif // !_MAC
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_PROJNAME "ASCOfficeXlsFile2"
END
IDR_ASCOFFICEXLSFILE2 REGISTRY "ASCOfficeXlsFile2.rgs"
////////////////////////////////////////////////////////////////////////////
#endif
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
HKCR
{
NoRemove AppID
{
'%APPID%' = s 'ASCOfficeXlsFile2'
'ASCOfficeXlsFile2.DLL'
{
val AppID = s '%APPID%'
}
}
}

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ASCOfficeXlsFile2", "ASCOfficeXlsFile2.vcproj", "{4260FEDF-E1DA-447F-991B-62F17DF5533E}"
ProjectSection(ProjectDependencies) = postProject
{77DDC8D7-5B12-4FF2-9629-26AEBCA8436D} = {77DDC8D7-5B12-4FF2-9629-26AEBCA8436D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XlsFormat", "source\XlsFormat.vcproj", "{77DDC8D7-5B12-4FF2-9629-26AEBCA8436D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4260FEDF-E1DA-447F-991B-62F17DF5533E}.Debug|Win32.ActiveCfg = Debug|Win32
{4260FEDF-E1DA-447F-991B-62F17DF5533E}.Debug|Win32.Build.0 = Debug|Win32
{4260FEDF-E1DA-447F-991B-62F17DF5533E}.Release|Win32.ActiveCfg = Release|Win32
{4260FEDF-E1DA-447F-991B-62F17DF5533E}.Release|Win32.Build.0 = Release|Win32
{77DDC8D7-5B12-4FF2-9629-26AEBCA8436D}.Debug|Win32.ActiveCfg = Debug|Win32
{77DDC8D7-5B12-4FF2-9629-26AEBCA8436D}.Debug|Win32.Build.0 = Debug|Win32
{77DDC8D7-5B12-4FF2-9629-26AEBCA8436D}.Release|Win32.ActiveCfg = Release|Win32
{77DDC8D7-5B12-4FF2-9629-26AEBCA8436D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="ASCOfficeXlsFile2"
ProjectGUID="{4260FEDF-E1DA-447F-991B-62F17DF5533E}"
Keyword="AtlProj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
UseOfATL="2"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
TargetEnvironment="1"
GenerateStublessProxies="true"
TypeLibraryName="$(IntDir)/ASCOfficeXlsFile2.tlb"
HeaderFileName="ASCOfficeXlsFile2.h"
DLLDataFileName=""
InterfaceIdentifierFileName="ASCOfficeXlsFile2_i.c"
ProxyFileName="ASCOfficeXlsFile2_p.c"
ValidateParameters="false"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG;_USRDLL;_ATL_ATTRIBUTES"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1033"
AdditionalIncludeDirectories="$(IntDir)"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RegisterOutput="true"
IgnoreImportLibrary="true"
LinkIncremental="2"
MergedIDLBaseFileName="_ASCOfficeXlsFile2.idl"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
UseOfATL="2"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="false"
TargetEnvironment="1"
GenerateStublessProxies="true"
TypeLibraryName="$(IntDir)/ASCOfficeXlsFile2.tlb"
HeaderFileName="ASCOfficeXlsFile2.h"
DLLDataFileName=""
InterfaceIdentifierFileName="ASCOfficeXlsFile2_i.c"
ProxyFileName="ASCOfficeXlsFile2_p.c"
ValidateParameters="false"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG;_USRDLL;_ATL_ATTRIBUTES"
RuntimeLibrary="2"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1033"
AdditionalIncludeDirectories="$(IntDir)"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
RegisterOutput="true"
IgnoreImportLibrary="true"
LinkIncremental="1"
MergedIDLBaseFileName="_ASCOfficeXlsFile2.idl"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\ASCOfficeXlsFile2.cpp"
>
</File>
<File
RelativePath=".\OfficeXlsFile.cpp"
>
</File>
<File
RelativePath=".\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\OfficeXlsFile.h"
>
</File>
<File
RelativePath=".\Resource.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\ASCOfficeXlsFile2.rc"
>
</File>
<File
RelativePath=".\ASCOfficeXlsFile2.rgs"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
// OfficeXlsFile.cpp : Implementation of COfficeXlsFile
#include "stdafx.h"
#include "OfficeXlsFile.h"
// COfficeXlsFile
HRESULT COfficeXlsFile::SaveToFile(BSTR sDstFileName, BSTR sSrcPath, BSTR sXMLOptions)
{
return E_NOTIMPL;
}
HRESULT COfficeXlsFile::LoadFromFile(BSTR sSrcFileName, BSTR sDstPath, BSTR sXMLOptions)
{
return E_NOTIMPL;
}
// OfficeXlsFile.h : Declaration of the COfficeXlsFile
#pragma once
#include "resource.h" // main symbols
#include "../Common/OfficeFileTemplate.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
// IOfficeXlsFile
[
object,
uuid("DC742420-E2C0-452D-8B59-9E52FD86CD9F"),
dual, helpstring("IOfficeXlsFile Interface"),
pointer_default(unique)
]
__interface IOfficeXlsFile : IAVSOfficeFileTemplate
{
};
// _IOfficeXlsFileEvents
[
dispinterface,
uuid("E3009CC7-399B-49FE-9D88-6CE6C8FF0F97"),
helpstring("_IOfficeXlsFileEvents Interface")
]
__interface _IOfficeXlsFileEvents
{
[id(1), helpstring("method OnProgress")] HRESULT OnProgress([in] DOUBLE progress);
[id(2), helpstring("method OnComplete")] HRESULT OnComplete([in] LONG status);
};
// COfficeXlsFile
[
coclass,
default(IOfficeXlsFile, _IOfficeXlsFileEvents),
threading(apartment),
event_source(com),
vi_progid("ASCOfficeXlsFile2.OfficeXlsFile"),
progid("ASCOfficeXlsFile2.OfficeXlsFile.1"),
version(1.0),
uuid("737DBB37-0309-4D1E-8DA4-3D6E247E693E"),
helpstring("OfficeXlsFile Class")
]
class ATL_NO_VTABLE COfficeXlsFile :
public IOfficeXlsFile
{
public:
COfficeXlsFile()
{
}
__event __interface _IOfficeXlsFileEvents;
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD(LoadFromFile) (BSTR sSrcFileName, BSTR sDstPath, BSTR sXMLOptions);
STDMETHOD(SaveToFile) (BSTR sDstFileName, BSTR sSrcPath, BSTR sXMLOptions);
};
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ASCOfficeXlsFile2.rc
//
#define IDS_PROJNAME 100
#define IDR_ASCOFFICEXLSFILE2 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 201
#define _APS_NEXT_COMMAND_VALUE 32768
#define _APS_NEXT_CONTROL_VALUE 201
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif
#include "stdafx.h"
#include "Converter.h"
#include <Document/Document.h>
const bool Converter::convert(Document& doc, MSXML2::IXMLDOMDocumentPtr xslt)
{
return VARIANT_TRUE == doc.getDoc()->loadXML(doc.getDoc()->transformNode(xslt));
}
#pragma once
class Document;
class Converter
{
public:
virtual const bool convertToX(Document& doc) = 0;
virtual const bool convertFromX(Document& doc) = 0;
protected:
const bool convert(Document& doc, MSXML2::IXMLDOMDocumentPtr xslt);
};
#include "stdafx.h"
#include "XLSConverter.h"
#include <Document/Document.h>
#include <fstream>
#include <iostream> // endl
#include "boost/filesystem.hpp"
namespace XLS
{;
XLSConverter::XLSConverter()
{
}
const bool XLSConverter::convertFromX(Document& doc)
{
MSXML2::IXMLDOMDocument3Ptr xslt_from_X(_T("Msxml2.FreeThreadedDOMDocument.6.0"));
xslt_from_X->Putasync(VARIANT_TRUE);
xslt_from_X->setProperty(L"SelectionNamespaces", L"xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
std::vector<std::wstring> resources;
wchar_t file_path[MAX_PATH];
GetModuleFileNameW(ATL::_AtlBaseModule.GetModuleInstance(), file_path, MAX_PATH);
std::wstring dll_file_name = boost::filesystem::wpath(file_path).filename();
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2012"); // x2xls.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2013"); // x2xls_Globals.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2014"); // propertiesTree.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2015"); // x2xls_Worksheet.xsl
if(!XMLSTUFF::loadXSLTFromResources(xslt_from_X, resources))
{
return false;
}
Log::event("XLSX to XLS XSLT table loaded from resources successfully");
#ifdef _DEBUG
// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
//xslt_from_X->save(L"../InFiles/convert.xsl");
// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
#endif
if(!convert(doc, xslt_from_X))
{
return false;
}
Log::event("The internal XLSX XML converted to XLS XML successfully");
return true;
}
const bool XLSConverter::convertToX(Document& doc)
{
MSXML2::IXMLDOMDocument3Ptr xslt_to_X(_T("Msxml2.FreeThreadedDOMDocument.6.0"));
xslt_to_X->setProperty(L"SelectionNamespaces", L"xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
xslt_to_X->Putasync(VARIANT_TRUE);
std::vector<std::wstring> resources;
wchar_t file_path[MAX_PATH];
GetModuleFileNameW(ATL::_AtlBaseModule.GetModuleInstance(), file_path, MAX_PATH);
std::wstring dll_file_name = boost::filesystem::wpath(file_path).filename();
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2001"); // xls2x.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2003"); // xls2x_rels.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2005"); // xls2x_wb.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2006"); // xls2x_ws.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2008"); // xls2x_styles.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2009"); // xls2x_sst.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2011"); // xls2x_comments.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2014"); // propertiesTree.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2018"); // xls2x_drawing.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2019"); // xls2x_chart.xsl
resources.push_back(L"res://" + dll_file_name + L"/XSL/#2020"); // xls2x_cs.xsl
if(!XMLSTUFF::loadXSLTFromResources(xslt_to_X, resources))
{
return false;
}
Log::event("XLS to XLSX XSLT table loaded from resources successfully");
#ifdef _DEBUG
// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
//xslt_to_X->save(L"../InFiles/convert.xsl");
boost::filesystem::path curr_path = boost::filesystem::current_path();
xslt_to_X->save(L"d://test//convert.xsl");
// Log::event("../InFiles/convert.xsl saved successfully");
// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG
DWORD time_before = GetTickCount();
#endif
if(!convert(doc, xslt_to_X))
{
return false;
}
#ifdef _DEBUG
DWORD ticks_spent = GetTickCount() - time_before;
std::cout << "XSLT conversion took " << ticks_spent / 1000 << " seconds (" << ticks_spent << " ms)" << std::endl;
#endif
Log::event("The internal XLS XML converted to XLSX XML successfully");
return true;
}
} // namespace XLS
#pragma once
#include <Converter/Converter.h>
namespace XLS
{;
class XLSConverter : public Converter
{
public:
XLSConverter();
virtual const bool convertToX(Document& doc);
virtual const bool convertFromX(Document& doc);
};
} // namespace XLS
#include "stdafx.h"
#include "XLSXConverter.h"
namespace XLSX
{;
const bool XLSXConverter::convertToX(Document& doc)
{
return true; // Already the necessary format
}
const bool XLSXConverter::convertFromX(Document& doc)
{
return true; // Already the necessary format
}
} // namespace XLS
#pragma once
#include <Converter/Converter.h>
namespace XLSX
{;
class XLSXConverter : public Converter
{
public:
virtual const bool convertToX(Document& doc);
virtual const bool convertFromX(Document& doc);
};
} // namespace XLSX
#pragma once
#include <Document/Document.h>
//namespace XLS
//{;
class Document;
class Serializer
{
public:
virtual const bool read(Document& doc, const _bstr_t& from) = 0;
virtual const bool write(const Document& doc, const _bstr_t& to) = 0;
};
//} // namespace XLS
#include "stdafx.h"
#include "XLSSerializer.h"
#include <XLS_bin/CFStream.h>
#include <XLS_bin/CompoundFile.h>
#include <XLS_bin/CFStreamCacheReader.h>
#include <XLS_bin/CFStreamCacheWriter.h>
#include <XLS_logic/GlobalWorkbookInfo.h>
#include <XLS_logic/WorkbookStreamObject.h>
#include <XLS_logic/BinProcessor.h>
#include <Exception/CompoundFileFormatError.h>
#include "XLS_logic/SummaryInformationStream/SummaryInformation.h"
#include "Auxiliary/HelpersTagsGenerator.h"
namespace XLS
{;
const bool XLSSerializer::read(Document& doc, const _bstr_t& from)
{
CompoundFile cfile(from, CompoundFile::cf_ReadMode);
/*
CFStreamPtr summary(cfile.getSummaryInformationStream());
size_t summary_size = static_cast<size_t>(summary->getStreamSize());
char* summary_raw = new char[summary_size];
summary->read(summary_raw, summary_size);
std::ofstream file1("SummaryInformation.bin", std::ios_base::binary);
file1.write(summary_raw, summary_size);
file1.flush();
return true;
*/
/*
CFStreamPtr summary(cfile.getDocumentSummaryInformationStream());
size_t summary_size = static_cast<size_t>(summary->getStreamSize());
char* summary_raw = new char[summary_size];
summary->read(summary_raw, summary_size);
std::ofstream file1("DocumentSummaryInformation.bin", std::ios_base::binary);
file1.write(summary_raw, summary_size);
file1.flush();
return true;
*/
CFStreamPtr summary;
CFStreamPtr doc_summary;
try
{
summary = cfile.getSummaryInformationStream();
}
catch (EXCEPT::RT::CompoundFileFormatError&)
{
}
try
{
doc_summary = cfile.getDocumentSummaryInformationStream();
}
catch (EXCEPT::RT::CompoundFileFormatError&)
{
}
WORD workbook_code_page = WorkbookStreamObject::DefaultCodePage;
if(summary)
{
OLEPS::SummaryInformation summary_info(summary);
workbook_code_page = summary_info.GetCodePage();
}
else if(doc_summary)
{
OLEPS::SummaryInformation doc_summary_info(doc_summary);
workbook_code_page = doc_summary_info.GetCodePage();
}
if(1200/* UTF-16 */ == workbook_code_page || 0/*error*/ == workbook_code_page)
{
workbook_code_page = WorkbookStreamObject::DefaultCodePage;
}
GlobalWorkbookInfoPtr global_info(new GlobalWorkbookInfo(workbook_code_page));
CFStreamCacheReader stream_reader(cfile.getWorkbookStream(), global_info);
BinReaderProcessor proc(stream_reader, doc.getRoot(), true);
return proc.mandatory(WorkbookStreamObject(workbook_code_page)) &&
AUX::HelpersTagsGenerator(doc.getRoot()).GenHelpers();
}
const bool XLSSerializer::write(const Document& doc, const _bstr_t& to)
{
CompoundFile cfile(to, CompoundFile::cf_WriteMode);
/*
{
char* summary_raw2 = new char[200];
std::ifstream file2("SummaryInformation.bin", std::ios_base::binary);
file2.read(summary_raw2, 200);
CFStreamPtr summary2(cfile.createSummaryInformationStream());
summary2->write(summary_raw2, 200);
cfile.closeSummaryInformationStream();
}
{
char* summary_raw = new char[116];
std::ifstream file1("DocumentSummaryInformation.bin", std::ios_base::binary);
file1.read(summary_raw, 116);
CFStreamPtr summary(cfile.createDocumentSummaryInformationStream());
summary->write(summary_raw, 116);
cfile.closeDocumentSummaryInformationStream();
}
*/
GlobalWorkbookInfoPtr global_info(new GlobalWorkbookInfo(WorkbookStreamObject::DefaultCodePage));
CFStreamCacheWriter stream_writer(cfile.createWorkbookStream(), global_info);
BinWriterProcessor proc(stream_writer, doc.getRoot(), true);
return proc.mandatory(WorkbookStreamObject());
}
} // namespace XLS
#pragma once
#include "Serializer.h"
namespace XLS
{;
class XLSSerializer : public Serializer
{
public:
virtual const bool read(Document& doc, const _bstr_t& from);
virtual const bool write(const Document& doc, const _bstr_t& to);
};
} // namespace XLS
#include "stdafx.h"
#include "XLSXSerializer.h"
#include <fstream>
#include <iostream> // endl
#include <direct.h>
#include "boost/filesystem.hpp"
namespace XLSX
{;
const bool loadDir(const Document& doc, MSXML2::IXMLDOMElementPtr cur_dir, const boost::filesystem::wpath path);
const bool storeDir(const Document& doc, MSXML2::IXMLDOMElementPtr cur_dir, const _bstr_t& path_for_dir);
const bool XLSXSerializer::read(Document& doc, const _bstr_t& from)
{
if(!boost::filesystem::exists(static_cast<wchar_t*>(from)) || !boost::filesystem::is_directory(static_cast<wchar_t*>(from)))
{
return false;
}
doc.newXMLDoc(L"root");
MSXML2::IXMLDOMElementPtr cur_dir = doc.getRoot();
bool res = loadDir(doc, cur_dir, static_cast<wchar_t*>(from));
if(res)
{
Log::event("\"" + std::string(static_cast<char*>(from)) + "\" loaded successfully");
return true;
}
return false;
}
const bool loadDir(const Document& doc, MSXML2::IXMLDOMElementPtr cur_dir, const boost::filesystem::wpath path)
{
for(boost::filesystem::wdirectory_iterator it(path), itEnd; it != itEnd; ++it)
{
if(boost::filesystem::is_directory(it->status()))
{
MSXML2::IXMLDOMElementPtr dir_tag = cur_dir->GetownerDocument()->createElement(L"dir");
dir_tag->setAttribute(L"name", it->filename().c_str());
cur_dir->appendChild(dir_tag);
if(!loadDir(doc, dir_tag, path / it->filename()))
{
return false;
}
continue;
}
if(boost::filesystem::is_regular_file(it->status()))
{
if(L".xml" == it->path().extension() || L".rels" == it->path().extension())
{
MSXML2::IXMLDOMElementPtr file_tag = cur_dir->GetownerDocument()->createElement(L"file");
file_tag->setAttribute(L"name", it->filename().c_str());
cur_dir->appendChild(file_tag);
MSXML2::IXMLDOMDocument3Ptr file_xml(_T("Msxml2.DOMDocument.6.0"));
VARIANT_BOOL res = file_xml->load(static_cast<std::wstring>(it->string()).c_str());
if(VARIANT_TRUE != res)
{
Log::warning("\"" + std::string(static_cast<char*>(_bstr_t(it->string().c_str()))) + "\" file is not a valid XML file.");
continue;
}
MSXML2::IXMLDOMNodePtr ins_elem = file_xml->removeChild(file_xml->GetdocumentElement());
file_tag->appendChild(ins_elem);
// Log::info("\"" + std::string(static_cast<char*>(_bstr_t(it->string().c_str()))) + "\" file has been read.");
}
if(L".bin" == it->path().extension())
{
MSXML2::IXMLDOMElementPtr file_tag = cur_dir->GetownerDocument()->createElement(L"file");
file_tag->setAttribute(L"name", it->filename().c_str());
cur_dir->appendChild(file_tag);
size_t file_size = static_cast<size_t>(boost::filesystem::file_size(it->path()));
boost::shared_array<char> buffer(new char[file_size]);
std::ifstream bin_file(static_cast<wchar_t*>(_bstr_t(it->string().c_str())), std::ios_base::binary | std::ios_base::in);
bin_file.read(buffer.get(), file_size);
file_tag->setAttribute(L"format", L"bin");
size_t bin_data_id = doc.appendBinaryData(file_tag, buffer, file_size);
MSXML2::IXMLDOMElementPtr bin_data_id_tag = cur_dir->GetownerDocument()->createElement(L"bin_data_id");
bin_data_id_tag->setAttribute(L"id", STR::int2str(bin_data_id).c_str());
file_tag->appendChild(bin_data_id_tag);
// Log::info("\"" + std::string(static_cast<char*>(_bstr_t(it->string().c_str()))) + "\" file has been read.");
}
}
}
return true;
}
const bool XLSXSerializer::write(const Document& doc, const _bstr_t& folder_path)
{
////////////////////////////
//
// http://www.rsdn.ru/forum/Message.aspx?mid=70479
//
// solved with <xsl:output method="xml" encoding="utf-16" indent="yes"/>
/*
Log::info("Saving to \"" + static_cast<char*>(to) + "\"");
_bstr_t xml = doc.getDoc()->Getxml();
CString strXml((char*)xml);
strXml.Replace(_T("><"), _T(">\n<"));
xml = strXml;
HRESULT res;
res = doc.getDoc()->loadXML(xml);
*/
/////////////////
std::wstring folder_path_w = static_cast<wchar_t*>(folder_path);
size_t pos1 = folder_path_w.find_last_of(L"\\/");
pos1 = std::string::npos == pos1 ? 0 : pos1;
std::wstring folder_name = folder_path_w.substr(pos1 + 1, folder_path_w.size() - pos1 - 1);
std::wstring folder_parent_path = folder_path_w.substr(0, pos1);
MSXML2::IXMLDOMElementPtr cur_dir = doc.getRoot();
cur_dir->setAttribute(L"name", folder_name.c_str());
if(storeDir(doc, cur_dir, folder_parent_path.c_str()))
{
//SetCurrentDirectoryA((dir_for_root + "/" + root_name).c_str());
//system(("7z a -r -tzip ../" + root_name + ".xlsx ./*.*").c_str());
return true;
}
return false;
}
const bool storeDir(const Document& doc, MSXML2::IXMLDOMElementPtr cur_dir, const _bstr_t& path_for_dir)
{
if(!cur_dir)
{
return false;
}
const _bstr_t node_type = cur_dir->GetnodeName();
const _bstr_t node_name = _bstr_t(cur_dir->getAttribute(L"name"));
if(_bstr_t(L"xlsx:dir") == node_type || _bstr_t(L"xlsx:root") == node_type)
{
const _bstr_t dir_name = path_for_dir + "/" + node_name;
_wmkdir(static_cast<wchar_t*>(dir_name));
MSXML2::IXMLDOMNodeListPtr children = cur_dir->GetchildNodes();
MSXML2::IXMLDOMNodePtr item;
while((item = children->nextNode()))
{
storeDir(doc, item, dir_name);
}
}
if(_bstr_t(L"xlsx:file") == node_type)
{
const _variant_t file_format = cur_dir->getAttribute(L"format");
if(VT_NULL != file_format.vt && _bstr_t(file_format) == _bstr_t(L"bin"))
{
const _bstr_t bin_data_id_str = _bstr_t(cur_dir->getAttribute(L"bin_data_id"));
if(!!bin_data_id_str)
{
int bin_data_id = atoi(static_cast<char*>(bin_data_id_str));
std::ofstream bin_file(static_cast<wchar_t*>(path_for_dir + "/" + node_name), std::ios_base::binary | std::ios_base::out);
const std::pair<char*, size_t> bin_data = doc.getBinaryData(bin_data_id);
bin_file.write(bin_data.first, bin_data.second);
}
}
else
{
MSXML2::IXMLDOMDocument3Ptr xml_doc(_T("Msxml2.DOMDocument.6.0"));
xml_doc->loadXML(L"<?xml version=\"1.0\" standalone=\"yes\" ?> <root/>");
xml_doc->PutRefdocumentElement(MSXML2::IXMLDOMElementPtr(cur_dir->removeChild(cur_dir->GetfirstChild())));
xml_doc->save(path_for_dir + "/" + node_name);
}
}
return true;
}
} // namespace XLSX
#pragma once
#include "Serializer.h"
namespace XLSX
{;
class XLSXSerializer : public Serializer
{
public:
virtual const bool read(Document& doc, const _bstr_t& from);
virtual const bool write(const Document& doc, const _bstr_t& folder_path);
};
} // namespace XLSX
#include "stdafx.h"
#include "XMLSerializer.h"
namespace XLS
{;
const bool XMLSerializer::read(Document& doc, const _bstr_t& from)
{
return S_OK == doc.getDoc()->load(from);
}
const bool XMLSerializer::write(const Document& doc, const _bstr_t& to)
{
// Log::info("XMLSerializer::write started \\n transformation.");
_bstr_t xml = doc.getDoc()->Getxml();
std::wstring wstr(static_cast<wchar_t*>(xml));
boost::algorithm::replace_all(wstr, L"><", L">\n<");
MSXML2::IXMLDOMDocument3Ptr full_indented_doc(_T("Msxml2.DOMDocument.6.0"));
try
{
full_indented_doc->loadXML(wstr.c_str());
}
catch (_com_error& e)
{
doc.getDoc()->save(to);
throw e;
}
// Log::info("XMLSerializer::write finished \\n transformation.");
return S_OK == full_indented_doc->save(to);
}
} // namespace XLS
#pragma once
#include "Serializer.h"
namespace XLS
{;
class XMLSerializer : public Serializer
{
public:
virtual const bool read(Document& doc, const _bstr_t& from);
virtual const bool write(const Document& doc, const _bstr_t& to);
};
} // namespace XLS
This diff is collapsed.
#include "precompiled_xls.h"
#include "BetterVariantT.h"
//#include <Exception/AttributeDataWrong.h>
namespace AUX
{;
BetterVariantT::BetterVariantT(const _variant_t& varSrc)
: _variant_t(varSrc)
{
}
// Extracts a VT_R8 into a double
//
BetterVariantT::operator double() const
{
if (V_VT(this) == VT_R8) {
return V_R8(this);
}
_variant_t varDest;
if(FAILED(::VariantChangeTypeEx(static_cast<VARIANT*>(&varDest),
const_cast<VARIANT*>(static_cast<const VARIANT*>(this)), 1252, 0, VT_R8)))
{
throw;// EXCEPT::LE::WrongIntermediateXMLFormat("Type mismatch", __FUNCTION__);
}
return V_R8(&varDest);
}
} // namespace AUX
#pragma once
#include <comutil.h>
namespace AUX
{;
class BetterVariantT : public _variant_t
{
public:
BetterVariantT(const _variant_t& varSrc) ;
operator double() const ; // Extracts a double from a VT_R8
};
} // namespace AUX
This diff is collapsed.
#pragma once
#include "guiddef.h"
namespace XLS
{
class CellRangeRef;
};
namespace AUX
{
const int normalizeColumn(const int column);
const int normalizeRow(const int row);
const std::wstring column2str(const int column);
const std::wstring row2str(const int row);
const std::wstring loc2str(const long row, const bool row_rel, const long column, const bool col_rel);
void str2loc(const std::wstring& str, long& row, bool& row_rel, long& column, bool& col_rel);
void str2loc(std::wstring::const_iterator& str_begin, std::wstring::const_iterator& str_end, long& row, bool& row_rel, long& column, bool& col_rel);
void str2refs(const std::wstring& str, std::vector<XLS::CellRangeRef>& vec);
};
namespace STR
{
const std::string int2str(const int val, const int radix = 10);
const std::wstring int2wstr(const int val, const int radix = 10);
const std::wstring double2str(const double val);
const std::string bin2str(const char* buf, const size_t nbuf);
const std::wstring guid2bstr(const GUID guid);
const std::string guid2str(const GUID guid);
const bool bstr2guid(const std::wstring & guid_str, GUID& guid);
const std::wstring int2hex_wstr(const int val, const size_t size_of = 4);
const std::wstring wchar_t2hex_str(const wchar_t val);
const std::wstring escapeUrlW(const std::wstring& str);
const std::wstring escape_ST_Xstring(const std::wstring& str);
const std::wstring unescape_ST_Xstring(const std::wstring& str);
const std::wstring toARGB(const unsigned int rgba);
const std::wstring toARGB(const unsigned char red, const unsigned char green, const unsigned char blue, const unsigned char alpha);
const std::wstring toRGB(const unsigned char red, const unsigned char green, const unsigned char blue);
const bool fromARGB(const std::wstring& argb, unsigned char& red, unsigned char& green, unsigned char& blue, unsigned char& alpha);
const size_t hex_str2int(const std::wstring& hex);
const size_t hex_str2int(const std::wstring::const_iterator& it_begin, const std::wstring::const_iterator& it_end);
//const std::string hres2wstr(const HRESULT hres);
const std::string toStdString(const std::wstring& wide_string, const unsigned int code_page);
const std::wstring toStdWString(const std::string& ansi_string, const unsigned int code_page);
};
namespace XMLSTUFF
{;
// Makes a new tag and append it to parent (no attributes set)
//BiffStructurePtr createElement(const std::wstring & tag_name, BiffStructurePtr & parent);
const std::wstring make3dRef(const unsigned __int16 ixti, const std::wstring cell_ref, std::vector<std::wstring>& xti_parsed);
//const unsigned __int16 sheetsnames2ixti(const std::wstring str, MSXML2::IXMLDOMDocumentPtr doc);
const std::wstring xti_indexes2sheet_name(const short itabFirst, const short itabLast, std::vector<std::wstring>& sheets_names);
}
#include "precompiled_xls.h"
#include "HelpersTagsGenerator.h"
namespace AUX
{;
//HelpersTagsGenerator::HelpersTagsGenerator(BiffStructurePtr & document_root)
//: document_root_(document_root)
//{
//}
//bool HelpersTagsGenerator::GenHelpers()
//{
// MSXML2::IXMLDOMDocumentPtr doc = document_root_->GetownerDocument();
// BiffStructurePtr helpers_tag = XMLSTUFF::createElement(L"Helpers", document_root_);
//
// GenColumnsRefs(helpers_tag);
// GenIndexedColors(helpers_tag);
//
// return true;
//}
//void HelpersTagsGenerator::GenColumnsRefs(BiffStructurePtr helpers_tag)
//{
// MSXML2::IXMLDOMDocumentPtr doc = document_root_->GetownerDocument();
// BiffStructurePtr col_names_tag = XMLSTUFF::createElement(L"col_names", helpers_tag);
// for (int i = 0; i < 256; i++)
// {
// BiffStructurePtr col_name_tag = doc->createElement(L"col_name");
// col_names_tag->appendChild(col_name_tag);
// col_name_tag->setAttribute(L"index", i);
// col_name_tag->setAttribute(L"ref", column2str(i).c_str());
// }
//
//}
//
//void HelpersTagsGenerator::GenIndexedColors(BiffStructurePtr helpers_tag)
//{
// static std::wstring color_strings[64] =
// {
// L"000000", L"FFFFFF", L"FF0000", L"00FF00", L"0000FF", L"FFFF00", L"FF00FF", L"00FFFF",
// L"000000", L"FFFFFF", L"FF0000", L"00FF00", L"0000FF", L"FFFF00", L"FF00FF", L"00FFFF",
// L"800000", L"008000", L"000080", L"808000", L"800080", L"008080", L"C0C0C0", L"808080",
// L"9999FF", L"993366", L"FFFFCC", L"CCFFFF", L"660066", L"FF8080", L"0066CC", L"CCCCFF",
// L"000080", L"FF00FF", L"FFFF00", L"00FFFF", L"800080", L"800000", L"008080", L"0000FF",
// L"00CCFF", L"CCFFFF", L"CCFFCC", L"FFFF99", L"99CCFF", L"FF99CC", L"CC99FF", L"FFCC99",
// L"3366FF", L"33CCCC", L"99CC00", L"FFCC00", L"FF9900", L"FF6600", L"666699", L"969696",
// L"003366", L"339966", L"003300", L"333300", L"993300", L"993366", L"333399", L"333333"
// };
//
// BiffStructurePtr doc = document_root_->GetownerDocument();
//
// BiffStructurePtr indexed_colors_tag = XMLSTUFF::createElement(L"indexedColors", helpers_tag);
//
// for (int i = 0; i < 64; i++)
// {
// BiffStructurePtr rgb_color_tag = doc->createElement(L"rgbColor");
// indexed_colors_tag->appendChild(rgb_color_tag);
// rgb_color_tag->setAttribute(L"rgb", color_strings[i].c_str());
// }
//}
//
//
} // namespace AUX
#pragma once
namespace AUX
{;
//
//class HelpersTagsGenerator
//{
//public:
// HelpersTagsGenerator(BiffStructurePtr & document_root);
//
// //bool GenHelpers();
//
//private:
// //void GenColumnsRefs(MSXML2::IXMLDOMElementPtr helpers_tag);
// //void GenIndexedColors(MSXML2::IXMLDOMElementPtr helpers_tag);
//
// BiffStructurePtr document_root_;
//};
} // namespace AUX
#pragma once
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/call_traits.hpp>
//#include "../../Exception/WrongAPIUsage.h"
template<typename T>
class nullable
{
private:
typedef typename boost::call_traits<T>::param_type Parameter;
public:
nullable() {}
nullable(Parameter value) : _value(value) {}
template<typename U>
const nullable<T>& operator =(const U& value)
{
return ::nullable_setter(*this, value);
}
template<typename U>
const nullable<T>& nullable_setter(const U& value)
{
_value = static_cast<T>(value);
return *this;
}
const nullable<T>& nullable_setter(const nullable<T>& value)
{
_value = value;
return *this;
}
operator Parameter() const {return _value.get();}
Parameter get() const {return _value.get();}
Parameter get_value_or(Parameter value) const {return _value.get_value_or(value);}
T const* operator->() const {return _value.get_ptr();}
T* operator->() {return _value.get_ptr();}
T const* get_ptr() const {return _value.get_ptr();}
T* get_ptr() {return _value.get_ptr();}
T const& operator*() const {return *_value;}
T& operator*() {return *_value;}
const bool is_init() const {return _value.is_init();}
void reset() {_value.reset();};
const bool operator== (nullable<T> const& rhs) const {return _value.get() == rhs._value.get();}
const bool operator!= (nullable<T> const& rhs) const {return _value.get() != rhs._value.get();}
const bool operator< (nullable<T> const& rhs) const {return _value.get() < rhs._value.get();}
const bool operator> (nullable<T> const& rhs) const {return _value.get() > rhs._value.get();}
const bool operator<= (nullable<T> const& rhs) const {return _value.get() <= rhs._value.get();}
const bool operator>= (nullable<T> const& rhs) const {return _value.get() >= rhs._value.get();}
const bool operator== (Parameter rhs) const {return _value.get() == rhs;}
const bool operator!= (Parameter rhs) const {return _value.get() != rhs;}
const bool operator< (Parameter rhs) const {return _value.get() < rhs;}
const bool operator> (Parameter rhs) const {return _value.get() > rhs;}
const bool operator<= (Parameter rhs) const {return _value.get() <= rhs;}
const bool operator>= (Parameter rhs) const {return _value.get() >= rhs;}
private:
template<class T, bool big_type>
class _nullable
{
private:
typedef typename boost::call_traits<T>::param_type Parameter;
public:
_nullable() {}
_nullable(Parameter val) : _value(new T(val)) {}
void operator =(Parameter val) { _value.reset(new T(val));}
void operator =(const nullable<T>& other)
{
if (other.is_init())
_value.reset(new T(other));
else
_value = boost::shared_ptr<T>();
}
Parameter get() const
{
if(is_init())
return *_value;
else
throw;// EXCEPT::LE::WrongAPIUsage("One of nullable objects was used uninitialized.", __FUNCTION__);
}
Parameter get_value_or(Parameter val) const {return is_init() ? get() : val;}
const bool is_init() const {return _value != 0;}
void reset() {_value.reset();}
T const* get_ptr() const {return _value.get();}
T* get_ptr() {return _value.get();}
T const& operator*() const {return get();}
T& operator*() {return get();}
private:
boost::shared_ptr<T> _value;
};
template<class T>
class _nullable<T, false>
{
private:
typedef typename boost::call_traits<T>::param_type Parameter;
public:
_nullable() {}
_nullable(Parameter value) : _value(value) {}
void operator =(Parameter val) {_value = val;}
void operator =(const nullable<T>& other)
{
if (other.is_init())
_value = other;
else
_value = boost::optional<T>();
}
Parameter get() const
{
if(is_init())
return _value.get();
else
throw;// EXCEPT::LE::WrongAPIUsage("One of nullable objects was used uninitialized.", __FUNCTION__);
}
Parameter get_value_or(Parameter val) const {return _value.get_value_or(val);}
const bool is_init() const {return _value.is_initialized();}
void reset() {_value.reset();}
T const* get_ptr() const {return _value.get_ptr();}
T* get_ptr() {return _value.get_ptr();}
T const& operator*() const {return get();}
T& operator*() {return get();}
private:
boost::optional<T> _value;
};
private:
static const int size_of_big_object = 128;
_nullable<T, sizeof(T) / (size_of_big_object + 1) >= 1> _value;
};
template<class T> const bool operator== (typename boost::call_traits<T>::param_type x, nullable<T> const& y) {return y == x;}
template<class T> const bool operator!= (typename boost::call_traits<T>::param_type x, nullable<T> const& y) {return y != x;}
template<class T> const bool operator< (typename boost::call_traits<T>::param_type x, nullable<T> const& y) {return y >= x;}
template<class T> const bool operator> (typename boost::call_traits<T>::param_type x, nullable<T> const& y) {return y <= x;}
template<class T> const bool operator<= (typename boost::call_traits<T>::param_type x, nullable<T> const& y) {return y > x;}
template<class T> const bool operator>= (typename boost::call_traits<T>::param_type x, nullable<T> const& y) {return y < x;}
template<typename T, typename U>
const nullable<T>& nullable_setter(nullable<T>& lhs, const U& rhs)
{
return lhs.nullable_setter(rhs);
}
#pragma once
namespace XLS
{;
class CFStream;
typedef boost::shared_ptr<CFStream> CFStreamPtr;
class CFRecord;
typedef boost::shared_ptr<CFRecord> CFRecordPtr;
typedef std::list<CFRecordPtr> CFRecordPtrList;
} // namespace XLS
#include "precompiled_xls.h"
#include "CFRecord.h"
#include "CFStream.h"
//#include <Exception/WrongFormatInterpretation.h>
//#include <Exception/WrongAPIUsage.h>
//#include <Exception/WrongBiffRecord.h>
namespace XLS
{;
char CFRecord::intData[MAX_RECORD_SIZE];
// Create a record and read its data from the stream
CFRecord::CFRecord(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info)
: rdPtr(0), // seek to the start
global_info_(global_info)
{
file_ptr = static_cast<unsigned int>(stream->getStreamPointer()); // Assume that files have size < 4Gb
*stream >> type_id_;
unsigned __int16 size_short;
*stream >> size_short;
size_ = size_short;
data_ = new char[size_];
unsigned __int64 rec_data_pos = stream->getStreamPointer();
stream->read(data_, size_);
if(global_info->decryptor && 0 != size_)
{
switch (type_id_) // this would decrease number of checks
{
case rt_BOF:
case rt_FilePass:
case rt_UsrExcl:
case rt_FileLock:
case rt_InterfaceHdr:
case rt_RRDInfo:
case rt_RRDHead:
break;
case rt_BoundSheet8:
global_info->decryptor->Decrypt(data_ + sizeof(unsigned int), size_ - sizeof(unsigned int), rec_data_pos + sizeof(unsigned int));
break;
default:
global_info->decryptor->Decrypt(data_, size_, rec_data_pos);
break;
}
}
}
// Create an empty record
CFRecord::CFRecord(CFRecordType::TypeId type_id, GlobalWorkbookInfoPtr global_info)
: type_id_(type_id),
size_(0),
rdPtr(0),
data_(NULL),
file_ptr(-1),
global_info_(global_info)
{
}
void CFRecord::save(CFStreamPtr stream)
{
file_ptr = static_cast<unsigned int>(stream->getStreamPointer()); // Assume that files have size < 4Gb
*stream << type_id_;
unsigned __int16 size_short = static_cast<unsigned __int16>(size_);
*stream << size_short;
if(data_)
{
stream->writeAndApplyDelayedItems(data_, size_, receiver_items, source_items);
}
rdPtr = 0; // seek to the start
}
void CFRecord::commitData()
{
if(!data_)
{
if(size_ > MAX_RECORD_SIZE)
{
throw;// EXCEPT::RT::WrongBiffRecord("Too much data written to CFRecord.", getTypeString());
}
data_ = new char[size_];
memcpy_s(data_, size_, intData, size_);
}
}
CFRecord::~CFRecord()
{
delete[] data_;
}
const CFRecordType::TypeId CFRecord::getTypeId() const
{
return type_id_;
}
const CFRecordType::TypeString& CFRecord::getTypeString() const
{
return CFRecordType::getStringById(type_id_);
}
// File Pointer to the start of the record in file
const unsigned int CFRecord::getStreamPointer() const
{
if(-1 == file_ptr)
{
throw;// EXCEPT::LE::WrongAPIUsage("Stream pointer was not initialized", __FUNCTION__);
}
return file_ptr;
}
const char* CFRecord::getData() const
{
if(data_)
{
return data_;
}
else
{
return intData;
}
}
const size_t CFRecord::getDataSize() const
{
return size_;
}
const size_t CFRecord::getMaxRecordSize() const
{
return MAX_RECORD_SIZE;
}
void CFRecord::appendRawData(CFRecordPtr where_from)
{
appendRawData(where_from->getData(), where_from->getDataSize());
}
void CFRecord::appendRawData(const char* raw_data, const size_t size)
{
char* data_new = new char[size_ + size];
memcpy(data_new, data_, size_);
memcpy(data_new + size_, raw_data, size);
size_ += size;
std::swap(data_, data_new);
delete[] data_new;
}
void CFRecord::insertDataFromRecordToBeginning(CFRecordPtr where_from)
{
const char* src_data = where_from->getData();
const size_t src_size = where_from->getDataSize();
char* data_new = new char[size_ + src_size];
memcpy(data_new, src_data, src_size);
memcpy(data_new + src_size, data_, size_);
size_ += src_size;
std::swap(data_, data_new);
delete[] data_new;
}
const size_t CFRecord::getRdPtr() const
{
return rdPtr;
}
// whether all the data have bean read
const bool CFRecord::isEOF() const
{
if(rdPtr > size_) // data buffer bounds crossing
{
throw;// EXCEPT::LE::WrongFormatInterpretation(__FUNCTION__);
}
return rdPtr >= size_;
}
// Checks whether the specified number of unsigned chars present in the non-read part of the buffer
// Doesn't generate an exception
const bool CFRecord::checkFitReadSafe(const size_t size) const
{
return (rdPtr + size <= size_);
}
// Checks whether the specified number of unsigned chars present in the non-read part of the buffer
// Generates an exception
void CFRecord::checkFitRead(const size_t size) const
{
if(!checkFitReadSafe(size))
{
throw;// EXCEPT::RT::WrongBiffRecord("Wrong record size.", getTypeString());
}
}
// Checks whether the specified number of unsigned chars fits in max size of the buffer
// Doesn't generate an exception
const bool CFRecord::checkFitWriteSafe(const size_t size) const
{
return (size_ + size <= MAX_RECORD_SIZE);
}
// Checks whether the specified number of unsigned chars fits in max size of the buffer
// Generates an exception
void CFRecord::checkFitWrite(const size_t size) const
{
if(!checkFitWriteSafe(size))
{
throw;// EXCEPT::RT::WrongBiffRecord("Some of the stored data doesn't fit the intermediate buffer.", getTypeString());
}
}
// Skip the specified number of unsigned chars without reading
void CFRecord::skipNunBytes(const size_t n)
{
//ASSERT(data_); // This throws if we use skipNunBytes instead of reserveNunBytes
checkFitRead(n);
rdPtr += n;
}
// Skip the specified number of unsigned chars without reading
void CFRecord::RollRdPtrBack(const size_t n)
{
//ASSERT(data_); // This throws if we use RollRdPtrBack while storing data
if(rdPtr - n < 0)
{
throw;// EXCEPT::RT::WrongBiffRecord("Wrong record pointer rolling back size.", getTypeString());
}
rdPtr -= n;
}
// Skip the specified number of unsigned chars filled them in with zeros
void CFRecord::reserveNunBytes(const size_t n)
{
reserveNunBytes(n, static_cast<unsigned int>(0));
}
// The following func is called every time the record is read again
void CFRecord::resetPointerToBegin()
{
rdPtr = 0;
}
CFRecord& CFRecord::operator>>(bool& val)
{
throw;// EXCEPT::LE::WrongAPIUsage("This function may only be called by mistake.", __FUNCTION__);
}
CFRecord& CFRecord::operator>>(std::wstring & val)
{
throw;// EXCEPT::LE::WrongAPIUsage("This function may only be called by mistake.", __FUNCTION__);
}
CFRecord& CFRecord::operator<<(bool& val)
{
throw;// EXCEPT::LE::WrongAPIUsage("This function may only be called by mistake.", __FUNCTION__);
}
CFRecord& CFRecord::operator<<(std::wstring & val)
{
throw;// EXCEPT::LE::WrongAPIUsage("This function may only be called by mistake.", __FUNCTION__);
}
// Registers data receiver place and reserves n unsigned chars for it
void CFRecord::registerDelayedDataReceiver(CFStream::DELAYED_DATA_SAVER fn, const size_t n, const CFRecordType::TypeId receiver_id)
{
//ASSERT(!data_); // This throws if used after Commit or while reading of binary
CFStream::ReceiverItem item;
item.fn = fn;
item.data_place = size_ + sizeof(unsigned __int16)/*size_short*/ + sizeof(CFRecordType::TypeId); // set offset relative to record beginning.
item.data_size = n;
item.receiver_id = rt_NONE == receiver_id ? getTypeId() : receiver_id;
receiver_items.push_back(item);
reserveNunBytes(n);
}
// Registers delayed source data as any user-defined unsigned int
void CFRecord::registerDelayedDataSource(const unsigned int data, const CFRecordType::TypeId receiver_id)
{
//ASSERT(!data_); // This throws if used after Commit or while reading of binary
CFStream::SourceItem item;
item.data = data;
item.is_file_ptr = false;
item.receiver_id = receiver_id;
item.source_id = getTypeId();
source_items.push_back(item);
}
// Registers delayed source data as file pointer of the start of the record
void CFRecord::registerDelayedFilePointerSource(const CFRecordType::TypeId receiver_id)
{
//ASSERT(!data_); // This throws if used after Commit or while reading of binary
CFStream::SourceItem item;
item.data = 0;
item.is_file_ptr = true;
item.receiver_id = receiver_id;
item.source_id = getTypeId();
source_items.push_back(item);
}
// Registers delayed source data as file pointer of the start of the record and the specified offset added
void CFRecord::registerDelayedFilePointerAndOffsetSource(const unsigned int offset, const CFRecordType::TypeId receiver_id)
{
//ASSERT(!data_); // This throws if used after Commit or while reading of binary
CFStream::SourceItem item;
item.data = offset;
item.is_file_ptr = true;
item.receiver_id = receiver_id;
item.source_id = getTypeId();
source_items.push_back(item);
}
void CFRecord::storeLongData(const char* buf, const size_t size)
{
checkFitWrite(size);
memcpy_s(&intData[size_], getMaxRecordSize() - size_, buf, size);
size_ += size;
}
} // namespace XLS
#pragma once
#include "CFRecordType.h"
#include "CFStream.h"
#include <Binary/BinSmartPointers.h>
#include <Logic/GlobalWorkbookInfo.h>
#include <Auxiliary/nullable/nullable.h>
namespace XLS
{;
// Binary representation of a record in BIFF8
class CFRecord
{
public:
CFRecord(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info); // Create a record an read its data from the stream
CFRecord(CFRecordType::TypeId type_id, GlobalWorkbookInfoPtr global_info); // Create an empty record
~CFRecord();
void save(CFStreamPtr stream);
void commitData();
/* ID */
const CFRecordType::TypeId getTypeId() const;
const CFRecordType::TypeString& getTypeString() const;
// File Pointer to the start of the record in file
const unsigned int getStreamPointer() const;
/* Data */
// Pointer to the beginning of the cached data
const char* getData() const ;
const size_t getDataSize() const;
const size_t getMaxRecordSize() const;
void appendRawData(CFRecordPtr where_from);
void appendRawData(const char* raw_data, const size_t size);
void insertDataFromRecordToBeginning(CFRecordPtr where_from);
/* Pointers */
const bool isEOF() const; // whether all the data have bean read
// Checks whether the specified number of unsigned chars present in the non-read part of the buffer
// Doesn't generate an exception
const bool checkFitReadSafe(const size_t size) const;
// Checks whether the specified number of unsigned chars present in the non-read part of the buffer
// Generates an exception
void checkFitRead(const size_t size) const;
// Checks whether the specified number of unsigned chars fits in max size of the buffer
// Doesn't generate an exception
const bool checkFitWriteSafe(const size_t size) const;
// Checks whether the specified number of unsigned chars fits in max size of the buffer
// Generates an exception
void checkFitWrite(const size_t size) const;
void skipNunBytes(const size_t n); // Skip the specified number of unsigned chars without reading
void RollRdPtrBack(const size_t n); // Move read pointer back to reread some data
void resetPointerToBegin();
void reserveNunBytes(const size_t n); // Skip the specified number of unsigned chars filled them in with zeros
template<class DataType>
void reserveNunBytes(const size_t n, const DataType fill_data) // Skip the specified number of unsigned chars filled them in with specified data
{
checkFitWrite(n);
size_t odd_size = n / sizeof(DataType) * sizeof(DataType);
for(size_t offset = 0; offset < odd_size; offset += sizeof(DataType))
{
reinterpret_cast<DataType*>(&intData[size_ + offset])[0] = fill_data;
}
for(size_t i = 0; i < n % sizeof(DataType); ++i)
{
intData[size_ + odd_size + i] = 0;
}
size_ += n;
}
/* Markup delayed data */
// Registers data receiver place and reserves n unsigned chars for it
void registerDelayedDataReceiver(CFStream::DELAYED_DATA_SAVER fn, const size_t n, const CFRecordType::TypeId receiver_id = rt_NONE);
// Registers delayed source data as any user-defined unsigned int
void registerDelayedDataSource(const unsigned int data, const CFRecordType::TypeId receiver_id);
// Registers delayed source data as file pointer of the start of the record
void registerDelayedFilePointerSource(const CFRecordType::TypeId receiver_id);
// Registers delayed source data as file pointer of the start of the record and the specified offset added
void registerDelayedFilePointerAndOffsetSource(const unsigned int offset, const CFRecordType::TypeId receiver_id);
// Extract the specified type of data without moving rdPtr
template<class T>
const T* getCurData() const
{
return reinterpret_cast<T*>(&data_[rdPtr]);
}
// Obtain the current rdPtr
const size_t getRdPtr() const;
template<class T>
void loadAnyData(T& val)
{
////ASSERT(data_); // This throws if we use >> instead of <<
checkFitRead(sizeof(T));
val = * getCurData<T>();
rdPtr += sizeof(T);
}
template<class T>
void storeAnyData(const T& val)
{
checkFitWrite(sizeof(T));
*reinterpret_cast<T*>(&intData[size_]) = val;
size_ += sizeof(T);
}
void storeLongData(const char* buf, const size_t size);
GlobalWorkbookInfoPtr getGlobalWorkbookInfo() { return global_info_; }
CFRecord& operator>>(unsigned char& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(unsigned __int16& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(unsigned int& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(long& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(double& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(GUID& val) { loadAnyData(val); return *this; };
//CFRecord& operator>>(unsigned int& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(short& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(char& val) { loadAnyData(val); return *this; };
CFRecord& operator>>(bool& val);
CFRecord& operator>>(std::wstring & val);
CFRecord& operator<<(unsigned char& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(unsigned __int16& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(unsigned int& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(long& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(double& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(GUID& val) { storeAnyData(val); return *this; };
//CFRecord& operator<<(unsigned int& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(short& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(char& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(wchar_t& val) { storeAnyData(val); return *this; };
CFRecord& operator<<(bool& val);
CFRecord& operator<<(std::wstring & val);
private:
static const size_t MAX_RECORD_SIZE = 8224;
private:
CFStream::ReceiverItems receiver_items;
CFStream::SourceItems source_items;
private: // parts of the record
unsigned int file_ptr;
CFRecordType::TypeId type_id_;
size_t size_;
char* data_;
size_t rdPtr;
static char intData[MAX_RECORD_SIZE];
private:
GlobalWorkbookInfoPtr global_info_;
};
// moved out of the class to be higher in priority than the universal operator
template<class T>
CFRecord& operator>>(CFRecord& record, std::vector<T>& vec)
{
while(!record.isEOF())
{
T element;
record >> element;
vec.push_back(element);
}
return record;
}
// moved out of the class to be higher in priority than the universal operator
template<class T>
CFRecord& operator<<(CFRecord& record, std::vector<T>& vec)
{
for(std::vector<T>::iterator it = vec.begin(), itEnd = vec.end(); it != itEnd; ++it)
{
record << *it;
}
return record;
}
// moved out of the class to be higher in priority than the universal operator
template<class T>
CFRecord& operator>>(CFRecord & record, std::basic_string<T, std::char_traits<T>, std::allocator<T> >& str)
{
str.clear();
T symbol;
do
{
record.loadAnyData(symbol);
str += symbol;
} while (symbol);
return record;
}
// moved out of the class to be higher in priority than the universal operator
template<class T>
CFRecord& operator<<(CFRecord & record, std::basic_string<T, std::char_traits<T>, std::allocator<T> >& str)
{
for(std::basic_string<T, std::char_traits<T>, std::allocator<T> >::iterator it = str.begin(), itEnd = str.end(); it != itEnd; ++it)
{
record << *it;
}
record.storeAnyData(static_cast<T>(0));
return record;
}
// moved out of the class to be higher in priority than the universal operator
template<class T>
CFRecord& operator>>(CFRecord & record, nullable<T>& val)
{
T temp_val;
record.loadAnyData(temp_val);
val = temp_val;
return record;
}
// moved out of the class to be higher in priority than the universal operator
template<class T>
CFRecord& operator<<(CFRecord & record, nullable<T>& val)
{
T temp_val(val);
record.storeAnyData(temp_val);
return record;
}
#define DET_TYPE(num_bits) num_bits <= 8 ? unsigned char : num_bits <=16 ? unsigned __int16 : unsigned int
#define GETBIT(from, num) ((from & (1 << num)) != 0)
#define GETBITS(from, numL, numH) ((from & (((1 << (numH - numL + 1)) - 1) << numL)) >> numL)
#define SETBIT(to, num, setorclear) {setorclear ? to |= (1 << num) : to &= ~(1 << num);}
#define SETBITS(to, numL, numH, val) {to &= ~(((1 << (numH - numL + 1)) - 1) << numL); to |= ((val & ((1 << (numH - numL + 1)) - 1)) << numL);}
} // namespace XLS
This diff is collapsed.
This diff is collapsed.
#include "precompiled_xls.h"
#include "CFStream.h"
#include "CFRecordType.h"
//#include <Exception/CompoundFileFormatError.h>
//#include <Exception/EndOfStreamReached.h>
#include <sstream>
namespace XLS
{;
CFStream::CFStream(IStream* stream)
: stream_(stream)
{
if(NULL == stream)
{
throw;// EXCEPT::RT::CompoundFileFormatError("Wrong IStream pointer (NULL)");
}
}
CFStream::~CFStream()
{
stream_->Commit(0);
stream_->Release();
}
// Read 'size' unsigned chars from the stream
void CFStream::read(void* buf, const size_t size)
{
if(NULL == buf)
{
throw;// EXCEPT::RT::CompoundFileFormatError("Wrong buffer pointer (NULL)");
}
ULONG num_read = 0;
HRESULT hres = stream_->Read(buf, size, &num_read);
if(FAILED(hres))
{
std::wstringstream str;
str << L"Impossible to read " << size << L" unsigned chars from \"" << getStreamName() << L"\" stream";
throw;// EXCEPT::RT::CompoundFileFormatError(str.str(), hres);
}
if(num_read < size)
{
throw;// EXCEPT::RT::EndOfStreamReached(getStreamName(), num_read, size);
}
// Tipa successful
}
// Write 'size' unsigned chars to the stream
void CFStream::write(const void* buf, const size_t size)
{
if(NULL == buf)
{
throw;// EXCEPT::RT::CompoundFileFormatError("Wrong buffer pointer (NULL)");
}
ULONG num_written = 0;
HRESULT hres = stream_->Write(buf, size, &num_written);
if(FAILED(hres))
{
std::wstringstream str;
str << L"Impossible to write " << size << L" unsigned chars to \"" << getStreamName() << L"\" stream";
throw;// EXCEPT::RT::CompoundFileFormatError(str.str(), hres);
}
if(num_written < size)
{
std::wstringstream str;
str << L"Only " << num_written << L" unsigned chars were saved instead of " << size << L" unsigned chars requested.";
throw;// EXCEPT::RT::CompoundFileFormatError(str.str(), hres);
}
// Tipa successful
}
// If the current pointer is exactly at the end of the stream.
const bool CFStream::isEOF() const
{
return getStreamPointer() == getStreamSize();
}
// Stream pointer
const unsigned __int64 CFStream::getStreamPointer() const
{
LARGE_INTEGER null_ptr;
null_ptr.QuadPart = 0;
ULARGE_INTEGER seek_ptr;
stream_->Seek(null_ptr, STREAM_SEEK_CUR, &seek_ptr);
return seek_ptr.QuadPart;
}
void CFStream::seekFromCurForward(const size_t offset)
{
LARGE_INTEGER seek_ptr;
seek_ptr.QuadPart = offset;
stream_->Seek(seek_ptr, STREAM_SEEK_CUR, NULL);
}
void CFStream::seekFromBegin(const unsigned __int64 offset)
{
LARGE_INTEGER seek_ptr;
seek_ptr.QuadPart = offset;
HRESULT result = stream_->Seek(seek_ptr, STREAM_SEEK_SET, NULL);
}
void CFStream::seekToEnd()
{
LARGE_INTEGER seek_ptr;
seek_ptr.QuadPart = 0;
HRESULT result = stream_->Seek(seek_ptr, STREAM_SEEK_END, NULL);
}
// Stream current size
const unsigned __int64 CFStream::getStreamSize() const
{
STATSTG info;
stream_->Stat(&info, STATFLAG_DEFAULT);
return info.cbSize.QuadPart;
}
// Stream name
//const std::string CFStream::getStreamName() const
//{
// STATSTG info;
// HRESULT hres = stream_->Stat(&info, STATFLAG_DEFAULT);
// if(FAILED(hres))
// {
// Log::warning("Can't obtain the name of the Compound File stream");
// return "";
// }
// return static_cast<char*>(std::wstring (info.pwcsName));
//}
const std::wstring CFStream::getStreamName() const
{
STATSTG info;
HRESULT hres = stream_->Stat(&info, STATFLAG_DEFAULT);
if(FAILED(hres))
{
Log::warning("Can't obtain the name of the Compound File stream");
return L"";
}
return std::wstring (info.pwcsName);
}
void CFStream::writeAndApplyDelayedItems(void* buf, const size_t size, const ReceiverItems& receiver_items_from_record, const SourceItems& source_items_from_record)
{
appendDelayedItems(receiver_items_from_record, source_items_from_record);
write(buf, size);
if(receiver_items_from_record.size() || source_items_from_record.size())
{
applyDelayedItems();
}
}
// The file pointer of the start of the record will be appended to all receiver items 'data_place' fields
// Then all items will be appended to the common queue
void CFStream::appendDelayedItems(const ReceiverItems& receiver_items_from_record, const SourceItems& source_items_from_record)
{
const unsigned int record_start_pointer = static_cast<unsigned int>(getStreamPointer()) - sizeof(unsigned __int16)/*size_short*/ - sizeof(CFRecordType::TypeId);
for(ReceiverItems::const_iterator it = receiver_items_from_record.begin(), itEnd = receiver_items_from_record.end(); it != itEnd; ++it)
{
ReceiverItem copy_item(*it);
copy_item.data_place += record_start_pointer;
receiver_items.push_back(copy_item);
}
for(SourceItems::const_iterator it = source_items_from_record.begin(), itEnd = source_items_from_record.end(); it != itEnd; ++it)
{
SourceItem copy_item(*it);
if(copy_item.is_file_ptr)
{
copy_item.data += record_start_pointer;
}
source_items.push_back(copy_item);
}
}
// Try to apply
void CFStream::applyDelayedItems()
{
ReceiverItems& res = receiver_items;
SourceItems& src = source_items;
for(ReceiverItems::iterator it = receiver_items.begin(); it != receiver_items.end();)
{
const CFRecordType::TypeId receiver_id = it->receiver_id;
SourceItems::iterator its = std::find_if(source_items.begin(), source_items.end(), boost::bind(&SourceItem::receiver_id, _1) == receiver_id || boost::bind(&SourceItem::receiver_id, _1) == rt_ANY_TYPE);
if(its != source_items.end())
{
if(NULL != it->fn)
{
it->fn(*this, it->data_place, its->data); // receiver_items and source_items may be expanded here.
}
else
{
seekFromBegin(it->data_place);
write(&its->data, it->data_size);
}
receiver_items.erase(it++);
source_items.erase(its);
continue;
}
++it;
}
seekToEnd();
}
} // namespace XLS
#pragma once
#include "objidl.h"
#include <Binary/CFRecordType.h>
#include <Binary/BinSmartPointers.h>
namespace XLS
{;
// Binary representation of a stream in BIFF8
class CFStream
{
public:
CFStream(IStream* stream);
~CFStream();
template<class Type>
CFStream& operator>>(Type& val) // Read a simple type or an object (not array)
{
read(&val, sizeof(Type));
return *this;
}
template<class Type>
CFStream& operator<<(Type& val) // Write a simple type or an object (not array)
{
write(&val, sizeof(Type));
return *this;
}
void read(void* buf, const size_t size); // Read 'size' unsigned chars from the stream
void write(const void* buf, const size_t size); // Write 'size' unsigned chars to the stream
void seekFromCurForward(const size_t offset);
void seekFromBegin(const unsigned __int64 offset);
void seekToEnd();
// If the current pointer is exactly at the end of the stream.
const bool isEOF() const;
// Stream pointer
const unsigned __int64 getStreamPointer() const;
// Stream current size
const unsigned __int64 getStreamSize() const;
typedef void (*DELAYED_DATA_SAVER)(CFStream& stream, const unsigned int data_place, const unsigned int data);
typedef struct
{
DELAYED_DATA_SAVER fn;
unsigned int data_place;
size_t data_size;
CFRecordType::TypeId receiver_id;
} ReceiverItem;
typedef std::list<ReceiverItem> ReceiverItems;
typedef struct
{
unsigned int data;
CFRecordType::TypeId receiver_id;
CFRecordType::TypeId source_id;
bool is_file_ptr;
} SourceItem;
typedef std::list<SourceItem> SourceItems;
// Write 'size' unsigned chars to the stream and append passed delayed items and after that apply all stored delayed items
void writeAndApplyDelayedItems(void* buf, const size_t size, const ReceiverItems& receiver_items_from_record, const SourceItems& source_items_from_record);
// The file pointer of the start of the record will be appended to all receiver items 'data_place' fields
// Then all items will be appended to the common queue
void appendDelayedItems(const ReceiverItems& receiver_items_from_record, const SourceItems& source_items_from_record);
void applyDelayedItems();
private:
// Stream name
const std::wstring getStreamName() const;
private:
IStream* stream_;
CFStream::ReceiverItems receiver_items;
CFStream::SourceItems source_items;
};
} // namespace XLS
#include "precompiled_xls.h"
#include "CFStreamCacheReader.h"
#include "CFRecord.h"
#include "CFStream.h"
#include <Logic/Biff_records/BOF.h>
//#include <Exception/RequestedRecordNotFound.h>
namespace XLS
{;
CFStreamCacheReader::CFStreamCacheReader(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info)
: stream_(stream),
global_info_(global_info)
{
skippable_records_names.push_back("StartBlock");
skippable_records_names.push_back("EndBlock");
skippable_records_names.push_back("ChartFrtInfo");
//skippable_records_names.push_back("TextPropsStream");
//skippable_records_names.push_back("ShapePropsStream");
}
CFStreamCacheReader::~CFStreamCacheReader()
{
}
// Reads the next CFRecord from the CFStream and if its type is not the desired one, caches it for the next call
CFRecordPtr CFStreamCacheReader::getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except)
{
CFRecordType::TypeId what_we_actually_read = rt_NONE;
while(readFromStream(1))
{
CFRecordType::TypeString rec_name = records_cache.front()->getTypeString();
if (desirable_type == rt_MsoDrawingGroup) // rt_MsoDrawingGroup + rt_Continue
{
if (checkNextRecord(desirable_type, 1))
{
readFromStream(2);
for(std::list<CFRecordPtr>::iterator good = records_cache.begin(), it = ++records_cache.begin();
it != records_cache.end(); ++it, ++good)
{
while ((it != records_cache.end()) && (desirable_type == (*it)->getTypeId()))
{
(*good)->appendRawData(*it);
records_cache.erase(it);
if(!stream_->isEOF())
{
records_cache.push_back(CFRecordPtr(new CFRecord(stream_, global_info_)));
}
it = good;
++it;
}
}
}
}
if(0 == rec_name.length())
{
Log::warning(L"The extracted record has obsoleted or unknown type(0x" + STR::int2hex_wstr(records_cache.front()->getTypeId(), sizeof(CFRecordType::TypeId)) + L")");
records_cache.pop_front();
continue;
}
if(skippable_records_names.end() != std::find(skippable_records_names.begin(), skippable_records_names.end(), rec_name))
{
Log::warning("The extracted record has been skipped (" + rec_name + ")");
records_cache.pop_front();
continue;
}
break;
}
if(0 != records_cache.size())
{
what_we_actually_read = records_cache.front()->getTypeId();
// if we get what was requested
if(desirable_type == what_we_actually_read || desirable_type == CFRecordType::ANY_TYPE)
{
CFRecordPtr ret = records_cache.front();
records_cache.pop_front();
return ret;
}
}
if(gen_except)
{
//
std::string inType = XLS::CFRecordType::getStringById(desirable_type);
std::string outType = CFRecordType::getStringById(what_we_actually_read);
Log::warning("The extracted record is not of requested type.\nRequested: \"" +
XLS::CFRecordType::getStringById(desirable_type) + "\" Extracted: \"" + CFRecordType::getStringById(what_we_actually_read) + "\"");
}
return CFRecordPtr();
}
// Check if the next read record would be of desired type
const bool CFStreamCacheReader::checkNextRecord(const CFRecordType::TypeId desirable_type, const size_t num_records_to_check)
{
readFromStream(num_records_to_check);
// if we would get what was requested
// ANY_TYPE is checked just to make the fake read from stream and get an error if the stream is ended
for(std::list<CFRecordPtr>::const_iterator it = records_cache.begin(), itEnd = records_cache.end(); it != itEnd; ++it)
{
size_t type = (*it)->getTypeId();
if(desirable_type == (*it)->getTypeId() || desirable_type == CFRecordType::ANY_TYPE)
{
return true;
}
}
return false;
}
// Make sure the internal buffer has concrete number of records. Returns number of records read
const size_t CFStreamCacheReader::readFromStream(const size_t num_of_records_min_necessary)
{
const size_t current_records_num = records_cache.size();
if(current_records_num >= num_of_records_min_necessary)
{
return current_records_num;
}
while(records_cache.size() < num_of_records_min_necessary && !stream_->isEOF())
{
records_cache.push_back(CFRecordPtr(new CFRecord(stream_, global_info_)));
}
checkAndAppendContinueData();
return records_cache.size();
}
// Checks whether the next record is Continue and append its data to the real record if so
void CFStreamCacheReader::checkAndAppendContinueData()
{
if(!records_cache.size())
{
return;
}
for(std::list<CFRecordPtr>::iterator good = records_cache.begin(), it = ++records_cache.begin();
it != records_cache.end(); ++it, ++good)
{
size_t typeRecord = (*it)->getTypeId();
while(it != records_cache.end() && (rt_Continue == (*it)->getTypeId()) )
{
(*good)->appendRawData(*it);
records_cache.erase(it); // now 'it' is invalid
if(!stream_->isEOF())
{
records_cache.push_back(CFRecordPtr(new CFRecord(stream_, global_info_)));
}
it = good;
++it; // Now it may became end(), checked in 'for'
}
}
}
const bool CFStreamCacheReader::isEOF() const
{
return !records_cache.size() && stream_->isEOF();
}
// Skip the specified number of unsigned chars without processing
void CFStreamCacheReader::skipNunBytes(const size_t n)
{
stream_->seekFromCurForward(n);
}
// Seek to the next substream (Read all records till EOF then skip EOF)
// Doesn't generate EndOfStreamReached if the stream is the last one
const bool CFStreamCacheReader::SeekToEOF()
{
while(readFromStream(1))
{
if(rt_EOF == records_cache.front()->getTypeId())
{
// records_cache.pop_front(); // Skip EOF
break;
}
records_cache.pop_front(); // Skip non-EOF
}
return true;
}
// Extract the next record from the stream leaving it in the cache for future read.
// Always call resetPointerToBegin for the extracted CFRecord after using it
CFRecordPtr CFStreamCacheReader::touchTheNextRecord()
{
if(readFromStream(1))// make sure something is in cache
{
return records_cache.front();
}
return CFRecordPtr();
}
// Check the next record type
const CFRecordType::TypeId CFStreamCacheReader::getNextRecordType()
{
if(isEOF())
{
return rt_NONE;
}
readFromStream(1); // I don't check the result of readFromStream() because it was done implicitly in isEOF()
return records_cache.front()->getTypeId();
}
} // namespace XLS
#pragma once
#include "CFRecordType.h"
#include "BinSmartPointers.h"
#include "Logic\GlobalWorkbookInfo.h"
#include "Logic/Biff_structures/ODRAW/OfficeArtRecordHeader.h"
namespace XLS
{;
// The only purpose of the reader is to avoid seeking back through IStream when, for example,
// we have read a record from a binary stream to the CFRecord, but the record of this type is
// not waitable right at the moment and shall be read a little bit later.
// Example of a construction:
// PIVOTTH = SXTH *ContinueFrt
// ContinueFrt may appear in the stream and may not. So, this class will increase performance much
class CFStreamCacheReader
{
public:
CFStreamCacheReader(CFStreamPtr stream, const GlobalWorkbookInfoPtr global_info);
~CFStreamCacheReader();
// Reads the next CFRecord from the CFStream and if it's type is not the desired one, caches it for the next call
CFRecordPtr getNextRecord(const CFRecordType::TypeId desirable_type, const bool gen_except = false);
// Check if the next read record would be of desired type
const bool checkNextRecord(const CFRecordType::TypeId desirable_type, const size_t num_records_to_check = 1);
// Checks whether the next record is Continue and append its data to the real record if so
void checkAndAppendContinueData();
const bool isEOF() const;
// Skip the specified number of unsigned chars without processing
void skipNunBytes(const size_t n);
// Seek to the next substream (Read all records till EOF then skip EOF)
// Doesn't generate EndOfStreamReached if the stream is the last one
const bool SeekToEOF();
// Extract the next record from the stream leaving it in the cache for future read.
// Always call resetPointerToBegin for the extracted CFRecord after using it
CFRecordPtr touchTheNextRecord();
// Check the next record type
const CFRecordType::TypeId getNextRecordType();
GlobalWorkbookInfoPtr getGlobalWorkbookInfo() { return global_info_; }
private:
// Make sure the internal buffer has concrete number of records. Returns number of records read
const size_t readFromStream(const size_t num_of_records_min_necessary);
private:
CFStreamPtr stream_;
CFRecordPtrList records_cache;
GlobalWorkbookInfoPtr global_info_;
std::vector<std::string> skippable_records_names;
};
} // namespace XLS
#include "precompiled_xls.h"
#include "CFStreamCacheWriter.h"
#include "CFRecord.h"
#include "CFStream.h"
#include <Logic/Biff_records/BOF.h>
//#include <Exception/RequestedRecordNotFound.h>
namespace XLS
{;
CFStreamCacheWriter::CFStreamCacheWriter(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info)
: stream_(stream),
global_info_(global_info)
{
}
CFStreamCacheWriter::~CFStreamCacheWriter()
{
}
// Saves the next CFRecord to the CFStream or caches for later saving.
// Returns whether the record was saved to file or stored for later saving
bool CFStreamCacheWriter::storeNextRecord(CFRecordPtr record)
{
record->save(stream_);
return true;
}
// Actual transporting record to the CFStream and then to IStream
const size_t CFStreamCacheWriter::writeToStream(const size_t num_of_records_min_necessary)
{
return 0;
}
} // namespace XLS
#pragma once
#include "BinSmartPointers.h"
#include "Logic\GlobalWorkbookInfo.h"
namespace XLS
{;
// The purpose of the writer is to avoid seeking back through IStream when, for example,
// we have write an offset of a record that would appear in processing much later.
// For example this is necessary in 'Index' record that shall reference DBCell records
// appearing later in the stream. So, this class will increase performance much
class CFStreamCacheWriter
{
public:
CFStreamCacheWriter(CFStreamPtr stream, GlobalWorkbookInfoPtr global_info);
~CFStreamCacheWriter();
// Saves the next CFRecord to the CFStream or caches for later saving. Returns whether the record was saved to file or stored for later saving
bool storeNextRecord(CFRecordPtr record);
GlobalWorkbookInfoPtr getGlobalWorkbookInfo() { return global_info_; }
private:
// Actual transporting record to the CFStream and then to IStream
const size_t writeToStream(const size_t num_of_records_min_necessary);
private:
CFStreamPtr stream_;
CFRecordPtrList records_cache;
GlobalWorkbookInfoPtr global_info_;
};
} // namespace XLS
#include "precompiled_xls.h"
#include "CompoundFile.h"
#include "CFStream.h"
//#include <Exception/CompoundFileFormatError.h>
#include <sstream>
namespace XLS
{;
CompoundFile::~CompoundFile()
{
storage_->Commit(0);
streams.clear();
storage_->Release();
}
CompoundFile::CompoundFile(const std::wstring & file_path, const ReadWriteMode mode)
: rwMode(mode)
{
HRESULT hres = S_OK;
unsigned int grfMode = 0;
switch(rwMode)
{
case cf_ReadMode:
hres = StgIsStorageFile(file_path.c_str());
switch(hres)
{
case S_FALSE:
throw;// EXCEPT::RT::CompoundFileFormatError("The specified file \"" + std::string(static_cast<char*>(file_path)) + "\" is not a valid Compound File.", hres);;
case STG_E_FILENOTFOUND:
throw;// EXCEPT::RT::CompoundFileFormatError("Not found the path \"" + std::string(static_cast<char*>(file_path)) + "\"", hres);;
}
grfMode = STGM_READ | STGM_DIRECT | STGM_SHARE_DENY_WRITE;
if(FAILED( hres = StgOpenStorage(file_path.c_str(), NULL, grfMode, NULL, 0, &storage_)))
{
throw;// EXCEPT::RT::CompoundFileFormatError("Error opening \"" + std::string(static_cast<char*>(file_path)) + "\"", hres);
}
break;
case cf_WriteMode:
grfMode = STGM_CREATE | STGM_READWRITE | STGM_SIMPLE | STGM_SHARE_EXCLUSIVE;
if(FAILED( hres = StgCreateStorageEx(file_path.c_str(), grfMode, STGFMT_STORAGE, 0, NULL, NULL,
IID_IStorage, reinterpret_cast<void**>(&storage_))))
{
throw;// EXCEPT::RT::CompoundFileFormatError("Error creating \"" + std::string(static_cast<char*>(file_path)) + "\"", hres);
}
break;
}
/*
IEnumSTATSTG* storageInfo = NULL;
if(FAILED(hres = storage_->EnumElements(0, 0, 0, &storageInfo)))
{
throw 1;
}
Log::info("The Compound File contains the following streams:");
STATSTG elem;
while(S_OK == storageInfo->Next(1, &elem, 0))
{
Log::info(std::string("name: \"") + static_cast<char*>(std::wstring (elem.pwcsName)) + "\" type: " + STR::int2str(elem.type) + " size: " +
STR::int2hex_wstr(elem.cbSize.HighPart) + STR::int2hex_wstr(elem.cbSize.LowPart));
}
*/
}
// Opens "Workbook" stream and returns the only reference
CFStreamPtr CompoundFile::getWorkbookStream()
{
return getNamedStream(L"Workbook");
}
// Creates "Workbook" stream and returns the only reference
CFStreamPtr CompoundFile::createWorkbookStream()
{
return createNamedStream(L"Workbook");
}
// Opens "SummaryInformation" stream and returns the only reference
CFStreamPtr CompoundFile::getSummaryInformationStream()
{
return getNamedStream(L"\005SummaryInformation");
}
// Creates "SummaryInformation" stream and returns the only reference
CFStreamPtr CompoundFile::createSummaryInformationStream()
{
return createNamedStream(L"\005SummaryInformation");
}
// Closes "SummaryInformation" stream
void CompoundFile::closeSummaryInformationStream()
{
return closeNamedStream(L"\005SummaryInformation");
}
// Opens "SummaryInformation" stream and returns the only reference
CFStreamPtr CompoundFile::getDocumentSummaryInformationStream()
{
return getNamedStream(L"\005DocumentSummaryInformation");
}
// Creates "SummaryInformation" stream and returns the only reference
CFStreamPtr CompoundFile::createDocumentSummaryInformationStream()
{
return createNamedStream(L"\005DocumentSummaryInformation");
}
// Closes "SummaryInformation" stream
void CompoundFile::closeDocumentSummaryInformationStream()
{
closeNamedStream(L"\005DocumentSummaryInformation");
}
CFStreamPtr CompoundFile::getNamedStream(const std::wstring& name)
{
if(!streams[name])
{
streams[name].reset(new CFStream(openStream(name.c_str())));
}
return streams[name];
}
CFStreamPtr CompoundFile::createNamedStream(const std::wstring& name)
{
if(!streams[name])
{
streams[name].reset(new CFStream(createStream(name.c_str())));
}
return streams[name];
}
void CompoundFile::closeNamedStream(const std::wstring& name)
{
streams[name].reset();
}
// Opens a stream in the storage (shall be called not more than once per stream)
IStream* CompoundFile::openStream(const std::wstring & stream_name)
{
IStream* pStream = NULL;
HRESULT hres = storage_->OpenStream(stream_name.c_str(), NULL, STGM_READ | STGM_DIRECT | STGM_SHARE_EXCLUSIVE, NULL, &pStream );
if(FAILED(hres))
{
throw;// EXCEPT::RT::CompoundFileFormatError(std::string("Error opening \"") + static_cast<char*>(stream_name) + "\" stream", hres);
}
return pStream;
}
// Creates a new stream in the storage
IStream* CompoundFile::createStream(const std::wstring & stream_name)
{
IStream* pStream = NULL;
HRESULT hres = storage_->CreateStream(stream_name.c_str(), STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, NULL, &pStream);
if(FAILED(hres))
{
throw;// EXCEPT::RT::CompoundFileFormatError(std::string("Error creating \"") + static_cast<char*>(stream_name) + "\" stream", hres);
}
return pStream;
}
} // namespace XLS
#pragma once
#include "objidl.h"
#include "BinSmartPointers.h"
namespace XLS
{;
class CompoundFile
{
public:
enum ReadWriteMode
{
cf_WriteMode,
cf_ReadMode
};
public:
CompoundFile(const std::wstring & file_path, const ReadWriteMode mode);
~CompoundFile();
CFStreamPtr getWorkbookStream();
CFStreamPtr createWorkbookStream();
CFStreamPtr getSummaryInformationStream();
CFStreamPtr createSummaryInformationStream();
void closeSummaryInformationStream();
CFStreamPtr getDocumentSummaryInformationStream();
CFStreamPtr createDocumentSummaryInformationStream();
void closeDocumentSummaryInformationStream();
private:
IStream* openStream (const std::wstring & stream_name); // Opens a stream in the storage (shall be called not more than once per stream)
IStream* createStream (const std::wstring & stream_name); // Creates a new stream in the storage
CFStreamPtr getNamedStream (const std::wstring& name);
CFStreamPtr createNamedStream (const std::wstring& name);
void closeNamedStream (const std::wstring& name);
private:
std::map<std::wstring, CFStreamPtr> streams;
IStorage* storage_;
ReadWriteMode rwMode;
};
} // namespace XLS
#include "precompiled_xls.h"
#include "BiffDecoder_RCF.h"
namespace CRYPT
{;
BiffDecoderBase::BiffDecoderBase() : mbValid(false)
{
}
BiffDecoderBase::~BiffDecoderBase()
{
}
bool BiffDecoderBase::verifyPassword(const std::wstring& rPassword)
{
mbValid = implVerify(rPassword);
return mbValid;
}
void BiffDecoderBase::decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const __int64 nStreamPos, const unsigned __int16 nBytes)
{
if(pnDestData && pnSrcData && (nBytes> 0))
{
if(mbValid)
implDecode(pnDestData, pnSrcData, nStreamPos, nBytes);
else
memcpy(pnDestData, pnSrcData, nBytes);
}
}
/** Returns the block index of the passed stream position for RCF decryption. */
int lclGetRcfBlock(__int64 nStreamPos)
{
return static_cast<int>(nStreamPos / BIFF_RCF_BLOCKSIZE);
}
/** Returns the offset of the passed stream position in a block for RCF decryption. */
int lclGetRcfOffset(__int64 nStreamPos)
{
return static_cast<int>(nStreamPos % BIFF_RCF_BLOCKSIZE);
}
BiffDecoder_RCF::BiffDecoder_RCF(unsigned char pnSalt[16], unsigned char pnVerifier[16], unsigned char pnVerifierHash[16])
: maPassword(16, 0),
maSalt(pnSalt, pnSalt + 16),
maVerifier(pnVerifier, pnVerifier + 16),
maVerifierHash(pnVerifierHash, pnVerifierHash + 16)
{
}
bool BiffDecoder_RCF::implVerify(const std::wstring& rPassword)
{
int nLen = rPassword.length();
if((0 <nLen) && (nLen <16))
{
// copy string to unsigned __int16 array
maPassword.clear();
maPassword.resize(16, 0);
const wchar_t* pcChar = rPassword.c_str();
const wchar_t* pcCharEnd = pcChar + nLen;
std::vector<unsigned __int16>::iterator aIt = maPassword.begin();
for(; pcChar <pcCharEnd; ++pcChar, ++aIt)
*aIt = static_cast<unsigned __int16>(*pcChar);
// init codec
maCodec.initKey(&maPassword.front(), &maSalt.front());
return maCodec.verifyKey(&maVerifier.front(), &maVerifierHash.front());
}
return false;
}
void BiffDecoder_RCF::implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const __int64 nStreamPos, const unsigned __int16 nBytes)
{
unsigned char* pnCurrDest = pnDestData;
const unsigned char* pnCurrSrc = pnSrcData;
__int64 nCurrPos = nStreamPos;
unsigned __int16 nBytesLeft = nBytes;
while(nBytesLeft> 0)
{
// initialize codec for current stream position
maCodec.startBlock(lclGetRcfBlock(nCurrPos));
maCodec.skip(lclGetRcfOffset(nCurrPos));
// decode the block
unsigned __int16 nBlockLeft = static_cast<unsigned __int16>(BIFF_RCF_BLOCKSIZE - lclGetRcfOffset(nCurrPos));
unsigned __int16 nDecBytes = nBytesLeft < nBlockLeft ? nBytesLeft : nBlockLeft;
maCodec.decode(pnCurrDest, pnCurrSrc, static_cast<int>(nDecBytes));
// prepare for next block
pnCurrDest += nDecBytes;
pnCurrSrc += nDecBytes;
nCurrPos += nDecBytes;
nBytesLeft = nBytesLeft - nDecBytes;
}
}
};
#pragma once
#include "BinaryCodec_RCF.h"
#include "rtl/cipher.h"
#include "rtl/digest.h"
namespace CRYPT
{;
const __int64 BIFF_RCF_BLOCKSIZE = 1024;
/** Base class for BIFF stream decoders. */
class BiffDecoderBase //: public ::comphelper::IDocPasswordVerifier
{
public:
explicit BiffDecoderBase();
virtual ~BiffDecoderBase();
/** Implementation of the ::comphelper::IDocPasswordVerifier interface,
calls the new virtual function implVerify(). */
virtual bool verifyPassword( const std::wstring& rPassword );
/** Returns true, if the decoder has been initialized correctly. */
inline bool isValid() const { return mbValid; }
/** Decodes nBytes unsigned chars and writes encrypted data into the buffer pnDestData. */
void decode(unsigned char* pnDestData, const unsigned char* pnSrcData, const __int64 nStreamPos, const unsigned __int16 nBytes);
private:
/** Derived classes implement password verification and initialization of
the decoder. */
virtual bool implVerify(const std::wstring& rPassword) = 0;
/** Implementation of decryption of a memory block. */
virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const __int64 nStreamPos, const unsigned __int16 nBytes) = 0;
private:
bool mbValid; /// True = decoder is correctly initialized.
};
typedef ::boost::shared_ptr<BiffDecoderBase> BiffDecoderRef;
class BiffDecoder_RCF : public BiffDecoderBase
{
public:
explicit BiffDecoder_RCF(unsigned char pnSalt[ 16 ], unsigned char pnVerifier[ 16 ], unsigned char pnVerifierHash[ 16 ]);
private:
/** Implements password verification and initialization of the decoder. */
virtual bool implVerify(const std::wstring& rPassword);
/** Implementation of decryption of a memory block. */
virtual void implDecode(unsigned char* pnDestData, const unsigned char* pnSrcData, const __int64 nStreamPos, const unsigned __int16 nBytes);
private:
BinaryCodec_RCF maCodec; /// Cipher algorithm implementation.
std::vector<unsigned __int16> maPassword;
std::vector<unsigned char> maSalt;
std::vector<unsigned char> maVerifier;
std::vector<unsigned char> maVerifierHash;
};
} // namespace CRYPT
#include "precompiled_xls.h"
#include "BinaryCodec_RCF.h"
namespace CRYPT
{;
BinaryCodec_RCF::BinaryCodec_RCF()
{
(void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) );
}
BinaryCodec_RCF::~BinaryCodec_RCF()
{
(void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) );
}
void BinaryCodec_RCF::initKey( const unsigned __int16 pnPassData[ 16 ], const unsigned char pnSalt[ 16 ] )
{
// create little-endian key data array from password data
unsigned char pnKeyData[ 64 ];
(void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
const unsigned __int16* pnCurrPass = pnPassData;
const unsigned __int16* pnPassEnd = pnPassData + 16;
unsigned char* pnCurrKey = pnKeyData;
size_t nPassSize = 0;
for( ; (pnCurrPass < pnPassEnd) && (*pnCurrPass != 0); ++pnCurrPass, ++nPassSize )
{
*pnCurrKey++ = static_cast< unsigned char >( *pnCurrPass );
*pnCurrKey++ = static_cast< unsigned char >( *pnCurrPass >> 8 );
}
pnKeyData[ 2 * nPassSize ] = 0x80;
pnKeyData[ 56 ] = static_cast< unsigned char >( nPassSize << 4 );
// fill raw digest of key data into key data
mhDigest.Update(pnKeyData, sizeof( pnKeyData ) );
mhDigest.Raw(pnKeyData, DigestMD5::RTL_DIGEST_LENGTH_MD5 );
// update digest with key data and passed salt data
for( size_t nIndex = 0; nIndex < 16; ++nIndex )
{
mhDigest.Update(pnKeyData, 5 );
mhDigest.Update(pnSalt, 16 );
}
// update digest with padding
pnKeyData[ 16 ] = 0x80;
(void)memset( pnKeyData + 17, 0, sizeof( pnKeyData ) - 17 );
pnKeyData[ 56 ] = 0x80;
pnKeyData[ 57 ] = 0x0A;
mhDigest.Update(pnKeyData + 16, sizeof( pnKeyData ) - 16 );
// fill raw digest of above updates into digest value
mhDigest.Raw(mpnDigestValue, sizeof( mpnDigestValue ) );
// erase key data array and leave
(void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
}
bool BinaryCodec_RCF::verifyKey( const unsigned char pnVerifier[ 16 ], const unsigned char pnVerifierHash[ 16 ] )
{
if( !startBlock( 0 ) )
return false;
unsigned char pnDigest[ DigestMD5::RTL_DIGEST_LENGTH_MD5 ];
unsigned char pnBuffer[ 64 ];
// decode salt data into buffer
mhCipher.Decode(pnVerifier, 16, pnBuffer, sizeof(pnBuffer));
pnBuffer[ 16 ] = 0x80;
(void)memset( pnBuffer + 17, 0, sizeof( pnBuffer ) - 17 );
pnBuffer[ 56 ] = 0x80;
// fill raw digest of buffer into digest
mhDigest.Update(pnBuffer, sizeof( pnBuffer ) );
mhDigest.Raw(pnDigest, sizeof( pnDigest ) );
// decode original salt digest into buffer
mhCipher.Decode(pnVerifierHash, 16, pnBuffer, sizeof(pnBuffer));
// compare buffer with computed digest
bool bResult = memcmp( pnBuffer, pnDigest, sizeof( pnDigest ) ) == 0;
// erase buffer and digest arrays and leave
(void)memset( pnBuffer, 0, sizeof( pnBuffer ) );
(void)memset( pnDigest, 0, sizeof( pnDigest ) );
return bResult;
}
bool BinaryCodec_RCF::startBlock( size_t nCounter )
{
// initialize key data array
unsigned char pnKeyData[ 64 ];
(void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
// fill 40 bit of digest value into [0..4]
(void)memcpy( pnKeyData, mpnDigestValue, 5 );
// fill little-endian counter into [5..8], static_cast masks out unneeded bits
pnKeyData[ 5 ] = static_cast<unsigned char>( nCounter );
pnKeyData[ 6 ] = static_cast<unsigned char>( nCounter >> 8 );
pnKeyData[ 7 ] = static_cast<unsigned char>( nCounter >> 16 );
pnKeyData[ 8 ] = static_cast<unsigned char>( nCounter >> 24 );
pnKeyData[ 9 ] = 0x80;
pnKeyData[ 56 ] = 0x48;
// fill raw digest of key data into key data
mhDigest.Update(pnKeyData, sizeof( pnKeyData ) );
mhDigest.Raw(pnKeyData, DigestMD5::RTL_DIGEST_LENGTH_MD5 );
// initialize cipher with key data (for decoding)
CipherARCFOUR::rtlCipherError eResult = mhCipher.Init(CipherARCFOUR::rtl_Cipher_DirectionDecode, pnKeyData, DigestMD5::RTL_DIGEST_LENGTH_MD5, 0, 0 );
// rrase key data array and leave
(void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
return eResult == CipherARCFOUR::rtl_Cipher_E_None;
}
bool BinaryCodec_RCF::decode( unsigned char* pnDestData, const unsigned char* pnSrcData, size_t nBytes )
{
return CipherARCFOUR::rtl_Cipher_E_None == mhCipher.Decode(pnSrcData, static_cast<size_t>(nBytes), pnDestData, static_cast<size_t>(nBytes));
}
bool BinaryCodec_RCF::skip( size_t nBytes )
{
// decode dummy data in memory to update internal state of RC4 cipher
unsigned char pnDummy[ 1024 ];
size_t nBytesLeft = nBytes;
bool bResult = true;
while(bResult && (nBytesLeft > 0))
{
size_t nBlockLen = nBytesLeft < sizeof(pnDummy) ? nBytesLeft : sizeof(pnDummy);
bResult = decode(pnDummy, pnDummy, nBlockLen);
nBytesLeft -= nBlockLen;
}
return bResult;
}
};
#pragma once
#include "Crypt.h"
#include "rtl/cipher.h"
#include "rtl/digest.h"
namespace CRYPT
{;
/** Encodes and decodes data from protected MSO 97+ documents.
This is a wrapper class around low level cryptographic functions from RTL.
Implementation is based on the wvDecrypt package by Caolan McNamara:
http://www.csn.ul.ie/~caolan/docs/wvDecrypt.html
*/
class BinaryCodec_RCF
{
public:
/** Default constructor.
Two-step construction in conjunction with the initKey() and verifyKey()
functions allows to try to initialize with different passwords (e.g.
built-in default password used for Excel workbook protection).
*/
explicit BinaryCodec_RCF();
~BinaryCodec_RCF();
/** Initializes the algorithm with the specified password and document ID.
@param pnPassData
Unicode character array containing the password. Must be zero
terminated, which results in a maximum length of 15 characters.
@param pnSalt
Random salt data block read from or written to the file.
*/
void initKey(const unsigned __int16 pnPassData[ 16 ], const unsigned char pnSalt[ 16 ] );
/** Verifies the validity of the password using the passed salt data.
@precond
The codec must be initialized with the initKey() function before
this function can be used.
@param pnVerifier
Verifier block read from the file.
@param pnVerifierHash
Verifier hash read from the file.
@return
True = test was successful.
*/
bool verifyKey(const unsigned char pnVerifier[ 16 ], const unsigned char pnVerifierHash[ 16 ] );
/** Rekeys the codec using the specified counter.
After reading a specific amount of data the cipher algorithm needs to
be rekeyed using a counter that counts the data blocks.
The block size is for example 512 unsigned chars for MS Word files and 1024
unsigned chars for MS Excel files.
@precond
The codec must be initialized with the initKey() function before
this function can be used.
@param nCounter
Block counter used to rekey the cipher.
*/
bool startBlock( size_t nCounter );
/** Decodes a block of memory.
@see rtl_cipher_decode()
@precond
The codec must be initialized with the initKey() function before
this function can be used.
@param pnDestData
Destination buffer. Will contain the decrypted data afterwards.
@param pnSrcData
Encrypted data block.
@param nBytes
Size of the passed data blocks. pnDestData and pnSrcData must be of
this size.
@return
True = decoding was successful (no error occured).
*/
bool decode(unsigned char* pnDestData, const unsigned char* pnSrcData, size_t nBytes );
/** Lets the cipher skip a specific amount of unsigned chars.
This function sets the cipher to the same state as if the specified
amount of data has been decoded with one or more calls of decode().
@precond
The codec must be initialized with the initKey() function before
this function can be used.
@param nBytes
Number of unsigned chars to be skipped (cipher "seeks" forward).
@return
True = skip was successful (no error occured).
*/
bool skip( size_t nBytes );
private:
CipherARCFOUR mhCipher;
DigestMD5 mhDigest;
unsigned char mpnDigestValue[DigestMD5::RTL_DIGEST_LENGTH_MD5];
};
} // namespace CRYPT
#pragma once
#include <boost/shared_ptr.hpp>
namespace CRYPT
{;
class Crypt
{
public:
virtual void Encrypt(char* data, const size_t size) = 0;
virtual void Decrypt(char* data, const size_t size, const unsigned __int64 stream_pos) = 0;
typedef enum
{
RC4,
RC4CryptoAPI,
XOR
} crypt_type;
};
typedef boost::shared_ptr<Crypt> CryptPtr;
} // namespace CRYPT
#include "precompiled_xls.h"
#include "Decryptor.h"
#include "RC4Crypt.h"
#include <Logic/Biff_structures/RC4EncryptionHeader.h>
//#include <Logic/Biff_structures/RC4CryptoAPIEncryptionHeader.h>
namespace CRYPT
{;
Decryptor::Decryptor(const CRYPTO::RC4EncryptionHeader& header)
: crypt(new RC4Crypt(header)),
type(Crypt::RC4)
{
}
void Decryptor::Decrypt(char* data, const size_t size, const unsigned __int64 stream_pos)
{
crypt->Decrypt(data, size, stream_pos);
}
};
#pragma once
#include "Crypt.h"
namespace CRYPTO
{;
class RC4EncryptionHeader;
} // namespace CRYPTO
namespace CRYPT
{;
class Decryptor
{
public:
Decryptor(const CRYPTO::RC4EncryptionHeader& header);
void Decrypt(char* data, const size_t size, const unsigned __int64 stream_pos);
private:
CryptPtr crypt;
Crypt::crypt_type type;
};
typedef boost::shared_ptr<Decryptor> DecryptorPtr;
} // namespace CRYPT
This diff is collapsed.
#pragma once
#include "Crypt.h"
#include <Logic/Biff_structures/RC4EncryptionHeader.h>
#include "BiffDecoder_RCF.h"
namespace CRYPT
{;
class RC4Crypt : public Crypt
{
public:
RC4Crypt(const CRYPTO::RC4EncryptionHeader& header);
virtual void Encrypt(char* data, const size_t size);
virtual void Decrypt(char* data, const size_t size, const unsigned __int64 stream_pos);
private:
void CopyDWORDs2Bytes(const unsigned int b1, const unsigned int b2, const unsigned int b3, const unsigned int b4, unsigned char* byte_array);
private:
unsigned char pnSalt[16];
unsigned char pnVerifier[16];
unsigned char pnVerifierHash[16];
BiffDecoderRef mxDecoder;
};
} // namespace CRYPT
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#pragma once
namespace MSXML2
{;
class MSXMLErrHandler
{
public:
MSXMLErrHandler(const HRESULT hres, IXMLDOMNode* object, REFIID iid, const std::string& func_name);
~MSXMLErrHandler();
const std::string& toString();
void logErrorAndThrow(bool force_throw = false);
private:
HRESULT hres_;
IXMLDOMNodePtr object_;
IID iid_;
std::string func_name_;
std::string message;
};
} // namespace MSXML2
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment