/*++

   Copyright    (c)    1995    Microsoft Corporation

   Module  Name :

      basereq.hxx
      
   Abstract:

      This file declares the class for http base request, that is used
        by the w3 information service.

   Author:

       Murali R. Krishnan    ( MuraliK )    16-Oct-1995

   Environment:

       Win32 -- User Mode

   Project:

       W3 Server DLL

   Revision History:
       Murali R. Krishnan  (MuraliK)  22-Jan-1996
                        make impersonation/revert function virtual

--*/

# ifndef _BASEREQ_HXX_
# define _BASEREQ_HXX_ 

/************************************************************
 *     Include Headers
 ************************************************************/

# include "string.hxx"
# include "httphdr.hxx"
# include "tssec.hxx"
# include "w3type.hxx"
# include "filter.hxx"
# include "redirect.hxx"

extern BOOL ReadEntireFile(
    CHAR        *pszFileName,
    TSVC_CACHE  &Cache,
    HANDLE      User,
    BUFFER      *pBuf,
    DWORD       *pdwBytesRead
    );

// Forward References
class CLIENT_CONN;
class HTTP_FILTER;
class HTTP_FILTER_DLL;
class W3_SERVER_INSTANCE;

/************************************************************
 *   Symbolic Constants
 ************************************************************/

//
//  HTTP Server response status codes
//

#define HT_OK                           200
#define HT_CREATED                      201
//#define HT_ACCEPTED                   202
//#define HT_PARTIAL                    203
#define HT_NO_CONTENT                   204
#define HT_RANGE                        206

//#define HT_MULT_CHOICE                300
#define HT_MOVED                        301
#define HT_REDIRECT                     302
#define HT_REDIRECT_METHOD              303
#define HT_NOT_MODIFIED                 304

#define HT_BAD_REQUEST                  400
#define HT_DENIED                       401
//#define HT_PAYMENT_REQ                402
#define HT_FORBIDDEN                    403
#define HT_NOT_FOUND                    404
#define HT_METHOD_NOT_ALLOWED           405
#define HT_NONE_ACCEPTABLE              406
#define HT_PROXY_AUTH_REQ               407
//#define HT_REQUEST_TIMEOUT            408
//#define HT_CONFLICT                   409
//#define HT_GONE                       410
#define HT_LENGTH_REQUIRED              411
#define HT_PRECOND_FAILED               412
#define HT_URL_TOO_LONG                 414
#define HT_RANGE_NOT_SATISFIABLE        416

#define HT_SERVER_ERROR                 500
#define HT_NOT_SUPPORTED                501
#define HT_BAD_GATEWAY                  502
#define HT_SVC_UNAVAILABLE              503
#define HT_GATEWAY_TIMOUT               504

//
//  Special invalid HTTP response code used to indicate a request should not
//  be logged
//

#define HT_DONT_LOG                     000

//
//  The versioning string for responses
//
#define HTTP_VERSION_STR        PSZ_HTTP_VERSION_STR

//
//  Flags for network communications over this request
//

#define IO_FLAG_ASYNC           0x00000010  // Call is async
#define IO_FLAG_SYNC            0x00000020  // Call is synchronous
#define IO_FLAG_SEND            0x00000040  // Call is a send
#define IO_FLAG_RECV            0x00000080  // Call is a recv
#define IO_FLAG_NO_FILTER       0x00000100  // Don't go through filters
#define IO_FLAG_AND_RECV        0x00000400  // Add recv operation to IO
#define IO_FLAG_NO_RECV         0x00000800  // Don't do auto-recv after TransmitFile
#define IO_FLAG_NO_DELAY        0x00001000  // Disable Nagling on the socket 


// Flags for header generation

#define HTTPH_SEND_GLOBAL_EXPIRE    0x00000001
#define HTTPH_NO_DATE               0x00000002
#define HTTPH_NO_CONNECTION         0x00000004
#define HTTPH_NO_CUSTOM             0x00000008

#define MIN_BUFFER_SIZE_FOR_HEADERS 384
#define MAX_CUSTOM_ERROR_FILE_SIZE  (48 * 1024)

#define MD_AUTH_ALL     (MD_AUTH_ANONYMOUS|MD_AUTH_BASIC|MD_AUTH_MD5|MD_AUTH_MAPBASIC)

#define MAX_CERT_FIELD_SIZE             4096

#define MAX_ALLOW_SIZE (sizeof("Allow: OPTIONS, TRACE, PUT, DELETE, HEAD, GET\r\n") - 1)

#define MAX_URI_LENGTH  255

//
// Back trace configuration
//

#define MAX_BACKTRACE_FRAMES            10

/************************************************************
 *   Type Definitions
 ************************************************************/

enum HTTP_VERB
{
    HTV_GET = 0,
    HTV_HEAD,
    HTV_TRACE,
    HTV_PUT,
    HTV_DELETE,
    HTV_TRACECK,
    HTV_POST,
    HTV_OPTIONS,
    HTV_UNKNOWN
};

//
// Class of a custom error entry.
//
class CUSTOM_ERROR_ENTRY
{
public:

    CUSTOM_ERROR_ENTRY( DWORD   dwErr,
                        DWORD   dwSubError,
                        BOOL    bWildcard,
                        CHAR    *pszPath,
                        BOOL    bFileError
                       )
    {
        m_dwErr = dwErr;
        m_dwSubError = dwSubError;
        m_bIsFileError = bFileError;
        m_bIsWildcard = bWildcard;

        if (bFileError)
        {
            m_pszNames.ErrorFileName = pszPath;
        }
        else
        {
            m_pszNames.ErrorURL = pszPath;
        }
    }

    ~CUSTOM_ERROR_ENTRY( VOID )
    {
        CHAR        *pszTemp;

        if (m_bIsFileError)
        {
            pszTemp = m_pszNames.ErrorFileName;
        }
        else
        {
            pszTemp = m_pszNames.ErrorURL;
        }

        if (pszTemp != NULL)
        {
            TCP_FREE(pszTemp);
        }
    }

    BOOL                IsFileError( VOID )
        { return m_bIsFileError; }

    CHAR                *QueryErrorFileName( VOID )
        { return m_pszNames.ErrorFileName; }

    CHAR                *QueryErrorURL( VOID )
        { return m_pszNames.ErrorURL; }

    DWORD               QueryError( VOID )
        { return m_dwErr; }

    DWORD               QuerySubError( VOID )
        { return m_dwSubError; }

    DWORD               QueryWildcard( VOID )
        { return m_bIsWildcard; }

    LIST_ENTRY          _ListEntry;

private:
    BOOL                m_bIsFileError;
    BOOL                m_bIsWildcard;
    DWORD               m_dwErr;
    DWORD               m_dwSubError;
    union
    {
        CHAR            *ErrorFileName;
        CHAR            *ErrorURL;

    } m_pszNames;
};

typedef CUSTOM_ERROR_ENTRY  *PCUSTOM_ERROR_ENTRY; 

//
// The structure of the server's pre-digested meta data.
//

#define W3MD_CREATE_PROCESS_AS_USER     0x00000001
#define W3MD_CREATE_PROCESS_NEW_CONSOLE 0x00000002

#define EXPIRE_MODE_NONE                0
#define EXPIRE_MODE_STATIC              1
#define EXPIRE_MODE_DYNAMIC             2
#define EXPIRE_MODE_OFF                 3

class W3_METADATA : public COMMON_METADATA {

public:

    //
    //  Hmmm, since most of these values aren't getting initialized, if
    //  somebody went and deleted all the metadata items from the tree, then
    //  bad things could happen.  We should initialize with defaults things
    //  that might mess us
    //

    W3_METADATA(VOID) :
          m_dwAuthentication    ( MD_AUTH_ANONYMOUS ),
          m_dwAuthenticationPersistence( MD_AUTH_SINGLEREQUESTIFPROXY ),
          m_fAnyExtAllowedOnReadDir( FALSE ),
          m_pRBlob              ( NULL ),
          m_dwFooterLength      ( 0 ),
          m_pszFooter           ( NULL ),
          m_bFooterEnabled      ( TRUE ),
          m_bHaveNoCache        ( FALSE ),
          m_bHaveMaxAge         ( FALSE ),
          m_bSSIExecDisabled    ( FALSE ),
          m_dwCGIScriptTimeout  ( DEFAULT_SCRIPT_TIMEOUT ),
          m_csecPoolIDCTimeout  ( 0 ),
          m_dwCreateProcessFlags( W3MD_CREATE_PROCESS_AS_USER ),
          m_fAllowKeepAlives    ( TRUE ),
          m_fCacheISAPIApps     ( TRUE ),
          m_fDoReverseDns       ( FALSE ),
          m_dwExpireMaxLength   ( 0 ),
          m_dwExpireMode        ( EXPIRE_MODE_NONE ),
          m_pWildcardMapping    ( NULL ),
          m_dwNotifyExAuth      ( 0 ),
          m_pszCCPointer        ( NULL ),
          m_dwUploadReadAhead   (DEFAULT_W3_UPLOAD_READ_AHEAD),
          m_dwPutReadSize       (8192),
#if defined(CAL_ENABLED)
          m_dwCalHnd            ( INVALID_CAL_EXEMPT_HANDLE ),
#endif
          m_dwDirBrowseFlags    ( MD_DIRBROW_LOADDEFAULT ),
          m_fJobCGIEnabled      ( FALSE ),
          m_fIgnoreTranslate    ( FALSE ),
          m_fUseDigestSSP       ( FALSE ),
          m_dwMaxExtLen         (0)
        {
            InitializeListHead( &m_ExtMapHead );
            InitializeListHead( &m_CustomErrorHead );

            memset( m_apszNTProviders, 0, sizeof(m_apszNTProviders) );

            if ( g_fIsWindows95 )
            {
                m_dwCreateProcessFlags &= ~W3MD_CREATE_PROCESS_AS_USER;
            }

        }

    ~W3_METADATA(VOID)
        {
            DWORD i = 0;

            DestroyCustomErrorTable();
            TerminateExtMap();

            if (m_pRBlob != NULL )
            {
                delete m_pRBlob;
                m_pRBlob = NULL;
            }

            while ( m_apszNTProviders[i] )
            {
                TCP_FREE( m_apszNTProviders[i++] );
            }

#if defined(CAL_ENABLED)
            if ( m_dwCalHnd != INVALID_CAL_EXEMPT_HANDLE )
            {
                CalExemptRelease( m_dwCalHnd );
            }
#endif
        }

    BOOL HandlePrivateProperty(
            LPSTR                   pszURL,
            PIIS_SERVER_INSTANCE    pInstance,
            METADATA_GETALL_INTERNAL_RECORD  *pMDRecord,
            LPVOID                  pDataPointer,
            BUFFER                  *pBuffer,
            DWORD                   *pdwBytesUsed,
            PMETADATA_ERROR_INFO    pMDErrorInfo
            );

    BOOL FinishPrivateProperties(
            BUFFER                  *pBuffer,
            DWORD                   dwBytesUsed,
            BOOL                    bSucceeded
            );

    //
    //  Query Methods
    //

    STR * QueryDefaultDocs( VOID )
        { return &m_strDefaultDocs; }

    STR * QueryHeaders( VOID )
        { return &m_strHeaders; }

    BUFFER * QueryMimeMap( VOID )
        { return &m_bufMimeMap; }

    DWORD QueryAuthentication( VOID ) const
        { return m_dwAuthentication; }

    DWORD QueryAuthenticationPersistence( VOID ) const
        { return m_dwAuthenticationPersistence; }

    DWORD QueryScriptTimeout( VOID ) const
        { return m_dwCGIScriptTimeout; }

    DWORD QueryDirBrowseFlags( VOID ) const
        { return m_dwDirBrowseFlags; }

    BOOL  LookupExtMap(
        IN  const CHAR *   pchExt,
        IN  BOOL           fNoWildcards,
        OUT STR *          pstrGatewayImage,
        OUT GATEWAY_TYPE * pGatewayType,
        OUT DWORD *        pcchExt,
        OUT BOOL *         pfImageInURL,
        OUT BOOL *         pfVerbExcluded,
        OUT DWORD *        pdwFlags,
        IN  const CHAR     *pszVerb,
        IN  enum HTTP_VERB Verb,
        IN OUT PVOID *     ppvExtMapInfo
        );

    PTCP_AUTHENT_INFO QueryAuthentInfo(VOID) const
        { return (const PTCP_AUTHENT_INFO) &m_TCPAuthentInfo; }

    BOOL
    BuildProviderList(
        CHAR            *pszProviders
        );

    BOOL
    CheckSSPPackage(
        IN LPCSTR pszAuthString
        );

    PCHAR QueryRealm(VOID) const
        { return (m_strRealm.IsEmpty() ? NULL : m_strRealm.QueryStr()); }

    DWORD QueryCreateProcessAsUser(VOID) const
        { return (m_dwCreateProcessFlags & W3MD_CREATE_PROCESS_AS_USER); }

    DWORD QueryCreateProcessNewConsole(VOID) const
        { return (m_dwCreateProcessFlags & W3MD_CREATE_PROCESS_NEW_CONSOLE); }

    BOOL QueryAnyExtAllowedOnReadDir() const
        { return m_fAnyExtAllowedOnReadDir; }

    PREDIRECTION_BLOB QueryRedirectionBlob(VOID) const
        { return m_pRBlob; }

    dllexp
    PCUSTOM_ERROR_ENTRY LookupCustomError( DWORD dwErr, DWORD dwSubError )
    {
        LIST_ENTRY          *pEntry;
        PCUSTOM_ERROR_ENTRY pCustomErrorItem;
        PCUSTOM_ERROR_ENTRY pCustomErrorWildcard = NULL;

        for ( pEntry  = m_CustomErrorHead.Flink;
              pEntry != &m_CustomErrorHead;
              pEntry  = pEntry->Flink )
        {
            pCustomErrorItem = CONTAINING_RECORD(   pEntry,
                                                    CUSTOM_ERROR_ENTRY,
                                                    _ListEntry );

            if ( pCustomErrorItem->QueryError() == dwErr )
            {
                if ( pCustomErrorItem->QuerySubError() == dwSubError )
                {
                    return pCustomErrorItem;
                }
                else if ( pCustomErrorItem->QueryWildcard() )
                {
                    pCustomErrorWildcard = pCustomErrorItem;
                }
            }
        }

        return pCustomErrorWildcard;

    }

    DWORD QueryFooterLength(VOID) const
        { return m_dwFooterLength; }

    CHAR  *QueryFooter(VOID) const
        { return m_pszFooter; }

    BOOL  FooterEnabled(VOID) const
        { return m_bFooterEnabled; }

    BOOL  SSIExecDisabled(VOID) const
        { return m_bSSIExecDisabled; }

    DWORD QueryPoolIDCTimeout( VOID ) const
        { return m_csecPoolIDCTimeout; }

    const LPSTR * QueryNTProviders( VOID ) const
        { return m_apszNTProviders; }

    BOOL QueryKeepAlives( VOID ) const
        { return m_fAllowKeepAlives; }

    BOOL QueryCacheISAPIApps( VOID ) const
        { return m_fCacheISAPIApps; }

    BOOL QueryDoReverseDns(VOID) const
        { return m_fDoReverseDns; }

    DWORD QueryExpireMaxLength(VOID) const
        { return m_dwExpireMaxLength;}

    DWORD QueryExpireDelta(VOID) const
        { return m_dwExpireDelta;}

    DWORD QueryExpireMode(VOID) const
        { return m_dwExpireMode;}

    LPSTR QueryExpireHeader(VOID) const
        { return m_strExpireHeader.QueryStr();}

    DWORD QueryExpireHeaderLength(VOID) const
        { return m_strExpireHeader.QueryCCH();}

    LARGE_INTEGER QueryExpireTime(VOID) const
        { return m_liExpireTime;}

    PVOID QueryWildcardMapping(VOID) const
        { return m_pWildcardMapping; }

    DWORD QueryNotifyExAuth(VOID) const
        { return m_dwNotifyExAuth; }

    BOOL QueryConfigNoCache(VOID) const
        { return m_bHaveNoCache; }

    BOOL QueryHaveMaxAge(VOID) const
        { return m_bHaveMaxAge; }

    LPSTR QueryCacheControlHeader(VOID) const
        { return m_strCacheControlHeader.QueryStr(); }

    DWORD QueryCacheControlHeaderLength(VOID) const
        { return m_strCacheControlHeader.QueryCB(); }

    STR * QueryRedirectHeaders( VOID )
        { return &m_strRedirectHeaders; }

    DWORD QueryUploadReadAhead(VOID) const
        { return m_dwUploadReadAhead;  }

    DWORD QueryPutReadSize(VOID) const
        { return m_dwPutReadSize;  }

    BOOL QueryJobCGIEnabled()
        { return m_fJobCGIEnabled; }

    BOOL QueryIgnoreTranslate() const
        { return m_fIgnoreTranslate; }

    BOOL QueryUseDigestSSP() const
        { return m_fUseDigestSSP; }

    //
    //  Set Methods
    //

    BOOL SetAnonUserName(PCHAR AnonUserName)
        { return m_TCPAuthentInfo.strAnonUserName.Copy( AnonUserName ); }

    BOOL SetAnonUserPassword(PCHAR AnonUserPassword)
        { return m_TCPAuthentInfo.strAnonUserPassword.Copy( AnonUserPassword ); }

    BOOL SetDefaultLogonDomain(PCHAR DefLogonDom)
        { return m_TCPAuthentInfo.strDefaultLogonDomain.Copy( DefLogonDom ); }

    VOID SetLogonMethod(DWORD dwLogonMethod)
        { m_TCPAuthentInfo.dwLogonMethod = dwLogonMethod; }

    VOID SetUseAnonSubAuth( BOOL fUseAnonSubAuth )
        { m_TCPAuthentInfo.fDontUseAnonSubAuth = !fUseAnonSubAuth; }

    VOID SetAuthentication( DWORD dwFlags )
        {
            if (g_fIsWindows95)
            {
                dwFlags &= INET_INFO_AUTH_W95_MASK;
            }
            m_dwAuthentication = dwFlags;
        }

    VOID SetAuthenticationPersistence( DWORD dwFlags )
        {
            m_dwAuthenticationPersistence = dwFlags;
        }

    VOID SetCGIScriptTimeout( DWORD dwScriptTimeout )
        { m_dwCGIScriptTimeout = dwScriptTimeout; }

    VOID SetDirBrowseFlags( DWORD dwDirBrowseFlags )
        { m_dwDirBrowseFlags = dwDirBrowseFlags; }

    BOOL BuildExtMap(CHAR *pszExtMapString);

    BOOL SetRealm(PCHAR pszRealm)
        { return m_strRealm.Copy( pszRealm ); }

    VOID SetCreateProcessAsUser(BOOL fValue)
        {
            if ( fValue )
            {
                if ( !g_fIsWindows95 ) {
                    m_dwCreateProcessFlags |= W3MD_CREATE_PROCESS_AS_USER;
                }
            }
            else
            {
                m_dwCreateProcessFlags &= ~W3MD_CREATE_PROCESS_AS_USER;
            }
        }

    VOID SetCreateProcessNewConsole(BOOL fValue)
        {
            if ( fValue )
            {
                m_dwCreateProcessFlags |= W3MD_CREATE_PROCESS_NEW_CONSOLE;
            }
            else
            {
                m_dwCreateProcessFlags &= ~W3MD_CREATE_PROCESS_NEW_CONSOLE;
            }
        }

    BOOL SetRedirectionBlob( STR & strSource,
                             STR & strDestination )
        {
            //
            // If the redirection is nullified, don't allocate a blob
            // and just return success.
            //

            if ( *( strDestination.QueryStr() ) == '!' )
            {
                return TRUE;
            }
            m_pRBlob = new REDIRECTION_BLOB( strSource, strDestination );
            if (m_pRBlob == NULL)
            {
                return FALSE;
            }
            return m_pRBlob->IsValid();
        }

    BOOL BuildCustomErrorTable( CHAR *pszErrorList,
                                PMETADATA_ERROR_INFO    pMDErrorInfo
                                );

    VOID DestroyCustomErrorTable( VOID );

    BOOL ReadCustomFooter(  CHAR *pszFooterString,
                            TSVC_CACHE &Cache,
                            HANDLE User,
                            PMETADATA_ERROR_INFO    pMDErrorInfo
                            );

    VOID SetFooter(DWORD dwLength, CHAR *pszFooter)
        { m_dwFooterLength = dwLength; m_pszFooter = pszFooter; }

    VOID SetFooterEnabled(BOOL bEnabled)
        { m_bFooterEnabled = bEnabled; }

    VOID SetSSIExecDisabled( BOOL bDisabled )
        { m_bSSIExecDisabled = bDisabled; }

    VOID SetPoolIDCTimeout( DWORD csecPoolIDCTimeout )
        { m_csecPoolIDCTimeout = csecPoolIDCTimeout; }

    VOID SetAllowKeepAlives( BOOL fAllowKeepAlives )
        { m_fAllowKeepAlives = fAllowKeepAlives; }

    VOID SetCacheISAPIApps( BOOL fCacheISAPIApps )
        { m_fCacheISAPIApps = fCacheISAPIApps; }

    BOOL SetExpire( CHAR*   pszExpire,
                    PMETADATA_ERROR_INFO    pMDErrorInfo
                    );

    VOID SetWildcardMapping(PVOID pMapping)
        { m_pWildcardMapping = pMapping; }

    VOID SetConfigNoCache(VOID)
        { m_bHaveNoCache = TRUE; }

    VOID SetHaveMaxAge(VOID)
        { m_bHaveMaxAge = TRUE; }

    VOID ClearConfigNoCache(VOID)
        { m_bHaveNoCache = FALSE; }

    VOID ClearHaveMaxAge(VOID)
        { m_bHaveMaxAge = FALSE; }

    BOOL
    SetCCHeader( BOOL           bNoCache,
                BOOL            bMaxAge,
                DWORD           dwMaxAge
                );

    VOID SetUploadReadAhead(DWORD dwUploadSize)
        { m_dwUploadReadAhead = dwUploadSize;  }

    VOID SetPutReadSize(DWORD dwSize)
        { m_dwPutReadSize = dwSize;  }

    //
    // Disable job objects on IIS5.1, original code would read the 
    // property from metabase
    //
    VOID SetJobCGIEnabled( BOOL f ) { m_fJobCGIEnabled = FALSE; }

    VOID SetIgnoreTranslate( BOOL f ) { m_fIgnoreTranslate = f; }

    VOID SetUseDigestSSP( BOOL f ) { m_fUseDigestSSP = f; }

private:
    VOID TerminateExtMap( VOID );
    TCP_AUTHENT_INFO    m_TCPAuthentInfo;
    STR                 m_strDefaultDocs;
    STR                 m_strHeaders;
    BUFFER              m_bufMimeMap;
    STR                 m_strRealm;
    DWORD               m_dwAuthentication;
    DWORD               m_dwAuthenticationPersistence;
    DWORD               m_dwCGIScriptTimeout;
    DWORD               m_dwDirBrowseFlags;
    DWORD               m_dwCreateProcessFlags;
    LIST_ENTRY          m_ExtMapHead;
    LIST_ENTRY          m_CustomErrorHead;
    PREDIRECTION_BLOB   m_pRBlob;
    DWORD               m_dwFooterLength;
    CHAR                *m_pszFooter;
    BUFFER              m_bufFooter;

    BOOL                m_fAnyExtAllowedOnReadDir:1;
    BOOL                m_bFooterEnabled:1;
    BOOL                m_bHaveNoCache:1;
    BOOL                m_bHaveMaxAge:1;

    BOOL                m_bSSIExecDisabled:1;
    BOOL                m_fAllowKeepAlives:1;
    BOOL                m_fCacheISAPIApps:1;
    BOOL                m_fDoReverseDns:1;

    DWORD               m_csecPoolIDCTimeout;
    LPSTR               m_apszNTProviders[MAX_SSPI_PROVIDERS];
    STR                 m_strExpireHeader;
    STR                 m_strCacheControlHeader;
    DWORD               m_dwExpireMaxLength;
    DWORD               m_dwExpireMode;
    DWORD               m_dwExpireDelta;
    LARGE_INTEGER       m_liExpireTime;
    PVOID               m_pWildcardMapping;
    DWORD               m_dwNotifyExAuth;
    LPSTR               m_pszCCPointer;
    STR                 m_strRedirectHeaders;
    DWORD               m_dwUploadReadAhead;
    DWORD               m_dwPutReadSize;
    BOOL                m_fJobCGIEnabled;
#if defined(CAL_ENABLED)
    DWORD               m_dwCalHnd;
#endif

    DWORD               m_dwMaxExtLen;
    BOOL                m_fIgnoreTranslate;
    BOOL                m_fUseDigestSSP;
};

typedef W3_METADATA *PW3_METADATA;

typedef struct _W3_METADATA_INFO
{

    DWORD                   dwMaxAge;

} W3_METADATA_INFO, *PW3_METADATA_INFO;


//
//  Various states the HTTP Request goes through
//

enum HTR_STATE
{
    //
    //  We're still gathering the client request header
    //

    HTR_READING_CLIENT_REQUEST = 0,

    //
    //  The client is supplying some gateway data, deal with it
    //

    HTR_READING_GATEWAY_DATA,

    //
    //  We need to take apart the client request and figure out what they
    //  want
    //

    HTR_PARSE,

    //
    //  We're executing the verb or handing the request off to a gateway
    //

    HTR_DOVERB,

    //
    //  The ISAPI application has submitted async IO operation
    //

    HTR_GATEWAY_ASYNC_IO,

    //
    //  The client requested a file so send them the file
    //

    HTR_SEND_FILE,

    //
    //  The proxy server is forwarding the request on to the remote server
    //

    HTR_PROXY_SENDING_REQUEST,

    //
    //  The proxy server is waiting for a response from the remote server
    //

    HTR_PROXY_READING_RESPONSE,

    //
    //  We're processing a CGI request so we need to ignore any IO
    //  completions that may occur as the CGIThread forwards the
    //  program's output
    //

    HTR_CGI,

    //
    //  Processing a range request
    //

    HTR_RANGE,

    //
    //  resume processing with clear text logon
    //

    HTR_RESTART_REQUEST,


    //
    //  We're in the process of writing data from a client PUT request to
    //  disk
    //

    HTR_WRITING_FILE,

    //
    //  We're renegotiating a certificate with the client
    //

    HTR_CERT_RENEGOTIATE,
    
    //
    //  We're reading the entity body before doing redirect
    //
    
    HTR_REDIRECT,

    //
    //  We're reading the entity body before sending access denial
    //
    
    HTR_ACCESS_DENIED,

    //
    //  We've completely handled the client's request
    //
    
    HTR_DONE
};


enum CHUNK_STATE
{
    READ_CHUNK_SIZE = 0,
    READ_CHUNK_PARAMS,
    READ_CHUNK,
    READ_CHUNK_FOOTER,
    READ_CHUNK_CRLF,
    READ_CHUNK_DONE
};

#if 0   // This routine is no longer used /SAB
#define IS_WRITE_VERB(__verb__) ( (__verb__) == HTV_PUT || \
                                  (__verb__) == HTV_DELETE)
#endif 0

#define CHUNK_READ_SIZE     80          // Important to keep this small, to
                                        // avoid getting two chunks into the
                                        // same buffer in one read.

#define CRLF_SIZE           2

#define SSLNEGO_MAP         0x00000001

/*******************************************************************

    CLASS:      HTTP_REQ_BASE

    SYNOPSIS:   Basic HTTP request object


    HISTORY:
        Johnl       24-Aug-1994 Created

********************************************************************/

class HTTP_REQ_BASE
{
public:

    //
    //  Constructor/Destructor
    //

    HTTP_REQ_BASE( CLIENT_CONN * pClientConn,
                   PVOID         pvInitialBuff,
                   DWORD         cbInitialBuff );

    virtual ~HTTP_REQ_BASE( VOID );

    //
    //  This is the work entry point that is driven by the completion of the
    //  async IO.
    //

    virtual BOOL DoWork( BOOL * pfFinished ) = 0;

    //
    //  Parses the client's HTTP request
    //

    virtual BOOL Parse( const CHAR*   pchRequest,
                        DWORD         cbData,
                        DWORD *       pcbExtraData,
                        BOOL *        pfHandled,
                        BOOL *        pfFinished ) = 0;


    // Following function can be overridden by individual derived object.
    virtual dllexp BOOL GetInfo( const TCHAR * pszValName,
                                 STR *         pstr,
                                 BOOL *        pfFound = NULL )
      { if ( pfFound )
        {
             *pfFound = FALSE;
        }

        return (TRUE);
      }

    //
    //  Kicks off the read for a client request header
    //

    BOOL StartNewRequest( PVOID  pvInitialBuff,
                          DWORD  cbInitialBuff,
                          BOOL   fFirst,
                          BOOL   *pfDoAgain);


    BOOL OnFillClientReq( BOOL * pfCompleteRequest,
                          BOOL * pfFinished,
                          BOOL * pfHandled );

    BOOL OnCompleteRequest( TCHAR * pchRequest,
                            DWORD   cbData,
                            BOOL *  pfFinished,
                            BOOL *  pfHandled );

    BOOL OnRestartRequest( TCHAR * pchRequest,
                            DWORD   cbData,
                            BOOL *  pfFinished,
                            BOOL *  pfHandled);

    BOOL HandleCertRenegotiation( BOOL * pfFinished,
                                  BOOL * pfHandled,
                                  DWORD cbData );

    BOOL DenyAccess( BOOL * pfFinished,
                     BOOL * pfDisconnected );

    BOOL VrootAccessCheck( PW3_METADATA pMetaData,
                           DWORD dwDesiredAccess );

    BOOL DoChange( LPBOOL );

    BOOL UnWrapRequest( BOOL * pfCompleteRequest,
                        BOOL * pfFinished,
                        BOOL * pfHandled );

    //
    //  Attempts to logon with the user information gleaned from the Parse
    //  we just did
    //

    BOOL LogonUser( BOOL * pfFinished );

    BOOL LogonAsSystem( VOID );
    //
    //  Common header parsing functions.
    //

    BOOL OnContentLength ( CHAR * pszValue );
    BOOL OnIfModifiedSince( CHAR * pszValue );
    BOOL OnIfUnmodifiedSince( CHAR * pszValue );
    BOOL OnIfMatch( CHAR * pszValue );
    BOOL OnIfNoneMatch( CHAR * pszValue );
    BOOL OnIfRange( CHAR * pszValue );
    BOOL OnUnlessModifiedSince( CHAR * pszValue );
    BOOL ProcessAuthorization ( CHAR * pszValue );
    BOOL OnProxyAuthorization ( CHAR * pszValue );
    BOOL OnHost ( CHAR * pszValue );
    BOOL OnRange ( CHAR * pszValue );

    //BOOL OnAuthorization ( CHAR * pszValue );

    BOOL ParseAuthorization( CHAR * pszValue );

    //
    //  Builds and optionally sends an HTTP server response back to the client
    //

    static BOOL BuildStatusLine(  BUFFER *       pstrResp,
                                  DWORD          dwHTTPError,
                                  DWORD          dwError2,
                                  LPSTR          pszError2 = NULL,
                                  STR            *pstrErrorStr = NULL
                                  );

    //
    //  Builds a complete HTTP reply with extended explanation text
    //

    static BOOL BuildExtendedStatus(
        STR   *        pstrResp,
        DWORD          dwHTTPError,
        DWORD          dwError2      = NO_ERROR,
        DWORD          dwExplanation = 0,
        LPSTR          pszError2 = NULL
        );

    //
    //  Sets the http status code and win32 error that should be used for
    //  this request when it gets written to the logfile
    //

    VOID SetLogStatus( DWORD LogHttpResponse, DWORD LogWinError )
    {
        _dwLogHttpResponse = LogHttpResponse;
        _dwLogWinError     = LogWinError;
    }

    DWORD QueryLogHttpResponse( VOID ) const
        { return _dwLogHttpResponse; }

    DWORD QueryLogWinError( VOID ) const
        { return _dwLogWinError; }

    //
    //  Builds a server header for responding back to the client
    //

    BOOL BuildBaseResponseHeader(
        BUFFER * pbufResponse,
        BOOL *   pfFinished,
        STR *    pstrStatus = NULL,             // Full status string
        DWORD    dwOptions = 0 );

    BOOL BuildHttpHeader( OUT BOOL * pfFinished,
                          IN  CHAR * pchStatus = NULL,
                          IN  CHAR * pchAdditionalHeaders = NULL,
                          IN  DWORD  dwOptions = 0);

    dllexp
    BOOL SendHeader( IN  CHAR * pchStatus OPTIONAL,
                     IN  CHAR * pchAdditionalHeaders OPTIONAL,
                     IN  DWORD  IOFlags,
                     OUT BOOL * pfFinished,
                     IN  DWORD  dwOptions = 0,
                     IN  BOOL   fWriteHeader = TRUE );

    BOOL SendHeader( IN  CHAR * pchHeaders,
                     IN  DWORD  cbHeaders,
                     IN  DWORD  IOFlags,
                     OUT BOOL * pfFinished );

    //
    //  Builds a 301 or 302 URL Moved message
    //

    dllexp
    BOOL BuildURLMovedResponse( BUFFER *    pbufResp,
                                STR *       pstrURL,
                                DWORD       dwServerCode,
                                BOOL        fIncludeParams = FALSE );

    dllexp
    BOOL WriteLogRecord( VOID );

    BOOL AppendLogParameter( CHAR * pszParam );

    //
    //  Sends an access denied message with the forms of authorization
    //  we support
    //

    BOOL SendAuthNeededResp( BOOL * pfFinished );

    BOOL SetUserNameAndPassword( TCHAR * pszUserName, TCHAR * pszPassword )
        { return _strUserName.Copy( pszUserName ) && _strPassword.Copy( pszPassword ); }

    STR * QueryDenialHeaders( VOID )
        { return &_strDenialHdrs; }

    STR * QueryAdditionalRespHeaders( VOID )
        { return &_strRespHdrs; }

    DWORD QueryAuthentication( VOID ) const
        { return _pMetaData->QueryAuthentication(); }

    DWORD QueryNotifyExAuth( VOID ) const
        { return _pMetaData->QueryNotifyExAuth(); }

    DWORD QueryDirBrowseFlags( VOID ) const
        { return _pMetaData->QueryDirBrowseFlags(); }

    BOOL IsIpDnsAccessCheckPresent( VOID ) const
        { return _pMetaData->IsIpDnsAccessCheckPresent(); }

    PW3_METADATA QueryMetaData( VOID ) const
            { return _pMetaData; }
    //
    //  Retrieves various bits of request information
    //

    enum HTR_STATE QueryState( VOID ) const
        { return _htrState; }

    BOOL IsKeepConnSet( VOID ) const
        { return _fKeepConn; }

    BOOL IsProcessByteRange( VOID ) const
        { return _fProcessByteRange; }

    BOOL IsAuthenticationRequested( VOID ) const
        { return _fAuthenticationRequested; }

    BOOL IsAuthenticated( VOID ) const
        { return !_strUserName.IsEmpty(); }

    DWORD IsChunked( VOID ) const
        { return _fChunked; }

    VOID SetChunked( VOID )
        { _fChunked = TRUE; }

    VOID ClearChunked( VOID )
        { _fChunked = FALSE; }

    VOID SetKeepConn( BOOL fKeepConn )
        { _fKeepConn = fKeepConn; }

    VOID SetAuthenticationRequested( BOOL fAuthenticationRequested )
        { _fAuthenticationRequested = fAuthenticationRequested; }

    BOOL IsLoggedOn( VOID ) const
        { return _fLoggedOn; }

    BOOL IsClearTextPassword( VOID ) const
        { return _fClearTextPass; };

    BOOL IsNTLMImpersonation( VOID ) const
        { return !_fClearTextPass && !_fAnonymous && !UseVrAccessToken(); }

    BOOL IsSecurePort( VOID ) const
        { return _fSecurePort; }

    BOOL IsProxyRequest( VOID ) const
        { return _fProxyRequest; }

    VOID SetProxyRequest( BOOL fIsProxyRequest )
        { _fProxyRequest = fIsProxyRequest; }

    BOOL IsClientProxy( VOID );

    CLIENT_CONN * QueryClientConn( VOID ) const
        { return _pClientConn; }

    W3_SERVER_INSTANCE * QueryW3Instance( VOID ) const
        { return _pW3Instance; }

    W3_SERVER_INSTANCE * QueryW3InstanceAggressively( VOID ) const;

    VOID SetW3Instance( IN W3_SERVER_INSTANCE* pInstance )
        { DBG_ASSERT(_pW3Instance == NULL); _pW3Instance = pInstance; }

    W3_SERVER_STATISTICS * QueryW3StatsObj( VOID ) const
        { return _pW3Stats; }

    VOID SetW3StatsObj( IN LPW3_SERVER_STATISTICS pW3Stats )
        { _pW3Stats = pW3Stats; }

    BOOL IsPointNine( VOID ) const
        { return (_VersionMajor < 1); }

    BOOL IsAtLeastOneOne( VOID ) const
        { return ((_VersionMajor == 1 && _VersionMinor >= 1) ||
            (_VersionMajor >= 2)); }

    BOOL IsOneOne( VOID ) const
        { return ((_VersionMajor == 1) && (_VersionMinor == 1)); }

    BOOL IsAuthenticating( VOID ) const
        { return _fAuthenticating; }

    DWORD QueryClientContentLength( VOID ) const
        { return _cbContentLength; }

    DWORD QueryTotalRequestLength( VOID ) const
        { return _cbContentLength + _cbClientRequest; }

    BYTE * QueryClientRequest( VOID ) const
        { return (BYTE *) _bufClientRequest.QueryPtr(); }

    BUFFER * QueryClientReqBuff( VOID )
        { return &_bufClientRequest; }

    CHAR * QueryURL( VOID ) const
        { return _strURL.QueryStr(); }

    CHAR * QueryURLParams( VOID ) const
        { return _strURLParams.QueryStr(); }

    HTTP_HEADERS * QueryHeaderList( VOID )
        { return &_HeaderList; }

    BUFFER * QueryRespBuf( VOID )
        { return &_bufServerResp; }

    CHAR * QueryRespBufPtr( VOID )
        { return (CHAR *) _bufServerResp.QueryPtr(); }

    DWORD QueryRespBufCB( VOID )
        { return strlen( (CHAR *)_bufServerResp.QueryPtr()); }

    VOID SetDeniedFlags( DWORD dwDeniedFlags )
        { _Filter.SetDeniedFlags( dwDeniedFlags ); }

    CHAR * QueryHostAddr( VOID );

    //
    //  If the client supplied additional data in their request, we store
    //  the byte count and data here.
    //

    DWORD QueryEntityBodyCB( VOID ) const
        { return _cbEntityBody; }

    DWORD QueryTotalEntityBodyCB( VOID ) const
            { return _cbTotalEntityBody; }

    VOID AddTotalEntityBodyCB( DWORD cbAdditionalEntityBody )
        { _cbTotalEntityBody += cbAdditionalEntityBody; }

    BYTE * QueryEntityBody( VOID ) const
        { return (BYTE *) _bufClientRequest.QueryPtr() + _cbClientRequest; }

    BOOL ReadMoreEntityBody(DWORD   cbOffset,
                            DWORD   cbSize);

    BOOL ReadEntityBody( BOOL *pfDone,
                          BOOL  fFirstRead = FALSE,
                          DWORD dwMaxAmountToRead = 0,
                          BOOL *pfDisconnected = NULL );

    BOOL DecodeChunkedBytes( LPBYTE lpBuffer,
                             LPDWORD pnBytes );

    BOOL IsChunkedReadComplete( ) {
        return ( _ChunkState == READ_CHUNK_DONE );
    }

    //
    //  IO Status stuff
    //

    VOID SetLastCompletionStatus( DWORD BytesWritten,
                                  DWORD CompletionStatus )
    { 
        _cbBytesWritten = BytesWritten; 
        _status         = CompletionStatus;

        //
        // Do accounting for async sends so that the total bytes matches
        // the number actually sent to they client.
        // 
        // TODO: If the client disconnects then the io completion may
        // complete with an error even the data was successfully sent.
        // This appears to be an issue with TCP, but requires further
        // investigation. (taylorw)
        //

        if ( _fAsyncSendPosted )
        {
            _cbBytesSent += BytesWritten;
            _fAsyncSendPosted = FALSE;
        }
    }

    DWORD QueryIOStatus( VOID ) const
        { return _status; }

    DWORD QueryBytesWritten( VOID ) const
        { return _cbBytesWritten; }

    DWORD QueryBytesReceived( VOID ) const
        { return _cbBytesReceived; }

    //
    //  Impersonation related stuff
    //

    BOOL UseVrAccessToken() const
        { return _pMetaData->QueryVrAccessToken() &&
                 (!_pMetaData->QueryVrPassThrough() || !_tcpauth.IsForwardable()); }


    BOOL ImpersonateUser( VOID )
        { return (!UseVrAccessToken() ?
                  _tcpauth.Impersonate() :
                  _pMetaData->ImpersonateVrAccessToken()
                  ); }

    VOID RevertUser( VOID )
        { (!UseVrAccessToken() ?
           _tcpauth.RevertToSelf():
           ::RevertToSelf()
           ); }

    HANDLE QueryPrimaryToken( HANDLE * phDelete );

    HANDLE QueryImpersonationHandle( BOOL fUnused = FALSE )
        { return (UseVrAccessToken() ?
                  _pMetaData->QueryVrAccessToken() :
                  _tcpauth.QueryImpersonationToken() ); }

    HANDLE QueryUserImpersonationHandle( VOID )
        { return _tcpauth.QueryImpersonationToken(); }

    HANDLE QueryVrootImpersonateHandle(VOID) const
        { return UseVrAccessToken() ? _pMetaData->QueryVrAccessToken() : NULL; }

    TCP_AUTHENT * QueryAuthenticationObj( VOID )
        { return &_tcpauth; }

    BOOL IsValid( VOID ) const
        { return _fValid; }

    //
    //  Forwards request to the client connection object
    //

    VOID Disconnect( DWORD htResp   = 0,
                     DWORD dwError2 = NO_ERROR,
                     BOOL  fShutdown= FALSE,
                     LPBOOL pfFinished = NULL );

    dllexp
    BOOL ReadFile( LPVOID  lpBuffer,
                   DWORD   nBytesToRead,
                   DWORD * pcbBytesRead,    // Only for sync reads
                   DWORD   dwFlags = IO_FLAG_ASYNC );

    dllexp
    BOOL WriteFile( LPVOID  lpBuffer,
                    DWORD   nBytesToRead,
                    DWORD * pcbBytesWritten, // Only for sync writes
                    DWORD   dwFlags = IO_FLAG_ASYNC );

    dllexp
    BOOL TestConnection( VOID );

    BOOL TransmitFile( TS_OPEN_FILE_INFO * pOpenFile,
                       HANDLE hFile,
                       DWORD  Offset,
                       DWORD  BytesToWrite,
                       DWORD  dwFlags    = IO_FLAG_ASYNC,
                       PVOID  pHead      = NULL,
                       DWORD  HeadLength = 0,
                       PVOID  pTail      = NULL,
                       DWORD  TailLength = 0);

    BOOL TransmitFileTs( TS_OPEN_FILE_INFO * pOpenFile,
                         DWORD               Offset,
                         DWORD               BytesToWrite,
                         DWORD               dwFlags    = IO_FLAG_ASYNC,
                         PVOID               pHead      = NULL,
                         DWORD               HeadLength = 0,
                         PVOID               pTail      = NULL,
                         DWORD               TailLength = 0);

    BOOL SyncWsaSend( WSABUF *    rgWsaBuffers,
                      DWORD       cWsaBuffers,
                      LPDWORD     pcbWritten );


    BOOL PostCompletionStatus( DWORD cbBytesTransferred );

    DWORD Reference( VOID );
    DWORD Dereference( VOID );
    DWORD QueryRefCount( VOID );

    //
    //  Reset is called at the beginning of every request
    //

    virtual BOOL Reset( BOOL fResetPipelineInfo );
    virtual VOID ReleaseCacheInfo( VOID );


    //
    //  Called to reset Authentication status
    //

    BOOL ResetAuth( BOOL fSessionTerminated = TRUE );

    // added these methods for exposing them to the Server extension processor
    dllexp
    const STR & QueryContentTypeStr( void) const { return ( _strContentType); }
    dllexp
    const STR & QueryMethodStr( void) const { return ( _strMethod); }

    dllexp
    const STR & QueryURLStr(void) const { return ( _strURL); }

    dllexp
    const STR & QueryPhysicalPathStr( void) const { return ( _strPhysicalPath); }

    dllexp
    const LPSTR QueryExpireHeader( void ) const 
        { return ( _pMetaData->QueryExpireHeader() ); }


    //
    //  Called at the beginning and end of a TCP session
    //

    VOID InitializeSession( CLIENT_CONN * pConn,
                            PVOID         pvInitialBuff,
                            DWORD         cbInitialBuff );

    virtual VOID EndOfRequest( VOID ) = 0;
    virtual VOID SessionTerminated( VOID );

    //
    //  Generally when the state is set to HTR_DONE
    //

    VOID SetState( enum HTR_STATE htrstate,
                   DWORD          dwLogHttpResponse = HT_DONT_LOG,
                   DWORD          dwLogWinError = NO_ERROR )
        { _htrState          = htrstate;
          _dwLogHttpResponse = dwLogHttpResponse;
          _dwLogWinError     = dwLogWinError;
        }

    BOOL SetCertificateInfo( PHTTP_FILTER_CERTIFICATE_INFO pData,
                                CtxtHandle* pCtxt,
                                HANDLE hImpersonationToken,
                                HTTP_FILTER_DLL* pFilter );

    BOOL CheckValidSSPILogin( VOID );

    BOOL NotifyRequestSecurityContextClose( CtxtHandle *pH )
        { return _pAuthFilter ? _Filter.NotifyRequestSecurityContextClose( _pAuthFilter,
                                                            pH ) : TRUE; }

    dllexp
    BOOL CheckForBasicAuthenticationHeader( LPSTR pszHeaders );

    BOOL IsAnonymous( VOID ) const
        { return _fAnonymous; }

    HTTP_FILTER * QueryFilter( VOID )
        { return &_Filter; }

    BOOL CheckCustomError(BUFFER *pBuf, DWORD dwErr, DWORD dwSubError,
                    BOOL *pfFinished, DWORD *pdwMsgSize, BOOL bCheckURL = TRUE);

    VOID SetNoCache( VOID )
        { _bForceNoCache = 1; }

    VOID ClearNoCache( VOID )
        { _bForceNoCache = 0; }

    DWORD QueryNoCache( VOID)
        { return _bForceNoCache; }

    VOID SetSendVary( VOID )
        { _bSendVary = 1; }

    VOID ClearSendVary( VOID )
        { _bSendVary = 0; }

    VOID ToggleSendCL( VOID )
        { _bSendContentLocation ^= 1; }

    VOID SetSendCL( VOID )
        { _bSendContentLocation = 1; }

    VOID ClearSendCL( VOID )
        { _bSendContentLocation = 0; }

    BOOL IsCGIRequest( VOID ) const
        { return _GatewayType == GATEWAY_CGI; }

    //
    //  The request looks like a gateway request (but may just be a poorly named
    //  directory)
    //

    BOOL IsProbablyGatewayRequest( VOID ) const
        { return (_GatewayType & GT_GATEWAY_REQUEST); }

    enum HTTP_VERB QueryVerb( VOID ) const
        { return _verb; }


    virtual DWORD BuildAllowHeader(CHAR *pszURL, CHAR *pszTail) = 0;

    //
    // Set the time for start of processing
    //

    VOID SetRequestStartTime( VOID )
        { if (!_fStartTimeValid) {   _msStartRequest= GetCurrentTime(); _fStartTimeValid= TRUE;}}
        
       
    HANDLE GetFileHandle( TS_OPEN_FILE_INFO * pOpenFile )
    {
        HANDLE          hHandle = INVALID_HANDLE_VALUE;
            
        if ( pOpenFile ) 
        {
            if ( ImpersonateUser() )
            {
                hHandle = pOpenFile->QueryFileHandle();
                RevertUser();
            }
        }
        return hHandle;
    }

    VOID IncrementBytesSeenByRawReadFilter( DWORD cbBytesSeen )
    {
        _cbOldData += cbBytesSeen;
    }
        
protected:

    //
    //  Breaks out the simple authorization info
    //

    BOOL ExtractClearNameAndPswd( CHAR *       pch,
                                  STR *        pstrUserName,
                                  STR *        pstrPassword,
                                  BOOL         fUUEncoded );

    //
    //  Appends the forms of authentication the server supports to the
    //  server response string
    //

    BOOL AppendAuthenticationHdrs( STR *    pstrAuthHdrs,
                                   BOOL *   pfFinished );


    //
    //  Data members
    //

    //
    //  Points to connection object we are communicating on
    //

    CLIENT_CONN *           _pClientConn;

    // Meta data info for this request.

    PW3_METADATA            _pMetaData;

    // URI related info (file and metadata) for this request.

    PW3_URI_INFO            _pURIInfo;

    //
    // Points to the w3 instance
    //

    W3_SERVER_INSTANCE *    _pW3Instance;

    //
    // Points to server instance's statistics object.
    //

    W3_SERVER_STATISTICS *  _pW3Stats;

    //
    //  Action the client is requesting
    //

    enum HTTP_VERB  _verb;

    //
    //  Statistics trackers
    //

    DWORD _cFilesSent;
    DWORD _cFilesReceived;
    DWORD _cbBytesSent;             // Total for this request
    DWORD _cbBytesReceived;

    DWORD _cbTotalBytesSent;        // Total for all requests using this
    DWORD _cbTotalBytesReceived;    // object


    //
    //  Flags
    //

    BOOL   _fValid:1;          // TRUE if this object constructed successfully
    BOOL   _fKeepConn:1;       // Pragma: Keep-connection was specified
    BOOL   _fAuthenticationRequested:1;   // request client authentication
    BOOL   _fLoggedOn:1;       // A user was successfully logged on
    BOOL   _fAnonymous:1;      // The user is using the Anonymous user token
    BOOL   _fSecurePort;     // This request is coming over an encrypted port
    BOOL   _fMappedAcct:1;     // The user is using a mapped account
    BOOL   _fClearTextPass:1;  // The user supplied a clear text password
    BOOL   _fAuthenticating:1; // We're in an NT authentication conversation
    BOOL   _fBasicRealm:1;     // TRUE if realm specified
    BOOL   _fAuthSystem:1;
    BOOL   _fAuthCert:1;
    BOOL   _fInvalidAccessToken:1;

    BOOL   _fAsyncSendPosted:1; // TRUE when we send data to the client asychronously

    BOOL   _fChunked:1;        // TRUE iff the entity body is in the chunked
                               // transfer-encoding
    BOOL   _fDiscNoError:1;    // TRUE if we're to disconnect w/o an error.
    BOOL   _fNoDisconnectOnError:1; // TRUE if we're not to disconnect on an early error.

    BOOL   _fProxyRequest:1;   // This is request is a proxy request

    //  Accept range variables

    BOOL   _fAcceptRange:1;      // TRUE if the referenced file accept byte ranges
    BOOL   _fProcessByteRange:1; // TRUE while processing a byte range request
    BOOL   _fUnsatisfiableByteRange:1; // TRUE if an unsatisfiable byte range was encountered
    BOOL   _fMimeMultipart:1;    // TRUE if generating a MIME multipart message
    BOOL   _fIfModifier:1;       // TRUE if we've seen an If-Match, etc.
    BOOL   _fHaveContentLength:1;// Set to TRUE if we've seen a content length
                                 // on this requests.
    BOOL   _fLogRecordWritten:1; // TRUE if we've written a log record
    DWORD  _iRangeIdx;           // index in strRange string
    DWORD  _dwRgNxOffset;        // next range offset
    DWORD  _dwRgNxSizeToSend;    // next range size
    DWORD  _cbMimeMultipart;     // length of a MIME multipart message body

    //
    //  The state of the HTTP request
    //

    enum HTR_STATE _htrState;

    enum GATEWAY_TYPE _GatewayType;   // BGI vs CGI vs BAT

    //
    //  List of raw headers passed by client
    //

    HTTP_HEADERS _HeaderList;

    //
    //  Client protocol version information
    //

    BYTE _VersionMajor;
    BYTE _VersionMinor;

    //
    //  If the client is passing data to a gateway, they will specify
    //  the length and type in a Content-length/type header that is stored
    //  here
    //

    STR  _strContentType;
    UINT _cbContentLength;

    //
    //  The URL the client is requesting
    //

    STR _strURL;                           // Just the URL
    STR _strURLPathInfo;                   // Combined URL and script path info
    STR _strURLParams;                     // Just the params (w/o '?')
    STR _strLogParams;                     // Copy of _strURLParams for logging 
    STR _strPathInfo;                      // Additional script path info
    STR _strRawURL;                        // Combined URL and params
    STR _strOriginalURL;                   // URL before being passed to filters

    //
    //  Various other pieces of data in the HTTP request we care about
    //

    STR _strMethod;                         // GET, HEAD, POST etc.
    STR _strAuthType;                       // "user", "kerberos", "nt" etc.
    STR _strAuthInfo;                       // Current SSP authorization blob
    STR _strUserName;                       // The user name (empty if Guest)
    STR _strPassword;                       // Temporarily holds the password
    STR _strUnmappedUserName;               // User before filter mappings
    STR _strUnmappedPassword;               // Password before filter mappings

    STR _strPhysicalPath;                   // Physical path of URL (maybe empty)
    STR _strUnmappedPhysicalPath;           // unmapped Physical path of URL (maybe empty)

    STR _strRespHdrs;                       // Optional headers from filters
    STR _strDenialHdrs;                     // Optional headers from filters
                                            // to add if request is denied
    STR _strHostAddr;                       // Host address as a domain name
    STR _strRange;

    BOOL _fAuthTypeDigest;                  // is auth type Digest/NT-Digest
    LARGE_INTEGER _liModifiedSince;         // Contains If-Modified-Since time
    LARGE_INTEGER _liUnlessModifiedSince;   // Contains Unless-Modified-Since time
    LARGE_INTEGER _liUnmodifiedSince;       // Contains If-Unmodified-Since time
    DWORD _dwExpireInDay;                   // # of days before pwd expiration
                                            // or 0x7fffffff if n/a
    DWORD _dwModifiedSinceLength;           // Length parameter passed in with IMS.

    BOOL  _bProcessingCustomError:1;        // TRUE if we're processing a custom error.
    BOOL  _bForceNoCache:1;                 // Set to TRUE if must force no-cache.
    BOOL  _bSendContentLocation:1;          // Set to TRUE if we need to send C-L:
    BOOL  _bSendVary:1;                     // Set to TRUE if we need to send Vary: *.

    //
    //  Encapsulates authentication and impersonation code
    //

    BOOL          _fSingleRequestAuth:1;
    TCP_AUTHENT   _tcpauth;

    //
    //  Used to calculate the time of this request
    //

    BOOL    _fStartTimeValid:1;
    DWORD   _msStartRequest;

    //
    //  Filter context information
    //

    HTTP_FILTER   _Filter;
    HTTP_FILTER_DLL * _pAuthFilter;

    //
    //  Contains the HTTP client request buffer
    //  _cbClientRequest indicates the number of bytes in the HTTP request
    //      (excluding gateway data)
    //  _cbOldData - Number of bytes in buffer raw read filters have already
    //      seen
    //  _cbEntityBody - Number of bytes of entity body currently in buffer
    //  _cbTotalEntityBody - Number of bytes expected in entity body.
    //  _cbChunkHeader - Number of bytes in chunk header processed.
    //  _cbChunkBytesRead - Number of bytes in the current transfer-encoded
    //      chunk we've read.
    //  _cbExtraData - Number of 'extra' bytes in buffer.
    //  _pchExtraData - Pointer to start of 'extra' bytes.
    //

    BUFFER _bufClientRequest;
    DWORD  _cbClientRequest;
    DWORD  _cbOldData;
    DWORD  _cbEntityBody;
    DWORD  _cbTotalEntityBody;
    DWORD  _cbChunkHeader;
    DWORD  _cbChunkBytesRead;
    DWORD  _cbExtraData;
    CHAR   *_pchExtraData;

    //
    //  Contains the server response buffer, generally only used for response
    //  headers
    //

    BUFFER _bufServerResp;

    //
    //  Stores the results of the last IO request
    //

    APIERR       _status;
    DWORD        _cbBytesWritten;
    DWORD        _cbRestartBytesWritten;
    DWORD        _dwRenegotiated;
    DWORD        _dwSslNegoFlags;
    AC_RESULT    _acIpAccess;
    BOOL         _fNeedDnsCheck;

    //
    //  Stores the request codes to write to the request log
    //

    DWORD        _dwLogHttpResponse;
    DWORD        _dwLogWinError;

    // Information used for decoding chunked requests.

    enum CHUNK_STATE _ChunkState;
    DWORD       _dwChunkSize;           // reset value is -1 => chunk size not sent.
    BYTE        _CRCount;
    BYTE        _LFCount;

    BUFFER                  _bufLastAnonAcctDesc;
    DWORD                   _cbLastAnonAcctDesc;

#if defined(CAL_ENABLED)
    LPVOID      m_pCalAuthCtxt;
    LPVOID      m_pCalSslCtxt;
#endif

    VOID *      m_ppvFrames[ MAX_BACKTRACE_FRAMES ];
};

#define CERT_NEGO_SUCCESS   1
#define CERT_NEGO_FAILURE   2

//
// Macro to check for both normal and localhost access
//

#define IS_ACCESS_ALLOWED(op)   (   \
        ((GetFilePerms() & VROOT_MASK_## op) != 0) &&                   \
             (((GetFilePerms() & VROOT_MASK_NO_REMOTE_## op) == 0) ||   \
               IsIPAddressLocal(                                        \
                    QueryClientConn()->QueryLocalIPAddress(),           \
                    QueryClientConn()->QueryRemoteIPAddress()) ) )

#define IS_ACCESS_ALLOWED2(_pExec, op)   (   \
        ((_pExec->_pMetaData->QueryAccessPerms() & VROOT_MASK_## op) != 0) &&                   \
             (((_pExec->_pMetaData->QueryAccessPerms() & VROOT_MASK_NO_REMOTE_## op) == 0) ||   \
               IsIPAddressLocal(                                        \
                    QueryClientConn()->QueryLocalIPAddress(),           \
                    QueryClientConn()->QueryRemoteIPAddress()) ) )

# endif // _BASEREQ_HXX_