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 "GenericUriParser.h"
20 * CGenericUriParser Constructor.
22 CGenericUriParser::CGenericUriParser()
28 * CGenericUriParser Static Factory Construction.
30 CGenericUriParser* CGenericUriParser::NewL()
32 CGenericUriParser* self = new (ELeave) CGenericUriParser;
33 CleanupStack::PushL(self);
35 CleanupStack::Pop(self);
40 Second phase of two-phase construction method.
42 @pre First phase of construction is complete.
43 @post The object is fully constructed and initialized.
45 void CGenericUriParser::ConstructL()
53 CGenericUriParser::~CGenericUriParser()
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.
61 @param aUri The descriptor containing the uri to be parsed for
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.
71 TInt CGenericUriParser::ParseScheme(const TPtrC8& aUri, TPtrC8& aScheme)
73 // Get the descriptor and look for scheme delimiter
75 TInt endSchemePos = FindFirstUriDelimiter(aUri, ESchemeDelimiterSearch);
77 if( endSchemePos != KErrNotFound )
79 // Got a scheme - store information
80 aScheme.Set(aUri.Left(endSchemePos));
82 // Set consumed amount move past scheme delimiter
83 consumed = endSchemePos + 1;
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.
94 @param aUri The descriptor containing the uri to be parsed
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.
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.
109 TInt CGenericUriParser::ParseAuthority(const TPtrC8& aUri, TPtrC8& aUserinfo, TPtrC8& aHost, TPtrC8& aPort, TBool aUseNetworkDelimiter)
111 // Get uri descriptor and see if authority exists - if aUseNetworkDelimiter is true it has to start with '//'
113 const TInt prefixLength = aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength : 0;
114 if( !aUseNetworkDelimiter ||
115 (aUri.Length() >= prefixLength && aUri[0] == KSlashDelimiter && aUri[1] == KSlashDelimiter ))
117 // There is an authority
118 TPtrC8 authority( aUri.Mid(prefixLength) );
120 // Authority delimited by '/', '?', '#' or the end of the string
121 TInt authorityEndPos = FindFirstUriDelimiter(authority, EAuthDelimiterSearch);
123 // Got authority - parse it for its components
124 authority.Set(authority.Left(authorityEndPos));
126 // Get the userinfo...
127 TInt userinfoEndPos = authority.Locate(KUserinfoDelimiter);
128 if( userinfoEndPos != KErrNotFound )
130 // Store the information
131 aUserinfo.Set(authority.Left(userinfoEndPos));
133 // Move past the userinfo and the delimiter '@'
134 authority.Set(authority.Mid(userinfoEndPos + 1));
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 )
141 authority.Set(authority.Left(semicolonPos));
142 authorityEndPos = semicolonPos + userinfoEndPos + 1;
145 // Set consumed amount to move past authority
146 consumed += prefixLength + authorityEndPos;
148 // Check if this is an IPv6 address by looking for the opening '['
149 TInt startHostIPv6 = authority.Locate(KIPv6UriOpenBrace);
151 if (startHostIPv6 == KErrNotFound)
153 // This isn't an IPv6 address.....
156 TInt hostEndPos = authority.Locate(KPortDelimiter);
158 // Host also delimited by the end of the authority
159 if( hostEndPos == KErrNotFound )
161 hostEndPos = authority.Length();
164 // There's always a host, but can be empty - store information
165 aHost.Set(authority.Left(hostEndPos));
167 // Move past the host
168 authority.Set(authority.Mid(hostEndPos));
173 // First, move past the opening brace
174 authority.Set(authority.Mid(startHostIPv6 + 1));
175 // auth now = X:X:X]?????
177 // This is an IPv6 address, so it MUST have the closing brace too....
178 TInt endIPv6Host = authority.Locate(KIPv6UriCloseBrace);
180 // Return an error if the closing IPv6 delimiter isn't there.
182 if (endIPv6Host == KErrNotFound || endIPv6Host == startHostIPv6 + 1)
184 return KUriUtilsErrInvalidUri;
187 // It's an ipv6 address, with an opening and closing brace. So now just extract it
188 // auth = [X:X:X]?????
191 // Set the host, and need to remove the closing brace
192 aHost.Set(authority.Left(endIPv6Host));
195 // Move past the host
196 authority.Set(authority.Mid(endIPv6Host + 1));
200 TInt portEndPos = authority.Length();
203 // Store the port - remove leading ':'
204 aPort.Set(authority.Mid(1, portEndPos - 1));
211 Function to parse a descriptor for a path/parameter component.There is always a path component.
212 The ouput argument aPath is set to the path/parameter component found.
214 @param aUri The descriptor containing the uri to be parsed for a path.
215 @param aComponent The output descriptor to refer to the path.
216 @return The number of characters consumed in parsing the path.
217 @pre The output descriptor has been initialized so that the pointer
218 to the associated descriptor buffer is NULL. The input descriptor
219 is set to the start of the path.
221 @post The output descriptor refers to the path component.
223 TInt CGenericUriParser::ParsePath(const TPtrC8& aUri, TPtrC8& aComponent)
225 // Get descriptor with the path
228 // Path is delimited by '?'. '#' or the end of the string
229 TInt pathEndPos = FindFirstUriDelimiter(aUri, EPathDelimiterSearch);
231 // Check for presence of path
232 if( pathEndPos != KErrNotFound )
234 // Got path - store information
235 aComponent.Set(aUri.Left(pathEndPos));
237 // Set consumed amount to move past path
238 consumed = pathEndPos;
244 Function to parse a descriptor for a query/header component.If a query is found then
245 the output argument aQuery is set to refer to it.
247 @param aUri The descriptor containing the uri to be parsed for
249 @param aComponent The output descriptor to refer to the query
250 @return The number of characters consumed in parsing the query.
251 @pre The output descriptor has been initialized so that the pointer
252 to the associated descriptor buffer is NULL. The input descriptor is set to
253 the start of the query.
254 @post If a query component exists then the output descriptor refers
255 to it, otherwise the output descriptor is left unchanged.
257 TInt CGenericUriParser::ParseQuery(const TPtrC8& aUri, TPtrC8& aComponent)
259 // Get descriptor with the query
262 // Query is delimited by '#' or end of the string
263 TInt queryEndPos = FindFirstUriDelimiter(aUri, EQueryDelimiterSearch);
265 // Check for presence of query
268 // Got query - store information; need to excluded leading '?'
269 aComponent.Set(aUri.Mid(1, queryEndPos - 1));
271 // Set consumed amount to move past query
272 consumed = queryEndPos;
278 Function to parse a descriptor for a fragment component. If a fragment is found then
279 the output argument aFragment is set to refer to it.
281 @param aUri The descriptor containing the uri to be parsed for a fragment.
282 @param aComponent The output descriptor to refer to the fragment.
283 @return The number of characters consumed in parsing the fragment.
284 @pre The output descriptor has been initialized so that the pointer
285 to the associated descriptor buffer is NULL. The input descriptor is set to
286 the start of the fragment.
287 @post If a fragment component exists then the output descriptor refers
288 to it, otherwise the output descriptor is left unchanged.
290 TInt CGenericUriParser::ParseFragment(const TPtrC8& aUri, TPtrC8& aComponent)
292 // Get descriptor with the fragment
295 // Fragment is delimited by end of the string
296 TInt fragmentEndPos = aUri.Length();
298 // Check for presence of fragment
301 // Got fragment - store information; need to excluded leading '#'
302 aComponent.Set(aUri.Mid(1, fragmentEndPos - 1));
304 // Set consumed amount to move past fragment
305 consumed = fragmentEndPos;
311 Function to find the position of the first delimiter in the descriptor specified
312 by the delimiter flags. Note that the end of the descriptor is also a delimiter if there are
313 no others. In the case of the scheme delimiter search, the position returned depends on the
314 position of the colon delimiter with respect to the other delimiters for a scheme.
316 @param aUri The descriptor containing the section of a uri to be searched.
317 @param aSearchFlag The enum specifying the delimiters to search for.
318 @return The position of nearest delimiter to start of the descriptor, where
319 zero is the start (left-most) position.
321 TInt CGenericUriParser::FindFirstUriDelimiter(const TPtrC8& aUri, TDelimiterSearchFlag aSearchFlag)
323 // Set ultimate delimiter - string length
324 TInt endPos = aUri.Length();
325 if( aSearchFlag & EHashDelimiterFlag )
327 TInt fragmentPos = aUri.Locate(KFragmentDelimiter);
328 if( fragmentPos != KErrNotFound && fragmentPos < endPos )
330 endPos = fragmentPos;
333 if( aSearchFlag & EQueryDelimiterFlag )
335 TInt queryPos = aUri.Locate(KQueryDelimiter);
336 if( queryPos != KErrNotFound && queryPos < endPos )
341 if( aSearchFlag & ESlashDelimiterFlag )
343 TInt slashPos = aUri.Locate(KSlashDelimiter);
344 if( slashPos != KErrNotFound && slashPos < endPos )
349 if( aSearchFlag & ESemiColonDelimiterFlag )
351 TInt semiColonPos = aUri.Locate(KParamDelimiter);
352 if( semiColonPos != KErrNotFound && semiColonPos < endPos )
354 endPos = semiColonPos;
357 if( aSearchFlag & EColonDelimiterFlag )
359 TInt schemePos = aUri.Locate(KSchemeDelimiter);
360 if( schemePos != KErrNotFound && schemePos < endPos )
365 else if( aSearchFlag == ESchemeDelimiterSearch )
367 // Ok different if looking for scheme delimiter - no scheme, return KErrNotFound
368 endPos = KErrNotFound;