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