realtimenetprots/sipfw/SDP/src/SdpAttributeField.cpp
changeset 0 307788aac0a8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/realtimenetprots/sipfw/SDP/src/SdpAttributeField.cpp	Tue Feb 02 01:03:15 2010 +0200
@@ -0,0 +1,986 @@
+// 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 "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          : SdpAttributeField.h
+// Part of       : SDP Codec
+// Version       : 1.0
+//
+
+
+
+#include <s32strm.h>
+#include <uri8.h>
+#include "SdpAttributeField.h"
+#include "SdpAttributeFieldPtrs.h"
+#include "SdpFmtAttributeField.h"
+#include "SdpUtil.h"
+#include "SDPCodec.pan"
+#include "sdpcodecstringconstants.h"
+#include "SdpCodecConstants.h"
+#include "SdpCodecStringPool.h"
+#include "SdpRtpmapValue.h"
+#include "SdpCodecErr.h"
+#include "_sdpdefs.h"
+
+// CONSTANTS
+const TInt KHeaderIndex = 0;
+const TInt KAttributeIndex = 1;
+const TInt KMinAttributeNum = 2;
+const TInt KMaxSubtagLength = 8;
+const TInt KMaxPrimarySubtagLength = 8;
+
+// Valid property attribute strings
+const TInt KPropertyStringNum = 4;
+const SdpCodecStringConstants::TStrings 
+    KValidPropertyStrings[KPropertyStringNum] =
+    {
+    SdpCodecStringConstants::EAttributeRecvonly,
+    SdpCodecStringConstants::EAttributeSendrecv,
+    SdpCodecStringConstants::EAttributeSendonly,
+    SdpCodecStringConstants::EAttributeInactive
+    };
+
+// Valid value attribute strings
+const TInt KValueStringNum = 22;
+const SdpCodecStringConstants::TStrings KValidValueStrings[KValueStringNum] =
+    {
+    SdpCodecStringConstants::EAttributeCat,
+    SdpCodecStringConstants::EAttributeKeywds,
+    SdpCodecStringConstants::EAttributeTool,
+    SdpCodecStringConstants::EAttributePtime,
+    SdpCodecStringConstants::EAttributeMaxptime,
+    SdpCodecStringConstants::EAttributeRtpmap,
+    SdpCodecStringConstants::EAttributeOrient,
+    SdpCodecStringConstants::EAttributeType,
+    SdpCodecStringConstants::EAttributeCharset,
+    SdpCodecStringConstants::EAttributeSdplang,
+    SdpCodecStringConstants::EAttributeLang,
+    SdpCodecStringConstants::EAttributeFramerate,
+    SdpCodecStringConstants::EAttributeQuality,    
+    SdpCodecStringConstants::EAttributeFmtp,
+    SdpCodecStringConstants::EAttributeControl,
+    SdpCodecStringConstants::EAttributeEtag,
+    SdpCodecStringConstants::EAttributeMid,
+    SdpCodecStringConstants::EAttributeGroup,
+    SdpCodecStringConstants::EAttributeCurr,
+    SdpCodecStringConstants::EAttributeDes,
+    SdpCodecStringConstants::EAttributeConf,
+    SdpCodecStringConstants::EAttributeRange
+    };
+
+// Valid orient value strings
+const TInt KValidOrientStringNum = 3;
+static const TText8* const KOrientStrings[KValidOrientStringNum] = 
+    {
+    _S8("portrait\0"),
+    _S8("landscape\0"),
+    _S8("seascape\0")
+    };
+
+const TInt KValidGroupSemanticsNum = 3;
+static const TText8* const KGroupSemantics[KValidGroupSemanticsNum] =
+    {
+    _S8("LS"),
+    _S8("FID"),
+    _S8("SRF")
+    };
+
+const TInt KValidStatusTypeNum = 3;
+static const TText8* const KStatusTypes[KValidStatusTypeNum] =
+    {
+    _S8("e2e"),
+    _S8("local"),
+    _S8("remote")
+    };
+
+const TInt KValidDirectionTagsNum = 4;
+static const TText8* const KDirectionTags[KValidDirectionTagsNum] =
+    {
+    _S8("none"),
+    _S8("send"),
+    _S8("recv"),
+    _S8("sendrecv")
+    };
+
+const TInt KValidStrengthTagsNum = 5;
+static const TText8* const KStrengthTags[KValidStrengthTagsNum] =
+    {
+    _S8("mandatory"),
+    _S8("optional"),
+    _S8("none"),
+    _S8("failure"),
+    _S8("unknown")
+    };
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CSdpAttributeField
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CSdpAttributeField::CSdpAttributeField()
+	{
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::ConstructL( const TDesC8& aText )
+	{
+    // aText should be in format
+    // a=<attribute> or a=<attribute>:<value> or 
+    // a=<attribute>:<value> <value specific attributes>
+
+    __ASSERT_ALWAYS(aText.Length() > 0, User::Leave(KErrSdpCodecAttributeField));
+
+    iPool = SdpCodecStringPool::StringPoolL();
+    CreateAttributeFieldPtrsL();
+    
+    RArray<TPtrC8> array;
+    
+    TInt length = aText.Length();
+    if ( aText[aText.Length() - 1] == KLFChar )
+        {
+        if ( length > 1 && aText[aText.Length() - 2] == KCRChar )
+            {
+            length--;
+            }
+        length--;
+        }  
+    TPtrC8 restValue( aText.Left( length ));
+    
+    __ASSERT_ALWAYS(SdpUtil::IsByteString(restValue) 
+            || SdpUtil::IsToken(restValue)
+            || SdpUtil::IsValidChars(KEqualStr, restValue),
+            User::Leave(KErrSdpCodecAttributeField));
+    
+    array = SdpUtil::GetElementsFromLineL( aText, KErrSdpCodecAttributeField );
+    CleanupClosePushL( array );
+
+    RStringF origHeader =  iPool.StringF( SdpCodecStringConstants::EAttribute, 
+                                          SdpCodecStringConstants::Table );
+    
+    // We need to have at least two tokens (and this should be always the case,
+    // unless TSdpUtil::GetElementsFromLineL() gets modified)
+    __ASSERT_ALWAYS( origHeader.DesC().Compare( array[KHeaderIndex] ) == 0
+                    && array.Count() >= KMinAttributeNum,
+        User::Leave( KErrSdpCodecAttributeField ) );
+        
+    if ( array[KAttributeIndex].Locate( KColonChar ) == KErrNotFound )
+        {
+        // For property attributes exactly two attributes are needed
+        __ASSERT_ALWAYS( array.Count() == KMinAttributeNum,
+            User::Leave( KErrSdpCodecAttributeField ));
+
+        FormatProperyAttributeL( array[KAttributeIndex] );  
+        }
+    else
+        {    
+        HBufC8* attribute = NULL;
+        HBufC8* value = NULL;             
+        CreateAttributeAndValueStringsLC( array, attribute, value );
+        FormatValueAttributeL( *attribute, *value );
+        CleanupStack::PopAndDestroy( 2 );   // attribute, value
+        }
+
+    CleanupStack::PopAndDestroy();  // array
+
+    __TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::ConstructL( RStringF aAttribute, 
+                                    const TDesC8& aValue )
+	{	
+    iPool = SdpCodecStringPool::StringPoolL();
+    CreateAttributeFieldPtrsL();
+
+    TBool property( EFalse );
+    for ( TInt i( 0 ); i < KPropertyStringNum && !property; i++ )
+        {
+        if ( aAttribute == 
+             iPool.StringF( KValidPropertyStrings[i], 
+                            SdpCodecStringConstants::Table ) )
+            {
+            property = ETrue;
+            }
+        }
+
+    if ( property || aValue.Length() == 0)
+        {
+        // For property attributes, no value is valid value
+        __ASSERT_ALWAYS( aValue.Length() == 0, 
+            User::Leave( KErrSdpCodecAttributeField ));
+                   
+        FormatProperyAttributeL( aAttribute.DesC() );  
+        }
+    else
+        {   
+        FormatValueAttributeL( aAttribute.DesC(), aValue );        
+        }        
+
+    __TEST_INVARIANT;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::DecodeL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSdpAttributeField* CSdpAttributeField::DecodeL( const TDesC8& aText )
+	{
+	CSdpAttributeField* obj = DecodeLC( aText );
+	CleanupStack::Pop();
+	return obj;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::DecodeLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSdpAttributeField* CSdpAttributeField::DecodeLC( 
+    const TDesC8& aText )
+	{
+	CSdpAttributeField* obj = new ( ELeave ) CSdpAttributeField;
+	CleanupStack::PushL( obj );
+	obj->ConstructL( aText );
+	return obj;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSdpAttributeField* CSdpAttributeField::NewL( RStringF aAttribute, 
+                                                    const TDesC8& aValue )
+	{
+	CSdpAttributeField* obj = NewLC( aAttribute, aValue );
+	CleanupStack::Pop();
+	return obj;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSdpAttributeField* CSdpAttributeField::NewLC( RStringF aAttribute,
+                                                        const TDesC8& aValue )
+	{
+	CSdpAttributeField* obj = new ( ELeave ) CSdpAttributeField;
+	CleanupStack::PushL(obj);
+	obj->ConstructL( aAttribute, aValue );
+	return obj;
+	}
+
+// Destructor
+EXPORT_C CSdpAttributeField::~CSdpAttributeField()
+	{    
+    iAttribute.Close();
+    CSdpAttributeFieldPtrs* tmp = 
+        reinterpret_cast< CSdpAttributeFieldPtrs* >( iValue ); 
+	delete tmp;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::EncodeL
+// Encodes a string into valid output string format
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSdpAttributeField::EncodeL( RWriteStream& aStream ) const
+	{
+	__TEST_INVARIANT;
+    
+    RStringF header = iPool.StringF( SdpCodecStringConstants::EAttribute, 
+                                     SdpCodecStringConstants::Table );
+    aStream.WriteL( header.DesC() );
+    aStream.WriteL( iAttribute.DesC() );
+    TPtrC8 value( AttributeFieldPtrs().Value() );
+    if ( value.Length() > 0 )
+        {
+        aStream.WriteL( KColonStr );
+        aStream.WriteL( value );
+        }
+    aStream.WriteL( KCRLFStr );
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CloneL
+// Clones an object and returns the new attribute field
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CSdpAttributeField * CSdpAttributeField::CloneL() const
+	{
+	__TEST_INVARIANT;
+
+    CSdpAttributeField* obj = 
+        CSdpAttributeField::NewL( iAttribute, AttributeFieldPtrs().Value() );
+
+	__ASSERT_DEBUG( *this == *obj, 
+                    User::Panic(KSdpCodecPanicCat, KSdpCodecPanicInternal) );
+	return obj;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::operator==
+// Checks if the two attribute fields are equal
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CSdpAttributeField::operator== (
+    const CSdpAttributeField& aObj ) const
+	{
+	__TEST_INVARIANT;
+
+    return ( iAttribute == aObj.Attribute() && 
+             AttributeFieldPtrs().Value().CompareF( aObj.Value() ) == 0 );
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::Attribute
+// Returns attribute part of attribute field
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RStringF CSdpAttributeField::Attribute() const
+	{
+    __TEST_INVARIANT;
+    return iAttribute;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::Value
+// Returns value part of attribute field
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TDesC8& CSdpAttributeField::Value() const
+	{
+    __TEST_INVARIANT;
+    
+    return AttributeFieldPtrs().Value();
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::SetL
+// Sets new attribute field values
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSdpAttributeField::SetL( RStringF aAttribute, 
+                                        const TDesC8& aValue )
+	{
+    __TEST_INVARIANT;
+
+    ConstructL( aAttribute, aValue ); 
+
+    __TEST_INVARIANT;  
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::AssignTo
+// Assigns attribute to a format attribute
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSdpAttributeField::AssignTo(
+    const CSdpFmtAttributeField& aFmtAttribute)
+	{
+	AttributeFieldPtrs().SetFmtAttribute(&aFmtAttribute);
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::BelongsTo
+// Check if the attribute field belongs to the format attribute
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CSdpAttributeField::BelongsTo(
+    const CSdpFmtAttributeField& aFmtAttribute) const
+	{
+	return ( AttributeFieldPtrs().FmtAttribute() == &aFmtAttribute );
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::ExternalizeL
+// Externalizes the object to stream
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::ExternalizeL( RWriteStream& aStream ) const
+	{
+    // Attribute
+    aStream.WriteUint32L( iAttribute.DesC().Length() );
+    aStream.WriteL( iAttribute.DesC() );
+    // Value
+    TPtrC8 value( AttributeFieldPtrs().Value() );
+    aStream.WriteUint32L( value.Length() );
+    if ( value.Length() > 0 )
+        {
+        aStream.WriteL( value, value.Length() );
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::InternalizeL
+// Internalizes the object from stream
+// -----------------------------------------------------------------------------
+//
+CSdpAttributeField* CSdpAttributeField::InternalizeL( RReadStream& aStream )
+	{
+    RStringPool pool = SdpCodecStringPool::StringPoolL();
+
+	// Attribute
+    HBufC8* tmpBuf2;
+    TUint32 length = aStream.ReadUint32L();
+    HBufC8* tmpBuf = HBufC8::NewLC( length );
+    TPtr8 ptr( tmpBuf->Des() );
+    aStream.ReadL( ptr, length ); 
+    RStringF attribute = pool.OpenFStringL( ptr );
+    CleanupClosePushL( attribute );
+
+    length = aStream.ReadUint32L();
+    if ( length > 0 )
+        {
+        tmpBuf2 = HBufC8::NewLC( length );
+        TPtr8 ptr2( tmpBuf2->Des() );
+        aStream.ReadL( ptr2, length );
+        }
+    else
+        {
+        tmpBuf2 = KNullDesC8().AllocLC();
+        }
+
+    CSdpAttributeField* obj = CSdpAttributeField::NewL( attribute, *tmpBuf2 );
+    CleanupStack::PopAndDestroy( 3 );  // attribute, tmpBuf, tmpBuf2
+
+    return obj;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::FormatPropertyAttributeL
+// Formats and initializes class to be a property attribute
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::FormatProperyAttributeL( const TDesC8& aAttribute )
+    {
+    __ASSERT_ALWAYS( SdpUtil::IsToken( aAttribute ), 
+        User::Leave( KErrSdpCodecAttributeField ));
+
+    TBool found( EFalse );
+    for ( TInt i( 0 ); i < KPropertyStringNum && !found; i++ )
+        {
+        RStringF attrString = 
+            iPool.StringF( KValidPropertyStrings[i], 
+                        SdpCodecStringConstants::Table );
+
+        if ( attrString.DesC().CompareF( aAttribute ) == 0 )
+            {
+            AttributeFieldPtrs().SetValueL( KNullDesC8 );
+            
+            iAttribute.Close();           
+            iAttribute = attrString.Copy();            
+            iPropertyAttribute = ETrue;            
+
+            found = ETrue;
+            }                                       
+        }
+
+    if ( !found )
+        {
+        HBufC8* tempValue = KNullDesC8().AllocLC();
+        SetNotPredefinedAttributeL(aAttribute, *tempValue);
+        CleanupStack::PopAndDestroy(); // tempValue
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::FormatValueAttributeL
+// Formats and initializes class to be a value attribute
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::FormatValueAttributeL( const TDesC8& aAttribute,
+                                                const TDesC8& aValue )
+    {
+    TBool found( EFalse ); 
+
+    __ASSERT_ALWAYS( SdpUtil::IsToken( aAttribute ) 
+                && SdpUtil::IsByteString( aValue ),
+            User::Leave( KErrSdpCodecAttributeField ) );
+
+    TInt i = 0;
+    for( i = 0; i < KPropertyStringNum && !found; i++)
+        {
+        RStringF attrString = 
+            iPool.StringF( KValidPropertyStrings[i], 
+                        SdpCodecStringConstants::Table );
+
+        if ( attrString.DesC().CompareF( aAttribute ) == 0 )
+            {
+            //found = ETrue;
+            User::Leave(KErrSdpCodecAttributeField);
+            }
+        }
+    
+    for ( i = 0; i < KValueStringNum && !found; i++ )
+        {
+        RStringF attrString = 
+            iPool.StringF( KValidValueStrings[i], 
+                        SdpCodecStringConstants::Table );
+
+        if ( attrString.DesC().CompareF( aAttribute ) == 0 )
+            {
+            VerifyValueAttributeL( KValidValueStrings[i], aValue );
+            iAttribute.Close();                          
+            iAttribute = attrString.Copy();            
+            found = ETrue;
+            }
+        }
+
+    if ( !found )
+        {
+        SetNotPredefinedAttributeL(aAttribute, aValue);
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::VerifyValueAttributeL
+// Verifies that value given to the attribute is valid
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::VerifyValueAttributeL( 
+    SdpCodecStringConstants::TStrings aString,
+    const TDesC8& aValue )
+    {
+    TUint str( aString );
+    switch ( str )
+        {
+        case SdpCodecStringConstants::EAttributeCat:
+        case SdpCodecStringConstants::EAttributeType:    
+        case SdpCodecStringConstants::EAttributeCharset: 
+        case SdpCodecStringConstants::EAttributeEtag:
+            __ASSERT_ALWAYS( aValue.Length() > 0 
+                && aValue.Locate( KSPChar ) == KErrNotFound,
+            User::Leave( KErrSdpCodecAttributeField ) );
+            break;
+
+        case SdpCodecStringConstants::EAttributeKeywds:
+        case SdpCodecStringConstants::EAttributeTool:      
+            __ASSERT_ALWAYS( aValue.Length() > 0, 
+                 User::Leave( KErrSdpCodecAttributeField ) );
+            break;
+
+        case SdpCodecStringConstants::EAttributePtime:
+        case SdpCodecStringConstants::EAttributeMaxptime:
+        case SdpCodecStringConstants::EAttributeQuality:
+            __ASSERT_ALWAYS( SdpUtil::IsDigit( aValue ),
+                User::Leave( KErrSdpCodecAttributeField ) );
+            break;
+
+        case SdpCodecStringConstants::EAttributeOrient:
+            CheckValidOrientL( aValue );
+            break;
+      
+        case SdpCodecStringConstants::EAttributeSdplang:
+        case SdpCodecStringConstants::EAttributeLang:
+            CheckValidLangStrL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeFramerate:
+            CheckValidFrameRateL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeControl:
+            CheckValidControlL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeMid:
+            if (SdpUtil::IsToken( aValue ) == EFalse)
+                {
+                User::Leave( KErrSdpCodecAttributeField );
+                }
+            break;
+
+        case SdpCodecStringConstants::EAttributeGroup:
+            CheckValidGroupL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeCurr:
+            CheckValidCurrAndConfL( aValue );
+            break;
+        
+        case SdpCodecStringConstants::EAttributeDes:
+            CheckValidDesL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeConf:
+            CheckValidCurrAndConfL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeRange:
+            CheckValidRangeL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeRtpmap:
+            CheckValidRtpmapL( aValue );
+            break;
+
+        case SdpCodecStringConstants::EAttributeFmtp:
+            CheckValidFmtpL( aValue );
+            break;
+
+        default:
+            User::Leave( KErrSdpCodecAttributeField );
+            break;
+        }
+
+    AttributeFieldPtrs().SetValueL( aValue );
+    iPropertyAttribute = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CreateAttributeAndValueStringsLC
+// Forms attribute and value strings
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::CreateAttributeAndValueStringsLC( 
+    RArray<TPtrC8>& aArray,
+    HBufC8*& aAttribute,
+    HBufC8*& aValue )
+    {
+    TInt pos = aArray[KAttributeIndex].Locate( KColonChar );
+    __ASSERT_ALWAYS( pos > 0, User::Leave( KErrSdpCodecAttributeField ) );
+
+    aAttribute = HBufC8::NewLC( pos );
+    aAttribute->Des().Copy( aArray[KAttributeIndex].Left( pos ) );
+
+    // Find out the total length of value string
+    TPtrC8 initialValue( aArray[KAttributeIndex].Right( 
+                            aArray[KAttributeIndex].Length() - pos - 1 ) );
+
+    TInt valueLength( initialValue.Length() );    
+    for ( TInt i( KAttributeIndex + 1 ); i < aArray.Count(); i++ )
+        {
+        valueLength += KSPStr().Length();
+        valueLength += aArray[i].Length();
+        }
+
+    // Copy the value string to the value buffer
+    aValue = HBufC8::NewLC( valueLength );
+    aValue->Des().Append( initialValue );
+    for ( TInt j( KAttributeIndex + 1 ); j < aArray.Count(); j++ )
+        {
+        aValue->Des().Append( KSPStr );
+        aValue->Des().Append( aArray[j] ) ;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidOrientL
+// Checks if value is valid orient value
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::CheckValidOrientL( const TDesC8& aValue )
+    {    
+    TBool found( EFalse );
+    for ( TInt i( 0 ); i < KValidOrientStringNum && !found; i++ )
+        {
+        TPtrC8 strPtr( KOrientStrings[i] );
+        if ( strPtr.CompareF( aValue ) == 0 )
+            {
+            found = ETrue;
+            } 
+        }
+
+    __ASSERT_ALWAYS(found, User::Leave( KErrSdpCodecAttributeField ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidLangStrL
+// Checks if value is valid language tag
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::CheckValidLangStrL( const TDesC8& aValue )
+    {
+    // Language-Tag = Primary-subtag *( "-" Subtag )
+    // Primary-subtag = 1*8ALPHA
+    // Subtag = 1*8(ALPHA / DIGIT)
+    TInt primarySubtagPos = aValue.Locate( KHyphenChar );
+
+    if ( primarySubtagPos > KMaxPrimarySubtagLength )
+        {
+        User::Leave( KErrSdpCodecAttributeField );
+        }    
+
+    TInt subtagPos( primarySubtagPos );    
+    TPtrC8 ptr( aValue.Right( aValue.Length() - subtagPos - 1 ) );
+    // Check all subtags
+    while ( subtagPos != ptr.Length() )
+        {
+        subtagPos = ptr.Locate( KHyphenChar );
+            
+        if ( subtagPos == KErrNotFound )
+            {
+            subtagPos = ptr.Length();
+            }
+      
+        // Check length
+        __ASSERT_ALWAYS( subtagPos > 0 && subtagPos < KMaxSubtagLength,
+            User::Leave( KErrSdpCodecAttributeField ) );
+   
+        if ( subtagPos != ptr.Length() )
+            {
+            ptr.Set( aValue.Right( ptr.Length() - subtagPos - 1 ) );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidFrameRateL
+// Checks if value is valid framerate value
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::CheckValidFrameRateL( const TDesC8& aValue )
+    {
+    TInt dotFound = 0;
+    // There can be one dot and digits
+    for ( TInt i( 0 ); i < aValue.Length(); i++ )
+        {
+        __ASSERT_ALWAYS((aValue[i] == KDotChar || TChar( aValue[i] ).IsDigit())
+            && dotFound <= 1,
+            User::Leave( KErrSdpCodecAttributeField ));
+                        
+        if ( aValue[i] == KDotChar )
+            {
+            dotFound++;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidControlL
+// Checks if value is valid uri for group attribute
+// -----------------------------------------------------------------------------
+//      
+void CSdpAttributeField::CheckValidControlL( const TDesC8& aValue )
+    {
+    TUriParser8 parser;
+	User::LeaveIfError(parser.Parse(aValue));
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidGroupL
+// Checks if value is valid value for group attribute
+// -----------------------------------------------------------------------------
+//      
+void CSdpAttributeField::CheckValidGroupL( const TDesC8& aValue )
+    {
+   ValidValueInListL(KValidGroupSemanticsNum, KGroupSemantics, aValue);
+    TInt pos = aValue.Locate( KSPChar );
+    TPtrC8 ptr(aValue);
+
+    while ( pos != KErrNotFound)
+        {
+        ptr.Set( ptr.Right( ptr.Length() - pos - 1 ) );
+        pos = ptr.Locate( KSPChar );           
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidDesL
+// Checks if value is valid value for des attribute
+// -----------------------------------------------------------------------------
+//      
+void CSdpAttributeField::CheckValidDesL( const TDesC8& aValue )
+    {
+    TInt pos = aValue.Locate( KSPChar );
+    __ASSERT_ALWAYS(pos > 0, User::Leave( KErrSdpCodecAttributeField ));
+    TPtrC8 ptr(aValue.Left(pos));
+    __ASSERT_ALWAYS( SdpUtil::IsToken(ptr), 
+        User::Leave( KErrSdpCodecAttributeField ) );
+        
+    ptr.Set(aValue.Right( aValue.Length() - pos - 1 ));
+    pos = ptr.Locate( KSPChar );
+    __ASSERT_ALWAYS(pos > 0, User::Leave( KErrSdpCodecAttributeField ));
+    ValidValueInListL(KValidStrengthTagsNum, KStrengthTags, ptr.Left( pos ));
+
+    ptr.Set(ptr.Right( ptr.Length() - pos - 1 ));
+    pos = ptr.Locate( KSPChar );
+    __ASSERT_ALWAYS(pos > 0, User::Leave( KErrSdpCodecAttributeField ));
+    ValidValueInListL(KValidStatusTypeNum, KStatusTypes, ptr.Left( pos ));
+    
+    ptr.Set(ptr.Right( ptr.Length() - pos - 1 ));
+    __ASSERT_ALWAYS(ptr.Locate( KSPChar ) == KErrNotFound, 
+                    User::Leave( KErrSdpCodecAttributeField ));
+    ValidValueInListL(KValidDirectionTagsNum, KDirectionTags, ptr);
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidCurrAndConfL
+// Checks if value is valid value for curr and conf attribute
+// -----------------------------------------------------------------------------
+//      
+void CSdpAttributeField::CheckValidCurrAndConfL( const TDesC8& aValue )
+    {
+    TInt pos = aValue.Locate( KSPChar );
+    __ASSERT_ALWAYS(pos > 0, User::Leave( KErrSdpCodecAttributeField ));
+    TPtrC8 ptr(aValue.Left(pos));
+    __ASSERT_ALWAYS( SdpUtil::IsToken(ptr), 
+        User::Leave( KErrSdpCodecAttributeField ) );
+    
+    ptr.Set(aValue.Right( aValue.Length() - pos - 1 ));
+    pos = ptr.Locate( KSPChar );
+    __ASSERT_ALWAYS(pos > 0, User::Leave( KErrSdpCodecAttributeField ));
+    ValidValueInListL(KValidStatusTypeNum, KStatusTypes, ptr.Left( pos ));
+
+    ptr.Set(ptr.Right( ptr.Length() - pos - 1 ));
+    __ASSERT_ALWAYS(ptr.Locate( KSPChar ) == KErrNotFound, 
+                    User::Leave( KErrSdpCodecAttributeField ));
+    ValidValueInListL(KValidDirectionTagsNum, KDirectionTags, ptr);
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::ValidValueInListL
+// Checks if value is included in predefined values list
+// -----------------------------------------------------------------------------
+//      
+void CSdpAttributeField::ValidValueInListL( TInt aItemsCount, 
+                                            const TText8* const aValuesList[],
+                                            const TDesC8& aValue )
+    {
+    TBool found( EFalse );
+    TInt pos = 0;
+    for ( TInt i( 0 ); i < aItemsCount && !found; i++ )
+        {
+        TPtrC8 strPtr( aValuesList[i] );
+        pos = aValue.Find(strPtr); 
+        if ( pos != KErrNotFound && pos >= 0 )
+            {
+            found = ETrue;
+            } 
+        }
+
+    __ASSERT_ALWAYS(found, User::Leave( KErrSdpCodecAttributeField ));
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidCRangefL
+// Checks if precondition type value is valid value
+// -----------------------------------------------------------------------------
+//      
+void CSdpAttributeField::CheckValidRangeL( const TDesC8& aValue )
+    {
+    TInt found = aValue.Find(KEqualStr);
+    __ASSERT_ALWAYS(found != KErrNotFound && found > 0, User::Leave( KErrSdpCodecAttributeField ));
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidRtpmapL
+// Checks if value is valid rtpmap value
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::CheckValidRtpmapL( const TDesC8& aValue )
+    {
+    // If this doesn't leave, then the value is OK
+    TSdpRtpmapValue::DecodeL( aValue );
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CheckValidFmtpL
+// Checks if value is valid format value
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::CheckValidFmtpL( const TDesC8& aValue )
+    {
+    __ASSERT_ALWAYS(SdpUtil::IsByteString(aValue) && aValue.Length() > 0, 
+                User::Leave( KErrSdpCodecMediaAttributeField ));
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::SetNotPredefinedAttributeL
+// Sets attribute and value. Attribute is not one of predefined ones.
+// -----------------------------------------------------------------------------
+//
+void CSdpAttributeField::SetNotPredefinedAttributeL(const TDesC8& aAttribute, 
+                                                    const TDesC8& aValue)
+    {
+    iAttribute.Close();
+    iAttribute = iPool.OpenFStringL(aAttribute);
+    AttributeFieldPtrs().SetValueL( aValue );
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::IsFmtAttribute
+// Check if the attribute field belongs to any format attribute
+// -----------------------------------------------------------------------------
+//
+TBool CSdpAttributeField::IsFmtAttribute()
+	{
+	if ( AttributeFieldPtrs().FmtAttribute() )
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::CreateAttributeFieldPtrsL
+// -----------------------------------------------------------------------------
+//	
+void CSdpAttributeField::CreateAttributeFieldPtrsL()
+    {
+    CSdpAttributeFieldPtrs* newObj = CSdpAttributeFieldPtrs::NewL();
+    CSdpAttributeFieldPtrs* oldObj = 
+        reinterpret_cast< CSdpAttributeFieldPtrs* >( iValue );
+    delete oldObj;
+    iValue = reinterpret_cast< HBufC8* >( newObj );
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::AttributeFieldPtrs
+// -----------------------------------------------------------------------------
+//  
+inline CSdpAttributeFieldPtrs& CSdpAttributeField::AttributeFieldPtrs()
+    {
+    return *( reinterpret_cast< CSdpAttributeFieldPtrs* >( iValue ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CSdpAttributeField::AttributeFieldPtrs
+// -----------------------------------------------------------------------------
+//  
+inline const CSdpAttributeFieldPtrs& 
+CSdpAttributeField::AttributeFieldPtrs() const
+    {
+    return *( reinterpret_cast< CSdpAttributeFieldPtrs* >( iValue ) );
+    }
+
+// For DEBUG builds
+
+// -----------------------------------------------------------------------------
+// CSdpOriginField::__DbgTestInvariant
+// Test invariant
+// -----------------------------------------------------------------------------
+//	
+void CSdpAttributeField::__DbgTestInvariant() const
+	{    
+	TBool invariant = ( 
+        SdpUtil::IsToken( iAttribute.DesC() ) 
+		&& iValue != 0 );
+
+	if (!invariant)
+		User::Invariant();
+	}