diff -r 000000000000 -r e4d67989cc36 compressionlibs/ziplib/src/ezip/zipfile.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compressionlibs/ziplib/src/ezip/zipfile.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,907 @@ +// 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: +// + + +#include +#include +#include + +// ==================================================================== +// 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 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 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; + } + +static 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= 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 + availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252, aFs); + if(availabilty != CCnvCharacterSetConverter::EAvailable) + User::Leave (KErrNotSupported); + } + + 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 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 temp(aUs); + + if (iData->Read(temp) != KErrNone) + { + return KZipFileIOError; + } + + aUs=temp(); + return KErrNone; + } + +TInt CZipFile::Read(TUint32& aUl) + { + TPckgBuf 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; + } + } +