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
ZipStorage(const Reference<XComponentContext> & rxContext,const Reference<XInputStream> & rxInStream)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
ZipStorage(const Reference<XComponentContext> & rxContext,const Reference<XStream> & rxStream)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
ZipStorage(const ZipStorage & rParentStorage,const Reference<XStorage> & rxStorage,const OUString & rElementName)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
~ZipStorage()104 ZipStorage::~ZipStorage()
105 {
106 }
107
implIsStorage() const108 bool ZipStorage::implIsStorage() const
109 {
110 return mxStorage.is();
111 }
112
implGetXStorage() const113 Reference< XStorage > ZipStorage::implGetXStorage() const
114 {
115 return mxStorage;
116 }
117
implGetElementNames(::std::vector<OUString> & orElementNames) const118 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
implOpenSubStorage(const OUString & rElementName,bool bCreateMissing)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
implOpenInputStream(const OUString & rElementName)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 // Bug 126720 - sometimes the relationship says the file is "sharedStrings.xml" but the file is actually "SharedStrings.xml".
176 // Do a case-insensitive search:
177 ::com::sun::star::uno::Sequence< ::rtl::OUString > aNames = mxStorage->getElementNames( );
178 for ( sal_Int32 i = 0; i < aNames.getLength(); i++ )
179 {
180 if ( aNames[i].equalsIgnoreAsciiCase( rElementName ) )
181 {
182 try
183 {
184 xInStream.set( mxStorage->openStreamElement( aNames[i], ::com::sun::star::embed::ElementModes::READ ), UNO_QUERY );
185 }
186 catch( Exception& )
187 {
188 }
189 break;
190 }
191 }
192 }
193 return xInStream;
194 }
195
implOpenOutputStream(const OUString & rElementName)196 Reference< XOutputStream > ZipStorage::implOpenOutputStream( const OUString& rElementName )
197 {
198 Reference< XOutputStream > xOutStream;
199 if( mxStorage.is() ) try
200 {
201 xOutStream.set( mxStorage->openStreamElement( rElementName, ::com::sun::star::embed::ElementModes::READWRITE ), UNO_QUERY );
202 }
203 catch( Exception& )
204 {
205 }
206 return xOutStream;
207 }
208
implCommit() const209 void ZipStorage::implCommit() const
210 {
211 try
212 {
213 Reference< XTransactedObject >( mxStorage, UNO_QUERY_THROW )->commit();
214 }
215 catch( Exception& )
216 {
217 }
218 }
219
220 // ============================================================================
221
222 } // namespace oox
223