1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericservices/httputils/UriParser/SipUriParser.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,365 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "SipUriParser.h"
1.20 +
1.21 +/**
1.22 + * CSIPUriParser Constructor.
1.23 + */
1.24 +CSIPUriParser::CSIPUriParser()
1.25 +: CGenericUriParser()
1.26 + {
1.27 + }
1.28 +
1.29 +/**
1.30 + * CSIPUriParser Static Factory Construction.
1.31 + */
1.32 +CSIPUriParser* CSIPUriParser::NewL()
1.33 + {
1.34 + CSIPUriParser* self = new (ELeave) CSIPUriParser;
1.35 + CleanupStack::PushL(self);
1.36 + self->ConstructL();
1.37 + CleanupStack::Pop(self);
1.38 + return self;
1.39 + }
1.40 +
1.41 +/**
1.42 + Second phase of two-phase construction method.
1.43 +
1.44 + @pre First phase of construction is complete.
1.45 + @post The object is fully constructed and initialized.
1.46 + */
1.47 +void CSIPUriParser::ConstructL()
1.48 + {
1.49 + // Does nothing.
1.50 + }
1.51 +
1.52 +/**
1.53 + * Default Destructor.
1.54 + */
1.55 +CSIPUriParser::~CSIPUriParser()
1.56 + {
1.57 + }
1.58 +
1.59 +/**
1.60 + Function to parse a descriptor for a scheme component. If a scheme is found
1.61 + then the output argument aScheme is set to refer to it.
1.62 +
1.63 + @param aUri The descriptor containing the uri to be parsed for a scheme.
1.64 + @param aScheme The output descriptor to refer to the scheme
1.65 + @return The number of characters consumed in parsing the scheme.
1.66 + @pre The output descriptor has been initialized so that the pointer
1.67 + to the associated descriptor buffer is NULL. The input descriptor
1.68 + is set to the start of the uri.
1.69 + @post If a scheme component exists then the output descriptor refers
1.70 + to it, otherwise the output descriptor is left unchanged.
1.71 +*/
1.72 +TInt CSIPUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme)
1.73 + {
1.74 + // Get the descriptor and look for scheme delimiter
1.75 + TInt consumed =0;
1.76 + TInt endSchemePos = FindFirstUriDelimiter(aUri, ESipSchemeDelimiterSearch);
1.77 +
1.78 + if( endSchemePos != KErrNotFound )
1.79 + {
1.80 + // Got a scheme - store information
1.81 + aScheme.Set(aUri.Left(endSchemePos));
1.82 +
1.83 + // Set consumed amount move past scheme delimiter
1.84 + consumed = endSchemePos + 1;
1.85 + }
1.86 + return consumed;
1.87 + }
1.88 +
1.89 +/**
1.90 + Function to parse a descriptor for an authority component. If an authority is
1.91 + found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts
1.92 + of the authority component. If an authority component exists then the host part exists. The
1.93 + userinfo and port parts are optional.
1.94 +
1.95 + @param aUri The descriptor containing the uri to be parsed
1.96 + for an authority.
1.97 + @param aUserinfo The output descriptor for the userinfo component.
1.98 + @param aHost The output descriptor for the host component.
1.99 + @param aPort The output descriptor for the port component.
1.100 + @param aUseNetworkDelimiter is not used as we know the Sip scheme
1.101 + not uses the network delimeter '//'
1.102 + @return The number of characters consumed in parsing the authority.
1.103 + @pre The output descriptors have been initialized so that the pointer
1.104 + to the their associated descriptor buffers is NULL. The input descriptor
1.105 + is set to the start of the start of the authority component.
1.106 +
1.107 + @post If an authority component exists then the output descriptors refer
1.108 + to the userinfo part (if exists), the host part and the port part (if exists),
1.109 + otherwise the output descriptors are left unchanged.
1.110 +*/
1.111 +TInt CSIPUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter)
1.112 + {
1.113 + // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//'
1.114 + TInt consumed =0;
1.115 + const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
1.116 + if( !aUseNetworkDelimiter ||
1.117 + (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
1.118 + {
1.119 + // There is an authority
1.120 + TPtrC8 authority( aUri.Mid(prefixLength) );
1.121 +
1.122 + // Authority delimited by ';', '?' or the end of the string
1.123 + TInt authorityEndPos = FindFirstUriDelimiter(authority, ESipAuthDelimiterSearch);
1.124 +
1.125 + // Got authority - parse it for its components
1.126 + authority.Set(authority.Left(authorityEndPos));
1.127 +
1.128 + // Get the userinfo...
1.129 + TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
1.130 + if( userinfoEndPos != KErrNotFound )
1.131 + {
1.132 + // Store the information
1.133 + aUserinfo.Set(authority.Left(userinfoEndPos));
1.134 +
1.135 + // Move past the userinfo and the delimiter '@'
1.136 + authority.Set(authority.Mid(userinfoEndPos + 1));
1.137 + }
1.138 +
1.139 + // Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now
1.140 + TInt semicolonPos = FindFirstUriDelimiter(authority, ESipSemiColonDelimiterFlag);
1.141 + if ( semicolonPos != KErrNotFound )
1.142 + {
1.143 + authority.Set(authority.Left(semicolonPos));
1.144 + authorityEndPos = semicolonPos + userinfoEndPos + 1;
1.145 + }
1.146 +
1.147 + // Set consumed amount to move past authority
1.148 + consumed += prefixLength + authorityEndPos;
1.149 +
1.150 + // Check if this is an IPv6 address by looking for the opening '['
1.151 + TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
1.152 +
1.153 + if (startHostIPv6 == KErrNotFound)
1.154 + {
1.155 + // This isn't an IPv6 address.....
1.156 +
1.157 + // Get host...
1.158 + TInt hostEndPos = authority.Locate(KPortDelimiter);
1.159 +
1.160 + // Host also delimited by the end of the authority
1.161 + if( hostEndPos == KErrNotFound )
1.162 + {
1.163 + hostEndPos = authority.Length();
1.164 + }
1.165 +
1.166 + // There's always a host, but can be empty - store information
1.167 + aHost.Set(authority.Left(hostEndPos));
1.168 +
1.169 + // Move past the host
1.170 + authority.Set(authority.Mid(hostEndPos));
1.171 + }
1.172 + else
1.173 + {
1.174 + // First, move past the opening brace
1.175 + authority.Set(authority.Mid(startHostIPv6 + 1));
1.176 + // auth now = X:X:X]?????
1.177 +
1.178 + // This is an IPv6 address, so it MUST have the closing brace too....
1.179 + TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
1.180 +
1.181 + // Return an error if the closing IPv6 delimiter isn't there.
1.182 + // or Host is empty
1.183 + if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1)
1.184 + {
1.185 + return KUriUtilsErrInvalidUri;
1.186 + }
1.187 +
1.188 + // It's an ipv6 address, with an opening and closing brace. So now just extract it
1.189 + // auth = [X:X:X]?????
1.190 +
1.191 +
1.192 + // Set the host, and need to remove the closing brace
1.193 + aHost.Set(authority.Left(endIPv6Host));
1.194 + // host = X:X:X
1.195 +
1.196 + // Move past the host
1.197 + authority.Set(authority.Mid(endIPv6Host + 1 ));
1.198 + }
1.199 +
1.200 + // Get the port...
1.201 + TInt portEndPos = authority.Length();
1.202 + if( portEndPos )
1.203 + {
1.204 + // Store the port - remove leading ':'
1.205 + aPort.Set(authority.Mid(1, portEndPos - 1));
1.206 + }
1.207 + }
1.208 + return consumed;
1.209 + }
1.210 +
1.211 +/**
1.212 + Function to parse a descriptor for a path/parameter component.There is always a path component.
1.213 + The ouput argument aPath is set to the path/parameter component found.
1.214 +
1.215 + @param aUri The descriptor containing the uri to be parsed for a path/parameter.
1.216 + @param aComponent The output descriptor to refer to the path.
1.217 + @return The number of characters consumed in parsing the path.
1.218 + @pre The output descriptor has been initialized so that the pointer
1.219 + to the associated descriptor buffer is NULL. The input descriptor
1.220 + is set to the start of the path.
1.221 +
1.222 + @post The output descriptor refers to the path component.
1.223 +*/
1.224 +TInt CSIPUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent)
1.225 + {
1.226 + // Get descriptor with the path
1.227 + TInt consumed =0;
1.228 +
1.229 + // Path is delimited by '?' or the end of the string
1.230 + TInt pathEndPos = FindFirstUriDelimiter(aUri, ESipPathDelimiterSearch);
1.231 +
1.232 + // Check for presence of path
1.233 + if( pathEndPos != KErrNotFound )
1.234 + {
1.235 + // Got path - store information
1.236 + aComponent.Set(aUri.Left(pathEndPos));
1.237 +
1.238 + // Set consumed amount to move past path
1.239 + consumed = pathEndPos;
1.240 + }
1.241 + return consumed;
1.242 + }
1.243 +
1.244 +/**
1.245 + Function to parse a descriptor for a query/header component.If a query is found then
1.246 + the output argument aQuery is set to refer to it.
1.247 +
1.248 + @param aUri The descriptor containing the uri to be parsed for a query/Header.
1.249 + @param aComponent The output descriptor to refer to the query
1.250 + @return The number of characters consumed in parsing the query.
1.251 + @pre The output descriptor has been initialized so that the pointer
1.252 + to the associated descriptor buffer is NULL. The input descriptor is set to
1.253 + the start of the query.
1.254 + @post If a query component exists then the output descriptor refers
1.255 + to it, otherwise the output descriptor is left unchanged.
1.256 +*/
1.257 +TInt CSIPUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent)
1.258 + {
1.259 + // Get descriptor with the query
1.260 + TInt consumed =0;
1.261 +
1.262 + // Query/Header is delimited by end of the string
1.263 + TInt queryEndPos = aUri.Length();
1.264 +
1.265 + // Check for presence of query
1.266 + if( queryEndPos )
1.267 + {
1.268 + // Got query - store information; need to excluded leading '?'
1.269 + aComponent.Set(aUri.Mid(1, queryEndPos - 1));
1.270 +
1.271 + // Set consumed amount to move past query
1.272 + consumed = queryEndPos;
1.273 + }
1.274 + return consumed;
1.275 + }
1.276 +
1.277 +/**
1.278 + Function to parse a descriptor for a fragment component.
1.279 + In Sip Uris no Fragment Component it contains. This is an dummy implementation.
1.280 +
1.281 + @param aUri not used.
1.282 + @param aComponent not used.
1.283 + @return returns zero.
1.284 +*/
1.285 +TInt CSIPUriParser::ParseFragment(const TPtrC8& /*aUri*/, TPtrC8& /* aComponent*/)
1.286 + {
1.287 + // Sip Uri Does not conatin Fragment
1.288 + return 0;
1.289 + }
1.290 +
1.291 +/**
1.292 + Function to find the position of the first delimiter in the descriptor specified
1.293 + by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are
1.294 + no others. In the case of the scheme delimiter search, the position returned depends on the
1.295 + position of the colon delimiter with respect to the other delimiters for a scheme.
1.296 +
1.297 + @param aUri The descriptor containing the section of a uri to be searched.
1.298 + @param aSearchFlag The enum specifying the delimiters to search for.
1.299 + @return The position of nearest delimiter to start of the descriptor, where
1.300 + zero is the start (left-most) position.
1.301 +*/
1.302 +TInt CSIPUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TSipDelimiterSearchFlag aSearchFlag)
1.303 + {
1.304 + // Set ultimate delimiter - string length
1.305 + TInt endPos = aUri.Length();
1.306 +
1.307 + if( aSearchFlag & ESipQueryDelimiterFlag )
1.308 + {
1.309 + TInt queryPos = aUri.Locate(KQueryDelimiter);
1.310 + if( queryPos != KErrNotFound && queryPos < endPos )
1.311 + {
1.312 + TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
1.313 + //QueryDelimiter may be in Userinfo
1.314 + if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > queryPos )
1.315 + {
1.316 + //Find QueryDelimiter after Userinfo
1.317 + queryPos = aUri.Mid(userinfoPos).Locate(KQueryDelimiter);
1.318 + if (queryPos != KErrNotFound && queryPos < endPos )
1.319 + {
1.320 + queryPos += userinfoPos;
1.321 + }
1.322 + }
1.323 + if(queryPos != KErrNotFound)
1.324 + {
1.325 + endPos = queryPos;
1.326 + }
1.327 + }
1.328 + }
1.329 +
1.330 + if( aSearchFlag & ESipSemiColonDelimiterFlag )
1.331 + {
1.332 + TInt semiColonPos = aUri.Locate(KParamDelimiter);
1.333 + if( semiColonPos != KErrNotFound && semiColonPos < endPos )
1.334 + {
1.335 + TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
1.336 + //ParamDelimiter may be in Userinfo
1.337 + if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > semiColonPos )
1.338 + {
1.339 + //Find ParamDelimiter after Userinfo
1.340 + semiColonPos = aUri.Mid(userinfoPos).Locate(KParamDelimiter);
1.341 + if (semiColonPos != KErrNotFound && semiColonPos < endPos )
1.342 + {
1.343 + semiColonPos += userinfoPos;
1.344 + }
1.345 + }
1.346 + if(semiColonPos != KErrNotFound)
1.347 + {
1.348 + endPos = semiColonPos;
1.349 + }
1.350 + }
1.351 + }
1.352 + if( aSearchFlag & ESipColonDelimiterFlag )
1.353 + {
1.354 + TInt schemePos = aUri.Locate(KSchemeDelimiter);
1.355 + if( schemePos != KErrNotFound && schemePos < endPos )
1.356 + {
1.357 + // There is a scheme
1.358 + endPos = schemePos;
1.359 + }
1.360 + else if( aSearchFlag == ESipSchemeDelimiterSearch )
1.361 + {
1.362 + // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
1.363 + endPos = KErrNotFound;
1.364 + }
1.365 + }
1.366 + return endPos;
1.367 + }
1.368 +