1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zipfileaccess.cxx,v $
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>
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>
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
)
59 , m_pListenersContainer( NULL
)
60 , m_bDisposed( sal_False
)
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() );
74 m_refCount
++; // dispose will use refcounting so the further distruction must be avoided
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 );
91 const sal_Unicode
* pString
= aString
.getStr();
94 if ( *pString
== (sal_Unicode
)'\\' )
98 if ( *pString
== (sal_Unicode
)'\\' )
100 aPattern
[nInd
] += ::rtl::OUString::valueOf( (sal_Unicode
)'\\' );
103 else if ( *pString
== (sal_Unicode
)'*' )
105 aPattern
[nInd
] += ::rtl::OUString::valueOf( (sal_Unicode
)'*' );
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 );
121 aPattern
[nInd
] += ::rtl::OUString::valueOf( *pString
);
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;
139 if ( !aPattern
[0].getLength() )
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() )
156 if ( nEndInd
== nBeginInd
)
159 // check that search does not use nEndInd position
160 sal_Int32 nLastInd
= aString
.lastIndexOf( aPattern
[nCurInd
], nEndInd
- 1 );
162 if ( nLastInd
== -1 )
165 if ( nLastInd
< nBeginInd
)
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() );
186 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
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
);
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(
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() );
249 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
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(),
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() );
276 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
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() );
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
);
304 // ----------------------------------------------------------------
305 sal_Bool SAL_CALL
OZipFileAccess::hasByName( const ::rtl::OUString
& aName
)
306 throw (uno::RuntimeException
)
308 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
311 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
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() );
328 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
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() );
343 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
346 throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
348 return ( m_pZipFile
->GetEntryHash().size() != 0 );
352 // ----------------------------------------------------------------
353 uno::Reference
< io::XInputStream
> SAL_CALL
OZipFileAccess::getStreamByPattern( const ::rtl::OUString
& aPatternString
)
354 throw ( container::NoSuchElementException
,
356 uno::RuntimeException
)
358 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
361 throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
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(),
378 if ( !xEntryStream
.is() )
379 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
384 throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
388 // ----------------------------------------------------------------
389 void SAL_CALL
OZipFileAccess::dispose()
390 throw ( uno::RuntimeException
)
392 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
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
;
411 if ( m_xContentStream
.is() )
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() );
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() );
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");
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 )
489 //-------------------------------------------------------------------------
490 uno::Sequence
< ::rtl::OUString
> SAL_CALL
OZipFileAccess::getSupportedServiceNames()
491 throw ( uno::RuntimeException
)
493 return impl_staticGetSupportedServiceNames();