messagingfw/sendas/server/src/csendasmessage.cpp
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2004-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 //
       
    15 
       
    16 #include "csendasmessage.h"
       
    17 
       
    18 #include <u32std.h>
       
    19 #include <mtclbase.h>
       
    20 #include <msvuids.h>
       
    21 #include <mtmuids.h>
       
    22 #include <txtrich.h>
       
    23 #include <mturutils.h>
       
    24 
       
    25 #include "csendassender.h"
       
    26 #include "csendassession.h"
       
    27 #include "csendasattachment.h"
       
    28 #include "csendasmtmmanager.h"
       
    29 #include "sendasserverdefs.h"
       
    30 #include "csendasactivecontainer.h"
       
    31 #include "csendaseditwatcher.h"
       
    32 #include "tsendasserverpanic.h"
       
    33 
       
    34 // max index for incoming RMessage parameters
       
    35 const TInt KSendAsMaxMessageIndex = 3;
       
    36 
       
    37 CSendAsMessage* CSendAsMessage::NewL(CSendAsSession& aSession)
       
    38 	{
       
    39 	CSendAsMessage* self = new(ELeave) CSendAsMessage(aSession);
       
    40 	return self;
       
    41 	}
       
    42 	
       
    43 CSendAsMessage::~CSendAsMessage()
       
    44 	{
       
    45 	delete iSender;
       
    46 	delete iClientMtm;
       
    47 	delete iAttachment;
       
    48 	}
       
    49 	
       
    50 CSendAsMessage::CSendAsMessage(CSendAsSession& aSession)
       
    51 : iSession(aSession)
       
    52 	{
       
    53 	// the data members of iProgress are defined such that when they
       
    54 	// are zero initialised (like being embedded in a C-Class) this is
       
    55 	// the same as the default progress structure.
       
    56 	}
       
    57 
       
    58 /** Dispatch the subsession message to the correct handler.
       
    59  
       
    60 The return value indicates to the owner session if we are doing an
       
    61 asynchronous operation.  ETrue is async: EFalse is sync.
       
    62 Errors can only be returned by leaving.  This method should be encapsulated
       
    63 in a trap harness to prevent the server AO from leaving during a ServiceL.
       
    64 
       
    65 @param	aMesasge
       
    66 The IPC message.
       
    67 
       
    68 @return
       
    69 A value of true if the request is asynchronous, otherwise a value of false
       
    70 indicating that the request is synchronous.
       
    71 */
       
    72 TBool CSendAsMessage::DoSubSessionServiceL(const RMessage2& aMessage)
       
    73 	{
       
    74 	TBool async = EFalse;
       
    75 
       
    76 	switch( aMessage.Function() )
       
    77 		{
       
    78 	case ESAMCreateForAccount:
       
    79 		{
       
    80 		CreateMessageForAccountL(aMessage);
       
    81 		} break;
       
    82 	case ESAMCreateByType:
       
    83 		{
       
    84 		CreateMessageByTypeL(aMessage);
       
    85 		} break;
       
    86 	case ESAMGetProgress:
       
    87 		{
       
    88 		ProgressL(aMessage);
       
    89 		} break;
       
    90 	case ESAMDelete:
       
    91 		{
       
    92 		DeleteMessageL(aMessage);
       
    93 		} break;
       
    94 	case ESAMSetBodyFirst:
       
    95 		{
       
    96 		SetBodyTextL(aMessage, ETrue);
       
    97 		} break;
       
    98 	case ESAMSetBodyNext:
       
    99 		{
       
   100 		SetBodyTextL(aMessage, EFalse);
       
   101 		} break;
       
   102 	case ESAMSetSubject:
       
   103 		{
       
   104 		SetSubjectL(aMessage);
       
   105 		} break;
       
   106 	case ESAMSetBioType:
       
   107 		{
       
   108 		SetBioTypeL(aMessage);
       
   109 		} break;
       
   110 	case ESAMAddRecipient:
       
   111 		{
       
   112 		AddRecipientL(aMessage);
       
   113 		} break;
       
   114 	case ESAMAddRecipientWithAlias:
       
   115 		{
       
   116 		AddRecipientWithAliasL(aMessage);
       
   117 		} break;
       
   118 	case ESAMTransferAttachmentFile:
       
   119 		{
       
   120 		TransferAttachmentFileL(aMessage);
       
   121 		} break;
       
   122 	case ESAMAddAttachment:
       
   123 		{
       
   124 		AddAttachmentL(aMessage);
       
   125 		async = ETrue;
       
   126 		} break;
       
   127 	case ESAMAddAttachmentWithType:
       
   128 		{
       
   129 		AddAttachmentWithMimeTypeL(aMessage);
       
   130 		async = ETrue;
       
   131 		} break;
       
   132 	case ESAMAddLinkedAttachment:
       
   133 		{
       
   134 		AddLinkedAttachmentL(aMessage);
       
   135 		async = ETrue;
       
   136 		} break;
       
   137 	case ESAMAddLinkedAttachmentWithType:
       
   138 		{
       
   139 		AddLinkedAttachmentWithMimeTypeL(aMessage);
       
   140 		async = ETrue;
       
   141 		} break;
       
   142 	case ESAMCreateAttachment:
       
   143 		{
       
   144 		// Message will complete upon transfering ownership of file to client.
       
   145 		CreateAttachmentL(aMessage);
       
   146 		async = ETrue;
       
   147 		} break;
       
   148 	case ESAMCreateAttachmentWithType:
       
   149 		{
       
   150 		// Message will complete upon transfering ownership of file to client.
       
   151 		CreateAttachmentWithMimeTypeL(aMessage);
       
   152 		async = ETrue;
       
   153 		} break;
       
   154 	case ESAMCancel:
       
   155 		{
       
   156 		Cancel();
       
   157 		} break;
       
   158 	case ESAMLaunchEditor:
       
   159 		{
       
   160 		LaunchEditorL(aMessage);
       
   161 		} break;
       
   162 	case ESAMSendMessageConfirmed:
       
   163 		{
       
   164 		async = ETrue;
       
   165 		// drop through to next case...
       
   166 		}
       
   167 	case ESAMSendMessageConfirmedBackground:
       
   168 		{
       
   169 		SendMessageL(aMessage, ETrue, !async);
       
   170 		} break;
       
   171 	case ESAMSendMessage:
       
   172 		{
       
   173 		async = ETrue;
       
   174 		// drop through to next case...
       
   175 		}
       
   176 	case ESAMSendMessageBackground:
       
   177 		{
       
   178 		SendMessageL(aMessage, EFalse, !async);
       
   179 		} break;
       
   180 	case ESAMSaveMessage:
       
   181 		{
       
   182 		__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage));
       
   183 		__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   184 		
       
   185 		DoSaveMessageL();
       
   186 		} break;
       
   187 	case ESAMSetCharacterSet:
       
   188 		{
       
   189 		// For setting the charset encoding value for the message.
       
   190 		SetMessageCharacterSetL(aMessage);	
       
   191 		}break;
       
   192 	
       
   193 	case ESAMCharSetInfoForAttachment:
       
   194 		{
       
   195 		// For setting the charset encoding value for the message.
       
   196 		SetCharsetInfoForAttachment(aMessage);	
       
   197 		}break;
       
   198 	default:
       
   199 		PanicClientL(aMessage, ESendAsClientPanicBadRequest);
       
   200 		break;
       
   201 		}
       
   202 	return async;
       
   203 	}
       
   204 	
       
   205 /** Cancels any asynchronous activity being done by the message.
       
   206 */
       
   207 void CSendAsMessage::CancelMessage()
       
   208 	{
       
   209 	// cancelling is a safe thing to do, like closing.
       
   210 	switch( iState )
       
   211 		{
       
   212 	case EAddingOrCreatingAttachment:
       
   213 		{
       
   214 		__ASSERT_DEBUG( iAttachment != NULL, User::Invariant() );
       
   215 		
       
   216 		// cancel and then delete the attachment object.
       
   217 		iAttachment->Cancel();
       
   218 		
       
   219 		delete iAttachment;
       
   220 		iAttachment = NULL;
       
   221 		} break;
       
   222 	case ESendingMessage:
       
   223 		{
       
   224 		__ASSERT_DEBUG( iSender != NULL, User::Invariant() );
       
   225 
       
   226 		// cancel and then delete the sender object.
       
   227 		iSender->Cancel();
       
   228 		
       
   229 		delete iSender;
       
   230 		iSender = NULL;
       
   231 		} break;
       
   232 	case EIdle:
       
   233 	case EMessageCreated:
       
   234 	case ESendingMessageComplete:
       
   235 	case EMessageDeleted:
       
   236 	case EPendingClose:
       
   237 	default:
       
   238 		// do nothing as cancel is a safe thing...
       
   239 		break;		
       
   240 		}
       
   241 	}
       
   242 
       
   243 /** Allocate a heap buffer to hold a descriptor parameter and copy it in.
       
   244 
       
   245 This method leaves if the desciptor is not valid. This method pushes the buffer
       
   246 onto the cleanup stack and leaves it there when it returns.
       
   247 
       
   248 @param	aMessage
       
   249 The IPC message.
       
   250 
       
   251 @param	aIndex
       
   252 The index of the parameter to read from the IPC message.
       
   253 
       
   254 @return
       
   255 A pointer to an array populated with the descriptor data. A copy of the pointer
       
   256 is left on the cleanup stack.
       
   257 */
       
   258 HBufC* CSendAsMessage::GetDesParamLC(const RMessage2& aMessage, TInt aIndex)
       
   259 	{
       
   260 	__ASSERT_DEBUG((aIndex >=0 && aIndex <=KSendAsMaxMessageIndex), PanicClientL(aMessage, ESendAsClientPanicBadRequestArgument));
       
   261 	
       
   262 	TInt len = User::LeaveIfError(aMessage.GetDesLength(aIndex));
       
   263 	HBufC* buffer = HBufC::NewLC(len);
       
   264 	TPtr ptr(buffer->Des());
       
   265 	aMessage.Read(aIndex, ptr);
       
   266 	return buffer;
       
   267 	}
       
   268 
       
   269 /** Allocate a heap buffer to hold a descriptor parameter and copy it in.
       
   270 
       
   271 This method leaves if the desciptor is not valid. This method pushes the buffer
       
   272 onto the cleanup stack and leaves it there when it returns.
       
   273 
       
   274 @param	aMessage
       
   275 The IPC message.
       
   276 
       
   277 @param	aIndex
       
   278 The index of the parameter to read from the IPC message.
       
   279 
       
   280 @return
       
   281 A pointer to an array populated with the descriptor data. A copy of the pointer
       
   282 is left on the cleanup stack.
       
   283 */
       
   284 HBufC8* CSendAsMessage::GetDesParam8LC(const RMessage2& aMessage, TInt aIndex)
       
   285 	{
       
   286 	__ASSERT_DEBUG((aIndex >=0 && aIndex <=KSendAsMaxMessageIndex), PanicClientL(aMessage, ESendAsClientPanicBadRequestArgument));
       
   287 	
       
   288 	TInt len = User::LeaveIfError(aMessage.GetDesLength(aIndex));
       
   289 	HBufC8* buffer = HBufC8::NewLC(len);
       
   290 	TPtr8 ptr(buffer->Des());
       
   291 	aMessage.Read(aIndex, ptr);
       
   292 	return buffer;
       
   293 	}
       
   294 
       
   295 /**
       
   296 Create a message in the drafts folder and set up this CSendAsMessage instance to
       
   297 operate on it.
       
   298 
       
   299 This method requires either an MTM UID or a valid account ID. 
       
   300 
       
   301 If the MTM UID is NULL, then the account ID must be valid otherwise the method will
       
   302 leave. If the account ID is valid, then the MTM of the account is used.
       
   303 
       
   304 @param	aMtm
       
   305 The UID of the MTM for the new message.
       
   306 
       
   307 @param	aAccount
       
   308 The account ID under which the message is created.
       
   309 
       
   310 @leave	KErrNotFound
       
   311 The MTM UID is NULL and the account ID is not valid.
       
   312 */
       
   313 void CSendAsMessage::DoCreateMessageL(TUid aMtm, TSendAsAccount aAccount)
       
   314 	{
       
   315 	// new context 
       
   316 	CMsvEntry* msvEntry = CMsvEntry::NewL(iSession.GetMsvSessionL(), aAccount, TMsvSelectionOrdering());
       
   317 	CleanupStack::PushL(msvEntry);
       
   318 	if( aMtm == KNullUid )
       
   319 		{
       
   320 		if( aAccount == KMsvRootIndexEntryId || msvEntry->Entry().iType != KUidMsvServiceEntry )
       
   321 			{
       
   322 			// not a valid account
       
   323 			User::Leave(KErrNotFound);
       
   324 			}
       
   325 		// get associated mtm uid
       
   326 		aMtm = msvEntry->Entry().iMtm;
       
   327 		}
       
   328 
       
   329 	// create mtm by uid	
       
   330 	DeleteClientMtm();
       
   331 	iClientMtm = iSession.GetClientMtmL(aMtm);
       
   332 	
       
   333 	// if no account provided, get default for this MTM
       
   334 	if( aAccount == KMsvRootIndexEntryId )
       
   335 		{
       
   336 		aAccount = iClientMtm->DefaultServiceL();
       
   337 		}
       
   338 	
       
   339 	// create message in drafts folder
       
   340 	msvEntry->SetEntryL(KMsvDraftEntryId);
       
   341 	
       
   342 	// mtm takes ownership of entry context	
       
   343 	CleanupStack::Pop(msvEntry);
       
   344 	iClientMtm->SetCurrentEntryL(msvEntry);
       
   345 
       
   346 	// create message
       
   347 	iClientMtm->CreateMessageL(aAccount);
       
   348 	iMessageType = aMtm;
       
   349 
       
   350 	// Change the context of the client MTM to the newly created message entry
       
   351 	iClientMtm->SwitchCurrentEntryL(iClientMtm->Entry().EntryId());
       
   352 
       
   353 	// Load the message created so far into the client MTMs cache. This ensures
       
   354 	// that SendAs will not overwrite any body text added during the
       
   355 	// CreateMessageL routine (such as signature text).
       
   356 	// Some MTMs don't actually write anything to store during the
       
   357 	// CreateMessageL phase, so the LoadMessageL can leave with KErrNotFound.
       
   358 	// It is safe to trap and ignore this as it just means there is no message
       
   359 	// body text to be loaded.
       
   360 	TRAPD(err, iClientMtm->LoadMessageL());
       
   361 
       
   362 	if (err != KErrNone && err != KErrNotFound)
       
   363 		{
       
   364 		User::Leave(err);
       
   365 		}
       
   366 
       
   367 	iState = EMessageCreated;
       
   368 	}
       
   369 
       
   370 /** Create a new message in the drafts folder, using the specified account.
       
   371 
       
   372 The account to use is passed from the client in a package buffer, held in
       
   373 parameter 0 of the message.
       
   374 
       
   375 @param	aMessage
       
   376 The IPC message.
       
   377 */
       
   378 void CSendAsMessage::CreateMessageForAccountL(const RMessage2& aMessage)
       
   379 	{
       
   380 	__ASSERT_ALWAYS( iState == EIdle, PanicClientL(aMessage, ESendAsClientPanicSubsessionInUse) );
       
   381 
       
   382 	TPckgBuf<TSendAsAccount> accountBuf;
       
   383 	aMessage.Read(0, accountBuf);
       
   384 
       
   385 	DoCreateMessageL(KNullUid, accountBuf()); 
       
   386 	}
       
   387 	
       
   388 /** Create a new message in the drafts folder, of the specified type.
       
   389 
       
   390 The message type (a TUid) to create is passed from the client in a package buffer,
       
   391 held in parameter 0 of the message.
       
   392 
       
   393 @param	aMessage
       
   394 The IPC message.
       
   395 */
       
   396 void CSendAsMessage::CreateMessageByTypeL(const RMessage2& aMessage)
       
   397 	{
       
   398 	__ASSERT_ALWAYS( iState == EIdle, PanicClientL(aMessage, ESendAsClientPanicSubsessionInUse) );
       
   399 	
       
   400 	// extract mtm uid
       
   401 	TPckgBuf<TUid> uidBuf;
       
   402 	aMessage.Read(0, uidBuf);
       
   403 
       
   404 	// create message using default account for this mtm
       
   405 	DoCreateMessageL(uidBuf());
       
   406 	}
       
   407 	
       
   408 /** Delete the open message from the drafts folder.
       
   409 @param aMessage
       
   410 The IPC message.
       
   411 */
       
   412 void CSendAsMessage::DeleteMessageL(const RMessage2& aMessage)
       
   413 	{
       
   414 	// Client code should cancel any outstanding requests prior to deleting
       
   415 	// the message. Failure to do so will result in the client being panicked.
       
   416 	switch (iState)
       
   417 		{
       
   418 	case EMessageCreated:
       
   419 		{
       
   420 		__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   421 		
       
   422 		iClientMtm->Session().RemoveEntry(iClientMtm->Entry().EntryId());
       
   423 		iState = EMessageDeleted;
       
   424 		} break;
       
   425 	case EIdle:
       
   426 	case ESendingMessageComplete:
       
   427 	case EPendingClose:
       
   428 		break;
       
   429 	case ESendingMessage:
       
   430 		{
       
   431 		PanicClientL(aMessage, ESendAsClientPanicSendingMessage);
       
   432 		} break;
       
   433 	case EAddingOrCreatingAttachment:
       
   434 		{
       
   435 		PanicClientL(aMessage, ESendAsClientPanicAddingCreatingAttachment);
       
   436 		} break;
       
   437 	case EMessageDeleted:
       
   438 	default:
       
   439 		PanicClientL(aMessage, ESendAsClientPanicMessageAlreadyDeleted);
       
   440 		break;
       
   441 		}
       
   442 
       
   443 	DeleteClientMtm();
       
   444 	}
       
   445 	
       
   446 /** Set the body text of the open message.
       
   447 
       
   448 The body text is specified using a CRichText object. This object is streamed 
       
   449 into a descriptor which is passed over the IPC boundary in parameter 0 of the
       
   450 message. The CRichText object is then internalised by the server.
       
   451 
       
   452 @param	aMessage
       
   453 The IPC message.
       
   454 
       
   455 @param	aFirstChunk
       
   456 A flag that indicates whether this is the first chunk of rich text received 
       
   457 from the client.
       
   458 */
       
   459 void CSendAsMessage::SetBodyTextL(const RMessage2& aMessage, TBool aFirstChunk)
       
   460 	{
       
   461 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   462 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   463 
       
   464 	TInt response = 0;
       
   465 	User::LeaveIfError(iClientMtm->QueryCapability(KUidMtmQuerySupportedBody, response));
       
   466 
       
   467 	// This location in the body text at which the text is to be inserted.
       
   468 	TInt insertLoc = 0;
       
   469 
       
   470 	if( aFirstChunk )
       
   471 		{
       
   472 		// Store the size of the signature text. This is added to the body
       
   473 		// text on creation of the message by the client MTM.
       
   474 		// All added body text is to be added before the signature text.
       
   475 		iSignatureSize = iClientMtm->Body().DocumentLength();
       
   476 		}
       
   477 	else
       
   478 		{
       
   479 		// insert added text before the signature text.
       
   480 		insertLoc = iClientMtm->Body().DocumentLength() - iSignatureSize;
       
   481 		}
       
   482 
       
   483 	TInt chunkLength = User::LeaveIfError(aMessage.GetDesLength(0));
       
   484 	HBufC* textBuffer = GetDesParamLC(aMessage, 0);
       
   485 	// Append the next chunk to the mtm's CRichText object.
       
   486 	TRAPD(insertError, iClientMtm->Body().InsertL(insertLoc, *textBuffer));
       
   487 	if( insertError != KErrNone )
       
   488 		{
       
   489 		iClientMtm->Body().Reset();
       
   490 		User::Leave(insertError);
       
   491 		}
       
   492 	CleanupStack::PopAndDestroy(textBuffer);
       
   493 	}
       
   494 
       
   495 /** Set the subject of the open message.
       
   496 
       
   497 The subject is plain text, held in a descriptor passed in parameter 0 of the
       
   498 message.
       
   499 
       
   500 @param	aMessage
       
   501 The IPC message.
       
   502 */
       
   503 void CSendAsMessage::SetSubjectL(const RMessage2& aMessage)
       
   504 	{
       
   505 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   506 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   507 
       
   508 	HBufC* subject = GetDesParamLC(aMessage, 0);
       
   509 	iClientMtm->SetSubjectL(*subject);
       
   510 		
       
   511 	CleanupStack::PopAndDestroy(subject);
       
   512 	}
       
   513 	
       
   514 /** Set the BIO type of the message.
       
   515 
       
   516 The BIO type is passed from the client in a package buffer, pointed to by 
       
   517 parameter 0 of the message.
       
   518 
       
   519 @param	aMessage
       
   520 The IPC message.
       
   521 */
       
   522 void CSendAsMessage::SetBioTypeL(const RMessage2& aMessage)
       
   523 	{
       
   524 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   525 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   526 
       
   527 	TPckgBuf<TUid> uidBuf;
       
   528 	aMessage.Read(0, uidBuf);
       
   529 	iClientMtm->BioTypeChangedL(uidBuf());
       
   530 	
       
   531 	TUid bioTypeUid = uidBuf();
       
   532 	iClientMtm->SaveMessageL();
       
   533 
       
   534 	TMsvEntry tempEntry = iClientMtm->Entry().Entry(); 
       
   535 	tempEntry.iBioType = bioTypeUid.iUid;
       
   536 	iClientMtm->Entry().ChangeL(tempEntry);	
       
   537 	}
       
   538 
       
   539 /** Add a recipient (plus alias) to the message.
       
   540 
       
   541 The recipient's address is passed in a descriptor, pointed to by parameter 0 of
       
   542 the message.  The alias is also passed in as a descriptor, this time pointed to
       
   543 by parameter 1.
       
   544 
       
   545 The recipient type (which indicates if a recipient is a To, Cc or Bcc type) is
       
   546 passed inside a package buffer pointed to by parameter 2.
       
   547 
       
   548 @param	aMessage
       
   549 The IPC message.
       
   550 */
       
   551 void CSendAsMessage::AddRecipientWithAliasL(const RMessage2& aMessage)
       
   552 	{
       
   553 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   554 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   555 	
       
   556 	HBufC* address = GetDesParamLC(aMessage, 0);
       
   557 	HBufC* alias = GetDesParamLC(aMessage, 1);
       
   558 
       
   559 	TPckgBuf<RSendAsMessage::TSendAsRecipientType> recipientTypeBuf;
       
   560 	aMessage.Read(2, recipientTypeBuf);
       
   561 
       
   562 	// client MTM manages handling of Bcc recipients
       
   563 	iClientMtm->AddAddresseeL(recipientTypeBuf(), *address, *alias);
       
   564 	
       
   565 	CleanupStack::PopAndDestroy(2, address); // alias, address
       
   566 	}
       
   567 	
       
   568 /** Add a recipient to the message.
       
   569 
       
   570 The recipient's address is passed in a descriptor, pointed to by parameter 0 of
       
   571 the message.
       
   572 
       
   573 The recipient type (which indicates if a recipient is a To, Cc or Bcc type) is
       
   574 passed inside a package buffer pointed to by parameter 1.
       
   575 
       
   576 @param	aMessage
       
   577 The IPC message.
       
   578 */
       
   579 void CSendAsMessage::AddRecipientL(const RMessage2& aMessage)
       
   580 	{
       
   581 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   582 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   583 
       
   584 	HBufC* address = GetDesParamLC(aMessage, 0);
       
   585 	
       
   586 	TPckgBuf<RSendAsMessage::TSendAsRecipientType> recipientTypeBuf;
       
   587 	aMessage.Read(1, recipientTypeBuf);
       
   588 
       
   589 	// call new implementation - let it manage handling of Bcc recipients
       
   590 	iClientMtm->AddAddresseeL(recipientTypeBuf(), *address);
       
   591 
       
   592 	CleanupStack::PopAndDestroy(address);
       
   593 	}
       
   594 	
       
   595 /** Prepare the message for subsequent add or create attachment operations.
       
   596 
       
   597 @param	aMessage
       
   598 The IPC message.
       
   599 */
       
   600 void CSendAsMessage::PrepareAddCreateAttachmentL(const RMessage2& aMessage)
       
   601 	{
       
   602 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   603 	
       
   604 	// delete any orphaned attachment object.
       
   605 	delete iAttachment;
       
   606 	iAttachment = NULL;
       
   607 
       
   608 	// queue the IPC message - used to notify the client when the attachment 
       
   609 	// operation is complete.
       
   610 	iQueuedMessage = aMessage;
       
   611 	iAttachment = CSendAsAttachment::NewL(*this, *iClientMtm);
       
   612 	}
       
   613 
       
   614 /** Take ownership of the RFile attachment
       
   615 
       
   616 @param	aMessage
       
   617 The IPC message.
       
   618 */
       
   619 void CSendAsMessage::TransferAttachmentFileL(const RMessage2& aMessage)
       
   620 	{
       
   621 	// Close if left open previously.
       
   622 	iAttachmentFile.Close();
       
   623 
       
   624 	// need to adopt the file from the client.
       
   625 	User::LeaveIfError(iAttachmentFile.AdoptFromClient(aMessage, 0, 1));
       
   626 	}
       
   627 	
       
   628 /** Add an attachment to the message.
       
   629 
       
   630 The attachment added to the message is copied into a new attachment by the
       
   631 message server.  The new attachment lives in the message store which is private
       
   632 to the msg server.
       
   633 
       
   634 The client must pass a file handle over to the server.  The server assumes that
       
   635 this handle allows it to have read access to the open file once it has been adopted.
       
   636 
       
   637 The file handles are passed over in the usual manner.
       
   638 
       
   639 @param	aMessage
       
   640 The IPC message.
       
   641 */
       
   642 void CSendAsMessage::AddAttachmentL(const RMessage2& aMessage)
       
   643 	{
       
   644 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   645 
       
   646 	PrepareAddCreateAttachmentL(aMessage);
       
   647 	iAttachment->AddExistingFileAttachmentL(iAttachmentFile);
       
   648 	iState = EAddingOrCreatingAttachment;
       
   649 	}
       
   650 	
       
   651 /** Add an attachment to the message.
       
   652 
       
   653 The attachment added to the message is copied into a new attachment by the
       
   654 message server.  The new attachment lives in the message store which is private
       
   655 to the msg server.
       
   656 
       
   657 The client must pass a file handle over to the server.  The server assumes that
       
   658 this handle allows it to have read access to the open file once it has been adopted.
       
   659 
       
   660 The mime type of the attachment is specified in aMessage parameter 2.
       
   661 
       
   662 The file handles are passed over in the usual manner.
       
   663 
       
   664 @param	aMessage
       
   665 The IPC message.
       
   666 */
       
   667 void CSendAsMessage::AddAttachmentWithMimeTypeL(const RMessage2& aMessage)
       
   668 	{
       
   669 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   670 
       
   671 	HBufC8* mimeType = GetDesParam8LC(aMessage, 0);
       
   672 	TUint charset = aMessage.Int1();
       
   673 
       
   674 	PrepareAddCreateAttachmentL(aMessage);
       
   675 	iAttachment->AddExistingFileAttachmentWithMimeTypeL(iAttachmentFile, *mimeType, charset);
       
   676 	iState = EAddingOrCreatingAttachment;
       
   677 
       
   678 	CleanupStack::PopAndDestroy(mimeType);
       
   679 	}
       
   680 	
       
   681 /** Add an attachment to the message.
       
   682 
       
   683 The filename of the attachment is linked to the message.
       
   684 
       
   685 The file must be in a location which the message server is able to read and it
       
   686 must also remain until the message has been sent or deleted.
       
   687 
       
   688 @param	aMessage
       
   689 The IPC message.
       
   690 */
       
   691 void CSendAsMessage::AddLinkedAttachmentL(const RMessage2& aMessage)
       
   692 	{
       
   693 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   694 
       
   695 	HBufC* fileName = GetDesParamLC(aMessage, 0);
       
   696 	
       
   697 	PrepareAddCreateAttachmentL(aMessage);
       
   698 	iAttachment->AddFileLinkAttachmentL(*fileName);
       
   699 	iState = EAddingOrCreatingAttachment;
       
   700 	
       
   701 	CleanupStack::PopAndDestroy(fileName);
       
   702 	}
       
   703 
       
   704 /** Add an attachment to the message.
       
   705 
       
   706 The filename of the attachment is linked to the message.
       
   707 
       
   708 The file must be in a location which the message server is able to read and it
       
   709 must also remain until the message has been sent or deleted.
       
   710 
       
   711 The mime type of the linked file is supplied.
       
   712 
       
   713 @param	aMessage
       
   714 The IPC message.
       
   715 */
       
   716 void CSendAsMessage::AddLinkedAttachmentWithMimeTypeL(const RMessage2& aMessage)
       
   717 	{
       
   718 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   719 
       
   720 	HBufC* fileName = GetDesParamLC(aMessage, 0);
       
   721 	HBufC8* mimeType = GetDesParam8LC(aMessage, 1);
       
   722 	TUint charset = aMessage.Int2();
       
   723 	
       
   724 	PrepareAddCreateAttachmentL(aMessage);
       
   725 	iAttachment->AddFileLinkAttachmentWithMimeTypeL(*fileName, *mimeType, charset);
       
   726 	iState = EAddingOrCreatingAttachment;
       
   727 	
       
   728 	CleanupStack::PopAndDestroy(2, fileName); // mimeType, fileName
       
   729 	}
       
   730 	
       
   731 /** Create an empty attachment in the open message.
       
   732 
       
   733 The SendAs server makes the empty attachment and returns a file handle to the
       
   734 client ready for writing.
       
   735 
       
   736 @param	aMessage
       
   737 The IPC message.
       
   738 */
       
   739 void CSendAsMessage::CreateAttachmentL(const RMessage2& aMessage)
       
   740 	{
       
   741 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   742 
       
   743 	HBufC* fileName = GetDesParamLC(aMessage, 1);
       
   744 
       
   745 	PrepareAddCreateAttachmentL(aMessage);
       
   746 	iAttachment->CreateNewFileAttachmentL(iAttachmentFile, *fileName);
       
   747 	iState = EAddingOrCreatingAttachment;
       
   748 
       
   749 	CleanupStack::PopAndDestroy(fileName);
       
   750 	}
       
   751 
       
   752 /** Create an empty attachment in the open message.
       
   753 
       
   754 The mime type of the attachment is specified.
       
   755 
       
   756 The SendAs server makes the empty attachment and returns a file handle to the
       
   757 client ready for writing.
       
   758 
       
   759 @param	aMessage
       
   760 The IPC message.
       
   761 */
       
   762 void CSendAsMessage::CreateAttachmentWithMimeTypeL(const RMessage2& aMessage)
       
   763 	{
       
   764 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   765 
       
   766 	HBufC* fileName = GetDesParamLC(aMessage, 1);
       
   767 		
       
   768 	HBufC8* mimeType = GetDesParam8LC(aMessage, 2);
       
   769 		
       
   770 	PrepareAddCreateAttachmentL(aMessage);
       
   771 	iAttachment->CreateNewFileAttachmentWithMimeTypeL(iAttachmentFile, *fileName, *mimeType, iCharSet);
       
   772 	iState = EAddingOrCreatingAttachment;
       
   773 		
       
   774 	CleanupStack::PopAndDestroy(2, fileName); // mimeType, fileName
       
   775 	}	
       
   776 
       
   777 void CSendAsMessage::SetCharsetInfoForAttachment(const RMessage2& aMessage)
       
   778 	{
       
   779 	iCharSet = aMessage.Int0();
       
   780 	}	
       
   781 
       
   782 
       
   783 /** Cancel any asynchronous activity being done by the message.
       
   784 
       
   785 @param	aMessage
       
   786 The IPC message.
       
   787 */
       
   788 void CSendAsMessage::Cancel()
       
   789 	{
       
   790 	CancelMessage();
       
   791 	}
       
   792 	
       
   793 /** Launch the message editor for the open message.
       
   794 
       
   795 @param	aMessage
       
   796 The IPC message.
       
   797 */
       
   798 void CSendAsMessage::LaunchEditorL(const RMessage2& aMessage)
       
   799 	{
       
   800 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   801 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   802 
       
   803 	iClientMtm->SaveMessageL();
       
   804 		
       
   805 	// the observer and owner is the SendAs Server, via active container.
       
   806 	CSendAsEditWatcher* editWatcher = CSendAsEditWatcher::NewL(iSession.ActiveContainer(), iSession.EditUtilsPluginUid());
       
   807 	iSession.ActiveContainer().AddEditWatcherL(*editWatcher);
       
   808 
       
   809 	TMsvId entryId = iClientMtm->Entry().EntryId();	
       
   810 	DeleteClientMtm();
       
   811 	editWatcher->LaunchEditorL(entryId);
       
   812 
       
   813 	iState = EPendingClose;
       
   814 	}
       
   815 		
       
   816 /** Send the message.
       
   817 
       
   818 This method handles both confirmed and unconfirmed sends. If an unconfirmed send
       
   819 is attempted but the client does not have the MTM-required capabilities then the
       
   820 send will be downgraded to a confirmed send.
       
   821 
       
   822 @param	aMessage
       
   823 The IPC message.
       
   824 
       
   825 @param	aConfirmed
       
   826 A value of true indicates that the send should be confirmed.
       
   827 
       
   828 @param	aBackground
       
   829 A value of true indicates that the send should be done in the background. This
       
   830 implies that the client does not wish to be notified of the progress of the send.
       
   831 
       
   832 @leave KErrNotSupported
       
   833 The client MTM does not support SendAs message sending.
       
   834 */
       
   835 void CSendAsMessage::SendMessageL(const RMessage2& aMessage, TBool aConfirmed, TBool aBackground)
       
   836 	{
       
   837 	__ASSERT_ALWAYS( iState == EMessageCreated, PanicClientL(aMessage, ESendAsClientPanicNoCurrentMessage) );
       
   838 	__ASSERT_DEBUG( iClientMtm != NULL, User::Invariant() );
       
   839 
       
   840 #if (defined SYMBIAN_USER_PROMPT_SERVICE)		
       
   841 	TBool hasCapability = EFalse;	
       
   842 #endif
       
   843 	// for unconfirmed send, check capabilities of client
       
   844 	if( !aConfirmed )
       
   845 		{
       
   846 		VerifyCallerCapabilitiesL(aMessage, aConfirmed);
       
   847 #if (defined SYMBIAN_USER_PROMPT_SERVICE)		
       
   848 		if(!aConfirmed)
       
   849 			{
       
   850 			hasCapability = ETrue;
       
   851 			}
       
   852 #endif			
       
   853 		}
       
   854 		
       
   855 
       
   856 	TBool result = KErrNone;
       
   857 	if( iClientMtm->QueryCapability(KUidMtmQuerySendAsMessageSendSupport, result) == KErrNotSupported )
       
   858 		{
       
   859 		User::Leave(KErrNotSupported);
       
   860 		}
       
   861 	// save message	
       
   862 	DoSaveMessageL();
       
   863 
       
   864 	// create the sender obejct
       
   865 	CSendAsSender* sender = NULL;
       
   866 	if( aBackground )
       
   867 		{
       
   868 		// this a background send - the observer and owner is the active container.
       
   869 		sender = CSendAsSender::NewL(iSession.ActiveContainer());
       
   870 		iSession.ActiveContainer().AddSenderL(*sender);
       
   871 		
       
   872 		iState = ESendingMessageComplete;
       
   873 		}
       
   874 	else
       
   875 		{
       
   876 		// this is a non-background send - the observer and owner is the send-as
       
   877 		// message.
       
   878 		delete iSender;
       
   879 		iSender = NULL;
       
   880 		
       
   881 		sender	= CSendAsSender::NewL(*this);
       
   882 		iSender = sender;
       
   883 		
       
   884 		// queue the IPC message - used to notify the client when the send is complete
       
   885 		iQueuedMessage = aMessage;
       
   886 		
       
   887 		iState = ESendingMessage;
       
   888 		}
       
   889 	// new sender takes ownership of the client MTM
       
   890 	sender->SetClientMtm(*iClientMtm);
       
   891 		
       
   892 #if (defined SYMBIAN_USER_PROMPT_SERVICE)	
       
   893 	TRAPD(err, sender->SendMessageL(aMessage, hasCapability));
       
   894 	if(err!=KErrNone)
       
   895 		{
       
   896 		// There was a error while sending the message... so delete the entry
       
   897 		iClientMtm->Session().RemoveEntry(iClientMtm->Entry().EntryId());
       
   898 		iClientMtm = NULL;
       
   899 		iState = ESendingMessageComplete;
       
   900 		User::Leave(err);
       
   901 		}
       
   902 	iClientMtm = NULL;	
       
   903 #else
       
   904 	iClientMtm = NULL;
       
   905 	if( aConfirmed )
       
   906 		{
       
   907 		TSecurityInfo securityInfo(aMessage);
       
   908 		sender->SendMessage(securityInfo, iSession.NotifierUid());
       
   909 		}
       
   910 	else
       
   911 		{
       
   912 		sender->SendMessage();
       
   913 		}
       
   914 #endif	
       
   915 	}
       
   916 	
       
   917 void CSendAsMessage::DeleteClientMtm()
       
   918 	{
       
   919 	delete iClientMtm;
       
   920 	iClientMtm = NULL;
       
   921 	}
       
   922 
       
   923 /** Get progress information 
       
   924 
       
   925 Used to provide progress information to the client. 
       
   926 
       
   927 1. Before sending, the progress is set to ESendStateInPreparation.
       
   928  
       
   929 2. Whilst sending, the progress is obtained from the send operation.
       
   930 
       
   931 3. After sending, the final progress is returned to the client (always a TMsvSendOperationProgress).
       
   932 
       
   933 @param	aMessage
       
   934 The IPC message.
       
   935 */
       
   936 void CSendAsMessage::ProgressL(const RMessage2& aMessage)
       
   937 	{
       
   938 	switch( iState )
       
   939 		{
       
   940 	case EIdle:
       
   941 	case EMessageCreated:
       
   942 	case EAddingOrCreatingAttachment:
       
   943 	case EMessageDeleted:
       
   944 	case EPendingClose:
       
   945 		{
       
   946 		iProgress().iState = CMsvSendOperation::ESendStateInPreparation;
       
   947 		iProgress().iError = KErrNone;
       
   948 		iProgress().iProgressMax = 0;
       
   949 		iProgress().iProgress = 0;
       
   950 		} break;
       
   951 	case ESendingMessage:
       
   952 		{
       
   953 		__ASSERT_DEBUG( iSender != NULL, User::Invariant() );
       
   954 
       
   955 		iSender->ProgressL(iProgress);
       
   956 		} break;
       
   957 	case ESendingMessageComplete:
       
   958 		{
       
   959 		// return the final progress 
       
   960 		if( iProgress().iError == KErrNone )
       
   961 			{
       
   962 			iProgress().iState = CMsvSendOperation::ESendStateDone;
       
   963 			}
       
   964 		else
       
   965 			{
       
   966 			iProgress().iState = CMsvSendOperation::ESendStateFailed;
       
   967 			}
       
   968 		} break;
       
   969 	default:
       
   970 		User::Invariant();
       
   971 		break;
       
   972 		}
       
   973 
       
   974 	aMessage.WriteL(0, iProgress);
       
   975 	}
       
   976 
       
   977 /** Verify that the client has the required capabilities to use the server MTM
       
   978 to send this message unconfirmed. Otherwise changes request to confirmed send.
       
   979 
       
   980 @param	aMessage
       
   981 The IPC message.
       
   982 */
       
   983 void CSendAsMessage::VerifyCallerCapabilitiesL(const RMessage2& aMessage, TBool& aConfirmed)
       
   984 	{
       
   985 	// get required capabilities
       
   986 	TCapabilitySet caps;
       
   987 	iClientMtm->Session().GetMtmRequiredCapabilitiesL(iMessageType, caps);
       
   988 
       
   989 	// get client thread capabilities
       
   990 	TSecurityInfo securityInfo(aMessage);
       
   991 	
       
   992 	// check client capabilities with required capabilities
       
   993 	if( !securityInfo.iCaps.HasCapabilities(caps) )
       
   994 		{
       
   995 		// fail capability check...
       
   996 		caps.Remove(securityInfo.iCaps);
       
   997 		PlatSec::CapabilityCheckFail(aMessage, caps, __PLATSEC_DIAGNOSTIC_STRING("Unconfirmed send downgraded to confirmed by CSendAsMessage::VerifyCallerCapabilitiesL"));
       
   998 		aConfirmed = ETrue;
       
   999 		}
       
  1000 	}
       
  1001 
       
  1002 /** Panic the client
       
  1003 
       
  1004 @param	aMessage
       
  1005 The IPC message.
       
  1006 
       
  1007 @param aPanic
       
  1008 The panic code.
       
  1009 */
       
  1010 void CSendAsMessage::PanicClientL(const RMessage2& aMessage, TSendAsClientPanic aPanic) const
       
  1011 	{
       
  1012 	iSession.PanicClient(aMessage, aPanic);
       
  1013 	}
       
  1014 
       
  1015 /*
       
  1016  *	Methods from MSendAsSenderObserver
       
  1017  */
       
  1018  
       
  1019 /** Notify the client that the send has completed
       
  1020 
       
  1021 @param	aError
       
  1022 The error code.
       
  1023 */
       
  1024 void CSendAsMessage::SenderComplete(TInt aError)
       
  1025 	{
       
  1026 	__ASSERT_ALWAYS( iState == ESendingMessage, User::Invariant() );
       
  1027 	__ASSERT_DEBUG( iSender != NULL, User::Invariant() );
       
  1028 
       
  1029 	// get final progress from the sender.
       
  1030 	iSender->FinalProgress(iProgress);
       
  1031 	
       
  1032 	// capture error
       
  1033 	if( iProgress().iError == KErrNone )
       
  1034 		{
       
  1035 		iProgress().iError = aError;
       
  1036 		}
       
  1037 	// notify the client that the send has completed - always complete with 
       
  1038 	// KErrNone as actual error is in the progress.
       
  1039 	iQueuedMessage.Complete(KErrNone);
       
  1040 	
       
  1041 	// Set the state to complete so we can call FinalProgress
       
  1042 	iState = ESendingMessageComplete;
       
  1043 	}
       
  1044 
       
  1045 /*
       
  1046  *	Methods from MSendAsAttachmentObserver
       
  1047  */
       
  1048 
       
  1049 /** Notify the client that the attachment operation has completed
       
  1050 
       
  1051 If the message is complete, the client is notified, otherwise the created
       
  1052 attachment is transferred to the client.
       
  1053 
       
  1054 @param	aError
       
  1055 The error code.
       
  1056 
       
  1057 @param	aCompleteMessage
       
  1058 Indicates if the message is complete.
       
  1059 */
       
  1060 void CSendAsMessage::AttachmentCompleteL(TInt aError, TBool aCompleteMessage)
       
  1061 	{
       
  1062 	__ASSERT_ALWAYS( iState == EAddingOrCreatingAttachment, User::Invariant() );
       
  1063 	
       
  1064 	// notify the client that the attachment operation has completed - if an
       
  1065 	// error has occurred the error code is returned in the complete status.
       
  1066 	if (aCompleteMessage)
       
  1067 		{
       
  1068 		iQueuedMessage.Complete(aError);
       
  1069 		}
       
  1070 	else
       
  1071 		{
       
  1072 		// transfer the created file to the client. Argument 0 of iQueuedMessage
       
  1073 		// contains the address to which the client should receive the file handle.
       
  1074 		User::LeaveIfError(iAttachmentFile.TransferToClient(iQueuedMessage, 0));
       
  1075 		iAttachmentFile.Close();
       
  1076 		}
       
  1077 	// the attachment file is now closed - set it to a blank RFile so that any 
       
  1078 	// later closes don't panic.
       
  1079 	iAttachmentFile = RFile();
       
  1080 	
       
  1081 	// The client can continue editing the message - move to appropriate state
       
  1082 	// and delete attachment object
       
  1083 
       
  1084 	// Delete the attachment object after use. If this is a notification of a 
       
  1085 	// cancel then the delete should happen after the cancel operation to avoid
       
  1086 	// a second cancel in the attachment object's destructor.
       
  1087 	if( aError != KErrCancel )
       
  1088 		{
       
  1089 		delete iAttachment;
       
  1090 		iAttachment = NULL;
       
  1091 		}
       
  1092 
       
  1093 	iState = EMessageCreated;
       
  1094 	}
       
  1095 
       
  1096 /** Sets the message entry's Visible flag to ETrue and inPreparation flag to EFalse 
       
  1097 saves the message, commits the changes  
       
  1098 */
       
  1099 
       
  1100 void CSendAsMessage::DoSaveMessageL() 
       
  1101     {     
       
  1102     iClientMtm->SaveMessageL();
       
  1103   
       
  1104     // set the InPreparation to false and visible to true
       
  1105     TMsvEntry tempEntry= iClientMtm->Entry().Entry();
       
  1106     tempEntry.iDate.UniversalTime();
       
  1107     tempEntry.SetVisible(ETrue);
       
  1108     tempEntry.SetInPreparation(EFalse);
       
  1109      
       
  1110     iClientMtm->Entry().ChangeL(tempEntry);
       
  1111     }
       
  1112 
       
  1113 /** 
       
  1114 Sets the character encoding value. The character encoding value options are 7-bit,
       
  1115 8-bit and 16-Bit Unicode. By default the character set encoding is 7 bit encoding.
       
  1116 It call the MTM functionality for setting the charset value.
       
  1117 @param	aMessage	The IPC message.
       
  1118 @return void
       
  1119 */
       
  1120    
       
  1121 void CSendAsMessage::SetMessageCharacterSetL(const RMessage2& aMessage)
       
  1122 	{
       
  1123 	TInt err =	iClientMtm->SetMessageCharacterSet(aMessage.Int0());
       
  1124 	TPckgBuf<TInt> pckg = err;
       
  1125 	aMessage.WriteL(1,pckg);
       
  1126 	}