os/ossrv/genericservices/httputils/UriParser/TEquiv.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "TEquiv.h"
sl@0
    17
#include <uriutils.h>
sl@0
    18
#include <uriutilscommon.h>
sl@0
    19
#include "UriUtilsInternal.h"
sl@0
    20
#include <delimitedpathsegment8.h>
sl@0
    21
#include <delimitedquery8.h>
sl@0
    22
#include <escapeutils.h>
sl@0
    23
sl@0
    24
_LIT8(KParamUserFull,	";user=");
sl@0
    25
_LIT8(KParamTtlFull,	";ttl=");
sl@0
    26
_LIT8(KParamMethodFull,	";method=");
sl@0
    27
_LIT8(KParamMaddrFull,	";maddr=");
sl@0
    28
_LIT8(KParamMaddr,		"maddr");
sl@0
    29
sl@0
    30
_LIT8(KHeaderId, "call-id");
sl@0
    31
_LIT8(KHeaderIdAbbr, "i");
sl@0
    32
_LIT8(KHeaderContact, "contact");
sl@0
    33
_LIT8(KHeaderContactAbbr, "m");
sl@0
    34
_LIT8(KHeaderEncoding, "content-encoding");
sl@0
    35
_LIT8(KHeaderEncodingAbbr, "e");
sl@0
    36
_LIT8(KHeaderLength, "content-length");
sl@0
    37
_LIT8(KHeaderLengthAbbr, "l");
sl@0
    38
_LIT8(KHeaderType, "content-type");
sl@0
    39
_LIT8(KHeaderTypeAbbr, "c");
sl@0
    40
_LIT8(KHeaderFrom, "from");
sl@0
    41
_LIT8(KHeaderFromAbbr, "f");
sl@0
    42
_LIT8(KHeaderSubject, "subject");
sl@0
    43
_LIT8(KHeaderSubjectAbbr, "s");
sl@0
    44
_LIT8(KHeaderTo, "to");
sl@0
    45
_LIT8(KHeaderToAbbr, "t");
sl@0
    46
sl@0
    47
TEquiv::TEquiv(const TUriC8& aLhs, const TUriC8& aRhs)
sl@0
    48
: iLhs(aLhs), iRhs(aRhs)
sl@0
    49
	{
sl@0
    50
	}
sl@0
    51
sl@0
    52
TBool TEquiv::EquivalentL() const
sl@0
    53
	{
sl@0
    54
	if (!IsMatchSchemeL())
sl@0
    55
		return KUriUtilsErrDifferentScheme;
sl@0
    56
	
sl@0
    57
	if (!IsMatchUserInfoL())
sl@0
    58
		return KUriUtilsErrDifferentUserInfo;
sl@0
    59
	
sl@0
    60
	if (!IsMatchHostL())
sl@0
    61
		return KUriUtilsErrDifferentHost;
sl@0
    62
	
sl@0
    63
	if (!IsMatchPortL())
sl@0
    64
		return KUriUtilsErrDifferentPort;
sl@0
    65
	
sl@0
    66
	if (!IsMatchPathL())
sl@0
    67
		return KUriUtilsErrDifferentPath;
sl@0
    68
	
sl@0
    69
	if (!IsMatchQueryL())
sl@0
    70
		return KUriUtilsErrDifferentQuery;
sl@0
    71
	
sl@0
    72
	if (!IsMatchFragmentL())
sl@0
    73
		return KUriUtilsErrDifferentFragment;
sl@0
    74
	
sl@0
    75
	return KErrNone;
sl@0
    76
	}
sl@0
    77
sl@0
    78
TBool TEquiv::IsMatchSchemeL() const
sl@0
    79
	{
sl@0
    80
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriScheme);
sl@0
    81
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriScheme);
sl@0
    82
	TBool result = IsMatchCaseless(*lhsDes, *rhsDes);
sl@0
    83
	CleanupStack::PopAndDestroy(2);
sl@0
    84
	return result;
sl@0
    85
	}
sl@0
    86
sl@0
    87
TBool TEquiv::IsMatchUserInfoL() const
sl@0
    88
	{
sl@0
    89
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriUserinfo);
sl@0
    90
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriUserinfo);
sl@0
    91
	TBool result = IsMatchCaseSensitive(*lhsDes, *rhsDes);
sl@0
    92
	CleanupStack::PopAndDestroy(2);
sl@0
    93
	return result;
sl@0
    94
	}
sl@0
    95
sl@0
    96
TBool TEquiv::IsMatchHostL() const
sl@0
    97
	{
sl@0
    98
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriHost);
sl@0
    99
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriHost);
sl@0
   100
	TBool result = IsMatchCaseless(*lhsDes, *rhsDes);
sl@0
   101
	CleanupStack::PopAndDestroy(2);
sl@0
   102
	return result;
sl@0
   103
	}
sl@0
   104
sl@0
   105
TBool TEquiv::IsMatchPortL() const
sl@0
   106
	{
sl@0
   107
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriPort);
sl@0
   108
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriPort);
sl@0
   109
	TBool result = IsMatchCaseSensitive(*lhsDes, *rhsDes);
sl@0
   110
	CleanupStack::PopAndDestroy(2);
sl@0
   111
	return result;
sl@0
   112
	}
sl@0
   113
sl@0
   114
TBool TEquiv::IsMatchPathL() const
sl@0
   115
	{
sl@0
   116
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriPath);
sl@0
   117
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriPath);
sl@0
   118
	TBool result = IsMatchCaseSensitive(*lhsDes, *rhsDes);
sl@0
   119
	CleanupStack::PopAndDestroy(2);
sl@0
   120
	return result;
sl@0
   121
	}
sl@0
   122
sl@0
   123
TBool TEquiv::IsMatchQueryL() const
sl@0
   124
	{
sl@0
   125
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriQuery);
sl@0
   126
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriQuery);
sl@0
   127
	TBool result = IsMatchCaseSensitive(*lhsDes, *rhsDes);
sl@0
   128
	CleanupStack::PopAndDestroy(2);
sl@0
   129
	return result;
sl@0
   130
	}
sl@0
   131
sl@0
   132
TBool TEquiv::IsMatchFragmentL() const
sl@0
   133
	{
sl@0
   134
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriFragment);
sl@0
   135
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriFragment);
sl@0
   136
	TBool result = IsMatchCaseSensitive(*lhsDes, *rhsDes);
sl@0
   137
	CleanupStack::PopAndDestroy(2);
sl@0
   138
	return result;
sl@0
   139
	}
sl@0
   140
sl@0
   141
HBufC8* TEquiv::DecodedSegmentLC(const TUriC8& aUri, TUriComponent aSegmentType) const
sl@0
   142
	{
sl@0
   143
	HBufC8* decoded = EscapeUtils::EscapeDecodeL(aUri.Extract(aSegmentType));
sl@0
   144
	CleanupStack::PushL(decoded);
sl@0
   145
	return decoded;
sl@0
   146
	}
sl@0
   147
sl@0
   148
TEquivSip::TEquivSip(const TUriC8& aLhs, const TUriC8& aRhs)
sl@0
   149
: TEquiv(aLhs, aRhs)
sl@0
   150
	{
sl@0
   151
	}
sl@0
   152
sl@0
   153
void TEquivSip::RemoveLeadingZeros(TPtr8 aHost) const
sl@0
   154
	{
sl@0
   155
	for (TInt i=0; i < aHost.Length(); i++)
sl@0
   156
		{
sl@0
   157
		TBool startOfNumber = (i == 0 || aHost[i-1] < '0' || aHost[i-1] > '9');
sl@0
   158
		if (aHost[i] == '0' && startOfNumber)
sl@0
   159
			{
sl@0
   160
			// The character is a zero and is either at the start of the string
sl@0
   161
			// or the fist number in a sequence.
sl@0
   162
			aHost.Delete(i--,1);
sl@0
   163
			}
sl@0
   164
		}
sl@0
   165
	}
sl@0
   166
sl@0
   167
TBool TEquivSip::IsMatchHostL(const TDesC8& aLhs, const TDesC8& aRhs) const
sl@0
   168
	{
sl@0
   169
	UriUtils::TUriHostType lhsType = UriUtils::HostType(aLhs);
sl@0
   170
	UriUtils::TUriHostType rhsType = UriUtils::HostType(aRhs);
sl@0
   171
	if (lhsType != rhsType)
sl@0
   172
		return EFalse;
sl@0
   173
	if (lhsType != UriUtils::ETextHost)
sl@0
   174
		{
sl@0
   175
		// Host is IPv4 or IPv6
sl@0
   176
		// Create a copy of the hosts and remove any leading '0's
sl@0
   177
		HBufC8* lhsCopy = aLhs.AllocLC();
sl@0
   178
		HBufC8* rhsCopy = aRhs.AllocLC();
sl@0
   179
		RemoveLeadingZeros(lhsCopy->Des());
sl@0
   180
		RemoveLeadingZeros(rhsCopy->Des());
sl@0
   181
		TBool result = IsMatchCaseSensitive(*lhsCopy, *rhsCopy);
sl@0
   182
		CleanupStack::PopAndDestroy(2);
sl@0
   183
		return result;
sl@0
   184
		}
sl@0
   185
sl@0
   186
	return IsMatchCaseless(aLhs, aRhs);
sl@0
   187
	}
sl@0
   188
sl@0
   189
TBool TEquivSip::IsMatchHostL() const
sl@0
   190
	{
sl@0
   191
	HBufC8* lhsDes = DecodedSegmentLC(iLhs, EUriHost);
sl@0
   192
	HBufC8* rhsDes = DecodedSegmentLC(iRhs, EUriHost);
sl@0
   193
	TBool result = IsMatchHostL(*lhsDes, *rhsDes);
sl@0
   194
	CleanupStack::PopAndDestroy(2);
sl@0
   195
	return result;
sl@0
   196
	}
sl@0
   197
sl@0
   198
TBool TEquivSip::IsParamCompatibleL(const TDesC8& aLhsName, const TDesC8& aLhsValue, const TDesC8& aRhsName, const TDesC8& aRhsValue) const
sl@0
   199
	{
sl@0
   200
	// Were're just checking that if the segments have the same name part
sl@0
   201
	// that their values are the same. This method only returns false if the lhs and rhs
sl@0
   202
	// have the same name but their values are different.
sl@0
   203
	if (!IsMatchCaseless(aLhsName, aRhsName))
sl@0
   204
		{
sl@0
   205
		// Names don't match so we're OK
sl@0
   206
		return ETrue;
sl@0
   207
		}
sl@0
   208
sl@0
   209
	// The maddr parameter needs to be handled differently from the others
sl@0
   210
	// The address is checked for equivalence not just a straight string compare.
sl@0
   211
	if (IsMatchCaseless(aLhsName, KParamMaddr))
sl@0
   212
		{
sl@0
   213
			return IsMatchHostL(aLhsValue, aRhsValue);
sl@0
   214
		}
sl@0
   215
	else
sl@0
   216
		{
sl@0
   217
		if (!IsMatchCaseless(aLhsValue, aRhsValue))
sl@0
   218
			{
sl@0
   219
			// Names are the same but the values are different
sl@0
   220
			// We have a incompatible parameter
sl@0
   221
			return EFalse;
sl@0
   222
			}
sl@0
   223
		}
sl@0
   224
sl@0
   225
	return ETrue;
sl@0
   226
	}
sl@0
   227
sl@0
   228
TBool TEquivSip::IsParamListCompatibleL(const TDelimitedParserBase8& aLhsParser, const TDelimitedParserBase8& aRhsParser) const
sl@0
   229
sl@0
   230
	{
sl@0
   231
	TPtrC8 lhsName;
sl@0
   232
	TPtrC8 lhsValue;
sl@0
   233
	TPtrC8 rhsName;
sl@0
   234
	TPtrC8 rhsValue;
sl@0
   235
sl@0
   236
	TPtrC8 lhsSegment;
sl@0
   237
	TPtrC8 rhsSegment;
sl@0
   238
sl@0
   239
	// roll back to the start of the lhs segment parser
sl@0
   240
	aLhsParser.Reset();
sl@0
   241
	
sl@0
   242
	while( aLhsParser.GetNext(lhsSegment) == KErrNone )
sl@0
   243
		{
sl@0
   244
		// roll back to the start of the rhs segment parser
sl@0
   245
		aRhsParser.Reset();
sl@0
   246
sl@0
   247
		GetNameValuePair(lhsSegment, lhsName, lhsValue);
sl@0
   248
		while( aRhsParser.GetNext(rhsSegment) == KErrNone )
sl@0
   249
			{
sl@0
   250
			GetNameValuePair(rhsSegment, rhsName, rhsValue);
sl@0
   251
			if (!IsParamCompatibleL(lhsName, lhsValue, rhsName, rhsValue))
sl@0
   252
				return EFalse;
sl@0
   253
			}
sl@0
   254
		}
sl@0
   255
sl@0
   256
	return ETrue;
sl@0
   257
	}
sl@0
   258
sl@0
   259
TInt TEquivSip::ListLength(const TDelimitedParserBase8& aParser) const
sl@0
   260
	{
sl@0
   261
	aParser.Reset();
sl@0
   262
	
sl@0
   263
	TInt result = 0;
sl@0
   264
	while (!aParser.Eos())
sl@0
   265
		{
sl@0
   266
		aParser.Inc();
sl@0
   267
		++result;
sl@0
   268
		}
sl@0
   269
		
sl@0
   270
	aParser.Reset();
sl@0
   271
	return result;
sl@0
   272
	}
sl@0
   273
sl@0
   274
TBool TEquivSip::IsMatchPathL() const
sl@0
   275
	{
sl@0
   276
	HBufC8* lhs = DecodedSegmentLC(iLhs, EUriPath);
sl@0
   277
	HBufC8* rhs = DecodedSegmentLC(iRhs, EUriPath);
sl@0
   278
sl@0
   279
	TDelimitedPathSegmentParser8 lhsParser;
sl@0
   280
	lhsParser.Parse(*lhs);
sl@0
   281
	TDelimitedPathSegmentParser8 rhsParser;
sl@0
   282
	rhsParser.Parse(*rhs);
sl@0
   283
	
sl@0
   284
	// Check each parameter in the lhs parameter list with those in
sl@0
   285
	// the rhs parameter list. If at any point a parameter is incompatible
sl@0
   286
	// we'll return false.
sl@0
   287
	TBool result = ETrue;
sl@0
   288
	
sl@0
   289
	// Alway check the parameter list with the most parameters against the other
sl@0
   290
	// so that we don't miss any
sl@0
   291
	TInt lhsLength = ListLength(lhsParser);
sl@0
   292
	TInt rhsLength = ListLength(rhsParser);
sl@0
   293
	
sl@0
   294
	if (lhsLength > rhsLength)
sl@0
   295
		{
sl@0
   296
		result = IsParamListCompatibleL(lhsParser, rhsParser);
sl@0
   297
		}
sl@0
   298
	else
sl@0
   299
		{
sl@0
   300
		result = IsParamListCompatibleL(rhsParser, lhsParser);
sl@0
   301
		}
sl@0
   302
sl@0
   303
	// check that the special parameters, if present, are present in both
sl@0
   304
	if (result)
sl@0
   305
		{
sl@0
   306
		if ((lhs->Find(KParamUserFull) == KErrNotFound) != (rhs->Find(KParamUserFull) == KErrNotFound) ||
sl@0
   307
		    (lhs->Find(KParamTtlFull) == KErrNotFound) != (rhs->Find(KParamTtlFull) == KErrNotFound) ||
sl@0
   308
		    (lhs->Find(KParamMethodFull) == KErrNotFound) != (rhs->Find(KParamMethodFull) == KErrNotFound) ||
sl@0
   309
		    (lhs->Find(KParamMaddrFull) == KErrNotFound) != (rhs->Find(KParamMaddrFull) == KErrNotFound) )
sl@0
   310
			{
sl@0
   311
			result = EFalse;
sl@0
   312
			}
sl@0
   313
		}
sl@0
   314
	
sl@0
   315
	CleanupStack::PopAndDestroy(2);
sl@0
   316
	return result;
sl@0
   317
	}
sl@0
   318
sl@0
   319
sl@0
   320
TEquivSip::THeaderType TEquivSip::HeaderType(const TDesC8& aHeaderName) const
sl@0
   321
	{
sl@0
   322
	if (IsMatchCaseless(aHeaderName, KHeaderId) || IsMatchCaseless(aHeaderName, KHeaderIdAbbr))
sl@0
   323
		return EHeaderId;
sl@0
   324
	if (IsMatchCaseless(aHeaderName, KHeaderContact) || IsMatchCaseless(aHeaderName, KHeaderContactAbbr))
sl@0
   325
		return EHeaderContact;
sl@0
   326
	if (IsMatchCaseless(aHeaderName, KHeaderEncoding) || IsMatchCaseless(aHeaderName, KHeaderEncodingAbbr))
sl@0
   327
		return EHeaderEncoding;
sl@0
   328
	if (IsMatchCaseless(aHeaderName, KHeaderLength) || IsMatchCaseless(aHeaderName, KHeaderLengthAbbr))
sl@0
   329
		return EHeaderLength;
sl@0
   330
	if (IsMatchCaseless(aHeaderName, KHeaderType) || IsMatchCaseless(aHeaderName, KHeaderTypeAbbr))
sl@0
   331
		return EHeaderType;
sl@0
   332
	if (IsMatchCaseless(aHeaderName, KHeaderFrom) || IsMatchCaseless(aHeaderName, KHeaderFromAbbr))
sl@0
   333
		return EHeaderFrom;
sl@0
   334
	if (IsMatchCaseless(aHeaderName, KHeaderSubject) || IsMatchCaseless(aHeaderName, KHeaderSubjectAbbr))
sl@0
   335
		return EHeaderSubject;
sl@0
   336
	if (IsMatchCaseless(aHeaderName, KHeaderTo) || IsMatchCaseless(aHeaderName, KHeaderToAbbr))
sl@0
   337
		return EHeaderTo;
sl@0
   338
sl@0
   339
	return EHeaderNormal;
sl@0
   340
	}
sl@0
   341
sl@0
   342
TBool TEquivSip::IsMatchHeader(const TDesC8& aLhs, const TDesC8& aRhs) const
sl@0
   343
	{
sl@0
   344
	if (IsMatchCaseless(aLhs, aRhs))
sl@0
   345
		{
sl@0
   346
		// identical headers are always OK
sl@0
   347
		return ETrue;
sl@0
   348
		}
sl@0
   349
sl@0
   350
	// We now need to check for abbreviated headers
sl@0
   351
	TPtrC8 lhsName;
sl@0
   352
	TPtrC8 lhsValue;
sl@0
   353
	TPtrC8 rhsName;
sl@0
   354
	TPtrC8 rhsValue;
sl@0
   355
sl@0
   356
	GetNameValuePair(aLhs, lhsName, lhsValue);
sl@0
   357
	GetNameValuePair(aRhs, rhsName, rhsValue);
sl@0
   358
sl@0
   359
	if (!IsMatchCaseless(lhsValue, rhsValue))
sl@0
   360
		{
sl@0
   361
		// headers with different values can never match
sl@0
   362
		return EFalse;
sl@0
   363
		}
sl@0
   364
sl@0
   365
	// We now have only those with different header names but with the same value
sl@0
   366
	// The last check is to see if the headers are in abbreviated forms
sl@0
   367
	THeaderType lhsType = HeaderType(lhsName);
sl@0
   368
	THeaderType rhsType = HeaderType(rhsName);
sl@0
   369
	if (lhsType != EHeaderNormal && (lhsType == rhsType))
sl@0
   370
		{
sl@0
   371
		// They are both special headers of the same type
sl@0
   372
		// Everything matches
sl@0
   373
		return ETrue;
sl@0
   374
		}
sl@0
   375
sl@0
   376
	return EFalse;
sl@0
   377
	}
sl@0
   378
sl@0
   379
TBool TEquivSip::IsQueryListCompatible(const TDelimitedParserBase8& aLhsParser, const TDelimitedParserBase8& aRhsParser) const
sl@0
   380
sl@0
   381
	{
sl@0
   382
	TPtrC8 lhsSegment;
sl@0
   383
	TPtrC8 rhsSegment;
sl@0
   384
sl@0
   385
	TBool found = EFalse;
sl@0
   386
	// roll back to the start of the lhs segment parser
sl@0
   387
	aLhsParser.Reset();
sl@0
   388
sl@0
   389
	while( aLhsParser.GetNext(lhsSegment) == KErrNone )
sl@0
   390
		{
sl@0
   391
		// roll back to the start of the rhs segment parser
sl@0
   392
		aRhsParser.Reset();
sl@0
   393
		
sl@0
   394
		found = EFalse;
sl@0
   395
sl@0
   396
		while( aRhsParser.GetNext(rhsSegment) == KErrNone )
sl@0
   397
			{
sl@0
   398
			if (IsMatchHeader(lhsSegment, rhsSegment))
sl@0
   399
				{
sl@0
   400
				// a match has been found for this header so move to the next
sl@0
   401
				// header in the lhs list
sl@0
   402
				found = ETrue;
sl@0
   403
				break;
sl@0
   404
				}
sl@0
   405
			}
sl@0
   406
		if (!found)
sl@0
   407
			{
sl@0
   408
			// no match has been found so the headers are not equvalent
sl@0
   409
			return EFalse;
sl@0
   410
			}
sl@0
   411
		}
sl@0
   412
sl@0
   413
	return ETrue;
sl@0
   414
	}
sl@0
   415
sl@0
   416
TBool TEquivSip::IsMatchQueryL() const
sl@0
   417
	{
sl@0
   418
	HBufC8* lhs = DecodedSegmentLC(iLhs, EUriQuery);
sl@0
   419
	HBufC8* rhs = DecodedSegmentLC(iRhs, EUriQuery);
sl@0
   420
sl@0
   421
	TDelimitedQueryParser8 lhsParser;
sl@0
   422
	lhsParser.Parse(*lhs);
sl@0
   423
	TDelimitedQueryParser8 rhsParser;
sl@0
   424
	rhsParser.Parse(*rhs);
sl@0
   425
sl@0
   426
	TBool result = EFalse;
sl@0
   427
	
sl@0
   428
	// first check that the number of headers are the same in both lists.
sl@0
   429
	TInt lhsLength = ListLength(lhsParser);
sl@0
   430
	TInt rhsLength = ListLength(rhsParser);
sl@0
   431
	if (lhsLength == rhsLength)
sl@0
   432
		{
sl@0
   433
		// Check each parameter in the lhs parameter list with those in
sl@0
   434
		// the rhs parameter list. If at any point a parameter is incompatible
sl@0
   435
		// we'll return false.
sl@0
   436
		result = IsQueryListCompatible(lhsParser, rhsParser);
sl@0
   437
		}
sl@0
   438
	
sl@0
   439
	CleanupStack::PopAndDestroy(2);
sl@0
   440
	return result;
sl@0
   441
	}
sl@0
   442
sl@0
   443
TBool TEquivSip::IsMatchFragmentL() const
sl@0
   444
	{
sl@0
   445
	// We don't care about the fragment for SIP URIs
sl@0
   446
	return ETrue;
sl@0
   447
	}