compressionlibs/ziplib/test/oldezlib/zip/ZipFile.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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