/*--
Copyright (c) 1995-1998  Microsoft Corporation
Module Name: HTTPD.H
Author: Arul Menezes
Abstract: Global defns for the HTTP server
--*/

#ifndef _HTTPD_H_
#define _HTTPD_H_


#ifndef UNDER_CE
#define SECURITY_WIN32
#endif

#if DBG
#define DEBUG
#endif

#include <windows.h>
#include <winsock2.h>

// OLD_CE_BUILD is defined when using the Windows CE Toolkit in Visual
// Studio (in proj servers\vc\httpexece).  We build this way when we're building for
// older Windows CE devices (version 2.x).  The reason we do this in the first place is
// for shipping a beta version of the web server.
// We won't have functions like sprintf or sscanf, so we implement our own, scaled down versions.
// Also, there is no ASP support in this case.

#ifdef OLD_CE_BUILD
#pragma message ("Using Visual Studio Windows CE Toolkit Settings")

// Write our own strrchr if we're using version 2.0 of CE, it wouldn't exist otherwise
inline char *strrchr( const char *string, int c )
{
    PCSTR pszTrav = string;
    PSTR pszLast = NULL;
    while ( *pszTrav )
    {
        if (*pszTrav == (CHAR) c)
            pszLast = (PSTR) pszTrav;
        pszTrav++;
    }
    return pszLast;
}

inline int isspace(int c) {
    return ( c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v');
}
#else
#include <stdio.h>
#endif


#include <httpext.h>
#include <httpfilt.h>
#include <service.h>
#include <uhres.h>
#include <creg.hxx>
#include <sspi.h>
#include <issperr.h>
#include <servutil.h>
#include <httpcomn.h>


#ifdef UNDER_CE
#include <windbase.h>
#include <extfile.h>
#else
#include <wininet.h>
#endif


//------------- Arbitrary constants -----------------------

// the assumption is that this buffer size covers the vast majority of requests
#define MINBUFSIZE      1024
// this the the timeout we use when waiting for the next request on a keep-alive connection
#define KEEPALIVETIMEOUT 60000
// subsequent-input timeout value. shoudl only hit on malformed headers/garbled packets
#define RECVTIMEOUT     30000
// maximum size of output headers
#define MAXHEADERS      512
// maximum size of a mime-type
#define MAXMIME         64
// maximum size username+password
#define MAXUSERPASS     256
// the assumption is that this buffer size covers most dir listings
#define DIRBUFSIZE      4096
// Size of response headers ("normal" headers, cookies and other extra headers are dynamic)
#define HEADERBUFSIZE   4096
// Used for dynamically growing arrays
#define VALUE_GROW_SIZE   5
// Size of buffer to hold all the bodies on web server errors
#define BODYSTRINGSIZE     2048

#define HTTPD_DEV_PREFIX   L"HTP"
#define HTTPD_DEV_INDEX   0
#define HTTPD_DEV_NAME     L"HTP0:"


//------------- not-so-arbitrary constants -----------------------

#define IPPORT_HTTP     2869


//-------------------- Debug defines ------------------------

// Debug zones
#ifdef DEBUG
  #define ZONE_ERROR    DEBUGZONE(0)
  #define ZONE_INIT     DEBUGZONE(1)
  #define ZONE_LISTEN   DEBUGZONE(2)
  #define ZONE_SOCKET   DEBUGZONE(3)
  #define ZONE_REQUEST  DEBUGZONE(4)
  #define ZONE_RESPONSE DEBUGZONE(5)
  #define ZONE_ISAPI    DEBUGZONE(6)
  #define ZONE_VROOTS   DEBUGZONE(7)
  #define ZONE_ASP      DEBUGZONE(8)
  #define ZONE_DEVICE   DEBUGZONE(9)
  #define ZONE_MEM      DEBUGZONE(13)
  #define ZONE_PARSER   DEBUGZONE(14)
  #define ZONE_TOKEN    DEBUGZONE(15)
#endif


#define NTLM_PACKAGE_NAME   TEXT("NTLM")

// We need CE_STRING because GetProcAddress takes a LPCSTR as arg on NT, but UNICODE is defined
// so the TEXT macro would return a UNICODE string
#ifdef  UNDER_CE
#define NTLM_DLL_NAME     TEXT("secur32.dll")
#define CE_STRING(x)      TEXT(x)
#define SECURITY_ENTRYPOINT_CE  SECURITY_ENTRYPOINT
#else
#define NTLM_DLL_NAME     TEXT("security.dll")
#define CE_STRING(x)      (LPCSTR) (x)
#define SECURITY_ENTRYPOINT_CE  SECURITY_ENTRYPOINT_ANSIA
#endif




#define ASP_DLL_NAME      TEXT("asp.dll")

/////////////////////////////////////////////////////////////////////////////
// Misc string handling helpers
/////////////////////////////////////////////////////////////////////////////

PSTR MySzDupA(PCSTR pszIn, int iLen=0);
PWSTR MySzDupW(PCWSTR wszIn, int iLen=0);
PWSTR MySzDupAtoW(PCSTR pszIn, int iInLen=-1);
PSTR MySzDupWtoA(PCWSTR wszIn, int iInLen=-1);
BOOL MyStrCatA(PSTR *ppszDest, PSTR pszSource, PSTR pszDivider=NULL);


// Misc HTTP helper macros
#define CHECKHCONN(h) if(!h || ((CHttpRequest*)h)->m_dwSig != CHTTPREQUEST_SIG) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
#define CHECKPFC(h)  if (!h || ((CHttpRequest*)h->ServerContext)->m_dwSig != CHTTPREQUEST_SIG) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
#define CHECKPTR(p) if (!p) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
#define CHECKPTRS2(p1, p2) if(!p1 || !p2) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
#define CHECKPTRS3(p1, p2, p3) if(!p1 || !p2 || !p3) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }

#define CHECKFILTER(pfc)    { if (! ((CHttpRequest*)pfc->ServerContext)->m_pFInfo->m_fFAccept)  \
                                    {       SetLastError(ERROR_OPERATION_ABORTED);  return FALSE;   } }
#define SkipWWhiteSpace(lpsz)    while ( (lpsz)[0] != L'\0' && iswspace((lpsz)[0])) ++(lpsz)



//------------- Scalar Data typedefs -----------------------
// HTTP status codes
typedef enum
{
    STATUS_OK = 0,
    STATUS_MOVED,
    STATUS_NOTMODIFIED,
    STATUS_BADREQ,
    STATUS_UNAUTHORIZED,
    STATUS_FORBIDDEN,
    STATUS_NOTFOUND,
    STATUS_INTERNALERR,
    STATUS_NOTIMPLEM,
    STATUS_NOTSUPP,
    STATUS_MAX,
}
RESPONSESTATUS;

// Data used for response static data
typedef struct
{
    DWORD dwStatusNumber;
    PCSTR pszStatusText;
    PCSTR pszStatusBody;
}
STATUSINFO;



//------------- Const data prototypes -----------------------


extern STATUSINFO rgStatus[STATUS_MAX];
extern const char cszTextHtml[];
extern const char cszEmpty[];
extern const char cszServerID[];
extern const char cszProductID[];
extern const char* rgMonth[];
extern const char cszKeepAlive[];
extern const char cszHTTPVER[];
extern const char cszDateParseFmt[];
extern const char cszDateOutputFmt[];
extern const char* rgWkday[];
extern const char* rgMonth[];
extern const char cszCRLF[];
extern const char cszBasic[];
extern BOOL g_fFromExe;     // Did the executable start us?


//----------------------- Class defns -----------------------


#include <asp.h>
#include <buffio.h>
#include <extns.h>
#include <vroots.hpp>
#include <auth.h>
#include <request.h>
#include <log.h>
#include <filters.h>
#include <authhlp.h>

//-------------------- All global data is accessed through Global Class ----------

class CGlobalVariables
{
public:
    SOCKET    m_sockListen;
    DWORD     m_dwListenPort;           // port we're listening on (can be modified in registry. default=80)
    CVRoots*  m_pVroots;                // ptr to VRoot structure, containing or URL-->Paths mappings
    BOOL      m_fBasicAuth;             // are we allowing Basic auth (from registry)
    BOOL      m_fNTLMAuth;              // are we allowing NTLM auth (from registry)
    BOOL      m_fFilters;               // Is ISAPI filter component included?
    BOOL      m_fExtensions;            // Is ISAPI extension component included?
    BOOL      m_fASP;                   // Is ASP component included?
    BOOL      m_fDirBrowse;             // are we allowing directory browsing (from registry)
    PWSTR     m_wszDefaultPages;        // are we allowing directory browsing (from registry)
    BOOL      m_fAcceptConnections;     // are we accepting new threads?
    LONG      m_nConnections;           // # of connections (threads) we're handling
    LONG      m_nMaxConnections;        // Maximum # of connections we support concurrently
    CLog*     m_pLog;                   // Logging structure
    DWORD     m_dwPostReadSize;         // Size of chunks of data to recv() in POST request.
    PSTR      m_pszServerID;            // Server ID

    CISAPICache *m_pISAPICache;         // Used to cache ISAPI extension and ASP dlls
    DWORD     m_dwCacheSleep;           // How often (in millesecs) do we

    PWSTR     m_wszAdminUsers;          // List of users who have administrative privelages
    PWSTR     m_wszAdminGroups;         // List of groups who have administrative privelages

    PSTR      m_pszStatusBodyBuf;       // Holds the strings of http bodies loaded from rc file

    SVSThreadPool *m_pThreadPool;       // All httpd threads other than HttpConnectionThread use this
    LONG      m_fISAPICacheRunning;     // Is ISAPI cache cleanup thread running?

    // ASP Specific
    SCRIPT_LANG m_ASPScriptLang;        // Registry set default scripting language
    LCID        m_ASPlcid;              // Registry set default LCID
    UINT        m_lASPCodePage;         // Registry set default Code Page

    // Authentication Specific
    HINSTANCE               m_hNTLMLib;         // Global NTLM library handle
    DWORD                   m_cbNTLMMax;        // max ntlm allowable data size
    PSecurityFunctionTable  m_pNTLMFuncs;       // fcn table for NTLM requests

    HANDLE                  m_hEventSelect;
    HANDLE                  m_hEventShutdown;


    CGlobalVariables();
    ~CGlobalVariables();
};

extern CGlobalVariables *g_pVars;
extern HINSTANCE g_hInst;
extern HANDLE    g_hListenThread;
extern BOOL      g_fRegistered;
extern LONG      g_fState;

//------------- Function prototypes -------------------------
DWORD WINAPI HttpConnectionThread(LPVOID lpv);
DWORD WINAPI HandleAccept(LPVOID lpv);
extern "C" int HttpInitialize(TCHAR *szRegPath);


void GetRemoteAddress(SOCKET sock, PSTR pszBuf);
void GetLocalAddress(SOCKET sock, PSTR pszBuf);
DWORD WINAPI RemoveUnusedISAPIs(LPVOID lpv);
BOOL SetHTTPVersion(PSTR pszVersion, DWORD *pdwVersion);
void WriteHTTPVersion(PSTR pszVersion, DWORD dwVersion);
char *strcpyEx(char *szDest, const char *szSrc);

BOOL SetHTTPDate(PSTR pszDate, PSTR pszMonth, SYSTEMTIME *pst,PDWORD pdwModifiedLength);
PSTR WriteHTTPDate(PSTR pszDateBuf, SYSTEMTIME *pst, BOOL fAddGMT);
void InitializeResponseCodes(PSTR pszStatusBodyBuf);

BOOL Base64Encode(
            BYTE *   bufin,          // in
            DWORD    nbytes,         // in
            char *   pbuffEncoded);   // out
BOOL Base64Decode(
            char   * bufcoded,       // in
            char   * pbuffdecoded,   // out
            DWORD  * pcbDecoded);     // in out


#endif //_HTTPD_H_