messagingappbase/obexmtms/obexmtm/obexutil/source/obexMtmUtil.cpp
changeset 31 ebfee66fde93
child 47 5b14749788d7
equal deleted inserted replaced
30:6a20128ce557 31:ebfee66fde93
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // $Workfile: obexMtmUtil.cpp $
       
    15 // $Author: Stevep $
       
    16 // $Revision: 7 $
       
    17 // $Date: 8/02/02 10:11 $
       
    18 // 
       
    19 //
       
    20 
       
    21 //class include
       
    22 #include "obexMtmUtil.h"
       
    23 #include "obexheaderlist.h"
       
    24 
       
    25 #ifdef _DEBUG
       
    26 #define DEBPRINT(Z)  User::InfoPrint(Z);
       
    27 #else
       
    28 #define DEBPRINT(Z)
       
    29 #endif
       
    30 
       
    31 // Uncomment this to test data compatibility with builds older than PHAR-5SDJG9.
       
    32 // (if uncommented, messages are externalised the same way it was done before the PHAR-5SDJG9 changes)
       
    33 //#define TEST_INC042468 
       
    34 
       
    35 static const TInt KObexArrayGranularity = 4;
       
    36 
       
    37 //
       
    38 //
       
    39 //  Class for externalising a set of filenames to the same message entry store. Rolls back if not explicitly committed.
       
    40 //
       
    41 
       
    42 // Static functions that do the whole process in one go:
       
    43 EXPORT_C  void CObexMtmFileNameExternaliser::ExternaliseAndCommit1FileNameL(CMsvEntry* aEntry, const TDesC16* aFileName)
       
    44 /**
       
    45 * Static function to write one and only one filename to the message store, then finalise and commit it. This function
       
    46 * should be called ONCE ONLY. To externalise more than one filename, instantiate this class and use ExternaliseFileNameL()
       
    47 * followed by CommitStoreL().
       
    48 * @param aEntry the entry whose store is to be written to
       
    49 * @param aFileName The filename to write to the store
       
    50 * @leave KErrXXX system-wide error codes
       
    51 */	
       
    52 	{
       
    53 	CMsvStore* messageStore = aEntry->EditStoreL();
       
    54 	CleanupStack::PushL(messageStore);
       
    55 
       
    56 	RMsvWriteStream messageWriteStream;
       
    57 	CleanupClosePushL(messageWriteStream);
       
    58 
       
    59 	messageWriteStream.AssignL(*messageStore, KObexFileNameStreamUid);
       
    60 
       
    61 	// write the identifier so we know we are internalizing a stream later
       
    62 #ifndef TEST_INC042468
       
    63 	messageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid);
       
    64 #endif
       
    65 	messageWriteStream.WriteInt32L(aFileName->Length());  
       
    66 	messageWriteStream.WriteL(*aFileName);
       
    67 
       
    68 #ifndef TEST_INC042468
       
    69 	messageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid);
       
    70 #endif
       
    71 	messageWriteStream.WriteInt32L(0);		//Mark the end of the filename list
       
    72 
       
    73 	messageWriteStream.CommitL();
       
    74 
       
    75 	CleanupStack::PopAndDestroy(); // trigger a call to Close(); on messageWriteStream as well as removing from the stack
       
    76 
       
    77 	messageStore->CommitL();
       
    78 	CleanupStack::PopAndDestroy(messageStore);
       
    79 	}
       
    80 
       
    81 
       
    82 EXPORT_C  void CObexMtmFileNameExternaliser::Internalise1FileNameL(CMsvEntry* aEntry,  TDes16* aFileName)
       
    83 /**
       
    84 * Static function to read in one filename from the store.
       
    85 *
       
    86 * @param aEntry entry to read the filename from
       
    87 * @param aFileName Descriptor to receive the new filename. Any existing data will be overwritten. MUST be long enough to contain the name.
       
    88 * @leave KErrXXX system wide error codes.
       
    89 */	
       
    90 	{
       
    91 	CMsvStore* messageStore = aEntry->ReadStoreL();
       
    92 	CleanupStack::PushL(messageStore);
       
    93 
       
    94 	RMsvReadStream messageReadStream;
       
    95 	messageReadStream.OpenLC(*messageStore, KObexFileNameStreamUid);  // If data hasn't been stored then this will provide the error.
       
    96 
       
    97 	// verify that we're reading the right type of data from the stream
       
    98 
       
    99 
       
   100 	// INC042468: "AV21: Data Compatibility break caused by "PHAR-5SDJG9""
       
   101 	// To regain compatibility, if the first integer read from the stream
       
   102 	// is not the expected "KObexFileNameStreamFileNameUid", it is assumed it 
       
   103 	// is the filename length. An extra check is made that it is a valid filename
       
   104 	// length (<= KMaxFileName).
       
   105 	// "KObexFileNameStreamFileNameUid" has also been modified so that there cannot
       
   106 	// be a file with a name length equal to KObexFileNameStreamFileNameUid (in which
       
   107 	// case we would have been in trouble ;-) )
       
   108 
       
   109 	TInt32 firstInt = messageReadStream.ReadInt32L();
       
   110 	TInt32 fileNameLength = 0;
       
   111 	if (firstInt == KObexFileNameStreamFileNameUid)
       
   112 		{
       
   113 		// next will be the filename length
       
   114 		fileNameLength = messageReadStream.ReadInt32L();
       
   115 		}
       
   116 	else if (firstInt <= KMaxFileName)
       
   117 		{
       
   118 		// let's assume the first integer in the stream was the filename length
       
   119 		// (this happens if the message was saved by an old build (previous to PHAR-5SDJG9)
       
   120 		fileNameLength = firstInt;
       
   121 		}
       
   122 	else
       
   123 		{
       
   124 		// neither the expected "KObexFileNameStreamFileNameUid" nor a valid filename length
       
   125 		User::Leave(KErrArgument);	
       
   126 		}
       
   127 
       
   128 	messageReadStream.ReadL(*aFileName, fileNameLength);
       
   129 
       
   130 	CleanupStack::PopAndDestroy(2, messageStore);  // messageStore, messageReadStream (calls Close() first)
       
   131 	}
       
   132 
       
   133 //
       
   134 //
       
   135 // Class for storing multiple Filenames within a CMsvEntry store.
       
   136 //
       
   137 EXPORT_C  CObexMtmFileNameExternaliser* CObexMtmFileNameExternaliser::NewL(CMsvSession* aSession, TMsvId aId)
       
   138 /**
       
   139 * Canonical NewL factory function.
       
   140 *
       
   141 * @param aSession A messaging server session
       
   142 * @param aId TMsvId of the entry to externalise/internalise to/from. This association is fixed for the lifetime of this instance of the class.
       
   143 * @return a newly constucted CObexMtmFileNameExternaliser
       
   144 * @leave KErrXXX system wide error codes
       
   145 */
       
   146 	{
       
   147 	CObexMtmFileNameExternaliser* self = new(ELeave) CObexMtmFileNameExternaliser(aSession);
       
   148 	CleanupStack::PushL(self);
       
   149 	self->InitialiseStoreL(aId);
       
   150 	CleanupStack::Pop();  // self
       
   151 	return self;
       
   152 	}
       
   153 CObexMtmFileNameExternaliser::CObexMtmFileNameExternaliser(CMsvSession* aSession)   :   iSession(aSession)
       
   154 /**
       
   155 * Constructor
       
   156 *
       
   157 *  @param aSession A messaging server session
       
   158 */
       
   159 	{}
       
   160 CObexMtmFileNameExternaliser::~CObexMtmFileNameExternaliser()
       
   161 /**
       
   162 * Destructor. Will revert the stream to its original state if the store hasn't been comitted.
       
   163 */
       
   164 	{
       
   165 	if(! iHaveCommitted)
       
   166 		{
       
   167 		iMessageWriteStream.Close();  
       
   168 		if(iMessageStore)
       
   169 		    iMessageStore->Revert();  // Don't commit. Should have been called explicitly using CommitStoreL().
       
   170 		}
       
   171 	delete iMessageStore;
       
   172 	delete iEntry;
       
   173 	}
       
   174 
       
   175 void CObexMtmFileNameExternaliser::InitialiseStoreL(TMsvId aId)
       
   176 /**
       
   177  * Initialises the store of the given entry, ready for reading or writing.
       
   178  *
       
   179  * @param aId The TMsvId of the entry whose store should be initialised.
       
   180  * @leave KErrXXX system wide error codes.
       
   181  */
       
   182 	{
       
   183 	iEntry = iSession->GetEntryL(aId);
       
   184 
       
   185 	iMessageStore = iEntry->EditStoreL();
       
   186 
       
   187 	iMessageWriteStream.AssignL(*iMessageStore, KObexFileNameStreamUid);
       
   188 	iHaveCommitted = EFalse;
       
   189 	}
       
   190 
       
   191 EXPORT_C  void CObexMtmFileNameExternaliser::ExternaliseFileNameL(const TDesC16* aFileName)
       
   192 /**
       
   193  * Externalises a single filename to the associated entry's message store.
       
   194  *
       
   195  * @param aFileName the filename to externalise.
       
   196  * @leave KErrXXX system-wide error codes.
       
   197  */
       
   198 	{
       
   199 #ifndef TEST_INC042468
       
   200 	iMessageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid);
       
   201 #endif
       
   202 	iMessageWriteStream.WriteInt32L(aFileName->Length());
       
   203 	iMessageWriteStream.WriteL(*aFileName);
       
   204 	}
       
   205 
       
   206 EXPORT_C  void CObexMtmFileNameExternaliser::ExternaliseFileNameAndHeadersL(const TDesC16* aFileName, const CObexHeaderList* aHeaderList)
       
   207 /**
       
   208  * Externalises a single filename to the associated entry's message store.
       
   209  *
       
   210  * @param aFileName the filename to externalise.
       
   211  * @leave KErrXXX system-wide error codes.
       
   212  */
       
   213 	{
       
   214 	ExternaliseFileNameL(aFileName);
       
   215 #ifndef TEST_INC042468
       
   216 	iMessageWriteStream.WriteInt32L(KObexFileNameStreamHeaderListUid);
       
   217 	aHeaderList->ExternalizeL(iMessageWriteStream);
       
   218 #endif
       
   219 	}
       
   220 
       
   221 EXPORT_C  void CObexMtmFileNameExternaliser::CommitStoreL()
       
   222 /**
       
   223  * Finalises and commits the store. This function MUST be called once all of the filenames have been externalised, and not
       
   224  * before. If it is not called, any changes will be lost and the store will revert to its former state.
       
   225  *
       
   226  * @leave KErrXXX system wide error codes.
       
   227  */
       
   228 	{
       
   229 #ifndef TEST_INC042468
       
   230 	iMessageWriteStream.WriteInt32L(KObexFileNameStreamFileNameUid);
       
   231 #endif
       
   232 	iMessageWriteStream.WriteInt32L(0);  // length == 0  --> no more names in store.
       
   233 	iMessageWriteStream.CommitL();
       
   234 	iHaveCommitted = ETrue;
       
   235 	iMessageWriteStream.Close();
       
   236 
       
   237 	iMessageStore->CommitL();
       
   238 
       
   239 	delete iMessageStore;
       
   240 	iMessageStore=NULL;
       
   241 	}
       
   242 
       
   243 EXPORT_C  RObexMtmFileNameWithHeadersArray* CObexMtmFileNameExternaliser::InternaliseFileNamesLC(CMsvStore& aMessageStore)
       
   244 /**
       
   245  * Static function to get the filenames stored within the message entry. The returned array is pushed onto the cleanup
       
   246  * stack.
       
   247  *
       
   248  * @param aMessageStore Store from which the names are to be read
       
   249  * @return Array of filenames, pushed onto the cleanup stack.
       
   250  * @leave System wide error codes
       
   251  */
       
   252 	{
       
   253 	RObexMtmFileNameWithHeadersArray* fileNameArray = new(ELeave) RObexMtmFileNameWithHeadersArray(KObexArrayGranularity);
       
   254 	CleanupStack::PushL(fileNameArray);
       
   255 
       
   256 	RMsvReadStream  newMessageReadStream;
       
   257 	newMessageReadStream.OpenL(aMessageStore, KObexFileNameStreamUid);  // If data hasn't been stored then this will provide the error.
       
   258 	CleanupClosePushL(newMessageReadStream);
       
   259 
       
   260 
       
   261 
       
   262 
       
   263 	// INC042468: "AV21: Data Compatibility break caused by "PHAR-5SDJG9""
       
   264 	// To regain compatibility, if the first integer read from the stream
       
   265 	// is not the expected "KObexFileNameStreamFileNameUid", it is assumed it 
       
   266 	// is the filename length. An extra check is made that it is a valid filename
       
   267 	// length (<= KMaxFileName).
       
   268 	// "KObexFileNameStreamFileNameUid" has also been modified so that there cannot
       
   269 	// be a file with a name length equal to KObexFileNameStreamFileNameUid (in which
       
   270 	// case we would have been in trouble ;-) )
       
   271 
       
   272 	TInt32 firstInt = newMessageReadStream.ReadInt32L();
       
   273 	
       
   274 	TInt32 fileNameLength = 0;
       
   275 	if (firstInt == KObexFileNameStreamFileNameUid)
       
   276 		{
       
   277 		// next will be the filename length
       
   278 		fileNameLength = newMessageReadStream.ReadInt32L();
       
   279 		}
       
   280 	else if (firstInt <= KMaxFileName)
       
   281 		{
       
   282 		// let's assume the first integer in the stream was the filename length
       
   283 		// (this happens if the message was saved by an old build (previous to PHAR-5SDJG9)
       
   284 		fileNameLength = firstInt;
       
   285 		}
       
   286 	else
       
   287 		{
       
   288 		// neither the expected "KObexFileNameStreamFileNameUid" nor a valid filename length
       
   289 		User::Leave(KErrArgument);	
       
   290 		}
       
   291 
       
   292 	TInt32 elementTypeID;
       
   293 	TBool lengthAlreadyReadFlag;
       
   294 	TFileName thisName;
       
   295 	CObexMtmFileNameWithHeaders *thisPackage;
       
   296 	while(fileNameLength)
       
   297 		{
       
   298 
       
   299 		thisPackage = CObexMtmFileNameWithHeaders::NewL();
       
   300 		CleanupStack::PushL(thisPackage);
       
   301 				
       
   302 		// read 'bodylength' bytes into a descriptor			
       
   303 		newMessageReadStream.ReadL(thisName, fileNameLength);
       
   304 		
       
   305 		// store this descriptor in the container
       
   306 		thisPackage->iFileName = new(ELeave) TFileName(thisName);
       
   307 		CleanupStack::PushL(thisPackage->iFileName);
       
   308 
       
   309 		lengthAlreadyReadFlag = EFalse;	
       
   310 		// get the type of the next element
       
   311 		elementTypeID = newMessageReadStream.ReadInt32L();
       
   312 
       
   313 		switch(elementTypeID)
       
   314 			{
       
   315 		case KObexFileNameStreamHeaderListUid:
       
   316 			// this filename has some headers associated with it
       
   317 			
       
   318 			// read these headers in...
       
   319 			thisPackage->iHeaderList = CObexHeaderList::NewLC();
       
   320 			thisPackage->iHeaderList->InternalizeL(newMessageReadStream);
       
   321 
       
   322 			// get the type of the next element
       
   323 			elementTypeID = newMessageReadStream.ReadInt32L();
       
   324 						
       
   325 			// fall through to add this container to the array
       
   326 		case KObexFileNameStreamFileNameUid:
       
   327 			// this filename has no headers associated with it, this is OK.
       
   328 			fileNameArray->Append(thisPackage);
       
   329 			break;
       
   330 
       
   331 		default:
       
   332 			// builds previous to PHAR-5SDJG9: 
       
   333 			// no stream Uids are externalised and elementTypeID contains already the filename length
       
   334 			if (elementTypeID <= KMaxFileName)
       
   335 				{
       
   336 				fileNameArray->Append(thisPackage);
       
   337 				fileNameLength = elementTypeID;
       
   338 				lengthAlreadyReadFlag = ETrue;
       
   339 				}
       
   340 			else
       
   341 				{
       
   342 				User::Leave(KErrArgument);
       
   343 				}
       
   344 			// if this value is not one of the two element types, then we can't read the stream
       
   345 			
       
   346 			break;
       
   347 			}
       
   348 
       
   349 		// this member will be zero if there were no headers on this filename
       
   350 		if(thisPackage->iHeaderList)
       
   351 			{
       
   352 			CleanupStack::Pop(thisPackage->iHeaderList);
       
   353 			}
       
   354 
       
   355 		// safely added filename and headers to list, pop the allocations off the cleanup stack.
       
   356 		CleanupStack::Pop(thisPackage->iFileName);
       
   357 		
       
   358 		CleanupStack::Pop(thisPackage);
       
   359 
       
   360 		// get the length of the next element
       
   361 		if (!lengthAlreadyReadFlag)
       
   362 			{
       
   363 			TRAPD (err, fileNameLength = newMessageReadStream.ReadInt32L();)  // Length == 0 --> end of array
       
   364 			}
       
   365 		}
       
   366 
       
   367 	newMessageReadStream.Close();
       
   368 	CleanupStack::PopAndDestroy();  //newMessageReadStream
       
   369 
       
   370 	return fileNameArray;
       
   371 	}
       
   372 
       
   373 //
       
   374 // CObexMtmFileNameWithHeaders
       
   375 //
       
   376 
       
   377 EXPORT_C CObexMtmFileNameWithHeaders* CObexMtmFileNameWithHeaders::NewL()
       
   378 	/**
       
   379 	 * Canonical NewL factory function.
       
   380 	 *
       
   381 	 * @return an empty CObexMtmFileNameWithHeaders class
       
   382 	 * @leave KErrXXX system wide error codes
       
   383 	 */
       
   384 	{
       
   385 	CObexMtmFileNameWithHeaders *self = new(ELeave)CObexMtmFileNameWithHeaders;
       
   386 	return self;
       
   387 	}
       
   388 
       
   389 CObexMtmFileNameWithHeaders::~CObexMtmFileNameWithHeaders()
       
   390 /**
       
   391  * Destructor. Will destroy the data pointed to by the 2 member pointers.
       
   392  */
       
   393 	{
       
   394 	delete iFileName;
       
   395 	delete iHeaderList;
       
   396 	}
       
   397 
       
   398 CObexMtmFileNameWithHeaders::CObexMtmFileNameWithHeaders()
       
   399 	/**
       
   400 	 * Constructor.
       
   401 	 */
       
   402 	{
       
   403 	}
       
   404 
       
   405