os/ossrv/genericservices/httputils/UriParser/SipUriParser.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) 2007-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 "SipUriParser.h"
sl@0
    17
sl@0
    18
/** 
sl@0
    19
 * CSIPUriParser Constructor.
sl@0
    20
 */ 
sl@0
    21
CSIPUriParser::CSIPUriParser()
sl@0
    22
: CGenericUriParser()
sl@0
    23
	{
sl@0
    24
	}
sl@0
    25
sl@0
    26
/** 
sl@0
    27
 * CSIPUriParser Static Factory Construction.
sl@0
    28
 */
sl@0
    29
CSIPUriParser* CSIPUriParser::NewL()
sl@0
    30
	{
sl@0
    31
	CSIPUriParser* self = new (ELeave) CSIPUriParser;
sl@0
    32
	CleanupStack::PushL(self);
sl@0
    33
	self->ConstructL();
sl@0
    34
	CleanupStack::Pop(self);
sl@0
    35
	return self;
sl@0
    36
	}
sl@0
    37
sl@0
    38
/**	
sl@0
    39
	Second phase of two-phase construction method. 
sl@0
    40
	
sl@0
    41
	@pre 			First phase of construction is complete.
sl@0
    42
	@post			The object is fully constructed and initialized.
sl@0
    43
 */
sl@0
    44
void CSIPUriParser::ConstructL()
sl@0
    45
	{
sl@0
    46
	// Does nothing.
sl@0
    47
	}
sl@0
    48
sl@0
    49
/**
sl@0
    50
 * Default Destructor.
sl@0
    51
 */
sl@0
    52
CSIPUriParser::~CSIPUriParser()
sl@0
    53
	{
sl@0
    54
	}
sl@0
    55
sl@0
    56
/**
sl@0
    57
	Function to parse a descriptor for a scheme component. If a scheme is found 
sl@0
    58
	then the output argument aScheme is set to refer to it.
sl@0
    59
						
sl@0
    60
	@param			aUri	The descriptor containing the uri to be parsed for a scheme.
sl@0
    61
	@param			aScheme	The output descriptor to refer to the scheme
sl@0
    62
	@return			The number of characters consumed in parsing the scheme.
sl@0
    63
	@pre 			The output descriptor has been initialized so that the pointer
sl@0
    64
					to the associated descriptor buffer is NULL. The input descriptor 
sl@0
    65
					is set to the start of the uri.
sl@0
    66
	@post			If a scheme component exists then the output descriptor refers
sl@0
    67
					to it, otherwise the output descriptor is left unchanged.
sl@0
    68
*/
sl@0
    69
TInt CSIPUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme)
sl@0
    70
	{
sl@0
    71
	// Get the descriptor and look for scheme delimiter
sl@0
    72
	TInt consumed =0;
sl@0
    73
	TInt endSchemePos = FindFirstUriDelimiter(aUri, ESipSchemeDelimiterSearch);
sl@0
    74
sl@0
    75
	if( endSchemePos != KErrNotFound )
sl@0
    76
		{
sl@0
    77
		// Got a scheme - store information
sl@0
    78
		aScheme.Set(aUri.Left(endSchemePos));
sl@0
    79
sl@0
    80
		// Set consumed amount move past scheme delimiter
sl@0
    81
		consumed = endSchemePos + 1;
sl@0
    82
		}
sl@0
    83
	return consumed;
sl@0
    84
	}
sl@0
    85
	
sl@0
    86
/**
sl@0
    87
	Function to parse a descriptor for an authority component. If an authority is 
sl@0
    88
	found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts 
sl@0
    89
	of the authority component. If an authority component exists then the host part exists. The 
sl@0
    90
	userinfo and port parts are optional.
sl@0
    91
						
sl@0
    92
	@param			aUri		The descriptor containing the uri to be parsed 
sl@0
    93
					for an authority.
sl@0
    94
	@param			aUserinfo	The output descriptor for the userinfo component.
sl@0
    95
	@param			aHost		The output descriptor for the host component.
sl@0
    96
	@param			aPort		The output descriptor for the port component.
sl@0
    97
	@param			aUseNetworkDelimiter is not used as we know the Sip scheme 
sl@0
    98
					not uses the network delimeter '//'
sl@0
    99
	@return			The number of characters consumed in parsing the authority.
sl@0
   100
	@pre 			The output descriptors have been initialized so that the pointer
sl@0
   101
					to the their associated descriptor buffers is NULL. The input descriptor 
sl@0
   102
					is set to the start of the start of the authority component.
sl@0
   103
	
sl@0
   104
	@post			If an authority component exists then the output descriptors refer
sl@0
   105
					to the userinfo part (if exists), the host part and the port part (if exists), 
sl@0
   106
					otherwise the output descriptors are left unchanged.
sl@0
   107
*/
sl@0
   108
TInt CSIPUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter)
sl@0
   109
	{
sl@0
   110
	// Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//' 
sl@0
   111
	TInt consumed =0;
sl@0
   112
	const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
sl@0
   113
  	if( !aUseNetworkDelimiter || 
sl@0
   114
  		(aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
sl@0
   115
		{
sl@0
   116
		// There is an authority
sl@0
   117
		TPtrC8 authority( aUri.Mid(prefixLength) );
sl@0
   118
sl@0
   119
		// Authority delimited by ';', '?' or the end of the string
sl@0
   120
		TInt authorityEndPos = FindFirstUriDelimiter(authority, ESipAuthDelimiterSearch);
sl@0
   121
sl@0
   122
		// Got authority - parse it for its components
sl@0
   123
		authority.Set(authority.Left(authorityEndPos));
sl@0
   124
sl@0
   125
		// Get the userinfo...
sl@0
   126
		TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
sl@0
   127
		if( userinfoEndPos != KErrNotFound )
sl@0
   128
			{
sl@0
   129
			// Store the information 
sl@0
   130
			aUserinfo.Set(authority.Left(userinfoEndPos));
sl@0
   131
			  
sl@0
   132
			// Move past the userinfo and the delimiter '@'
sl@0
   133
			authority.Set(authority.Mid(userinfoEndPos + 1));
sl@0
   134
			}
sl@0
   135
sl@0
   136
		// Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now
sl@0
   137
		TInt semicolonPos = FindFirstUriDelimiter(authority, ESipSemiColonDelimiterFlag);
sl@0
   138
		if ( semicolonPos != KErrNotFound )
sl@0
   139
			{
sl@0
   140
			authority.Set(authority.Left(semicolonPos));
sl@0
   141
			authorityEndPos = semicolonPos + userinfoEndPos + 1;
sl@0
   142
			}
sl@0
   143
		
sl@0
   144
		// Set consumed amount to move past authority
sl@0
   145
		consumed += prefixLength + authorityEndPos;
sl@0
   146
		
sl@0
   147
		// Check if this is an IPv6 address	by looking for the opening '['
sl@0
   148
		TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
sl@0
   149
sl@0
   150
		if (startHostIPv6 == KErrNotFound)
sl@0
   151
			{
sl@0
   152
			// This isn't an IPv6 address.....
sl@0
   153
sl@0
   154
			// Get host...
sl@0
   155
			TInt hostEndPos = authority.Locate(KPortDelimiter);
sl@0
   156
sl@0
   157
			// Host also delimited by the end of the authority
sl@0
   158
			if( hostEndPos == KErrNotFound )
sl@0
   159
				{
sl@0
   160
				hostEndPos = authority.Length();	
sl@0
   161
				}
sl@0
   162
sl@0
   163
			// There's always a host, but can be empty - store information
sl@0
   164
			aHost.Set(authority.Left(hostEndPos));
sl@0
   165
sl@0
   166
			// Move past the host
sl@0
   167
			authority.Set(authority.Mid(hostEndPos));
sl@0
   168
			}
sl@0
   169
		else
sl@0
   170
			{
sl@0
   171
		// First, move past the opening brace
sl@0
   172
		    authority.Set(authority.Mid(startHostIPv6 + 1));
sl@0
   173
		    // auth now = X:X:X]?????
sl@0
   174
sl@0
   175
			// This is an IPv6 address, so it MUST have the closing brace too....
sl@0
   176
			TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
sl@0
   177
sl@0
   178
			// Return an error if the closing IPv6 delimiter isn't there.
sl@0
   179
			// or Host is empty
sl@0
   180
			if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1)
sl@0
   181
				{
sl@0
   182
				return KUriUtilsErrInvalidUri;	
sl@0
   183
				}
sl@0
   184
sl@0
   185
			// It's an ipv6  address, with an opening and closing brace. So now just extract it
sl@0
   186
			// auth = [X:X:X]?????
sl@0
   187
sl@0
   188
sl@0
   189
			// Set the host, and need to remove the closing brace
sl@0
   190
			aHost.Set(authority.Left(endIPv6Host));
sl@0
   191
			// host = X:X:X
sl@0
   192
sl@0
   193
			// Move past the host
sl@0
   194
			authority.Set(authority.Mid(endIPv6Host + 1 ));
sl@0
   195
			}
sl@0
   196
		
sl@0
   197
		// Get the port...
sl@0
   198
		TInt portEndPos = authority.Length();
sl@0
   199
		if( portEndPos )
sl@0
   200
			{
sl@0
   201
			// Store the port - remove leading ':'
sl@0
   202
			aPort.Set(authority.Mid(1, portEndPos - 1));
sl@0
   203
			}
sl@0
   204
		}
sl@0
   205
	return consumed;
sl@0
   206
	}
sl@0
   207
sl@0
   208
/**
sl@0
   209
	Function to parse a descriptor for a path/parameter component.There is always a path component.
sl@0
   210
	The ouput argument aPath is set to the path/parameter component found.
sl@0
   211
						
sl@0
   212
	@param			aUri	The descriptor containing the uri to be parsed for a path/parameter.
sl@0
   213
	@param			aComponent	The output descriptor to refer to the path.
sl@0
   214
	@return			The number of characters consumed in parsing the path.
sl@0
   215
	@pre 			The output descriptor has been initialized so that the pointer
sl@0
   216
					to the associated descriptor buffer is NULL. The input descriptor 
sl@0
   217
					is set to the start of the path.
sl@0
   218
					
sl@0
   219
	@post			The output descriptor refers to the path component.
sl@0
   220
*/	
sl@0
   221
TInt CSIPUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent)
sl@0
   222
	{
sl@0
   223
	// Get descriptor with the path
sl@0
   224
	TInt consumed =0;
sl@0
   225
sl@0
   226
	// Path is delimited by '?' or the end of the string
sl@0
   227
	TInt pathEndPos = FindFirstUriDelimiter(aUri, ESipPathDelimiterSearch);
sl@0
   228
sl@0
   229
	// Check for presence of path
sl@0
   230
	if( pathEndPos != KErrNotFound )
sl@0
   231
		{
sl@0
   232
		// Got path - store information
sl@0
   233
		aComponent.Set(aUri.Left(pathEndPos));
sl@0
   234
	
sl@0
   235
		// Set consumed amount to move past path
sl@0
   236
		consumed = pathEndPos;
sl@0
   237
		}
sl@0
   238
	return consumed;
sl@0
   239
	}
sl@0
   240
sl@0
   241
/**
sl@0
   242
	Function to parse a descriptor for a query/header component.If a query is found then 
sl@0
   243
	the output argument aQuery is set to refer to it.
sl@0
   244
						
sl@0
   245
	@param			aUri	The descriptor containing the uri to be parsed for a query/Header.
sl@0
   246
	@param			aComponent	The output descriptor to refer to the query
sl@0
   247
	@return			The number of characters consumed in parsing the query.
sl@0
   248
	@pre 			The output descriptor has been initialized so that the pointer
sl@0
   249
					to the associated descriptor buffer is NULL. The input descriptor is set to
sl@0
   250
					the start of the query.
sl@0
   251
	@post			If a query component exists then the output descriptor refers
sl@0
   252
					to it, otherwise the output descriptor is left unchanged.
sl@0
   253
*/
sl@0
   254
TInt CSIPUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent)
sl@0
   255
	{
sl@0
   256
	// Get descriptor with the query
sl@0
   257
	TInt consumed =0;
sl@0
   258
sl@0
   259
	// Query/Header is delimited by end of the string 
sl@0
   260
	TInt queryEndPos = aUri.Length();
sl@0
   261
sl@0
   262
	// Check for presence of query
sl@0
   263
	if( queryEndPos )
sl@0
   264
		{
sl@0
   265
		// Got query - store information; need to excluded leading '?'
sl@0
   266
		aComponent.Set(aUri.Mid(1, queryEndPos - 1));
sl@0
   267
	
sl@0
   268
		// Set consumed amount to move past query
sl@0
   269
		consumed = queryEndPos;
sl@0
   270
		}
sl@0
   271
	return consumed;
sl@0
   272
	}
sl@0
   273
	
sl@0
   274
/**
sl@0
   275
	Function to parse a descriptor for a fragment component. 
sl@0
   276
	In Sip Uris no Fragment Component it contains. This is an dummy implementation.
sl@0
   277
						
sl@0
   278
	@param			aUri not used.
sl@0
   279
	@param			aComponent	not used.
sl@0
   280
	@return			returns zero.
sl@0
   281
*/
sl@0
   282
TInt CSIPUriParser::ParseFragment(const TPtrC8& /*aUri*/, TPtrC8& /* aComponent*/)
sl@0
   283
	{
sl@0
   284
	// Sip Uri Does not conatin Fragment
sl@0
   285
	return 0;
sl@0
   286
	}
sl@0
   287
	
sl@0
   288
/**
sl@0
   289
	Function to find the position of the first delimiter in the descriptor specified 
sl@0
   290
	by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are 
sl@0
   291
	no others. In the case of the scheme delimiter search, the position returned depends on the 
sl@0
   292
	position of the colon delimiter with respect to the other delimiters for a scheme.
sl@0
   293
						
sl@0
   294
	@param			aUri The descriptor containing the section of a uri to be searched.
sl@0
   295
	@param			aSearchFlag	The enum specifying the delimiters to search for.
sl@0
   296
	@return			The position of nearest delimiter to start of the descriptor, where
sl@0
   297
					zero is the start (left-most) position.
sl@0
   298
*/
sl@0
   299
TInt CSIPUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TSipDelimiterSearchFlag aSearchFlag)
sl@0
   300
	{
sl@0
   301
	// Set ultimate delimiter - string length
sl@0
   302
	TInt endPos = aUri.Length();
sl@0
   303
sl@0
   304
	if( aSearchFlag & ESipQueryDelimiterFlag )
sl@0
   305
		{
sl@0
   306
		TInt queryPos = aUri.Locate(KQueryDelimiter);
sl@0
   307
		if( queryPos != KErrNotFound && queryPos < endPos )
sl@0
   308
			{
sl@0
   309
			TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
sl@0
   310
			//QueryDelimiter may be in Userinfo
sl@0
   311
			if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > queryPos ) 
sl@0
   312
				{
sl@0
   313
				//Find QueryDelimiter after Userinfo
sl@0
   314
				queryPos = aUri.Mid(userinfoPos).Locate(KQueryDelimiter);
sl@0
   315
				if (queryPos != KErrNotFound  && queryPos < endPos )
sl@0
   316
					{
sl@0
   317
					queryPos += userinfoPos;	
sl@0
   318
					}
sl@0
   319
				}
sl@0
   320
			if(queryPos != KErrNotFound)
sl@0
   321
				{
sl@0
   322
				endPos = queryPos;		
sl@0
   323
				}
sl@0
   324
			}
sl@0
   325
		}
sl@0
   326
sl@0
   327
	if( aSearchFlag & ESipSemiColonDelimiterFlag )
sl@0
   328
		{
sl@0
   329
		TInt semiColonPos = aUri.Locate(KParamDelimiter);
sl@0
   330
		if( semiColonPos != KErrNotFound && semiColonPos < endPos )
sl@0
   331
			{
sl@0
   332
			TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
sl@0
   333
			//ParamDelimiter may be in Userinfo
sl@0
   334
			if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > semiColonPos ) 
sl@0
   335
				{
sl@0
   336
				//Find ParamDelimiter after Userinfo
sl@0
   337
				semiColonPos = aUri.Mid(userinfoPos).Locate(KParamDelimiter);
sl@0
   338
				if (semiColonPos != KErrNotFound  && semiColonPos < endPos )
sl@0
   339
					{
sl@0
   340
					semiColonPos += userinfoPos;	
sl@0
   341
					}
sl@0
   342
				}
sl@0
   343
			if(semiColonPos != KErrNotFound)
sl@0
   344
				{
sl@0
   345
				endPos = semiColonPos;		
sl@0
   346
				}
sl@0
   347
			}
sl@0
   348
		}
sl@0
   349
	if( aSearchFlag & ESipColonDelimiterFlag )
sl@0
   350
		{
sl@0
   351
		TInt schemePos = aUri.Locate(KSchemeDelimiter);
sl@0
   352
		if( schemePos != KErrNotFound && schemePos < endPos )
sl@0
   353
			{
sl@0
   354
			// There is a scheme
sl@0
   355
			endPos = schemePos;
sl@0
   356
			}
sl@0
   357
		else if( aSearchFlag == ESipSchemeDelimiterSearch )
sl@0
   358
			{
sl@0
   359
			// Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
sl@0
   360
			endPos = KErrNotFound;
sl@0
   361
			}
sl@0
   362
		}
sl@0
   363
	return endPos;
sl@0
   364
	}
sl@0
   365