diff -r 238255e8b033 -r 84d9eb65b26f messagingappbase/smsmtm/clientmtm/src/smut.cpp --- a/messagingappbase/smsmtm/clientmtm/src/smut.cpp Fri Apr 16 14:56:15 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,951 +0,0 @@ -// Copyright (c) 1999-2009 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: -// smut.cpp -// -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "SMCMMAIN.H" -#include "SMUTSET.H" - -// Used by ValidGsmNumber(). The characters that may appear at the start of a -// valid GSM number -_LIT(KSmsValidGsmNumberFirstChar, "+"); - -// Used by ValidGsmNumber(). The characters that may appear after the first -// character of a valid GSM number -_LIT(KSmsValidGsmNumberOtherChar, "#*"); - -const TInt KSmsValidGsmNumberMinLength = 2; - -/** -Finds and returns all the Service IDs for the specified MTM. - -A Service ID is the entry ID for an service-type entry. The first Service ID -for the specified MTM is returned. - -If the complete set of Service IDs for the MTM is required then the caller -should provide a valid CMsvEntrySelection object in aServiceIds. The Service -Ids are appended to this object. If the complete set is not required then the -input/output argument aServiceIds should be set to NULL. - -@param aEntry -A server message entry that can be used by this function. - -@param aFirstId -An output argument with the first Service ID. - -@param aMtm -The specified MTM. This has a default value of KUidMsgTypeSMS. - -@param aServiceIds -An input/output argument with the complete selection of Service IDs. This has -a default value of NULL. - -@leave KErrNotFound -A service entry could not be found for the specified MTM. -*/ -EXPORT_C void TSmsUtilities::ServiceIdL(CMsvServerEntry& aEntry, TMsvId& aFirstId, TUid aMtm, CMsvEntrySelection* aServiceIds) - { - aFirstId = KMsvNullIndexEntryId; - - CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection(); - CleanupStack::PushL(selection); - - User::LeaveIfError(aEntry.SetEntry(KMsvRootIndexEntryId)); - - TMsvSelectionOrdering order; - order.SetShowInvisibleEntries(ETrue); - aEntry.SetSort(order); - - // Get the children on the Root Index Entry - User::LeaveIfError(aEntry.GetChildrenWithType(KUidMsvServiceEntry, *selection)); - - TInt count = selection->Count(); - - // Find an entry for MTM aMtm - for (TInt curChild = 0; curChild < count && (aFirstId == KMsvNullIndexEntryId || aServiceIds); ++curChild) - { - User::LeaveIfError(aEntry.SetEntry(selection->At(curChild))); - CompareEntryL(aEntry.Entry(), aMtm, aFirstId, aServiceIds); - } - - // Leave if no Service Entry found for MTM aMtm - if (aFirstId == KMsvNullIndexEntryId) - User::Leave(KErrNotFound); - - CleanupStack::PopAndDestroy(selection); - } - -/** -Finds and returns all the Service IDs for the specified MTM. - -A Service ID is the entry ID for an service-type entry. The first Service ID -for the specified MTM is returned. - -If the complete set of Service IDs for the MTM is required then the caller -should provide a valid CMsvEntrySelection object in aServiceIds. The Service -Ids are appended to this object. If the complete set is not required then the -input/output argument aServiceIds should be set to NULL. - -@param aSession -A message server session. - -@param aFirstId -An output argument with the first Service ID. - -@param aMtm -The specified MTM. This has a default value of KUidMsgTypeSMS. - -@param aServiceIds -An input/output argument with the complete selection of Service IDs. This has -a default value of NULL. - -@leave KErrNotFound -A service entry could not be found for the specified MTM. -*/ -EXPORT_C void TSmsUtilities::ServiceIdL(CMsvSession& aSession, TMsvId& aFirstId, TUid aMtm, CMsvEntrySelection* aServiceIds) - { - TMsvSelectionOrdering order; - order.SetShowInvisibleEntries(ETrue); - - CMsvEntry* root = CMsvEntry::NewL(aSession, KMsvRootIndexEntryId, order); - CleanupStack::PushL(root); - - ServiceIdL(*root, aFirstId, aMtm, aServiceIds); - - CleanupStack::PopAndDestroy(root); - } - -/** -Finds and returns all the Service IDs for the specified MTM. - -A Service ID is the entry ID for an service-type entry. The first Service ID -for the specified MTM is returned. - -If the complete set of Service IDs for the MTM is required then the caller -should provide a valid CMsvEntrySelection object in aServiceIds. The Service -Ids are appended to this object. If the complete set is not required then the -input/output argument aServiceIds should be set to NULL. - -@param aEntry -A message entry that can be used by this function. - -@param aFirstId -An output argument with the first Service ID. - -@param aMtm -The specified MTM. This has a default value of KUidMsgTypeSMS. - -@param aServiceIds -An input/output argument with the complete selection of Service IDs. This has -a default value of NULL. - -@leave KErrNotFound -A service entry could not be found for the specified MTM. -*/ -EXPORT_C void TSmsUtilities::ServiceIdL(CMsvEntry& aEntry, TMsvId& aFirstId, TUid aMtm, CMsvEntrySelection* aServiceIds) - { - aFirstId = KMsvNullIndexEntryId; - - TMsvSelectionOrdering order(aEntry.SortType()); - if (!order.ShowInvisibleEntries()) - { - order.SetShowInvisibleEntries(ETrue); - aEntry.SetSortTypeL(order); - } - - aEntry.SetEntryL(KMsvRootIndexEntryId); - const TInt count = aEntry.Count(); - - // Find an entry for MTM aMtm - for (TInt curChild = 0; curChild < count && (aFirstId == KMsvNullIndexEntryId || aServiceIds != NULL); ++curChild) - { - CompareEntryL(aEntry[curChild], aMtm, aFirstId, aServiceIds); - } - - // Leave if no Service Entry found for MTM aMtm - if (aFirstId == KMsvNullIndexEntryId) - User::Leave(KErrNotFound); - } - -/** -Populates a message index. - -The input data is used to set the fields in supplied message index. The affected -fields are the entry type, MTM, entry date, Service ID and error fields. The -date field is set from the time information in the aMessage argument. - -This function can be used as part of the process when creating SMS messages in -the message store. - -@param aEntry -An input/output argument with the index entry to populate. - -@param aMessage -The SMS message object for the index entry. - -@param aServiceId -The Service ID for the message. - -@param aMtm -The specified MTM. This has a default value of KUidMsgTypeSMS. -*/ -EXPORT_C void TSmsUtilities::PopulateMsgEntry(TMsvEntry& aEntry, const CSmsMessage& aMessage, TMsvId aServiceId, TUid aMtm) - { - aEntry.iType = KUidMsvMessageEntry; - aEntry.iMtm = aMtm; - aEntry.iDate = aMessage.Time(); - aEntry.iServiceId = aServiceId; - aEntry.iError = KErrNone; - } - -/** -Populates a message index. - -The input data is used to set the fields in supplied message index. The affected -fields are the entry type, MTM, entry date, Service ID and error fields. The -date field is either set from the time information in the aMessage argument or from -the service center timestamp in the PDU depending on the associated SMS setting. - -This function can be used as part of the process when creating SMS messages in -the message store. - -@param aEntry -An input/output argument with the index entry to populate. - -@param aMessage -The SMS message object for the index entry. - -@param aServiceId -The Service ID for the message. - -@param aSettings -The settings for the SMS account. - -@param aMtm -The specified MTM. This has a default value of KUidMsgTypeSMS. -*/ -EXPORT_C void TSmsUtilities::PopulateMsgEntry(TMsvEntry& aEntry, const CSmsMessage& aMessage, TMsvId aServiceId, const CSmsSettings& aSettings, TUid aMtm) - { - TSmsUtilities::PopulateMsgEntry(aEntry, aMessage, aServiceId, aMtm); - - if (aSettings.UseServiceCenterTimeStampForDate()) - { - const CSmsPDU& pdu = aMessage.SmsPDU(); - - TTime time = 0; - TInt gmtOffset = 0; - - if (pdu.Type() == CSmsPDU::ESmsDeliver) - { - CSmsDeliver& smsDeliver = - const_cast(static_cast(pdu)); - smsDeliver.ServiceCenterTimeStamp(time, gmtOffset); - } - else if (pdu.Type() == CSmsPDU::ESmsStatusReport) - { - CSmsStatusReport& smsStatusReport = - const_cast(static_cast(pdu)); - smsStatusReport.ServiceCenterTimeStamp(time, gmtOffset); - } - - if (time > 0) - { - aEntry.iDate = time; - } - } - } - -/** -Get the SMS message recipient/sender details. - -The recipient/sender telephone number is extracted from the supplied message -object. If the recipient/sender telephone number appears uniquely in the contacts -database then the family name and given name contact details are set into the -output argument aDetails in the format specified by the resource item -R_SENDER_NAME_FORMAT. The buffer limit specified by aMaxLength is observed. - -If there is not a unique contact entry for the recipient/sender telephone number -then aDetails will contain the orginally telephone number. - -@param aFs -A connected file server session. - -@param aMessage -The message object with the recipient/sender telephone number. - -@param aDetails -The output argument to contain the message details. - -@param aMaxLength -The maximum length of the supplied buffer in aDetails. - -@return -KErrNotSupported if the message is not of type SMS-SUBMIT, SMS-DELIVER or SMS-STATUS-REPORT. -KErrArgument if the telephone number is invalid. -KErrNotFound if a contact could not be found. -KErrAlreadyExists if more than one contact entry found. -KErrNone if details is obtained successfully. -*/ -EXPORT_C TInt TSmsUtilities::GetDetails(RFs& aFs, const CSmsMessage& aMessage, TDes& aDetails, TInt aMaxLength) - { - __ASSERT_DEBUG( aMaxLength <= aDetails.MaxLength(), User::Invariant() ); - - if (aMaxLength > aDetails.MaxLength()) - { - aMaxLength = aDetails.MaxLength(); - } - - aDetails.Zero(); - - TPtrC fromAddress; - - switch (aMessage.SmsPDU().Type()) - { - case CSmsPDU::ESmsSubmit: - case CSmsPDU::ESmsDeliver: - case CSmsPDU::ESmsStatusReport: - fromAddress.Set(aMessage.SmsPDU().ToFromAddress()); - break; - default: - return KErrNotSupported; - } - - return GetDetails(aFs, fromAddress, aDetails, aMaxLength); - } - -/** -Get the SMS message recipient/sender details. - -The recipient/sender telephone number is searched for in the contacts database. -If a unique match is found then the family name and given name contact details -are set into the output argument aDetails in the format specified by the -resource item R_SENDER_NAME_FORMAT. The buffer limit specified by aMaxLength is -observed. - -If a unique match is not found or the supplied telephone number is invalid, then -aDetails will contain the orginally telephone number. - -@param aFs -A connected file server session. - -@param aFromAddress -The recipient/sender telephone number. - -@param aDetails -The output argument to contain the message details. - -@param aMaxLength -The maximum length of the supplied buffer in aDetails. - -@return -KErrArgument if aFromAddress is not a valid GSM number. -KErrNotFound if a contact could not be found. -KErrAlreadyExists if more than one contact entry found. -KErrNone if details is obtained successfully. -*/ -EXPORT_C TInt TSmsUtilities::GetDetails(RFs& aFs, const TDesC& aFromAddress, TDes& aDetails, TInt aMaxLength) - { - __ASSERT_DEBUG( aMaxLength <= aDetails.MaxLength(), User::Invariant() ); - - if (aMaxLength > aDetails.MaxLength()) - { - aMaxLength = aDetails.MaxLength(); - } - - TRAPD(err, DoGetDetailsL(aFs, aFromAddress, aDetails, aMaxLength)); - - if ( (err != KErrNone) || (aDetails.Length() == 0) ) - { - if (aFromAddress.Length() <= aMaxLength) - { - aDetails = aFromAddress; - aDetails.Trim(); - } - else - { - // Truncate aFromAddress so that it fits into aDetails. - aDetails = aFromAddress.Left(aMaxLength); - aDetails.Trim(); - } - } - - return KErrNone; - } - -/** -Get the SMS message description. - -If the message is Special Message Indication SMS then the description will -contain the appropriate localised text for the indication. - -If the message is a Status Report then the description will contain the -appropriate localised text for a Status Report. - -If the message is a standard text message the description will contain the -beginning section of the SMS message text itself. - -In all cases the buffer limit specified by aMaxLength is observered. - -@param aMessage -The SMS message object. - -@param aDescription -The output argument for the description. - -@param aMaxLength -The maximum length of the supplied buffer in aDescription. - -@return -An error code if the localised text for a SMS-STATUS-REPORT message could not be -obtained. Otherwise KErrNone is returned. -*/ -EXPORT_C TInt TSmsUtilities::GetDescription(const CSmsMessage& aMessage, TDes& aDescription, TInt aMaxLength) - { - __ASSERT_DEBUG( aMaxLength <= aDescription.MaxLength(), User::Invariant() ); - - if (aMaxLength > aDescription.MaxLength()) - { - aMaxLength = aDescription.MaxLength(); - } - - aDescription.Zero(); - - TBool gotDescription = EFalse; - TRAPD(err, gotDescription = DoGetDescriptionL(aMessage, aDescription, aMaxLength)); - if(err != KErrNone || !gotDescription) - ExtractDescriptionFromMessage(aMessage, aDescription, aMaxLength); - - return KErrNone; - } - -/** -Opens and returns the SMS client MTM resource file. - -It is the responsibility of the caller to ensure that the resource file is -closed once it is no longer required. - -@param aFs -A connected file server session. - -@return -The opened resource file. -*/ -EXPORT_C RResourceFile TSmsUtilities::OpenResourceFileL(RFs& aFs) - { - TFileName fileName(KSmsResourceFile); - MsvUtils::AddPathAndExtensionToResFileL(fileName); - BaflUtils::NearestLanguageFile(aFs, fileName); - - RResourceFile resFile; - resFile.OpenL(aFs, fileName); - return resFile; - } - -/** -Reads the resource specified by aResourceId from the supplied resource file. - -The resource is returned in the output argument aString. The supplied resource -file must be open or this function will leave. - -@param aResourceFile -The opened resource file to read the resource from. - -@param aResourceId -The ID of the resource that is required. - -@param aString -An output buffer into which the read resource is placed. - -@leave KErrOverflow -The length of the resource string is greater than the maximum allowed. -*/ -EXPORT_C void TSmsUtilities::ReadResourceStringL(RResourceFile aResourceFile, TInt aResourceId, TDes& aString) - - { - HBufC8* buf = aResourceFile.AllocReadLC(aResourceId); - TResourceReader reader; - reader.SetBuffer(buf); - - TPtrC resString = reader.ReadTPtrC(); - - if (resString.Length() <= aString.MaxLength()) - { - aString.Copy(resString); - } - else - { - User::Leave(KErrOverflow); - } - - CleanupStack::PopAndDestroy(buf); - } - -void TSmsUtilities::CompareEntryL(const TMsvEntry& aEntry, TUid aMtm, TMsvId& aFirstId, CMsvEntrySelection* aServiceIds) - { - if (aEntry.iType == KUidMsvServiceEntry && aEntry.iMtm == aMtm) - { - const TMsvId id = aEntry.Id(); - - if (aFirstId == KMsvNullIndexEntryId) - aFirstId = id; - - if (aServiceIds) - aServiceIds->AppendL(id); - } - } - -void TSmsUtilities::DoGetDetailsL(RFs& aFs, const TDesC& aFromAddress, TDes& aDetails, TInt aMaxLength) - { - __UHEAP_MARK; - - // Check that aFromAddress is a valid GSM telephone number - if (!ValidGsmNumber(aFromAddress)) - User::Leave(KErrArgument); - - aDetails.Zero(); - - CContactDatabase* db = CContactDatabase::OpenL(); - CleanupStack::PushL(db); - - // Lookup the telephone number (aFromAddress) in the contact database - CContactIdArray* contactId = db->MatchPhoneNumberL(aFromAddress, KLowerSevenDigits); - CleanupStack::PushL(contactId); - - // Add the name if there is one and only one match in contacts. If there's more than - // one then wouldn't know which one to choose - if (contactId->Count() <= 0) - { - //The telephone number (aFromAddress) was not found in the contact database. - User::Leave(KErrNotFound); - } - else if (contactId->Count() > 1) - { - //There's more than one telephone number match in contacts. - User::Leave(KErrAlreadyExists); - } - - CContactItem* newContact = db->ReadMinimalContactL((*contactId)[0]); - CleanupStack::PushL(newContact); - - CContactItemFieldSet& fieldSet = newContact->CardFields(); - - TInt count = fieldSet.Count(); - - HBufC* family = HBufC::NewLC(aMaxLength); - HBufC* given = HBufC::NewLC(aMaxLength); - TPtr familyPtr(family->Des()); - TPtr givenPtr(given->Des()); - - // Find the Given and First Name of the contact - // Order important - for (TInt curField = 0; curField < count && !(familyPtr.Length() && givenPtr.Length()); curField++) - { - CContactItemField& field = fieldSet[curField]; - - if (!familyPtr.Length()) - GetName(field, KUidContactFieldFamilyName, familyPtr); - - if (!givenPtr.Length()) - GetName(field, KUidContactFieldGivenName, givenPtr); - } - - familyPtr.Trim(); - givenPtr.Trim(); - - TInt familyLen = familyPtr.Length(); - TInt givenLen = givenPtr.Length(); - - if (!familyLen && !givenLen) - { - //Leave if no family nor given name found - User::Leave(KErrNotFound); - } - else if (givenLen == 0) - { - // The maximum length of familyPtr may be greater than - // aMaxLength, so need to check its length before copying. - if (familyPtr.Length() > aMaxLength) - { - familyPtr.Set(familyPtr.LeftTPtr(aMaxLength)); - } - - aDetails = familyPtr; - } - else if (familyLen == 0) - { - // The maximum length of givenPtr may be greater than - // aMaxLength, so need to check its length before copying. - if (givenPtr.Length() > aMaxLength) - { - givenPtr.Set(givenPtr.LeftTPtr(aMaxLength)); - } - - aDetails = givenPtr; - } - else - { - RResourceFile resFile = OpenResourceFileL(aFs); - CleanupClosePushL(resFile); - ReadResourceStringL(resFile, R_SENDER_NAME_FORMAT, aDetails); - CleanupStack::PopAndDestroy(&resFile); - - TBuf<8> givenPlaceHolder = L_SMS_GIVEN_NAME; - TBuf<8> familyPlaceHolder = L_SMS_FAMILY_NAME; - TInt minLength = aDetails.Length() - givenPlaceHolder.Length() - familyPlaceHolder.Length(); - - if ((familyLen + givenLen + minLength) > aMaxLength) - { - // The maximum length of familyPtr may be greater than - // aMaxLength, so need to check its length before copying. - if (familyPtr.Length() > aMaxLength) - { - familyPtr.Set(familyPtr.LeftTPtr(aMaxLength)); - } - aDetails = familyPtr; - } - else - { - Replace(givenPlaceHolder, givenPtr, aDetails); - Replace(familyPlaceHolder, familyPtr, aDetails); - } - } - - //Remove leading and trailing spaces - aDetails.Trim(); - CleanupStack::PopAndDestroy(5, db); - - __UHEAP_MARKEND; - } - - TBool TSmsUtilities::ValidGsmNumber(const TDesC& aTelephone) - { - // Returns ETrue if - // aTelephone is not zero length; and - // aTelephone[0] is a digit or "+"; and - // aTelephone[1..] is a digit or "*" or "#". - // aTelephone has at least 2 valid characters - //Note: Returns EFalse if aTelephone contains any alpha character - // All spaces are ignored - const TInt length = aTelephone.Length(); - - if (length < KSmsValidGsmNumberMinLength) - return EFalse; - - TPtrC KFirstChar(KSmsValidGsmNumberFirstChar); - TPtrC KOtherChar(KSmsValidGsmNumberOtherChar); - TBool validTel = ETrue; - TInt validCharsFound = 0; //must be >= KSmsValidGsmNumberMinLength by the end - - const TText* first = aTelephone.Ptr(); //Points to the first character in aTelephone - const TText* last = first + length - 1; //Points to the last character in aTelephone - - //Check each character in the telephone number - while (validTel && first <= last) - { - TChar ch(*first); - if (!ch.IsSpace()) //ignore whitespace - { - if (!ch.IsDigit()) - { - //Need to create TPtrC because TDesC::Find() does not take a TChar - TPtrC telCharacter(first, 1); - - if (validCharsFound) - { - //Check the remaining characters of the telephone number - validTel = (KOtherChar.Find(telCharacter) != KErrNotFound); - } - else //validCharsFound == 0 - { - //Check the first character of the telephone number - validTel = (KFirstChar.Find(telCharacter) != KErrNotFound); - } - } - validCharsFound++; - } - - first++; //move to the next character - } - - return validTel && validCharsFound >= KSmsValidGsmNumberMinLength; - } - - void TSmsUtilities::GetName(CContactItemField& aField, TUid aFieldType, TDes& aName) - { - __UHEAP_MARK; - if (aField.ContentType().ContainsFieldType(aFieldType)) - { - TPtrC name = aField.TextStorage()->Text(); - aName = name.Left(Min(aName.MaxLength(), name.Length())); - } - __UHEAP_MARKEND; - - } - -TBool TSmsUtilities::DoGetDescriptionL(const CSmsMessage& aMessage, TDes& aDescription, TInt aMaxLength) -// this function returns EFalse if aMessage has no special message indication data and is not an SMS_STATUS_REPORT, -// i.e. more needs to be done to extract the description from the message -// otherwise returns ETrue - { - TInt resourceId = 0; - TBuf format; - TSmsMessageIndicationType messageIndicationType; - TExtendedSmsIndicationType extendedType; - TSmsMessageProfileType messageProfileType; - TBool toStore=EFalse; - TUint totalIndicationCount=0; - TUint totalMessageCount=0; - - //check if the messae contains an enhanced voice mail indication - CSmsEnhancedVoiceMailOperations& enhancedVoiceMailOperations = STATIC_CAST(CSmsEnhancedVoiceMailOperations&,aMessage.GetOperationsForIEL(CSmsInformationElement::ESmsEnhanceVoiceMailInformation)); - - if(enhancedVoiceMailOperations.ContainsEnhancedVoiceMailIEL()) - { - //get a copy of the indication - CEnhancedVoiceMailBoxInformation* retrievedNotification=enhancedVoiceMailOperations.CopyEnhancedVoiceMailIEL(); - TVoiceMailInfoType typeInfo=retrievedNotification->Type(); - //check its type - if(typeInfo==EGsmSmsVoiceMailNotification) - { - //increment the indication count - ++totalIndicationCount; - resourceId = R_MESSAGE_INDICATION_ENHANCED_VOICEMAIL_ONE; - } - - TUint8 messageCount=retrievedNotification->NumberOfVoiceMessages(); - //add the message count to the running total - totalMessageCount+=messageCount; - //if there is more that one message of this type then set the resouce id to 'many' - if(messageCount!=1) - { - ++resourceId; - } - - delete retrievedNotification; - } - - //check for special message waiting indications - CSmsSpecialSMSMessageOperations& operations = STATIC_CAST(CSmsSpecialSMSMessageOperations&,aMessage.GetOperationsForIEL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication)); - TUint specialMessageIndicationCount=operations.GetCountOfSpecialMessageIndicationsL(); - - if(specialMessageIndicationCount!=0) - { - //add special message indications to out indication count - totalIndicationCount+=specialMessageIndicationCount; - - if(totalIndicationCount>1) - { - //set the resource id to R_MESSAGE_INDICATION_OTHER_ONE - resourceId = R_MESSAGE_INDICATION_OTHER_ONE; - //get the total number of messages from the indicatations - TUint8 messageCount=0; - for(TInt loopCount=0;loopCount