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会不会觉得邪恶):

咦,怎么添加附件?先来个百度云盘吧。

posted @ 2014-07-09 14:26  lichmama  阅读(4441)  评论(1编辑  收藏  举报