os/ossrv/compressionlibs/ziplib/test/oldezlib/zip/ZipFile.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // $Revision: 1.1 $
    15 // 
    16 //
    17 
    18 
    19 
    20 #include <caf/content.h>
    21 #include <caf/data.h>
    22 #include "oldzipfile.h"
    23 
    24 using namespace TOLDEZIP;
    25 // ====================================================================
    26 // CZipFile public exported interface
    27 // ====================================================================
    28 
    29 /**
    30 Creates a new CZipFile object using the supplied file server session and 
    31 a valid file handle. The caller must have sufficient sufficient rights to 
    32 access the content of the zipfile, if encrypted/protected.
    33 
    34 @param aFs File server session used for opening the zipfile
    35 @param aFile File handle to be used for accessing the zipfile
    36 @return CZipFile object associated with the zipfile if it succeeded
    37 @leave KZipArchiveError If file cannot be accessed(invalid handle, corrupt file header, etc.)
    38 @leave KZipFileIOError If file cannot be read
    39 @leave KCentralDirectoryTrailerNotFound If zip file header doesn't contain information about files inside the archive
    40 @leave KCentralDirectoryTrailerInvalid If the information about files inside the archive is corrupt
    41 @leave KMultiDiskArchivesNotSupported If zipfile is a multi disk archive
    42 @leave ... Any one of the system-wide error codes for other errors.
    43 */
    44 EXPORT_C CZipFile* CZipFile::NewL(RFs& aFs, RFile& aFile)
    45 	{
    46 	TFileName file;
    47 	aFile.Name(file);
    48 	CZipFile* zipFile = new(ELeave) CZipFile(aFs, file);
    49 	CleanupStack::PushL(zipFile);
    50 	zipFile->ConstructL(aFile);
    51 	CleanupStack::Pop(zipFile);
    52 	return zipFile;
    53 	}
    54 	
    55 /**
    56 Creates a new CZipFile object using the supplied file server session and 
    57 file name. The caller must have sufficient capabilities to access the directory. 
    58 The caller must also have sufficient rights to access the content of the 
    59 zipfile, if encrypted/protected.
    60 
    61 @param aFs File server session used for opening the zipfile
    62 @param aFileName Name of the zipfile 
    63 @return CZipFile object associated with the zipfile if it succeeded
    64 @leave KZipArchiveError If file cannot be accessed(invalid handle, corrupt file header, etc.)
    65 @leave KZipFileIOError If file cannot be read
    66 @leave KCentralDirectoryTrailerNotFound If zip file header doesn't contain information about files inside the archive
    67 @leave KCentralDirectoryTrailerInvalid If the information about files inside the archive is corrupt
    68 @leave KMultiDiskArchivesNotSupported If zipfile is a multi disk archive. 
    69 @leave ... Any one of the system-wide error codes for other errors.
    70 */
    71 EXPORT_C CZipFile* CZipFile::NewL(RFs& aFs, const TDesC& aFileName)
    72 	{
    73 	CZipFile* zipFile = new(ELeave) CZipFile(aFs, aFileName);
    74 	CleanupStack::PushL(zipFile);
    75 	zipFile->ConstructL(aFileName);
    76 	CleanupStack::Pop(zipFile);
    77 	return zipFile;
    78 	}
    79 
    80 /**
    81 Destructor
    82 */
    83 EXPORT_C CZipFile::~CZipFile()
    84 	{
    85 	DeleteMemberPointers();
    86 	}
    87 
    88 /** 
    89 @deprecated in 7.0 
    90 */
    91 EXPORT_C CZipFile::CZipFile(RFs& aFs, const TDesC& aFileName)
    92 	: iFileName(aFileName), iFs(aFs)
    93 	{
    94 	}
    95  
    96 /** 
    97 @deprecated in 7.0 
    98 */	
    99 EXPORT_C TInt CZipFile::OpenL(void)
   100 	{
   101 	if (!iMemberPointers)
   102 		{
   103 		ConstructL(iFileName);
   104 		}
   105 	return KErrNone;
   106 	}
   107 	
   108 /** 
   109 @deprecated in 7.0 
   110 */
   111 EXPORT_C void CZipFile::Close(void)
   112 	{
   113 	DeleteMemberPointers();
   114 	}
   115 
   116 /**
   117 Second phase of construction. Used by Rfile using NewL overload.
   118 
   119 @leave ... Any one of the system-wide error codes for other errors.
   120 */
   121 EXPORT_C void CZipFile::ConstructL(RFile& aFile)
   122 	{
   123 	// Use the full name derived from the session path
   124 	ContentAccess::CContent* content = 
   125 		ContentAccess::CContent::NewL(aFile);
   126 	CleanupStack::PushL(content);
   127 	iData = content->OpenContentL(ContentAccess::EPeek);
   128 
   129 	// Parent content object no longer needed because we only need data
   130 	CleanupStack::PopAndDestroy(content);
   131 
   132 	// Seek to the end
   133 	TInt length = 0;
   134 	User::LeaveIfError(iData->Seek(ESeekEnd, length));
   135 	iFileLength = length;
   136 
   137 	TInt status;
   138 	TUint32 offset;
   139 
   140 	if ((status = FindCentralDirectoryTrailer(offset)) != KErrNone) 
   141 		{
   142 		DeleteMemberPointers();
   143 		User::Leave(status);
   144 		}
   145 
   146 	if ((status = ReadCentralDirectoryTrailer(offset, iTrailer)) != KErrNone) 
   147 		{
   148 		DeleteMemberPointers();
   149 		User::Leave(status);
   150 		}
   151 
   152 	if (iTrailer.iStartDiskNumber != iTrailer.iDiskNumber) 
   153 		{
   154 		DeleteMemberPointers();
   155 		User::Leave(KMultiDiskArchivesNotSupported);
   156 		}
   157 
   158 	if ((iTrailer.iOffset + iTrailer.iSize) > iFileLength)
   159 		{
   160 		DeleteMemberPointers();
   161 	    User::Leave(KCentralDirectoryTrailerInvalid);
   162 		}
   163 
   164 	if (LoadMemberPointersL() != KErrNone)
   165 		{
   166 		User::Leave(KZipFileIOError);
   167 		}	
   168 	}
   169 
   170 /**
   171 Second phase of construction. Used by filename using NewL overload
   172 
   173 @leave ... Any one of the system-wide error codes for other errors.
   174 */
   175 EXPORT_C void CZipFile::ConstructL(const TDesC& aFileName)
   176 	{
   177 	TInt status;
   178 	TUint32 offset;
   179 	
   180 	TRAP(status, OpenFileL(aFileName));
   181 	if (status)
   182 		{
   183 		User::Leave(KZipArchiveError);
   184 		}
   185 	else
   186 	if ((status = FindCentralDirectoryTrailer(offset)) != KErrNone) 
   187 		{
   188 		DeleteMemberPointers();
   189 		User::Leave(status);
   190 		}
   191 	else 
   192 	if ((status = ReadCentralDirectoryTrailer(offset, iTrailer)) != KErrNone) 
   193 		{
   194 		DeleteMemberPointers();
   195 		User::Leave(status);
   196 		}
   197 	else 
   198 	if (iTrailer.iStartDiskNumber != iTrailer.iDiskNumber) 
   199 		{
   200 		DeleteMemberPointers();
   201 		User::Leave(KMultiDiskArchivesNotSupported);
   202 		}
   203 	else
   204 	if ((iTrailer.iOffset > iFileLength) ||
   205 	    ((iTrailer.iOffset + iTrailer.iSize) > iFileLength)) 
   206 		{
   207 		DeleteMemberPointers();
   208 	    User::Leave(KCentralDirectoryTrailerInvalid);
   209 		}
   210 	else
   211 	if (LoadMemberPointersL() != KErrNone)
   212 		{
   213 		User::Leave(KZipFileIOError);
   214 		}	
   215 	}
   216 
   217 /**
   218 Gets the size of the compressed data contained in the zip file in bytes
   219 Each CZipFile object has a compressed and uncompressed size. This method will 
   220 return the compressed size of a zip file.
   221 
   222 @param aSize On return, the size of the compressed data in bytes
   223 @return KErrNotReady If object hasn't been properly constructed
   224 @return KErrCASizeNotDetermined	If size could not be determined 
   225 @return ... Any one of the system-wide error codes for other errors.
   226 */
   227 EXPORT_C TInt CZipFile::Size(TInt& aSize) const
   228 {
   229 	TInt err = KErrNotReady;
   230 	if (iData)
   231 		{
   232 		TRAP(err, iData->DataSizeL(aSize));
   233 		}
   234 	return err;
   235 }
   236 
   237 /**
   238 Constructs and returns a CZipFileMember object which is used to access 
   239 information about a compressed file contained in the CZipFile archive. 
   240 The name of the file to be searched for in the zipfile is case-sensitive. 
   241 
   242 @param aName The name of the file to be searched in the zipfile 
   243 @return the pointer to CZipFileMember object
   244 @return NULL if the file doesn't exist in the zipfile
   245 @leave ... Any one of the system-wide error codes for other errors.
   246 */
   247 EXPORT_C CZipFileMember* CZipFile::MemberL(const TDesC& aName)
   248 	{
   249 	TLocalHeader		  header;
   250 	const TMemberPointer* memberPointer;
   251 	HBufC* localName = aName.AllocL();
   252 	TInt loop = 0;
   253 	while (loop < localName->Length())
   254 		{
   255 		if ((*localName)[loop] == '\\')
   256 			{
   257 			(localName->Des())[loop] = '/';
   258 			}
   259 		loop++;
   260 		}
   261 	
   262 	memberPointer = FindMemberPointer(*localName, EFalse);
   263 	if (memberPointer == NULL)
   264 		{
   265 		delete localName;
   266 		return NULL;
   267 		}
   268 	else
   269 	if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
   270 		{
   271 		delete localName;
   272 		return NULL;
   273 		}
   274 	else
   275 		{
   276 		CleanupStack::PushL(localName);
   277 		CZipFileMember* thisMember = MakeMemberL(*memberPointer, header);
   278 		CleanupStack::PopAndDestroy();		// localName
   279 		return thisMember;
   280 		}
   281 	}
   282 
   283 /**
   284 Constructs and returns a CZipFileMember object which is used to access 
   285 information about a compressed file contained in the CZipFile archive. 
   286 The name of the file to be searched for in the zipfile is case-insensitive.
   287 
   288 @param aName The name of the file to be searched in the zipfile 
   289 @return A pointer to a member object of zip file
   290 @return NULL If the file doesn't exist in the zipfile
   291 @leave ... Any one of the system-wide error codes for other errors.
   292 */
   293 EXPORT_C CZipFileMember* CZipFile::CaseInsensitiveMemberL(const TDesC& aName)
   294 {
   295 	TLocalHeader		  header;
   296 	const TMemberPointer* memberPointer;
   297 	HBufC* localName = aName.AllocL();
   298 	TInt loop=0;
   299 	while (loop < localName->Length())
   300 		{
   301 		if ((*localName)[loop] == '\\')
   302 			{
   303 			(localName->Des())[loop] = '/';
   304 			}
   305 		loop++;
   306 		}
   307 	
   308 	memberPointer = FindMemberPointer(*localName, ETrue);
   309 	if (memberPointer == NULL)
   310 		{
   311 		delete localName;
   312 		return NULL;
   313 		}
   314 	else
   315 	if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
   316 		{
   317 		delete localName;
   318 		return NULL;
   319 		}
   320 	else
   321 		{
   322 		CleanupStack::PushL(localName);
   323 		CZipFileMember* thisMember = MakeMemberL(*memberPointer, header);
   324 		CleanupStack::PopAndDestroy();
   325 		return thisMember;
   326 		}
   327 
   328 	}
   329 
   330 /**
   331 Constructs and returns a CZipFileMember object which is used to access 
   332 information about a compressed file contained in the CZipFile archive. 
   333 An exact match for the filename is searched for first. If a match is not found, 
   334 a case-insensitive search is performed. If both filenames exist in the archive, 
   335 the case-sensitive match will be returned.
   336  
   337 @param aName The name of the file to be searched in the zipfile 
   338 @return A pointer to a member object of zip file
   339 @return NULL If the file doesn't exist in the zipfile
   340 @leave ... Any one of the system-wide error codes for other errors.
   341 */
   342 EXPORT_C CZipFileMember* CZipFile::CaseSensitiveOrCaseInsensitiveMemberL(const TDesC& aName)
   343 {
   344 	CZipFileMember* member;
   345 	member = MemberL(aName);
   346 	if (member)
   347 		{
   348 		return member;
   349 		}
   350 	else
   351 		{
   352 		return CaseInsensitiveMemberL(aName);
   353 		}
   354 }
   355 
   356 /**
   357 Creates and returns the input stream for a file in the archive. Only files 
   358 compressed with Stored or Deflated compression methods are supported.
   359 
   360 @param aMember The compressed file in the archive
   361 @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.
   362 @return KErrNone if successful
   363 @return KCompressionMethodNotSupported if compression format unsupported 
   364 @return ... Any one of the system-wide error codes for other errors.
   365 @leave ... Any one of the system-wide error codes for other errors.
   366 */
   367 EXPORT_C TInt CZipFile::GetInputStreamL(const CZipFileMember* aMember, RZipFileMemberReaderStream*& aStream)
   368 	{
   369 	TUint32 compressionMethod;
   370 	
   371 	compressionMethod = aMember->iCompressionMethod;
   372 	if ((compressionMethod != EStored) && (compressionMethod != EDeflated)) 
   373 	    {
   374 	    return KCompressionMethodNotSupported;
   375 	    }
   376 	aStream = RZipFileMemberReaderStream::NewL(
   377 								*this,
   378 							   aMember->iDataOffset,
   379 							   aMember->iCompressedSize,
   380 							   aMember->iUncompressedSize,
   381 							   compressionMethod);
   382 	return KErrNone;
   383 	}
   384 	
   385 
   386 
   387 /**
   388 Gets the iterator used for iterating through the files contained in the ZIP 
   389 file. It is the caller's responsibility to release the iterator when finsihed.
   390  
   391 @return Pointer to a newly allocated CZipFileMemberIterator object
   392 @leave ... Any one of the system-wide error codes for other errors.
   393 */
   394 EXPORT_C CZipFileMemberIterator* CZipFile::GetMembersL()
   395 	{
   396 	return new (ELeave) CZipFileMemberIterator(this);
   397 	}
   398 	
   399 
   400 
   401 // Implementation
   402 
   403 /*
   404  * Find the 'end of central directory record'. This is at the 'end' of
   405  * the file, but since it is not a fixed length structure, we have to
   406  * hunt for it.
   407  *
   408  * We try assuming that the variable length section of the record is
   409  * empty, which usually appears to be the case.
   410  *
   411  * If this does not work we resort to 'walking backwards' through the
   412  * file looking for the signature bytes.
   413  *
   414  */
   415  
   416 TInt CZipFile::FindCentralDirectoryTrailer(TUint32& offset)
   417 {
   418 	TBuf8<KSignatureLength> signature;
   419 		
   420     if (iFileLength <= KCentralDirectoryTrailerFixedLength) 
   421 		{
   422     	return KZipArchiveError;
   423 		}
   424     // Try the obvious place first.Assuming that the comment (variable 
   425     // length section) is empty,try to find the signature at the offset.
   426     offset = iFileLength - KCentralDirectoryTrailerFixedLength;
   427 	if (Seek(offset) != KErrNone) 
   428 		{
   429     	return KZipFileIOError;
   430 		}
   431 	TInt err = iData->Read(signature);
   432 
   433 	if ( err != KErrNone) 
   434 		{
   435 		return KZipFileIOError;
   436 		}
   437 
   438 	if ((signature[0] == 0x50) && 
   439 		(signature[1] == 0x4b) &&
   440 		(signature[2] == 0x05) &&
   441 		(signature[3] == 0x06)) 
   442 		{
   443 		return KErrNone;
   444 		}
   445 	else 
   446 		{
   447 		// There must be some comments, hence the central directory 
   448 		// record > 22 bytes.
   449 		// This is a slow but fairly obvious way of searching 
   450 		// backwards through the file starting from the offset.
   451 		TUint EndOfTrailerSearch = 0; //Upto beginning of File
   452 
   453 		if(iFileLength > KMaxTrailerSearchLength+KCentralDirectoryTrailerFixedLength)
   454 			EndOfTrailerSearch = offset - KMaxTrailerSearchLength; //Upto Last 64K+22 bytes
   455 
   456 		while (offset >= EndOfTrailerSearch) 
   457 			{
   458 			if (Seek(offset) != KErrNone)
   459 				{
   460 				return KZipFileIOError;
   461 				}
   462 			if (iData->Read(signature) != KErrNone)
   463 				{
   464 				return KZipFileIOError;
   465 				}
   466 			if ((signature[0] == 0x50) && 
   467 				(signature[1] == 0x4b) &&
   468 				(signature[2] == 0x05) &&
   469 				(signature[3] == 0x06)) 
   470 				{			
   471 				return KErrNone;
   472 				}
   473 			--offset;
   474 			}
   475 		return KCentralDirectoryTrailerNotFound;
   476 		}	
   477 	}
   478 	
   479 TInt CZipFile::ReadCentralDirectoryTrailer(TUint32 offset, struct TCentralDirectoryTrailer& r )
   480 {
   481     // Skip the signature		    
   482     if (Seek(offset + KSignatureLength) != KErrNone) 
   483     	{
   484     	return KZipFileIOError;
   485     	} 
   486 	else
   487 	if (Read(r.iDiskNumber) != KErrNone) 
   488 		{
   489 		return KZipFileIOError;
   490 		}
   491 	else
   492 	if (Read(r.iStartDiskNumber)!= KErrNone) 
   493 		{
   494 		return KZipFileIOError;
   495 		}
   496 	else
   497 	if (Read(r.iLocalEntryCount) != KErrNone) 
   498 		{
   499 		return KZipFileIOError;
   500 		}
   501 	else
   502 	if (Read(r.iTotalEntryCount) != KErrNone) 
   503 		{
   504 		return KZipFileIOError;
   505 		}
   506 	else
   507 	if (Read(r.iSize) != KErrNone) 
   508 		{
   509 		return KZipFileIOError;
   510 		}
   511 	else
   512 	if (Read(r.iOffset) != KErrNone) 
   513 		{
   514 		return KZipFileIOError;
   515 		}
   516 	else
   517 		{
   518 		return KErrNone;
   519 		}
   520 }
   521 
   522 TInt CZipFile::LoadMemberPointersL(void)
   523 	{
   524 	TCentralDirectoryHeader	header;
   525 	TUint32					i;
   526 	TUint32					memberPointerCount;
   527 		
   528 	if (Seek(iTrailer.iOffset) != KErrNone)
   529 		{
   530 		return KZipFileIOError;
   531 		}
   532 	memberPointerCount = iTrailer.iTotalEntryCount;
   533 	iMemberPointers = new (ELeave) TMemberPointer[memberPointerCount];
   534 	for (i = 0; i < memberPointerCount; i++)
   535 		{
   536 		iMemberPointers[i].iName = NULL;
   537 		}
   538 	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewL();
   539 	CleanupStack::PushL(converter);
   540 	TInt converterState = CCnvCharacterSetConverter::KStateDefault;
   541 	for (i = 0; i < memberPointerCount; i++)
   542 		{
   543 		if (ReadCentralDirectoryHeaderL(header, iMemberPointers[i], converter, converterState) != KErrNone)
   544 			{
   545 			return KZipFileError;
   546 			}
   547 		}
   548 	CleanupStack::PopAndDestroy(converter);
   549 	return KErrNone;
   550 	}
   551 	
   552 LOCAL_C void ConvertFileNameToUnicodeL(
   553 						TDes16& aUnicode,
   554 						const TDesC8& aForeign,
   555 						const TUint16& aMadeBy,
   556 						CCnvCharacterSetConverter* aConverter,
   557 						TInt aConverterState,
   558 						RFs aFs)
   559 // Have to decide whether filename encoding is CP850 or CP1252. According to tec support
   560 // at WinZip, if 'madeby' is set to DOS(0) then the encoding is CP850 and if it's set to
   561 // NTFS (11) then it's CP1252.  However, if the MS Compressed Folders program was used
   562 // to zip, then madeby is always set to NTFS and the encoding is always CP850 - the exact
   563 // opposite. Because of this confusion, I have written a very basic decision algorithm
   564 // based on the premise that filenames are likely to use alphabet-style extended
   565 // characters (rather than box edges or punctuation etc.)
   566 	{
   567 	TInt len = aForeign.Length();
   568 	TInt ANSIpoints = 0;
   569 	TInt OEMpoints = 0;
   570 	for (TInt i=0; i<len; i++)
   571 		{
   572 		if (aForeign[i] >= 128 && aForeign[i] <= 165)
   573 			OEMpoints ++;
   574 		if (aForeign[i] >= 192 && aForeign[i] <= 255)
   575 			ANSIpoints ++;
   576 		}
   577 	if (ANSIpoints == OEMpoints)
   578 		{
   579 		if (aMadeBy>>8) //only interested in the upper byte
   580 			ANSIpoints ++;
   581 		else
   582 			OEMpoints ++;
   583 		}
   584 	TInt unconvertibleChars = 0;
   585 
   586 	CCnvCharacterSetConverter::TAvailability availabilty = CCnvCharacterSetConverter::EAvailable;
   587 	if (ANSIpoints > OEMpoints)
   588 		{
   589 		// It's probably ANSI (CP1252)
   590 		availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252,aFs);
   591 		aConverter->ConvertToUnicode(aUnicode, aForeign, aConverterState, unconvertibleChars);
   592 		
   593 		}
   594 	if (OEMpoints > ANSIpoints || unconvertibleChars)
   595 		{
   596 		// It's definitely OEM (CP850)
   597  		availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCP850,aFs);
   598 		if(availabilty != CCnvCharacterSetConverter::EAvailable )
   599 			{
   600 			//if cp850 plugin is not available, use cp1252
   601 			aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252, aFs);
   602 			}
   603 		
   604 		aConverter->ConvertToUnicode(aUnicode, aForeign, aConverterState);
   605 		
   606 		}
   607 	}
   608 
   609 TInt CZipFile::ReadCentralDirectoryHeaderL(
   610 		 		   TCentralDirectoryHeader& aHeader, 
   611 		 		   TMemberPointer&          aMemberPointer,
   612 				   CCnvCharacterSetConverter* aConverter,
   613 				   TInt aConverterState)
   614 /*
   615 As this function might be called many times and the request will 
   616 eventually be translated to calls to server to read the data, 
   617 so performance is the major issue. Try to minimize calls to server.
   618 Read data in a chunk rather than member-by-member.
   619 */
   620 	{
   621 	TByte tmpHeader[KCentralDirectoryHeaderFixedLength];
   622  
   623 	if (Read(tmpHeader,KCentralDirectoryHeaderFixedLength) != KErrNone)
   624 		{
   625 		return KZipFileIOError;
   626 		}
   627 
   628 	Mem::Copy(&aHeader.iSignature, &tmpHeader[0], 4);
   629 
   630 	if (aHeader.iSignature != KCentralDirectoryHeaderSignature)
   631 		{
   632 		return KZipFileIOError;
   633 		}
   634 
   635 	Mem::Copy(&aHeader.iMadeBy, &tmpHeader[4], 2);
   636 	Mem::Copy(&aHeader.iRequired, &tmpHeader[6], 2);
   637 	Mem::Copy(&aHeader.iFlags, &tmpHeader[8], 2);
   638 	Mem::Copy(&aHeader.iCompressionMethod, &tmpHeader[10], 2);
   639 	Mem::Copy(&aHeader.iLastModifiedFileTime, &tmpHeader[12], 2);
   640 	Mem::Copy(&aHeader.iLastModifiedFileDate, &tmpHeader[14], 2);
   641 	Mem::Copy(&aHeader.iCRC32, &tmpHeader[16], 4);
   642 	Mem::Copy(&aHeader.iCompressedSize, &tmpHeader[20], 4);
   643 	Mem::Copy(&aHeader.iUncompressedSize, &tmpHeader[24], 4);
   644 	Mem::Copy(&aHeader.iFileNameLength, &tmpHeader[28], 2);
   645 	Mem::Copy(&aHeader.iExtraFieldLength, &tmpHeader[30], 2);
   646 	Mem::Copy(&aHeader.iFileCommentLength, &tmpHeader[32], 2);
   647 	Mem::Copy(&aHeader.iDiskNumberStart, &tmpHeader[34], 2);
   648 	Mem::Copy(&aHeader.iInternalFileAttributes, &tmpHeader[36], 2);
   649 	Mem::Copy(&aHeader.iExternalFileAttributes, &tmpHeader[38], 4);
   650 	Mem::Copy(&aHeader.iLocalHeaderOffset, &tmpHeader[42], 4);
   651 
   652 	aMemberPointer.iCRC32             = aHeader.iCRC32;
   653 	aMemberPointer.iCompressedSize    = aHeader.iCompressedSize;
   654 	aMemberPointer.iUncompressedSize  = aHeader.iUncompressedSize;
   655 	aMemberPointer.iLocalHeaderOffset = aHeader.iLocalHeaderOffset;
   656     aMemberPointer.iName = new(ELeave) TFileName;
   657 	
   658 	TBuf8<KMaxFileName> input;
   659 	if (iData->Read(input, aHeader.iFileNameLength) != KErrNone)
   660 		{
   661 		return KZipFileIOError;
   662 		}
   663 	ConvertFileNameToUnicodeL(*aMemberPointer.iName, input, aHeader.iMadeBy, aConverter, aConverterState, iFs);
   664 	
   665     // Ignore the remaining fields
   666 	TInt pos;
   667 
   668 	pos = aHeader.iExtraFieldLength;	
   669 	if (pos != 0)
   670 		{
   671 		// Don't pass aHeader.iExtraFieldLength in place of pos
   672 		// as the below function will update the content of that variable.
   673 		// In this case, the function is used to ignore the data
   674 		// by just moving the current file pointer location.
   675 		if (iData->Seek(ESeekCurrent, pos) != KErrNone) 
   676 			{
   677 			return KZipFileIOError;
   678 			}
   679 		}
   680 
   681 	pos = aHeader.iFileCommentLength;
   682 	if (pos != 0)
   683 		{
   684 		// Don't pass aHeader.iFileCommentLength in place of pos
   685 		// as the below function will update the content of that variable.
   686 		// In this case, the function is used to ignore the data
   687 		// by just moving the current file pointer location.
   688 		if (iData->Seek(ESeekCurrent, pos) != KErrNone) 
   689 			{
   690 			return KZipFileIOError;
   691 			}
   692 		}
   693 
   694   	return  KErrNone;
   695 }
   696 
   697 TInt CZipFile::ReadLocalHeader(TUint32 aOffset, TLocalHeader& aHeader)
   698 /*
   699 As this function might be called many times and the request will 
   700 eventually be translated to calls to server to read the data, 
   701 so performance is the major issue. Try to minimize calls to server.
   702 Read data in a chunk rather than member-by-member.
   703 */
   704 	{
   705 	TByte tmpHeader[KLocalHeaderFixedLength];
   706 
   707 	if (Seek(aOffset) != KErrNone)
   708 		{
   709 		return KZipFileIOError;
   710 		}
   711 	if (Read(tmpHeader,KLocalHeaderFixedLength) != KErrNone)
   712 		{
   713 		return KZipFileIOError;
   714 		}
   715 	Mem::Copy(&aHeader.iSignature, &tmpHeader[0], 4);
   716 
   717 	if (aHeader.iSignature != KLocalHeaderSignature)
   718 		{
   719 		return KLocalHeaderSignatureInvalid;
   720 		}
   721 
   722 	Mem::Copy(&aHeader.iVersionNeeded, &tmpHeader[4], 2);
   723 	Mem::Copy(&aHeader.iFlags, &tmpHeader[6], 2);
   724 	Mem::Copy(&aHeader.iCompressionMethod, &tmpHeader[8], 2);
   725 	Mem::Copy(&aHeader.iLastModifiedFileTime, &tmpHeader[10], 2);
   726 	Mem::Copy(&aHeader.iLastModifiedFileDate, &tmpHeader[12], 2);
   727 	Mem::Copy(&aHeader.iCRC32, &tmpHeader[14], 4);
   728 	Mem::Copy(&aHeader.iCompressedSize, &tmpHeader[18], 4);
   729 	Mem::Copy(&aHeader.iUncompressedSize, &tmpHeader[22], 4);
   730 	Mem::Copy(&aHeader.iFileNameLength, &tmpHeader[26], 2);
   731 	Mem::Copy(&aHeader.iExtraFieldLength, &tmpHeader[28], 2);
   732 
   733 	return  KErrNone;
   734 	}
   735 	
   736 const CZipFile::TMemberPointer* CZipFile::FindMemberPointer(const TDesC& aName, TBool aCaseInsensitive)
   737 	{
   738 	for (TUint32 i = 0; i < iTrailer.iTotalEntryCount; i++)
   739 		{
   740 		if (aCaseInsensitive && (!aName.CompareF(*iMemberPointers[i].iName)))
   741 			{
   742 			return iMemberPointers + i;
   743 			}
   744 		else if (aName == *iMemberPointers[i].iName)
   745 			{
   746 			return iMemberPointers + i;
   747 			}
   748 		}
   749 	return NULL;
   750 	}
   751 
   752 RZipFileMemberReaderStream* CZipFile::MakeInputStreamL(
   753 							TUint32 aDataOffset, 
   754 							TUint32 aCompressedSize, 
   755 							TUint32 aUncompressedSize, 
   756 							TUint32 aCompressionMethod)
   757 	{
   758 	return RZipFileMemberReaderStream::NewL(
   759 						    *this,
   760 							aDataOffset,
   761 							aCompressedSize,
   762 							aUncompressedSize, 
   763 							aCompressionMethod);
   764 	}
   765 
   766 CZipFileMember* CZipFile::MakeMemberL(TInt aMemberIndex)
   767 	{
   768 	TLocalHeader    header;
   769 	TMemberPointer*	memberPointer;
   770 	
   771 	if (aMemberIndex >= iTrailer.iTotalEntryCount)
   772 		{
   773 		return NULL;
   774 		}
   775 	memberPointer = iMemberPointers + aMemberIndex;
   776 	if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
   777 		{
   778 		return NULL;
   779 		}
   780 	else
   781 		{
   782 		return MakeMemberL(*memberPointer, header);
   783 		}
   784 	}
   785 	
   786 CZipFileMember* CZipFile::MakeMemberL(
   787                               const TMemberPointer& aMemberPointer, 
   788 			                  const TLocalHeader&   aHeader)
   789 	{
   790 	CZipFileMember* member;
   791 	
   792 	member = new (ELeave) CZipFileMember;
   793 	CleanupStack::PushL(member);
   794 	member->iCRC32 = aMemberPointer.iCRC32;
   795 	member->iCompressedSize = aMemberPointer.iCompressedSize;
   796 	member->iCompressionMethod = aHeader.iCompressionMethod;
   797 	member->iName = new (ELeave) TFileName(*aMemberPointer.iName);
   798 	TInt loop=0;
   799 	while (loop < member->iName->Length())
   800 		{
   801 		if ((*member->iName)[loop] == '/')
   802 			{
   803 			(*member->iName)[loop] = '\\';
   804 			}
   805 		loop++;
   806 		}
   807 	member->iUncompressedSize = aMemberPointer.iUncompressedSize;
   808 	member->iDataOffset = aMemberPointer.iLocalHeaderOffset + 
   809 		                  KLocalHeaderFixedLength + 
   810 						  aHeader.iFileNameLength + 
   811 						  aHeader.iExtraFieldLength;
   812 	CleanupStack::Pop();
   813 	return member;
   814 	}
   815 
   816 void CZipFile::DeleteMemberPointers()
   817 	{
   818 	if (iMemberPointers)
   819 		{
   820 		for (TUint32 i = 0; i < iTrailer.iTotalEntryCount; i++)
   821 			{
   822 			delete iMemberPointers[i].iName;
   823 			}
   824 		delete[] iMemberPointers;
   825 		iMemberPointers = 0;
   826 		}
   827 
   828 	delete iData;
   829 	iData = NULL;
   830 	return;
   831 	}
   832 
   833 void CZipFile::OpenFileL(const TDesC& aFileName)
   834 	{
   835 	// We need to look at the session path of the filesystem passed
   836 	// in to derive the fullpath of the file to open
   837 	HBufC* sessionPath = HBufC::NewLC(KMaxFileName);
   838 	TPtr ptr(sessionPath->Des());
   839 	User::LeaveIfError(iFs.SessionPath(ptr));
   840 	TParse parse;
   841 	User::LeaveIfError(parse.Set(aFileName, sessionPath, NULL));
   842 	
   843 	// Use the full name derived from the session path
   844 	ContentAccess::CContent* content = 
   845 		ContentAccess::CContent::NewL(parse.FullName());
   846 	CleanupStack::PushL(content);
   847 	iData = content->OpenContentL(ContentAccess::EPeek);
   848 
   849 	// Parent content object no longer needed because we only need data
   850 	CleanupStack::PopAndDestroy(content);
   851 
   852 	// Seek to the end
   853 	TInt length = 0;
   854 	User::LeaveIfError(iData->Seek(ESeekEnd, length));
   855 	iFileLength = length;
   856 	CleanupStack::PopAndDestroy(sessionPath);
   857 	}
   858 
   859 TInt CZipFile::Read(TUint16& aUs)
   860 	{
   861 	TPckgBuf<TUint16> temp(aUs);
   862 	
   863 	if (iData->Read(temp) != KErrNone)
   864 		{
   865 		return KZipFileIOError;
   866 		}
   867 	
   868 	aUs=temp();
   869 	return KErrNone;
   870 	}
   871 	
   872 TInt CZipFile::Read(TUint32& aUl)
   873 	{
   874 	TPckgBuf<TUint32> temp;
   875 	
   876 	if (iData->Read(temp) != KErrNone)
   877 		{
   878 		return KZipFileIOError;
   879 		}
   880 	aUl=temp();
   881 	return KErrNone;
   882 	}
   883 
   884 TInt CZipFile::Read(TByte* aBytes, TUint32 aLength)
   885 
   886 	{
   887 	TPtr8 ptr(aBytes, aLength);
   888 	if(iData->Read(ptr, aLength))
   889 		{
   890 		return KZipFileIOError;
   891 		}
   892 	else
   893 		{
   894 		return KErrNone;
   895 		}
   896 	}
   897 	
   898 TInt CZipFile::Seek(TInt aOffset)
   899 	{
   900 	if (iData->Seek(ESeekStart, aOffset) < 0) 
   901 		{
   902 		return KZipFileIOError;
   903 		}
   904 	else
   905 		{
   906 		return KErrNone;
   907 		}
   908 	}
   909