1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_comphelper.hxx" 26 27 #ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_ 28 #include <com/sun/star/beans/StringPair.hpp> 29 #endif 30 #ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP 31 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32 #endif 33 #ifndef _COM_SUN_STAR_IO_XACTIVEDATASOURCE_HPP 34 #include <com/sun/star/io/XActiveDataSource.hpp> 35 #endif 36 #ifndef _COM_SUN_STAR_XML_SAX_XPARSER_HPP 37 #include <com/sun/star/xml/sax/XParser.hpp> 38 #endif 39 #ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP 40 #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 41 #endif 42 #ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP 43 #include <com/sun/star/lang/IllegalArgumentException.hpp> 44 #endif 45 46 #include <comphelper/ofopxmlhelper.hxx> 47 #include <comphelper/attributelist.hxx> 48 49 #define RELATIONINFO_FORMAT 0 50 #define CONTENTTYPE_FORMAT 1 51 #define FORMAT_MAX_ID CONTENTTYPE_FORMAT 52 53 using namespace ::com::sun::star; 54 55 namespace comphelper { 56 57 // ----------------------------------- 58 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadRelationsInfoSequence( const uno::Reference< io::XInputStream >& xInStream, const ::rtl::OUString aStreamName, const uno::Reference< lang::XMultiServiceFactory > xFactory ) 59 { 60 ::rtl::OUString aStringID = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/" ) ); 61 aStringID += aStreamName; 62 return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, xFactory ); 63 } 64 65 // ----------------------------------- 66 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadContentTypeSequence( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< lang::XMultiServiceFactory > xFactory ) 67 { 68 ::rtl::OUString aStringID = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[Content_Types].xml" ) ); 69 return ReadSequence_Impl( xInStream, aStringID, CONTENTTYPE_FORMAT, xFactory ); 70 } 71 72 // ----------------------------------- 73 void SAL_CALL OFOPXMLHelper::WriteRelationsInfoSequence( const uno::Reference< io::XOutputStream >& xOutStream, const uno::Sequence< uno::Sequence< beans::StringPair > >& aSequence, const uno::Reference< lang::XMultiServiceFactory > xFactory ) 74 { 75 if ( !xOutStream.is() ) 76 throw uno::RuntimeException(); 77 78 uno::Reference< io::XActiveDataSource > xWriterSource( 79 xFactory->createInstance( 80 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), 81 uno::UNO_QUERY_THROW ); 82 uno::Reference< xml::sax::XDocumentHandler > xWriterHandler( xWriterSource, uno::UNO_QUERY_THROW ); 83 84 xWriterSource->setOutputStream( xOutStream ); 85 86 ::rtl::OUString aRelListElement( RTL_CONSTASCII_USTRINGPARAM( "Relationships" ) ); 87 ::rtl::OUString aRelElement( RTL_CONSTASCII_USTRINGPARAM( "Relationship" ) ); 88 ::rtl::OUString aIDAttr( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ); 89 ::rtl::OUString aTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ); 90 ::rtl::OUString aTargetModeAttr( RTL_CONSTASCII_USTRINGPARAM( "TargetMode" ) ); 91 ::rtl::OUString aTargetAttr( RTL_CONSTASCII_USTRINGPARAM( "Target" ) ); 92 ::rtl::OUString aCDATAString( RTL_CONSTASCII_USTRINGPARAM ( "CDATA" ) ); 93 ::rtl::OUString aWhiteSpace( RTL_CONSTASCII_USTRINGPARAM ( " " ) ); 94 95 // write the namespace 96 AttributeList* pRootAttrList = new AttributeList; 97 uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); 98 pRootAttrList->AddAttribute( 99 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "xmlns" ) ), 100 aCDATAString, 101 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "http://schemas.openxmlformats.org/package/2006/relationships" ) ) ); 102 103 xWriterHandler->startDocument(); 104 xWriterHandler->startElement( aRelListElement, xRootAttrList ); 105 106 for ( sal_Int32 nInd = 0; nInd < aSequence.getLength(); nInd++ ) 107 { 108 AttributeList *pAttrList = new AttributeList; 109 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList ); 110 for( sal_Int32 nSecInd = 0; nSecInd < aSequence[nInd].getLength(); nSecInd++ ) 111 { 112 if ( aSequence[nInd][nSecInd].First.equals( aIDAttr ) 113 || aSequence[nInd][nSecInd].First.equals( aTypeAttr ) 114 || aSequence[nInd][nSecInd].First.equals( aTargetModeAttr ) 115 || aSequence[nInd][nSecInd].First.equals( aTargetAttr ) ) 116 { 117 pAttrList->AddAttribute( aSequence[nInd][nSecInd].First, aCDATAString, aSequence[nInd][nSecInd].Second ); 118 } 119 else 120 { 121 // TODO/LATER: should the extensions be allowed? 122 throw lang::IllegalArgumentException(); 123 } 124 } 125 126 xWriterHandler->startElement( aRelElement, xAttrList ); 127 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 128 xWriterHandler->endElement( aRelElement ); 129 } 130 131 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 132 xWriterHandler->endElement( aRelListElement ); 133 xWriterHandler->endDocument(); 134 } 135 136 // ----------------------------------- 137 void SAL_CALL OFOPXMLHelper::WriteContentSequence( const uno::Reference< io::XOutputStream >& xOutStream, const uno::Sequence< beans::StringPair >& aDefaultsSequence, const uno::Sequence< beans::StringPair >& aOverridesSequence, const uno::Reference< lang::XMultiServiceFactory > xFactory ) 138 { 139 if ( !xOutStream.is() ) 140 throw uno::RuntimeException(); 141 142 uno::Reference< io::XActiveDataSource > xWriterSource( 143 xFactory->createInstance( 144 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), 145 uno::UNO_QUERY_THROW ); 146 uno::Reference< xml::sax::XDocumentHandler > xWriterHandler( xWriterSource, uno::UNO_QUERY_THROW ); 147 148 xWriterSource->setOutputStream( xOutStream ); 149 150 ::rtl::OUString aTypesElement( RTL_CONSTASCII_USTRINGPARAM( "Types" ) ); 151 ::rtl::OUString aDefaultElement( RTL_CONSTASCII_USTRINGPARAM( "Default" ) ); 152 ::rtl::OUString aOverrideElement( RTL_CONSTASCII_USTRINGPARAM( "Override" ) ); 153 ::rtl::OUString aExtensionAttr( RTL_CONSTASCII_USTRINGPARAM( "Extension" ) ); 154 ::rtl::OUString aPartNameAttr( RTL_CONSTASCII_USTRINGPARAM( "PartName" ) ); 155 ::rtl::OUString aContentTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ); 156 ::rtl::OUString aCDATAString( RTL_CONSTASCII_USTRINGPARAM ( "CDATA" ) ); 157 ::rtl::OUString aWhiteSpace( RTL_CONSTASCII_USTRINGPARAM ( " " ) ); 158 159 // write the namespace 160 AttributeList* pRootAttrList = new AttributeList; 161 uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); 162 pRootAttrList->AddAttribute( 163 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "xmlns" ) ), 164 aCDATAString, 165 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "http://schemas.openxmlformats.org/package/2006/content-types" ) ) ); 166 167 xWriterHandler->startDocument(); 168 xWriterHandler->startElement( aTypesElement, xRootAttrList ); 169 170 for ( sal_Int32 nInd = 0; nInd < aDefaultsSequence.getLength(); nInd++ ) 171 { 172 AttributeList *pAttrList = new AttributeList; 173 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList ); 174 pAttrList->AddAttribute( aExtensionAttr, aCDATAString, aDefaultsSequence[nInd].First ); 175 pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aDefaultsSequence[nInd].Second ); 176 177 xWriterHandler->startElement( aDefaultElement, xAttrList ); 178 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 179 xWriterHandler->endElement( aDefaultElement ); 180 } 181 182 for ( sal_Int32 nInd = 0; nInd < aOverridesSequence.getLength(); nInd++ ) 183 { 184 AttributeList *pAttrList = new AttributeList; 185 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList ); 186 pAttrList->AddAttribute( aPartNameAttr, aCDATAString, aOverridesSequence[nInd].First ); 187 pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aOverridesSequence[nInd].Second ); 188 189 xWriterHandler->startElement( aOverrideElement, xAttrList ); 190 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 191 xWriterHandler->endElement( aOverrideElement ); 192 } 193 194 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 195 xWriterHandler->endElement( aTypesElement ); 196 xWriterHandler->endDocument(); 197 198 } 199 200 // ================================================================================== 201 202 // ----------------------------------- 203 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadSequence_Impl( const uno::Reference< io::XInputStream >& xInStream, const ::rtl::OUString& aStringID, sal_uInt16 nFormat, const uno::Reference< lang::XMultiServiceFactory > xFactory ) 204 { 205 if ( !xFactory.is() || !xInStream.is() || nFormat > FORMAT_MAX_ID ) 206 throw uno::RuntimeException(); 207 208 uno::Sequence< uno::Sequence< beans::StringPair > > aResult; 209 210 uno::Reference< xml::sax::XParser > xParser( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Parser" ) ) ), uno::UNO_QUERY_THROW ); 211 212 OFOPXMLHelper* pHelper = new OFOPXMLHelper( nFormat ); 213 uno::Reference< xml::sax::XDocumentHandler > xHelper( static_cast< xml::sax::XDocumentHandler* >( pHelper ) ); 214 xml::sax::InputSource aParserInput; 215 aParserInput.aInputStream = xInStream; 216 aParserInput.sSystemId = aStringID; 217 xParser->setDocumentHandler( xHelper ); 218 xParser->parseStream( aParserInput ); 219 xParser->setDocumentHandler( uno::Reference < xml::sax::XDocumentHandler > () ); 220 221 return pHelper->GetParsingResult(); 222 } 223 224 // ----------------------------------- 225 OFOPXMLHelper::OFOPXMLHelper( sal_uInt16 nFormat ) 226 : m_nFormat( nFormat ) 227 , m_aRelListElement( RTL_CONSTASCII_USTRINGPARAM( "Relationships" ) ) 228 , m_aRelElement( RTL_CONSTASCII_USTRINGPARAM( "Relationship" ) ) 229 , m_aIDAttr( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ) 230 , m_aTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) 231 , m_aTargetModeAttr( RTL_CONSTASCII_USTRINGPARAM( "TargetMode" ) ) 232 , m_aTargetAttr( RTL_CONSTASCII_USTRINGPARAM( "Target" ) ) 233 , m_aTypesElement( RTL_CONSTASCII_USTRINGPARAM( "Types" ) ) 234 , m_aDefaultElement( RTL_CONSTASCII_USTRINGPARAM( "Default" ) ) 235 , m_aOverrideElement( RTL_CONSTASCII_USTRINGPARAM( "Override" ) ) 236 , m_aExtensionAttr( RTL_CONSTASCII_USTRINGPARAM( "Extension" ) ) 237 , m_aPartNameAttr( RTL_CONSTASCII_USTRINGPARAM( "PartName" ) ) 238 , m_aContentTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ) 239 { 240 } 241 242 // ----------------------------------- 243 OFOPXMLHelper::~OFOPXMLHelper() 244 { 245 } 246 247 // ----------------------------------- 248 uno::Sequence< uno::Sequence< beans::StringPair > > OFOPXMLHelper::GetParsingResult() 249 { 250 if ( m_aElementsSeq.getLength() ) 251 throw uno::RuntimeException(); // the parsing has still not finished! 252 253 return m_aResultSeq; 254 } 255 256 // ----------------------------------- 257 void SAL_CALL OFOPXMLHelper::startDocument() 258 { 259 } 260 261 // ----------------------------------- 262 void SAL_CALL OFOPXMLHelper::endDocument() 263 { 264 } 265 266 // ----------------------------------- 267 void SAL_CALL OFOPXMLHelper::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) 268 { 269 if ( m_nFormat == RELATIONINFO_FORMAT ) 270 { 271 if ( aName == m_aRelListElement ) 272 { 273 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 274 275 if ( nNewLength != 1 ) 276 throw xml::sax::SAXException(); // TODO: this element must be the first level element 277 278 m_aElementsSeq.realloc( nNewLength ); 279 m_aElementsSeq[nNewLength-1] = aName; 280 281 return; // nothing to do 282 } 283 else if ( aName == m_aRelElement ) 284 { 285 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 286 if ( nNewLength != 2 ) 287 throw xml::sax::SAXException(); // TODO: this element must be the second level element 288 289 m_aElementsSeq.realloc( nNewLength ); 290 m_aElementsSeq[nNewLength-1] = aName; 291 292 sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1; 293 m_aResultSeq.realloc( nNewEntryNum ); 294 sal_Int32 nAttrNum = 0; 295 m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 296 297 ::rtl::OUString aIDValue = xAttribs->getValueByName( m_aIDAttr ); 298 if ( aIDValue.isEmpty() ) 299 throw xml::sax::SAXException(); // TODO: the ID value must present 300 301 ::rtl::OUString aTypeValue = xAttribs->getValueByName( m_aTypeAttr ); 302 ::rtl::OUString aTargetValue = xAttribs->getValueByName( m_aTargetAttr ); 303 ::rtl::OUString aTargetModeValue = xAttribs->getValueByName( m_aTargetModeAttr ); 304 305 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aIDAttr; 306 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue; 307 308 if ( !aTypeValue.isEmpty() ) 309 { 310 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTypeAttr; 311 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue; 312 } 313 314 if ( !aTargetValue.isEmpty() ) 315 { 316 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetAttr; 317 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue; 318 } 319 320 if ( !aTargetModeValue.isEmpty() ) 321 { 322 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetModeAttr; 323 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue; 324 } 325 326 m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum ); 327 } 328 else 329 throw xml::sax::SAXException(); // TODO: no other elements expected! 330 } 331 else if ( m_nFormat == CONTENTTYPE_FORMAT ) 332 { 333 if ( aName == m_aTypesElement ) 334 { 335 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 336 337 if ( nNewLength != 1 ) 338 throw xml::sax::SAXException(); // TODO: this element must be the first level element 339 340 m_aElementsSeq.realloc( nNewLength ); 341 m_aElementsSeq[nNewLength-1] = aName; 342 343 if ( !m_aResultSeq.getLength() ) 344 m_aResultSeq.realloc( 2 ); 345 346 return; // nothing to do 347 } 348 else if ( aName == m_aDefaultElement ) 349 { 350 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 351 if ( nNewLength != 2 ) 352 throw xml::sax::SAXException(); // TODO: this element must be the second level element 353 354 m_aElementsSeq.realloc( nNewLength ); 355 m_aElementsSeq[nNewLength-1] = aName; 356 357 if ( !m_aResultSeq.getLength() ) 358 m_aResultSeq.realloc( 2 ); 359 360 if ( m_aResultSeq.getLength() != 2 ) 361 throw uno::RuntimeException(); 362 363 ::rtl::OUString aExtensionValue = xAttribs->getValueByName( m_aExtensionAttr ); 364 if ( aExtensionValue.isEmpty() ) 365 throw xml::sax::SAXException(); // TODO: the Extension value must present 366 367 ::rtl::OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr ); 368 if ( aContentTypeValue.isEmpty() ) 369 throw xml::sax::SAXException(); // TODO: the ContentType value must present 370 371 sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1; 372 m_aResultSeq[0].realloc( nNewResultLen ); 373 374 m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue; 375 m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue; 376 } 377 else if ( aName == m_aOverrideElement ) 378 { 379 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 380 if ( nNewLength != 2 ) 381 throw xml::sax::SAXException(); // TODO: this element must be the second level element 382 383 m_aElementsSeq.realloc( nNewLength ); 384 m_aElementsSeq[nNewLength-1] = aName; 385 386 if ( !m_aResultSeq.getLength() ) 387 m_aResultSeq.realloc( 2 ); 388 389 if ( m_aResultSeq.getLength() != 2 ) 390 throw uno::RuntimeException(); 391 392 ::rtl::OUString aPartNameValue = xAttribs->getValueByName( m_aPartNameAttr ); 393 if ( aPartNameValue.isEmpty() ) 394 throw xml::sax::SAXException(); // TODO: the PartName value must present 395 396 ::rtl::OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr ); 397 if ( aContentTypeValue.isEmpty() ) 398 throw xml::sax::SAXException(); // TODO: the ContentType value must present 399 400 sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1; 401 m_aResultSeq[1].realloc( nNewResultLen ); 402 403 m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue; 404 m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue; 405 } 406 else 407 throw xml::sax::SAXException(); // TODO: no other elements expected! 408 } 409 else 410 throw xml::sax::SAXException(); // TODO: no other elements expected! 411 } 412 413 // ----------------------------------- 414 void SAL_CALL OFOPXMLHelper::endElement( const ::rtl::OUString& aName ) 415 { 416 if ( m_nFormat == RELATIONINFO_FORMAT || m_nFormat == CONTENTTYPE_FORMAT ) 417 { 418 sal_Int32 nLength = m_aElementsSeq.getLength(); 419 if ( nLength <= 0 ) 420 throw xml::sax::SAXException(); // TODO: no other end elements expected! 421 422 if ( !m_aElementsSeq[nLength-1].equals( aName ) ) 423 throw xml::sax::SAXException(); // TODO: unexpected element ended 424 425 m_aElementsSeq.realloc( nLength - 1 ); 426 } 427 } 428 429 // ----------------------------------- 430 void SAL_CALL OFOPXMLHelper::characters( const ::rtl::OUString& /*aChars*/ ) 431 { 432 } 433 434 // ----------------------------------- 435 void SAL_CALL OFOPXMLHelper::ignorableWhitespace( const ::rtl::OUString& /*aWhitespaces*/ ) 436 { 437 } 438 439 // ----------------------------------- 440 void SAL_CALL OFOPXMLHelper::processingInstruction( const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) 441 { 442 } 443 444 // ----------------------------------- 445 void SAL_CALL OFOPXMLHelper::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ ) 446 { 447 } 448 449 } // namespace comphelper 450