os/ossrv/genericservices/httputils/UriParser/CUri.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericservices/httputils/UriParser/CUri.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1462 @@
     1.4 +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include <escapeutils.h>
    1.20 +#include <uri8.h>
    1.21 +#include <uri16.h>
    1.22 +#include <delimitedpath8.h>
    1.23 +#include <delimitedpath16.h>
    1.24 +#include <uriutilscommon.h>
    1.25 +#include <uriutils.h>
    1.26 +
    1.27 +#include "UriUtilsInternal.h"
    1.28 +#include "TUriCInternal.h"
    1.29 +#include "CUriInternal.h"
    1.30 +
    1.31 +// Panic category
    1.32 +//
    1.33 +#ifdef _DEBUG
    1.34 +	_LIT(KUriPanicCategory,"URI-CURI"); 
    1.35 +#endif
    1.36 +
    1.37 +// Constants
    1.38 +//
    1.39 +_LIT(KFileUriPanicCategory,"FILEURI-CURI");
    1.40 +
    1.41 +
    1.42 +
    1.43 +
    1.44 +//
    1.45 +//
    1.46 +// Implementation of CUri8
    1.47 +//
    1.48 +//
    1.49 +
    1.50 +/**
    1.51 +	Static factory constructor. Uses two phase construction and leaves nothing on the 
    1.52 +	CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
    1.53 +	
    1.54 +	@since			6.0
    1.55 +	@param			aUri	A reference to a parsed uri object.
    1.56 +	@return			A pointer to the newly created CUri8 object. 
    1.57 +	@post			A fully constructed and initialized CUri8 object.
    1.58 + */
    1.59 +EXPORT_C CUri8* CUri8::NewL(const TUriC8& aUri)
    1.60 +	{
    1.61 +	CUri8* self = CUri8::NewLC(aUri);
    1.62 +	CleanupStack::Pop(self);
    1.63 +	return self;
    1.64 +	}
    1.65 +
    1.66 +/**	
    1.67 +	Static factory constructor. Uses two phase construction and leaves a pointer to 
    1.68 +	created object on the CleanupStack. Creates a uri object which is a copy of the 
    1.69 +	input parameter aUri.
    1.70 +	
    1.71 +	@since			6.0
    1.72 +	@param			aUri	A reference to a parsed uri object.
    1.73 +	@return			A pointer to the newly created CUri8 object. 
    1.74 +	@post			A fully constructed and initialized CUri8 object.
    1.75 + */
    1.76 +EXPORT_C CUri8* CUri8::NewLC(const TUriC8& aUri)
    1.77 +	{
    1.78 +	CUri8* self = new (ELeave) CUri8(aUri);
    1.79 +	CleanupStack::PushL(self);
    1.80 +	self->ConstructL();
    1.81 +	return self;
    1.82 +	}
    1.83 +	
    1.84 +/**	
    1.85 +	Static factory constructor. Uses two phase construction and leaves nothing on the 
    1.86 +	CleanupStack. Creates a uri object which is empty.
    1.87 +	
    1.88 +	@since			6.0
    1.89 +	@return			A pointer to the newly created CUri8 object. 
    1.90 +	@post			A fully constructed and initialized CUri8 object.
    1.91 + */
    1.92 +EXPORT_C CUri8* CUri8::NewL()
    1.93 +	{
    1.94 +	CUri8* self = CUri8::NewLC();
    1.95 +	CleanupStack::Pop(self);
    1.96 +	return self;
    1.97 +	}
    1.98 +
    1.99 +/**
   1.100 +	Static factory constructor. Uses two phase construction and leaves a pointer to created 
   1.101 +	object on the CleanupStack. Creates a uri object which is empty.
   1.102 +	
   1.103 +	@since			6.0
   1.104 +	@return			A pointer to the newly created CUri8 object. 
   1.105 +	@post			A fully constructed and initialized CUri8 object.
   1.106 + */
   1.107 +EXPORT_C CUri8* CUri8::NewLC()
   1.108 +	{
   1.109 +	CUri8* self = new (ELeave) CUri8(TUriC8());
   1.110 +	CleanupStack::PushL(self);
   1.111 +	self->ConstructL();
   1.112 +	return self;
   1.113 +	}
   1.114 +
   1.115 +/**	
   1.116 +	Static factory constructor. This creates a CUri8 object that is an absolute uri resulting 
   1.117 +	from a reference uri being resolved against a base uri.
   1.118 +	
   1.119 +	@warning		Ownership of created CUri8 object is transferred to the caller.
   1.120 +	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
   1.121 +	@since			6.0
   1.122 +	@param			aBaseUri	A referece to the parsed base uri.
   1.123 +	@param			aRefUri		A referece to the parsed reference uri.
   1.124 +	@return			A pointer to the newly created CUri8 object.
   1.125 +	@pre 			The base uri must have an absolute or empty path, otherwise will leave
   1.126 +	with KUriErrBadBasePath.
   1.127 +	@post			A fully constructed and initialized CUri8 object.
   1.128 + */
   1.129 +EXPORT_C CUri8* CUri8::ResolveL(const TUriC8& aBaseUri, const TUriC8& aRefUri)
   1.130 +	{
   1.131 +	// Check for a base Uri
   1.132 +	if( aBaseUri.UriDes().Compare(KNullDesC8) == 0 )
   1.133 +		{
   1.134 +		// Empty base Uri - resolved Uri is the reference Uri
   1.135 +		return NewL(aRefUri);
   1.136 +		}
   1.137 +	// See if ref has scheme and it is the same as base Uri
   1.138 +	if( aRefUri.IsPresent(EUriScheme) && (aRefUri.Compare(aBaseUri, EUriScheme) != 0) )
   1.139 +		{
   1.140 +		// Ref has a scheme different to base Uri's - it is an absolute Uri
   1.141 +		return NewL(aRefUri);
   1.142 +		}
   1.143 +	// Check for presence of components
   1.144 +	TBool useBaseQuery = EFalse;
   1.145 +	HBufC8* resolvedPath = FormResolvedPathLC<HBufC8>(aBaseUri, aRefUri, useBaseQuery);
   1.146 +
   1.147 +	//Removes dot segemnts in Resolved uri as specified in RFC3986 section 5.2.
   1.148 +	RemoveExtraneousDotSegmentsL(resolvedPath);
   1.149 +	
   1.150 +	// Put the Uri together
   1.151 +	TUriC8 uri;
   1.152 +	FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
   1.153 +
   1.154 +	// Create the resolved Uri and cleanup
   1.155 +	CUri8* resolvedUri = NewL(uri);
   1.156 +	CleanupStack::PopAndDestroy(resolvedPath);
   1.157 +
   1.158 +	return resolvedUri;
   1.159 +	}
   1.160 +
   1.161 +/**	
   1.162 +	Destructor.
   1.163 +	
   1.164 +	@since			6.0
   1.165 + */
   1.166 +EXPORT_C CUri8::~CUri8()
   1.167 +	{
   1.168 +	delete iUriBuf;
   1.169 +	}
   1.170 +
   1.171 +/**	
   1.172 +	Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC8.
   1.173 +	
   1.174 +	@since			6.0
   1.175 +	@return			A const reference to the parsed uri object.
   1.176 + */
   1.177 +EXPORT_C const TUriC8& CUri8::Uri() const
   1.178 +	{
   1.179 +	return iUri;
   1.180 +	}
   1.181 +
   1.182 +/**	
   1.183 +	Intended Usage	:	Sets the specified component in the uri. The component is set to the value 
   1.184 +	given in the argument aData. If the specified component already exists  then it is replaced 
   1.185 +	with the new value.
   1.186 +	
   1.187 +	@warning		The userinfo and port components can only be set if the host component
   1.188 +	is present. Setting these components without a host component present will have no 
   1.189 +	effect on the uri.
   1.190 +	@since			6.0
   1.191 +	@param			aData		A descriptor pointer to the new value for the uri component.
   1.192 +	@param			aComponent	An enum specifying the component to be set.
   1.193 +	@pre 			Object is fully constructed.
   1.194 +	@post			The uri has the specified component set to the new value.
   1.195 +	@Leave          KErrArgument  If aComponent goes out of range.
   1.196 + */
   1.197 +EXPORT_C void CUri8::SetComponentL(const TDesC8& aData, TUriComponent aComponent)
   1.198 +	{
   1.199 +	// Update the appropriate component table entry
   1.200 +	iUri.iComponent[aComponent].Set(aData);
   1.201 +
   1.202 +	// Copy to the buffer by forming the uri
   1.203 +	FormUriL();
   1.204 +	}
   1.205 +
   1.206 +/**	
   1.207 +	Removes the specified component from the uri. If the component does not exist then this function 
   1.208 +	does nothing.
   1.209 +	
   1.210 +	@warning		If host is removed, then userinfo and port components will also
   1.211 +	be removed.
   1.212 +	@since			6.0
   1.213 +	@param			aComponent	An enum specifying the component to be removed.
   1.214 +	@pre 			Object is fully constructed.
   1.215 +	@post			The uri is updated to exclude the specified component.
   1.216 + */
   1.217 +EXPORT_C void CUri8::RemoveComponentL(TUriComponent aComponent)
   1.218 +	{
   1.219 +	if( iUri.IsPresent(aComponent) )
   1.220 +		{
   1.221 +		// Remove the component - set pointer to NULL and length to zero
   1.222 +		iUri.iComponent[aComponent].Set(NULL,0);
   1.223 +
   1.224 +		// Re-form buffer and component table
   1.225 +		FormUriL();
   1.226 +		}
   1.227 +	}
   1.228 +
   1.229 +/**	
   1.230 +	Constructor. First phase of two-phase construction method. Does	non-allocating construction.
   1.231 +	
   1.232 +	@since			6.0
   1.233 +	@param			aUri	The parsed uri component information from which to create 
   1.234 +	the uri.
   1.235 +*/
   1.236 +CUri8::CUri8(const TUriC8& aUri)
   1.237 +: CBase(), iUri(aUri)
   1.238 +	{
   1.239 +	}
   1.240 +
   1.241 +/**	
   1.242 +	Second phase of two-phase construction method. Does any allocations required to fully construct 
   1.243 +	the object.
   1.244 +	
   1.245 +	@since			6.0
   1.246 +	@pre 			First phase of construction is complete.
   1.247 +	@post			The object is fully constructed and initialized.
   1.248 + */
   1.249 +void CUri8::ConstructL()
   1.250 +	{
   1.251 +	// Create the HBufC
   1.252 +	FormUriL();
   1.253 +	}
   1.254 +
   1.255 +/**	
   1.256 +	Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri 
   1.257 +	is changed to refer to the copy.
   1.258 +	
   1.259 +	@since			6.0
   1.260 +	@pre 			The parsed uri information is set.
   1.261 +	@post			The uri buffer is updated with the parsed uri information.
   1.262 + */
   1.263 +void CUri8::FormUriL()
   1.264 +	{
   1.265 +	TBool isIPv6Host;
   1.266 +
   1.267 +	// Calculate length of of the Uri
   1.268 +	TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
   1.269 +
   1.270 +	// Create a temporary buffer and descriptor pointer to it
   1.271 +	HBufC8* buf = HBufC8::NewL(length);
   1.272 +	TPtr8 uri = buf->Des();
   1.273 +
   1.274 +	// Create the uri, updating the internal uri object
   1.275 +	DoFormUri(uri, iUri.iComponent, isIPv6Host);
   1.276 +
   1.277 +	// Update the internal buffer and descriptor pointer
   1.278 +	delete iUriBuf;
   1.279 +	iUriBuf = buf;
   1.280 +	iUri.iUriDes.Set(iUriBuf->Des());
   1.281 +	}
   1.282 +
   1.283 +//
   1.284 +//
   1.285 +// Implementation of CUri16
   1.286 +//
   1.287 +//
   1.288 +
   1.289 +/**	
   1.290 +	Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack. 
   1.291 +	Creates a uri object which is a copy of the input parameter aUri.
   1.292 +	
   1.293 +	@deprecated Deprecated in 9.1
   1.294 +	@since			6.0
   1.295 +	@param			aUri	A reference to a parsed uri object.
   1.296 +	@return			A pointer to the newly created CUri16 object. 
   1.297 +	@post			A fully constructed and initialized CUri16 object.
   1.298 + */
   1.299 +EXPORT_C CUri16* CUri16::NewL(const TUriC16& aUri)
   1.300 +	{
   1.301 +	CUri16* self = CUri16::NewLC(aUri);
   1.302 +	CleanupStack::Pop(self);
   1.303 +	return self;
   1.304 +	}
   1.305 +
   1.306 +/**	
   1.307 +	Static factory constructor. Uses two phase construction and leaves a pointer to created object on 
   1.308 +	the CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
   1.309 +	
   1.310 +	@since			6.0
   1.311 +	@deprecated Deprecated in 9.1
   1.312 +	@param			aUri	A reference to a parsed uri object.
   1.313 +	@return			A pointer to the newly created CUri16 object. 
   1.314 +	@post			A fully constructed and initialized CUri16 object.
   1.315 + */
   1.316 +EXPORT_C CUri16* CUri16::NewLC(const TUriC16& aUri)
   1.317 +	{
   1.318 +	CUri16* self = new (ELeave) CUri16(aUri);
   1.319 +	CleanupStack::PushL(self);
   1.320 +	self->ConstructL();
   1.321 +	return self;
   1.322 +	}
   1.323 +
   1.324 +/**
   1.325 +	Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack. 
   1.326 +	Creates a uri object which is empty.
   1.327 +	
   1.328 +	@since			6.0
   1.329 +	@deprecated Deprecated in 9.1
   1.330 +	@return			A pointer to the newly created CUri16 object. 
   1.331 +	@post			A fully constructed and initialized CUri16 object.
   1.332 + */
   1.333 +EXPORT_C CUri16* CUri16::NewL()
   1.334 +	{
   1.335 +	CUri16* self = CUri16::NewLC();
   1.336 +	CleanupStack::Pop(self);
   1.337 +	return self;
   1.338 +	}
   1.339 +
   1.340 +/**
   1.341 +	Static factory constructor. Uses two phase construction and leaves a pointer to created object on 
   1.342 +	the CleanupStack. Creates a uri object which is empty.
   1.343 +	
   1.344 +	@since			6.0
   1.345 +	@deprecated Deprecated in 9.1
   1.346 +	@return			A pointer to the newly created CUri16 object. 
   1.347 +	@post			A fully constructed and initialized CUri16 object.
   1.348 + */
   1.349 +EXPORT_C CUri16* CUri16::NewLC()
   1.350 +	{
   1.351 +	CUri16* self = new (ELeave) CUri16(TUriC16());
   1.352 +	CleanupStack::PushL(self);
   1.353 +	self->ConstructL();
   1.354 +	return self;
   1.355 +	}
   1.356 +
   1.357 +/**	
   1.358 +	Static factory constructor. This creates a CUri16 object that is an absolute uri resulting from a 
   1.359 +	reference uri being resolved against a base uri.
   1.360 +	
   1.361 +	@warning		Ownership of created CUri16 object is transferred to caller.
   1.362 +	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
   1.363 +	@since			6.0
   1.364 +	@deprecated Deprecated in 9.1
   1.365 +	@param			aBaseUri	A referece to the parsed base uri.
   1.366 +	@param			aRefUri		A referece to the parsed reference uri.
   1.367 +	@return			A pointer to the newly created CUri16 object.
   1.368 +	@pre 			The base uri must have an absolute or empty path, otherwise will leave
   1.369 +	with KUriErrBadBasePath.
   1.370 +	@post			A fully constructed and initialized CUri16 object.
   1.371 + */
   1.372 +EXPORT_C CUri16* CUri16::ResolveL(const TUriC16& aBaseUri, const TUriC16& aRefUri)
   1.373 +	{
   1.374 +	// Check for a base Uri
   1.375 +	if( aBaseUri.UriDes().Compare(KNullDesC16) == 0 )
   1.376 +		{
   1.377 +		// Empty base Uri - resolved Uri is the reference Uri
   1.378 +		return NewL(aRefUri);
   1.379 +		}
   1.380 +	// See if ref has scheme and it is the same as base Uri
   1.381 +	if( aRefUri.IsPresent(EUriScheme) && aRefUri.Compare(aBaseUri, EUriScheme) != 0 )
   1.382 +		{
   1.383 +		// Ref has a scheme different to base Uri's - it is an absolute Uri
   1.384 +		return NewL(aRefUri);
   1.385 +		}
   1.386 +	// Check for presence of components
   1.387 +	TBool useBaseQuery = EFalse;
   1.388 +	HBufC16* resolvedPath = FormResolvedPathLC<HBufC16>(aBaseUri, aRefUri, useBaseQuery);
   1.389 +
   1.390 +	// Put the Uri together
   1.391 +	TUriC16 uri;
   1.392 +	FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
   1.393 +
   1.394 +	// Create the resolved Uri and cleanup
   1.395 +	CUri16* resolvedUri = NewL(uri);
   1.396 +	CleanupStack::PopAndDestroy(resolvedPath);
   1.397 +
   1.398 +	return resolvedUri;
   1.399 +	}
   1.400 +
   1.401 +/**	
   1.402 +	Destructor.
   1.403 +	
   1.404 +	@since			6.0
   1.405 +	@deprecated Deprecated in 9.1
   1.406 + */
   1.407 +EXPORT_C CUri16::~CUri16()
   1.408 +	{
   1.409 +	delete iUriBuf;
   1.410 +	}
   1.411 +
   1.412 +/**	
   1.413 +	Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC16.
   1.414 +	
   1.415 +	@since			6.0
   1.416 +	@deprecated Deprecated in 9.1
   1.417 +	@return			A const reference to the parsed uri object.
   1.418 + */
   1.419 +EXPORT_C const TUriC16& CUri16::Uri() const
   1.420 +	{
   1.421 +	return iUri;
   1.422 +	}
   1.423 +
   1.424 +/**
   1.425 +	Sets the specified component in the uri. The component is set to the value given in the argument 
   1.426 +	aData. If the specified component already exists then it is replaced with the new value.
   1.427 +	
   1.428 +	@warning		The userinfo and port components can only be set if the host component
   1.429 +	is present. Setting these components without a host component present will have no 
   1.430 +	effect on the uri.
   1.431 +	@since			6.0
   1.432 +	@deprecated Deprecated in 9.1
   1.433 +	@param			aData		A descriptor pointer to the new value for the uri component.
   1.434 +	@param			aComponent	An enum specifying the component to be set.
   1.435 +	@pre 			Object is fully constructed.
   1.436 +	@post			The uri has the specified component set to the new value.
   1.437 +	@Leave          KErrArgument  If aComponent goes out of range.
   1.438 + */
   1.439 +EXPORT_C void CUri16::SetComponentL(const TDesC16& aData, TUriComponent aComponent)
   1.440 +	{
   1.441 +	// Update the appropriate component table entry
   1.442 +	iUri.iComponent[aComponent].Set(aData);
   1.443 +
   1.444 +	// Copy to the buffer by forming the uri
   1.445 +	FormUriL();
   1.446 +	}
   1.447 +
   1.448 +/**
   1.449 +	Removes the specified component from the uri. If the component does not exist then this function 
   1.450 +	does nothing.
   1.451 +	
   1.452 +	@warning		If host is removed, then userinfo and port components will also
   1.453 +	be removed.
   1.454 +	@since			6.0
   1.455 +	@deprecated Deprecated in 9.1
   1.456 +	@param			aComponent	An enum specifying the component to be removed.
   1.457 +	@pre 			Object is fully constructed.
   1.458 +	@post			The uri is updated to exclude the specified component.
   1.459 + */
   1.460 +EXPORT_C void CUri16::RemoveComponentL(TUriComponent aComponent)
   1.461 +	{
   1.462 +	if( iUri.IsPresent(aComponent) )
   1.463 +		{
   1.464 +		// Remove the component - set pointer to NULL and length to zero
   1.465 +		iUri.iComponent[aComponent].Set(NULL,0);
   1.466 +
   1.467 +		// Re-form buffer and component table
   1.468 +		FormUriL();
   1.469 +		}
   1.470 +	}
   1.471 +
   1.472 +/**
   1.473 +	Constructor. First phase of two-phase construction method. Does	non-allocating construction.
   1.474 +	
   1.475 +	@since			6.0
   1.476 +	@param			aUri	The parsed uri component information from which to create
   1.477 +	the uri.
   1.478 + */
   1.479 +
   1.480 +CUri16::CUri16(const TUriC16& aUri)
   1.481 +: CBase(), iUri(aUri)
   1.482 +	{
   1.483 +	}
   1.484 +
   1.485 +/**
   1.486 +	Second phase of two-phase construction method. Does any allocations required to fully construct 
   1.487 +	the object.
   1.488 +	
   1.489 +	@since			6.0
   1.490 +	@pre 			First phase of construction is complete.
   1.491 +	@post			The object is fully constructed and initialized.
   1.492 + */
   1.493 +void CUri16::ConstructL()
   1.494 +	{
   1.495 +	// Create the HBufC
   1.496 +	FormUriL();
   1.497 +	}
   1.498 +
   1.499 +/**
   1.500 +	Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri 
   1.501 +	is changed to refer to the copy.
   1.502 +	
   1.503 +	@since			6.0
   1.504 +	@pre 			The parsed uri information is set.
   1.505 +	@post			The uri buffer is updated with the parsed uri information.
   1.506 + */
   1.507 +void CUri16::FormUriL()
   1.508 +	{
   1.509 +	TBool isIPv6Host;
   1.510 +
   1.511 +	// Calculate length of of the Uri
   1.512 +	TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
   1.513 +
   1.514 +	// Create a temporary buffer and descriptor pointer to it
   1.515 +	HBufC16* buf = HBufC16::NewL(length);
   1.516 +	TPtr16 uri = buf->Des();
   1.517 +
   1.518 +	// Create the uri, updating the internal uri object
   1.519 +	DoFormUri(uri, iUri.iComponent, isIPv6Host);
   1.520 +
   1.521 +	// Update the internal buffer and descriptor pointer
   1.522 +	delete iUriBuf;
   1.523 +	iUriBuf = buf;
   1.524 +	iUri.iUriDes.Set(iUriBuf->Des());
   1.525 +	}
   1.526 +
   1.527 +//
   1.528 +//
   1.529 +// Implementation of templated LOCAL functions
   1.530 +//
   1.531 +//
   1.532 +
   1.533 +/**
   1.534 +	Calculates the length of the uri from a list of the components.
   1.535 +	
   1.536 +	@since			6.0
   1.537 +	@param			aComponent	The array of descriptor pointers to the uri 
   1.538 +					components.
   1.539 +	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
   1.540 +	@return			The length of the uri including the required delimiters.	
   1.541 +*/
   1.542 +template<class TPtrCType>
   1.543 +TInt CalculateUriLength(const TPtrCType aComponent[], TBool& aIsIPv6Host)
   1.544 +	{
   1.545 +	TBool noAuthority = ETrue;
   1.546 +	TInt length=0;
   1.547 +	aIsIPv6Host=EFalse;
   1.548 +	for( TInt i=0; i<EUriMaxComponents; ++i )
   1.549 +		{
   1.550 +		if( aComponent[i].Ptr() )
   1.551 +			{
   1.552 +			length += aComponent[i].Length();
   1.553 +			if( noAuthority && (i==EUriUserinfo || i==EUriHost || i==EUriPort) )
   1.554 +				{
   1.555 +				// There's an authority part...
   1.556 +				noAuthority = EFalse;
   1.557 +				}
   1.558 +			// Need to make space for a delimiter if not path or host
   1.559 +			if( i!=EUriHost && i!=EUriPath )
   1.560 +				++length;		
   1.561 +			
   1.562 +			// If it's an IPv6 hostname, need extra space for []
   1.563 +			if(i==EUriHost && (UriUtils::HostType(aComponent[i])==UriUtils::EIPv6Host))
   1.564 +				{
   1.565 +				length+=2;				
   1.566 +				aIsIPv6Host=ETrue;
   1.567 +				}
   1.568 +			}
   1.569 +		}
   1.570 +	if( !noAuthority && IsNetworkScheme(aComponent[EUriScheme]))
   1.571 +		{
   1.572 +		// Make space for authority delimiter
   1.573 +		length += KUriNetworkAuthorityDelimiterLength;
   1.574 +		}
   1.575 +	return length;
   1.576 +	}
   1.577 +
   1.578 +/**
   1.579 +	Templated function to form a uri. The output argument aUri points to a descriptor 
   1.580 +	buffer large enough to hold the uri. The new uri component information is given by 
   1.581 +	the input/output argument aComponent. For each uri component that exists in aComponent,
   1.582 +	that component and its appropriate delimiters are appended to aUri. Then the components 
   1.583 +	in aComponent are updated to refer to the copies versions in aUri.
   1.584 +						
   1.585 +	@since			6.0
   1.586 +	@param			aUri		The descriptor pointer to buffer to be appended.
   1.587 +	@param			aComponent	The array of descriptor pointers to be copied and 
   1.588 +					then updated.
   1.589 +	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
   1.590 +	@pre 			The buffer pointed to by aUri should be large enough to have the uri 
   1.591 +					components given in aNewComponent copied into it, as well as the required delimiters.
   1.592 +					This can be obtained using CalculateUriLength().
   1.593 +	@post			The uri buffer pointed to by aUri will have a copy of the uri defined 
   1.594 +					in aComponent, and then aComponent will refer to the copies of these components in aUri.
   1.595 +*/
   1.596 +template<class TPtrType, class TPtrCType>
   1.597 +void DoFormUri(TPtrType& aUri, TPtrCType aComponent[], TBool& aIsIPv6Host)
   1.598 +	{
   1.599 +	TBool isNetworkScheme = ETrue;
   1.600 +	if( aComponent[EUriScheme].Ptr() )
   1.601 +		{
   1.602 +		// Update the scheme
   1.603 +		SetScheme(aUri, aComponent[EUriScheme]);
   1.604 +		isNetworkScheme = IsNetworkScheme(aComponent[EUriScheme]);
   1.605 +		}
   1.606 +	if( aComponent[EUriHost].Ptr() )
   1.607 +		{
   1.608 +		// Update the authority - only needed if there is a host; update userinfo, host and port
   1.609 +		SetAuthority(aUri, aComponent[EUriUserinfo], aComponent[EUriHost], aComponent[EUriPort], aIsIPv6Host, isNetworkScheme);
   1.610 +		}
   1.611 +	else
   1.612 +		{
   1.613 +		// Ensure that there is no userinfo or port components if there is no host 
   1.614 +		// - set pointer to NULL and length to zero
   1.615 +		aComponent[EUriUserinfo].Set(NULL,0);
   1.616 +		aComponent[EUriPort].Set(NULL,0);
   1.617 +		}
   1.618 +	if( aComponent[EUriPath].Ptr() )
   1.619 +		{
   1.620 +		// Update the path
   1.621 +		SetPath(aUri, aComponent[EUriPath]);
   1.622 +		}
   1.623 +	if( aComponent[EUriQuery].Ptr() )
   1.624 +		{
   1.625 +		// Update the query
   1.626 +		SetQuery(aUri, aComponent[EUriQuery]);
   1.627 +		}
   1.628 +	if( aComponent[EUriFragment].Ptr() )
   1.629 +		{
   1.630 +		// Update the fragment
   1.631 +		SetFragment(aUri, aComponent[EUriFragment]);
   1.632 +		}
   1.633 +	}
   1.634 +
   1.635 +/**
   1.636 +	Templated function to set the scheme in a uri. The output argument aUri points to the descriptor 
   1.637 +	buffer into which aScheme will be copied.The argument aScheme is then updated to point to the 
   1.638 +	copied version in aUri.
   1.639 +						
   1.640 +	@warning		This function will panic with KUriErrBufferOverflow if there is not
   1.641 +					enough space in the descriptor to append the scheme and the required delimiter.
   1.642 +	@since			6.0
   1.643 +	@param			aUri	The descriptor pointer to buffer to be appended.
   1.644 +	@param			aScheme	The descriptor pointer to the scheme component to be copied 
   1.645 +					and then updated.
   1.646 +	@pre 			The buffer pointed to by aUri should be large enough to have aNewScheme
   1.647 +					appended to it with the required delimiter. This can be obtained using CalculateUriLength().
   1.648 +	@post			The uri buffer now includes a copy of aScheme and aScheme points to the 
   1.649 +					copy of the scheme component in aUri.
   1.650 +*/
   1.651 +template<class TPtrType, class TPtrCType>
   1.652 +void SetScheme(TPtrType& aUri, TPtrCType& aScheme)
   1.653 +	{
   1.654 +	__ASSERT_DEBUG(aUri.Length() + aScheme.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.655 +
   1.656 +	// Append the scheme and delimiter
   1.657 +	aUri.Append(aScheme);
   1.658 +	aUri.Append(KSchemeDelimiter);
   1.659 +
   1.660 +	// Update the component table to use the copy
   1.661 +	aScheme.Set(aUri.Left(aScheme.Length()));
   1.662 +	}
   1.663 +	
   1.664 +/**
   1.665 +	Templated function to set the authority in a uri. The output argument aUri points to the descriptor 
   1.666 +	buffer into which aUserinfo, aHost and aPort will be copied. The arguments aUserinfo, aHost and aPort 
   1.667 +	are updated to point to the copied versions in aUri.
   1.668 +						
   1.669 +	@warning		This function will panic with KUriErrBufferOverflow if there 
   1.670 +					is not enough space in the descriptor to append the components and any required 
   1.671 +					delimiters. 
   1.672 +	@since			6.0
   1.673 +	@param			aUri		The descriptor pointer to buffer to be appended.
   1.674 +	@param			aUserinfo	The descriptor pointer to the userinfo component to 
   1.675 +					be copied and then updated.
   1.676 +	@param			aHost		The descriptor pointer to the host component to 
   1.677 +					be copied and then updated.
   1.678 +	@param			aPort		The descriptor pointer to the port component to 
   1.679 +					be copied and then updated.
   1.680 +	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
   1.681 +	@param			aUseNetworkDelimiter EFalse if this is a SIP scheme otherwise ETrue
   1.682 +	@pre 			The buffer pointed to by aUri should be large enough to have 
   1.683 +					aUserinfo, aHost and aPort appended to it with the required delimiters.
   1.684 +					This can be obtained using CalculateUriLength().
   1.685 +	@post			The uri buffer now includes a copy of aUserinfo, aHost and
   1.686 +					aPort, and aUserinfo, aHost and aPort will refer to the copies versions in aUri.
   1.687 +*/
   1.688 +template<class TPtrType, class TPtrCType>
   1.689 +void SetAuthority(TPtrType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool& aIsIPv6Host, TBool aUseNetworkDelimiter)
   1.690 +	{
   1.691 +	__ASSERT_DEBUG(aUri.Length() + aHost.Length() + (aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength:0) <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.692 +	
   1.693 +	if (aUseNetworkDelimiter)
   1.694 +		{
   1.695 +		// If a network scheme append authority delimiter (TWO slash delimiters!)
   1.696 +		aUri.Append(KSlashDelimiter);
   1.697 +		aUri.Append(KSlashDelimiter);
   1.698 +		}
   1.699 +
   1.700 +	// Check for userinfo
   1.701 +	if( aUserinfo.Ptr() )
   1.702 +		{
   1.703 +		__ASSERT_DEBUG(aUri.Length() + aUserinfo.Length() + aHost.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.704 +
   1.705 +		// Append userinfo and update the component table to use copy
   1.706 +		aUri.Append(aUserinfo);
   1.707 +		aUserinfo.Set(aUri.Right(aUserinfo.Length()));
   1.708 +
   1.709 +		// Append delimiter
   1.710 +		aUri.Append(KUserinfoDelimiter);
   1.711 +		}
   1.712 +	// There's always a host - append and update the component table to use the copy
   1.713 +	
   1.714 +	// Check if it's an IPv6 address
   1.715 +	if ( aIsIPv6Host )
   1.716 +		{
   1.717 +		aUri.Append(KIPv6UriOpenBrace); 
   1.718 +		aUri.Append(aHost);
   1.719 +		aUri.Append(KIPv6UriCloseBrace);
   1.720 +		// Dont include the braces in the host
   1.721 +		// Position = (length of uri - length of host) - length of end brace
   1.722 +		aHost.Set( aUri.Mid((aUri.Length()-aHost.Length())-1, aHost.Length()) );
   1.723 +		}
   1.724 +	else
   1.725 +		{
   1.726 +		aUri.Append(aHost);
   1.727 +		aHost.Set(aUri.Right(aHost.Length()));
   1.728 +		}
   1.729 +	
   1.730 +	// Check for a port
   1.731 +	if( aPort.Ptr() )
   1.732 +		{
   1.733 +		__ASSERT_DEBUG(aUri.Length() + aPort.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.734 +				   
   1.735 +		// Append delimiter
   1.736 +		aUri.Append(KPortDelimiter);
   1.737 +	
   1.738 +		// Append port and update the component table to use copy
   1.739 +		aUri.Append(aPort);
   1.740 +		aPort.Set(aUri.Right(aPort.Length()));
   1.741 +		}
   1.742 +	}
   1.743 +/**
   1.744 +	Templated function to set the path in a uri. The output argument aUri points to the descriptor 
   1.745 +	buffer into which aPath will be copied.The argument aPath is then updated to point to the copied 
   1.746 +	version in aUri.
   1.747 +						
   1.748 +	@warning		This function will panic with KUriErrBufferOverflow if there 
   1.749 +					is not enough space in the descriptor to append the path.
   1.750 +	@since			6.0
   1.751 +	@param			aUri	The descriptor pointer to buffer to be appended.
   1.752 +	@param			aPath	The descriptor pointer to the path component to be copied 
   1.753 +					and then updated.
   1.754 +	@pre 			The buffer pointed to by aUri should be large enough to have 
   1.755 +					aPath appended to it. This can be obtained using CalculateUriLength().
   1.756 +	@post			The uri buffer now includes a copy of aPath and aPath points to the 
   1.757 +					copy of the path component in aUri.
   1.758 +*/
   1.759 +template<class TPtrType, class TPtrCType>
   1.760 +void SetPath(TPtrType& aUri, TPtrCType& aPath)
   1.761 +	{
   1.762 +	__ASSERT_DEBUG(aUri.Length() + aPath.Length() <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.763 +
   1.764 +	// Append the path
   1.765 +	aUri.Append(aPath);
   1.766 +
   1.767 +	// Update the component table
   1.768 +	aPath.Set(aUri.Right(aPath.Length()));
   1.769 +	}
   1.770 +
   1.771 +/**
   1.772 +	Templated function to set the query in a uri. The output argument aUri points to the descriptor 
   1.773 +	buffer into which aQuery will be copied. The argument aQuery is then updated to point to the copied 
   1.774 +	version in aUri.
   1.775 +						
   1.776 +	@warning		This function will panic with KUriErrBufferOverflow if there 
   1.777 +					is not enough space in the descriptor to append the query and the delimiter.
   1.778 +	@since			6.0
   1.779 +	@param			aUri	The descriptor pointer to buffer to be appended.
   1.780 +	@param			aQuery	The descriptor pointer to the query component to be copied 
   1.781 +					and then updated.
   1.782 +	@pre 			The buffer pointed to by aUri should be large enough to have 
   1.783 +					aQuery appended to it. This can be obtained using CalculateUriLength().
   1.784 +	@post			The uri buffer now includes a copy of aQuery and aQuery points to the 
   1.785 +					copy of the query component in aUri.
   1.786 +*/
   1.787 +template<class TPtrType, class TPtrCType>
   1.788 +void SetQuery(TPtrType& aUri, TPtrCType& aQuery)
   1.789 +	{
   1.790 +	__ASSERT_DEBUG(aUri.Length() + aQuery.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.791 +
   1.792 +	// Append delimiter and the query
   1.793 +	aUri.Append(KQueryDelimiter);
   1.794 +	aUri.Append(aQuery);
   1.795 +
   1.796 +	// Update the component table
   1.797 +	aQuery.Set(aUri.Right(aQuery.Length()));
   1.798 +	}
   1.799 +
   1.800 +/**
   1.801 +	Templated function to set the fragment in a uri. The output argument aUri points to the descriptor 
   1.802 +	buffer into which aFragment will be copied. The argument aFragment is then updated to point to the 
   1.803 +	copied version in aUri.
   1.804 +						
   1.805 +	@warning		This function will panic with KUriErrBufferOverflow if there 
   1.806 +					is not enough space in the descriptor to append the fragment and the delimiter.
   1.807 +	@since			6.0
   1.808 +	@param			aUri		The descriptor pointer to buffer to be appended.
   1.809 +	@param			aFragment	The descriptor pointer to the fragment component
   1.810 +					to be copied and then updated.
   1.811 +	@pre 			The buffer pointed to by aUri should be large enough to have 
   1.812 +					aFragment appended to it. This can be obtained using CalculateUriLength().
   1.813 +	@post			The uri buffer now includes a copy of aFragment and aFragment points 
   1.814 +					to the copy of the fragment component in aUri.
   1.815 +*/
   1.816 +template<class TPtrType, class TPtrCType>
   1.817 +void SetFragment(TPtrType& aUri, TPtrCType& aFragment)
   1.818 +	{
   1.819 +	__ASSERT_DEBUG(aUri.Length() + aFragment.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   1.820 +
   1.821 +	// Append delimiter and the fragment
   1.822 +	aUri.Append(KFragmentDelimiter);
   1.823 +	aUri.Append(aFragment);
   1.824 +
   1.825 +	// Update the component table
   1.826 +	aFragment.Set(aUri.Right(aFragment.Length()));
   1.827 +	}
   1.828 +
   1.829 +/**
   1.830 +	Forms the resolved path. Checks to see if the base query needs to be used in the resolved uri. 
   1.831 +	The pointer to the resolved path is left on the cleanup stack.
   1.832 +						
   1.833 +	@since			6.0
   1.834 +	@param			aBaseUri		The base uri.
   1.835 +	@param			aRefUri			The reference uri.
   1.836 +	@param			aUseBaseQuery	An output argument specifying whether the base
   1.837 +					query should be used in the resolved uri.
   1.838 +	@return			A pointer to a buffer that contains the resolved path.
   1.839 +*/
   1.840 +template<class HBufCType, class TUriCType>
   1.841 +HBufCType* FormResolvedPathLC(const TUriCType& aBaseUri, const TUriCType& aRefUri, TBool& aUseBaseQuery)
   1.842 +	{
   1.843 +	HBufCType* resolvedPath = NULL;
   1.844 +	if( !aRefUri.IsPresent(EUriScheme) && !aRefUri.IsPresent(EUriHost) && !aRefUri.Extract(EUriPath).Length() && !aRefUri.IsPresent(EUriQuery) )
   1.845 +		{
   1.846 +		// Ref is just a fragment
   1.847 +		aUseBaseQuery = ETrue;
   1.848 +		resolvedPath = aBaseUri.Extract(EUriPath).AllocLC();
   1.849 +		}
   1.850 +	else if( aRefUri.IsPresent(EUriHost) )
   1.851 +		{
   1.852 +		// Ref is a network path
   1.853 +		resolvedPath = aRefUri.Extract(EUriPath).AllocLC();
   1.854 +		}
   1.855 +	else
   1.856 +		{
   1.857 +		// Need to some path resolving...
   1.858 +		resolvedPath = ResolvePathsL(aBaseUri.Extract(EUriPath), aRefUri.Extract(EUriPath));
   1.859 +		CleanupStack::PushL(resolvedPath);
   1.860 +		}
   1.861 +	return resolvedPath;
   1.862 +	}
   1.863 +
   1.864 +/**
   1.865 +	Cleans up a resolved path. This deals with occurences of '.' and '..' where these are complete 
   1.866 +	path segments.
   1.867 +						
   1.868 +	@since			6.0
   1.869 +	@param			aResolvedPath	The delimited data object that contains the 
   1.870 +					resolved path.
   1.871 +	@pre 			The input/output argument contains the path to be cleaned.
   1.872 +	@post			The resolved path has had all the occurences of '.' and '..' 
   1.873 +					processed and has been updated to contain the cleaned path.
   1.874 + */
   1.875 +template<class TPtrCType, class CDelimitedDataBaseType>
   1.876 +void CleanResolvedPathL(CDelimitedDataBaseType* aResolvedPath)
   1.877 +	{
   1.878 +	// Create a modifiable path object for resolved path
   1.879 +	aResolvedPath->Parse();
   1.880 +
   1.881 +	TBool done = EFalse;
   1.882 +	while( !done )
   1.883 +   		{
   1.884 +   		// Get the next segment
   1.885 +   		TPtrCType segment;
   1.886 +   		TInt more = aResolvedPath->Parser().Peek(segment);
   1.887 +
   1.888 +   		if( more == KErrNotFound )
   1.889 +   			{
   1.890 +   			// No more segments - done
   1.891 +   			done = ETrue;
   1.892 +   			}
   1.893 +   		else if( IsParentDir(segment) )
   1.894 +   			{
   1.895 +   			// Found a '..' - remove '..' from path, and remove previous segment
   1.896 +			aResolvedPath->RemoveCurrentL();
   1.897 +			if( aResolvedPath->Parser().Dec() == KErrNotFound )
   1.898 +				{
   1.899 +				// No previous directory - put back '..' and stop
   1.900 +				InsertParentDirL(aResolvedPath);
   1.901 +				done = ETrue;
   1.902 +				}
   1.903 +			else
   1.904 +				{
   1.905 +				// Remove the parent directory
   1.906 +				aResolvedPath->RemoveCurrentL();
   1.907 +				if( aResolvedPath->Parser().Eos() )
   1.908 +					{
   1.909 +					// '..' is the last segment - add a '/' to the path (add empty segment)
   1.910 +					aResolvedPath->AddBackDelimiterL();
   1.911 +					done = ETrue;
   1.912 +					}
   1.913 +				}
   1.914 +			}
   1.915 +   		else if( IsSameDir(segment) )
   1.916 +   			{
   1.917 +   			// Found a '.' - remove -.- from the path
   1.918 +			aResolvedPath->RemoveCurrentL();
   1.919 +			if( aResolvedPath->Parser().Eos() )
   1.920 +				{
   1.921 +				// '..' is the last segment - add a '/' to the path (add empty segment)
   1.922 +				aResolvedPath->AddBackDelimiterL();
   1.923 +				done = ETrue;
   1.924 +				}
   1.925 +			}
   1.926 +   		else
   1.927 +   			{
   1.928 +   			// Segment wasn't '.' or '..' - parse to next segment
   1.929 +   			aResolvedPath->Parser().Inc();
   1.930 +   			}
   1.931 +   		}
   1.932 +	}
   1.933 +
   1.934 +/**
   1.935 +	Forms the resolved uri. Sets the components for the resolved uri from those in the base uri and 
   1.936 +	the reference uri. The resolved path is given by the input argument aResolvedPath
   1.937 +						
   1.938 +	@since			6.0
   1.939 +	@param			aComponent		The array of components to be set for the resolved uri.
   1.940 +	@param			aBaseUri		The base uri.
   1.941 +	@param			aRefUri			The reference uri.
   1.942 +	@param			aResolvedPath	The resolved path.
   1.943 +	@param			aUseBaseQuery	A boolean indicating whether the base query 
   1.944 +					should be used.
   1.945 +*/
   1.946 +template<class TPtrCType, class TUriCType, class HBufCType>
   1.947 +void FormResolvedUri(TPtrCType aComponent[], const TUriCType& aBaseUri, const TUriCType& aRefUri, const HBufCType* aResolvedPath, TBool aUseBaseQuery)
   1.948 +	{
   1.949 +	// Scheme...
   1.950 +	if( aBaseUri.IsPresent(EUriScheme) )
   1.951 +		{
   1.952 +		// Use the base scheme
   1.953 +		aComponent[EUriScheme].Set(aBaseUri.Extract(EUriScheme));
   1.954 +		}
   1.955 +	// Authority
   1.956 +	if( aRefUri.IsPresent(EUriHost) )
   1.957 +		{
   1.958 +		// Use the ref host, userinfo and port - must set host first
   1.959 +		aComponent[EUriHost].Set(aRefUri.Extract(EUriHost));
   1.960 +		aComponent[EUriUserinfo].Set(aRefUri.Extract(EUriUserinfo));
   1.961 +		aComponent[EUriPort].Set(aRefUri.Extract(EUriPort));
   1.962 +		}
   1.963 +	else if( aBaseUri.IsPresent(EUriHost) )
   1.964 +		{
   1.965 +		// Use the base host, userinfo and port - must set host first
   1.966 +		aComponent[EUriHost].Set(aBaseUri.Extract(EUriHost));
   1.967 +		aComponent[EUriUserinfo].Set(aBaseUri.Extract(EUriUserinfo));
   1.968 +		aComponent[EUriPort].Set(aBaseUri.Extract(EUriPort));
   1.969 +		}
   1.970 +	// Path...
   1.971 +	aComponent[EUriPath].Set(*aResolvedPath);
   1.972 +
   1.973 +	// Query...
   1.974 +	if( aUseBaseQuery && aBaseUri.IsPresent(EUriQuery) )
   1.975 +		{
   1.976 +		// Use the query from the base
   1.977 +		aComponent[EUriQuery].Set(aBaseUri.Extract(EUriQuery));
   1.978 +		}
   1.979 +	else if( aRefUri.IsPresent(EUriQuery) )
   1.980 +		{
   1.981 +		// Use the query from the ref
   1.982 +		aComponent[EUriQuery].Set(aRefUri.Extract(EUriQuery));
   1.983 +		}
   1.984 +	// Fragment
   1.985 +	if( aRefUri.IsPresent(EUriFragment) )
   1.986 +		{
   1.987 +		// Use the fragment from the ref
   1.988 +		aComponent[EUriFragment].Set(aRefUri.Extract(EUriFragment));
   1.989 +		}
   1.990 +	}
   1.991 +
   1.992 +//
   1.993 +//
   1.994 +// Implemetation of LOCAL functions
   1.995 +//
   1.996 +//
   1.997 +
   1.998 +/**
   1.999 +	Function used to resolve a base path (aBasePath) against a reference path (aRefPath),
  1.1000 +	as described by RFC2396.
  1.1001 +						
  1.1002 +	@since			6.0
  1.1003 +	@param			aBasePath	A descriptor reference to the base path.
  1.1004 +	@param			aRefPath	A descriptor reference to the reference path.
  1.1005 +	@return			A pointer to a buffer containing the resolve path.
  1.1006 +	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
  1.1007 +*/
  1.1008 +HBufC8* ResolvePathsL(const TDesC8& aBasePath, const TDesC8& aRefPath)
  1.1009 +	{
  1.1010 +	TInt refLength = aRefPath.Length();
  1.1011 +	if( refLength && aRefPath[0] == KSlashDelimiter )
  1.1012 +		{
  1.1013 +		// Relative path is absolute - that is the resolved path
  1.1014 +		return aRefPath.AllocL();
  1.1015 +		}
  1.1016 +	// Ok got work to do - base path must be absolute (check 1st char) or empty
  1.1017 +	if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
  1.1018 +		{
  1.1019 +		// Base path not empty and not abosolute - bad base path
  1.1020 +		User::Leave(KUriUtilsErrBadBasePath);
  1.1021 +		}
  1.1022 +	// Create a modifiable path object for resolved path
  1.1023 +	CDelimitedPath8* resolvedPath = CDelimitedPath8::NewLC(aBasePath);
  1.1024 +
  1.1025 +	// Check for empty ref path - use all of base path if empty
  1.1026 +	if( refLength )
  1.1027 +		{
  1.1028 +		// Not empty - ensure that base path's last segment is removed and add reference
  1.1029 +		resolvedPath->PopBackL();
  1.1030 +		resolvedPath->PushBackL(aRefPath);
  1.1031 +		}
  1.1032 +	// Clean up the path to resolve occurences of '..' and '.' - parser path first
  1.1033 +	CleanResolvedPathL<TPtrC8>(resolvedPath);
  1.1034 +
  1.1035 +	// Return pointer to HBufC with path
  1.1036 +	HBufC8* path = resolvedPath->Parser().Des().AllocL();
  1.1037 +	CleanupStack::PopAndDestroy(resolvedPath);
  1.1038 +	return path;
  1.1039 +	}
  1.1040 +
  1.1041 +/**
  1.1042 +	Function used to resolve a base path (aBasePath) against a reference path (aRefPath), 
  1.1043 +	as described by RFC2396.
  1.1044 +						
  1.1045 +	@since			6.0
  1.1046 +	@param			aBasePath	A descriptor reference to the base path.
  1.1047 +	@param			aRefPath	A descriptor reference to the reference path.
  1.1048 +	@return			A pointer to a buffer containing the resolve path.
  1.1049 +	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
  1.1050 +*/
  1.1051 +HBufC16* ResolvePathsL(const TDesC16& aBasePath, const TDesC16& aRefPath)
  1.1052 +	{
  1.1053 +	TInt refLength = aRefPath.Length();
  1.1054 +	if( refLength && aRefPath[0] == KSlashDelimiter )
  1.1055 +		{
  1.1056 +		// Relative path is absolute - that is the resolved path
  1.1057 +		return aRefPath.AllocL();
  1.1058 +		}
  1.1059 +	// Ok got work to do - base path must be absolute (check 1st char) or empty
  1.1060 +	if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
  1.1061 +		{
  1.1062 +		// Base path not empty and not abosolute - bad base path
  1.1063 +		User::Leave(KUriUtilsErrBadBasePath);
  1.1064 +		}
  1.1065 +	// Create a modifiable path object for resolved path
  1.1066 +	CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(aBasePath);
  1.1067 +
  1.1068 +	// Check for empty ref path - use all of base path if empty
  1.1069 +	if( refLength )
  1.1070 +		{
  1.1071 +		// Not empty - ensure that base path's last segment is removed and add reference
  1.1072 +		resolvedPath->PopBackL();
  1.1073 +		resolvedPath->PushBackL(aRefPath);
  1.1074 +		}
  1.1075 +	// Clean up the path to resolve occurences of '..' and '.' - parser path first
  1.1076 +	CleanResolvedPathL<TPtrC16>(resolvedPath);
  1.1077 +
  1.1078 +	// Return pointer to HBufC with path
  1.1079 +	HBufC16* path = resolvedPath->Parser().Des().AllocL();
  1.1080 +	CleanupStack::PopAndDestroy(resolvedPath);
  1.1081 +	return path;
  1.1082 +	}
  1.1083 +	
  1.1084 +/**
  1.1085 +	Checks if the segment is '.' (8-bit version).
  1.1086 +	
  1.1087 +	@since			6.0
  1.1088 +	@param			aSegment	A descriptor with the segment to check.
  1.1089 +	@return			A boolean value of ETrue if the segment is '.', EFalse if not.
  1.1090 +*/
  1.1091 +TBool IsSameDir(const TDesC8& aSegment)
  1.1092 +	{
  1.1093 +	_LIT8(KSameDir, ".");
  1.1094 +	return (aSegment.Compare(KSameDir) == 0);
  1.1095 +	}
  1.1096 +	
  1.1097 +/**
  1.1098 +	Checks if the segment is '.' (16-bit version).
  1.1099 +	
  1.1100 +	@since			6.0
  1.1101 +	@param			aSegment	A descriptor with the segment to check.
  1.1102 +	@return			A boolean value of ETrue if the segment is '.', EFalse if not.
  1.1103 +*/
  1.1104 +TBool IsSameDir(const TDesC16& aSegment)
  1.1105 +	{
  1.1106 +	_LIT16(KSameDir, ".");
  1.1107 +	return (aSegment.Compare(KSameDir) == 0);
  1.1108 +	}
  1.1109 +	
  1.1110 +/**
  1.1111 +	Checks if the segment is '..' (8-bit version).
  1.1112 +	
  1.1113 +	@since			6.0
  1.1114 +	@param			aSegment	A descriptor with the segment to check.
  1.1115 +	@return			A boolean value of ETrue if the segment is '..', EFalse if not.
  1.1116 +*/
  1.1117 +TBool IsParentDir(const TDesC8& aSegment)
  1.1118 +	{
  1.1119 +	_LIT8(KParentDir, "..");
  1.1120 +	return (aSegment.Compare(KParentDir) == 0);
  1.1121 +	}
  1.1122 +
  1.1123 +/**
  1.1124 +	Checks if the segment is '..' (16-bit version).
  1.1125 +	
  1.1126 +	@since			6.0
  1.1127 +	@param			aSegment	A descriptor with the segment to check.
  1.1128 +	@return			A boolean value of ETrue if the segment is '..', EFalse if not.
  1.1129 +*/
  1.1130 +TBool IsParentDir(const TDesC16& aSegment)
  1.1131 +	{
  1.1132 +	_LIT16(KParentDir, "..");
  1.1133 +	return (aSegment.Compare(KParentDir) == 0);
  1.1134 +	}
  1.1135 +
  1.1136 +/**
  1.1137 +	Inserts the segment '..' at the current parsed position (8-bit version).
  1.1138 +						
  1.1139 +	@since			6.0
  1.1140 +	@param			aResolvedPath	The delimited data object to have the segment
  1.1141 +					inserted.
  1.1142 +	@pre			The delimited data object must be parsed to the position where 
  1.1143 +					the segment is to be inserted.
  1.1144 +	@post			The segment '..' has been inserted at the current position.
  1.1145 +*/
  1.1146 +void InsertParentDirL(CDelimitedDataBase8* aResolvedPath)
  1.1147 +	{
  1.1148 +	_LIT8(KParentDir, "..");
  1.1149 +	aResolvedPath->InsertCurrentL(KParentDir);
  1.1150 +	}
  1.1151 +	
  1.1152 +/**
  1.1153 +	Inserts the segment '..' at the current parsed position (16-bit version).
  1.1154 +						
  1.1155 +	@since			6.0
  1.1156 +	@param			aResolvedPath	The delimited data object to have the segment
  1.1157 +					inserted.
  1.1158 +	@pre			The delimited data object must be parsed to the position where 
  1.1159 +					the segment is to be inserted.
  1.1160 +	@post			The segment '..' has been inserted at the current position.
  1.1161 +*/
  1.1162 +void InsertParentDirL(CDelimitedDataBase16* aResolvedPath)
  1.1163 +	{
  1.1164 +	_LIT16(KParentDir, "..");
  1.1165 +	aResolvedPath->InsertCurrentL(KParentDir);
  1.1166 +	}
  1.1167 +	
  1.1168 +
  1.1169 +//
  1.1170 +//
  1.1171 +// File URI Implementation - CUri8
  1.1172 +//
  1.1173 +//
  1.1174 +
  1.1175 +/**
  1.1176 +	Initializes the file URI components (scheme, empty hostname and path).	 
  1.1177 +	
  1.1178 +	It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive. 
  1.1179 +	
  1.1180 +	@since			9.1
  1.1181 +	@param			aFileName	A reference to a filename 
  1.1182 +	@param			aDrive		A drive number. This is a TFileUriFlags value.
  1.1183 +	@param			aFlags		A flag to indicate if the file exists on a fixed drive or removable media drive.
  1.1184 +					This is a TFileUriFlags value.
  1.1185 +	@pre 			Object fully constructed
  1.1186 +	@post			The object is initialized with file URI components.
  1.1187 + */
  1.1188 +void CUri8::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
  1.1189 +	{
  1.1190 +	HBufC* uriPath16 = GenerateFileUriPathL(aFileName, aDrive, aFlags);
  1.1191 +	CleanupStack::PushL(uriPath16);
  1.1192 +	HBufC8* uriPath = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath16);
  1.1193 +	CleanupStack::PopAndDestroy(uriPath16);
  1.1194 +	CleanupStack::PushL(uriPath);
  1.1195 +	HBufC8* escpedUriPath = EscapeUtils::EscapeEncodeL(*uriPath, EscapeUtils::EEscapeNormal);
  1.1196 +	CleanupStack::PopAndDestroy(uriPath);
  1.1197 +	CleanupStack::PushL(escpedUriPath);
  1.1198 +	
  1.1199 +	//SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation, 
  1.1200 +	//tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer 
  1.1201 +	//for each SetComponent call     
  1.1202 +	iUri.iComponent[EUriPath].Set(*escpedUriPath);
  1.1203 +	iUri.iComponent[EUriHost].Set(KNullDesC8);
  1.1204 +	iUri.iComponent[EUriScheme].Set(KFileUriScheme8);
  1.1205 +	FormUriL();
  1.1206 +	
  1.1207 +	CleanupStack::PopAndDestroy(escpedUriPath);
  1.1208 +	}
  1.1209 +
  1.1210 +/**
  1.1211 +	Allocates and constructs a file URI object for a specified file.
  1.1212 +	 
  1.1213 +	- If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.	
  1.1214 +	- If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
  1.1215 +	
  1.1216 +	@since			9.1
  1.1217 +	@param			aFullFileName	A reference to a fully qualified filename 
  1.1218 +	@param			aFlags			A flag to indicate if the file exists on a fixed drive or removable media drive.
  1.1219 +									This is a TFileUriFlags value.
  1.1220 +	@return			A pointer to the newly created file URI (CUri8) object. 
  1.1221 +	@post			A fully constructed and initialized file URI (CUri8) object.
  1.1222 + */
  1.1223 +EXPORT_C CUri8* CUri8::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
  1.1224 +	{
  1.1225 +	//It should be called to construct a file URI for a public file stored on a fix drive 
  1.1226 +	// or on a removable media drive only
  1.1227 +	__ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1.1228 +		
  1.1229 +	CUri8* self = CUri8::NewLC();
  1.1230 +	self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
  1.1231 +	CleanupStack::Pop(self);
  1.1232 +	return self;
  1.1233 +	}
  1.1234 +
  1.1235 +/**
  1.1236 +	Allocates and constructs a file URI object for a file that is private to the application.
  1.1237 +
  1.1238 +	- If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
  1.1239 +	- If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
  1.1240 +	
  1.1241 +	@since			9.1
  1.1242 +	@param			aRelativeFileName	A reference to the filename relative to the application's private directory.
  1.1243 +	@param			aDrive				Drive number, if the private file stored on fixed drive, otherwise not used
  1.1244 +										This is a TDriveNumber value
  1.1245 +	@param			aFlags				A flag to indicate if the file exists on a fixed drive or removable media drive.
  1.1246 +										This is a TFileUriFlags value.
  1.1247 +	@return			A pointer to the newly created file URI (CUri8) object. 
  1.1248 +	@post			A fully constructed and initialized file URI (CUri8) object.
  1.1249 +*/	
  1.1250 +
  1.1251 +
  1.1252 +EXPORT_C CUri8* CUri8::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags) 
  1.1253 +	{
  1.1254 +	//It should be called to construct a file URI for the application's private file stored on a fix drive 
  1.1255 +	// or on a removable media drive only
  1.1256 +	__ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1.1257 +
  1.1258 +	CUri8* self = CUri8::NewLC();
  1.1259 +	self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
  1.1260 +	CleanupStack::Pop(self);
  1.1261 +	return self;
  1.1262 +	}
  1.1263 +
  1.1264 +
  1.1265 +//
  1.1266 +//
  1.1267 +// File URI Implementation - CUri16
  1.1268 +//
  1.1269 +//
  1.1270 +
  1.1271 +/**
  1.1272 +	Initializes the file URI components (scheme, empty hostname and path).	 
  1.1273 +	
  1.1274 +	It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive. 
  1.1275 +	
  1.1276 +	@since			9.1
  1.1277 +	@param			aFileName	A reference to a filename 
  1.1278 +	@param			aDrive		A drive number. This is a TFileUriFlags value.
  1.1279 +	@param			aFlags		A flag to indicate if the file exists on a fixed drive or removable media drive.
  1.1280 +					This is a TFileUriFlags value.
  1.1281 +	@pre 			Object fully constructed
  1.1282 +	@post			The object is initialized with file URI components.
  1.1283 + */
  1.1284 +void CUri16::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
  1.1285 +	{	
  1.1286 +	HBufC* uriPath = GenerateFileUriPathL(aFileName, aDrive, aFlags);
  1.1287 +	CleanupStack::PushL(uriPath);
  1.1288 +
  1.1289 +	HBufC8* uriPath8 = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath);
  1.1290 +	CleanupStack::PopAndDestroy(uriPath);
  1.1291 +	CleanupStack::PushL(uriPath8);
  1.1292 +
  1.1293 +	HBufC8* escapedUriPath8 = EscapeUtils::EscapeEncodeL(*uriPath8, EscapeUtils::EEscapeNormal);
  1.1294 +	CleanupStack::PopAndDestroy(uriPath8);
  1.1295 +	CleanupStack::PushL(escapedUriPath8);
  1.1296 +
  1.1297 +	HBufC* escapedUriPath = HBufC::NewLC(escapedUriPath8->Length());
  1.1298 +	escapedUriPath->Des().Copy(*escapedUriPath8); 
  1.1299 +	
  1.1300 +	//SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation, 
  1.1301 +	//tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer 
  1.1302 +	//for each SetComponent call     
  1.1303 +	iUri.iComponent[EUriPath].Set(*escapedUriPath);
  1.1304 +	iUri.iComponent[EUriHost].Set(KNullDesC16);
  1.1305 +	iUri.iComponent[EUriScheme].Set(KFileUriScheme16);
  1.1306 +	FormUriL();
  1.1307 +	
  1.1308 +	CleanupStack::PopAndDestroy(escapedUriPath);
  1.1309 +	CleanupStack::PopAndDestroy(escapedUriPath8);
  1.1310 +	}
  1.1311 +
  1.1312 +/**
  1.1313 +	Allocates and constructs a file URI object for a specified file.
  1.1314 +	 
  1.1315 +	- If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.	
  1.1316 +	- If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
  1.1317 +	
  1.1318 +	@since			9.1
  1.1319 +	@param			aFullFileName	A reference to a fully qualified filename 
  1.1320 +	@param			aFlags	A flag to indicate if the file exists on a fixed drive or removable media drive.
  1.1321 +					This is a TFileUriFlags value.
  1.1322 +	@return			A pointer to the newly created file URI (CUri16) object. 
  1.1323 +	@post			A fully constructed and initialized file URI (CUri16) object.
  1.1324 + */
  1.1325 +EXPORT_C CUri16* CUri16::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
  1.1326 +	{
  1.1327 +	//It should be called to construct a file URI for a public file stored on a fix drive 
  1.1328 +	// or on a removable media drive only
  1.1329 +	__ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1.1330 +		
  1.1331 +	CUri16* self = CUri16::NewLC();
  1.1332 +	self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
  1.1333 +	CleanupStack::Pop(self);
  1.1334 +	return self;
  1.1335 +	}
  1.1336 +	
  1.1337 +/**
  1.1338 +	Allocates and constructs a file URI object for a file that is private to the application.
  1.1339 +
  1.1340 +	- If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
  1.1341 +	- If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
  1.1342 +	
  1.1343 +	@since			9.1
  1.1344 +	@param			aRelativeFileName	A reference to the filename relative to the application's private directory.
  1.1345 +	@param			aDrive				Drive number, if the private file stored on fixed drive, otherwise not used
  1.1346 +										This is a TDriveNumber value
  1.1347 +	@param			aFlags				A flag to indicate if the file exists on a fixed drive or removable media drive.
  1.1348 +										This is a TFileUriFlags value.
  1.1349 +	@return			A pointer to the newly created file URI (CUri16) object. 
  1.1350 +	@post			A fully constructed and initialized file URI (CUri16) object.
  1.1351 +*/
  1.1352 +
  1.1353 +
  1.1354 +EXPORT_C CUri16* CUri16::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags) 
  1.1355 +	{
  1.1356 +	//It should be called to construct a file URI for the application's private file stored on a fix drive 
  1.1357 +	// or on a removable media drive only
  1.1358 +	__ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1.1359 +
  1.1360 +	CUri16* self = CUri16::NewLC();
  1.1361 +	self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
  1.1362 +	CleanupStack::Pop(self);
  1.1363 +	return self;
  1.1364 +	}
  1.1365 +
  1.1366 +
  1.1367 +//
  1.1368 +//
  1.1369 +// Implemetation of LOCAL functions for the File URI
  1.1370 +//
  1.1371 +//
  1.1372 +	
  1.1373 +/**
  1.1374 +	Function used to generate 16bit file uri using 1st parameter aFileName and 
  1.1375 +	2nd parameter aDrive for the application's private or a public file.
  1.1376 +	
  1.1377 +	This is called by API CreateFileUri() and CreatePrivateFileUri()to 
  1.1378 +	generate a filename.
  1.1379 +	
  1.1380 +	Note: The space allocated for the returned descriptor will likely be larger 
  1.1381 +		  than the length of the descriptor
  1.1382 +	
  1.1383 +	@leave			KErrBadName	A provided Drivename or filename is not valid 
  1.1384 +	@since			9.1
  1.1385 +	@param			aFileName	A descriptor reference to the filename.
  1.1386 +	@param			aDrive		A descriptor reference to drive letter.
  1.1387 +	@param			aFlags		A flag to indicate the private or a public file exists on removable media or a fixed drive.
  1.1388 +	@return			A pointer to a buffer containing the resolved fully qualified filename.
  1.1389 + */
  1.1390 +HBufC* GenerateFileUriPathL(const TDesC& aFileName, TDriveNumber aDrive,  TUint aFlags)
  1.1391 +	{
  1.1392 +	TInt origLength = aFileName.Length();
  1.1393 +
  1.1394 +	//Leaves with KErrBadName if filename length is out of range 
  1.1395 +	if (origLength == 0 || origLength > KMaxFileName)
  1.1396 +		{
  1.1397 +		User::Leave(KErrBadName);	
  1.1398 +		}
  1.1399 +		
  1.1400 +	TPtrC filename(aFileName);
  1.1401 +	
  1.1402 +	//extract drive letter and remove drive "x:" from filename
  1.1403 +	TUint drive = filename[0];
  1.1404 +	
  1.1405 +	 // hasDrive means it begins with a drive, e.g. "c:"
  1.1406 +	 const TBool hasDrive =  ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z')) && (filename[1] == KDriveSeparator);
  1.1407 +	 // hasTopPath means it begins with a \ (possibly after the drive)
  1.1408 +	 const TBool hasTopPath = (hasDrive && (filename[2] == KFilePathSeparator)) || (!hasDrive && (drive == TUint(KFilePathSeparator) ));
  1.1409 + 
  1.1410 +	 TInt skip = KDefaultPath().Length(); //  skip leading "<drive>:\" by default
  1.1411 +	 if(aFlags & TUint(EPrivate)) 
  1.1412 +		{
  1.1413 +		skip = (hasDrive ? (KDefaultPath().Length() - 1) : 0) + (hasTopPath ? 1 : 0) ;
  1.1414 +		}
  1.1415 +	 else
  1.1416 +		{
  1.1417 +		// if not private then it should have valid drive i.e. "<drive>:\"
  1.1418 +		if (!(hasDrive && hasTopPath)) 
  1.1419 +			{
  1.1420 +			User::Leave(KErrBadName);
  1.1421 +			}
  1.1422 +		}
  1.1423 +	
  1.1424 +	if(skip)
  1.1425 +		  {
  1.1426 +		  filename.Set(aFileName.Right(origLength - skip));
  1.1427 +		  } 	
  1.1428 +
  1.1429 +	TInt uriLen = aFileName.Length() + KExtMedia().Length() + KPrivate().Length() + 1 /* for drive letter */;
  1.1430 +	
  1.1431 +	HBufC* fileUri = HBufC::NewLC(uriLen);
  1.1432 +	TPtr fileUriPtr = fileUri->Des(); 
  1.1433 +	fileUriPtr.Append(KUriPathSeparator);
  1.1434 +	
  1.1435 +	if (aFlags & TUint(EPrivate))
  1.1436 +		{
  1.1437 +		fileUriPtr.Append(KPrivate);
  1.1438 +		drive = TInt16('A' + aDrive);
  1.1439 +		}
  1.1440 +		
  1.1441 +	if (aFlags & EExtMedia)
  1.1442 +		{
  1.1443 +		fileUriPtr.Append(KExtMedia);			
  1.1444 +		}
  1.1445 +	else
  1.1446 +		{
  1.1447 +		fileUriPtr.Append(drive);
  1.1448 +		fileUriPtr.Append(KUriPathSeparator);	
  1.1449 +		}
  1.1450 +		
  1.1451 +	fileUriPtr.Append(filename);
  1.1452 +		
  1.1453 +	//Convert "\" to "/"
  1.1454 +	ChangePathSeparator(fileUriPtr, KFilePathSeparator, KUriPathSeparator);
  1.1455 +
  1.1456 +	//Handling "./" and "../" in the file URI path  or resolving the URI path 
  1.1457 +	CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(fileUriPtr);
  1.1458 + 	// Clean up the path to resolve occurences of '..' and '.'
  1.1459 + 	CleanResolvedPathL<TPtrC>(resolvedPath);
  1.1460 + 	fileUriPtr.Copy(resolvedPath->Parser().Des()); // new path will always be shorter than old one
  1.1461 + 	CleanupStack::PopAndDestroy(resolvedPath);
  1.1462 + 		
  1.1463 +	CleanupStack::Pop(fileUri);
  1.1464 +	return fileUri;
  1.1465 +	}