📄 cgi.cpp
字号:
/*____________________________________________________________________________*\
*
Copyright (c) 1997-2003 John Roy, Holger Zimmermann. All rights reserved.
These sources, libraries and applications are
FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
as long as the following conditions are adhered to.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHORS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*____________________________________________________________________________*|
*
* $Source: /cvsroot/pi3web/Pi3Web_200/Source/HTTP/CGI.cpp,v $
* $Date: 2003/05/13 18:42:02 $
*
Description:
CGI Handler
Rewritten to handle standard CGI only, windows CGI is in WinCGI.cpp
\*____________________________________________________________________________*/
//$SourceTop:$
#include <ctype.h>
#include <stdio.h>
#include "PIStrStr.h"
#include "HTTPCore.h"
#include "HTTPUtil.h"
#include "PIHTTP.h"
#include "Pi2API.h"
#include "StrToken.h"
#include "DeQuote.h"
#include "HandBase.h"
#include "Pi3Expr.h"
#if WIN32
# include <windows.h>
# include <shellapi.h>
# include <io.h>
typedef HANDLE FILEDESC;
typedef HANDLE PROCDESC;
# define INVALID_DESC (INVALID_HANDLE_VALUE)
typedef void * ENVIRONMENT;
inline bool CloseFileDesc( FILEDESC &tFileDesc )
{
# if !defined(NDEBUG)
int iRet = ::CloseHandle( tFileDesc )==0 ? false : true;
tFileDesc = INVALID_DESC;
return iRet;
# else
return ::CloseHandle( tFileDesc )==0 ? false : true;
# endif
};
#elif POSIX
# include <unistd.h>
# include <errno.h>
# include <signal.h>
typedef int PROCDESC;
typedef int FILEDESC;
# define INVALID_DESC (-1)
typedef void **ENVIRONMENT;
inline bool CloseFileDesc( FILEDESC &tFileDesc )
{
# if !defined(NDEBUG)
int iRet = ::close( tFileDesc )==-1 ? false : true;
tFileDesc = INVALID_DESC;
return iRet;
# else
return ::close( tFileDesc )==-1 ? false : true;
# endif
};
#else
# error Unsupported operating system
#endif
/*____________________________________________________________________________*\
*
Description:
\*____________________________________________________________________________*/
#define KEY_CONF_FILEIOOBJECT "FileIOObject"
#define KEY_CONF_DEFAULTCOMMANDLINE "DefaultCommandLine"
#define KEY_CONF_COMMANDLINEBYEXT "CommandLineByExt"
#define KEY_CONF_VARIABLE "Variable"
#define KEY_CONF_ENVIRONMENTSIZE "EnvironmentSize"
#define KEY_CONF_INCLUDEPARENTSENVIRONMENT "IncludeParentsEnvironment"
#define KEY_CONF_EXTRAHEADERS "ExtraHeaders"
#define VALUE_NO "No"
#define VALUE_YES "Yes"
#define KEY_CONF_EXTRAHEADERSPREFIX "ExtraHeadersPrefix"
#define KEY_CONF_EXTRAHEADERSIGNORE "ExtraHeadersIgnore"
#define KEY_CONF_SENDCRLF "SendCRLF"
#define KEY_CONF_DATABLOCK "DataBlock"
#define KEY_CONF_FLAG "Flag"
#define KEY_CONF_KILLAFTER "KillAfter"
#define VALUE_16BIT "16-Bit"
/* --- really verbose development-time debugging --- */
#define VERBOSE_DEBUG 0
#if VERBOSE_DEBUG
# define D { cerr << __FILE__ << ", " << dec << __LINE__ << ": " << endl; }
#else
# define D
#endif
/*
** Flags
*/
#define FLG_16BIT 0x0001
/*____________________________________________________________________________*\
*
Description:
Documentation.
\*____________________________________________________________________________*/
#if 0
/*___+++CNF_BEGIN+++___*/
<Class>
Name CGIClass
Type LogicExtension
Library HTTP
OnClassLoad HandlerBaseHTTP_onClassLoad
Constructor CGI_constructor
CopyConstructor HandlerBaseHTTP_copyConstructor
Destructor HandlerBaseHTTP_destructor
Execute HandlerBaseHTTP_execute
</Class>
<Object>
Name CGI
Class CGIClass
</Object>
/*___+++CNF_END+++___*/
#endif
#if 0
/*
** HTML documentation for this handler
*/
/*___+++HTMLDOC_BEGIN+++___*/
Name:
CGI
Description:
This HTTP Handler handles CGI requests.
Options:
<H5>Overview</H5>
<TABLE BORDER=1>
<TH>Option
<TH>Default
<TH>Values
<TH>Short Description
<TH>Example(s)
<TR>
<TD>FileIOObject
<TD>+
<TD><objectname>
<TD>A Pi3 IO object
<TD>FileIOObject "CGIFileIO"
<TR>
<TD>CommandLineByExt
<TD>-
<TD><key>="<Pi3Expression>"
<TD>A key-value pair with an extension and a Pi3Expression
<TD>CommandLineByExt .cgi="perl %p%q"
<TR>
<TD>DefaultCommandLine
<TD>-
<TD><Pi3Expression>
<TD>A Pi3Expression, which expands to a command line
<TD>DefaultCommandLine "%p %d"
<TR>
<TD>IncludeParentsEnvironment
<TD>Yes
<TD>Yes|No
<TD>Indicates if parents environment is inherited to CGI children
<TD>IncludeParentsEnvironment Yes
<TR>
<TD>EnvironmentSize
<TD>4096
<TD><A number>
<TD>The number of bytes used for the environment block of CGI children
<TD>EnvironmentSize 8192
<TR>
<TD>Variable
<TD>-
<TD><Pi3Expression>
<TD>A variable definition
<TD>Variable "GATEWAY_INTERFACE=CGI/1.1"
<TR>
<TD>ExtraHeaders
<TD>Yes
<TD>Yes|No
<TD>Indicates if extra headers are considered
<TD>ExtraHeaders Yes
<TR>
<TD>ExtraHeadersPrefix
<TD>-
<TD><A string>
<TD>Used as prefix of each extra header
<TD>ExtraHeadersPrefix "HTTP_"
<TR>
<TD>ExtraHeadersIgnore
<TD>-
<TD><Space delimited Strings>
<TD>List of unconsidered extra headers
<TD>ExtraHeadersIgnore "Content-Type Content-Length"
<TR>
<TD>KillAfter
<TD>-1
<TD><A number>
<TD>Time to wait before killing the process.
<TD>KillAfter "-1"
<TR>
<TD>SendCRLF
<TD>No
<TD>Yes|No
<TD>Adds additional "CRLF" to the CGI input.
<TD>SendCRLF Yes
<TR>
<TD>Flag
<TD>-
<TD>"16-Bit", etc.
<TD>A flag to effect CGI
<TD>Flag "16-Bit"
</TABLE>
<STRONG>-</STRONG> in the <IT>default</IT> indicates no default<BR>
<STRONG>+</STRONG> in the <IT>default</IT> indicates the field is mandatory<BR>
<H4>Description of Options</H4>
<H5>FileIOObject</H5>
Specifies the IO object to be used to communicate with CGI programs.
A prototype object is created on initialization and a copy is generated
using PIObject_copy() for each CGI program.
<H5>CommandLineByExt</H5>
This configuration key could be given multiple times to declare command
line mappings for file extensions of CGI programs. The value is treated
as Pi3Expression.
<H5>DefaultCommandLine</H5>
This configuration key is used to declare the default command line,
which is used, if no mapping matches. The value is treated as
Pi3Expression.
<H5>IncludeParentsEnvironment</H5>
Indicates, if the environment variables of the parent process
are included in the environment of the CGI child process.
<H5>EnvironmentSize</H5>
Specifies a sufficient number of bytes for the environment block,
which is used to fork the CGI child process.
<H5>Variable</H5>
Specifies an environment variable expression to be set into the
environment block of CGI programs. Could be set multiple times in
one configuration object.
<H5>ExtraHeaders</H5>
This configuration key defines, if extra headers are considered by
the processing of this handler.
<H5>ExtraHeadersPrefix</H5>
This configuration value will be the trailing string of each extra
request header.
<H5>ExtraHeadersIgnore</H5>
The headers in this list are not treated as extra headers.
<H5>KillAfter</H5>
Specifies the amount of time the server will wait for a CGI response
before forceably killing the process. -1 specifies an infinite timeout.
This value is measured in seconds.
<H5>SendCRLF</H5>
If this option is set to "Yes", an additional linefeed (CRLF),
which is not contained in the Content-Length, is added to the CGI input
by the handler. This is required by some CGI programs.
<H5>Flag</H5>
Specifies a flag which changes CGI behaviour. This directive can be
repeated multiple times to add different flags.<P>
Flags are:-<BR>
<I>16-Bit</I> <B>Windows NT only</B>, expect CGI programs to be 16-Bit
Windows or MS-DOS images, change semantics appropriately.
Parameters:
The Pi3Expressions in the configuration variables DefaultCommandLine,
CommandLineByExt and Variable may contain besides the standard shortcuts
used in Pi3Expressions the following, context specific parameters.
<CENTER>
<TABLE BORDER=1>
<TH>Parameter<TH>Evaluates to<TR>
<TD>%p<TD>Full pathname to CGI program<TR>
<TD>%q<TD>Value of an "isIndex" query<TR>
</TABLE>
</CENTER>
Example:
<PRE>
<Object>
Name CGI
Class CGIClass
FileIOObject "CGIFileIO"
DefaultCommandLine "%p%q"
CommandLineByExt .cmd="cmd.exe /c %p%q"
CommandLineByExt .pl="perl %p%q"
IncludeParentsEnvironment Yes
EnvironmentSize 8192
Variable "CONTENT_LENGTH=$Y"
Variable "CONTENT_TYPE=$C"
Variable "GATEWAY_INTERFACE=CGI/1.1"
Variable "PATH_INFO=$I"
Variable "PATH_TRANSLATED=$Z"
Variable "QUERY_STRING=$q"
ExtraHeaders Yes
ExtraHeadersPrefix "HTTP_"
ExtraHeadersIgnore "Content-Type Content-Length"
SendCRLF Yes
KillAfter 60
</Object>
</PRE>
/*___+++HTMLDOC_END+++___*/
#endif
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
inline void CloseIfValidDesc( FILEDESC &tFD )
{
if (tFD!=INVALID_DESC)
{ ::CloseFileDesc( tFD ); };
}
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
inline void CloseProcessDesc( PROCDESC &tProcess )
{
#if WIN32
CloseIfValidDesc( tProcess );
#else
(void)tProcess;
#endif
}
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class CGI : HandlerBaseHTTP
{
private:
/* --- forbid copy constructor --- */
CGI( const CGI &t )
: HandlerBaseHTTP( t )
{ assert( 0 ); };
/* ---
Configuration data
--- */
PIObject *pPipeIO; /* the pipe IO object */
Pi3Expression *pDefaultCommandLine;
/* default command line */
DblList lCommandLineByExt; /* mappings of file extension to command line */
int iIncludeParentsEnvironment;
/* include parents environment */
int iEnvironmentSize; /* maximum size for an environment */
DblList lVariables; /* environment variables */
int iExtraHeaders; /* whether or not to send extra headers */
int iSendCRLF; /* send CRLF to CGI program after data */
enum { DEFAULT_ENVIRONMENT_SIZE=4094 };
PIString sExtraHeadersPrefix;
/* prefix for extra header information */
DblList lIgnoreHeaders; /* extra headers to ignore */
FnPi3Write aFunctions[256]; /* callback functions */
int iFlags; /* flags */
int iKillAfter; /* kill the CGI process after this time */
/* ---
FastKeys
--- */
const char *pFKContentType; /* RFC822: Content-Type */
const char *pFKFileInfo; /* OPAQUE: Pointer to fileinfo object */
const char *pFKPath; /* STRING: Translated path */
const char *pFKURI; /* RFC822: URI from request header */
/* ---
Class with context data for expressions
--- */
class CGIContextData
{
public:
PIString sExePath;
PIString sIsIndexValue;
public:
CGIContextData()
{};
};
/* ---
Class for fileextension to commandline
--- */
class FileExtToCommandLineMap
{
public:
PIString sFileExtension;
Pi3Expression *pExpr;
int iOK;
FileExtToCommandLineMap( const char *pPattern,
FnPi3Write *paFunctions, PIString &sError )
: pExpr( 0 ),
iOK( 0 )
{
StringTokenizer tTokens( pPattern, "=", 0 );
if ( tTokens.NumTokens()!=2 )
{ return; };
DeQuote tTmp( tTokens.GetToken( 0 ) );
const char *pExt = tTmp;
sFileExtension = (*pExt=='.') ? &(pExt[1]) : pExt;
DeQuote tTmp2( tTokens.GetToken( 1 ) );
const PIString &sTmp = (const PIString &)tTmp2;
Pi3String *pError = Pi3String_new( 0 );
pExpr = Pi3Expression_new( sTmp, paFunctions, pError );
if ( !pExpr )
{
sError = Pi3String_getPtr( pError );
Pi3String_delete( pError );
return;
};
Pi3String_delete( pError );
iOK = 1;
};
~FileExtToCommandLineMap()
{
Pi3Expression_delete( pExpr );
};
inline int IsOK() { return iOK; };
};
private:
int LoadExpression( const char *pName, Pi3Expression **ppExpression,
const char *pValue, PIOStrStream &os )
{
assert( pName );
assert( pValue );
assert( ppExpression );
Pi3Expression *pExpr = *ppExpression;
if ( pExpr )
{
os << "'" << pName << "' may only be specified once." << ends;
CONFIG_ERR( Object(), os.str() );
return 0;
};
Pi3String *pError = Pi3String_new( 0 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -