sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "SipUriParser.h" sl@0: sl@0: /** sl@0: * CSIPUriParser Constructor. sl@0: */ sl@0: CSIPUriParser::CSIPUriParser() sl@0: : CGenericUriParser() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: * CSIPUriParser Static Factory Construction. sl@0: */ sl@0: CSIPUriParser* CSIPUriParser::NewL() sl@0: { sl@0: CSIPUriParser* self = new (ELeave) CSIPUriParser; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: /** sl@0: Second phase of two-phase construction method. sl@0: sl@0: @pre First phase of construction is complete. sl@0: @post The object is fully constructed and initialized. sl@0: */ sl@0: void CSIPUriParser::ConstructL() sl@0: { sl@0: // Does nothing. sl@0: } sl@0: sl@0: /** sl@0: * Default Destructor. sl@0: */ sl@0: CSIPUriParser::~CSIPUriParser() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: Function to parse a descriptor for a scheme component. If a scheme is found sl@0: then the output argument aScheme is set to refer to it. sl@0: sl@0: @param aUri The descriptor containing the uri to be parsed for a scheme. sl@0: @param aScheme The output descriptor to refer to the scheme sl@0: @return The number of characters consumed in parsing the scheme. sl@0: @pre The output descriptor has been initialized so that the pointer sl@0: to the associated descriptor buffer is NULL. The input descriptor sl@0: is set to the start of the uri. sl@0: @post If a scheme component exists then the output descriptor refers sl@0: to it, otherwise the output descriptor is left unchanged. sl@0: */ sl@0: TInt CSIPUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme) sl@0: { sl@0: // Get the descriptor and look for scheme delimiter sl@0: TInt consumed =0; sl@0: TInt endSchemePos = FindFirstUriDelimiter(aUri, ESipSchemeDelimiterSearch); sl@0: sl@0: if( endSchemePos != KErrNotFound ) sl@0: { sl@0: // Got a scheme - store information sl@0: aScheme.Set(aUri.Left(endSchemePos)); sl@0: sl@0: // Set consumed amount move past scheme delimiter sl@0: consumed = endSchemePos + 1; sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Function to parse a descriptor for an authority component. If an authority is sl@0: found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts sl@0: of the authority component. If an authority component exists then the host part exists. The sl@0: userinfo and port parts are optional. sl@0: sl@0: @param aUri The descriptor containing the uri to be parsed sl@0: for an authority. sl@0: @param aUserinfo The output descriptor for the userinfo component. sl@0: @param aHost The output descriptor for the host component. sl@0: @param aPort The output descriptor for the port component. sl@0: @param aUseNetworkDelimiter is not used as we know the Sip scheme sl@0: not uses the network delimeter '//' sl@0: @return The number of characters consumed in parsing the authority. sl@0: @pre The output descriptors have been initialized so that the pointer sl@0: to the their associated descriptor buffers is NULL. The input descriptor sl@0: is set to the start of the start of the authority component. sl@0: sl@0: @post If an authority component exists then the output descriptors refer sl@0: to the userinfo part (if exists), the host part and the port part (if exists), sl@0: otherwise the output descriptors are left unchanged. sl@0: */ sl@0: TInt CSIPUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter) sl@0: { sl@0: // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//' sl@0: TInt consumed =0; sl@0: const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0; sl@0: if( !aUseNetworkDelimiter || sl@0: (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter )) sl@0: { sl@0: // There is an authority sl@0: TPtrC8 authority( aUri.Mid(prefixLength) ); sl@0: sl@0: // Authority delimited by ';', '?' or the end of the string sl@0: TInt authorityEndPos = FindFirstUriDelimiter(authority, ESipAuthDelimiterSearch); sl@0: sl@0: // Got authority - parse it for its components sl@0: authority.Set(authority.Left(authorityEndPos)); sl@0: sl@0: // Get the userinfo... sl@0: TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter); sl@0: if( userinfoEndPos != KErrNotFound ) sl@0: { sl@0: // Store the information sl@0: aUserinfo.Set(authority.Left(userinfoEndPos)); sl@0: sl@0: // Move past the userinfo and the delimiter '@' sl@0: authority.Set(authority.Mid(userinfoEndPos + 1)); sl@0: } sl@0: sl@0: // Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now sl@0: TInt semicolonPos = FindFirstUriDelimiter(authority, ESipSemiColonDelimiterFlag); sl@0: if ( semicolonPos != KErrNotFound ) sl@0: { sl@0: authority.Set(authority.Left(semicolonPos)); sl@0: authorityEndPos = semicolonPos + userinfoEndPos + 1; sl@0: } sl@0: sl@0: // Set consumed amount to move past authority sl@0: consumed += prefixLength + authorityEndPos; sl@0: sl@0: // Check if this is an IPv6 address by looking for the opening '[' sl@0: TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace); sl@0: sl@0: if (startHostIPv6 == KErrNotFound) sl@0: { sl@0: // This isn't an IPv6 address..... sl@0: sl@0: // Get host... sl@0: TInt hostEndPos = authority.Locate(KPortDelimiter); sl@0: sl@0: // Host also delimited by the end of the authority sl@0: if( hostEndPos == KErrNotFound ) sl@0: { sl@0: hostEndPos = authority.Length(); sl@0: } sl@0: sl@0: // There's always a host, but can be empty - store information sl@0: aHost.Set(authority.Left(hostEndPos)); sl@0: sl@0: // Move past the host sl@0: authority.Set(authority.Mid(hostEndPos)); sl@0: } sl@0: else sl@0: { sl@0: // First, move past the opening brace sl@0: authority.Set(authority.Mid(startHostIPv6 + 1)); sl@0: // auth now = X:X:X]????? sl@0: sl@0: // This is an IPv6 address, so it MUST have the closing brace too.... sl@0: TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace); sl@0: sl@0: // Return an error if the closing IPv6 delimiter isn't there. sl@0: // or Host is empty sl@0: if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1) sl@0: { sl@0: return KUriUtilsErrInvalidUri; sl@0: } sl@0: sl@0: // It's an ipv6 address, with an opening and closing brace. So now just extract it sl@0: // auth = [X:X:X]????? sl@0: sl@0: sl@0: // Set the host, and need to remove the closing brace sl@0: aHost.Set(authority.Left(endIPv6Host)); sl@0: // host = X:X:X sl@0: sl@0: // Move past the host sl@0: authority.Set(authority.Mid(endIPv6Host + 1 )); sl@0: } sl@0: sl@0: // Get the port... sl@0: TInt portEndPos = authority.Length(); sl@0: if( portEndPos ) sl@0: { sl@0: // Store the port - remove leading ':' sl@0: aPort.Set(authority.Mid(1, portEndPos - 1)); sl@0: } sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Function to parse a descriptor for a path/parameter component.There is always a path component. sl@0: The ouput argument aPath is set to the path/parameter component found. sl@0: sl@0: @param aUri The descriptor containing the uri to be parsed for a path/parameter. sl@0: @param aComponent The output descriptor to refer to the path. sl@0: @return The number of characters consumed in parsing the path. sl@0: @pre The output descriptor has been initialized so that the pointer sl@0: to the associated descriptor buffer is NULL. The input descriptor sl@0: is set to the start of the path. sl@0: sl@0: @post The output descriptor refers to the path component. sl@0: */ sl@0: TInt CSIPUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent) sl@0: { sl@0: // Get descriptor with the path sl@0: TInt consumed =0; sl@0: sl@0: // Path is delimited by '?' or the end of the string sl@0: TInt pathEndPos = FindFirstUriDelimiter(aUri, ESipPathDelimiterSearch); sl@0: sl@0: // Check for presence of path sl@0: if( pathEndPos != KErrNotFound ) sl@0: { sl@0: // Got path - store information sl@0: aComponent.Set(aUri.Left(pathEndPos)); sl@0: sl@0: // Set consumed amount to move past path sl@0: consumed = pathEndPos; sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Function to parse a descriptor for a query/header component.If a query is found then sl@0: the output argument aQuery is set to refer to it. sl@0: sl@0: @param aUri The descriptor containing the uri to be parsed for a query/Header. sl@0: @param aComponent The output descriptor to refer to the query sl@0: @return The number of characters consumed in parsing the query. sl@0: @pre The output descriptor has been initialized so that the pointer sl@0: to the associated descriptor buffer is NULL. The input descriptor is set to sl@0: the start of the query. sl@0: @post If a query component exists then the output descriptor refers sl@0: to it, otherwise the output descriptor is left unchanged. sl@0: */ sl@0: TInt CSIPUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent) sl@0: { sl@0: // Get descriptor with the query sl@0: TInt consumed =0; sl@0: sl@0: // Query/Header is delimited by end of the string sl@0: TInt queryEndPos = aUri.Length(); sl@0: sl@0: // Check for presence of query sl@0: if( queryEndPos ) sl@0: { sl@0: // Got query - store information; need to excluded leading '?' sl@0: aComponent.Set(aUri.Mid(1, queryEndPos - 1)); sl@0: sl@0: // Set consumed amount to move past query sl@0: consumed = queryEndPos; sl@0: } sl@0: return consumed; sl@0: } sl@0: sl@0: /** sl@0: Function to parse a descriptor for a fragment component. sl@0: In Sip Uris no Fragment Component it contains. This is an dummy implementation. sl@0: sl@0: @param aUri not used. sl@0: @param aComponent not used. sl@0: @return returns zero. sl@0: */ sl@0: TInt CSIPUriParser::ParseFragment(const TPtrC8& /*aUri*/, TPtrC8& /* aComponent*/) sl@0: { sl@0: // Sip Uri Does not conatin Fragment sl@0: return 0; sl@0: } sl@0: sl@0: /** sl@0: Function to find the position of the first delimiter in the descriptor specified sl@0: by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are sl@0: no others. In the case of the scheme delimiter search, the position returned depends on the sl@0: position of the colon delimiter with respect to the other delimiters for a scheme. sl@0: sl@0: @param aUri The descriptor containing the section of a uri to be searched. sl@0: @param aSearchFlag The enum specifying the delimiters to search for. sl@0: @return The position of nearest delimiter to start of the descriptor, where sl@0: zero is the start (left-most) position. sl@0: */ sl@0: TInt CSIPUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TSipDelimiterSearchFlag aSearchFlag) sl@0: { sl@0: // Set ultimate delimiter - string length sl@0: TInt endPos = aUri.Length(); sl@0: sl@0: if( aSearchFlag & ESipQueryDelimiterFlag ) sl@0: { sl@0: TInt queryPos = aUri.Locate(KQueryDelimiter); sl@0: if( queryPos != KErrNotFound && queryPos < endPos ) sl@0: { sl@0: TInt userinfoPos = aUri.Locate(KUserinfoDelimiter); sl@0: //QueryDelimiter may be in Userinfo sl@0: if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > queryPos ) sl@0: { sl@0: //Find QueryDelimiter after Userinfo sl@0: queryPos = aUri.Mid(userinfoPos).Locate(KQueryDelimiter); sl@0: if (queryPos != KErrNotFound && queryPos < endPos ) sl@0: { sl@0: queryPos += userinfoPos; sl@0: } sl@0: } sl@0: if(queryPos != KErrNotFound) sl@0: { sl@0: endPos = queryPos; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if( aSearchFlag & ESipSemiColonDelimiterFlag ) sl@0: { sl@0: TInt semiColonPos = aUri.Locate(KParamDelimiter); sl@0: if( semiColonPos != KErrNotFound && semiColonPos < endPos ) sl@0: { sl@0: TInt userinfoPos = aUri.Locate(KUserinfoDelimiter); sl@0: //ParamDelimiter may be in Userinfo sl@0: if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > semiColonPos ) sl@0: { sl@0: //Find ParamDelimiter after Userinfo sl@0: semiColonPos = aUri.Mid(userinfoPos).Locate(KParamDelimiter); sl@0: if (semiColonPos != KErrNotFound && semiColonPos < endPos ) sl@0: { sl@0: semiColonPos += userinfoPos; sl@0: } sl@0: } sl@0: if(semiColonPos != KErrNotFound) sl@0: { sl@0: endPos = semiColonPos; sl@0: } sl@0: } sl@0: } sl@0: if( aSearchFlag & ESipColonDelimiterFlag ) sl@0: { sl@0: TInt schemePos = aUri.Locate(KSchemeDelimiter); sl@0: if( schemePos != KErrNotFound && schemePos < endPos ) sl@0: { sl@0: // There is a scheme sl@0: endPos = schemePos; sl@0: } sl@0: else if( aSearchFlag == ESipSchemeDelimiterSearch ) sl@0: { sl@0: // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound sl@0: endPos = KErrNotFound; sl@0: } sl@0: } sl@0: return endPos; sl@0: } sl@0: