sl@0: // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: // System includes sl@0: #include sl@0: #include sl@0: #include "TUriCInternal.h" sl@0: #include sl@0: #include sl@0: #include "UriUtilsInternal.h" sl@0: #include "TValidator.h" sl@0: #include "TEquiv.h" sl@0: #include sl@0: sl@0: sl@0: sl@0: // Panic category sl@0: // sl@0: _LIT(KUriPanicCategory,"URI-BASE"); sl@0: sl@0: // sl@0: // sl@0: // Implementation of TUriC8 sl@0: // sl@0: // sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: @since 6.0 sl@0: */ sl@0: EXPORT_C TUriC8::TUriC8() sl@0: { sl@0: // Reset the component table and the Uri sl@0: Reset(); sl@0: } sl@0: sl@0: /** sl@0: Retrieves the specified component in the uri. sl@0: sl@0: @since 6.0 sl@0: @param aComponent The enum specifying the component. sl@0: @return A constant reference to a descriptor pointer to the specified sl@0: component. sl@0: */ sl@0: EXPORT_C const TDesC8& TUriC8::Extract(TUriComponent aComponent) const sl@0: { sl@0: __ASSERT_ALWAYS(aComponentEUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: return iComponent[aComponent]; sl@0: } sl@0: sl@0: /** sl@0: Indicates whether the specified component is present in the uri. sl@0: sl@0: @since 6.0 sl@0: @param aComponent The enum specifying the component. sl@0: @return A boolean value of ETrue if the desired component is present, sl@0: or EFalse if the desired component is not present. sl@0: */ sl@0: EXPORT_C TBool TUriC8::IsPresent(TUriComponent aComponent) const sl@0: { sl@0: __ASSERT_ALWAYS(aComponentEUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: return TBool(iComponent[aComponent].Ptr()); sl@0: } sl@0: sl@0: /** sl@0: Checks the scheme to be valid. If there is no scheme then the return value sl@0: indicates an invalid scheme. sl@0: sl@0: @since 6.0 sl@0: @return A boolean value of ETrue if the scheme is valid, or EFalse if sl@0: the scheme is not. sl@0: */ sl@0: EXPORT_C TBool TUriC8::IsSchemeValid() const sl@0: { sl@0: if( !IsPresent(EUriScheme) ) sl@0: { sl@0: return EFalse; sl@0: } sl@0: return HasValidSchemeChars(iComponent[EUriScheme]); sl@0: } sl@0: sl@0: /** sl@0: Compares the specified component against the one in the uri passed in. sl@0: sl@0: @since 6.0 sl@0: @param aUri The uri to compare components against. sl@0: @param aComponent The enum specifying the component to compare. sl@0: @return An integer value of zero if the components are the same, sl@0: any other value if the components are not the same. sl@0: */ sl@0: EXPORT_C TInt TUriC8::Compare(const TUriC8& aUri, TUriComponent aComponent) const sl@0: { sl@0: __ASSERT_ALWAYS(aComponentEUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: // Does the component exist in both the Uri's sl@0: if( IsPresent(aComponent) && aUri.IsPresent(aComponent) ) sl@0: { sl@0: if( aComponent == EUriScheme || aComponent == EUriHost ) sl@0: { sl@0: // Do case insensitive compare for scheme and host sl@0: return (iComponent[aComponent].CompareF(aUri.iComponent[aComponent])); sl@0: } sl@0: else sl@0: { sl@0: // Do case sensitive compare for all other components sl@0: return (iComponent[aComponent].Compare(aUri.iComponent[aComponent])); sl@0: } sl@0: } sl@0: else sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: /** sl@0: Retrieves the descriptor for the entire uri. sl@0: sl@0: @since 6.0 sl@0: @return A const reference to a descriptor pointer to the uri. sl@0: */ sl@0: EXPORT_C const TDesC8& TUriC8::UriDes() const sl@0: { sl@0: return iUriDes; sl@0: } sl@0: sl@0: /** sl@0: @publishedPartner sl@0: @released sl@0: Ensures that all components of the URI are valid. If the method returns sl@0: KUriUtilsErrInvalidUri then one or more components are not valid. It is sl@0: possible for URIs declared valid by this method to be, on detailed inspection, sl@0: invalid. sl@0: sl@0: @return KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported. sl@0: */ sl@0: EXPORT_C TInt TUriC8::Validate() const sl@0: { sl@0: return DoValidate(*this); sl@0: } sl@0: sl@0: /** sl@0: Compares the given URI to determine if it is equivalent to this URI. It is possible sl@0: for URIs declared NOT equivalent by this method to be equvalent to a level not checked sl@0: by this method. sl@0: @publishedPartner sl@0: @released sl@0: @param aUri Contains URI to compare sl@0: @return ETrue if the two URIs are equivalent otherwise EFalse sl@0: */ sl@0: EXPORT_C TInt TUriC8::Equivalent(const TUriC8& aUri) const sl@0: { sl@0: TInt result = EFalse; sl@0: TRAPD(error, result = DoEquivalenceL(*this, aUri)); sl@0: if (error != KErrNone) sl@0: { sl@0: result = error; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Retrieves the uri without the fragment component. sl@0: sl@0: @since 6.0 sl@0: @param aUriNoFrag An output parameter which is set the non-reference sl@0: version of the uri. sl@0: */ sl@0: EXPORT_C void TUriC8::UriWithoutFragment(TPtrC8& aUriNoFrag) const sl@0: { sl@0: if( IsPresent(EUriFragment) ) sl@0: { sl@0: // There is a fragment, find where it starts sl@0: TInt fragmentStartPos = iUriDes.Locate(KFragmentDelimiter); sl@0: aUriNoFrag.Set(iUriDes.Left(fragmentStartPos)); sl@0: } sl@0: else{ sl@0: aUriNoFrag.Set(iUriDes); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Create a new HBufC descriptor containing the desired component or the full URI. sl@0: sl@0: @param aComponent The component to convert into Unicode (EUriScheme - EUriFragment), or sl@0: the full URI (EUriComplete -- the default). sl@0: @return The descriptor containing the desired component. sl@0: */ sl@0: EXPORT_C HBufC* TUriC8::DisplayFormL(TUriComponent aComponent) const sl@0: { sl@0: TPtrC8 component; sl@0: sl@0: if (aComponent == EUriComplete) sl@0: { sl@0: component.Set(iUriDes); sl@0: } sl@0: else sl@0: { // extract the specified component, will Panic if invalid sl@0: component.Set( Extract(aComponent) ); sl@0: } sl@0: // convert descriptor from UTF-8 into Unicode sl@0: return EscapeUtils::ConvertToUnicodeFromUtf8L(component); sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: Resets the descriptor pointers for the uri components and the uri. sl@0: sl@0: @since 6.0 sl@0: @post All uri component information is removed and the uri descriptor is sl@0: set to NULL. sl@0: */ sl@0: void TUriC8::Reset() sl@0: { sl@0: // Set descriptor pointers to NULL and lengths to zero sl@0: for( TInt i=0; iEUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: return iComponent[aComponent]; sl@0: } sl@0: sl@0: /** sl@0: Indicates whether the specified component is present in the uri. sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: @param aComponent The enum specifying the component. sl@0: @return A boolean value of ETrue if the desired component is present, sl@0: or EFalse if the desired component is not present. sl@0: */ sl@0: EXPORT_C TBool TUriC16::IsPresent(TUriComponent aComponent) const sl@0: { sl@0: __ASSERT_ALWAYS(aComponentEUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: return TBool(iComponent[aComponent].Ptr()); sl@0: } sl@0: sl@0: /** sl@0: Checks to see if the scheme is valid. If there is no scheme then the return value sl@0: indicates an invalid scheme (EFalse). sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: @return A boolean value of ETrue if the scheme is valid, or EFalse if sl@0: the scheme is not. sl@0: */ sl@0: EXPORT_C TBool TUriC16::IsSchemeValid() const sl@0: { sl@0: if( !IsPresent(EUriScheme) ) sl@0: { sl@0: return EFalse; sl@0: } sl@0: return HasValidSchemeChars(iComponent[EUriScheme]); sl@0: } sl@0: sl@0: /** sl@0: Compares the specified component against the one in the uri passed in. sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: @param aUri The uri to compare components against. sl@0: @param aComponent The enum specifying the component to compare. sl@0: @return An integer value of zero if the components are the same, any other sl@0: value if the components are not the same. sl@0: */ sl@0: EXPORT_C TBool TUriC16::Compare(const TUriC16& aUri, TUriComponent aComponent) const sl@0: { sl@0: __ASSERT_ALWAYS(aComponentEUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: // Does the component exist in both the Uri's sl@0: if( IsPresent(aComponent) && aUri.IsPresent(aComponent) ) sl@0: { sl@0: if( aComponent == EUriScheme || aComponent == EUriHost ) sl@0: { sl@0: // Do case insensitive compare for scheme and host sl@0: return (iComponent[aComponent].CompareF(aUri.iComponent[aComponent])); sl@0: } sl@0: else sl@0: { sl@0: // Do case sensitive compare for all other components sl@0: return (iComponent[aComponent].Compare(aUri.iComponent[aComponent])); sl@0: } sl@0: } sl@0: else sl@0: return KErrNotFound; sl@0: } sl@0: sl@0: /** sl@0: Retrieves the descriptor for the entire uri. sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: @return A const reference to a descriptor pointer to the uri. sl@0: */ sl@0: EXPORT_C const TDesC16& TUriC16::UriDes() const sl@0: { sl@0: return iUriDes; sl@0: } sl@0: sl@0: /** sl@0: @deprecated Deprecated in 9.1 -- provided for compatibility sl@0: sl@0: Ensures that all components of the URI are valid. If the method returns sl@0: KUriUtilsErrInvalidUri then one or more components are not valid. It is possible sl@0: for URIs declared valid by this method to be, on detailed inspection, invalid. sl@0: sl@0: @return KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported. sl@0: */ sl@0: EXPORT_C TInt TUriC16::Validate() const sl@0: { sl@0: TInt result = KErrNone; sl@0: TRAPD(error, result = ValidateL()); sl@0: if (error) sl@0: { sl@0: // problem allocating resourses sl@0: return error; sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: @deprecated Deprecated in 9.1 -- provided for compatibility sl@0: sl@0: Compares the given URI to determine if it is equivalent to this URI. It is possible sl@0: for URIs declared NOT equivalent by this method to be equvalent to a level not checked sl@0: by this method. sl@0: @param aUri Contains URI to compare sl@0: @return ETrue if the two URIs are equivalent otherwise EFalse sl@0: */ sl@0: EXPORT_C TInt TUriC16::Equivalent(const TUriC16& aUri) const sl@0: { sl@0: TInt result = KErrNone; sl@0: TRAPD(error, result = EquivalentL(aUri.UriDes())); sl@0: if (error) sl@0: { sl@0: // problem allocating resourses sl@0: return error; sl@0: } sl@0: return result; sl@0: } sl@0: /** sl@0: Retrieves the uri without the fragment component. sl@0: sl@0: @since 6.0 sl@0: @deprecated Deprecated in 9.1 sl@0: @param aUriNoFrag An output parameter which is set the non-reference sl@0: version of the uri. sl@0: */ sl@0: sl@0: EXPORT_C void TUriC16::UriWithoutFragment(TPtrC16& aUriNoFrag) const sl@0: { sl@0: if( IsPresent(EUriFragment) ) sl@0: { sl@0: // There is a fragment, find where it starts sl@0: TInt fragmentStartPos = iUriDes.Locate(KFragmentDelimiter); sl@0: aUriNoFrag.Set(iUriDes.Left(fragmentStartPos)); sl@0: } sl@0: else{ sl@0: aUriNoFrag.Set(iUriDes); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Create a new HBufC descriptor containing the desired component or the full URI. sl@0: @deprecated Deprecated in 9.1 - provided for compatibility sl@0: sl@0: @param aComponent The component to convert into Unicode (EUriScheme - EUriFragment), or sl@0: the full URI (EUriComplete -- the default). sl@0: @return The descriptor containing the desired component. sl@0: */ sl@0: EXPORT_C HBufC* TUriC16::DisplayFormL(TUriComponent aComponent) const sl@0: { sl@0: if ( aComponent == EUriComplete) // extract the full URI sl@0: { sl@0: return iUriDes.AllocL(); sl@0: } sl@0: return Extract(aComponent).AllocL(); sl@0: } sl@0: sl@0: /** sl@0: @internalComponent sl@0: Resets the descriptor pointers for the uri components and the uri. sl@0: sl@0: @since 6.0 sl@0: @post All uri component information is removed and the uri descriptor is sl@0: set to NULL. sl@0: */ sl@0: void TUriC16::Reset() sl@0: { sl@0: // Set descriptor pointers to NULL and lengths to zero sl@0: for( TInt i=0; i sl@0: LOCAL_C TBool HasValidSchemeChars(const TPtrCType& aScheme) sl@0: { sl@0: TInt length = aScheme.Length(); sl@0: TBool valid = ( length && TChar(aScheme[0]).IsAlpha() ); sl@0: sl@0: // Start checking from the second character sl@0: TInt i=1; sl@0: while( valid && i c:\path\to\file\name.ext sl@0: @endcode sl@0: sl@0: - public file on removable media drive: sl@0: The fully-qualified filename is resolved by finding the first drive on which the file exists. sl@0: If the file does not exist, this will Leave with KErrNotFound sl@0: @code sl@0: file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext sl@0: @endcode sl@0: (where f: is the first drive found containing "\path\to\file\name.ext") sl@0: sl@0: - private file on fixed drive: sl@0: @code sl@0: file://private/c/path/to/file/name.ext -> c:\private\0x1001234f\path\to\file\name.ext sl@0: @endcode sl@0: (where 0x1001234f is the SID of the current application) sl@0: sl@0: - private file on removable media drive: sl@0: @code sl@0: file://private/ext-media/path/to/file/name.ext -> h:\private\0x1001234f\path\to\file\name.ext sl@0: @endcode sl@0: (where h: is the first drive found containing "\private\0x1001234f\path\to\file\name.ext") sl@0: sl@0: The returned file name is not guaranteed to exist except where specified above. sl@0: sl@0: Be warned that this method may be slow when resolving special paths (like "/ext-media") sl@0: sl@0: @leave KErrNotSupported URI does not specify a local file sl@0: @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any. sl@0: @since 9.1 sl@0: @return A descriptor containing the fully-qualified filename. sl@0: @pre Object is fully constructed. sl@0: */ sl@0: #else sl@0: /** sl@0: Generates a fully-qualified filename from a file URI object. sl@0: sl@0: The form of the returned filename depends on the file location, as follows: sl@0: - public file on a fixed drive: sl@0: @code sl@0: file://c/path/to/file/name.ext -> c:\path\to\file\name.ext sl@0: @endcode sl@0: sl@0: - public file on removable media drive: sl@0: The fully-qualified filename is resolved by finding the first drive on which the file exists. sl@0: If the file does not exist, this will Leave with KErrNotFound sl@0: @code sl@0: file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext sl@0: @endcode sl@0: (where f: is the first drive found containing "\path\to\file\name.ext") sl@0: sl@0: The returned file name is not guaranteed to exist except where specified above. sl@0: sl@0: Be warned that this method may be slow when resolving special paths (like "/ext-media") sl@0: sl@0: @leave KErrNotSupported URI does not specify a local file sl@0: @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any. sl@0: @since 9.1 sl@0: @return A descriptor containing the fully-qualified filename. sl@0: @pre Object is fully constructed. sl@0: */ sl@0: #endif sl@0: EXPORT_C HBufC* TUriC8::GetFileNameL() const sl@0: { sl@0: return GetFileNameL(EUriFileNameFull); sl@0: } sl@0: sl@0: sl@0: /** sl@0: This creates a file name from the URI, changing the network path separator (/) to the sl@0: local file system path separator (\\). sl@0: sl@0: If called with EUriFileNamePath, this will generate a file name containing the path relative to the drive. sl@0: Any parameters in the URI are stripped off: sl@0: @code sl@0: http://www.foo.com/dir/file/name.ext;param1;param2 -> \dir\file\name.ext sl@0: @endcode sl@0: sl@0: If called with EUriFileNameTail, this will generate a just the name, with no directories or drive. sl@0: Any parameters in the URI are stripped off: sl@0: @code sl@0: http://www.foo.com/dir/file/name.ext;param1;param2 -> name.ext sl@0: @endcode sl@0: sl@0: EUriFileNamePath and EUriFileNameTail can be used for any hierarchical URI (http, ftp, file, etc) sl@0: and may have unexpected behaviour when called on any other type of URI. sl@0: sl@0: If called with EUriFileNameFull, this will convert the URI into a fully-qualified filename. this is only valid sl@0: for file URIs and will Leave if called on any other type of URI. The form of the returned filename is described in sl@0: GetFileNameL with no arguments. sl@0: sl@0: @leave KErrNotSupported The URI scheme cannot be converted into the desired type sl@0: @since 9.1 sl@0: @pre Object is fully constructed. sl@0: @param aType specifies what part of the filename is to be converted. The default is EUriFileNameFull). sl@0: @return A descriptor containing the desired filename components. sl@0: */ sl@0: EXPORT_C HBufC* TUriC8::GetFileNameL(TUriFileName aType) const sl@0: { sl@0: TBool isFileUri = Extract(EUriScheme).Compare(KFileUriScheme8) == 0; sl@0: if(aType == EUriFileNameFull && !isFileUri) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: return ResolveFileNameL(Extract(EUriPath), aType, isFileUri); sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // File URI Implementation - CUri16 sl@0: // sl@0: // sl@0: sl@0: #ifdef __SECURE_DATA__ sl@0: /** sl@0: Generates a fully-qualified filename from a file URI object. sl@0: sl@0: The form of the returned filename depends on the file location, as follows: sl@0: - public file on a fixed drive: sl@0: @code sl@0: file://c/path/to/file/name.ext -> c:\path\to\file\name.ext sl@0: @endcode sl@0: sl@0: - public file on removable media drive: sl@0: The fully-qualified filename is resolved by finding the first drive on which the file exists. sl@0: If the file does not exist, this will Leave with KErrNotFound sl@0: @code sl@0: file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext sl@0: @endcode sl@0: (where f: is the first drive found containing "\path\to\file\name.ext") sl@0: sl@0: - private file on fixed drive: sl@0: @code sl@0: file://private/c/path/to/file/name.ext -> c:\private\0x1001234f\path\to\file\name.ext sl@0: @endcode sl@0: (where 0x1001234f is the SID of the current application) sl@0: sl@0: - private file on removable media drive: sl@0: @code sl@0: file://private/ext-media/path/to/file/name.ext -> h:\private\0x1001234f\path\to\file\name.ext sl@0: @endcode sl@0: (where h: is the first drive found containing "\private\0x1001234f\path\to\file\name.ext") sl@0: sl@0: The returned file name is not guaranteed to exist except where specified above. sl@0: sl@0: Be warned that this method may be slow when resolving special paths (like "/ext-media") sl@0: sl@0: @leave KErrNotSupported URI does not specify a local file sl@0: @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any. sl@0: @since 9.1 sl@0: @return A descriptor containing the fully-qualified filename. sl@0: @pre Object is fully constructed. sl@0: sl@0: */ sl@0: #else sl@0: /** sl@0: Generates a fully-qualified filename from a file URI object. sl@0: sl@0: The form of the returned filename depends on the file location, as follows: sl@0: - public file on a fixed drive: sl@0: @code sl@0: file://c/path/to/file/name.ext -> c:\path\to\file\name.ext sl@0: @endcode sl@0: sl@0: - public file on removable media drive: sl@0: The fully-qualified filename is resolved by finding the first drive on which the file exists. sl@0: If the file does not exist, this will Leave with KErrNotFound sl@0: @code sl@0: file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext sl@0: @endcode sl@0: (where f: is the first drive found containing "\path\to\file\name.ext") sl@0: sl@0: The returned file name is not guaranteed to exist except where specified above. sl@0: sl@0: Be warned that this method may be slow when resolving special paths (like "/ext-media") sl@0: sl@0: @leave KErrNotSupported URI does not specify a local file sl@0: @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any. sl@0: @since 9.1 sl@0: @return A descriptor containing the fully-qualified filename. sl@0: @pre Object is fully constructed. sl@0: sl@0: */ sl@0: #endif sl@0: EXPORT_C HBufC* TUriC16::GetFileNameL() const sl@0: { sl@0: return GetFileNameL(EUriFileNameFull); sl@0: } sl@0: sl@0: sl@0: /** sl@0: This creates a file name from the URI, changing the network path separator (/) to the sl@0: local file system path separator (\\). sl@0: sl@0: If called with EUriFileNamePath, this will generate a file name containing the path relative to the drive. sl@0: Any parameters in the URI are stripped off: sl@0: @code sl@0: http://www.foo.com/dir/file/name.ext;param1;param2 -> \dir\file\name.ext sl@0: @endcode sl@0: sl@0: If called with EUriFileNameTail, this will generate a just the name, with no directories or drive. sl@0: Any parameters in the URI are stripped off: sl@0: @code sl@0: http://www.foo.com/dir/file/name.ext;param1;param2 -> name.ext sl@0: @endcode sl@0: sl@0: EUriFileNamePath and EUriFileNameTail can be used for any hierarchical URI (http, ftp, file) sl@0: and may have unexpected behaviour when called on any other type of URI. sl@0: sl@0: If called with EUriFileNameFull, this will convert the URI into a fully-qualified filename. this is only valid sl@0: for file URIs and will Leave if called on any other type of URI. The form of the returned filename is described in sl@0: GetFileNameL with no arguments. sl@0: sl@0: @leave KErrNotSupported The URI scheme cannot be converted into the desired type sl@0: @since 9.1 sl@0: @pre Object is fully constructed. sl@0: @param aType specifies what part of the filename is to be converted. The default is (EUriFileNameFull). sl@0: @return A descriptor containing the desired filename components. sl@0: */ sl@0: EXPORT_C HBufC* TUriC16::GetFileNameL(TUriFileName aType) const sl@0: { sl@0: TBool isFileUri = Extract(EUriScheme).Compare(KFileUriScheme16) == 0; sl@0: sl@0: if(aType == EUriFileNameFull && !isFileUri ) sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: HBufC8* fileUriPath8 = HBufC8::NewLC(Extract(EUriPath).Length()); sl@0: fileUriPath8->Des().Copy(Extract(EUriPath)); sl@0: HBufC* absFileName = ResolveFileNameL(*fileUriPath8, aType, isFileUri); sl@0: CleanupStack::PopAndDestroy(fileUriPath8); sl@0: return absFileName; sl@0: } sl@0: sl@0: sl@0: // sl@0: // sl@0: // Implementation of LOCAL functions sl@0: // sl@0: // sl@0: sl@0: /** sl@0: Function used to convert '\' to '/' and vice versa. sl@0: sl@0: @since 9.1 sl@0: @param aDesPtr A descriptor reference to the string. sl@0: @param aPathSeperatorFrom A path seperator to be converted (from) sl@0: @param aPathSeperatorTo A path seperator to converte (To). sl@0: */ sl@0: void ChangePathSeparator(TDes& aDesPtr, TUint aPathSeperatorFrom, TUint aPathSeperatorTo) sl@0: { sl@0: for(TInt offset = aDesPtr.Length() - 1;offset >= 0;offset--) sl@0: { sl@0: if (aDesPtr[offset] == aPathSeperatorFrom) sl@0: { sl@0: aDesPtr[offset] = TUint16(aPathSeperatorTo); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Function used to generate a fully qualified file name for a public or private file sl@0: stored on a fix drive or a removable media drive from File URI path (parameter aFileUriPath). sl@0: sl@0: This will be called by API GetFileName() to generate and return a filename. sl@0: sl@0: @leave KErrBadName if the path doesn't contain valid drivename. sl@0: @since 9.1 sl@0: @param aFileUriPath A descriptor reference to the File URI's path component. sl@0: @return A pointer to a buffer containing the resolved fully qualified filename sl@0: if the file uri path is not empty or a top level dir on main drive (C:\\) sl@0: */ sl@0: HBufC* GetFullFileNameFromFileUriPathL(const TDesC& aFileUriPath) sl@0: { sl@0: TFileName filename(KDefaultPath); sl@0: sl@0: TInt origLength = aFileUriPath.Length(); sl@0: if(origLength == 0) sl@0: { sl@0: return filename.AllocL(); sl@0: } sl@0: sl@0: TInt index = 0; sl@0: TPtrC fileUriPath(aFileUriPath); sl@0: sl@0: //skip KUriPathSeparator (/) from the Uri path sl@0: if (fileUriPath[0] == KUriPathSeparator) sl@0: { sl@0: index++; sl@0: } sl@0: sl@0: fileUriPath.Set(aFileUriPath.Right(origLength - index)); sl@0: sl@0: RFs fs; sl@0: TBool fsOpen = EFalse; sl@0: sl@0: #ifdef __SECURE_DATA__ sl@0: if (fileUriPath.Left(KPrivate().Length()).Compare(KPrivate) == 0) sl@0: { sl@0: index += KPrivate().Length(); sl@0: User::LeaveIfError(fs.Connect()); sl@0: CleanupClosePushL(fs); sl@0: fsOpen = ETrue; sl@0: User::LeaveIfError(fs.PrivatePath(filename)); sl@0: filename.Insert(0, KDefaultPath().Left((KDefaultPath().Length() - 1) )); //Insert : sl@0: fileUriPath.Set(aFileUriPath.Right(origLength - index)); sl@0: } sl@0: #endif sl@0: sl@0: TBool isExtMedia = (fileUriPath.Left(KExtMedia().Length()).Compare(KExtMedia) == 0); sl@0: if (!isExtMedia ) sl@0: { sl@0: TUint driveLetter = fileUriPath[0]; sl@0: //Checking for valid driveletter (should between A to Z or a to z) and followed by Uri path seperator "/" sl@0: if ( fileUriPath[1] != KUriPathSeparator || sl@0: ( (driveLetter < 'A' || driveLetter > 'Z') && sl@0: (driveLetter < 'a' || driveLetter > 'z') ) ) sl@0: { sl@0: User::Leave(KErrBadName); sl@0: } sl@0: index += (KDefaultPath().Length() - 1); //skip / sl@0: filename[0] = TUint16(driveLetter); sl@0: } sl@0: else sl@0: { sl@0: index += KExtMedia().Length(); sl@0: } sl@0: sl@0: filename.Append(aFileUriPath.Right(origLength - index)); sl@0: sl@0: //Convert "/" to "\" sl@0: ChangePathSeparator(filename, KUriPathSeparator, KFilePathSeparator); sl@0: sl@0: if (isExtMedia ) sl@0: { sl@0: if (fsOpen == EFalse) sl@0: { sl@0: User::LeaveIfError(fs.Connect()); sl@0: CleanupClosePushL(fs); sl@0: fsOpen = ETrue; sl@0: } sl@0: sl@0: TDriveInfo driveInfo; sl@0: TInt err = KErrNotFound; sl@0: sl@0: for (TInt driveNum = EDriveA; driveNum <= EDriveZ && err!=KErrNone; driveNum++) sl@0: { sl@0: if (fs.Drive(driveInfo, driveNum ) == KErrNone sl@0: && (driveInfo.iDriveAtt & KDriveAttRemovable)) sl@0: { sl@0: filename[0]= TInt16('A' + driveNum); sl@0: TUint attValue; sl@0: err = fs.Att(filename, attValue); sl@0: } sl@0: } sl@0: User::LeaveIfError(err); sl@0: } sl@0: sl@0: if (fsOpen) sl@0: { sl@0: CleanupStack::PopAndDestroy(&fs); sl@0: } sl@0: sl@0: return filename.AllocL(); sl@0: } sl@0: sl@0: /** sl@0: Creates an 8 bit URI descriptor from an 16 bit one sl@0: sl@0: @param aBuf16 The full 16 bit URI descriptor sl@0: @return Pointer to the newly created 8 bit URI descriptor sl@0: are valid, otherwise EFalse. sl@0: */ sl@0: HBufC8* CreateUri8LC(const TDesC16& aBuf16) sl@0: { sl@0: TInt length = aBuf16.Length(); sl@0: HBufC8* newBuf = HBufC8::NewMaxLC(length); sl@0: TPtr8 des8Ptr = newBuf->Des(); sl@0: for (TInt i = 0; i < length; ++i) sl@0: { sl@0: des8Ptr[i] = static_cast(aBuf16[i]); sl@0: } sl@0: return newBuf; sl@0: } sl@0: sl@0: /** sl@0: Check the components of a URI to ensure they are all valid sl@0: sl@0: @since 8.1 sl@0: @param aUri The URI to check sl@0: @return KErrNone if all components are valid, otherwise one of the 'invalid' error codes sl@0: */ sl@0: TInt DoValidate(const TUriC8& aUri) sl@0: { sl@0: TInt result; sl@0: TPtrC8 subComponent(aUri.Extract(EUriScheme)); sl@0: if (!HasValidSchemeChars(subComponent)) sl@0: { sl@0: result = KUriUtilsErrInvalidScheme; sl@0: } sl@0: else if(SchemeType(subComponent) == ESchemeTypeSip) sl@0: //To validate Sip uri sl@0: { sl@0: TValidatorSip validator(aUri); sl@0: result = validator.Validate(); sl@0: } sl@0: else if(SchemeType(subComponent) == ESchemeTypeTel) sl@0: //To validate Tel uri sl@0: { sl@0: TValidatorTel validator(aUri); sl@0: result = validator.Validate(); sl@0: } sl@0: else sl@0: { sl@0: result = KErrNotSupported; sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: /** sl@0: Compare the components of two URIs to see if they identify the same resource sl@0: sl@0: @since 8.1 sl@0: @param aLhs The left hand side URI to compare sl@0: @param aRhs The right hand side URI to compare sl@0: @return ETrue if they point to the same resource, EFalse otherwise. sl@0: */ sl@0: TInt DoEquivalenceL(const TUriC8& aLhs, const TUriC8& aRhs) sl@0: { sl@0: TInt result; sl@0: if (SchemeType(aLhs.Extract(EUriScheme)) == ESchemeTypeSip) sl@0: { sl@0: TEquivSip equiv(aLhs, aRhs); sl@0: result = equiv.EquivalentL(); sl@0: } sl@0: else sl@0: { sl@0: // unknown scheme so assume network scheme sl@0: TEquiv equiv(aLhs, aRhs); sl@0: result = equiv.EquivalentL(); sl@0: } sl@0: sl@0: return result; sl@0: } sl@0: sl@0: sl@0: /** sl@0: Get the desired part of the filename from the URI path sl@0: sl@0: @param aPath A descriptor reference to the File URI's path component. sl@0: @param aType enum value of TUriFileName. sl@0: @param aIsFileUri Specifies the whether it is FileUri or not. sl@0: @return Pointer to the newly created URI descriptor which contains the sl@0: desired part of the filename from the URI path. sl@0: */ sl@0: HBufC* ResolveFileNameL(const TDesC8& aPath, TUriFileName aType, TBool aIsFileUri) sl@0: { sl@0: // replace % codes sl@0: HBufC8* fileUriPath8 = EscapeUtils::EscapeDecodeL(aPath); sl@0: CleanupStack::PushL(fileUriPath8); sl@0: sl@0: // convert to unicode sl@0: HBufC* fileUriPath = EscapeUtils::ConvertToUnicodeFromUtf8L(*fileUriPath8); sl@0: CleanupStack::PopAndDestroy(fileUriPath8); sl@0: CleanupStack::PushL(fileUriPath); sl@0: sl@0: HBufC* absFileName = NULL; // setting to NULL makes compiler happy sl@0: if ( aIsFileUri ) sl@0: { sl@0: /* awlays do full conversion for file URIs sl@0: It's not optimal time-wise, but it uses the least code and is sl@0: forward-compatible. */ sl@0: absFileName = GetFullFileNameFromFileUriPathL(*fileUriPath); sl@0: CleanupStack::PopAndDestroy(fileUriPath); sl@0: if ( aType == EUriFileNameFull ) sl@0: { sl@0: return absFileName; sl@0: } sl@0: fileUriPath = absFileName; // code below uses fileUriPath sl@0: CleanupStack::PushL(fileUriPath); sl@0: TPtr path(fileUriPath->Des()); sl@0: path.Delete(0,2); // delete drive and ':' (always begins with drive letter and :) sl@0: } sl@0: else // not a file URI sl@0: { // convert '/' to '\' for all other URIs sl@0: TPtr path(fileUriPath->Des()); sl@0: ChangePathSeparator(path, KUriPathSeparator, KFilePathSeparator); sl@0: } sl@0: sl@0: // EUriFileNameFull must only ever be used with a file URI. Failures should be caught by the caller sl@0: __ASSERT_DEBUG(aType != EUriFileNameFull, sl@0: User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: TPtrC name; sl@0: GetFileComponent(name, *fileUriPath, aType ); // get path or tail sl@0: if (name.Length() == fileUriPath->Length()) sl@0: { // no changes, just return fileUriPath sl@0: absFileName = fileUriPath; sl@0: CleanupStack::Pop(fileUriPath); sl@0: } sl@0: else sl@0: { sl@0: absFileName = name.AllocL(); sl@0: CleanupStack::PopAndDestroy(fileUriPath); sl@0: } sl@0: sl@0: return absFileName; sl@0: } sl@0: sl@0: /** sl@0: Gets the desired file path or tail. sl@0: sl@0: @param aNewName An outparameter, reference to descriptor . sl@0: @param aOldName An inparameter descriptor reference. sl@0: @param aType enum value of TUriFileName. sl@0: */ sl@0: void GetFileComponent(TPtrC& aNewName, const TDesC& aOldName, TUriFileName aType ) sl@0: { sl@0: __ASSERT_ALWAYS(aType != EUriFileNameFull, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex)); sl@0: sl@0: aNewName.Set(aOldName); sl@0: // chop off everything after the first ; sl@0: TInt pos = aNewName.Locate(KParamDelimiter); sl@0: if( pos == 0 ) // the ; is at the start sl@0: { sl@0: aNewName.Set(KNullDesC); sl@0: } sl@0: else if (pos > 0) sl@0: { // set to the text untilt he ; sl@0: aNewName.Set(aNewName.Left(pos)); sl@0: } sl@0: if( aType == EUriFileNameTail) sl@0: { sl@0: // chop off everything before the last / sl@0: TInt pos = aNewName.LocateReverse(KFilePathSeparator); sl@0: if( pos >=0 ) // there is a / sl@0: { sl@0: if( pos >= aNewName.Length() - 1 ) // the / is at the end sl@0: { sl@0: aNewName.Set(KNullDesC); sl@0: } sl@0: else sl@0: { // set to the text following the last / sl@0: aNewName.Set(aNewName.Right(aNewName.Length()-1-pos)); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: