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