diff options
Diffstat (limited to 'comphelper/source/xml')
-rw-r--r-- | comphelper/source/xml/attributelist.cxx | 76 | ||||
-rw-r--r-- | comphelper/source/xml/ofopxmlhelper.cxx | 491 | ||||
-rw-r--r-- | comphelper/source/xml/xmltools.cxx | 106 |
3 files changed, 673 insertions, 0 deletions
diff --git a/comphelper/source/xml/attributelist.cxx b/comphelper/source/xml/attributelist.cxx new file mode 100644 index 000000000..fa918d01d --- /dev/null +++ b/comphelper/source/xml/attributelist.cxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/attributelist.hxx> + +#include <vector> + +using namespace osl; +using namespace com::sun::star; + + +namespace comphelper { + +OUString SAL_CALL AttributeList::getTypeByName( const OUString& sName ) +{ + for (auto const& attribute : mAttributes) + { + if( attribute.sName == sName ) { + return attribute.sType; + } + } + return OUString(); +} + +OUString SAL_CALL AttributeList::getValueByName(const OUString& sName) +{ + for (auto const& attribute : mAttributes) + { + if( attribute.sName == sName ) { + return attribute.sValue; + } + } + return OUString(); +} + +AttributeList::AttributeList() +{ + // performance improvement during adding + mAttributes.reserve(20); +} + +AttributeList::AttributeList(const AttributeList &r) + : cppu::WeakImplHelper<XAttributeList, XCloneable>(r) +{ + mAttributes = r.mAttributes; +} + +AttributeList::~AttributeList() +{ +} + +css::uno::Reference< css::util::XCloneable > AttributeList::createClone() +{ + AttributeList *p = new AttributeList( *this ); + return css::uno::Reference< css::util::XCloneable > ( static_cast<css::util::XCloneable *>(p) ); +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/xml/ofopxmlhelper.cxx b/comphelper/source/xml/ofopxmlhelper.cxx new file mode 100644 index 000000000..46785b35c --- /dev/null +++ b/comphelper/source/xml/ofopxmlhelper.cxx @@ -0,0 +1,491 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <comphelper/ofopxmlhelper.hxx> +#include <comphelper/attributelist.hxx> + +#include <cppuhelper/implbase.hxx> + +#include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <vector> + +#define RELATIONINFO_FORMAT 0 +#define CONTENTTYPE_FORMAT 1 +#define FORMAT_MAX_ID CONTENTTYPE_FORMAT + +using namespace ::com::sun::star; + +namespace comphelper { + +namespace { + +// this helper class is designed to allow to parse ContentType- and Relationship-related information from OfficeOpenXML format +class OFOPXMLHelper_Impl + : public cppu::WeakImplHelper< css::xml::sax::XDocumentHandler > +{ + sal_uInt16 const m_nFormat; // which format to parse + + css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > m_aResultSeq; + std::vector< OUString > m_aElementsSeq; // stack of elements being parsed + + +public: + css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > const & GetParsingResult() const; + + explicit OFOPXMLHelper_Impl( sal_uInt16 nFormat ); // must not be created directly + + // XDocumentHandler + virtual void SAL_CALL startDocument() override; + virtual void SAL_CALL endDocument() override; + virtual void SAL_CALL startElement( const OUString& aName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override; + virtual void SAL_CALL endElement( const OUString& aName ) override; + virtual void SAL_CALL characters( const OUString& aChars ) override; + virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; + virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override; + virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override; +}; + +} + +namespace OFOPXMLHelper { + +/// @throws css::uno::Exception +static uno::Sequence<uno::Sequence< beans::StringPair>> ReadSequence_Impl( + const uno::Reference<io::XInputStream>& xInStream, + const OUString& aStringID, sal_uInt16 nFormat, + const uno::Reference<uno::XComponentContext>& xContext); + +uno::Sequence< uno::Sequence< beans::StringPair > > ReadRelationsInfoSequence( + const uno::Reference< io::XInputStream >& xInStream, + const OUString & aStreamName, + const uno::Reference< uno::XComponentContext >& rContext ) +{ + OUString aStringID = "_rels/" + aStreamName; + return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, rContext ); +} + + +uno::Sequence< uno::Sequence< beans::StringPair > > ReadContentTypeSequence( + const uno::Reference< io::XInputStream >& xInStream, + const uno::Reference< uno::XComponentContext >& rContext ) +{ + OUString aStringID = "[Content_Types].xml"; + return ReadSequence_Impl( xInStream, aStringID, CONTENTTYPE_FORMAT, rContext ); +} + +OUString GetContentTypeByName( + const css::uno::Sequence<css::uno::Sequence<css::beans::StringPair>>& rContentTypes, + const OUString& rFilename) +{ + if (rContentTypes.getLength() < 2) + { + return OUString(); + } + + const uno::Sequence<beans::StringPair>& rDefaults = rContentTypes[0]; + const uno::Sequence<beans::StringPair>& rOverrides = rContentTypes[1]; + + // Find the extension and use it to get the type. + const sal_Int32 nDotOffset = rFilename.lastIndexOf('.'); + const OUString aExt = (nDotOffset >= 0 ? rFilename.copy(nDotOffset + 1) : rFilename); // Skip the dot. + + const std::vector<OUString> aNames = { aExt, "/" + rFilename }; + for (const OUString& aName : aNames) + { + const auto it1 = std::find_if(rOverrides.begin(), rOverrides.end(), [&aName](const beans::StringPair& rPair) + { return rPair.First == aName; }); + if (it1 != rOverrides.end()) + return it1->Second; + + const auto it2 = std::find_if(rDefaults.begin(), rDefaults.end(), [&aName](const beans::StringPair& rPair) + { return rPair.First == aName; }); + if (it2 != rDefaults.end()) + return it2->Second; + } + + return OUString(); +} + +void WriteRelationsInfoSequence( + const uno::Reference< io::XOutputStream >& xOutStream, + const uno::Sequence< uno::Sequence< beans::StringPair > >& aSequence, + const uno::Reference< uno::XComponentContext >& rContext ) +{ + if ( !xOutStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(rContext); + + xWriter->setOutputStream( xOutStream ); + + OUString aRelListElement( "Relationships" ); + OUString aRelElement( "Relationship" ); + OUString aCDATAString( "CDATA" ); + OUString aWhiteSpace( " " ); + + // write the namespace + AttributeList* pRootAttrList = new AttributeList; + uno::Reference< css::xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); + pRootAttrList->AddAttribute( + "xmlns", + aCDATAString, + "http://schemas.openxmlformats.org/package/2006/relationships" ); + + xWriter->startDocument(); + xWriter->startElement( aRelListElement, xRootAttrList ); + + for ( sal_Int32 nInd = 0; nInd < aSequence.getLength(); nInd++ ) + { + AttributeList *pAttrList = new AttributeList; + uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); + for( sal_Int32 nSecInd = 0; nSecInd < aSequence[nInd].getLength(); nSecInd++ ) + { + if ( !(aSequence[nInd][nSecInd].First == "Id" + || aSequence[nInd][nSecInd].First == "Type" + || aSequence[nInd][nSecInd].First == "TargetMode" + || aSequence[nInd][nSecInd].First == "Target") ) + { + // TODO/LATER: should the extensions be allowed? + throw lang::IllegalArgumentException(); + } + pAttrList->AddAttribute( aSequence[nInd][nSecInd].First, aCDATAString, aSequence[nInd][nSecInd].Second ); + } + + xWriter->startElement( aRelElement, xAttrList ); + xWriter->ignorableWhitespace( aWhiteSpace ); + xWriter->endElement( aRelElement ); + } + + xWriter->ignorableWhitespace( aWhiteSpace ); + xWriter->endElement( aRelListElement ); + xWriter->endDocument(); +} + + +void WriteContentSequence( + const uno::Reference< io::XOutputStream >& xOutStream, + const uno::Sequence< beans::StringPair >& aDefaultsSequence, + const uno::Sequence< beans::StringPair >& aOverridesSequence, + const uno::Reference< uno::XComponentContext >& rContext ) +{ + if ( !xOutStream.is() ) + throw uno::RuntimeException(); + + uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(rContext); + + xWriter->setOutputStream( xOutStream ); + + static const OUString aTypesElement("Types"); + static const OUString aDefaultElement("Default"); + static const OUString aOverrideElement("Override"); + static const OUString aContentTypeAttr("ContentType"); + static const OUString aCDATAString("CDATA"); + static const OUString aWhiteSpace(" "); + + // write the namespace + AttributeList* pRootAttrList = new AttributeList; + uno::Reference< css::xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); + pRootAttrList->AddAttribute( + "xmlns", + aCDATAString, + "http://schemas.openxmlformats.org/package/2006/content-types" ); + + xWriter->startDocument(); + xWriter->startElement( aTypesElement, xRootAttrList ); + + for ( sal_Int32 nInd = 0; nInd < aDefaultsSequence.getLength(); nInd++ ) + { + AttributeList *pAttrList = new AttributeList; + uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); + pAttrList->AddAttribute( "Extension", aCDATAString, aDefaultsSequence[nInd].First ); + pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aDefaultsSequence[nInd].Second ); + + xWriter->startElement( aDefaultElement, xAttrList ); + xWriter->ignorableWhitespace( aWhiteSpace ); + xWriter->endElement( aDefaultElement ); + } + + for ( sal_Int32 nInd = 0; nInd < aOverridesSequence.getLength(); nInd++ ) + { + AttributeList *pAttrList = new AttributeList; + uno::Reference< css::xml::sax::XAttributeList > xAttrList( pAttrList ); + pAttrList->AddAttribute( "PartName", aCDATAString, aOverridesSequence[nInd].First ); + pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aOverridesSequence[nInd].Second ); + + xWriter->startElement( aOverrideElement, xAttrList ); + xWriter->ignorableWhitespace( aWhiteSpace ); + xWriter->endElement( aOverrideElement ); + } + + xWriter->ignorableWhitespace( aWhiteSpace ); + xWriter->endElement( aTypesElement ); + xWriter->endDocument(); + +} + +uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( + const uno::Reference< io::XInputStream >& xInStream, + const OUString& aStringID, sal_uInt16 nFormat, + const uno::Reference< uno::XComponentContext >& rContext ) +{ + if ( !rContext.is() || !xInStream.is() || nFormat > FORMAT_MAX_ID ) + throw uno::RuntimeException(); + + uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create( rContext ); + + OFOPXMLHelper_Impl *const pHelper = new OFOPXMLHelper_Impl( nFormat ); + uno::Reference< css::xml::sax::XDocumentHandler > xHelper( static_cast< css::xml::sax::XDocumentHandler* >( pHelper ) ); + css::xml::sax::InputSource aParserInput; + aParserInput.aInputStream = xInStream; + aParserInput.sSystemId = aStringID; + xParser->setDocumentHandler( xHelper ); + xParser->parseStream( aParserInput ); + xParser->setDocumentHandler( uno::Reference < css::xml::sax::XDocumentHandler > () ); + + return pHelper->GetParsingResult(); +} + +} // namespace OFOPXMLHelper + +// Relations info related strings +static OUString const g_aRelListElement("Relationships"); +static OUString const g_aRelElement( "Relationship" ); +static OUString const g_aIDAttr( "Id" ); +static OUString const g_aTypeAttr( "Type" ); +static OUString const g_aTargetModeAttr( "TargetMode" ); +static OUString const g_aTargetAttr( "Target" ); + +// ContentType related strings +static OUString const g_aTypesElement( "Types" ); +static OUString const g_aDefaultElement( "Default" ); +static OUString const g_aOverrideElement( "Override" ); +static OUString const g_aExtensionAttr( "Extension" ); +static OUString const g_aPartNameAttr( "PartName" ); +static OUString const g_aContentTypeAttr( "ContentType" ); + +OFOPXMLHelper_Impl::OFOPXMLHelper_Impl( sal_uInt16 nFormat ) +: m_nFormat( nFormat ) +{ +} + +uno::Sequence< uno::Sequence< beans::StringPair > > const & OFOPXMLHelper_Impl::GetParsingResult() const +{ + if ( !m_aElementsSeq.empty() ) + throw uno::RuntimeException(); // the parsing has still not finished! + + return m_aResultSeq; +} + + +void SAL_CALL OFOPXMLHelper_Impl::startDocument() +{ +} + + +void SAL_CALL OFOPXMLHelper_Impl::endDocument() +{ +} + + +void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) +{ + if ( m_nFormat == RELATIONINFO_FORMAT ) + { + if ( aName == g_aRelListElement ) + { + sal_Int32 nNewLength = m_aElementsSeq.size() + 1; + + if ( nNewLength != 1 ) + throw css::xml::sax::SAXException(); // TODO: this element must be the first level element + + m_aElementsSeq.push_back( aName ); + + return; // nothing to do + } + else if ( aName == g_aRelElement ) + { + sal_Int32 nNewLength = m_aElementsSeq.size() + 1; + if ( nNewLength != 2 ) + throw css::xml::sax::SAXException(); // TODO: this element must be the second level element + + m_aElementsSeq.push_back( aName ); + + sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1; + m_aResultSeq.realloc( nNewEntryNum ); + sal_Int32 nAttrNum = 0; + m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 + + OUString aIDValue = xAttribs->getValueByName( g_aIDAttr ); + if ( aIDValue.isEmpty() ) + throw css::xml::sax::SAXException(); // TODO: the ID value must present + + OUString aTypeValue = xAttribs->getValueByName( g_aTypeAttr ); + OUString aTargetValue = xAttribs->getValueByName( g_aTargetAttr ); + OUString aTargetModeValue = xAttribs->getValueByName( g_aTargetModeAttr ); + + m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aIDAttr; + m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue; + + if ( !aTypeValue.isEmpty() ) + { + m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTypeAttr; + m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue; + } + + if ( !aTargetValue.isEmpty() ) + { + m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTargetAttr; + m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue; + } + + if ( !aTargetModeValue.isEmpty() ) + { + m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = g_aTargetModeAttr; + m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue; + } + + m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum ); + } + else + throw css::xml::sax::SAXException(); // TODO: no other elements expected! + } + else if ( m_nFormat == CONTENTTYPE_FORMAT ) + { + if ( aName == g_aTypesElement ) + { + sal_Int32 nNewLength = m_aElementsSeq.size() + 1; + + if ( nNewLength != 1 ) + throw css::xml::sax::SAXException(); // TODO: this element must be the first level element + + m_aElementsSeq.push_back( aName ); + + if ( !m_aResultSeq.hasElements() ) + m_aResultSeq.realloc( 2 ); + + return; // nothing to do + } + else if ( aName == g_aDefaultElement ) + { + sal_Int32 nNewLength = m_aElementsSeq.size() + 1; + if ( nNewLength != 2 ) + throw css::xml::sax::SAXException(); // TODO: this element must be the second level element + + m_aElementsSeq.push_back( aName ); + + if ( !m_aResultSeq.hasElements() ) + m_aResultSeq.realloc( 2 ); + + if ( m_aResultSeq.getLength() != 2 ) + throw uno::RuntimeException(); + + const OUString aExtensionValue = xAttribs->getValueByName( g_aExtensionAttr ); + if ( aExtensionValue.isEmpty() ) + throw css::xml::sax::SAXException(); // TODO: the Extension value must present + + const OUString aContentTypeValue = xAttribs->getValueByName( g_aContentTypeAttr ); + if ( aContentTypeValue.isEmpty() ) + throw css::xml::sax::SAXException(); // TODO: the ContentType value must present + + const sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1; + m_aResultSeq[0].realloc( nNewResultLen ); + + m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue; + m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue; + } + else if ( aName == g_aOverrideElement ) + { + sal_Int32 nNewLength = m_aElementsSeq.size() + 1; + if ( nNewLength != 2 ) + throw css::xml::sax::SAXException(); // TODO: this element must be the second level element + + m_aElementsSeq.push_back( aName ); + + if ( !m_aResultSeq.hasElements() ) + m_aResultSeq.realloc( 2 ); + + if ( m_aResultSeq.getLength() != 2 ) + throw uno::RuntimeException(); + + OUString aPartNameValue = xAttribs->getValueByName( g_aPartNameAttr ); + if ( aPartNameValue.isEmpty() ) + throw css::xml::sax::SAXException(); // TODO: the PartName value must present + + OUString aContentTypeValue = xAttribs->getValueByName( g_aContentTypeAttr ); + if ( aContentTypeValue.isEmpty() ) + throw css::xml::sax::SAXException(); // TODO: the ContentType value must present + + sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1; + m_aResultSeq[1].realloc( nNewResultLen ); + + m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue; + m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue; + } + else + throw css::xml::sax::SAXException(); // TODO: no other elements expected! + } + else + throw css::xml::sax::SAXException(); // TODO: no other elements expected! +} + + +void SAL_CALL OFOPXMLHelper_Impl::endElement( const OUString& aName ) +{ + if ( m_nFormat == RELATIONINFO_FORMAT || m_nFormat == CONTENTTYPE_FORMAT ) + { + sal_Int32 nLength = m_aElementsSeq.size(); + if ( nLength <= 0 ) + throw css::xml::sax::SAXException(); // TODO: no other end elements expected! + + if ( m_aElementsSeq[nLength-1] != aName ) + throw css::xml::sax::SAXException(); // TODO: unexpected element ended + + m_aElementsSeq.resize( nLength - 1 ); + } +} + + +void SAL_CALL OFOPXMLHelper_Impl::characters( const OUString& /*aChars*/ ) +{ +} + + +void SAL_CALL OFOPXMLHelper_Impl::ignorableWhitespace( const OUString& /*aWhitespaces*/ ) +{ +} + + +void SAL_CALL OFOPXMLHelper_Impl::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ ) +{ +} + + +void SAL_CALL OFOPXMLHelper_Impl::setDocumentLocator( const uno::Reference< css::xml::sax::XLocator >& /*xLocator*/ ) +{ +} + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/comphelper/source/xml/xmltools.cxx b/comphelper/source/xml/xmltools.cxx new file mode 100644 index 000000000..f506bc33a --- /dev/null +++ b/comphelper/source/xml/xmltools.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <comphelper/xmltools.hxx> +#include <rtl/random.h> +#include <rtl/uuid.h> +#include <vector> + +using namespace com::sun::star; + +namespace +{ + //Will be inside an xml comment, so can't use '-' in case '--' appears in + //output, etc. Despite what *is* legal in an xml comment, just using the + //base-64 subset to avoid pain with simplistic third-party parsers + static const sal_uInt8 aChaffEncoder[] = + { + 'A', 'Q', 'g', 'w', 'B', 'R', 'h', 'x', + 'C', 'S', 'i', 'y', 'D', 'T', 'j', 'z', + 'E', 'U', 'k', '0', 'F', 'V', 'l', '1', + 'G', 'W', 'm', '2', 'H', 'X', 'n', '3', + 'I', 'Y', 'o', '4', 'J', 'Z', 'p', '5', + 'K', 'a', 'q', '6', 'L', 'b', 'r', '7', + 'M', 'c', 's', '8', 'N', 'd', 't', '9', + 'O', 'e', 'u', '+', 'P', 'f', 'v', '/', + + 'A', 'Q', 'g', 'w', 'B', 'R', 'h', 'x', + 'C', 'S', 'i', 'y', 'D', 'T', 'j', 'z', + 'E', 'U', 'k', '0', 'F', 'V', 'l', '1', + 'G', 'W', 'm', '2', 'H', 'X', 'n', '3', + 'I', 'Y', 'o', '4', 'J', 'Z', 'p', '5', + 'K', 'a', 'q', '6', 'L', 'b', 'r', '7', + 'M', 'c', 's', '8', 'N', 'd', 't', '9', + 'O', 'e', 'u', '+', 'P', 'f', 'v', '/', + + 'A', 'Q', 'g', 'w', 'B', 'R', 'h', 'x', + 'C', 'S', 'i', 'y', 'D', 'T', 'j', 'z', + 'E', 'U', 'k', '0', 'F', 'V', 'l', '1', + 'G', 'W', 'm', '2', 'H', 'X', 'n', '3', + 'I', 'Y', 'o', '4', 'J', 'Z', 'p', '5', + 'K', 'a', 'q', '6', 'L', 'b', 'r', '7', + 'M', 'c', 's', '8', 'N', 'd', 't', '9', + 'O', 'e', 'u', '+', 'P', 'f', 'v', '/', + + 'A', 'Q', 'g', 'w', 'B', 'R', 'h', 'x', + 'C', 'S', 'i', 'y', 'D', 'T', 'j', 'z', + 'E', 'U', 'k', '0', 'F', 'V', 'l', '1', + 'G', 'W', 'm', '2', 'H', 'X', 'n', '3', + 'I', 'Y', 'o', '4', 'J', 'Z', 'p', '5', + 'K', 'a', 'q', '6', 'L', 'b', 'r', '7', + 'M', 'c', 's', '8', 'N', 'd', 't', '9', + 'O', 'e', 'u', '+', 'P', 'f', 'v', '/' + }; + + void encodeChaff(std::vector<sal_uInt8> &rChaff) + { + static_assert(sizeof(aChaffEncoder) == 256, "this has to cover all chars"); + + for (auto & elem : rChaff) + { + elem = aChaffEncoder[elem]; + } + } +} + +namespace comphelper::xml +{ + OString makeXMLChaff() + { + rtlRandomPool pool = rtl_random_createPool(); + + sal_Int8 n; + rtl_random_getBytes(pool, &n, 1); + + sal_Int32 nLength = 1024+n; + // coverity[tainted_data] - 1024 deliberate random minus max -127/plus max 128 + std::vector<sal_uInt8> aChaff(nLength); + rtl_random_getBytes(pool, aChaff.data(), nLength); + + rtl_random_destroyPool(pool); + + encodeChaff(aChaff); + + return OString(reinterpret_cast<const char*>(aChaff.data()), nLength); + } + + OString generateGUIDString() + { + sal_uInt8 aSeq[16]; + rtl_createUuid(aSeq, nullptr, true); + + char str[39]; + sprintf(str, "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + aSeq[0], aSeq[1], aSeq[2], aSeq[3], aSeq[4], aSeq[5], aSeq[6], aSeq[7], aSeq[8], + aSeq[9], aSeq[10], aSeq[11], aSeq[12], aSeq[13], aSeq[14], aSeq[15]); + + return str; + } +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |