genericservices/httputils/UriParser/TUriC.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 // System includes
       
    17 #include <uri8.h>
       
    18 #include <uri16.h>
       
    19 #include "TUriCInternal.h"
       
    20 #include <uriutilscommon.h>
       
    21 #include <uriutils.h>
       
    22 #include "UriUtilsInternal.h"
       
    23 #include "TValidator.h"
       
    24 #include "TEquiv.h"
       
    25 #include <escapeutils.h>
       
    26 
       
    27 
       
    28 
       
    29 // Panic category
       
    30 //
       
    31 _LIT(KUriPanicCategory,"URI-BASE");
       
    32 
       
    33 //
       
    34 //
       
    35 // Implementation of TUriC8
       
    36 //
       
    37 //
       
    38 
       
    39 /**
       
    40   Constructor.
       
    41 	
       
    42   @since			6.0
       
    43  */
       
    44 EXPORT_C TUriC8::TUriC8()
       
    45 	{
       
    46 	// Reset the component table and the Uri
       
    47 	Reset();
       
    48 	}
       
    49 
       
    50 /**
       
    51   Retrieves the specified component in the uri.
       
    52 	
       
    53   @since			6.0
       
    54   @param			aComponent	The enum specifying the component.
       
    55   @return			A constant reference to a descriptor pointer to the specified 
       
    56   component.
       
    57  */
       
    58 EXPORT_C const TDesC8& TUriC8::Extract(TUriComponent aComponent) const
       
    59 	{
       
    60 	__ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
    61 
       
    62 	return iComponent[aComponent];
       
    63 	}
       
    64 
       
    65 /**
       
    66   Indicates whether the specified component is present in the uri.
       
    67 	
       
    68   @since			6.0
       
    69   @param			aComponent	The enum specifying the component.
       
    70   @return			A boolean value of ETrue if the desired component is present, 
       
    71   or EFalse if the desired component is not present.
       
    72  */
       
    73 EXPORT_C TBool TUriC8::IsPresent(TUriComponent aComponent) const
       
    74 	{
       
    75 	__ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
    76 
       
    77 	return TBool(iComponent[aComponent].Ptr());
       
    78 	}
       
    79 
       
    80 /**
       
    81   Checks the scheme to be valid. If there is no scheme then the return value 
       
    82   indicates an invalid scheme.
       
    83 	
       
    84   @since			6.0
       
    85   @return			A boolean value of ETrue if the scheme is valid, or EFalse if
       
    86   the scheme is not.
       
    87  */
       
    88 EXPORT_C TBool TUriC8::IsSchemeValid() const
       
    89 	{
       
    90 	if( !IsPresent(EUriScheme) )
       
    91 		{
       
    92 		return EFalse;
       
    93 		}
       
    94 	return HasValidSchemeChars(iComponent[EUriScheme]);
       
    95 	}
       
    96 
       
    97 /**
       
    98   Compares the specified component against the one in the uri passed in.
       
    99 	
       
   100   @since			6.0
       
   101   @param			aUri		The uri to compare components against.
       
   102   @param			aComponent	The enum specifying the component to compare.
       
   103   @return			An integer value of zero if the components are the same,
       
   104   any other value if the components are not the same.
       
   105  */
       
   106 EXPORT_C TInt TUriC8::Compare(const TUriC8& aUri, TUriComponent aComponent) const
       
   107 	{
       
   108 	__ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
   109 
       
   110 	// Does the component exist in both the Uri's
       
   111 	if( IsPresent(aComponent) && aUri.IsPresent(aComponent) )
       
   112 		{
       
   113 		if( aComponent == EUriScheme || aComponent == EUriHost )
       
   114 			{
       
   115 			// Do case insensitive compare for scheme and host
       
   116 			return (iComponent[aComponent].CompareF(aUri.iComponent[aComponent]));
       
   117 			}
       
   118 		else
       
   119 			{
       
   120 			// Do case sensitive compare for all other components
       
   121 			return (iComponent[aComponent].Compare(aUri.iComponent[aComponent]));
       
   122 			}
       
   123 		}
       
   124 	else
       
   125 		return KErrNotFound;
       
   126 	}
       
   127 
       
   128 /**
       
   129   Retrieves the descriptor for the entire uri.
       
   130 	
       
   131   @since			6.0
       
   132   @return			A const reference to a descriptor pointer to the uri.
       
   133  */
       
   134 EXPORT_C const TDesC8& TUriC8::UriDes() const
       
   135 	{
       
   136 	return iUriDes;
       
   137 	}
       
   138 
       
   139 /**
       
   140   @publishedPartner
       
   141   @released
       
   142   Ensures that all components of the URI are valid. If the method	returns 
       
   143   KUriUtilsErrInvalidUri then one or more components are not valid. It is
       
   144   possible for URIs declared valid by this method to be, on detailed inspection, 
       
   145   invalid.
       
   146 	
       
   147   @return	KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported.
       
   148  */
       
   149 EXPORT_C TInt TUriC8::Validate() const
       
   150 	{
       
   151 	return DoValidate(*this);
       
   152 	}
       
   153 
       
   154 /**
       
   155   Compares the given URI to determine if it is equivalent to this URI. It is possible
       
   156   for URIs declared NOT equivalent by this method to be equvalent to a level not checked 
       
   157   by this method.
       
   158   @publishedPartner
       
   159   @released
       
   160   @param			aUri	Contains URI to compare 
       
   161   @return			ETrue if the two URIs are equivalent otherwise EFalse
       
   162  */
       
   163 EXPORT_C TInt TUriC8::Equivalent(const TUriC8& aUri) const
       
   164 	{
       
   165 	TInt result = EFalse;
       
   166 	TRAPD(error, result = DoEquivalenceL(*this, aUri));
       
   167 	if (error != KErrNone)
       
   168 		{
       
   169 		result = error;
       
   170 		}
       
   171 	return result;
       
   172 	}
       
   173 
       
   174 /**
       
   175   Retrieves the uri without the fragment component.
       
   176 	
       
   177   @since			6.0
       
   178   @param			aUriNoFrag	An output parameter which is set the non-reference 
       
   179   version of the uri.
       
   180  */
       
   181 EXPORT_C void TUriC8::UriWithoutFragment(TPtrC8& aUriNoFrag) const
       
   182 	{
       
   183 	if( IsPresent(EUriFragment) )
       
   184 		{
       
   185 		// There is a fragment, find where it starts
       
   186 		TInt fragmentStartPos = iUriDes.Locate(KFragmentDelimiter);
       
   187 		aUriNoFrag.Set(iUriDes.Left(fragmentStartPos));
       
   188 		}
       
   189 	else{
       
   190 		aUriNoFrag.Set(iUriDes);
       
   191 		}
       
   192 	}
       
   193 
       
   194 /** 
       
   195   Create a new HBufC descriptor containing the desired component or the full URI.
       
   196 	
       
   197   @param    aComponent  The component to convert into Unicode (EUriScheme - EUriFragment),  or
       
   198   the full URI (EUriComplete -- the default).
       
   199   @return    The descriptor containing the desired component. 
       
   200  */
       
   201 EXPORT_C HBufC* TUriC8::DisplayFormL(TUriComponent aComponent) const
       
   202 	{
       
   203 	TPtrC8 component;	
       
   204 	
       
   205 	if (aComponent == EUriComplete) 
       
   206 		{
       
   207 		component.Set(iUriDes);
       
   208 		}
       
   209 	else 
       
   210 		{  // extract the specified component, will Panic if invalid
       
   211 		component.Set( Extract(aComponent) );
       
   212 		}
       
   213 	// convert descriptor from UTF-8 into Unicode
       
   214 	return EscapeUtils::ConvertToUnicodeFromUtf8L(component);
       
   215 	}
       
   216 
       
   217 /**
       
   218   @internalComponent
       
   219   Resets the descriptor pointers for the uri components and the uri.
       
   220 	
       
   221   @since		6.0
       
   222   @post			All uri component information is removed and the uri descriptor is 
       
   223   set to NULL.
       
   224  */
       
   225 void TUriC8::Reset()
       
   226 	{
       
   227 	// Set descriptor pointers to NULL and lengths to zero
       
   228 	for( TInt i=0; i<EUriMaxComponents; ++i )
       
   229 		{
       
   230 		iComponent[i].Set(NULL,0);
       
   231 		}
       
   232 	iUriDes.Set(NULL,0);
       
   233 	}
       
   234 	
       
   235 //
       
   236 //
       
   237 // Implementation of TUriC16
       
   238 //
       
   239 //
       
   240 /**
       
   241   Constructor.
       
   242 	
       
   243   @since		6.0
       
   244   @deprecated 	Deprecated in 9.1
       
   245  */
       
   246 EXPORT_C TUriC16::TUriC16()
       
   247 	{
       
   248 	// Reset the component table and the Uri
       
   249 	Reset();
       
   250 	}
       
   251 
       
   252 /**
       
   253   Retrieves the specified component in the uri.
       
   254 	
       
   255   @since			6.0
       
   256   @deprecated 		Deprecated in 9.1
       
   257   @param			aComponent	The enum specifying the component.
       
   258   @return			A constant reference to a descriptor pointer to the specified component.
       
   259  */
       
   260 EXPORT_C const TDesC16& TUriC16::Extract(TUriComponent aComponent) const
       
   261 	{
       
   262 	__ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
   263 
       
   264 	return iComponent[aComponent];
       
   265 	}
       
   266 
       
   267 /**
       
   268   Indicates whether the specified component is present in the uri.
       
   269 	
       
   270   @since			6.0
       
   271   @deprecated Deprecated in 9.1
       
   272   @param			aComponent	The enum specifying the component.
       
   273   @return			A boolean value of ETrue if the desired component is present, 
       
   274   or EFalse if the desired component is not present.
       
   275  */
       
   276 EXPORT_C TBool TUriC16::IsPresent(TUriComponent aComponent) const
       
   277 	{
       
   278 	__ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
   279 
       
   280 	return TBool(iComponent[aComponent].Ptr());
       
   281 	}
       
   282 
       
   283 /**
       
   284   Checks to see if the scheme is valid. If there is no scheme then the return value 
       
   285   indicates an invalid scheme (EFalse).
       
   286 	
       
   287   @since		6.0
       
   288   @deprecated 	Deprecated in 9.1
       
   289   @return		A boolean value of ETrue if the scheme is valid, or EFalse if
       
   290   the scheme is not.
       
   291  */
       
   292 EXPORT_C TBool TUriC16::IsSchemeValid() const
       
   293 	{
       
   294 	if( !IsPresent(EUriScheme) )
       
   295 		{
       
   296 		return EFalse;
       
   297 		}
       
   298 	return HasValidSchemeChars(iComponent[EUriScheme]);
       
   299 	}
       
   300 
       
   301 /**
       
   302   Compares the specified component against the one in the uri passed in.
       
   303 	
       
   304   @since		6.0
       
   305   @deprecated 	Deprecated in 9.1
       
   306   @param		aUri		The uri to compare components against.
       
   307   @param		aComponent	The enum specifying the component to compare.
       
   308   @return		An integer value of zero if the components are the same, any other
       
   309   value if the components are not the same.
       
   310  */
       
   311 EXPORT_C TBool TUriC16::Compare(const TUriC16& aUri, TUriComponent aComponent) const
       
   312 	{
       
   313 	__ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
   314 
       
   315 	// Does the component exist in both the Uri's
       
   316 	if( IsPresent(aComponent) && aUri.IsPresent(aComponent) )
       
   317 		{
       
   318 		if( aComponent == EUriScheme || aComponent == EUriHost )
       
   319 			{
       
   320 			// Do case insensitive compare for scheme and host
       
   321 			return (iComponent[aComponent].CompareF(aUri.iComponent[aComponent]));
       
   322 			}
       
   323 		else
       
   324 			{
       
   325 			// Do case sensitive compare for all other components
       
   326 			return (iComponent[aComponent].Compare(aUri.iComponent[aComponent]));
       
   327 			}
       
   328 		}
       
   329 	else
       
   330 		return KErrNotFound;
       
   331 	}
       
   332 
       
   333 /**
       
   334   Retrieves the descriptor for the entire uri.
       
   335 	
       
   336   @since			6.0
       
   337   @deprecated Deprecated in 9.1
       
   338   @return			A const reference to a descriptor pointer to the uri.
       
   339  */
       
   340 EXPORT_C const TDesC16& TUriC16::UriDes() const
       
   341 	{
       
   342 	return iUriDes;
       
   343 	}
       
   344 
       
   345 /**
       
   346   @deprecated Deprecated in 9.1 -- provided for compatibility
       
   347 	
       
   348   Ensures that all components of the URI are valid. If the method	returns 
       
   349   KUriUtilsErrInvalidUri then one or more components are not valid. It is possible
       
   350   for URIs declared valid by this method to be, on detailed inspection, invalid.
       
   351 	
       
   352   @return			KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported.
       
   353  */
       
   354 EXPORT_C TInt TUriC16::Validate() const
       
   355 	{
       
   356 	TInt result = KErrNone;
       
   357 	TRAPD(error, result = ValidateL());
       
   358 	if (error)
       
   359 		{
       
   360 		// problem allocating resourses 
       
   361 		return error;
       
   362 		}
       
   363 	return result;
       
   364 	}
       
   365 
       
   366 /**
       
   367   @deprecated Deprecated in 9.1 -- provided for compatibility
       
   368 
       
   369   Compares the given URI to determine if it is equivalent to this URI. It is possible
       
   370   for URIs declared NOT equivalent by this method to be equvalent to a level not checked 
       
   371   by this method.
       
   372   @param			aUri	Contains URI to compare 
       
   373   @return			ETrue if the two URIs are equivalent otherwise EFalse
       
   374  */
       
   375 EXPORT_C TInt TUriC16::Equivalent(const TUriC16& aUri) const
       
   376 	{
       
   377 	TInt result = KErrNone;
       
   378 	TRAPD(error, result = EquivalentL(aUri.UriDes()));
       
   379 	if (error)
       
   380 		{
       
   381 		// problem allocating resourses 
       
   382 		return error;
       
   383 		}
       
   384 	return result;
       
   385 	}
       
   386 /**
       
   387   Retrieves the uri without the fragment component.
       
   388 	
       
   389   @since			6.0
       
   390   @deprecated Deprecated in 9.1
       
   391   @param			aUriNoFrag	An output parameter which is set the non-reference 
       
   392   version of the uri.
       
   393  */
       
   394 
       
   395 EXPORT_C void TUriC16::UriWithoutFragment(TPtrC16& aUriNoFrag) const
       
   396 	{
       
   397 	if( IsPresent(EUriFragment) )
       
   398 		{
       
   399 		// There is a fragment, find where it starts
       
   400 		TInt fragmentStartPos = iUriDes.Locate(KFragmentDelimiter);
       
   401 		aUriNoFrag.Set(iUriDes.Left(fragmentStartPos));
       
   402 		}
       
   403 	else{
       
   404 		aUriNoFrag.Set(iUriDes);
       
   405 		}
       
   406 	}
       
   407 
       
   408 /** 
       
   409   Create a new HBufC descriptor containing the desired component or the full URI.
       
   410   @deprecated Deprecated in 9.1 - provided for compatibility	
       
   411   
       
   412   @param aComponent  The component to convert into Unicode (EUriScheme - EUriFragment),  or
       
   413   the full URI (EUriComplete -- the default).
       
   414   @return The descriptor containing the desired component. 
       
   415  */
       
   416 EXPORT_C HBufC* TUriC16::DisplayFormL(TUriComponent aComponent) const
       
   417 	{
       
   418 	if ( aComponent == EUriComplete) // extract the full URI
       
   419 		{
       
   420 		return iUriDes.AllocL();	
       
   421 		}
       
   422 	return Extract(aComponent).AllocL();
       
   423 	}
       
   424 
       
   425 /**	
       
   426   @internalComponent
       
   427   Resets the descriptor pointers for the uri components and the uri.
       
   428 	
       
   429   @since			6.0
       
   430   @post			All uri component information is removed and the uri descriptor is 
       
   431   set to NULL.
       
   432  */
       
   433 void TUriC16::Reset()
       
   434 	{
       
   435 	// Set descriptor pointers to NULL and lengths to zero
       
   436 	for( TInt i=0; i<EUriMaxComponents; ++i )
       
   437 		{
       
   438 		iComponent[i].Set(NULL,0);
       
   439 		}
       
   440 	iUriDes.Set(NULL,0);
       
   441 	}
       
   442 
       
   443 /**
       
   444   @deprecated Deprecated in 9.1 
       
   445 	
       
   446   Ensures that all components of the URI are valid. If the method	returns 
       
   447   KUriUtilsErrInvalidUri then one or more components are not valid. It is possible
       
   448   for URIs declared valid by this method to be, on detailed inspection, invalid.
       
   449 	
       
   450   @return			KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported.
       
   451  */
       
   452 TInt TUriC16::ValidateL() const
       
   453 	{
       
   454 	TInt result;
       
   455 	
       
   456 	HBufC8* uri8 = CreateUri8LC(UriDes());
       
   457 	TUriParser8 uriParser;		
       
   458 	if(uriParser.Parse(*uri8) != KErrNone)
       
   459 		{
       
   460 		result = KUriUtilsErrInvalidUri;
       
   461 		}
       
   462 	else		
       
   463 		{
       
   464 		result = DoValidate(uriParser);		
       
   465 		}
       
   466 	
       
   467 	CleanupStack::PopAndDestroy(uri8);
       
   468 	return result;	
       
   469 	}
       
   470 
       
   471 /**
       
   472   @deprecated Deprecated in 9.1 
       
   473 
       
   474   Compares the given URI to determine if it is equivalent to this URI. It is possible
       
   475   for URIs declared NOT equivalent by this method to be equvalent to a level not checked 
       
   476   by this method.
       
   477   @param			aUri	Contains URI to compare 
       
   478   @return			ETrue if the two URIs are equivalent otherwise EFalse
       
   479  */
       
   480 TBool TUriC16::EquivalentL(const TDesC16& aUri) const
       
   481 	{
       
   482 	HBufC8* lhs = CreateUri8LC(UriDes());
       
   483 	HBufC8* rhs = CreateUri8LC(aUri);
       
   484 	
       
   485 	TUriParser8 lhsParser;		
       
   486 	if(lhsParser.Parse(*lhs) != KErrNone)
       
   487 		{
       
   488 		User::Leave(KUriUtilsErrInvalidUri);
       
   489 		}
       
   490 		
       
   491 	TUriParser8 rhsParser;		
       
   492 	if(rhsParser.Parse(*rhs) != KErrNone)
       
   493 		{
       
   494 		User::Leave(KUriUtilsErrInvalidUri);
       
   495 		}
       
   496 	
       
   497 	TBool result = DoEquivalenceL(lhsParser, rhsParser);		
       
   498 	
       
   499 	CleanupStack::PopAndDestroy(2);
       
   500 	return result;	
       
   501 	}
       
   502 
       
   503 //
       
   504 //
       
   505 // Implementation of LOCAL functions
       
   506 //
       
   507 //
       
   508 
       
   509 /**
       
   510 	Checks the scheme for invalid characters. The scheme is invalid if it is empty.
       
   511 						
       
   512 	@since			6.0
       
   513 	@param			aScheme	The descriptor with the scheme.
       
   514 	@return			A boolean value of ETrue if all the characters in the scheme
       
   515 	are valid, otherwise EFalse.
       
   516 */
       
   517 template<class TPtrCType>
       
   518 LOCAL_C TBool HasValidSchemeChars(const TPtrCType& aScheme)
       
   519 	{
       
   520 	TInt length = aScheme.Length();
       
   521 	TBool valid = ( length && TChar(aScheme[0]).IsAlpha() );
       
   522 
       
   523 	// Start checking from the second character
       
   524 	TInt i=1;
       
   525 	while( valid && i<length )
       
   526 		{
       
   527 		TChar c = aScheme[i];
       
   528 		valid = c.IsAlphaDigit() || c==KPlusChar || c==KMinusChar || c==KPeriodChar;
       
   529 		++i;
       
   530 		}
       
   531 	return valid;
       
   532 	}
       
   533 
       
   534 
       
   535 //
       
   536 //
       
   537 // File URI Implementation - CUri8
       
   538 //
       
   539 //
       
   540 #ifdef __SECURE_DATA__	
       
   541 /**
       
   542 	Generates a fully-qualified filename from a file URI object.
       
   543 
       
   544 	The form of the returned filename depends on the file location, as follows: 	
       
   545 	- public file on a fixed drive: 
       
   546 		@code
       
   547 		file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
       
   548 		@endcode
       
   549 
       
   550 	- public file on removable media drive:
       
   551 	 The fully-qualified filename is resolved by finding the first drive on which the file exists.
       
   552 	 If the file does not exist, this will Leave with KErrNotFound
       
   553 	 	@code
       
   554 		file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
       
   555 		@endcode
       
   556 		 (where f: is the first drive found containing "\path\to\file\name.ext")
       
   557 		 
       
   558 	- private file on fixed drive:
       
   559 		@code
       
   560 		file://private/c/path/to/file/name.ext -> c:\private\0x1001234f\path\to\file\name.ext
       
   561 		@endcode
       
   562 		 (where 0x1001234f is the SID of the current application)
       
   563 
       
   564 	- private file on removable media drive:
       
   565 		@code
       
   566 		file://private/ext-media/path/to/file/name.ext -> h:\private\0x1001234f\path\to\file\name.ext
       
   567 		@endcode
       
   568 		 (where h: is the first drive found containing "\private\0x1001234f\path\to\file\name.ext")
       
   569 
       
   570 	The returned file name is not guaranteed to exist except where specified above.
       
   571 
       
   572 	Be warned that this method may be slow when resolving special paths (like "/ext-media")
       
   573 	
       
   574 	@leave			KErrNotSupported URI does not specify a local file
       
   575 	@leave			KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
       
   576 	@since			9.1
       
   577 	@return			A descriptor containing the fully-qualified filename. 
       
   578 	@pre 			Object is fully constructed.
       
   579  */
       
   580 #else
       
   581  /**
       
   582 	Generates a fully-qualified filename from a file URI object.
       
   583 
       
   584 	The form of the returned filename depends on the file location, as follows: 	
       
   585 	- public file on a fixed drive: 
       
   586 		@code
       
   587 		file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
       
   588 		@endcode
       
   589 
       
   590 	- public file on removable media drive:
       
   591 	 The fully-qualified filename is resolved by finding the first drive on which the file exists.
       
   592 	 If the file does not exist, this will Leave with KErrNotFound
       
   593 	 	@code
       
   594 		file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
       
   595 		@endcode
       
   596 		 (where f: is the first drive found containing "\path\to\file\name.ext")
       
   597 
       
   598 	The returned file name is not guaranteed to exist except where specified above.
       
   599 
       
   600 	Be warned that this method may be slow when resolving special paths (like "/ext-media")
       
   601 	
       
   602 	@leave			KErrNotSupported URI does not specify a local file
       
   603 	@leave			KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
       
   604 	@since			9.1
       
   605 	@return			A descriptor containing the fully-qualified filename. 
       
   606 	@pre 			Object is fully constructed.
       
   607  */
       
   608  #endif
       
   609 EXPORT_C HBufC* TUriC8::GetFileNameL() const
       
   610 	{
       
   611 	return GetFileNameL(EUriFileNameFull);
       
   612 	}
       
   613 
       
   614 
       
   615 /**
       
   616 	This creates a file name from the URI, changing the network path separator (/) to the 
       
   617 	local file system path separator (\\). 
       
   618 	
       
   619 	If called with EUriFileNamePath, this will generate a file name containing  the path relative to the drive. 
       
   620 	Any parameters in the URI are stripped off:
       
   621 		@code
       
   622 		http://www.foo.com/dir/file/name.ext;param1;param2 -> \dir\file\name.ext
       
   623 		@endcode
       
   624 	
       
   625 	If called with EUriFileNameTail, this will generate a just the name, with no directories or drive.
       
   626 	Any parameters in the URI are stripped off:
       
   627 		@code
       
   628 		http://www.foo.com/dir/file/name.ext;param1;param2 -> name.ext
       
   629 		@endcode
       
   630 	
       
   631 	EUriFileNamePath and EUriFileNameTail can be used for any hierarchical URI (http, ftp, file, etc)
       
   632 	and may have unexpected behaviour when called on any other type of URI.
       
   633 
       
   634 	If called with EUriFileNameFull, this will convert the URI into a fully-qualified filename. this is only valid
       
   635 	for file URIs and will Leave if called on any other type of URI. The form of the returned filename is described in 
       
   636 	GetFileNameL with no arguments.
       
   637 	
       
   638 	@leave			KErrNotSupported The URI scheme cannot be converted into the desired  type
       
   639 	@since			9.1
       
   640 	@pre 			Object is fully constructed.
       
   641 	@param			aType specifies what part of the filename is to be  converted. The default is EUriFileNameFull).
       
   642 	@return			A descriptor containing the desired filename components.
       
   643  */
       
   644 EXPORT_C HBufC* TUriC8::GetFileNameL(TUriFileName aType) const
       
   645 	{
       
   646 	TBool isFileUri = Extract(EUriScheme).Compare(KFileUriScheme8) == 0;
       
   647 	if(aType == EUriFileNameFull && !isFileUri)
       
   648 		{		
       
   649 		User::Leave(KErrNotSupported);
       
   650 		}
       
   651 	return ResolveFileNameL(Extract(EUriPath), aType, isFileUri);
       
   652 	}
       
   653 	
       
   654 
       
   655 //
       
   656 //
       
   657 // File URI Implementation - CUri16
       
   658 //
       
   659 //
       
   660 
       
   661 #ifdef  __SECURE_DATA__
       
   662 /**
       
   663 	Generates a fully-qualified filename from a file URI object.
       
   664 
       
   665 	The form of the returned filename depends on the file location, as follows: 	
       
   666 	- public file on a fixed drive: 
       
   667 		@code
       
   668 		file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
       
   669 		@endcode
       
   670 
       
   671 	- public file on removable media drive:
       
   672 	 The fully-qualified filename is resolved by finding the first drive on which the file exists.
       
   673 	 If the file does not exist, this will Leave with KErrNotFound
       
   674 		@code
       
   675 		file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
       
   676 		@endcode
       
   677 		 (where f: is the first drive found containing "\path\to\file\name.ext")
       
   678 
       
   679 	- private file on fixed drive:
       
   680 		@code
       
   681 		file://private/c/path/to/file/name.ext -> c:\private\0x1001234f\path\to\file\name.ext
       
   682 		@endcode
       
   683 		 (where 0x1001234f is the SID of the current application)
       
   684 
       
   685 	- private file on removable media drive:
       
   686 		@code
       
   687 		file://private/ext-media/path/to/file/name.ext -> h:\private\0x1001234f\path\to\file\name.ext
       
   688 		@endcode
       
   689 		 (where h: is the first drive found containing "\private\0x1001234f\path\to\file\name.ext")
       
   690 
       
   691 	The returned file name is not guaranteed to exist except where specified above.
       
   692 
       
   693 	Be warned that this method may be slow when resolving special paths (like "/ext-media")
       
   694 	
       
   695 	@leave			KErrNotSupported URI does not specify a local file
       
   696 	@leave			KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
       
   697 	@since			9.1
       
   698 	@return			A descriptor containing the fully-qualified filename. 
       
   699 	@pre 			Object is fully constructed.
       
   700 	
       
   701  */
       
   702 #else 
       
   703 /**
       
   704 	Generates a fully-qualified filename from a file URI object.
       
   705 
       
   706 	The form of the returned filename depends on the file location, as follows: 	
       
   707 	- public file on a fixed drive: 
       
   708 		@code
       
   709 		file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
       
   710 		@endcode
       
   711 
       
   712 	- public file on removable media drive:
       
   713 	 The fully-qualified filename is resolved by finding the first drive on which the file exists.
       
   714 	 If the file does not exist, this will Leave with KErrNotFound
       
   715 		@code
       
   716 		file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
       
   717 		@endcode
       
   718 		 (where f: is the first drive found containing "\path\to\file\name.ext")
       
   719 
       
   720 	The returned file name is not guaranteed to exist except where specified above.
       
   721 
       
   722 	Be warned that this method may be slow when resolving special paths (like "/ext-media")
       
   723 	
       
   724 	@leave			KErrNotSupported URI does not specify a local file
       
   725 	@leave			KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
       
   726 	@since			9.1
       
   727 	@return			A descriptor containing the fully-qualified filename. 
       
   728 	@pre 			Object is fully constructed.
       
   729 	
       
   730  */
       
   731  #endif
       
   732 EXPORT_C HBufC* TUriC16::GetFileNameL() const
       
   733 	{
       
   734 	return GetFileNameL(EUriFileNameFull);
       
   735 	}
       
   736 
       
   737 
       
   738 /**
       
   739 	This creates a file name from the URI, changing the network path separator (/) to the 
       
   740 	local file system path separator (\\). 
       
   741 	
       
   742 	If called with EUriFileNamePath, this will generate a file name containing  the path relative to the drive. 
       
   743 	Any parameters in the URI are stripped off:
       
   744 		@code
       
   745 		http://www.foo.com/dir/file/name.ext;param1;param2 -> \dir\file\name.ext
       
   746 		@endcode
       
   747 	
       
   748 	If called with EUriFileNameTail, this will generate a just the name, with no directories or drive.
       
   749 	Any parameters in the URI are stripped off:
       
   750 		@code
       
   751 		http://www.foo.com/dir/file/name.ext;param1;param2 -> name.ext
       
   752 		@endcode
       
   753 	
       
   754 	EUriFileNamePath and EUriFileNameTail can be used for any hierarchical URI (http, ftp, file)
       
   755 	and may have unexpected behaviour when called on any other type of URI.
       
   756 
       
   757 	If called with EUriFileNameFull, this will convert the URI into a fully-qualified filename. this is only valid
       
   758 	for file URIs and will Leave if called on any other type of URI. The form of the returned filename is described in 
       
   759 	GetFileNameL with no arguments.
       
   760 	
       
   761 	@leave			KErrNotSupported The URI scheme cannot be converted into the desired  type
       
   762 	@since			9.1
       
   763 	@pre 			Object is fully constructed.
       
   764 	@param			aType specifies what part of the filename is to be converted. The default is (EUriFileNameFull).
       
   765 	@return			A descriptor containing the desired filename components.
       
   766  */
       
   767 EXPORT_C HBufC* TUriC16::GetFileNameL(TUriFileName aType) const
       
   768 	{
       
   769 	TBool isFileUri = Extract(EUriScheme).Compare(KFileUriScheme16) == 0;
       
   770 
       
   771 	if(aType == EUriFileNameFull &&  !isFileUri )
       
   772 		{		
       
   773 		User::Leave(KErrNotSupported);
       
   774 		}		
       
   775 
       
   776 	HBufC8* fileUriPath8 = HBufC8::NewLC(Extract(EUriPath).Length());
       
   777 	fileUriPath8->Des().Copy(Extract(EUriPath));
       
   778 	HBufC* absFileName = ResolveFileNameL(*fileUriPath8, aType, isFileUri);
       
   779 	CleanupStack::PopAndDestroy(fileUriPath8);
       
   780 	return absFileName;
       
   781 	}
       
   782 
       
   783 
       
   784 //
       
   785 //
       
   786 // Implementation of LOCAL functions
       
   787 //
       
   788 //
       
   789 
       
   790 /**
       
   791   Function used to convert '\' to '/' and vice versa.
       
   792 	
       
   793   @since			9.1
       
   794   @param			aDesPtr				A descriptor reference to the string.
       
   795   @param			aPathSeperatorFrom	A path seperator to be converted (from)
       
   796   @param			aPathSeperatorTo 	A path seperator to converte (To).
       
   797  */
       
   798 void ChangePathSeparator(TDes& aDesPtr, TUint aPathSeperatorFrom, TUint aPathSeperatorTo)
       
   799 	{
       
   800 	for(TInt offset = aDesPtr.Length() - 1;offset >= 0;offset--)
       
   801 		{
       
   802 		if (aDesPtr[offset] == aPathSeperatorFrom)
       
   803 			{	
       
   804 				aDesPtr[offset] = TUint16(aPathSeperatorTo);
       
   805 			}
       
   806 		}
       
   807 	}
       
   808 
       
   809 /**
       
   810   Function used to generate a fully qualified file name for a public or private file 
       
   811   stored on a fix drive or a removable media drive from File URI path (parameter aFileUriPath).
       
   812 	
       
   813   This will be called by API GetFileName() to generate and return a filename.
       
   814 	
       
   815   @leave			KErrBadName 	if the path doesn't contain valid drivename.
       
   816   @since			9.1
       
   817   @param			aFileUriPath	A descriptor reference to the File URI's path component.
       
   818   @return			A pointer to a buffer containing the resolved fully qualified filename 
       
   819 					if the file uri path is not empty or a top level dir on main drive (C:\\)
       
   820  */
       
   821 HBufC* GetFullFileNameFromFileUriPathL(const TDesC& aFileUriPath)
       
   822 	{	
       
   823 	TFileName filename(KDefaultPath);
       
   824 	
       
   825 	TInt origLength = aFileUriPath.Length();
       
   826 	if(origLength == 0)
       
   827 		{
       
   828 		return filename.AllocL();
       
   829 		}
       
   830 		
       
   831 	TInt index = 0;
       
   832  	TPtrC fileUriPath(aFileUriPath);
       
   833  	
       
   834  	//skip KUriPathSeparator (/) from the Uri path
       
   835  	if (fileUriPath[0] == KUriPathSeparator)
       
   836   		{
       
   837 		index++;
       
   838 		}
       
   839 	
       
   840 	fileUriPath.Set(aFileUriPath.Right(origLength - index));
       
   841 
       
   842 	RFs fs;
       
   843 	TBool fsOpen = EFalse;
       
   844 				
       
   845 #ifdef __SECURE_DATA__			
       
   846 	if (fileUriPath.Left(KPrivate().Length()).Compare(KPrivate) == 0)
       
   847 		{
       
   848 		index += KPrivate().Length();
       
   849 		User::LeaveIfError(fs.Connect());
       
   850 		CleanupClosePushL(fs);		
       
   851 		fsOpen = ETrue;
       
   852 		User::LeaveIfError(fs.PrivatePath(filename));
       
   853 		filename.Insert(0, KDefaultPath().Left((KDefaultPath().Length() - 1) )); //Insert <drive>: 
       
   854 		fileUriPath.Set(aFileUriPath.Right(origLength - index));
       
   855 		}
       
   856 #endif
       
   857 	
       
   858 	TBool isExtMedia = (fileUriPath.Left(KExtMedia().Length()).Compare(KExtMedia) == 0);
       
   859 	if (!isExtMedia )
       
   860 		{
       
   861 		TUint driveLetter = fileUriPath[0];	
       
   862 		//Checking for valid driveletter (should between A to Z or a to z) and followed by Uri path seperator "/"
       
   863 		if ( fileUriPath[1] != KUriPathSeparator ||
       
   864 		 (  (driveLetter < 'A' || driveLetter > 'Z') && 
       
   865 			(driveLetter < 'a' || driveLetter > 'z')  )  )
       
   866 			{
       
   867 			User::Leave(KErrBadName);
       
   868 			}
       
   869 		index += (KDefaultPath().Length() - 1); //skip <driveLetter>/
       
   870 		filename[0] = TUint16(driveLetter); 
       
   871 		}
       
   872 	else
       
   873 		{
       
   874 		index += KExtMedia().Length();
       
   875 		}
       
   876 		
       
   877 	filename.Append(aFileUriPath.Right(origLength - index));
       
   878 		
       
   879 	//Convert "/" to "\"
       
   880 	ChangePathSeparator(filename, KUriPathSeparator, KFilePathSeparator);
       
   881 
       
   882 	if (isExtMedia )
       
   883 		{		
       
   884 		if (fsOpen == EFalse)
       
   885 			{
       
   886 			User::LeaveIfError(fs.Connect());
       
   887 			CleanupClosePushL(fs);		
       
   888 			fsOpen = ETrue;	
       
   889 			}
       
   890 		
       
   891 		TDriveInfo driveInfo;
       
   892 		TInt err = KErrNotFound;
       
   893 
       
   894 		for (TInt driveNum = EDriveA; driveNum <= EDriveZ && err!=KErrNone; driveNum++)   
       
   895 			{
       
   896 			if (fs.Drive(driveInfo, driveNum ) == KErrNone
       
   897     			&& (driveInfo.iDriveAtt & KDriveAttRemovable))       
       
   898     			{
       
   899     			filename[0]= TInt16('A' + driveNum);
       
   900     			TUint attValue;
       
   901     			err = fs.Att(filename, attValue);
       
   902     			}
       
   903 			}
       
   904   		User::LeaveIfError(err);
       
   905 		}
       
   906 							
       
   907 	if (fsOpen)
       
   908 		{
       
   909 		CleanupStack::PopAndDestroy(&fs);
       
   910 		}
       
   911 		
       
   912 	return filename.AllocL();	
       
   913 	}
       
   914 
       
   915 /**
       
   916   Creates an 8 bit URI descriptor from an 16  bit one
       
   917 	
       
   918   @param			aBuf16	The full 16 bit URI descriptor
       
   919   @return			Pointer to the newly created 8 bit URI descriptor
       
   920 					are valid, otherwise EFalse.
       
   921 */
       
   922 HBufC8* CreateUri8LC(const TDesC16& aBuf16)
       
   923 	{
       
   924 	TInt length = aBuf16.Length();
       
   925 	HBufC8* newBuf = HBufC8::NewMaxLC(length);
       
   926 	TPtr8 des8Ptr = newBuf->Des();
       
   927 	for (TInt i = 0; i < length; ++i)
       
   928 		{
       
   929 		des8Ptr[i] = static_cast<TText8>(aBuf16[i]);
       
   930 		}
       
   931 	return newBuf;
       
   932 	}
       
   933 
       
   934 /**
       
   935   Check the components of a URI to ensure they are all valid
       
   936 	
       
   937   @since			8.1
       
   938   @param			aUri The URI to check
       
   939   @return			KErrNone if all components are valid, otherwise one of the 'invalid' error codes
       
   940 */
       
   941 TInt DoValidate(const TUriC8& aUri)
       
   942 	{
       
   943 	TInt result;
       
   944 	TPtrC8 subComponent(aUri.Extract(EUriScheme));
       
   945 	if (!HasValidSchemeChars(subComponent))
       
   946 		{
       
   947 		result = KUriUtilsErrInvalidScheme;
       
   948 		}
       
   949 	else if(SchemeType(subComponent) == ESchemeTypeSip) 
       
   950 		//To validate Sip uri
       
   951 		{
       
   952 		TValidatorSip validator(aUri);
       
   953 		result = validator.Validate();		
       
   954 		}	
       
   955 	else if(SchemeType(subComponent) == ESchemeTypeTel) 
       
   956 		//To validate Tel uri
       
   957 		{
       
   958 		TValidatorTel validator(aUri);
       
   959 		result = validator.Validate();
       
   960 		}
       
   961 	else		
       
   962 		{
       
   963 		result = KErrNotSupported;		
       
   964 		}
       
   965 		
       
   966 	return result;
       
   967 	}
       
   968 
       
   969 /**
       
   970   Compare the components of two URIs to see if they identify the same resource
       
   971 	
       
   972   @since			8.1
       
   973   @param			aLhs The left hand side URI to compare
       
   974   @param			aRhs The right hand side URI to compare
       
   975   @return			ETrue if they point to the same resource, EFalse otherwise.
       
   976 */
       
   977 TInt DoEquivalenceL(const TUriC8& aLhs, const TUriC8& aRhs)
       
   978 	{
       
   979 	TInt result;
       
   980 	if (SchemeType(aLhs.Extract(EUriScheme)) == ESchemeTypeSip)
       
   981 		{
       
   982 		TEquivSip equiv(aLhs, aRhs);
       
   983 		result = equiv.EquivalentL();
       
   984 		}
       
   985 	else
       
   986 		{
       
   987 		// unknown scheme so assume network scheme
       
   988 		TEquiv equiv(aLhs, aRhs);
       
   989 		result = equiv.EquivalentL();
       
   990 		}
       
   991 	
       
   992 	return result;
       
   993 	}
       
   994 
       
   995 
       
   996 /**
       
   997   Get the desired part of the filename from the URI path
       
   998 	
       
   999   @param			aPath A descriptor reference to the File URI's path component.
       
  1000   @param			aType enum value of TUriFileName.
       
  1001   @param			aIsFileUri Specifies the whether it is FileUri or not.
       
  1002   @return			Pointer to the newly created URI descriptor which contains the 
       
  1003   					desired part of the filename from the URI path.
       
  1004 */
       
  1005 HBufC* ResolveFileNameL(const TDesC8& aPath, TUriFileName aType, TBool aIsFileUri)
       
  1006 	{	
       
  1007 	// replace % codes
       
  1008 	HBufC8* fileUriPath8 = EscapeUtils::EscapeDecodeL(aPath);
       
  1009 	CleanupStack::PushL(fileUriPath8);
       
  1010 	
       
  1011 	// convert to unicode 
       
  1012 	HBufC* fileUriPath = EscapeUtils::ConvertToUnicodeFromUtf8L(*fileUriPath8);
       
  1013 	CleanupStack::PopAndDestroy(fileUriPath8);
       
  1014 	CleanupStack::PushL(fileUriPath);			
       
  1015 
       
  1016 	HBufC* absFileName = NULL; // setting to NULL makes compiler happy
       
  1017 	if ( aIsFileUri )
       
  1018 		{ 
       
  1019 		/* awlays do full conversion for file URIs
       
  1020 		 It's not optimal time-wise, but it uses the least code and is
       
  1021 		 forward-compatible. */
       
  1022 		absFileName = GetFullFileNameFromFileUriPathL(*fileUriPath);		
       
  1023 		CleanupStack::PopAndDestroy(fileUriPath);
       
  1024 		if ( aType == EUriFileNameFull )
       
  1025 			{	
       
  1026 			return absFileName;
       
  1027 			}
       
  1028 		fileUriPath = absFileName;	// code below uses fileUriPath
       
  1029 		CleanupStack::PushL(fileUriPath);			
       
  1030 		TPtr path(fileUriPath->Des());
       
  1031 		path.Delete(0,2);	// delete drive and ':' (always begins with drive letter and :)
       
  1032 		}
       
  1033 	else  // not a file URI
       
  1034 		{ // convert '/' to '\' for all other URIs
       
  1035 		TPtr path(fileUriPath->Des());
       
  1036 		ChangePathSeparator(path, KUriPathSeparator, KFilePathSeparator);
       
  1037 		}
       
  1038 		
       
  1039 	// EUriFileNameFull must only ever be used with a file URI. Failures should be caught by the caller
       
  1040 	__ASSERT_DEBUG(aType != EUriFileNameFull, 
       
  1041 		User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
  1042 	
       
  1043 	TPtrC name;
       
  1044 	GetFileComponent(name, *fileUriPath, aType ); // get path or tail
       
  1045 	if (name.Length() == fileUriPath->Length()) 
       
  1046 		{ // no changes, just return fileUriPath
       
  1047 		absFileName = fileUriPath;
       
  1048 		CleanupStack::Pop(fileUriPath);
       
  1049 		}
       
  1050 	else
       
  1051 		{
       
  1052 		absFileName = name.AllocL();
       
  1053 		CleanupStack::PopAndDestroy(fileUriPath); 
       
  1054 		}
       
  1055 	
       
  1056 	return absFileName;
       
  1057 	}
       
  1058 
       
  1059 /**
       
  1060   Gets the desired file path or tail.
       
  1061 	
       
  1062   @param			aNewName An outparameter, reference to descriptor .
       
  1063   @param			aOldName An inparameter descriptor reference.
       
  1064   @param			aType enum value of TUriFileName.
       
  1065  */
       
  1066 void GetFileComponent(TPtrC& aNewName, const TDesC& aOldName, TUriFileName aType )
       
  1067 	{
       
  1068 	__ASSERT_ALWAYS(aType != EUriFileNameFull, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
       
  1069 
       
  1070 	aNewName.Set(aOldName);
       
  1071 	// chop off everything after the first ;
       
  1072 	TInt pos = aNewName.Locate(KParamDelimiter);
       
  1073 	if( pos == 0 ) // the ; is at the start
       
  1074 		{	
       
  1075 		aNewName.Set(KNullDesC);
       
  1076 		}
       
  1077 	else if (pos > 0)
       
  1078 		{ // set to the text untilt he ;
       
  1079 		aNewName.Set(aNewName.Left(pos));
       
  1080 		}
       
  1081 	if( aType == EUriFileNameTail)
       
  1082 		{	
       
  1083 		// chop off everything before the last /
       
  1084 		TInt pos = aNewName.LocateReverse(KFilePathSeparator);
       
  1085 		if( pos >=0 ) // there is a /
       
  1086 			{
       
  1087 			if( pos >= aNewName.Length() - 1 ) // the / is at the end
       
  1088 				{
       
  1089 				aNewName.Set(KNullDesC);
       
  1090 				}
       
  1091 			else
       
  1092 				{ // set to the text following the last /
       
  1093 				aNewName.Set(aNewName.Right(aNewName.Length()-1-pos));
       
  1094 				}
       
  1095 			}
       
  1096 		}
       
  1097 	}
       
  1098 
       
  1099 
       
  1100 
       
  1101