diff -r 000000000000 -r 3553901f7fa8 smsprotocols/smsstack/gsmu/src/gsmuieoperations.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smsprotocols/smsstack/gsmu/src/gsmuieoperations.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,1852 @@ +// 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: +// + +#include "Gsmumain.h" +#include "gsmuieoperations.h" +#include "Gsmumsg.h" +#include "gsmumsgadditionalattributes.h" +#include "Gsmuelem.h" +#include "smsstacklog.h" + + +/** + * This is used by the CSmsMessage to create a CSmsIEOperation. + * Each instance is owned by the CSmsMessage which created it. + * Therefore only the CSmsMessage (GSMU component) is allowed to + * create and delete CSmsIEOperations. + * + * @param aId + * The ID for the CSmsInformationElement for whom an operation class needs to be created. + * @param aMessage + * The CSmsMessage that this operations class belongs to. + * @param aCharacterSetConverter + * A reference to a character set converter, needed by some derived operation classes. + * @param aFs + * A reference to the file server, needed by some derived operations classes. + * + * @internalComponent + */ +CSmsIEOperation* CSmsIEOperation::NewL(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) + { + LOGGSMU1("CSmsIEOperation::NewL()"); + + CSmsIEOperation* iEOperation = NULL; + + switch (aId) + { + case CSmsInformationElement::ESmsHyperLinkFormat: + iEOperation = new (ELeave) CSmsHyperLinkOperations(aId,aMessage); + break; + case CSmsInformationElement::ESmsReplyAddressFormat: + iEOperation = new (ELeave) CSmsReplyAddressOperations(aId, aMessage, aCharacterSetConverter, aFs); + break; + case CSmsInformationElement::ESmsEnhanceVoiceMailInformation: + iEOperation = new (ELeave) CSmsEnhancedVoiceMailOperations(aId, aMessage, aCharacterSetConverter, aFs); + break; + case CSmsInformationElement::ESmsIEISpecialSMSMessageIndication: + iEOperation = new (ELeave) CSmsSpecialSMSMessageOperations(aId,aMessage); + break; + case CSmsInformationElement::ESmsIEISMSCControlParameters: + iEOperation = new (ELeave) CSmsSMSCCtrlParameterOperations(aId,aMessage); + break; + default: + User::Leave(KErrArgument); + break; + } + + iEOperation->ConstructL(); + + return iEOperation; + } // CSmsIEOperation::NewL + + +/** + * @publishedAll + * + * Identifies the information element which is supported by this operations class. + * + * @return The information element ID supported by this operations class. + * @capability None + */ +EXPORT_C CSmsInformationElement::TSmsInformationElementIdentifier CSmsIEOperation::Id() const + { + LOGGSMU1("CSmsIEOperation::Id()"); + + return iId; + } // CSmsInformationElement::TSmsInformationElementIdentifier + + +/** + * @internalComponent + * + * Identifies whether the message type supports is supported + * + * @return True if the message type is supported. False otherwise. + */ +TBool CSmsIEOperation::MessageTypeSupported() const + { + LOGGSMU1("CSmsIEOperation::MessageTypeSupported()"); + + CSmsPDU::TSmsPDUType type = iMessage.Type(); + + return ((type == CSmsPDU::ESmsDeliver) || + (type == CSmsPDU::ESmsSubmit)); + } // CSmsIEOperation::MessageTypeSupported + + +CSmsIEOperation::CSmsIEOperation(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : iId(aId), iMessage(aMessage) + { + //NOP + } // CSmsIEOperation::CSmsIEOperation + + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsIEOperation::operator=(const CSmsIEOperation&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsIEOperation::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsIEOperation::operator==(const CSmsIEOperation&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsIEOperation::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsCtrlOperation::operator=(const CSmsCtrlOperation&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsCtrlOperation::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsCtrlOperation::operator==(const CSmsCtrlOperation&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsCtrlOperation::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + BULLSEYE_RESTORE + } + +CSmsCtrlOperation::CSmsCtrlOperation(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : CSmsIEOperation(aId, aMessage) + { + //NOP + } // CSmsCtrlOperation::CSmsCtrlOperation + + +CSmsHyperLinkOperations::CSmsHyperLinkOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : CSmsCtrlOperation(aId, aMessage) + { + //NOP + } // CSmsHyperLinkOperations::CSmsHyperLinkOperations + + +void CSmsIEOperation::ConstructL() + { + LOGGSMU1("CSmsIEOperation::ConstructL()"); + } // CSmsIEOperation::ConstructL + + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsHyperLinkOperations::operator=(const CSmsHyperLinkOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsHyperLinkOperations::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsHyperLinkOperations::operator==(const CSmsHyperLinkOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsHyperLinkOperations::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Identifies whether the message type or version supports this operation + * + * @leave + * If the message type or version does not support this operation. + */ +void CSmsHyperLinkOperations::ValidateOperationL() const + { + LOGGSMU1("CSmsHyperLinkOperations::ValidateOperationL()"); + + if (iMessage.Version() < CSmsMessage::ESmsMessageV1) + { + LOGGSMU2("CSmsHyperLinkOperations::AddHyperLinkL, Operation not supported, Msg Version %d", iMessage.Version()); + User::Leave(KErrNotSupported); + } + + if (!MessageTypeSupported()) + { + LOGGSMU2("CSmsHyperLinkOperations::AddHyperLinkL, Operation not supported by this PDU type, type = %d", iMessage.Type()); + User::Leave(KErrNotSupported); + } + } // CSmsHyperLinkOperations::ValidateOperationL + + +/** + * @publishedAll + * + * This method adds a HyperLink to the CSmsMessage. + * + * @param aPosition + * The absolute character position within the message text. + * @param aTitle + * An integer representation of the number of characters in the hyperlink title. + * @param URL Length + * An integer representation of the number of characters in the URL. + * @leave KErrNotSupported + * If the message version or type does not support hyperlinks. + * @capability None + */ +EXPORT_C void CSmsHyperLinkOperations::AddHyperLinkL(TUint aPosition, TUint8 aTitleLength, TUint8 aURLLength) const + { + LOGGSMU1("CSmsHyperLinkOperations::AddHyperLinkL()"); + + ValidateOperationL(); + + CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo()); + + TBuf8 <4> buffer; + buffer.SetLength(4); + buffer[0] = (TUint8) (aPosition >> 8); // lowest octet contains the + buffer[1] = (TUint8) aPosition; // most significant bits + buffer[2] = aTitleLength; + buffer[3] = aURLLength; + + CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::ESmsHyperLinkFormat, buffer); + CleanupStack::PushL(iE); + additionalAttributes.AddControlInformationElementL(iE); + CleanupStack::Pop(iE); + } // CSmsHyperLinkOperations::AddHyperLinkL + + +/** + * @publishedAll + * + * Returns the number of Hyper Link IEs contained in this message. + * @leave KErrNotSupported + * If this functionality is not supported by this version or type of message. + * @return + * The number of hyper links contained in this message. + * @capability None + */ +EXPORT_C TUint CSmsHyperLinkOperations::NumberOfHyperLinksL() const + { + LOGGSMU1("CSmsHyperLinkOperations::NumberOfHyperLinks"); + + ValidateOperationL(); + + TUint numberOfHyperLinks = 0; + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::ESmsHyperLinkFormat) + { + numberOfHyperLinks++; + } + } + + return numberOfHyperLinks; + } // CSmsHyperLinkOperations::NumberOfHyperLinksL + + +/** + * @publishedAll + * + * Copies the attributes of the specified hyperlink. + * aIndex has the range [0..[n-1]] where n is the + * value returned by NumberOfHyperLinks() + * + * @param aIndex + * Identifies the hyperlink to extract. Has the range [0..[n-1]] + * where n is the value returned by NumberOfHyperLinks(). + * @param &aPosition + * The absolute character position within the message text. + * @param &aTitleLength + * An integer representation of the number of characters in the hyperlink title. + * @param &aURLLength + * An integer representation of the number of characters in the URL. + * @leave KErrNotSupported + * If the message version or type does not support hyperlinks. + * @leave KErrArgument + * If aIndex is out of range. + * @capability None + */ +EXPORT_C void CSmsHyperLinkOperations::CopyHyperLinkAtIndexL(TUint aIndex, TUint& aPosition, TUint8& aTitleLength, TUint8& aURLLength) const + { + LOGGSMU2("CSmsHyperLinkOperations::CopyHyperLinkAtIndexL(): aIndex=%d", aIndex); + + ValidateOperationL(); + + TUint numberOfHyperLinks = 0; + + TSmsInformationElementCategories::TInformationElementCategory category; + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + if (aIndex >= numberOfElements) + { + User::Leave(KErrArgument); + } + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if ((id == CSmsInformationElement::ESmsHyperLinkFormat) && + (numberOfHyperLinks++ == aIndex)) + { + aPosition = (additionalAttributes->GetControlInformationElementL(category, i).Data()[0] << 8); + aPosition += additionalAttributes->GetControlInformationElementL(category, i).Data()[1]; + + aTitleLength = additionalAttributes->GetControlInformationElementL(category, i).Data()[2]; + aURLLength = additionalAttributes->GetControlInformationElementL(category, i).Data()[3]; + break; + } + } + } // CSmsHyperLinkOperations::CopyHyperLinkAtIndexL + + +/** + * @publishedAll + * + * Removes all hyper Link IEs contained in this message. + * + * @leave KErrNotSupported + * If the message version or type does not support hyperlinks. + * @capability None + */ +EXPORT_C void CSmsHyperLinkOperations::RemoveAllHyperLinksL() const + { + LOGGSMU1("CSmsHyperLinkOperations::RemoveAllHyperLinks"); + + ValidateOperationL(); + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint i = additionalAttributes->NumberOfControlInformationElements(category); + + while (i-- != 0) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::ESmsHyperLinkFormat) + { + additionalAttributes->DeleteControlInformationElement(category, i); + } + } + } // CSmsHyperLinkOperations::RemoveAllHyperLinksL + + +/** + * @publishedAll + * + * Removes the indexed hyperlink from this message. + * + * @param aIndex + * aIndex has the range [0..[n-1]] where n is the + * value returned by NumberOfHyperLinks() + * @leave KErrNotSupported + * If the message version or type does not support hyperlinks. + * @leave KErrArgument + * If the index is out of range. + * @capability None + */ +EXPORT_C void CSmsHyperLinkOperations::RemoveHyperLinkL(TUint aIndex) const + { + LOGGSMU1("CSmsHyperLinkOperations::RemoveHyperLink"); + + ValidateOperationL(); + + TUint numberOfHyperLinks = 0; + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + if (aIndex >= numberOfElements) + { + User::Leave(KErrArgument); + } + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if ((id == CSmsInformationElement::ESmsHyperLinkFormat) && + (numberOfHyperLinks++ == aIndex)) + { + additionalAttributes->DeleteControlInformationElement(category, i); + break; + } + } + } // CSmsHyperLinkOperations::RemoveHyperLinkL + + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsReplyAddressOperations::operator=(const CSmsReplyAddressOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsReplyAddressOperations::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsReplyAddressOperations::operator==(const CSmsReplyAddressOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsReplyAddressOperations::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Identifies whether the message type or version supports this operation + * + * @leave + * If the message type or version does not support this operation. + */ +void CSmsReplyAddressOperations::ValidateOperationL() const + { + LOGGSMU1("CSmsReplyAddressOperations::ValidateOperationL()"); + + if (iMessage.Version() < CSmsMessage::ESmsMessageV1) + { + LOGGSMU2("CSmsReplyAddressOperations::AddReplyAddressL, Operation not supported, Msg Version %d", iMessage.Version()); + User::Leave(KErrNotSupported); + } + + if (!MessageTypeSupported()) + { + LOGGSMU2("CSmsReplyAddressOperations::AddReplyAddressL, Operation not supported by this PDU type, type = %d", iMessage.Type()); + User::Leave(KErrNotSupported); + } + } // CSmsReplyAddressOperations::ValidateOperationL + + +/** + * @publishedAll + * + * Adds a reply address information element. + * + * @param aAddress + * The international number to be used in the reply address. + * @leave KErrNotSupported + * If the message version or type does not support a reply addresses. + * @leave KErrAlreadyExists + * If the message already contains a reply address. + * @capability None + */ +EXPORT_C void CSmsReplyAddressOperations::AddReplyAddressL(const TDesC& aAddress) const + { + LOGGSMU1("CSmsReplyAddressOperations::AddReplyAddressL()"); + + ValidateOperationL(); + + if (ContainsReplyAddressIEL()) + { + LOGGSMU1("CSmsReplyAddressOperations::AddReplyAddressL, Already Exists"); + User::Leave(KErrAlreadyExists); + } + + CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo()); + + CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs); // needed for encoding the address into the IE. + CleanupStack::PushL(address); + address->SetAddressL(aAddress); + TBuf8 addressBuffer; + addressBuffer.SetLength(CSmsAddress::KSmsAddressMaxAddressLength); + TUint8* startPtr = &addressBuffer[0]; + TUint8* endPtr = address->EncodeL(startPtr); + TInt length = 0; + (endPtr > startPtr) ? (length = endPtr - startPtr) : (length = startPtr - endPtr); + addressBuffer.SetLength(length); + CleanupStack::PopAndDestroy(address); + + CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::ESmsReplyAddressFormat, addressBuffer); + CleanupStack::PushL(iE); + additionalAttributes.AddControlInformationElementL(iE); + CleanupStack::Pop(iE); + } // CSmsReplyAddressOperations::AddReplyAddressL + + +/** + * @publishedAll + * + * Adds a reply address information element. + * + * @param aAddress + * Sets To and From addresses in ETSI format. + * @leave KErrNotSupported + * If the message version or type does not support a reply addresses. + * @leave KErrAlreadyExists + * If the message already contains a reply address. + * @capability None + */ +EXPORT_C void CSmsReplyAddressOperations::AddParsedReplyAddressL(const TGsmSmsTelNumber& aParsedAddress) const + { + LOGGSMU1("CSmsReplyAddressOperations::AddParsedReplyAddressL"); + + ValidateOperationL(); + + if (ContainsReplyAddressIEL()) + { + LOGGSMU1("CSmsReplyAddressOperations::AddParsedReplyAddressL, Already Exists"); + User::Leave(KErrAlreadyExists); + } + + CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo()); + + CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs); + CleanupStack::PushL(address); + address->SetParsedAddressL(aParsedAddress); + TBuf8 addressBuffer; + addressBuffer.SetLength(CSmsAddress::KSmsAddressMaxAddressLength); + TUint8* startPtr = &addressBuffer[0]; + TUint8* endPtr = address->EncodeL(startPtr); + TInt length = 0; + (endPtr > startPtr) ? (length = endPtr - startPtr) : (length = startPtr - endPtr); + addressBuffer.SetLength(length); + CleanupStack::PopAndDestroy(address); + + CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::ESmsReplyAddressFormat, addressBuffer); + CleanupStack::PushL(iE); + additionalAttributes.AddControlInformationElementL(iE); + CleanupStack::Pop(iE); + } // CSmsReplyAddressOperations::AddParsedReplyAddressL + + +/** + * @publishedAll + * + * Identifies whether a reply address has already been added to this + * CSmsMessage using the CSmsReplyAddressOperations interface. + * + * @return + * True if the reply address has already been added using this interface. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @capability None + */ +EXPORT_C TBool CSmsReplyAddressOperations::ContainsReplyAddressIEL() const + { + LOGGSMU1("CSmsReplyAddressOperations::ContainsReplyAddressIEL()"); + + TBool rc = EFalse; + + ValidateOperationL(); + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::ESmsReplyAddressFormat) + { + rc = ETrue; + break; + } + } + + return rc; + } // CSmsReplyAddressOperations::ContainsReplyAddressIEL + + +/** + * @publishedAll + * + * Returns the reply address as an international number + * + * @return + * The reply address as an international number. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @leave KErrNotFound + * If the message does not contain a reply address information element. + * @leave KErrCorrupt + * If the reply address is corrupt + * @capability None + */ +EXPORT_C HBufC* CSmsReplyAddressOperations::GetReplyAddressL() const + { + LOGGSMU1("CSmsReplyAddressOperations::GetReplyAddressL"); + + ValidateOperationL(); + + TBool found = EFalse; + + CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs); + CleanupStack::PushL(address); + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::ESmsReplyAddressFormat) + { + TGsmuLex8 encodedAddress(additionalAttributes->GetControlInformationElementL(category, i).Data()); + TRAPD(err,address->DecodeL(encodedAddress)); + + if (err == KErrNone) + { + found = ETrue; + break; + } + else + { + User::Leave(KErrCorrupt); + } + } + } + + HBufC* buf = NULL; + if (found) + { + buf = HBufC::NewL(TGsmSmsTelNumberMaxLen); // 20 characters preceeded by '+' + *buf = address->Address(); + } + else + { + User::Leave(KErrNotFound); + } + + CleanupStack::PopAndDestroy(address); + + return buf; + } // CSmsReplyAddressOperations::GetReplyAddressL + + +/** + * @publishedAll + * + * Returns the reply address in ETSI format. + * + * @return + * True, if the CSmsMessage contains a reply address. + * False, otherwise + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @leave KErrCorrupt + * If the reply address is corrupt + * @capability None + */ +EXPORT_C TInt CSmsReplyAddressOperations::GetParsedReplyAddressL(TGsmSmsTelNumber& aParsedAddress) const + { + LOGGSMU1("CSmsReplyAddressOperations::GetParsedReplyAddressL"); + + ValidateOperationL(); + + TBool rc = EFalse; + + CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs); + CleanupStack::PushL(address); + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + // CSmsAddress is used here for encoding the reply address into an IE. + // It also used to encode the source / destination address in the CSmsMessage. + // CSmsAddress::DecodeL expects internally that alphanumeric addresses will be size + // CSmsAddress::KSmsAddressMaxAddressValueLength=10. + // Need to add padding bytes to bring the address field up to the maximum size. + if (id == CSmsInformationElement::ESmsReplyAddressFormat) + { + TBuf8 data; + data = additionalAttributes->GetControlInformationElementL(category, i).Data(); + TUint8 actualDataLength = data.Length(); + data.SetLength(CSmsAddress::KSmsAddressMaxAddressLength); + for (TUint8 j = actualDataLength; j < CSmsAddress::KSmsAddressMaxAddressLength; j++) + { + data[j] = 0; + } + + TGsmuLex8 encodedAddress(data); + TRAPD(err,address->DecodeL(encodedAddress)); + if (err==KErrNone) + { + address->ParsedAddress(aParsedAddress); + rc = ETrue; + break; + } + else + { + User::Leave(KErrCorrupt); + } + } + } + + CleanupStack::PopAndDestroy(address); + + return rc; + } // CSmsReplyAddressOperations::GetParsedReplyAddressL + + +/** + * @publishedAll + * + * Removes the reply address information element. + * + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @capability None + */ +EXPORT_C void CSmsReplyAddressOperations::RemoveReplyAddressL() const + { + LOGGSMU1("CSmsReplyAddressOperations::RemoveReplyAddress"); + + ValidateOperationL(); + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TInt i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::ESmsReplyAddressFormat) + { + additionalAttributes->DeleteControlInformationElement(category, i); + break; + } + } + } // CSmsReplyAddressOperations::RemoveReplyAddressL + + +CSmsReplyAddressOperations::CSmsReplyAddressOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage, + CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) : CSmsCtrlOperation(aId, aMessage), + iCharacterSetConverter(aCharacterSetConverter), iFs(aFs) + { + //NOP + } // CSmsReplyAddressOperations::CSmsReplyAddressOperations + + +/** + * @internalComponent + * + * Identifies whether the message type or version supports this operation + * + * @leave + * If the message type or version does not support this operation. + */ +void CSmsSpecialSMSMessageOperations::ValidateOperationL() const + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::ValidateOperationL()"); + + if (iMessage.Version() < CSmsMessage::ESmsMessageV1) + { + LOGGSMU2("CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL, Operation not supported, version %d", iMessage.Version()); + User::Leave(KErrNotSupported); + } + + if (!MessageTypeSupported()) + { + LOGGSMU2("CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL, Operation not supported by this PDU type, type = %d", iMessage.Type()); + User::Leave(KErrNotSupported); + } + } // CSmsSpecialSMSMessageOperations::ValidateOperationL + + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsSpecialSMSMessageOperations::operator=(const CSmsSpecialSMSMessageOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsSpecialSMSMessageOperations::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsSpecialSMSMessageOperations::operator==(const CSmsSpecialSMSMessageOperations&) + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + } // CSmsSpecialSMSMessageOperations::operator + + +/** + * @publishedAll + * + * Either adds a new or updates an existing special message indication information element. + * + * @param aStore + * Indicates whether or not the message shall be stored. + * @param aMessageIndicationType + * Indicates the basic message type + * @param aExtendedType + * Indicates the extended message type + * @param aProfile + * Indicates the profile ID of the Multiple Subscriber Profile + * @param aMessageCount + * Indicates the number of messages of the type specified in Octet 1 that are waiting + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @capability None + */ +EXPORT_C void CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL(TBool aStore, + TSmsMessageIndicationType aMessageIndicationType, + TExtendedSmsIndicationType aExtendedType, + TSmsMessageProfileType aProfile, + TUint8 aMessageCount) const + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL"); + + ValidateOperationL(); + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + TBuf8<2> data; + data.SetLength(2); + + data[0] = ( ((TUint8) aMessageIndicationType) + + ((TUint8) (aExtendedType << 2)) + + ((TUint8) (aProfile << 5)) + + ((TUint8) (aStore << 7)) ); + + data[1] = aMessageCount; + + CArrayFixFlat* indices = new(ELeave) CArrayFixFlat(4); + CleanupStack::PushL(indices); + userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication, *indices); + + TBool found = EFalse; + TInt count = indices->Count(); + for (TInt i=0; ((ioperator[](i); + CSmsInformationElement& ieAlreadyInWorkingPDU = userData.InformationElement(index); + + if (ieAlreadyInWorkingPDU.Data()[0] == data[0]) + { + ieAlreadyInWorkingPDU.Data()[1] = data[1]; + found = ETrue; + break; + } + } + CleanupStack::PopAndDestroy(indices); + + if (found == EFalse) + { + userData.AddInformationElementL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,data); + } + } // CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL + + +/** + * @publishedAll + * + * Gets a count of the number of special message indication information elements which + * are stored inside the user data. + * + * @return The number of special message indication information elements which + * are stored inside the user data. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @capability None + */ +EXPORT_C TUint CSmsSpecialSMSMessageOperations::GetCountOfSpecialMessageIndicationsL() const + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::GetCountOfSpecialMessageIndicationsL()"); + + ValidateOperationL(); + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + CArrayFixFlat* indices = new (ELeave) CArrayFixFlat(8); + CleanupStack::PushL(indices); + userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices); + TUint count = indices->Count(); + CleanupStack::PopAndDestroy(indices); + + return count; + } // CSmsSpecialSMSMessageOperations::GetCountOfSpecialMessageIndicationsL + + +/** + * @publishedAll + * + * Gets the attributes of the Special Message Indication specified by aIndex. + * + * @param aIndex + * aIndex is a value less than GetCountOfSpecialMessageIndications(). + * @param aStore + * Indicates whether or not the message shall be stored. + * @param aMessageIndicationType + * Indicates the basic message type + * @param aExtendedType + * Indicates the extended message type + * @param aProfile + * Indicates the profile ID of the Multiple Subscriber Profile + * @param aMessageCount + * Indicates the number of messages of the type specified in Octet 1 that are waiting + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @leave KErrArgument + * If aIndex is >= GetCountOfSpecialMessageIndications() + * @capability None + */ +EXPORT_C void CSmsSpecialSMSMessageOperations::GetMessageIndicationIEL(TUint aIndex, + TBool& aStore, + TSmsMessageIndicationType& aMessageIndicationType, + TExtendedSmsIndicationType& aExtendedType, + TSmsMessageProfileType& aProfile, + TUint8& aMessageCount) const + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::GetMessageIndicationIEL()"); + + ValidateOperationL(); + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + CArrayFixFlat* indices = new (ELeave) CArrayFixFlat(8); + CleanupStack::PushL(indices); + userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices); + + if (aIndex < indices->Count()) + { + CSmsInformationElement& informationElement = userData.InformationElement((*indices)[aIndex]); + + aMessageIndicationType = (TSmsMessageIndicationType) (informationElement.Data()[0] & 0x03); + aExtendedType = (TExtendedSmsIndicationType) ((informationElement.Data()[0] >> 2) & 0x07); + aProfile = (TSmsMessageProfileType) ((informationElement.Data()[0] >> 5) & 0x03); + aStore = (TBool) ((informationElement.Data()[0] >> 7) & 0x01); + aMessageCount = (TUint8) (informationElement.Data()[1]); + } + else + { + User::Leave(KErrArgument); + } + + CleanupStack::PopAndDestroy(indices); + } // CSmsSpecialSMSMessageOperations::GetMessageIndicationIEL + + +/** + * @publishedAll + * + * Removes the Special Message Indication specified by the input attributes, provided it exists. + * + * @param aMessageIndicationType + * Indicates the basic message type + * @param aExtendedType + * Indicates the extended message type + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @capability None + */ +EXPORT_C void CSmsSpecialSMSMessageOperations::RemoveSpecialMessageIndicationL(TSmsMessageIndicationType aMessageIndicationType, TExtendedSmsIndicationType aExtendedType) const + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndications"); + + ValidateOperationL(); + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + CArrayFixFlat* indices = new (ELeave) CArrayFixFlat(8); + CleanupStack::PushL(indices); + userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices); + + TUint i = indices->Count(); + + while (i-- != 0) + { + CSmsInformationElement& informationElement = userData.InformationElement((*indices)[i]); + + TSmsMessageIndicationType type = ((TSmsMessageIndicationType) (informationElement.Data()[0] & 0x03)); + TExtendedSmsIndicationType extendedType = (TExtendedSmsIndicationType) ((informationElement.Data()[0] >> 2) & 0x07); + + if ( (aMessageIndicationType == type) && + (aExtendedType == extendedType) ) + { + userData.RemoveInformationElement((*indices)[i]); + break; + } + } + + CleanupStack::PopAndDestroy(indices); + } // CSmsSpecialSMSMessageOperations::RemoveSpecialMessageIndicationL + + +/** + * @publishedAll + * + * Removes all Special Message Indications Information Elements contained in the message. + * + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @capability None + */ +EXPORT_C void CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndicationsL() const + { + LOGGSMU1("CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndicationsL"); + + ValidateOperationL(); + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + CArrayFixFlat* indices = new (ELeave) CArrayFixFlat(8); + CleanupStack::PushL(indices); + userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices); + + TUint i = indices->Count(); + + while (i-- != 0) + { + userData.RemoveInformationElement((*indices)[i]); + } + + CleanupStack::PopAndDestroy(indices); + } // CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndicationsL + + +CSmsSpecialSMSMessageOperations::CSmsSpecialSMSMessageOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : CSmsCtrlOperation(aId, aMessage) + { + //NOP + } // CSmsSpecialSMSMessageOperations::CSmsSpecialSMSMessageOperations + + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsEnhancedVoiceMailOperations::operator=(const CSmsEnhancedVoiceMailOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsEnhancedVoiceMailOperations::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsEnhancedVoiceMailOperations::operator==(const CSmsEnhancedVoiceMailOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsEnhancedVoiceMailOperations::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Identifies whether the message type or version supports this operation + * + * @leave + * If the message type or version does not support this operation. + */ +void CSmsEnhancedVoiceMailOperations::ValidateOperationL() const + { + LOGGSMU1("CSmsEnhancedVoiceMailOperations::ValidateOperationL()"); + + if (iMessage.Version() < CSmsMessage::ESmsMessageV1) + { + LOGGSMU2("CSmsEnhancedVoiceMailInformation::AddEnhancedVoiceMailIEL, Operation not supported, Msg Version %d", iMessage.Version()); + User::Leave(KErrNotSupported); + } + + if (!MessageTypeSupported()) + { + LOGGSMU2("CSmsSpecialSMSMessageOperations::AddEnhancedVoiceMailIEL, Operation not supported by this PDU type, type = %d", iMessage.Type()); + User::Leave(KErrNotSupported); + } + } // CSmsEnhancedVoiceMailOperations::ValidateOperationL + + +/** + * @publishedAll + * + * Adds an Enhanced Voice Mail Information Element to the CSmsMessage. + * The information element can be either an Enhanced Voice Mail Notification or + * an Enhanced Voice Mail Delete Confirmation. Enhanced Voice Mail Notifications + * and Enhanced Voice Mail Delete Confirmations are abstracted in classes derived + * from CEnhancedVoiceMailBoxInformation. + * @param aEVMI + * A pointer to the Enhanced Voice Mail Information Element. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @leave KErrAlreadyExists + * If an Enhanced Voice Mail Information Element has already been installed. + * @leave KErrArgument + * If the input parameter contains invalid parameters. + * @capability None + */ +EXPORT_C void CSmsEnhancedVoiceMailOperations::AddEnhancedVoiceMailIEL(const CEnhancedVoiceMailBoxInformation& aEVMI) const + { + LOGGSMU1("CSmsEnhancedVoiceMailInformation::AddEnhancedVoiceMailIEL"); + + ValidateOperationL(); + + if (ContainsEnhancedVoiceMailIEL()) + { + LOGGSMU1("CSmsEnhancedVoiceMailInformation::AddEnhancedVoiceMailIEL, Already Exists"); + User::Leave(KErrAlreadyExists); + } + + CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo()); + + // The Enhanced Voice Mail Information Element must fit into a single PDU. + // The maximum size for its data field is therefore + // the maximum size of the user data minus user data header length, the ie identifier byte and + // ie length byte. + TBuf8 voiceMailInfo; + voiceMailInfo.SetLength(CEnhancedVoiceMailNotification::KSmsMaxEnhancedVoiceMailSize); + TUint8* startPtr = &voiceMailInfo[0]; + TUint8* endPtr = aEVMI.EncodeL(startPtr, iCharacterSetConverter, iFs); + TInt length = (TInt) (endPtr - startPtr); + voiceMailInfo.SetLength(length); + + CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::CSmsInformationElement::ESmsEnhanceVoiceMailInformation, voiceMailInfo); + CleanupStack::PushL(iE); + + additionalAttributes.AddControlInformationElementL(iE); + CleanupStack::Pop(); + } // CSmsEnhancedVoiceMailOperations::AddEnhancedVoiceMailIEL + + +/** + * @publishedAll + * + * Removes the Enhanced Voice Mail Information Element from the CSmsMessage, + * provided it exists. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @leave KErrNotFound + * If the CSmsMessage does not contain an Enhanced Voice Mail Information Element + * @capability None + */ +EXPORT_C CEnhancedVoiceMailBoxInformation* CSmsEnhancedVoiceMailOperations::RemoveEnhancedVoiceMailIEL() const + { + LOGGSMU1("CSmsEnhancedVoiceMailInformation::RemoveEnhancedVoiceMailIE"); + + ValidateOperationL(); + + CEnhancedVoiceMailBoxInformation* voiceMailBoxInfo = NULL; + TBool deleteInformationElement = ETrue; + + // If function leaves, allow the error to propagate upwards + voiceMailBoxInfo = GetEnhancedVoiceMailIEL(deleteInformationElement); + + return voiceMailBoxInfo; + } // CSmsEnhancedVoiceMailOperations::RemoveEnhancedVoiceMailIEL + + +/** + * @publishedAll + * + * Copies the Enhanced Voice Mail Information Element contained in the CSmsMessage, + * provided one exists. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @leave KErrNotFound + * If the CSmsMessage does not contain an Enhanced Voice Mail Information Element to copy. + * @capability None + */ +EXPORT_C CEnhancedVoiceMailBoxInformation* CSmsEnhancedVoiceMailOperations::CopyEnhancedVoiceMailIEL() const + { + LOGGSMU1("CSmsEnhancedVoiceMailInformation::CopyEnhancedVoiceMailIEL"); + + ValidateOperationL(); + + CEnhancedVoiceMailBoxInformation* voiceMailBoxInfo = NULL; + TBool deleteInformationElement = EFalse; + + // If function leaves, allow the error to propagate upwards + voiceMailBoxInfo = GetEnhancedVoiceMailIEL(deleteInformationElement); + + return voiceMailBoxInfo; + } // CSmsEnhancedVoiceMailOperations::CopyEnhancedVoiceMailIEL + + +/** + * @internalComponent + * + * Returns a copy of the Enhanced Voice Mail Information Element contained in the CSmsMessage, + * provided one exists. Optionally deletes the information element. + * @param aRemove + * Indicates that the information element should be deleted once its contents have been copied. + * @leave KErrNotFound + * If the CSmsMessage does not contain an Enhanced Voice Mail Information Element to copy. + */ +CEnhancedVoiceMailBoxInformation* CSmsEnhancedVoiceMailOperations::GetEnhancedVoiceMailIEL(TBool aRemove) const + { + LOGGSMU1("CSmsEnhancedVoiceMailOperations::GetEnhancedVoiceMailIEL()"); + + TBool found = EFalse; + + CEnhancedVoiceMailBoxInformation* voiceMailBoxInfo = NULL; + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsEnhanceVoiceMailInformation, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::CSmsInformationElement::ESmsEnhanceVoiceMailInformation) + { + if (additionalAttributes->GetControlInformationElementL(category, i).Data()[0] & 0x01) + { + voiceMailBoxInfo = CEnhancedVoiceMailDeleteConfirmations::NewL(); + } + else + { + voiceMailBoxInfo = CEnhancedVoiceMailNotification::NewL(); + } + + CleanupStack::PushL(voiceMailBoxInfo); + TGsmuLex8 encodedVoiceMailBox(additionalAttributes->GetControlInformationElementL(category, i).Data()); + voiceMailBoxInfo->DecodeL(encodedVoiceMailBox, iCharacterSetConverter, iFs); + CleanupStack::Pop(voiceMailBoxInfo); + + if (aRemove) + { + additionalAttributes->DeleteControlInformationElement(category, i); + } + + found = ETrue; + + break; + } + } + + if (found == EFalse) + { + User::Leave(KErrNotFound); + } + + return voiceMailBoxInfo; + } // CSmsEnhancedVoiceMailOperations::GetEnhancedVoiceMailIEL + + +/** + * @publishedAll + * + * Determines whether the CSmsMessage contains an Enhanced Voice Mail Information Element. + * @leave KErrNotSupported + * If the message version or type does not support this query. + * @return + * True if the CSmsMessage contains an Enhanced Voice Mail Information Element. + * @capability None + */ +EXPORT_C TBool CSmsEnhancedVoiceMailOperations::ContainsEnhancedVoiceMailIEL() const + { + LOGGSMU1("CSmsEnhancedVoiceMailInformation::ContainsEnhancedVoiceMailIEL"); + + ValidateOperationL(); + + TBool rc = EFalse; + + TSmsInformationElementCategories::TInformationElementCategory category; + + if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsEnhanceVoiceMailInformation, category) == EFalse) + { + User::Leave(KErrArgument); + } + + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category); + + for (TUint i = 0; i < numberOfElements; i++) + { + CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum; + + // If function leaves, allow the error to propagate upwards + id = additionalAttributes->GetControlInformationElementL(category, i).Identifier(); + + if (id == CSmsInformationElement::ESmsEnhanceVoiceMailInformation) + { + rc = ETrue; + break; + } + } + + return rc; + } // CSmsEnhancedVoiceMailOperations::ContainsEnhancedVoiceMailIEL + + +/** + * Status Reporting. + * + * @note This should be the last thing that should be configured in CSmsMessage. + * If anything is changed after this then the number of PDUs might change which + * will affect status reporting. + */ +CSmsEnhancedVoiceMailOperations::CSmsEnhancedVoiceMailOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage, + CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) : CSmsCtrlOperation(aId, aMessage), + iCharacterSetConverter(aCharacterSetConverter), iFs(aFs) + { + // NOP + } // CSmsEnhancedVoiceMailOperations::CSmsEnhancedVoiceMailOperations + + +CSmsSMSCCtrlParameterOperations::CSmsSMSCCtrlParameterOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) +: CSmsCtrlOperation(aId, aMessage) + { + + } // CSmsSMSCCtrlParameterOperations::CSmsSMSCCtrlParameterOperations + + +/** + * @internalComponent + * + * Prevent clients from using the assignment operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +void CSmsSMSCCtrlParameterOperations::operator=(const CSmsSMSCCtrlParameterOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsSMSCCtrlParameterOperations::operator="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Prevent clients from using the equality operator by including it in the class definition + * but making it protected and not exporting it. + * + * @capability None + */ +TBool CSmsSMSCCtrlParameterOperations::operator==(const CSmsSMSCCtrlParameterOperations&) + { + // Ignore in code coverage - not intended to be used + BULLSEYE_OFF + LOGGSMU1("CSmsSMSCCtrlParameterOperations::operator=="); + Panic(KGsmuPanicMethodBodyNotImplemented1); + return EFalse; + BULLSEYE_RESTORE + } + +/** + * @internalComponent + * + * Identifies whether the message type or version supports this operation + * + * @leave + * If the message type or version does not support this operation. + */ +void CSmsSMSCCtrlParameterOperations::ValidateOperationL() const + { + if (iMessage.Version() < CSmsMessage::ESmsMessageV2) + { + LOGGSMU2("CSmsSMSCCtrlParameterOperations Operation not supported, Msg Version %d", iMessage.Version()); + User::Leave(KErrNotSupported); + } + + if (!MessageTypeSupported()) + { + LOGGSMU2("CSmsSMSCCtrlParameterOperations Operation not supported by this PDU type, type = %d", iMessage.Type()); + User::Leave(KErrNotSupported); + } + } // CSmsSMSCCtrlParameterOperations::ValidateOperationL() + + +/** + * @internalComponent + * + * Checks that the octet passed to it has the valid bits set in it. If the bits which + * are not supported yet are set then reset it. + * This method is called by SetStatusReportL. + * + * @param aSelectiveStatus + * The octet which needs to be set as the Selective Status for the report. + * @return + * ETrue if the selective status is valid. + * @leave KErrNotSupported + * If the last 4 bits are set as they are not supported. + */ +TBool CSmsSMSCCtrlParameterOperations::ValidateControlParametersL(TUint8& aSelectiveStatus) const + { + if (aSelectiveStatus & ESmsStatusReportForFutureUse1) + { + User::Leave(KErrNotSupported); + } + + if (aSelectiveStatus & ESmsStatusReportForFutureUse2) + { + User::Leave(KErrNotSupported); + } + + if (aSelectiveStatus & ESmsStatusReportCancelRestSRR) + { + User::Leave(KErrNotSupported); + } + + if (aSelectiveStatus & ESmsStatusReportIncludeOriginalUDH) + { + User::Leave(KErrNotSupported); + } + + return ETrue; + } // CSmsSMSCCtrlParameterOperations::ValidateControlParametersL + + +/** + * @publishedAll + * + * Sets the status report for a PDU. First the scheme is obtained by calling the + * GetStatusReportScheme and checked if it is the valid scheme. Then aSelectiveStatus is + * checked to see if it is the default value. If it is then nothing is done. But if + * aSelectiveStatus is non-default then it is appended to the array + * iControlParametersStatusReport along with the aSegmentSequenceNum + * + * @param aSegmentSequenceNum + * The segment sequence number of the PDU which needs to be updated. + * @param aSelectiveStatus + * The octet which needs to be set as the Selective Status for the report. + * @return KErrNone if the operation is successful. + * KErrNotFound if the Segment Sequence Number is out of range or the scheme is inavlid. + * KErrNotSupported if aSelectiveStatus is not valid. + * @leave + * If ValidateOperationL or AppendL leaves. + * @capability None + */ +EXPORT_C TInt CSmsSMSCCtrlParameterOperations::SetStatusReportL(TUint aSegmentSequenceNum, TUint8 aSelectiveStatus) + { + ValidateOperationL(); + TBool validateStatus = ValidateControlParametersL(aSelectiveStatus); + + if(validateStatus) + { + CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo()); + CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes.GetStatusReportScheme(); + if (scheme.Id() == EControlParametersScheme) + { + CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme; + if(aSegmentSequenceNum>=ctrlParamsScheme.iNumOfPDUs) + { + return KErrNotFound; // aSegmentSequenceNum out of range. + } + if (aSelectiveStatus == ctrlParamsScheme.iDefaultStatusReport) + { + return KErrNone; // It's the same as default so need for any updation. + } + else + { + TInt count = (ctrlParamsScheme.iControlParametersStatusReport).Count(); + TBool found(EFalse); + for (TInt ii=0; !found && iiGetStatusReportScheme(); + if (scheme.Id() == EControlParametersScheme) + { + CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme; + + if(aSegmentSequenceNum>=ctrlParamsScheme.iNumOfPDUs) + { + return KErrNotFound; // aSegmentSequenceNum out of range. + } + + TInt count = (ctrlParamsScheme.iControlParametersStatusReport).Count(); + + for (TInt ii=0; ii buffer; + buffer.SetLength(1); + buffer[0] = 0; + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + userData.AddInformationElementL(CSmsInformationElement::ESmsIEISMSCControlParameters,buffer); + + CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes.GetStatusReportScheme(); + CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme; + ctrlParamsScheme.iNumOfPDUs = iMessage.NumMessagePDUsL(); + + SetDefaultL(0); + } // CSmsSMSCCtrlParameterOperations::SetSchemeL + + +/** + * @publishedAll + * + * Gets the current scheme being used. + * + * @return + * EControlParametrsScheme is returned when Control Parameters Scheme is being used. + * @capability None + */ +EXPORT_C TSmsStatusReportScheme CSmsSMSCCtrlParameterOperations::GetScheme() const + { + CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo(); + + return (additionalAttributes->GetStatusReportScheme()).Id(); + } // CSmsSMSCCtrlParameterOperations::GetScheme + + +/** + * @publishedAll + * + * This method re-sets the scheme to the Default Scheme. + * + * @capability None + */ +EXPORT_C void CSmsSMSCCtrlParameterOperations::ResetSchemeL() + { + CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo()); + + CSmsUserData& userData = iMessage.SmsPDU().UserData(); + + CArrayFixFlat* indices = new (ELeave) CArrayFixFlat(8); + CleanupStack::PushL(indices); + userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISMSCControlParameters,*indices); + + TUint i = indices->Count(); + + while (i-- != 0) + { + userData.RemoveInformationElement((*indices)[i]); + } + + CleanupStack::PopAndDestroy(indices); + additionalAttributes.SetStatusReportSchemeL(EDefaultScheme); + } // CSmsSMSCCtrlParameterOperations::ResetSchemeL +