imaging/imagingfws/src/ImageConvResolvrUtils.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     1 // Copyright (c) 1997-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 "ImageConvResolvrUtils.h"
       
    17 #include <icl/icl_propertyuids.h>
       
    18 
       
    19 //
       
    20 // COpaqueDataParse
       
    21 //    Class for reading and processing opaque data from the ECOM resource file
       
    22 //    Note that the opaque data can not exceed 255 bytes.
       
    23 //    We store this as follows:
       
    24 //		Version (1 byte)
       
    25 // 		Optional flags (2 bytes) if Version >= 1
       
    26 //		Main Uid (4 bytes)
       
    27 //		Sub Uid (4 bytes)
       
    28 //		Number extensions (1 byte)
       
    29 //		{ ".XXX" \r } (x number extensions)
       
    30 //		Number mime types (1 byte)
       
    31 //		[ "mimetype" \r ] (for each mimetype)
       
    32 //		Number of binary properties (1 byte)
       
    33 //		List of the binary properties uids (4 bytes each)
       
    34 //
       
    35 
       
    36 // Note to avoid overhead, we only read the extensions, mime types and binary properties on demand
       
    37 // Until EnsureExtnsReadL() is called, ExtnsCount() and Extn is invalid. Similarly
       
    38 // for mime types and plugin binary properties.
       
    39 
       
    40 COpaqueDataParse* COpaqueDataParse::NewL(const TDesC8& aOpaqueData)
       
    41 	{
       
    42 	COpaqueDataParse* result = COpaqueDataParse::NewLC(aOpaqueData);
       
    43 	CleanupStack::Pop(result);
       
    44 	return result;
       
    45 	}
       
    46 
       
    47 COpaqueDataParse* COpaqueDataParse::NewLC(const TDesC8& aOpaqueData)
       
    48 	{
       
    49 	COpaqueDataParse* result = new (ELeave) COpaqueDataParse(aOpaqueData);
       
    50 	CleanupStack::PushL(result);
       
    51 	result->ConstructL();
       
    52 	return result;
       
    53 	}
       
    54 
       
    55 COpaqueDataParse::COpaqueDataParse(const TDesC8& aOpaqueData):
       
    56 	iOpaqueData(aOpaqueData)
       
    57 	{
       
    58 	}
       
    59 
       
    60 void COpaqueDataParse::ConstructL()
       
    61 	{
       
    62 	ReadVersion();
       
    63 	if (iVersion > KIclPluginFrameworkVersionMax)
       
    64 		{
       
    65 		User::Leave(KErrNotSupported);
       
    66 		}
       
    67 	ReadFlags();
       
    68 	ReadUids();
       
    69 	}
       
    70 
       
    71 COpaqueDataParse::~COpaqueDataParse()
       
    72 	{
       
    73 	iArray.Close();
       
    74 	iBinaryPropertiesArray.Close();
       
    75 	}
       
    76 
       
    77 // Extract the Version number 
       
    78 void COpaqueDataParse::ReadVersion()
       
    79 	{
       
    80 	ASSERT(iState<=EVersionProcessed); // should only call this on construction
       
    81 	ASSERT(iOpaqueData.Length() >= KIndexForVersion + 1);
       
    82 	//The version is one byte
       
    83 	iVersion = iOpaqueData[KIndexForVersion];
       
    84 	iState = EVersionProcessed;
       
    85 	}
       
    86 
       
    87 
       
    88 // Extract the (optional) flags
       
    89 void COpaqueDataParse::ReadFlags()
       
    90 	{
       
    91 	ASSERT(iState<EFlagsProcessed);
       
    92 
       
    93 	switch(iVersion)
       
    94 		{
       
    95 		case KIclPluginFrameworkVersionZero:
       
    96 			iLenOfFlags = 0;
       
    97 			iLenOfUids = 8;
       
    98 			break;
       
    99 		case KIclPluginFrameworkVersionOne:
       
   100 			ASSERT(iOpaqueData.Length() >= KIndexForFlags + 2); // opaque data not valid otherwise
       
   101 			iFlags = (iOpaqueData[KIndexForFlags+0] << 8) | (iOpaqueData[KIndexForFlags+1]);
       
   102 			iLenOfFlags = 2;
       
   103 			iLenOfUids = 8;
       
   104 			break;
       
   105 		case KIclPluginFrameworkVersionTwo:
       
   106 			ASSERT(iOpaqueData.Length() >= KIndexForFlags + 2); // opaque data not valid otherwise
       
   107 			iFlags = (iOpaqueData[KIndexForFlags+0] << 8) | (iOpaqueData[KIndexForFlags+1]);
       
   108 			iLenOfFlags = 2;
       
   109 			iLenOfUids = 12;			
       
   110 			break;
       
   111 		}
       
   112 	
       
   113 	iStartOfUids = 1 + iLenOfFlags;
       
   114 	iStartOfNumberOfExtns = 1 + iLenOfFlags + iLenOfUids;
       
   115 	
       
   116 	iState = EFlagsProcessed;
       
   117 	}
       
   118 
       
   119 // Extract the two Uids 
       
   120 void COpaqueDataParse::ReadUids()
       
   121 	{
       
   122 	ASSERT(iState<EUidsProcessed);
       
   123 	ASSERT(iOpaqueData.Length() >= iStartOfUids + 4); // opaque data not valid otherwise
       
   124 	// A given OpaqueData should either contain one Uid, in 4 bytes,
       
   125 	// highest to lowest, with an implied second Uid set to KNullUid,
       
   126 	// or two consecutive Uids, in 4 bytes each - 8 in all - main type followed by sub-type.
       
   127 	// The 8 bytes may be followed, for basic types, by info on the file extensions
       
   128 	// and MIME typesassociated with this plugin but this info is ignored here.
       
   129 	iImageTypeUid.iUid = (iOpaqueData[iStartOfUids] << 24) | (iOpaqueData[iStartOfUids+1] << 16) | (iOpaqueData[iStartOfUids+2] << 8) | (iOpaqueData[iStartOfUids+3]);
       
   130 	
       
   131 	// In versions 0 and 1, we allow omission of the sub-type, but this is mandatory in 
       
   132 	// versions 2 and greater
       
   133 	if ( (iVersion < 2) && (iOpaqueData.Length() == iStartOfUids + 4) )
       
   134 		{
       
   135 		iImageSubTypeUid = KNullUid;
       
   136 		}
       
   137 	else 
       
   138 		{
       
   139 		ASSERT(iOpaqueData.Length() >= iStartOfUids + 8);
       
   140 		iImageSubTypeUid.iUid = (iOpaqueData[iStartOfUids+4] << 24) | (iOpaqueData[iStartOfUids+5] << 16) + (iOpaqueData[iStartOfUids+6] << 8) + (iOpaqueData[iStartOfUids+7]);
       
   141 		
       
   142 	// In version 2 and greater, the plugin class Uid can be supplied
       
   143 	    if (iVersion == 2) 
       
   144 	    	{	    	
       
   145 			if (iOpaqueData.Length() == iStartOfUids + 8)
       
   146 				{
       
   147 				iPluginClassUid = KNullUid;
       
   148 				}
       
   149 			else	
       
   150 				{		
       
   151 				ASSERT(iOpaqueData.Length() >= iStartOfUids + 12);
       
   152 				iPluginClassUid.iUid = (iOpaqueData[iStartOfUids+8] << 24) | (iOpaqueData[iStartOfUids+9] << 16) + (iOpaqueData[iStartOfUids+10] << 8) + (iOpaqueData[iStartOfUids+11]);
       
   153 				}
       
   154 	    	}
       
   155 		}
       
   156 	iState = EUidsProcessed;
       
   157 	}
       
   158 
       
   159 // read in the Extns from the opaque data
       
   160 void COpaqueDataParse::EnsureExtnsReadL()
       
   161 	{
       
   162 	// if we've already read in the extensions, is a NOP
       
   163 	if (iState>=EExtnsProcessed)
       
   164 		return;
       
   165 
       
   166 	ASSERT(iArray.Count()==0); // assume nothing in there at the moment
       
   167 
       
   168 	iExtnCount = iOpaqueData[iStartOfNumberOfExtns];
       
   169 	TInt pos = iStartOfNumberOfExtns+1; // start just after the extn count byte	
       
   170 
       
   171 	for (TInt index=0; index<iExtnCount; index++)
       
   172 		{
       
   173 		TPtrC8 restOfData = iOpaqueData.Mid(pos);
       
   174 		TInt endPos = restOfData.Locate(TChar('\r')); // \r is used to terminate each suffix
       
   175 		ASSERT(endPos>0); // if we have -1, would not have found the CR
       
   176 		TPtrC8 extn = restOfData.Left(endPos);
       
   177 		User::LeaveIfError(iArray.Append(extn));
       
   178 		pos += endPos + 1; // skip over the CR
       
   179 		}
       
   180 	iStartOfMimeTypes = pos;
       
   181 	iState = EExtnsProcessed;
       
   182 	ASSERT(iArray.Count()==iExtnCount);
       
   183 	}
       
   184 
       
   185 void COpaqueDataParse::EnsureMIMETypesReadL()
       
   186 	{
       
   187 	// if we've already read in the mime types, is a NOP
       
   188 	if (iState>=EMIMETypesProcessed)
       
   189 		return;
       
   190 
       
   191 	EnsureExtnsReadL();
       
   192 	ASSERT(iState==EExtnsProcessed);
       
   193 
       
   194 	TInt pos = iStartOfMimeTypes;
       
   195 	const TInt numMimeTypes = iOpaqueData[pos];
       
   196 	pos += 1;
       
   197 
       
   198 	for (TInt index=0; index<numMimeTypes; index++)
       
   199 		{
       
   200 		TPtrC8 restOfData = iOpaqueData.Mid(pos);
       
   201 		TInt endPos = restOfData.Locate(TChar('\r')); // \r is used to terminate each suffix
       
   202 		ASSERT(endPos>0); // if we have -1, would not have found the CR
       
   203 		TPtrC8 mimeType = restOfData.Left(endPos);
       
   204 		User::LeaveIfError(iArray.Append(mimeType));
       
   205 		pos += endPos + 1; // skip over the CR
       
   206 		}
       
   207 	iStartOfNumberOfBinProperties = pos;
       
   208 	iState = EMIMETypesProcessed;
       
   209 	ASSERT(iArray.Count()==iExtnCount+numMimeTypes);
       
   210 	}
       
   211 
       
   212 // Read in the binary properties from the opaque data.
       
   213 void COpaqueDataParse::EnsureBinaryPropertiesReadL()
       
   214 	{
       
   215 	// If we've already read in the binary properties or if 
       
   216 	if (iState >= EBinPropertiesProcessed || iVersion < KIclPluginFrameworkVersionTwo)
       
   217 		{
       
   218 		return;
       
   219 		}
       
   220 	
       
   221 	EnsureMIMETypesReadL();
       
   222 	ASSERT(iState == EMIMETypesProcessed);
       
   223 	ASSERT(iBinaryPropertiesArray.Count() == 0);
       
   224 	
       
   225 	//If we have a field for the binary properties
       
   226 	if(iStartOfNumberOfBinProperties < iOpaqueData.Length())
       
   227 		{
       
   228 		TInt binPropertiesCount = iOpaqueData[iStartOfNumberOfBinProperties];
       
   229 		
       
   230 		TInt pos = iStartOfNumberOfBinProperties + 1; // start just after the binary properties count byte	
       
   231 		
       
   232 		if(binPropertiesCount > 0)
       
   233 			{
       
   234 			// The lentgh of the binary properties field sould be a multiple of the size of TUid
       
   235 			if(((iOpaqueData.Length() - pos )/binPropertiesCount) != sizeof(TUid))
       
   236 				{
       
   237 				User::Leave(KErrNotSupported);
       
   238 				}
       
   239 			}
       
   240 		
       
   241 		TUid tempUid;
       
   242 		for (TInt index = 0; (index < binPropertiesCount) && ( (pos + sizeof(TUid)) <= iOpaqueData.Length()) ; index++)
       
   243 			{
       
   244 			// Real uids cannot have first byte in range 0x01 through 0x0f.
       
   245 			if(0x01 <= iOpaqueData[pos] && iOpaqueData[pos] <= 0x0f)
       
   246 				{
       
   247 				User::Leave(KErrNotSupported);
       
   248 				}
       
   249 			tempUid.iUid = (iOpaqueData[pos] << 24) | (iOpaqueData[pos+1] << 16) | (iOpaqueData[pos+2] << 8) | (iOpaqueData[pos+3]);
       
   250 			User::LeaveIfError(iBinaryPropertiesArray.Append(tempUid));
       
   251 			pos = pos + sizeof(TUid);
       
   252 			}
       
   253 		
       
   254 		iState = EBinPropertiesProcessed;
       
   255 		ASSERT(iBinaryPropertiesArray.Count() == binPropertiesCount);
       
   256 		}
       
   257 	}
       
   258 
       
   259 TBool COpaqueDataParse::CompareMIMETypes(const TDesC8& aMimeType1, const TDesC8& aMimeType2)
       
   260 	{
       
   261 	if (aMimeType1.Length() != aMimeType2.Length())
       
   262 		return EFalse;
       
   263 	return aMimeType1.CompareF(aMimeType2)==0; // true if exactly the same, if we ignore the case
       
   264 	}
       
   265 
       
   266 TBool COpaqueDataParse::CompareFileSuffixL(const TDesC& aFileSuffix1, const TDesC8& aFileSuffix2)
       
   267 	{
       
   268 	//First do a quick compare
       
   269 	if (aFileSuffix1.Length() != aFileSuffix2.Length())
       
   270 		return EFalse;
       
   271 
       
   272 	//Change aFileSuffix2 from TDesC8 to TDesC
       
   273 	HBufC* fileSuffix = HBufC::NewL(aFileSuffix2.Length()); //Not on CleanupStack since nothing can leave
       
   274 	TPtr fileSuffixPtr(fileSuffix->Des());
       
   275 	fileSuffixPtr.Copy(aFileSuffix2);
       
   276 
       
   277 	const TBool result = aFileSuffix1.CompareF(*fileSuffix)==0; // true if exactly the same, if we ignore the case
       
   278 	delete fileSuffix;
       
   279 
       
   280 	return result;
       
   281 	}
       
   282 
       
   283 void COpaqueDataParse::GetBinaryPropertiesArrayL(RUidDataArray& aBinaryPropertiesArray) const
       
   284 	{
       
   285 	aBinaryPropertiesArray.Reset();
       
   286 	for(TInt index = 0 ; index < iBinaryPropertiesArray.Count() ; index++)
       
   287 		{
       
   288 		User::LeaveIfError(aBinaryPropertiesArray.Append(iBinaryPropertiesArray[index]));
       
   289 		}
       
   290 	}
       
   291 
       
   292 TBool COpaqueDataParse::CheckRequiredUids(const RUidDataArray& aRequiredUids)
       
   293 	{
       
   294 	//First do a quick compare: we can't require more uids than provided, 
       
   295 	if(aRequiredUids.Count() > (iBinaryPropertiesArray.Count() + 3)) // 3 for the image-type, image-subtype and class plugin UIDs.
       
   296 		{
       
   297 		return EFalse;
       
   298 		}
       
   299 	
       
   300 	for(TInt index = 0 ; index < aRequiredUids.Count() ; index++)
       
   301 		{
       
   302 		if(
       
   303 			(iBinaryPropertiesArray.Find(aRequiredUids[index]) == KErrNotFound)
       
   304 			&& ( aRequiredUids[index]!=iImageTypeUid )
       
   305 			&& ( aRequiredUids[index]!=iImageSubTypeUid )
       
   306 			&& ( aRequiredUids[index]!=iPluginClassUid )
       
   307 			)
       
   308 			{
       
   309 			return EFalse;
       
   310 			}			
       
   311 		}
       
   312 
       
   313 	return ETrue;
       
   314 	}
       
   315 
       
   316 TBool COpaqueDataParse::CheckOptionsUids(const RUidDataArray& aOptionsUids)
       
   317 	{
       
   318 	//First do a quick compare: we can't require more uids than provided, 
       
   319 	if(aOptionsUids.Count() > (iBinaryPropertiesArray.Count() + 3)) // 3 for the image-type, image-subtype and class plugin UIDs.
       
   320 		{
       
   321 		return EFalse;
       
   322 		}
       
   323 	
       
   324 	for(TInt index = 0 ; index < aOptionsUids.Count() ; index++)
       
   325 		{
       
   326 		if(iBinaryPropertiesArray.Find(aOptionsUids[index]) == KErrNotFound)
       
   327 			{
       
   328 			return EFalse;
       
   329 			}			
       
   330 		}
       
   331 
       
   332 	return ETrue;
       
   333 	}
       
   334 
       
   335 TBool COpaqueDataParse::IsDefaultCodec() const
       
   336 	{
       
   337 	return (iBinaryPropertiesArray.Find(KUidDefaultCodec) != KErrNotFound);
       
   338 	}
       
   339 
       
   340 
       
   341 /*
       
   342  * Checks opaque data for the pair KUidICLExtension <extension_flags_modifier> where all
       
   343  * bits set in aRequiredExtensions are also set in <extension_flags_modifier>.
       
   344  * This signifies that the extension interfaces required are supported by the codec.
       
   345  * 
       
   346  * Note that there may be more than one KUidICLExtension pair set in the opaque data.
       
   347  * 
       
   348  * @return TBool
       
   349  *    ETrue indicates that the extensions are supported (interoperably)
       
   350  */
       
   351 TBool COpaqueDataParse::SupportsExtensionsL(TUint aRequiredExtensions)
       
   352 	{
       
   353 	if (!aRequiredExtensions)
       
   354 		{
       
   355 		return ETrue;
       
   356 		}
       
   357 	
       
   358 	EnsureBinaryPropertiesReadL();
       
   359 	
       
   360 	// Search through the iBinaryPropertiesArray looking for KUidICLExtension.
       
   361 	// The next entry should be the flags.
       
   362 	
       
   363 	TInt count = iBinaryPropertiesArray.Count();
       
   364 	for (TInt i = 0; i < (count - 1); i++)
       
   365 		{
       
   366 		TUid uid = iBinaryPropertiesArray[i];
       
   367 		if (uid == KUidICLExtension)
       
   368 			{
       
   369 			// It's stored in the array as a TUid but is really a TUint.
       
   370 			TUint codecCaps = static_cast<TUint>(iBinaryPropertiesArray[++i].iUid);
       
   371 			if ((codecCaps & aRequiredExtensions) == aRequiredExtensions)
       
   372 				{
       
   373 				return ETrue;
       
   374 				}
       
   375 			}
       
   376 		}
       
   377 	
       
   378 	return EFalse;
       
   379 	}
       
   380 
       
   381 
       
   382 /*
       
   383  * 
       
   384  * Searches for a match of aPluginString in aClientString. Match returns ETrue
       
   385  * if aPluginString is found within aImplementationType according to the
       
   386  * following rules:
       
   387  * 1) All bytes in aClientString are exact but instances of '?' (0x3F) in
       
   388  *    aPluginString are treated as wildcards - matching any byte value at that
       
   389  *    position in aClientString.
       
   390  * 2) If aClientString is longer than aPluginString, ignore any excess bytes.
       
   391  * 3) aClientString is treated as a single descriptor - the '||' delimiters
       
   392  *    are not recognised.
       
   393  * 4) ETrue is returned if aPluginString matches the start of aClientString
       
   394  *    exactly, subject to wildcards.
       
   395  * 5) aBytesMatched will be filled in with the number of non-wildcard bytes in
       
   396  *    aPluginString. This is used to rank matches.
       
   397  *
       
   398  * @param     "const TDesC8& aClientString"
       
   399  *            The string from the client to search for a match
       
   400  * @param     "const TDesC8& aPluginString"
       
   401  *            The data to search for from the plugin
       
   402  * @param     "TInt& aBytesMatched"
       
   403  *            The number of non-wildcard bytes matched
       
   404  * @return    "TBool"
       
   405  *            ETrue if a match was found, EFalse otherwise
       
   406  */
       
   407 TBool CImageConversionResolverUtils::Match(const TDesC8& aClientString, const TDesC8& aPluginString, TInt& aBytesMatched)
       
   408 	{
       
   409 	TInt pluginStringLength = aPluginString.Length();
       
   410 	while (pluginStringLength>0 && (aPluginString[pluginStringLength - 1] == '?'))
       
   411 		{ // Clip extraneous '?' wildcards off the end of the plugin match string
       
   412 		pluginStringLength--;
       
   413 		}
       
   414 	if (pluginStringLength == 0)
       
   415 		{ // Plugin has no match string (or just '?')
       
   416 		return EFalse;
       
   417 		}
       
   418 	if (aClientString.Length() == 0)
       
   419 		{ // Client string too short - can't match
       
   420 		return EFalse;
       
   421 		}
       
   422 	// Now let's run along the string
       
   423 	aBytesMatched = 0;
       
   424 	TUint matchLength = Min(pluginStringLength, aClientString.Length());
       
   425 	for (TInt index = 0; index < matchLength; index++)
       
   426 		{
       
   427 		const TUint8 pluginChar = aPluginString[index];
       
   428 		if (pluginChar=='?') // just ignore a wildchar
       
   429 			continue;
       
   430 		if (aClientString[index] != pluginChar)
       
   431 			return EFalse;
       
   432 		// else we've matched expected byte, so keep going
       
   433 		aBytesMatched += 1;
       
   434 		}
       
   435 	return aBytesMatched != 0;
       
   436 	}
       
   437