📄 si_bpi.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
-------
990526 (KHN) Corrigendum WAG-WMLScript-28 implemented.
Access control changes. Since access control is by default
disabled, there is no need for a certain pragma for this and it
has therefore been removed.
990726 (KHN) Error in BPI_New
First the IANAcharset parameter was used to update the BPI struct's
charset parameter. Then the BPI struct was updated and also the
charset parameter. Then finally a charset check was made but not
with the BPI struct as it should but instead with the IANAcharset
parameter. This error has now been corrected.
990824 (KHN) Correction of BPI_AccessCheck:
Now the function properly handles relative paths.
An access path that is not relative is resolved and then the path
is extracted.
000329 (KHN) Changes due to function name change. ReadByte -> wip_ReadByte
**********/
#include "si_bpi.h"
#include "si_types.h"
#include "url.h"
#include "wmlif.h"
#include "trnscode.h"
/******* private functions *******/
BOOL ParseAndCheckVersion( pstructBPInfo bpi, BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
BYTE version;
BYTE majorVersion;
BYTE minorVersion;
if ( wip_ReadByte( &version, BP, BPend, pos ) )
{
majorVersion = (BYTE)( (version >> 4) + 1 );
minorVersion = (BYTE)( (version & 0x0F) );
allOk = (BOOL)( ( majorVersion == SI_MAJOR_VERSION ) && (minorVersion <= SI_MINOR_VERSION) );
}
else allOk = FALSE;
if (allOk)
{
bpi->version = version;
}
return allOk;
}
BOOL ParseAndCheckSize( BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
UINT32 size = 0;
if ( ReadMBUInt32( &size, BP, BPend, pos ) )
{
allOk = (BOOL)( ( size == (UINT32)(BPend - *pos) ) );
}
else allOk = FALSE;
return allOk;
}
BOOL ParseAndCheckConstant( pstructBPInfo bpi, pstructConstInfo pInfo, BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
UINT32 strSize;
UINT8 constType;
bpi = bpi; /* to get rid of compilation warning */
if ( ReadUInt8( &constType, BP, BPend, pos ) )
{
allOk = (BOOL)( constType < CONST_TYPE_MAX );
}
else allOk = FALSE;
if (allOk)
{
pInfo->type = (enumConstType)constType;
pInfo->pos = *pos;
switch(constType)
{
case CONST_TYPE_INT8:
allOk = StepBytes( sizeof(INT8), BPend, pos );
break;
case CONST_TYPE_INT16:
allOk = StepBytes( sizeof(INT16), BPend, pos );
break;
case CONST_TYPE_INT32:
allOk = StepBytes( sizeof(INT32), BPend, pos );
break;
case CONST_TYPE_FLOAT32:
allOk = StepBytes( sizeof(FLOAT32), BPend, pos );
break;
case CONST_TYPE_UTF8:
case CONST_TYPE_EXT_CHARSET:
allOk = ReadMBUInt32( &strSize, BP, BPend, pos );
if (allOk)
{
allOk = StepBytes( strSize, BPend, pos );
}
break;
}
}
return allOk;
}
BOOL ParseAndCheckConstantPool( pstructBPInfo bpi, BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
UINT16 nbrOfConsts = 0;
UINT16 charSet = 0;
UINT16 i;
pstructConstInfo pInfo = NULL;
allOk = ReadMBUInt16( &nbrOfConsts, BP, BPend, pos );
if (allOk)
{
bpi->nbrOfConstants = nbrOfConsts;
}
allOk = ReadMBUInt16( &charSet, BP, BPend, pos );
if (allOk && (charSet != 0))
{
/* if charSet is 0, it means that the encoding of
the CONST_TYPE_EXT_CHARSET is given in the WSP header.
If no encoding is given there either, the
default charSet will be assumed */
bpi->characterSet = charSet;
}
if (allOk && (nbrOfConsts > 0))
{
bpi->constants = NEWARRAY( structConstInfo, nbrOfConsts );
i = 0;
pInfo = bpi->constants;
while ( allOk && (i < nbrOfConsts) )
{
allOk = ParseAndCheckConstant( bpi, pInfo, BP, BPend, pos );
i++;
pInfo++;
}
}
else bpi->constants = NULL;
return allOk;
}
BOOL ParseAndCheckPragma( pstructBPInfo bpi, pstructPragmaInfo pInfo, BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
UINT8 pragmaType;
UINT16 aParam;
UINT8 nbrOfParams;
UINT8 i;
enumConstType constType;
if ( ReadUInt8( &pragmaType, BP, BPend, pos ) )
{
allOk = ((BOOL)( pragmaType < PRAGMA_MAX ));
}
else allOk = FALSE;
if (allOk) {
pInfo->type = (enumPragmaType)pragmaType;
pInfo->pos = *pos;
switch(pragmaType) {
case PRAGMA_ACCESS_DOMAIN:
case PRAGMA_ACCESS_PATH:
nbrOfParams = 1;
break;
case PRAGMA_UA_PROP:
nbrOfParams = 2;
break;
case PRAGMA_UA_PROP_SCHEME:
nbrOfParams = 3;
break;
}
i = 0;
while ( (i<nbrOfParams) && allOk )
{
allOk = ReadMBUInt16( &aParam, BP, BPend, pos );
if (allOk)
{
if ( BPI_GetConstantType( bpi, aParam, &constType ) )
{
allOk = (BOOL)((constType >= CONST_TYPE_UTF8) &&
(constType <= CONST_TYPE_EXT_CHARSET));
/* each pragma has a set of params, each param is a string constant
a check must be made to ensure the param which is an index into the constant pool
is a legal string constant */
}
else allOk = FALSE;
}
i++;
}
}
return allOk;
}
BOOL ParseAndCheckPragmaPool( pstructBPInfo bpi, BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
UINT16 nbrOfPragmas = 0;
UINT16 i;
pstructPragmaInfo pInfo = NULL;
allOk = ReadMBUInt16( &nbrOfPragmas, BP, BPend, pos );
if (allOk) {
bpi->nbrOfPragmas = nbrOfPragmas;
}
if (allOk && nbrOfPragmas) {
bpi->pragmas = NEWARRAY( structPragmaInfo, nbrOfPragmas );
i = 0;
pInfo = bpi->pragmas;
while ( allOk && (i < nbrOfPragmas) ) {
allOk = ParseAndCheckPragma( bpi, pInfo, BP, BPend, pos );
i++;
pInfo++;
}
}
else bpi->pragmas = NULL;
return allOk;
}
BOOL CheckFunctionName( BYTE* funcName, UINT8 strLen )
/* checks that a UTF8 encoded string is a valid function name */
{
UINT8 i;
BOOL ok = TRUE;
ok = ((BOOL)( ( (funcName[0] >= 'a') && (funcName[0] <= 'z') ) ||
( (funcName[0] >= 'A') && (funcName[0] <= 'Z') ) || (funcName[0] == '_') ));
i = 1;
while ((i < strLen) && ok) {
ok = (BOOL)( ( (funcName[i] >= 'a') && (funcName[i] <= 'z') ) ||
( (funcName[i] >= 'A') && (funcName[i] <= 'Z') ) ||
(funcName[i] == '_') ||
( (funcName[i] >= '0') && (funcName[i] <= '9') ) );
i++;
}
return ok;
}
BOOL ParseAndCheckFunctionPool( pstructBPInfo bpi, BYTE* BP, UINT32 BPend, UINT32 *pos )
{
BOOL allOk = TRUE;
UINT8 nbrOfFunc;
UINT8 nbrOfPubFunc; /* number of funcs in func name list */
UINT8 funcIndex;
UINT8 nameSize;
UINT8 nbrOfArgs;
UINT8 nbrOfLocVars;
UINT32 funcSize;
UINT8 i;
allOk = ReadUInt8( &nbrOfFunc, BP, BPend, pos );
if (allOk) {
allOk = (BOOL)( nbrOfFunc > 0 );
}
if (allOk) {
bpi->nbrOfFunctions = nbrOfFunc;
bpi->functions = NEWARRAY( structFuncInfo, nbrOfFunc );
/* Start of function name list */
/* first start with setting funcNamePos of the functions to 0 */
i = 0;
while (i < nbrOfFunc) {
bpi->functions[i].funcNamePos = 0;
i++;
}
allOk = ReadUInt8( &nbrOfPubFunc, BP, BPend, pos );
if (allOk) {
allOk = (BOOL)( (nbrOfPubFunc > 0) && (nbrOfPubFunc <= nbrOfFunc) );
}
if (allOk) {
i = 0;
while ((i < nbrOfPubFunc) && allOk) {
allOk = ReadUInt8( &funcIndex, BP, BPend, pos );
if (allOk) {
allOk = (BOOL)( funcIndex < nbrOfFunc );
}
if (allOk) {
bpi->functions[funcIndex].funcNamePos = *pos;
/* the funcNamePos is used by Accesscheck to search for the function with a certain function name */
allOk = ReadUInt8( &nameSize, BP, BPend, pos );
}
if (allOk) {
allOk = StepBytes( nameSize, BPend, pos );
/* step the bytes to see that the BP doesn't end abruptly */
}
if (allOk) {
allOk = CheckFunctionName( (BP + *pos - nameSize), nameSize );
/* check that it is a legal func name string (UTF8 encoded) */
}
i++;
}
}
if (allOk) {
/* Start of functions section (func prologue and and code array) */
i = 0;
while ((i < nbrOfFunc) && allOk) {
allOk = ReadUInt8( &nbrOfArgs, BP, BPend, pos );
if (allOk) {
bpi->functions[i].nbrOfArgs = nbrOfArgs;
allOk = ReadUInt8( &nbrOfLocVars, BP, BPend, pos );
}
if (allOk) {
bpi->functions[i].nbrOfVars = nbrOfLocVars;
allOk = (BOOL)( (nbrOfArgs + nbrOfLocVars) <= 256 );
}
if (allOk) {
allOk = ReadMBUInt32( &funcSize, BP, BPend, pos );
}
if (allOk) {
bpi->functions[i].startPos = *pos;
bpi->functions[i].endPos = *pos + funcSize;
allOk = StepBytes( funcSize, BPend, pos );
}
i++;
}
}
}
return allOk;
}
/******* end private functions **************/
/*==========================================
BPI_Delete
============================================
---Purpose:
To deallocate a BPI and its components.
Note! The BPI pointer will be set to NULL after deallocation so that
it's not possible to use the pointer by mistake.
---Params:
pThis a reference to the BPI to delete
---Return:
------------------------------------------------------------------------*/
VOID BPI_Delete( pstructBPInfo *pThis )
{
if (*pThis != NULL) {
DEALLOC( &( (*pThis)->constants ) );
DEALLOC( &( (*pThis)->pragmas ) );
DEALLOC( &( (*pThis)->functions ) );
DEALLOC(pThis);
}
}
/*==========================================
BPI_New
============================================
---Purpose:
To create and init a BPI.
The BP will be parsed and the BPI will be filled out with all the info
that can be derived from the BP.
---Params:
BP the bytecode package which is to be parsed
BPlen the length (in bytes) of the BP
IANAcharset string encoding within the BP file according to the WSP header
---Return:
pstructBPInfo the BPI was successfully created and initialised.
NULL the operation failed.
------------------------------------------------------------------------*/
pstructBPInfo BPI_New( BYTE* BP, UINT32 BPlen, INT16 IANAcharset )
{
UINT32 pos = 0;
BOOL allOk = TRUE;
pstructBPInfo bpi = NEWSTRUCT(structBPInfo);
bpi->constants = NULL;
bpi->pragmas = NULL;
bpi->functions = NULL;
bpi->characterSet = IANAcharset;
/* a bytecode pacakage has one string encodein (UTF8, UCS2 or UCS4) */
allOk = ParseAndCheckVersion( bpi, BP, BPlen, &pos );
if (allOk) {
allOk = ParseAndCheckSize( BP, BPlen, &pos );
}
if (allOk) {
allOk = ParseAndCheckConstantPool( bpi, BP, BPlen, &pos );
if (bpi->characterSet < 1)
{
/* if charSet is 0, it means that the encoding of
the CONST_TYPE_EXT_CHARSET is given in the WSP header.
If no encoding is given there either, the
default charSet will be assumed (IANA_CHARSET_LATIN1).
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
This is a deliberate deviation from the WMLS 1.1 spec which
says UTF-8 as the default.
The reason for this deviation is that assuming ISO-Latin1 will never
result in faulty strings since all values of a BYTE* string is a valid
ISO-LATIN1 string which is not the case with UTF-8. We believe that
this will make the interpreter more robust.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
bpi->characterSet = IANA_CHARSET_LATIN1;
}
}
if (allOk) {
allOk = Iana2Unicode_canConvert( bpi->characterSet );
/* if transcoding is not supported, verification error will occur */
}
if (allOk) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -