diff -r 84d9eb65b26f -r 2981cb3aa489 email/mail/UtilsSrc/MsgMailAppUi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/email/mail/UtilsSrc/MsgMailAppUi.cpp Wed Nov 03 09:52:46 2010 +0530 @@ -0,0 +1,1424 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: A common base class for Mail application ui classes. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include + +#include +#include // CImHeader +#include // CMsvEntry +#include // CImEmailMessage +#include +#include +#include // RConeResourceLoader +#include // ContentPolicy +#include // MUIU MTM utils + + + + +#include +#include +#include // FeatureManager +#include +#include +#include +#include +#include + +// Editor base classes: +#include +#include +#include +#include +#include +#include + +#include // CMuiuOperationWait +#include + +#include +#include "MsgMailAppUi.h" +#include "MsgMailDocument.h" +#include "MsgMailPreferences.h" +#include "MailUtils.h" + +// Mail Central Repository handler +#include "CMailCRHandler.h" + +// LOCAL CONSTANTS AND MACROS + +_LIT(KResourcesWithDir,"z:MsgMailUtils.rSC"); +_LIT( KMsgMailMBMFileName, "z:msgmailutils.mbm" ); +/// Message details item separator. +_LIT( KMsgDetailsSeparator, "; " ); +/// Max length used for message details. +const TInt KMsgMaxDetailsLength = 128; + +// LOCAL FUNCTION PROTOTYPES +typedef TBool (*TParseFunc)( TLex& aLex ); +LOCAL_C TBool DoOrReverse( TParseFunc aFunc, TLex& aLex ); +LOCAL_C TBool Star( TParseFunc aFunc, TLex& aLex ); +LOCAL_C TBool Plus( TParseFunc aFunc, TLex& aLex ); +LOCAL_C TBool NoWSCtl( TLex& aLex ); +LOCAL_C TBool WSP( TLex& aLex ); +LOCAL_C TBool FWS( TLex& aLex ); +LOCAL_C TBool CText( TLex& aLex ); +LOCAL_C TBool QuotedPair( TLex& aLex ); +LOCAL_C TBool FWSCContent( TLex& aLex ); +LOCAL_C TBool CContent( TLex& aLex ); +LOCAL_C TBool Comment( TLex& aLex ); +LOCAL_C TBool CFWS( TLex& aLex ); +LOCAL_C TBool AText( TLex& aLex ); +LOCAL_C TBool Atom( TLex& aLex ); +LOCAL_C TBool DotAtomText( TLex& aLex ); +LOCAL_C TBool DotAtom( TLex& aLex ); +LOCAL_C TBool DotPlusAText( TLex& aLex ); +LOCAL_C TBool QText( TLex& aLex ); +LOCAL_C TBool QContent( TLex& aLex ); +LOCAL_C TBool FWSQContent( TLex& aLex ); +LOCAL_C TBool QuotedString( TLex& aLex ); +LOCAL_C TBool LocalPart( TLex& aLex ); +LOCAL_C TBool DText( TLex& aLex ); +LOCAL_C TBool DContent( TLex& aLex ); +LOCAL_C TBool DomainLiteral( TLex& aLex ); +LOCAL_C TBool Domain( TLex& aLex ); +LOCAL_C TBool FWSDContent( TLex& aLex ); +LOCAL_C TBool AddrSpec( TLex& aLex ); +LOCAL_C TBool Word( TLex& aLex ); +LOCAL_C TBool DisplayName( TLex& aLex ); +LOCAL_C TBool CommaMailbox( TLex& aLex ); +LOCAL_C TBool AngleAddr( TLex& aLex ); +LOCAL_C TBool NameAddr( TLex& aLex ); +LOCAL_C TBool Mailbox( TLex& aLex ); +LOCAL_C TBool MailboxList( TLex& aLex ); +LOCAL_C TBool Group( TLex& aLex ); +LOCAL_C TBool Address( TLex& aLex ); + +// ==================== LOCAL FUNCTIONS ==================== + +// ---------------------------------------------------- +// DoOrReverse() +// Calls aFunc. If it fails, the lexer is returned to +// the state before calling DoOrReverse(). +// ---------------------------------------------------- +// +LOCAL_C TBool DoOrReverse( TParseFunc aFunc, TLex& aLex ) + { + TLexMark mark; + aLex.Mark( mark ); + if( (*aFunc)(aLex) ) + { + return ETrue; + } + else + { + aLex.UnGetToMark( mark ); + return EFalse; + } + } + +// ---------------------------------------------------- +// Star() +// Calls aFunc repeatedly until aFunc returns EFalse. +// The lexer is left to the state where it was after +// the last succesful aFunc call. Returns ETrue if +// at least one call to aFunc succeeded. +// ---------------------------------------------------- +// +LOCAL_C TBool Star( TParseFunc aFunc, TLex& aLex ) + { + TBool hasMore( ETrue ); + TBool hasOne( EFalse ); + while( hasMore ) + { + if( DoOrReverse( aFunc, aLex ) ) + { + hasOne = ETrue; + } + else + { + hasMore = EFalse; + } + } + + return hasOne; + } + +// ---------------------------------------------------- +// Like Star() except enforces one succesful call +// to aFunc. +// ---------------------------------------------------- +// +LOCAL_C TBool Plus( TParseFunc aFunc, TLex& aLex ) + { + if( !DoOrReverse( aFunc, aLex ) ) + { + return EFalse; + } + + Star( aFunc, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// NO-WS-CTL := %d1-8 / %d11 / %d12 / %d14-31 / %d127 ; US-ASCII +// control characters that do not include the carriage return, +// line feed, and white space characters +// ---------------------------------------------------- +// +LOCAL_C TBool NoWSCtl( TLex& aLex ) + { + TChar ch( aLex.Get() ); + return ( (ch >= 1 && ch <= 8) // CSI: 47 # See a comment above. + || ch == 11 // CSI: 47 # See a comment above. + || ch == 12 // CSI: 47 # See a comment above. + || (ch >= 14 && ch <= 31) // CSI: 47 # See a comment above. + || ch == 127 ); // CSI: 47 # See a comment above. + } + + +// ---------------------------------------------------- +// text := %d1-9 / %d11 / %d12 / %d14-127 / obs-text ; Characters excluding CR and LF +// ---------------------------------------------------- +// +LOCAL_C TBool Text( TLex& aLex ) + { + TChar ch( aLex.Get() ); + return ( (ch >= 1 && ch <= 9) // CSI: 47 # See a comment above. + || ch == 11 // CSI: 47 # See a comment above. + || ch == 12 // CSI: 47 # See a comment above. + || (ch >= 14 && ch <= 127) ); // CSI: 47 # See a comment above. + } + +// ---------------------------------------------------- +// quoted-pair := ("\" text) / obs-qp +// ---------------------------------------------------- +// +LOCAL_C TBool QuotedPair( TLex& aLex ) + { + if( aLex.Get() != '\\' ) + { + return EFalse; + } + + return Text( aLex ); + } + +// ---------------------------------------------------- +// WSP = SPACE / HTAB +// ---------------------------------------------------- +// +LOCAL_C TBool WSP( TLex& aLex ) + { + TChar ch( aLex.Get() ); + return ch == EKeySpace || ch == EKeyTab; + } + +// ---------------------------------------------------- +// FWS := ([*WSP CRLF] 1*WSP) / obs-FWS ; Folding white space +// ---------------------------------------------------- +// +LOCAL_C TBool FWS( TLex& aLex ) + { + return Plus( WSP, aLex ); + } + +// ---------------------------------------------------- +// ctext := NO-WS-CTL / %d33-39 / %d42-91 / %d93-126 ; Non white space +// controls and The rest of the US-ASCII characters not including "(", ")", or "\" +// ---------------------------------------------------- +// +LOCAL_C TBool CText( TLex& aLex ) + { + if( !DoOrReverse( NoWSCtl, aLex ) ) + { + TChar ch( aLex.Get() ); + return( (ch >= 33 && ch <= 39) // CSI: 47 # See a comment above. + || (ch >= 42 && ch <= 91) // CSI: 47 # See a comment above. + || (ch >= 93 && ch <= 126) ); // CSI: 47 # See a comment above. + } + else + { + return ETrue; + } + } + +// ---------------------------------------------------- +// ccontent := ctext / quoted-pair / comment +// ---------------------------------------------------- +// +LOCAL_C TBool CContent( TLex& aLex ) + { + return DoOrReverse( CText, aLex ) || DoOrReverse( QuotedPair, aLex ) || Comment( aLex ); + } + +// ---------------------------------------------------- +// [FWS] ccontent +// ---------------------------------------------------- +// +LOCAL_C TBool FWSCContent( TLex& aLex ) + { + FWS( aLex ); + return CContent( aLex ); + } + +// ---------------------------------------------------- +// comment := "(" *([FWS] ccontent) [FWS] ")" +// ---------------------------------------------------- +// +LOCAL_C TBool Comment( TLex& aLex ) + { + if( aLex.Get() != '(' ) + { + return EFalse; + } + + Star( FWSCContent, aLex ); + FWS( aLex ); + return aLex.Get() == ')'; + } + +// ---------------------------------------------------- +// [FWS] comment +// ---------------------------------------------------- +// +LOCAL_C TBool FWSComment( TLex& aLex ) + { + FWS( aLex ); + return Comment( aLex ); + } + +// ---------------------------------------------------- +// CFWS := *([FWS] comment) (([FWS] comment) / FWS) +// ---------------------------------------------------- +// +LOCAL_C TBool CFWS( TLex& aLex ) + { + TBool hasOne( Star( FWSComment, aLex ) ); + + return hasOne || FWS( aLex ); + } + +// ---------------------------------------------------- +// atext := ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / +// "-" / "/" / "=" / "?" "^" / "_" / "`" / "{" / "|" / "}" / "~"; Any +// character except controls, SP, and specials. Used for atoms +// ---------------------------------------------------- +// +LOCAL_C TBool AText( TLex& aLex ) + { + //ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" "^" / "_" / + // "`" / "{" / "|" / "}" / "~" + TChar ch( aLex.Get() ); + return( (ch >= 'a' && ch <= 'z' ) + || (ch >= 'A' && ch <= 'Z' ) + || (ch >= '0' && ch <= '9' ) + || ch == '!' + || ch == '#' + || ch == '$' + || ch == '%' + || ch == '&' + || ch == '\'' + || ch == '*' + || ch == '+' + || ch == '-' + || ch == '/' + || ch == '=' + || ch == '?' + || ch == '^' + || ch == '_' + || ch == '`' + || ch == '{' + || ch == '|' + || ch == '}' + || ch == '~' ); + } + +// ---------------------------------------------------- +// atom := [CFWS] 1*atext [CFWS] +// ---------------------------------------------------- +// +LOCAL_C TBool Atom( TLex& aLex ) + { + DoOrReverse( CFWS, aLex ); + + if( !Plus( AText, aLex ) ) + { + return EFalse; + } + + DoOrReverse( CFWS, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// dot-atom := [CFWS] dot-atom-text [CFWS] +// ---------------------------------------------------- +// +LOCAL_C TBool DotAtom( TLex& aLex ) + { + DoOrReverse( CFWS, aLex ); + if( !DoOrReverse( DotAtomText, aLex ) ) + { + return EFalse; + } + DoOrReverse( CFWS, aLex ); + + return ETrue; + } + +// ---------------------------------------------------- +// "." 1*atext +// ---------------------------------------------------- +// +LOCAL_C TBool DotPlusAText( TLex& aLex ) + { + return aLex.Get() == '.' && Plus( AText, aLex ); + } + +// ---------------------------------------------------- +// dot-atom-text := 1*atext *("." 1*atext) +// ---------------------------------------------------- +// +LOCAL_C TBool DotAtomText( TLex& aLex ) + { + if( !Plus( AText, aLex ) ) + { + return EFalse; + } + + Star( DotPlusAText, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// qtext := NO-WS-CTL / %d33 / %d35-91 / %d93-126 ; Non white space +// controls and The rest of the US-ASCII characters not including "\" +// or the quote character +// ---------------------------------------------------- +// +LOCAL_C TBool QText( TLex& aLex ) + { + if( DoOrReverse( NoWSCtl, aLex ) ) + { + return ETrue; + } + + TChar ch( aLex.Get() ); + return ch == 33 // CSI: 47 # See a comment above. + || (ch >= 35 && ch <= 91) // CSI: 47 # See a comment above. + || (ch >= 93 && ch <= 126); // CSI: 47 # See a comment above. + } + +// ---------------------------------------------------- +// qcontent := qtext / quoted-pair +// ---------------------------------------------------- +// +LOCAL_C TBool QContent( TLex& aLex ) + { + return DoOrReverse( QText, aLex ) || QuotedPair( aLex ); + } + +// ---------------------------------------------------- +// [FWS] qcontent +// ---------------------------------------------------- +// +LOCAL_C TBool FWSQContent( TLex& aLex ) + { + FWS( aLex ); + return QContent( aLex ); + } + +// ---------------------------------------------------- +// quoted-string := [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS] +// ---------------------------------------------------- +// +LOCAL_C TBool QuotedString( TLex& aLex ) + { + DoOrReverse( CFWS, aLex ); + + if( aLex.Get() != '"' ) + { + return EFalse; + } + + Star( FWSQContent, aLex ); + + DoOrReverse( FWS, aLex ); + + if( aLex.Get() != '"' ) + { + return EFalse; + } + + DoOrReverse( CFWS, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// word := atom / quoted-string +// ---------------------------------------------------- +// +LOCAL_C TBool Word( TLex& aLex ) + { + return DoOrReverse( Atom, aLex ) || QuotedString( aLex ); + } + +// ---------------------------------------------------- +// address := mailbox / group +// ---------------------------------------------------- +// +LOCAL_C TBool Address( TLex& aLex ) + { + return DoOrReverse( Mailbox, aLex ) || Group( aLex ); + } + +// ---------------------------------------------------- +// mailbox := name-addr / addr-spec +// ---------------------------------------------------- +// +LOCAL_C TBool Mailbox( TLex& aLex ) + { + return DoOrReverse( NameAddr, aLex ) || AddrSpec( aLex ); + } + +// ---------------------------------------------------- +// name-addr := [display-name] angle-addr +// ---------------------------------------------------- +// +LOCAL_C TBool NameAddr( TLex& aLex ) + { + DoOrReverse( DisplayName, aLex ); + return AngleAddr( aLex ); + } + +// ---------------------------------------------------- +// angle-addr := [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr +// ---------------------------------------------------- +// +LOCAL_C TBool AngleAddr( TLex& aLex ) + { + DoOrReverse( CFWS, aLex ); + if( aLex.Get() != '<' ) + { + return EFalse; + } + + if( !DoOrReverse( AddrSpec, aLex ) ) + { + return EFalse; + } + + if( aLex.Get() != '>' ) + { + return EFalse; + } + + DoOrReverse( CFWS, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// group := display-name ":" [mailbox-list / CFWS] ";" [CFWS] +// ---------------------------------------------------- +// +LOCAL_C TBool Group( TLex& aLex ) + { + if( !DisplayName( aLex ) ) + { + return EFalse; + } + + if( aLex.Get() != ':' ) + { + return EFalse; + } + + if( !DoOrReverse( MailboxList, aLex ) ) + { + DoOrReverse( CFWS, aLex ); + } + + if( aLex.Get() != ';' ) + { + return EFalse; + } + + DoOrReverse( CFWS, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// display-name := phrase +// phrase := 1*word / obs-phrase +// ---------------------------------------------------- +// +LOCAL_C TBool DisplayName( TLex& aLex ) + { + return Plus( Word, aLex ); + } + +// ---------------------------------------------------- +// "," mailbox +// ---------------------------------------------------- +// +LOCAL_C TBool CommaMailbox( TLex& aLex ) + { + return aLex.Get() == ',' && Mailbox( aLex ); + } + +// ---------------------------------------------------- +// mailbox-list := (mailbox *("," mailbox)) / obs-mbox-list +// ---------------------------------------------------- +// +LOCAL_C TBool MailboxList( TLex& aLex ) + { + if( !DoOrReverse( Mailbox, aLex ) ) + { + return EFalse; + } + + Star( CommaMailbox, aLex ); + + return ETrue; + } + +// ---------------------------------------------------- +// addr-spec := local-part "@" domain +// ---------------------------------------------------- +// +LOCAL_C TBool AddrSpec( TLex& aLex ) + { + if( !LocalPart( aLex ) ) + { + return EFalse; + } + + if( aLex.Get() != '@' ) + { + return EFalse; + } + + return Domain( aLex ); + } + +// ---------------------------------------------------- +// local-part := dot-atom / quoted-string / obs-local-part +// ---------------------------------------------------- +// +LOCAL_C TBool LocalPart( TLex& aLex ) + { + return DoOrReverse( DotAtom, aLex ) || QuotedString( aLex ); + } + +// ---------------------------------------------------- +// domain := dot-atom / domain-literal / obs-domain +// ---------------------------------------------------- +// +LOCAL_C TBool Domain( TLex& aLex ) + { + return DoOrReverse( DotAtom, aLex ) || DomainLiteral( aLex ); + } + +// ---------------------------------------------------- +// [FWS] dcontent +// ---------------------------------------------------- +// +LOCAL_C TBool FWSDContent( TLex& aLex ) + { + FWS( aLex ); + return DContent( aLex ); + } + +// ---------------------------------------------------- +// domain-literal := [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] +// ---------------------------------------------------- +// +LOCAL_C TBool DomainLiteral( TLex& aLex ) + { + DoOrReverse( CFWS, aLex ); + if( aLex.Get() != '[' ) + { + return EFalse; + } + + Star( FWSDContent, aLex ); + + DoOrReverse( FWS, aLex ); + if( aLex.Get() != ']' ) + { + return EFalse; + } + + DoOrReverse( CFWS, aLex ); + return ETrue; + } + +// ---------------------------------------------------- +// dcontent := dtext / quoted-pair +// ---------------------------------------------------- +// +LOCAL_C TBool DContent( TLex& aLex ) + { + return DoOrReverse( DText, aLex ) || QuotedPair( aLex ); + } + +// ---------------------------------------------------- +// dtext := NO-WS-CTL / %d33-90 / %d94-126 ; Non white space controls and +// the rest of the US-ASCII characters not including "[", "]", or "\" +// ---------------------------------------------------- +// +LOCAL_C TBool DText( TLex& aLex ) + { + if( DoOrReverse( NoWSCtl, aLex ) ) + { + return ETrue; + } + + TChar ch( aLex.Get() ); + return (ch >= 33 && ch <= 90) // CSI: 47 # See a comment above. + || (ch >= 94 && ch <= 126); // CSI: 47 # See a comment above. + } + +// ================= MEMBER FUNCTIONS ======================= + +// C++ default constructor cannot contain any code that might leave +EXPORT_C CMsgMailAppUi::CMsgMailAppUi() + : iResource(*iCoeEnv) + { + } + +// Symbian OS default constructor can leave. +EXPORT_C void CMsgMailAppUi::ConstructL() + { + // the implementation of this virtual function must call + // CEikAppUi::ConstructL or CEikAppUi::BaseConstructL + // before calling any other leaving function + CMsgEditorAppUi::ConstructL(); + SetSmallIconL(); + + TParse* fp = new(ELeave) TParse(); + fp->Set(KResourcesWithDir, &KDC_RESOURCE_FILES_DIR, NULL); + + TFileName fileName(fp->FullName()); + delete fp; + iResource.OpenL(fileName); + + // Used in derived AppUI classes + if (FeatureManager::FeatureSupported( KFeatureIdHelp )) + { + iCommonFlags |= EHelpSupported; + } + if (FeatureManager::FeatureSupported( KFeatureIdAvkonELaf )) + { + iCommonFlags |= EWestern; + } + + // Call PrepareToLaunchL if opened as standalone + if( !iEikonEnv->StartedAsServerApp( ) ) + { + Document()->PrepareToLaunchL( this ); + } + + } + + +// Destructor +EXPORT_C CMsgMailAppUi::~CMsgMailAppUi() + { + delete iBannedChars; + iResource.Close(); + } + + +// ---------------------------------------------------------------------------- +// CMsgMailAppUi::MsgSaveL() +// Saves message header, body, attachments and send options +// in message store. +// Argument: +// TBool aInPreparation +// In certain cases (e.g. printing) new message has to be saved temporarily, +// then aInPreparation flag is set to ETrue (default is EEalse) so automatic +// cleanup is made by the server if something goes wrong. +// ---------------------------------------------------------------------------- +// +EXPORT_C TBool CMsgMailAppUi::MsgSaveL(const TBool aInPreparation, + const TBool aReply /*= EFalse*/) + { + TBool saved(ETrue); + if ( Document()->MediaAvailable() ) + { + saved = DoSaveMessageL( aInPreparation, aReply ); + } + return saved; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::CheckStoreSpaceL() +// ----------------------------------------------------------------------------- +// +void CMsgMailAppUi::CheckStoreSpaceL( TMsvEmailEntry aMessage, TBool aReply ) + { + // calculate message size + // if forwarding HTML message, all attachments are copied. + TBool countAttachments( ( aMessage.MHTMLEmail() && !aReply ) ); + TInt docSize( MessageSizeL( countAttachments ) ); + LOG1( "CMsgMailAppUi::CheckStoreSpaceL: %d", docSize ); + + MailDocument()->DiskSpaceBelowCriticalLevelL( docSize ); + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::SetServiceIdL() +// ----------------------------------------------------------------------------- +// +TBool CMsgMailAppUi::SetServiceIdL( + TMsvEmailEntry& aEntry, CMsgMailDocument& aDocument ) + { + TBool returnValue( ETrue ); + + // set related service ID + CMsvEntry* rootEntry = + aDocument.Session().GetEntryL(KMsvRootIndexEntryIdValue); + CleanupStack::PushL(rootEntry); + rootEntry->SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping, + EMsvSortByNone,ETrue)); + + TMsvEntry serviceEntry; + TRAPD(err, serviceEntry = rootEntry->ChildDataL(aEntry.iServiceId)); + CMsgMailPreferences& pref = aDocument.SendOptions(); + if (err == KErrNotFound) // mailbox deleted, look for default + { + const TMsvId defaultId( + MsvUiServiceUtilitiesInternal::DefaultServiceForMTML( + aDocument.Session(), KUidMsgTypeSMTP, ETrue)); + if (defaultId == KMsvUnknownServiceIndexEntryId) + { // no mailboxes defined + returnValue = EFalse; + } + else // set default mailbox's values to entry + { + serviceEntry = rootEntry->ChildDataL(defaultId); + aEntry.iServiceId = defaultId; + pref.SetServiceId(defaultId); + } + } + aEntry.iRelatedId = serviceEntry.iRelatedId; + + CleanupStack::PopAndDestroy(); // rootEntry + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::SetEntryTimeL() +// ----------------------------------------------------------------------------- +// +void CMsgMailAppUi::SetEntryTimeL( TMsvEntry& aEntry ) + { + TInt muiuFlags(0); + MailDocument()->MailCRHandler()->GetCRInt( + KCRUidMuiuVariation, + KMuiuMceFeatures, muiuFlags); + + if ( (muiuFlags & KMceFeatureIdUseUtcTime) ) + { + LOG( "CMsgMailAppUi::SetEntryTimeL UTC" ); + aEntry.iDate.UniversalTime(); + } + else + { + aEntry.iDate.HomeTime(); + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::SetEntryFlagsL() +// ----------------------------------------------------------------------------- +// +void CMsgMailAppUi::SetEntryFlagsL( + TMsvEmailEntry& aEntry, TMsvId aOrigMessageId ) + { + CMsgMailDocument* doc = MailDocument(); + // buf must be available when ChangeL() is called + HBufC* buf = NULL; + // update entry details + CMsgAddressControl* control = AddressControl( EMsgComponentIdTo ); + if( control ) + { + buf = MakeDetailsLC( *control ); + aEntry.iDetails.Set( *buf ); + } + else + { + control = AddressControl( EMsgComponentIdFrom ); + if( control ) + { + buf = MakeDetailsLC( *control ); + TPtr bufPtr( buf->Des() ); + StripIllegalCharsL( bufPtr ); + aEntry.iDetails.Set( bufPtr ); + } + } + + // calculate new message size + aEntry.iSize = MessageSizeL( ETrue ); + //aEntry.iSize += doc->Header().DataSize(); + LOG1( "CMsgMailAppUi::SetEntryFlagsL entry size: %d", aEntry.iSize ); + + // changed flag + doc->SetChanged(EFalse); + + if (aOrigMessageId != doc->Entry().Id()) + { + doc->SetEntryL( aOrigMessageId ); + } + doc->CurrentEntry().ChangeL( aEntry ); + // LockEntryL(); + + // buf must be available when ChangeL() is called + if (buf) + { + CleanupStack::PopAndDestroy(); + } + LOG1( "CMsgMailAppUi::SetEntryFlagsL entry size final: %d", aEntry.iSize ); + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::SetHeaderFieldsL() +// ----------------------------------------------------------------------------- +// +void CMsgMailAppUi::SetHeaderFieldsL( TMsvEmailEntry& aMessage ) + { + CMsgMailDocument* doc = MailDocument(); + CImHeader& header = doc->HeaderL(); + // set subject to header & entry description + if (SubjectControl()) + { + CRichText& subject = SubjectControl()->TextContent(); + header.SetSubjectL(subject.Read(0, subject.DocumentLength())); + + // update entry description + aMessage.iDescription.Set(subject.Read(0, subject.DocumentLength())); + } + else + { + header.SetSubjectL(KNullDesC); + aMessage.iDescription.Set(KNullDesC); + } + + iNeedRefresh = EFalse; + + TInt recipientCount(0); + CMsgAddressControl* toControl = AddressControl(EMsgComponentIdTo); + AppendRecipientsL( toControl, header.ToRecipients() ); + recipientCount += header.ToRecipients().Count(); + + CMsgAddressControl* ccControl = AddressControl(EMsgComponentIdCc); + AppendRecipientsL( ccControl, header.CcRecipients() ); + recipientCount += header.CcRecipients().Count(); + + CMsgAddressControl* bccControl = AddressControl(EMsgComponentIdBcc); + AppendRecipientsL( bccControl, header.BccRecipients() ); + recipientCount += header.BccRecipients().Count(); + + // Set multiblerecipient flag + aMessage.SetMultipleRecipients( ( recipientCount > 1 ) ); + + CMsgAddressControl* fromControl = AddressControl(EMsgComponentIdFrom); + if (fromControl) + { + CMsgRecipientArray* fromAddress = fromControl->GetRecipientsL(); + if (fromAddress->Count() > 0) + { + CMsgRecipientItem* recItem = fromAddress->At(0); + HBufC* fullAddress = ConstructAddressStringLC(recItem); + header.SetFromL(*fullAddress); + CleanupStack::PopAndDestroy(); // fullAddress + } + if (iNeedRefresh) + { + fromControl->RefreshL(*fromAddress); + iNeedRefresh = EFalse; + } + } + + // save CImHeader information to current entry's store + doc->SaveHeaderToStoreL(); + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::SetSmallIconL() +// ----------------------------------------------------------------------------- +// +void CMsgMailAppUi::SetSmallIconL() + { + CAknTitlePane* titlePane = static_cast + ( StatusPane()->ControlL( TUid::Uid( EEikStatusPaneUidTitle ) ) ); + if( titlePane ) + { + TParse fileParse; + fileParse.Set( KMsgMailMBMFileName, &KDC_APP_BITMAP_DIR, NULL ); + CGulIcon* image = AknsUtils::CreateGulIconL( + AknsUtils::SkinInstance(), + KAknsIIDQgnPropMceEmailTitle, + fileParse.FullName(), + EMbmMsgmailutilsQgn_prop_mce_email_title, + EMbmMsgmailutilsQgn_prop_mce_email_title_mask + ); + TRect mainPane; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, mainPane ); + TAknLayoutRect titleIconPaneLayoutRect; + titleIconPaneLayoutRect.LayoutRect( + mainPane, + AknLayoutScalable_Avkon::title_pane_g2( 0 ).LayoutLine() ); + TSize iconSize = titleIconPaneLayoutRect.Rect( ).Size( ); + AknIconUtils::SetSize( image->Bitmap(), iconSize, EAspectRatioPreserved ); + + image->SetBitmapsOwnedExternally( ETrue ); + // takes ownership of bitmaps. Be sure nothing leaves before this + titlePane->SetSmallPicture( image->Bitmap(), image->Mask(), ETrue ); + delete image; + } + } +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::MailDocument() +// ----------------------------------------------------------------------------- +// +CMsgMailDocument* CMsgMailAppUi::MailDocument() + { + return static_cast ( Document() ); + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::DoSaveMessageL() +// ----------------------------------------------------------------------------- +// +TBool CMsgMailAppUi::DoSaveMessageL( TBool aInPreparation, TBool aReply ) + { + CMsgMailDocument* doc = MailDocument(); + if ( doc->CurrentEntry().Entry().Id() != iMessageID ) + { + doc->SetEntryL( iMessageID ); + } + TMsvEmailEntry entry(doc->CurrentEntry().Entry()); + LOG1( "CMsgMailAppUi::DoSaveMessageL entry size: %d", entry.iSize ); + entry.SetBodyTextComplete( ETrue ); + + ASSERT( entry.Id() == iMessageID ); + CheckStoreSpaceL( entry, aReply ); + + // set preparation flag + if (!entry.MHTMLEmail() && !aReply) + { + entry.SetInPreparation(aInPreparation); + // set visible if not in preparation state + entry.SetVisible(!aInPreparation); + UnlockEntry(); + doc->CurrentEntry().ChangeL(entry); + } + //------------------------------- + // 1. set variables + //------------------------------- + TBool returnValue(ETrue); + + //------------------------------------- + // 2. create new message id, if needed + //------------------------------------- + const TMsvId origMessageId(entry.Id()); + + entry.iType = KUidMsvMessageEntry; + CMsgMailPreferences& pref = doc->SendOptions(); + + + // EMail type + entry.iMtm = KUidMsgTypeSMTP; + // set related service ID + returnValue = SetServiceIdL( entry, *doc ); + + // set Send options + pref.ImportSendOptionsL(entry); + // set entry time + SetEntryTimeL( entry ); + + //------------------------------- + // 3. set CImHeader fields + //------------------------------- + SetHeaderFieldsL( entry ); + + // store message body + CMsgBodyControl* bodyControl = BodyControl(); + if (bodyControl) + { + CMuiuOperationWait* wait = CMuiuOperationWait::NewLC(); + doc->MessageL().StoreBodyTextL( + origMessageId, + bodyControl->TextContent(), + wait->iStatus); + + wait->Start(); + CleanupStack::PopAndDestroy(); //wait + } + + //------------------------------- + // 5. update the entry + //------------------------------- + SetEntryFlagsL( entry, origMessageId ); + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::ConstructAddressStringLC() +// ----------------------------------------------------------------------------- +// +HBufC* CMsgMailAppUi::ConstructAddressStringLC(CMsgRecipientItem* aRecItem) + { + HBufC* fullAddress = NULL; + + // remove illegal characters from user inputted addresses + if (!aRecItem->Name()->Length()) + { + TPtr address(aRecItem->Address()->Des()); + // won't overflow, only removing characters + if (StripIllegalCharsL(address)) + { + aRecItem->SetAddressL(address); + } + } + + // check that address item has alias and address and they are not the same + if (aRecItem->Name()->Length() && + aRecItem->Name()->Compare(*(aRecItem->Address())) != 0) + { + // 2 Array for name and address + CDesCArrayFlat* strings = new(ELeave) CDesCArrayFlat( 2 ); // CSI: 47 # See a comment above. + CleanupStack::PushL( strings ); + + strings->AppendL( *aRecItem->Name() ); + strings->AppendL( *aRecItem->Address() ); + + fullAddress = StringLoader::LoadL( + R_MAIL_ADDRESS_FORMAT_STRING, *strings, iCoeEnv); + CleanupStack::PopAndDestroy(); // strings + CleanupStack::PushL( fullAddress ); + } + // otherwise return just address + else + { + fullAddress = aRecItem->Address()->AllocLC(); + } + return fullAddress; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::StripIllegalCharsL() +// ----------------------------------------------------------------------------- +// +TBool CMsgMailAppUi::StripIllegalCharsL(TDes& aString) + { + TBool returnValue(EFalse); + // initialise array when called for the 1st time + if (!iBannedChars) + { + iBannedChars = iEikonEnv->ReadDesC16ArrayResourceL( + R_MAIL_BANNED_CHARS ); + iBannedChars->Compress(); + } + + // Check that inputted address does not contain illegal characters + // These characters would mess up address inputting if they were saved + const TInt count(iBannedChars->Count()); + for (TInt i = 0; i < count; i++) + { + TInt pos(aString.Find((*iBannedChars)[i])); + while (pos != KErrNotFound) + { + aString.Delete(pos, 1); + pos = aString.Find((*iBannedChars)[i]); + iNeedRefresh = ETrue; + returnValue = ETrue; + } + } + + aString.Trim(); + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::AppendRecipientsL() +// ----------------------------------------------------------------------------- +// +void CMsgMailAppUi::AppendRecipientsL( + CMsgAddressControl* aField, CDesCArray& aArray ) + { + aArray.Reset(); + + if ( aField ) + { + const CMsgRecipientArray* recipients = aField->GetRecipientsL(); + const TInt count(recipients->Count()); + for (TInt i=0; i < count; i++) + { + CMsgRecipientItem* recItem = recipients->At(i); + HBufC* fullAddress = ConstructAddressStringLC(recItem); + aArray.AppendL(*fullAddress); + CleanupStack::PopAndDestroy(); // fullAddress + } + + if (iNeedRefresh) + { + aField->RefreshL(*recipients); + iNeedRefresh = EFalse; + } + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::CheckFFSL() +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CMsgMailAppUi::CheckFFSL(const TInt aSize) + { + return MailDocument()->DiskSpaceBelowCriticalLevelL( aSize ); + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::IsBannedMimeL() +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CMsgMailAppUi::IsBannedMimeL(const TDesC& /*aBuf*/) const + { + // Use MailUtils::IsClosedFileL instead of this + User::Leave( KErrNotSupported ); + return EFalse; + } +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::IsValidAddress() +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CMsgMailAppUi::IsValidAddress( const TDesC& aAddress ) const + { + TLex lex( aAddress ); + return Address( lex ) && lex.Eos(); + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::CheckIfBannedL() +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CMsgMailAppUi::CheckIfBannedL(const TDesC& /*aMimeType*/) + { + // Use MailUtils::IsClosedFileL instead of this + User::Leave( KErrNotSupported ); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::CheckIfBannedL() +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CMsgMailAppUi::CheckIfBannedL(RFile& /*aFile*/) + { + // Use MailUtils::IsClosedFileL instead of this + User::Leave( KErrNotSupported ); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::CleanupWaitNoteWrapper() +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMsgMailAppUi::CleanupWaitNoteWrapper(TAny* aAny) + { + CAknWaitNoteWrapper** wrapper = STATIC_CAST(CAknWaitNoteWrapper**, aAny); + if (wrapper && *wrapper) + { + delete *wrapper; + *wrapper = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::CleanupWaitDialog() +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMsgMailAppUi::CleanupWaitDialog(TAny* aAny) + { + CAknWaitDialog** dialog = STATIC_CAST(CAknWaitDialog**, aAny); + if (dialog && *dialog) + { + delete *dialog; + *dialog = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::MessageSizeL() +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CMsgMailAppUi::MessageSizeL( TBool aCountAttachments ) // CSI: 40 # We must return + // the integer value although this + // is a leaving method. + { + // calculate message size + const TInt multibleByTwoForUnicode(2); + + TInt fieldSize(0); + TInt count; + + CMsgAddressControl* addressField; + + addressField = AddressControl( EMsgComponentIdTo ); + if (addressField) + { + addressField->GetSizeOfAddresses(count, fieldSize); + } + TInt docSize(fieldSize); + addressField = AddressControl( EMsgComponentIdCc ); + if (addressField) + { + addressField->GetSizeOfAddresses(count, fieldSize); + docSize += fieldSize; + } + + addressField = AddressControl( EMsgComponentIdBcc ); + if (addressField) + { + addressField->GetSizeOfAddresses(count, fieldSize); + docSize += fieldSize; + } + + if( SubjectControl() ) + { + docSize += SubjectControl()->TextContent().DocumentLength() + * multibleByTwoForUnicode; + } + CRichText& rtf = BodyControl()->TextContent(); + docSize += rtf.DocumentLength() * multibleByTwoForUnicode; + + // Attachments + if ( aCountAttachments ) + { + CMsgAttachmentModel& attModel = Document()->AttachmentModel(); + const TInt attCount( attModel.NumberOfItems() ); + + for (TInt cc=0; cc < attCount; cc++) + { + docSize += attModel.AttachmentInfoAt(cc).Size(); + } + } + + LOG1( "CMsgMailAppUi::MessageSizeL: %d", docSize ); + return docSize; + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::SetDialerEnabled() +// ----------------------------------------------------------------------------- +// +EXPORT_C void CMsgMailAppUi::SetDialerEnabled( TBool aEnable ) + { + if( aEnable ) + { + // send key handling enabled + SetKeyEventFlags( 0 ); + } + else + { + // send key handling disabled + SetKeyEventFlags( + CAknAppUiBase::EDisableSendKeyShort | + CAknAppUiBase::EDisableSendKeyLong ); + } + } + +// ----------------------------------------------------------------------------- +// CMsgMailAppUi::MakeDetailsLC() +// ----------------------------------------------------------------------------- +// +HBufC* CMsgMailAppUi::MakeDetailsLC( CMsgAddressControl& aControl ) + { + // Array is owned by the control + CMsgRecipientArray* recipients = aControl.GetRecipientsL(); + TInt recipCount = recipients->Count(); + + LOG1( "CMsgMailAppUi::MakeDetailsLC: %d Recipient(s)", recipCount ); + if( recipCount == 0 ) + { + // no recipients + return KNullDesC().AllocLC(); + } + + // Append recipients to text. + HBufC* detailsBuf = HBufC::NewLC( KMsgMaxDetailsLength ); + TPtr details( detailsBuf->Des() ); + TInt separatorLen = KMsgDetailsSeparator().Length(); + + for( TInt i = 0; i < recipCount; ++i ) + { + CMsgRecipientItem* item = recipients->At(i); + + // Select name or address (prefer name if available) + HBufC* textToAdd = item->Name(); + if( !textToAdd ) + { + textToAdd = item->Address(); + } + else if( textToAdd->Length() == 0 ) + { + textToAdd = item->Address(); + } + + if( textToAdd ) + { + TInt textSpace = KMsgMaxDetailsLength - details.Length(); + + // Append separator + if( textSpace < separatorLen ) + { + // no space for separator -> all done + break; + } + if( details.Length() > 0 ) + { + // not a first recipient -> add separator + details.Append( KMsgDetailsSeparator ); + textSpace -= separatorLen; + } + + // Append recipient's name or address + details.Append( textToAdd->Left( textSpace ) ); + + if( KMsgMaxDetailsLength - details.Length() <= 0 ) + { + // No more space -> all done + break; + } + } + } + + return detailsBuf; + } + + +// End of File