📄 _pi3expr.cpp
字号:
Respectively case sensitive and insensitive comparision of two text
patterns.
<H5>
dblookup(dbname,type,variable[,flags][,fnvalue][,first][,last])
</H5>
<STRONG>NOTE:</STRONG>This function is not currently supported to the full
specification as described here.
Iterate over a number of elements of a specific type in a particular database.
<CENTER>
Function arguments:-
<TABLE BORDER=1>
<TH>Argument position
<TH>Description
<TH>Default, (+)=Mandatory
<TH>Values
<TR>
<TD>1
<TD>name of database
<TD>+
<TD>program|connection|host|request|response
<TR>
<TD>2
<TD>type of element
<TD>+
<TD>rfc822|string|opaque
<TR>
<TD>3
<TD>variable name
<TD>+
<TD>a variable name (or empty for all)
<TR>
<TD>4
<TD>db flags affecting lookup
<TD>0
<TD>pidbflag_propagateup|pidbflag_fastkey|0
<TR>
<TD>5
<TD>callback argument
<TD>&_()
<TD>Expression invoked for value of every db entry
<TR>
<TD>6
<TD>start index
<TD>0
<TD>Number
<TR>
<TD>7
<TD>end index
<TD>0
<TD>Number
</TABLE>
</CENTER>
<H5>
dbreplace(dbname,type,variable,value[,flags])
</H5>
Replace the value of a variable of the specific type in a particular
database. The function arguments are the same as described above.
<H5>
if(boolean,true_text,false_text)
</H5>
If boolean is true (i.e., boolean is any character sequence with length
greater than zero), then this function evaluates to true_text, otherwise this
function evaluates to false_text.
<H5>
not(boolean)
</H5>
If boolean is true (i.e., boolean is any character sequence with length
greater than zero), then this function returns a zero length text string
(false), otherwise a non-zero length text string (true) is returned.
The net result is the negation of the boolean argument.
<H5>
regexp(regexp,text)
</H5>
Determine if the regular expression 'regex' matches the text 'text'.
Returns 'true' (non-empty text) on success, 'false' (empty text) on
failure.
Regular expression matching is done using the function HTTPUtil_regexMatch(),
reference that function to see which regular expression constructs which
are supported.
<H5>
trunc(text,number)
</H5>
Truncate text to the the decimal value of number.
/*___+++HTMLDOC_END+++___*/
#endif
/*____________________________________________________________________________*\
*
Class:
Description:
Component context, largely used for nested functions.
\*____________________________________________________________________________*/
class Context
{
public:
PIHTTP &tPIHTTP;
enum { CONTEXT_SIZE=10 };
Context *pParent;
void *pData;
const char *aString[CONTEXT_SIZE];
int aLength[CONTEXT_SIZE];
Context(
Context *pTheParent,
PIHTTP &tThePIHTTP,
void *pTheData )
: tPIHTTP( tThePIHTTP ),
pParent( pTheParent ),
pData( pTheData )
{
memset( aString, 0, sizeof( const char * ) * CONTEXT_SIZE );
memset( aLength, 0, sizeof( int ) * CONTEXT_SIZE );
};
/* --- traverse up list of contexts --- */
inline Context *GetContext( int iOffset )
{
assert( iOffset>=0 );
if ( !pParent )
{ return 0; };
if ( iOffset==0 )
{ return this; };
return pParent->GetContext( iOffset-1 );
};
};
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class StringComponent : public ComponentBase
{
private:
PIString sString;
public:
/* --- string with length iLen --- */
StringComponent( const char *pString, int iLen )
: sString( pString, iLen )
{};
/* --- null terminated string --- */
StringComponent( const char *pString )
: sString( pString )
{};
virtual void WriteDebugTree( int iIndent ) const
{
for(int i=0; i<iIndent; i++ )
{ cerr << INDENT_PATTERN; };
cerr << "String:'" << sString << "'" << endl;
};
virtual int Write( Context &, char *pszBuffer, int iLength ) const
{
if ( iLength>0 )
{
assert( pszBuffer );
strncpy( pszBuffer, sString, iLength );
};
return sString.Len();
};
virtual int IsOK() const { return 1; };
virtual int IsStatic() const { return 1; };
};
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class ExpressionComponent : public ComponentBase
{
private:
DblList lComponents;
int iOK;
int iStatic;
/* --- internal methods --- */
int Compile( Context &tContext, DblList &lRawComponents,
PIString & /* sError */ )
{
/* ---
optimize the expression by merging static components
together
--- */
/* --- make a really big buffer --- */
enum { BUF_SIZE=32767 };
char *pszBuffer = PI_NEW( char[BUF_SIZE+1] ); /* too big for auto */
assert( pszBuffer );
/* --- iterate over components merging where possible --- */
int iLength = 0; /* --- length of buffer with static data --- */
iStatic = 1; /* --- mark this static till we know otherwise ---*/
for( ; lRawComponents.Size() ; )
{
ComponentBase *pComp = (ComponentBase *)lRawComponents.Cap();
assert( pComp );
if ( pComp->IsStatic() )
{
/* --- static --- */
int iWritten = pComp->Write( tContext, &(pszBuffer[iLength]),
BUF_SIZE-iLength );
assert( iWritten!=-1 );
if ( iWritten==-1 )
{
PI_DELETE( pComp );
PI_DELETE( [] pszBuffer );
return 0;
};
if ( (iLength+iWritten)<=BUF_SIZE )
{
/* --- component is written into buffer, start next one --*/
PI_DELETE( pComp );
iLength+=iWritten;
continue;
};
/* --- else don't merge this component --- */
};
/* --- flush the buffer --- */
if ( iLength )
{
/* --- previous components have been written --- */
lComponents.Append( (DblList::type)PI_NEW(
StringComponent( pszBuffer, iLength ) ) );
iLength = 0;
};
iStatic = 0;
lComponents.Append( (DblList::type)pComp );
};
if ( iLength )
{
/* --- previous components have been written --- */
lComponents.Append( (DblList::type)PI_NEW(
StringComponent( pszBuffer, iLength ) ) );
iLength = 0;
};
PI_DELETE( [] pszBuffer );
return 1;
};
/* --- forbid copy constructor --- */
ExpressionComponent( const ExpressionComponent & )
{ assert( 0 ); };
public:
ExpressionComponent( Context &tContext, DblList &lRawComponents,
PIString &sError )
: iOK( 0 ),
iStatic( 0 )
{
if ( Compile( tContext, lRawComponents, sError ) )
{ iOK = 1; };
};
~ExpressionComponent()
{
for( DblListIterator i( lComponents ); !i.BadIndex(); i++ )
{
ComponentBase *pComp = (ComponentBase *)i.Current();
PI_DELETE( pComp );
};
};
virtual void WriteDebugTree( int /* iIndent */ ) const
{
#if 0
for(int i=0; i<iIndent; i++ )
{ cerr << INDENT_PATTERN; };
cerr << "String:'" << sString << "'" << endl;
#endif
};
virtual int Write( Context &tContext, char *pszBuffer, int iMaxLen ) const
{
int iWrittenSoFar = 0;
int iLengthSoFar = 0;
for( ConstDblListIterator i( lComponents ); !i.BadIndex(); i++ )
{
ComponentBase *pComp = (ComponentBase *)i.Current();
assert( pComp );
int iWritten = pComp->Write( tContext,
&( pszBuffer[iWrittenSoFar] ), iMaxLen-iWrittenSoFar );
if ( iWritten==-1 )
{
assert( 0 );
return -1;
};
/* else */
iLengthSoFar += iWritten;
if ( iLengthSoFar>iMaxLen )
{
iWritten = iMaxLen - iWrittenSoFar;
};
iWrittenSoFar += iWritten;
assert( iWrittenSoFar<=iMaxLen );
};
return iLengthSoFar;
};
virtual int IsOK() const
{
return iOK;
};
virtual int IsStatic() const
{
return iStatic;
};
};
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class ParameterComponent : public ComponentBase
{
private:
FnPi3Write tFunction;
public:
ParameterComponent( FnPi3Write tTheFunction )
: tFunction( tTheFunction )
{
if ( !tTheFunction )
{ return; };
}
virtual void WriteDebugTree( int iIndent ) const
{
for(int i=0; i<iIndent; i++ )
{ cerr << INDENT_PATTERN; };
cerr << "Parameter:" << endl;
};
virtual int Write( Context &tContext, char *pszBuffer, int iLength ) const
{
assert( tFunction );
return (tFunction)(&(tContext.tPIHTTP), tContext.pData, pszBuffer,
iLength );
};
virtual int IsOK() const { return tFunction!=0; };
virtual int IsStatic() const { return 0; /* some params only */ };
};
/*____________________________________________________________________________*\
*
Description:
\*____________________________________________________________________________*/
typedef int (* SCFnWrite)( Context &, char *, int );
int iShortcutsInitialized = 0;
static SCFnWrite aFunctions[256];
/* --- macros to simplify shortcut functions --- */
#define O PIDBTYPE_OPAQUE
#define S PIDBTYPE_STRING
#define F PIDBTYPE_RFC822
#define C(x,y) PIDB_lookup( tContext.tPIHTTP.GetConnectionDB(), x, y, 0 )
#define Q(x,y) PIDB_lookup( tContext.tPIHTTP.GetRequestDB(), x, y, 0 )
#define R(x,y) PIDB_lookup( tContext.tPIHTTP.GetResponseDB(), x, y, 0 )
#define V(x,y) PIDB_lookup( tContext.tPIHTTP.GetHostDB(), x, y, 0 )
#define SC_STR_FUNCTION(fn, value)\
static int (fn)( Context &tContext, char *pszBuffer, int iLength ) \
{ \
(void)tContext; \
const char *pString = (const char *)(value); \
if ( !pString ) { return 0; }; \
int iValueLen = strlen( pString ); \
int iLen = iValueLen < iLength ? iValueLen : iLength; \
if ( iLen>0 ) \
{ \
assert( pszBuffer ); \
strncpy( pszBuffer, pString, iLen ); \
}; \
return iValueLen; \
}
# define SC_NUM_FUNCTION(fn, value, flags)\
static int (fn)( Context &tContext, char *pszBuffer, int iLength ) \
{ \
(void)tContext; \
enum { BUF_SIZE=63 }; \
char szBuf[BUF_SIZE+1]; \
*szBuf = '\0'; \
sprintf( szBuf, flags, (value) ); \
int iValueLen = strlen( szBuf ); \
int iLen = iValueLen < iLength ? iValueLen : iLength; \
if ( iLen>0 ) \
{ \
assert( pszBuffer ); \
strncpy( pszBuffer, szBuf, iLen ); \
}; \
return iValueLen; \
}
SC_STR_FUNCTION( sc_a, V( F, "Administrator") );
SC_STR_FUNCTION( sc_A, C( S, KEY_INT_REMOTEADDR ) );
SC_NUM_FUNCTION( sc_b, tContext.tPIHTTP.GetIOBuffer().GetBytesSent(), "%d" );
SC_STR_FUNCTION( sc_c, R( F, KEY_HTTP_CONTENTTYPE ) );
SC_STR_FUNCTION( sc_C, Q( F, KEY_HTTP_CONTENTTYPE ) );
SC_STR_FUNCTION( sc_d, HTTPCore_debugEnabled() ? "true" : "" );
SC_NUM_FUNCTION( sc_D, tContext.tPIHTTP.iDelta, "%d" );
SC_STR_FUNCTION( sc_e, C( S, KEY_HTTPS_CIPHERNAME ) );
SC_STR_FUNCTION( sc_f, R( S, KEY_INT_PATH ) );
SC_STR_FUNCTION( sc_G, C( S, KEY_HTTPS_SECRETKEYSIZE ) );
SC_STR_FUNCTION( sc_h, C( S, KEY_INT_REMOTEHOST ) );
SC_STR_FUNCTION( sc_H, Q( S, KEY_HTTP_PROTOCOL ) );
SC_STR_FUNCTION( sc_i, C( S, KEY_INT_REMOTEIDENT ) );
SC_STR_FUNCTION( sc_I, R( S, KEY_INT_PATHINFO ) );
SC_NUM_FUNCTION( sc_k, (long)PIThread_getSystemHandle( PIThread_getCurrent() ),
"%ld");
SC_STR_FUNCTION( sc_K, C( S, KEY_HTTPS_KEYSIZE ) );
SC_STR_FUNCTION( sc_m, Q( S, KEY_HTTP_METHOD ) );
#if POSIX
SC_STR_FUNCTION( sc_M, "\n" );
#else
SC_STR_FUNCTION( sc_M, "\r\n" );
#endif
SC_STR_FUNCTION( sc_n, tContext.tPIHTTP.pHandlerName );
SC_STR_FUNCTION( sc_N, HTTPUtil_phaseNumberToName(
tContext.tPIHTTP.ciPhase ) );
SC_STR_FUNCTION( sc_l, C( S, KEY_INT_LOCALADDR ) );
SC_STR_FUNCTION( sc_o, V( F, KEY_INT_OBJECTNAME ) );
SC_STR_FUNCTION( sc_p, HTTPUtil_getHostPort(&(tContext.tPIHTTP)) );
SC_NUM_FUNCTION( sc_P, PIPlatform_getProcessId(), "%d" );
SC_STR_FUNCTION( sc_q, Q( S, KEY_HTTP_QUERYSTRING ) );
SC_STR_FUNCTION( sc_r, Q( S, KEY_HTTP_CLF ) );
SC_STR_FUNCTION( sc_R, HTTPUtil_rcNumberToName(
tContext.tPIHTTP.iLastResultCode ) );
SC_NUM_FUNCTION( sc_s, tContext.tPIHTTP.iStatus, "%d" );
SC_STR_FUNCTION( sc_S, HTTPCore_getServerStamp() );
SC_STR_FUNCTION( sc_u, R( S, KEY_INT_REMOTEUSER ) );
SC_STR_FUNCTION( sc_U, Q( S, KEY_HTTP_URI ) );
SC_STR_FUNCTION( sc_v, HTTPUtil_getHostName(&(tContext.tPIHTTP)) );
SC_STR_FUNCTION( sc_x, R( S, KEY_INT_AUTHTYPE ) );
SC_NUM_FUNCTION( sc_X, tContext.tPIHTTP.iDepth, "%d" );
SC_STR_FUNCTION( sc_y, R( F, KEY_HTTP_CONTENTLENGTH ) );
SC_STR_FUNCTION( sc_Y, Q( F, KEY_HTTP_CONTENTLENGTH ) );
SC_STR_FUNCTION( sc_z, R( S, KEY_INT_SCRIPTNAME ) );
SC_STR_FUNCTION( sc_Z, R( S, KEY_INT_PATHTRANSLATED ) );
/* ---
Functions which don't conform to the standard template
--- */
static int sc_E( Context &tContext, char *pszBuffer, int iLength )
{
/* ---
Print out all error messages
--- */
int iTotalLen = 0;
PIDBIterator *pIter = PIDB_getIterator( tContext.tPIHTTP.pResponseDB,
PIDBTYPE_STRING, KEY_INT_ERRORMESSAGE, 0 );
if ( pIter )
{
for( ;
PIDBIterator_atValidElement( pIter );
PIDBIterator_next( pIter ) )
{
const char *pDummy;
const char *pMessage = (const char *)PIDBIterator_current(
pIter, &pDummy );
int iLen = strlen( pMessage );
iTotalLen += iLen;
if ( iLen>iLength )
{ iLen = iLength; };
if ( iLen )
{
assert( pszBuffer );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -