summaryrefslogtreecommitdiff
path: root/package/source/zipapi/ZipFile.cxx
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2003-09-11 09:17:20 +0000
committerKurt Zenker <kz@openoffice.org>2003-09-11 09:17:20 +0000
commiteb522d5bdeccd98ee2f215ca0070e0d34dd24a09 (patch)
tree12abaa91d5a47053187df6110e1127f62decace7 /package/source/zipapi/ZipFile.cxx
parent00824e23750cb807c97b1dc4c306979af3913695 (diff)
INTEGRATION: CWS mav05 (1.38.12); FILE MERGED
2003/09/04 13:54:22 mav 1.38.12.4: RESYNC: (1.38-1.39); FILE MERGED 2003/09/04 07:57:15 mav 1.38.12.3: #i15929# WrongPasswordException.idl is in packages now 2003/07/21 14:14:22 mav 1.38.12.2: #i15929# include MediaType in raw stream header, and other fixes 2003/07/18 14:20:51 mav 1.38.12.1: #i15929# support encryption in storages
Diffstat (limited to 'package/source/zipapi/ZipFile.cxx')
-rw-r--r--package/source/zipapi/ZipFile.cxx243
1 files changed, 185 insertions, 58 deletions
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx
index 0bbccada9..34fc9b9c6 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: ZipFile.cxx,v $
*
- * $Revision: 1.39 $
+ * $Revision: 1.40 $
*
- * last change: $Author: vg $ $Date: 2003-07-01 15:11:54 $
+ * last change: $Author: kz $ $Date: 2003-09-11 10:17:20 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -205,12 +205,16 @@ void ZipFile::StaticGetCipher ( const ORef < EncryptionData > & xEncryptionData,
}
}
-void ZipFile::StaticFillHeader ( const ORef < EncryptionData > & rData, sal_Int32 nSize, sal_Int8 * & pHeader )
+void ZipFile::StaticFillHeader ( const ORef < EncryptionData > & rData,
+ sal_Int32 nSize,
+ const ::rtl::OUString& aMediaType,
+ sal_Int8 * & pHeader )
{
// I think it's safe to restrict vector and salt length to 2 bytes !
sal_Int16 nIVLength = static_cast < sal_Int16 > ( rData->aInitVector.getLength() );
sal_Int16 nSaltLength = static_cast < sal_Int16 > ( rData->aSalt.getLength() );
sal_Int16 nDigestLength = static_cast < sal_Int16 > ( rData->aDigest.getLength() );
+ sal_Int16 nMediaTypeLength = static_cast < sal_Int16 > ( aMediaType.getLength() * sizeof( sal_Unicode ) );
// First the header
*(pHeader++) = ( n_ConstHeader >> 0 ) & 0xFF;
@@ -247,6 +251,10 @@ void ZipFile::StaticFillHeader ( const ORef < EncryptionData > & rData, sal_Int3
*(pHeader++) = ( nDigestLength >> 0 ) & 0xFF;
*(pHeader++) = ( nDigestLength >> 8 ) & 0xFF;
+ // Then the mediatype length
+ *(pHeader++) = ( nMediaTypeLength >> 0 ) & 0xFF;
+ *(pHeader++) = ( nMediaTypeLength >> 8 ) & 0xFF;
+
// Then the salt content
memcpy ( pHeader, rData->aSalt.getConstArray(), nSaltLength );
pHeader += nSaltLength;
@@ -258,8 +266,16 @@ void ZipFile::StaticFillHeader ( const ORef < EncryptionData > & rData, sal_Int3
// Then the digest content
memcpy ( pHeader, rData->aDigest.getConstArray(), nDigestLength );
pHeader += nDigestLength;
+
+ // Then the mediatype itself
+ memcpy ( pHeader, aMediaType.getStr(), nMediaTypeLength );
+ pHeader += nMediaTypeLength;
}
-sal_Bool ZipFile::StaticFillData ( ORef < EncryptionData > & rData, sal_Int32 &rSize, Reference < XInputStream > &rStream )
+
+sal_Bool ZipFile::StaticFillData ( ORef < EncryptionData > & rData,
+ sal_Int32 &rSize,
+ ::rtl::OUString& aMediaType,
+ Reference < XInputStream > &rStream )
{
sal_Bool bOk = sal_False;
const sal_Int32 nHeaderSize = n_ConstHeaderSize - 4;
@@ -290,6 +306,9 @@ sal_Bool ZipFile::StaticFillData ( ORef < EncryptionData > & rData, sal_Int32 &r
sal_Int16 nDigestLength = pBuffer[nPos++] & 0xFF;
nDigestLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
+ sal_Int16 nMediaTypeLength = pBuffer[nPos++] & 0xFF;
+ nMediaTypeLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
+
if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) )
{
rData->aSalt.realloc ( nSaltLength );
@@ -302,7 +321,13 @@ sal_Bool ZipFile::StaticFillData ( ORef < EncryptionData > & rData, sal_Int32 &r
{
rData->aDigest.realloc ( nDigestLength );
memcpy ( rData->aDigest.getArray(), aBuffer.getConstArray(), nDigestLength );
- bOk = sal_True;
+
+ if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) )
+ {
+ aMediaType = ::rtl::OUString( (sal_Unicode*)aBuffer.getConstArray(),
+ nMediaTypeLength / sizeof( sal_Unicode ) );
+ bOk = sal_True;
+ }
}
}
}
@@ -311,57 +336,113 @@ sal_Bool ZipFile::StaticFillData ( ORef < EncryptionData > & rData, sal_Int32 &r
return bOk;
}
+Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const Reference< XInputStream >& xStream,
+ const ORef < EncryptionData > &rData )
+ throw ( packages::WrongPasswordException, ZipIOException, RuntimeException )
+{
+ if ( rData.isEmpty() )
+ throw ZipIOException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
+ Reference< XInterface >() );
+
+ if ( !rData->aKey.getLength() )
+ throw packages::WrongPasswordException();
+
+ Reference< XSeekable > xSeek( xStream, UNO_QUERY );
+ if ( !xSeek.is() )
+ throw ZipIOException( OUString::createFromAscii( "The stream must be seekable!\n" ),
+ Reference< XInterface >() );
+
+
+ // if we have a digest, then this file is an encrypted one and we should
+ // check if we can decrypt it or not
+ OSL_ENSURE( rData->aDigest.getLength(), "Can't detect password correctness without digest!\n" );
+ if ( rData->aDigest.getLength() )
+ {
+ sal_Int32 nSize = xSeek->getLength();
+ nSize = nSize > n_ConstDigestLength ? n_ConstDigestLength : nSize;
+
+ // skip header
+ xSeek->seek( n_ConstHeaderSize + rData->aInitVector.getLength() +
+ rData->aSalt.getLength() + rData->aDigest.getLength() );
+
+ // Only want to read enough to verify the digest
+ Sequence < sal_Int8 > aReadBuffer ( nSize );
+
+ xStream->readBytes( aReadBuffer, nSize );
+
+ if ( !StaticHasValidPassword( aReadBuffer, rData ) )
+ throw packages::WrongPasswordException();
+ }
+
+ return new XUnbufferedStream ( xStream, rData );
+}
+
+sal_Bool ZipFile::StaticHasValidPassword( const Sequence< sal_Int8 > &aReadBuffer, const ORef < EncryptionData > &rData )
+{
+ if ( !rData.isValid() || !rData->aKey.getLength() )
+ return sal_False;
+
+ sal_Bool bRet = sal_False;
+ sal_Int32 nSize = aReadBuffer.getLength();
+
+ // make a temporary cipher
+ rtlCipher aCipher;
+ StaticGetCipher ( rData, aCipher );
+
+ Sequence < sal_Int8 > aDecryptBuffer ( nSize );
+ rtlDigest aDigest = rtl_digest_createSHA1();
+ rtlDigestError aDigestResult;
+ Sequence < sal_uInt8 > aDigestSeq ( RTL_DIGEST_LENGTH_SHA1 );
+ rtlCipherError aResult = rtl_cipher_decode ( aCipher,
+ aReadBuffer.getConstArray(),
+ nSize,
+ reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()),
+ nSize);
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+
+ aDigestResult = rtl_digest_updateSHA1 ( aDigest,
+ static_cast < const void * > ( aDecryptBuffer.getConstArray() ), nSize );
+ OSL_ASSERT ( aDigestResult == rtl_Digest_E_None );
+
+ aDigestResult = rtl_digest_getSHA1 ( aDigest, aDigestSeq.getArray(), RTL_DIGEST_LENGTH_SHA1 );
+ OSL_ASSERT ( aDigestResult == rtl_Digest_E_None );
+
+ // If we don't have a digest, then we have to assume that the password is correct
+ if ( rData->aDigest.getLength() != 0 &&
+ ( aDigestSeq.getLength() != rData->aDigest.getLength() ||
+ 0 != rtl_compareMemory ( aDigestSeq.getConstArray(),
+ rData->aDigest.getConstArray(),
+ aDigestSeq.getLength() ) ) )
+ {
+ // We should probably tell the user that the password they entered was wrong
+ }
+ else
+ bRet = sal_True;
+
+ rtl_digest_destroySHA1 ( aDigest );
+
+ return bRet;
+}
+
sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ORef < EncryptionData > &rData )
{
sal_Bool bRet = sal_False;
if ( rData->aKey.getLength() )
{
- // make a temporary cipher
- rtlCipher aCipher;
- StaticGetCipher ( rData, aCipher );
-
xSeek->seek( rEntry.nOffset );
sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize;
// Only want to read enough to verify the digest
nSize = nSize > n_ConstDigestLength ? n_ConstDigestLength : nSize;
- Sequence < sal_Int8 > aReadBuffer ( nSize ), aDecryptBuffer ( nSize );
+ Sequence < sal_Int8 > aReadBuffer ( nSize );
xStream->readBytes( aReadBuffer, nSize );
- rtlDigest aDigest = rtl_digest_createSHA1();
- rtlDigestError aDigestResult;
- Sequence < sal_uInt8 > aDigestSeq ( RTL_DIGEST_LENGTH_SHA1 );
- rtlCipherError aResult = rtl_cipher_decode ( aCipher,
- aReadBuffer.getConstArray(),
- nSize,
- reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()),
- nSize);
- OSL_ASSERT (aResult == rtl_Cipher_E_None);
-
- aDigestResult = rtl_digest_updateSHA1 ( aDigest, static_cast < const void * > ( aDecryptBuffer.getConstArray() ), nSize );
- OSL_ASSERT ( aDigestResult == rtl_Digest_E_None );
-
- aDigestResult = rtl_digest_getSHA1 ( aDigest, aDigestSeq.getArray(), RTL_DIGEST_LENGTH_SHA1 );
- OSL_ASSERT ( aDigestResult == rtl_Digest_E_None );
-
- // If we don't have a digest, then we have to assume that the password is correct
- if ( rData->aDigest.getLength() != 0 &&
- ( aDigestSeq.getLength() != rData->aDigest.getLength() ||
- 0 != rtl_compareMemory ( aDigestSeq.getConstArray(),
- rData->aDigest.getConstArray(),
- aDigestSeq.getLength() ) ) )
- {
- // We should probably tell the user that the password they entered was wrong,
- // but for now we'll just give the upper levels the raw unencrypted data
- }
- else
- bRet = sal_True;
-
- rtl_digest_destroySHA1 ( aDigest );
+ bRet = StaticHasValidPassword( aReadBuffer, rData );
}
return bRet;
}
+
#if 0
Reference < XInputStream > ZipFile::createFileStream(
ZipEntry & rEntry,
@@ -458,10 +539,11 @@ Reference < XInputStream > ZipFile::createMemoryStream(
Reference < XInputStream > ZipFile::createUnbufferedStream(
ZipEntry & rEntry,
const ORef < EncryptionData > &rData,
- sal_Bool bRawStream,
- sal_Bool bIsEncrypted )
+ sal_Int8 nStreamMode,
+ sal_Bool bIsEncrypted,
+ ::rtl::OUString aMediaType )
{
- return new XUnbufferedStream ( rEntry, xStream, rData, bRawStream, bIsEncrypted );
+ return new XUnbufferedStream ( rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType );
}
@@ -500,17 +582,50 @@ Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry,
if ( bIsEncrypted && !rData.isEmpty() && rData->aDigest.getLength() )
bNeedRawStream = !hasValidPassword ( rEntry, rData );
- return createUnbufferedStream ( rEntry, rData, bNeedRawStream, bIsEncrypted );
- /*
- return rEntry.nSize > n_ConstMaxMemoryStreamSize ?
- createFileStream ( rEntry, rData, bNeedRawStream, bIsEncrypted ) :
- createMemoryStream ( rEntry, rData, bNeedRawStream, bIsEncrypted);
- */
- //return createMemoryStream( rEntry, rData, sal_False );
+ return createUnbufferedStream ( rEntry,
+ rData,
+ bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
+ bIsEncrypted );
+}
+
+Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Bool bIsEncrypted )
+ throw ( packages::WrongPasswordException,
+ IOException,
+ ZipException,
+ RuntimeException )
+{
+ if ( rEntry.nOffset <= 0 )
+ readLOC( rEntry );
+ // An exception must be thrown in case stream is encrypted and
+ // there is no key or the key is wrong
+ sal_Bool bNeedRawStream = sal_False;
+ if ( bIsEncrypted )
+ {
+ // in case no digest is provided there is no way
+ // to detect password correctness
+ if ( rData.isEmpty() )
+ throw ZipException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
+ Reference< XInterface >() );
+
+ // if we have a digest, then this file is an encrypted one and we should
+ // check if we can decrypt it or not
+ OSL_ENSURE( rData->aDigest.getLength(), "Can't detect password correctness without digest!\n" );
+ if ( rData->aDigest.getLength() && !hasValidPassword ( rEntry, rData ) )
+ throw packages::WrongPasswordException();
+ }
+ else
+ bNeedRawStream = ( rEntry.nMethod == STORED );
+
+ return createUnbufferedStream ( rEntry,
+ rData,
+ bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
+ bIsEncrypted );
}
-Reference< XInputStream > SAL_CALL ZipFile::getRawStream( ZipEntry& rEntry,
+Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry,
const vos::ORef < EncryptionData > &rData,
sal_Bool bIsEncrypted )
throw(IOException, ZipException, RuntimeException)
@@ -518,13 +633,25 @@ Reference< XInputStream > SAL_CALL ZipFile::getRawStream( ZipEntry& rEntry,
if ( rEntry.nOffset <= 0 )
readLOC( rEntry );
- return createUnbufferedStream ( rEntry, rData, sal_True, bIsEncrypted );
- /*
- return ( rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize > n_ConstMaxMemoryStreamSize ) ?
- createFileStream ( rEntry, rData, sal_True, bIsEncrypted ) :
- createMemoryStream ( rEntry, rData, sal_True, bIsEncrypted );
- */
- //return createMemoryStream( rEntry, rData, sal_True );
+ return createUnbufferedStream ( rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted );
+}
+
+Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream(
+ ZipEntry& rEntry,
+ const vos::ORef < EncryptionData > &rData,
+ const ::rtl::OUString& aMediaType )
+ throw ( packages::NoEncryptionException,
+ IOException,
+ ZipException,
+ RuntimeException )
+{
+ if ( rData.isEmpty() )
+ throw packages::NoEncryptionException();
+
+ if ( rEntry.nOffset <= 0 )
+ readLOC( rEntry );
+
+ return createUnbufferedStream ( rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, sal_True, aMediaType );
}
sal_Bool ZipFile::readLOC( ZipEntry &rEntry )