sl@0: // Copyright (c) 2001-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: // System includes sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: //User includes sl@0: #include "TUriParserInternal.h" sl@0: #include "UriUtilsInternal.h" sl@0: #include "TUriCInternal.h" sl@0: #include "GenericUriParser.h" sl@0: #include "SipUriParser.h" sl@0: sl@0: sl@0: sl@0: // Constants sl@0: // sl@0: sl@0: _LIT8(KSIP, "Sip"); sl@0: _LIT8(KSIPS, "Sips"); sl@0: sl@0: sl@0: // sl@0: // sl@0: // Implementation of TUriParser8 sl@0: // sl@0: // sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: @since 6.0 sl@0: */ sl@0: EXPORT_C TUriParser8::TUriParser8() sl@0: : TUriC8() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: Parses the descriptor aUri into uri components. sl@0: sl@0: @since 6.0 sl@0: @param aUri A reference to a descriptor pointer to be parsed. sl@0: @return KErrNone if the descriptor has been parsed into uri components. sl@0: KUriUtilsParserErrInvalidUri if the descriptor is an invalid uri. sl@0: KErrNoMemory if out of memory sl@0: @post The object references the input descriptor. sl@0: */ sl@0: EXPORT_C TInt TUriParser8::Parse(const TDesC8& aUri) sl@0: { sl@0: // Reset the Uri information and then set the Uri sl@0: if( iUriDes.Length() ) sl@0: { sl@0: Reset(); sl@0: } sl@0: iUriDes.Set(aUri); sl@0: sl@0: // Check uri is valid sl@0: if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter ) sl@0: { sl@0: return KUriUtilsErrInvalidUri; sl@0: } sl@0: sl@0: TPtrC8 schemeComponent; sl@0: RetrieveScheme(iUriDes,schemeComponent); sl@0: CGenericUriParser* UriHandler = NULL; sl@0: TInt err=KErrNone; sl@0: if(schemeComponent.CompareF(KSIP()) == 0 || schemeComponent.CompareF(KSIPS()) == 0 ) sl@0: { sl@0: TRAP(err,UriHandler = CSIPUriParser::NewL()); sl@0: } sl@0: else sl@0: { sl@0: TRAP(err,UriHandler = CGenericUriParser::NewL()); sl@0: } sl@0: if(UriHandler) sl@0: { sl@0: UriHandler->DoParseUri(iUriDes, iComponent); sl@0: delete UriHandler; sl@0: } sl@0: sl@0: return err; sl@0: sl@0: } sl@0: sl@0: /** sl@0: Parses the descriptor aUri into uri components. sl@0: sl@0: @param aUri A reference to a descriptor pointer of an Uri. sl@0: @param aScheme A reference to a descriptor pointer for retieved sl@0: scheme component. sl@0: */ sl@0: void TUriParser8::RetrieveScheme(const TPtrC8& aUri, TPtrC8& aScheme) sl@0: { sl@0: TInt schemePos = aUri.Locate(KSchemeDelimiter); sl@0: if(schemePos != KErrNotFound) sl@0: { sl@0: // Got a scheme - store information sl@0: aScheme.Set(aUri.Left(schemePos)); sl@0: } sl@0: } sl@0: sl@0: // sl@0: // sl@0: // Implementation of TUriParser16 sl@0: // sl@0: // sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: */ sl@0: EXPORT_C TUriParser16::TUriParser16() sl@0: : TUriC16() sl@0: { sl@0: } sl@0: sl@0: /** sl@0: Parses the descriptor aUri into uri components. sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: @param aUri A reference to a descriptor pointer to be parsed. sl@0: @return KErrNone if the descriptor has been parsed into uri components. sl@0: EUriParserErrInvalidUri if the descriptor is an invalid uri. sl@0: @post The object references the input descriptor. sl@0: */ sl@0: EXPORT_C TInt TUriParser16::Parse(const TDesC16& aUri) sl@0: { sl@0: // Reset the Uri information and then set the Uri sl@0: if( iUriDes.Length() ) sl@0: Reset(); sl@0: iUriDes.Set(aUri); sl@0: sl@0: // Check uri is valid sl@0: if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter ) sl@0: return KUriUtilsErrInvalidUri; sl@0: sl@0: // Parse the uri. sl@0: DoParseUri(iUriDes, iComponent); sl@0: return KErrNone; sl@0: } sl@0: sl@0: // sl@0: // sl@0: // Implementation of templated LOCAL functions sl@0: // sl@0: // sl@0: sl@0: /** sl@0: Templated function that parses a descriptor into the components of a uri. sl@0: sl@0: @since 6.0 sl@0: @param aUri The descriptor with the data to parse. sl@0: @param aComponent The output array of descriptors of each uri component. sl@0: @pre Each descriptor pointer in aComponent has had the pointer to its sl@0: associated descriptor buffer set to NULL. sl@0: @post The descriptor pointers in aComponent are updated to refer to the sl@0: appropriate sections of aUri that represent the components of a uri. sl@0: */ sl@0: template sl@0: void DoParseUri(const TPtrCType& aUri, TPtrCType aComponent[]) sl@0: { sl@0: // Parse the components sl@0: TPtrCType uri = aUri; sl@0: TInt consumed = 0; sl@0: TPtrCType& scheme = aComponent[EUriScheme]; sl@0: if( (consumed = ParseScheme(uri, scheme)) > 0 ) sl@0: { sl@0: uri.Set(uri.Mid(consumed)); sl@0: } sl@0: if( (consumed = ParseAuthority(uri, aComponent[EUriUserinfo], sl@0: aComponent[EUriHost], aComponent[EUriPort], IsNetworkScheme(scheme))) > 0 ) sl@0: { sl@0: uri.Set(uri.Mid(consumed)); sl@0: } sl@0: if( (consumed = ParsePath(uri, aComponent[EUriPath])) > 0 ) sl@0: { sl@0: uri.Set(uri.Mid(consumed)); sl@0: } sl@0: if( (consumed = ParseQuery(uri, aComponent[EUriQuery])) > 0 ) sl@0: { sl@0: uri.Set(uri.Mid(consumed)); sl@0: } sl@0: if( (consumed = ParseFragment(uri, aComponent[EUriFragment])) > 0 ) sl@0: { sl@0: uri.Set(uri.Mid(consumed)); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Templated 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: @since 6.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: template sl@0: TInt ParseScheme(const TPtrCType& aUri, TPtrCType& 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: Templated 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: @since 6.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: sl@0: template sl@0: TInt ParseAuthority(const TPtrCType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& 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: TPtrCType 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: hostEndPos = authority.Length(); 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: if (endIPv6Host==KErrNotFound) sl@0: return KUriUtilsErrInvalidUri; 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: Templated function to parse a descriptor for a path component.There is always a path component. sl@0: The ouput argument aPath is set to the path component found. sl@0: sl@0: @since 6.0 sl@0: @param aUri The descriptor containing the uri to be parsed for sl@0: 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: template sl@0: TInt ParsePath(const TPtrCType& aUri, TPtrCType& 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: Templated function to parse a descriptor for a query component.If a query is found then sl@0: the output argument aQuery is set to refer to it. sl@0: sl@0: @since 6.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: template sl@0: TInt ParseQuery(const TPtrCType& aUri, TPtrCType& 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: Templated 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: @since 6.0 sl@0: @param aUri The descriptor containing the uri to be parsed for sl@0: 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: template sl@0: TInt ParseFragment(const TPtrCType& aUri, TPtrCType& 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: Templated 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: @since 6.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: template sl@0: TInt FindFirstUriDelimiter(const TPtrCType& 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: endPos = fragmentPos; 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: endPos = queryPos; 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: endPos = slashPos; 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: endPos = semiColonPos; 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: }