VB6之HTTP服务器的实现(二)
接上篇,这次做了小小的改动和提升。增加了对POST的支持和对其他方法(GET和POST之外的)选择405回复。另外,增加了对CGI的支持,目前可以使用C语言来写(是不是好蠢的赶脚)。相对于上篇,整体做了小小的优化。这次代码就只贴mod_cgi.bas的部分,其他文件我打包了,感兴趣的同学可以下来看看。
注:由于我不是很了解WebServer,写这个东西也是盲人摸象。像什么状态控制、任务调度、容错之类的基本上能省则省,另外也是因为不会写,哈哈。如果有不足之处,还请不吝赐教,右路西裤(霓虹语:请多多指教)!
1 'mod_cgi.bas 2 'code by lichmama from cnblogs.com 3 'CGI支持状态 4 Public CGI_ENABLED As Boolean 5 'CGI程序目录 6 Public Const CGI_ROOT As String = "c:\cgi-bin\" 7 8 Private Declare Function CreatePipe Lib "kernel32" ( _ 9 phReadPipe As Long, _ 10 phWritePipe As Long, _ 11 lpPipeAttributes As SECURITY_ATTRIBUTES, _ 12 ByVal nSize As Long) As Long 13 14 Private Declare Sub GetStartupInfo Lib "kernel32" Alias "GetStartupInfoA" ( _ 15 lpStartupInfo As STARTUPINFO) 16 17 Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" ( _ 18 ByVal lpApplicationName As String, _ 19 ByVal lpCommandLine As String, _ 20 lpProcessAttributes As Any, _ 21 lpThreadAttributes As Any, _ 22 ByVal bInheritHandles As Boolean, _ 23 ByVal dwCreationFlags As Long, _ 24 lpEnvironment As Any, _ 25 ByVal lpCurrentDriectory As String, _ 26 lpStartupInfo As STARTUPINFO, _ 27 lpProcessInformation As PROCESS_INFORMATION) As Long 28 29 Private Declare Function ReadFile Lib "kernel32" ( _ 30 ByVal hFile As Long, _ 31 lpBuffer As Any, _ 32 ByVal nNumberOfBytesToRead As Long, _ 33 lpNumberOfBytesRead As Long, _ 34 lpOverlapped As Any) As Long 35 36 Private Declare Function CloseHandle Lib "kernel32" ( _ 37 ByVal hObject As Long) As Long 38 39 Private Type SECURITY_ATTRIBUTES 40 nLength As Long 41 lpSecurityDescriptor As Long 42 bInheritHandle As Long 43 End Type 44 45 Private Type PROCESS_INFORMATION 46 hProcess As Long 47 hThread As Long 48 dwProcessId As Long 49 dwThreadId As Long 50 End Type 51 52 Private Type STARTUPINFO 53 cb As Long 54 lpReserved As Long 55 lpDesktop As Long 56 lpTitle As Long 57 dwX As Long 58 dwY As Long 59 dwXSize As Long 60 dwYSize As Long 61 dwXCountChars As Long 62 dwYCountChars As Long 63 dwFillAttribute As Long 64 dwFlags As Long 65 wShowWindow As Integer 66 cbReserved2 As Integer 67 lpReserved2 As Byte 68 hStdInput As Long 69 hStdOutput As Long 70 hStdError As Long 71 End Type 72 73 Private Type OVERLAPPED 74 ternal As Long 75 ternalHigh As Long 76 offset As Long 77 OffsetHigh As Long 78 hEvent As Long 79 End Type 80 81 Private Const STARTF_USESHOWWINDOW = &H1 82 Private Const STARTF_USESTDHANDLES = &H100 83 Private Const SW_HIDE = 0 84 Private Declare Sub RtlZeroMemory Lib "kernel32" (dest As Any, ByVal _ 85 numBytes As Long) 86 87 88 Public Function ShellCGI(ByVal head As Object, rep_state As Long) As String 89 Dim sa As SECURITY_ATTRIBUTES 90 Dim si As STARTUPINFO 91 Dim pi As PROCESS_INFORMATION 92 Dim hrp As Long 93 Dim hwp As Long 94 Dim ret As Long 95 Dim envstr As String 96 97 'fill this with CGI standard envrionment strings, 98 ' which delimited by chr(0) 99 envstr = MakeEnvString(head) 100 Call RtlZeroMemory(ByVal VarPtr(sa), Len(sa)) 101 Call RtlZeroMemory(ByVal VarPtr(si), Len(si)) 102 Call RtlZeroMemory(ByVal VarPtr(pi), Len(pi)) 103 104 sa.nLength = Len(sa) 105 sa.lpSecurityDescriptor = 0& 106 sa.bInheritHandle = 1& 107 108 'create pipe 109 ret = CreatePipe(hrp, hwp, sa, 0&) 110 If ret = 0 Then 111 Debug.Print "[HTTP-VBS]: CGI Exception, pipe failed" 112 Exit Function 113 End If 114 115 si.cb = Len(si) 116 si.hStdOutput = hwp 117 si.hStdError = hwp 118 si.dwFlags = STARTF_USESHOWWINDOW Or STARTF_USESTDHANDLES 119 si.wShowWindow = SW_HIDE 120 121 'create the cgi-process, cgi-path: head("Path_Translated") 122 ret = CreateProcess(head("Path_Translated"), vbNullString, _ 123 ByVal 0&, ByVal 0&, True, 0&, ByVal envstr, vbNullString, si, pi) 124 If ret = 0 Then 125 Debug.Print "[HTTP-VBS]: CGI Exception, create process failed" 126 Exit Function 127 End If 128 129 'read response from cgi 130 Dim nobr As Long 'num of bytes read 131 Dim lpbuff As String 132 Dim szbuff(65536 * 100) As Byte 133 Dim sum As Long 134 sum = 0 135 Call RtlZeroMemory(ByVal VarPtr(szbuff(0)), 65536 * 100) 136 Do 137 nobr = 0& 138 lpbuff = String(1024, " ") 139 If ReadFile(hrp, ByVal lpbuff, 1024&, nobr, ByVal 0&) Then 140 Call RtlMoveMemory(ByVal VarPtr(szbuff(sum)), ByVal StrPtr(lpbuff), LenB(lpbuff)) 141 sum = sum + LenB(lpbuff) 142 Else 143 Exit Do 144 End If 145 Call CloseHandle(hwp) 146 Loop 147 Call CloseHandle(hrp) 148 149 rep_state = 200 150 ShellCGI = Left(szbuff, sum) 151 End Function 152 153 Private Function MakeEnvString(ByVal head As Object) As String 154 MakeEnvString = "REQUEST_METHOD=" & head("Request")("Method") & Chr(0) & _ 155 "CONTENT_TYPE=" & head("Content-Type") & Chr(0) & _ 156 "CONTENT_LENGTH=" & head("Content-Length") & Chr(0) & _ 157 "QUERY_STRING=" & head("Query_String") & Chr(0) & _ 158 "SCRIPT_NAME=" & head("Script_Name") & Chr(0) & _ 159 "PATH_INFO=" & head("Path_Info") & Chr(0) & _ 160 "PATH_TRANSLATED=" & head("Path_Translated") & Chr(0) & _ 161 "REMOTE_HOST=" & head("Remote_Host") & Chr(0) & _ 162 "REMOTE_ADDR=" & head("Remote_Addr") & Chr(0) & _ 163 "REMOTE_PORT=" & head("Remote_Port") & Chr(0) & _ 164 "REMOTE_USER=" & head("Remote_User") & Chr(0) & _ 165 "REMOTE_IDENT=" & head("Remote_Ident") & Chr(0) & _ 166 "AUTH_TYPE=" & head("Auth_Type") & Chr(0) & _ 167 "SERVER_NAME=http-vb/0.1" & Chr(0) & _ 168 "SERVER_PORT=80" & Chr(0) & _ 169 "SERVER_PROTOCOL=HTTP/1.1" & Chr(0) & _ 170 "DOCUMENT_ROOT=" & head("Document_Root") & Chr(0) & _ 171 "SERVER_SOFTWARE=http-vb/0.1 vb/6.0" & Chr(0) & _ 172 "HTTP_ACCEPT=" & head("Accept") & Chr(0) & _ 173 "HTTP_USER_AGENT=" & head("User-Agent") & Chr(0) & _ 174 "HTTP_REFERER=" & head("Referer") & Chr(0) & _ 175 "HTTP_COOKIE=" & head("Cookie") & Chr(0) & _ 176 "GATEWAY_INTERFACE=CGI/1.1" & Chr(0) 177 End Function
CGI的代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <windows.h> 4 #define ENV_MAX_LENGTH 0x7fff 5 6 char *GetEnv(const char *lpName, char *lpbuff){ 7 memset(lpbuff, 0, ENV_MAX_LENGTH); 8 GetEnvironmentVariable(lpName, lpbuff, ENV_MAX_LENGTH); 9 return lpbuff; 10 } 11 12 int main(int argc, char *argv[]){ 13 char lpbuff[ENV_MAX_LENGTH]={0}; 14 printf("Content-Type: text/html; charset=utf-8\n"); 15 printf("\n"); 16 printf("<html>\n"); 17 printf("<head>\n"); 18 printf("<meta content='text/html; charset=utf-8' http-equiv='content-type' />\n"); 19 printf("<title>cgi page@lichmama</title>\n"); 20 printf("</head>\n"); 21 printf("<body>\n"); 22 printf("<ul style='font-family:courier new'>\n"); 23 printf("<li>REQUEST_METHOD: %s</li>\n", GetEnv("REQUEST_METHOD", lpbuff)); 24 printf("<li>CONTENT_TYPE: %s</li>\n", GetEnv("CONTENT_TYPE", lpbuff)); 25 printf("<li>CONTENT_LENGTH: %s</li>\n", GetEnv("CONTENT_LENGTH", lpbuff)); 26 printf("<li>QUERY_STRING: %s</li>\n", GetEnv("QUERY_STRING", lpbuff)); 27 printf("<li>SCRIPT_NAME: %s</li>\n", GetEnv("SCRIPT_NAME", lpbuff)); 28 printf("<li>PATH_INFO: %s</li>\n", GetEnv("PATH_INFO", lpbuff)); 29 printf("<li>PATH_TRANSLATED: %s</li>\n",GetEnv("PATH_TRANSLATED", lpbuff)); 30 printf("<li>REMOTE_HOST: %s</li>\n", GetEnv("REMOTE_HOST", lpbuff)); 31 printf("<li>REMOTE_ADDR: %s</li>\n", GetEnv("REMOTE_ADDR", lpbuff)); 32 printf("<li>REMOTE_PORT: %s</li>\n", GetEnv("REMOTE_PORT", lpbuff)); 33 printf("<li>REMOTE_USER: %s</li>\n", GetEnv("REMOTE_USER", lpbuff)); 34 printf("<li>REMOTE_IDENT: %s</li>\n", GetEnv("REMOTE_IDENT", lpbuff)); 35 printf("<li>AUTH_TYPE: %s</li>\n", GetEnv("AUTH_TYPE", lpbuff)); 36 printf("<li>GATEWAY_INTERFACE: %s</li>\n", GetEnv("GATEWAY_INTERFACE", lpbuff)); 37 printf("<li>SERVER_NAME: %s</li>\n", GetEnv("SERVER_NAME", lpbuff)); 38 printf("<li>SERVER_PORT: %s</li>\n", GetEnv("SERVER_PORT", lpbuff)); 39 printf("<li>SERVER_PROTOCOL: %s</li>\n",GetEnv("SERVER_PROTOCOL", lpbuff)); 40 printf("<li>DOCUMENT_ROOT: %s</li>\n", GetEnv("DOCUMENT_ROOT", lpbuff)); 41 printf("<li>SERVER_SOFTWARE: %s</li>\n",GetEnv("SERVER_SOFTWARE", lpbuff)); 42 printf("<li>HTTP_ACCEPT: %s</li>\n", GetEnv("HTTP_ACCEPT", lpbuff)); 43 printf("<li>HTTP_USER_AGENT: %s</li>\n",GetEnv("HTTP_USER_AGENT", lpbuff)); 44 printf("<li>HTTP_REFERER: %s</li>\n", GetEnv("HTTP_REFERER", lpbuff)); 45 printf("<li>HTTP_COOKIE: %s</li>\n", GetEnv("HTTP_COOKIE", lpbuff)); 46 printf("</ul>\n"); 47 printf("</body>\n"); 48 printf("</html>\n"); 49 return 0; 50 }
贴张图,看看效果(看到.exe会不会觉得邪恶):
咦,怎么添加附件?先来个百度云盘吧。