--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/sms/smsevent.cpp Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,303 @@
+// smsevent.cpp
+//
+// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+
+#include "smsevent.h"
+#include "sms.h"
+
+_LIT(KInternationlDialDirectIndicator, "+");
+
+//
+// CSmsEventBase
+//
+CSmsEventBase::CSmsEventBase(CCmdSms& aObserver):
+CActive(CActive::EPriorityStandard), iObserver(aObserver)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+//
+// CSmsEventDial
+//
+CSmsEventDial* CSmsEventDial::NewL(CCmdSms& aObserver, RCall::TTelNumberC& aTelNumber)
+ {
+ CSmsEventDial* self = new (ELeave) CSmsEventDial(aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL(aTelNumber);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSmsEventDial::CSmsEventDial(CCmdSms& aObserver):
+CSmsEventBase(aObserver), iState(ESmsEventNetworkIdle)
+ {
+ }
+
+CSmsEventDial::~CSmsEventDial()
+ {
+ Cancel();
+ iTimeout.Cancel();
+ iTimeout.Close();
+ if (iCall.SubSessionHandle() > 0)
+ iCall.Close(); // should also force a hangup on the call object if it's active
+ if (iLine.SubSessionHandle() > 0)
+ iLine.Close();
+ if (iPhone.SubSessionHandle() > 0)
+ iPhone.Close();
+ if (iTelServer.Handle() > 0)
+ iTelServer.Close();
+ }
+
+void CSmsEventDial::ConstructL(RCall::TTelNumberC& aTelNumber)
+ {
+ // timeout timer
+ iTimeout.CreateLocal();
+
+ // capture the number to dial
+ iNumber.iTypeOfNumber = RMobilePhone::ENationalNumber;
+ iNumber.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
+ iNumber.iTelNumber.Copy(aTelNumber);
+
+ // check if there's a '+' at the front of the number
+ if (aTelNumber.MatchC(KInternationlDialDirectIndicator) == 0)
+ iNumber.iTypeOfNumber = RMobilePhone::EInternationalNumber;
+
+ // connect to ETel. Note we're assuming the TSY has been loaded already
+ RTelServer::TPhoneInfo phoneInfo;
+ User::LeaveIfError(iTelServer.Connect());
+ User::LeaveIfError(iTelServer.GetPhoneInfo(0, phoneInfo));
+
+ // open the first phone object
+ User::LeaveIfError(iPhone.Open(iTelServer, phoneInfo.iName));
+
+ // find the voice line & open it
+ TInt lines = 0;
+ RPhone::TLineInfo lineInfo;
+ User::LeaveIfError(iPhone.EnumerateLines(lines));
+ if (lines <= 0)
+ User::Leave(KErrNotSupported);
+ for (TInt ii = 0 ; ii < lines ; ii++)
+ {
+ User::LeaveIfError(iPhone.GetLineInfo(ii, lineInfo));
+ if (lineInfo.iLineCapsFlags & RLine::KCapsVoice)
+ {
+ // found our voice line
+ if (lineInfo.iStatus > RCall::EStatusIdle)
+ User::Leave(KErrInUse);
+ User::LeaveIfError(iLine.Open(iPhone, lineInfo.iName));
+ break;
+ }
+ }
+ if (iLine.SubSessionHandle() <= 0)
+ User::Leave(KErrNotFound);
+
+ // create a voice call (note it's not currently active)
+ User::LeaveIfError(iCall.OpenNewCall(iLine, iCallName));
+ }
+
+//
+// CSmsEventDial::StartL
+// start the dial-out procedure, beginning
+// with a check of the network, line/call status
+//
+void CSmsEventDial::StartL()
+ {
+ User::LeaveIfError(iLine.GetMobileLineStatus(iCallStatus));
+ if (iCallStatus > RMobileCall::EStatusIdle)
+ User::Leave(KErrInUse);
+
+ // some product tsy implementations can't handle a dial request immediately following receiving an sms. so we wait a little bit..5 seconds in fact
+ iTimeout.After(iStatus, 5000000);
+ SetActive();
+ iState = ESmsEventDial;
+ }
+
+void CSmsEventDial::RunL()
+ {
+ User::LeaveIfError(iStatus.Int()); // process the error elsewhere
+ switch (iState)
+ {
+ case ESmsEventDial:
+ {
+ // dial the number
+ iCall.Dial(iStatus, iNumber.iTelNumber);
+ SetActive();
+ iState = ESmsEventStatusChange;
+ }
+ break;
+
+ case ESmsEventWatchStatus:
+ case ESmsEventStatusChange:
+ {
+ User::LeaveIfError(iCall.GetMobileCallStatus(iCallStatus));
+ if (iCallStatus > RMobileCall::EStatusIdle)
+ {
+ // keep the call going until it drops
+ iCall.NotifyMobileCallStatusChange(iStatus, iCallStatus);
+ SetActive();
+ iState = ESmsEventWatchStatus;
+ return;
+ }
+ }
+ break;
+
+ default:
+ break;
+ };
+ }
+
+//
+// CSmsEventDial::RunError
+// inform the observer we hit a prob. with execution of the dial state machine
+//
+TInt CSmsEventDial::RunError(TInt /*aError*/)
+ {
+ //TODO iObserver.EventComplete(aError);
+ return KErrNone;
+ }
+
+void CSmsEventDial::DoCancel()
+ {
+ switch (iState)
+ {
+ case ESmsEventDial:
+ iTimeout.Cancel();
+ break;
+
+ case ESmsEventStatusChange:
+ iCall.DialCancel();
+ break;
+
+ case ESmsEventWatchStatus:
+ iCall.NotifyStatusChangeCancel();
+ break;
+
+ default:
+ break;
+ };
+ }
+
+CSmsShellCommand* CSmsShellCommand::NewL(CCmdSms& aObserver, const TDesC& aCommandText, const TDesC& aSenderAddress)
+ {
+ CSmsShellCommand* self = new(ELeave) CSmsShellCommand(aObserver);
+ CleanupStack::PushL(self);
+ self->ConstructL(aCommandText, aSenderAddress);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSmsShellCommand::CSmsShellCommand(CCmdSms& aObserver)
+ : CSmsEventBase(aObserver)
+ {
+ }
+
+void CSmsShellCommand::ConstructL(const TDesC& aCommandText, const TDesC& aSenderAddress)
+ {
+ iSmsSender.CreateL(aSenderAddress);
+ // Set up environment for script
+ iScriptEnv = CEnvironment::NewL(iObserver.Env());
+ _LIT(KSmsSenderEnvironmentVariable, "SMS_SENDER");
+ iScriptEnv->SetL(KSmsSenderEnvironmentVariable, iSmsSender);
+
+ const TDesC* scriptName = NULL;
+ _LIT(KFshellName, "C:\\shared\\fshellscript%d.script");
+ _LIT(KPerlName, "C:\\shared\\perlscript%d.pl");
+ if (aCommandText.MatchF(_L("#!fshell*")) == 0)
+ {
+ iExeName = _L("fshell.exe");
+ scriptName = &KFshellName;
+ }
+ else if (aCommandText.MatchF(_L("#!perl*")) == 0)
+ {
+ iExeName = _L("perl.exe");
+ scriptName = &KPerlName;
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+
+ RBuf8 buf;
+ CleanupClosePushL(buf);
+ buf.CreateL(aCommandText.Length());
+ buf.Copy(aCommandText);
+
+ RFile scriptFile;
+ CleanupClosePushL(scriptFile);
+ TInt nonce = 0;
+ iObserver.Fs().MkDirAll(*scriptName);
+ TInt err = KErrNone;
+ do {
+ iScriptFile.Format(*scriptName, nonce);
+ nonce++;
+ err = scriptFile.Create(iObserver.Fs(), iScriptFile, EFileShareAny|EFileWrite);
+ } while (err == KErrAlreadyExists);
+ User::LeaveIfError(scriptFile.Write(buf));
+ CleanupStack::PopAndDestroy(2, &buf);
+ }
+
+void CSmsShellCommand::StartL()
+ {
+ iProcess.CreateL(iExeName, iScriptFile, iObserver.IoSession(), iObserver.Stdin(), iObserver.Stdout(), iObserver.Stderr(), *iScriptEnv);
+ iProcess.Run(iStatus);
+ SetActive();
+ }
+
+void CSmsShellCommand::DoCancel()
+ {
+ iProcess.Process().LogonCancel(iStatus);
+ }
+
+CSmsShellCommand::~CSmsShellCommand()
+ {
+ Cancel();
+ iProcess.Close();
+ if (!iObserver.Debug())
+ {
+ iObserver.Fs().Delete(iScriptFile);
+ }
+ delete iScriptEnv;
+ iSmsSender.Close();
+ }
+
+void CSmsShellCommand::RunL()
+ {
+ TExitType exitType = iProcess.Process().ExitType();
+ TInt exitReason = iProcess.Process().ExitReason();
+ TBool ok = exitType == EExitKill && exitReason == 0;
+ if (ok)
+ {
+ iObserver.Printf(_L("Script from %S completed ok.\r\n"), &iSmsSender);
+ }
+ else
+ {
+ TInt err = exitReason;
+ if (err >= 0) err = KErrGeneral;
+ switch (iProcess.Process().ExitType())
+ {
+ case EExitKill:
+ iObserver.PrintError(err, _L("Script %S failed, returned %d"), &iScriptFile, exitReason);
+ break;
+ case EExitTerminate:
+ iObserver.PrintError(err, _L("Script %S terminated with %d"), &iScriptFile, exitReason);
+ break;
+ case EExitPanic:
+ {
+ TExitCategoryName cat = iProcess.Process().ExitCategory();
+ iObserver.PrintError(err, _L("Script %S panicked with %S %d"), &iScriptFile, &cat, exitReason);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ delete this;
+ }