os/ossrv/genericservices/httputils/UriParser/CUri.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <escapeutils.h>
sl@0
    17
#include <uri8.h>
sl@0
    18
#include <uri16.h>
sl@0
    19
#include <delimitedpath8.h>
sl@0
    20
#include <delimitedpath16.h>
sl@0
    21
#include <uriutilscommon.h>
sl@0
    22
#include <uriutils.h>
sl@0
    23
sl@0
    24
#include "UriUtilsInternal.h"
sl@0
    25
#include "TUriCInternal.h"
sl@0
    26
#include "CUriInternal.h"
sl@0
    27
sl@0
    28
// Panic category
sl@0
    29
//
sl@0
    30
#ifdef _DEBUG
sl@0
    31
	_LIT(KUriPanicCategory,"URI-CURI"); 
sl@0
    32
#endif
sl@0
    33
sl@0
    34
// Constants
sl@0
    35
//
sl@0
    36
_LIT(KFileUriPanicCategory,"FILEURI-CURI");
sl@0
    37
sl@0
    38
sl@0
    39
sl@0
    40
sl@0
    41
//
sl@0
    42
//
sl@0
    43
// Implementation of CUri8
sl@0
    44
//
sl@0
    45
//
sl@0
    46
sl@0
    47
/**
sl@0
    48
	Static factory constructor. Uses two phase construction and leaves nothing on the 
sl@0
    49
	CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
sl@0
    50
	
sl@0
    51
	@since			6.0
sl@0
    52
	@param			aUri	A reference to a parsed uri object.
sl@0
    53
	@return			A pointer to the newly created CUri8 object. 
sl@0
    54
	@post			A fully constructed and initialized CUri8 object.
sl@0
    55
 */
sl@0
    56
EXPORT_C CUri8* CUri8::NewL(const TUriC8& aUri)
sl@0
    57
	{
sl@0
    58
	CUri8* self = CUri8::NewLC(aUri);
sl@0
    59
	CleanupStack::Pop(self);
sl@0
    60
	return self;
sl@0
    61
	}
sl@0
    62
sl@0
    63
/**	
sl@0
    64
	Static factory constructor. Uses two phase construction and leaves a pointer to 
sl@0
    65
	created object on the CleanupStack. Creates a uri object which is a copy of the 
sl@0
    66
	input parameter aUri.
sl@0
    67
	
sl@0
    68
	@since			6.0
sl@0
    69
	@param			aUri	A reference to a parsed uri object.
sl@0
    70
	@return			A pointer to the newly created CUri8 object. 
sl@0
    71
	@post			A fully constructed and initialized CUri8 object.
sl@0
    72
 */
sl@0
    73
EXPORT_C CUri8* CUri8::NewLC(const TUriC8& aUri)
sl@0
    74
	{
sl@0
    75
	CUri8* self = new (ELeave) CUri8(aUri);
sl@0
    76
	CleanupStack::PushL(self);
sl@0
    77
	self->ConstructL();
sl@0
    78
	return self;
sl@0
    79
	}
sl@0
    80
	
sl@0
    81
/**	
sl@0
    82
	Static factory constructor. Uses two phase construction and leaves nothing on the 
sl@0
    83
	CleanupStack. Creates a uri object which is empty.
sl@0
    84
	
sl@0
    85
	@since			6.0
sl@0
    86
	@return			A pointer to the newly created CUri8 object. 
sl@0
    87
	@post			A fully constructed and initialized CUri8 object.
sl@0
    88
 */
sl@0
    89
EXPORT_C CUri8* CUri8::NewL()
sl@0
    90
	{
sl@0
    91
	CUri8* self = CUri8::NewLC();
sl@0
    92
	CleanupStack::Pop(self);
sl@0
    93
	return self;
sl@0
    94
	}
sl@0
    95
sl@0
    96
/**
sl@0
    97
	Static factory constructor. Uses two phase construction and leaves a pointer to created 
sl@0
    98
	object on the CleanupStack. Creates a uri object which is empty.
sl@0
    99
	
sl@0
   100
	@since			6.0
sl@0
   101
	@return			A pointer to the newly created CUri8 object. 
sl@0
   102
	@post			A fully constructed and initialized CUri8 object.
sl@0
   103
 */
sl@0
   104
EXPORT_C CUri8* CUri8::NewLC()
sl@0
   105
	{
sl@0
   106
	CUri8* self = new (ELeave) CUri8(TUriC8());
sl@0
   107
	CleanupStack::PushL(self);
sl@0
   108
	self->ConstructL();
sl@0
   109
	return self;
sl@0
   110
	}
sl@0
   111
sl@0
   112
/**	
sl@0
   113
	Static factory constructor. This creates a CUri8 object that is an absolute uri resulting 
sl@0
   114
	from a reference uri being resolved against a base uri.
sl@0
   115
	
sl@0
   116
	@warning		Ownership of created CUri8 object is transferred to the caller.
sl@0
   117
	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
sl@0
   118
	@since			6.0
sl@0
   119
	@param			aBaseUri	A referece to the parsed base uri.
sl@0
   120
	@param			aRefUri		A referece to the parsed reference uri.
sl@0
   121
	@return			A pointer to the newly created CUri8 object.
sl@0
   122
	@pre 			The base uri must have an absolute or empty path, otherwise will leave
sl@0
   123
	with KUriErrBadBasePath.
sl@0
   124
	@post			A fully constructed and initialized CUri8 object.
sl@0
   125
 */
sl@0
   126
EXPORT_C CUri8* CUri8::ResolveL(const TUriC8& aBaseUri, const TUriC8& aRefUri)
sl@0
   127
	{
sl@0
   128
	// Check for a base Uri
sl@0
   129
	if( aBaseUri.UriDes().Compare(KNullDesC8) == 0 )
sl@0
   130
		{
sl@0
   131
		// Empty base Uri - resolved Uri is the reference Uri
sl@0
   132
		return NewL(aRefUri);
sl@0
   133
		}
sl@0
   134
	// See if ref has scheme and it is the same as base Uri
sl@0
   135
	if( aRefUri.IsPresent(EUriScheme) && (aRefUri.Compare(aBaseUri, EUriScheme) != 0) )
sl@0
   136
		{
sl@0
   137
		// Ref has a scheme different to base Uri's - it is an absolute Uri
sl@0
   138
		return NewL(aRefUri);
sl@0
   139
		}
sl@0
   140
	// Check for presence of components
sl@0
   141
	TBool useBaseQuery = EFalse;
sl@0
   142
	HBufC8* resolvedPath = FormResolvedPathLC<HBufC8>(aBaseUri, aRefUri, useBaseQuery);
sl@0
   143
sl@0
   144
	//Removes dot segemnts in Resolved uri as specified in RFC3986 section 5.2.
sl@0
   145
	RemoveExtraneousDotSegmentsL(resolvedPath);
sl@0
   146
	
sl@0
   147
	// Put the Uri together
sl@0
   148
	TUriC8 uri;
sl@0
   149
	FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
sl@0
   150
sl@0
   151
	// Create the resolved Uri and cleanup
sl@0
   152
	CUri8* resolvedUri = NewL(uri);
sl@0
   153
	CleanupStack::PopAndDestroy(resolvedPath);
sl@0
   154
sl@0
   155
	return resolvedUri;
sl@0
   156
	}
sl@0
   157
sl@0
   158
/**	
sl@0
   159
	Destructor.
sl@0
   160
	
sl@0
   161
	@since			6.0
sl@0
   162
 */
sl@0
   163
EXPORT_C CUri8::~CUri8()
sl@0
   164
	{
sl@0
   165
	delete iUriBuf;
sl@0
   166
	}
sl@0
   167
sl@0
   168
/**	
sl@0
   169
	Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC8.
sl@0
   170
	
sl@0
   171
	@since			6.0
sl@0
   172
	@return			A const reference to the parsed uri object.
sl@0
   173
 */
sl@0
   174
EXPORT_C const TUriC8& CUri8::Uri() const
sl@0
   175
	{
sl@0
   176
	return iUri;
sl@0
   177
	}
sl@0
   178
sl@0
   179
/**	
sl@0
   180
	Intended Usage	:	Sets the specified component in the uri. The component is set to the value 
sl@0
   181
	given in the argument aData. If the specified component already exists  then it is replaced 
sl@0
   182
	with the new value.
sl@0
   183
	
sl@0
   184
	@warning		The userinfo and port components can only be set if the host component
sl@0
   185
	is present. Setting these components without a host component present will have no 
sl@0
   186
	effect on the uri.
sl@0
   187
	@since			6.0
sl@0
   188
	@param			aData		A descriptor pointer to the new value for the uri component.
sl@0
   189
	@param			aComponent	An enum specifying the component to be set.
sl@0
   190
	@pre 			Object is fully constructed.
sl@0
   191
	@post			The uri has the specified component set to the new value.
sl@0
   192
	@Leave          KErrArgument  If aComponent goes out of range.
sl@0
   193
 */
sl@0
   194
EXPORT_C void CUri8::SetComponentL(const TDesC8& aData, TUriComponent aComponent)
sl@0
   195
	{
sl@0
   196
	// Update the appropriate component table entry
sl@0
   197
	iUri.iComponent[aComponent].Set(aData);
sl@0
   198
sl@0
   199
	// Copy to the buffer by forming the uri
sl@0
   200
	FormUriL();
sl@0
   201
	}
sl@0
   202
sl@0
   203
/**	
sl@0
   204
	Removes the specified component from the uri. If the component does not exist then this function 
sl@0
   205
	does nothing.
sl@0
   206
	
sl@0
   207
	@warning		If host is removed, then userinfo and port components will also
sl@0
   208
	be removed.
sl@0
   209
	@since			6.0
sl@0
   210
	@param			aComponent	An enum specifying the component to be removed.
sl@0
   211
	@pre 			Object is fully constructed.
sl@0
   212
	@post			The uri is updated to exclude the specified component.
sl@0
   213
 */
sl@0
   214
EXPORT_C void CUri8::RemoveComponentL(TUriComponent aComponent)
sl@0
   215
	{
sl@0
   216
	if( iUri.IsPresent(aComponent) )
sl@0
   217
		{
sl@0
   218
		// Remove the component - set pointer to NULL and length to zero
sl@0
   219
		iUri.iComponent[aComponent].Set(NULL,0);
sl@0
   220
sl@0
   221
		// Re-form buffer and component table
sl@0
   222
		FormUriL();
sl@0
   223
		}
sl@0
   224
	}
sl@0
   225
sl@0
   226
/**	
sl@0
   227
	Constructor. First phase of two-phase construction method. Does	non-allocating construction.
sl@0
   228
	
sl@0
   229
	@since			6.0
sl@0
   230
	@param			aUri	The parsed uri component information from which to create 
sl@0
   231
	the uri.
sl@0
   232
*/
sl@0
   233
CUri8::CUri8(const TUriC8& aUri)
sl@0
   234
: CBase(), iUri(aUri)
sl@0
   235
	{
sl@0
   236
	}
sl@0
   237
sl@0
   238
/**	
sl@0
   239
	Second phase of two-phase construction method. Does any allocations required to fully construct 
sl@0
   240
	the object.
sl@0
   241
	
sl@0
   242
	@since			6.0
sl@0
   243
	@pre 			First phase of construction is complete.
sl@0
   244
	@post			The object is fully constructed and initialized.
sl@0
   245
 */
sl@0
   246
void CUri8::ConstructL()
sl@0
   247
	{
sl@0
   248
	// Create the HBufC
sl@0
   249
	FormUriL();
sl@0
   250
	}
sl@0
   251
sl@0
   252
/**	
sl@0
   253
	Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri 
sl@0
   254
	is changed to refer to the copy.
sl@0
   255
	
sl@0
   256
	@since			6.0
sl@0
   257
	@pre 			The parsed uri information is set.
sl@0
   258
	@post			The uri buffer is updated with the parsed uri information.
sl@0
   259
 */
sl@0
   260
void CUri8::FormUriL()
sl@0
   261
	{
sl@0
   262
	TBool isIPv6Host;
sl@0
   263
sl@0
   264
	// Calculate length of of the Uri
sl@0
   265
	TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
sl@0
   266
sl@0
   267
	// Create a temporary buffer and descriptor pointer to it
sl@0
   268
	HBufC8* buf = HBufC8::NewL(length);
sl@0
   269
	TPtr8 uri = buf->Des();
sl@0
   270
sl@0
   271
	// Create the uri, updating the internal uri object
sl@0
   272
	DoFormUri(uri, iUri.iComponent, isIPv6Host);
sl@0
   273
sl@0
   274
	// Update the internal buffer and descriptor pointer
sl@0
   275
	delete iUriBuf;
sl@0
   276
	iUriBuf = buf;
sl@0
   277
	iUri.iUriDes.Set(iUriBuf->Des());
sl@0
   278
	}
sl@0
   279
sl@0
   280
//
sl@0
   281
//
sl@0
   282
// Implementation of CUri16
sl@0
   283
//
sl@0
   284
//
sl@0
   285
sl@0
   286
/**	
sl@0
   287
	Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack. 
sl@0
   288
	Creates a uri object which is a copy of the input parameter aUri.
sl@0
   289
	
sl@0
   290
	@deprecated Deprecated in 9.1
sl@0
   291
	@since			6.0
sl@0
   292
	@param			aUri	A reference to a parsed uri object.
sl@0
   293
	@return			A pointer to the newly created CUri16 object. 
sl@0
   294
	@post			A fully constructed and initialized CUri16 object.
sl@0
   295
 */
sl@0
   296
EXPORT_C CUri16* CUri16::NewL(const TUriC16& aUri)
sl@0
   297
	{
sl@0
   298
	CUri16* self = CUri16::NewLC(aUri);
sl@0
   299
	CleanupStack::Pop(self);
sl@0
   300
	return self;
sl@0
   301
	}
sl@0
   302
sl@0
   303
/**	
sl@0
   304
	Static factory constructor. Uses two phase construction and leaves a pointer to created object on 
sl@0
   305
	the CleanupStack. Creates a uri object which is a copy of the input parameter aUri.
sl@0
   306
	
sl@0
   307
	@since			6.0
sl@0
   308
	@deprecated Deprecated in 9.1
sl@0
   309
	@param			aUri	A reference to a parsed uri object.
sl@0
   310
	@return			A pointer to the newly created CUri16 object. 
sl@0
   311
	@post			A fully constructed and initialized CUri16 object.
sl@0
   312
 */
sl@0
   313
EXPORT_C CUri16* CUri16::NewLC(const TUriC16& aUri)
sl@0
   314
	{
sl@0
   315
	CUri16* self = new (ELeave) CUri16(aUri);
sl@0
   316
	CleanupStack::PushL(self);
sl@0
   317
	self->ConstructL();
sl@0
   318
	return self;
sl@0
   319
	}
sl@0
   320
sl@0
   321
/**
sl@0
   322
	Static factory constructor. Uses two phase construction and leaves nothing on the CleanupStack. 
sl@0
   323
	Creates a uri object which is empty.
sl@0
   324
	
sl@0
   325
	@since			6.0
sl@0
   326
	@deprecated Deprecated in 9.1
sl@0
   327
	@return			A pointer to the newly created CUri16 object. 
sl@0
   328
	@post			A fully constructed and initialized CUri16 object.
sl@0
   329
 */
sl@0
   330
EXPORT_C CUri16* CUri16::NewL()
sl@0
   331
	{
sl@0
   332
	CUri16* self = CUri16::NewLC();
sl@0
   333
	CleanupStack::Pop(self);
sl@0
   334
	return self;
sl@0
   335
	}
sl@0
   336
sl@0
   337
/**
sl@0
   338
	Static factory constructor. Uses two phase construction and leaves a pointer to created object on 
sl@0
   339
	the CleanupStack. Creates a uri object which is empty.
sl@0
   340
	
sl@0
   341
	@since			6.0
sl@0
   342
	@deprecated Deprecated in 9.1
sl@0
   343
	@return			A pointer to the newly created CUri16 object. 
sl@0
   344
	@post			A fully constructed and initialized CUri16 object.
sl@0
   345
 */
sl@0
   346
EXPORT_C CUri16* CUri16::NewLC()
sl@0
   347
	{
sl@0
   348
	CUri16* self = new (ELeave) CUri16(TUriC16());
sl@0
   349
	CleanupStack::PushL(self);
sl@0
   350
	self->ConstructL();
sl@0
   351
	return self;
sl@0
   352
	}
sl@0
   353
sl@0
   354
/**	
sl@0
   355
	Static factory constructor. This creates a CUri16 object that is an absolute uri resulting from a 
sl@0
   356
	reference uri being resolved against a base uri.
sl@0
   357
	
sl@0
   358
	@warning		Ownership of created CUri16 object is transferred to caller.
sl@0
   359
	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
sl@0
   360
	@since			6.0
sl@0
   361
	@deprecated Deprecated in 9.1
sl@0
   362
	@param			aBaseUri	A referece to the parsed base uri.
sl@0
   363
	@param			aRefUri		A referece to the parsed reference uri.
sl@0
   364
	@return			A pointer to the newly created CUri16 object.
sl@0
   365
	@pre 			The base uri must have an absolute or empty path, otherwise will leave
sl@0
   366
	with KUriErrBadBasePath.
sl@0
   367
	@post			A fully constructed and initialized CUri16 object.
sl@0
   368
 */
sl@0
   369
EXPORT_C CUri16* CUri16::ResolveL(const TUriC16& aBaseUri, const TUriC16& aRefUri)
sl@0
   370
	{
sl@0
   371
	// Check for a base Uri
sl@0
   372
	if( aBaseUri.UriDes().Compare(KNullDesC16) == 0 )
sl@0
   373
		{
sl@0
   374
		// Empty base Uri - resolved Uri is the reference Uri
sl@0
   375
		return NewL(aRefUri);
sl@0
   376
		}
sl@0
   377
	// See if ref has scheme and it is the same as base Uri
sl@0
   378
	if( aRefUri.IsPresent(EUriScheme) && aRefUri.Compare(aBaseUri, EUriScheme) != 0 )
sl@0
   379
		{
sl@0
   380
		// Ref has a scheme different to base Uri's - it is an absolute Uri
sl@0
   381
		return NewL(aRefUri);
sl@0
   382
		}
sl@0
   383
	// Check for presence of components
sl@0
   384
	TBool useBaseQuery = EFalse;
sl@0
   385
	HBufC16* resolvedPath = FormResolvedPathLC<HBufC16>(aBaseUri, aRefUri, useBaseQuery);
sl@0
   386
sl@0
   387
	// Put the Uri together
sl@0
   388
	TUriC16 uri;
sl@0
   389
	FormResolvedUri(uri.iComponent, aBaseUri, aRefUri, resolvedPath, useBaseQuery);
sl@0
   390
sl@0
   391
	// Create the resolved Uri and cleanup
sl@0
   392
	CUri16* resolvedUri = NewL(uri);
sl@0
   393
	CleanupStack::PopAndDestroy(resolvedPath);
sl@0
   394
sl@0
   395
	return resolvedUri;
sl@0
   396
	}
sl@0
   397
sl@0
   398
/**	
sl@0
   399
	Destructor.
sl@0
   400
	
sl@0
   401
	@since			6.0
sl@0
   402
	@deprecated Deprecated in 9.1
sl@0
   403
 */
sl@0
   404
EXPORT_C CUri16::~CUri16()
sl@0
   405
	{
sl@0
   406
	delete iUriBuf;
sl@0
   407
	}
sl@0
   408
sl@0
   409
/**	
sl@0
   410
	Provides a reference to the parsed uri. Allows access to the non-modifying API for TUriC16.
sl@0
   411
	
sl@0
   412
	@since			6.0
sl@0
   413
	@deprecated Deprecated in 9.1
sl@0
   414
	@return			A const reference to the parsed uri object.
sl@0
   415
 */
sl@0
   416
EXPORT_C const TUriC16& CUri16::Uri() const
sl@0
   417
	{
sl@0
   418
	return iUri;
sl@0
   419
	}
sl@0
   420
sl@0
   421
/**
sl@0
   422
	Sets the specified component in the uri. The component is set to the value given in the argument 
sl@0
   423
	aData. If the specified component already exists then it is replaced with the new value.
sl@0
   424
	
sl@0
   425
	@warning		The userinfo and port components can only be set if the host component
sl@0
   426
	is present. Setting these components without a host component present will have no 
sl@0
   427
	effect on the uri.
sl@0
   428
	@since			6.0
sl@0
   429
	@deprecated Deprecated in 9.1
sl@0
   430
	@param			aData		A descriptor pointer to the new value for the uri component.
sl@0
   431
	@param			aComponent	An enum specifying the component to be set.
sl@0
   432
	@pre 			Object is fully constructed.
sl@0
   433
	@post			The uri has the specified component set to the new value.
sl@0
   434
	@Leave          KErrArgument  If aComponent goes out of range.
sl@0
   435
 */
sl@0
   436
EXPORT_C void CUri16::SetComponentL(const TDesC16& aData, TUriComponent aComponent)
sl@0
   437
	{
sl@0
   438
	// Update the appropriate component table entry
sl@0
   439
	iUri.iComponent[aComponent].Set(aData);
sl@0
   440
sl@0
   441
	// Copy to the buffer by forming the uri
sl@0
   442
	FormUriL();
sl@0
   443
	}
sl@0
   444
sl@0
   445
/**
sl@0
   446
	Removes the specified component from the uri. If the component does not exist then this function 
sl@0
   447
	does nothing.
sl@0
   448
	
sl@0
   449
	@warning		If host is removed, then userinfo and port components will also
sl@0
   450
	be removed.
sl@0
   451
	@since			6.0
sl@0
   452
	@deprecated Deprecated in 9.1
sl@0
   453
	@param			aComponent	An enum specifying the component to be removed.
sl@0
   454
	@pre 			Object is fully constructed.
sl@0
   455
	@post			The uri is updated to exclude the specified component.
sl@0
   456
 */
sl@0
   457
EXPORT_C void CUri16::RemoveComponentL(TUriComponent aComponent)
sl@0
   458
	{
sl@0
   459
	if( iUri.IsPresent(aComponent) )
sl@0
   460
		{
sl@0
   461
		// Remove the component - set pointer to NULL and length to zero
sl@0
   462
		iUri.iComponent[aComponent].Set(NULL,0);
sl@0
   463
sl@0
   464
		// Re-form buffer and component table
sl@0
   465
		FormUriL();
sl@0
   466
		}
sl@0
   467
	}
sl@0
   468
sl@0
   469
/**
sl@0
   470
	Constructor. First phase of two-phase construction method. Does	non-allocating construction.
sl@0
   471
	
sl@0
   472
	@since			6.0
sl@0
   473
	@param			aUri	The parsed uri component information from which to create
sl@0
   474
	the uri.
sl@0
   475
 */
sl@0
   476
sl@0
   477
CUri16::CUri16(const TUriC16& aUri)
sl@0
   478
: CBase(), iUri(aUri)
sl@0
   479
	{
sl@0
   480
	}
sl@0
   481
sl@0
   482
/**
sl@0
   483
	Second phase of two-phase construction method. Does any allocations required to fully construct 
sl@0
   484
	the object.
sl@0
   485
	
sl@0
   486
	@since			6.0
sl@0
   487
	@pre 			First phase of construction is complete.
sl@0
   488
	@post			The object is fully constructed and initialized.
sl@0
   489
 */
sl@0
   490
void CUri16::ConstructL()
sl@0
   491
	{
sl@0
   492
	// Create the HBufC
sl@0
   493
	FormUriL();
sl@0
   494
	}
sl@0
   495
sl@0
   496
/**
sl@0
   497
	Forms the uri from the parsed uri information. A copy of the parsed uri is created. The parsed uri 
sl@0
   498
	is changed to refer to the copy.
sl@0
   499
	
sl@0
   500
	@since			6.0
sl@0
   501
	@pre 			The parsed uri information is set.
sl@0
   502
	@post			The uri buffer is updated with the parsed uri information.
sl@0
   503
 */
sl@0
   504
void CUri16::FormUriL()
sl@0
   505
	{
sl@0
   506
	TBool isIPv6Host;
sl@0
   507
sl@0
   508
	// Calculate length of of the Uri
sl@0
   509
	TInt length = CalculateUriLength(iUri.iComponent, isIPv6Host);
sl@0
   510
sl@0
   511
	// Create a temporary buffer and descriptor pointer to it
sl@0
   512
	HBufC16* buf = HBufC16::NewL(length);
sl@0
   513
	TPtr16 uri = buf->Des();
sl@0
   514
sl@0
   515
	// Create the uri, updating the internal uri object
sl@0
   516
	DoFormUri(uri, iUri.iComponent, isIPv6Host);
sl@0
   517
sl@0
   518
	// Update the internal buffer and descriptor pointer
sl@0
   519
	delete iUriBuf;
sl@0
   520
	iUriBuf = buf;
sl@0
   521
	iUri.iUriDes.Set(iUriBuf->Des());
sl@0
   522
	}
sl@0
   523
sl@0
   524
//
sl@0
   525
//
sl@0
   526
// Implementation of templated LOCAL functions
sl@0
   527
//
sl@0
   528
//
sl@0
   529
sl@0
   530
/**
sl@0
   531
	Calculates the length of the uri from a list of the components.
sl@0
   532
	
sl@0
   533
	@since			6.0
sl@0
   534
	@param			aComponent	The array of descriptor pointers to the uri 
sl@0
   535
					components.
sl@0
   536
	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
sl@0
   537
	@return			The length of the uri including the required delimiters.	
sl@0
   538
*/
sl@0
   539
template<class TPtrCType>
sl@0
   540
TInt CalculateUriLength(const TPtrCType aComponent[], TBool& aIsIPv6Host)
sl@0
   541
	{
sl@0
   542
	TBool noAuthority = ETrue;
sl@0
   543
	TInt length=0;
sl@0
   544
	aIsIPv6Host=EFalse;
sl@0
   545
	for( TInt i=0; i<EUriMaxComponents; ++i )
sl@0
   546
		{
sl@0
   547
		if( aComponent[i].Ptr() )
sl@0
   548
			{
sl@0
   549
			length += aComponent[i].Length();
sl@0
   550
			if( noAuthority && (i==EUriUserinfo || i==EUriHost || i==EUriPort) )
sl@0
   551
				{
sl@0
   552
				// There's an authority part...
sl@0
   553
				noAuthority = EFalse;
sl@0
   554
				}
sl@0
   555
			// Need to make space for a delimiter if not path or host
sl@0
   556
			if( i!=EUriHost && i!=EUriPath )
sl@0
   557
				++length;		
sl@0
   558
			
sl@0
   559
			// If it's an IPv6 hostname, need extra space for []
sl@0
   560
			if(i==EUriHost && (UriUtils::HostType(aComponent[i])==UriUtils::EIPv6Host))
sl@0
   561
				{
sl@0
   562
				length+=2;				
sl@0
   563
				aIsIPv6Host=ETrue;
sl@0
   564
				}
sl@0
   565
			}
sl@0
   566
		}
sl@0
   567
	if( !noAuthority && IsNetworkScheme(aComponent[EUriScheme]))
sl@0
   568
		{
sl@0
   569
		// Make space for authority delimiter
sl@0
   570
		length += KUriNetworkAuthorityDelimiterLength;
sl@0
   571
		}
sl@0
   572
	return length;
sl@0
   573
	}
sl@0
   574
sl@0
   575
/**
sl@0
   576
	Templated function to form a uri. The output argument aUri points to a descriptor 
sl@0
   577
	buffer large enough to hold the uri. The new uri component information is given by 
sl@0
   578
	the input/output argument aComponent. For each uri component that exists in aComponent,
sl@0
   579
	that component and its appropriate delimiters are appended to aUri. Then the components 
sl@0
   580
	in aComponent are updated to refer to the copies versions in aUri.
sl@0
   581
						
sl@0
   582
	@since			6.0
sl@0
   583
	@param			aUri		The descriptor pointer to buffer to be appended.
sl@0
   584
	@param			aComponent	The array of descriptor pointers to be copied and 
sl@0
   585
					then updated.
sl@0
   586
	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
sl@0
   587
	@pre 			The buffer pointed to by aUri should be large enough to have the uri 
sl@0
   588
					components given in aNewComponent copied into it, as well as the required delimiters.
sl@0
   589
					This can be obtained using CalculateUriLength().
sl@0
   590
	@post			The uri buffer pointed to by aUri will have a copy of the uri defined 
sl@0
   591
					in aComponent, and then aComponent will refer to the copies of these components in aUri.
sl@0
   592
*/
sl@0
   593
template<class TPtrType, class TPtrCType>
sl@0
   594
void DoFormUri(TPtrType& aUri, TPtrCType aComponent[], TBool& aIsIPv6Host)
sl@0
   595
	{
sl@0
   596
	TBool isNetworkScheme = ETrue;
sl@0
   597
	if( aComponent[EUriScheme].Ptr() )
sl@0
   598
		{
sl@0
   599
		// Update the scheme
sl@0
   600
		SetScheme(aUri, aComponent[EUriScheme]);
sl@0
   601
		isNetworkScheme = IsNetworkScheme(aComponent[EUriScheme]);
sl@0
   602
		}
sl@0
   603
	if( aComponent[EUriHost].Ptr() )
sl@0
   604
		{
sl@0
   605
		// Update the authority - only needed if there is a host; update userinfo, host and port
sl@0
   606
		SetAuthority(aUri, aComponent[EUriUserinfo], aComponent[EUriHost], aComponent[EUriPort], aIsIPv6Host, isNetworkScheme);
sl@0
   607
		}
sl@0
   608
	else
sl@0
   609
		{
sl@0
   610
		// Ensure that there is no userinfo or port components if there is no host 
sl@0
   611
		// - set pointer to NULL and length to zero
sl@0
   612
		aComponent[EUriUserinfo].Set(NULL,0);
sl@0
   613
		aComponent[EUriPort].Set(NULL,0);
sl@0
   614
		}
sl@0
   615
	if( aComponent[EUriPath].Ptr() )
sl@0
   616
		{
sl@0
   617
		// Update the path
sl@0
   618
		SetPath(aUri, aComponent[EUriPath]);
sl@0
   619
		}
sl@0
   620
	if( aComponent[EUriQuery].Ptr() )
sl@0
   621
		{
sl@0
   622
		// Update the query
sl@0
   623
		SetQuery(aUri, aComponent[EUriQuery]);
sl@0
   624
		}
sl@0
   625
	if( aComponent[EUriFragment].Ptr() )
sl@0
   626
		{
sl@0
   627
		// Update the fragment
sl@0
   628
		SetFragment(aUri, aComponent[EUriFragment]);
sl@0
   629
		}
sl@0
   630
	}
sl@0
   631
sl@0
   632
/**
sl@0
   633
	Templated function to set the scheme in a uri. The output argument aUri points to the descriptor 
sl@0
   634
	buffer into which aScheme will be copied.The argument aScheme is then updated to point to the 
sl@0
   635
	copied version in aUri.
sl@0
   636
						
sl@0
   637
	@warning		This function will panic with KUriErrBufferOverflow if there is not
sl@0
   638
					enough space in the descriptor to append the scheme and the required delimiter.
sl@0
   639
	@since			6.0
sl@0
   640
	@param			aUri	The descriptor pointer to buffer to be appended.
sl@0
   641
	@param			aScheme	The descriptor pointer to the scheme component to be copied 
sl@0
   642
					and then updated.
sl@0
   643
	@pre 			The buffer pointed to by aUri should be large enough to have aNewScheme
sl@0
   644
					appended to it with the required delimiter. This can be obtained using CalculateUriLength().
sl@0
   645
	@post			The uri buffer now includes a copy of aScheme and aScheme points to the 
sl@0
   646
					copy of the scheme component in aUri.
sl@0
   647
*/
sl@0
   648
template<class TPtrType, class TPtrCType>
sl@0
   649
void SetScheme(TPtrType& aUri, TPtrCType& aScheme)
sl@0
   650
	{
sl@0
   651
	__ASSERT_DEBUG(aUri.Length() + aScheme.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   652
sl@0
   653
	// Append the scheme and delimiter
sl@0
   654
	aUri.Append(aScheme);
sl@0
   655
	aUri.Append(KSchemeDelimiter);
sl@0
   656
sl@0
   657
	// Update the component table to use the copy
sl@0
   658
	aScheme.Set(aUri.Left(aScheme.Length()));
sl@0
   659
	}
sl@0
   660
	
sl@0
   661
/**
sl@0
   662
	Templated function to set the authority in a uri. The output argument aUri points to the descriptor 
sl@0
   663
	buffer into which aUserinfo, aHost and aPort will be copied. The arguments aUserinfo, aHost and aPort 
sl@0
   664
	are updated to point to the copied versions in aUri.
sl@0
   665
						
sl@0
   666
	@warning		This function will panic with KUriErrBufferOverflow if there 
sl@0
   667
					is not enough space in the descriptor to append the components and any required 
sl@0
   668
					delimiters. 
sl@0
   669
	@since			6.0
sl@0
   670
	@param			aUri		The descriptor pointer to buffer to be appended.
sl@0
   671
	@param			aUserinfo	The descriptor pointer to the userinfo component to 
sl@0
   672
					be copied and then updated.
sl@0
   673
	@param			aHost		The descriptor pointer to the host component to 
sl@0
   674
					be copied and then updated.
sl@0
   675
	@param			aPort		The descriptor pointer to the port component to 
sl@0
   676
					be copied and then updated.
sl@0
   677
	@param			aIsIPv6Host	ETrue if an IPv6 format host is used
sl@0
   678
	@param			aUseNetworkDelimiter EFalse if this is a SIP scheme otherwise ETrue
sl@0
   679
	@pre 			The buffer pointed to by aUri should be large enough to have 
sl@0
   680
					aUserinfo, aHost and aPort appended to it with the required delimiters.
sl@0
   681
					This can be obtained using CalculateUriLength().
sl@0
   682
	@post			The uri buffer now includes a copy of aUserinfo, aHost and
sl@0
   683
					aPort, and aUserinfo, aHost and aPort will refer to the copies versions in aUri.
sl@0
   684
*/
sl@0
   685
template<class TPtrType, class TPtrCType>
sl@0
   686
void SetAuthority(TPtrType& aUri, TPtrCType& aUserinfo, TPtrCType& aHost, TPtrCType& aPort, TBool& aIsIPv6Host, TBool aUseNetworkDelimiter)
sl@0
   687
	{
sl@0
   688
	__ASSERT_DEBUG(aUri.Length() + aHost.Length() + (aUseNetworkDelimiter ? KUriNetworkAuthorityDelimiterLength:0) <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   689
	
sl@0
   690
	if (aUseNetworkDelimiter)
sl@0
   691
		{
sl@0
   692
		// If a network scheme append authority delimiter (TWO slash delimiters!)
sl@0
   693
		aUri.Append(KSlashDelimiter);
sl@0
   694
		aUri.Append(KSlashDelimiter);
sl@0
   695
		}
sl@0
   696
sl@0
   697
	// Check for userinfo
sl@0
   698
	if( aUserinfo.Ptr() )
sl@0
   699
		{
sl@0
   700
		__ASSERT_DEBUG(aUri.Length() + aUserinfo.Length() + aHost.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   701
sl@0
   702
		// Append userinfo and update the component table to use copy
sl@0
   703
		aUri.Append(aUserinfo);
sl@0
   704
		aUserinfo.Set(aUri.Right(aUserinfo.Length()));
sl@0
   705
sl@0
   706
		// Append delimiter
sl@0
   707
		aUri.Append(KUserinfoDelimiter);
sl@0
   708
		}
sl@0
   709
	// There's always a host - append and update the component table to use the copy
sl@0
   710
	
sl@0
   711
	// Check if it's an IPv6 address
sl@0
   712
	if ( aIsIPv6Host )
sl@0
   713
		{
sl@0
   714
		aUri.Append(KIPv6UriOpenBrace); 
sl@0
   715
		aUri.Append(aHost);
sl@0
   716
		aUri.Append(KIPv6UriCloseBrace);
sl@0
   717
		// Dont include the braces in the host
sl@0
   718
		// Position = (length of uri - length of host) - length of end brace
sl@0
   719
		aHost.Set( aUri.Mid((aUri.Length()-aHost.Length())-1, aHost.Length()) );
sl@0
   720
		}
sl@0
   721
	else
sl@0
   722
		{
sl@0
   723
		aUri.Append(aHost);
sl@0
   724
		aHost.Set(aUri.Right(aHost.Length()));
sl@0
   725
		}
sl@0
   726
	
sl@0
   727
	// Check for a port
sl@0
   728
	if( aPort.Ptr() )
sl@0
   729
		{
sl@0
   730
		__ASSERT_DEBUG(aUri.Length() + aPort.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   731
				   
sl@0
   732
		// Append delimiter
sl@0
   733
		aUri.Append(KPortDelimiter);
sl@0
   734
	
sl@0
   735
		// Append port and update the component table to use copy
sl@0
   736
		aUri.Append(aPort);
sl@0
   737
		aPort.Set(aUri.Right(aPort.Length()));
sl@0
   738
		}
sl@0
   739
	}
sl@0
   740
/**
sl@0
   741
	Templated function to set the path in a uri. The output argument aUri points to the descriptor 
sl@0
   742
	buffer into which aPath will be copied.The argument aPath is then updated to point to the copied 
sl@0
   743
	version in aUri.
sl@0
   744
						
sl@0
   745
	@warning		This function will panic with KUriErrBufferOverflow if there 
sl@0
   746
					is not enough space in the descriptor to append the path.
sl@0
   747
	@since			6.0
sl@0
   748
	@param			aUri	The descriptor pointer to buffer to be appended.
sl@0
   749
	@param			aPath	The descriptor pointer to the path component to be copied 
sl@0
   750
					and then updated.
sl@0
   751
	@pre 			The buffer pointed to by aUri should be large enough to have 
sl@0
   752
					aPath appended to it. This can be obtained using CalculateUriLength().
sl@0
   753
	@post			The uri buffer now includes a copy of aPath and aPath points to the 
sl@0
   754
					copy of the path component in aUri.
sl@0
   755
*/
sl@0
   756
template<class TPtrType, class TPtrCType>
sl@0
   757
void SetPath(TPtrType& aUri, TPtrCType& aPath)
sl@0
   758
	{
sl@0
   759
	__ASSERT_DEBUG(aUri.Length() + aPath.Length() <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   760
sl@0
   761
	// Append the path
sl@0
   762
	aUri.Append(aPath);
sl@0
   763
sl@0
   764
	// Update the component table
sl@0
   765
	aPath.Set(aUri.Right(aPath.Length()));
sl@0
   766
	}
sl@0
   767
sl@0
   768
/**
sl@0
   769
	Templated function to set the query in a uri. The output argument aUri points to the descriptor 
sl@0
   770
	buffer into which aQuery will be copied. The argument aQuery is then updated to point to the copied 
sl@0
   771
	version in aUri.
sl@0
   772
						
sl@0
   773
	@warning		This function will panic with KUriErrBufferOverflow if there 
sl@0
   774
					is not enough space in the descriptor to append the query and the delimiter.
sl@0
   775
	@since			6.0
sl@0
   776
	@param			aUri	The descriptor pointer to buffer to be appended.
sl@0
   777
	@param			aQuery	The descriptor pointer to the query component to be copied 
sl@0
   778
					and then updated.
sl@0
   779
	@pre 			The buffer pointed to by aUri should be large enough to have 
sl@0
   780
					aQuery appended to it. This can be obtained using CalculateUriLength().
sl@0
   781
	@post			The uri buffer now includes a copy of aQuery and aQuery points to the 
sl@0
   782
					copy of the query component in aUri.
sl@0
   783
*/
sl@0
   784
template<class TPtrType, class TPtrCType>
sl@0
   785
void SetQuery(TPtrType& aUri, TPtrCType& aQuery)
sl@0
   786
	{
sl@0
   787
	__ASSERT_DEBUG(aUri.Length() + aQuery.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   788
sl@0
   789
	// Append delimiter and the query
sl@0
   790
	aUri.Append(KQueryDelimiter);
sl@0
   791
	aUri.Append(aQuery);
sl@0
   792
sl@0
   793
	// Update the component table
sl@0
   794
	aQuery.Set(aUri.Right(aQuery.Length()));
sl@0
   795
	}
sl@0
   796
sl@0
   797
/**
sl@0
   798
	Templated function to set the fragment in a uri. The output argument aUri points to the descriptor 
sl@0
   799
	buffer into which aFragment will be copied. The argument aFragment is then updated to point to the 
sl@0
   800
	copied version in aUri.
sl@0
   801
						
sl@0
   802
	@warning		This function will panic with KUriErrBufferOverflow if there 
sl@0
   803
					is not enough space in the descriptor to append the fragment and the delimiter.
sl@0
   804
	@since			6.0
sl@0
   805
	@param			aUri		The descriptor pointer to buffer to be appended.
sl@0
   806
	@param			aFragment	The descriptor pointer to the fragment component
sl@0
   807
					to be copied and then updated.
sl@0
   808
	@pre 			The buffer pointed to by aUri should be large enough to have 
sl@0
   809
					aFragment appended to it. This can be obtained using CalculateUriLength().
sl@0
   810
	@post			The uri buffer now includes a copy of aFragment and aFragment points 
sl@0
   811
					to the copy of the fragment component in aUri.
sl@0
   812
*/
sl@0
   813
template<class TPtrType, class TPtrCType>
sl@0
   814
void SetFragment(TPtrType& aUri, TPtrCType& aFragment)
sl@0
   815
	{
sl@0
   816
	__ASSERT_DEBUG(aUri.Length() + aFragment.Length() + 1 <= aUri.MaxLength(), User::Panic(KUriPanicCategory, KUriUtilsErrBufferOverflow));
sl@0
   817
sl@0
   818
	// Append delimiter and the fragment
sl@0
   819
	aUri.Append(KFragmentDelimiter);
sl@0
   820
	aUri.Append(aFragment);
sl@0
   821
sl@0
   822
	// Update the component table
sl@0
   823
	aFragment.Set(aUri.Right(aFragment.Length()));
sl@0
   824
	}
sl@0
   825
sl@0
   826
/**
sl@0
   827
	Forms the resolved path. Checks to see if the base query needs to be used in the resolved uri. 
sl@0
   828
	The pointer to the resolved path is left on the cleanup stack.
sl@0
   829
						
sl@0
   830
	@since			6.0
sl@0
   831
	@param			aBaseUri		The base uri.
sl@0
   832
	@param			aRefUri			The reference uri.
sl@0
   833
	@param			aUseBaseQuery	An output argument specifying whether the base
sl@0
   834
					query should be used in the resolved uri.
sl@0
   835
	@return			A pointer to a buffer that contains the resolved path.
sl@0
   836
*/
sl@0
   837
template<class HBufCType, class TUriCType>
sl@0
   838
HBufCType* FormResolvedPathLC(const TUriCType& aBaseUri, const TUriCType& aRefUri, TBool& aUseBaseQuery)
sl@0
   839
	{
sl@0
   840
	HBufCType* resolvedPath = NULL;
sl@0
   841
	if( !aRefUri.IsPresent(EUriScheme) && !aRefUri.IsPresent(EUriHost) && !aRefUri.Extract(EUriPath).Length() && !aRefUri.IsPresent(EUriQuery) )
sl@0
   842
		{
sl@0
   843
		// Ref is just a fragment
sl@0
   844
		aUseBaseQuery = ETrue;
sl@0
   845
		resolvedPath = aBaseUri.Extract(EUriPath).AllocLC();
sl@0
   846
		}
sl@0
   847
	else if( aRefUri.IsPresent(EUriHost) )
sl@0
   848
		{
sl@0
   849
		// Ref is a network path
sl@0
   850
		resolvedPath = aRefUri.Extract(EUriPath).AllocLC();
sl@0
   851
		}
sl@0
   852
	else
sl@0
   853
		{
sl@0
   854
		// Need to some path resolving...
sl@0
   855
		resolvedPath = ResolvePathsL(aBaseUri.Extract(EUriPath), aRefUri.Extract(EUriPath));
sl@0
   856
		CleanupStack::PushL(resolvedPath);
sl@0
   857
		}
sl@0
   858
	return resolvedPath;
sl@0
   859
	}
sl@0
   860
sl@0
   861
/**
sl@0
   862
	Cleans up a resolved path. This deals with occurences of '.' and '..' where these are complete 
sl@0
   863
	path segments.
sl@0
   864
						
sl@0
   865
	@since			6.0
sl@0
   866
	@param			aResolvedPath	The delimited data object that contains the 
sl@0
   867
					resolved path.
sl@0
   868
	@pre 			The input/output argument contains the path to be cleaned.
sl@0
   869
	@post			The resolved path has had all the occurences of '.' and '..' 
sl@0
   870
					processed and has been updated to contain the cleaned path.
sl@0
   871
 */
sl@0
   872
template<class TPtrCType, class CDelimitedDataBaseType>
sl@0
   873
void CleanResolvedPathL(CDelimitedDataBaseType* aResolvedPath)
sl@0
   874
	{
sl@0
   875
	// Create a modifiable path object for resolved path
sl@0
   876
	aResolvedPath->Parse();
sl@0
   877
sl@0
   878
	TBool done = EFalse;
sl@0
   879
	while( !done )
sl@0
   880
   		{
sl@0
   881
   		// Get the next segment
sl@0
   882
   		TPtrCType segment;
sl@0
   883
   		TInt more = aResolvedPath->Parser().Peek(segment);
sl@0
   884
sl@0
   885
   		if( more == KErrNotFound )
sl@0
   886
   			{
sl@0
   887
   			// No more segments - done
sl@0
   888
   			done = ETrue;
sl@0
   889
   			}
sl@0
   890
   		else if( IsParentDir(segment) )
sl@0
   891
   			{
sl@0
   892
   			// Found a '..' - remove '..' from path, and remove previous segment
sl@0
   893
			aResolvedPath->RemoveCurrentL();
sl@0
   894
			if( aResolvedPath->Parser().Dec() == KErrNotFound )
sl@0
   895
				{
sl@0
   896
				// No previous directory - put back '..' and stop
sl@0
   897
				InsertParentDirL(aResolvedPath);
sl@0
   898
				done = ETrue;
sl@0
   899
				}
sl@0
   900
			else
sl@0
   901
				{
sl@0
   902
				// Remove the parent directory
sl@0
   903
				aResolvedPath->RemoveCurrentL();
sl@0
   904
				if( aResolvedPath->Parser().Eos() )
sl@0
   905
					{
sl@0
   906
					// '..' is the last segment - add a '/' to the path (add empty segment)
sl@0
   907
					aResolvedPath->AddBackDelimiterL();
sl@0
   908
					done = ETrue;
sl@0
   909
					}
sl@0
   910
				}
sl@0
   911
			}
sl@0
   912
   		else if( IsSameDir(segment) )
sl@0
   913
   			{
sl@0
   914
   			// Found a '.' - remove -.- from the path
sl@0
   915
			aResolvedPath->RemoveCurrentL();
sl@0
   916
			if( aResolvedPath->Parser().Eos() )
sl@0
   917
				{
sl@0
   918
				// '..' is the last segment - add a '/' to the path (add empty segment)
sl@0
   919
				aResolvedPath->AddBackDelimiterL();
sl@0
   920
				done = ETrue;
sl@0
   921
				}
sl@0
   922
			}
sl@0
   923
   		else
sl@0
   924
   			{
sl@0
   925
   			// Segment wasn't '.' or '..' - parse to next segment
sl@0
   926
   			aResolvedPath->Parser().Inc();
sl@0
   927
   			}
sl@0
   928
   		}
sl@0
   929
	}
sl@0
   930
sl@0
   931
/**
sl@0
   932
	Forms the resolved uri. Sets the components for the resolved uri from those in the base uri and 
sl@0
   933
	the reference uri. The resolved path is given by the input argument aResolvedPath
sl@0
   934
						
sl@0
   935
	@since			6.0
sl@0
   936
	@param			aComponent		The array of components to be set for the resolved uri.
sl@0
   937
	@param			aBaseUri		The base uri.
sl@0
   938
	@param			aRefUri			The reference uri.
sl@0
   939
	@param			aResolvedPath	The resolved path.
sl@0
   940
	@param			aUseBaseQuery	A boolean indicating whether the base query 
sl@0
   941
					should be used.
sl@0
   942
*/
sl@0
   943
template<class TPtrCType, class TUriCType, class HBufCType>
sl@0
   944
void FormResolvedUri(TPtrCType aComponent[], const TUriCType& aBaseUri, const TUriCType& aRefUri, const HBufCType* aResolvedPath, TBool aUseBaseQuery)
sl@0
   945
	{
sl@0
   946
	// Scheme...
sl@0
   947
	if( aBaseUri.IsPresent(EUriScheme) )
sl@0
   948
		{
sl@0
   949
		// Use the base scheme
sl@0
   950
		aComponent[EUriScheme].Set(aBaseUri.Extract(EUriScheme));
sl@0
   951
		}
sl@0
   952
	// Authority
sl@0
   953
	if( aRefUri.IsPresent(EUriHost) )
sl@0
   954
		{
sl@0
   955
		// Use the ref host, userinfo and port - must set host first
sl@0
   956
		aComponent[EUriHost].Set(aRefUri.Extract(EUriHost));
sl@0
   957
		aComponent[EUriUserinfo].Set(aRefUri.Extract(EUriUserinfo));
sl@0
   958
		aComponent[EUriPort].Set(aRefUri.Extract(EUriPort));
sl@0
   959
		}
sl@0
   960
	else if( aBaseUri.IsPresent(EUriHost) )
sl@0
   961
		{
sl@0
   962
		// Use the base host, userinfo and port - must set host first
sl@0
   963
		aComponent[EUriHost].Set(aBaseUri.Extract(EUriHost));
sl@0
   964
		aComponent[EUriUserinfo].Set(aBaseUri.Extract(EUriUserinfo));
sl@0
   965
		aComponent[EUriPort].Set(aBaseUri.Extract(EUriPort));
sl@0
   966
		}
sl@0
   967
	// Path...
sl@0
   968
	aComponent[EUriPath].Set(*aResolvedPath);
sl@0
   969
sl@0
   970
	// Query...
sl@0
   971
	if( aUseBaseQuery && aBaseUri.IsPresent(EUriQuery) )
sl@0
   972
		{
sl@0
   973
		// Use the query from the base
sl@0
   974
		aComponent[EUriQuery].Set(aBaseUri.Extract(EUriQuery));
sl@0
   975
		}
sl@0
   976
	else if( aRefUri.IsPresent(EUriQuery) )
sl@0
   977
		{
sl@0
   978
		// Use the query from the ref
sl@0
   979
		aComponent[EUriQuery].Set(aRefUri.Extract(EUriQuery));
sl@0
   980
		}
sl@0
   981
	// Fragment
sl@0
   982
	if( aRefUri.IsPresent(EUriFragment) )
sl@0
   983
		{
sl@0
   984
		// Use the fragment from the ref
sl@0
   985
		aComponent[EUriFragment].Set(aRefUri.Extract(EUriFragment));
sl@0
   986
		}
sl@0
   987
	}
sl@0
   988
sl@0
   989
//
sl@0
   990
//
sl@0
   991
// Implemetation of LOCAL functions
sl@0
   992
//
sl@0
   993
//
sl@0
   994
sl@0
   995
/**
sl@0
   996
	Function used to resolve a base path (aBasePath) against a reference path (aRefPath),
sl@0
   997
	as described by RFC2396.
sl@0
   998
						
sl@0
   999
	@since			6.0
sl@0
  1000
	@param			aBasePath	A descriptor reference to the base path.
sl@0
  1001
	@param			aRefPath	A descriptor reference to the reference path.
sl@0
  1002
	@return			A pointer to a buffer containing the resolve path.
sl@0
  1003
	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
sl@0
  1004
*/
sl@0
  1005
HBufC8* ResolvePathsL(const TDesC8& aBasePath, const TDesC8& aRefPath)
sl@0
  1006
	{
sl@0
  1007
	TInt refLength = aRefPath.Length();
sl@0
  1008
	if( refLength && aRefPath[0] == KSlashDelimiter )
sl@0
  1009
		{
sl@0
  1010
		// Relative path is absolute - that is the resolved path
sl@0
  1011
		return aRefPath.AllocL();
sl@0
  1012
		}
sl@0
  1013
	// Ok got work to do - base path must be absolute (check 1st char) or empty
sl@0
  1014
	if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
sl@0
  1015
		{
sl@0
  1016
		// Base path not empty and not abosolute - bad base path
sl@0
  1017
		User::Leave(KUriUtilsErrBadBasePath);
sl@0
  1018
		}
sl@0
  1019
	// Create a modifiable path object for resolved path
sl@0
  1020
	CDelimitedPath8* resolvedPath = CDelimitedPath8::NewLC(aBasePath);
sl@0
  1021
sl@0
  1022
	// Check for empty ref path - use all of base path if empty
sl@0
  1023
	if( refLength )
sl@0
  1024
		{
sl@0
  1025
		// Not empty - ensure that base path's last segment is removed and add reference
sl@0
  1026
		resolvedPath->PopBackL();
sl@0
  1027
		resolvedPath->PushBackL(aRefPath);
sl@0
  1028
		}
sl@0
  1029
	// Clean up the path to resolve occurences of '..' and '.' - parser path first
sl@0
  1030
	CleanResolvedPathL<TPtrC8>(resolvedPath);
sl@0
  1031
sl@0
  1032
	// Return pointer to HBufC with path
sl@0
  1033
	HBufC8* path = resolvedPath->Parser().Des().AllocL();
sl@0
  1034
	CleanupStack::PopAndDestroy(resolvedPath);
sl@0
  1035
	return path;
sl@0
  1036
	}
sl@0
  1037
sl@0
  1038
/**
sl@0
  1039
	Function used to resolve a base path (aBasePath) against a reference path (aRefPath), 
sl@0
  1040
	as described by RFC2396.
sl@0
  1041
						
sl@0
  1042
	@since			6.0
sl@0
  1043
	@param			aBasePath	A descriptor reference to the base path.
sl@0
  1044
	@param			aRefPath	A descriptor reference to the reference path.
sl@0
  1045
	@return			A pointer to a buffer containing the resolve path.
sl@0
  1046
	@leave			KUriErrBadBasePath if the base path is not an absolute path and not empty.
sl@0
  1047
*/
sl@0
  1048
HBufC16* ResolvePathsL(const TDesC16& aBasePath, const TDesC16& aRefPath)
sl@0
  1049
	{
sl@0
  1050
	TInt refLength = aRefPath.Length();
sl@0
  1051
	if( refLength && aRefPath[0] == KSlashDelimiter )
sl@0
  1052
		{
sl@0
  1053
		// Relative path is absolute - that is the resolved path
sl@0
  1054
		return aRefPath.AllocL();
sl@0
  1055
		}
sl@0
  1056
	// Ok got work to do - base path must be absolute (check 1st char) or empty
sl@0
  1057
	if( aBasePath.Length() && aBasePath[0] != KSlashDelimiter )
sl@0
  1058
		{
sl@0
  1059
		// Base path not empty and not abosolute - bad base path
sl@0
  1060
		User::Leave(KUriUtilsErrBadBasePath);
sl@0
  1061
		}
sl@0
  1062
	// Create a modifiable path object for resolved path
sl@0
  1063
	CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(aBasePath);
sl@0
  1064
sl@0
  1065
	// Check for empty ref path - use all of base path if empty
sl@0
  1066
	if( refLength )
sl@0
  1067
		{
sl@0
  1068
		// Not empty - ensure that base path's last segment is removed and add reference
sl@0
  1069
		resolvedPath->PopBackL();
sl@0
  1070
		resolvedPath->PushBackL(aRefPath);
sl@0
  1071
		}
sl@0
  1072
	// Clean up the path to resolve occurences of '..' and '.' - parser path first
sl@0
  1073
	CleanResolvedPathL<TPtrC16>(resolvedPath);
sl@0
  1074
sl@0
  1075
	// Return pointer to HBufC with path
sl@0
  1076
	HBufC16* path = resolvedPath->Parser().Des().AllocL();
sl@0
  1077
	CleanupStack::PopAndDestroy(resolvedPath);
sl@0
  1078
	return path;
sl@0
  1079
	}
sl@0
  1080
	
sl@0
  1081
/**
sl@0
  1082
	Checks if the segment is '.' (8-bit version).
sl@0
  1083
	
sl@0
  1084
	@since			6.0
sl@0
  1085
	@param			aSegment	A descriptor with the segment to check.
sl@0
  1086
	@return			A boolean value of ETrue if the segment is '.', EFalse if not.
sl@0
  1087
*/
sl@0
  1088
TBool IsSameDir(const TDesC8& aSegment)
sl@0
  1089
	{
sl@0
  1090
	_LIT8(KSameDir, ".");
sl@0
  1091
	return (aSegment.Compare(KSameDir) == 0);
sl@0
  1092
	}
sl@0
  1093
	
sl@0
  1094
/**
sl@0
  1095
	Checks if the segment is '.' (16-bit version).
sl@0
  1096
	
sl@0
  1097
	@since			6.0
sl@0
  1098
	@param			aSegment	A descriptor with the segment to check.
sl@0
  1099
	@return			A boolean value of ETrue if the segment is '.', EFalse if not.
sl@0
  1100
*/
sl@0
  1101
TBool IsSameDir(const TDesC16& aSegment)
sl@0
  1102
	{
sl@0
  1103
	_LIT16(KSameDir, ".");
sl@0
  1104
	return (aSegment.Compare(KSameDir) == 0);
sl@0
  1105
	}
sl@0
  1106
	
sl@0
  1107
/**
sl@0
  1108
	Checks if the segment is '..' (8-bit version).
sl@0
  1109
	
sl@0
  1110
	@since			6.0
sl@0
  1111
	@param			aSegment	A descriptor with the segment to check.
sl@0
  1112
	@return			A boolean value of ETrue if the segment is '..', EFalse if not.
sl@0
  1113
*/
sl@0
  1114
TBool IsParentDir(const TDesC8& aSegment)
sl@0
  1115
	{
sl@0
  1116
	_LIT8(KParentDir, "..");
sl@0
  1117
	return (aSegment.Compare(KParentDir) == 0);
sl@0
  1118
	}
sl@0
  1119
sl@0
  1120
/**
sl@0
  1121
	Checks if the segment is '..' (16-bit version).
sl@0
  1122
	
sl@0
  1123
	@since			6.0
sl@0
  1124
	@param			aSegment	A descriptor with the segment to check.
sl@0
  1125
	@return			A boolean value of ETrue if the segment is '..', EFalse if not.
sl@0
  1126
*/
sl@0
  1127
TBool IsParentDir(const TDesC16& aSegment)
sl@0
  1128
	{
sl@0
  1129
	_LIT16(KParentDir, "..");
sl@0
  1130
	return (aSegment.Compare(KParentDir) == 0);
sl@0
  1131
	}
sl@0
  1132
sl@0
  1133
/**
sl@0
  1134
	Inserts the segment '..' at the current parsed position (8-bit version).
sl@0
  1135
						
sl@0
  1136
	@since			6.0
sl@0
  1137
	@param			aResolvedPath	The delimited data object to have the segment
sl@0
  1138
					inserted.
sl@0
  1139
	@pre			The delimited data object must be parsed to the position where 
sl@0
  1140
					the segment is to be inserted.
sl@0
  1141
	@post			The segment '..' has been inserted at the current position.
sl@0
  1142
*/
sl@0
  1143
void InsertParentDirL(CDelimitedDataBase8* aResolvedPath)
sl@0
  1144
	{
sl@0
  1145
	_LIT8(KParentDir, "..");
sl@0
  1146
	aResolvedPath->InsertCurrentL(KParentDir);
sl@0
  1147
	}
sl@0
  1148
	
sl@0
  1149
/**
sl@0
  1150
	Inserts the segment '..' at the current parsed position (16-bit version).
sl@0
  1151
						
sl@0
  1152
	@since			6.0
sl@0
  1153
	@param			aResolvedPath	The delimited data object to have the segment
sl@0
  1154
					inserted.
sl@0
  1155
	@pre			The delimited data object must be parsed to the position where 
sl@0
  1156
					the segment is to be inserted.
sl@0
  1157
	@post			The segment '..' has been inserted at the current position.
sl@0
  1158
*/
sl@0
  1159
void InsertParentDirL(CDelimitedDataBase16* aResolvedPath)
sl@0
  1160
	{
sl@0
  1161
	_LIT16(KParentDir, "..");
sl@0
  1162
	aResolvedPath->InsertCurrentL(KParentDir);
sl@0
  1163
	}
sl@0
  1164
	
sl@0
  1165
sl@0
  1166
//
sl@0
  1167
//
sl@0
  1168
// File URI Implementation - CUri8
sl@0
  1169
//
sl@0
  1170
//
sl@0
  1171
sl@0
  1172
/**
sl@0
  1173
	Initializes the file URI components (scheme, empty hostname and path).	 
sl@0
  1174
	
sl@0
  1175
	It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive. 
sl@0
  1176
	
sl@0
  1177
	@since			9.1
sl@0
  1178
	@param			aFileName	A reference to a filename 
sl@0
  1179
	@param			aDrive		A drive number. This is a TFileUriFlags value.
sl@0
  1180
	@param			aFlags		A flag to indicate if the file exists on a fixed drive or removable media drive.
sl@0
  1181
					This is a TFileUriFlags value.
sl@0
  1182
	@pre 			Object fully constructed
sl@0
  1183
	@post			The object is initialized with file URI components.
sl@0
  1184
 */
sl@0
  1185
void CUri8::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
sl@0
  1186
	{
sl@0
  1187
	HBufC* uriPath16 = GenerateFileUriPathL(aFileName, aDrive, aFlags);
sl@0
  1188
	CleanupStack::PushL(uriPath16);
sl@0
  1189
	HBufC8* uriPath = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath16);
sl@0
  1190
	CleanupStack::PopAndDestroy(uriPath16);
sl@0
  1191
	CleanupStack::PushL(uriPath);
sl@0
  1192
	HBufC8* escpedUriPath = EscapeUtils::EscapeEncodeL(*uriPath, EscapeUtils::EEscapeNormal);
sl@0
  1193
	CleanupStack::PopAndDestroy(uriPath);
sl@0
  1194
	CleanupStack::PushL(escpedUriPath);
sl@0
  1195
	
sl@0
  1196
	//SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation, 
sl@0
  1197
	//tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer 
sl@0
  1198
	//for each SetComponent call     
sl@0
  1199
	iUri.iComponent[EUriPath].Set(*escpedUriPath);
sl@0
  1200
	iUri.iComponent[EUriHost].Set(KNullDesC8);
sl@0
  1201
	iUri.iComponent[EUriScheme].Set(KFileUriScheme8);
sl@0
  1202
	FormUriL();
sl@0
  1203
	
sl@0
  1204
	CleanupStack::PopAndDestroy(escpedUriPath);
sl@0
  1205
	}
sl@0
  1206
sl@0
  1207
/**
sl@0
  1208
	Allocates and constructs a file URI object for a specified file.
sl@0
  1209
	 
sl@0
  1210
	- If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.	
sl@0
  1211
	- If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
sl@0
  1212
	
sl@0
  1213
	@since			9.1
sl@0
  1214
	@param			aFullFileName	A reference to a fully qualified filename 
sl@0
  1215
	@param			aFlags			A flag to indicate if the file exists on a fixed drive or removable media drive.
sl@0
  1216
									This is a TFileUriFlags value.
sl@0
  1217
	@return			A pointer to the newly created file URI (CUri8) object. 
sl@0
  1218
	@post			A fully constructed and initialized file URI (CUri8) object.
sl@0
  1219
 */
sl@0
  1220
EXPORT_C CUri8* CUri8::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
sl@0
  1221
	{
sl@0
  1222
	//It should be called to construct a file URI for a public file stored on a fix drive 
sl@0
  1223
	// or on a removable media drive only
sl@0
  1224
	__ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
sl@0
  1225
		
sl@0
  1226
	CUri8* self = CUri8::NewLC();
sl@0
  1227
	self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
sl@0
  1228
	CleanupStack::Pop(self);
sl@0
  1229
	return self;
sl@0
  1230
	}
sl@0
  1231
sl@0
  1232
/**
sl@0
  1233
	Allocates and constructs a file URI object for a file that is private to the application.
sl@0
  1234
sl@0
  1235
	- If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
sl@0
  1236
	- If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
sl@0
  1237
	
sl@0
  1238
	@since			9.1
sl@0
  1239
	@param			aRelativeFileName	A reference to the filename relative to the application's private directory.
sl@0
  1240
	@param			aDrive				Drive number, if the private file stored on fixed drive, otherwise not used
sl@0
  1241
										This is a TDriveNumber value
sl@0
  1242
	@param			aFlags				A flag to indicate if the file exists on a fixed drive or removable media drive.
sl@0
  1243
										This is a TFileUriFlags value.
sl@0
  1244
	@return			A pointer to the newly created file URI (CUri8) object. 
sl@0
  1245
	@post			A fully constructed and initialized file URI (CUri8) object.
sl@0
  1246
*/	
sl@0
  1247
sl@0
  1248
sl@0
  1249
EXPORT_C CUri8* CUri8::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags) 
sl@0
  1250
	{
sl@0
  1251
	//It should be called to construct a file URI for the application's private file stored on a fix drive 
sl@0
  1252
	// or on a removable media drive only
sl@0
  1253
	__ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
sl@0
  1254
sl@0
  1255
	CUri8* self = CUri8::NewLC();
sl@0
  1256
	self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
sl@0
  1257
	CleanupStack::Pop(self);
sl@0
  1258
	return self;
sl@0
  1259
	}
sl@0
  1260
sl@0
  1261
sl@0
  1262
//
sl@0
  1263
//
sl@0
  1264
// File URI Implementation - CUri16
sl@0
  1265
//
sl@0
  1266
//
sl@0
  1267
sl@0
  1268
/**
sl@0
  1269
	Initializes the file URI components (scheme, empty hostname and path).	 
sl@0
  1270
	
sl@0
  1271
	It uses GenerateFileUriPathL() to generate a file Uri path using the filename and drive. 
sl@0
  1272
	
sl@0
  1273
	@since			9.1
sl@0
  1274
	@param			aFileName	A reference to a filename 
sl@0
  1275
	@param			aDrive		A drive number. This is a TFileUriFlags value.
sl@0
  1276
	@param			aFlags		A flag to indicate if the file exists on a fixed drive or removable media drive.
sl@0
  1277
					This is a TFileUriFlags value.
sl@0
  1278
	@pre 			Object fully constructed
sl@0
  1279
	@post			The object is initialized with file URI components.
sl@0
  1280
 */
sl@0
  1281
void CUri16::InitializeFileUriComponentsL(const TDesC& aFileName, TDriveNumber aDrive, TUint aFlags)
sl@0
  1282
	{	
sl@0
  1283
	HBufC* uriPath = GenerateFileUriPathL(aFileName, aDrive, aFlags);
sl@0
  1284
	CleanupStack::PushL(uriPath);
sl@0
  1285
sl@0
  1286
	HBufC8* uriPath8 = EscapeUtils::ConvertFromUnicodeToUtf8L(*uriPath);
sl@0
  1287
	CleanupStack::PopAndDestroy(uriPath);
sl@0
  1288
	CleanupStack::PushL(uriPath8);
sl@0
  1289
sl@0
  1290
	HBufC8* escapedUriPath8 = EscapeUtils::EscapeEncodeL(*uriPath8, EscapeUtils::EEscapeNormal);
sl@0
  1291
	CleanupStack::PopAndDestroy(uriPath8);
sl@0
  1292
	CleanupStack::PushL(escapedUriPath8);
sl@0
  1293
sl@0
  1294
	HBufC* escapedUriPath = HBufC::NewLC(escapedUriPath8->Length());
sl@0
  1295
	escapedUriPath->Des().Copy(*escapedUriPath8); 
sl@0
  1296
	
sl@0
  1297
	//SetComponent is not used in order to increase efficiency, by avoiding overhead of length calculation, 
sl@0
  1298
	//tmp buffer allocation and updation of internal uri object, internal buffer & descriptor pointer 
sl@0
  1299
	//for each SetComponent call     
sl@0
  1300
	iUri.iComponent[EUriPath].Set(*escapedUriPath);
sl@0
  1301
	iUri.iComponent[EUriHost].Set(KNullDesC16);
sl@0
  1302
	iUri.iComponent[EUriScheme].Set(KFileUriScheme16);
sl@0
  1303
	FormUriL();
sl@0
  1304
	
sl@0
  1305
	CleanupStack::PopAndDestroy(escapedUriPath);
sl@0
  1306
	CleanupStack::PopAndDestroy(escapedUriPath8);
sl@0
  1307
	}
sl@0
  1308
sl@0
  1309
/**
sl@0
  1310
	Allocates and constructs a file URI object for a specified file.
sl@0
  1311
	 
sl@0
  1312
	- If the file exists on a fixed drive, then the file URI takes the form: 'file://\<drive-letter\>/\<filepath including filename\>'.	
sl@0
  1313
	- If the file exists on a removable media drive, then the file URI takes the form: 'file://ext-media/\<filepath including filename\>'.
sl@0
  1314
	
sl@0
  1315
	@since			9.1
sl@0
  1316
	@param			aFullFileName	A reference to a fully qualified filename 
sl@0
  1317
	@param			aFlags	A flag to indicate if the file exists on a fixed drive or removable media drive.
sl@0
  1318
					This is a TFileUriFlags value.
sl@0
  1319
	@return			A pointer to the newly created file URI (CUri16) object. 
sl@0
  1320
	@post			A fully constructed and initialized file URI (CUri16) object.
sl@0
  1321
 */
sl@0
  1322
EXPORT_C CUri16* CUri16::CreateFileUriL(const TDesC& aFullFileName, TUint aFlags)
sl@0
  1323
	{
sl@0
  1324
	//It should be called to construct a file URI for a public file stored on a fix drive 
sl@0
  1325
	// or on a removable media drive only
sl@0
  1326
	__ASSERT_ALWAYS( ((aFlags == 0) || (aFlags & EExtMedia)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
sl@0
  1327
		
sl@0
  1328
	CUri16* self = CUri16::NewLC();
sl@0
  1329
	self->InitializeFileUriComponentsL(aFullFileName, EDriveA, aFlags);
sl@0
  1330
	CleanupStack::Pop(self);
sl@0
  1331
	return self;
sl@0
  1332
	}
sl@0
  1333
	
sl@0
  1334
/**
sl@0
  1335
	Allocates and constructs a file URI object for a file that is private to the application.
sl@0
  1336
sl@0
  1337
	- If the file exists on a fixed drive, then the file URI takes the form 'file://private/\<drive-letter\>/<filepath including filename\>'.
sl@0
  1338
	- If the file exists on a removable media drive, then the file URI takes the form 'file://private/ext-media/\<filepath including filename\>'.
sl@0
  1339
	
sl@0
  1340
	@since			9.1
sl@0
  1341
	@param			aRelativeFileName	A reference to the filename relative to the application's private directory.
sl@0
  1342
	@param			aDrive				Drive number, if the private file stored on fixed drive, otherwise not used
sl@0
  1343
										This is a TDriveNumber value
sl@0
  1344
	@param			aFlags				A flag to indicate if the file exists on a fixed drive or removable media drive.
sl@0
  1345
										This is a TFileUriFlags value.
sl@0
  1346
	@return			A pointer to the newly created file URI (CUri16) object. 
sl@0
  1347
	@post			A fully constructed and initialized file URI (CUri16) object.
sl@0
  1348
*/
sl@0
  1349
sl@0
  1350
sl@0
  1351
EXPORT_C CUri16* CUri16::CreatePrivateFileUriL(const TDesC& aRelativeFileName, TDriveNumber aDrive, TInt aFlags) 
sl@0
  1352
	{
sl@0
  1353
	//It should be called to construct a file URI for the application's private file stored on a fix drive 
sl@0
  1354
	// or on a removable media drive only
sl@0
  1355
	__ASSERT_ALWAYS( (((aFlags == 0) || (aFlags & EExtMedia)) && (aDrive >= EDriveA && aDrive <= EDriveZ)), User::Panic(KFileUriPanicCategory, KUriUtilsCannotConvert) );
sl@0
  1356
sl@0
  1357
	CUri16* self = CUri16::NewLC();
sl@0
  1358
	self->InitializeFileUriComponentsL(aRelativeFileName, aDrive, aFlags|EPrivate);
sl@0
  1359
	CleanupStack::Pop(self);
sl@0
  1360
	return self;
sl@0
  1361
	}
sl@0
  1362
sl@0
  1363
sl@0
  1364
//
sl@0
  1365
//
sl@0
  1366
// Implemetation of LOCAL functions for the File URI
sl@0
  1367
//
sl@0
  1368
//
sl@0
  1369
	
sl@0
  1370
/**
sl@0
  1371
	Function used to generate 16bit file uri using 1st parameter aFileName and 
sl@0
  1372
	2nd parameter aDrive for the application's private or a public file.
sl@0
  1373
	
sl@0
  1374
	This is called by API CreateFileUri() and CreatePrivateFileUri()to 
sl@0
  1375
	generate a filename.
sl@0
  1376
	
sl@0
  1377
	Note: The space allocated for the returned descriptor will likely be larger 
sl@0
  1378
		  than the length of the descriptor
sl@0
  1379
	
sl@0
  1380
	@leave			KErrBadName	A provided Drivename or filename is not valid 
sl@0
  1381
	@since			9.1
sl@0
  1382
	@param			aFileName	A descriptor reference to the filename.
sl@0
  1383
	@param			aDrive		A descriptor reference to drive letter.
sl@0
  1384
	@param			aFlags		A flag to indicate the private or a public file exists on removable media or a fixed drive.
sl@0
  1385
	@return			A pointer to a buffer containing the resolved fully qualified filename.
sl@0
  1386
 */
sl@0
  1387
HBufC* GenerateFileUriPathL(const TDesC& aFileName, TDriveNumber aDrive,  TUint aFlags)
sl@0
  1388
	{
sl@0
  1389
	TInt origLength = aFileName.Length();
sl@0
  1390
sl@0
  1391
	//Leaves with KErrBadName if filename length is out of range 
sl@0
  1392
	if (origLength == 0 || origLength > KMaxFileName)
sl@0
  1393
		{
sl@0
  1394
		User::Leave(KErrBadName);	
sl@0
  1395
		}
sl@0
  1396
		
sl@0
  1397
	TPtrC filename(aFileName);
sl@0
  1398
	
sl@0
  1399
	//extract drive letter and remove drive "x:" from filename
sl@0
  1400
	TUint drive = filename[0];
sl@0
  1401
	
sl@0
  1402
	 // hasDrive means it begins with a drive, e.g. "c:"
sl@0
  1403
	 const TBool hasDrive =  ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z')) && (filename[1] == KDriveSeparator);
sl@0
  1404
	 // hasTopPath means it begins with a \ (possibly after the drive)
sl@0
  1405
	 const TBool hasTopPath = (hasDrive && (filename[2] == KFilePathSeparator)) || (!hasDrive && (drive == TUint(KFilePathSeparator) ));
sl@0
  1406
 
sl@0
  1407
	 TInt skip = KDefaultPath().Length(); //  skip leading "<drive>:\" by default
sl@0
  1408
	 if(aFlags & TUint(EPrivate)) 
sl@0
  1409
		{
sl@0
  1410
		skip = (hasDrive ? (KDefaultPath().Length() - 1) : 0) + (hasTopPath ? 1 : 0) ;
sl@0
  1411
		}
sl@0
  1412
	 else
sl@0
  1413
		{
sl@0
  1414
		// if not private then it should have valid drive i.e. "<drive>:\"
sl@0
  1415
		if (!(hasDrive && hasTopPath)) 
sl@0
  1416
			{
sl@0
  1417
			User::Leave(KErrBadName);
sl@0
  1418
			}
sl@0
  1419
		}
sl@0
  1420
	
sl@0
  1421
	if(skip)
sl@0
  1422
		  {
sl@0
  1423
		  filename.Set(aFileName.Right(origLength - skip));
sl@0
  1424
		  } 	
sl@0
  1425
sl@0
  1426
	TInt uriLen = aFileName.Length() + KExtMedia().Length() + KPrivate().Length() + 1 /* for drive letter */;
sl@0
  1427
	
sl@0
  1428
	HBufC* fileUri = HBufC::NewLC(uriLen);
sl@0
  1429
	TPtr fileUriPtr = fileUri->Des(); 
sl@0
  1430
	fileUriPtr.Append(KUriPathSeparator);
sl@0
  1431
	
sl@0
  1432
	if (aFlags & TUint(EPrivate))
sl@0
  1433
		{
sl@0
  1434
		fileUriPtr.Append(KPrivate);
sl@0
  1435
		drive = TInt16('A' + aDrive);
sl@0
  1436
		}
sl@0
  1437
		
sl@0
  1438
	if (aFlags & EExtMedia)
sl@0
  1439
		{
sl@0
  1440
		fileUriPtr.Append(KExtMedia);			
sl@0
  1441
		}
sl@0
  1442
	else
sl@0
  1443
		{
sl@0
  1444
		fileUriPtr.Append(drive);
sl@0
  1445
		fileUriPtr.Append(KUriPathSeparator);	
sl@0
  1446
		}
sl@0
  1447
		
sl@0
  1448
	fileUriPtr.Append(filename);
sl@0
  1449
		
sl@0
  1450
	//Convert "\" to "/"
sl@0
  1451
	ChangePathSeparator(fileUriPtr, KFilePathSeparator, KUriPathSeparator);
sl@0
  1452
sl@0
  1453
	//Handling "./" and "../" in the file URI path  or resolving the URI path 
sl@0
  1454
	CDelimitedPath16* resolvedPath = CDelimitedPath16::NewLC(fileUriPtr);
sl@0
  1455
 	// Clean up the path to resolve occurences of '..' and '.'
sl@0
  1456
 	CleanResolvedPathL<TPtrC>(resolvedPath);
sl@0
  1457
 	fileUriPtr.Copy(resolvedPath->Parser().Des()); // new path will always be shorter than old one
sl@0
  1458
 	CleanupStack::PopAndDestroy(resolvedPath);
sl@0
  1459
 		
sl@0
  1460
	CleanupStack::Pop(fileUri);
sl@0
  1461
	return fileUri;
sl@0
  1462
	}