commands/sms/smsevent.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // smsevent.cpp
       
     2 // 
       
     3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include "smsevent.h"
       
    14 #include "sms.h"
       
    15 
       
    16 _LIT(KInternationlDialDirectIndicator,	"+");
       
    17 
       
    18 //
       
    19 // CSmsEventBase
       
    20 //
       
    21 CSmsEventBase::CSmsEventBase(CCmdSms& aObserver):
       
    22 CActive(CActive::EPriorityStandard), iObserver(aObserver)
       
    23 	{
       
    24 	CActiveScheduler::Add(this);
       
    25 	}
       
    26 
       
    27 //
       
    28 // CSmsEventDial
       
    29 //
       
    30 CSmsEventDial* CSmsEventDial::NewL(CCmdSms& aObserver, RCall::TTelNumberC& aTelNumber)
       
    31 	{
       
    32 	CSmsEventDial* self = new (ELeave) CSmsEventDial(aObserver);
       
    33 	CleanupStack::PushL(self);
       
    34 	self->ConstructL(aTelNumber);
       
    35 	CleanupStack::Pop(self);
       
    36 	return self;
       
    37 	}
       
    38 
       
    39 CSmsEventDial::CSmsEventDial(CCmdSms& aObserver):
       
    40 CSmsEventBase(aObserver), iState(ESmsEventNetworkIdle)
       
    41 	{
       
    42 	}
       
    43 
       
    44 CSmsEventDial::~CSmsEventDial()
       
    45 	{
       
    46 	Cancel();
       
    47 	iTimeout.Cancel();
       
    48 	iTimeout.Close();
       
    49 	if (iCall.SubSessionHandle() > 0)
       
    50 		iCall.Close(); // should also force a hangup on the call object if it's active
       
    51 	if (iLine.SubSessionHandle() > 0)
       
    52 		iLine.Close();
       
    53 	if (iPhone.SubSessionHandle() > 0)
       
    54 		iPhone.Close();
       
    55 	if (iTelServer.Handle() > 0)
       
    56 		iTelServer.Close();
       
    57 	}
       
    58 
       
    59 void CSmsEventDial::ConstructL(RCall::TTelNumberC& aTelNumber)
       
    60 	{
       
    61 	// timeout timer 
       
    62 	iTimeout.CreateLocal();
       
    63 	
       
    64 	// capture the number to dial
       
    65 	iNumber.iTypeOfNumber = RMobilePhone::ENationalNumber;
       
    66 	iNumber.iNumberPlan = RMobilePhone::EIsdnNumberPlan;
       
    67 	iNumber.iTelNumber.Copy(aTelNumber);
       
    68 	
       
    69 	// check if there's a '+' at the front of the number
       
    70 	if (aTelNumber.MatchC(KInternationlDialDirectIndicator) == 0)
       
    71 		iNumber.iTypeOfNumber = RMobilePhone::EInternationalNumber;
       
    72 	
       
    73 	// connect to ETel. Note we're assuming the TSY has been loaded already
       
    74 	RTelServer::TPhoneInfo phoneInfo;
       
    75 	User::LeaveIfError(iTelServer.Connect());
       
    76 	User::LeaveIfError(iTelServer.GetPhoneInfo(0, phoneInfo));
       
    77 	
       
    78 	// open the first phone object
       
    79 	User::LeaveIfError(iPhone.Open(iTelServer, phoneInfo.iName));
       
    80 	
       
    81 	// find the voice line & open it
       
    82 	TInt lines = 0;
       
    83 	RPhone::TLineInfo lineInfo;
       
    84 	User::LeaveIfError(iPhone.EnumerateLines(lines));
       
    85 	if (lines <= 0)
       
    86 		User::Leave(KErrNotSupported);
       
    87 	for (TInt ii = 0 ; ii < lines ; ii++)
       
    88 		{
       
    89 		User::LeaveIfError(iPhone.GetLineInfo(ii, lineInfo));
       
    90 		if (lineInfo.iLineCapsFlags & RLine::KCapsVoice)
       
    91 			{
       
    92 			// found our voice line
       
    93 			if (lineInfo.iStatus > RCall::EStatusIdle)
       
    94 				User::Leave(KErrInUse);
       
    95 			User::LeaveIfError(iLine.Open(iPhone, lineInfo.iName));
       
    96 			break;
       
    97 			}
       
    98 		}
       
    99 	if (iLine.SubSessionHandle() <= 0)
       
   100 		User::Leave(KErrNotFound);
       
   101 	
       
   102 	// create a voice call (note it's not currently active)
       
   103 	User::LeaveIfError(iCall.OpenNewCall(iLine, iCallName));
       
   104 	}
       
   105 
       
   106 //
       
   107 // CSmsEventDial::StartL
       
   108 // start the dial-out procedure, beginning
       
   109 // with a check of the network, line/call status
       
   110 //
       
   111 void CSmsEventDial::StartL()
       
   112 	{
       
   113 	User::LeaveIfError(iLine.GetMobileLineStatus(iCallStatus));
       
   114 	if (iCallStatus > RMobileCall::EStatusIdle)
       
   115 		User::Leave(KErrInUse);
       
   116 	
       
   117 	// 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
       
   118 	iTimeout.After(iStatus, 5000000);
       
   119 	SetActive();
       
   120 	iState = ESmsEventDial;
       
   121 	}
       
   122 
       
   123 void CSmsEventDial::RunL()
       
   124 	{
       
   125 	User::LeaveIfError(iStatus.Int()); // process the error elsewhere
       
   126 	switch (iState)
       
   127 		{
       
   128 		case ESmsEventDial:
       
   129 			{
       
   130 			// dial the number
       
   131 			iCall.Dial(iStatus, iNumber.iTelNumber);
       
   132 			SetActive();
       
   133 			iState = ESmsEventStatusChange;
       
   134 			}
       
   135 		break;
       
   136 				
       
   137 		case ESmsEventWatchStatus:
       
   138 		case ESmsEventStatusChange:
       
   139 			{
       
   140 			User::LeaveIfError(iCall.GetMobileCallStatus(iCallStatus));
       
   141 			if (iCallStatus > RMobileCall::EStatusIdle)
       
   142 				{
       
   143 				// keep the call going until it drops
       
   144 				iCall.NotifyMobileCallStatusChange(iStatus, iCallStatus);
       
   145 				SetActive();
       
   146 				iState = ESmsEventWatchStatus;
       
   147 				return;
       
   148 				}
       
   149 			}
       
   150 		break;
       
   151 		
       
   152 		default:
       
   153 		break;
       
   154 		};
       
   155 	}
       
   156 
       
   157 //
       
   158 // CSmsEventDial::RunError
       
   159 // inform the observer we hit a prob. with execution of the dial state machine
       
   160 //
       
   161 TInt CSmsEventDial::RunError(TInt /*aError*/)
       
   162 	{
       
   163 	//TODO iObserver.EventComplete(aError); 
       
   164 	return KErrNone;
       
   165 	}
       
   166 
       
   167 void CSmsEventDial::DoCancel()
       
   168 	{
       
   169 	switch (iState)
       
   170 		{
       
   171 		case ESmsEventDial:
       
   172 			iTimeout.Cancel();
       
   173 		break;
       
   174 		
       
   175 		case ESmsEventStatusChange:
       
   176 			iCall.DialCancel();
       
   177 		break;
       
   178 		
       
   179 		case ESmsEventWatchStatus:
       
   180 			iCall.NotifyStatusChangeCancel();			
       
   181 		break;
       
   182 		
       
   183 		default:
       
   184 		break;
       
   185 		};
       
   186 	}
       
   187 
       
   188 CSmsShellCommand* CSmsShellCommand::NewL(CCmdSms& aObserver, const TDesC& aCommandText, const TDesC& aSenderAddress)
       
   189 	{
       
   190 	CSmsShellCommand* self = new(ELeave) CSmsShellCommand(aObserver);
       
   191 	CleanupStack::PushL(self);
       
   192 	self->ConstructL(aCommandText, aSenderAddress);
       
   193 	CleanupStack::Pop(self);
       
   194 	return self;
       
   195 	}
       
   196 
       
   197 CSmsShellCommand::CSmsShellCommand(CCmdSms& aObserver)
       
   198 	: CSmsEventBase(aObserver)
       
   199 	{
       
   200 	}
       
   201 
       
   202 void CSmsShellCommand::ConstructL(const TDesC& aCommandText, const TDesC& aSenderAddress)
       
   203 	{
       
   204 	iSmsSender.CreateL(aSenderAddress);
       
   205 	// Set up environment for script
       
   206 	iScriptEnv = CEnvironment::NewL(iObserver.Env());
       
   207 	_LIT(KSmsSenderEnvironmentVariable, "SMS_SENDER");
       
   208 	iScriptEnv->SetL(KSmsSenderEnvironmentVariable, iSmsSender);
       
   209 
       
   210 	const TDesC* scriptName = NULL;
       
   211 	_LIT(KFshellName, "C:\\shared\\fshellscript%d.script");
       
   212 	_LIT(KPerlName, "C:\\shared\\perlscript%d.pl");
       
   213 	if (aCommandText.MatchF(_L("#!fshell*")) == 0)
       
   214 		{
       
   215 		iExeName = _L("fshell.exe");
       
   216 		scriptName = &KFshellName;
       
   217 		}
       
   218 	else if (aCommandText.MatchF(_L("#!perl*")) == 0)
       
   219 		{
       
   220 		iExeName = _L("perl.exe");
       
   221 		scriptName = &KPerlName;
       
   222 		}
       
   223 	else
       
   224 		{
       
   225 		User::Leave(KErrArgument);
       
   226 		}	
       
   227 	
       
   228 	RBuf8 buf;
       
   229 	CleanupClosePushL(buf);
       
   230 	buf.CreateL(aCommandText.Length());
       
   231 	buf.Copy(aCommandText);
       
   232 
       
   233 	RFile scriptFile;
       
   234 	CleanupClosePushL(scriptFile);
       
   235 	TInt nonce = 0;
       
   236 	iObserver.Fs().MkDirAll(*scriptName);
       
   237 	TInt err = KErrNone;
       
   238 	do {
       
   239 		iScriptFile.Format(*scriptName, nonce);
       
   240 		nonce++;
       
   241 		err = scriptFile.Create(iObserver.Fs(), iScriptFile, EFileShareAny|EFileWrite);
       
   242 		} while (err == KErrAlreadyExists);
       
   243 	User::LeaveIfError(scriptFile.Write(buf));
       
   244 	CleanupStack::PopAndDestroy(2, &buf);
       
   245 	}
       
   246 
       
   247 void CSmsShellCommand::StartL()
       
   248 	{
       
   249 	iProcess.CreateL(iExeName, iScriptFile, iObserver.IoSession(), iObserver.Stdin(), iObserver.Stdout(), iObserver.Stderr(), *iScriptEnv);
       
   250 	iProcess.Run(iStatus);
       
   251 	SetActive();
       
   252 	}
       
   253 
       
   254 void CSmsShellCommand::DoCancel()
       
   255 	{
       
   256 	iProcess.Process().LogonCancel(iStatus);
       
   257 	}
       
   258 
       
   259 CSmsShellCommand::~CSmsShellCommand()
       
   260 	{
       
   261 	Cancel();
       
   262 	iProcess.Close();
       
   263 	if (!iObserver.Debug())
       
   264 		{
       
   265 		iObserver.Fs().Delete(iScriptFile);
       
   266 		}
       
   267 	delete iScriptEnv;
       
   268 	iSmsSender.Close();
       
   269 	}
       
   270 
       
   271 void CSmsShellCommand::RunL()
       
   272 	{
       
   273 	TExitType exitType = iProcess.Process().ExitType();
       
   274 	TInt exitReason = iProcess.Process().ExitReason();
       
   275 	TBool ok = exitType == EExitKill && exitReason == 0;
       
   276 	if (ok)
       
   277 		{
       
   278 		iObserver.Printf(_L("Script from %S completed ok.\r\n"), &iSmsSender);
       
   279 		}
       
   280 	else
       
   281 		{
       
   282 		TInt err = exitReason;
       
   283 		if (err >= 0) err = KErrGeneral;
       
   284 		switch (iProcess.Process().ExitType())
       
   285 			{
       
   286 			case EExitKill:
       
   287 				iObserver.PrintError(err, _L("Script %S failed, returned %d"), &iScriptFile, exitReason);
       
   288 				break;
       
   289 			case EExitTerminate:
       
   290 				iObserver.PrintError(err, _L("Script %S terminated with %d"), &iScriptFile, exitReason);
       
   291 				break;
       
   292 			case EExitPanic:
       
   293 				{
       
   294 				TExitCategoryName cat = iProcess.Process().ExitCategory();
       
   295 				iObserver.PrintError(err, _L("Script %S panicked with %S %d"), &iScriptFile, &cat, exitReason);
       
   296 				break;
       
   297 				}
       
   298 			default:
       
   299 				break;
       
   300 			}
       
   301 		}
       
   302 	delete this;
       
   303 	}