os/ossrv/genericservices/httputils/UriParser/TUriC.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 // 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