realtimenetprots/sipfw/ClientResolver/Resolver/src/CSIPFeatureSet.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/ClientResolver/Resolver/src/CSIPFeatureSet.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,357 @@
+// Copyright (c) 2006-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:
+// Name          : CSIPFeatureSet.cpp
+// Part of       : SIP Client Resolver
+// Version       : 1.0
+//
+
+
+
+#include "CSIPFeatureSet.h"
+#include "CSIPBooleanFeatureTag.h"
+#include "CSIPNumericFeatureTag.h"
+#include "CSIPStringFeatureTag.h"
+#include "CSIPTokenFeatureTag.h"
+#include "sipacceptcontactheader.h"
+#include "TTagValueListParser.h"
+#include "sipstrings.h"
+#include "sipstrconsts.h"
+
+_LIT8(KTrue, "TRUE");
+_LIT8(KFalse, "FALSE");
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::NewL
+// -----------------------------------------------------------------------------
+//
+CSIPFeatureSet* CSIPFeatureSet::NewL()
+	{
+	CSIPFeatureSet* self = CSIPFeatureSet::NewLC();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::NewLC
+// -----------------------------------------------------------------------------
+//
+CSIPFeatureSet* CSIPFeatureSet::NewLC()
+	{
+	CSIPFeatureSet* self = new(ELeave)CSIPFeatureSet;
+	CleanupStack::PushL(self);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::NewL
+// -----------------------------------------------------------------------------
+//
+CSIPFeatureSet* CSIPFeatureSet::NewL(
+    const CSIPAcceptContactHeader& aAcceptContactHeader)
+	{
+	CSIPFeatureSet* self = CSIPFeatureSet::NewLC(aAcceptContactHeader);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::NewLC
+// -----------------------------------------------------------------------------
+//
+CSIPFeatureSet* CSIPFeatureSet::NewLC(
+    const CSIPAcceptContactHeader& aAcceptContactHeader)
+	{
+	CSIPFeatureSet* self = new(ELeave)CSIPFeatureSet;
+	CleanupStack::PushL(self);
+	self->ConstructL(aAcceptContactHeader);
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::CSIPFeatureSet
+// -----------------------------------------------------------------------------
+//
+CSIPFeatureSet::CSIPFeatureSet()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CSIPFeatureSet::ConstructL(
+    const CSIPAcceptContactHeader& aAcceptContactHeader)
+	{
+    AddFeaturesL(aAcceptContactHeader);
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::~CSIPFeatureSet
+// -----------------------------------------------------------------------------
+//
+CSIPFeatureSet::~CSIPFeatureSet()
+	{
+	iFeatureTags.ResetAndDestroy();
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::AddFeaturesL
+// -----------------------------------------------------------------------------
+//
+void CSIPFeatureSet::AddFeaturesL(
+    const CSIPAcceptContactHeader& aAcceptContactHeader)
+    {
+	TInt paramCount = aAcceptContactHeader.ParamCount();
+	for(TInt i = 0; i < paramCount; i++)
+	    {
+	    RStringF name;
+	    User::LeaveIfError(aAcceptContactHeader.Param(i,name));
+	    CleanupClosePushL(name);
+	    if (IsFeatureParamName(name))
+	        {
+    	    RStringF value = aAcceptContactHeader.ParamValue(name);
+    	    AddFeatureTagsL(name,value.DesC());
+	        }
+	    CleanupStack::PopAndDestroy(1); // name
+	    }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::Require
+// -----------------------------------------------------------------------------
+//
+TBool CSIPFeatureSet::Require() const
+	{
+	return iRequire;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::CalculateScore
+// -----------------------------------------------------------------------------
+//
+TInt CSIPFeatureSet::CalculateScore(const CSIPFeatureSet& aFeatureSet) const
+	{
+	TInt score = 0;
+	for(TInt i = 0; i < aFeatureSet.iFeatureTags.Count(); i++)
+	    {
+	    const CSIPFeatureTag* otherTag = aFeatureSet.iFeatureTags[i];
+        for(TInt j = 0; j < iFeatureTags.Count(); j++)
+            {
+            const CSIPFeatureTag* myTag = iFeatureTags[j];
+            if (myTag->Match(*otherTag))
+    	        {
+    	        score++;
+    	        }
+    	    }
+	    }
+	if (aFeatureSet.Require() && score < aFeatureSet.iFeatureTags.Count())
+	    {
+	    // All feature tags should match if require-tag is present
+	    score = 0;
+	    }
+	return score;
+	}
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::AddFeatureTagsL
+// -----------------------------------------------------------------------------
+//	
+void CSIPFeatureSet::AddFeatureTagsL(
+    RStringF aName,
+    const TDesC8& aValue)
+    {
+    if (aValue.Length() > 0)
+        {
+        TPtrC8 value;
+        RemoveQuotesL(aValue,value);
+        if (value[0] == '<')
+            {
+            CSIPFeatureTag* fTag = CSIPStringFeatureTag::NewLC(aName,value);
+            iFeatureTags.AppendL(fTag);
+            CleanupStack::Pop(fTag);            
+            }
+        else
+            {
+            TTagValueListParser parser;
+            parser.Parse(value);
+            while (!parser.Eos())
+                {
+                TPtrC8 segment;
+                User::LeaveIfError(parser.GetNext(segment));
+                AddFeatureTagL(aName,segment);
+                }            
+            }
+        }
+    else
+        {
+        AddBooleanFeatureTagL(aName,EFalse,ETrue);    
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::AddFeatureTagL
+// -----------------------------------------------------------------------------
+//
+void CSIPFeatureSet::AddFeatureTagL(
+    RStringF aName,
+    const TDesC8& aValue)
+    {
+    TBool negation = EFalse;
+    TLex8 lex(aValue);
+    TChar chr = lex.Get();
+    if (chr == '!')
+        {
+        negation = ETrue;
+        chr = lex.Get();
+        }
+    if (chr == '#')
+        {
+        CSIPFeatureTag* fTag = 
+            CSIPNumericFeatureTag::NewLC(aName,negation,lex.Remainder());
+        iFeatureTags.AppendL(fTag);
+        CleanupStack::Pop(fTag);
+        }
+    else
+        {
+        lex.UnGet();
+        TPtrC8 value(lex.Remainder());
+        if (value.CompareF(KTrue) == 0 || 
+            value.CompareF(KFalse) == 0 ||
+            value.Length() == 0)
+            {
+            TBool boolVal = !(value.CompareF(KFalse) == 0);
+            AddBooleanFeatureTagL(aName,negation,boolVal);
+            }
+        else
+            {
+            CSIPFeatureTag* fTag = 
+                CSIPTokenFeatureTag::NewLC(aName,negation,value);
+            iFeatureTags.AppendL(fTag);
+            CleanupStack::Pop(fTag);            
+            }
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::AddBooleanFeatureTagL
+// -----------------------------------------------------------------------------
+//
+void CSIPFeatureSet::AddBooleanFeatureTagL(
+    RStringF aName,
+    TBool aNegation,
+    TBool aValue)
+    {
+    if (aName == SIPStrings::StringF(SipStrConsts::ERequire))
+        {
+        iRequire = ETrue;
+        }
+    else if (aName == SIPStrings::StringF(SipStrConsts::EExplicit))
+        {
+        // explicit-parameter not handled. 
+        // It must not be added to feature set
+        }
+    else
+        {
+        CSIPFeatureTag* fTag = 
+            CSIPBooleanFeatureTag::NewLC(aName,aNegation,aValue);
+        iFeatureTags.AppendL(fTag);
+        CleanupStack::Pop(fTag);
+        }   
+    } 		
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::RemoveQuotesL
+// -----------------------------------------------------------------------------
+//    
+void CSIPFeatureSet::RemoveQuotesL(
+    const TDesC8& aValue,
+    TPtrC8& aWithoutQuotes) const
+    {
+    __ASSERT_ALWAYS(aValue.Length() > 0, User::Leave(KErrCorrupt));
+    TLex8 lex(aValue);
+    lex.SkipSpace();
+    TPtrC8 remainder(lex.Remainder());
+    if (StartsAndEndsWithQuotes(remainder))
+        {
+        lex.Get(); // Skip the opening quote
+        remainder.Set(lex.Remainder());
+        aWithoutQuotes.Set(remainder.Left(remainder.Length()-1));
+        }
+    else
+        {
+        aWithoutQuotes.Set(aValue);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::StartsAndEndsWithQuotes
+// -----------------------------------------------------------------------------
+//
+TBool CSIPFeatureSet::StartsAndEndsWithQuotes(const TDesC8& aValue) const
+    {
+	// trim and check quotes
+	TLex8 lex(aValue);
+	lex.SkipSpace();
+	TPtrC8 trimmedVal(lex.Remainder());
+	const TInt KTwoQuotesLength = 2;
+	if (trimmedVal.Length() < KTwoQuotesLength) 
+		{
+		return EFalse;
+		}
+	if (trimmedVal.Locate('"') != 0) 
+		{
+		return EFalse;
+		}
+	if (trimmedVal.LocateReverse('"') != trimmedVal.Length()-1) 
+		{
+		return EFalse;
+		}
+	return ETrue; 
+    }
+
+// -----------------------------------------------------------------------------
+// CSIPFeatureSet::IsFeatureParamName
+// -----------------------------------------------------------------------------
+//
+TBool CSIPFeatureSet::IsFeatureParamName(RStringF aName) const
+    {
+    if (aName == SIPStrings::StringF(SipStrConsts::EAudio) ||
+        aName == SIPStrings::StringF(SipStrConsts::EAutomata) ||
+		aName == SIPStrings::StringF(SipStrConsts::EClass) ||
+		aName == SIPStrings::StringF(SipStrConsts::EDuplex) ||
+		aName == SIPStrings::StringF(SipStrConsts::EData) ||
+		aName == SIPStrings::StringF(SipStrConsts::EControl) ||
+		aName == SIPStrings::StringF(SipStrConsts::EMobility) ||
+		aName == SIPStrings::StringF(SipStrConsts::EDescription) ||
+		aName == SIPStrings::StringF(SipStrConsts::EEvents) ||
+		aName == SIPStrings::StringF(SipStrConsts::EPriority) ||
+		aName == SIPStrings::StringF(SipStrConsts::EMethods) ||
+		aName == SIPStrings::StringF(SipStrConsts::ESchemes) ||
+		aName == SIPStrings::StringF(SipStrConsts::EApplication) ||
+		aName == SIPStrings::StringF(SipStrConsts::EVideo) ||
+		aName == SIPStrings::StringF(SipStrConsts::ELanguage) ||
+		aName == SIPStrings::StringF(SipStrConsts::EType) ||
+		aName == SIPStrings::StringF(SipStrConsts::EIsfocus) ||
+		aName == SIPStrings::StringF(SipStrConsts::EActor) ||
+		aName == SIPStrings::StringF(SipStrConsts::EText) ||
+		aName == SIPStrings::StringF(SipStrConsts::EExtensions) ||
+		aName == SIPStrings::StringF(SipStrConsts::ERequire) ||
+		aName == SIPStrings::StringF(SipStrConsts::EExplicit))
+        {
+        return ETrue;
+        }
+    TLex8 lex(aName.DesC());
+    lex.SkipSpace();
+    return (lex.Peek() == '+');
+    }