1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericservices/httputils/UriParser/TUriC.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1101 @@
1.4 +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +// System includes
1.20 +#include <uri8.h>
1.21 +#include <uri16.h>
1.22 +#include "TUriCInternal.h"
1.23 +#include <uriutilscommon.h>
1.24 +#include <uriutils.h>
1.25 +#include "UriUtilsInternal.h"
1.26 +#include "TValidator.h"
1.27 +#include "TEquiv.h"
1.28 +#include <escapeutils.h>
1.29 +
1.30 +
1.31 +
1.32 +// Panic category
1.33 +//
1.34 +_LIT(KUriPanicCategory,"URI-BASE");
1.35 +
1.36 +//
1.37 +//
1.38 +// Implementation of TUriC8
1.39 +//
1.40 +//
1.41 +
1.42 +/**
1.43 + Constructor.
1.44 +
1.45 + @since 6.0
1.46 + */
1.47 +EXPORT_C TUriC8::TUriC8()
1.48 + {
1.49 + // Reset the component table and the Uri
1.50 + Reset();
1.51 + }
1.52 +
1.53 +/**
1.54 + Retrieves the specified component in the uri.
1.55 +
1.56 + @since 6.0
1.57 + @param aComponent The enum specifying the component.
1.58 + @return A constant reference to a descriptor pointer to the specified
1.59 + component.
1.60 + */
1.61 +EXPORT_C const TDesC8& TUriC8::Extract(TUriComponent aComponent) const
1.62 + {
1.63 + __ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.64 +
1.65 + return iComponent[aComponent];
1.66 + }
1.67 +
1.68 +/**
1.69 + Indicates whether the specified component is present in the uri.
1.70 +
1.71 + @since 6.0
1.72 + @param aComponent The enum specifying the component.
1.73 + @return A boolean value of ETrue if the desired component is present,
1.74 + or EFalse if the desired component is not present.
1.75 + */
1.76 +EXPORT_C TBool TUriC8::IsPresent(TUriComponent aComponent) const
1.77 + {
1.78 + __ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.79 +
1.80 + return TBool(iComponent[aComponent].Ptr());
1.81 + }
1.82 +
1.83 +/**
1.84 + Checks the scheme to be valid. If there is no scheme then the return value
1.85 + indicates an invalid scheme.
1.86 +
1.87 + @since 6.0
1.88 + @return A boolean value of ETrue if the scheme is valid, or EFalse if
1.89 + the scheme is not.
1.90 + */
1.91 +EXPORT_C TBool TUriC8::IsSchemeValid() const
1.92 + {
1.93 + if( !IsPresent(EUriScheme) )
1.94 + {
1.95 + return EFalse;
1.96 + }
1.97 + return HasValidSchemeChars(iComponent[EUriScheme]);
1.98 + }
1.99 +
1.100 +/**
1.101 + Compares the specified component against the one in the uri passed in.
1.102 +
1.103 + @since 6.0
1.104 + @param aUri The uri to compare components against.
1.105 + @param aComponent The enum specifying the component to compare.
1.106 + @return An integer value of zero if the components are the same,
1.107 + any other value if the components are not the same.
1.108 + */
1.109 +EXPORT_C TInt TUriC8::Compare(const TUriC8& aUri, TUriComponent aComponent) const
1.110 + {
1.111 + __ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.112 +
1.113 + // Does the component exist in both the Uri's
1.114 + if( IsPresent(aComponent) && aUri.IsPresent(aComponent) )
1.115 + {
1.116 + if( aComponent == EUriScheme || aComponent == EUriHost )
1.117 + {
1.118 + // Do case insensitive compare for scheme and host
1.119 + return (iComponent[aComponent].CompareF(aUri.iComponent[aComponent]));
1.120 + }
1.121 + else
1.122 + {
1.123 + // Do case sensitive compare for all other components
1.124 + return (iComponent[aComponent].Compare(aUri.iComponent[aComponent]));
1.125 + }
1.126 + }
1.127 + else
1.128 + return KErrNotFound;
1.129 + }
1.130 +
1.131 +/**
1.132 + Retrieves the descriptor for the entire uri.
1.133 +
1.134 + @since 6.0
1.135 + @return A const reference to a descriptor pointer to the uri.
1.136 + */
1.137 +EXPORT_C const TDesC8& TUriC8::UriDes() const
1.138 + {
1.139 + return iUriDes;
1.140 + }
1.141 +
1.142 +/**
1.143 + @publishedPartner
1.144 + @released
1.145 + Ensures that all components of the URI are valid. If the method returns
1.146 + KUriUtilsErrInvalidUri then one or more components are not valid. It is
1.147 + possible for URIs declared valid by this method to be, on detailed inspection,
1.148 + invalid.
1.149 +
1.150 + @return KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported.
1.151 + */
1.152 +EXPORT_C TInt TUriC8::Validate() const
1.153 + {
1.154 + return DoValidate(*this);
1.155 + }
1.156 +
1.157 +/**
1.158 + Compares the given URI to determine if it is equivalent to this URI. It is possible
1.159 + for URIs declared NOT equivalent by this method to be equvalent to a level not checked
1.160 + by this method.
1.161 + @publishedPartner
1.162 + @released
1.163 + @param aUri Contains URI to compare
1.164 + @return ETrue if the two URIs are equivalent otherwise EFalse
1.165 + */
1.166 +EXPORT_C TInt TUriC8::Equivalent(const TUriC8& aUri) const
1.167 + {
1.168 + TInt result = EFalse;
1.169 + TRAPD(error, result = DoEquivalenceL(*this, aUri));
1.170 + if (error != KErrNone)
1.171 + {
1.172 + result = error;
1.173 + }
1.174 + return result;
1.175 + }
1.176 +
1.177 +/**
1.178 + Retrieves the uri without the fragment component.
1.179 +
1.180 + @since 6.0
1.181 + @param aUriNoFrag An output parameter which is set the non-reference
1.182 + version of the uri.
1.183 + */
1.184 +EXPORT_C void TUriC8::UriWithoutFragment(TPtrC8& aUriNoFrag) const
1.185 + {
1.186 + if( IsPresent(EUriFragment) )
1.187 + {
1.188 + // There is a fragment, find where it starts
1.189 + TInt fragmentStartPos = iUriDes.Locate(KFragmentDelimiter);
1.190 + aUriNoFrag.Set(iUriDes.Left(fragmentStartPos));
1.191 + }
1.192 + else{
1.193 + aUriNoFrag.Set(iUriDes);
1.194 + }
1.195 + }
1.196 +
1.197 +/**
1.198 + Create a new HBufC descriptor containing the desired component or the full URI.
1.199 +
1.200 + @param aComponent The component to convert into Unicode (EUriScheme - EUriFragment), or
1.201 + the full URI (EUriComplete -- the default).
1.202 + @return The descriptor containing the desired component.
1.203 + */
1.204 +EXPORT_C HBufC* TUriC8::DisplayFormL(TUriComponent aComponent) const
1.205 + {
1.206 + TPtrC8 component;
1.207 +
1.208 + if (aComponent == EUriComplete)
1.209 + {
1.210 + component.Set(iUriDes);
1.211 + }
1.212 + else
1.213 + { // extract the specified component, will Panic if invalid
1.214 + component.Set( Extract(aComponent) );
1.215 + }
1.216 + // convert descriptor from UTF-8 into Unicode
1.217 + return EscapeUtils::ConvertToUnicodeFromUtf8L(component);
1.218 + }
1.219 +
1.220 +/**
1.221 + @internalComponent
1.222 + Resets the descriptor pointers for the uri components and the uri.
1.223 +
1.224 + @since 6.0
1.225 + @post All uri component information is removed and the uri descriptor is
1.226 + set to NULL.
1.227 + */
1.228 +void TUriC8::Reset()
1.229 + {
1.230 + // Set descriptor pointers to NULL and lengths to zero
1.231 + for( TInt i=0; i<EUriMaxComponents; ++i )
1.232 + {
1.233 + iComponent[i].Set(NULL,0);
1.234 + }
1.235 + iUriDes.Set(NULL,0);
1.236 + }
1.237 +
1.238 +//
1.239 +//
1.240 +// Implementation of TUriC16
1.241 +//
1.242 +//
1.243 +/**
1.244 + Constructor.
1.245 +
1.246 + @since 6.0
1.247 + @deprecated Deprecated in 9.1
1.248 + */
1.249 +EXPORT_C TUriC16::TUriC16()
1.250 + {
1.251 + // Reset the component table and the Uri
1.252 + Reset();
1.253 + }
1.254 +
1.255 +/**
1.256 + Retrieves the specified component in the uri.
1.257 +
1.258 + @since 6.0
1.259 + @deprecated Deprecated in 9.1
1.260 + @param aComponent The enum specifying the component.
1.261 + @return A constant reference to a descriptor pointer to the specified component.
1.262 + */
1.263 +EXPORT_C const TDesC16& TUriC16::Extract(TUriComponent aComponent) const
1.264 + {
1.265 + __ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.266 +
1.267 + return iComponent[aComponent];
1.268 + }
1.269 +
1.270 +/**
1.271 + Indicates whether the specified component is present in the uri.
1.272 +
1.273 + @since 6.0
1.274 + @deprecated Deprecated in 9.1
1.275 + @param aComponent The enum specifying the component.
1.276 + @return A boolean value of ETrue if the desired component is present,
1.277 + or EFalse if the desired component is not present.
1.278 + */
1.279 +EXPORT_C TBool TUriC16::IsPresent(TUriComponent aComponent) const
1.280 + {
1.281 + __ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.282 +
1.283 + return TBool(iComponent[aComponent].Ptr());
1.284 + }
1.285 +
1.286 +/**
1.287 + Checks to see if the scheme is valid. If there is no scheme then the return value
1.288 + indicates an invalid scheme (EFalse).
1.289 +
1.290 + @since 6.0
1.291 + @deprecated Deprecated in 9.1
1.292 + @return A boolean value of ETrue if the scheme is valid, or EFalse if
1.293 + the scheme is not.
1.294 + */
1.295 +EXPORT_C TBool TUriC16::IsSchemeValid() const
1.296 + {
1.297 + if( !IsPresent(EUriScheme) )
1.298 + {
1.299 + return EFalse;
1.300 + }
1.301 + return HasValidSchemeChars(iComponent[EUriScheme]);
1.302 + }
1.303 +
1.304 +/**
1.305 + Compares the specified component against the one in the uri passed in.
1.306 +
1.307 + @since 6.0
1.308 + @deprecated Deprecated in 9.1
1.309 + @param aUri The uri to compare components against.
1.310 + @param aComponent The enum specifying the component to compare.
1.311 + @return An integer value of zero if the components are the same, any other
1.312 + value if the components are not the same.
1.313 + */
1.314 +EXPORT_C TBool TUriC16::Compare(const TUriC16& aUri, TUriComponent aComponent) const
1.315 + {
1.316 + __ASSERT_ALWAYS(aComponent<EUriMaxComponents && aComponent >EUriComplete, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.317 +
1.318 + // Does the component exist in both the Uri's
1.319 + if( IsPresent(aComponent) && aUri.IsPresent(aComponent) )
1.320 + {
1.321 + if( aComponent == EUriScheme || aComponent == EUriHost )
1.322 + {
1.323 + // Do case insensitive compare for scheme and host
1.324 + return (iComponent[aComponent].CompareF(aUri.iComponent[aComponent]));
1.325 + }
1.326 + else
1.327 + {
1.328 + // Do case sensitive compare for all other components
1.329 + return (iComponent[aComponent].Compare(aUri.iComponent[aComponent]));
1.330 + }
1.331 + }
1.332 + else
1.333 + return KErrNotFound;
1.334 + }
1.335 +
1.336 +/**
1.337 + Retrieves the descriptor for the entire uri.
1.338 +
1.339 + @since 6.0
1.340 + @deprecated Deprecated in 9.1
1.341 + @return A const reference to a descriptor pointer to the uri.
1.342 + */
1.343 +EXPORT_C const TDesC16& TUriC16::UriDes() const
1.344 + {
1.345 + return iUriDes;
1.346 + }
1.347 +
1.348 +/**
1.349 + @deprecated Deprecated in 9.1 -- provided for compatibility
1.350 +
1.351 + Ensures that all components of the URI are valid. If the method returns
1.352 + KUriUtilsErrInvalidUri then one or more components are not valid. It is possible
1.353 + for URIs declared valid by this method to be, on detailed inspection, invalid.
1.354 +
1.355 + @return KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported.
1.356 + */
1.357 +EXPORT_C TInt TUriC16::Validate() const
1.358 + {
1.359 + TInt result = KErrNone;
1.360 + TRAPD(error, result = ValidateL());
1.361 + if (error)
1.362 + {
1.363 + // problem allocating resourses
1.364 + return error;
1.365 + }
1.366 + return result;
1.367 + }
1.368 +
1.369 +/**
1.370 + @deprecated Deprecated in 9.1 -- provided for compatibility
1.371 +
1.372 + Compares the given URI to determine if it is equivalent to this URI. It is possible
1.373 + for URIs declared NOT equivalent by this method to be equvalent to a level not checked
1.374 + by this method.
1.375 + @param aUri Contains URI to compare
1.376 + @return ETrue if the two URIs are equivalent otherwise EFalse
1.377 + */
1.378 +EXPORT_C TInt TUriC16::Equivalent(const TUriC16& aUri) const
1.379 + {
1.380 + TInt result = KErrNone;
1.381 + TRAPD(error, result = EquivalentL(aUri.UriDes()));
1.382 + if (error)
1.383 + {
1.384 + // problem allocating resourses
1.385 + return error;
1.386 + }
1.387 + return result;
1.388 + }
1.389 +/**
1.390 + Retrieves the uri without the fragment component.
1.391 +
1.392 + @since 6.0
1.393 + @deprecated Deprecated in 9.1
1.394 + @param aUriNoFrag An output parameter which is set the non-reference
1.395 + version of the uri.
1.396 + */
1.397 +
1.398 +EXPORT_C void TUriC16::UriWithoutFragment(TPtrC16& aUriNoFrag) const
1.399 + {
1.400 + if( IsPresent(EUriFragment) )
1.401 + {
1.402 + // There is a fragment, find where it starts
1.403 + TInt fragmentStartPos = iUriDes.Locate(KFragmentDelimiter);
1.404 + aUriNoFrag.Set(iUriDes.Left(fragmentStartPos));
1.405 + }
1.406 + else{
1.407 + aUriNoFrag.Set(iUriDes);
1.408 + }
1.409 + }
1.410 +
1.411 +/**
1.412 + Create a new HBufC descriptor containing the desired component or the full URI.
1.413 + @deprecated Deprecated in 9.1 - provided for compatibility
1.414 +
1.415 + @param aComponent The component to convert into Unicode (EUriScheme - EUriFragment), or
1.416 + the full URI (EUriComplete -- the default).
1.417 + @return The descriptor containing the desired component.
1.418 + */
1.419 +EXPORT_C HBufC* TUriC16::DisplayFormL(TUriComponent aComponent) const
1.420 + {
1.421 + if ( aComponent == EUriComplete) // extract the full URI
1.422 + {
1.423 + return iUriDes.AllocL();
1.424 + }
1.425 + return Extract(aComponent).AllocL();
1.426 + }
1.427 +
1.428 +/**
1.429 + @internalComponent
1.430 + Resets the descriptor pointers for the uri components and the uri.
1.431 +
1.432 + @since 6.0
1.433 + @post All uri component information is removed and the uri descriptor is
1.434 + set to NULL.
1.435 + */
1.436 +void TUriC16::Reset()
1.437 + {
1.438 + // Set descriptor pointers to NULL and lengths to zero
1.439 + for( TInt i=0; i<EUriMaxComponents; ++i )
1.440 + {
1.441 + iComponent[i].Set(NULL,0);
1.442 + }
1.443 + iUriDes.Set(NULL,0);
1.444 + }
1.445 +
1.446 +/**
1.447 + @deprecated Deprecated in 9.1
1.448 +
1.449 + Ensures that all components of the URI are valid. If the method returns
1.450 + KUriUtilsErrInvalidUri then one or more components are not valid. It is possible
1.451 + for URIs declared valid by this method to be, on detailed inspection, invalid.
1.452 +
1.453 + @return KErrNone for vaild URIs, KUriUtilsErrInvalidUri for invalid URIs or KErrNotSupported.
1.454 + */
1.455 +TInt TUriC16::ValidateL() const
1.456 + {
1.457 + TInt result;
1.458 +
1.459 + HBufC8* uri8 = CreateUri8LC(UriDes());
1.460 + TUriParser8 uriParser;
1.461 + if(uriParser.Parse(*uri8) != KErrNone)
1.462 + {
1.463 + result = KUriUtilsErrInvalidUri;
1.464 + }
1.465 + else
1.466 + {
1.467 + result = DoValidate(uriParser);
1.468 + }
1.469 +
1.470 + CleanupStack::PopAndDestroy(uri8);
1.471 + return result;
1.472 + }
1.473 +
1.474 +/**
1.475 + @deprecated Deprecated in 9.1
1.476 +
1.477 + Compares the given URI to determine if it is equivalent to this URI. It is possible
1.478 + for URIs declared NOT equivalent by this method to be equvalent to a level not checked
1.479 + by this method.
1.480 + @param aUri Contains URI to compare
1.481 + @return ETrue if the two URIs are equivalent otherwise EFalse
1.482 + */
1.483 +TBool TUriC16::EquivalentL(const TDesC16& aUri) const
1.484 + {
1.485 + HBufC8* lhs = CreateUri8LC(UriDes());
1.486 + HBufC8* rhs = CreateUri8LC(aUri);
1.487 +
1.488 + TUriParser8 lhsParser;
1.489 + if(lhsParser.Parse(*lhs) != KErrNone)
1.490 + {
1.491 + User::Leave(KUriUtilsErrInvalidUri);
1.492 + }
1.493 +
1.494 + TUriParser8 rhsParser;
1.495 + if(rhsParser.Parse(*rhs) != KErrNone)
1.496 + {
1.497 + User::Leave(KUriUtilsErrInvalidUri);
1.498 + }
1.499 +
1.500 + TBool result = DoEquivalenceL(lhsParser, rhsParser);
1.501 +
1.502 + CleanupStack::PopAndDestroy(2);
1.503 + return result;
1.504 + }
1.505 +
1.506 +//
1.507 +//
1.508 +// Implementation of LOCAL functions
1.509 +//
1.510 +//
1.511 +
1.512 +/**
1.513 + Checks the scheme for invalid characters. The scheme is invalid if it is empty.
1.514 +
1.515 + @since 6.0
1.516 + @param aScheme The descriptor with the scheme.
1.517 + @return A boolean value of ETrue if all the characters in the scheme
1.518 + are valid, otherwise EFalse.
1.519 +*/
1.520 +template<class TPtrCType>
1.521 +LOCAL_C TBool HasValidSchemeChars(const TPtrCType& aScheme)
1.522 + {
1.523 + TInt length = aScheme.Length();
1.524 + TBool valid = ( length && TChar(aScheme[0]).IsAlpha() );
1.525 +
1.526 + // Start checking from the second character
1.527 + TInt i=1;
1.528 + while( valid && i<length )
1.529 + {
1.530 + TChar c = aScheme[i];
1.531 + valid = c.IsAlphaDigit() || c==KPlusChar || c==KMinusChar || c==KPeriodChar;
1.532 + ++i;
1.533 + }
1.534 + return valid;
1.535 + }
1.536 +
1.537 +
1.538 +//
1.539 +//
1.540 +// File URI Implementation - CUri8
1.541 +//
1.542 +//
1.543 +#ifdef __SECURE_DATA__
1.544 +/**
1.545 + Generates a fully-qualified filename from a file URI object.
1.546 +
1.547 + The form of the returned filename depends on the file location, as follows:
1.548 + - public file on a fixed drive:
1.549 + @code
1.550 + file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
1.551 + @endcode
1.552 +
1.553 + - public file on removable media drive:
1.554 + The fully-qualified filename is resolved by finding the first drive on which the file exists.
1.555 + If the file does not exist, this will Leave with KErrNotFound
1.556 + @code
1.557 + file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
1.558 + @endcode
1.559 + (where f: is the first drive found containing "\path\to\file\name.ext")
1.560 +
1.561 + - private file on fixed drive:
1.562 + @code
1.563 + file://private/c/path/to/file/name.ext -> c:\private\0x1001234f\path\to\file\name.ext
1.564 + @endcode
1.565 + (where 0x1001234f is the SID of the current application)
1.566 +
1.567 + - private file on removable media drive:
1.568 + @code
1.569 + file://private/ext-media/path/to/file/name.ext -> h:\private\0x1001234f\path\to\file\name.ext
1.570 + @endcode
1.571 + (where h: is the first drive found containing "\private\0x1001234f\path\to\file\name.ext")
1.572 +
1.573 + The returned file name is not guaranteed to exist except where specified above.
1.574 +
1.575 + Be warned that this method may be slow when resolving special paths (like "/ext-media")
1.576 +
1.577 + @leave KErrNotSupported URI does not specify a local file
1.578 + @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
1.579 + @since 9.1
1.580 + @return A descriptor containing the fully-qualified filename.
1.581 + @pre Object is fully constructed.
1.582 + */
1.583 +#else
1.584 + /**
1.585 + Generates a fully-qualified filename from a file URI object.
1.586 +
1.587 + The form of the returned filename depends on the file location, as follows:
1.588 + - public file on a fixed drive:
1.589 + @code
1.590 + file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
1.591 + @endcode
1.592 +
1.593 + - public file on removable media drive:
1.594 + The fully-qualified filename is resolved by finding the first drive on which the file exists.
1.595 + If the file does not exist, this will Leave with KErrNotFound
1.596 + @code
1.597 + file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
1.598 + @endcode
1.599 + (where f: is the first drive found containing "\path\to\file\name.ext")
1.600 +
1.601 + The returned file name is not guaranteed to exist except where specified above.
1.602 +
1.603 + Be warned that this method may be slow when resolving special paths (like "/ext-media")
1.604 +
1.605 + @leave KErrNotSupported URI does not specify a local file
1.606 + @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
1.607 + @since 9.1
1.608 + @return A descriptor containing the fully-qualified filename.
1.609 + @pre Object is fully constructed.
1.610 + */
1.611 + #endif
1.612 +EXPORT_C HBufC* TUriC8::GetFileNameL() const
1.613 + {
1.614 + return GetFileNameL(EUriFileNameFull);
1.615 + }
1.616 +
1.617 +
1.618 +/**
1.619 + This creates a file name from the URI, changing the network path separator (/) to the
1.620 + local file system path separator (\\).
1.621 +
1.622 + If called with EUriFileNamePath, this will generate a file name containing the path relative to the drive.
1.623 + Any parameters in the URI are stripped off:
1.624 + @code
1.625 + http://www.foo.com/dir/file/name.ext;param1;param2 -> \dir\file\name.ext
1.626 + @endcode
1.627 +
1.628 + If called with EUriFileNameTail, this will generate a just the name, with no directories or drive.
1.629 + Any parameters in the URI are stripped off:
1.630 + @code
1.631 + http://www.foo.com/dir/file/name.ext;param1;param2 -> name.ext
1.632 + @endcode
1.633 +
1.634 + EUriFileNamePath and EUriFileNameTail can be used for any hierarchical URI (http, ftp, file, etc)
1.635 + and may have unexpected behaviour when called on any other type of URI.
1.636 +
1.637 + If called with EUriFileNameFull, this will convert the URI into a fully-qualified filename. this is only valid
1.638 + for file URIs and will Leave if called on any other type of URI. The form of the returned filename is described in
1.639 + GetFileNameL with no arguments.
1.640 +
1.641 + @leave KErrNotSupported The URI scheme cannot be converted into the desired type
1.642 + @since 9.1
1.643 + @pre Object is fully constructed.
1.644 + @param aType specifies what part of the filename is to be converted. The default is EUriFileNameFull).
1.645 + @return A descriptor containing the desired filename components.
1.646 + */
1.647 +EXPORT_C HBufC* TUriC8::GetFileNameL(TUriFileName aType) const
1.648 + {
1.649 + TBool isFileUri = Extract(EUriScheme).Compare(KFileUriScheme8) == 0;
1.650 + if(aType == EUriFileNameFull && !isFileUri)
1.651 + {
1.652 + User::Leave(KErrNotSupported);
1.653 + }
1.654 + return ResolveFileNameL(Extract(EUriPath), aType, isFileUri);
1.655 + }
1.656 +
1.657 +
1.658 +//
1.659 +//
1.660 +// File URI Implementation - CUri16
1.661 +//
1.662 +//
1.663 +
1.664 +#ifdef __SECURE_DATA__
1.665 +/**
1.666 + Generates a fully-qualified filename from a file URI object.
1.667 +
1.668 + The form of the returned filename depends on the file location, as follows:
1.669 + - public file on a fixed drive:
1.670 + @code
1.671 + file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
1.672 + @endcode
1.673 +
1.674 + - public file on removable media drive:
1.675 + The fully-qualified filename is resolved by finding the first drive on which the file exists.
1.676 + If the file does not exist, this will Leave with KErrNotFound
1.677 + @code
1.678 + file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
1.679 + @endcode
1.680 + (where f: is the first drive found containing "\path\to\file\name.ext")
1.681 +
1.682 + - private file on fixed drive:
1.683 + @code
1.684 + file://private/c/path/to/file/name.ext -> c:\private\0x1001234f\path\to\file\name.ext
1.685 + @endcode
1.686 + (where 0x1001234f is the SID of the current application)
1.687 +
1.688 + - private file on removable media drive:
1.689 + @code
1.690 + file://private/ext-media/path/to/file/name.ext -> h:\private\0x1001234f\path\to\file\name.ext
1.691 + @endcode
1.692 + (where h: is the first drive found containing "\private\0x1001234f\path\to\file\name.ext")
1.693 +
1.694 + The returned file name is not guaranteed to exist except where specified above.
1.695 +
1.696 + Be warned that this method may be slow when resolving special paths (like "/ext-media")
1.697 +
1.698 + @leave KErrNotSupported URI does not specify a local file
1.699 + @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
1.700 + @since 9.1
1.701 + @return A descriptor containing the fully-qualified filename.
1.702 + @pre Object is fully constructed.
1.703 +
1.704 + */
1.705 +#else
1.706 +/**
1.707 + Generates a fully-qualified filename from a file URI object.
1.708 +
1.709 + The form of the returned filename depends on the file location, as follows:
1.710 + - public file on a fixed drive:
1.711 + @code
1.712 + file://c/path/to/file/name.ext -> c:\path\to\file\name.ext
1.713 + @endcode
1.714 +
1.715 + - public file on removable media drive:
1.716 + The fully-qualified filename is resolved by finding the first drive on which the file exists.
1.717 + If the file does not exist, this will Leave with KErrNotFound
1.718 + @code
1.719 + file://ext-media/path/to/file/name.ext -> f:\path\to\file\name.ext
1.720 + @endcode
1.721 + (where f: is the first drive found containing "\path\to\file\name.ext")
1.722 +
1.723 + The returned file name is not guaranteed to exist except where specified above.
1.724 +
1.725 + Be warned that this method may be slow when resolving special paths (like "/ext-media")
1.726 +
1.727 + @leave KErrNotSupported URI does not specify a local file
1.728 + @leave KErrNotFound If the URI indicates the file is on removable media and the file does not exist on any.
1.729 + @since 9.1
1.730 + @return A descriptor containing the fully-qualified filename.
1.731 + @pre Object is fully constructed.
1.732 +
1.733 + */
1.734 + #endif
1.735 +EXPORT_C HBufC* TUriC16::GetFileNameL() const
1.736 + {
1.737 + return GetFileNameL(EUriFileNameFull);
1.738 + }
1.739 +
1.740 +
1.741 +/**
1.742 + This creates a file name from the URI, changing the network path separator (/) to the
1.743 + local file system path separator (\\).
1.744 +
1.745 + If called with EUriFileNamePath, this will generate a file name containing the path relative to the drive.
1.746 + Any parameters in the URI are stripped off:
1.747 + @code
1.748 + http://www.foo.com/dir/file/name.ext;param1;param2 -> \dir\file\name.ext
1.749 + @endcode
1.750 +
1.751 + If called with EUriFileNameTail, this will generate a just the name, with no directories or drive.
1.752 + Any parameters in the URI are stripped off:
1.753 + @code
1.754 + http://www.foo.com/dir/file/name.ext;param1;param2 -> name.ext
1.755 + @endcode
1.756 +
1.757 + EUriFileNamePath and EUriFileNameTail can be used for any hierarchical URI (http, ftp, file)
1.758 + and may have unexpected behaviour when called on any other type of URI.
1.759 +
1.760 + If called with EUriFileNameFull, this will convert the URI into a fully-qualified filename. this is only valid
1.761 + for file URIs and will Leave if called on any other type of URI. The form of the returned filename is described in
1.762 + GetFileNameL with no arguments.
1.763 +
1.764 + @leave KErrNotSupported The URI scheme cannot be converted into the desired type
1.765 + @since 9.1
1.766 + @pre Object is fully constructed.
1.767 + @param aType specifies what part of the filename is to be converted. The default is (EUriFileNameFull).
1.768 + @return A descriptor containing the desired filename components.
1.769 + */
1.770 +EXPORT_C HBufC* TUriC16::GetFileNameL(TUriFileName aType) const
1.771 + {
1.772 + TBool isFileUri = Extract(EUriScheme).Compare(KFileUriScheme16) == 0;
1.773 +
1.774 + if(aType == EUriFileNameFull && !isFileUri )
1.775 + {
1.776 + User::Leave(KErrNotSupported);
1.777 + }
1.778 +
1.779 + HBufC8* fileUriPath8 = HBufC8::NewLC(Extract(EUriPath).Length());
1.780 + fileUriPath8->Des().Copy(Extract(EUriPath));
1.781 + HBufC* absFileName = ResolveFileNameL(*fileUriPath8, aType, isFileUri);
1.782 + CleanupStack::PopAndDestroy(fileUriPath8);
1.783 + return absFileName;
1.784 + }
1.785 +
1.786 +
1.787 +//
1.788 +//
1.789 +// Implementation of LOCAL functions
1.790 +//
1.791 +//
1.792 +
1.793 +/**
1.794 + Function used to convert '\' to '/' and vice versa.
1.795 +
1.796 + @since 9.1
1.797 + @param aDesPtr A descriptor reference to the string.
1.798 + @param aPathSeperatorFrom A path seperator to be converted (from)
1.799 + @param aPathSeperatorTo A path seperator to converte (To).
1.800 + */
1.801 +void ChangePathSeparator(TDes& aDesPtr, TUint aPathSeperatorFrom, TUint aPathSeperatorTo)
1.802 + {
1.803 + for(TInt offset = aDesPtr.Length() - 1;offset >= 0;offset--)
1.804 + {
1.805 + if (aDesPtr[offset] == aPathSeperatorFrom)
1.806 + {
1.807 + aDesPtr[offset] = TUint16(aPathSeperatorTo);
1.808 + }
1.809 + }
1.810 + }
1.811 +
1.812 +/**
1.813 + Function used to generate a fully qualified file name for a public or private file
1.814 + stored on a fix drive or a removable media drive from File URI path (parameter aFileUriPath).
1.815 +
1.816 + This will be called by API GetFileName() to generate and return a filename.
1.817 +
1.818 + @leave KErrBadName if the path doesn't contain valid drivename.
1.819 + @since 9.1
1.820 + @param aFileUriPath A descriptor reference to the File URI's path component.
1.821 + @return A pointer to a buffer containing the resolved fully qualified filename
1.822 + if the file uri path is not empty or a top level dir on main drive (C:\\)
1.823 + */
1.824 +HBufC* GetFullFileNameFromFileUriPathL(const TDesC& aFileUriPath)
1.825 + {
1.826 + TFileName filename(KDefaultPath);
1.827 +
1.828 + TInt origLength = aFileUriPath.Length();
1.829 + if(origLength == 0)
1.830 + {
1.831 + return filename.AllocL();
1.832 + }
1.833 +
1.834 + TInt index = 0;
1.835 + TPtrC fileUriPath(aFileUriPath);
1.836 +
1.837 + //skip KUriPathSeparator (/) from the Uri path
1.838 + if (fileUriPath[0] == KUriPathSeparator)
1.839 + {
1.840 + index++;
1.841 + }
1.842 +
1.843 + fileUriPath.Set(aFileUriPath.Right(origLength - index));
1.844 +
1.845 + RFs fs;
1.846 + TBool fsOpen = EFalse;
1.847 +
1.848 +#ifdef __SECURE_DATA__
1.849 + if (fileUriPath.Left(KPrivate().Length()).Compare(KPrivate) == 0)
1.850 + {
1.851 + index += KPrivate().Length();
1.852 + User::LeaveIfError(fs.Connect());
1.853 + CleanupClosePushL(fs);
1.854 + fsOpen = ETrue;
1.855 + User::LeaveIfError(fs.PrivatePath(filename));
1.856 + filename.Insert(0, KDefaultPath().Left((KDefaultPath().Length() - 1) )); //Insert <drive>:
1.857 + fileUriPath.Set(aFileUriPath.Right(origLength - index));
1.858 + }
1.859 +#endif
1.860 +
1.861 + TBool isExtMedia = (fileUriPath.Left(KExtMedia().Length()).Compare(KExtMedia) == 0);
1.862 + if (!isExtMedia )
1.863 + {
1.864 + TUint driveLetter = fileUriPath[0];
1.865 + //Checking for valid driveletter (should between A to Z or a to z) and followed by Uri path seperator "/"
1.866 + if ( fileUriPath[1] != KUriPathSeparator ||
1.867 + ( (driveLetter < 'A' || driveLetter > 'Z') &&
1.868 + (driveLetter < 'a' || driveLetter > 'z') ) )
1.869 + {
1.870 + User::Leave(KErrBadName);
1.871 + }
1.872 + index += (KDefaultPath().Length() - 1); //skip <driveLetter>/
1.873 + filename[0] = TUint16(driveLetter);
1.874 + }
1.875 + else
1.876 + {
1.877 + index += KExtMedia().Length();
1.878 + }
1.879 +
1.880 + filename.Append(aFileUriPath.Right(origLength - index));
1.881 +
1.882 + //Convert "/" to "\"
1.883 + ChangePathSeparator(filename, KUriPathSeparator, KFilePathSeparator);
1.884 +
1.885 + if (isExtMedia )
1.886 + {
1.887 + if (fsOpen == EFalse)
1.888 + {
1.889 + User::LeaveIfError(fs.Connect());
1.890 + CleanupClosePushL(fs);
1.891 + fsOpen = ETrue;
1.892 + }
1.893 +
1.894 + TDriveInfo driveInfo;
1.895 + TInt err = KErrNotFound;
1.896 +
1.897 + for (TInt driveNum = EDriveA; driveNum <= EDriveZ && err!=KErrNone; driveNum++)
1.898 + {
1.899 + if (fs.Drive(driveInfo, driveNum ) == KErrNone
1.900 + && (driveInfo.iDriveAtt & KDriveAttRemovable))
1.901 + {
1.902 + filename[0]= TInt16('A' + driveNum);
1.903 + TUint attValue;
1.904 + err = fs.Att(filename, attValue);
1.905 + }
1.906 + }
1.907 + User::LeaveIfError(err);
1.908 + }
1.909 +
1.910 + if (fsOpen)
1.911 + {
1.912 + CleanupStack::PopAndDestroy(&fs);
1.913 + }
1.914 +
1.915 + return filename.AllocL();
1.916 + }
1.917 +
1.918 +/**
1.919 + Creates an 8 bit URI descriptor from an 16 bit one
1.920 +
1.921 + @param aBuf16 The full 16 bit URI descriptor
1.922 + @return Pointer to the newly created 8 bit URI descriptor
1.923 + are valid, otherwise EFalse.
1.924 +*/
1.925 +HBufC8* CreateUri8LC(const TDesC16& aBuf16)
1.926 + {
1.927 + TInt length = aBuf16.Length();
1.928 + HBufC8* newBuf = HBufC8::NewMaxLC(length);
1.929 + TPtr8 des8Ptr = newBuf->Des();
1.930 + for (TInt i = 0; i < length; ++i)
1.931 + {
1.932 + des8Ptr[i] = static_cast<TText8>(aBuf16[i]);
1.933 + }
1.934 + return newBuf;
1.935 + }
1.936 +
1.937 +/**
1.938 + Check the components of a URI to ensure they are all valid
1.939 +
1.940 + @since 8.1
1.941 + @param aUri The URI to check
1.942 + @return KErrNone if all components are valid, otherwise one of the 'invalid' error codes
1.943 +*/
1.944 +TInt DoValidate(const TUriC8& aUri)
1.945 + {
1.946 + TInt result;
1.947 + TPtrC8 subComponent(aUri.Extract(EUriScheme));
1.948 + if (!HasValidSchemeChars(subComponent))
1.949 + {
1.950 + result = KUriUtilsErrInvalidScheme;
1.951 + }
1.952 + else if(SchemeType(subComponent) == ESchemeTypeSip)
1.953 + //To validate Sip uri
1.954 + {
1.955 + TValidatorSip validator(aUri);
1.956 + result = validator.Validate();
1.957 + }
1.958 + else if(SchemeType(subComponent) == ESchemeTypeTel)
1.959 + //To validate Tel uri
1.960 + {
1.961 + TValidatorTel validator(aUri);
1.962 + result = validator.Validate();
1.963 + }
1.964 + else
1.965 + {
1.966 + result = KErrNotSupported;
1.967 + }
1.968 +
1.969 + return result;
1.970 + }
1.971 +
1.972 +/**
1.973 + Compare the components of two URIs to see if they identify the same resource
1.974 +
1.975 + @since 8.1
1.976 + @param aLhs The left hand side URI to compare
1.977 + @param aRhs The right hand side URI to compare
1.978 + @return ETrue if they point to the same resource, EFalse otherwise.
1.979 +*/
1.980 +TInt DoEquivalenceL(const TUriC8& aLhs, const TUriC8& aRhs)
1.981 + {
1.982 + TInt result;
1.983 + if (SchemeType(aLhs.Extract(EUriScheme)) == ESchemeTypeSip)
1.984 + {
1.985 + TEquivSip equiv(aLhs, aRhs);
1.986 + result = equiv.EquivalentL();
1.987 + }
1.988 + else
1.989 + {
1.990 + // unknown scheme so assume network scheme
1.991 + TEquiv equiv(aLhs, aRhs);
1.992 + result = equiv.EquivalentL();
1.993 + }
1.994 +
1.995 + return result;
1.996 + }
1.997 +
1.998 +
1.999 +/**
1.1000 + Get the desired part of the filename from the URI path
1.1001 +
1.1002 + @param aPath A descriptor reference to the File URI's path component.
1.1003 + @param aType enum value of TUriFileName.
1.1004 + @param aIsFileUri Specifies the whether it is FileUri or not.
1.1005 + @return Pointer to the newly created URI descriptor which contains the
1.1006 + desired part of the filename from the URI path.
1.1007 +*/
1.1008 +HBufC* ResolveFileNameL(const TDesC8& aPath, TUriFileName aType, TBool aIsFileUri)
1.1009 + {
1.1010 + // replace % codes
1.1011 + HBufC8* fileUriPath8 = EscapeUtils::EscapeDecodeL(aPath);
1.1012 + CleanupStack::PushL(fileUriPath8);
1.1013 +
1.1014 + // convert to unicode
1.1015 + HBufC* fileUriPath = EscapeUtils::ConvertToUnicodeFromUtf8L(*fileUriPath8);
1.1016 + CleanupStack::PopAndDestroy(fileUriPath8);
1.1017 + CleanupStack::PushL(fileUriPath);
1.1018 +
1.1019 + HBufC* absFileName = NULL; // setting to NULL makes compiler happy
1.1020 + if ( aIsFileUri )
1.1021 + {
1.1022 + /* awlays do full conversion for file URIs
1.1023 + It's not optimal time-wise, but it uses the least code and is
1.1024 + forward-compatible. */
1.1025 + absFileName = GetFullFileNameFromFileUriPathL(*fileUriPath);
1.1026 + CleanupStack::PopAndDestroy(fileUriPath);
1.1027 + if ( aType == EUriFileNameFull )
1.1028 + {
1.1029 + return absFileName;
1.1030 + }
1.1031 + fileUriPath = absFileName; // code below uses fileUriPath
1.1032 + CleanupStack::PushL(fileUriPath);
1.1033 + TPtr path(fileUriPath->Des());
1.1034 + path.Delete(0,2); // delete drive and ':' (always begins with drive letter and :)
1.1035 + }
1.1036 + else // not a file URI
1.1037 + { // convert '/' to '\' for all other URIs
1.1038 + TPtr path(fileUriPath->Des());
1.1039 + ChangePathSeparator(path, KUriPathSeparator, KFilePathSeparator);
1.1040 + }
1.1041 +
1.1042 + // EUriFileNameFull must only ever be used with a file URI. Failures should be caught by the caller
1.1043 + __ASSERT_DEBUG(aType != EUriFileNameFull,
1.1044 + User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.1045 +
1.1046 + TPtrC name;
1.1047 + GetFileComponent(name, *fileUriPath, aType ); // get path or tail
1.1048 + if (name.Length() == fileUriPath->Length())
1.1049 + { // no changes, just return fileUriPath
1.1050 + absFileName = fileUriPath;
1.1051 + CleanupStack::Pop(fileUriPath);
1.1052 + }
1.1053 + else
1.1054 + {
1.1055 + absFileName = name.AllocL();
1.1056 + CleanupStack::PopAndDestroy(fileUriPath);
1.1057 + }
1.1058 +
1.1059 + return absFileName;
1.1060 + }
1.1061 +
1.1062 +/**
1.1063 + Gets the desired file path or tail.
1.1064 +
1.1065 + @param aNewName An outparameter, reference to descriptor .
1.1066 + @param aOldName An inparameter descriptor reference.
1.1067 + @param aType enum value of TUriFileName.
1.1068 + */
1.1069 +void GetFileComponent(TPtrC& aNewName, const TDesC& aOldName, TUriFileName aType )
1.1070 + {
1.1071 + __ASSERT_ALWAYS(aType != EUriFileNameFull, User::Panic(KUriPanicCategory, KUriUtilsErrBadComponentIndex));
1.1072 +
1.1073 + aNewName.Set(aOldName);
1.1074 + // chop off everything after the first ;
1.1075 + TInt pos = aNewName.Locate(KParamDelimiter);
1.1076 + if( pos == 0 ) // the ; is at the start
1.1077 + {
1.1078 + aNewName.Set(KNullDesC);
1.1079 + }
1.1080 + else if (pos > 0)
1.1081 + { // set to the text untilt he ;
1.1082 + aNewName.Set(aNewName.Left(pos));
1.1083 + }
1.1084 + if( aType == EUriFileNameTail)
1.1085 + {
1.1086 + // chop off everything before the last /
1.1087 + TInt pos = aNewName.LocateReverse(KFilePathSeparator);
1.1088 + if( pos >=0 ) // there is a /
1.1089 + {
1.1090 + if( pos >= aNewName.Length() - 1 ) // the / is at the end
1.1091 + {
1.1092 + aNewName.Set(KNullDesC);
1.1093 + }
1.1094 + else
1.1095 + { // set to the text following the last /
1.1096 + aNewName.Set(aNewName.Right(aNewName.Length()-1-pos));
1.1097 + }
1.1098 + }
1.1099 + }
1.1100 + }
1.1101 +
1.1102 +
1.1103 +
1.1104 +