First public contribution.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "SipUriParser.h"
19 * CSIPUriParser Constructor.
21 CSIPUriParser::CSIPUriParser()
27 * CSIPUriParser Static Factory Construction.
29 CSIPUriParser* CSIPUriParser::NewL()
31 CSIPUriParser* self = new (ELeave) CSIPUriParser;
32 CleanupStack::PushL(self);
34 CleanupStack::Pop(self);
39 Second phase of two-phase construction method.
41 @pre First phase of construction is complete.
42 @post The object is fully constructed and initialized.
44 void CSIPUriParser::ConstructL()
52 CSIPUriParser::~CSIPUriParser()
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.
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.
69 TInt CSIPUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme)
71 // Get the descriptor and look for scheme delimiter
73 TInt endSchemePos = FindFirstUriDelimiter(aUri, ESipSchemeDelimiterSearch);
75 if( endSchemePos != KErrNotFound )
77 // Got a scheme - store information
78 aScheme.Set(aUri.Left(endSchemePos));
80 // Set consumed amount move past scheme delimiter
81 consumed = endSchemePos + 1;
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.
92 @param aUri The descriptor containing the uri to be parsed
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.
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.
108 TInt CSIPUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter)
110 // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//'
112 const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
113 if( !aUseNetworkDelimiter ||
114 (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
116 // There is an authority
117 TPtrC8 authority( aUri.Mid(prefixLength) );
119 // Authority delimited by ';', '?' or the end of the string
120 TInt authorityEndPos = FindFirstUriDelimiter(authority, ESipAuthDelimiterSearch);
122 // Got authority - parse it for its components
123 authority.Set(authority.Left(authorityEndPos));
125 // Get the userinfo...
126 TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
127 if( userinfoEndPos != KErrNotFound )
129 // Store the information
130 aUserinfo.Set(authority.Left(userinfoEndPos));
132 // Move past the userinfo and the delimiter '@'
133 authority.Set(authority.Mid(userinfoEndPos + 1));
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 )
140 authority.Set(authority.Left(semicolonPos));
141 authorityEndPos = semicolonPos + userinfoEndPos + 1;
144 // Set consumed amount to move past authority
145 consumed += prefixLength + authorityEndPos;
147 // Check if this is an IPv6 address by looking for the opening '['
148 TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
150 if (startHostIPv6 == KErrNotFound)
152 // This isn't an IPv6 address.....
155 TInt hostEndPos = authority.Locate(KPortDelimiter);
157 // Host also delimited by the end of the authority
158 if( hostEndPos == KErrNotFound )
160 hostEndPos = authority.Length();
163 // There's always a host, but can be empty - store information
164 aHost.Set(authority.Left(hostEndPos));
166 // Move past the host
167 authority.Set(authority.Mid(hostEndPos));
171 // First, move past the opening brace
172 authority.Set(authority.Mid(startHostIPv6 + 1));
173 // auth now = X:X:X]?????
175 // This is an IPv6 address, so it MUST have the closing brace too....
176 TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
178 // Return an error if the closing IPv6 delimiter isn't there.
180 if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1)
182 return KUriUtilsErrInvalidUri;
185 // It's an ipv6 address, with an opening and closing brace. So now just extract it
186 // auth = [X:X:X]?????
189 // Set the host, and need to remove the closing brace
190 aHost.Set(authority.Left(endIPv6Host));
193 // Move past the host
194 authority.Set(authority.Mid(endIPv6Host + 1 ));
198 TInt portEndPos = authority.Length();
201 // Store the port - remove leading ':'
202 aPort.Set(authority.Mid(1, portEndPos - 1));
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.
212 @param aUri The descriptor containing the uri to be parsed for a path/parameter.
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.
219 @post The output descriptor refers to the path component.
221 TInt CSIPUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent)
223 // Get descriptor with the path
226 // Path is delimited by '?' or the end of the string
227 TInt pathEndPos = FindFirstUriDelimiter(aUri, ESipPathDelimiterSearch);
229 // Check for presence of path
230 if( pathEndPos != KErrNotFound )
232 // Got path - store information
233 aComponent.Set(aUri.Left(pathEndPos));
235 // Set consumed amount to move past path
236 consumed = pathEndPos;
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.
245 @param aUri The descriptor containing the uri to be parsed for a query/Header.
246 @param aComponent The output descriptor to refer to the query
247 @return The number of characters consumed in parsing the query.
248 @pre The output descriptor has been initialized so that the pointer
249 to the associated descriptor buffer is NULL. The input descriptor is set to
250 the start of the query.
251 @post If a query component exists then the output descriptor refers
252 to it, otherwise the output descriptor is left unchanged.
254 TInt CSIPUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent)
256 // Get descriptor with the query
259 // Query/Header is delimited by end of the string
260 TInt queryEndPos = aUri.Length();
262 // Check for presence of query
265 // Got query - store information; need to excluded leading '?'
266 aComponent.Set(aUri.Mid(1, queryEndPos - 1));
268 // Set consumed amount to move past query
269 consumed = queryEndPos;
275 Function to parse a descriptor for a fragment component.
276 In Sip Uris no Fragment Component it contains. This is an dummy implementation.
278 @param aUri not used.
279 @param aComponent not used.
280 @return returns zero.
282 TInt CSIPUriParser::ParseFragment(const TPtrC8& /*aUri*/, TPtrC8& /* aComponent*/)
284 // Sip Uri Does not conatin Fragment
289 Function to find the position of the first delimiter in the descriptor specified
290 by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are
291 no others. In the case of the scheme delimiter search, the position returned depends on the
292 position of the colon delimiter with respect to the other delimiters for a scheme.
294 @param aUri The descriptor containing the section of a uri to be searched.
295 @param aSearchFlag The enum specifying the delimiters to search for.
296 @return The position of nearest delimiter to start of the descriptor, where
297 zero is the start (left-most) position.
299 TInt CSIPUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TSipDelimiterSearchFlag aSearchFlag)
301 // Set ultimate delimiter - string length
302 TInt endPos = aUri.Length();
304 if( aSearchFlag & ESipQueryDelimiterFlag )
306 TInt queryPos = aUri.Locate(KQueryDelimiter);
307 if( queryPos != KErrNotFound && queryPos < endPos )
309 TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
310 //QueryDelimiter may be in Userinfo
311 if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > queryPos )
313 //Find QueryDelimiter after Userinfo
314 queryPos = aUri.Mid(userinfoPos).Locate(KQueryDelimiter);
315 if (queryPos != KErrNotFound && queryPos < endPos )
317 queryPos += userinfoPos;
320 if(queryPos != KErrNotFound)
327 if( aSearchFlag & ESipSemiColonDelimiterFlag )
329 TInt semiColonPos = aUri.Locate(KParamDelimiter);
330 if( semiColonPos != KErrNotFound && semiColonPos < endPos )
332 TInt userinfoPos = aUri.Locate(KUserinfoDelimiter);
333 //ParamDelimiter may be in Userinfo
334 if(userinfoPos != KErrNotFound && userinfoPos < endPos && userinfoPos > semiColonPos )
336 //Find ParamDelimiter after Userinfo
337 semiColonPos = aUri.Mid(userinfoPos).Locate(KParamDelimiter);
338 if (semiColonPos != KErrNotFound && semiColonPos < endPos )
340 semiColonPos += userinfoPos;
343 if(semiColonPos != KErrNotFound)
345 endPos = semiColonPos;
349 if( aSearchFlag & ESipColonDelimiterFlag )
351 TInt schemePos = aUri.Locate(KSchemeDelimiter);
352 if( schemePos != KErrNotFound && schemePos < endPos )
357 else if( aSearchFlag == ESipSchemeDelimiterSearch )
359 // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
360 endPos = KErrNotFound;