1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "ooxmldocpropimport.hxx" 29 30 #include <vector> 31 #include <com/sun/star/embed/ElementModes.hpp> 32 #include <com/sun/star/embed/XHierarchicalStorageAccess.hpp> 33 #include <com/sun/star/embed/XRelationshipAccess.hpp> 34 #include <com/sun/star/embed/XStorage.hpp> 35 #include "oox/core/fastparser.hxx" 36 #include "oox/core/relations.hxx" 37 #include "oox/helper/containerhelper.hxx" 38 #include "oox/helper/helper.hxx" 39 #include "docprophandler.hxx" 40 41 namespace oox { 42 namespace docprop { 43 44 // ============================================================================ 45 46 using namespace ::com::sun::star::beans; 47 using namespace ::com::sun::star::document; 48 using namespace ::com::sun::star::embed; 49 using namespace ::com::sun::star::io; 50 using namespace ::com::sun::star::lang; 51 using namespace ::com::sun::star::uno; 52 using namespace ::com::sun::star::xml::sax; 53 54 using ::rtl::OUString; 55 56 // ============================================================================ 57 58 OUString SAL_CALL DocumentPropertiesImport_getImplementationName() 59 { 60 return CREATE_OUSTRING( "com.sun.star.comp.oox.docprop.DocumentPropertiesImporter" ); 61 } 62 63 Sequence< OUString > SAL_CALL DocumentPropertiesImport_getSupportedServiceNames() 64 { 65 Sequence< OUString > aServices( 1 ); 66 aServices[ 0 ] = CREATE_OUSTRING( "com.sun.star.document.OOXMLDocumentPropertiesImporter" ); 67 return aServices; 68 } 69 70 Reference< XInterface > SAL_CALL DocumentPropertiesImport_createInstance( const Reference< XComponentContext >& rxContext ) SAL_THROW((Exception)) 71 { 72 return static_cast< ::cppu::OWeakObject* >( new DocumentPropertiesImport( rxContext ) ); 73 } 74 75 // ============================================================================ 76 77 namespace { 78 79 Sequence< InputSource > lclGetRelatedStreams( const Reference< XStorage >& rxStorage, const OUString& rStreamType ) throw (RuntimeException) 80 { 81 Reference< XRelationshipAccess > xRelation( rxStorage, UNO_QUERY_THROW ); 82 Reference< XHierarchicalStorageAccess > xHierarchy( rxStorage, UNO_QUERY_THROW ); 83 84 Sequence< Sequence< StringPair > > aPropsInfo = xRelation->getRelationshipsByType( rStreamType ); 85 86 ::std::vector< InputSource > aResult; 87 88 for( sal_Int32 nIndex = 0, nLength = aPropsInfo.getLength(); nIndex < nLength; ++nIndex ) 89 { 90 const Sequence< StringPair >& rEntries = aPropsInfo[ nIndex ]; 91 for( sal_Int32 nEntryIndex = 0, nEntryLength = rEntries.getLength(); nEntryIndex < nEntryLength; ++nEntryIndex ) 92 { 93 const StringPair& rEntry = rEntries[ nEntryIndex ]; 94 if( rEntry.First.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Target" ) ) ) 95 { 96 Reference< XExtendedStorageStream > xExtStream( 97 xHierarchy->openStreamElementByHierarchicalName( rEntry.Second, ElementModes::READ ), UNO_QUERY_THROW ); 98 Reference< XInputStream > xInStream = xExtStream->getInputStream(); 99 if( xInStream.is() ) 100 { 101 aResult.resize( aResult.size() + 1 ); 102 aResult.back().sSystemId = rEntry.Second; 103 aResult.back().aInputStream = xExtStream->getInputStream(); 104 } 105 break; 106 } 107 } 108 } 109 110 return ContainerHelper::vectorToSequence( aResult ); 111 } 112 113 } // namespace 114 115 // ============================================================================ 116 117 DocumentPropertiesImport::DocumentPropertiesImport( const Reference< XComponentContext >& rxContext ) : 118 mxContext( rxContext ) 119 { 120 } 121 122 // XServiceInfo 123 124 OUString SAL_CALL DocumentPropertiesImport::getImplementationName() throw (RuntimeException) 125 { 126 return DocumentPropertiesImport_getImplementationName(); 127 } 128 129 sal_Bool SAL_CALL DocumentPropertiesImport::supportsService( const OUString& rServiceName ) throw (RuntimeException) 130 { 131 Sequence< OUString > aServiceNames = DocumentPropertiesImport_getSupportedServiceNames(); 132 for( sal_Int32 nIndex = 0, nLength = aServiceNames.getLength(); nIndex < nLength; ++nIndex ) 133 if( aServiceNames[ nIndex ] == rServiceName ) 134 return sal_True; 135 return sal_False; 136 } 137 138 Sequence< OUString > SAL_CALL DocumentPropertiesImport::getSupportedServiceNames() throw (RuntimeException) 139 { 140 return DocumentPropertiesImport_getSupportedServiceNames(); 141 } 142 143 // XOOXMLDocumentPropertiesImporter 144 145 void SAL_CALL DocumentPropertiesImport::importProperties( 146 const Reference< XStorage >& rxSource, const Reference< XDocumentProperties >& rxDocumentProperties ) 147 throw (RuntimeException, IllegalArgumentException, SAXException, Exception) 148 { 149 if( !mxContext.is() ) 150 throw RuntimeException(); 151 152 if( !rxSource.is() || !rxDocumentProperties.is() ) 153 throw IllegalArgumentException(); 154 155 Sequence< InputSource > aCoreStreams = lclGetRelatedStreams( rxSource, CREATE_OFFICEDOC_RELATION_TYPE( "metadata/core-properties" ) ); 156 // MS Office seems to have a bug, so we have to do similar handling 157 if( !aCoreStreams.hasElements() ) 158 aCoreStreams = lclGetRelatedStreams( rxSource, CREATE_PACKAGE_RELATION_TYPE( "metadata/core-properties" ) ); 159 160 Sequence< InputSource > aExtStreams = lclGetRelatedStreams( rxSource, CREATE_OFFICEDOC_RELATION_TYPE( "extended-properties" ) ); 161 Sequence< InputSource > aCustomStreams = lclGetRelatedStreams( rxSource, CREATE_OFFICEDOC_RELATION_TYPE( "custom-properties" ) ); 162 163 if( aCoreStreams.hasElements() || aExtStreams.hasElements() || aCustomStreams.hasElements() ) 164 { 165 if( aCoreStreams.getLength() > 1 ) 166 throw IOException( CREATE_OUSTRING( "Unexpected core properties stream!" ), Reference< XInterface >() ); 167 168 ::oox::core::FastParser aParser( mxContext ); 169 aParser.registerNamespace( NMSP_packageMetaCorePr ); 170 aParser.registerNamespace( NMSP_dc ); 171 aParser.registerNamespace( NMSP_dcTerms ); 172 aParser.registerNamespace( NMSP_officeExtPr ); 173 aParser.registerNamespace( NMSP_officeCustomPr ); 174 aParser.registerNamespace( NMSP_officeDocPropsVT ); 175 aParser.setDocumentHandler( new OOXMLDocPropHandler( mxContext, rxDocumentProperties ) ); 176 177 if( aCoreStreams.hasElements() ) 178 aParser.parseStream( aCoreStreams[ 0 ], true ); 179 for( sal_Int32 nIndex = 0; nIndex < aExtStreams.getLength(); ++nIndex ) 180 aParser.parseStream( aExtStreams[ nIndex ], true ); 181 for( sal_Int32 nIndex = 0; nIndex < aCustomStreams.getLength(); ++nIndex ) 182 aParser.parseStream( aCustomStreams[ nIndex ], true ); 183 } 184 } 185 186 // ============================================================================ 187 188 } // namespace docprop 189 } // namespace oox 190