genericservices/mimerecognitionfw/apmime/APMREC.CPP
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/mimerecognitionfw/apmime/APMREC.CPP	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,670 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+// Defines CApaDataRecognizerType the base class for concrete mime recognizers that
+// perform the actual mime type recognitionand the CApaDataRecognizer that provides
+// the interface to the collection of recognizers.
+// 
+//
+
+
+#include "APMSTD.H"
+#include "APMREC.H"
+#include "APMPAN.H"
+#include "APMFNDR.H"
+
+#ifdef USING_ECOM_RECOGS
+#include <ecom/ecom.h>
+#endif
+
+NONSHARABLE_CLASS(CDataRecognizerExtension) : public CBase
+	{
+public:
+	inline static CDataRecognizerExtension* NewL() {return new(ELeave) CDataRecognizerExtension;}
+	inline TUid DestructorUid() const {return iDtorKey;}
+	inline TUid& DestructorUidReference() {return iDtorKey;}
+	inline CApaDataRecognizer& DataRecognizer() {return *iDataRecognizer;}
+	inline void SetDataRecognizer(CApaDataRecognizer& aDataRecognizer) {iDataRecognizer=&aDataRecognizer;}
+private:
+	inline CDataRecognizerExtension() {}
+private:
+	CApaDataRecognizer* iDataRecognizer; // no ownership
+	TUid iDtorKey; // destructor key to track the instance of ECOM implementation class
+	};
+
+class TDataToRecognize
+	{
+public:
+	TDataToRecognize(const TDesC& aName, const TDesC8& aBuffer);
+	TDataToRecognize(CApaDataRecognizer& aDataRecognizer, RFile& aFile, TInt aPreferredBufSize);
+	void RecognizeL(CApaDataRecognizerType& aDataRecognizerType);
+	void PrepareForRecognizeLoopLC();
+	void PopOffCleanupStackAndResetAfterRecognizeLoopL();
+private:
+	enum
+		{
+		EFlagFilePositionStored	=0x00000001,
+		EFlagLeaveIfError		=0x00000002
+		};
+private:
+	static void ResetAfterRecognizeLoopL(TAny* aThis);
+	void ResetAfterRecognizeLoopL();
+private:
+	TUint iFlags;
+	const TDesC* iName; // owned if iFile!=NULL
+	const TDesC8* iBuffer; // owned if iFile!=NULL
+	CApaDataRecognizer* iDataRecognizer;
+	RFile* iFile;
+	TInt iFilePosition;
+	TInt iPreferredBufSize;
+	};
+
+//
+// class CApaDataRecognizer
+//
+
+EXPORT_C TDataRecognitionResult CApaDataRecognizer::RecognizeL(const TDesC& aName, const TDesC8& aBuffer)
+	{
+	TDataToRecognize dataToRecognize(aName, aBuffer);
+	return RecognizeL(dataToRecognize);
+	}
+
+EXPORT_C TDataRecognitionResult CApaDataRecognizer::RecognizeL(RFile& aFile, TInt aPreferredBufSize)
+	{
+	TDataToRecognize dataToRecognize(*this, aFile, aPreferredBufSize);
+	return RecognizeL(dataToRecognize);
+	}
+
+TDataRecognitionResult CApaDataRecognizer::RecognizeL(TDataToRecognize& aDataToRecognize)
+// attempt to recognize using all recognizers
+// keeps recognizing until either a recognizer's confidence meets or 
+// exceeds the currently acceptable confidence, or all recognizers 
+// have been used
+	{
+	iResult.Reset();
+	aDataToRecognize.PrepareForRecognizeLoopLC();
+	TInt storedErr=KErrNone;
+	TInt count=iDataRecognizerList.Count();
+	for (TInt i=0; i<count; i++)
+		{
+		if (DoRecognize(iDataRecognizerList[i], aDataToRecognize, TDataType(), storedErr))
+			{
+			break;
+			}
+		}
+	aDataToRecognize.PopOffCleanupStackAndResetAfterRecognizeLoopL();
+	// if we haven't recognized anything and there was a problem with a recognizer, propagate
+	// the error.  n.b. if several recognizers had errors, only propagate the first error we 
+	// encountered
+	if (iResult.iConfidence==CApaDataRecognizerType::ENotRecognized)
+		{
+		User::LeaveIfError(storedErr);
+		}
+	return iResult;
+	}
+
+EXPORT_C TBool CApaDataRecognizer::RecognizeL(const TDesC& aName, const TDesC8& aBuffer, const TDataType& aDataType)
+	{
+	TDataToRecognize dataToRecognize(aName, aBuffer);
+	return RecognizeL(dataToRecognize, aDataType);
+	}
+
+EXPORT_C TBool CApaDataRecognizer::RecognizeL(RFile& aFile, TInt aPreferredBufSize, const TDataType& aDataType)
+	{
+	TDataToRecognize dataToRecognize(*this, aFile, aPreferredBufSize);
+	return RecognizeL(dataToRecognize, aDataType);
+	}
+
+TBool CApaDataRecognizer::RecognizeL(TDataToRecognize& aDataToRecognize, const TDataType& aDataType)
+// recognize using only recognizers which supply the aDataType
+	{
+	iResult.Reset();
+	TInt count=iDataRecognizerList.Count();
+	TInt storedErr=KErrNone;
+	aDataToRecognize.PrepareForRecognizeLoopLC();
+	for (TInt i=0; i<count; i++)
+		{
+		CApaDataRecognizerType* rec=iDataRecognizerList[i];
+		TInt countMime=rec->MimeTypesCount();
+		for (TInt ii=0; ii<countMime; ii++)
+			{
+			TDataType supportedDataType;
+			TRAPD(err, supportedDataType=rec->SupportedDataTypeL(ii));
+			if (err == KErrNone)
+				{
+				if (supportedDataType == aDataType)
+					{
+					if (DoRecognize(rec, aDataToRecognize, aDataType, storedErr))
+						{
+						aDataToRecognize.PopOffCleanupStackAndResetAfterRecognizeLoopL();
+						return ETrue;
+						}
+					break;
+					}
+				}
+			else if (storedErr==KErrNone)
+				{
+				// this is the first time we've hit an error with SupportedDataType,
+				// so store it now and propagate later if we don't find a suitable 
+				// recognizer
+				storedErr=err;
+				}
+			}
+		}
+	aDataToRecognize.PopOffCleanupStackAndResetAfterRecognizeLoopL();
+	if (iResult.iConfidence==CApaDataRecognizerType::ENotRecognized)
+		{
+		// a suitable recognizer wasn't found, but we may have encountered an
+		// error with one of the recognizers we scanned n.b. only the first error
+		// encountered is propagated
+		User::LeaveIfError(storedErr);
+		}
+	return iResult.iConfidence!=CApaDataRecognizerType::ENotRecognized;
+	}
+
+TBool CApaDataRecognizer::DoRecognize(CApaDataRecognizerType* aDataRecognizerType, TDataToRecognize& aDataToRecognize, const TDataType& aDataType, TInt& aError)
+// do the recognition, if the recognizer is sufficiently confident, return ETrue
+	{
+	TDataRecognitionResult result;
+	TRAPD(err, result=aDataRecognizerType->RecognizeL(aDataToRecognize));
+	if (err != KErrNone)
+		{
+		// We only want to store the first error, it if is not KErrNone, it means
+		// we have set this error previously
+		if (aError==KErrNone)
+			{
+			aError=err;
+			}
+		return EFalse;
+		}
+ 
+	if (aDataType!=result.iDataType && aDataType!=TDataType())
+		{
+		return EFalse;
+		}
+	if (result.iConfidence>iResult.iConfidence)
+		{
+		iResult=result;
+		return (result.iConfidence>=iAcceptedConfidence);
+		}
+	return EFalse;
+	}
+
+EXPORT_C TInt CApaDataRecognizer::AcceptedConfidence() const
+	{
+	return iAcceptedConfidence;
+	}
+
+EXPORT_C void CApaDataRecognizer::SetAcceptedConfidence(TInt aConfidence)
+	{
+	iAcceptedConfidence=aConfidence;
+	}
+
+EXPORT_C CApaDataRecognizer::~CApaDataRecognizer()
+	{
+	iDataRecognizerList.ResetAndDestroy();
+	iDataArray.Reset();
+	}
+
+EXPORT_C CApaDataRecognizer::CApaDataRecognizer(RFs& aFs)
+	:iFs(aFs),
+	iMaxBufferSize(-1),
+	iDataRecognizerList(KDataArrayGranularity),
+	iDataArray(KDataArrayGranularity),
+	iAcceptedConfidence(CApaDataRecognizerType::ECertain)
+	{}
+
+EXPORT_C void CApaDataRecognizer::AddDataRecognizerTypeL(CApaDataRecognizerType* aDataRecognizerType)
+// add the concrete recognizer into the list at the appropriate priority
+	{
+#if defined(_DEBUG)
+ 	CApaDataRecognizerType* rec=NULL;
+	const TInt countDeb=iDataRecognizerList.Count();
+	for (TInt ii=0; ii<countDeb; ii++)
+		{
+		rec=iDataRecognizerList[ii];
+ 		__ASSERT_ALWAYS(rec->TypeUid()!=aDataRecognizerType->TypeUid(), Panic(EDPanicDuplicateRecognizer));
+		}
+#endif // _DEBUG
+
+	TInt priority=aDataRecognizerType->Priority();
+	TInt count=iDataRecognizerList.Count();
+	for (TInt i=0; i<count; i++)
+		{
+		if (iDataRecognizerList[i]->Priority()<priority)
+			{
+			iDataRecognizerList.InsertL(aDataRecognizerType, i);
+			aDataRecognizerType->DataRecognizerExtension()->SetDataRecognizer(*this);
+			return;
+			}
+		}
+	iDataRecognizerList.AppendL(aDataRecognizerType);
+	aDataRecognizerType->DataRecognizerExtension()->SetDataRecognizer(*this);
+	}
+
+EXPORT_C void CApaDataRecognizer::CApaDataRecognizer_Reserved_1()
+	{}
+
+EXPORT_C TInt CApaDataRecognizer::RemoveDataRecognizerType(const CApaDataRecognizerType* aDataRecognizerType)
+// remove the concrete recognizer from the list
+// if it is not locked, if it fails return an error code
+	{
+	// find the recognizer in the list
+	TInt count=iDataRecognizerList.Count();
+	TUid uid=aDataRecognizerType->TypeUid();
+	TInt i;
+	for (i=0; i<count; i++)
+		{
+		if (iDataRecognizerList[i]->TypeUid()==uid)
+			break;
+		}
+	// did we find a match
+	if (i==count)
+		return KErrNotFound;
+	// is the matching recognizer locked
+	CApaDataRecognizerType* rec=iDataRecognizerList[i];
+	if (rec->Locked())
+		return KErrLocked;
+	// remove the recognizer from the list, then delete it
+	delete rec;
+	iDataRecognizerList.Remove(i);
+	iDataRecognizerList.Compress();
+	return KErrNone;
+	}
+
+EXPORT_C void CApaDataRecognizer::DataTypeL(CDataTypeArray& aArray)
+	{
+	TInt count=iDataArray.Count();
+	for (TInt i=0; i<count; i++)
+		aArray.AppendL(iDataArray[i]);
+	}
+
+EXPORT_C void CApaDataRecognizer::UpdateDataTypesL()
+// rebuild the list of unique mime types
+	{
+	iDataArray.Reset();
+	TInt count=iDataRecognizerList.Count();
+	for (TInt i=0; i<count; i++)
+		{
+		CApaDataRecognizerType* rec=iDataRecognizerList[i];
+		TRAP_IGNORE(rec->UpdateDataTypesL());
+		TInt mimeCount=rec->MimeTypesCount();
+		for (TInt ii=0; ii<mimeCount; ii++)
+			{
+			TRAP_IGNORE(AddDataTypeL(rec->SupportedDataTypeL(ii)));
+			}
+		}
+	}
+
+EXPORT_C TInt CApaDataRecognizer::PreferredBufSize() const
+// return the maximum preferred buf size
+	{
+	if (iMaxBufferSize < 0)
+		{
+		// The recognizers have been (re)loaded, so calulate the maximum buffer size.
+		TInt count=iDataRecognizerList.Count();
+		for (TInt i=0; i<count; i++)
+			iMaxBufferSize=Max((TInt)iDataRecognizerList[i]->PreferredBufSize(), iMaxBufferSize);
+		}
+	return iMaxBufferSize;
+	}
+
+EXPORT_C void CApaDataRecognizer::DestroyRecognizerList()
+	{
+	iDataRecognizerList.ResetAndDestroy();
+	iDataArray.Reset();
+	}
+
+void CApaDataRecognizer::AddDataTypeL(const TDataType& aDataType)
+// add a mime type to the array if it's unique
+	{
+	TInt i=iDataArray.Count()-1;
+	for (; i>=0; i--)
+		{
+		if (aDataType==iDataArray[i])
+			return;
+		}
+	iDataArray.AppendL(aDataType);
+	}
+
+//
+// class CApaDataRecognizerType
+//
+
+EXPORT_C CApaDataRecognizerType::CApaDataRecognizerType(TUid aUid, TInt aPriority)
+	:iTypeUid(aUid),
+	iPriority(aPriority),iDataRecognizerExtn(NULL)
+/** Constructs the recognizer with a UID and a priority.
+
+Typically, a derived class constructor calls this constructor through a constructor 
+initialization list.
+
+The UID is the way that a recognizer is detected by the framework.
+
+@param aUid A UID that identifies the recognizer.
+@param aPriority A value that estimates the probability that the recognizer 
+will successfully identify data. This is one of the CApaDataRecognizerType::TRecognizerPriority 
+enumerators.
+@see CApaDataRecognizerType::TRecognizerPriority */
+	{}
+
+EXPORT_C CApaDataRecognizerType::~CApaDataRecognizerType()
+// Destructor.
+	{
+#ifdef USING_ECOM_RECOGS
+	//if ecom plugin is used destroy its implementation
+	if(iDataRecognizerExtn!=NULL)
+		{
+		REComSession::DestroyedImplementation(iDataRecognizerExtn->DestructorUid());
+		delete iDataRecognizerExtn;
+		}
+#endif
+	}
+
+EXPORT_C void CApaDataRecognizerType::Lock()
+/** Adds a lock to the recognizer.
+
+This may be called any number of times, but each call to this function must 
+be matched by a corresponding call to Unlock() to completely unlock the recognizer.
+
+This function is used to prevent the recognizer DLL from being unloaded.
+
+@see Unlock()
+@see Locked() */
+	{
+	iLock++;
+	}
+
+EXPORT_C void CApaDataRecognizerType::Unlock()
+/** Removes a lock from the recognizer.
+
+All calls to Lock() should be matched by a corresponding call to this function. 
+The recognizer is not unlocked until all calls to Lock() have been matched 
+by corresponding calls to this function.
+
+@see Lock()
+@see Locked() */
+	{
+	if (iLock>0)
+		iLock--;
+	}
+
+EXPORT_C TUint CApaDataRecognizerType::PreferredBufSize()
+/** Gets the size of buffer preferred for the purpose of recognizing the data type.
+
+Regardless of the preferred buffer size returned by an implementation of this 
+function, the actual size used is never greater than a maximum value as set 
+by the client of the Application Architecture server through a call to RApaLsSession::SetMaxDataBufSize().
+
+@return The preferred data size. The default implementation returns zero.
+@see RApaLsSession::SetMaxDataBufSize() */
+	{
+	return 0;	// default to no buffer
+				// name recognition only
+	}
+
+EXPORT_C void CApaDataRecognizerType::UpdateDataTypesL()
+/** Refreshes the list of data (MIME) types supported by this recognizer. */
+	{
+	}
+
+EXPORT_C void CApaDataRecognizerType::DoRecognizeL(const TDesC& aName, const TDesC8& aBuffer)
+/** Implements the attempt to recognize data.
+
+Recognizers should provide an implementation of this function in a derived 
+class. Note that, when the implementation recognizes data, it must put the 
+result of the operation in the iDataType and iConfidence data members.
+
+Note that if more data is required than is provided in aBuffer, then 
+CApaDataRecognizerType::FilePassedByHandleL should be called and the data 
+read from the returned RFile (if not NULL). If this returns NULL, it may be 
+possible to retrieve the data by calling RFile::Open() on aName, but only if 
+aName is a legal file-name. It may be something else, such as a URL.
+
+The default implementation does not recognize data.
+
+@param aName The name of the data; typically this is a file name containing 
+the data to be recognized. It is not necessarily a legal file-name though. It 
+may, for example, be a URL/URI.
+@param aBuffer A buffer containing data to be recognized; typically, this is 
+read from the start of the file containing the data.
+@see RecognizeL()
+@see FilePassedByHandleL()
+*/
+	{
+	(void)aName;
+	(void)aBuffer;
+	iDataType=TDataType();
+	}
+
+EXPORT_C RFile* CApaDataRecognizerType::FilePassedByHandleL()
+/** Returns the RFile (if any) of file to be recognized.
+
+This function returns the file passed by handle from the client-side (i.e. from calls to the RFile-parameter overloads of RApaLsSession's RecognizeData, RecognizeSpecificData, AppForDocument and StartDocument). The function returns NULL if the file to be recognized was not passed by handle.
+
+It may only be called from implementations of DoRecognizeL - indeed the purpose of this function is logically to provide an extra parameter to the virtual DoRecognizeL function. All references/pointers to the 
+RFile object returned must be discarded when the implementation of DoRecognizeL returns.
+
+The RFile returned (if any) may be used by implementations of DoRecognizeL to retrieve more data than is provided in DoRecognizeL's aBuffer parameter.
+
+The current-position of the returned RFile is the start of the file.
+
+@return The file, passed by handle, to be recognized. Returns NULL if the data to be recognized was passed from the client-side by name/buffer rather than by file-handle. Ownership of the returned object is NOT transferred to the caller.
+@see DoRecognizeL()
+*/
+	{
+	RFile* const filePassedByHandle=iDataRecognizerExtn->DataRecognizer().FilePassedByHandle();
+	if (filePassedByHandle!=NULL && (filePassedByHandle->SubSessionHandle()!=KNullHandle))
+		{
+		// set the current file-position to the start of the file
+		TInt filePosition=0;
+		User::LeaveIfError(filePassedByHandle->Seek(ESeekStart, filePosition));
+		}
+	return filePassedByHandle;
+	}
+
+EXPORT_C TDataRecognitionResult CApaDataRecognizerType::RecognizeL(const TDesC& aName, const TDesC8& aBuffer)
+/** Attempts to recognize data.
+
+This function is called by the Application Architecture server as a result 
+of client calls to the server through an instance of RApaLsSession.
+
+The function calls DoRecognizeL() which implements recognition behaviour.
+
+@param aName The name of the data; typically this is a file name containing 
+the data to be recognized.
+@param aBuffer A buffer containing data to be recognized; typically, this is 
+read from the start of the file containing the data. Implement PreferredBufSize() 
+to define the ideal size for this buffer. Note that failure to implement PreferredBufSize() 
+results in a default buffer size of zero.
+@return The result of the attempt to recognize the data.
+@see PreferredBufSize()
+@see RApaLsSession
+@see RApaLsSession::SetMaxDataBufSize() */
+	{
+	TDataToRecognize dataToRecognize(aName, aBuffer);
+	return RecognizeL(dataToRecognize);
+	}
+
+TDataRecognitionResult CApaDataRecognizerType::RecognizeL(TDataToRecognize& aDataToRecognize)
+/**
+@internalComponent
+*/
+	{
+	iDataType=TDataType();
+	iConfidence=ENotRecognized;
+	aDataToRecognize.RecognizeL(*this);
+	TDataRecognitionResult rec;
+	rec.iDataType=iDataType;
+	rec.iConfidence=iConfidence;
+	return rec;
+	}
+
+EXPORT_C TDataType CApaDataRecognizerType::MimeType()
+/** Gets the data (MIME) type of the most recently recognized data.
+
+@return The data (MIME) type.
+@see iDataType */
+	{
+	return iDataType;
+	}
+
+EXPORT_C void CApaDataRecognizerType::Reserved_1()
+// a spare empty virtual function
+	{}
+
+// instantiate the ecom implementation class 
+EXPORT_C CApaDataRecognizerType* CApaDataRecognizerType::CreateDataRecognizerL(TUid aImplUid)
+	{
+#if !defined(USING_ECOM_RECOGS)
+	(void)aImplUid;
+	return NULL;
+#endif
+	CDataRecognizerExtension* const dataRecognizerExtn=CDataRecognizerExtension::NewL();
+	CleanupStack::PushL(dataRecognizerExtn);
+
+	CApaDataRecognizerType* const dataRecType=static_cast <CApaDataRecognizerType*>(REComSession::CreateImplementationL(aImplUid, dataRecognizerExtn->DestructorUidReference()));
+
+	dataRecType->iDataRecognizerExtn = dataRecognizerExtn;
+	CleanupStack::Pop(dataRecognizerExtn);
+
+	return dataRecType;
+	}
+
+CDataRecognizerExtension* CApaDataRecognizerType::DataRecognizerExtension()
+/** @internalComponent */
+	{
+	return iDataRecognizerExtn;
+	}
+
+//
+// class TDataRecognitionResult
+//
+
+EXPORT_C void TDataRecognitionResult::Reset()
+/** Resets the data type to the default data type and sets the confidence rating 
+to CApaDataRecognizerType::ENotRecognized.
+
+@see CApaDataRecognizerType::TRecognitionConfidence
+@see TDataType */
+	{
+	iDataType=TDataType();
+	iConfidence=CApaDataRecognizerType::ENotRecognized;
+	}
+
+//
+// class TDataToRecognize
+//
+
+TDataToRecognize::TDataToRecognize(const TDesC& aName, const TDesC8& aBuffer)
+	:iFlags(0),
+	 iName(&aName),
+	 iBuffer(&aBuffer),
+	 iDataRecognizer(NULL),
+	 iFile(NULL),
+	 iFilePosition(0),
+	 iPreferredBufSize(0)
+	{
+	__ASSERT_DEBUG(aName.Length()>0 || aBuffer.Length()>0, Panic(EDPanicInvalidData));
+	}
+
+TDataToRecognize::TDataToRecognize(CApaDataRecognizer& aDataRecognizer, RFile& aFile, TInt aPreferredBufSize)
+	:iFlags(0),
+	 iName(NULL),
+	 iBuffer(NULL),
+	 iDataRecognizer(&aDataRecognizer),
+	 iFile(&aFile),
+	 iFilePosition(0),
+	 iPreferredBufSize(aPreferredBufSize)
+	{
+	}
+
+void TDataToRecognize::RecognizeL(CApaDataRecognizerType& aDataRecognizerType)
+	{
+	__ASSERT_DEBUG(iName!=NULL, Panic(EDPanicNullPointer1));
+	__ASSERT_DEBUG(iBuffer!=NULL, Panic(EDPanicNullPointer2));
+	aDataRecognizerType.DoRecognizeL(*iName, *iBuffer);
+	}
+
+void TDataToRecognize::PrepareForRecognizeLoopLC()
+	{
+	CleanupStack::PushL(TCleanupItem(ResetAfterRecognizeLoopL, this));
+	if (iFile!=NULL)
+		{
+		// set the file-pointer returned by CApaDataRecognizerType::FilePassedByHandleL
+		iDataRecognizer->SetFilePassedByHandle(iFile);
+
+		// store current-position in iFilePosition
+		__ASSERT_DEBUG((iFlags&EFlagFilePositionStored)==0, Panic(EDPanicBadFlagState1));
+		iFlags|=EFlagFilePositionStored;
+		iFilePosition=0;
+		User::LeaveIfError(iFile->Seek(ESeekCurrent, iFilePosition));
+
+		// read a buffer of the appropriate length from the start of the file
+		__ASSERT_DEBUG(iBuffer==NULL, Panic(EDPanicNullPointerExpected1));
+		TInt filePosition=0;
+		User::LeaveIfError(iFile->Seek(ESeekStart, filePosition));
+		HBufC8* const buffer=HBufC8::NewL(iPreferredBufSize);
+		iBuffer=buffer; // iBuffer now "owns" this (as long as iFile!=NULL, which is true)
+		TPtr8 buffer_asWritable(buffer->Des());
+		User::LeaveIfError(iFile->Read(buffer_asWritable));
+
+		// prepend "::" to the file-name to be passed to DoRecognizeL to make it an illegal file-name - this
+		// is to prevent any behavioural break since implementers of DoRecognizeL may assume that if aName is
+		// *not* an illegal file-name they can pass it to RFile::Open, which will not be possible if we're
+		// recognizing by file-handle, both because of data-caging (the file may not live in a directory that
+		// the Apparc process has permission to open it from) and because aName does not contain the full path
+		__ASSERT_DEBUG(iName==NULL, Panic(EDPanicNullPointerExpected2));
+		TDes* const name=new(ELeave) TFileName;
+		iName=name; // iName now "owns" this (as long as iFile!=NULL, which is true)
+		User::LeaveIfError(iFile->Name(*name));
+		_LIT(KLitIllegalifier, "::");
+		name->Insert(0, KLitIllegalifier);
+		}
+	}
+
+void TDataToRecognize::PopOffCleanupStackAndResetAfterRecognizeLoopL()
+	{
+	iFlags|=EFlagLeaveIfError; // we don't want to leave from ResetAfterRecognizeLoopL if we're being cleaned up from the clean-up stack because of a leave, but if we're leaving because of a CleanupStack::PopAndDestroy then it's okay to leave
+	CleanupStack::PopAndDestroy(this); // calls ResetAfterRecognizeLoopL
+	}
+
+void TDataToRecognize::ResetAfterRecognizeLoopL(TAny* aThis)
+	{ // static
+	STATIC_CAST(TDataToRecognize*, aThis)->ResetAfterRecognizeLoopL();
+	}
+
+void TDataToRecognize::ResetAfterRecognizeLoopL()
+	{
+	TInt error=KErrNone;
+	if (iFile!=NULL)
+		{
+		// NULLify the file-pointer returned by CApaDataRecognizerType::FilePassedByHandleL
+		iDataRecognizer->SetFilePassedByHandle(NULL);
+
+		// reset the current-position of the file
+		__ASSERT_DEBUG(iFlags&EFlagFilePositionStored, Panic(EDPanicBadFlagState2));
+		error=iFile->Seek(ESeekStart, iFilePosition);
+		iFlags&=~EFlagFilePositionStored;
+
+		// delete the objects that are owned if iFile!=NULL (which is true)
+		delete iName;
+		delete iBuffer;
+		}
+	if (iFlags&EFlagLeaveIfError)
+		{
+		iFlags&=~EFlagLeaveIfError; // probably not necessary, just defensive programming
+		User::LeaveIfError(error);
+		}
+	}
+