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 throw( uno::Exception ) 60 { 61 ::rtl::OUString aStringID = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_rels/" ) ); 62 aStringID += aStreamName; 63 return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, xFactory ); 64 } 65 66 // ----------------------------------- 67 uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadContentTypeSequence( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< lang::XMultiServiceFactory > xFactory ) 68 throw( uno::Exception ) 69 { 70 ::rtl::OUString aStringID = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "[Content_Types].xml" ) ); 71 return ReadSequence_Impl( xInStream, aStringID, CONTENTTYPE_FORMAT, xFactory ); 72 } 73 74 // ----------------------------------- 75 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 ) 76 throw( uno::Exception ) 77 { 78 if ( !xOutStream.is() ) 79 throw uno::RuntimeException(); 80 81 uno::Reference< io::XActiveDataSource > xWriterSource( 82 xFactory->createInstance( 83 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), 84 uno::UNO_QUERY_THROW ); 85 uno::Reference< xml::sax::XDocumentHandler > xWriterHandler( xWriterSource, uno::UNO_QUERY_THROW ); 86 87 xWriterSource->setOutputStream( xOutStream ); 88 89 ::rtl::OUString aRelListElement( RTL_CONSTASCII_USTRINGPARAM( "Relationships" ) ); 90 ::rtl::OUString aRelElement( RTL_CONSTASCII_USTRINGPARAM( "Relationship" ) ); 91 ::rtl::OUString aIDAttr( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ); 92 ::rtl::OUString aTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ); 93 ::rtl::OUString aTargetModeAttr( RTL_CONSTASCII_USTRINGPARAM( "TargetMode" ) ); 94 ::rtl::OUString aTargetAttr( RTL_CONSTASCII_USTRINGPARAM( "Target" ) ); 95 ::rtl::OUString aCDATAString( RTL_CONSTASCII_USTRINGPARAM ( "CDATA" ) ); 96 ::rtl::OUString aWhiteSpace( RTL_CONSTASCII_USTRINGPARAM ( " " ) ); 97 98 // write the namespace 99 AttributeList* pRootAttrList = new AttributeList; 100 uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); 101 pRootAttrList->AddAttribute( 102 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "xmlns" ) ), 103 aCDATAString, 104 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "http://schemas.openxmlformats.org/package/2006/relationships" ) ) ); 105 106 xWriterHandler->startDocument(); 107 xWriterHandler->startElement( aRelListElement, xRootAttrList ); 108 109 for ( sal_Int32 nInd = 0; nInd < aSequence.getLength(); nInd++ ) 110 { 111 AttributeList *pAttrList = new AttributeList; 112 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList ); 113 for( sal_Int32 nSecInd = 0; nSecInd < aSequence[nInd].getLength(); nSecInd++ ) 114 { 115 if ( aSequence[nInd][nSecInd].First.equals( aIDAttr ) 116 || aSequence[nInd][nSecInd].First.equals( aTypeAttr ) 117 || aSequence[nInd][nSecInd].First.equals( aTargetModeAttr ) 118 || aSequence[nInd][nSecInd].First.equals( aTargetAttr ) ) 119 { 120 pAttrList->AddAttribute( aSequence[nInd][nSecInd].First, aCDATAString, aSequence[nInd][nSecInd].Second ); 121 } 122 else 123 { 124 // TODO/LATER: should the extensions be allowed? 125 throw lang::IllegalArgumentException(); 126 } 127 } 128 129 xWriterHandler->startElement( aRelElement, xAttrList ); 130 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 131 xWriterHandler->endElement( aRelElement ); 132 } 133 134 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 135 xWriterHandler->endElement( aRelListElement ); 136 xWriterHandler->endDocument(); 137 } 138 139 // ----------------------------------- 140 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 ) 141 throw( uno::Exception ) 142 { 143 if ( !xOutStream.is() ) 144 throw uno::RuntimeException(); 145 146 uno::Reference< io::XActiveDataSource > xWriterSource( 147 xFactory->createInstance( 148 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Writer" ) ) ), 149 uno::UNO_QUERY_THROW ); 150 uno::Reference< xml::sax::XDocumentHandler > xWriterHandler( xWriterSource, uno::UNO_QUERY_THROW ); 151 152 xWriterSource->setOutputStream( xOutStream ); 153 154 ::rtl::OUString aTypesElement( RTL_CONSTASCII_USTRINGPARAM( "Types" ) ); 155 ::rtl::OUString aDefaultElement( RTL_CONSTASCII_USTRINGPARAM( "Default" ) ); 156 ::rtl::OUString aOverrideElement( RTL_CONSTASCII_USTRINGPARAM( "Override" ) ); 157 ::rtl::OUString aExtensionAttr( RTL_CONSTASCII_USTRINGPARAM( "Extension" ) ); 158 ::rtl::OUString aPartNameAttr( RTL_CONSTASCII_USTRINGPARAM( "PartName" ) ); 159 ::rtl::OUString aContentTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ); 160 ::rtl::OUString aCDATAString( RTL_CONSTASCII_USTRINGPARAM ( "CDATA" ) ); 161 ::rtl::OUString aWhiteSpace( RTL_CONSTASCII_USTRINGPARAM ( " " ) ); 162 163 // write the namespace 164 AttributeList* pRootAttrList = new AttributeList; 165 uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList ); 166 pRootAttrList->AddAttribute( 167 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "xmlns" ) ), 168 aCDATAString, 169 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "http://schemas.openxmlformats.org/package/2006/content-types" ) ) ); 170 171 xWriterHandler->startDocument(); 172 xWriterHandler->startElement( aTypesElement, xRootAttrList ); 173 174 for ( sal_Int32 nInd = 0; nInd < aDefaultsSequence.getLength(); nInd++ ) 175 { 176 AttributeList *pAttrList = new AttributeList; 177 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList ); 178 pAttrList->AddAttribute( aExtensionAttr, aCDATAString, aDefaultsSequence[nInd].First ); 179 pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aDefaultsSequence[nInd].Second ); 180 181 xWriterHandler->startElement( aDefaultElement, xAttrList ); 182 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 183 xWriterHandler->endElement( aDefaultElement ); 184 } 185 186 for ( sal_Int32 nInd = 0; nInd < aOverridesSequence.getLength(); nInd++ ) 187 { 188 AttributeList *pAttrList = new AttributeList; 189 uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList ); 190 pAttrList->AddAttribute( aPartNameAttr, aCDATAString, aOverridesSequence[nInd].First ); 191 pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aOverridesSequence[nInd].Second ); 192 193 xWriterHandler->startElement( aOverrideElement, xAttrList ); 194 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 195 xWriterHandler->endElement( aOverrideElement ); 196 } 197 198 xWriterHandler->ignorableWhitespace( aWhiteSpace ); 199 xWriterHandler->endElement( aTypesElement ); 200 xWriterHandler->endDocument(); 201 202 } 203 204 // ================================================================================== 205 206 // ----------------------------------- 207 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 ) 208 throw( uno::Exception ) 209 { 210 if ( !xFactory.is() || !xInStream.is() || nFormat > FORMAT_MAX_ID ) 211 throw uno::RuntimeException(); 212 213 uno::Sequence< uno::Sequence< beans::StringPair > > aResult; 214 215 uno::Reference< xml::sax::XParser > xParser( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.sax.Parser" ) ) ), uno::UNO_QUERY_THROW ); 216 217 OFOPXMLHelper* pHelper = new OFOPXMLHelper( nFormat ); 218 uno::Reference< xml::sax::XDocumentHandler > xHelper( static_cast< xml::sax::XDocumentHandler* >( pHelper ) ); 219 xml::sax::InputSource aParserInput; 220 aParserInput.aInputStream = xInStream; 221 aParserInput.sSystemId = aStringID; 222 xParser->setDocumentHandler( xHelper ); 223 xParser->parseStream( aParserInput ); 224 xParser->setDocumentHandler( uno::Reference < xml::sax::XDocumentHandler > () ); 225 226 return pHelper->GetParsingResult(); 227 } 228 229 // ----------------------------------- 230 OFOPXMLHelper::OFOPXMLHelper( sal_uInt16 nFormat ) 231 : m_nFormat( nFormat ) 232 , m_aRelListElement( RTL_CONSTASCII_USTRINGPARAM( "Relationships" ) ) 233 , m_aRelElement( RTL_CONSTASCII_USTRINGPARAM( "Relationship" ) ) 234 , m_aIDAttr( RTL_CONSTASCII_USTRINGPARAM( "Id" ) ) 235 , m_aTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "Type" ) ) 236 , m_aTargetModeAttr( RTL_CONSTASCII_USTRINGPARAM( "TargetMode" ) ) 237 , m_aTargetAttr( RTL_CONSTASCII_USTRINGPARAM( "Target" ) ) 238 , m_aTypesElement( RTL_CONSTASCII_USTRINGPARAM( "Types" ) ) 239 , m_aDefaultElement( RTL_CONSTASCII_USTRINGPARAM( "Default" ) ) 240 , m_aOverrideElement( RTL_CONSTASCII_USTRINGPARAM( "Override" ) ) 241 , m_aExtensionAttr( RTL_CONSTASCII_USTRINGPARAM( "Extension" ) ) 242 , m_aPartNameAttr( RTL_CONSTASCII_USTRINGPARAM( "PartName" ) ) 243 , m_aContentTypeAttr( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ) 244 { 245 } 246 247 // ----------------------------------- 248 OFOPXMLHelper::~OFOPXMLHelper() 249 { 250 } 251 252 // ----------------------------------- 253 uno::Sequence< uno::Sequence< beans::StringPair > > OFOPXMLHelper::GetParsingResult() 254 { 255 if ( m_aElementsSeq.getLength() ) 256 throw uno::RuntimeException(); // the parsing has still not finished! 257 258 return m_aResultSeq; 259 } 260 261 // ----------------------------------- 262 void SAL_CALL OFOPXMLHelper::startDocument() 263 throw(xml::sax::SAXException, uno::RuntimeException) 264 { 265 } 266 267 // ----------------------------------- 268 void SAL_CALL OFOPXMLHelper::endDocument() 269 throw(xml::sax::SAXException, uno::RuntimeException) 270 { 271 } 272 273 // ----------------------------------- 274 void SAL_CALL OFOPXMLHelper::startElement( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) 275 throw( xml::sax::SAXException, uno::RuntimeException ) 276 { 277 if ( m_nFormat == RELATIONINFO_FORMAT ) 278 { 279 if ( aName == m_aRelListElement ) 280 { 281 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 282 283 if ( nNewLength != 1 ) 284 throw xml::sax::SAXException(); // TODO: this element must be the first level element 285 286 m_aElementsSeq.realloc( nNewLength ); 287 m_aElementsSeq[nNewLength-1] = aName; 288 289 return; // nothing to do 290 } 291 else if ( aName == m_aRelElement ) 292 { 293 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 294 if ( nNewLength != 2 ) 295 throw xml::sax::SAXException(); // TODO: this element must be the second level element 296 297 m_aElementsSeq.realloc( nNewLength ); 298 m_aElementsSeq[nNewLength-1] = aName; 299 300 sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1; 301 m_aResultSeq.realloc( nNewEntryNum ); 302 sal_Int32 nAttrNum = 0; 303 m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 304 305 ::rtl::OUString aIDValue = xAttribs->getValueByName( m_aIDAttr ); 306 if ( !aIDValue.getLength() ) 307 throw xml::sax::SAXException(); // TODO: the ID value must present 308 309 ::rtl::OUString aTypeValue = xAttribs->getValueByName( m_aTypeAttr ); 310 ::rtl::OUString aTargetValue = xAttribs->getValueByName( m_aTargetAttr ); 311 ::rtl::OUString aTargetModeValue = xAttribs->getValueByName( m_aTargetModeAttr ); 312 313 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aIDAttr; 314 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue; 315 316 if ( aTypeValue.getLength() ) 317 { 318 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTypeAttr; 319 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue; 320 } 321 322 if ( aTargetValue.getLength() ) 323 { 324 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetAttr; 325 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue; 326 } 327 328 if ( aTargetModeValue.getLength() ) 329 { 330 m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetModeAttr; 331 m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue; 332 } 333 334 m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum ); 335 } 336 else 337 throw xml::sax::SAXException(); // TODO: no other elements expected! 338 } 339 else if ( m_nFormat == CONTENTTYPE_FORMAT ) 340 { 341 if ( aName == m_aTypesElement ) 342 { 343 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 344 345 if ( nNewLength != 1 ) 346 throw xml::sax::SAXException(); // TODO: this element must be the first level element 347 348 m_aElementsSeq.realloc( nNewLength ); 349 m_aElementsSeq[nNewLength-1] = aName; 350 351 if ( !m_aResultSeq.getLength() ) 352 m_aResultSeq.realloc( 2 ); 353 354 return; // nothing to do 355 } 356 else if ( aName == m_aDefaultElement ) 357 { 358 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 359 if ( nNewLength != 2 ) 360 throw xml::sax::SAXException(); // TODO: this element must be the second level element 361 362 m_aElementsSeq.realloc( nNewLength ); 363 m_aElementsSeq[nNewLength-1] = aName; 364 365 if ( !m_aResultSeq.getLength() ) 366 m_aResultSeq.realloc( 2 ); 367 368 if ( m_aResultSeq.getLength() != 2 ) 369 throw uno::RuntimeException(); 370 371 ::rtl::OUString aExtensionValue = xAttribs->getValueByName( m_aExtensionAttr ); 372 if ( !aExtensionValue.getLength() ) 373 throw xml::sax::SAXException(); // TODO: the Extension value must present 374 375 ::rtl::OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr ); 376 if ( !aContentTypeValue.getLength() ) 377 throw xml::sax::SAXException(); // TODO: the ContentType value must present 378 379 sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1; 380 m_aResultSeq[0].realloc( nNewResultLen ); 381 382 m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue; 383 m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue; 384 } 385 else if ( aName == m_aOverrideElement ) 386 { 387 sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1; 388 if ( nNewLength != 2 ) 389 throw xml::sax::SAXException(); // TODO: this element must be the second level element 390 391 m_aElementsSeq.realloc( nNewLength ); 392 m_aElementsSeq[nNewLength-1] = aName; 393 394 if ( !m_aResultSeq.getLength() ) 395 m_aResultSeq.realloc( 2 ); 396 397 if ( m_aResultSeq.getLength() != 2 ) 398 throw uno::RuntimeException(); 399 400 ::rtl::OUString aPartNameValue = xAttribs->getValueByName( m_aPartNameAttr ); 401 if ( !aPartNameValue.getLength() ) 402 throw xml::sax::SAXException(); // TODO: the PartName value must present 403 404 ::rtl::OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr ); 405 if ( !aContentTypeValue.getLength() ) 406 throw xml::sax::SAXException(); // TODO: the ContentType value must present 407 408 sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1; 409 m_aResultSeq[1].realloc( nNewResultLen ); 410 411 m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue; 412 m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue; 413 } 414 else 415 throw xml::sax::SAXException(); // TODO: no other elements expected! 416 } 417 else 418 throw xml::sax::SAXException(); // TODO: no other elements expected! 419 } 420 421 // ----------------------------------- 422 void SAL_CALL OFOPXMLHelper::endElement( const ::rtl::OUString& aName ) 423 throw( xml::sax::SAXException, uno::RuntimeException ) 424 { 425 if ( m_nFormat == RELATIONINFO_FORMAT || m_nFormat == CONTENTTYPE_FORMAT ) 426 { 427 sal_Int32 nLength = m_aElementsSeq.getLength(); 428 if ( nLength <= 0 ) 429 throw xml::sax::SAXException(); // TODO: no other end elements expected! 430 431 if ( !m_aElementsSeq[nLength-1].equals( aName ) ) 432 throw xml::sax::SAXException(); // TODO: unexpected element ended 433 434 m_aElementsSeq.realloc( nLength - 1 ); 435 } 436 } 437 438 // ----------------------------------- 439 void SAL_CALL OFOPXMLHelper::characters( const ::rtl::OUString& /*aChars*/ ) 440 throw(xml::sax::SAXException, uno::RuntimeException) 441 { 442 } 443 444 // ----------------------------------- 445 void SAL_CALL OFOPXMLHelper::ignorableWhitespace( const ::rtl::OUString& /*aWhitespaces*/ ) 446 throw(xml::sax::SAXException, uno::RuntimeException) 447 { 448 } 449 450 // ----------------------------------- 451 void SAL_CALL OFOPXMLHelper::processingInstruction( const ::rtl::OUString& /*aTarget*/, const ::rtl::OUString& /*aData*/ ) 452 throw(xml::sax::SAXException, uno::RuntimeException) 453 { 454 } 455 456 // ----------------------------------- 457 void SAL_CALL OFOPXMLHelper::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ ) 458 throw(xml::sax::SAXException, uno::RuntimeException) 459 { 460 } 461 462 } // namespace comphelper 463 464