// 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<CSmsAddress::KSmsAddressMaxAddressLength> 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<CSmsAddress::KSmsAddressMaxAddressLength> 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<CSmsAddress::KSmsAddressMaxAddressLength> 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<TInt>* indices = new(ELeave) CArrayFixFlat<TInt>(4);
CleanupStack::PushL(indices);
userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication, *indices);
TBool found = EFalse;
TInt count = indices->Count();
for (TInt i=0; ((i<count) && (found==EFalse)); i++)
{
TUint index = indices->operator[](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<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(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<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(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<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(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<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(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<CEnhancedVoiceMailBoxInformation::KSmsMaxEnhancedVoiceMailSize> 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 && ii<count; ii++)
{
if ((ctrlParamsScheme.iControlParametersStatusReport[ii]).iSegmentSequenceNum == aSegmentSequenceNum)
{
(ctrlParamsScheme.iControlParametersStatusReport[ii]).iSelectiveStatus = aSelectiveStatus;
found = ETrue;
break;
}
}
if (!found)
{
CSmsMessageAdditionalAttributes::CControlParametersScheme::TSmsSMSCCtrlParameterStatus smscCtrlParameterStatus;
smscCtrlParameterStatus.iSegmentSequenceNum = aSegmentSequenceNum;
smscCtrlParameterStatus.iSelectiveStatus = aSelectiveStatus;
(ctrlParamsScheme.iControlParametersStatusReport).AppendL(smscCtrlParameterStatus);
}
return KErrNone;
}
}
else
{
return KErrNotFound; // Scheme not valid.
}
}
else
{
return KErrNotSupported; // Invalid aSlectiveStatus.
}
} // CSmsSMSCCtrlParameterOperations::SetStatusReportL
/**
* @publishedAll
*
* Gets the selective status for a PDU if the scheme is set to the Control
* Parameters Scheme.
*
* @param aSegmentSequenceNum
* The segment sequence number of the PDU whose status report is required.
* @param aSelectiveStatus
* Returns the selective status octet for that PDU.
*
* @return KErrNotFound if the segment sequence number or the scheme is invalid.
*
* @capability None
*/
EXPORT_C TInt CSmsSMSCCtrlParameterOperations::GetStatusReport(TUint aSegmentSequenceNum,
TUint8& aSelectiveStatus) const
{
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.
}
TInt count = (ctrlParamsScheme.iControlParametersStatusReport).Count();
for (TInt ii=0; ii<count; ii++)
{
if (ctrlParamsScheme.iControlParametersStatusReport[ii].iSegmentSequenceNum == aSegmentSequenceNum)
{
aSelectiveStatus = ctrlParamsScheme.iControlParametersStatusReport[ii].iSelectiveStatus;
return KErrNone;
}
}
aSelectiveStatus = ctrlParamsScheme.iDefaultStatusReport;
return KErrNone;
}
return KErrNotFound;
} // CSmsSMSCCtrlParameterOperations::GetStatusReport
/**
* @publishedAll
*
* Sets the default value of the status report to aDefaultSelectiveStatus.
*
* @param aDefaultSelectiveStatus
* The selective status to be used as default.
* @leave KErrNotFound
* If the scheme is invalid.
* @capability None
*/
EXPORT_C void CSmsSMSCCtrlParameterOperations::SetDefaultL(TUint8 aDefaultSelectiveStatus)
{
CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes.GetStatusReportScheme();
if (scheme.Id() == EControlParametersScheme)
{
CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
if(aDefaultSelectiveStatus & ESmsSMSCControlParametersMask)
{
ctrlParamsScheme.iDefaultStatusReport = aDefaultSelectiveStatus;
}
else
{
ctrlParamsScheme.iDefaultStatusReport = 0x00;
}
}
else
{
User::Leave(KErrNotFound);
}
} // CSmsSMSCCtrlParameterOperations::SetDefaultL
/**
* @publishedAll
*
* This method is called to set the scheme to Control Parameters Scheme.
* First iStatusReportScheme, which is obtained by calling GetStatusReportScheme,
* is deleted and set to NULL. Then a new scheme is created and a default value is set.
* This should be the last method to be called in a message sending process as all the
* operations in this interface depend on the number of PDUs being set.
*
* @leave
* If ValidateOperationL or NumMessagePDUsL leaves.
* @capability None
*/
EXPORT_C void CSmsSMSCCtrlParameterOperations::SetSchemeL()
{
ValidateOperationL();
CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
additionalAttributes.SetStatusReportSchemeL(EControlParametersScheme);
TBuf8 <1> 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<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(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