contentmgmt/contentaccessfwfordrm/source/reccaf/CafApaRecognizer.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contentmgmt/contentaccessfwfordrm/source/reccaf/CafApaRecognizer.cpp	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,271 @@
+/*
+* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include <s32file.h>
+#include <ecom/ecom.h>
+#include <ecom/implementationproxy.h>
+
+#include "resolver.h"
+#include "mimetypemapping.h"
+#include "CafApaRecognizer.h"
+
+using namespace ContentAccess;
+
+
+CApaCafRecognizer* CApaCafRecognizer::NewL()
+	{
+	CApaCafRecognizer* self;
+	self = new (ELeave) CApaCafRecognizer();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CApaCafRecognizer::ConstructL()
+	{
+	iResolver = CAgentResolver::NewL(ETrue);
+	SetupContentTypesL();
+	}
+
+CApaCafRecognizer::CApaCafRecognizer() : 
+	CApaDataRecognizerType(KUidCafApaRecognizer, CApaDataRecognizerType::ELow)
+	{
+	// Assume initially we don't recognize any data types (ie. no agents)
+	iCountDataTypes = 0;
+	}
+
+CApaCafRecognizer::~CApaCafRecognizer()
+	{
+	iContentTypes.ResetAndDestroy();
+	delete iResolver;
+	}
+
+void CApaCafRecognizer::SetupContentTypesL()
+	{
+	// Construct the array used to map content types to our drm mime types
+	CMimeTypeMapping* mimeType; 
+
+	// The RecCaf configuration file is just a list of content mime types
+	// CApaCafRecognizer expects each mime type to be on a separate line
+	// The configuration file is stored in the Apparc server's private directory.
+	// This should be ok since the recognizer is run in the apparc servers process
+	
+	// ROM file
+	_LIT(KRomConfigurationFile, "Z:\\private\\10003A3F\\RecCaf\\RecCafMimeTypes.txt");
+
+	// System drive file	
+	_LIT(KConfigurationFile, "_:\\private\\10003A3F\\RecCaf\\RecCafMimeTypes.txt");
+	TBuf<47> sysDriveConfigFile(KConfigurationFile);
+	sysDriveConfigFile[0] = 'A' + static_cast<TInt>(RFs::GetSystemDrive());
+
+	RFs fs;
+	User::LeaveIfError(fs.Connect());
+	CleanupClosePushL(fs);
+
+	RFile file;
+	TInt result = file.Open(fs, sysDriveConfigFile, EFileRead | EFileStream | EFileShareAny);
+	if (result != KErrNone)
+		{
+		result = file.Open(fs, KRomConfigurationFile(), EFileRead | EFileStream | EFileShareAny);
+		}
+
+	if (result == KErrNone)
+		{
+		CleanupClosePushL(file);
+		
+		// create file stream
+		RFileReadStream inputFileStream(file);
+	    CleanupClosePushL(inputFileStream);
+
+		TBuf8 <KMaxDataTypeLength> buf;
+
+		do
+			{
+			// Read a content mime type from the file
+			result = ReadLine(inputFileStream, buf);
+
+			if (result == KErrNone || result == KErrEof)
+				{
+				// Add a new entry into the array of mime types
+				if (buf.Length())
+					{
+					// force to lower case to ensure that chosen lower case scheme for mime
+					// types is maintained
+					buf.LowerCase();
+					mimeType = CMimeTypeMapping::NewL(buf);
+					CleanupStack::PushL(mimeType);
+					User::LeaveIfError(iContentTypes.Append(mimeType));
+					CleanupStack::Pop(mimeType); 
+					}
+				}
+			else
+				{
+				// Encountered an error reading the file
+				// don't know how to recover so leave
+				iContentTypes.ResetAndDestroy();
+				User::Leave(result);
+				}
+			} while (result != KErrEof);
+
+		CleanupStack::PopAndDestroy(2, &file); // inputFileStream, file
+		}
+
+	CleanupStack::PopAndDestroy(&fs);
+
+	// Add multiple content object file mime type
+	_LIT8(KApplicationXCafStr, "application/x-caf");
+	mimeType = CMimeTypeMapping::NewL(KApplicationXCafStr());
+	CleanupStack::PushL(mimeType);
+	User::LeaveIfError(iContentTypes.Append(mimeType));
+	CleanupStack::Pop(mimeType); 
+
+
+	// Add supplier Mime types 
+	// otherwise nobody will recognize unprocessed files 
+	// that could be churned through the CAF Supplier API
+	// The resolver ensures that its supplier mime types are lower case
+	for(TInt index = 0; index < iResolver->SupplierMimeTypes().Count(); index++)
+		{
+		mimeType = CMimeTypeMapping::NewL(iResolver->SupplierMimeTypes()[index],
+										  iResolver->SupplierMimeTypes()[index]);
+		CleanupStack::PushL(mimeType);
+		User::LeaveIfError(iContentTypes.Append(mimeType));
+		CleanupStack::Pop(mimeType); 
+		}
+	
+	iCountDataTypes = iContentTypes.Count();
+	}
+
+TInt CApaCafRecognizer::ReadLine(RFileReadStream& aInStream, TDes8& aBuffer)
+	{
+	const TChar KCarriageReturn = '\r';
+	const TChar KLineFeed = '\n';
+
+	// Clear the buffer
+	aBuffer.SetLength(0);
+	
+	// Read line upto linefeed delimiter
+	TRAPD(err, aInStream.ReadL(aBuffer, KLineFeed));
+	TInt length = aBuffer.Length();
+	
+	// assume all lines must end in CRLF and do not 
+	// allow blank lines. So length must be at least 2 for
+	// the CRLF characters
+	if(length < 3)
+		{
+		err = KErrEof;
+		}
+	if (err == KErrNone)
+		{
+		// remove line feed and any carriage return 
+		if (aBuffer[length - 1] == KLineFeed)
+			{
+			--length;
+			}
+		if (aBuffer[length - 1] == KCarriageReturn)
+			{
+			--length;
+			}
+		aBuffer.SetLength(length);
+		}
+	return err;
+	}
+
+
+TUint CApaCafRecognizer::PreferredBufSize()
+	{
+	// Ask all of the agents if they have a preferred buffer size for calls to DoRecognizeL()
+	return iResolver->PreferredBufferSize();
+	}
+
+TDataType CApaCafRecognizer::SupportedDataTypeL(TInt aIndex) const
+	{
+	// leave if an out of range aIndex is supplied
+	if (aIndex < 0 || aIndex >= iContentTypes.Count())
+		{
+		User::Leave(KErrArgument);
+		}
+
+	return TDataType(iContentTypes[aIndex]->CafMimeType());
+	}
+	
+void CApaCafRecognizer::DoRecognizeL(const TDesC& aName, const TDesC8& aBuffer)
+	{
+	TBuf8 <KMaxDataTypeLength> FileMimeType;
+	TBuf8 <KMaxDataTypeLength> ContentMimeType;
+	
+	// Need to start by assuming we don't recognize the file
+	iConfidence = ENotRecognized;
+	
+	TBool isRecognized = EFalse;
+	
+	// If aName is prepended with 2 colons (::), then it is not valid, and we need to
+	// derive it from the file handle. Otherwise, we assume that aName is valid
+	if (aName.Match(_L("::*")) == KErrNotFound)
+		{
+		isRecognized = iResolver->DoRecognizeL(aName, aBuffer, FileMimeType, ContentMimeType);
+		}
+	// aName is not a valid URI/filename and a file handle must be used. This is marked
+	// by two colons at the start of aName.
+	// We need to get the actual file name from the file handle.
+	else 
+		{
+		RFile* fileHandle = CApaCafRecognizer::FilePassedByHandleL();
+		TBuf<KMaxDataTypeLength> fileName;
+		User::LeaveIfError(fileHandle->Name(fileName));
+		isRecognized = iResolver->DoRecognizeL(fileName, aBuffer, FileMimeType, ContentMimeType);
+		}
+	
+	if (isRecognized)
+		{
+		// If there is no content type but the file is recognized it is assumed
+		// to be a file that can be processed through the supplier interface
+		
+		// dummy object for comparison in match function
+		CMimeTypeMapping* mimeTypeMapping = (ContentMimeType.Length() == 0) ?  
+												CMimeTypeMapping::NewL(FileMimeType) :
+												CMimeTypeMapping::NewL(ContentMimeType);
+
+
+		// check that the content mime type is one of the ones we
+		// told Apparc we can recognize in the beginning
+		// The mime type should always be found as the file has been recognised.
+		// If not it is because an agent, when recognising the file, has set a mime type not in its supplier list.
+		// Mime types are always forced to lower case therefore this match can be case sensitive.
+		TInt index = iContentTypes.Find(mimeTypeMapping, CMimeTypeMapping::ContentMimeTypeMatch);
+		if (index != KErrNotFound)
+			{
+			iDataType = TDataType(iContentTypes[index]->CafMimeType());
+			iConfidence=ECertain;
+			}
+
+		delete mimeTypeMapping;
+		}
+	}
+
+const TImplementationProxy ImplementationTable[] = 
+	{
+	IMPLEMENTATION_PROXY_ENTRY(0x102031E9, CApaCafRecognizer::NewL)
+	};
+
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+	{
+	aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+	return ImplementationTable;
+	}