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 +