os/ossrv/compressionlibs/ziplib/test/oldezlib/zip/ZipFile.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/compressionlibs/ziplib/test/oldezlib/zip/ZipFile.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,909 @@
     1.4 +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// $Revision: 1.1 $
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +
    1.22 +
    1.23 +#include <caf/content.h>
    1.24 +#include <caf/data.h>
    1.25 +#include "oldzipfile.h"
    1.26 +
    1.27 +using namespace TOLDEZIP;
    1.28 +// ====================================================================
    1.29 +// CZipFile public exported interface
    1.30 +// ====================================================================
    1.31 +
    1.32 +/**
    1.33 +Creates a new CZipFile object using the supplied file server session and 
    1.34 +a valid file handle. The caller must have sufficient sufficient rights to 
    1.35 +access the content of the zipfile, if encrypted/protected.
    1.36 +
    1.37 +@param aFs File server session used for opening the zipfile
    1.38 +@param aFile File handle to be used for accessing the zipfile
    1.39 +@return CZipFile object associated with the zipfile if it succeeded
    1.40 +@leave KZipArchiveError If file cannot be accessed(invalid handle, corrupt file header, etc.)
    1.41 +@leave KZipFileIOError If file cannot be read
    1.42 +@leave KCentralDirectoryTrailerNotFound If zip file header doesn't contain information about files inside the archive
    1.43 +@leave KCentralDirectoryTrailerInvalid If the information about files inside the archive is corrupt
    1.44 +@leave KMultiDiskArchivesNotSupported If zipfile is a multi disk archive
    1.45 +@leave ... Any one of the system-wide error codes for other errors.
    1.46 +*/
    1.47 +EXPORT_C CZipFile* CZipFile::NewL(RFs& aFs, RFile& aFile)
    1.48 +	{
    1.49 +	TFileName file;
    1.50 +	aFile.Name(file);
    1.51 +	CZipFile* zipFile = new(ELeave) CZipFile(aFs, file);
    1.52 +	CleanupStack::PushL(zipFile);
    1.53 +	zipFile->ConstructL(aFile);
    1.54 +	CleanupStack::Pop(zipFile);
    1.55 +	return zipFile;
    1.56 +	}
    1.57 +	
    1.58 +/**
    1.59 +Creates a new CZipFile object using the supplied file server session and 
    1.60 +file name. The caller must have sufficient capabilities to access the directory. 
    1.61 +The caller must also have sufficient rights to access the content of the 
    1.62 +zipfile, if encrypted/protected.
    1.63 +
    1.64 +@param aFs File server session used for opening the zipfile
    1.65 +@param aFileName Name of the zipfile 
    1.66 +@return CZipFile object associated with the zipfile if it succeeded
    1.67 +@leave KZipArchiveError If file cannot be accessed(invalid handle, corrupt file header, etc.)
    1.68 +@leave KZipFileIOError If file cannot be read
    1.69 +@leave KCentralDirectoryTrailerNotFound If zip file header doesn't contain information about files inside the archive
    1.70 +@leave KCentralDirectoryTrailerInvalid If the information about files inside the archive is corrupt
    1.71 +@leave KMultiDiskArchivesNotSupported If zipfile is a multi disk archive. 
    1.72 +@leave ... Any one of the system-wide error codes for other errors.
    1.73 +*/
    1.74 +EXPORT_C CZipFile* CZipFile::NewL(RFs& aFs, const TDesC& aFileName)
    1.75 +	{
    1.76 +	CZipFile* zipFile = new(ELeave) CZipFile(aFs, aFileName);
    1.77 +	CleanupStack::PushL(zipFile);
    1.78 +	zipFile->ConstructL(aFileName);
    1.79 +	CleanupStack::Pop(zipFile);
    1.80 +	return zipFile;
    1.81 +	}
    1.82 +
    1.83 +/**
    1.84 +Destructor
    1.85 +*/
    1.86 +EXPORT_C CZipFile::~CZipFile()
    1.87 +	{
    1.88 +	DeleteMemberPointers();
    1.89 +	}
    1.90 +
    1.91 +/** 
    1.92 +@deprecated in 7.0 
    1.93 +*/
    1.94 +EXPORT_C CZipFile::CZipFile(RFs& aFs, const TDesC& aFileName)
    1.95 +	: iFileName(aFileName), iFs(aFs)
    1.96 +	{
    1.97 +	}
    1.98 + 
    1.99 +/** 
   1.100 +@deprecated in 7.0 
   1.101 +*/	
   1.102 +EXPORT_C TInt CZipFile::OpenL(void)
   1.103 +	{
   1.104 +	if (!iMemberPointers)
   1.105 +		{
   1.106 +		ConstructL(iFileName);
   1.107 +		}
   1.108 +	return KErrNone;
   1.109 +	}
   1.110 +	
   1.111 +/** 
   1.112 +@deprecated in 7.0 
   1.113 +*/
   1.114 +EXPORT_C void CZipFile::Close(void)
   1.115 +	{
   1.116 +	DeleteMemberPointers();
   1.117 +	}
   1.118 +
   1.119 +/**
   1.120 +Second phase of construction. Used by Rfile using NewL overload.
   1.121 +
   1.122 +@leave ... Any one of the system-wide error codes for other errors.
   1.123 +*/
   1.124 +EXPORT_C void CZipFile::ConstructL(RFile& aFile)
   1.125 +	{
   1.126 +	// Use the full name derived from the session path
   1.127 +	ContentAccess::CContent* content = 
   1.128 +		ContentAccess::CContent::NewL(aFile);
   1.129 +	CleanupStack::PushL(content);
   1.130 +	iData = content->OpenContentL(ContentAccess::EPeek);
   1.131 +
   1.132 +	// Parent content object no longer needed because we only need data
   1.133 +	CleanupStack::PopAndDestroy(content);
   1.134 +
   1.135 +	// Seek to the end
   1.136 +	TInt length = 0;
   1.137 +	User::LeaveIfError(iData->Seek(ESeekEnd, length));
   1.138 +	iFileLength = length;
   1.139 +
   1.140 +	TInt status;
   1.141 +	TUint32 offset;
   1.142 +
   1.143 +	if ((status = FindCentralDirectoryTrailer(offset)) != KErrNone) 
   1.144 +		{
   1.145 +		DeleteMemberPointers();
   1.146 +		User::Leave(status);
   1.147 +		}
   1.148 +
   1.149 +	if ((status = ReadCentralDirectoryTrailer(offset, iTrailer)) != KErrNone) 
   1.150 +		{
   1.151 +		DeleteMemberPointers();
   1.152 +		User::Leave(status);
   1.153 +		}
   1.154 +
   1.155 +	if (iTrailer.iStartDiskNumber != iTrailer.iDiskNumber) 
   1.156 +		{
   1.157 +		DeleteMemberPointers();
   1.158 +		User::Leave(KMultiDiskArchivesNotSupported);
   1.159 +		}
   1.160 +
   1.161 +	if ((iTrailer.iOffset + iTrailer.iSize) > iFileLength)
   1.162 +		{
   1.163 +		DeleteMemberPointers();
   1.164 +	    User::Leave(KCentralDirectoryTrailerInvalid);
   1.165 +		}
   1.166 +
   1.167 +	if (LoadMemberPointersL() != KErrNone)
   1.168 +		{
   1.169 +		User::Leave(KZipFileIOError);
   1.170 +		}	
   1.171 +	}
   1.172 +
   1.173 +/**
   1.174 +Second phase of construction. Used by filename using NewL overload
   1.175 +
   1.176 +@leave ... Any one of the system-wide error codes for other errors.
   1.177 +*/
   1.178 +EXPORT_C void CZipFile::ConstructL(const TDesC& aFileName)
   1.179 +	{
   1.180 +	TInt status;
   1.181 +	TUint32 offset;
   1.182 +	
   1.183 +	TRAP(status, OpenFileL(aFileName));
   1.184 +	if (status)
   1.185 +		{
   1.186 +		User::Leave(KZipArchiveError);
   1.187 +		}
   1.188 +	else
   1.189 +	if ((status = FindCentralDirectoryTrailer(offset)) != KErrNone) 
   1.190 +		{
   1.191 +		DeleteMemberPointers();
   1.192 +		User::Leave(status);
   1.193 +		}
   1.194 +	else 
   1.195 +	if ((status = ReadCentralDirectoryTrailer(offset, iTrailer)) != KErrNone) 
   1.196 +		{
   1.197 +		DeleteMemberPointers();
   1.198 +		User::Leave(status);
   1.199 +		}
   1.200 +	else 
   1.201 +	if (iTrailer.iStartDiskNumber != iTrailer.iDiskNumber) 
   1.202 +		{
   1.203 +		DeleteMemberPointers();
   1.204 +		User::Leave(KMultiDiskArchivesNotSupported);
   1.205 +		}
   1.206 +	else
   1.207 +	if ((iTrailer.iOffset > iFileLength) ||
   1.208 +	    ((iTrailer.iOffset + iTrailer.iSize) > iFileLength)) 
   1.209 +		{
   1.210 +		DeleteMemberPointers();
   1.211 +	    User::Leave(KCentralDirectoryTrailerInvalid);
   1.212 +		}
   1.213 +	else
   1.214 +	if (LoadMemberPointersL() != KErrNone)
   1.215 +		{
   1.216 +		User::Leave(KZipFileIOError);
   1.217 +		}	
   1.218 +	}
   1.219 +
   1.220 +/**
   1.221 +Gets the size of the compressed data contained in the zip file in bytes
   1.222 +Each CZipFile object has a compressed and uncompressed size. This method will 
   1.223 +return the compressed size of a zip file.
   1.224 +
   1.225 +@param aSize On return, the size of the compressed data in bytes
   1.226 +@return KErrNotReady If object hasn't been properly constructed
   1.227 +@return KErrCASizeNotDetermined	If size could not be determined 
   1.228 +@return ... Any one of the system-wide error codes for other errors.
   1.229 +*/
   1.230 +EXPORT_C TInt CZipFile::Size(TInt& aSize) const
   1.231 +{
   1.232 +	TInt err = KErrNotReady;
   1.233 +	if (iData)
   1.234 +		{
   1.235 +		TRAP(err, iData->DataSizeL(aSize));
   1.236 +		}
   1.237 +	return err;
   1.238 +}
   1.239 +
   1.240 +/**
   1.241 +Constructs and returns a CZipFileMember object which is used to access 
   1.242 +information about a compressed file contained in the CZipFile archive. 
   1.243 +The name of the file to be searched for in the zipfile is case-sensitive. 
   1.244 +
   1.245 +@param aName The name of the file to be searched in the zipfile 
   1.246 +@return the pointer to CZipFileMember object
   1.247 +@return NULL if the file doesn't exist in the zipfile
   1.248 +@leave ... Any one of the system-wide error codes for other errors.
   1.249 +*/
   1.250 +EXPORT_C CZipFileMember* CZipFile::MemberL(const TDesC& aName)
   1.251 +	{
   1.252 +	TLocalHeader		  header;
   1.253 +	const TMemberPointer* memberPointer;
   1.254 +	HBufC* localName = aName.AllocL();
   1.255 +	TInt loop = 0;
   1.256 +	while (loop < localName->Length())
   1.257 +		{
   1.258 +		if ((*localName)[loop] == '\\')
   1.259 +			{
   1.260 +			(localName->Des())[loop] = '/';
   1.261 +			}
   1.262 +		loop++;
   1.263 +		}
   1.264 +	
   1.265 +	memberPointer = FindMemberPointer(*localName, EFalse);
   1.266 +	if (memberPointer == NULL)
   1.267 +		{
   1.268 +		delete localName;
   1.269 +		return NULL;
   1.270 +		}
   1.271 +	else
   1.272 +	if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
   1.273 +		{
   1.274 +		delete localName;
   1.275 +		return NULL;
   1.276 +		}
   1.277 +	else
   1.278 +		{
   1.279 +		CleanupStack::PushL(localName);
   1.280 +		CZipFileMember* thisMember = MakeMemberL(*memberPointer, header);
   1.281 +		CleanupStack::PopAndDestroy();		// localName
   1.282 +		return thisMember;
   1.283 +		}
   1.284 +	}
   1.285 +
   1.286 +/**
   1.287 +Constructs and returns a CZipFileMember object which is used to access 
   1.288 +information about a compressed file contained in the CZipFile archive. 
   1.289 +The name of the file to be searched for in the zipfile is case-insensitive.
   1.290 +
   1.291 +@param aName The name of the file to be searched in the zipfile 
   1.292 +@return A pointer to a member object of zip file
   1.293 +@return NULL If the file doesn't exist in the zipfile
   1.294 +@leave ... Any one of the system-wide error codes for other errors.
   1.295 +*/
   1.296 +EXPORT_C CZipFileMember* CZipFile::CaseInsensitiveMemberL(const TDesC& aName)
   1.297 +{
   1.298 +	TLocalHeader		  header;
   1.299 +	const TMemberPointer* memberPointer;
   1.300 +	HBufC* localName = aName.AllocL();
   1.301 +	TInt loop=0;
   1.302 +	while (loop < localName->Length())
   1.303 +		{
   1.304 +		if ((*localName)[loop] == '\\')
   1.305 +			{
   1.306 +			(localName->Des())[loop] = '/';
   1.307 +			}
   1.308 +		loop++;
   1.309 +		}
   1.310 +	
   1.311 +	memberPointer = FindMemberPointer(*localName, ETrue);
   1.312 +	if (memberPointer == NULL)
   1.313 +		{
   1.314 +		delete localName;
   1.315 +		return NULL;
   1.316 +		}
   1.317 +	else
   1.318 +	if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
   1.319 +		{
   1.320 +		delete localName;
   1.321 +		return NULL;
   1.322 +		}
   1.323 +	else
   1.324 +		{
   1.325 +		CleanupStack::PushL(localName);
   1.326 +		CZipFileMember* thisMember = MakeMemberL(*memberPointer, header);
   1.327 +		CleanupStack::PopAndDestroy();
   1.328 +		return thisMember;
   1.329 +		}
   1.330 +
   1.331 +	}
   1.332 +
   1.333 +/**
   1.334 +Constructs and returns a CZipFileMember object which is used to access 
   1.335 +information about a compressed file contained in the CZipFile archive. 
   1.336 +An exact match for the filename is searched for first. If a match is not found, 
   1.337 +a case-insensitive search is performed. If both filenames exist in the archive, 
   1.338 +the case-sensitive match will be returned.
   1.339 + 
   1.340 +@param aName The name of the file to be searched in the zipfile 
   1.341 +@return A pointer to a member object of zip file
   1.342 +@return NULL If the file doesn't exist in the zipfile
   1.343 +@leave ... Any one of the system-wide error codes for other errors.
   1.344 +*/
   1.345 +EXPORT_C CZipFileMember* CZipFile::CaseSensitiveOrCaseInsensitiveMemberL(const TDesC& aName)
   1.346 +{
   1.347 +	CZipFileMember* member;
   1.348 +	member = MemberL(aName);
   1.349 +	if (member)
   1.350 +		{
   1.351 +		return member;
   1.352 +		}
   1.353 +	else
   1.354 +		{
   1.355 +		return CaseInsensitiveMemberL(aName);
   1.356 +		}
   1.357 +}
   1.358 +
   1.359 +/**
   1.360 +Creates and returns the input stream for a file in the archive. Only files 
   1.361 +compressed with Stored or Deflated compression methods are supported.
   1.362 +
   1.363 +@param aMember The compressed file in the archive
   1.364 +@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.
   1.365 +@return KErrNone if successful
   1.366 +@return KCompressionMethodNotSupported if compression format unsupported 
   1.367 +@return ... Any one of the system-wide error codes for other errors.
   1.368 +@leave ... Any one of the system-wide error codes for other errors.
   1.369 +*/
   1.370 +EXPORT_C TInt CZipFile::GetInputStreamL(const CZipFileMember* aMember, RZipFileMemberReaderStream*& aStream)
   1.371 +	{
   1.372 +	TUint32 compressionMethod;
   1.373 +	
   1.374 +	compressionMethod = aMember->iCompressionMethod;
   1.375 +	if ((compressionMethod != EStored) && (compressionMethod != EDeflated)) 
   1.376 +	    {
   1.377 +	    return KCompressionMethodNotSupported;
   1.378 +	    }
   1.379 +	aStream = RZipFileMemberReaderStream::NewL(
   1.380 +								*this,
   1.381 +							   aMember->iDataOffset,
   1.382 +							   aMember->iCompressedSize,
   1.383 +							   aMember->iUncompressedSize,
   1.384 +							   compressionMethod);
   1.385 +	return KErrNone;
   1.386 +	}
   1.387 +	
   1.388 +
   1.389 +
   1.390 +/**
   1.391 +Gets the iterator used for iterating through the files contained in the ZIP 
   1.392 +file. It is the caller's responsibility to release the iterator when finsihed.
   1.393 + 
   1.394 +@return Pointer to a newly allocated CZipFileMemberIterator object
   1.395 +@leave ... Any one of the system-wide error codes for other errors.
   1.396 +*/
   1.397 +EXPORT_C CZipFileMemberIterator* CZipFile::GetMembersL()
   1.398 +	{
   1.399 +	return new (ELeave) CZipFileMemberIterator(this);
   1.400 +	}
   1.401 +	
   1.402 +
   1.403 +
   1.404 +// Implementation
   1.405 +
   1.406 +/*
   1.407 + * Find the 'end of central directory record'. This is at the 'end' of
   1.408 + * the file, but since it is not a fixed length structure, we have to
   1.409 + * hunt for it.
   1.410 + *
   1.411 + * We try assuming that the variable length section of the record is
   1.412 + * empty, which usually appears to be the case.
   1.413 + *
   1.414 + * If this does not work we resort to 'walking backwards' through the
   1.415 + * file looking for the signature bytes.
   1.416 + *
   1.417 + */
   1.418 + 
   1.419 +TInt CZipFile::FindCentralDirectoryTrailer(TUint32& offset)
   1.420 +{
   1.421 +	TBuf8<KSignatureLength> signature;
   1.422 +		
   1.423 +    if (iFileLength <= KCentralDirectoryTrailerFixedLength) 
   1.424 +		{
   1.425 +    	return KZipArchiveError;
   1.426 +		}
   1.427 +    // Try the obvious place first.Assuming that the comment (variable 
   1.428 +    // length section) is empty,try to find the signature at the offset.
   1.429 +    offset = iFileLength - KCentralDirectoryTrailerFixedLength;
   1.430 +	if (Seek(offset) != KErrNone) 
   1.431 +		{
   1.432 +    	return KZipFileIOError;
   1.433 +		}
   1.434 +	TInt err = iData->Read(signature);
   1.435 +
   1.436 +	if ( err != KErrNone) 
   1.437 +		{
   1.438 +		return KZipFileIOError;
   1.439 +		}
   1.440 +
   1.441 +	if ((signature[0] == 0x50) && 
   1.442 +		(signature[1] == 0x4b) &&
   1.443 +		(signature[2] == 0x05) &&
   1.444 +		(signature[3] == 0x06)) 
   1.445 +		{
   1.446 +		return KErrNone;
   1.447 +		}
   1.448 +	else 
   1.449 +		{
   1.450 +		// There must be some comments, hence the central directory 
   1.451 +		// record > 22 bytes.
   1.452 +		// This is a slow but fairly obvious way of searching 
   1.453 +		// backwards through the file starting from the offset.
   1.454 +		TUint EndOfTrailerSearch = 0; //Upto beginning of File
   1.455 +
   1.456 +		if(iFileLength > KMaxTrailerSearchLength+KCentralDirectoryTrailerFixedLength)
   1.457 +			EndOfTrailerSearch = offset - KMaxTrailerSearchLength; //Upto Last 64K+22 bytes
   1.458 +
   1.459 +		while (offset >= EndOfTrailerSearch) 
   1.460 +			{
   1.461 +			if (Seek(offset) != KErrNone)
   1.462 +				{
   1.463 +				return KZipFileIOError;
   1.464 +				}
   1.465 +			if (iData->Read(signature) != KErrNone)
   1.466 +				{
   1.467 +				return KZipFileIOError;
   1.468 +				}
   1.469 +			if ((signature[0] == 0x50) && 
   1.470 +				(signature[1] == 0x4b) &&
   1.471 +				(signature[2] == 0x05) &&
   1.472 +				(signature[3] == 0x06)) 
   1.473 +				{			
   1.474 +				return KErrNone;
   1.475 +				}
   1.476 +			--offset;
   1.477 +			}
   1.478 +		return KCentralDirectoryTrailerNotFound;
   1.479 +		}	
   1.480 +	}
   1.481 +	
   1.482 +TInt CZipFile::ReadCentralDirectoryTrailer(TUint32 offset, struct TCentralDirectoryTrailer& r )
   1.483 +{
   1.484 +    // Skip the signature		    
   1.485 +    if (Seek(offset + KSignatureLength) != KErrNone) 
   1.486 +    	{
   1.487 +    	return KZipFileIOError;
   1.488 +    	} 
   1.489 +	else
   1.490 +	if (Read(r.iDiskNumber) != KErrNone) 
   1.491 +		{
   1.492 +		return KZipFileIOError;
   1.493 +		}
   1.494 +	else
   1.495 +	if (Read(r.iStartDiskNumber)!= KErrNone) 
   1.496 +		{
   1.497 +		return KZipFileIOError;
   1.498 +		}
   1.499 +	else
   1.500 +	if (Read(r.iLocalEntryCount) != KErrNone) 
   1.501 +		{
   1.502 +		return KZipFileIOError;
   1.503 +		}
   1.504 +	else
   1.505 +	if (Read(r.iTotalEntryCount) != KErrNone) 
   1.506 +		{
   1.507 +		return KZipFileIOError;
   1.508 +		}
   1.509 +	else
   1.510 +	if (Read(r.iSize) != KErrNone) 
   1.511 +		{
   1.512 +		return KZipFileIOError;
   1.513 +		}
   1.514 +	else
   1.515 +	if (Read(r.iOffset) != KErrNone) 
   1.516 +		{
   1.517 +		return KZipFileIOError;
   1.518 +		}
   1.519 +	else
   1.520 +		{
   1.521 +		return KErrNone;
   1.522 +		}
   1.523 +}
   1.524 +
   1.525 +TInt CZipFile::LoadMemberPointersL(void)
   1.526 +	{
   1.527 +	TCentralDirectoryHeader	header;
   1.528 +	TUint32					i;
   1.529 +	TUint32					memberPointerCount;
   1.530 +		
   1.531 +	if (Seek(iTrailer.iOffset) != KErrNone)
   1.532 +		{
   1.533 +		return KZipFileIOError;
   1.534 +		}
   1.535 +	memberPointerCount = iTrailer.iTotalEntryCount;
   1.536 +	iMemberPointers = new (ELeave) TMemberPointer[memberPointerCount];
   1.537 +	for (i = 0; i < memberPointerCount; i++)
   1.538 +		{
   1.539 +		iMemberPointers[i].iName = NULL;
   1.540 +		}
   1.541 +	CCnvCharacterSetConverter* converter = CCnvCharacterSetConverter::NewL();
   1.542 +	CleanupStack::PushL(converter);
   1.543 +	TInt converterState = CCnvCharacterSetConverter::KStateDefault;
   1.544 +	for (i = 0; i < memberPointerCount; i++)
   1.545 +		{
   1.546 +		if (ReadCentralDirectoryHeaderL(header, iMemberPointers[i], converter, converterState) != KErrNone)
   1.547 +			{
   1.548 +			return KZipFileError;
   1.549 +			}
   1.550 +		}
   1.551 +	CleanupStack::PopAndDestroy(converter);
   1.552 +	return KErrNone;
   1.553 +	}
   1.554 +	
   1.555 +LOCAL_C void ConvertFileNameToUnicodeL(
   1.556 +						TDes16& aUnicode,
   1.557 +						const TDesC8& aForeign,
   1.558 +						const TUint16& aMadeBy,
   1.559 +						CCnvCharacterSetConverter* aConverter,
   1.560 +						TInt aConverterState,
   1.561 +						RFs aFs)
   1.562 +// Have to decide whether filename encoding is CP850 or CP1252. According to tec support
   1.563 +// at WinZip, if 'madeby' is set to DOS(0) then the encoding is CP850 and if it's set to
   1.564 +// NTFS (11) then it's CP1252.  However, if the MS Compressed Folders program was used
   1.565 +// to zip, then madeby is always set to NTFS and the encoding is always CP850 - the exact
   1.566 +// opposite. Because of this confusion, I have written a very basic decision algorithm
   1.567 +// based on the premise that filenames are likely to use alphabet-style extended
   1.568 +// characters (rather than box edges or punctuation etc.)
   1.569 +	{
   1.570 +	TInt len = aForeign.Length();
   1.571 +	TInt ANSIpoints = 0;
   1.572 +	TInt OEMpoints = 0;
   1.573 +	for (TInt i=0; i<len; i++)
   1.574 +		{
   1.575 +		if (aForeign[i] >= 128 && aForeign[i] <= 165)
   1.576 +			OEMpoints ++;
   1.577 +		if (aForeign[i] >= 192 && aForeign[i] <= 255)
   1.578 +			ANSIpoints ++;
   1.579 +		}
   1.580 +	if (ANSIpoints == OEMpoints)
   1.581 +		{
   1.582 +		if (aMadeBy>>8) //only interested in the upper byte
   1.583 +			ANSIpoints ++;
   1.584 +		else
   1.585 +			OEMpoints ++;
   1.586 +		}
   1.587 +	TInt unconvertibleChars = 0;
   1.588 +
   1.589 +	CCnvCharacterSetConverter::TAvailability availabilty = CCnvCharacterSetConverter::EAvailable;
   1.590 +	if (ANSIpoints > OEMpoints)
   1.591 +		{
   1.592 +		// It's probably ANSI (CP1252)
   1.593 +		availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252,aFs);
   1.594 +		aConverter->ConvertToUnicode(aUnicode, aForeign, aConverterState, unconvertibleChars);
   1.595 +		
   1.596 +		}
   1.597 +	if (OEMpoints > ANSIpoints || unconvertibleChars)
   1.598 +		{
   1.599 +		// It's definitely OEM (CP850)
   1.600 + 		availabilty = aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCP850,aFs);
   1.601 +		if(availabilty != CCnvCharacterSetConverter::EAvailable )
   1.602 +			{
   1.603 +			//if cp850 plugin is not available, use cp1252
   1.604 +			aConverter->PrepareToConvertToOrFromL(KCharacterSetIdentifierCodePage1252, aFs);
   1.605 +			}
   1.606 +		
   1.607 +		aConverter->ConvertToUnicode(aUnicode, aForeign, aConverterState);
   1.608 +		
   1.609 +		}
   1.610 +	}
   1.611 +
   1.612 +TInt CZipFile::ReadCentralDirectoryHeaderL(
   1.613 +		 		   TCentralDirectoryHeader& aHeader, 
   1.614 +		 		   TMemberPointer&          aMemberPointer,
   1.615 +				   CCnvCharacterSetConverter* aConverter,
   1.616 +				   TInt aConverterState)
   1.617 +/*
   1.618 +As this function might be called many times and the request will 
   1.619 +eventually be translated to calls to server to read the data, 
   1.620 +so performance is the major issue. Try to minimize calls to server.
   1.621 +Read data in a chunk rather than member-by-member.
   1.622 +*/
   1.623 +	{
   1.624 +	TByte tmpHeader[KCentralDirectoryHeaderFixedLength];
   1.625 + 
   1.626 +	if (Read(tmpHeader,KCentralDirectoryHeaderFixedLength) != KErrNone)
   1.627 +		{
   1.628 +		return KZipFileIOError;
   1.629 +		}
   1.630 +
   1.631 +	Mem::Copy(&aHeader.iSignature, &tmpHeader[0], 4);
   1.632 +
   1.633 +	if (aHeader.iSignature != KCentralDirectoryHeaderSignature)
   1.634 +		{
   1.635 +		return KZipFileIOError;
   1.636 +		}
   1.637 +
   1.638 +	Mem::Copy(&aHeader.iMadeBy, &tmpHeader[4], 2);
   1.639 +	Mem::Copy(&aHeader.iRequired, &tmpHeader[6], 2);
   1.640 +	Mem::Copy(&aHeader.iFlags, &tmpHeader[8], 2);
   1.641 +	Mem::Copy(&aHeader.iCompressionMethod, &tmpHeader[10], 2);
   1.642 +	Mem::Copy(&aHeader.iLastModifiedFileTime, &tmpHeader[12], 2);
   1.643 +	Mem::Copy(&aHeader.iLastModifiedFileDate, &tmpHeader[14], 2);
   1.644 +	Mem::Copy(&aHeader.iCRC32, &tmpHeader[16], 4);
   1.645 +	Mem::Copy(&aHeader.iCompressedSize, &tmpHeader[20], 4);
   1.646 +	Mem::Copy(&aHeader.iUncompressedSize, &tmpHeader[24], 4);
   1.647 +	Mem::Copy(&aHeader.iFileNameLength, &tmpHeader[28], 2);
   1.648 +	Mem::Copy(&aHeader.iExtraFieldLength, &tmpHeader[30], 2);
   1.649 +	Mem::Copy(&aHeader.iFileCommentLength, &tmpHeader[32], 2);
   1.650 +	Mem::Copy(&aHeader.iDiskNumberStart, &tmpHeader[34], 2);
   1.651 +	Mem::Copy(&aHeader.iInternalFileAttributes, &tmpHeader[36], 2);
   1.652 +	Mem::Copy(&aHeader.iExternalFileAttributes, &tmpHeader[38], 4);
   1.653 +	Mem::Copy(&aHeader.iLocalHeaderOffset, &tmpHeader[42], 4);
   1.654 +
   1.655 +	aMemberPointer.iCRC32             = aHeader.iCRC32;
   1.656 +	aMemberPointer.iCompressedSize    = aHeader.iCompressedSize;
   1.657 +	aMemberPointer.iUncompressedSize  = aHeader.iUncompressedSize;
   1.658 +	aMemberPointer.iLocalHeaderOffset = aHeader.iLocalHeaderOffset;
   1.659 +    aMemberPointer.iName = new(ELeave) TFileName;
   1.660 +	
   1.661 +	TBuf8<KMaxFileName> input;
   1.662 +	if (iData->Read(input, aHeader.iFileNameLength) != KErrNone)
   1.663 +		{
   1.664 +		return KZipFileIOError;
   1.665 +		}
   1.666 +	ConvertFileNameToUnicodeL(*aMemberPointer.iName, input, aHeader.iMadeBy, aConverter, aConverterState, iFs);
   1.667 +	
   1.668 +    // Ignore the remaining fields
   1.669 +	TInt pos;
   1.670 +
   1.671 +	pos = aHeader.iExtraFieldLength;	
   1.672 +	if (pos != 0)
   1.673 +		{
   1.674 +		// Don't pass aHeader.iExtraFieldLength in place of pos
   1.675 +		// as the below function will update the content of that variable.
   1.676 +		// In this case, the function is used to ignore the data
   1.677 +		// by just moving the current file pointer location.
   1.678 +		if (iData->Seek(ESeekCurrent, pos) != KErrNone) 
   1.679 +			{
   1.680 +			return KZipFileIOError;
   1.681 +			}
   1.682 +		}
   1.683 +
   1.684 +	pos = aHeader.iFileCommentLength;
   1.685 +	if (pos != 0)
   1.686 +		{
   1.687 +		// Don't pass aHeader.iFileCommentLength in place of pos
   1.688 +		// as the below function will update the content of that variable.
   1.689 +		// In this case, the function is used to ignore the data
   1.690 +		// by just moving the current file pointer location.
   1.691 +		if (iData->Seek(ESeekCurrent, pos) != KErrNone) 
   1.692 +			{
   1.693 +			return KZipFileIOError;
   1.694 +			}
   1.695 +		}
   1.696 +
   1.697 +  	return  KErrNone;
   1.698 +}
   1.699 +
   1.700 +TInt CZipFile::ReadLocalHeader(TUint32 aOffset, TLocalHeader& aHeader)
   1.701 +/*
   1.702 +As this function might be called many times and the request will 
   1.703 +eventually be translated to calls to server to read the data, 
   1.704 +so performance is the major issue. Try to minimize calls to server.
   1.705 +Read data in a chunk rather than member-by-member.
   1.706 +*/
   1.707 +	{
   1.708 +	TByte tmpHeader[KLocalHeaderFixedLength];
   1.709 +
   1.710 +	if (Seek(aOffset) != KErrNone)
   1.711 +		{
   1.712 +		return KZipFileIOError;
   1.713 +		}
   1.714 +	if (Read(tmpHeader,KLocalHeaderFixedLength) != KErrNone)
   1.715 +		{
   1.716 +		return KZipFileIOError;
   1.717 +		}
   1.718 +	Mem::Copy(&aHeader.iSignature, &tmpHeader[0], 4);
   1.719 +
   1.720 +	if (aHeader.iSignature != KLocalHeaderSignature)
   1.721 +		{
   1.722 +		return KLocalHeaderSignatureInvalid;
   1.723 +		}
   1.724 +
   1.725 +	Mem::Copy(&aHeader.iVersionNeeded, &tmpHeader[4], 2);
   1.726 +	Mem::Copy(&aHeader.iFlags, &tmpHeader[6], 2);
   1.727 +	Mem::Copy(&aHeader.iCompressionMethod, &tmpHeader[8], 2);
   1.728 +	Mem::Copy(&aHeader.iLastModifiedFileTime, &tmpHeader[10], 2);
   1.729 +	Mem::Copy(&aHeader.iLastModifiedFileDate, &tmpHeader[12], 2);
   1.730 +	Mem::Copy(&aHeader.iCRC32, &tmpHeader[14], 4);
   1.731 +	Mem::Copy(&aHeader.iCompressedSize, &tmpHeader[18], 4);
   1.732 +	Mem::Copy(&aHeader.iUncompressedSize, &tmpHeader[22], 4);
   1.733 +	Mem::Copy(&aHeader.iFileNameLength, &tmpHeader[26], 2);
   1.734 +	Mem::Copy(&aHeader.iExtraFieldLength, &tmpHeader[28], 2);
   1.735 +
   1.736 +	return  KErrNone;
   1.737 +	}
   1.738 +	
   1.739 +const CZipFile::TMemberPointer* CZipFile::FindMemberPointer(const TDesC& aName, TBool aCaseInsensitive)
   1.740 +	{
   1.741 +	for (TUint32 i = 0; i < iTrailer.iTotalEntryCount; i++)
   1.742 +		{
   1.743 +		if (aCaseInsensitive && (!aName.CompareF(*iMemberPointers[i].iName)))
   1.744 +			{
   1.745 +			return iMemberPointers + i;
   1.746 +			}
   1.747 +		else if (aName == *iMemberPointers[i].iName)
   1.748 +			{
   1.749 +			return iMemberPointers + i;
   1.750 +			}
   1.751 +		}
   1.752 +	return NULL;
   1.753 +	}
   1.754 +
   1.755 +RZipFileMemberReaderStream* CZipFile::MakeInputStreamL(
   1.756 +							TUint32 aDataOffset, 
   1.757 +							TUint32 aCompressedSize, 
   1.758 +							TUint32 aUncompressedSize, 
   1.759 +							TUint32 aCompressionMethod)
   1.760 +	{
   1.761 +	return RZipFileMemberReaderStream::NewL(
   1.762 +						    *this,
   1.763 +							aDataOffset,
   1.764 +							aCompressedSize,
   1.765 +							aUncompressedSize, 
   1.766 +							aCompressionMethod);
   1.767 +	}
   1.768 +
   1.769 +CZipFileMember* CZipFile::MakeMemberL(TInt aMemberIndex)
   1.770 +	{
   1.771 +	TLocalHeader    header;
   1.772 +	TMemberPointer*	memberPointer;
   1.773 +	
   1.774 +	if (aMemberIndex >= iTrailer.iTotalEntryCount)
   1.775 +		{
   1.776 +		return NULL;
   1.777 +		}
   1.778 +	memberPointer = iMemberPointers + aMemberIndex;
   1.779 +	if (ReadLocalHeader(memberPointer->iLocalHeaderOffset, header) != KErrNone)
   1.780 +		{
   1.781 +		return NULL;
   1.782 +		}
   1.783 +	else
   1.784 +		{
   1.785 +		return MakeMemberL(*memberPointer, header);
   1.786 +		}
   1.787 +	}
   1.788 +	
   1.789 +CZipFileMember* CZipFile::MakeMemberL(
   1.790 +                              const TMemberPointer& aMemberPointer, 
   1.791 +			                  const TLocalHeader&   aHeader)
   1.792 +	{
   1.793 +	CZipFileMember* member;
   1.794 +	
   1.795 +	member = new (ELeave) CZipFileMember;
   1.796 +	CleanupStack::PushL(member);
   1.797 +	member->iCRC32 = aMemberPointer.iCRC32;
   1.798 +	member->iCompressedSize = aMemberPointer.iCompressedSize;
   1.799 +	member->iCompressionMethod = aHeader.iCompressionMethod;
   1.800 +	member->iName = new (ELeave) TFileName(*aMemberPointer.iName);
   1.801 +	TInt loop=0;
   1.802 +	while (loop < member->iName->Length())
   1.803 +		{
   1.804 +		if ((*member->iName)[loop] == '/')
   1.805 +			{
   1.806 +			(*member->iName)[loop] = '\\';
   1.807 +			}
   1.808 +		loop++;
   1.809 +		}
   1.810 +	member->iUncompressedSize = aMemberPointer.iUncompressedSize;
   1.811 +	member->iDataOffset = aMemberPointer.iLocalHeaderOffset + 
   1.812 +		                  KLocalHeaderFixedLength + 
   1.813 +						  aHeader.iFileNameLength + 
   1.814 +						  aHeader.iExtraFieldLength;
   1.815 +	CleanupStack::Pop();
   1.816 +	return member;
   1.817 +	}
   1.818 +
   1.819 +void CZipFile::DeleteMemberPointers()
   1.820 +	{
   1.821 +	if (iMemberPointers)
   1.822 +		{
   1.823 +		for (TUint32 i = 0; i < iTrailer.iTotalEntryCount; i++)
   1.824 +			{
   1.825 +			delete iMemberPointers[i].iName;
   1.826 +			}
   1.827 +		delete[] iMemberPointers;
   1.828 +		iMemberPointers = 0;
   1.829 +		}
   1.830 +
   1.831 +	delete iData;
   1.832 +	iData = NULL;
   1.833 +	return;
   1.834 +	}
   1.835 +
   1.836 +void CZipFile::OpenFileL(const TDesC& aFileName)
   1.837 +	{
   1.838 +	// We need to look at the session path of the filesystem passed
   1.839 +	// in to derive the fullpath of the file to open
   1.840 +	HBufC* sessionPath = HBufC::NewLC(KMaxFileName);
   1.841 +	TPtr ptr(sessionPath->Des());
   1.842 +	User::LeaveIfError(iFs.SessionPath(ptr));
   1.843 +	TParse parse;
   1.844 +	User::LeaveIfError(parse.Set(aFileName, sessionPath, NULL));
   1.845 +	
   1.846 +	// Use the full name derived from the session path
   1.847 +	ContentAccess::CContent* content = 
   1.848 +		ContentAccess::CContent::NewL(parse.FullName());
   1.849 +	CleanupStack::PushL(content);
   1.850 +	iData = content->OpenContentL(ContentAccess::EPeek);
   1.851 +
   1.852 +	// Parent content object no longer needed because we only need data
   1.853 +	CleanupStack::PopAndDestroy(content);
   1.854 +
   1.855 +	// Seek to the end
   1.856 +	TInt length = 0;
   1.857 +	User::LeaveIfError(iData->Seek(ESeekEnd, length));
   1.858 +	iFileLength = length;
   1.859 +	CleanupStack::PopAndDestroy(sessionPath);
   1.860 +	}
   1.861 +
   1.862 +TInt CZipFile::Read(TUint16& aUs)
   1.863 +	{
   1.864 +	TPckgBuf<TUint16> temp(aUs);
   1.865 +	
   1.866 +	if (iData->Read(temp) != KErrNone)
   1.867 +		{
   1.868 +		return KZipFileIOError;
   1.869 +		}
   1.870 +	
   1.871 +	aUs=temp();
   1.872 +	return KErrNone;
   1.873 +	}
   1.874 +	
   1.875 +TInt CZipFile::Read(TUint32& aUl)
   1.876 +	{
   1.877 +	TPckgBuf<TUint32> temp;
   1.878 +	
   1.879 +	if (iData->Read(temp) != KErrNone)
   1.880 +		{
   1.881 +		return KZipFileIOError;
   1.882 +		}
   1.883 +	aUl=temp();
   1.884 +	return KErrNone;
   1.885 +	}
   1.886 +
   1.887 +TInt CZipFile::Read(TByte* aBytes, TUint32 aLength)
   1.888 +
   1.889 +	{
   1.890 +	TPtr8 ptr(aBytes, aLength);
   1.891 +	if(iData->Read(ptr, aLength))
   1.892 +		{
   1.893 +		return KZipFileIOError;
   1.894 +		}
   1.895 +	else
   1.896 +		{
   1.897 +		return KErrNone;
   1.898 +		}
   1.899 +	}
   1.900 +	
   1.901 +TInt CZipFile::Seek(TInt aOffset)
   1.902 +	{
   1.903 +	if (iData->Seek(ESeekStart, aOffset) < 0) 
   1.904 +		{
   1.905 +		return KZipFileIOError;
   1.906 +		}
   1.907 +	else
   1.908 +		{
   1.909 +		return KErrNone;
   1.910 +		}
   1.911 +	}
   1.912 +