Update contrib.
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
20 #include <uriutilscommon.h>
24 #include "TUriParserInternal.h"
25 #include "UriUtilsInternal.h"
26 #include "TUriCInternal.h"
27 #include "GenericUriParser.h"
28 #include "SipUriParser.h"
41 // Implementation of TUriParser8
50 EXPORT_C TUriParser8::TUriParser8()
56 Parses the descriptor aUri into uri components.
59 @param aUri A reference to a descriptor pointer to be parsed.
60 @return KErrNone if the descriptor has been parsed into uri components.
61 KUriUtilsParserErrInvalidUri if the descriptor is an invalid uri.
62 KErrNoMemory if out of memory
63 @post The object references the input descriptor.
65 EXPORT_C TInt TUriParser8::Parse(const TDesC8& aUri)
67 // Reset the Uri information and then set the Uri
68 if( iUriDes.Length() )
75 if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter )
77 return KUriUtilsErrInvalidUri;
80 TPtrC8 schemeComponent;
81 RetrieveScheme(iUriDes,schemeComponent);
82 CGenericUriParser* UriHandler = NULL;
84 if(schemeComponent.CompareF(KSIP()) == 0 || schemeComponent.CompareF(KSIPS()) == 0 )
86 TRAP(err,UriHandler = CSIPUriParser::NewL());
90 TRAP(err,UriHandler = CGenericUriParser::NewL());
94 UriHandler->DoParseUri(iUriDes, iComponent);
103 Parses the descriptor aUri into uri components.
105 @param aUri A reference to a descriptor pointer of an Uri.
106 @param aScheme A reference to a descriptor pointer for retieved
109 void TUriParser8::RetrieveScheme(const TPtrC8& aUri, TPtrC8& aScheme)
111 TInt schemePos = aUri.Locate(KSchemeDelimiter);
112 if(schemePos != KErrNotFound)
114 // Got a scheme - store information
115 aScheme.Set(aUri.Left(schemePos));
121 // Implementation of TUriParser16
129 @deprecated Deprecated in 9.1
131 EXPORT_C TUriParser16::TUriParser16()
137 Parses the descriptor aUri into uri components.
140 @deprecated Deprecated in 9.1
141 @param aUri A reference to a descriptor pointer to be parsed.
142 @return KErrNone if the descriptor has been parsed into uri components.
143 EUriParserErrInvalidUri if the descriptor is an invalid uri.
144 @post The object references the input descriptor.
146 EXPORT_C TInt TUriParser16::Parse(const TDesC16& aUri)
148 // Reset the Uri information and then set the Uri
149 if( iUriDes.Length() )
153 // Check uri is valid
154 if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter )
155 return KUriUtilsErrInvalidUri;
158 DoParseUri(iUriDes, iComponent);
164 // Implementation of templated LOCAL functions
169 Templated function that parses a descriptor into the components of a uri.
172 @param aUri The descriptor with the data to parse.
173 @param aComponent The output array of descriptors of each uri component.
174 @pre Each descriptor pointer in aComponent has had the pointer to its
175 associated descriptor buffer set to NULL.
176 @post The descriptor pointers in aComponent are updated to refer to the
177 appropriate sections of aUri that represent the components of a uri.
179 template<class TPtrCType>
180 void DoParseUri(const TPtrCType& aUri, TPtrCType aComponent[])
182 // Parse the components
183 TPtrCType uri = aUri;
185 TPtrCType& scheme = aComponent[EUriScheme];
186 if( (consumed = ParseScheme(uri, scheme)) > 0 )
188 uri.Set(uri.Mid(consumed));
190 if( (consumed = ParseAuthority(uri, aComponent[EUriUserinfo],
191 aComponent[EUriHost], aComponent[EUriPort], IsNetworkScheme(scheme))) > 0 )
193 uri.Set(uri.Mid(consumed));
195 if( (consumed = ParsePath(uri, aComponent[EUriPath])) > 0 )
197 uri.Set(uri.Mid(consumed));
199 if( (consumed = ParseQuery(uri, aComponent[EUriQuery])) > 0 )
201 uri.Set(uri.Mid(consumed));
203 if( (consumed = ParseFragment(uri, aComponent[EUriFragment])) > 0 )
205 uri.Set(uri.Mid(consumed));
210 Templated function to parse a descriptor for a scheme component. If a scheme is found
211 then the output argument aScheme is set to refer to it.
214 @param aUri The descriptor containing the uri to be parsed for
216 @param aScheme The output descriptor to refer to the scheme
217 @return The number of characters consumed in parsing the scheme.
218 @pre The output descriptor has been initialized so that the pointer
219 to the associated descriptor buffer is NULL. The input descriptor
220 is set to the start of the uri.
221 @post If a scheme component exists then the output descriptor refers
222 to it, otherwise the output descriptor is left unchanged.
224 template<class TPtrCType>
225 TInt ParseScheme(const TPtrCType& aUri, TPtrCType& aScheme)
227 // Get the descriptor and look for scheme delimiter
229 TInt endSchemePos = FindFirstUriDelimiter(aUri, ESchemeDelimiterSearch);
231 if( endSchemePos != KErrNotFound )
233 // Got a scheme - store information
234 aScheme.Set(aUri.Left(endSchemePos));
236 // Set consumed amount move past scheme delimiter
237 consumed = endSchemePos + 1;
243 Templated function to parse a descriptor for an authority component. If an authority is
244 found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts
245 of the authority component. If an authority component exists then the host part exists. The
246 userinfo and port parts are optional.
249 @param aUri The descriptor containing the uri to be parsed
251 @param aUserinfo The output descriptor for the userinfo component.
252 @param aHost The output descriptor for the host component.
253 @param aPort The output descriptor for the port component.
254 @param aUseNetworkDelimiter Whether the scheme uses the network delimeter '//'
255 @return The number of characters consumed in parsing the authority.
256 @pre The output descriptors have been initialized so that the pointer
257 to the their associated descriptor buffers is NULL. The input descriptor
258 is set to the start of the start of the authority component.
260 @post If an authority component exists then the output descriptors refer
261 to the userinfo part (if exists), the host part and the port part (if exists),
262 otherwise the output descriptors are left unchanged.
265 template<class TPtrCType>
266 TInt ParseAuthority(const TPtrCType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool aUseNetworkDelimiter)
268 // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//'
270 const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
271 if( !aUseNetworkDelimiter ||
272 (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
274 // There is an authority
275 TPtrCType authority = aUri.Mid(prefixLength);
277 // Authority delimited by '/', '?', '#' or the end of the string
278 TInt authorityEndPos = FindFirstUriDelimiter(authority, EAuthDelimiterSearch);
280 // Got authority - parse it for its components
281 authority.Set(authority.Left(authorityEndPos));
283 // Get the userinfo...
284 TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
285 if( userinfoEndPos != KErrNotFound )
287 // Store the information
288 aUserinfo.Set(authority.Left(userinfoEndPos));
290 // Move past the userinfo and the delimiter '@'
291 authority.Set(authority.Mid(userinfoEndPos + 1));
294 // Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now
295 TInt semicolonPos = FindFirstUriDelimiter(authority, ESemiColonDelimiterFlag);
296 if ( semicolonPos != KErrNotFound )
298 authority.Set(authority.Left(semicolonPos));
299 authorityEndPos = semicolonPos + userinfoEndPos + 1;
302 // Set consumed amount to move past authority
303 consumed += prefixLength + authorityEndPos;
305 // Check if this is an IPv6 address by looking for the opening '['
306 TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
308 if (startHostIPv6==KErrNotFound)
310 // This isn't an IPv6 address.....
313 TInt hostEndPos = authority.Locate(KPortDelimiter);
315 // Host also delimited by the end of the authority
316 if( hostEndPos == KErrNotFound )
317 hostEndPos = authority.Length();
319 // There's always a host, but can be empty - store information
320 aHost.Set(authority.Left(hostEndPos));
322 // Move past the host
323 authority.Set(authority.Mid(hostEndPos));
328 // First, move past the opening brace
329 authority.Set(authority.Mid(startHostIPv6 + 1));
330 // auth now = X:X:X]?????
332 // This is an IPv6 address, so it MUST have the closing brace too....
333 TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
335 // Return an error if the closing IPv6 delimiter isn't there.
336 if (endIPv6Host==KErrNotFound)
337 return KUriUtilsErrInvalidUri;
339 // It's an ipv6 address, with an opening and closing brace. So now just extract it
340 // auth = [X:X:X]?????
343 // Set the host, and need to remove the closing brace
344 aHost.Set(authority.Left(endIPv6Host));
347 // Move past the host
348 authority.Set(authority.Mid(endIPv6Host + 1 ));
352 TInt portEndPos = authority.Length();
355 // Store the port - remove leading ':'
356 aPort.Set(authority.Mid(1, portEndPos - 1));
363 Templated function to parse a descriptor for a path component.There is always a path component.
364 The ouput argument aPath is set to the path component found.
367 @param aUri The descriptor containing the uri to be parsed for
369 @param aComponent The output descriptor to refer to the path.
370 @return The number of characters consumed in parsing the path.
371 @pre The output descriptor has been initialized so that the pointer
372 to the associated descriptor buffer is NULL. The input descriptor
373 is set to the start of the path.
375 @post The output descriptor refers to the path component.
377 template<class TPtrCType>
378 TInt ParsePath(const TPtrCType& aUri, TPtrCType& aComponent)
380 // Get descriptor with the path
383 // Path is delimited by '?'. '#' or the end of the string
384 TInt pathEndPos = FindFirstUriDelimiter(aUri, EPathDelimiterSearch);
386 // Check for presence of path
387 if( pathEndPos != KErrNotFound )
389 // Got path - store information
390 aComponent.Set(aUri.Left(pathEndPos));
392 // Set consumed amount to move past path
393 consumed = pathEndPos;
399 Templated function to parse a descriptor for a query component.If a query is found then
400 the output argument aQuery is set to refer to it.
403 @param aUri The descriptor containing the uri to be parsed for
405 @param aComponent The output descriptor to refer to the query
406 @return The number of characters consumed in parsing the query.
407 @pre The output descriptor has been initialized so that the pointer
408 to the associated descriptor buffer is NULL. The input descriptor is set to
409 the start of the query.
410 @post If a query component exists then the output descriptor refers
411 to it, otherwise the output descriptor is left unchanged.
413 template<class TPtrCType>
414 TInt ParseQuery(const TPtrCType& aUri, TPtrCType& aComponent)
416 // Get descriptor with the query
419 // Query is delimited by '#' or end of the string
420 TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch);
422 // Check for presence of query
425 // Got query - store information; need to excluded leading '?'
426 aComponent.Set(aUri.Mid(1, queryEndPos - 1));
428 // Set consumed amount to move past query
429 consumed = queryEndPos;
435 Templated function to parse a descriptor for a fragment component. If a fragment is found then
436 the output argument aFragment is set to refer to it.
439 @param aUri The descriptor containing the uri to be parsed for
441 @param aComponent The output descriptor to refer to the fragment.
442 @return The number of characters consumed in parsing the fragment.
443 @pre The output descriptor has been initialized so that the pointer
444 to the associated descriptor buffer is NULL. The input descriptor is set to
445 the start of the fragment.
446 @post If a fragment component exists then the output descriptor refers
447 to it, otherwise the output descriptor is left unchanged.
449 template<class TPtrCType>
450 TInt ParseFragment(const TPtrCType& aUri, TPtrCType& aComponent)
452 // Get descriptor with the fragment
455 // Fragment is delimited by end of the string
456 TInt fragmentEndPos = aUri.Length();
458 // Check for presence of fragment
461 // Got fragment - store information; need to excluded leading '#'
462 aComponent.Set(aUri.Mid(1, fragmentEndPos - 1));
464 // Set consumed amount to move past fragment
465 consumed = fragmentEndPos;
471 Templated function to find the position of the first delimiter in the descriptor specified
472 by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are
473 no others. In the case of the scheme delimiter search, the position returned depends on the
474 position of the colon delimiter with respect to the other delimiters for a scheme.
477 @param aUri The descriptor containing the section of a uri to be searched.
478 @param aSearchFlag The enum specifying the delimiters to search for.
479 @return The position of nearest delimiter to start of the descriptor, where
480 zero is the start (left-most) position.
482 template<class TPtrCType>
483 TInt FindFirstUriDelimiter(const TPtrCType& aUri, TDelimiterSearchFlag aSearchFlag)
485 // Set ultimate delimiter - string length
486 TInt endPos = aUri.Length();
487 if( aSearchFlag & EHashDelimiterFlag )
489 TInt fragmentPos = aUri.Locate(KFragmentDelimiter);
490 if( fragmentPos != KErrNotFound && fragmentPos < endPos )
491 endPos = fragmentPos;
493 if( aSearchFlag & EQueryDelimiterFlag )
495 TInt queryPos = aUri.Locate(KQueryDelimiter);
496 if( queryPos != KErrNotFound && queryPos < endPos )
499 if( aSearchFlag & ESlashDelimiterFlag )
501 TInt slashPos = aUri.Locate(KSlashDelimiter);
502 if( slashPos != KErrNotFound && slashPos < endPos )
505 if( aSearchFlag & ESemiColonDelimiterFlag )
507 TInt semiColonPos = aUri.Locate(KParamDelimiter);
508 if( semiColonPos != KErrNotFound && semiColonPos < endPos )
509 endPos = semiColonPos;
511 if( aSearchFlag & EColonDelimiterFlag )
513 TInt schemePos = aUri.Locate(KSchemeDelimiter);
514 if( schemePos != KErrNotFound && schemePos < endPos )
519 else if( aSearchFlag == ESchemeDelimiterSearch )
521 // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
522 endPos = KErrNotFound;