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