update dev300-m58
[ooovba.git] / package / source / zippackage / zipfileaccess.cxx
blob26a01c7fd42c4d6fed0a4b262bc0bcae10e0a5f2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zipfileaccess.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_package.hxx"
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #ifndef _COM_SUN_STAR_LANG_INVALIDARGUMENTEXCEPTION_HPP_
35 #include <com/sun/star/lang/IllegalArgumentException.hpp>
36 #endif
37 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
38 #include <com/sun/star/io/XActiveDataSink.hpp>
39 #include <com/sun/star/io/XStream.hpp>
40 #include <com/sun/star/io/XSeekable.hpp>
42 #include <zipfileaccess.hxx>
43 #include <ZipEnumeration.hxx>
44 #include <ZipPackageSink.hxx>
45 #include <EncryptionData.hxx>
47 #include <ucbhelper/content.hxx>
49 #include <memory>
52 using namespace ::com::sun::star;
54 // ----------------------------------------------------------------
55 OZipFileAccess::OZipFileAccess( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
56 : m_aMutexHolder( new SotMutexHolder )
57 , m_xFactory( xFactory )
58 , m_pZipFile( NULL )
59 , m_pListenersContainer( NULL )
60 , m_bDisposed( sal_False )
62 if ( !xFactory.is() )
63 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
66 // ----------------------------------------------------------------
67 OZipFileAccess::~OZipFileAccess()
70 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
71 if ( !m_bDisposed )
73 try {
74 m_refCount++; // dispose will use refcounting so the further distruction must be avoided
75 dispose();
76 } catch( uno::Exception& )
82 // ----------------------------------------------------------------
83 uno::Sequence< ::rtl::OUString > OZipFileAccess::GetPatternsFromString_Impl( const ::rtl::OUString& aString )
85 if ( !aString.getLength() )
86 return uno::Sequence< ::rtl::OUString >();
88 uno::Sequence< ::rtl::OUString > aPattern( 1 );
89 sal_Int32 nInd = 0;
91 const sal_Unicode* pString = aString.getStr();
92 while( *pString )
94 if ( *pString == (sal_Unicode)'\\' )
96 pString++;
98 if ( *pString == (sal_Unicode)'\\' )
100 aPattern[nInd] += ::rtl::OUString::valueOf( (sal_Unicode)'\\' );
101 pString++;
103 else if ( *pString == (sal_Unicode)'*' )
105 aPattern[nInd] += ::rtl::OUString::valueOf( (sal_Unicode)'*' );
106 pString++;
108 else
110 OSL_ENSURE( sal_False, "The backslash is not guarded!\n" );
111 aPattern[nInd] += ::rtl::OUString::valueOf( (sal_Unicode)'\\' );
114 else if ( *pString == (sal_Unicode)'*' )
116 aPattern.realloc( ( ++nInd ) + 1 );
117 pString++;
119 else
121 aPattern[nInd] += ::rtl::OUString::valueOf( *pString );
122 pString++;
126 return aPattern;
129 // ----------------------------------------------------------------
130 sal_Bool OZipFileAccess::StringGoodForPattern_Impl( const ::rtl::OUString& aString,
131 const uno::Sequence< ::rtl::OUString >& aPattern )
133 sal_Int32 nInd = aPattern.getLength() - 1;
134 if ( nInd < 0 )
135 return sal_False;
137 if ( nInd == 0 )
139 if ( !aPattern[0].getLength() )
140 return sal_True;
142 return aString.equals( aPattern[0] );
145 sal_Int32 nBeginInd = aPattern[0].getLength();
146 sal_Int32 nEndInd = aString.getLength() - aPattern[nInd].getLength();
147 if ( nEndInd >= nBeginInd
148 && ( nEndInd == aString.getLength() || aString.copy( nEndInd ).equals( aPattern[nInd] ) )
149 && ( nBeginInd == 0 || aString.copy( 0, nBeginInd ).equals( aPattern[0] ) ) )
151 for ( sal_Int32 nCurInd = aPattern.getLength() - 2; nCurInd > 0; nCurInd-- )
153 if ( !aPattern[nCurInd].getLength() )
154 continue;
156 if ( nEndInd == nBeginInd )
157 return sal_False;
159 // check that search does not use nEndInd position
160 sal_Int32 nLastInd = aString.lastIndexOf( aPattern[nCurInd], nEndInd - 1 );
162 if ( nLastInd == -1 )
163 return sal_False;
165 if ( nLastInd < nBeginInd )
166 return sal_False;
168 nEndInd = nLastInd;
171 return sal_True;
174 return sal_False;
177 // XInitialization
178 // ----------------------------------------------------------------
179 void SAL_CALL OZipFileAccess::initialize( const uno::Sequence< uno::Any >& aArguments )
180 throw ( uno::Exception,
181 uno::RuntimeException )
183 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
185 if ( m_bDisposed )
186 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
188 if ( m_pZipFile )
189 throw uno::Exception( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); // initialization is allowed only one time
191 if ( !aArguments.getLength() )
192 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
194 OSL_ENSURE( aArguments.getLength() == 1, "Too meny arguments are provided, only the first one will be used!\n" );
196 ::rtl::OUString aParamURL;
197 uno::Reference< io::XStream > xStream;
198 uno::Reference< io::XSeekable > xSeekable;
200 if ( ( aArguments[0] >>= aParamURL ) )
202 ::ucbhelper::Content aContent ( aParamURL, uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
203 uno::Reference < io::XActiveDataSink > xSink = new ZipPackageSink;
204 if ( aContent.openStream ( xSink ) )
206 m_xContentStream = xSink->getInputStream();
207 xSeekable = uno::Reference< io::XSeekable >( m_xContentStream, uno::UNO_QUERY );
210 else if ( (aArguments[0] >>= xStream ) )
212 // a writable stream can implement both XStream & XInputStream
213 m_xContentStream = xStream->getInputStream();
214 xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
216 else if ( !( aArguments[0] >>= m_xContentStream ) )
218 xSeekable = uno::Reference< io::XSeekable >( m_xContentStream, uno::UNO_QUERY );
220 else
221 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
223 if ( !m_xContentStream.is() )
224 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
226 if ( !xSeekable.is() )
228 // TODO: after fwkbugfix02 is integrated a helper class can be used to make the stream seekable
229 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
232 // TODO: in case xSeekable is implemented on separated XStream implementation a wrapper is required
233 m_pZipFile = new ZipFile(
234 m_xContentStream,
235 m_xFactory,
236 sal_True );
239 // XNameAccess
240 // ----------------------------------------------------------------
241 uno::Any SAL_CALL OZipFileAccess::getByName( const ::rtl::OUString& aName )
242 throw ( container::NoSuchElementException,
243 lang::WrappedTargetException,
244 uno::RuntimeException )
246 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
248 if ( m_bDisposed )
249 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
251 if ( !m_pZipFile )
252 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
254 EntryHash::iterator aIter = m_pZipFile->GetEntryHash().find( aName );
255 if ( aIter == m_pZipFile->GetEntryHash().end() )
256 throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
258 uno::Reference< io::XInputStream > xEntryStream( m_pZipFile->getDataStream( (*aIter).second,
259 new EncryptionData(),
260 sal_False,
261 m_aMutexHolder ) );
263 if ( !xEntryStream.is() )
264 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
266 return uno::makeAny ( xEntryStream );
269 // ----------------------------------------------------------------
270 uno::Sequence< ::rtl::OUString > SAL_CALL OZipFileAccess::getElementNames()
271 throw ( uno::RuntimeException )
273 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
275 if ( m_bDisposed )
276 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
278 if ( !m_pZipFile )
279 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
281 uno::Sequence< ::rtl::OUString > aNames( m_pZipFile->GetEntryHash().size() );
282 sal_Int32 nLen = 0;
284 for ( EntryHash::iterator aIter = m_pZipFile->GetEntryHash().begin(); aIter != m_pZipFile->GetEntryHash().end(); aIter++ )
286 if ( aNames.getLength() < ++nLen )
288 OSL_ENSURE( sal_False, "The size must be the same!\n" );
289 aNames.realloc( nLen );
292 aNames[nLen-1] = (*aIter).second.sName;
295 if ( aNames.getLength() != nLen )
297 OSL_ENSURE( sal_False, "The size must be the same!\n" );
298 aNames.realloc( nLen );
301 return aNames;
304 // ----------------------------------------------------------------
305 sal_Bool SAL_CALL OZipFileAccess::hasByName( const ::rtl::OUString& aName )
306 throw (uno::RuntimeException)
308 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
310 if ( m_bDisposed )
311 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
313 if ( !m_pZipFile )
314 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
316 EntryHash::iterator aIter = m_pZipFile->GetEntryHash().find( aName );
318 return ( aIter != m_pZipFile->GetEntryHash().end() );
321 // ----------------------------------------------------------------
322 uno::Type SAL_CALL OZipFileAccess::getElementType()
323 throw ( uno::RuntimeException )
325 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
327 if ( m_bDisposed )
328 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
330 if ( !m_pZipFile )
331 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
333 return getCppuType( ( const uno::Reference< io::XInputStream >* )NULL );
336 // ----------------------------------------------------------------
337 sal_Bool SAL_CALL OZipFileAccess::hasElements()
338 throw ( uno::RuntimeException )
340 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
342 if ( m_bDisposed )
343 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
345 if ( !m_pZipFile )
346 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
348 return ( m_pZipFile->GetEntryHash().size() != 0 );
351 // XZipFileAccess
352 // ----------------------------------------------------------------
353 uno::Reference< io::XInputStream > SAL_CALL OZipFileAccess::getStreamByPattern( const ::rtl::OUString& aPatternString )
354 throw ( container::NoSuchElementException,
355 io::IOException,
356 uno::RuntimeException )
358 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
360 if ( m_bDisposed )
361 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
363 if ( !m_pZipFile )
364 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
366 // Code to compare strings by patterns
367 uno::Sequence< ::rtl::OUString > aPattern = GetPatternsFromString_Impl( aPatternString );
369 for ( EntryHash::iterator aIter = m_pZipFile->GetEntryHash().begin(); aIter != m_pZipFile->GetEntryHash().end(); aIter++ )
371 if ( StringGoodForPattern_Impl( (*aIter).second.sName, aPattern ) )
373 uno::Reference< io::XInputStream > xEntryStream( m_pZipFile->getDataStream( (*aIter).second,
374 new EncryptionData(),
375 sal_False,
376 m_aMutexHolder ) );
378 if ( !xEntryStream.is() )
379 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
380 return xEntryStream;
384 throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
387 // XComponent
388 // ----------------------------------------------------------------
389 void SAL_CALL OZipFileAccess::dispose()
390 throw ( uno::RuntimeException )
392 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
394 if ( m_bDisposed )
395 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
397 if ( m_pListenersContainer )
399 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
400 m_pListenersContainer->disposeAndClear( aSource );
401 delete m_pListenersContainer;
402 m_pListenersContainer = NULL;
405 if ( m_pZipFile )
407 delete m_pZipFile;
408 m_pZipFile = NULL;
411 if ( m_xContentStream.is() )
412 try {
413 m_xContentStream->closeInput();
414 } catch( uno::Exception& )
417 m_bDisposed = sal_True;
420 // ----------------------------------------------------------------
421 void SAL_CALL OZipFileAccess::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
422 throw ( uno::RuntimeException )
424 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
426 if ( m_bDisposed )
427 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
429 if ( !m_pListenersContainer )
430 m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutexHolder->GetMutex() );
431 m_pListenersContainer->addInterface( xListener );
434 // ----------------------------------------------------------------
435 void SAL_CALL OZipFileAccess::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
436 throw ( uno::RuntimeException )
438 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
440 if ( m_bDisposed )
441 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
443 if ( m_pListenersContainer )
444 m_pListenersContainer->removeInterface( xListener );
447 //-------------------------------------------------------------------------
448 uno::Sequence< ::rtl::OUString > SAL_CALL OZipFileAccess::impl_staticGetSupportedServiceNames()
450 uno::Sequence< ::rtl::OUString > aRet(2);
451 aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.packages.zip.ZipFileAccess");
452 aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.packages.zip.ZipFileAccess");
453 return aRet;
456 //-------------------------------------------------------------------------
457 ::rtl::OUString SAL_CALL OZipFileAccess::impl_staticGetImplementationName()
459 return ::rtl::OUString::createFromAscii("com.sun.star.comp.package.zip.ZipFileAccess");
462 //-------------------------------------------------------------------------
463 uno::Reference< uno::XInterface > SAL_CALL OZipFileAccess::impl_staticCreateSelfInstance(
464 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
466 return uno::Reference< uno::XInterface >( *new OZipFileAccess( xServiceManager ) );
469 //-------------------------------------------------------------------------
470 ::rtl::OUString SAL_CALL OZipFileAccess::getImplementationName()
471 throw ( uno::RuntimeException )
473 return impl_staticGetImplementationName();
476 //-------------------------------------------------------------------------
477 sal_Bool SAL_CALL OZipFileAccess::supportsService( const ::rtl::OUString& ServiceName )
478 throw ( uno::RuntimeException )
480 uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
482 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
483 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
484 return sal_True;
486 return sal_False;
489 //-------------------------------------------------------------------------
490 uno::Sequence< ::rtl::OUString > SAL_CALL OZipFileAccess::getSupportedServiceNames()
491 throw ( uno::RuntimeException )
493 return impl_staticGetSupportedServiceNames();