// Copyright (c) 1998-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:// BSP.CPP (Base Script Parser)// //#include "bsp.h"#include "regpsdll.h" // CRegisteredParserDll#include "msventry.h" // CMsvServerEntry#include <msvuids.h> // KUidMsvMessageEntry, KUidMsvServiceEntry#include <msvids.h>#include <biouids.h>#include <biodb.h>const TInt KMaxStringLength = 1024;EXPORT_C CBaseScriptParser::CBaseScriptParser(CRegisteredParserDll& aRegisteredParserDll,CMsvServerEntry& aEntry, RFs& aFs):CActive(EPriorityStandard), iRegisteredParserDll(aRegisteredParserDll), iEntry(aEntry), iFs(aFs)/** Constructor.This is called by CBIOServerMtm to create a parser object.@param aRegisteredParserDll Object that loaded the parser. It contains a reference counter of the use of the parser.@param aEntry The message entry the parser should parse@param aFs Connected file server handle */ { iEntryId = iEntry.Entry().Id(); //id of SMS entry }EXPORT_C CBaseScriptParser::~CBaseScriptParser()/** Destructor.This deletes iSettings and iReadBuffer and calls iRegisteredParserDll.ReleaseLibrary(). */ { delete iReadBuffer; delete iSettings; iRegisteredParserDll.ReleaseLibrary(); }EXPORT_C void CBaseScriptParser::UnfoldMessageL()/** Utility function for unfolding Smart Messages.Nokia protocol allows for folding of long fields (see Nokia Smart Messaging spec 2.0.0pre, 3-34 and RFC822, 3.1.1). This method unfolds the message by deleting any linefeed characters which are followed immediately by linear white space. It expects the buffer to be in iSmsBuf. */ { // Nokia protocol allows for folding of long fields (see Nokia Smart // Messaging spec 2.0.0pre, 3-34 and RFC822, 3.1.1). This method // unfolds the message by deleting any linefeed characters which are // followed immediately by linear white space. // Note that the value returned by pBuf.Length() will change if // linefeeds are deleted. Hence this is called for each iteration to // avoid violating buffer bounds. TPtr pBuf(iSmsBuf->Des()); // Create modifiable pointer to HBufC for (TInt pos = 0; pos < (pBuf.Length() - 1); pos++) { // Find linefeed followed by whitespace if (pBuf[pos] == KCharLineFeed && (pBuf[pos+1] == KCharSpace || pBuf[pos+1] == KCharTab)) { pBuf.Delete(pos, 1); } } iSmsBuf = iSmsBuf->ReAllocL(pBuf.Length()); // Reallocate iSmsBuf with new size. }// end CBaseScriptParser::UnfoldSmsL()void CBaseScriptParser::InternalizeL(RMsvReadStream& aReadStream) { ResetL(); iParsedFieldArray = new(ELeave) CArrayPtrSeg<CParsedField>(16); CParsedField* parsedField = NULL; TInt count = aReadStream.ReadUint8L(); for (TInt i=0; i < count; i++) { parsedField = new (ELeave) CParsedField(); CleanupStack::PushL(parsedField); parsedField->InternalizeL(aReadStream); iParsedFieldArray->AppendL(parsedField); CleanupStack::Pop(parsedField); } }void CBaseScriptParser::ExternalizeL(RMsvWriteStream& aStream) const { TInt count = iParsedFieldArray->Count(); aStream.WriteInt8L(count); for(TInt number = 0; number<count; number++) // must keep order, go forwards { aStream << *(*iParsedFieldArray)[number]; } }EXPORT_C void CBaseScriptParser::StoreL(CMsvStore& aMsvStore) const/** Stores the parsed fields array.It stores the iParsedFieldArray array in the specified CMsvStore.@param aMsvStore Store to write to */ { RMsvWriteStream out; out.AssignLC( aMsvStore, KUidMsvBIODataStream); // pushes 'out' to the stack TRAPD(error, ExternalizeL(out)); if (error==KErrNone) out.CommitL(); out.Close(); // make sure we close the file User::LeaveIfError(error); aMsvStore.CommitL(); CleanupStack::PopAndDestroy(); }EXPORT_C void CBaseScriptParser::RestoreL( CMsvStore& aMessageStore )/** Restores the parsed fields array.It restores the iParsedFieldArray array from the specified CMsvStore.@param aMessageStore Store to read from */ { RMsvReadStream in; in.OpenLC( aMessageStore, KUidMsvBIODataStream ); InternalizeL(in); CleanupStack::PopAndDestroy(); }//// write contents of Smart message to a file as attachment//EXPORT_C void CBaseScriptParser::StoreL(const TFileName& aFileName) const/** Stores the message data in a specified file.It stores iSettings in the specified file.@param aFileName File to write to */ { // TFileName filePath; // creates directory for current entry to put file into iEntry.GetFilePath(filePath); // create the full file name with path TParse parse; parse.Set(aFileName, &filePath, NULL); // create the file RFile file; User::LeaveIfError(file.Replace(iFs, parse.FullName(), EFileWrite|EFileShareExclusive|EFileStream)); CleanupClosePushL(file); // if it worked stream data to it // first copy data into 8-bit buffer (it's 8bit content anyway?) TPtr dataContents = iSettings->Des(); HBufC8* buf = HBufC8::NewLC(dataContents.Length()); buf->Des().Copy(dataContents); TInt fileErr = file.Write( buf->Des() ); file.Close(); if(fileErr!=KErrNone) { iFs.Delete(parse.FullName()); User::Leave(fileErr); } CleanupStack::PopAndDestroy(2); // buf, file }EXPORT_C void CBaseScriptParser::RestoreL( const TFileName& aFileName )/** Restores the message data from a specified file.It restores iSettings from the specified file.@param aFileName File to read from */ { // TFileName filePath; // creates directory for current entry to put file into iEntry.GetFilePath(filePath); // create the full file name with path TParse parse; parse.Set(aFileName, &filePath, NULL); // create the file RFile file; User::LeaveIfError(file.Open(iFs, parse.FullName(), EFileShareExclusive|EFileStream)); CleanupClosePushL(file); // read into descriptor resizing as we go iReadBuffer = HBufC8::NewL(256); TBuf8<256> fileChunk; TInt fileErr = KErrNone; while(fileErr==KErrNone) { fileErr = file.Read(fileChunk, fileChunk.MaxLength()); if(fileChunk.Length()==0) break; // check if we need to resize TInt newLength = iReadBuffer->Des().Length() + fileChunk.Length(); if( newLength > iReadBuffer->Des().MaxLength()) { iReadBuffer = iReadBuffer->ReAllocL(newLength); } iReadBuffer->Des().Append(fileChunk); } // if it worked stream data to it // first copy data into 8-bit buffer (it's 8bit content anyway?) file.Close(); if(fileErr!=KErrNone) User::Leave(fileErr); CleanupStack::PopAndDestroy(1); // file delete iSettings; iSettings = NULL; iSettings = HBufC::NewL(iReadBuffer->Length()); iSettings->Des().Copy(iReadBuffer->Des()); } EXPORT_C TUid CBaseScriptParser::ParserUid()/** Gets the UID of the BIO message type handled by the parser.@return BIO message type UID */ { return (iRegisteredParserDll.UidType()[2]); }EXPORT_C void CBaseScriptParser::ResetL()/** Deletes the iParsedFieldArray parsed fields array and sets it to NULL. */ { // delete previous array and create a new one if(iParsedFieldArray) { iParsedFieldArray->ResetAndDestroy(); delete iParsedFieldArray; iParsedFieldArray=NULL; } }//// Class CParsed field container class for // data item extracted from smart message//EXPORT_C CParsedField::CParsedField()/** Constructor. */ { iFieldName =NULL; iFieldValue =NULL; iMandatoryField =ETrue; }EXPORT_C CParsedField::~CParsedField()/** Destructor. */ { delete iFieldName; delete iFieldValue; }EXPORT_C TPtrC CParsedField::FieldName() const/** Gets the field name.@return Field name */ { return iFieldName->Des(); }EXPORT_C void CParsedField::SetFieldNameL(const TDesC& aFieldName)/** Sets the field name.@param aFieldName Field name */ { HBufC* temp =aFieldName.AllocL(); delete iFieldName; iFieldName = temp; }EXPORT_C TPtrC CParsedField::FieldValue() const /** Gets the field value.@return Field value */ { return iFieldValue->Des(); }EXPORT_C void CParsedField::SetFieldValueL(const TDesC& aFieldValue)/** Sets the field value.@param aFieldValue Field value */ { HBufC* temp =aFieldValue.AllocL(); delete iFieldValue; iFieldValue = temp; }EXPORT_C TBool CParsedField::MandatoryField() const /** Tests if this is a mandatory field.@return True if this is a mandatory field */ { return iMandatoryField; }EXPORT_C void CParsedField::SetMandatoryField(TBool aMandatoryField)/** Sets/unsets this as a mandatory field.@param aMandatoryField True if this is a mandatory field, false if not */ { iMandatoryField = aMandatoryField; }EXPORT_C void CParsedField::InternalizeL(RReadStream& aStream)/** Internalises the object.@param aStream Stream to read from */ { Reset(); delete iFieldName; iFieldName = NULL; iFieldName = HBufC::NewL( aStream, KMaxStringLength ); TInt fieldValueLength = aStream.ReadInt16L(); delete iFieldValue; iFieldValue = NULL; iFieldValue = HBufC::NewL( aStream, fieldValueLength ); iMandatoryField = aStream.ReadInt8L(); }EXPORT_C void CParsedField::ExternalizeL(RWriteStream& aStream) const/** Externalises the object.@param aStream Stream to write to */ { aStream << *iFieldName; aStream.WriteUint16L( iFieldValue->Length() ); aStream << *iFieldValue; aStream.WriteUint8L( iMandatoryField ? 1 : 0); }//// Reset contetnts of field//void CParsedField::Reset() { delete iFieldName; iFieldName = NULL; delete iFieldValue; iFieldValue = NULL; iMandatoryField= EFalse; }