📄 request.h
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: REQUEST.H
Abstract: HTTP request class
--*/
// Scalar types used by CHTTPRequest
typedef enum {
TOK_DATE,
TOK_PRAGMA,
TOK_COOKIE,
TOK_ACCEPT,
TOK_REFERER,
TOK_UAGENT,
TOK_AUTH,
TOK_IFMOD,
TOK_TYPE,
TOK_LENGTH,
TOK_ENCODING,
TOK_CONNECTION,
TOK_HOST,
}
TOKEN;
// NOTE: This follows same order as "const char *rg_cszMethods" list in parser.cpp
// and also davTable in webdav.cpp
typedef enum {
VERB_UNKNOWN,
VERB_GET,
VERB_HEAD,
VERB_POST,
VERB_OPTIONS,
VERB_PUT,
VERB_MOVE,
VERB_COPY,
VERB_DELETE,
VERB_MKCOL,
VERB_PROPFIND,
VERB_PROPPATCH,
// VERB_SEARCH,
VERB_LOCK,
VERB_UNLOCK,
#if 1
VERB_LAST_VALID = VERB_UNLOCK,
#else // unsupported DAV vebs
VERB_SUBSCRIBE,
VERB_UNSUBSCRIBE,
VERB_POLL,
VERB_BDELETE,
VERB_BCOPY,
VERB_BMOVE,
VERB_BPROPPATCH,
VERB_BPROPFIND,
VERB_X_MS_ENUMATTS,
VERB_LAST_VALID = VERB_X_MS_ENUMATTS,
#endif
}
VERB;
inline BOOL IsBasic(AUTHTYPE a) { return (a == AUTHTYPE_BASIC); }
inline BOOL IsNTLM(AUTHTYPE a) { return (a == AUTHTYPE_NTLM); }
inline BOOL IsNegotiate(AUTHTYPE a) { return (a == AUTHTYPE_NEGOTIATE); }
inline BOOL IsSupportedAuth(AUTHTYPE a) { return (IsNTLM(a) || IsBasic(a) || IsNegotiate(a)); }
typedef enum {
CONN_NONE = 0,
CONN_CLOSE = 1,
CONN_KEEP = 2,
CONN_UNKNOWN = 3
}
CONNHEADER;
#define CHTTPREQUEST_SIG 0xAB0D
// If strlen(url) is already known, don't recalc it but pass it in. If unknown set = -1.
inline BOOL URLHasTrailingSlashA(PCSTR pszURL, int iURLLen=-1) {
if (iURLLen == -1)
iURLLen = strlen(pszURL);
DEBUGCHK((iURLLen == (int)strlen(pszURL)) && (iURLLen>=1));
return (pszURL[iURLLen-1]=='/' || pszURL[iURLLen-1]=='\\');
}
inline BOOL URLHasTrailingSlashW(WCHAR *wszURL, int iURLLen=-1) {
if (iURLLen == -1)
iURLLen = wcslen(wszURL);
DEBUGCHK((iURLLen == (int)wcslen(wszURL)) && (iURLLen>=1));
return (wszURL[iURLLen-1]=='/' || wszURL[iURLLen-1]=='\\');
}
inline void RemoveTrailingSlashIfNeededA(PSTR pszURL, int iURLLen=-1) {
if (iURLLen == -1)
iURLLen = strlen(pszURL);
if (URLHasTrailingSlashA(pszURL,iURLLen))
pszURL[iURLLen-1] = 0;
}
RESPONSESTATUS GLEtoStatus(int iGLE);
// This object is the top-level object for an incoming HTTP request. One such object
// is created per request & a thread is created to handle it.
class CFilterInfo;
class CWebDav;
class CHttpResponse;
class CHttpRequest {
// socket
DWORD m_dwSig;
SOCKET m_socket;
CHttpRequest *m_pNext;
// buffers
CBuffer m_bufRequest;
CBuffer m_bufRespBody;
// method, version, URL etc. Direct results of parse
PSTR m_pszMethod;
PSTR m_pszURL;
PSTR m_pszContentType;
DWORD m_dwContentLength;
PSTR m_pszAccept;
FILETIME m_ftIfModifiedSince;
DWORD m_dwIfModifiedLength;
PSTR m_pszCookie;
PSTR m_pszHost;
// Decoded URL (indirect results of parse)
PSTR m_pszQueryString;
PWSTR m_wszPath;
PWSTR m_wszExt;
PSTR m_pszPathInfo;
PSTR m_pszPathTranslated;
DWORD m_dwFileAttributes; // results of GetFileAttributes(m_wszPath) call.
DWORD m_dwInitialPostRead; // how much we read off wire before calling ISAPI extension
DWORD m_ccWPath; // # of wide chars of m_wszPath.
PVROOTINFO m_pVRoot; // do NOT free, points to global data that is alloced/freed on server init/deinit.
// Logging members
PSTR m_pszLogParam;
RESPONSESTATUS m_rs;
BOOL m_fBufferedResponse; // Are we using m_bufResponse or sending straight to client?
HRINPUT m_hrPreviousReadClient; // Should next call to ReadClient() timeout?
// Parsing functions
void FreeHeaders(void) {
MyFree(m_pszMethod);
MyFree(m_pszURL);
MyFree(m_pszContentType);
MyFree(m_pszAccept);
MyFree(m_pszQueryString);
MyFree(m_wszPath);
MyFree(m_wszExt);
MyFree(m_pszCookie);
MyFree(m_pszHost);
MyFree(m_pszLogParam);
MyFree(m_pszPathInfo);
MyFree(m_pszPathTranslated);
MyFree(m_pszAuthType);
}
BOOL ParseHeaders();
BOOL MyCrackURL(PSTR pszRawURL, int iLen);
BOOL CheckAuth(AUTHLEVEL auth) {
return (m_AuthLevelGranted >= auth) ? TRUE : FALSE;
}
public:
BOOL ParseMethod(PCSTR pszMethod, int cbMethod);
BOOL ParseContentLength(PCSTR pszMethod, TOKEN id);
BOOL ParseContentType(PCSTR pszMethod, TOKEN id);
BOOL ParseIfModifiedSince(PCSTR pszMethod, TOKEN id);
BOOL ParseAuthorization(PCSTR pszMethod, TOKEN id);
BOOL ParseAccept(PCSTR pszMethod, TOKEN id);
BOOL ParseConnection(PCSTR pszMethod, TOKEN id);
BOOL ParseCookie(PCSTR pszMethod, TOKEN id);
BOOL ParseHost(PCSTR pszMethod, TOKEN id);
BOOL HandleNTLMNegotiateAuth(PSTR pszSecurityToken, BOOL fUseNTLM);
PSTR m_pszSecurityOutBuf; // buffer to send client on NTLM/negotiate response, Base64 encoded
DWORD m_dwVersion; // LOWORD=minor, HIWORD=major.
VERB m_idMethod;
CBuffer m_bufRespHeaders;
CFilterInfo *m_pFInfo; // Filter state information
BOOL m_fKeepAlive;
BOOL m_fResponseHTTP11; // put "HTTP/1.1" in response headers? Currently only WebDAV will spit out HTTP 1.1 headers, so an HTTP/1.1 request to non WebDAV resource still returns 1.0.
DWORD MinorHTTPStatus(void) { return m_fResponseHTTP11 ? 1 : 0; }
RESPONSESTATUS GetStatus(void) { return m_rs; }
#if defined (DEBUG)
// When HTTP header buf has a \0 temporarily put into it to create a string, no further
// calls to FindHttpHeader can be made, as header we're looking for maybe after '\0'.
BOOL m_fHeadersInvalid;
void DebugSetHeadersInvalid(BOOL f) { m_fHeadersInvalid = f; }
#else
void DebugSetHeadersInvalid(BOOL f) { ; }
#endif
PSTR FindHttpHeader(PCSTR szHeaderName, DWORD ccHeaderName);
BOOL TranslateRequestToScript(void);
// which set of config variables (vroots, auth, etc...) to use, depending on website request services.
// Note that certain functionality (the thread pool, ISAPI extension dll cache,
// parts of auth like function table interfaces into security DLLs, and ISAPI filters)
// are handled globally and will access g_pVars (default website) directly.
CGlobalVariables *m_pWebsite;
BOOL m_fResolvedHostWebSite;
// When using SSL client certificates, we don't use standard BASIC/NTLM/...
// authentication at the same time.
BOOL SendAuthenticate(void) { return !(m_SSLInfo.m_pClientCertContext); }
void CloseSocket(void) {
if (m_socket) {
// In certain scenarios, HTTPD may not be reading the last 2 bytes of content.
// Read them now if they are available so we do not send a TCP reset to the client.
// For certain TCP stacks, receiving this reset will cause it to kill the client
// connection even though HTTPD has sent back all the required bytes and closed the connection.
BYTE recvBuf[4]; // Recv up to 4 bytes just in case
RecvToBuf(m_socket,recvBuf,sizeof(recvBuf),0);
// Now perform socket shutdown.
shutdown(m_socket, 1);
closesocket(m_socket);
m_socket = 0;
}
}
// In some scenarios it's easier to manipulate m_wszPath if it can
// be assumed there's a '\' as trailing character.
void AddTrailingSlashToPhysicalPath(void) {
if ((m_ccWPath > 1) && (! URLHasTrailingSlashW(m_wszPath,m_ccWPath))) {
m_wszPath[m_ccWPath++] = '\\';
m_wszPath[m_ccWPath] = 0;
}
DEBUGCHK(m_ccWPath == wcslen(m_wszPath));
}
void RemoveTrailingSlashToPhysicalPath(void) {
if ((m_ccWPath > 1) && URLHasTrailingSlashW(m_wszPath,m_ccWPath)) {
m_wszPath[--m_ccWPath] = 0;
}
DEBUGCHK((m_wszPath==NULL) || m_ccWPath == wcslen(m_wszPath));
}
BOOL IsRootPath(void) {
return ((m_wszPath[0] == '\\' || m_wszPath[0] == '/') && m_wszPath[1] == 0);
}
BOOL IsRootVDir(void) {
return (IsSlash(m_pszURL[0]) && m_pszURL[1] == 0);
}
// Only case we'd be inactive is during shutdown.
BOOL IsActive(void) { return (m_socket != 0); }
CONNHEADER GetConnHeader() { return m_fKeepAlive ? CONN_KEEP : CONN_CLOSE; }
void GetContentTypeOfRequestURI(PSTR szContentType, DWORD ccContentType, const WCHAR *wszExt=NULL);
private:
friend class CHttpResponse;
// Authentication data members
AUTHLEVEL m_AuthLevelGranted;
PSTR m_pszAuthType;
PSTR m_pszRawRemoteUser; // Holds base64 encoded data, before auth decodes it
PSTR m_pszRemoteUser;
WCHAR* m_wszRemoteUser;
WCHAR* m_wszMemberOf;
PSTR m_pszPassword;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -