1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericservices/httputils/UriParser/CUri.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1462 @@
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 +#include <escapeutils.h>
1.20 +#include <uri8.h>
1.21 +#include <uri16.h>
1.22 +#include <delimitedpath8.h>
1.23 +#include <delimitedpath16.h>
1.24 +#include <uriutilscommon.h>
1.25 +#include <uriutils.h>
1.26 +
1.27 +#include "UriUtilsInternal.h"
1.28 +#include "TUriCInternal.h"
1.29 +#include "CUriInternal.h"
1.30 +
1.31 +// Panic category
1.32 +//
1.33 +#ifdef _DEBUG
1.34 + _LIT(KUriPanicCategory,"URI-CURI");
1.35 +#endif
1.36 +
1.37 +// Constants
1.38 +//
1.39 +_LIT(KFileUriPanicCategory,"FILEURI-CURI");
1.40 +
1.41 +
1.42 +
1.43 +
1.44 +//
1.45 +//
1.46 +// Implementation of CUri8
1.47 +//
1.48 +//
1.49 +
1.50 +/**
1.51 + Static factory constructor. Uses two phase construction and leaves nothing on the
1.52 + CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
1.53 +
1.54 + @since 6.0
1.55 + @param aUri A reference to a parsed uri object.
1.56 + @return A pointer to the newly created CUri8 object.
1.57 + @post A fully constructed and initialized CUri8 object.
1.58 + */
1.59 +EXPORT_C CUri8* CUri8::NewL(const TUriC8& aUri)
1.60 + {
1.61 + CUri8* self = CUri8::NewLC(aUri);
1.62 + CleanupStack::Pop(self);
1.63 + return self;
1.64 + }
1.65 +
1.66 +/**
1.67 + Static factory constructor. Uses two phase construction and leaves a pointer to
1.68 + created object on the CleanupStack. Creates a uri object which is a copy of the
1.69 + input parameter aUri.
1.70 +
1.71 + @since 6.0
1.72 + @param aUri A reference to a parsed uri object.
1.73 + @return A pointer to the newly created CUri8 object.
1.74 + @post A fully constructed and initialized CUri8 object.
1.75 + */
1.76 +EXPORT_C CUri8* CUri8::NewLC(const TUriC8& aUri)
1.77 + {
1.78 + CUri8* self = new (ELeave) CUri8(aUri);
1.79 + CleanupStack::PushL(self);
1.80 + self->ConstructL();
1.81 + return self;
1.82 + }
1.83 +
1.84 +/**
1.85 + Static factory constructor. Uses two phase construction and leaves nothing on the
1.86 + CleanupStack. Creates a uri object which is empty.
1.87 +
1.88 + @since 6.0
1.89 + @return A pointer to the newly created CUri8 object.
1.90 + @post A fully constructed and initialized CUri8 object.
1.91 + */
1.92 +EXPORT_C CUri8* CUri8::NewL()
1.93 + {
1.94 + CUri8* self = CUri8::NewLC();
1.95 + CleanupStack::Pop(self);
1.96 + return self;
1.97 + }
1.98 +
1.99 +/**
1.100 + Static factory constructor. Uses two phase construction and leaves a pointer to created
1.101 + object on the CleanupStack. Creates a uri object which is empty.
1.102 +
1.103 + @since 6.0
1.104 + @return A pointer to the newly created CUri8 object.
1.105 + @post A fully constructed and initialized CUri8 object.
1.106 + */
1.107 +EXPORT_C CUri8* CUri8::NewLC()
1.108 + {
1.109 + CUri8* self = new (ELeave) CUri8(TUriC8());
1.110 + CleanupStack::PushL(self);
1.111 + self->ConstructL();
1.112 + return self;
1.113 + }
1.114 +
1.115 +/**
1.116 + Static factory constructor. This creates a CUri8 object that is an absolute uri resulting
1.117 + from a reference uri being resolved against a base uri.
1.118 +
1.119 + @warning Ownership of created CUri8 object is transferred to the caller.
1.120 + @leave KUriErrBadBasePath if the base path is not an absolute path and not empty.
1.121 + @since 6.0
1.122 + @param aBaseUri A referece to the parsed base uri.
1.123 + @param aRefUri A referece to the parsed reference uri.
1.124 + @return A pointer to the newly created CUri8 object.
1.125 + @pre The base uri must have an absolute or empty path, otherwise will leave
1.126 + with KUriErrBadBasePath.
1.127 + @post A fully constructed and initialized CUri8 object.
1.128 + */
1.129 +EXPORT_C CUri8* CUri8::ResolveL(const TUriC8& aBaseUri, const TUriC8& aRefUri)
1.130 + {
1.131 + // Check for a base Uri
1.132 + if( aBaseUri.UriDes().Compare(KNullDesC8) == 0 )
1.133 + {
1.134 + // Empty base Uri - resolved Uri is the reference Uri
1.135 + return NewL(aRefUri);
1.136 + }
1.137 + // See if ref has scheme and it is the same as base Uri
1.138 + if( aRefUri.IsPresent(EUriScheme) && (aRefUri.Compare(aBaseUri, EUriScheme) != 0) )
1.139 + {
1.140 + // Ref has a scheme different to base Uri's - it is an absolute Uri
1.141 + return NewL(aRefUri);
1.142 + }
1.143 + // Check for presence of components
1.144 + TBool useBaseQuery = EFalse;
1.145 + HBufC8* resolvedPath = FormResolvedPathLC<HBufC8>(aBaseUri, aRefUri, useBaseQuery);
1.146 +
1.147 + //Removes dot segemnts in Resolved uri as specified in RFC3986 section 5.2.
1.148 + RemoveExtraneousDotSegmentsL(resolvedPath);
1.149 +
1.150 + // Put the Uri together
1.151 + TUriC8 uri;
1.152 + FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
1.153 +
1.154 + // Create the resolved Uri and cleanup
1.155 + CUri8* resolvedUri = NewL(uri);
1.156 + CleanupStack::PopAndDestroy(resolvedPath);
1.157 +
1.158 + return resolvedUri;
1.159 + }
1.160 +
1.161 +/**
1.162 + Destructor.
1.163 +
1.164 + @since 6.0
1.165 + */
1.166 +EXPORT_C CUri8::~CUri8()
1.167 + {
1.168 + delete iUriBuf;
1.169 + }
1.170 +
1.171 +/**
1.172 + Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC8.
1.173 +
1.174 + @since 6.0
1.175 + @return A const reference to the parsed uri object.
1.176 + */
1.177 +EXPORT_C const TUriC8& CUri8::Uri() const
1.178 + {
1.179 + return iUri;
1.180 + }
1.181 +
1.182 +/**
1.183 + Intended Usage : Sets the specified component in the uri. The component is set to the value
1.184 + given in the argument aData. If the specified component already exists then it is replaced
1.185 + with the new value.
1.186 +
1.187 + @warning The userinfo and port components can only be set if the host component
1.188 + is present. Setting these components without a host component present will have no
1.189 + effect on the uri.
1.190 + @since 6.0
1.191 + @param aData A descriptor pointer to the new value for the uri component.
1.192 + @param aComponent An enum specifying the component to be set.
1.193 + @pre Object is fully constructed.
1.194 + @post The uri has the specified component set to the new value.
1.195 + @Leave KErrArgument If aComponent goes out of range.
1.196 + */
1.197 +EXPORT_C void CUri8::SetComponentL(const TDesC8& aData, TUriComponent aComponent)
1.198 + {
1.199 + // Update the appropriate component table entry
1.200 + iUri.iComponent[aComponent].Set(aData);
1.201 +
1.202 + // Copy to the buffer by forming the uri
1.203 + FormUriL();
1.204 + }
1.205 +
1.206 +/**
1.207 + Removes the specified component from the uri. If the component does not exist then this function
1.208 + does nothing.
1.209 +
1.210 + @warning If host is removed, then userinfo and port components will also
1.211 + be removed.
1.212 + @since 6.0
1.213 + @param aComponent An enum specifying the component to be removed.
1.214 + @pre Object is fully constructed.
1.215 + @post The uri is updated to exclude the specified component.
1.216 + */
1.217 +EXPORT_C void CUri8::RemoveComponentL(TUriComponent aComponent)
1.218 + {
1.219 + if( iUri.IsPresent(aComponent) )
1.220 + {
1.221 + // Remove the component - set pointer to NULL and length to zero
1.222 + iUri.iComponent[aComponent].Set(NULL,0);
1.223 +
1.224 + // Re-form buffer and component table
1.225 + FormUriL();
1.226 + }
1.227 + }
1.228 +
1.229 +/**
1.230 + Constructor. First phase of two-phase construction method. Does non-allocating construction.
1.231 +
1.232 + @since 6.0
1.233 + @param aUri The parsed uri component information from which to create
1.234 + the uri.
1.235 +*/
1.236 +CUri8::CUri8(const TUriC8& aUri)
1.237 +: CBase(), iUri(aUri)
1.238 + {
1.239 + }
1.240 +
1.241 +/**
1.242 + Second phase of two-phase construction method. Does any allocations required to fully construct
1.243 + the object.
1.244 +
1.245 + @since 6.0
1.246 + @pre First phase of construction is complete.
1.247 + @post The object is fully constructed and initialized.
1.248 + */
1.249 +void CUri8::ConstructL()
1.250 + {
1.251 + // Create the HBufC
1.252 + FormUriL();
1.253 + }
1.254 +
1.255 +/**
1.256 + Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri
1.257 + is changed to refer to the copy.
1.258 +
1.259 + @since 6.0
1.260 + @pre The parsed uri information is set.
1.261 + @post The uri buffer is updated with the parsed uri information.
1.262 + */
1.263 +void CUri8::FormUriL()
1.264 + {
1.265 + TBool isIPv6Host;
1.266 +
1.267 + // Calculate length of of the Uri
1.268 + TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
1.269 +
1.270 + // Create a temporary buffer and descriptor pointer to it
1.271 + HBufC8* buf = HBufC8::NewL(length);
1.272 + TPtr8 uri = buf->Des();
1.273 +
1.274 + // Create the uri, updating the internal uri object
1.275 + DoFormUri(uri, iUri.iComponent, isIPv6Host);
1.276 +
1.277 + // Update the internal buffer and descriptor pointer
1.278 + delete iUriBuf;
1.279 + iUriBuf = buf;
1.280 + iUri.iUriDes.Set(iUriBuf->Des());
1.281 + }
1.282 +
1.283 +//
1.284 +//
1.285 +// Implementation of CUri16
1.286 +//
1.287 +//
1.288 +
1.289 +/**
1.290 + Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack.
1.291 + Creates a uri object which is a copy of the input parameter aUri.
1.292 +
1.293 + @deprecated Deprecated in 9.1
1.294 + @since 6.0
1.295 + @param aUri A reference to a parsed uri object.
1.296 + @return A pointer to the newly created CUri16 object.
1.297 + @post A fully constructed and initialized CUri16 object.
1.298 + */
1.299 +EXPORT_C CUri16* CUri16::NewL(const TUriC16& aUri)
1.300 + {
1.301 + CUri16* self = CUri16::NewLC(aUri);
1.302 + CleanupStack::Pop(self);
1.303 + return self;
1.304 + }
1.305 +
1.306 +/**
1.307 + Static factory constructor. Uses two phase construction and leaves a pointer to created object on
1.308 + the CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
1.309 +
1.310 + @since 6.0
1.311 + @deprecated Deprecated in 9.1
1.312 + @param aUri A reference to a parsed uri object.
1.313 + @return A pointer to the newly created CUri16 object.
1.314 + @post A fully constructed and initialized CUri16 object.
1.315 + */
1.316 +EXPORT_C CUri16* CUri16::NewLC(const TUriC16& aUri)
1.317 + {
1.318 + CUri16* self = new (ELeave) CUri16(aUri);
1.319 + CleanupStack::PushL(self);
1.320 + self->ConstructL();
1.321 + return self;
1.322 + }
1.323 +
1.324 +/**
1.325 + Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack.
1.326 + Creates a uri object which is empty.
1.327 +
1.328 + @since 6.0
1.329 + @deprecated Deprecated in 9.1
1.330 + @return A pointer to the newly created CUri16 object.
1.331 + @post A fully constructed and initialized CUri16 object.
1.332 + */
1.333 +EXPORT_C CUri16* CUri16::NewL()
1.334 + {
1.335 + CUri16* self = CUri16::NewLC();
1.336 + CleanupStack::Pop(self);
1.337 + return self;
1.338 + }
1.339 +
1.340 +/**
1.341 + Static factory constructor. Uses two phase construction and leaves a pointer to created object on
1.342 + the CleanupStack. Creates a uri object which is empty.
1.343 +
1.344 + @since 6.0
1.345 + @deprecated Deprecated in 9.1
1.346 + @return A pointer to the newly created CUri16 object.
1.347 + @post A fully constructed and initialized CUri16 object.
1.348 + */
1.349 +EXPORT_C CUri16* CUri16::NewLC()
1.350 + {
1.351 + CUri16* self = new (ELeave) CUri16(TUriC16());
1.352 + CleanupStack::PushL(self);
1.353 + self->ConstructL();
1.354 + return self;
1.355 + }
1.356 +
1.357 +/**
1.358 + Static factory constructor. This creates a CUri16 object that is an absolute uri resulting from a
1.359 + reference uri being resolved against a base uri.
1.360 +
1.361 + @warning Ownership of created CUri16 object is transferred to caller.
1.362 + @leave KUriErrBadBasePath if the base path is not an absolute path and not empty.
1.363 + @since 6.0
1.364 + @deprecated Deprecated in 9.1
1.365 + @param aBaseUri A referece to the parsed base uri.
1.366 + @param aRefUri A referece to the parsed reference uri.
1.367 + @return A pointer to the newly created CUri16 object.
1.368 + @pre The base uri must have an absolute or empty path, otherwise will leave
1.369 + with KUriErrBadBasePath.
1.370 + @post A fully constructed and initialized CUri16 object.
1.371 + */
1.372 +EXPORT_C CUri16* CUri16::ResolveL(const TUriC16& aBaseUri, const TUriC16& aRefUri)
1.373 + {
1.374 + // Check for a base Uri
1.375 + if( aBaseUri.UriDes().Compare(KNullDesC16) == 0 )
1.376 + {
1.377 + // Empty base Uri - resolved Uri is the reference Uri
1.378 + return NewL(aRefUri);
1.379 + }
1.380 + // See if ref has scheme and it is the same as base Uri
1.381 + if( aRefUri.IsPresent(EUriScheme) && aRefUri.Compare(aBaseUri, EUriScheme) != 0 )
1.382 + {
1.383 + // Ref has a scheme different to base Uri's - it is an absolute Uri
1.384 + return NewL(aRefUri);
1.385 + }
1.386 + // Check for presence of components
1.387 + TBool useBaseQuery = EFalse;
1.388 + HBufC16* resolvedPath = FormResolvedPathLC<HBufC16>(aBaseUri, aRefUri, useBaseQuery);
1.389 +
1.390 + // Put the Uri together
1.391 + TUriC16 uri;
1.392 + FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
1.393 +
1.394 + // Create the resolved Uri and cleanup
1.395 + CUri16* resolvedUri = NewL(uri);
1.396 + CleanupStack::PopAndDestroy(resolvedPath);
1.397 +
1.398 + return resolvedUri;
1.399 + }
1.400 +
1.401 +/**
1.402 + Destructor.
1.403 +
1.404 + @since 6.0
1.405 + @deprecated Deprecated in 9.1
1.406 + */
1.407 +EXPORT_C CUri16::~CUri16()
1.408 + {
1.409 + delete iUriBuf;
1.410 + }
1.411 +
1.412 +/**
1.413 + Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC16.
1.414 +
1.415 + @since 6.0
1.416 + @deprecated Deprecated in 9.1
1.417 + @return A const reference to the parsed uri object.
1.418 + */
1.419 +EXPORT_C const TUriC16& CUri16::Uri() const
1.420 + {
1.421 + return iUri;
1.422 + }
1.423 +
1.424 +/**
1.425 + Sets the specified component in the uri. The component is set to the value given in the argument
1.426 + aData. If the specified component already exists then it is replaced with the new value.
1.427 +
1.428 + @warning The userinfo and port components can only be set if the host component
1.429 + is present. Setting these components without a host component present will have no
1.430 + effect on the uri.
1.431 + @since 6.0
1.432 + @deprecated Deprecated in 9.1
1.433 + @param aData A descriptor pointer to the new value for the uri component.
1.434 + @param aComponent An enum specifying the component to be set.
1.435 + @pre Object is fully constructed.
1.436 + @post The uri has the specified component set to the new value.
1.437 + @Leave KErrArgument If aComponent goes out of range.
1.438 + */
1.439 +EXPORT_C void CUri16::SetComponentL(const TDesC16& aData, TUriComponent aComponent)
1.440 + {
1.441 + // Update the appropriate component table entry
1.442 + iUri.iComponent[aComponent].Set(aData);
1.443 +
1.444 + // Copy to the buffer by forming the uri
1.445 + FormUriL();
1.446 + }
1.447 +
1.448 +/**
1.449 + Removes the specified component from the uri. If the component does not exist then this function
1.450 + does nothing.
1.451 +
1.452 + @warning If host is removed, then userinfo and port components will also
1.453 + be removed.
1.454 + @since 6.0
1.455 + @deprecated Deprecated in 9.1
1.456 + @param aComponent An enum specifying the component to be removed.
1.457 + @pre Object is fully constructed.
1.458 + @post The uri is updated to exclude the specified component.
1.459 + */
1.460 +EXPORT_C void CUri16::RemoveComponentL(TUriComponent aComponent)
1.461 + {
1.462 + if( iUri.IsPresent(aComponent) )
1.463 + {
1.464 + // Remove the component - set pointer to NULL and length to zero
1.465 + iUri.iComponent[aComponent].Set(NULL,0);
1.466 +
1.467 + // Re-form buffer and component table
1.468 + FormUriL();
1.469 + }
1.470 + }
1.471 +
1.472 +/**
1.473 + Constructor. First phase of two-phase construction method. Does non-allocating construction.
1.474 +
1.475 + @since 6.0
1.476 + @param aUri The parsed uri component information from which to create
1.477 + the uri.
1.478 + */
1.479 +
1.480 +CUri16::CUri16(const TUriC16& aUri)
1.481 +: CBase(), iUri(aUri)
1.482 + {
1.483 + }
1.484 +
1.485 +/**
1.486 + Second phase of two-phase construction method. Does any allocations required to fully construct
1.487 + the object.
1.488 +
1.489 + @since 6.0
1.490 + @pre First phase of construction is complete.
1.491 + @post The object is fully constructed and initialized.
1.492 + */
1.493 +void CUri16::ConstructL()
1.494 + {
1.495 + // Create the HBufC
1.496 + FormUriL();
1.497 + }
1.498 +
1.499 +/**
1.500 + Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri
1.501 + is changed to refer to the copy.
1.502 +
1.503 + @since 6.0
1.504 + @pre The parsed uri information is set.
1.505 + @post The uri buffer is updated with the parsed uri information.
1.506 + */
1.507 +void CUri16::FormUriL()
1.508 + {
1.509 + TBool isIPv6Host;
1.510 +
1.511 + // Calculate length of of the Uri
1.512 + TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
1.513 +
1.514 + // Create a temporary buffer and descriptor pointer to it
1.515 + HBufC16* buf = HBufC16::NewL(length);
1.516 + TPtr16 uri = buf->Des();
1.517 +
1.518 + // Create the uri, updating the internal uri object
1.519 + DoFormUri(uri, iUri.iComponent, isIPv6Host);
1.520 +
1.521 + // Update the internal buffer and descriptor pointer
1.522 + delete iUriBuf;
1.523 + iUriBuf = buf;
1.524 + iUri.iUriDes.Set(iUriBuf->Des());
1.525 + }
1.526 +
1.527 +//
1.528 +//
1.529 +// Implementation of templated LOCAL functions
1.530 +//
1.531 +//
1.532 +
1.533 +/**
1.534 + Calculates the length of the uri from a list of the components.
1.535 +
1.536 + @since 6.0
1.537 + @param aComponent The array of descriptor pointers to the uri
1.538 + components.
1.539 + @param aIsIPv6Host ETrue if an IPv6 format host is used
1.540 + @return The length of the uri including the required delimiters.
1.541 +*/
1.542 +template<class TPtrCType>
1.543 +TInt CalculateUriLength(const TPtrCType aComponent[], TBool& aIsIPv6Host)
1.544 + {
1.545 + TBool noAuthority = ETrue;
1.546 + TInt length=0;
1.547 + aIsIPv6Host=EFalse;
1.548 + for( TInt i=0; i<EUriMaxComponents; ++i )
1.549 + {
1.550 + if( aComponent[i].Ptr() )
1.551 + {
1.552 + length += aComponent[i].Length();
1.553 + if( noAuthority && (i==EUriUserinfo || i==EUriHost || i==EUriPort) )
1.554 + {
1.555 + // There's an authority part...
1.556 + noAuthority = EFalse;
1.557 + }
1.558 + // Need to make space for a delimiter if not path or host
1.559 + if( i!=EUriHost && i!=EUriPath )
1.560 + ++length;
1.561 +
1.562 + // If it's an IPv6 hostname, need extra space for []
1.563 + if(i==EUriHost && (UriUtils::HostType(aComponent[i])==UriUtils::EIPv6Host))
1.564 + {
1.565 + length+=2;
1.566 + aIsIPv6Host=ETrue;
1.567 + }
1.568 + }
1.569 + }
1.570 + if( !noAuthority && IsNetworkScheme(aComponent[EUriScheme]))
1.571 + {
1.572 + // Make space for authority delimiter
1.573 + length += KUriNetworkAuthorityDelimiterLength;
1.574 + }
1.575 + return length;
1.576 + }
1.577 +
1.578 +/**
1.579 + Templated function to form a uri. The output argument aUri points to a descriptor
1.580 + buffer large enough to hold the uri. The new uri component information is given by
1.581 + the input/output argument aComponent. For each uri component that exists in aComponent,
1.582 + that component and its appropriate delimiters are appended to aUri. Then the components
1.583 + in aComponent are updated to refer to the copies versions in aUri.
1.584 +
1.585 + @since 6.0
1.586 + @param aUri The descriptor pointer to buffer to be appended.
1.587 + @param aComponent The array of descriptor pointers to be copied and
1.588 + then updated.
1.589 + @param aIsIPv6Host ETrue if an IPv6 format host is used
1.590 + @pre The buffer pointed to by aUri should be large enough to have the uri
1.591 + components given in aNewComponent copied into it, as well as the required delimiters.
1.592 + This can be obtained using CalculateUriLength().
1.593 + @post The uri buffer pointed to by aUri will have a copy of the uri defined
1.594 + in aComponent, and then aComponent will refer to the copies of these components in aUri.
1.595 +*/
1.596 +template<class TPtrType, class TPtrCType>
1.597 +void DoFormUri(TPtrType& aUri, TPtrCType aComponent[], TBool& aIsIPv6Host)
1.598 + {
1.599 + TBool isNetworkScheme = ETrue;
1.600 + if( aComponent[EUriScheme].Ptr() )
1.601 + {
1.602 + // Update the scheme
1.603 + SetScheme(aUri, aComponent[EUriScheme]);
1.604 + isNetworkScheme = IsNetworkScheme(aComponent[EUriScheme]);
1.605 + }
1.606 + if( aComponent[EUriHost].Ptr() )
1.607 + {
1.608 + // Update the authority - only needed if there is a host; update userinfo, host and port
1.609 + SetAuthority(aUri, aComponent[EUriUserinfo], aComponent[EUriHost], aComponent[EUriPort], aIsIPv6Host, isNetworkScheme);
1.610 + }
1.611 + else
1.612 + {
1.613 + // Ensure that there is no userinfo or port components if there is no host
1.614 + // - set pointer to NULL and length to zero
1.615 + aComponent[EUriUserinfo].Set(NULL,0);
1.616 + aComponent[EUriPort].Set(NULL,0);
1.617 + }
1.618 + if( aComponent[EUriPath].Ptr() )
1.619 + {
1.620 + // Update the path
1.621 + SetPath(aUri, aComponent[EUriPath]);
1.622 + }
1.623 + if( aComponent[EUriQuery].Ptr() )
1.624 + {
1.625 + // Update the query
1.626 + SetQuery(aUri, aComponent[EUriQuery]);
1.627 + }
1.628 + if( aComponent[EUriFragment].Ptr() )
1.629 + {
1.630 + // Update the fragment
1.631 + SetFragment(aUri, aComponent[EUriFragment]);
1.632 + }
1.633 + }
1.634 +
1.635 +/**
1.636 + Templated function to set the scheme in a uri. The output argument aUri points to the descriptor
1.637 + buffer into which aScheme will be copied.The argument aScheme is then updated to point to the
1.638 + copied version in aUri.
1.639 +
1.640 + @warning This function will panic with KUriErrBufferOverflow if there is not
1.641 + enough space in the descriptor to append the scheme and the required delimiter.
1.642 + @since 6.0
1.643 + @param aUri The descriptor pointer to buffer to be appended.
1.644 + @param aScheme The descriptor pointer to the scheme component to be copied
1.645 + and then updated.
1.646 + @pre The buffer pointed to by aUri should be large enough to have aNewScheme
1.647 + appended to it with the required delimiter. This can be obtained using CalculateUriLength().
1.648 + @post The uri buffer now includes a copy of aScheme and aScheme points to the
1.649 + copy of the scheme component in aUri.
1.650 +*/
1.651 +template<class TPtrType, class TPtrCType>
1.652 +void SetScheme(TPtrType& aUri, TPtrCType& aScheme)
1.653 + {
1.654 + __ASSERT_DEBUG(aUri.Length() + aScheme.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.655 +
1.656 + // Append the scheme and delimiter
1.657 + aUri.Append(aScheme);
1.658 + aUri.Append(KSchemeDelimiter);
1.659 +
1.660 + // Update the component table to use the copy
1.661 + aScheme.Set(aUri.Left(aScheme.Length()));
1.662 + }
1.663 +
1.664 +/**
1.665 + Templated function to set the authority in a uri. The output argument aUri points to the descriptor
1.666 + buffer into which aUserinfo, aHost and aPort will be copied. The arguments aUserinfo, aHost and aPort
1.667 + are updated to point to the copied versions in aUri.
1.668 +
1.669 + @warning This function will panic with KUriErrBufferOverflow if there
1.670 + is not enough space in the descriptor to append the components and any required
1.671 + delimiters.
1.672 + @since 6.0
1.673 + @param aUri The descriptor pointer to buffer to be appended.
1.674 + @param aUserinfo The descriptor pointer to the userinfo component to
1.675 + be copied and then updated.
1.676 + @param aHost The descriptor pointer to the host component to
1.677 + be copied and then updated.
1.678 + @param aPort The descriptor pointer to the port component to
1.679 + be copied and then updated.
1.680 + @param aIsIPv6Host ETrue if an IPv6 format host is used
1.681 + @param aUseNetworkDelimiter EFalse if this is a SIP scheme otherwise ETrue
1.682 + @pre The buffer pointed to by aUri should be large enough to have
1.683 + aUserinfo, aHost and aPort appended to it with the required delimiters.
1.684 + This can be obtained using CalculateUriLength().
1.685 + @post The uri buffer now includes a copy of aUserinfo, aHost and
1.686 + aPort, and aUserinfo, aHost and aPort will refer to the copies versions in aUri.
1.687 +*/
1.688 +template<class TPtrType, class TPtrCType>
1.689 +void SetAuthority(TPtrType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool& aIsIPv6Host, TBool aUseNetworkDelimiter)
1.690 + {
1.691 + __ASSERT_DEBUG(aUri.Length() + aHost.Length() + (aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength:0) <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.692 +
1.693 + if (aUseNetworkDelimiter)
1.694 + {
1.695 + // If a network scheme append authority delimiter (TWO slash delimiters!)
1.696 + aUri.Append(KSlashDelimiter);
1.697 + aUri.Append(KSlashDelimiter);
1.698 + }
1.699 +
1.700 + // Check for userinfo
1.701 + if( aUserinfo.Ptr() )
1.702 + {
1.703 + __ASSERT_DEBUG(aUri.Length() + aUserinfo.Length() + aHost.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.704 +
1.705 + // Append userinfo and update the component table to use copy
1.706 + aUri.Append(aUserinfo);
1.707 + aUserinfo.Set(aUri.Right(aUserinfo.Length()));
1.708 +
1.709 + // Append delimiter
1.710 + aUri.Append(KUserinfoDelimiter);
1.711 + }
1.712 + // There's always a host - append and update the component table to use the copy
1.713 +
1.714 + // Check if it's an IPv6 address
1.715 + if ( aIsIPv6Host )
1.716 + {
1.717 + aUri.Append(KIPv6UriOpenBrace);
1.718 + aUri.Append(aHost);
1.719 + aUri.Append(KIPv6UriCloseBrace);
1.720 + // Dont include the braces in the host
1.721 + // Position = (length of uri - length of host) - length of end brace
1.722 + aHost.Set( aUri.Mid((aUri.Length()-aHost.Length())-1, aHost.Length()) );
1.723 + }
1.724 + else
1.725 + {
1.726 + aUri.Append(aHost);
1.727 + aHost.Set(aUri.Right(aHost.Length()));
1.728 + }
1.729 +
1.730 + // Check for a port
1.731 + if( aPort.Ptr() )
1.732 + {
1.733 + __ASSERT_DEBUG(aUri.Length() + aPort.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.734 +
1.735 + // Append delimiter
1.736 + aUri.Append(KPortDelimiter);
1.737 +
1.738 + // Append port and update the component table to use copy
1.739 + aUri.Append(aPort);
1.740 + aPort.Set(aUri.Right(aPort.Length()));
1.741 + }
1.742 + }
1.743 +/**
1.744 + Templated function to set the path in a uri. The output argument aUri points to the descriptor
1.745 + buffer into which aPath will be copied.The argument aPath is then updated to point to the copied
1.746 + version in aUri.
1.747 +
1.748 + @warning This function will panic with KUriErrBufferOverflow if there
1.749 + is not enough space in the descriptor to append the path.
1.750 + @since 6.0
1.751 + @param aUri The descriptor pointer to buffer to be appended.
1.752 + @param aPath The descriptor pointer to the path component to be copied
1.753 + and then updated.
1.754 + @pre The buffer pointed to by aUri should be large enough to have
1.755 + aPath appended to it. This can be obtained using CalculateUriLength().
1.756 + @post The uri buffer now includes a copy of aPath and aPath points to the
1.757 + copy of the path component in aUri.
1.758 +*/
1.759 +template<class TPtrType, class TPtrCType>
1.760 +void SetPath(TPtrType& aUri, TPtrCType& aPath)
1.761 + {
1.762 + __ASSERT_DEBUG(aUri.Length() + aPath.Length() <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.763 +
1.764 + // Append the path
1.765 + aUri.Append(aPath);
1.766 +
1.767 + // Update the component table
1.768 + aPath.Set(aUri.Right(aPath.Length()));
1.769 + }
1.770 +
1.771 +/**
1.772 + Templated function to set the query in a uri. The output argument aUri points to the descriptor
1.773 + buffer into which aQuery will be copied. The argument aQuery is then updated to point to the copied
1.774 + version in aUri.
1.775 +
1.776 + @warning This function will panic with KUriErrBufferOverflow if there
1.777 + is not enough space in the descriptor to append the query and the delimiter.
1.778 + @since 6.0
1.779 + @param aUri The descriptor pointer to buffer to be appended.
1.780 + @param aQuery The descriptor pointer to the query component to be copied
1.781 + and then updated.
1.782 + @pre The buffer pointed to by aUri should be large enough to have
1.783 + aQuery appended to it. This can be obtained using CalculateUriLength().
1.784 + @post The uri buffer now includes a copy of aQuery and aQuery points to the
1.785 + copy of the query component in aUri.
1.786 +*/
1.787 +template<class TPtrType, class TPtrCType>
1.788 +void SetQuery(TPtrType& aUri, TPtrCType& aQuery)
1.789 + {
1.790 + __ASSERT_DEBUG(aUri.Length() + aQuery.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.791 +
1.792 + // Append delimiter and the query
1.793 + aUri.Append(KQueryDelimiter);
1.794 + aUri.Append(aQuery);
1.795 +
1.796 + // Update the component table
1.797 + aQuery.Set(aUri.Right(aQuery.Length()));
1.798 + }
1.799 +
1.800 +/**
1.801 + Templated function to set the fragment in a uri. The output argument aUri points to the descriptor
1.802 + buffer into which aFragment will be copied. The argument aFragment is then updated to point to the
1.803 + copied version in aUri.
1.804 +
1.805 + @warning This function will panic with KUriErrBufferOverflow if there
1.806 + is not enough space in the descriptor to append the fragment and the delimiter.
1.807 + @since 6.0
1.808 + @param aUri The descriptor pointer to buffer to be appended.
1.809 + @param aFragment The descriptor pointer to the fragment component
1.810 + to be copied and then updated.
1.811 + @pre The buffer pointed to by aUri should be large enough to have
1.812 + aFragment appended to it. This can be obtained using CalculateUriLength().
1.813 + @post The uri buffer now includes a copy of aFragment and aFragment points
1.814 + to the copy of the fragment component in aUri.
1.815 +*/
1.816 +template<class TPtrType, class TPtrCType>
1.817 +void SetFragment(TPtrType& aUri, TPtrCType& aFragment)
1.818 + {
1.819 + __ASSERT_DEBUG(aUri.Length() + aFragment.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
1.820 +
1.821 + // Append delimiter and the fragment
1.822 + aUri.Append(KFragmentDelimiter);
1.823 + aUri.Append(aFragment);
1.824 +
1.825 + // Update the component table
1.826 + aFragment.Set(aUri.Right(aFragment.Length()));
1.827 + }
1.828 +
1.829 +/**
1.830 + Forms the resolved path. Checks to see if the base query needs to be used in the resolved uri.
1.831 + The pointer to the resolved path is left on the cleanup stack.
1.832 +
1.833 + @since 6.0
1.834 + @param aBaseUri The base uri.
1.835 + @param aRefUri The reference uri.
1.836 + @param aUseBaseQuery An output argument specifying whether the base
1.837 + query should be used in the resolved uri.
1.838 + @return A pointer to a buffer that contains the resolved path.
1.839 +*/
1.840 +template<class HBufCType, class TUriCType>
1.841 +HBufCType* FormResolvedPathLC(const TUriCType& aBaseUri, const TUriCType& aRefUri, TBool& aUseBaseQuery)
1.842 + {
1.843 + HBufCType* resolvedPath = NULL;
1.844 + if( !aRefUri.IsPresent(EUriScheme) && !aRefUri.IsPresent(EUriHost) && !aRefUri.Extract(EUriPath).Length() && !aRefUri.IsPresent(EUriQuery) )
1.845 + {
1.846 + // Ref is just a fragment
1.847 + aUseBaseQuery = ETrue;
1.848 + resolvedPath = aBaseUri.Extract(EUriPath).AllocLC();
1.849 + }
1.850 + else if( aRefUri.IsPresent(EUriHost) )
1.851 + {
1.852 + // Ref is a network path
1.853 + resolvedPath = aRefUri.Extract(EUriPath).AllocLC();
1.854 + }
1.855 + else
1.856 + {
1.857 + // Need to some path resolving...
1.858 + resolvedPath = ResolvePathsL(aBaseUri.Extract(EUriPath), aRefUri.Extract(EUriPath));
1.859 + CleanupStack::PushL(resolvedPath);
1.860 + }
1.861 + return resolvedPath;
1.862 + }
1.863 +
1.864 +/**
1.865 + Cleans up a resolved path. This deals with occurences of '.' and '..' where these are complete
1.866 + path segments.
1.867 +
1.868 + @since 6.0
1.869 + @param aResolvedPath The delimited data object that contains the
1.870 + resolved path.
1.871 + @pre The input/output argument contains the path to be cleaned.
1.872 + @post The resolved path has had all the occurences of '.' and '..'
1.873 + processed and has been updated to contain the cleaned path.
1.874 + */
1.875 +template<class TPtrCType, class CDelimitedDataBaseType>
1.876 +void CleanResolvedPathL(CDelimitedDataBaseType* aResolvedPath)
1.877 + {
1.878 + // Create a modifiable path object for resolved path
1.879 + aResolvedPath->Parse();
1.880 +
1.881 + TBool done = EFalse;
1.882 + while( !done )
1.883 + {
1.884 + // Get the next segment
1.885 + TPtrCType segment;
1.886 + TInt more = aResolvedPath->Parser().Peek(segment);
1.887 +
1.888 + if( more == KErrNotFound )
1.889 + {
1.890 + // No more segments - done
1.891 + done = ETrue;
1.892 + }
1.893 + else if( IsParentDir(segment) )
1.894 + {
1.895 + // Found a '..' - remove '..' from path, and remove previous segment
1.896 + aResolvedPath->RemoveCurrentL();
1.897 + if( aResolvedPath->Parser().Dec() == KErrNotFound )
1.898 + {
1.899 + // No previous directory - put back '..' and stop
1.900 + InsertParentDirL(aResolvedPath);
1.901 + done = ETrue;
1.902 + }
1.903 + else
1.904 + {
1.905 + // Remove the parent directory
1.906 + aResolvedPath->RemoveCurrentL();
1.907 + if( aResolvedPath->Parser().Eos() )
1.908 + {
1.909 + // '..' is the last segment - add a '/' to the path (add empty segment)
1.910 + aResolvedPath->AddBackDelimiterL();
1.911 + done = ETrue;
1.912 + }
1.913 + }
1.914 + }
1.915 + else if( IsSameDir(segment) )
1.916 + {
1.917 + // Found a '.' - remove -.- from the path
1.918 + aResolvedPath->RemoveCurrentL();
1.919 + if( aResolvedPath->Parser().Eos() )
1.920 + {
1.921 + // '..' is the last segment - add a '/' to the path (add empty segment)
1.922 + aResolvedPath->AddBackDelimiterL();
1.923 + done = ETrue;
1.924 + }
1.925 + }
1.926 + else
1.927 + {
1.928 + // Segment wasn't '.' or '..' - parse to next segment
1.929 + aResolvedPath->Parser().Inc();
1.930 + }
1.931 + }
1.932 + }
1.933 +
1.934 +/**
1.935 + Forms the resolved uri. Sets the components for the resolved uri from those in the base uri and
1.936 + the reference uri. The resolved path is given by the input argument aResolvedPath
1.937 +
1.938 + @since 6.0
1.939 + @param aComponent The array of components to be set for the resolved uri.
1.940 + @param aBaseUri The base uri.
1.941 + @param aRefUri The reference uri.
1.942 + @param aResolvedPath The resolved path.
1.943 + @param aUseBaseQuery A boolean indicating whether the base query
1.944 + should be used.
1.945 +*/
1.946 +template<class TPtrCType, class TUriCType, class HBufCType>
1.947 +void FormResolvedUri(TPtrCType aComponent[], const TUriCType& aBaseUri, const TUriCType& aRefUri, const HBufCType* aResolvedPath, TBool aUseBaseQuery)
1.948 + {
1.949 + // Scheme...
1.950 + if( aBaseUri.IsPresent(EUriScheme) )
1.951 + {
1.952 + // Use the base scheme
1.953 + aComponent[EUriScheme].Set(aBaseUri.Extract(EUriScheme));
1.954 + }
1.955 + // Authority
1.956 + if( aRefUri.IsPresent(EUriHost) )
1.957 + {
1.958 + // Use the ref host, userinfo and port - must set host first
1.959 + aComponent[EUriHost].Set(aRefUri.Extract(EUriHost));
1.960 + aComponent[EUriUserinfo].Set(aRefUri.Extract(EUriUserinfo));
1.961 + aComponent[EUriPort].Set(aRefUri.Extract(EUriPort));
1.962 + }
1.963 + else if( aBaseUri.IsPresent(EUriHost) )
1.964 + {
1.965 + // Use the base host, userinfo and port - must set host first
1.966 + aComponent[EUriHost].Set(aBaseUri.Extract(EUriHost));
1.967 + aComponent[EUriUserinfo].Set(aBaseUri.Extract(EUriUserinfo));
1.968 + aComponent[EUriPort].Set(aBaseUri.Extract(EUriPort));
1.969 + }
1.970 + // Path...
1.971 + aComponent[EUriPath].Set(*aResolvedPath);
1.972 +
1.973 + // Query...
1.974 + if( aUseBaseQuery && aBaseUri.IsPresent(EUriQuery) )
1.975 + {
1.976 + // Use the query from the base
1.977 + aComponent[EUriQuery].Set(aBaseUri.Extract(EUriQuery));
1.978 + }
1.979 + else if( aRefUri.IsPresent(EUriQuery) )
1.980 + {
1.981 + // Use the query from the ref
1.982 + aComponent[EUriQuery].Set(aRefUri.Extract(EUriQuery));
1.983 + }
1.984 + // Fragment
1.985 + if( aRefUri.IsPresent(EUriFragment) )
1.986 + {
1.987 + // Use the fragment from the ref
1.988 + aComponent[EUriFragment].Set(aRefUri.Extract(EUriFragment));
1.989 + }
1.990 + }
1.991 +
1.992 +//
1.993 +//
1.994 +// Implemetation of LOCAL functions
1.995 +//
1.996 +//
1.997 +
1.998 +/**
1.999 + Function used to resolve a base path (aBasePath) against a reference path (aRefPath),
1.1000 + as described by RFC2396.
1.1001 +
1.1002 + @since 6.0
1.1003 + @param aBasePath A descriptor reference to the base path.
1.1004 + @param aRefPath A descriptor reference to the reference path.
1.1005 + @return A pointer to a buffer containing the resolve path.
1.1006 + @leave KUriErrBadBasePath if the base path is not an absolute path and not empty.
1.1007 +*/
1.1008 +HBufC8* ResolvePathsL(const TDesC8& aBasePath, const TDesC8& aRefPath)
1.1009 + {
1.1010 + TInt refLength = aRefPath.Length();
1.1011 + if( refLength && aRefPath[0] == KSlashDelimiter )
1.1012 + {
1.1013 + // Relative path is absolute - that is the resolved path
1.1014 + return aRefPath.AllocL();
1.1015 + }
1.1016 + // Ok got work to do - base path must be absolute (check 1st char) or empty
1.1017 + if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
1.1018 + {
1.1019 + // Base path not empty and not abosolute - bad base path
1.1020 + User::Leave(KUriUtilsErrBadBasePath);
1.1021 + }
1.1022 + // Create a modifiable path object for resolved path
1.1023 + CDelimitedPath8* resolvedPath = CDelimitedPath8::NewLC(aBasePath);
1.1024 +
1.1025 + // Check for empty ref path - use all of base path if empty
1.1026 + if( refLength )
1.1027 + {
1.1028 + // Not empty - ensure that base path's last segment is removed and add reference
1.1029 + resolvedPath->PopBackL();
1.1030 + resolvedPath->PushBackL(aRefPath);
1.1031 + }
1.1032 + // Clean up the path to resolve occurences of '..' and '.' - parser path first
1.1033 + CleanResolvedPathL<TPtrC8>(resolvedPath);
1.1034 +
1.1035 + // Return pointer to HBufC with path
1.1036 + HBufC8* path = resolvedPath->Parser().Des().AllocL();
1.1037 + CleanupStack::PopAndDestroy(resolvedPath);
1.1038 + return path;
1.1039 + }
1.1040 +
1.1041 +/**
1.1042 + Function used to resolve a base path (aBasePath) against a reference path (aRefPath),
1.1043 + as described by RFC2396.
1.1044 +
1.1045 + @since 6.0
1.1046 + @param aBasePath A descriptor reference to the base path.
1.1047 + @param aRefPath A descriptor reference to the reference path.
1.1048 + @return A pointer to a buffer containing the resolve path.
1.1049 + @leave KUriErrBadBasePath if the base path is not an absolute path and not empty.
1.1050 +*/
1.1051 +HBufC16* ResolvePathsL(const TDesC16& aBasePath, const TDesC16& aRefPath)
1.1052 + {
1.1053 + TInt refLength = aRefPath.Length();
1.1054 + if( refLength && aRefPath[0] == KSlashDelimiter )
1.1055 + {
1.1056 + // Relative path is absolute - that is the resolved path
1.1057 + return aRefPath.AllocL();
1.1058 + }
1.1059 + // Ok got work to do - base path must be absolute (check 1st char) or empty
1.1060 + if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
1.1061 + {
1.1062 + // Base path not empty and not abosolute - bad base path
1.1063 + User::Leave(KUriUtilsErrBadBasePath);
1.1064 + }
1.1065 + // Create a modifiable path object for resolved path
1.1066 + CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(aBasePath);
1.1067 +
1.1068 + // Check for empty ref path - use all of base path if empty
1.1069 + if( refLength )
1.1070 + {
1.1071 + // Not empty - ensure that base path's last segment is removed and add reference
1.1072 + resolvedPath->PopBackL();
1.1073 + resolvedPath->PushBackL(aRefPath);
1.1074 + }
1.1075 + // Clean up the path to resolve occurences of '..' and '.' - parser path first
1.1076 + CleanResolvedPathL<TPtrC16>(resolvedPath);
1.1077 +
1.1078 + // Return pointer to HBufC with path
1.1079 + HBufC16* path = resolvedPath->Parser().Des().AllocL();
1.1080 + CleanupStack::PopAndDestroy(resolvedPath);
1.1081 + return path;
1.1082 + }
1.1083 +
1.1084 +/**
1.1085 + Checks if the segment is '.' (8-bit version).
1.1086 +
1.1087 + @since 6.0
1.1088 + @param aSegment A descriptor with the segment to check.
1.1089 + @return A boolean value of ETrue if the segment is '.', EFalse if not.
1.1090 +*/
1.1091 +TBool IsSameDir(const TDesC8& aSegment)
1.1092 + {
1.1093 + _LIT8(KSameDir, ".");
1.1094 + return (aSegment.Compare(KSameDir) == 0);
1.1095 + }
1.1096 +
1.1097 +/**
1.1098 + Checks if the segment is '.' (16-bit version).
1.1099 +
1.1100 + @since 6.0
1.1101 + @param aSegment A descriptor with the segment to check.
1.1102 + @return A boolean value of ETrue if the segment is '.', EFalse if not.
1.1103 +*/
1.1104 +TBool IsSameDir(const TDesC16& aSegment)
1.1105 + {
1.1106 + _LIT16(KSameDir, ".");
1.1107 + return (aSegment.Compare(KSameDir) == 0);
1.1108 + }
1.1109 +
1.1110 +/**
1.1111 + Checks if the segment is '..' (8-bit version).
1.1112 +
1.1113 + @since 6.0
1.1114 + @param aSegment A descriptor with the segment to check.
1.1115 + @return A boolean value of ETrue if the segment is '..', EFalse if not.
1.1116 +*/
1.1117 +TBool IsParentDir(const TDesC8& aSegment)
1.1118 + {
1.1119 + _LIT8(KParentDir, "..");
1.1120 + return (aSegment.Compare(KParentDir) == 0);
1.1121 + }
1.1122 +
1.1123 +/**
1.1124 + Checks if the segment is '..' (16-bit version).
1.1125 +
1.1126 + @since 6.0
1.1127 + @param aSegment A descriptor with the segment to check.
1.1128 + @return A boolean value of ETrue if the segment is '..', EFalse if not.
1.1129 +*/
1.1130 +TBool IsParentDir(const TDesC16& aSegment)
1.1131 + {
1.1132 + _LIT16(KParentDir, "..");
1.1133 + return (aSegment.Compare(KParentDir) == 0);
1.1134 + }
1.1135 +
1.1136 +/**
1.1137 + Inserts the segment '..' at the current parsed position (8-bit version).
1.1138 +
1.1139 + @since 6.0
1.1140 + @param aResolvedPath The delimited data object to have the segment
1.1141 + inserted.
1.1142 + @pre The delimited data object must be parsed to the position where
1.1143 + the segment is to be inserted.
1.1144 + @post The segment '..' has been inserted at the current position.
1.1145 +*/
1.1146 +void InsertParentDirL(CDelimitedDataBase8* aResolvedPath)
1.1147 + {
1.1148 + _LIT8(KParentDir, "..");
1.1149 + aResolvedPath->InsertCurrentL(KParentDir);
1.1150 + }
1.1151 +
1.1152 +/**
1.1153 + Inserts the segment '..' at the current parsed position (16-bit version).
1.1154 +
1.1155 + @since 6.0
1.1156 + @param aResolvedPath The delimited data object to have the segment
1.1157 + inserted.
1.1158 + @pre The delimited data object must be parsed to the position where
1.1159 + the segment is to be inserted.
1.1160 + @post The segment '..' has been inserted at the current position.
1.1161 +*/
1.1162 +void InsertParentDirL(CDelimitedDataBase16* aResolvedPath)
1.1163 + {
1.1164 + _LIT16(KParentDir, "..");
1.1165 + aResolvedPath->InsertCurrentL(KParentDir);
1.1166 + }
1.1167 +
1.1168 +
1.1169 +//
1.1170 +//
1.1171 +// File URI Implementation - CUri8
1.1172 +//
1.1173 +//
1.1174 +
1.1175 +/**
1.1176 + Initializes the file URI components (scheme, empty hostname and path).
1.1177 +
1.1178 + It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive.
1.1179 +
1.1180 + @since 9.1
1.1181 + @param aFileName A reference to a filename
1.1182 + @param aDrive A drive number. This is a TFileUriFlags value.
1.1183 + @param aFlags A flag to indicate if the file exists on a fixed drive or removable media drive.
1.1184 + This is a TFileUriFlags value.
1.1185 + @pre Object fully constructed
1.1186 + @post The object is initialized with file URI components.
1.1187 + */
1.1188 +void CUri8::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
1.1189 + {
1.1190 + HBufC* uriPath16 = GenerateFileUriPathL(aFileName, aDrive, aFlags);
1.1191 + CleanupStack::PushL(uriPath16);
1.1192 + HBufC8* uriPath = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath16);
1.1193 + CleanupStack::PopAndDestroy(uriPath16);
1.1194 + CleanupStack::PushL(uriPath);
1.1195 + HBufC8* escpedUriPath = EscapeUtils::EscapeEncodeL(*uriPath, EscapeUtils::EEscapeNormal);
1.1196 + CleanupStack::PopAndDestroy(uriPath);
1.1197 + CleanupStack::PushL(escpedUriPath);
1.1198 +
1.1199 + //SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation,
1.1200 + //tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer
1.1201 + //for each SetComponent call
1.1202 + iUri.iComponent[EUriPath].Set(*escpedUriPath);
1.1203 + iUri.iComponent[EUriHost].Set(KNullDesC8);
1.1204 + iUri.iComponent[EUriScheme].Set(KFileUriScheme8);
1.1205 + FormUriL();
1.1206 +
1.1207 + CleanupStack::PopAndDestroy(escpedUriPath);
1.1208 + }
1.1209 +
1.1210 +/**
1.1211 + Allocates and constructs a file URI object for a specified file.
1.1212 +
1.1213 + - If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.
1.1214 + - If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
1.1215 +
1.1216 + @since 9.1
1.1217 + @param aFullFileName A reference to a fully qualified filename
1.1218 + @param aFlags A flag to indicate if the file exists on a fixed drive or removable media drive.
1.1219 + This is a TFileUriFlags value.
1.1220 + @return A pointer to the newly created file URI (CUri8) object.
1.1221 + @post A fully constructed and initialized file URI (CUri8) object.
1.1222 + */
1.1223 +EXPORT_C CUri8* CUri8::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
1.1224 + {
1.1225 + //It should be called to construct a file URI for a public file stored on a fix drive
1.1226 + // or on a removable media drive only
1.1227 + __ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
1.1228 +
1.1229 + CUri8* self = CUri8::NewLC();
1.1230 + self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
1.1231 + CleanupStack::Pop(self);
1.1232 + return self;
1.1233 + }
1.1234 +
1.1235 +/**
1.1236 + Allocates and constructs a file URI object for a file that is private to the application.
1.1237 +
1.1238 + - If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
1.1239 + - If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
1.1240 +
1.1241 + @since 9.1
1.1242 + @param aRelativeFileName A reference to the filename relative to the application's private directory.
1.1243 + @param aDrive Drive number, if the private file stored on fixed drive, otherwise not used
1.1244 + This is a TDriveNumber value
1.1245 + @param aFlags A flag to indicate if the file exists on a fixed drive or removable media drive.
1.1246 + This is a TFileUriFlags value.
1.1247 + @return A pointer to the newly created file URI (CUri8) object.
1.1248 + @post A fully constructed and initialized file URI (CUri8) object.
1.1249 +*/
1.1250 +
1.1251 +
1.1252 +EXPORT_C CUri8* CUri8::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags)
1.1253 + {
1.1254 + //It should be called to construct a file URI for the application's private file stored on a fix drive
1.1255 + // or on a removable media drive only
1.1256 + __ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
1.1257 +
1.1258 + CUri8* self = CUri8::NewLC();
1.1259 + self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
1.1260 + CleanupStack::Pop(self);
1.1261 + return self;
1.1262 + }
1.1263 +
1.1264 +
1.1265 +//
1.1266 +//
1.1267 +// File URI Implementation - CUri16
1.1268 +//
1.1269 +//
1.1270 +
1.1271 +/**
1.1272 + Initializes the file URI components (scheme, empty hostname and path).
1.1273 +
1.1274 + It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive.
1.1275 +
1.1276 + @since 9.1
1.1277 + @param aFileName A reference to a filename
1.1278 + @param aDrive A drive number. This is a TFileUriFlags value.
1.1279 + @param aFlags A flag to indicate if the file exists on a fixed drive or removable media drive.
1.1280 + This is a TFileUriFlags value.
1.1281 + @pre Object fully constructed
1.1282 + @post The object is initialized with file URI components.
1.1283 + */
1.1284 +void CUri16::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
1.1285 + {
1.1286 + HBufC* uriPath = GenerateFileUriPathL(aFileName, aDrive, aFlags);
1.1287 + CleanupStack::PushL(uriPath);
1.1288 +
1.1289 + HBufC8* uriPath8 = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath);
1.1290 + CleanupStack::PopAndDestroy(uriPath);
1.1291 + CleanupStack::PushL(uriPath8);
1.1292 +
1.1293 + HBufC8* escapedUriPath8 = EscapeUtils::EscapeEncodeL(*uriPath8, EscapeUtils::EEscapeNormal);
1.1294 + CleanupStack::PopAndDestroy(uriPath8);
1.1295 + CleanupStack::PushL(escapedUriPath8);
1.1296 +
1.1297 + HBufC* escapedUriPath = HBufC::NewLC(escapedUriPath8->Length());
1.1298 + escapedUriPath->Des().Copy(*escapedUriPath8);
1.1299 +
1.1300 + //SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation,
1.1301 + //tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer
1.1302 + //for each SetComponent call
1.1303 + iUri.iComponent[EUriPath].Set(*escapedUriPath);
1.1304 + iUri.iComponent[EUriHost].Set(KNullDesC16);
1.1305 + iUri.iComponent[EUriScheme].Set(KFileUriScheme16);
1.1306 + FormUriL();
1.1307 +
1.1308 + CleanupStack::PopAndDestroy(escapedUriPath);
1.1309 + CleanupStack::PopAndDestroy(escapedUriPath8);
1.1310 + }
1.1311 +
1.1312 +/**
1.1313 + Allocates and constructs a file URI object for a specified file.
1.1314 +
1.1315 + - If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.
1.1316 + - If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
1.1317 +
1.1318 + @since 9.1
1.1319 + @param aFullFileName A reference to a fully qualified filename
1.1320 + @param aFlags A flag to indicate if the file exists on a fixed drive or removable media drive.
1.1321 + This is a TFileUriFlags value.
1.1322 + @return A pointer to the newly created file URI (CUri16) object.
1.1323 + @post A fully constructed and initialized file URI (CUri16) object.
1.1324 + */
1.1325 +EXPORT_C CUri16* CUri16::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
1.1326 + {
1.1327 + //It should be called to construct a file URI for a public file stored on a fix drive
1.1328 + // or on a removable media drive only
1.1329 + __ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
1.1330 +
1.1331 + CUri16* self = CUri16::NewLC();
1.1332 + self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
1.1333 + CleanupStack::Pop(self);
1.1334 + return self;
1.1335 + }
1.1336 +
1.1337 +/**
1.1338 + Allocates and constructs a file URI object for a file that is private to the application.
1.1339 +
1.1340 + - If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
1.1341 + - If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
1.1342 +
1.1343 + @since 9.1
1.1344 + @param aRelativeFileName A reference to the filename relative to the application's private directory.
1.1345 + @param aDrive Drive number, if the private file stored on fixed drive, otherwise not used
1.1346 + This is a TDriveNumber value
1.1347 + @param aFlags A flag to indicate if the file exists on a fixed drive or removable media drive.
1.1348 + This is a TFileUriFlags value.
1.1349 + @return A pointer to the newly created file URI (CUri16) object.
1.1350 + @post A fully constructed and initialized file URI (CUri16) object.
1.1351 +*/
1.1352 +
1.1353 +
1.1354 +EXPORT_C CUri16* CUri16::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags)
1.1355 + {
1.1356 + //It should be called to construct a file URI for the application's private file stored on a fix drive
1.1357 + // or on a removable media drive only
1.1358 + __ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
1.1359 +
1.1360 + CUri16* self = CUri16::NewLC();
1.1361 + self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
1.1362 + CleanupStack::Pop(self);
1.1363 + return self;
1.1364 + }
1.1365 +
1.1366 +
1.1367 +//
1.1368 +//
1.1369 +// Implemetation of LOCAL functions for the File URI
1.1370 +//
1.1371 +//
1.1372 +
1.1373 +/**
1.1374 + Function used to generate 16bit file uri using 1st parameter aFileName and
1.1375 + 2nd parameter aDrive for the application's private or a public file.
1.1376 +
1.1377 + This is called by API CreateFileUri() and CreatePrivateFileUri()to
1.1378 + generate a filename.
1.1379 +
1.1380 + Note: The space allocated for the returned descriptor will likely be larger
1.1381 + than the length of the descriptor
1.1382 +
1.1383 + @leave KErrBadName A provided Drivename or filename is not valid
1.1384 + @since 9.1
1.1385 + @param aFileName A descriptor reference to the filename.
1.1386 + @param aDrive A descriptor reference to drive letter.
1.1387 + @param aFlags A flag to indicate the private or a public file exists on removable media or a fixed drive.
1.1388 + @return A pointer to a buffer containing the resolved fully qualified filename.
1.1389 + */
1.1390 +HBufC* GenerateFileUriPathL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
1.1391 + {
1.1392 + TInt origLength = aFileName.Length();
1.1393 +
1.1394 + //Leaves with KErrBadName if filename length is out of range
1.1395 + if (origLength == 0 || origLength > KMaxFileName)
1.1396 + {
1.1397 + User::Leave(KErrBadName);
1.1398 + }
1.1399 +
1.1400 + TPtrC filename(aFileName);
1.1401 +
1.1402 + //extract drive letter and remove drive "x:" from filename
1.1403 + TUint drive = filename[0];
1.1404 +
1.1405 + // hasDrive means it begins with a drive, e.g. "c:"
1.1406 + const TBool hasDrive = ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z')) && (filename[1] == KDriveSeparator);
1.1407 + // hasTopPath means it begins with a \ (possibly after the drive)
1.1408 + const TBool hasTopPath = (hasDrive && (filename[2] == KFilePathSeparator)) || (!hasDrive && (drive == TUint(KFilePathSeparator) ));
1.1409 +
1.1410 + TInt skip = KDefaultPath().Length(); // skip leading "<drive>:\" by default
1.1411 + if(aFlags & TUint(EPrivate))
1.1412 + {
1.1413 + skip = (hasDrive ? (KDefaultPath().Length() - 1) : 0) + (hasTopPath ? 1 : 0) ;
1.1414 + }
1.1415 + else
1.1416 + {
1.1417 + // if not private then it should have valid drive i.e. "<drive>:\"
1.1418 + if (!(hasDrive && hasTopPath))
1.1419 + {
1.1420 + User::Leave(KErrBadName);
1.1421 + }
1.1422 + }
1.1423 +
1.1424 + if(skip)
1.1425 + {
1.1426 + filename.Set(aFileName.Right(origLength - skip));
1.1427 + }
1.1428 +
1.1429 + TInt uriLen = aFileName.Length() + KExtMedia().Length() + KPrivate().Length() + 1 /* for drive letter */;
1.1430 +
1.1431 + HBufC* fileUri = HBufC::NewLC(uriLen);
1.1432 + TPtr fileUriPtr = fileUri->Des();
1.1433 + fileUriPtr.Append(KUriPathSeparator);
1.1434 +
1.1435 + if (aFlags & TUint(EPrivate))
1.1436 + {
1.1437 + fileUriPtr.Append(KPrivate);
1.1438 + drive = TInt16('A' + aDrive);
1.1439 + }
1.1440 +
1.1441 + if (aFlags & EExtMedia)
1.1442 + {
1.1443 + fileUriPtr.Append(KExtMedia);
1.1444 + }
1.1445 + else
1.1446 + {
1.1447 + fileUriPtr.Append(drive);
1.1448 + fileUriPtr.Append(KUriPathSeparator);
1.1449 + }
1.1450 +
1.1451 + fileUriPtr.Append(filename);
1.1452 +
1.1453 + //Convert "\" to "/"
1.1454 + ChangePathSeparator(fileUriPtr, KFilePathSeparator, KUriPathSeparator);
1.1455 +
1.1456 + //Handling "./" and "../" in the file URI path or resolving the URI path
1.1457 + CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(fileUriPtr);
1.1458 + // Clean up the path to resolve occurences of '..' and '.'
1.1459 + CleanResolvedPathL<TPtrC>(resolvedPath);
1.1460 + fileUriPtr.Copy(resolvedPath->Parser().Des()); // new path will always be shorter than old one
1.1461 + CleanupStack::PopAndDestroy(resolvedPath);
1.1462 +
1.1463 + CleanupStack::Pop(fileUri);
1.1464 + return fileUri;
1.1465 + }