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 "GenericUriParser.h" sl@0: sl@0: sl@0: /** sl@0: * CGenericUriParser Constructor. sl@0: */ sl@0: CGenericUriParser::CGenericUriParser() sl@0: : CBase() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: * CGenericUriParser Static Factory Construction. sl@0: */ sl@0: CGenericUriParser* CGenericUriParser::NewL() sl@0: { sl@0: CGenericUriParser* self = new (ELeave) CGenericUriParser; 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 CGenericUriParser::ConstructL() sl@0: { sl@0: // Does nothing. sl@0: } sl@0: sl@0: /** sl@0: * Default Destructor. sl@0: */ sl@0: CGenericUriParser::~CGenericUriParser() 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 sl@0: 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 CGenericUriParser::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, ESchemeDelimiterSearch); 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 Whether the scheme 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 CGenericUriParser::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, EAuthDelimiterSearch); 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, ESemiColonDelimiterFlag); 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: 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. 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 CGenericUriParser::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, EPathDelimiterSearch); 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 sl@0: a query. 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 CGenericUriParser::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 is delimited by '#' or end of the string sl@0: TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch); 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. If a fragment is found then sl@0: the output argument aFragment is set to refer to it. sl@0: sl@0: @param aUri The descriptor containing the uri to be parsed for a fragment. sl@0: @param aComponent The output descriptor to refer to the fragment. sl@0: @return The number of characters consumed in parsing the fragment. 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 fragment. sl@0: @post If a fragment component exists then the output descriptor refers sl@0: to it, otherwise the output descriptor is left unchanged. sl@0: */ sl@0: TInt CGenericUriParser::ParseFragment(const TPtrC8& aUri, TPtrC8& aComponent) sl@0: { sl@0: // Get descriptor with the fragment sl@0: TInt consumed =0; sl@0: sl@0: // Fragment is delimited by end of the string sl@0: TInt fragmentEndPos = aUri.Length(); sl@0: sl@0: // Check for presence of fragment sl@0: if( fragmentEndPos ) sl@0: { sl@0: // Got fragment - store information; need to excluded leading '#' sl@0: aComponent.Set(aUri.Mid(1, fragmentEndPos - 1)); sl@0: sl@0: // Set consumed amount to move past fragment sl@0: consumed = fragmentEndPos; sl@0: } sl@0: return consumed; 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 CGenericUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TDelimiterSearchFlag aSearchFlag) sl@0: { sl@0: // Set ultimate delimiter - string length sl@0: TInt endPos = aUri.Length(); sl@0: if( aSearchFlag & EHashDelimiterFlag ) sl@0: { sl@0: TInt fragmentPos = aUri.Locate(KFragmentDelimiter); sl@0: if( fragmentPos != KErrNotFound && fragmentPos < endPos ) sl@0: { sl@0: endPos = fragmentPos; sl@0: } sl@0: } sl@0: if( aSearchFlag & EQueryDelimiterFlag ) sl@0: { sl@0: TInt queryPos = aUri.Locate(KQueryDelimiter); sl@0: if( queryPos != KErrNotFound && queryPos < endPos ) sl@0: { sl@0: endPos = queryPos; sl@0: } sl@0: } sl@0: if( aSearchFlag & ESlashDelimiterFlag ) sl@0: { sl@0: TInt slashPos = aUri.Locate(KSlashDelimiter); sl@0: if( slashPos != KErrNotFound && slashPos < endPos ) sl@0: { sl@0: endPos = slashPos; sl@0: } sl@0: } sl@0: if( aSearchFlag & ESemiColonDelimiterFlag ) sl@0: { sl@0: TInt semiColonPos = aUri.Locate(KParamDelimiter); sl@0: if( semiColonPos != KErrNotFound && semiColonPos < endPos ) sl@0: { sl@0: endPos = semiColonPos; sl@0: } sl@0: } sl@0: if( aSearchFlag & EColonDelimiterFlag ) 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 == ESchemeDelimiterSearch ) 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: sl@0: sl@0: sl@0: sl@0: