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 #include "oox/helper/zipstorage.hxx" 25 26 #include <com/sun/star/embed/ElementModes.hpp> 27 #include <com/sun/star/embed/XStorage.hpp> 28 #include <com/sun/star/embed/XTransactedObject.hpp> 29 #include <com/sun/star/io/XInputStream.hpp> 30 #include <com/sun/star/io/XOutputStream.hpp> 31 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32 #include <com/sun/star/uno/XComponentContext.hpp> 33 #include <comphelper/storagehelper.hxx> 34 #include "oox/helper/helper.hxx" 35 36 namespace oox { 37 38 // ============================================================================ 39 40 using namespace ::com::sun::star::container; 41 using namespace ::com::sun::star::embed; 42 using namespace ::com::sun::star::io; 43 using namespace ::com::sun::star::lang; 44 using namespace ::com::sun::star::uno; 45 46 using ::rtl::OUString; 47 48 // ============================================================================ 49 50 ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStream ) : 51 StorageBase( rxInStream, false ) 52 { 53 OSL_ENSURE( rxContext.is(), "ZipStorage::ZipStorage - missing component context" ); 54 // create base storage object 55 if( rxContext.is() ) try 56 { 57 /* #i105325# ::comphelper::OStorageHelper::GetStorageFromInputStream() 58 cannot be used here as it will open a storage with format type 59 'PackageFormat' that will not work with OOXML packages. 60 61 #161971# The MS-document storages should always be opened in repair 62 mode to ignore the format errors and get so much info as possible. 63 I hate this solution, but it seems to be the only consistent way to 64 handle the MS documents. 65 66 TODO: #i105410# switch to 'OFOPXMLFormat' and use its 67 implementation of relations handling. 68 */ 69 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 70 mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( 71 ZIP_STORAGE_FORMAT_STRING, rxInStream, xFactory, 72 sal_False ); // DEV300_m80: Was sal_True, but DOCX and others did not load 73 } 74 catch( Exception& ) 75 { 76 } 77 } 78 79 ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const Reference< XStream >& rxStream ) : 80 StorageBase( rxStream, false ) 81 { 82 OSL_ENSURE( rxContext.is(), "ZipStorage::ZipStorage - missing component context" ); 83 // create base storage object 84 if( rxContext.is() ) try 85 { 86 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 87 const sal_Int32 nOpenMode = ElementModes::READWRITE | ElementModes::TRUNCATE; 88 mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( 89 OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, xFactory, sal_True ); 90 } 91 catch( Exception& ) 92 { 93 OSL_ENSURE( false, "ZipStorage::ZipStorage - cannot open output storage" ); 94 } 95 } 96 97 ZipStorage::ZipStorage( const ZipStorage& rParentStorage, const Reference< XStorage >& rxStorage, const OUString& rElementName ) : 98 StorageBase( rParentStorage, rElementName, rParentStorage.isReadOnly() ), 99 mxStorage( rxStorage ) 100 { 101 OSL_ENSURE( mxStorage.is(), "ZipStorage::ZipStorage - missing storage" ); 102 } 103 104 ZipStorage::~ZipStorage() 105 { 106 } 107 108 bool ZipStorage::implIsStorage() const 109 { 110 return mxStorage.is(); 111 } 112 113 Reference< XStorage > ZipStorage::implGetXStorage() const 114 { 115 return mxStorage; 116 } 117 118 void ZipStorage::implGetElementNames( ::std::vector< OUString >& orElementNames ) const 119 { 120 Sequence< OUString > aNames; 121 if( mxStorage.is() ) try 122 { 123 aNames = mxStorage->getElementNames(); 124 if( aNames.getLength() > 0 ) 125 orElementNames.insert( orElementNames.end(), aNames.getConstArray(), aNames.getConstArray() + aNames.getLength() ); 126 } 127 catch( Exception& ) 128 { 129 } 130 } 131 132 StorageRef ZipStorage::implOpenSubStorage( const OUString& rElementName, bool bCreateMissing ) 133 { 134 Reference< XStorage > xSubXStorage; 135 bool bMissing = false; 136 if( mxStorage.is() ) try 137 { 138 // XStorage::isStorageElement may throw various exceptions... 139 if( mxStorage->isStorageElement( rElementName ) ) 140 xSubXStorage = mxStorage->openStorageElement( 141 rElementName, ::com::sun::star::embed::ElementModes::READ ); 142 } 143 catch( NoSuchElementException& ) 144 { 145 bMissing = true; 146 } 147 catch( Exception& ) 148 { 149 } 150 151 if( bMissing && bCreateMissing ) try 152 { 153 xSubXStorage = mxStorage->openStorageElement( 154 rElementName, ::com::sun::star::embed::ElementModes::READWRITE ); 155 } 156 catch( Exception& ) 157 { 158 } 159 160 StorageRef xSubStorage; 161 if( xSubXStorage.is() ) 162 xSubStorage.reset( new ZipStorage( *this, xSubXStorage, rElementName ) ); 163 return xSubStorage; 164 } 165 166 Reference< XInputStream > ZipStorage::implOpenInputStream( const OUString& rElementName ) 167 { 168 Reference< XInputStream > xInStream; 169 if( mxStorage.is() ) try 170 { 171 xInStream.set( mxStorage->openStreamElement( rElementName, ::com::sun::star::embed::ElementModes::READ ), UNO_QUERY ); 172 } 173 catch( Exception& ) 174 { 175 } 176 return xInStream; 177 } 178 179 Reference< XOutputStream > ZipStorage::implOpenOutputStream( const OUString& rElementName ) 180 { 181 Reference< XOutputStream > xOutStream; 182 if( mxStorage.is() ) try 183 { 184 xOutStream.set( mxStorage->openStreamElement( rElementName, ::com::sun::star::embed::ElementModes::READWRITE ), UNO_QUERY ); 185 } 186 catch( Exception& ) 187 { 188 } 189 return xOutStream; 190 } 191 192 void ZipStorage::implCommit() const 193 { 194 try 195 { 196 Reference< XTransactedObject >( mxStorage, UNO_QUERY_THROW )->commit(); 197 } 198 catch( Exception& ) 199 { 200 } 201 } 202 203 // ============================================================================ 204 205 } // namespace oox 206