imaging/imagingplugins/codecs/JPEGCodec/Exif/ifdgeneral.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     1 // Copyright (c) 2004-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 //
       
    15 
       
    16 #include "ifdgeneral.h"
       
    17 #include "ifdgeneralentry.h"
       
    18 #include "ExifTagDescriptions.h"
       
    19 #include "exifreaderwriter.h"
       
    20 #include "ExifTagHelper.h"
       
    21 #include <bafl/sysutil.h>
       
    22 
       
    23 // Number of consecutive invalid IFD entries that may appear before the whole IFD is considered corrupt
       
    24 // This value is set in the ExifLibStatic.mmp file, the default is 7.
       
    25 const TUint KMaxNumberOfConsecInvalidEntries = SYMBIAN_ICL_EXIF_CONSEC_INVALID_TAGS;
       
    26 
       
    27 CIfdGeneral::CIfdGeneral(const TInt aIfdNumber, const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
    28 	: iIfdNumber(aIfdNumber)
       
    29 	, iIntel(aIntel)
       
    30 	, iOffsetToIfd(aOffsetToIfd)
       
    31 	, iBase(aBase)
       
    32 	, iExifDataLength(aExifDataLength)
       
    33 	{	
       
    34 	}
       
    35 
       
    36 CIfdGeneral::~CIfdGeneral()
       
    37 	{
       
    38 	iIfdEntries.ResetAndDestroy();
       
    39 	}
       
    40 	
       
    41 void CIfdGeneral::ConstructL()
       
    42 	{
       
    43 	if(iBase)
       
    44 		{
       
    45 		// read the entries from the data block
       
    46 		AddAllIfdEntriesL();
       
    47 		}
       
    48 	else
       
    49 		{
       
    50 		// create default entries
       
    51 		SetupDirectoryEntriesL();
       
    52 		}
       
    53 	}
       
    54 
       
    55 // Alters a directory in a given IFD - used when the directory is known to exist 
       
    56 // (i.e. for mandatory entries) which are set/created upon initialisation.
       
    57 TInt CIfdGeneral::SetParam8(const TUint aTag, HBufC8* aParam)
       
    58 	{	
       
    59 	ASSERT(aParam!=NULL);
       
    60 		
       
    61 	// find the entry with the required tag.
       
    62 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
    63 		{
       
    64 		if(aTag == iIfdEntries[i]->Tag())
       
    65 			{
       
    66 			// Found the tag.
       
    67 			// May be undefined type or ascii type.
       
    68 			if(iIfdEntries[i]->IsStringFormat())
       
    69 				{
       
    70 				//pass in ifd number as the same ascii tag may be in more than one ifd
       
    71 				return iIfdEntries[i]->UpdateString(aParam);				
       
    72 				}
       
    73 			else if(iIfdEntries[i]->IsUndefinedFormat())
       
    74 				{
       
    75 				return iIfdEntries[i]->UpdateData(aParam->Length(), aParam->Des().Ptr());	
       
    76 				}
       
    77 			else if (iIfdEntries[i]->Format()==EByte)
       
    78 				{
       
    79 				//we need to support byte entries too as they are Param8
       
    80 				return iIfdEntries[i]->UpdateData(aParam->Length(), aParam->Des().Ptr());
       
    81 				}			
       
    82 			}
       
    83 		}
       
    84 	return KErrNotSupported;
       
    85 	}
       
    86 	
       
    87 TInt CIfdGeneral::SetParam16(const TUint aTag, HBufC16* aParam)
       
    88 	{	
       
    89 	ASSERT(aParam!=NULL);
       
    90 			
       
    91 	// find the entry with the required tag.
       
    92 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
    93 		{
       
    94 		if(aTag == iIfdEntries[i]->Tag())
       
    95 			{
       
    96 			// Found the tag.			
       
    97 			HBufC8* extendedData=NULL;
       
    98 			TRAPD(err, extendedData=TExifTagHelper::CreateUnicodePrefixedBufferL(*aParam));
       
    99 			if(err!=KErrNone)
       
   100 				{
       
   101 				return KErrNoMemory;
       
   102 				} 
       
   103 			TInt componentCount=extendedData->Length();
       
   104 			TInt updateErr = iIfdEntries[i]->UpdateData(componentCount, extendedData->Des().Ptr()); 
       
   105 			delete extendedData;		
       
   106 			return updateErr;
       
   107 			}
       
   108 		}
       
   109 	return KErrNotSupported;
       
   110 	}
       
   111 	
       
   112 TInt CIfdGeneral::SetIntegerParam(const TUint aTag, const TInt aParam)
       
   113 	{
       
   114 	// find the entry with the required tag.
       
   115 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   116 		{
       
   117 		if(aTag == iIfdEntries[i]->Tag())
       
   118 			{
       
   119 			// Found the tag.
       
   120 			return iIfdEntries[i]->UpdateInteger(aParam);
       
   121 			}
       
   122 		}
       
   123 	return KErrNotSupported;
       
   124 	}
       
   125 	
       
   126 TInt CIfdGeneral::SetShortParam(const TUint aTag, const TUint16 aParam)
       
   127 	{
       
   128 	// find the entry with the required tag.
       
   129 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   130 		{
       
   131 		if(aTag == iIfdEntries[i]->Tag())
       
   132 			{
       
   133 			// Found the tag.
       
   134 			return iIfdEntries[i]->UpdateShort(aParam);
       
   135 			}
       
   136 		}
       
   137 	return KErrNotSupported;
       
   138 	}
       
   139 
       
   140 TInt CIfdGeneral::SetRationalParam(const TUint aTag, const TInt aNumerator, const TInt aDenominator)
       
   141 	{
       
   142 	// find the entry with the required tag.
       
   143 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   144 		{
       
   145 		if(aTag == iIfdEntries[i]->Tag())
       
   146 			{
       
   147 			// Found the tag.
       
   148 			return iIfdEntries[i]->UpdateRational(aNumerator, aDenominator);
       
   149 			}
       
   150 		}
       
   151 	return KErrNotSupported;
       
   152 	}
       
   153 
       
   154 
       
   155 /* 
       
   156 Add a directory in a given IFD - used for the optional directories, since these are not
       
   157 set/created upon initialisation.  Must check for existence of the tag along with validity
       
   158 of adding the tag to this particular IFD.
       
   159 */
       
   160 void CIfdGeneral::AddParam8L(const TUint aTag, const TUint aFormat, const TUint aComponentCount, HBufC8* aParam)
       
   161 	{
       
   162 	ASSERT(aParam!=NULL);
       
   163 		
       
   164 	TInt err = KErrNotSupported;
       
   165 	
       
   166 	// Check that aTag belongs in this IFD.
       
   167 	TInt index = GetTagIndex(aTag);
       
   168 	if(index != KErrNotFound)
       
   169 		{
       
   170 		//The length is checked, but really it should be done in the IfdEntry
       
   171 		TUint paramLength=aParam->Length();
       
   172 		const TUint* tag = GetTagInformation(index);
       
   173 		TUint requiredComponentCount=tag[EComponentCountValue];
       
   174 		TBool legal=EFalse;
       
   175 		if((requiredComponentCount==0) || (aFormat!=EAscii))
       
   176 			{
       
   177 			//Either this tag can be of any length (so no further length checks needed)
       
   178 			//or it is not ASCII, which means it simply has to be at least as long
       
   179 			//as the required length
       
   180 			legal=(paramLength >= requiredComponentCount * KDataFormatSize[aFormat]);	
       
   181 			}
       
   182 		else
       
   183 			{
       
   184 			//We have a fixed length ASCII string.  For such strings we must
       
   185 			//consider NULL termination.  Considering that we add the NULL if the 
       
   186 			//user forgets to add it for other tags, we should do it here as well 
       
   187 			//to be consistent.
       
   188 			if (paramLength==requiredComponentCount)
       
   189 				{
       
   190 				//The string is already of the max length so it is only legal if it is NULL
       
   191 				//terminated
       
   192 				legal=((*aParam)[paramLength-1] == KNullCharacter);	
       
   193 				}
       
   194 			else if (paramLength==requiredComponentCount-1)
       
   195 				{
       
   196 				//The string is one less than the required length.  If it is NULL terminated already,
       
   197 				//then the string is too short (illegal).  If it is not NULL terminated, we let it
       
   198 				//pass anyway and CEncoderIfdEntry software will add the NULL.  
       
   199 				legal=((*aParam)[paramLength-1] != KNullCharacter);						
       
   200 				}
       
   201 			else
       
   202 				{
       
   203 				//Strings that pass the first two checks are only legal if exactly the
       
   204 				//required length.
       
   205 				legal=(paramLength == requiredComponentCount);	
       
   206 				}
       
   207 			}
       
   208 		if (legal)				
       
   209 			{
       
   210 			// Entry is legal, so add entry.
       
   211 			const TUint8* valueOffset = aParam->Des().Ptr();			
       
   212 			CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, valueOffset, this);
       
   213 			iIfdEntries.AppendL(entry);
       
   214 			CleanupStack::Pop(entry);
       
   215 			err = KErrNone;
       
   216 			}
       
   217 		else
       
   218 			{
       
   219 			err = KErrNotSupported;
       
   220 			}
       
   221 		}
       
   222 	User::LeaveIfError(err);
       
   223 	}
       
   224 	
       
   225 void CIfdGeneral::AddParam16L(const TUint aTag, const TUint aFormat, const TUint /*aComponentCount*/, HBufC16* aParam)
       
   226 	{
       
   227 	ASSERT(aParam!=NULL);
       
   228 		
       
   229 	TInt err = KErrNotSupported;
       
   230 	
       
   231 	// Check that aTag belongs in this IFD.
       
   232 	TInt index = GetTagIndex(aTag);
       
   233 	if(index != KErrNotFound)
       
   234 		{	
       
   235 		TUint paramLength=aParam->Length();
       
   236 		const TUint* tag = GetTagInformation(index);
       
   237 		if( (paramLength >= tag[EComponentCountValue] * KDataFormatSize[aFormat]))
       
   238 			{				
       
   239 			
       
   240 			// Entry is legal, so add entry.
       
   241 			// Must add UNICODE\0 to start of data.				
       
   242 			TInt size = aParam->Length()*2 + KUnicode().Length();
       
   243 			TUint8* data = static_cast<TUint8*>(User::AllocL(size));								
       
   244 			CleanupStack::PushL(data);
       
   245 			
       
   246 			Mem::Copy(data, KUnicode().Ptr(), KUnicode().Length());
       
   247 			Mem::Copy(data+KUnicode().Length(), aParam->Des().Ptr(), aParam->Length()*2);												
       
   248 			
       
   249 			CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, size, data, this);
       
   250 			iIfdEntries.AppendL(entry);
       
   251 			CleanupStack::Pop(entry);
       
   252 			CleanupStack::PopAndDestroy(data);
       
   253 			err = KErrNone;		
       
   254 			}
       
   255 		} 
       
   256 	User::LeaveIfError(err);
       
   257 	}
       
   258 
       
   259 	
       
   260 void CIfdGeneral::AddIntegerParamL(const TUint aTag, const TUint aFormat, const TUint aComponentCount, TInt aParam)
       
   261 	{
       
   262 	TInt err = KErrNotSupported;
       
   263 	
       
   264 	// Check that aTag belongs in this IFD.
       
   265 	if(FindTag(aTag))
       
   266 		{
       
   267 		// Entry is legal, so add entry.
       
   268 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, reinterpret_cast<const TUint8*>(&aParam), this);
       
   269 		iIfdEntries.AppendL(entry);
       
   270 		CleanupStack::Pop(entry);
       
   271 		err = KErrNone;		
       
   272 		} 
       
   273 	User::LeaveIfError(err);
       
   274 	}
       
   275 	
       
   276 void CIfdGeneral::AddShortParamL(const TUint aTag, const TUint aFormat, const TUint aComponentCount, TUint16 aParam)
       
   277 	{
       
   278 	TInt err = KErrNotSupported;
       
   279 	
       
   280 	// Check that aTag belongs in this IFD.
       
   281 	if(FindTag(aTag))
       
   282 		{
       
   283 		// Entry is legal, so add entry.
       
   284 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, reinterpret_cast<const TUint8*>(&aParam),this);
       
   285 		iIfdEntries.AppendL(entry);
       
   286 		CleanupStack::Pop(entry);
       
   287 		err = KErrNone;		
       
   288 		} 
       
   289 	User::LeaveIfError(err);
       
   290 	}
       
   291 	
       
   292 void CIfdGeneral::AddRationalParamL(const TUint aTag, const TUint aFormat, const TUint aComponentCount, const TInt aNumerator, const TInt aDenominator)
       
   293 	{
       
   294 	TInt err = KErrNotSupported;
       
   295 	
       
   296 	// Check that aTag belongs in this IFD.
       
   297 	if(FindTag(aTag))
       
   298 		{
       
   299 		TUint8* valueOffset = static_cast<TUint8*>(User::AllocL(KSizeOfRational));
       
   300 		CleanupStack::PushL(valueOffset);
       
   301 		
       
   302 		// Entry is legal, so add entry.
       
   303 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aComponentCount, valueOffset, this);
       
   304 		User::LeaveIfError(entry->UpdateRational(aNumerator, aDenominator));
       
   305 		iIfdEntries.AppendL(entry);
       
   306 		CleanupStack::Pop(entry);
       
   307 		CleanupStack::PopAndDestroy(valueOffset);
       
   308 	
       
   309 		err = KErrNone;			
       
   310 		} 
       
   311 	if(err != KErrNone)
       
   312 		{
       
   313 		User::LeaveIfError(err);			
       
   314 		}
       
   315 	return;
       
   316 	}
       
   317 
       
   318 
       
   319 
       
   320 void CIfdGeneral::SetIntegerArrayParamL(const TUint aTag, const CArrayFix<TInt>& aParam)
       
   321 	{
       
   322 	TInt err = KErrNotSupported;
       
   323 	
       
   324 	// find the entry with the required tag.
       
   325 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   326 		{
       
   327 		if(aTag == iIfdEntries[i]->Tag())
       
   328 			{
       
   329 			// Found the tag.
       
   330 			HBufC8* ptr = HBufC8::NewL(aParam.Count()*K32BitIntegerByteCount/K8BitIntegerByteCount);
       
   331 			CleanupStack::PushL(ptr);
       
   332 			const TUint8* bytePtr = ptr->Des().Ptr();
       
   333 			TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr));								
       
   334 			for(TInt j = 0; j < aParam.Count(); j++)
       
   335 				{
       
   336 				TInt value = aParam.At(j);
       
   337 				dataPtr[j] = value;
       
   338 				}
       
   339 			User::LeaveIfError(iIfdEntries[i]->UpdateData(aParam.Count(), bytePtr));
       
   340 			CleanupStack::PopAndDestroy(ptr);
       
   341 			err = KErrNone;
       
   342 			}
       
   343 		}
       
   344 	User::LeaveIfError(err);
       
   345 	}
       
   346 
       
   347 void CIfdGeneral::AddIntegerArrayParamL(const TUint aTag, const TUint aFormat, const CArrayFix<TInt>& aParam)
       
   348 	{
       
   349 	TInt err = KErrNotSupported;
       
   350 	
       
   351 	// Check that aTag belongs in this IFD.
       
   352 	if(FindTag(aTag))
       
   353 		{
       
   354 		// Entry is legal, so add entry.
       
   355 		HBufC8* ptr = HBufC8::NewL(aParam.Count()*K32BitIntegerByteCount/K8BitIntegerByteCount);
       
   356 		CleanupStack::PushL(ptr);
       
   357 		const TUint8* bytePtr = ptr->Des().Ptr();
       
   358 		TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr));								
       
   359 		for(TInt i = 0; i < aParam.Count(); i++)
       
   360 			{
       
   361 			TInt value = aParam.At(i);
       
   362 			dataPtr[i] = value;
       
   363 			}
       
   364 
       
   365 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aParam.Count(), bytePtr, this);								
       
   366 		iIfdEntries.AppendL(entry);
       
   367 		CleanupStack::Pop(entry);
       
   368 		CleanupStack::PopAndDestroy(ptr);
       
   369 		err = KErrNone;					
       
   370 		}
       
   371 	User::LeaveIfError(err);
       
   372 	}
       
   373 
       
   374 void CIfdGeneral::AddRationalArrayParamL(const TUint aTag, const TUint aFormat, const CArrayFix<TRational>& aParam)
       
   375 	{
       
   376 	TInt err = KErrNotSupported;
       
   377 	// Check that aTag belongs in this IFD.
       
   378 	if(FindTag(aTag))
       
   379 		{
       
   380 		// Entry is legal, so add entry.
       
   381 		HBufC8* ptr = HBufC8::NewL((aParam.Count()*2) * K32BitIntegerByteCount);
       
   382 		CleanupStack::PushL(ptr);
       
   383 		const TUint8* bytePtr = ptr->Des().Ptr();
       
   384 		TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr));
       
   385 		TInt ptrInc = 0;
       
   386 		for(TInt i = 0; i < aParam.Count(); i++)
       
   387 			{
       
   388 			TInt numer = (aParam.At(i)).iNumerator;
       
   389 			TInt denom = (aParam.At(i)).iDenominator;
       
   390 			dataPtr[ptrInc++] = numer;
       
   391 			dataPtr[ptrInc++] = denom;
       
   392 			}
       
   393 
       
   394 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aParam.Count(), bytePtr, this);								
       
   395 		iIfdEntries.AppendL(entry);
       
   396 		CleanupStack::Pop(entry);
       
   397 		CleanupStack::PopAndDestroy(ptr);
       
   398 		err = KErrNone;						
       
   399 		} 
       
   400 	User::LeaveIfError(err);
       
   401 	}
       
   402 	
       
   403 void CIfdGeneral::SetRationalArrayParamL(const TUint aTag, const CArrayFix<TRational>& aParam)
       
   404 	{
       
   405 	TInt err = KErrNotSupported;
       
   406 	// find the entry with the required tag.
       
   407 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   408 		{
       
   409 		if(aTag == iIfdEntries[i]->Tag())
       
   410 			{
       
   411 			// Found the tag.
       
   412 			HBufC8* ptr = HBufC8::NewL((aParam.Count()*2) * K32BitIntegerByteCount);
       
   413 			CleanupStack::PushL(ptr);
       
   414 			const TUint8* bytePtr = ptr->Des().Ptr();
       
   415 			TInt* dataPtr = const_cast<TInt*>(reinterpret_cast<const TInt*>(bytePtr));
       
   416 			TInt ptrInc = 0;
       
   417 			for(TInt j = 0; j < aParam.Count(); j++)
       
   418 				{
       
   419 				TInt numer = (aParam.At(j)).iNumerator;
       
   420 				TInt denom = (aParam.At(j)).iDenominator;
       
   421 				dataPtr[ptrInc++] = numer;
       
   422 				dataPtr[ptrInc++] = denom;
       
   423 				}
       
   424 			User::LeaveIfError(iIfdEntries[i]->UpdateData(aParam.Count(), bytePtr));
       
   425 			CleanupStack::PopAndDestroy(ptr);
       
   426 			err = KErrNone;
       
   427 			}
       
   428 		}
       
   429 	User::LeaveIfError(err);
       
   430 	}
       
   431 	
       
   432 	
       
   433 void CIfdGeneral::AddShortArrayParamL(const TUint aTag, const TUint aFormat, const CArrayFix<TUint16>& aParam)
       
   434 	{
       
   435 	TInt err = KErrNotSupported;
       
   436 	// Check that aTag belongs in this IFD.
       
   437 	if(FindTag(aTag))
       
   438 		{
       
   439 		// Entry is legal, so add entry.
       
   440 		HBufC8* ptr = HBufC8::NewL(aParam.Count()*K16BitIntegerByteCount/K8BitIntegerByteCount);
       
   441 		CleanupStack::PushL(ptr);
       
   442 		const TUint8* bytePtr = ptr->Des().Ptr();
       
   443 		TInt16* dataPtr = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(bytePtr));								
       
   444 		for(TInt i = 0; i < aParam.Count(); i++)
       
   445 			{
       
   446 			TInt value = aParam.At(i);
       
   447 			dataPtr[i] = value;
       
   448 			}
       
   449 
       
   450 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(aTag, aFormat, aParam.Count(), bytePtr, this);								
       
   451 		iIfdEntries.AppendL(entry);
       
   452 		CleanupStack::Pop(entry);
       
   453 		CleanupStack::PopAndDestroy(ptr);
       
   454 		err = KErrNone;							
       
   455 		} 
       
   456 	User::LeaveIfError(err);
       
   457 	}
       
   458 
       
   459 void CIfdGeneral::SetShortArrayParamL(const TUint aTag, const CArrayFix<TUint16>& aParam)
       
   460 	{
       
   461 	TInt err = KErrNotSupported;
       
   462 	// Find the entry with the required tag.
       
   463 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   464 		{
       
   465 		if(aTag == iIfdEntries[i]->Tag())
       
   466 			{
       
   467 			HBufC8* ptr = HBufC8::NewL(aParam.Count()*K16BitIntegerByteCount/K8BitIntegerByteCount);
       
   468 			CleanupStack::PushL(ptr);
       
   469 			const TUint8* bytePtr = ptr->Des().Ptr();
       
   470 			TInt16* dataPtr = const_cast<TInt16*>(reinterpret_cast<const TInt16*>(bytePtr));								
       
   471 			for(TInt j = 0; j < aParam.Count(); j++)
       
   472 				{
       
   473 				TInt value = aParam.At(j);
       
   474 				dataPtr[j] = value;
       
   475 				}
       
   476 			User::LeaveIfError(iIfdEntries[i]->UpdateData(aParam.Count(), bytePtr));
       
   477 			CleanupStack::PopAndDestroy(ptr);
       
   478 			err = KErrNone;
       
   479 			}		
       
   480 		}
       
   481 	User::LeaveIfError(err);
       
   482 	}	
       
   483 
       
   484 TInt CIfdGeneral::GetIntegerParam(const TUint aTag, TInt& aParam) const
       
   485 	{
       
   486 	TInt entry = LocateEntry(aTag);
       
   487 	if(entry == KErrNotFound)
       
   488 		{
       
   489 		return KErrNotFound;
       
   490 		}
       
   491 	
       
   492 	// Check that we are dealing with an Integer format.
       
   493 	switch(iIfdEntries[entry]->Format())
       
   494 		{		
       
   495 		case (EUnsignedLong):
       
   496 		case (ESignedLong):
       
   497 			break;
       
   498 		default:
       
   499 			return KErrArgument;
       
   500 		}
       
   501 
       
   502 	// Check the size.
       
   503 	TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()];
       
   504 	if(totalSize > KSizeOfValueOffsetField)
       
   505 		{
       
   506 		// Data is offset, so we are dealing with more than one integer, so this function cannot deal with it.
       
   507 		return KErrArgument;
       
   508 		}
       
   509 	
       
   510 	aParam = iIfdEntries[entry]->ValueOffset();
       
   511 	return KErrNone;
       
   512 	}
       
   513 	
       
   514 	
       
   515 
       
   516 
       
   517 TInt CIfdGeneral::GetShortParam(const TUint aTag, TUint16& aParam) const
       
   518 	{
       
   519 	TInt entry = LocateEntry(aTag);
       
   520 	if(entry == KErrNotFound)
       
   521 		{
       
   522 		return KErrNotFound;
       
   523 		}
       
   524 	
       
   525 	// Check that we are dealing with an short format.
       
   526 	if(iIfdEntries[entry]->Format() != EUnsignedShort)
       
   527 		{
       
   528 		return KErrArgument;
       
   529 		}
       
   530 
       
   531 	// Check the size.
       
   532 	TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()];
       
   533 
       
   534 	 // Since 2 shorts could be in 4 byte field, we only return one!
       
   535 	if(totalSize > KSizeOfValueOffsetField / 2)
       
   536 		{
       
   537 		// Data is offset, so we are dealing with more than one integer, so this function cannot deal with it.
       
   538 		return KErrArgument;
       
   539 		}
       
   540 	
       
   541 	aParam = iIfdEntries[entry]->ValueOffset();
       
   542 
       
   543 	return KErrNone;
       
   544 	}
       
   545 
       
   546 TInt CIfdGeneral::GetRationalParam(const TUint aTag, TInt& aNumer, TInt& aDenom) const
       
   547 	{
       
   548 	TInt entry = LocateEntry(aTag);
       
   549 	if(entry == KErrNotFound)
       
   550 		{
       
   551 		return KErrNotFound;
       
   552 		}
       
   553 	
       
   554 	// Check that we are dealing with an rational format.
       
   555 	switch(iIfdEntries[entry]->Format())
       
   556 		{
       
   557 		case (EUnsignedRational):
       
   558 		case (ESignedRational):
       
   559 			break;
       
   560 		default:
       
   561 			return KErrArgument;
       
   562 		}
       
   563 
       
   564 	// Check the size.
       
   565 	TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()];
       
   566 
       
   567 	// A single rational datum is 8 bytes, so we only deal with single values here.
       
   568 	if(totalSize > KSizeOfValueOffsetField * 2)
       
   569 		{
       
   570 		return KErrArgument;
       
   571 		}
       
   572 	
       
   573 	const TUint8* rationalData = iIfdEntries[entry]->ActualValue();
       
   574 	if(!rationalData)
       
   575 		{
       
   576 		return KErrArgument;
       
   577 		}
       
   578 	Mem::Copy(&aNumer, rationalData, sizeof(aNumer));
       
   579 	Mem::Copy(&aDenom, rationalData+sizeof(aNumer), sizeof(aDenom));
       
   580 	return KErrNone;
       
   581 	}
       
   582 
       
   583 TInt CIfdGeneral::GetParam8(const TUint aTag, HBufC8*& aParam) const
       
   584 	{
       
   585 	TInt entry = LocateEntry(aTag);
       
   586 	if(entry == KErrNotFound)
       
   587 		{
       
   588 		return KErrNotFound;
       
   589 		}
       
   590 	
       
   591 	// Check that we are dealing with correct format.
       
   592 	TUint format = iIfdEntries[entry]->Format();
       
   593 	switch(format)
       
   594 		{
       
   595 		case (EByte):
       
   596 		case (EAscii):
       
   597 		case (EUndefined):
       
   598 			break;
       
   599 		default:
       
   600 			return KErrArgument;
       
   601 		}
       
   602 
       
   603 	// Check the size.
       
   604 	TUint totalSize = iIfdEntries[entry]->ComponentCount();
       
   605 	
       
   606 	delete aParam;
       
   607 	aParam = HBufC8::New(totalSize);				
       
   608 	if(aParam == NULL)
       
   609 		{
       
   610 		return KErrNoMemory;
       
   611 		}
       
   612 		
       
   613 	_LIT8(KStringFormat, "%s");
       
   614 	if(totalSize > KSizeOfValueOffsetField)
       
   615 		{
       
   616 		const TUint8* theData=iIfdEntries[entry]->ActualValue();
       
   617 		if(!theData)
       
   618 			{
       
   619 			return KErrArgument;
       
   620 			}
       
   621 
       
   622 		if (aTag == KTag8298[ETagValue])
       
   623 			{
       
   624 			//the copyright tag is a special case as it can have null mid string
       
   625 			if (*(theData+totalSize-1) == NULL)
       
   626 				{
       
   627 				//we remove null at the end for consistency
       
   628 				totalSize--;
       
   629 				}
       
   630 			aParam->Des().Copy(theData, totalSize);	
       
   631 			}
       
   632 		else if (format == EAscii)
       
   633 			{
       
   634 			aParam->Des().Format(KStringFormat, theData);
       
   635 			}
       
   636 		else
       
   637 			{
       
   638 			aParam->Des().Copy(theData, totalSize);	
       
   639 			}
       
   640 		}
       
   641 	else if (totalSize>0)
       
   642 		{
       
   643 		// Get data from value/offset field.
       
   644 		TInt value = iIfdEntries[entry]->ValueOffset();
       
   645 
       
   646 		if (aTag == KTag8298[ETagValue])
       
   647 			{
       
   648 			//the copyright tag is a special case as it can have null mid string
       
   649 			//note we would only get here if the copyright was <= 4 bytes
       
   650 			if (*(reinterpret_cast<TUint8*>(&value)+totalSize-1) == NULL)
       
   651 				{
       
   652 				//we remove null at the end for consistency
       
   653 				totalSize--;
       
   654 				}
       
   655 			aParam->Des().Copy(reinterpret_cast<TUint8*> (&value), totalSize);	
       
   656 			}
       
   657 		else if (format == EAscii)
       
   658 			{
       
   659 			aParam->Des().Format(KStringFormat, reinterpret_cast<TUint8*> (&value));
       
   660 			}
       
   661 		else
       
   662 			{
       
   663 			aParam->Des().Copy(reinterpret_cast<TUint8*> (&value), totalSize);
       
   664 			}
       
   665 		}
       
   666 	return KErrNone;
       
   667 	}
       
   668 
       
   669 TInt CIfdGeneral::GetParam16(const TUint aTag, HBufC16*& aParam) const
       
   670 	{
       
   671 	TInt entry = LocateEntry(aTag);
       
   672 	if(entry == KErrNotFound)
       
   673 		{
       
   674 		return KErrNotFound;
       
   675 		}
       
   676 	
       
   677 	// Check that we are dealing with the undefined format.
       
   678 	switch(iIfdEntries[entry]->Format())
       
   679 		{
       
   680 		case (EUndefined):
       
   681 			break;
       
   682 		default:
       
   683 			return KErrArgument;
       
   684 		}
       
   685 
       
   686 	// Check the size.
       
   687 	const TInt totalByteSize = iIfdEntries[entry]->ComponentCount();
       
   688 	
       
   689 	delete aParam;
       
   690 	aParam = HBufC16::NewMax((totalByteSize+1)>>1);
       
   691 	if(aParam == NULL)
       
   692 		{
       
   693 		return KErrNoMemory;
       
   694 		}
       
   695 
       
   696 	TPtr ptr(aParam->Des());
       
   697 	Mem::Copy(reinterpret_cast<TText8*>(&ptr[0]), iIfdEntries[entry]->ActualValue(), totalByteSize);
       
   698 
       
   699 	return KErrNone;
       
   700 	}
       
   701 
       
   702 void CIfdGeneral::GetIntegerArrayParamL(const TUint aTag, CArrayFix<TInt>& aParam) const
       
   703 	{
       
   704 	TInt entry = LocateEntry(aTag);
       
   705 	if(entry == KErrNotFound)
       
   706 		{
       
   707 		User::Leave(KErrNotFound);
       
   708 		}
       
   709 	
       
   710 	// Check that we are dealing with an Integer format.
       
   711 	switch(iIfdEntries[entry]->Format())
       
   712 		{
       
   713 		case (EUnsignedLong):
       
   714 		case (ESignedLong):
       
   715 			break;
       
   716 		default:
       
   717 			User::Leave(KErrArgument);
       
   718 		}
       
   719 
       
   720 	// Check the size.
       
   721 	TUint totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()];
       
   722 	if(totalSize > KSizeOfValueOffsetField)
       
   723 		{
       
   724 		// Obviously have multiple entries.
       
   725 		// However, as of Exif 2.2 there are no Integer Array tags defined that have
       
   726 		// more than one entry.
       
   727 		TInt numberOfInts = totalSize / KDataFormatSize[iIfdEntries[entry]->Format()];
       
   728 		aParam.ResizeL(numberOfInts);
       
   729 		const TUint8* dataStream = iIfdEntries[entry]->ActualValue();
       
   730 		if(!dataStream)
       
   731 			{
       
   732 			User::Leave(KErrArgument);
       
   733 			}
       
   734 
       
   735 		TInt value = 0;
       
   736 		for(TInt i = 0; i < numberOfInts; i++)
       
   737 			{
       
   738 			Mem::Copy(&value, dataStream, sizeof(value));
       
   739 			aParam[i] = value;
       
   740 			dataStream += sizeof(value);
       
   741 			}
       
   742 		}
       
   743 	else
       
   744 		{
       
   745 		// A single entry
       
   746 		aParam.ResizeL(1);
       
   747 		aParam[0] = iIfdEntries[entry]->ValueOffset();
       
   748 		}
       
   749 	}
       
   750 
       
   751 void CIfdGeneral::GetShortArrayParamL(const TUint aTag, CArrayFix<TUint16>& aParam) const
       
   752 	{
       
   753 	TInt entry = LocateEntry(aTag);
       
   754 	if(entry == KErrNotFound)
       
   755 		{
       
   756 		User::Leave(KErrNotFound);
       
   757 		}
       
   758 
       
   759 	// Check that we are dealing with an Short format.
       
   760 	TUint format = iIfdEntries[entry]->Format();
       
   761 	if(format != EUnsignedShort)
       
   762 		{
       
   763 		User::Leave(KErrArgument);
       
   764 		}
       
   765 		
       
   766 	// Check the size.
       
   767 	TUint componentCount = iIfdEntries[entry]->ComponentCount();
       
   768 	TUint dataSize = KDataFormatSize[format];
       
   769 	TUint totalSize = componentCount * dataSize;	
       
   770 	if(totalSize > KSizeOfValueOffsetField)
       
   771 		{
       
   772 		// Obviously have multiple entries.
       
   773 		aParam.ResizeL(componentCount);
       
   774 		const TUint8* dataStream = iIfdEntries[entry]->ActualValue();
       
   775 		if(dataStream==NULL)
       
   776 			{
       
   777 			User::Leave(KErrArgument);
       
   778 			}
       
   779 
       
   780 		TUint16 value = 0;
       
   781 		for(TInt i = 0; i < componentCount; i++)
       
   782 			{
       
   783 			Mem::Copy(&value, dataStream, sizeof(value));
       
   784 			aParam[i] = value;
       
   785 			dataStream += sizeof(value);
       
   786 			}
       
   787 		}
       
   788 	else
       
   789 		{
       
   790 		// Either one or two entries
       
   791 		ASSERT((componentCount==1) || (componentCount==2));
       
   792 		aParam.ResizeL(componentCount);
       
   793 		TUint value = iIfdEntries[entry]->ValueOffset();
       
   794 		
       
   795 		// When component count is 1, we read a UShort as a UShort,
       
   796 		// so the byte order is correct on return.
       
   797 		//
       
   798 		// When component count is 2, we read the UShorts as a UInt.
       
   799 		// i.e. Data is stored on DISK as TWO Shorts but read as ONE TUint32.
       
   800 		//
       
   801 		// Example representation of data on Disk:
       
   802 		//    0x0300 0x0500 (Intel II LittleEndian) - 0x0003 & 0x0005 (Motorola MM BigEndian)
       
   803 		//
       
   804 		// For Intel data, it is read in as an Intel UInt and the bytes reversed. 
       
   805 		// This is important as a pointer is usually stored here:
       
   806 		//    0x0300 0500  becomes  0x0005 0003
       
   807 		//
       
   808 
       
   809 		// For Big-endian formatted files
       
   810 		TUint32 highOrderShortMask = 0xFFFF0000;
       
   811 		TUint32 lowOrderShortMask  = 0x0000FFFF;
       
   812 		
       
   813 		if (componentCount==1)
       
   814 			{
       
   815 			aParam[0] = (value & lowOrderShortMask);
       
   816 			}
       
   817 		else
       
   818 			{
       
   819 			if(iIntel)	
       
   820 				{ // II format
       
   821 				aParam[0] = (value & lowOrderShortMask);				
       
   822 				aParam[1] = (value & highOrderShortMask) >> 16;									
       
   823 				}				
       
   824 			else
       
   825 				{ // MM format
       
   826 				aParam[0] = (value & highOrderShortMask) >> 16;									
       
   827 				aParam[1] = (value & lowOrderShortMask);				
       
   828 				}
       
   829 			}
       
   830 		}
       
   831    	}
       
   832 
       
   833 void CIfdGeneral::GetRationalArrayParamL(const TUint aTag, CArrayFix<TRational>& aParam) const
       
   834 	{
       
   835 	TInt entry = LocateEntry(aTag);
       
   836 	if(entry == KErrNotFound)
       
   837 		{
       
   838 		User::Leave(KErrNotFound);
       
   839 		}
       
   840 	
       
   841 	// Check that we are dealing with an Rational format.
       
   842 	switch(iIfdEntries[entry]->Format())
       
   843 		{
       
   844 		case (EUnsignedRational):
       
   845 		case (ESignedRational):
       
   846 			break;
       
   847 		default:
       
   848 			User::Leave(KErrArgument);
       
   849 		}
       
   850 
       
   851 	// Check the size.
       
   852 	TInt totalSize = iIfdEntries[entry]->ComponentCount() * KDataFormatSize[iIfdEntries[entry]->Format()];
       
   853 	// Obviously have multiple entries.
       
   854 	TInt numberOfRationalValues = totalSize / KDataFormatSize[iIfdEntries[entry]->Format()];
       
   855 	aParam.ResizeL(numberOfRationalValues);
       
   856 	const TUint8* dataStream = iIfdEntries[entry]->ActualValue();
       
   857 	if(!dataStream)
       
   858 		{
       
   859 		User::Leave(KErrArgument);
       
   860 		}
       
   861 
       
   862 	TRational rational;
       
   863 	for(TInt i = 0; i < numberOfRationalValues; i++)
       
   864 		{
       
   865 		Mem::Copy(&rational.iNumerator, dataStream, sizeof(rational.iNumerator));
       
   866 		Mem::Copy(&rational.iDenominator, dataStream+sizeof(rational.iNumerator), sizeof(rational.iDenominator));
       
   867 		aParam[i] = rational;
       
   868 		dataStream += sizeof(rational.iNumerator) + sizeof(rational.iDenominator); // Move pointer on 8 bytes.
       
   869 		}
       
   870 	}
       
   871 
       
   872 TInt CIfdGeneral::Size() const
       
   873 	{
       
   874 	TUint totalSize = 0;
       
   875 	// Get the size of each directory entry.
       
   876 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
   877 		{
       
   878 		TInt size = iIfdEntries[i]->TotalSize();
       
   879 		totalSize+=size;				
       
   880 		}
       
   881 	return totalSize;
       
   882 	}
       
   883 	
       
   884 	
       
   885 
       
   886 // Can only be called by the 0th Ifd (otherwise returns KErrNotSupported).
       
   887 TInt CIfdGeneral::GetOffsetToFirstIfd(TUint& aOffset) const
       
   888 	{
       
   889 	if(iIfdNumber == 0)
       
   890 		{
       
   891 		aOffset = CExifReaderWriter::ReadUint32(iIntel, iBase +
       
   892 													(iIfdEntryCount * KMinimumIfdEntrySize)+
       
   893 													sizeof(TUint16)+
       
   894 													iOffsetToIfd);		
       
   895 		return KErrNone;
       
   896 		}
       
   897 	return KErrNotSupported;
       
   898 	}
       
   899 
       
   900 /**
       
   901 	Parses the buffer, extracting the data.
       
   902 	Ignores corrupt IFD entries (e.g. one with a value offset that is beyond the buffer's boundaries)
       
   903 	unless more than KMaxNumberOfConsecInvalidEntries invalid entries appear in succession. In that case
       
   904 	the whole IFD is considered corrupt.
       
   905 	
       
   906 	@leave	KErrNoMemory	If there is insufficient memory to process the data
       
   907 	@leave	KErrCorrupt		If there are more than KMaxNumberOfConsecInvalidEntries consecutive
       
   908 							corrupt entries
       
   909 */
       
   910 void CIfdGeneral::AddAllIfdEntriesL()
       
   911 	{
       
   912 	// Set the Ifd entry count.
       
   913 	iIfdEntryCount = CExifReaderWriter::ReadUint16(iIntel, iBase + iOffsetToIfd);
       
   914 	
       
   915 	const TUint8* ifdPtr = iBase + iOffsetToIfd + sizeof(iIfdEntryCount);
       
   916 	
       
   917 	//check for the validity of the iIfdEntryCount
       
   918 	if(!IsValidIfdEntryCount(iIfdEntryCount))
       
   919 		{//most likely an invalid exif header
       
   920 		User::Leave(KErrCorrupt);		
       
   921 		}
       
   922 
       
   923 	// records if an entry is corrupt
       
   924 	TBool ifdEntryIsCorrupt = EFalse;
       
   925 	
       
   926 	// counter to track the number of consec corrupt ifd entries
       
   927 	// if more than KMaxNumberOfConsecInvalidEntries corrupt ifd entries occurr in a
       
   928 	// row then the entire IFD is deemed to be corrupt and all the iIfdEntries are to
       
   929 	// be deleted
       
   930 	TUint numberOfConsecutiveCorruptIfdEntries = 0;
       
   931 
       
   932 	// initialise the offset, which acts as a pointer increment.
       
   933 	TInt offset = 0;
       
   934 	for(TInt ifdEntry = 0; ifdEntry < iIfdEntryCount; ifdEntry++)
       
   935 		{
       
   936 		ifdEntryIsCorrupt = EFalse;
       
   937 		
       
   938 		// Create the new CIfdEntry to populate.
       
   939 
       
   940 		// Set the general data of the Ifd entry.
       
   941 		TUint16 tag = CExifReaderWriter::ReadUint16(iIntel, ifdPtr + offset+KTagFieldPosition);
       
   942 		TUint16 format = CExifReaderWriter::ReadUint16(iIntel, ifdPtr + offset+KFormatFieldPosition);
       
   943 		TUint componentCount = CExifReaderWriter::ReadUint32(iIntel, ifdPtr + offset+KComponentCountFieldPosition);
       
   944 
       
   945 		// Determine if the data is held in the value/offset or if it is pointed to.
       
   946 		TUint totalSize = 0;
       
   947 		
       
   948 		TUint valueOffset;
       
   949 		TBool endianess = iIntel;
       
   950 		const TUint8* valuePtr = NULL;
       
   951 			
       
   952 		if (!(format < KDataFormatSizeLength) ||
       
   953 			((totalSize = componentCount * KDataFormatSize[format]) > iExifDataLength) ||
       
   954 			(totalSize == 0) ||
       
   955 			(tag == NULL && !AllowNullTags())) //null tag is valid for GPS IFD
       
   956 			{
       
   957 			// if invalid format or size is unreasonable this IFD entry is corrupt
       
   958 			// (second check is a bit crude but worthwhile since it
       
   959 			//  can catch some obviously invalid entries early on)
       
   960 			ifdEntryIsCorrupt = ETrue;
       
   961 			}
       
   962 		else
       
   963 			{
       
   964 			if (((format == EAscii)||(format == EByte)||(format == EUndefined)) && (totalSize <= KSizeOfValueOffsetField))
       
   965 				{
       
   966 				//If the above condition is true then the data is such that it needs to 
       
   967 				//keep the byte order as is ie an ASCII field, a byte field or an undefined field
       
   968 				//if this is the case we do not want to invert the bytes for big endian/motorola
       
   969 				//ie order is unchanged
       
   970 				//if the data is greater than 4 bytes then it should be copied across as is
       
   971 				endianess = ETrue; //so set endianess to Intel even if the file is motorola
       
   972 				}
       
   973 			if(totalSize <= sizeof(TUint16))
       
   974 				{
       
   975 				valueOffset = CExifReaderWriter::ReadUint16(endianess, ifdPtr + offset+KValueOffsetFieldPosition);
       
   976 				}
       
   977 			else
       
   978 				{
       
   979 				valueOffset = CExifReaderWriter::ReadUint32(endianess, ifdPtr + offset+KValueOffsetFieldPosition);
       
   980 				}
       
   981 					
       
   982 			if (totalSize>KSizeOfValueOffsetField)
       
   983 				{
       
   984 				if((valueOffset) && ((valueOffset + totalSize) <= iExifDataLength))
       
   985 					{
       
   986 					valuePtr = iBase+valueOffset;
       
   987 					}
       
   988 				else
       
   989 					{
       
   990 					// the offset is either null, pointing beyond the length of the exif data or
       
   991 					// pointing to a value which goes beyond the length of the exif data
       
   992 					// ie we are dealing with a corrupt entry
       
   993 					ifdEntryIsCorrupt = ETrue;
       
   994 					}
       
   995 				}
       
   996 			else
       
   997 				{
       
   998 				valuePtr = reinterpret_cast<const TUint8*> (&valueOffset);
       
   999 				}
       
  1000 			}
       
  1001 			
       
  1002 		// try to make the entry
       
  1003 		CIfdGeneralEntry* entry = NULL;
       
  1004 		if(!ifdEntryIsCorrupt)
       
  1005 			{
       
  1006 			// entries with unknown tags are created but count towards corrupt entries
       
  1007 			// so that if many appear in succession we assume the IFD is corrupt
       
  1008 			entry = CreateIfdEntryLC(tag, format, componentCount, valuePtr, valueOffset, totalSize, ifdEntryIsCorrupt);
       
  1009 			
       
  1010 			if(!entry)
       
  1011 				{
       
  1012 				ifdEntryIsCorrupt = ETrue;
       
  1013 				}
       
  1014 			}		
       
  1015 			
       
  1016 		//an entry of all 0's could be padding so don't count it as corrupt
       
  1017 		if ((ifdEntryIsCorrupt) && !((tag == 0)&&(format == 0)&&(componentCount == 0)))
       
  1018 			{
       
  1019 			numberOfConsecutiveCorruptIfdEntries++;
       
  1020 			if ((numberOfConsecutiveCorruptIfdEntries == iIfdEntryCount)||(numberOfConsecutiveCorruptIfdEntries > KMaxNumberOfConsecInvalidEntries))
       
  1021 				{
       
  1022 				//if the above condition is true then it is likely that we are scanning the IFD from the offset
       
  1023 				//or that the data is non IFD
       
  1024 				//so we will skip further processing of the IFD and abandon
       
  1025 				User::Leave(KErrCorrupt);
       
  1026 				}
       
  1027 			}
       
  1028 		else
       
  1029 			{
       
  1030 			numberOfConsecutiveCorruptIfdEntries = 0; //reset
       
  1031 			}
       
  1032 			
       
  1033 		if (entry)
       
  1034 			{//always ensure entry is valid before appending - might not be if we have a null tag
       
  1035 			iIfdEntries.AppendL(entry);
       
  1036 			CleanupStack::Pop(entry);
       
  1037 			}
       
  1038 
       
  1039 		offset += KMinimumIfdEntrySize;
       
  1040 		}
       
  1041 	
       
  1042 	// All entries have now been added.	
       
  1043 	}
       
  1044 	
       
  1045 /**
       
  1046 	Creates an IFD entry and pushes it onto the cleanup stack.
       
  1047 	If the entry cannot be created (most likely due to some
       
  1048 	corrupt data) NULL will be returned.
       
  1049 	
       
  1050 	@param	aTag			EXIF tag number for this entry
       
  1051 	@param	aFormat			Format of this entry's data
       
  1052 	@param	aComponentCount	Number of values in the data
       
  1053 	@param	aValuePtr		Pointer to the start of the data
       
  1054 	@param	aValueOffset	Offset from start of EXIF data to start of entry data
       
  1055 	@param	aTotalSize		Length of the data
       
  1056 	@param	aUnknownTag		Set to ETrue if the entry's tag is unknown (for this IFD),
       
  1057 							EFalse otherwise.
       
  1058 	
       
  1059 	@return	The newly created entry or NULL if it could not be created.
       
  1060 	
       
  1061 	@leave	KErrNoMemory	If there wasn't sufficient memory to create entry. This
       
  1062 							is the only type of leave this function can make.
       
  1063 
       
  1064 */
       
  1065 CIfdGeneralEntry* CIfdGeneral::CreateIfdEntryLC(const TUint& aTag, const TUint& aFormat, const TUint& aComponentCount, const TUint8* aValuePtr, TUint aValueOffset, TUint aTotalSize, TBool& aUnknownTag)
       
  1066 	{
       
  1067 	CIfdGeneralEntry* entry= NULL;
       
  1068 	
       
  1069 	TRAPD(err, entry = CIfdGeneralEntry::NewL(aTag, aFormat, aComponentCount, aValuePtr, this, aUnknownTag));
       
  1070 	if (err != KErrNone)
       
  1071 		{
       
  1072 		if (err == KErrNoMemory)
       
  1073 			{
       
  1074 			User::Leave(err); //only leave if no memory
       
  1075 			}
       
  1076 		}
       
  1077 	else
       
  1078 		{
       
  1079 		CleanupStack::PushL( entry );
       
  1080 		// no errors so far, so read the entry's values
       
  1081 		if(aTotalSize > KSizeOfValueOffsetField)
       
  1082 			{
       
  1083 			// Byte swap each component, if necessary.
       
  1084 			TUint8* byteSwappedDataBuffer = static_cast<TUint8*>(User::AllocL(aTotalSize));
       
  1085 			TUint8* tempPtr = byteSwappedDataBuffer;
       
  1086 			TInt updateErr=KErrNone;
       
  1087 			TInt i;
       
  1088 			switch(aFormat)
       
  1089 				{
       
  1090 				case(EByte):
       
  1091 				case(EAscii):
       
  1092 				case(EUndefined):
       
  1093 					updateErr = entry->SetActualData(iBase+aValueOffset, aComponentCount, KDataFormatSize[aFormat]);						
       
  1094 					break;
       
  1095 				case(EUnsignedRational):
       
  1096 				case(ESignedRational):
       
  1097 					// Comprised of 2 * 4-byte integers.
       
  1098 					{
       
  1099 					for(i = 0; i < aComponentCount; i++)
       
  1100 						{
       
  1101 						TUint numer = CExifReaderWriter::ReadUint32(iIntel, iBase + aValueOffset + 8*i);
       
  1102 						TUint denom = CExifReaderWriter::ReadUint32(iIntel, iBase + aValueOffset + 8*i + 4);
       
  1103 						tempPtr = Mem::Copy(tempPtr, &numer, sizeof(numer));
       
  1104 						tempPtr = Mem::Copy(tempPtr, &denom, sizeof(denom));
       
  1105 						}
       
  1106 					updateErr = entry->SetActualData(byteSwappedDataBuffer, aComponentCount, KDataFormatSize[aFormat]);						
       
  1107 					}
       
  1108 					break;
       
  1109 				case(EUnsignedLong):
       
  1110 				case(ESignedLong):
       
  1111 					{
       
  1112 					for(i = 0; i < aComponentCount; i++)
       
  1113 						{
       
  1114 						TUint value = CExifReaderWriter::ReadUint32(iIntel, iBase + aValueOffset+(i*sizeof(value)));
       
  1115 						tempPtr = Mem::Copy(tempPtr, &value, sizeof(value));
       
  1116 						}
       
  1117 					updateErr = entry->SetActualData(byteSwappedDataBuffer, aComponentCount, KDataFormatSize[aFormat]);						
       
  1118 					}
       
  1119 					break;
       
  1120 				case(EUnsignedShort):
       
  1121 					{
       
  1122 					for(i = 0; i < aComponentCount; i++)
       
  1123 						{
       
  1124 						TUint16 value = CExifReaderWriter::ReadUint16(iIntel, iBase + aValueOffset+(i*sizeof(value)));
       
  1125 						tempPtr = Mem::Copy(tempPtr, &value, sizeof(value));
       
  1126 						}
       
  1127 					updateErr = entry->SetActualData(byteSwappedDataBuffer, aComponentCount, KDataFormatSize[aFormat]);						
       
  1128 					}
       
  1129 					break;
       
  1130 				default:
       
  1131 					break;
       
  1132 				}
       
  1133 			User::Free(byteSwappedDataBuffer);
       
  1134 			if(updateErr)
       
  1135 				{
       
  1136 				if(updateErr == KErrNoMemory)
       
  1137 					{
       
  1138 					User::Leave(KErrNoMemory);
       
  1139 					}
       
  1140 				else
       
  1141 					{
       
  1142 					// if we get here entry object was made, but data could not be set
       
  1143 					// so we remove the entry object
       
  1144 					CleanupStack::PopAndDestroy( entry );
       
  1145 					entry = NULL;
       
  1146 					}
       
  1147 				}
       
  1148 			} // end if(aTotalSize > KSizeOfValueOffsetField)
       
  1149 		}
       
  1150 
       
  1151 		return entry;	
       
  1152 	}
       
  1153 	
       
  1154 
       
  1155 void CIfdGeneral::SetupDirectoryEntriesL()
       
  1156 	{
       
  1157 	// Loop through all legal tags.
       
  1158 	for(TInt i = 0; i < GetNumberOfValidTags(); i++)
       
  1159 		{
       
  1160 		const TUint* tagInfo = GetTagInformation(i);
       
  1161 		// Only initialise the default Ifd with Mandatory tags.
       
  1162 		if (tagInfo[ESupportLevelValue] == EMandatory)
       
  1163 			{
       
  1164 			TUint temp = tagInfo[EValueOffsetValue];
       
  1165 			TUint8* valueOffset = reinterpret_cast<TUint8*>(&temp);
       
  1166 			
       
  1167 			TUint format = tagInfo[EFormatValue];
       
  1168 			TUint componentCount = tagInfo[EComponentCountValue];
       
  1169 			if (format == EAscii)
       
  1170 				{
       
  1171 				valueOffset = reinterpret_cast<TUint8*> (temp);
       
  1172 				componentCount = 0;
       
  1173 
       
  1174 				TUint8* strPtr = valueOffset;
       
  1175 				while(*strPtr++)
       
  1176 					componentCount++;
       
  1177 				}
       
  1178 			
       
  1179 			CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(tagInfo[ETagValue], format, componentCount, valueOffset, this);
       
  1180 			iIfdEntries.AppendL(entry); 	
       
  1181 			CleanupStack::Pop(entry);
       
  1182 			}			
       
  1183 		}
       
  1184 	}
       
  1185 
       
  1186 TInt CIfdGeneral::LocateEntry(const TUint16 aTag) const
       
  1187 	{
       
  1188 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
  1189 		{
       
  1190 		if(aTag == iIfdEntries[i]->Tag())
       
  1191 			{
       
  1192 			return i;
       
  1193 			}
       
  1194 		}
       
  1195 	return KErrNotFound;
       
  1196 	}	
       
  1197 	
       
  1198 TInt CIfdGeneral::Ifd() const
       
  1199 	{
       
  1200 	return iIfdNumber;
       
  1201 	}
       
  1202 
       
  1203 TUint CIfdGeneral::EntryCount() const
       
  1204 	{
       
  1205 	return iIfdEntries.Count();
       
  1206 	}
       
  1207 	
       
  1208 TUint8* CIfdGeneral::CreateIfdBlockL(TUint aOffset)
       
  1209 	{
       
  1210 	TUint allocSize = Size() + KIfdOffsetByteCount;
       
  1211 	aOffset += KIfdOffsetByteCount;
       
  1212 	TUint8* ifdBlock = static_cast<TUint8*>(User::AllocLC(allocSize)); // Allocate buffer for all IFD data.	
       
  1213 	WriteIfdDirEntriesL(ifdBlock, aOffset);
       
  1214 	TUint8* tempPtr = ifdBlock + EntryCount() * KMinimumIfdEntrySize;
       
  1215 
       
  1216 	TInt temporary = 0;
       
  1217 	// The pointer to the next Ifd is temporarily zero-filled, and the actual value filled later.
       
  1218 	tempPtr = Mem::Copy(tempPtr, &temporary, sizeof(temporary));		
       
  1219 
       
  1220 	WriteIfdData(tempPtr);
       
  1221 	CleanupStack::Pop();
       
  1222 	return ifdBlock;
       
  1223 	}	
       
  1224 	
       
  1225 TBool CIfdGeneral::AllowNullTags() 
       
  1226 	{
       
  1227 	// The general case
       
  1228 	return EFalse;
       
  1229 	}
       
  1230 
       
  1231 TBool CIfdGeneral::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const
       
  1232 	{
       
  1233 	// Check that aIfdEntryCount is reasonable
       
  1234 	// The check is fairly basic but we will check that the minimum size of the ifd entry 
       
  1235 	// based on the aIfdEntryCount does not exceed the exif data length
       
  1236 	// no check for minimum number of mandatory entries is done	
       
  1237 	if ( (iOffsetToIfd + sizeof(aIfdEntryCount) + (aIfdEntryCount * KMinimumIfdEntrySize)) > iExifDataLength)
       
  1238 		{
       
  1239 		return EFalse;
       
  1240 		}
       
  1241 	else
       
  1242 		{
       
  1243 		return ETrue;		
       
  1244 		}
       
  1245 	}
       
  1246 
       
  1247 
       
  1248 void CIfdGeneral::WriteIfdDirEntriesL(TUint8* aBlock, TUint aOffset)
       
  1249 	{
       
  1250 	TUint16 dirCount = EntryCount();
       
  1251 
       
  1252 	//Address where data pointed to by offset values, starts.
       
  1253 	TUint offsetDataAddress = aOffset + sizeof(dirCount) + (dirCount * KMinimumIfdEntrySize); 
       
  1254 	
       
  1255 	// Copy each stored directory entry into the buffer.
       
  1256 	TInt i;
       
  1257 	TUint tag;
       
  1258 	TUint format;
       
  1259 	TUint sizeOfData;
       
  1260 	for(i = 0; i < dirCount; i++)
       
  1261 		{
       
  1262 		tag = iIfdEntries[i]->Tag();		
       
  1263 		format = iIfdEntries[i]->Format();
       
  1264 		
       
  1265 			
       
  1266 		TUint compCount = iIfdEntries[i]->ComponentCount();		
       
  1267 		TBool unicode = iIfdEntries[i]->IsUnicodeData();
       
  1268 		
       
  1269 		aBlock = Mem::Copy(aBlock, &tag, KSizeOfTagField); // Write tag.
       
  1270 		aBlock = Mem::Copy(aBlock, &format, KSizeOfFormatField); // Write format
       
  1271 		aBlock = Mem::Copy(aBlock, &compCount, KSizeOfComponentCountField); // Write component count.
       
  1272 		// tempPtr now points to the value/offset field.
       
  1273 	
       
  1274 		sizeOfData = iIfdEntries[i]->ExtraSize();
       
  1275 		
       
  1276 		// Here we must check  as to whether we are writing an offset to an IFD, since 
       
  1277 		// its component count is 1 and it is a long - thus check explicitly for tag number 0x8769
       
  1278 		// (Exif Sub Ifd), or 0xA005 (Interoperability Ifd), and write the offset.
       
  1279 		
       
  1280 		if((iIfdEntries[i]->Tag() == KTag8769[ETagValue]) ||
       
  1281 			(iIfdEntries[i]->Tag() == KTagA005[ETagValue]) ||
       
  1282 			(iIfdEntries[i]->Tag() == KThumbTag8769[ETagValue]) ||
       
  1283 			(iIfdEntries[i]->Tag() == KThumbTag0201[ETagValue]))
       
  1284 			{
       
  1285 			TUint address = Size() + aOffset + sizeof(dirCount);	
       
  1286 			// Write offset value.  The value to which this points will be written later.
       
  1287 			aBlock = Mem::Copy(aBlock, &address, KSizeOfValueOffsetField);			
       
  1288 			}				
       
  1289 		//Must check if we are writing an offset or an actual value.
       
  1290 		else if(sizeOfData > 0)
       
  1291 			{
       
  1292 			// Write offset value.  The value to which this points will be written later.
       
  1293 			aBlock = Mem::Copy(aBlock, &offsetDataAddress, KSizeOfValueOffsetField);
       
  1294 			// Move the offset address onward, ready for next time.
       
  1295 			offsetDataAddress += sizeOfData;
       
  1296 			}
       
  1297 		else
       
  1298 			{
       
  1299 			TUint valueOffset = iIfdEntries[i]->ValueOffset();
       
  1300 			aBlock = Mem::Copy(aBlock, &valueOffset, sizeof(valueOffset)); // Write actual value.				
       
  1301 			}
       
  1302 		// tempPtr now points to position after the value/offset field.
       
  1303 		}
       
  1304 
       
  1305 	}
       
  1306 	
       
  1307 void CIfdGeneral::WriteIfdData(TUint8* aBlock)
       
  1308 	{
       
  1309 	TUint16 dirCount = EntryCount();
       
  1310 
       
  1311 	TInt i;
       
  1312 	TUint format;
       
  1313 	TUint sizeOfData;
       
  1314 	
       
  1315 	// We have written the main blocks of data, so now need to write out the values that any offsets point to.
       
  1316 	for(i = 0; i < dirCount; i++)
       
  1317 		{
       
  1318 		format = iIfdEntries[i]->Format();
       
  1319 		sizeOfData = KDataFormatSize[format] * iIfdEntries[i]->ComponentCount();
       
  1320 		if(sizeOfData > KSizeOfValueOffsetField)
       
  1321 			{
       
  1322 			if(iIfdEntries[i]->ActualValue() != NULL)
       
  1323 				{
       
  1324 				aBlock = Mem::Copy(aBlock, iIfdEntries[i]->ActualValue(), sizeOfData);
       
  1325 				if ((sizeOfData%2) == 1) 
       
  1326 					{
       
  1327 					(*aBlock++) = '\0'; 
       
  1328 					}
       
  1329 				}
       
  1330 			}
       
  1331 		}
       
  1332 	}
       
  1333 
       
  1334 
       
  1335 // Does the given tag exist in this Ifd?
       
  1336 TBool CIfdGeneral::EntryExists(const TUint aTag) const
       
  1337 	{
       
  1338 	for(TInt i = 0; i < iIfdEntries.Count(); i++)
       
  1339 		{
       
  1340 		if(aTag == iIfdEntries[i]->Tag())
       
  1341 			{
       
  1342 			return ETrue;
       
  1343 			}
       
  1344 		}
       
  1345 	return EFalse;
       
  1346 	}
       
  1347 	
       
  1348 TBool CIfdGeneral::FindTag(const TUint aTag)
       
  1349 	{
       
  1350 	return GetTagIndex(aTag)!=KErrNotFound;
       
  1351 	}
       
  1352 
       
  1353 	
       
  1354 TInt CIfdGeneral::GetFormat(TUint aTag, TUint& aFormat)
       
  1355 	{
       
  1356 	TInt index = GetTagIndex(aTag);
       
  1357 	if (index != KErrNotFound)
       
  1358 		{
       
  1359 		const TUint* tag = GetTagInformation(index);
       
  1360 		aFormat = tag[EFormatValue];
       
  1361 		return KErrNone;
       
  1362 		}
       
  1363 	return KErrNotFound;
       
  1364 	}
       
  1365 	
       
  1366 TInt CIfdGeneral::GetComponentCount(TUint aTag, TUint& aComponentCount)
       
  1367 	{
       
  1368 	TInt index = GetTagIndex(aTag);
       
  1369 	if (index != KErrNotFound)
       
  1370 		{
       
  1371 		const TUint* tag = GetTagInformation(index);
       
  1372 		aComponentCount = tag[EComponentCountValue];
       
  1373 		return KErrNone;
       
  1374 		}
       
  1375 	return KErrNotFound;
       
  1376 	}
       
  1377 	
       
  1378 TInt CIfdGeneral::GetTagIndex(const TUint aTag)
       
  1379 	{
       
  1380 	for (TInt i = 0 ; i< GetNumberOfValidTags(); i++ ) 
       
  1381 		{
       
  1382 		if (GetTagInformation(i)[ETagValue] == aTag)
       
  1383 			{
       
  1384 			return i;	
       
  1385 			}
       
  1386 		}	
       
  1387 	return KErrNotFound;
       
  1388 	}
       
  1389 
       
  1390 void CIfdGeneral::RemoveEntryL(const TUint aTag)
       
  1391 	{
       
  1392 	TInt entry=LocateEntry(aTag);
       
  1393 	if(entry==KErrNotFound)
       
  1394 		{
       
  1395 		User::Leave(entry);
       
  1396 		}
       
  1397 	delete iIfdEntries[entry];
       
  1398 	iIfdEntries.Remove(entry);
       
  1399 	}
       
  1400 
       
  1401 void CIfdGeneral::CheckMandatoryEntriesL()
       
  1402 	{
       
  1403 	}
       
  1404 
       
  1405 // class CIfd0
       
  1406 CIfd0* CIfd0::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1407 	{
       
  1408 	CIfd0* self = new (ELeave) CIfd0(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1409 	CleanupStack::PushL(self);
       
  1410 	self->ConstructL();
       
  1411 	return self;		
       
  1412 	}
       
  1413 
       
  1414 	
       
  1415 TInt CIfd0::GetNumberOfValidTags()
       
  1416 	{
       
  1417 	return KIfd0NumberTags;		
       
  1418 	}
       
  1419 	
       
  1420 const TUint* CIfd0::GetTagInformation(TInt aIndex) 
       
  1421 	{
       
  1422 	if((aIndex < 0) || (aIndex >= KIfd0NumberTags))
       
  1423 		{//invalid argument
       
  1424 		return NULL;
       
  1425 		}
       
  1426 	else
       
  1427 		{
       
  1428 		TUint tagValue = KIfd0TagArray[aIndex][ETagValue];
       
  1429 		if(tagValue == KTag010F[ETagValue])
       
  1430 			{
       
  1431 			return iTag010F;
       
  1432 			}
       
  1433 		else if(tagValue == KTag0110[ETagValue])
       
  1434 			{
       
  1435 			return iTag0110;
       
  1436 			}
       
  1437 		else if(tagValue == KTag0131[ETagValue])
       
  1438 			{
       
  1439 			return iTag0131;
       
  1440 			}
       
  1441 		else 
       
  1442 			{
       
  1443 			return KIfd0TagArray[aIndex];
       
  1444 			}		
       
  1445 		}
       
  1446 	}
       
  1447 
       
  1448 void CIfd0::ConstructL()
       
  1449 	{
       
  1450 	//For Device information tags - copy the contents from the constants and 
       
  1451 	//overwrite only the - EValueOffsetValue. 
       
  1452 	Mem::Copy(iTag010F, KTag010F, sizeof(KTag010F));
       
  1453 	Mem::Copy(iTag0110, KTag0110, sizeof(KTag0110));
       
  1454 	Mem::Copy(iTag0131, KTag0131, sizeof(KTag0131));
       
  1455 	//get the device information from SysUtil API.
       
  1456 	iManufacturerName = GetDeviceInfo(KTag010F[ETagValue]);
       
  1457 	iModelName = GetDeviceInfo(KTag0110[ETagValue]);
       
  1458 	iUIPlatform = GetDeviceInfo(KTag0131[ETagValue]);
       
  1459 	TUint8* data = NULL;
       
  1460 	//If reading from SysUtil API is not successful, let the tags carry the values from the constants.
       
  1461 	//Moreover, the tags manufacturer and model are mandatory. They should have non-NULL value for EValueOffsetValue.
       
  1462 	if(iManufacturerName != NULL)
       
  1463 		{
       
  1464 		data = const_cast<TUint8*>(iManufacturerName->Des().PtrZ());
       
  1465 		iTag010F[EValueOffsetValue] = reinterpret_cast<TUint>(data);
       
  1466 		}
       
  1467 	if(iModelName != NULL)
       
  1468 		{
       
  1469 		data = const_cast<TUint8*>(iModelName->Des().PtrZ());
       
  1470 		iTag0110[EValueOffsetValue] = reinterpret_cast<TUint>(data);
       
  1471 		}
       
  1472 	if(iUIPlatform != NULL)
       
  1473 		{
       
  1474 		data = const_cast<TUint8*>(iUIPlatform->Des().PtrZ());
       
  1475 		iTag0131[EValueOffsetValue] = reinterpret_cast<TUint>(data);
       
  1476 		}
       
  1477 
       
  1478 	CIfdGeneral::ConstructL();
       
  1479 	}
       
  1480 
       
  1481 //Reads device information from SysUtil API and makes a copy and returns the value.
       
  1482 //On failure returns NULL.If the tag aTagValue, does not belong to device information returns NULL.
       
  1483 HBufC8* CIfd0::GetDeviceInfo(TUint aTagValue)
       
  1484 	{
       
  1485 	HBufC8* buff = NULL;
       
  1486 	//if the tag is one of - manufacturer name, device model name and UI Platform - get 
       
  1487 	//the values from SysUtil.
       
  1488 	if((aTagValue == KTag010F[ETagValue]) || (aTagValue == KTag0110[ETagValue]) || (aTagValue == KTag0131[ETagValue]))
       
  1489 		{
       
  1490 		CDeviceTypeInformation* deviceAtts = NULL;
       
  1491 		TInt err = KErrNone;
       
  1492 		//Get device type information
       
  1493 		TRAP(err, deviceAtts = SysUtil::GetDeviceTypeInfoL());
       
  1494 		if(err == KErrNone && deviceAtts != NULL)
       
  1495 			{
       
  1496 			TPtrC16 ptr;
       
  1497 			if(aTagValue == KTag010F[ETagValue])
       
  1498 				{//manufacturer name
       
  1499 				err = deviceAtts->GetManufacturerName(ptr);
       
  1500 				}
       
  1501 			else if(aTagValue == KTag0110[ETagValue])
       
  1502 				{//model name
       
  1503 				err = deviceAtts->GetModelName(ptr);
       
  1504 				}
       
  1505 			else if(aTagValue == KTag0131[ETagValue])
       
  1506 				{//UI platform
       
  1507 				err = deviceAtts->GetUIPlatformName(ptr);
       
  1508 				}
       
  1509 			delete deviceAtts;
       
  1510 			//error code should be one of - KErrNone, KDefaultValue and KErrOverflow
       
  1511 			if((err == KErrNone) || (err == CDeviceTypeInformation::KDefaultValue) || (err == KErrOverflow))
       
  1512 				{
       
  1513 				buff = HBufC8::NewMax(ptr.Length() + 1);
       
  1514 				if(buff != NULL)
       
  1515 					{
       
  1516 					TPtr8 ptr8 = buff->Des();
       
  1517 					ptr8.Copy(ptr);
       
  1518 					}
       
  1519 				}			
       
  1520 			}
       
  1521 		}	
       
  1522 	return buff;
       
  1523 	}
       
  1524 
       
  1525 CIfd0::~CIfd0()
       
  1526 	{
       
  1527 	delete iManufacturerName;
       
  1528 	delete iModelName;
       
  1529 	delete iUIPlatform;
       
  1530 	}
       
  1531 
       
  1532 TBool CIfd0::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const
       
  1533 	{
       
  1534 	//should have atleast one mandatory entry
       
  1535 	if(aIfdEntryCount >= 1)
       
  1536 		{
       
  1537 		return 	CIfdGeneral::IsValidIfdEntryCount(aIfdEntryCount);
       
  1538 		}
       
  1539 	else
       
  1540 		{
       
  1541 		return EFalse;			
       
  1542 		}
       
  1543 	}
       
  1544 
       
  1545 CIfd0::CIfd0(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1546 	: CIfdGeneral(EZeroth, aOffsetToIfd, aBase, aIntel, aExifDataLength)
       
  1547 	{
       
  1548 	}
       
  1549 	
       
  1550 //class CExifIfd
       
  1551 CExifIfd* CExifIfd::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1552 	{
       
  1553 	CExifIfd* self = new (ELeave) CExifIfd(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1554 	CleanupStack::PushL(self);
       
  1555 	self->ConstructL();
       
  1556 	return self;		
       
  1557 	}
       
  1558 	
       
  1559 CExifIfd* CExifIfd::NewL(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1560 	{
       
  1561 	CExifIfd* self = NewLC(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1562 	CleanupStack::Pop(self);
       
  1563 	return self;		
       
  1564 	}
       
  1565 
       
  1566 TInt CExifIfd::GetNumberOfValidTags()
       
  1567 	{
       
  1568 	return KExifSubNumberTags;		
       
  1569 	}
       
  1570 	
       
  1571 const TUint* CExifIfd::GetTagInformation(TInt aIndex) 
       
  1572 	{
       
  1573 	return KExifSubTagArray[aIndex];
       
  1574 	}
       
  1575 
       
  1576 void CExifIfd::CheckMandatoryEntriesL()
       
  1577 	{
       
  1578 	HBufC8* buffer = NULL;
       
  1579 	TInt err = GetParam8(KTag9000[ETagValue], buffer);
       
  1580 	if (err == KErrNotFound)
       
  1581 		{
       
  1582 		TUint temp = KTag9000[EValueOffsetValue];
       
  1583 		TUint8* valueOffset = reinterpret_cast<TUint8*>(&temp);
       
  1584 		TUint format = KTag9000[EFormatValue];
       
  1585 		TUint componentCount = KTag9000[EComponentCountValue];
       
  1586 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(KTag9000[ETagValue], format, componentCount, valueOffset, this);
       
  1587 		iIfdEntries.AppendL(entry); 	
       
  1588 		CleanupStack::Pop(entry);
       
  1589 		}	
       
  1590 	delete buffer;
       
  1591 	buffer = NULL;	
       
  1592 	
       
  1593 	err = GetParam8(KTag9101[ETagValue], buffer);
       
  1594 	if (err == KErrNotFound)
       
  1595 		{
       
  1596 		_LIT8(KComponentsConfigurationDefault, "1230");
       
  1597 		buffer = KComponentsConfigurationDefault().AllocL();
       
  1598 		CleanupStack::PushL(buffer);
       
  1599 		TUint format = 0;
       
  1600 		err = GetFormat(KTag9101[ETagValue], format);		
       
  1601 		if (err == KErrNone) 
       
  1602 			{
       
  1603 			AddParam8L(KTag9101[ETagValue], format, buffer->Length(), buffer);
       
  1604 			}
       
  1605 		CleanupStack::Pop();
       
  1606 		}
       
  1607 	delete buffer;
       
  1608 	buffer = NULL;
       
  1609 			
       
  1610 	err = GetParam8(KTagA000[ETagValue], buffer);
       
  1611 	if (err == KErrNotFound)
       
  1612 		{
       
  1613 		TUint temp = KTagA000[EValueOffsetValue];
       
  1614 		TUint8* valueOffset = reinterpret_cast<TUint8*>(&temp);
       
  1615 		TUint format = KTagA000[EFormatValue];
       
  1616 		TUint componentCount = KTagA000[EComponentCountValue];
       
  1617 		CIfdGeneralEntry* entry = CIfdGeneralEntry::NewLC(KTagA000[ETagValue], format, componentCount, valueOffset, this);
       
  1618 		iIfdEntries.AppendL(entry); 	
       
  1619 		CleanupStack::Pop(entry);		
       
  1620 		}
       
  1621 	delete buffer;
       
  1622 	buffer = NULL;	
       
  1623 				
       
  1624 	TUint16 buffer16 = 0;
       
  1625 	err = GetShortParam(KTagA001[ETagValue], buffer16);
       
  1626 	if (err == KErrNotFound)
       
  1627 		{
       
  1628 		const TUint KColorSpaceDefault = 0xFFFF;
       
  1629 		TUint format = 0;
       
  1630 		err = GetFormat(KTagA001[ETagValue], format);		
       
  1631 		if (err == KErrNone) 
       
  1632 			{
       
  1633 			AddShortParamL(KTagA001[ETagValue], format, 1, KColorSpaceDefault);
       
  1634 			}
       
  1635 		}	
       
  1636 	}
       
  1637 	
       
  1638 TBool CExifIfd::CheckImageSizeTags()
       
  1639 	{
       
  1640 	TUint16 buffer16 = NULL;
       
  1641 	TInt err = GetShortParam(KTagA002[ETagValue], buffer16);
       
  1642 	if (err == KErrNotFound)
       
  1643 		{
       
  1644 		return EFalse;
       
  1645 		}
       
  1646 	err = GetShortParam(KTagA003[ETagValue], buffer16);
       
  1647 	if (err == KErrNotFound)
       
  1648 		{
       
  1649 		return EFalse;
       
  1650 		}
       
  1651 	return ETrue;
       
  1652 	}
       
  1653 	
       
  1654 void CExifIfd::UpdateImageSizeTagsL(const TSize& aSize)
       
  1655 	{
       
  1656 	TUint16 value = NULL;
       
  1657 	TInt err = GetShortParam(KTagA002[ETagValue], value);
       
  1658 	if (err == KErrNotFound)
       
  1659 		{
       
  1660 		TUint format = 0;
       
  1661 		err = GetFormat(KTagA002[ETagValue], format);		
       
  1662 		if (err == KErrNone) 
       
  1663 			{
       
  1664 			AddShortParamL(KTagA002[ETagValue], format, 1, aSize.iWidth);
       
  1665 			}
       
  1666 		}
       
  1667 	else
       
  1668 		{
       
  1669 		if (value != aSize.iWidth)
       
  1670 			{
       
  1671 			SetShortParam(KTagA002[ETagValue], aSize.iWidth);
       
  1672 			}
       
  1673 		}
       
  1674 	err = GetShortParam(KTagA003[ETagValue], value);
       
  1675 	if (err == KErrNotFound)
       
  1676 		{
       
  1677 		TUint format = 0;
       
  1678 		err = GetFormat(KTagA003[ETagValue], format);		
       
  1679 		if (err == KErrNone) 
       
  1680 			{
       
  1681 			AddShortParamL(KTagA003[ETagValue], format, 1, aSize.iHeight);
       
  1682 			}
       
  1683 		}
       
  1684 	else
       
  1685 		{
       
  1686 		if (value != aSize.iHeight)
       
  1687 			{
       
  1688 			SetShortParam(KTagA003[ETagValue], aSize.iHeight);
       
  1689 			}
       
  1690 		}
       
  1691 	}
       
  1692 
       
  1693 CExifIfd::CExifIfd(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1694 	: CIfdGeneral(EExifSub, aOffsetToIfd, aBase, aIntel, aExifDataLength)
       
  1695 	{	
       
  1696 	}
       
  1697 
       
  1698 
       
  1699 //class CInteropIfd
       
  1700 CInteropIfd* CInteropIfd::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1701 	{
       
  1702 	CInteropIfd* self = new (ELeave) CInteropIfd(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1703 	CleanupStack::PushL(self);
       
  1704 	self->ConstructL();
       
  1705 	return self;		
       
  1706 	}
       
  1707 
       
  1708 CInteropIfd* CInteropIfd::NewL(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1709 	{
       
  1710 	CInteropIfd* self = NewLC(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1711 	CleanupStack::Pop(self);
       
  1712 	return self;	
       
  1713 	}
       
  1714 	
       
  1715 TInt CInteropIfd::GetNumberOfValidTags()
       
  1716 	{
       
  1717 	return KInteropNumberTags;		
       
  1718 	}
       
  1719 	
       
  1720 const TUint* CInteropIfd::GetTagInformation(TInt aIndex) 
       
  1721 	{
       
  1722 	return KInteropTagArray[aIndex];
       
  1723 	}
       
  1724 
       
  1725 TBool CInteropIfd::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const
       
  1726 	{
       
  1727 	//should have atleast one mandatory entry
       
  1728 	if(aIfdEntryCount >= 1)
       
  1729 		{
       
  1730 		return 	CIfdGeneral::IsValidIfdEntryCount(aIfdEntryCount);
       
  1731 		}
       
  1732 	else
       
  1733 		{
       
  1734 		return EFalse;			
       
  1735 		}
       
  1736 	}
       
  1737 
       
  1738 CInteropIfd::CInteropIfd(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1739 	: CIfdGeneral(EInterop, aOffsetToIfd, aBase, aIntel, aExifDataLength)
       
  1740 	{	
       
  1741 	}
       
  1742 
       
  1743 //class CIfd1
       
  1744 CIfd1* CIfd1::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1745 	{
       
  1746 	CIfd1* self = new (ELeave) CIfd1(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1747 	CleanupStack::PushL(self);
       
  1748 	self->ConstructL();
       
  1749 	return self;		
       
  1750 	}
       
  1751 	
       
  1752 	
       
  1753 TInt CIfd1::GetNumberOfValidTags()
       
  1754 	{
       
  1755 	return KIfd1NumberTags;		
       
  1756 	}
       
  1757 	
       
  1758 const TUint* CIfd1::GetTagInformation(TInt aIndex) 
       
  1759 	{
       
  1760 	return KIfd1TagArray[aIndex];
       
  1761 	}
       
  1762 
       
  1763 CIfd1::CIfd1(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1764 	: CIfdGeneral(EFirst, aOffsetToIfd, aBase, aIntel, aExifDataLength)
       
  1765 	{	
       
  1766 	}
       
  1767 
       
  1768 //class CGpsIfd
       
  1769 CGpsIfd* CGpsIfd::NewLC(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1770 	{
       
  1771 	CGpsIfd* self = new (ELeave) CGpsIfd(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1772 	CleanupStack::PushL(self);
       
  1773 	self->ConstructL();
       
  1774 	return self;		
       
  1775 	}
       
  1776 
       
  1777 CGpsIfd* CGpsIfd::NewL(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1778 	{
       
  1779 	CGpsIfd* self = NewLC(aOffsetToIfd, aBase, aIntel, aExifDataLength);
       
  1780 	CleanupStack::Pop(self);
       
  1781 	return self;	
       
  1782 	}
       
  1783 	
       
  1784 TInt CGpsIfd::GetNumberOfValidTags()
       
  1785 	{
       
  1786 	return KGpsSubNumberTags;		
       
  1787 	}
       
  1788 	
       
  1789 const TUint* CGpsIfd::GetTagInformation(TInt aIndex) 
       
  1790 	{
       
  1791 	return KGpsSubTagArray[aIndex];
       
  1792 	}
       
  1793 
       
  1794 TBool CGpsIfd::IsValidIfdEntryCount(TUint16 aIfdEntryCount) const
       
  1795 	{
       
  1796 	//should have atleast one mandatory entry
       
  1797 	if(aIfdEntryCount >= 1)
       
  1798 		{
       
  1799 		return 	CIfdGeneral::IsValidIfdEntryCount(aIfdEntryCount);
       
  1800 		}
       
  1801 	else
       
  1802 		{
       
  1803 		return EFalse;			
       
  1804 		}		
       
  1805 	}
       
  1806 
       
  1807 CGpsIfd::CGpsIfd(const TUint aOffsetToIfd, const TUint8* aBase, const TBool aIntel, const TUint aExifDataLength)
       
  1808 	: CIfdGeneral(EGpsSub, aOffsetToIfd, aBase, aIntel, aExifDataLength)
       
  1809 	{	
       
  1810 	}
       
  1811 
       
  1812 TBool CGpsIfd::AllowNullTags() 
       
  1813 	{
       
  1814 	// Null tags are allowed for GPS
       
  1815 	return ETrue;
       
  1816 	}
       
  1817