1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/lang/DisposedException.hpp>
21 #include <com/sun/star/lang/IllegalArgumentException.hpp>
22 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
23 #include <com/sun/star/io/XActiveDataSink.hpp>
24 #include <com/sun/star/io/XStream.hpp>
25 #include <com/sun/star/io/XSeekable.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <cppuhelper/supportsservice.hxx>
28 #include <zipfileaccess.hxx>
29 #include <ZipEnumeration.hxx>
30 #include <ZipPackageSink.hxx>
31 #include <EncryptionData.hxx>
33 #include <ucbhelper/content.hxx>
34 #include <rtl/ref.hxx>
36 using namespace ::com::sun::star
;
38 #if OSL_DEBUG_LEVEL > 0
39 #define THROW_WHERE SAL_WHERE
41 #define THROW_WHERE ""
44 OZipFileAccess::OZipFileAccess( const uno::Reference
< uno::XComponentContext
>& rxContext
)
45 : m_aMutexHolder( new SotMutexHolder
)
46 , m_xContext( rxContext
)
48 , m_pListenersContainer( NULL
)
49 , m_bDisposed( false )
50 , m_bOwnContent( false )
52 if ( !rxContext
.is() )
53 throw uno::RuntimeException(THROW_WHERE
);
56 OZipFileAccess::~OZipFileAccess()
59 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
63 m_refCount
++; // dispose will use refcounting so the further destruction must be avoided
65 } catch( uno::Exception
& )
71 uno::Sequence
< OUString
> OZipFileAccess::GetPatternsFromString_Impl( const OUString
& aString
)
73 if ( aString
.isEmpty() )
74 return uno::Sequence
< OUString
>();
76 uno::Sequence
< OUString
> aPattern( 1 );
79 const sal_Unicode
* pString
= aString
.getStr();
82 if ( *pString
== (sal_Unicode
)'\\' )
86 if ( *pString
== (sal_Unicode
)'\\' )
88 aPattern
[nInd
] += OUString( (sal_Unicode
)'\\' );
91 else if ( *pString
== (sal_Unicode
)'*' )
93 aPattern
[nInd
] += OUString( (sal_Unicode
)'*' );
98 OSL_FAIL( "The backslash is not guarded!\n" );
99 aPattern
[nInd
] += OUString( (sal_Unicode
)'\\' );
102 else if ( *pString
== (sal_Unicode
)'*' )
104 aPattern
.realloc( ( ++nInd
) + 1 );
109 aPattern
[nInd
] += OUString( *pString
);
117 bool OZipFileAccess::StringGoodForPattern_Impl( const OUString
& aString
,
118 const uno::Sequence
< OUString
>& aPattern
)
120 sal_Int32 nInd
= aPattern
.getLength() - 1;
126 if ( aPattern
[0].isEmpty() )
129 return aString
.equals( aPattern
[0] );
132 sal_Int32 nBeginInd
= aPattern
[0].getLength();
133 sal_Int32 nEndInd
= aString
.getLength() - aPattern
[nInd
].getLength();
134 if ( nEndInd
>= nBeginInd
135 && ( nEndInd
== aString
.getLength() || aString
.copy( nEndInd
).equals( aPattern
[nInd
] ) )
136 && ( nBeginInd
== 0 || aString
.copy( 0, nBeginInd
).equals( aPattern
[0] ) ) )
138 for ( sal_Int32 nCurInd
= aPattern
.getLength() - 2; nCurInd
> 0; nCurInd
-- )
140 if ( aPattern
[nCurInd
].isEmpty() )
143 if ( nEndInd
== nBeginInd
)
146 // check that search does not use nEndInd position
147 sal_Int32 nLastInd
= aString
.lastIndexOf( aPattern
[nCurInd
], nEndInd
- 1 );
149 if ( nLastInd
== -1 )
152 if ( nLastInd
< nBeginInd
)
165 void SAL_CALL
OZipFileAccess::initialize( const uno::Sequence
< uno::Any
>& aArguments
)
166 throw ( uno::Exception
,
167 uno::RuntimeException
, std::exception
)
169 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
172 throw lang::DisposedException(THROW_WHERE
);
175 throw uno::RuntimeException(THROW_WHERE
); // initialization is allowed only one time
177 if ( !aArguments
.getLength() )
178 throw lang::IllegalArgumentException(THROW_WHERE
, uno::Reference
< uno::XInterface
>(), 1 );
180 OSL_ENSURE( aArguments
.getLength() == 1, "Too many arguments are provided, only the first one will be used!\n" );
183 uno::Reference
< io::XStream
> xStream
;
184 uno::Reference
< io::XSeekable
> xSeekable
;
186 if ( ( aArguments
[0] >>= aParamURL
) )
188 ::ucbhelper::Content
aContent(
190 uno::Reference
< ::com::sun::star::ucb::XCommandEnvironment
>(),
192 uno::Reference
< io::XActiveDataSink
> xSink
= new ZipPackageSink
;
193 if ( aContent
.openStream ( xSink
) )
195 m_xContentStream
= xSink
->getInputStream();
196 m_bOwnContent
= true;
197 xSeekable
= uno::Reference
< io::XSeekable
>( m_xContentStream
, uno::UNO_QUERY
);
200 else if ( (aArguments
[0] >>= xStream
) )
202 // a writable stream can implement both XStream & XInputStream
203 m_xContentStream
= xStream
->getInputStream();
204 xSeekable
= uno::Reference
< io::XSeekable
>( xStream
, uno::UNO_QUERY
);
206 else if ( aArguments
[0] >>= m_xContentStream
)
208 xSeekable
= uno::Reference
< io::XSeekable
>( m_xContentStream
, uno::UNO_QUERY
);
211 throw lang::IllegalArgumentException(THROW_WHERE
, uno::Reference
< uno::XInterface
>(), 1 );
213 if ( !m_xContentStream
.is() )
214 throw io::IOException(THROW_WHERE
);
216 if ( !xSeekable
.is() )
218 // TODO: after fwkbugfix02 is integrated a helper class can be used to make the stream seekable
219 throw io::IOException(THROW_WHERE
);
222 // TODO: in case xSeekable is implemented on separated XStream implementation a wrapper is required
223 m_pZipFile
= new ZipFile(
230 uno::Any SAL_CALL
OZipFileAccess::getByName( const OUString
& aName
)
231 throw ( container::NoSuchElementException
,
232 lang::WrappedTargetException
,
233 uno::RuntimeException
, std::exception
)
235 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
238 throw lang::DisposedException(THROW_WHERE
);
241 throw uno::RuntimeException(THROW_WHERE
);
243 EntryHash::iterator aIter
= m_pZipFile
->GetEntryHash().find( aName
);
244 if ( aIter
== m_pZipFile
->GetEntryHash().end() )
245 throw container::NoSuchElementException(THROW_WHERE
);
247 uno::Reference
< io::XInputStream
> xEntryStream
;
250 xEntryStream
= m_pZipFile
->getDataStream((*aIter
).second
,
251 ::rtl::Reference
< EncryptionData
>(),
255 catch (const container::NoSuchElementException
&)
259 catch (const lang::WrappedTargetException
&)
263 catch (const uno::RuntimeException
&)
267 catch (const uno::Exception
& e
)
269 throw lang::WrappedTargetException( "This package is unusable!",
270 static_cast < OWeakObject
* > ( this ),
274 if ( !xEntryStream
.is() )
275 throw uno::RuntimeException(THROW_WHERE
);
277 return uno::makeAny ( xEntryStream
);
280 uno::Sequence
< OUString
> SAL_CALL
OZipFileAccess::getElementNames()
281 throw ( uno::RuntimeException
, std::exception
)
283 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
286 throw lang::DisposedException(THROW_WHERE
);
289 throw uno::RuntimeException(THROW_WHERE
);
291 uno::Sequence
< OUString
> aNames( m_pZipFile
->GetEntryHash().size() );
294 for ( EntryHash::iterator aIter
= m_pZipFile
->GetEntryHash().begin(); aIter
!= m_pZipFile
->GetEntryHash().end(); ++aIter
)
296 if ( aNames
.getLength() < ++nLen
)
298 OSL_FAIL( "The size must be the same!\n" );
299 aNames
.realloc( nLen
);
302 aNames
[nLen
-1] = (*aIter
).second
.sPath
;
305 if ( aNames
.getLength() != nLen
)
307 OSL_FAIL( "The size must be the same!\n" );
308 aNames
.realloc( nLen
);
314 sal_Bool SAL_CALL
OZipFileAccess::hasByName( const OUString
& aName
)
315 throw (uno::RuntimeException
, std::exception
)
317 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
320 throw lang::DisposedException(THROW_WHERE
);
323 throw uno::RuntimeException(THROW_WHERE
);
325 EntryHash::iterator aIter
= m_pZipFile
->GetEntryHash().find( aName
);
327 return ( aIter
!= m_pZipFile
->GetEntryHash().end() );
330 uno::Type SAL_CALL
OZipFileAccess::getElementType()
331 throw ( uno::RuntimeException
, std::exception
)
333 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
336 throw lang::DisposedException(THROW_WHERE
);
339 throw uno::RuntimeException(THROW_WHERE
);
341 return cppu::UnoType
<io::XInputStream
>::get();
344 sal_Bool SAL_CALL
OZipFileAccess::hasElements()
345 throw ( uno::RuntimeException
, std::exception
)
347 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
350 throw lang::DisposedException(THROW_WHERE
);
353 throw uno::RuntimeException(THROW_WHERE
);
355 return ( m_pZipFile
->GetEntryHash().size() != 0 );
359 uno::Reference
< io::XInputStream
> SAL_CALL
OZipFileAccess::getStreamByPattern( const OUString
& aPatternString
)
360 throw ( container::NoSuchElementException
,
361 io::IOException
, packages::WrongPasswordException
, packages::zip::ZipException
,
362 uno::RuntimeException
, std::exception
)
364 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
367 throw lang::DisposedException(THROW_WHERE
);
370 throw io::NotConnectedException(THROW_WHERE
);
372 // Code to compare strings by patterns
373 uno::Sequence
< OUString
> aPattern
= GetPatternsFromString_Impl( aPatternString
);
375 for ( EntryHash::iterator aIter
= m_pZipFile
->GetEntryHash().begin(); aIter
!= m_pZipFile
->GetEntryHash().end(); ++aIter
)
377 if ( StringGoodForPattern_Impl( (*aIter
).second
.sPath
, aPattern
) )
379 uno::Reference
< io::XInputStream
> xEntryStream( m_pZipFile
->getDataStream( (*aIter
).second
,
380 ::rtl::Reference
< EncryptionData
>(),
384 if ( !xEntryStream
.is() )
385 throw uno::RuntimeException(THROW_WHERE
);
390 throw container::NoSuchElementException(THROW_WHERE
);
394 void SAL_CALL
OZipFileAccess::dispose()
395 throw ( uno::RuntimeException
, std::exception
)
397 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
400 throw lang::DisposedException(THROW_WHERE
);
402 if ( m_pListenersContainer
)
404 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >(this) );
405 m_pListenersContainer
->disposeAndClear( aSource
);
406 delete m_pListenersContainer
;
407 m_pListenersContainer
= NULL
;
416 if ( m_xContentStream
.is() && m_bOwnContent
)
418 m_xContentStream
->closeInput();
419 } catch( uno::Exception
& )
425 void SAL_CALL
OZipFileAccess::addEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
426 throw ( uno::RuntimeException
, std::exception
)
428 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
431 throw lang::DisposedException(THROW_WHERE
);
433 if ( !m_pListenersContainer
)
434 m_pListenersContainer
= new ::cppu::OInterfaceContainerHelper( m_aMutexHolder
->GetMutex() );
435 m_pListenersContainer
->addInterface( xListener
);
438 void SAL_CALL
OZipFileAccess::removeEventListener( const uno::Reference
< lang::XEventListener
>& xListener
)
439 throw ( uno::RuntimeException
, std::exception
)
441 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
444 throw lang::DisposedException(THROW_WHERE
);
446 if ( m_pListenersContainer
)
447 m_pListenersContainer
->removeInterface( xListener
);
450 uno::Sequence
< OUString
> SAL_CALL
OZipFileAccess::impl_staticGetSupportedServiceNames()
452 uno::Sequence
< OUString
> aRet(2);
453 aRet
[0] = "com.sun.star.packages.zip.ZipFileAccess";
454 aRet
[1] = "com.sun.star.comp.packages.zip.ZipFileAccess";
458 OUString SAL_CALL
OZipFileAccess::impl_staticGetImplementationName()
460 return OUString("com.sun.star.comp.package.zip.ZipFileAccess");
463 uno::Reference
< uno::XInterface
> SAL_CALL
OZipFileAccess::impl_staticCreateSelfInstance(
464 const uno::Reference
< lang::XMultiServiceFactory
>& rxMSF
)
466 return uno::Reference
< uno::XInterface
>( *new OZipFileAccess( comphelper::getComponentContext(rxMSF
) ) );
469 OUString SAL_CALL
OZipFileAccess::getImplementationName()
470 throw ( uno::RuntimeException
, std::exception
)
472 return impl_staticGetImplementationName();
475 sal_Bool SAL_CALL
OZipFileAccess::supportsService( const OUString
& ServiceName
)
476 throw ( uno::RuntimeException
, std::exception
)
478 return cppu::supportsService(this, ServiceName
);
481 uno::Sequence
< OUString
> SAL_CALL
OZipFileAccess::getSupportedServiceNames()
482 throw ( uno::RuntimeException
, std::exception
)
484 return impl_staticGetSupportedServiceNames();
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */