|
1 // Copyright (c) 2007-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 #include "GenericUriParser.h" |
|
17 |
|
18 |
|
19 /** |
|
20 * CGenericUriParser Constructor. |
|
21 */ |
|
22 CGenericUriParser::CGenericUriParser() |
|
23 : CBase() |
|
24 { |
|
25 } |
|
26 |
|
27 /** |
|
28 * CGenericUriParser Static Factory Construction. |
|
29 */ |
|
30 CGenericUriParser* CGenericUriParser::NewL() |
|
31 { |
|
32 CGenericUriParser* self = new (ELeave) CGenericUriParser; |
|
33 CleanupStack::PushL(self); |
|
34 self->ConstructL(); |
|
35 CleanupStack::Pop(self); |
|
36 return self; |
|
37 } |
|
38 |
|
39 /** |
|
40 Second phase of two-phase construction method. |
|
41 |
|
42 @pre First phase of construction is complete. |
|
43 @post The object is fully constructed and initialized. |
|
44 */ |
|
45 void CGenericUriParser::ConstructL() |
|
46 { |
|
47 // Does nothing. |
|
48 } |
|
49 |
|
50 /** |
|
51 * Default Destructor. |
|
52 */ |
|
53 CGenericUriParser::~CGenericUriParser() |
|
54 { |
|
55 } |
|
56 |
|
57 /** |
|
58 Function to parse a descriptor for a scheme component. If a scheme is found |
|
59 then the output argument aScheme is set to refer to it. |
|
60 |
|
61 @param aUri The descriptor containing the uri to be parsed for |
|
62 a scheme. |
|
63 @param aScheme The output descriptor to refer to the scheme |
|
64 @return The number of characters consumed in parsing the scheme. |
|
65 @pre The output descriptor has been initialized so that the pointer |
|
66 to the associated descriptor buffer is NULL. The input descriptor |
|
67 is set to the start of the uri. |
|
68 @post If a scheme component exists then the output descriptor refers |
|
69 to it, otherwise the output descriptor is left unchanged. |
|
70 */ |
|
71 TInt CGenericUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme) |
|
72 { |
|
73 // Get the descriptor and look for scheme delimiter |
|
74 TInt consumed =0; |
|
75 TInt endSchemePos = FindFirstUriDelimiter(aUri, ESchemeDelimiterSearch); |
|
76 |
|
77 if( endSchemePos != KErrNotFound ) |
|
78 { |
|
79 // Got a scheme - store information |
|
80 aScheme.Set(aUri.Left(endSchemePos)); |
|
81 |
|
82 // Set consumed amount move past scheme delimiter |
|
83 consumed = endSchemePos + 1; |
|
84 } |
|
85 return consumed; |
|
86 } |
|
87 |
|
88 /** |
|
89 Function to parse a descriptor for an authority component. If an authority is |
|
90 found then the output arguments aUserinfo, aHost and aPort are set to refer to those parts |
|
91 of the authority component. If an authority component exists then the host part exists. The |
|
92 userinfo and port parts are optional. |
|
93 |
|
94 @param aUri The descriptor containing the uri to be parsed |
|
95 for an authority. |
|
96 @param aUserinfo The output descriptor for the userinfo component. |
|
97 @param aHost The output descriptor for the host component. |
|
98 @param aPort The output descriptor for the port component. |
|
99 @param aUseNetworkDelimiter Whether the scheme uses the network delimeter '//' |
|
100 @return The number of characters consumed in parsing the authority. |
|
101 @pre The output descriptors have been initialized so that the pointer |
|
102 to the their associated descriptor buffers is NULL. The input descriptor |
|
103 is set to the start of the start of the authority component. |
|
104 |
|
105 @post If an authority component exists then the output descriptors refer |
|
106 to the userinfo part (if exists), the host part and the port part (if exists), |
|
107 otherwise the output descriptors are left unchanged. |
|
108 */ |
|
109 TInt CGenericUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter) |
|
110 { |
|
111 // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//' |
|
112 TInt consumed =0; |
|
113 const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0; |
|
114 if( !aUseNetworkDelimiter || |
|
115 (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter )) |
|
116 { |
|
117 // There is an authority |
|
118 TPtrC8 authority( aUri.Mid(prefixLength) ); |
|
119 |
|
120 // Authority delimited by '/', '?', '#' or the end of the string |
|
121 TInt authorityEndPos = FindFirstUriDelimiter(authority, EAuthDelimiterSearch); |
|
122 |
|
123 // Got authority - parse it for its components |
|
124 authority.Set(authority.Left(authorityEndPos)); |
|
125 |
|
126 // Get the userinfo... |
|
127 TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter); |
|
128 if( userinfoEndPos != KErrNotFound ) |
|
129 { |
|
130 // Store the information |
|
131 aUserinfo.Set(authority.Left(userinfoEndPos)); |
|
132 |
|
133 // Move past the userinfo and the delimiter '@' |
|
134 authority.Set(authority.Mid(userinfoEndPos + 1)); |
|
135 } |
|
136 |
|
137 // Authority is also delimited by ';' but this is valid in the userinfo so can only be checked now |
|
138 TInt semicolonPos = FindFirstUriDelimiter(authority, ESemiColonDelimiterFlag); |
|
139 if ( semicolonPos != KErrNotFound ) |
|
140 { |
|
141 authority.Set(authority.Left(semicolonPos)); |
|
142 authorityEndPos = semicolonPos + userinfoEndPos + 1; |
|
143 } |
|
144 |
|
145 // Set consumed amount to move past authority |
|
146 consumed += prefixLength + authorityEndPos; |
|
147 |
|
148 // Check if this is an IPv6 address by looking for the opening '[' |
|
149 TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace); |
|
150 |
|
151 if (startHostIPv6 == KErrNotFound) |
|
152 { |
|
153 // This isn't an IPv6 address..... |
|
154 |
|
155 // Get host... |
|
156 TInt hostEndPos = authority.Locate(KPortDelimiter); |
|
157 |
|
158 // Host also delimited by the end of the authority |
|
159 if( hostEndPos == KErrNotFound ) |
|
160 { |
|
161 hostEndPos = authority.Length(); |
|
162 } |
|
163 |
|
164 // There's always a host, but can be empty - store information |
|
165 aHost.Set(authority.Left(hostEndPos)); |
|
166 |
|
167 // Move past the host |
|
168 authority.Set(authority.Mid(hostEndPos)); |
|
169 } |
|
170 else |
|
171 { |
|
172 // This is an IPv6 address, so it MUST have the closing brace too.... |
|
173 TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace); |
|
174 |
|
175 // Return an error if the closing IPv6 delimiter isn't there. |
|
176 // or Host is empty |
|
177 if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1) |
|
178 { |
|
179 return KUriUtilsErrInvalidUri; |
|
180 } |
|
181 |
|
182 // It's an ipv6 address, with an opening and closing brace. So now just extract it |
|
183 // auth = [X:X:X]????? |
|
184 |
|
185 // First, move past the opening brace |
|
186 authority.Set(authority.Mid(startHostIPv6 + 1)); |
|
187 // auth now = X:X:X]????? |
|
188 |
|
189 // Set the host, and need to remove the closing brace |
|
190 aHost.Set(authority.Left(endIPv6Host - 1)); |
|
191 // host = X:X:X |
|
192 |
|
193 // Move past the host |
|
194 authority.Set(authority.Mid(endIPv6Host)); |
|
195 } |
|
196 |
|
197 // Get the port... |
|
198 TInt portEndPos = authority.Length(); |
|
199 if( portEndPos ) |
|
200 { |
|
201 // Store the port - remove leading ':' |
|
202 aPort.Set(authority.Mid(1, portEndPos - 1)); |
|
203 } |
|
204 } |
|
205 return consumed; |
|
206 } |
|
207 |
|
208 /** |
|
209 Function to parse a descriptor for a path/parameter component.There is always a path component. |
|
210 The ouput argument aPath is set to the path/parameter component found. |
|
211 |
|
212 @param aUri The descriptor containing the uri to be parsed for a path. |
|
213 @param aComponent The output descriptor to refer to the path. |
|
214 @return The number of characters consumed in parsing the path. |
|
215 @pre The output descriptor has been initialized so that the pointer |
|
216 to the associated descriptor buffer is NULL. The input descriptor |
|
217 is set to the start of the path. |
|
218 |
|
219 @post The output descriptor refers to the path component. |
|
220 */ |
|
221 TInt CGenericUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent) |
|
222 { |
|
223 // Get descriptor with the path |
|
224 TInt consumed =0; |
|
225 |
|
226 // Path is delimited by '?'. '#' or the end of the string |
|
227 TInt pathEndPos = FindFirstUriDelimiter(aUri, EPathDelimiterSearch); |
|
228 |
|
229 // Check for presence of path |
|
230 if( pathEndPos != KErrNotFound ) |
|
231 { |
|
232 // Got path - store information |
|
233 aComponent.Set(aUri.Left(pathEndPos)); |
|
234 |
|
235 // Set consumed amount to move past path |
|
236 consumed = pathEndPos; |
|
237 } |
|
238 return consumed; |
|
239 } |
|
240 |
|
241 /** |
|
242 Function to parse a descriptor for a query/header component.If a query is found then |
|
243 the output argument aQuery is set to refer to it. |
|
244 |
|
245 @param aUri The descriptor containing the uri to be parsed for |
|
246 a query. |
|
247 @param aComponent The output descriptor to refer to the query |
|
248 @return The number of characters consumed in parsing the query. |
|
249 @pre The output descriptor has been initialized so that the pointer |
|
250 to the associated descriptor buffer is NULL. The input descriptor is set to |
|
251 the start of the query. |
|
252 @post If a query component exists then the output descriptor refers |
|
253 to it, otherwise the output descriptor is left unchanged. |
|
254 */ |
|
255 TInt CGenericUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent) |
|
256 { |
|
257 // Get descriptor with the query |
|
258 TInt consumed =0; |
|
259 |
|
260 // Query is delimited by '#' or end of the string |
|
261 TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch); |
|
262 |
|
263 // Check for presence of query |
|
264 if( queryEndPos ) |
|
265 { |
|
266 // Got query - store information; need to excluded leading '?' |
|
267 aComponent.Set(aUri.Mid(1, queryEndPos - 1)); |
|
268 |
|
269 // Set consumed amount to move past query |
|
270 consumed = queryEndPos; |
|
271 } |
|
272 return consumed; |
|
273 } |
|
274 |
|
275 /** |
|
276 Function to parse a descriptor for a fragment component. If a fragment is found then |
|
277 the output argument aFragment is set to refer to it. |
|
278 |
|
279 @param aUri The descriptor containing the uri to be parsed for a fragment. |
|
280 @param aComponent The output descriptor to refer to the fragment. |
|
281 @return The number of characters consumed in parsing the fragment. |
|
282 @pre The output descriptor has been initialized so that the pointer |
|
283 to the associated descriptor buffer is NULL. The input descriptor is set to |
|
284 the start of the fragment. |
|
285 @post If a fragment component exists then the output descriptor refers |
|
286 to it, otherwise the output descriptor is left unchanged. |
|
287 */ |
|
288 TInt CGenericUriParser::ParseFragment(const TPtrC8& aUri, TPtrC8& aComponent) |
|
289 { |
|
290 // Get descriptor with the fragment |
|
291 TInt consumed =0; |
|
292 |
|
293 // Fragment is delimited by end of the string |
|
294 TInt fragmentEndPos = aUri.Length(); |
|
295 |
|
296 // Check for presence of fragment |
|
297 if( fragmentEndPos ) |
|
298 { |
|
299 // Got fragment - store information; need to excluded leading '#' |
|
300 aComponent.Set(aUri.Mid(1, fragmentEndPos - 1)); |
|
301 |
|
302 // Set consumed amount to move past fragment |
|
303 consumed = fragmentEndPos; |
|
304 } |
|
305 return consumed; |
|
306 } |
|
307 |
|
308 /** |
|
309 Function to find the position of the first delimiter in the descriptor specified |
|
310 by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are |
|
311 no others. In the case of the scheme delimiter search, the position returned depends on the |
|
312 position of the colon delimiter with respect to the other delimiters for a scheme. |
|
313 |
|
314 @param aUri The descriptor containing the section of a uri to be searched. |
|
315 @param aSearchFlag The enum specifying the delimiters to search for. |
|
316 @return The position of nearest delimiter to start of the descriptor, where |
|
317 zero is the start (left-most) position. |
|
318 */ |
|
319 TInt CGenericUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TDelimiterSearchFlag aSearchFlag) |
|
320 { |
|
321 // Set ultimate delimiter - string length |
|
322 TInt endPos = aUri.Length(); |
|
323 if( aSearchFlag & EHashDelimiterFlag ) |
|
324 { |
|
325 TInt fragmentPos = aUri.Locate(KFragmentDelimiter); |
|
326 if( fragmentPos != KErrNotFound && fragmentPos < endPos ) |
|
327 { |
|
328 endPos = fragmentPos; |
|
329 } |
|
330 } |
|
331 if( aSearchFlag & EQueryDelimiterFlag ) |
|
332 { |
|
333 TInt queryPos = aUri.Locate(KQueryDelimiter); |
|
334 if( queryPos != KErrNotFound && queryPos < endPos ) |
|
335 { |
|
336 endPos = queryPos; |
|
337 } |
|
338 } |
|
339 if( aSearchFlag & ESlashDelimiterFlag ) |
|
340 { |
|
341 TInt slashPos = aUri.Locate(KSlashDelimiter); |
|
342 if( slashPos != KErrNotFound && slashPos < endPos ) |
|
343 { |
|
344 endPos = slashPos; |
|
345 } |
|
346 } |
|
347 if( aSearchFlag & ESemiColonDelimiterFlag ) |
|
348 { |
|
349 TInt semiColonPos = aUri.Locate(KParamDelimiter); |
|
350 if( semiColonPos != KErrNotFound && semiColonPos < endPos ) |
|
351 { |
|
352 endPos = semiColonPos; |
|
353 } |
|
354 } |
|
355 if( aSearchFlag & EColonDelimiterFlag ) |
|
356 { |
|
357 TInt schemePos = aUri.Locate(KSchemeDelimiter); |
|
358 if( schemePos != KErrNotFound && schemePos < endPos ) |
|
359 { |
|
360 // There is a scheme |
|
361 endPos = schemePos; |
|
362 } |
|
363 else if( aSearchFlag == ESchemeDelimiterSearch ) |
|
364 { |
|
365 // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound |
|
366 endPos = KErrNotFound; |
|
367 } |
|
368 } |
|
369 return endPos; |
|
370 } |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |