os/ossrv/genericservices/httputils/UriParser/CUri.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2001-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 <escapeutils.h>
    17 #include <uri8.h>
    18 #include <uri16.h>
    19 #include <delimitedpath8.h>
    20 #include <delimitedpath16.h>
    21 #include <uriutilscommon.h>
    22 #include <uriutils.h>
    23 
    24 #include "UriUtilsInternal.h"
    25 #include "TUriCInternal.h"
    26 #include "CUriInternal.h"
    27 
    28 // Panic category
    29 //
    30 #ifdef _DEBUG
    31 	_LIT(KUriPanicCategory,"URI-CURI"); 
    32 #endif
    33 
    34 // Constants
    35 //
    36 _LIT(KFileUriPanicCategory,"FILEURI-CURI");
    37 
    38 
    39 
    40 
    41 //
    42 //
    43 // Implementation of CUri8
    44 //
    45 //
    46 
    47 /**
    48 	Static factory constructor. Uses two phase construction and leaves nothing on the 
    49 	CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
    50 	
    51 	@since			6.0
    52 	@param			aUri	A reference to a parsed uri object.
    53 	@return			A pointer to the newly created CUri8 object. 
    54 	@post			A fully constructed and initialized CUri8 object.
    55  */
    56 EXPORT_C CUri8* CUri8::NewL(const TUriC8& aUri)
    57 	{
    58 	CUri8* self = CUri8::NewLC(aUri);
    59 	CleanupStack::Pop(self);
    60 	return self;
    61 	}
    62 
    63 /**	
    64 	Static factory constructor. Uses two phase construction and leaves a pointer to 
    65 	created object on the CleanupStack. Creates a uri object which is a copy of the 
    66 	input parameter aUri.
    67 	
    68 	@since			6.0
    69 	@param			aUri	A reference to a parsed uri object.
    70 	@return			A pointer to the newly created CUri8 object. 
    71 	@post			A fully constructed and initialized CUri8 object.
    72  */
    73 EXPORT_C CUri8* CUri8::NewLC(const TUriC8& aUri)
    74 	{
    75 	CUri8* self = new (ELeave) CUri8(aUri);
    76 	CleanupStack::PushL(self);
    77 	self->ConstructL();
    78 	return self;
    79 	}
    80 	
    81 /**	
    82 	Static factory constructor. Uses two phase construction and leaves nothing on the 
    83 	CleanupStack. Creates a uri object which is empty.
    84 	
    85 	@since			6.0
    86 	@return			A pointer to the newly created CUri8 object. 
    87 	@post			A fully constructed and initialized CUri8 object.
    88  */
    89 EXPORT_C CUri8* CUri8::NewL()
    90 	{
    91 	CUri8* self = CUri8::NewLC();
    92 	CleanupStack::Pop(self);
    93 	return self;
    94 	}
    95 
    96 /**
    97 	Static factory constructor. Uses two phase construction and leaves a pointer to created 
    98 	object on the CleanupStack. Creates a uri object which is empty.
    99 	
   100 	@since			6.0
   101 	@return			A pointer to the newly created CUri8 object. 
   102 	@post			A fully constructed and initialized CUri8 object.
   103  */
   104 EXPORT_C CUri8* CUri8::NewLC()
   105 	{
   106 	CUri8* self = new (ELeave) CUri8(TUriC8());
   107 	CleanupStack::PushL(self);
   108 	self->ConstructL();
   109 	return self;
   110 	}
   111 
   112 /**	
   113 	Static factory constructor. This creates a CUri8 object that is an absolute uri resulting 
   114 	from a reference uri being resolved against a base uri.
   115 	
   116 	@warning		Ownership of created CUri8 object is transferred to the caller.
   117 	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
   118 	@since			6.0
   119 	@param			aBaseUri	A referece to the parsed base uri.
   120 	@param			aRefUri		A referece to the parsed reference uri.
   121 	@return			A pointer to the newly created CUri8 object.
   122 	@pre 			The base uri must have an absolute or empty path, otherwise will leave
   123 	with KUriErrBadBasePath.
   124 	@post			A fully constructed and initialized CUri8 object.
   125  */
   126 EXPORT_C CUri8* CUri8::ResolveL(const TUriC8& aBaseUri, const TUriC8& aRefUri)
   127 	{
   128 	// Check for a base Uri
   129 	if( aBaseUri.UriDes().Compare(KNullDesC8) == 0 )
   130 		{
   131 		// Empty base Uri - resolved Uri is the reference Uri
   132 		return NewL(aRefUri);
   133 		}
   134 	// See if ref has scheme and it is the same as base Uri
   135 	if( aRefUri.IsPresent(EUriScheme) && (aRefUri.Compare(aBaseUri, EUriScheme) != 0) )
   136 		{
   137 		// Ref has a scheme different to base Uri's - it is an absolute Uri
   138 		return NewL(aRefUri);
   139 		}
   140 	// Check for presence of components
   141 	TBool useBaseQuery = EFalse;
   142 	HBufC8* resolvedPath = FormResolvedPathLC<HBufC8>(aBaseUri, aRefUri, useBaseQuery);
   143 
   144 	//Removes dot segemnts in Resolved uri as specified in RFC3986 section 5.2.
   145 	RemoveExtraneousDotSegmentsL(resolvedPath);
   146 	
   147 	// Put the Uri together
   148 	TUriC8 uri;
   149 	FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
   150 
   151 	// Create the resolved Uri and cleanup
   152 	CUri8* resolvedUri = NewL(uri);
   153 	CleanupStack::PopAndDestroy(resolvedPath);
   154 
   155 	return resolvedUri;
   156 	}
   157 
   158 /**	
   159 	Destructor.
   160 	
   161 	@since			6.0
   162  */
   163 EXPORT_C CUri8::~CUri8()
   164 	{
   165 	delete iUriBuf;
   166 	}
   167 
   168 /**	
   169 	Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC8.
   170 	
   171 	@since			6.0
   172 	@return			A const reference to the parsed uri object.
   173  */
   174 EXPORT_C const TUriC8& CUri8::Uri() const
   175 	{
   176 	return iUri;
   177 	}
   178 
   179 /**	
   180 	Intended Usage	:	Sets the specified component in the uri. The component is set to the value 
   181 	given in the argument aData. If the specified component already exists  then it is replaced 
   182 	with the new value.
   183 	
   184 	@warning		The userinfo and port components can only be set if the host component
   185 	is present. Setting these components without a host component present will have no 
   186 	effect on the uri.
   187 	@since			6.0
   188 	@param			aData		A descriptor pointer to the new value for the uri component.
   189 	@param			aComponent	An enum specifying the component to be set.
   190 	@pre 			Object is fully constructed.
   191 	@post			The uri has the specified component set to the new value.
   192 	@Leave          KErrArgument  If aComponent goes out of range.
   193  */
   194 EXPORT_C void CUri8::SetComponentL(const TDesC8& aData, TUriComponent aComponent)
   195 	{
   196 	// Update the appropriate component table entry
   197 	iUri.iComponent[aComponent].Set(aData);
   198 
   199 	// Copy to the buffer by forming the uri
   200 	FormUriL();
   201 	}
   202 
   203 /**	
   204 	Removes the specified component from the uri. If the component does not exist then this function 
   205 	does nothing.
   206 	
   207 	@warning		If host is removed, then userinfo and port components will also
   208 	be removed.
   209 	@since			6.0
   210 	@param			aComponent	An enum specifying the component to be removed.
   211 	@pre 			Object is fully constructed.
   212 	@post			The uri is updated to exclude the specified component.
   213  */
   214 EXPORT_C void CUri8::RemoveComponentL(TUriComponent aComponent)
   215 	{
   216 	if( iUri.IsPresent(aComponent) )
   217 		{
   218 		// Remove the component - set pointer to NULL and length to zero
   219 		iUri.iComponent[aComponent].Set(NULL,0);
   220 
   221 		// Re-form buffer and component table
   222 		FormUriL();
   223 		}
   224 	}
   225 
   226 /**	
   227 	Constructor. First phase of two-phase construction method. Does	non-allocating construction.
   228 	
   229 	@since			6.0
   230 	@param			aUri	The parsed uri component information from which to create 
   231 	the uri.
   232 */
   233 CUri8::CUri8(const TUriC8& aUri)
   234 : CBase(), iUri(aUri)
   235 	{
   236 	}
   237 
   238 /**	
   239 	Second phase of two-phase construction method. Does any allocations required to fully construct 
   240 	the object.
   241 	
   242 	@since			6.0
   243 	@pre 			First phase of construction is complete.
   244 	@post			The object is fully constructed and initialized.
   245  */
   246 void CUri8::ConstructL()
   247 	{
   248 	// Create the HBufC
   249 	FormUriL();
   250 	}
   251 
   252 /**	
   253 	Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri 
   254 	is changed to refer to the copy.
   255 	
   256 	@since			6.0
   257 	@pre 			The parsed uri information is set.
   258 	@post			The uri buffer is updated with the parsed uri information.
   259  */
   260 void CUri8::FormUriL()
   261 	{
   262 	TBool isIPv6Host;
   263 
   264 	// Calculate length of of the Uri
   265 	TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
   266 
   267 	// Create a temporary buffer and descriptor pointer to it
   268 	HBufC8* buf = HBufC8::NewL(length);
   269 	TPtr8 uri = buf->Des();
   270 
   271 	// Create the uri, updating the internal uri object
   272 	DoFormUri(uri, iUri.iComponent, isIPv6Host);
   273 
   274 	// Update the internal buffer and descriptor pointer
   275 	delete iUriBuf;
   276 	iUriBuf = buf;
   277 	iUri.iUriDes.Set(iUriBuf->Des());
   278 	}
   279 
   280 //
   281 //
   282 // Implementation of CUri16
   283 //
   284 //
   285 
   286 /**	
   287 	Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack. 
   288 	Creates a uri object which is a copy of the input parameter aUri.
   289 	
   290 	@deprecated Deprecated in 9.1
   291 	@since			6.0
   292 	@param			aUri	A reference to a parsed uri object.
   293 	@return			A pointer to the newly created CUri16 object. 
   294 	@post			A fully constructed and initialized CUri16 object.
   295  */
   296 EXPORT_C CUri16* CUri16::NewL(const TUriC16& aUri)
   297 	{
   298 	CUri16* self = CUri16::NewLC(aUri);
   299 	CleanupStack::Pop(self);
   300 	return self;
   301 	}
   302 
   303 /**	
   304 	Static factory constructor. Uses two phase construction and leaves a pointer to created object on 
   305 	the CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
   306 	
   307 	@since			6.0
   308 	@deprecated Deprecated in 9.1
   309 	@param			aUri	A reference to a parsed uri object.
   310 	@return			A pointer to the newly created CUri16 object. 
   311 	@post			A fully constructed and initialized CUri16 object.
   312  */
   313 EXPORT_C CUri16* CUri16::NewLC(const TUriC16& aUri)
   314 	{
   315 	CUri16* self = new (ELeave) CUri16(aUri);
   316 	CleanupStack::PushL(self);
   317 	self->ConstructL();
   318 	return self;
   319 	}
   320 
   321 /**
   322 	Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack. 
   323 	Creates a uri object which is empty.
   324 	
   325 	@since			6.0
   326 	@deprecated Deprecated in 9.1
   327 	@return			A pointer to the newly created CUri16 object. 
   328 	@post			A fully constructed and initialized CUri16 object.
   329  */
   330 EXPORT_C CUri16* CUri16::NewL()
   331 	{
   332 	CUri16* self = CUri16::NewLC();
   333 	CleanupStack::Pop(self);
   334 	return self;
   335 	}
   336 
   337 /**
   338 	Static factory constructor. Uses two phase construction and leaves a pointer to created object on 
   339 	the CleanupStack. Creates a uri object which is empty.
   340 	
   341 	@since			6.0
   342 	@deprecated Deprecated in 9.1
   343 	@return			A pointer to the newly created CUri16 object. 
   344 	@post			A fully constructed and initialized CUri16 object.
   345  */
   346 EXPORT_C CUri16* CUri16::NewLC()
   347 	{
   348 	CUri16* self = new (ELeave) CUri16(TUriC16());
   349 	CleanupStack::PushL(self);
   350 	self->ConstructL();
   351 	return self;
   352 	}
   353 
   354 /**	
   355 	Static factory constructor. This creates a CUri16 object that is an absolute uri resulting from a 
   356 	reference uri being resolved against a base uri.
   357 	
   358 	@warning		Ownership of created CUri16 object is transferred to caller.
   359 	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
   360 	@since			6.0
   361 	@deprecated Deprecated in 9.1
   362 	@param			aBaseUri	A referece to the parsed base uri.
   363 	@param			aRefUri		A referece to the parsed reference uri.
   364 	@return			A pointer to the newly created CUri16 object.
   365 	@pre 			The base uri must have an absolute or empty path, otherwise will leave
   366 	with KUriErrBadBasePath.
   367 	@post			A fully constructed and initialized CUri16 object.
   368  */
   369 EXPORT_C CUri16* CUri16::ResolveL(const TUriC16& aBaseUri, const TUriC16& aRefUri)
   370 	{
   371 	// Check for a base Uri
   372 	if( aBaseUri.UriDes().Compare(KNullDesC16) == 0 )
   373 		{
   374 		// Empty base Uri - resolved Uri is the reference Uri
   375 		return NewL(aRefUri);
   376 		}
   377 	// See if ref has scheme and it is the same as base Uri
   378 	if( aRefUri.IsPresent(EUriScheme) && aRefUri.Compare(aBaseUri, EUriScheme) != 0 )
   379 		{
   380 		// Ref has a scheme different to base Uri's - it is an absolute Uri
   381 		return NewL(aRefUri);
   382 		}
   383 	// Check for presence of components
   384 	TBool useBaseQuery = EFalse;
   385 	HBufC16* resolvedPath = FormResolvedPathLC<HBufC16>(aBaseUri, aRefUri, useBaseQuery);
   386 
   387 	// Put the Uri together
   388 	TUriC16 uri;
   389 	FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
   390 
   391 	// Create the resolved Uri and cleanup
   392 	CUri16* resolvedUri = NewL(uri);
   393 	CleanupStack::PopAndDestroy(resolvedPath);
   394 
   395 	return resolvedUri;
   396 	}
   397 
   398 /**	
   399 	Destructor.
   400 	
   401 	@since			6.0
   402 	@deprecated Deprecated in 9.1
   403  */
   404 EXPORT_C CUri16::~CUri16()
   405 	{
   406 	delete iUriBuf;
   407 	}
   408 
   409 /**	
   410 	Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC16.
   411 	
   412 	@since			6.0
   413 	@deprecated Deprecated in 9.1
   414 	@return			A const reference to the parsed uri object.
   415  */
   416 EXPORT_C const TUriC16& CUri16::Uri() const
   417 	{
   418 	return iUri;
   419 	}
   420 
   421 /**
   422 	Sets the specified component in the uri. The component is set to the value given in the argument 
   423 	aData. If the specified component already exists then it is replaced with the new value.
   424 	
   425 	@warning		The userinfo and port components can only be set if the host component
   426 	is present. Setting these components without a host component present will have no 
   427 	effect on the uri.
   428 	@since			6.0
   429 	@deprecated Deprecated in 9.1
   430 	@param			aData		A descriptor pointer to the new value for the uri component.
   431 	@param			aComponent	An enum specifying the component to be set.
   432 	@pre 			Object is fully constructed.
   433 	@post			The uri has the specified component set to the new value.
   434 	@Leave          KErrArgument  If aComponent goes out of range.
   435  */
   436 EXPORT_C void CUri16::SetComponentL(const TDesC16& aData, TUriComponent aComponent)
   437 	{
   438 	// Update the appropriate component table entry
   439 	iUri.iComponent[aComponent].Set(aData);
   440 
   441 	// Copy to the buffer by forming the uri
   442 	FormUriL();
   443 	}
   444 
   445 /**
   446 	Removes the specified component from the uri. If the component does not exist then this function 
   447 	does nothing.
   448 	
   449 	@warning		If host is removed, then userinfo and port components will also
   450 	be removed.
   451 	@since			6.0
   452 	@deprecated Deprecated in 9.1
   453 	@param			aComponent	An enum specifying the component to be removed.
   454 	@pre 			Object is fully constructed.
   455 	@post			The uri is updated to exclude the specified component.
   456  */
   457 EXPORT_C void CUri16::RemoveComponentL(TUriComponent aComponent)
   458 	{
   459 	if( iUri.IsPresent(aComponent) )
   460 		{
   461 		// Remove the component - set pointer to NULL and length to zero
   462 		iUri.iComponent[aComponent].Set(NULL,0);
   463 
   464 		// Re-form buffer and component table
   465 		FormUriL();
   466 		}
   467 	}
   468 
   469 /**
   470 	Constructor. First phase of two-phase construction method. Does	non-allocating construction.
   471 	
   472 	@since			6.0
   473 	@param			aUri	The parsed uri component information from which to create
   474 	the uri.
   475  */
   476 
   477 CUri16::CUri16(const TUriC16& aUri)
   478 : CBase(), iUri(aUri)
   479 	{
   480 	}
   481 
   482 /**
   483 	Second phase of two-phase construction method. Does any allocations required to fully construct 
   484 	the object.
   485 	
   486 	@since			6.0
   487 	@pre 			First phase of construction is complete.
   488 	@post			The object is fully constructed and initialized.
   489  */
   490 void CUri16::ConstructL()
   491 	{
   492 	// Create the HBufC
   493 	FormUriL();
   494 	}
   495 
   496 /**
   497 	Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri 
   498 	is changed to refer to the copy.
   499 	
   500 	@since			6.0
   501 	@pre 			The parsed uri information is set.
   502 	@post			The uri buffer is updated with the parsed uri information.
   503  */
   504 void CUri16::FormUriL()
   505 	{
   506 	TBool isIPv6Host;
   507 
   508 	// Calculate length of of the Uri
   509 	TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
   510 
   511 	// Create a temporary buffer and descriptor pointer to it
   512 	HBufC16* buf = HBufC16::NewL(length);
   513 	TPtr16 uri = buf->Des();
   514 
   515 	// Create the uri, updating the internal uri object
   516 	DoFormUri(uri, iUri.iComponent, isIPv6Host);
   517 
   518 	// Update the internal buffer and descriptor pointer
   519 	delete iUriBuf;
   520 	iUriBuf = buf;
   521 	iUri.iUriDes.Set(iUriBuf->Des());
   522 	}
   523 
   524 //
   525 //
   526 // Implementation of templated LOCAL functions
   527 //
   528 //
   529 
   530 /**
   531 	Calculates the length of the uri from a list of the components.
   532 	
   533 	@since			6.0
   534 	@param			aComponent	The array of descriptor pointers to the uri 
   535 					components.
   536 	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
   537 	@return			The length of the uri including the required delimiters.	
   538 */
   539 template<class TPtrCType>
   540 TInt CalculateUriLength(const TPtrCType aComponent[], TBool& aIsIPv6Host)
   541 	{
   542 	TBool noAuthority = ETrue;
   543 	TInt length=0;
   544 	aIsIPv6Host=EFalse;
   545 	for( TInt i=0; i<EUriMaxComponents; ++i )
   546 		{
   547 		if( aComponent[i].Ptr() )
   548 			{
   549 			length += aComponent[i].Length();
   550 			if( noAuthority && (i==EUriUserinfo || i==EUriHost || i==EUriPort) )
   551 				{
   552 				// There's an authority part...
   553 				noAuthority = EFalse;
   554 				}
   555 			// Need to make space for a delimiter if not path or host
   556 			if( i!=EUriHost && i!=EUriPath )
   557 				++length;		
   558 			
   559 			// If it's an IPv6 hostname, need extra space for []
   560 			if(i==EUriHost && (UriUtils::HostType(aComponent[i])==UriUtils::EIPv6Host))
   561 				{
   562 				length+=2;				
   563 				aIsIPv6Host=ETrue;
   564 				}
   565 			}
   566 		}
   567 	if( !noAuthority && IsNetworkScheme(aComponent[EUriScheme]))
   568 		{
   569 		// Make space for authority delimiter
   570 		length += KUriNetworkAuthorityDelimiterLength;
   571 		}
   572 	return length;
   573 	}
   574 
   575 /**
   576 	Templated function to form a uri. The output argument aUri points to a descriptor 
   577 	buffer large enough to hold the uri. The new uri component information is given by 
   578 	the input/output argument aComponent. For each uri component that exists in aComponent,
   579 	that component and its appropriate delimiters are appended to aUri. Then the components 
   580 	in aComponent are updated to refer to the copies versions in aUri.
   581 						
   582 	@since			6.0
   583 	@param			aUri		The descriptor pointer to buffer to be appended.
   584 	@param			aComponent	The array of descriptor pointers to be copied and 
   585 					then updated.
   586 	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
   587 	@pre 			The buffer pointed to by aUri should be large enough to have the uri 
   588 					components given in aNewComponent copied into it, as well as the required delimiters.
   589 					This can be obtained using CalculateUriLength().
   590 	@post			The uri buffer pointed to by aUri will have a copy of the uri defined 
   591 					in aComponent, and then aComponent will refer to the copies of these components in aUri.
   592 */
   593 template<class TPtrType, class TPtrCType>
   594 void DoFormUri(TPtrType& aUri, TPtrCType aComponent[], TBool& aIsIPv6Host)
   595 	{
   596 	TBool isNetworkScheme = ETrue;
   597 	if( aComponent[EUriScheme].Ptr() )
   598 		{
   599 		// Update the scheme
   600 		SetScheme(aUri, aComponent[EUriScheme]);
   601 		isNetworkScheme = IsNetworkScheme(aComponent[EUriScheme]);
   602 		}
   603 	if( aComponent[EUriHost].Ptr() )
   604 		{
   605 		// Update the authority - only needed if there is a host; update userinfo, host and port
   606 		SetAuthority(aUri, aComponent[EUriUserinfo], aComponent[EUriHost], aComponent[EUriPort], aIsIPv6Host, isNetworkScheme);
   607 		}
   608 	else
   609 		{
   610 		// Ensure that there is no userinfo or port components if there is no host 
   611 		// - set pointer to NULL and length to zero
   612 		aComponent[EUriUserinfo].Set(NULL,0);
   613 		aComponent[EUriPort].Set(NULL,0);
   614 		}
   615 	if( aComponent[EUriPath].Ptr() )
   616 		{
   617 		// Update the path
   618 		SetPath(aUri, aComponent[EUriPath]);
   619 		}
   620 	if( aComponent[EUriQuery].Ptr() )
   621 		{
   622 		// Update the query
   623 		SetQuery(aUri, aComponent[EUriQuery]);
   624 		}
   625 	if( aComponent[EUriFragment].Ptr() )
   626 		{
   627 		// Update the fragment
   628 		SetFragment(aUri, aComponent[EUriFragment]);
   629 		}
   630 	}
   631 
   632 /**
   633 	Templated function to set the scheme in a uri. The output argument aUri points to the descriptor 
   634 	buffer into which aScheme will be copied.The argument aScheme is then updated to point to the 
   635 	copied version in aUri.
   636 						
   637 	@warning		This function will panic with KUriErrBufferOverflow if there is not
   638 					enough space in the descriptor to append the scheme and the required delimiter.
   639 	@since			6.0
   640 	@param			aUri	The descriptor pointer to buffer to be appended.
   641 	@param			aScheme	The descriptor pointer to the scheme component to be copied 
   642 					and then updated.
   643 	@pre 			The buffer pointed to by aUri should be large enough to have aNewScheme
   644 					appended to it with the required delimiter. This can be obtained using CalculateUriLength().
   645 	@post			The uri buffer now includes a copy of aScheme and aScheme points to the 
   646 					copy of the scheme component in aUri.
   647 */
   648 template<class TPtrType, class TPtrCType>
   649 void SetScheme(TPtrType& aUri, TPtrCType& aScheme)
   650 	{
   651 	__ASSERT_DEBUG(aUri.Length() + aScheme.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   652 
   653 	// Append the scheme and delimiter
   654 	aUri.Append(aScheme);
   655 	aUri.Append(KSchemeDelimiter);
   656 
   657 	// Update the component table to use the copy
   658 	aScheme.Set(aUri.Left(aScheme.Length()));
   659 	}
   660 	
   661 /**
   662 	Templated function to set the authority in a uri. The output argument aUri points to the descriptor 
   663 	buffer into which aUserinfo, aHost and aPort will be copied. The arguments aUserinfo, aHost and aPort 
   664 	are updated to point to the copied versions in aUri.
   665 						
   666 	@warning		This function will panic with KUriErrBufferOverflow if there 
   667 					is not enough space in the descriptor to append the components and any required 
   668 					delimiters. 
   669 	@since			6.0
   670 	@param			aUri		The descriptor pointer to buffer to be appended.
   671 	@param			aUserinfo	The descriptor pointer to the userinfo component to 
   672 					be copied and then updated.
   673 	@param			aHost		The descriptor pointer to the host component to 
   674 					be copied and then updated.
   675 	@param			aPort		The descriptor pointer to the port component to 
   676 					be copied and then updated.
   677 	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
   678 	@param			aUseNetworkDelimiter EFalse if this is a SIP scheme otherwise ETrue
   679 	@pre 			The buffer pointed to by aUri should be large enough to have 
   680 					aUserinfo, aHost and aPort appended to it with the required delimiters.
   681 					This can be obtained using CalculateUriLength().
   682 	@post			The uri buffer now includes a copy of aUserinfo, aHost and
   683 					aPort, and aUserinfo, aHost and aPort will refer to the copies versions in aUri.
   684 */
   685 template<class TPtrType, class TPtrCType>
   686 void SetAuthority(TPtrType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool& aIsIPv6Host, TBool aUseNetworkDelimiter)
   687 	{
   688 	__ASSERT_DEBUG(aUri.Length() + aHost.Length() + (aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength:0) <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   689 	
   690 	if (aUseNetworkDelimiter)
   691 		{
   692 		// If a network scheme append authority delimiter (TWO slash delimiters!)
   693 		aUri.Append(KSlashDelimiter);
   694 		aUri.Append(KSlashDelimiter);
   695 		}
   696 
   697 	// Check for userinfo
   698 	if( aUserinfo.Ptr() )
   699 		{
   700 		__ASSERT_DEBUG(aUri.Length() + aUserinfo.Length() + aHost.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   701 
   702 		// Append userinfo and update the component table to use copy
   703 		aUri.Append(aUserinfo);
   704 		aUserinfo.Set(aUri.Right(aUserinfo.Length()));
   705 
   706 		// Append delimiter
   707 		aUri.Append(KUserinfoDelimiter);
   708 		}
   709 	// There's always a host - append and update the component table to use the copy
   710 	
   711 	// Check if it's an IPv6 address
   712 	if ( aIsIPv6Host )
   713 		{
   714 		aUri.Append(KIPv6UriOpenBrace); 
   715 		aUri.Append(aHost);
   716 		aUri.Append(KIPv6UriCloseBrace);
   717 		// Dont include the braces in the host
   718 		// Position = (length of uri - length of host) - length of end brace
   719 		aHost.Set( aUri.Mid((aUri.Length()-aHost.Length())-1, aHost.Length()) );
   720 		}
   721 	else
   722 		{
   723 		aUri.Append(aHost);
   724 		aHost.Set(aUri.Right(aHost.Length()));
   725 		}
   726 	
   727 	// Check for a port
   728 	if( aPort.Ptr() )
   729 		{
   730 		__ASSERT_DEBUG(aUri.Length() + aPort.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   731 				   
   732 		// Append delimiter
   733 		aUri.Append(KPortDelimiter);
   734 	
   735 		// Append port and update the component table to use copy
   736 		aUri.Append(aPort);
   737 		aPort.Set(aUri.Right(aPort.Length()));
   738 		}
   739 	}
   740 /**
   741 	Templated function to set the path in a uri. The output argument aUri points to the descriptor 
   742 	buffer into which aPath will be copied.The argument aPath is then updated to point to the copied 
   743 	version in aUri.
   744 						
   745 	@warning		This function will panic with KUriErrBufferOverflow if there 
   746 					is not enough space in the descriptor to append the path.
   747 	@since			6.0
   748 	@param			aUri	The descriptor pointer to buffer to be appended.
   749 	@param			aPath	The descriptor pointer to the path component to be copied 
   750 					and then updated.
   751 	@pre 			The buffer pointed to by aUri should be large enough to have 
   752 					aPath appended to it. This can be obtained using CalculateUriLength().
   753 	@post			The uri buffer now includes a copy of aPath and aPath points to the 
   754 					copy of the path component in aUri.
   755 */
   756 template<class TPtrType, class TPtrCType>
   757 void SetPath(TPtrType& aUri, TPtrCType& aPath)
   758 	{
   759 	__ASSERT_DEBUG(aUri.Length() + aPath.Length() <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   760 
   761 	// Append the path
   762 	aUri.Append(aPath);
   763 
   764 	// Update the component table
   765 	aPath.Set(aUri.Right(aPath.Length()));
   766 	}
   767 
   768 /**
   769 	Templated function to set the query in a uri. The output argument aUri points to the descriptor 
   770 	buffer into which aQuery will be copied. The argument aQuery is then updated to point to the copied 
   771 	version in aUri.
   772 						
   773 	@warning		This function will panic with KUriErrBufferOverflow if there 
   774 					is not enough space in the descriptor to append the query and the delimiter.
   775 	@since			6.0
   776 	@param			aUri	The descriptor pointer to buffer to be appended.
   777 	@param			aQuery	The descriptor pointer to the query component to be copied 
   778 					and then updated.
   779 	@pre 			The buffer pointed to by aUri should be large enough to have 
   780 					aQuery appended to it. This can be obtained using CalculateUriLength().
   781 	@post			The uri buffer now includes a copy of aQuery and aQuery points to the 
   782 					copy of the query component in aUri.
   783 */
   784 template<class TPtrType, class TPtrCType>
   785 void SetQuery(TPtrType& aUri, TPtrCType& aQuery)
   786 	{
   787 	__ASSERT_DEBUG(aUri.Length() + aQuery.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   788 
   789 	// Append delimiter and the query
   790 	aUri.Append(KQueryDelimiter);
   791 	aUri.Append(aQuery);
   792 
   793 	// Update the component table
   794 	aQuery.Set(aUri.Right(aQuery.Length()));
   795 	}
   796 
   797 /**
   798 	Templated function to set the fragment in a uri. The output argument aUri points to the descriptor 
   799 	buffer into which aFragment will be copied. The argument aFragment is then updated to point to the 
   800 	copied version in aUri.
   801 						
   802 	@warning		This function will panic with KUriErrBufferOverflow if there 
   803 					is not enough space in the descriptor to append the fragment and the delimiter.
   804 	@since			6.0
   805 	@param			aUri		The descriptor pointer to buffer to be appended.
   806 	@param			aFragment	The descriptor pointer to the fragment component
   807 					to be copied and then updated.
   808 	@pre 			The buffer pointed to by aUri should be large enough to have 
   809 					aFragment appended to it. This can be obtained using CalculateUriLength().
   810 	@post			The uri buffer now includes a copy of aFragment and aFragment points 
   811 					to the copy of the fragment component in aUri.
   812 */
   813 template<class TPtrType, class TPtrCType>
   814 void SetFragment(TPtrType& aUri, TPtrCType& aFragment)
   815 	{
   816 	__ASSERT_DEBUG(aUri.Length() + aFragment.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
   817 
   818 	// Append delimiter and the fragment
   819 	aUri.Append(KFragmentDelimiter);
   820 	aUri.Append(aFragment);
   821 
   822 	// Update the component table
   823 	aFragment.Set(aUri.Right(aFragment.Length()));
   824 	}
   825 
   826 /**
   827 	Forms the resolved path. Checks to see if the base query needs to be used in the resolved uri. 
   828 	The pointer to the resolved path is left on the cleanup stack.
   829 						
   830 	@since			6.0
   831 	@param			aBaseUri		The base uri.
   832 	@param			aRefUri			The reference uri.
   833 	@param			aUseBaseQuery	An output argument specifying whether the base
   834 					query should be used in the resolved uri.
   835 	@return			A pointer to a buffer that contains the resolved path.
   836 */
   837 template<class HBufCType, class TUriCType>
   838 HBufCType* FormResolvedPathLC(const TUriCType& aBaseUri, const TUriCType& aRefUri, TBool& aUseBaseQuery)
   839 	{
   840 	HBufCType* resolvedPath = NULL;
   841 	if( !aRefUri.IsPresent(EUriScheme) && !aRefUri.IsPresent(EUriHost) && !aRefUri.Extract(EUriPath).Length() && !aRefUri.IsPresent(EUriQuery) )
   842 		{
   843 		// Ref is just a fragment
   844 		aUseBaseQuery = ETrue;
   845 		resolvedPath = aBaseUri.Extract(EUriPath).AllocLC();
   846 		}
   847 	else if( aRefUri.IsPresent(EUriHost) )
   848 		{
   849 		// Ref is a network path
   850 		resolvedPath = aRefUri.Extract(EUriPath).AllocLC();
   851 		}
   852 	else
   853 		{
   854 		// Need to some path resolving...
   855 		resolvedPath = ResolvePathsL(aBaseUri.Extract(EUriPath), aRefUri.Extract(EUriPath));
   856 		CleanupStack::PushL(resolvedPath);
   857 		}
   858 	return resolvedPath;
   859 	}
   860 
   861 /**
   862 	Cleans up a resolved path. This deals with occurences of '.' and '..' where these are complete 
   863 	path segments.
   864 						
   865 	@since			6.0
   866 	@param			aResolvedPath	The delimited data object that contains the 
   867 					resolved path.
   868 	@pre 			The input/output argument contains the path to be cleaned.
   869 	@post			The resolved path has had all the occurences of '.' and '..' 
   870 					processed and has been updated to contain the cleaned path.
   871  */
   872 template<class TPtrCType, class CDelimitedDataBaseType>
   873 void CleanResolvedPathL(CDelimitedDataBaseType* aResolvedPath)
   874 	{
   875 	// Create a modifiable path object for resolved path
   876 	aResolvedPath->Parse();
   877 
   878 	TBool done = EFalse;
   879 	while( !done )
   880    		{
   881    		// Get the next segment
   882    		TPtrCType segment;
   883    		TInt more = aResolvedPath->Parser().Peek(segment);
   884 
   885    		if( more == KErrNotFound )
   886    			{
   887    			// No more segments - done
   888    			done = ETrue;
   889    			}
   890    		else if( IsParentDir(segment) )
   891    			{
   892    			// Found a '..' - remove '..' from path, and remove previous segment
   893 			aResolvedPath->RemoveCurrentL();
   894 			if( aResolvedPath->Parser().Dec() == KErrNotFound )
   895 				{
   896 				// No previous directory - put back '..' and stop
   897 				InsertParentDirL(aResolvedPath);
   898 				done = ETrue;
   899 				}
   900 			else
   901 				{
   902 				// Remove the parent directory
   903 				aResolvedPath->RemoveCurrentL();
   904 				if( aResolvedPath->Parser().Eos() )
   905 					{
   906 					// '..' is the last segment - add a '/' to the path (add empty segment)
   907 					aResolvedPath->AddBackDelimiterL();
   908 					done = ETrue;
   909 					}
   910 				}
   911 			}
   912    		else if( IsSameDir(segment) )
   913    			{
   914    			// Found a '.' - remove -.- from the path
   915 			aResolvedPath->RemoveCurrentL();
   916 			if( aResolvedPath->Parser().Eos() )
   917 				{
   918 				// '..' is the last segment - add a '/' to the path (add empty segment)
   919 				aResolvedPath->AddBackDelimiterL();
   920 				done = ETrue;
   921 				}
   922 			}
   923    		else
   924    			{
   925    			// Segment wasn't '.' or '..' - parse to next segment
   926    			aResolvedPath->Parser().Inc();
   927    			}
   928    		}
   929 	}
   930 
   931 /**
   932 	Forms the resolved uri. Sets the components for the resolved uri from those in the base uri and 
   933 	the reference uri. The resolved path is given by the input argument aResolvedPath
   934 						
   935 	@since			6.0
   936 	@param			aComponent		The array of components to be set for the resolved uri.
   937 	@param			aBaseUri		The base uri.
   938 	@param			aRefUri			The reference uri.
   939 	@param			aResolvedPath	The resolved path.
   940 	@param			aUseBaseQuery	A boolean indicating whether the base query 
   941 					should be used.
   942 */
   943 template<class TPtrCType, class TUriCType, class HBufCType>
   944 void FormResolvedUri(TPtrCType aComponent[], const TUriCType& aBaseUri, const TUriCType& aRefUri, const HBufCType* aResolvedPath, TBool aUseBaseQuery)
   945 	{
   946 	// Scheme...
   947 	if( aBaseUri.IsPresent(EUriScheme) )
   948 		{
   949 		// Use the base scheme
   950 		aComponent[EUriScheme].Set(aBaseUri.Extract(EUriScheme));
   951 		}
   952 	// Authority
   953 	if( aRefUri.IsPresent(EUriHost) )
   954 		{
   955 		// Use the ref host, userinfo and port - must set host first
   956 		aComponent[EUriHost].Set(aRefUri.Extract(EUriHost));
   957 		aComponent[EUriUserinfo].Set(aRefUri.Extract(EUriUserinfo));
   958 		aComponent[EUriPort].Set(aRefUri.Extract(EUriPort));
   959 		}
   960 	else if( aBaseUri.IsPresent(EUriHost) )
   961 		{
   962 		// Use the base host, userinfo and port - must set host first
   963 		aComponent[EUriHost].Set(aBaseUri.Extract(EUriHost));
   964 		aComponent[EUriUserinfo].Set(aBaseUri.Extract(EUriUserinfo));
   965 		aComponent[EUriPort].Set(aBaseUri.Extract(EUriPort));
   966 		}
   967 	// Path...
   968 	aComponent[EUriPath].Set(*aResolvedPath);
   969 
   970 	// Query...
   971 	if( aUseBaseQuery && aBaseUri.IsPresent(EUriQuery) )
   972 		{
   973 		// Use the query from the base
   974 		aComponent[EUriQuery].Set(aBaseUri.Extract(EUriQuery));
   975 		}
   976 	else if( aRefUri.IsPresent(EUriQuery) )
   977 		{
   978 		// Use the query from the ref
   979 		aComponent[EUriQuery].Set(aRefUri.Extract(EUriQuery));
   980 		}
   981 	// Fragment
   982 	if( aRefUri.IsPresent(EUriFragment) )
   983 		{
   984 		// Use the fragment from the ref
   985 		aComponent[EUriFragment].Set(aRefUri.Extract(EUriFragment));
   986 		}
   987 	}
   988 
   989 //
   990 //
   991 // Implemetation of LOCAL functions
   992 //
   993 //
   994 
   995 /**
   996 	Function used to resolve a base path (aBasePath) against a reference path (aRefPath),
   997 	as described by RFC2396.
   998 						
   999 	@since			6.0
  1000 	@param			aBasePath	A descriptor reference to the base path.
  1001 	@param			aRefPath	A descriptor reference to the reference path.
  1002 	@return			A pointer to a buffer containing the resolve path.
  1003 	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
  1004 */
  1005 HBufC8* ResolvePathsL(const TDesC8& aBasePath, const TDesC8& aRefPath)
  1006 	{
  1007 	TInt refLength = aRefPath.Length();
  1008 	if( refLength && aRefPath[0] == KSlashDelimiter )
  1009 		{
  1010 		// Relative path is absolute - that is the resolved path
  1011 		return aRefPath.AllocL();
  1012 		}
  1013 	// Ok got work to do - base path must be absolute (check 1st char) or empty
  1014 	if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
  1015 		{
  1016 		// Base path not empty and not abosolute - bad base path
  1017 		User::Leave(KUriUtilsErrBadBasePath);
  1018 		}
  1019 	// Create a modifiable path object for resolved path
  1020 	CDelimitedPath8* resolvedPath = CDelimitedPath8::NewLC(aBasePath);
  1021 
  1022 	// Check for empty ref path - use all of base path if empty
  1023 	if( refLength )
  1024 		{
  1025 		// Not empty - ensure that base path's last segment is removed and add reference
  1026 		resolvedPath->PopBackL();
  1027 		resolvedPath->PushBackL(aRefPath);
  1028 		}
  1029 	// Clean up the path to resolve occurences of '..' and '.' - parser path first
  1030 	CleanResolvedPathL<TPtrC8>(resolvedPath);
  1031 
  1032 	// Return pointer to HBufC with path
  1033 	HBufC8* path = resolvedPath->Parser().Des().AllocL();
  1034 	CleanupStack::PopAndDestroy(resolvedPath);
  1035 	return path;
  1036 	}
  1037 
  1038 /**
  1039 	Function used to resolve a base path (aBasePath) against a reference path (aRefPath), 
  1040 	as described by RFC2396.
  1041 						
  1042 	@since			6.0
  1043 	@param			aBasePath	A descriptor reference to the base path.
  1044 	@param			aRefPath	A descriptor reference to the reference path.
  1045 	@return			A pointer to a buffer containing the resolve path.
  1046 	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
  1047 */
  1048 HBufC16* ResolvePathsL(const TDesC16& aBasePath, const TDesC16& aRefPath)
  1049 	{
  1050 	TInt refLength = aRefPath.Length();
  1051 	if( refLength && aRefPath[0] == KSlashDelimiter )
  1052 		{
  1053 		// Relative path is absolute - that is the resolved path
  1054 		return aRefPath.AllocL();
  1055 		}
  1056 	// Ok got work to do - base path must be absolute (check 1st char) or empty
  1057 	if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
  1058 		{
  1059 		// Base path not empty and not abosolute - bad base path
  1060 		User::Leave(KUriUtilsErrBadBasePath);
  1061 		}
  1062 	// Create a modifiable path object for resolved path
  1063 	CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(aBasePath);
  1064 
  1065 	// Check for empty ref path - use all of base path if empty
  1066 	if( refLength )
  1067 		{
  1068 		// Not empty - ensure that base path's last segment is removed and add reference
  1069 		resolvedPath->PopBackL();
  1070 		resolvedPath->PushBackL(aRefPath);
  1071 		}
  1072 	// Clean up the path to resolve occurences of '..' and '.' - parser path first
  1073 	CleanResolvedPathL<TPtrC16>(resolvedPath);
  1074 
  1075 	// Return pointer to HBufC with path
  1076 	HBufC16* path = resolvedPath->Parser().Des().AllocL();
  1077 	CleanupStack::PopAndDestroy(resolvedPath);
  1078 	return path;
  1079 	}
  1080 	
  1081 /**
  1082 	Checks if the segment is '.' (8-bit version).
  1083 	
  1084 	@since			6.0
  1085 	@param			aSegment	A descriptor with the segment to check.
  1086 	@return			A boolean value of ETrue if the segment is '.', EFalse if not.
  1087 */
  1088 TBool IsSameDir(const TDesC8& aSegment)
  1089 	{
  1090 	_LIT8(KSameDir, ".");
  1091 	return (aSegment.Compare(KSameDir) == 0);
  1092 	}
  1093 	
  1094 /**
  1095 	Checks if the segment is '.' (16-bit version).
  1096 	
  1097 	@since			6.0
  1098 	@param			aSegment	A descriptor with the segment to check.
  1099 	@return			A boolean value of ETrue if the segment is '.', EFalse if not.
  1100 */
  1101 TBool IsSameDir(const TDesC16& aSegment)
  1102 	{
  1103 	_LIT16(KSameDir, ".");
  1104 	return (aSegment.Compare(KSameDir) == 0);
  1105 	}
  1106 	
  1107 /**
  1108 	Checks if the segment is '..' (8-bit version).
  1109 	
  1110 	@since			6.0
  1111 	@param			aSegment	A descriptor with the segment to check.
  1112 	@return			A boolean value of ETrue if the segment is '..', EFalse if not.
  1113 */
  1114 TBool IsParentDir(const TDesC8& aSegment)
  1115 	{
  1116 	_LIT8(KParentDir, "..");
  1117 	return (aSegment.Compare(KParentDir) == 0);
  1118 	}
  1119 
  1120 /**
  1121 	Checks if the segment is '..' (16-bit version).
  1122 	
  1123 	@since			6.0
  1124 	@param			aSegment	A descriptor with the segment to check.
  1125 	@return			A boolean value of ETrue if the segment is '..', EFalse if not.
  1126 */
  1127 TBool IsParentDir(const TDesC16& aSegment)
  1128 	{
  1129 	_LIT16(KParentDir, "..");
  1130 	return (aSegment.Compare(KParentDir) == 0);
  1131 	}
  1132 
  1133 /**
  1134 	Inserts the segment '..' at the current parsed position (8-bit version).
  1135 						
  1136 	@since			6.0
  1137 	@param			aResolvedPath	The delimited data object to have the segment
  1138 					inserted.
  1139 	@pre			The delimited data object must be parsed to the position where 
  1140 					the segment is to be inserted.
  1141 	@post			The segment '..' has been inserted at the current position.
  1142 */
  1143 void InsertParentDirL(CDelimitedDataBase8* aResolvedPath)
  1144 	{
  1145 	_LIT8(KParentDir, "..");
  1146 	aResolvedPath->InsertCurrentL(KParentDir);
  1147 	}
  1148 	
  1149 /**
  1150 	Inserts the segment '..' at the current parsed position (16-bit version).
  1151 						
  1152 	@since			6.0
  1153 	@param			aResolvedPath	The delimited data object to have the segment
  1154 					inserted.
  1155 	@pre			The delimited data object must be parsed to the position where 
  1156 					the segment is to be inserted.
  1157 	@post			The segment '..' has been inserted at the current position.
  1158 */
  1159 void InsertParentDirL(CDelimitedDataBase16* aResolvedPath)
  1160 	{
  1161 	_LIT16(KParentDir, "..");
  1162 	aResolvedPath->InsertCurrentL(KParentDir);
  1163 	}
  1164 	
  1165 
  1166 //
  1167 //
  1168 // File URI Implementation - CUri8
  1169 //
  1170 //
  1171 
  1172 /**
  1173 	Initializes the file URI components (scheme, empty hostname and path).	 
  1174 	
  1175 	It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive. 
  1176 	
  1177 	@since			9.1
  1178 	@param			aFileName	A reference to a filename 
  1179 	@param			aDrive		A drive number. This is a TFileUriFlags value.
  1180 	@param			aFlags		A flag to indicate if the file exists on a fixed drive or removable media drive.
  1181 					This is a TFileUriFlags value.
  1182 	@pre 			Object fully constructed
  1183 	@post			The object is initialized with file URI components.
  1184  */
  1185 void CUri8::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
  1186 	{
  1187 	HBufC* uriPath16 = GenerateFileUriPathL(aFileName, aDrive, aFlags);
  1188 	CleanupStack::PushL(uriPath16);
  1189 	HBufC8* uriPath = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath16);
  1190 	CleanupStack::PopAndDestroy(uriPath16);
  1191 	CleanupStack::PushL(uriPath);
  1192 	HBufC8* escpedUriPath = EscapeUtils::EscapeEncodeL(*uriPath, EscapeUtils::EEscapeNormal);
  1193 	CleanupStack::PopAndDestroy(uriPath);
  1194 	CleanupStack::PushL(escpedUriPath);
  1195 	
  1196 	//SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation, 
  1197 	//tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer 
  1198 	//for each SetComponent call     
  1199 	iUri.iComponent[EUriPath].Set(*escpedUriPath);
  1200 	iUri.iComponent[EUriHost].Set(KNullDesC8);
  1201 	iUri.iComponent[EUriScheme].Set(KFileUriScheme8);
  1202 	FormUriL();
  1203 	
  1204 	CleanupStack::PopAndDestroy(escpedUriPath);
  1205 	}
  1206 
  1207 /**
  1208 	Allocates and constructs a file URI object for a specified file.
  1209 	 
  1210 	- If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.	
  1211 	- If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
  1212 	
  1213 	@since			9.1
  1214 	@param			aFullFileName	A reference to a fully qualified filename 
  1215 	@param			aFlags			A flag to indicate if the file exists on a fixed drive or removable media drive.
  1216 									This is a TFileUriFlags value.
  1217 	@return			A pointer to the newly created file URI (CUri8) object. 
  1218 	@post			A fully constructed and initialized file URI (CUri8) object.
  1219  */
  1220 EXPORT_C CUri8* CUri8::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
  1221 	{
  1222 	//It should be called to construct a file URI for a public file stored on a fix drive 
  1223 	// or on a removable media drive only
  1224 	__ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1225 		
  1226 	CUri8* self = CUri8::NewLC();
  1227 	self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
  1228 	CleanupStack::Pop(self);
  1229 	return self;
  1230 	}
  1231 
  1232 /**
  1233 	Allocates and constructs a file URI object for a file that is private to the application.
  1234 
  1235 	- If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
  1236 	- If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
  1237 	
  1238 	@since			9.1
  1239 	@param			aRelativeFileName	A reference to the filename relative to the application's private directory.
  1240 	@param			aDrive				Drive number, if the private file stored on fixed drive, otherwise not used
  1241 										This is a TDriveNumber value
  1242 	@param			aFlags				A flag to indicate if the file exists on a fixed drive or removable media drive.
  1243 										This is a TFileUriFlags value.
  1244 	@return			A pointer to the newly created file URI (CUri8) object. 
  1245 	@post			A fully constructed and initialized file URI (CUri8) object.
  1246 */	
  1247 
  1248 
  1249 EXPORT_C CUri8* CUri8::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags) 
  1250 	{
  1251 	//It should be called to construct a file URI for the application's private file stored on a fix drive 
  1252 	// or on a removable media drive only
  1253 	__ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1254 
  1255 	CUri8* self = CUri8::NewLC();
  1256 	self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
  1257 	CleanupStack::Pop(self);
  1258 	return self;
  1259 	}
  1260 
  1261 
  1262 //
  1263 //
  1264 // File URI Implementation - CUri16
  1265 //
  1266 //
  1267 
  1268 /**
  1269 	Initializes the file URI components (scheme, empty hostname and path).	 
  1270 	
  1271 	It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive. 
  1272 	
  1273 	@since			9.1
  1274 	@param			aFileName	A reference to a filename 
  1275 	@param			aDrive		A drive number. This is a TFileUriFlags value.
  1276 	@param			aFlags		A flag to indicate if the file exists on a fixed drive or removable media drive.
  1277 					This is a TFileUriFlags value.
  1278 	@pre 			Object fully constructed
  1279 	@post			The object is initialized with file URI components.
  1280  */
  1281 void CUri16::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
  1282 	{	
  1283 	HBufC* uriPath = GenerateFileUriPathL(aFileName, aDrive, aFlags);
  1284 	CleanupStack::PushL(uriPath);
  1285 
  1286 	HBufC8* uriPath8 = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath);
  1287 	CleanupStack::PopAndDestroy(uriPath);
  1288 	CleanupStack::PushL(uriPath8);
  1289 
  1290 	HBufC8* escapedUriPath8 = EscapeUtils::EscapeEncodeL(*uriPath8, EscapeUtils::EEscapeNormal);
  1291 	CleanupStack::PopAndDestroy(uriPath8);
  1292 	CleanupStack::PushL(escapedUriPath8);
  1293 
  1294 	HBufC* escapedUriPath = HBufC::NewLC(escapedUriPath8->Length());
  1295 	escapedUriPath->Des().Copy(*escapedUriPath8); 
  1296 	
  1297 	//SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation, 
  1298 	//tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer 
  1299 	//for each SetComponent call     
  1300 	iUri.iComponent[EUriPath].Set(*escapedUriPath);
  1301 	iUri.iComponent[EUriHost].Set(KNullDesC16);
  1302 	iUri.iComponent[EUriScheme].Set(KFileUriScheme16);
  1303 	FormUriL();
  1304 	
  1305 	CleanupStack::PopAndDestroy(escapedUriPath);
  1306 	CleanupStack::PopAndDestroy(escapedUriPath8);
  1307 	}
  1308 
  1309 /**
  1310 	Allocates and constructs a file URI object for a specified file.
  1311 	 
  1312 	- If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.	
  1313 	- If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
  1314 	
  1315 	@since			9.1
  1316 	@param			aFullFileName	A reference to a fully qualified filename 
  1317 	@param			aFlags	A flag to indicate if the file exists on a fixed drive or removable media drive.
  1318 					This is a TFileUriFlags value.
  1319 	@return			A pointer to the newly created file URI (CUri16) object. 
  1320 	@post			A fully constructed and initialized file URI (CUri16) object.
  1321  */
  1322 EXPORT_C CUri16* CUri16::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
  1323 	{
  1324 	//It should be called to construct a file URI for a public file stored on a fix drive 
  1325 	// or on a removable media drive only
  1326 	__ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1327 		
  1328 	CUri16* self = CUri16::NewLC();
  1329 	self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
  1330 	CleanupStack::Pop(self);
  1331 	return self;
  1332 	}
  1333 	
  1334 /**
  1335 	Allocates and constructs a file URI object for a file that is private to the application.
  1336 
  1337 	- If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
  1338 	- If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
  1339 	
  1340 	@since			9.1
  1341 	@param			aRelativeFileName	A reference to the filename relative to the application's private directory.
  1342 	@param			aDrive				Drive number, if the private file stored on fixed drive, otherwise not used
  1343 										This is a TDriveNumber value
  1344 	@param			aFlags				A flag to indicate if the file exists on a fixed drive or removable media drive.
  1345 										This is a TFileUriFlags value.
  1346 	@return			A pointer to the newly created file URI (CUri16) object. 
  1347 	@post			A fully constructed and initialized file URI (CUri16) object.
  1348 */
  1349 
  1350 
  1351 EXPORT_C CUri16* CUri16::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags) 
  1352 	{
  1353 	//It should be called to construct a file URI for the application's private file stored on a fix drive 
  1354 	// or on a removable media drive only
  1355 	__ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
  1356 
  1357 	CUri16* self = CUri16::NewLC();
  1358 	self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
  1359 	CleanupStack::Pop(self);
  1360 	return self;
  1361 	}
  1362 
  1363 
  1364 //
  1365 //
  1366 // Implemetation of LOCAL functions for the File URI
  1367 //
  1368 //
  1369 	
  1370 /**
  1371 	Function used to generate 16bit file uri using 1st parameter aFileName and 
  1372 	2nd parameter aDrive for the application's private or a public file.
  1373 	
  1374 	This is called by API CreateFileUri() and CreatePrivateFileUri()to 
  1375 	generate a filename.
  1376 	
  1377 	Note: The space allocated for the returned descriptor will likely be larger 
  1378 		  than the length of the descriptor
  1379 	
  1380 	@leave			KErrBadName	A provided Drivename or filename is not valid 
  1381 	@since			9.1
  1382 	@param			aFileName	A descriptor reference to the filename.
  1383 	@param			aDrive		A descriptor reference to drive letter.
  1384 	@param			aFlags		A flag to indicate the private or a public file exists on removable media or a fixed drive.
  1385 	@return			A pointer to a buffer containing the resolved fully qualified filename.
  1386  */
  1387 HBufC* GenerateFileUriPathL(const TDesC& aFileName, TDriveNumber aDrive,  TUint aFlags)
  1388 	{
  1389 	TInt origLength = aFileName.Length();
  1390 
  1391 	//Leaves with KErrBadName if filename length is out of range 
  1392 	if (origLength == 0 || origLength > KMaxFileName)
  1393 		{
  1394 		User::Leave(KErrBadName);	
  1395 		}
  1396 		
  1397 	TPtrC filename(aFileName);
  1398 	
  1399 	//extract drive letter and remove drive "x:" from filename
  1400 	TUint drive = filename[0];
  1401 	
  1402 	 // hasDrive means it begins with a drive, e.g. "c:"
  1403 	 const TBool hasDrive =  ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z')) && (filename[1] == KDriveSeparator);
  1404 	 // hasTopPath means it begins with a \ (possibly after the drive)
  1405 	 const TBool hasTopPath = (hasDrive && (filename[2] == KFilePathSeparator)) || (!hasDrive && (drive == TUint(KFilePathSeparator) ));
  1406  
  1407 	 TInt skip = KDefaultPath().Length(); //  skip leading "<drive>:\" by default
  1408 	 if(aFlags & TUint(EPrivate)) 
  1409 		{
  1410 		skip = (hasDrive ? (KDefaultPath().Length() - 1) : 0) + (hasTopPath ? 1 : 0) ;
  1411 		}
  1412 	 else
  1413 		{
  1414 		// if not private then it should have valid drive i.e. "<drive>:\"
  1415 		if (!(hasDrive && hasTopPath)) 
  1416 			{
  1417 			User::Leave(KErrBadName);
  1418 			}
  1419 		}
  1420 	
  1421 	if(skip)
  1422 		  {
  1423 		  filename.Set(aFileName.Right(origLength - skip));
  1424 		  } 	
  1425 
  1426 	TInt uriLen = aFileName.Length() + KExtMedia().Length() + KPrivate().Length() + 1 /* for drive letter */;
  1427 	
  1428 	HBufC* fileUri = HBufC::NewLC(uriLen);
  1429 	TPtr fileUriPtr = fileUri->Des(); 
  1430 	fileUriPtr.Append(KUriPathSeparator);
  1431 	
  1432 	if (aFlags & TUint(EPrivate))
  1433 		{
  1434 		fileUriPtr.Append(KPrivate);
  1435 		drive = TInt16('A' + aDrive);
  1436 		}
  1437 		
  1438 	if (aFlags & EExtMedia)
  1439 		{
  1440 		fileUriPtr.Append(KExtMedia);			
  1441 		}
  1442 	else
  1443 		{
  1444 		fileUriPtr.Append(drive);
  1445 		fileUriPtr.Append(KUriPathSeparator);	
  1446 		}
  1447 		
  1448 	fileUriPtr.Append(filename);
  1449 		
  1450 	//Convert "\" to "/"
  1451 	ChangePathSeparator(fileUriPtr, KFilePathSeparator, KUriPathSeparator);
  1452 
  1453 	//Handling "./" and "../" in the file URI path  or resolving the URI path 
  1454 	CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(fileUriPtr);
  1455  	// Clean up the path to resolve occurences of '..' and '.'
  1456  	CleanResolvedPathL<TPtrC>(resolvedPath);
  1457  	fileUriPtr.Copy(resolvedPath->Parser().Des()); // new path will always be shorter than old one
  1458  	CleanupStack::PopAndDestroy(resolvedPath);
  1459  		
  1460 	CleanupStack::Pop(fileUri);
  1461 	return fileUri;
  1462 	}