📄 si_sq.c
字号:
/*
* Copyright (C) Ericsson Mobile Communications AB, 2000.
* Licensed to AU-System AB.
* All rights reserved.
*
* This software is covered by the license agreement between
* the end user and AU-System AB, and may be used and copied
* only in accordance with the terms of the said agreement.
*
* Neither Ericsson Mobile Communications AB nor AU-System AB
* assumes any responsibility or liability for any errors or inaccuracies in
* this software, or any consequential, incidental or indirect damage arising
* out of the use of the Generic WAP Client software.
*/
/*********
History
-------
990824 (KHN) The interception of the Lang.exit call was not correctly
getting the WMLBrowser invoked action (i.e. go/prev) if any.
This is now corrected.
000118 (KHN) Added handling for a new type of returnInfo in the SI struct.
(i.e. SI_RETURN_EXTERNAL_NO_PARAMS)
This was made in order to recognize the situation when
an adaptor call has been made and the script is now waiting
for a result without passing back parameters to SDL.
Also added calling SI_New... functions with invokeID as a new
parameter. This was done to enable script lib functions to
call adaptorfunctions directly without having to return
parameters to SDL when it is possible to make the call in C.
000124 (KHN) Added SQ_TextSigned that is only available when CAN_SIGN_TEXT
has been defined. The SQ_TextSigned function is needed to
get the MMIc_textSigned connector call from SDL to C (so we can
finish the WMLS library call to Crypto.signText).
001103 (HEAD) Added the function SQ_ProprietaryLibraryFunctionResponse that
is only available if USE_PROPRIETARY_WMLS_LIBS is defined
**********/
#include "si_sq.h"
#include "si_libs.h"
/*******************************/
pstructBPElement SQ_NewBPElement( BYTE *BP, UINT32 BPlen, INT16 IANAcharset,
WCHAR **pCallURL, BOOL firstBPinCallList )
{
pstructBPElement result = NEWSTRUCT( structBPElement );
result->BP = BP;
result->BPlen = BPlen;
result->IANAcharset = IANAcharset;
result->callURL = *pCallURL;
result->isInitialBPInvoked = firstBPinCallList;
result->theSI = NULL;
result->next = NULL;
*pCallURL = NULL;
return result;
}
VOID SQ_DeleteBPElement( pstructBPElement *pThis )
{
if (*pThis != NULL)
{
DEALLOC( &((*pThis)->BP) );
DEALLOC( &((*pThis)->callURL) );
SI_Delete( &((*pThis)->theSI) );
DEALLOC( pThis );
}
}
VOID SQ_CreateAndAddBPElement( pstructInvokeHead thisx, BYTE *BP, UINT32 BPlen,
INT16 IANAcharset, WCHAR **callURL, BOOL firstBPinCallList )
{
/* ASSERT( thisx != NULL ) */
pstructBPElement newEl = SQ_NewBPElement( BP, BPlen, IANAcharset, callURL, firstBPinCallList );
newEl->next = thisx->BPcallList;
thisx->BPcallList = newEl;
}
pstructInvokeHead SQ_NewInvokeHead( pstructSQ thisx, UINT32 UApidInt, pUA theUA,
BYTE **pBP, UINT32 BPlen, INT16 IANAcharset, WCHAR **pCallURL )
{
pstructInvokeHead result = NEWSTRUCT( structInvokeHead );
result->invokeID = thisx->nextInvokeID;
thisx->nextInvokeID = (thisx->nextInvokeID == UINT8_MAX) ? (1) : (thisx->nextInvokeID + 1);
result->UApidAsInt = UApidInt;
result->theUAStruct = theUA;
result->isDone = FALSE;
result->isInWaitState = FALSE;
result->errorCode = ERR_WAE_WMLS_NONE;
result->theResult = NULL;
result->browserPrev = FALSE;
result->browserGoUrl = NULL;
result->BPcallList = NULL;
SQ_CreateAndAddBPElement( result, *pBP, BPlen, IANAcharset, pCallURL, TRUE );
*pBP = NULL;
result->next = NULL;
return result;
}
VOID SQ_ClearBPCallList( pstructInvokeHead thisx )
{
pstructBPElement el = NULL;
pstructBPElement tmpEl = NULL;
if (thisx != NULL)
{
el = thisx->BPcallList;
thisx->BPcallList = NULL;
while (el != NULL)
{
tmpEl = el->next;
SQ_DeleteBPElement( &el );
el = tmpEl;
}
}
}
VOID SQ_DeleteInvokeHead( pstructInvokeHead *pThis )
{
if (*pThis != NULL)
{
Var_Delete( &( (*pThis)->theResult ) );
DEALLOC( &( (*pThis)->browserGoUrl ) );
SQ_ClearBPCallList( *pThis );
DEALLOC( pThis );
}
}
VOID SQ_RemoveAndDeleteInvokeHeadFromQ( pstructSQ theSQ, pstructInvokeHead *pThis )
{
pstructInvokeHead theInvokeBeforeThis = NULL;
if (theSQ != NULL)
{
if (theSQ->invokeList == *pThis)
{ /* the first InvokeHead is to be removed */
theSQ->invokeList = theSQ->invokeList->next;
}
else
{
theInvokeBeforeThis = theSQ->invokeList;
if (theInvokeBeforeThis != NULL)
{
while ((theInvokeBeforeThis->next != NULL) && (theInvokeBeforeThis->next != *pThis))
{
theInvokeBeforeThis = theInvokeBeforeThis->next;
}
if (theInvokeBeforeThis->next != NULL)
{ /* found the invokeHead */
/* take it out of the q */
theInvokeBeforeThis->next = theInvokeBeforeThis->next->next;
}
}
}
}
SQ_DeleteInvokeHead( pThis );
}
pstructInvokeHead SQ_FindInvokeHead( pstructSQ thisx, UINT8 invokeID )
{
pstructInvokeHead invokeEl = NULL;
if (thisx == NULL)
{ /* error! */
return NULL;
}
invokeEl = thisx->invokeList;
while ((invokeEl != NULL) && (invokeEl->invokeID != invokeID))
{
invokeEl = invokeEl->next;
}
return invokeEl;
}
/*******************************/
pstructSQ SQ_Init( UINT16 timeSlice, BOOL roundRobin, BOOL oneScriptPerUA, BOOL handlesTopPrio )
{
pstructSQ result = NEWSTRUCT( structSQ );
if (result != NULL)
{
result->timeSlice = timeSlice;
result->nextInvokeID = 1; /* the next invoke will get this invokeID */
result->doRoundRobinScheduling = roundRobin;
result->onlyOneScriptPerUA = oneScriptPerUA;
result->handlesTopPriorityREQ = handlesTopPrio;
result->currentInvoke = NULL;
result->invokeList = NULL;
}
return result;
}
VOID SQ_Terminate( pstructSQ *pThis )
{
pstructInvokeHead el = NULL;
pstructInvokeHead next = NULL;
if (*pThis != NULL)
{
/* first clear the InvokeList */
el = (*pThis)->invokeList;
while (el != NULL)
{
next = el->next;
SQ_DeleteInvokeHead( &el );
el = next;
}
/* now dealloc the SQ itself */
DEALLOC( pThis );
}
}
UINT8 SQ_InvokeScript( pstructSQ thisx, UINT32 UApidInt, pUA theUA, BYTE **pBP,
UINT32 BPlen, INT16 IANAcharset, WCHAR **pCallURL, BOOL isTopPriority )
/* returns 0 if something went wrong */
{
UINT8 resultInvokeID = 0;
pstructInvokeHead el = NULL;
pstructInvokeHead newEl = NULL;
BOOL uaHasScriptInvoke = FALSE;
/*
if the UA has a script invokation in the queue (Q)
This variable is only important if onlyOneScriptPerUA is set to TRUE for the scriptQ
*/
if ((thisx != NULL) && (theUA != NULL) && (*pBP != NULL) && (*pCallURL != NULL) )
{
newEl = SQ_NewInvokeHead( thisx, UApidInt, theUA, pBP, BPlen, IANAcharset, pCallURL );
if (newEl == NULL)
{ /* something went wrong */
return 0;
}
/* find last element in q and check if the UA has more invokations in the q */
if (thisx->invokeList != NULL)
{
el = thisx->invokeList;
while (el->next != NULL)
{
uaHasScriptInvoke = (uaHasScriptInvoke) ? (TRUE):(UApidInt == el->UApidAsInt);
el = el->next;
}
/* last element must also be checked */
uaHasScriptInvoke = (uaHasScriptInvoke) ? (TRUE):(UApidInt == el->UApidAsInt);
}
/* el is either NULL (no invokes in q) or pointing to the last in the invoke list */
if (uaHasScriptInvoke && thisx->onlyOneScriptPerUA)
{ /* the UA has already one script invoked and additional invokes are not allowed! */
SQ_DeleteInvokeHead( &newEl );
return 0; /* ERROR! */
}
if (isTopPriority && thisx->handlesTopPriorityREQ)
{ /* if top priority then this invoke will be inserted first in the q */
newEl->next = thisx->invokeList;
thisx->invokeList = newEl;
thisx->currentInvoke = NULL; /* this will make this invoke the next script run */
resultInvokeID = newEl->invokeID;
newEl = NULL;
}
else
{ /* insert invoke last in the q */
if (el != NULL)
{
el->next = newEl;
}
else
{ /* no invokes in the q */
thisx->invokeList = newEl;
}
resultInvokeID = newEl->invokeID;
newEl = NULL;
}
}
else
{
/* couldn't invoke script so memory must be deallocated */
DEALLOC( pBP );
DEALLOC( pCallURL );
}
return resultInvokeID;
}
VOID SQ_AbortScriptsForSpecificUA( pstructSQ thisx, UINT32 UApidInt )
{
pstructInvokeHead el = NULL;
pstructInvokeHead lastEl = NULL;
if (thisx != NULL)
{
el = thisx->invokeList;
while (el != NULL)
{
if (el->UApidAsInt == UApidInt)
{ /* this invoke is to be removed */
if (el == thisx->currentInvoke)
{
if (thisx->doRoundRobinScheduling)
{ /* make the previous invoke the current since it will be advanced to the next when scheduling */
thisx->currentInvoke = lastEl;
}
else
{ /* make NULL the current. This will make the first in the list the next to be taken care of */
thisx->currentInvoke = NULL;
}
}
/* remove it from the q */
if (lastEl == NULL)
{ /* this invoke is first in the list */
thisx->invokeList = el->next;
SQ_DeleteInvokeHead( &el );
el = thisx->invokeList;
}
else
{ /* normal remove */
lastEl->next = el->next;
SQ_DeleteInvokeHead( &el );
el = lastEl->next;
}
if (thisx->onlyOneScriptPerUA)
{ /* there can be only one invoke from this UA thus there is no need to search any further */
return;
}
}
else
{ /* el is not an invoke to be aborted (removed from the q) */
lastEl = el;
el = el->next;
}
}
}
}
enumScriptStatus SQ_Exec( pstructSQ thisx, UINT8 *pInvokeIDThatExecuted, UINT32 *pUApidInt )
{
pstructInvokeHead invokeEl = NULL;
pstructBPElement BPel = NULL;
BYTE *theBP = NULL;
UINT32 BPlen = 0;
INT16 IANAcharset = -1;
enumErrorCode siErrCode;
WCHAR *baseURL = NULL;
UINT32 baseURLlen = 0;
UINT32 i = 0;
WCHAR *goURL = NULL;
BOOL goPrev = FALSE;
pstructVar siResult = NULL;
WCHAR *callURL = NULL;
BYTE *funcName = NULL;
pstructOpS argOpS = NULL;
/*first make sure there is invokes to be procesed */
if (thisx->invokeList == NULL)
{
/* signal that there is nothing to proccess for now */
*pInvokeIDThatExecuted = 0;
return eSs_more;
}
/* find the InvokeHead to execute a block of script for */
if (thisx->doRoundRobinScheduling)
{
/* schedule to the next invoke */
if ((thisx->currentInvoke != NULL) && (thisx->currentInvoke->next != NULL))
{
thisx->currentInvoke = thisx->currentInvoke->next;
}
else
{ /* reached the end of the q and thus the first becomes the current invoke */
thisx->currentInvoke = thisx->invokeList;
}
}
else
{ /* */
thisx->currentInvoke = thisx->invokeList;
}
invokeEl = thisx->currentInvoke;
/* make sure that we have an invoke that is ready to run */
if (thisx->doRoundRobinScheduling)
{
/* traverse the q until a runnable invoke is found */
while (invokeEl->isDone || invokeEl->isInWaitState)
{
invokeEl = invokeEl->next;
}
thisx->currentInvoke = invokeEl;
if (invokeEl == NULL)
{ /* we have come to the end of the q */
/* signal that there is nothing to proccess for now */
*pInvokeIDThatExecuted = 0;
return eSs_more;
}
}
else
{
if (invokeEl->isDone && invokeEl->errorCode != ERR_WAE_WMLS_NONE)
{
/* signal that there is an script that failed */
*pInvokeIDThatExecuted = invokeEl->invokeID;
*pUApidInt = invokeEl->UApidAsInt;
return eSs_error;
}
else if (invokeEl->isInWaitState)
{
/* signal that there is nothing to proccess for now */
*pInvokeIDThatExecuted = 0;
return eSs_more;
}
}
/* Ok. We have now found an invoke that is ready to be executed */
/* first see if we must create a SI or there is one ready to run directly */
/* ASSERT( invokeEl->BPcallList != NULL) */
if (invokeEl->BPcallList->theSI == NULL)
{
/* we must create an SI */
/* first get the BP */
BPlen = invokeEl->BPcallList->BPlen;
theBP = invokeEl->BPcallList->BP;
IANAcharset = invokeEl->BPcallList->IANAcharset;
if ((theBP == NULL) || (BPlen == 0))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -