Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
21 : : #include <com/sun/star/ucb/XSimpleFileAccess2.hpp>
22 : : #include <com/sun/star/embed/ElementModes.hpp>
23 : : #include <com/sun/star/embed/StorageFormats.hpp>
24 : : #include <com/sun/star/beans/PropertyValue.hpp>
25 : : #include <com/sun/star/io/XSeekable.hpp>
26 : :
27 : : #include <comphelper/componentcontext.hxx>
28 : : #include <comphelper/storagehelper.hxx>
29 : :
30 : : #include "xfactory.hxx"
31 : : #include "xstorage.hxx"
32 : :
33 : :
34 : : using namespace ::com::sun::star;
35 : :
36 : : //-------------------------------------------------------------------------
37 : 2746 : sal_Bool CheckPackageSignature_Impl( const uno::Reference< io::XInputStream >& xInputStream,
38 : : const uno::Reference< io::XSeekable >& xSeekable )
39 : : {
40 [ + - ][ - + ]: 2746 : if ( !xInputStream.is() || !xSeekable.is() )
[ - + ]
41 [ # # ]: 0 : throw uno::RuntimeException();
42 : :
43 [ + + ]: 2746 : if ( xSeekable->getLength() )
44 : : {
45 [ + - ]: 2464 : uno::Sequence< sal_Int8 > aData( 4 );
46 [ + - ][ + - ]: 2464 : xSeekable->seek( 0 );
47 [ + - ][ + - ]: 2464 : sal_Int32 nRead = xInputStream->readBytes( aData, 4 );
48 [ + - ][ + - ]: 2464 : xSeekable->seek( 0 );
49 : :
50 : : // TODO/LATER: should the disk spanned files be supported?
51 : : // 0x50, 0x4b, 0x07, 0x08
52 [ + - ][ + - ]: 2464 : return ( nRead == 4 && aData[0] == 0x50 && aData[1] == 0x4b && aData[2] == 0x03 && aData[3] == 0x04 );
[ + + ][ + - ]
[ + + ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
53 : : }
54 : : else
55 : 2746 : return sal_True; // allow to create a storage based on empty stream
56 : : }
57 : :
58 : : //-------------------------------------------------------------------------
59 : 123 : uno::Sequence< ::rtl::OUString > SAL_CALL OStorageFactory::impl_staticGetSupportedServiceNames()
60 : : {
61 : 123 : uno::Sequence< ::rtl::OUString > aRet(2);
62 [ + - ][ + - ]: 123 : aRet[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.embed.StorageFactory") );
63 [ + - ][ + - ]: 123 : aRet[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.embed.StorageFactory") );
64 : 123 : return aRet;
65 : : }
66 : :
67 : : //-------------------------------------------------------------------------
68 : 246 : ::rtl::OUString SAL_CALL OStorageFactory::impl_staticGetImplementationName()
69 : : {
70 : 246 : return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.embed.StorageFactory") );
71 : : }
72 : :
73 : : //-------------------------------------------------------------------------
74 : 123 : uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::impl_staticCreateSelfInstance(
75 : : const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
76 : : {
77 [ + - ]: 123 : return uno::Reference< uno::XInterface >( *new OStorageFactory( xServiceManager ) );
78 : : }
79 : :
80 : : //-------------------------------------------------------------------------
81 : 2459 : uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstance()
82 : : throw ( uno::Exception,
83 : : uno::RuntimeException )
84 : : {
85 : : // TODO: reimplement TempStream service to support XStream interface
86 : : uno::Reference < io::XStream > xTempStream(
87 [ + - ]: 2459 : m_xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.TempFile") ) ),
88 [ + - ][ + - ]: 2459 : uno::UNO_QUERY );
[ + - ]
89 : :
90 [ - + ]: 2459 : if ( !xTempStream.is() )
91 [ # # ]: 0 : throw uno::RuntimeException(); // TODO:
92 : :
93 : : return uno::Reference< uno::XInterface >(
94 : : static_cast< OWeakObject* >( new OStorage( xTempStream,
95 : : embed::ElementModes::READWRITE,
96 : : uno::Sequence< beans::PropertyValue >(),
97 : : m_xFactory,
98 [ + - ][ + - ]: 4918 : embed::StorageFormats::PACKAGE ) ),
[ + - ][ + - ]
99 [ + - ]: 4918 : uno::UNO_QUERY );
100 : : }
101 : :
102 : : //-------------------------------------------------------------------------
103 : 2746 : uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstanceWithArguments(
104 : : const uno::Sequence< uno::Any >& aArguments )
105 : : throw ( uno::Exception,
106 : : uno::RuntimeException )
107 : : {
108 : : // The request for storage can be done with up to three arguments
109 : :
110 : : // The first argument specifies a source for the storage
111 : : // it can be URL, XStream, XInputStream.
112 : : // The second value is a mode the storage should be open in.
113 : : // And the third value is a media descriptor.
114 : :
115 : 2746 : sal_Int32 nArgNum = aArguments.getLength();
116 : : OSL_ENSURE( nArgNum < 4, "Wrong parameter number" );
117 : :
118 [ - + ]: 2746 : if ( !nArgNum )
119 [ # # ]: 0 : return createInstance();
120 : :
121 : : // first try to retrieve storage open mode if any
122 : : // by default the storage will be open in readonly mode
123 : 2746 : sal_Int32 nStorageMode = embed::ElementModes::READ;
124 [ + - ]: 2746 : if ( nArgNum >= 2 )
125 : : {
126 [ - + ]: 2746 : if( !( aArguments[1] >>= nStorageMode ) )
127 : : {
128 : : OSL_FAIL( "Wrong second argument!\n" );
129 [ # # ]: 0 : throw lang::IllegalArgumentException(); // TODO:
130 : : }
131 : : // it's allways possible to read written storage in this implementation
132 : 2746 : nStorageMode |= embed::ElementModes::READ;
133 : : }
134 : :
135 [ + + ][ - + ]: 2746 : if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE
136 : : && ( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE )
137 [ # # ]: 0 : throw lang::IllegalArgumentException(); // TODO:
138 : :
139 : : // retrieve storage source stream
140 : 2746 : ::rtl::OUString aURL;
141 : 2746 : uno::Reference< io::XStream > xStream;
142 : 2746 : uno::Reference< io::XInputStream > xInputStream;
143 : :
144 [ + + ]: 2746 : if ( aArguments[0] >>= aURL )
145 : : {
146 [ - + ]: 214 : if ( aURL.isEmpty() )
147 : : {
148 : : OSL_FAIL( "Empty URL is provided!\n" );
149 [ # # ]: 0 : throw lang::IllegalArgumentException(); // TODO:
150 : : }
151 : :
152 [ - + ]: 214 : if ( aURL.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg")) )
153 : : {
154 : : OSL_FAIL( "Packages URL's are not valid for storages!\n" ); // ???
155 [ # # ]: 0 : throw lang::IllegalArgumentException(); // TODO:
156 : : }
157 : :
158 : : uno::Reference < ucb::XSimpleFileAccess2 > xTempAccess(
159 : : ucb::SimpleFileAccess::create(
160 [ + - ][ + - ]: 214 : comphelper::ComponentContext(m_xFactory).getUNOContext() ) );
[ + - ][ + - ]
161 : :
162 [ + + ]: 214 : if ( nStorageMode & embed::ElementModes::WRITE )
163 [ + - ][ + - ]: 174 : xStream = xTempAccess->openFileReadWrite( aURL );
[ + - ]
164 : : else
165 [ + - ][ + - ]: 214 : xInputStream = xTempAccess->openFileRead( aURL );
[ + - ]
166 : : }
167 [ + - ][ + + ]: 2532 : else if ( !( aArguments[0] >>= xStream ) && !( aArguments[0] >>= xInputStream ) )
[ + - ][ - + ]
[ - + ]
168 : : {
169 : : OSL_FAIL( "Wrong first argument!\n" );
170 [ # # ]: 0 : throw uno::Exception(); // TODO: Illegal argument
171 : : }
172 : :
173 : : // retrieve mediadescriptor and set storage properties
174 [ + - ]: 2746 : uno::Sequence< beans::PropertyValue > aDescr;
175 [ + - ]: 2746 : uno::Sequence< beans::PropertyValue > aPropsToSet;
176 : :
177 : 2746 : sal_Int32 nStorageType = embed::StorageFormats::PACKAGE;
178 : :
179 [ + + ]: 2746 : if ( nArgNum >= 3 )
180 : : {
181 [ + - ][ + - ]: 1536 : if( aArguments[2] >>= aDescr )
182 : : {
183 [ - + ]: 1536 : if ( !aURL.isEmpty() )
184 : : {
185 [ # # ]: 0 : aPropsToSet.realloc(1);
186 [ # # ][ # # ]: 0 : aPropsToSet[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("URL") );
187 [ # # ][ # # ]: 0 : aPropsToSet[0].Value <<= aURL;
188 : : }
189 : :
190 [ + + ]: 3129 : for ( sal_Int32 nInd = 0, nNumArgs = 1; nInd < aDescr.getLength(); nInd++ )
191 : : {
192 [ + - ][ + - : 6315 : if ( aDescr[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ) )
+ - + + -
+ ][ + + ]
193 [ + - ]: 1593 : || aDescr[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Password" ) )
194 [ + - ]: 1593 : || aDescr[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ) )
195 [ + - ]: 1536 : || aDescr[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ) ) )
196 : : // || aDescr[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Unpacked" ) ) // TODO:
197 : : {
198 [ + - ]: 57 : aPropsToSet.realloc( ++nNumArgs );
199 [ + - ][ + - ]: 57 : aPropsToSet[nNumArgs-1].Name = aDescr[nInd].Name;
200 [ + - ][ + - ]: 57 : aPropsToSet[nNumArgs-1].Value = aDescr[nInd].Value;
201 : : }
202 [ + - ][ + - ]: 1536 : else if ( aDescr[nInd].Name == "StorageFormat" )
203 : : {
204 : 1536 : ::rtl::OUString aFormatName;
205 : 1536 : sal_Int32 nFormatID = 0;
206 [ + - ][ + - ]: 1536 : if ( aDescr[nInd].Value >>= aFormatName )
207 : : {
208 [ + - ][ - + ]: 1536 : if ( aFormatName.equals( PACKAGE_STORAGE_FORMAT_STRING ) )
209 : 0 : nStorageType = embed::StorageFormats::PACKAGE;
210 [ + - ][ + + ]: 1536 : else if ( aFormatName.equals( ZIP_STORAGE_FORMAT_STRING ) )
211 : 923 : nStorageType = embed::StorageFormats::ZIP;
212 [ + - ][ + - ]: 613 : else if ( aFormatName.equals( OFOPXML_STORAGE_FORMAT_STRING ) )
213 : 613 : nStorageType = embed::StorageFormats::OFOPXML;
214 : : else
215 [ # # ][ # # ]: 0 : throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
216 : : }
217 [ # # ][ # # ]: 0 : else if ( aDescr[nInd].Value >>= nFormatID )
218 : : {
219 [ # # ][ # # ]: 0 : if ( nFormatID != embed::StorageFormats::PACKAGE
[ # # ]
220 : : && nFormatID != embed::StorageFormats::ZIP
221 : : && nFormatID != embed::StorageFormats::OFOPXML )
222 [ # # ][ # # ]: 0 : throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
223 : :
224 : 0 : nStorageType = nFormatID;
225 : : }
226 : : else
227 [ # # ][ # # ]: 1536 : throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
228 : : }
229 : : else
230 : : OSL_FAIL( "Unacceptable property, will be ignored!\n" );
231 : : }
232 : : }
233 : : else
234 : : {
235 : : OSL_FAIL( "Wrong third argument!\n" );
236 [ # # ]: 0 : throw uno::Exception(); // TODO: Illegal argument
237 : : }
238 : :
239 : : }
240 : :
241 : : // create storage based on source
242 [ + + ]: 2746 : if ( xInputStream.is() )
243 : : {
244 : : // if xInputStream is set the storage should be open from it
245 [ - + ]: 1433 : if ( ( nStorageMode & embed::ElementModes::WRITE ) )
246 [ # # ]: 0 : throw uno::Exception(); // TODO: access denied
247 : :
248 [ + - ]: 1433 : uno::Reference< io::XSeekable > xSeekable( xInputStream, uno::UNO_QUERY );
249 : 1433 : if ( !xSeekable.is() )
250 : : {
251 : : // TODO: wrap stream to let it be seekable
252 : : OSL_FAIL( "Nonseekable streams are not supported for now!\n" );
253 : : }
254 : :
255 [ + + ][ + - ]: 1433 : if ( !CheckPackageSignature_Impl( xInputStream, xSeekable ) )
256 [ + - ]: 150 : throw io::IOException(); // TODO: this is not a package file
257 : :
258 : : return uno::Reference< uno::XInterface >(
259 [ + - ][ + - ]: 2566 : static_cast< OWeakObject* >( new OStorage( xInputStream, nStorageMode, aPropsToSet, m_xFactory, nStorageType ) ),
[ + - ][ + - ]
260 [ + - ]: 2716 : uno::UNO_QUERY );
261 : : }
262 [ + - ]: 1313 : else if ( xStream.is() )
263 : : {
264 [ + + ][ + - ]: 3939 : if ( ( ( nStorageMode & embed::ElementModes::WRITE ) && !xStream->getOutputStream().is() )
[ + - ]
[ + - - + ]
[ + + ]
[ - + # # ]
265 [ + - ][ + - ]: 2626 : || !xStream->getInputStream().is() )
[ + - ][ # # ]
266 [ # # ]: 0 : throw uno::Exception(); // TODO: access denied
267 : :
268 [ + - ]: 1313 : uno::Reference< io::XSeekable > xSeekable( xStream, uno::UNO_QUERY );
269 : 1313 : if ( !xSeekable.is() )
270 : : {
271 : : // TODO: wrap stream to let it be seekable
272 : : OSL_FAIL( "Nonseekable streams are not supported for now!\n" );
273 : : }
274 : :
275 [ + - ][ + - ]: 1313 : if ( !CheckPackageSignature_Impl( xStream->getInputStream(), xSeekable ) )
[ + + ][ + - ]
276 [ + - ]: 184 : throw io::IOException(); // TODO: this is not a package file
277 : :
278 : : return uno::Reference< uno::XInterface >(
279 [ + - ][ + - ]: 2258 : static_cast< OWeakObject* >( new OStorage( xStream, nStorageMode, aPropsToSet, m_xFactory, nStorageType ) ),
[ + - ][ + - ]
280 [ + - ]: 2442 : uno::UNO_QUERY );
281 : : }
282 : :
283 [ # # ][ + - ]: 2746 : throw uno::Exception(); // general error during creation
[ + - ]
284 : : }
285 : :
286 : : //-------------------------------------------------------------------------
287 : 0 : ::rtl::OUString SAL_CALL OStorageFactory::getImplementationName()
288 : : throw ( uno::RuntimeException )
289 : : {
290 : 0 : return impl_staticGetImplementationName();
291 : : }
292 : :
293 : : //-------------------------------------------------------------------------
294 : 0 : sal_Bool SAL_CALL OStorageFactory::supportsService( const ::rtl::OUString& ServiceName )
295 : : throw ( uno::RuntimeException )
296 : : {
297 [ # # ]: 0 : uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
298 : :
299 [ # # ]: 0 : for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
300 [ # # ][ # # ]: 0 : if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
301 : 0 : return sal_True;
302 : :
303 [ # # ]: 0 : return sal_False;
304 : : }
305 : :
306 : : //-------------------------------------------------------------------------
307 : 0 : uno::Sequence< ::rtl::OUString > SAL_CALL OStorageFactory::getSupportedServiceNames()
308 : : throw ( uno::RuntimeException )
309 : : {
310 : 0 : return impl_staticGetSupportedServiceNames();
311 : : }
312 : :
313 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|