diff -r 000000000000 -r 3553901f7fa8 smsprotocols/smsstack/test/smspdudb.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/smsprotocols/smsstack/test/smspdudb.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,660 @@ +// Copyright (c) 2003-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 "smspdudb.h" +#include +#include "Gsmumsg.h" +#include "gsmubuf.h" + +const TInt KSmsPduDbMaxReadWriteChunk = 0x200; + +EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs) +/** + * CSmsPduDatabase default factory function + * + * Calls the other overload of NewL with the default section, filename and component. + */ + { + return NewL(aFs, KSmsPduDbDefaultSection, KSmsPduDbDefaultFilename, KSmsPduDbDefaultComponent); + } + +EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs, const TDesC8& aSection, const TDesC& aFileName, const TDesC& aComponent) + { + CSmsPduDatabase* self = new (ELeave) CSmsPduDatabase(aFs); + CleanupStack::PushL(self); + + //Construct iConfigFile and set iSection to aSection + CTestConfig* testConfig = CTestConfig::NewLC(aFs, aComponent, aFileName); + CleanupStack::Pop(testConfig); + + self->iConfigFile = testConfig; + self->SetSectionL(aSection); + + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CSmsPduDatabase* CSmsPduDatabase::NewL(RFs& aFs, const CTestConfigSection& aSection) +/** + * Constructs a CSmsPduDatabase and sets iSection to aSection. + * @note iConfigFile is not constructed and should remain NULL + */ + { + CSmsPduDatabase* self = new (ELeave) CSmsPduDatabase(aFs); + self->SetSection(aSection); + return self; + } + +EXPORT_C CSmsPduDatabase::~CSmsPduDatabase() + { + delete iConfigFile; + // @note Don't delete iSection because it is either owned by iConfigFile or by another config file + } + +TPtrC8 CSmsPduDatabase::GetTypeL(CSmsPDU::TSmsPDUType aType) const + { + TPtrC8 type; + + switch (aType) + { + case CSmsPDU::ESmsSubmit: + + type.Set(KSmsPduDbSubmit); + break; + + case CSmsPDU::ESmsDeliver: + + type.Set(KSmsPduDbDeliver); + break; + + case CSmsPDU::ESmsCommand: + + type.Set(KSmsPduDbCommand); + break; + + case CSmsPDU::ESmsStatusReport: + + type.Set(KSmsPduDbStatusReport); + break; + + case CSmsPDU::ESmsSubmitReport: + + type.Set(KSmsPduDbSubmitReport); + break; + + case CSmsPDU::ESmsDeliverReport: + + type.Set(KSmsPduDbDeliverReport); + break; + + default: + + User::Leave(KErrNotSupported); + break; + } + + return type; + } + +TPtrC8 CSmsPduDatabase::GetConcatTypeL(CSmsPDU::TSmsPDUType aType) const + { + TPtrC8 type; + + switch (aType) + { + case CSmsPDU::ESmsSubmit: + + type.Set(KSmsPduDbSubmitConcat); + break; + + case CSmsPDU::ESmsDeliver: + + type.Set(KSmsPduDbDeliverConcat); + break; + + default: + + User::Leave(KErrNotSupported); + break; + } + + return type; + } + + +EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::GetPduLC(CSmsPDU::TSmsPDUType aType, TInt aId) const + { + const TPtrC8 type(GetTypeL(aType)); + RSmsPduDbIdArray array(type); + CleanupClosePushL(array); + GetIdsL(array, aId); + + const CTestConfigItem& item = *array[0].iItem; + + CSmsPduDbPdu* pdu = CSmsPduDbPdu::NewL(iFs, item, aType); + CleanupStack::PopAndDestroy(&array); + CleanupStack::PushL(pdu); + return pdu; + } + +EXPORT_C void CSmsPduDatabase::GetPduL(RPointerArray& aArray, CSmsPDU::TSmsPDUType aType) const + { + const TPtrC8 type(GetTypeL(aType)); + RSmsPduDbIdArray array(type); + CleanupClosePushL(array); + + GetIdsL(array); + const TInt count = array.Count(); + + for (TInt i = 0; i < count; i++) + { + CSmsPduDbPdu* pdu = CSmsPduDbPdu::NewL(iFs, *array[i].iItem, aType); + CleanupStack::PushL(pdu); + User::LeaveIfError(aArray.Append(pdu)); + CleanupStack::Pop(pdu); + } + + CleanupStack::PopAndDestroy(&array); + } + +EXPORT_C CSmsPduDbConcatSegment* CSmsPduDatabase::GetConcatSegmentLC(CSmsPDU::TSmsPDUType aType, TInt aId, TInt aSegment) const + { + const TPtrC8 type(GetConcatTypeL(aType)); + RSmsPduDbIdArray array(type, ETrue); + CleanupClosePushL(array); + GetIdsL(array, aId); + + CSmsPduDbConcatSegment* concat = GetConcatSegmentL(array, aType, aId, aSegment); + + CleanupStack::PopAndDestroy(&array); + CleanupStack::PushL(concat); + return concat; + } + +CSmsPduDbConcatSegment* CSmsPduDatabase::GetConcatSegmentL(const RSmsPduDbIdArray& aIdArray, CSmsPDU::TSmsPDUType aType, TInt aId, TInt aSegment) const + { + const TInt count = aIdArray.Count(); + CSmsPduDbConcatSegment* concat = NULL; + + for (TInt i = 0; i < count; i++) //order important + { + const TSmsPduDbId& id = aIdArray[i]; + + if (id.iId == aId) + { + const TDesC8& val = id.iItem->Value(); + TInt segment = KErrNotFound; + const TInt err = CTestConfig::GetElement(val, KSmsPduDbDelimiter, CSmsPduDbConcatSegment::EConcatSegment, segment); + + if (err == KErrNone && segment == aSegment) + { + concat = CSmsPduDbConcatSegment::NewL(iFs, *id.iItem, aType); + break; + } + } + } + + if (concat == NULL) + User::Leave(KErrNotFound); + + return concat; + } + +EXPORT_C CSmsPduDbConcat* CSmsPduDatabase::GetConcatLC(CSmsPDU::TSmsPDUType aType, TInt aId) const + { + const TPtrC8 type(GetConcatTypeL(aType)); + RSmsPduDbIdArray array(type, ETrue); + CleanupClosePushL(array); + GetIdsL(array, aId); + + CSmsPduDbConcat* concat = new (ELeave) CSmsPduDbConcat(); + CleanupStack::PushL(concat); + + const TInt count = array.Count(); + + for (TInt i=0; iiSegments.Append(concatSegment)); + } + + concat->DecodeL(iFs); + + CleanupStack::PopAndDestroy(&array); + return concat; + } + +EXPORT_C void CSmsPduDatabase::GetConcatL(RPointerArray& aArray, CSmsPDU::TSmsPDUType aType) const + { + const TPtrC8 type(GetConcatTypeL(aType)); + RSmsPduDbIdArray array(type, ETrue); + CleanupClosePushL(array); + GetIdsL(array); + + const TInt count = array.Count(); + TInt lastId = KErrNotFound; + CSmsPduDbConcat* concat = NULL; + + for (TInt i=0; iDecodeL(iFs); + + concat = new (ELeave) CSmsPduDbConcat(); + CleanupStack::PushL(concat); + User::LeaveIfError(aArray.Append(concat)); + CleanupStack::Pop(concat); + lastId = id; + } + + CSmsPduDbConcatSegment* segment = CSmsPduDbConcatSegment::NewL(iFs, item, aType); + CleanupStack::PushL(segment); + User::LeaveIfError(concat->iSegments.Append(segment)); + CleanupStack::Pop(segment); + } + + if (concat != NULL) + concat->DecodeL(iFs); + + CleanupStack::PopAndDestroy(&array); + } + +EXPORT_C CSmsPduDbMessage* CSmsPduDatabase::GetMessageLC(CSmsPDU::TSmsPDUType aType, TInt aId) const + { + RSmsPduDbIdArray array(KSmsPduDbMessage); + CleanupClosePushL(array); + GetIdsL(array, aId); + + const CTestConfigItem& item = *array[0].iItem; + CSmsPduDbMessage* pdu = CSmsPduDbMessage::NewL(iFs, item, aType); + CleanupStack::PushL(pdu); + + + CleanupStack::PopAndDestroy(&array); + return pdu; + } + +EXPORT_C void CSmsPduDatabase::GetMessageL(RPointerArray& aArray, CSmsPDU::TSmsPDUType aType) const + { + RSmsPduDbIdArray array(KSmsPduDbMessage); + CleanupClosePushL(array); + GetIdsL(array); + + const TInt count = array.Count(); + + for (TInt i=0; i array; + CleanupClosePushL(array); + + iSection->ItemsL(array, aIds.Type()); + + const TInt count = array.Count(); + + for (TInt i=0; iValue(), KSmsPduDbDelimiter, CSmsPduDbBase::ESmsPduDbId, item.iId); + if (err == KErrNone) + { + aIds.InsertL(item); + } + } + + CleanupStack::PopAndDestroy(&array); + } + +void CSmsPduDatabase::GetIdsL(RSmsPduDbIdArray& aIds, TInt aId) const + { + RSmsPduDbIdArray tempArray(aIds.Type(), ETrue); + CleanupClosePushL(tempArray); + + GetIdsL(tempArray); + + TInt find = KErrNotFound; + + while ((find = tempArray.Find(aId)) != KErrNotFound) + { + User::LeaveIfError(aIds.Append(tempArray[find])); + tempArray.Remove(find); + } + + CleanupStack::PopAndDestroy(&tempArray); + if (aIds.Count() == 0) + User::Leave(KErrNotFound); + } + +void CSmsPduDatabase::ReadFileL(const TDesC& aInputFileName, const TDesC& aInputComponent, CBufFlat& aData) const + { + TParse parse; + User::LeaveIfError(CTestConfig::ResolveFile(iFs, aInputComponent, aInputFileName, parse)); + + RFile file; + User::LeaveIfError(file.Open(iFs, parse.FullName(), EFileRead)); + CleanupClosePushL(file); + + TInt size(0); + User::LeaveIfError(file.Size(size)); + + for (TInt i = 0; i < size; i += KSmsPduDbMaxReadWriteChunk) + { + const TInt readSize = Min(KSmsPduDbMaxReadWriteChunk, size - i); + TBuf8 read; + User::LeaveIfError(file.Read(read, readSize)); + const TInt pos = aData.Size(); + aData.InsertL(pos, read); + } + + CleanupStack::PopAndDestroy(&file); + } + +void CSmsPduDatabase::WriteFileL(const TDesC& aOutputFileName, const CBufFlat& aData) const + { + RFile file; + User::LeaveIfError(file.Replace(iFs, aOutputFileName, EFileWrite)); + CleanupClosePushL(file); + + const TInt size = aData.Size(); + + for (TInt i = 0; i < size; i += KSmsPduDbMaxReadWriteChunk) + { + const TInt readSize = Min(KSmsPduDbMaxReadWriteChunk, size - i); + TBuf8 read; + aData.Read(i, read, readSize); + User::LeaveIfError(file.Write(read)); + } + + User::LeaveIfError(file.Flush()); + + CleanupStack::PopAndDestroy(&file); + } + +EXPORT_C void CSmsPduDatabase::RewriteFileL(const TDesC& aInputFileName, const TDesC& aInputComponent, const TDesC& aOutputFileName) const + { + CBufFlat* buffer = CBufFlat::NewL(0x100); //< TODO Remove this magic number + CleanupStack::PushL(buffer); + + ReadFileL(aInputFileName, aInputComponent, *buffer); + + ParseFileL(*buffer); + + WriteFileL(aOutputFileName, *buffer); + + CleanupStack::PopAndDestroy(buffer); + } + +void CSmsPduDatabase::ParseFileL(CBufFlat& aData) const + { + TPtrC8 ptr(aData.Ptr(0)); + TLex8 lex(ptr); + lex.Mark(); + + while (!lex.Eos()) + { + if (lex.Peek() == KSmsPduDbTagStart) + { + ParseTagL(aData, ptr, lex); + } + else + { + lex.Inc(); + } + } + } + +void CSmsPduDatabase::ParseTagL(CBufFlat& aData, TPtrC8& aPtr, TLex8& aLex) const + { + const TInt startingPos = aLex.Offset(); + + const TPtrC8 remainder(aLex.Remainder()); + const TInt locate = remainder.Locate(KSmsPduDbTagEnd); + TInt err = locate; + + if (locate != KErrNotFound) + { + aLex.Mark(); + aLex.Inc(locate+1); + + const TPtrC8 marked(aLex.MarkedToken()); + CSmsPduDbPdu* pdu = NULL; + + TRAP(err, pdu = PduFactoryL(marked)); + + if (err == KErrNone) + { + CleanupStack::PushL(pdu); + TBuf8 hexPdu; + pdu->GetHexPdu(hexPdu); + aData.Delete(startingPos, marked.Length()); + aData.InsertL(startingPos, hexPdu); + aPtr.Set(aData.Ptr(0)); + aLex = aPtr; + aLex.Inc(startingPos + pdu->iPdu.Length()); + CleanupStack::PopAndDestroy(pdu); + } + } + + if (err != KErrNone) + { + aLex.Inc(); + } + } + +TBool CSmsPduDatabase::IsPdu(const TDesC8& aTag, CSmsPDU::TSmsPDUType& aType) const + { + TBool ret = EFalse; + + if (aTag.CompareF(KSmsPduDbSubmit) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsSubmit; + } + else if (aTag.CompareF(KSmsPduDbDeliver) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsDeliver; + } + else if (aTag.CompareF(KSmsPduDbStatusReport) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsStatusReport; + } + else if (aTag.CompareF(KSmsPduDbCommand) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsCommand; + } + else if (aTag.CompareF(KSmsPduDbSubmitReport) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsSubmitReport; + } + else if (aTag.CompareF(KSmsPduDbDeliverReport) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsDeliverReport; + } + + return ret; + } + +TBool CSmsPduDatabase::IsConcatSegment(const TDesC8& aTag, CSmsPDU::TSmsPDUType& aType) const + { + TBool ret = EFalse; + + if (aTag.CompareF(KSmsPduDbSubmitConcat) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsSubmit; + } + else if (aTag.CompareF(KSmsPduDbDeliverConcat) == KErrNone) + { + ret = ETrue; + aType = CSmsPDU::ESmsDeliver; + } + + return ret; + } + +EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactoryL(const CTestConfigItem& aItem, CSmsPDU::TSmsPDUType aTypeForMessageTags) const + { + const TDesC8& type = aItem.Item(); + CSmsPduDbPdu* pdu = NULL; + CSmsPDU::TSmsPDUType pduType; + + if (IsPdu(type, pduType)) + { + pdu = CSmsPduDbPdu::NewL(iFs, aItem, pduType); + } + else if (IsConcatSegment(type, pduType)) + { + pdu = CSmsPduDbConcatSegment::NewL(iFs, aItem, pduType); + } + else if (IsMessage(type)) + { + pdu = CSmsPduDbMessage::NewL(iFs, aItem, aTypeForMessageTags); + } + else + { + //Attempt to parse aItem.Value() using the other overload of PduFactoryL() + pdu = PduFactoryL(aItem.Value(), aTypeForMessageTags); + } + + __ASSERT_DEBUG(pdu != NULL, PduDbPanic(EPduDbPanicPduNotConstructed)); + return pdu; + } + +EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactoryL(const TDesC8& aTag, CSmsPDU::TSmsPDUType aTypeForMessageTags) const +/** + * Parses tags of the form , e.g. or or + * If the MESSAGE_TYPE and ID combination if found in the PDU database then a CSmsPduDbPdu-derived object is created. + * SEGMENT is only compulsory if MESSAGE_TYPE is a concatenated message. + * + * @param aTag Tag of the form . MESSAGE_TYPE and ID are compulsory and must be delimited by a semicolon (;) + * @param aTypeForMessageTags PDU Type used when creating a CSmsPduDbMessage. This occurs if MESSAGE_TYPE == "message" + */ + { + TPtrC8 tag(CTestConfig::Trim(aTag)); + const TInt len = tag.Length(); + + if (len < 4) + User::Leave(KErrBadName); + + TInt midStart = 0; + TInt midLen = len; + if (tag[0] == KSmsPduDbTagStart) + { + midStart++; + midLen--; + } + + if (tag[len-1] == KSmsPduDbTagEnd) + midLen--; + + tag.Set(tag.Mid(midStart, midLen)); + + TPtrC8 type; + TInt id(0); + + User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagType, type)); + User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagId, id)); + + CSmsPduDbPdu* pdu = NULL; + CSmsPDU::TSmsPDUType pduType; + + if (IsPdu(type, pduType)) + { + pdu = GetPduLC(pduType, id); + } + else if (IsConcatSegment(type, pduType)) + { + TInt segment; + User::LeaveIfError(CTestConfig::GetElement(tag, KSmsPduDbTagDelimitier, ETagSegment, segment)); + pdu = GetConcatSegmentLC(pduType, id, segment); + } + else if (IsMessage(type)) + { + pdu = GetMessageLC(aTypeForMessageTags, id); + } + else + { + User::Leave(KErrBadName); + } + + __ASSERT_DEBUG(pdu != NULL, PduDbPanic(EPduDbPanicPduNotConstructed)); + CleanupStack::Pop(pdu); + return pdu; + } + +EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactory(const TDesC8& aTag, CSmsPDU::TSmsPDUType aTypeForMessageTags) const + { + CSmsPduDbPdu* pdu = NULL; + TRAPD(err, (pdu = PduFactoryL(aTag, aTypeForMessageTags))); + return ((err == KErrNone) ? pdu : NULL); + } + +EXPORT_C CSmsPduDbPdu* CSmsPduDatabase::PduFactory(const CTestConfigItem& aItem, CSmsPDU::TSmsPDUType aTypeForMessageTags) const + { + CSmsPduDbPdu* pdu = NULL; + TRAPD(err, (pdu = PduFactoryL(aItem, aTypeForMessageTags))); + return ((err == KErrNone) ? pdu : NULL); + } + +TInt CSmsPduDatabase::RSmsPduDbIdArray::Compare(const TSmsPduDbId& aLeft, const TSmsPduDbId& aRight) + { + return aLeft.iId - aRight.iId; + } + +TInt CSmsPduDatabase::RSmsPduDbIdArray::Find(TInt aId) const + { + TLinearOrder order(Compare); + const TSmsPduDbId tempId(NULL, aId); + return FindInOrder(tempId, order); + } + +void CSmsPduDatabase::RSmsPduDbIdArray::InsertL(const TSmsPduDbId& aId) + { + TLinearOrder order(Compare); + + if (iAllowDuplicates) + User::LeaveIfError(InsertInOrderAllowRepeats(aId, order)); + else + User::LeaveIfError(InsertInOrder(aId, order)); + }