--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/compressionlibs/ziplib/test/oldezlib/zip/ZipFile.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,909 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// $Revision: 1.1 $
+//
+//
+
+
+
+#include <caf/content.h>
+#include <caf/data.h>
+#include "oldzipfile.h"
+
+using namespace TOLDEZIP;
+// ====================================================================
+// CZipFile public exported interface
+// ====================================================================
+
+/**
+Creates a new CZipFile object using the supplied file server session and
+a valid file handle. The caller must have sufficient sufficient rights to
+access the content of the zipfile, if encrypted/protected.
+
+@param aFs File server session used for opening the zipfile
+@param aFile File handle to be used for accessing the zipfile
+@return CZipFile object associated with the zipfile if it succeeded
+@leave KZipArchiveError If file cannot be accessed(invalid handle, corrupt file header, etc.)
+@leave KZipFileIOError If file cannot be read
+@leave KCentralDirectoryTrailerNotFound If zip file header doesn't contain information about files inside the archive
+@leave KCentralDirectoryTrailerInvalid If the information about files inside the archive is corrupt
+@leave KMultiDiskArchivesNotSupported If zipfile is a multi disk archive
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C CZipFile* CZipFile::NewL(RFs& aFs, RFile& aFile)
+ {
+ TFileName file;
+ aFile.Name(file);
+ CZipFile* zipFile = new(ELeave) CZipFile(aFs, file);
+ CleanupStack::PushL(zipFile);
+ zipFile->ConstructL(aFile);
+ CleanupStack::Pop(zipFile);
+ return zipFile;
+ }
+
+/**
+Creates a new CZipFile object using the supplied file server session and
+file name. The caller must have sufficient capabilities to access the directory.
+The caller must also have sufficient rights to access the content of the
+zipfile, if encrypted/protected.
+
+@param aFs File server session used for opening the zipfile
+@param aFileName Name of the zipfile
+@return CZipFile object associated with the zipfile if it succeeded
+@leave KZipArchiveError If file cannot be accessed(invalid handle, corrupt file header, etc.)
+@leave KZipFileIOError If file cannot be read
+@leave KCentralDirectoryTrailerNotFound If zip file header doesn't contain information about files inside the archive
+@leave KCentralDirectoryTrailerInvalid If the information about files inside the archive is corrupt
+@leave KMultiDiskArchivesNotSupported If zipfile is a multi disk archive.
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C CZipFile* CZipFile::NewL(RFs& aFs, const TDesC& aFileName)
+ {
+ CZipFile* zipFile = new(ELeave) CZipFile(aFs, aFileName);
+ CleanupStack::PushL(zipFile);
+ zipFile->ConstructL(aFileName);
+ CleanupStack::Pop(zipFile);
+ return zipFile;
+ }
+
+/**
+Destructor
+*/
+EXPORT_C CZipFile::~CZipFile()
+ {
+ DeleteMemberPointers();
+ }
+
+/**
+@deprecated in 7.0
+*/
+EXPORT_C CZipFile::CZipFile(RFs& aFs, const TDesC& aFileName)
+ : iFileName(aFileName), iFs(aFs)
+ {
+ }
+
+/**
+@deprecated in 7.0
+*/
+EXPORT_C TInt CZipFile::OpenL(void)
+ {
+ if (!iMemberPointers)
+ {
+ ConstructL(iFileName);
+ }
+ return KErrNone;
+ }
+
+/**
+@deprecated in 7.0
+*/
+EXPORT_C void CZipFile::Close(void)
+ {
+ DeleteMemberPointers();
+ }
+
+/**
+Second phase of construction. Used by Rfile using NewL overload.
+
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C void CZipFile::ConstructL(RFile& aFile)
+ {
+ // Use the full name derived from the session path
+ ContentAccess::CContent* content =
+ ContentAccess::CContent::NewL(aFile);
+ CleanupStack::PushL(content);
+ iData = content->OpenContentL(ContentAccess::EPeek);
+
+ // Parent content object no longer needed because we only need data
+ CleanupStack::PopAndDestroy(content);
+
+ // Seek to the end
+ TInt length = 0;
+ User::LeaveIfError(iData->Seek(ESeekEnd, length));
+ iFileLength = length;
+
+ TInt status;
+ TUint32 offset;
+
+ if ((status = FindCentralDirectoryTrailer(offset)) != KErrNone)
+ {
+ DeleteMemberPointers();
+ User::Leave(status);
+ }
+
+ if ((status = ReadCentralDirectoryTrailer(offset, iTrailer)) != KErrNone)
+ {
+ DeleteMemberPointers();
+ User::Leave(status);
+ }
+
+ if (iTrailer.iStartDiskNumber != iTrailer.iDiskNumber)
+ {
+ DeleteMemberPointers();
+ User::Leave(KMultiDiskArchivesNotSupported);
+ }
+
+ if ((iTrailer.iOffset + iTrailer.iSize) > iFileLength)
+ {
+ DeleteMemberPointers();
+ User::Leave(KCentralDirectoryTrailerInvalid);
+ }
+
+ if (LoadMemberPointersL() != KErrNone)
+ {
+ User::Leave(KZipFileIOError);
+ }
+ }
+
+/**
+Second phase of construction. Used by filename using NewL overload
+
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C void CZipFile::ConstructL(const TDesC& aFileName)
+ {
+ TInt status;
+ TUint32 offset;
+
+ TRAP(status, OpenFileL(aFileName));
+ if (status)
+ {
+ User::Leave(KZipArchiveError);
+ }
+ else
+ if ((status = FindCentralDirectoryTrailer(offset)) != KErrNone)
+ {
+ DeleteMemberPointers();
+ User::Leave(status);
+ }
+ else
+ if ((status = ReadCentralDirectoryTrailer(offset, iTrailer)) != KErrNone)
+ {
+ DeleteMemberPointers();
+ User::Leave(status);
+ }
+ else
+ if (iTrailer.iStartDiskNumber != iTrailer.iDiskNumber)
+ {
+ DeleteMemberPointers();
+ User::Leave(KMultiDiskArchivesNotSupported);
+ }
+ else
+ if ((iTrailer.iOffset > iFileLength) ||
+ ((iTrailer.iOffset + iTrailer.iSize) > iFileLength))
+ {
+ DeleteMemberPointers();
+ User::Leave(KCentralDirectoryTrailerInvalid);
+ }
+ else
+ if (LoadMemberPointersL() != KErrNone)
+ {
+ User::Leave(KZipFileIOError);
+ }
+ }
+
+/**
+Gets the size of the compressed data contained in the zip file in bytes
+Each CZipFile object has a compressed and uncompressed size. This method will
+return the compressed size of a zip file.
+
+@param aSize On return, the size of the compressed data in bytes
+@return KErrNotReady If object hasn't been properly constructed
+@return KErrCASizeNotDetermined If size could not be determined
+@return ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C TInt CZipFile::Size(TInt& aSize) const
+{
+ TInt err = KErrNotReady;
+ if (iData)
+ {
+ TRAP(err, iData->DataSizeL(aSize));
+ }
+ return err;
+}
+
+/**
+Constructs and returns a CZipFileMember object which is used to access
+information about a compressed file contained in the CZipFile archive.
+The name of the file to be searched for in the zipfile is case-sensitive.
+
+@param aName The name of the file to be searched in the zipfile
+@return the pointer to CZipFileMember object
+@return NULL if the file doesn't exist in the zipfile
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C CZipFileMember* CZipFile::MemberL(const TDesC& aName)
+ {
+ TLocalHeader header;
+ const TMemberPointer* memberPointer;
+ HBufC* localName = aName.AllocL();
+ TInt loop = 0;
+ while (loop < localName->Length())
+ {
+ if ((*localName)[loop] == '\\')
+ {
+ (localName->Des())[loop] = '/';
+ }
+ loop++;
+ }
+
+ memberPointer = FindMemberPointer(*localName, EFalse);
+ if (memberPointer == NULL)
+ {
+ delete localName;
+ return NULL;
+ }
+ else
+ if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
+ {
+ delete localName;
+ return NULL;
+ }
+ else
+ {
+ CleanupStack::PushL(localName);
+ CZipFileMember* thisMember = MakeMemberL(*memberPointer, header);
+ CleanupStack::PopAndDestroy(); // localName
+ return thisMember;
+ }
+ }
+
+/**
+Constructs and returns a CZipFileMember object which is used to access
+information about a compressed file contained in the CZipFile archive.
+The name of the file to be searched for in the zipfile is case-insensitive.
+
+@param aName The name of the file to be searched in the zipfile
+@return A pointer to a member object of zip file
+@return NULL If the file doesn't exist in the zipfile
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C CZipFileMember* CZipFile::CaseInsensitiveMemberL(const TDesC& aName)
+{
+ TLocalHeader header;
+ const TMemberPointer* memberPointer;
+ HBufC* localName = aName.AllocL();
+ TInt loop=0;
+ while (loop < localName->Length())
+ {
+ if ((*localName)[loop] == '\\')
+ {
+ (localName->Des())[loop] = '/';
+ }
+ loop++;
+ }
+
+ memberPointer = FindMemberPointer(*localName, ETrue);
+ if (memberPointer == NULL)
+ {
+ delete localName;
+ return NULL;
+ }
+ else
+ if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
+ {
+ delete localName;
+ return NULL;
+ }
+ else
+ {
+ CleanupStack::PushL(localName);
+ CZipFileMember* thisMember = MakeMemberL(*memberPointer, header);
+ CleanupStack::PopAndDestroy();
+ return thisMember;
+ }
+
+ }
+
+/**
+Constructs and returns a CZipFileMember object which is used to access
+information about a compressed file contained in the CZipFile archive.
+An exact match for the filename is searched for first. If a match is not found,
+a case-insensitive search is performed. If both filenames exist in the archive,
+the case-sensitive match will be returned.
+
+@param aName The name of the file to be searched in the zipfile
+@return A pointer to a member object of zip file
+@return NULL If the file doesn't exist in the zipfile
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C CZipFileMember* CZipFile::CaseSensitiveOrCaseInsensitiveMemberL(const TDesC& aName)
+{
+ CZipFileMember* member;
+ member = MemberL(aName);
+ if (member)
+ {
+ return member;
+ }
+ else
+ {
+ return CaseInsensitiveMemberL(aName);
+ }
+}
+
+/**
+Creates and returns the input stream for a file in the archive. Only files
+compressed with Stored or Deflated compression methods are supported.
+
+@param aMember The compressed file in the archive
+@param aStream On return, the stream to be used for reading the contents of the compressed file. The caller owns this object and is responsible for deleting it.
+@return KErrNone if successful
+@return KCompressionMethodNotSupported if compression format unsupported
+@return ... Any one of the system-wide error codes for other errors.
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C TInt CZipFile::GetInputStreamL(const CZipFileMember* aMember, RZipFileMemberReaderStream*& aStream)
+ {
+ TUint32 compressionMethod;
+
+ compressionMethod = aMember->iCompressionMethod;
+ if ((compressionMethod != EStored) && (compressionMethod != EDeflated))
+ {
+ return KCompressionMethodNotSupported;
+ }
+ aStream = RZipFileMemberReaderStream::NewL(
+ *this,
+ aMember->iDataOffset,
+ aMember->iCompressedSize,
+ aMember->iUncompressedSize,
+ compressionMethod);
+ return KErrNone;
+ }
+
+
+
+/**
+Gets the iterator used for iterating through the files contained in the ZIP
+file. It is the caller's responsibility to release the iterator when finsihed.
+
+@return Pointer to a newly allocated CZipFileMemberIterator object
+@leave ... Any one of the system-wide error codes for other errors.
+*/
+EXPORT_C CZipFileMemberIterator* CZipFile::GetMembersL()
+ {
+ return new (ELeave) CZipFileMemberIterator(this);
+ }
+
+
+
+// Implementation
+
+/*
+ * Find the 'end of central directory record'. This is at the 'end' of
+ * the file, but since it is not a fixed length structure, we have to
+ * hunt for it.
+ *
+ * We try assuming that the variable length section of the record is
+ * empty, which usually appears to be the case.
+ *
+ * If this does not work we resort to 'walking backwards' through the
+ * file looking for the signature bytes.
+ *
+ */
+
+TInt CZipFile::FindCentralDirectoryTrailer(TUint32& offset)
+{
+ TBuf8<KSignatureLength> signature;
+
+ if (iFileLength <= KCentralDirectoryTrailerFixedLength)
+ {
+ return KZipArchiveError;
+ }
+ // Try the obvious place first.Assuming that the comment (variable
+ // length section) is empty,try to find the signature at the offset.
+ offset = iFileLength - KCentralDirectoryTrailerFixedLength;
+ if (Seek(offset) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ TInt err = iData->Read(signature);
+
+ if ( err != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+
+ if ((signature[0] == 0x50) &&
+ (signature[1] == 0x4b) &&
+ (signature[2] == 0x05) &&
+ (signature[3] == 0x06))
+ {
+ return KErrNone;
+ }
+ else
+ {
+ // There must be some comments, hence the central directory
+ // record > 22 bytes.
+ // This is a slow but fairly obvious way of searching
+ // backwards through the file starting from the offset.
+ TUint EndOfTrailerSearch = 0; //Upto beginning of File
+
+ if(iFileLength > KMaxTrailerSearchLength+KCentralDirectoryTrailerFixedLength)
+ EndOfTrailerSearch = offset - KMaxTrailerSearchLength; //Upto Last 64K+22 bytes
+
+ while (offset >= EndOfTrailerSearch)
+ {
+ if (Seek(offset) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ if (iData->Read(signature) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ if ((signature[0] == 0x50) &&
+ (signature[1] == 0x4b) &&
+ (signature[2] == 0x05) &&
+ (signature[3] == 0x06))
+ {
+ return KErrNone;
+ }
+ --offset;
+ }
+ return KCentralDirectoryTrailerNotFound;
+ }
+ }
+
+TInt CZipFile::ReadCentralDirectoryTrailer(TUint32 offset, struct TCentralDirectoryTrailer& r )
+{
+ // Skip the signature
+ if (Seek(offset + KSignatureLength) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ if (Read(r.iDiskNumber) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ if (Read(r.iStartDiskNumber)!= KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ if (Read(r.iLocalEntryCount) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ if (Read(r.iTotalEntryCount) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ if (Read(r.iSize) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ if (Read(r.iOffset) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ else
+ {
+ return KErrNone;
+ }
+}
+
+TInt CZipFile::LoadMemberPointersL(void)
+ {
+ TCentralDirectoryHeader header;
+ TUint32 i;
+ TUint32 memberPointerCount;
+
+ if (Seek(iTrailer.iOffset) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ memberPointerCount = iTrailer.iTotalEntryCount;
+ iMemberPointers = new (ELeave) TMemberPointer[memberPointerCount];
+ for (i = 0; i < memberPointerCount; i++)
+ {
+ iMemberPointers[i].iName = NULL;
+ }
+ CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewL();
+ CleanupStack::PushL(converter);
+ TInt converterState = CCnvCharacterSetConverter::KStateDefault;
+ for (i = 0; i < memberPointerCount; i++)
+ {
+ if (ReadCentralDirectoryHeaderL(header, iMemberPointers[i], converter, converterState) != KErrNone)
+ {
+ return KZipFileError;
+ }
+ }
+ CleanupStack::PopAndDestroy(converter);
+ return KErrNone;
+ }
+
+LOCAL_C void ConvertFileNameToUnicodeL(
+ TDes16& aUnicode,
+ const TDesC8& aForeign,
+ const TUint16& aMadeBy,
+ CCnvCharacterSetConverter* aConverter,
+ TInt aConverterState,
+ RFs aFs)
+// Have to decide whether filename encoding is CP850 or CP1252. According to tec support
+// at WinZip, if 'madeby' is set to DOS(0) then the encoding is CP850 and if it's set to
+// NTFS (11) then it's CP1252. However, if the MS Compressed Folders program was used
+// to zip, then madeby is always set to NTFS and the encoding is always CP850 - the exact
+// opposite. Because of this confusion, I have written a very basic decision algorithm
+// based on the premise that filenames are likely to use alphabet-style extended
+// characters (rather than box edges or punctuation etc.)
+ {
+ TInt len = aForeign.Length();
+ TInt ANSIpoints = 0;
+ TInt OEMpoints = 0;
+ for (TInt i=0; i<len; i++)
+ {
+ if (aForeign[i] >= 128 && aForeign[i] <= 165)
+ OEMpoints ++;
+ if (aForeign[i] >= 192 && aForeign[i] <= 255)
+ ANSIpoints ++;
+ }
+ if (ANSIpoints == OEMpoints)
+ {
+ if (aMadeBy>>8) //only interested in the upper byte
+ ANSIpoints ++;
+ else
+ OEMpoints ++;
+ }
+ TInt unconvertibleChars = 0;
+
+ CCnvCharacterSetConverter::TAvailability availabilty = CCnvCharacterSetConverter::EAvailable;
+ if (ANSIpoints > OEMpoints)
+ {
+ // It's probably ANSI (CP1252)
+ availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252,aFs);
+ aConverter->ConvertToUnicode(aUnicode, aForeign, aConverterState, unconvertibleChars);
+
+ }
+ if (OEMpoints > ANSIpoints || unconvertibleChars)
+ {
+ // It's definitely OEM (CP850)
+ availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCP850,aFs);
+ if(availabilty != CCnvCharacterSetConverter::EAvailable )
+ {
+ //if cp850 plugin is not available, use cp1252
+ aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252, aFs);
+ }
+
+ aConverter->ConvertToUnicode(aUnicode, aForeign, aConverterState);
+
+ }
+ }
+
+TInt CZipFile::ReadCentralDirectoryHeaderL(
+ TCentralDirectoryHeader& aHeader,
+ TMemberPointer& aMemberPointer,
+ CCnvCharacterSetConverter* aConverter,
+ TInt aConverterState)
+/*
+As this function might be called many times and the request will
+eventually be translated to calls to server to read the data,
+so performance is the major issue. Try to minimize calls to server.
+Read data in a chunk rather than member-by-member.
+*/
+ {
+ TByte tmpHeader[KCentralDirectoryHeaderFixedLength];
+
+ if (Read(tmpHeader,KCentralDirectoryHeaderFixedLength) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+
+ Mem::Copy(&aHeader.iSignature, &tmpHeader[0], 4);
+
+ if (aHeader.iSignature != KCentralDirectoryHeaderSignature)
+ {
+ return KZipFileIOError;
+ }
+
+ Mem::Copy(&aHeader.iMadeBy, &tmpHeader[4], 2);
+ Mem::Copy(&aHeader.iRequired, &tmpHeader[6], 2);
+ Mem::Copy(&aHeader.iFlags, &tmpHeader[8], 2);
+ Mem::Copy(&aHeader.iCompressionMethod, &tmpHeader[10], 2);
+ Mem::Copy(&aHeader.iLastModifiedFileTime, &tmpHeader[12], 2);
+ Mem::Copy(&aHeader.iLastModifiedFileDate, &tmpHeader[14], 2);
+ Mem::Copy(&aHeader.iCRC32, &tmpHeader[16], 4);
+ Mem::Copy(&aHeader.iCompressedSize, &tmpHeader[20], 4);
+ Mem::Copy(&aHeader.iUncompressedSize, &tmpHeader[24], 4);
+ Mem::Copy(&aHeader.iFileNameLength, &tmpHeader[28], 2);
+ Mem::Copy(&aHeader.iExtraFieldLength, &tmpHeader[30], 2);
+ Mem::Copy(&aHeader.iFileCommentLength, &tmpHeader[32], 2);
+ Mem::Copy(&aHeader.iDiskNumberStart, &tmpHeader[34], 2);
+ Mem::Copy(&aHeader.iInternalFileAttributes, &tmpHeader[36], 2);
+ Mem::Copy(&aHeader.iExternalFileAttributes, &tmpHeader[38], 4);
+ Mem::Copy(&aHeader.iLocalHeaderOffset, &tmpHeader[42], 4);
+
+ aMemberPointer.iCRC32 = aHeader.iCRC32;
+ aMemberPointer.iCompressedSize = aHeader.iCompressedSize;
+ aMemberPointer.iUncompressedSize = aHeader.iUncompressedSize;
+ aMemberPointer.iLocalHeaderOffset = aHeader.iLocalHeaderOffset;
+ aMemberPointer.iName = new(ELeave) TFileName;
+
+ TBuf8<KMaxFileName> input;
+ if (iData->Read(input, aHeader.iFileNameLength) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ ConvertFileNameToUnicodeL(*aMemberPointer.iName, input, aHeader.iMadeBy, aConverter, aConverterState, iFs);
+
+ // Ignore the remaining fields
+ TInt pos;
+
+ pos = aHeader.iExtraFieldLength;
+ if (pos != 0)
+ {
+ // Don't pass aHeader.iExtraFieldLength in place of pos
+ // as the below function will update the content of that variable.
+ // In this case, the function is used to ignore the data
+ // by just moving the current file pointer location.
+ if (iData->Seek(ESeekCurrent, pos) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ }
+
+ pos = aHeader.iFileCommentLength;
+ if (pos != 0)
+ {
+ // Don't pass aHeader.iFileCommentLength in place of pos
+ // as the below function will update the content of that variable.
+ // In this case, the function is used to ignore the data
+ // by just moving the current file pointer location.
+ if (iData->Seek(ESeekCurrent, pos) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ }
+
+ return KErrNone;
+}
+
+TInt CZipFile::ReadLocalHeader(TUint32 aOffset, TLocalHeader& aHeader)
+/*
+As this function might be called many times and the request will
+eventually be translated to calls to server to read the data,
+so performance is the major issue. Try to minimize calls to server.
+Read data in a chunk rather than member-by-member.
+*/
+ {
+ TByte tmpHeader[KLocalHeaderFixedLength];
+
+ if (Seek(aOffset) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ if (Read(tmpHeader,KLocalHeaderFixedLength) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ Mem::Copy(&aHeader.iSignature, &tmpHeader[0], 4);
+
+ if (aHeader.iSignature != KLocalHeaderSignature)
+ {
+ return KLocalHeaderSignatureInvalid;
+ }
+
+ Mem::Copy(&aHeader.iVersionNeeded, &tmpHeader[4], 2);
+ Mem::Copy(&aHeader.iFlags, &tmpHeader[6], 2);
+ Mem::Copy(&aHeader.iCompressionMethod, &tmpHeader[8], 2);
+ Mem::Copy(&aHeader.iLastModifiedFileTime, &tmpHeader[10], 2);
+ Mem::Copy(&aHeader.iLastModifiedFileDate, &tmpHeader[12], 2);
+ Mem::Copy(&aHeader.iCRC32, &tmpHeader[14], 4);
+ Mem::Copy(&aHeader.iCompressedSize, &tmpHeader[18], 4);
+ Mem::Copy(&aHeader.iUncompressedSize, &tmpHeader[22], 4);
+ Mem::Copy(&aHeader.iFileNameLength, &tmpHeader[26], 2);
+ Mem::Copy(&aHeader.iExtraFieldLength, &tmpHeader[28], 2);
+
+ return KErrNone;
+ }
+
+const CZipFile::TMemberPointer* CZipFile::FindMemberPointer(const TDesC& aName, TBool aCaseInsensitive)
+ {
+ for (TUint32 i = 0; i < iTrailer.iTotalEntryCount; i++)
+ {
+ if (aCaseInsensitive && (!aName.CompareF(*iMemberPointers[i].iName)))
+ {
+ return iMemberPointers + i;
+ }
+ else if (aName == *iMemberPointers[i].iName)
+ {
+ return iMemberPointers + i;
+ }
+ }
+ return NULL;
+ }
+
+RZipFileMemberReaderStream* CZipFile::MakeInputStreamL(
+ TUint32 aDataOffset,
+ TUint32 aCompressedSize,
+ TUint32 aUncompressedSize,
+ TUint32 aCompressionMethod)
+ {
+ return RZipFileMemberReaderStream::NewL(
+ *this,
+ aDataOffset,
+ aCompressedSize,
+ aUncompressedSize,
+ aCompressionMethod);
+ }
+
+CZipFileMember* CZipFile::MakeMemberL(TInt aMemberIndex)
+ {
+ TLocalHeader header;
+ TMemberPointer* memberPointer;
+
+ if (aMemberIndex >= iTrailer.iTotalEntryCount)
+ {
+ return NULL;
+ }
+ memberPointer = iMemberPointers + aMemberIndex;
+ if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
+ {
+ return NULL;
+ }
+ else
+ {
+ return MakeMemberL(*memberPointer, header);
+ }
+ }
+
+CZipFileMember* CZipFile::MakeMemberL(
+ const TMemberPointer& aMemberPointer,
+ const TLocalHeader& aHeader)
+ {
+ CZipFileMember* member;
+
+ member = new (ELeave) CZipFileMember;
+ CleanupStack::PushL(member);
+ member->iCRC32 = aMemberPointer.iCRC32;
+ member->iCompressedSize = aMemberPointer.iCompressedSize;
+ member->iCompressionMethod = aHeader.iCompressionMethod;
+ member->iName = new (ELeave) TFileName(*aMemberPointer.iName);
+ TInt loop=0;
+ while (loop < member->iName->Length())
+ {
+ if ((*member->iName)[loop] == '/')
+ {
+ (*member->iName)[loop] = '\\';
+ }
+ loop++;
+ }
+ member->iUncompressedSize = aMemberPointer.iUncompressedSize;
+ member->iDataOffset = aMemberPointer.iLocalHeaderOffset +
+ KLocalHeaderFixedLength +
+ aHeader.iFileNameLength +
+ aHeader.iExtraFieldLength;
+ CleanupStack::Pop();
+ return member;
+ }
+
+void CZipFile::DeleteMemberPointers()
+ {
+ if (iMemberPointers)
+ {
+ for (TUint32 i = 0; i < iTrailer.iTotalEntryCount; i++)
+ {
+ delete iMemberPointers[i].iName;
+ }
+ delete[] iMemberPointers;
+ iMemberPointers = 0;
+ }
+
+ delete iData;
+ iData = NULL;
+ return;
+ }
+
+void CZipFile::OpenFileL(const TDesC& aFileName)
+ {
+ // We need to look at the session path of the filesystem passed
+ // in to derive the fullpath of the file to open
+ HBufC* sessionPath = HBufC::NewLC(KMaxFileName);
+ TPtr ptr(sessionPath->Des());
+ User::LeaveIfError(iFs.SessionPath(ptr));
+ TParse parse;
+ User::LeaveIfError(parse.Set(aFileName, sessionPath, NULL));
+
+ // Use the full name derived from the session path
+ ContentAccess::CContent* content =
+ ContentAccess::CContent::NewL(parse.FullName());
+ CleanupStack::PushL(content);
+ iData = content->OpenContentL(ContentAccess::EPeek);
+
+ // Parent content object no longer needed because we only need data
+ CleanupStack::PopAndDestroy(content);
+
+ // Seek to the end
+ TInt length = 0;
+ User::LeaveIfError(iData->Seek(ESeekEnd, length));
+ iFileLength = length;
+ CleanupStack::PopAndDestroy(sessionPath);
+ }
+
+TInt CZipFile::Read(TUint16& aUs)
+ {
+ TPckgBuf<TUint16> temp(aUs);
+
+ if (iData->Read(temp) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+
+ aUs=temp();
+ return KErrNone;
+ }
+
+TInt CZipFile::Read(TUint32& aUl)
+ {
+ TPckgBuf<TUint32> temp;
+
+ if (iData->Read(temp) != KErrNone)
+ {
+ return KZipFileIOError;
+ }
+ aUl=temp();
+ return KErrNone;
+ }
+
+TInt CZipFile::Read(TByte* aBytes, TUint32 aLength)
+
+ {
+ TPtr8 ptr(aBytes, aLength);
+ if(iData->Read(ptr, aLength))
+ {
+ return KZipFileIOError;
+ }
+ else
+ {
+ return KErrNone;
+ }
+ }
+
+TInt CZipFile::Seek(TInt aOffset)
+ {
+ if (iData->Seek(ESeekStart, aOffset) < 0)
+ {
+ return KZipFileIOError;
+ }
+ else
+ {
+ return KErrNone;
+ }
+ }
+