|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 // System includes |
|
17 #include <uri8.h> |
|
18 #include <uri16.h> |
|
19 #include <uriutils.h> |
|
20 #include <uriutilscommon.h> |
|
21 |
|
22 |
|
23 //User includes |
|
24 #include "TUriParserInternal.h" |
|
25 #include "UriUtilsInternal.h" |
|
26 #include "TUriCInternal.h" |
|
27 #include "GenericUriParser.h" |
|
28 #include "SipUriParser.h" |
|
29 |
|
30 |
|
31 |
|
32 // Constants |
|
33 // |
|
34 |
|
35 _LIT8(KSIP, "Sip"); |
|
36 _LIT8(KSIPS, "Sips"); |
|
37 |
|
38 |
|
39 // |
|
40 // |
|
41 // Implementation of TUriParser8 |
|
42 // |
|
43 // |
|
44 |
|
45 /** |
|
46 Constructor. |
|
47 |
|
48 @since 6.0 |
|
49 */ |
|
50 EXPORT_C TUriParser8::TUriParser8() |
|
51 : TUriC8() |
|
52 { |
|
53 } |
|
54 |
|
55 /** |
|
56 Parses the descriptor aUri into uri components. |
|
57 |
|
58 @since 6.0 |
|
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. |
|
64 */ |
|
65 EXPORT_C TInt TUriParser8::Parse(const TDesC8& aUri) |
|
66 { |
|
67 // Reset the Uri information and then set the Uri |
|
68 if( iUriDes.Length() ) |
|
69 { |
|
70 Reset(); |
|
71 } |
|
72 iUriDes.Set(aUri); |
|
73 |
|
74 // Check uri is valid |
|
75 if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter ) |
|
76 { |
|
77 return KUriUtilsErrInvalidUri; |
|
78 } |
|
79 |
|
80 TPtrC8 schemeComponent; |
|
81 RetrieveScheme(iUriDes,schemeComponent); |
|
82 CGenericUriParser* UriHandler = NULL; |
|
83 TInt err=KErrNone; |
|
84 if(schemeComponent.CompareF(KSIP()) == 0 || schemeComponent.CompareF(KSIPS()) == 0 ) |
|
85 { |
|
86 TRAP(err,UriHandler = CSIPUriParser::NewL()); |
|
87 } |
|
88 else |
|
89 { |
|
90 TRAP(err,UriHandler = CGenericUriParser::NewL()); |
|
91 } |
|
92 if(UriHandler) |
|
93 { |
|
94 UriHandler->DoParseUri(iUriDes, iComponent); |
|
95 delete UriHandler; |
|
96 } |
|
97 |
|
98 return err; |
|
99 |
|
100 } |
|
101 |
|
102 /** |
|
103 Parses the descriptor aUri into uri components. |
|
104 |
|
105 @param aUri A reference to a descriptor pointer of an Uri. |
|
106 @param aScheme A reference to a descriptor pointer for retieved |
|
107 scheme component. |
|
108 */ |
|
109 void TUriParser8::RetrieveScheme(const TPtrC8& aUri, TPtrC8& aScheme) |
|
110 { |
|
111 TInt schemePos = aUri.Locate(KSchemeDelimiter); |
|
112 if(schemePos != KErrNotFound) |
|
113 { |
|
114 // Got a scheme - store information |
|
115 aScheme.Set(aUri.Left(schemePos)); |
|
116 } |
|
117 } |
|
118 |
|
119 // |
|
120 // |
|
121 // Implementation of TUriParser16 |
|
122 // |
|
123 // |
|
124 |
|
125 /** |
|
126 Constructor. |
|
127 |
|
128 @since 6.0 |
|
129 @deprecated Deprecated in 9.1 |
|
130 */ |
|
131 EXPORT_C TUriParser16::TUriParser16() |
|
132 : TUriC16() |
|
133 { |
|
134 } |
|
135 |
|
136 /** |
|
137 Parses the descriptor aUri into uri components. |
|
138 |
|
139 @since 6.0 |
|
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. |
|
145 */ |
|
146 EXPORT_C TInt TUriParser16::Parse(const TDesC16& aUri) |
|
147 { |
|
148 // Reset the Uri information and then set the Uri |
|
149 if( iUriDes.Length() ) |
|
150 Reset(); |
|
151 iUriDes.Set(aUri); |
|
152 |
|
153 // Check uri is valid |
|
154 if( iUriDes.Length() && iUriDes[0]==KSchemeDelimiter ) |
|
155 return KUriUtilsErrInvalidUri; |
|
156 |
|
157 // Parse the uri. |
|
158 DoParseUri(iUriDes, iComponent); |
|
159 return KErrNone; |
|
160 } |
|
161 |
|
162 // |
|
163 // |
|
164 // Implementation of templated LOCAL functions |
|
165 // |
|
166 // |
|
167 |
|
168 /** |
|
169 Templated function that parses a descriptor into the components of a uri. |
|
170 |
|
171 @since 6.0 |
|
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. |
|
178 */ |
|
179 template<class TPtrCType> |
|
180 void DoParseUri(const TPtrCType& aUri, TPtrCType aComponent[]) |
|
181 { |
|
182 // Parse the components |
|
183 TPtrCType uri = aUri; |
|
184 TInt consumed = 0; |
|
185 TPtrCType& scheme = aComponent[EUriScheme]; |
|
186 if( (consumed = ParseScheme(uri, scheme)) > 0 ) |
|
187 { |
|
188 uri.Set(uri.Mid(consumed)); |
|
189 } |
|
190 if( (consumed = ParseAuthority(uri, aComponent[EUriUserinfo], |
|
191 aComponent[EUriHost], aComponent[EUriPort], IsNetworkScheme(scheme))) > 0 ) |
|
192 { |
|
193 uri.Set(uri.Mid(consumed)); |
|
194 } |
|
195 if( (consumed = ParsePath(uri, aComponent[EUriPath])) > 0 ) |
|
196 { |
|
197 uri.Set(uri.Mid(consumed)); |
|
198 } |
|
199 if( (consumed = ParseQuery(uri, aComponent[EUriQuery])) > 0 ) |
|
200 { |
|
201 uri.Set(uri.Mid(consumed)); |
|
202 } |
|
203 if( (consumed = ParseFragment(uri, aComponent[EUriFragment])) > 0 ) |
|
204 { |
|
205 uri.Set(uri.Mid(consumed)); |
|
206 } |
|
207 } |
|
208 |
|
209 /** |
|
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. |
|
212 |
|
213 @since 6.0 |
|
214 @param aUri The descriptor containing the uri to be parsed for |
|
215 a scheme. |
|
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. |
|
223 */ |
|
224 template<class TPtrCType> |
|
225 TInt ParseScheme(const TPtrCType& aUri, TPtrCType& aScheme) |
|
226 { |
|
227 // Get the descriptor and look for scheme delimiter |
|
228 TInt consumed =0; |
|
229 TInt endSchemePos = FindFirstUriDelimiter(aUri, ESchemeDelimiterSearch); |
|
230 |
|
231 if( endSchemePos != KErrNotFound ) |
|
232 { |
|
233 // Got a scheme - store information |
|
234 aScheme.Set(aUri.Left(endSchemePos)); |
|
235 |
|
236 // Set consumed amount move past scheme delimiter |
|
237 consumed = endSchemePos + 1; |
|
238 } |
|
239 return consumed; |
|
240 } |
|
241 |
|
242 /** |
|
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. |
|
247 |
|
248 @since 6.0 |
|
249 @param aUri The descriptor containing the uri to be parsed |
|
250 for an authority. |
|
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. |
|
259 |
|
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. |
|
263 */ |
|
264 |
|
265 template<class TPtrCType> |
|
266 TInt ParseAuthority(const TPtrCType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool aUseNetworkDelimiter) |
|
267 { |
|
268 // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//' |
|
269 TInt consumed =0; |
|
270 const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0; |
|
271 if( !aUseNetworkDelimiter || |
|
272 (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter )) |
|
273 { |
|
274 // There is an authority |
|
275 TPtrCType authority = aUri.Mid(prefixLength); |
|
276 |
|
277 // Authority delimited by '/', '?', '#' or the end of the string |
|
278 TInt authorityEndPos = FindFirstUriDelimiter(authority, EAuthDelimiterSearch); |
|
279 |
|
280 // Got authority - parse it for its components |
|
281 authority.Set(authority.Left(authorityEndPos)); |
|
282 |
|
283 // Get the userinfo... |
|
284 TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter); |
|
285 if( userinfoEndPos != KErrNotFound ) |
|
286 { |
|
287 // Store the information |
|
288 aUserinfo.Set(authority.Left(userinfoEndPos)); |
|
289 |
|
290 // Move past the userinfo and the delimiter '@' |
|
291 authority.Set(authority.Mid(userinfoEndPos + 1)); |
|
292 } |
|
293 |
|
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 ) |
|
297 { |
|
298 authority.Set(authority.Left(semicolonPos)); |
|
299 authorityEndPos = semicolonPos + userinfoEndPos + 1; |
|
300 } |
|
301 |
|
302 // Set consumed amount to move past authority |
|
303 consumed += prefixLength + authorityEndPos; |
|
304 |
|
305 // Check if this is an IPv6 address by looking for the opening '[' |
|
306 TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace); |
|
307 |
|
308 if (startHostIPv6==KErrNotFound) |
|
309 { |
|
310 // This isn't an IPv6 address..... |
|
311 |
|
312 // Get host... |
|
313 TInt hostEndPos = authority.Locate(KPortDelimiter); |
|
314 |
|
315 // Host also delimited by the end of the authority |
|
316 if( hostEndPos == KErrNotFound ) |
|
317 hostEndPos = authority.Length(); |
|
318 |
|
319 // There's always a host, but can be empty - store information |
|
320 aHost.Set(authority.Left(hostEndPos)); |
|
321 |
|
322 // Move past the host |
|
323 authority.Set(authority.Mid(hostEndPos)); |
|
324 } |
|
325 else |
|
326 { |
|
327 // This is an IPv6 address, so it MUST have the closing brace too.... |
|
328 TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace); |
|
329 |
|
330 // Return an error if the closing IPv6 delimiter isn't there. |
|
331 if (endIPv6Host==KErrNotFound) |
|
332 return KUriUtilsErrInvalidUri; |
|
333 |
|
334 // It's an ipv6 address, with an opening and closing brace. So now just extract it |
|
335 // auth = [X:X:X]????? |
|
336 |
|
337 // First, move past the opening brace |
|
338 authority.Set(authority.Mid(startHostIPv6 + 1)); |
|
339 // auth now = X:X:X]????? |
|
340 |
|
341 // Set the host, and need to remove the closing brace |
|
342 aHost.Set(authority.Left(endIPv6Host -1)); |
|
343 // host = X:X:X |
|
344 |
|
345 // Move past the host |
|
346 authority.Set(authority.Mid(endIPv6Host)); |
|
347 } |
|
348 |
|
349 // Get the port... |
|
350 TInt portEndPos = authority.Length(); |
|
351 if( portEndPos ) |
|
352 { |
|
353 // Store the port - remove leading ':' |
|
354 aPort.Set(authority.Mid(1, portEndPos - 1)); |
|
355 } |
|
356 } |
|
357 return consumed; |
|
358 } |
|
359 |
|
360 /** |
|
361 Templated function to parse a descriptor for a path component.There is always a path component. |
|
362 The ouput argument aPath is set to the path component found. |
|
363 |
|
364 @since 6.0 |
|
365 @param aUri The descriptor containing the uri to be parsed for |
|
366 a path. |
|
367 @param aComponent The output descriptor to refer to the path. |
|
368 @return The number of characters consumed in parsing the path. |
|
369 @pre The output descriptor has been initialized so that the pointer |
|
370 to the associated descriptor buffer is NULL. The input descriptor |
|
371 is set to the start of the path. |
|
372 |
|
373 @post The output descriptor refers to the path component. |
|
374 */ |
|
375 template<class TPtrCType> |
|
376 TInt ParsePath(const TPtrCType& aUri, TPtrCType& aComponent) |
|
377 { |
|
378 // Get descriptor with the path |
|
379 TInt consumed =0; |
|
380 |
|
381 // Path is delimited by '?'. '#' or the end of the string |
|
382 TInt pathEndPos = FindFirstUriDelimiter(aUri, EPathDelimiterSearch); |
|
383 |
|
384 // Check for presence of path |
|
385 if( pathEndPos != KErrNotFound ) |
|
386 { |
|
387 // Got path - store information |
|
388 aComponent.Set(aUri.Left(pathEndPos)); |
|
389 |
|
390 // Set consumed amount to move past path |
|
391 consumed = pathEndPos; |
|
392 } |
|
393 return consumed; |
|
394 } |
|
395 |
|
396 /** |
|
397 Templated function to parse a descriptor for a query component.If a query is found then |
|
398 the output argument aQuery is set to refer to it. |
|
399 |
|
400 @since 6.0 |
|
401 @param aUri The descriptor containing the uri to be parsed for |
|
402 a query. |
|
403 @param aComponent The output descriptor to refer to the query |
|
404 @return The number of characters consumed in parsing the query. |
|
405 @pre The output descriptor has been initialized so that the pointer |
|
406 to the associated descriptor buffer is NULL. The input descriptor is set to |
|
407 the start of the query. |
|
408 @post If a query component exists then the output descriptor refers |
|
409 to it, otherwise the output descriptor is left unchanged. |
|
410 */ |
|
411 template<class TPtrCType> |
|
412 TInt ParseQuery(const TPtrCType& aUri, TPtrCType& aComponent) |
|
413 { |
|
414 // Get descriptor with the query |
|
415 TInt consumed =0; |
|
416 |
|
417 // Query is delimited by '#' or end of the string |
|
418 TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch); |
|
419 |
|
420 // Check for presence of query |
|
421 if( queryEndPos ) |
|
422 { |
|
423 // Got query - store information; need to excluded leading '?' |
|
424 aComponent.Set(aUri.Mid(1, queryEndPos - 1)); |
|
425 |
|
426 // Set consumed amount to move past query |
|
427 consumed = queryEndPos; |
|
428 } |
|
429 return consumed; |
|
430 } |
|
431 |
|
432 /** |
|
433 Templated function to parse a descriptor for a fragment component. If a fragment is found then |
|
434 the output argument aFragment is set to refer to it. |
|
435 |
|
436 @since 6.0 |
|
437 @param aUri The descriptor containing the uri to be parsed for |
|
438 a fragment. |
|
439 @param aComponent The output descriptor to refer to the fragment. |
|
440 @return The number of characters consumed in parsing the fragment. |
|
441 @pre The output descriptor has been initialized so that the pointer |
|
442 to the associated descriptor buffer is NULL. The input descriptor is set to |
|
443 the start of the fragment. |
|
444 @post If a fragment component exists then the output descriptor refers |
|
445 to it, otherwise the output descriptor is left unchanged. |
|
446 */ |
|
447 template<class TPtrCType> |
|
448 TInt ParseFragment(const TPtrCType& aUri, TPtrCType& aComponent) |
|
449 { |
|
450 // Get descriptor with the fragment |
|
451 TInt consumed =0; |
|
452 |
|
453 // Fragment is delimited by end of the string |
|
454 TInt fragmentEndPos = aUri.Length(); |
|
455 |
|
456 // Check for presence of fragment |
|
457 if( fragmentEndPos ) |
|
458 { |
|
459 // Got fragment - store information; need to excluded leading '#' |
|
460 aComponent.Set(aUri.Mid(1, fragmentEndPos - 1)); |
|
461 |
|
462 // Set consumed amount to move past fragment |
|
463 consumed = fragmentEndPos; |
|
464 } |
|
465 return consumed; |
|
466 } |
|
467 |
|
468 /** |
|
469 Templated function to find the position of the first delimiter in the descriptor specified |
|
470 by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are |
|
471 no others. In the case of the scheme delimiter search, the position returned depends on the |
|
472 position of the colon delimiter with respect to the other delimiters for a scheme. |
|
473 |
|
474 @since 6.0 |
|
475 @param aUri The descriptor containing the section of a uri to be searched. |
|
476 @param aSearchFlag The enum specifying the delimiters to search for. |
|
477 @return The position of nearest delimiter to start of the descriptor, where |
|
478 zero is the start (left-most) position. |
|
479 */ |
|
480 template<class TPtrCType> |
|
481 TInt FindFirstUriDelimiter(const TPtrCType& aUri, TDelimiterSearchFlag aSearchFlag) |
|
482 { |
|
483 // Set ultimate delimiter - string length |
|
484 TInt endPos = aUri.Length(); |
|
485 if( aSearchFlag & EHashDelimiterFlag ) |
|
486 { |
|
487 TInt fragmentPos = aUri.Locate(KFragmentDelimiter); |
|
488 if( fragmentPos != KErrNotFound && fragmentPos < endPos ) |
|
489 endPos = fragmentPos; |
|
490 } |
|
491 if( aSearchFlag & EQueryDelimiterFlag ) |
|
492 { |
|
493 TInt queryPos = aUri.Locate(KQueryDelimiter); |
|
494 if( queryPos != KErrNotFound && queryPos < endPos ) |
|
495 endPos = queryPos; |
|
496 } |
|
497 if( aSearchFlag & ESlashDelimiterFlag ) |
|
498 { |
|
499 TInt slashPos = aUri.Locate(KSlashDelimiter); |
|
500 if( slashPos != KErrNotFound && slashPos < endPos ) |
|
501 endPos = slashPos; |
|
502 } |
|
503 if( aSearchFlag & ESemiColonDelimiterFlag ) |
|
504 { |
|
505 TInt semiColonPos = aUri.Locate(KParamDelimiter); |
|
506 if( semiColonPos != KErrNotFound && semiColonPos < endPos ) |
|
507 endPos = semiColonPos; |
|
508 } |
|
509 if( aSearchFlag & EColonDelimiterFlag ) |
|
510 { |
|
511 TInt schemePos = aUri.Locate(KSchemeDelimiter); |
|
512 if( schemePos != KErrNotFound && schemePos < endPos ) |
|
513 { |
|
514 // There is a scheme |
|
515 endPos = schemePos; |
|
516 } |
|
517 else if( aSearchFlag == ESchemeDelimiterSearch ) |
|
518 { |
|
519 // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound |
|
520 endPos = KErrNotFound; |
|
521 } |
|
522 } |
|
523 return endPos; |
|
524 } |