├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── Server.au3 ├── main.au3 ├── settings.ini └── www ├── favicon.ico ├── img ├── logo.png └── logo.svg ├── index.au3 ├── index.html └── index.php /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | php*/ 2 | autoit*/ 3 | au3pm/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 genius257 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoIt HTTP Server 2 | 3 | This server does not have security as a priority, therefore it is NOT advised to use this for anything but local hosting! 4 | 5 | [![](https://img.shields.io/github/license/genius257/AutoIt-HTTP-Server.svg?style=flat-square)](LICENSE) 6 | 7 | My additions/modifications to [__jvanegmond__](https://www.autoitscript.com/forum/profile/10412-jvanegmond/)'s POST Server 8 | 9 | The original source can be found [__here__](https://www.autoitscript.com/forum/topic/68851-powerful-http-server-in-pure-autoit/) 10 | 11 | Added: 12 | 13 | - Query strings are now supported, instead for being included as the file name/path 14 | - PHP support 15 | - More MIME types 16 | - 404 status code when returning the 404 response 17 | - Default index file if trying to access only folder path, not just on root 18 | - Support for multiple index files, a bit like apatche's DirectoryIndex 19 | - 403 status code if no index is found, instead of sending a stream of no file 20 | - Removed double newline at end of "_HTTP_SendData" it appended to any file and seemed to not be needed. 21 | - Added [If...Then](https://www.autoitscript.com/autoit3/docs/keywords/If.htm) statment with [ContinueCase](https://www.autoitscript.com/autoit3/docs/keywords/ContinueCase.htm) in case required PHP files is not present 22 | - Server URI does now support percent encoding 23 | - AU3 CGI support 24 | 25 | Looking into: 26 | 27 | - gzip 28 | - If-Modified-Since header 29 | - HEAD Method support 30 | -------------------------------------------------------------------------------- /Server.au3: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | Opt("TCPTimeout", 10) 8 | 9 | ;# Enums used with the response of _HTTP_ParseHttpRequest method 10 | Global Enum $HttpRequest_METHOD, $HttpRequest_URI, $HttpRequest_PROTOCOL, $HttpRequest_HEADERS, $HttpRequest_BODY 11 | Global Enum $HttpUri_Scheme, $HttpUri_Path, $httpUri_Query, $HttpUri_Fragment 12 | 13 | Global Const $FMFD_DEFAULT = 0x00000000 14 | Global Const $FMFD_URLASFILENAME = 0x00000001 15 | Global Const $FMFD_ENABLEMIMESNIFFING = 0x00000002 16 | Global Const $FMFD_IGNOREMIMETEXTPLAIN = 0x00000004 17 | Global Const $FMFD_SERVERMIME = 0x00000008 18 | Global Const $FMFD_RESPECTTEXTPLAIN = 0x00000010 19 | Global Const $FMFD_RETURNUPDATEDIMGMIMES = 0x00000020 20 | 21 | Global Const $HTTP_STATUS_200 = "200 OK" 22 | Global Const $HTTP_STATUS_403 = "403 Forbidden" 23 | 24 | ;Global server variables 25 | Global $aRequest 26 | Global $aHeaders 27 | Global $aUri 28 | Global $x ;FIXME: change to more unique variable name 29 | Global $aSocket 30 | Global $sLocalPath 31 | 32 | #Region // DEFAULT OPTIONS HERE // 33 | Global $sRootDir = _WinAPI_GetFullPathName('.\www\'); The absolute path to the root directory of the server. 34 | ;~ Global $sIP = @IPAddress1 ; ip address as defined by AutoIt 35 | ;~ Global $sIP = "127.0.0.1" 36 | Global $sIP = "0.0.0.0"; http://localhost/ and more 37 | Global $iPort = 80; the listening port 38 | Global $sServerAddress = "http://" & $sIP & ":" & $iPort & "/" 39 | Global $iMaxUsers = 15; Maximum number of users who can simultaneously get/post 40 | Global $sServerName = "AutoIt HTTP Server/0.1 (" & @OSVersion & ") AutoIt/" & @AutoItVersion 41 | Global $DirectoryIndex="index.html" 42 | Global $bAllowIndexes=False 43 | 44 | Global $PHP_Path = "" 45 | Global $AU3_Path = "" 46 | 47 | Global $_HTTP_Server_Request_Handler = _HTTP_Server_Request_Handle 48 | #EndRegion // END OF DEFAULT OPTIONS // 49 | 50 | Func _HTTP_Server_Start() 51 | ;Local $aSocket[$iMaxUsers] ; Creates an array to store all the possible users 52 | Global $aSocket[$iMaxUsers] ; Creates an array to store all the possible users 53 | Local $sBuffer[$iMaxUsers] ; All these users have buffers when sending/receiving, so we need a place to store those 54 | 55 | For $x = 0 to UBound($aSocket)-1 ; Fills the entire socket array with -1 integers, so that the server knows they are empty. 56 | $aSocket[$x] = -1 57 | Next 58 | 59 | TCPStartup() ; AutoIt needs to initialize the TCP functions 60 | 61 | $iMainSocket = TCPListen($sIP,$iPort, $iMaxUsers) ;create main listening socket 62 | If @error Then ; if you fail creating a socket, exit the application 63 | MsgBox(0x20, "AutoIt Webserver", "Unable to create a socket on port " & $iPort & ".") ; notifies the user that the HTTP server will not run 64 | Exit ; if your server is part of a GUI that has nothing to do with the server, you'll need to remove the Exit keyword and notify the user that the HTTP server will not work. 65 | EndIf 66 | 67 | Debug("Server created on " & $sServerAddress) 68 | 69 | While 1 70 | Local $iNewSocket = TCPAccept($iMainSocket) ; Tries to accept incoming connections 71 | 72 | If $iNewSocket <> -1 Then ; Verifies that there actually is an incoming connection 73 | For $x = 0 to UBound($aSocket)-1 ; Attempts to store the incoming connection 74 | If $aSocket[$x] = -1 Then 75 | $aSocket[$x] = $iNewSocket ;store the new socket 76 | Debug("Accepted new request on position: "&$x) 77 | ExitLoop 78 | EndIf 79 | Next 80 | If $aSocket[$x] = -1 Then TCPCloseSocket($iNewSocket); No room for socket 81 | EndIf 82 | 83 | For $x = 0 to UBound($aSocket)-1 ; A big loop to receive data from everyone connected 84 | If $aSocket[$x] = -1 Then ContinueLoop ; if the socket is empty, it will continue to the next iteration, doing nothing 85 | 86 | Debug("("&$aSocket[$x]&")Getting request information on position: "&$x) 87 | 88 | $sNewData = TCPRecv($aSocket[$x], 1024, 1) ; Receives a whole lot of data if possible 89 | If @error <> 0 Or @extended<>0 Then ; Client has disconnected 90 | TCPCloseSocket($aSocket[$x]) 91 | Debug("Client has disconnected on position: "&$x) 92 | $aSocket[$x] = -1 ; Socket is freed so that a new user may join 93 | $sBuffer[$x] = "" 94 | ContinueLoop ; Go to the next iteration of the loop, not really needed but looks oh so good 95 | EndIf 96 | 97 | $sNewData = BinaryToString($sNewData) ; Receives a whole lot of data if possible 98 | 99 | if (StringLen($sNewData)>0) Then Debug(VarGetType($sNewData)&"("&StringLen($sNewData)&"): "&$sNewData) 100 | $sBuffer[$x] &= $sNewData ;store it in the buffer 101 | 102 | If StringInStr(StringStripCR($sBuffer[$x]),@LF&@LF) Then ; if the request headers are ready .. 103 | Local $aRequest = _HTTP_ParseHttpRequest($sBuffer[$x]) 104 | $aContentLength = StringRegExp($sBuffer[$x], "(?m)^Content-Length: ([0-9]+)$", 1) 105 | If @error = 0 And Not ($aContentLength[0] >= BinaryLen(StringToBinary($aRequest[$HttpRequest_BODY]))) Then ContinueLoop ; If we havent gotten the complete request body yet, we process other requests and try again later. 106 | Else 107 | ContinueLoop 108 | EndIf 109 | 110 | If (StringLen($sBuffer[$x])>0) Then Debug("Starting processing request on position: "&$x) 111 | 112 | Assign("x", $x, BitOR($ASSIGN_FORCEGLOBAL, $ASSIGN_EXISTFAIL)) ; NOTE $x is forced local, when used in For loop above. This gives issues when other functions need the $x value. 113 | $_HTTP_Server_Request_Handler($aSocket[$x], $sBuffer[$x]) 114 | 115 | TCPCloseSocket($aSocket[$x]) 116 | $aSocket[$x] = -1 ; the socket is closed so we reset the socket so that we may accept new clients 117 | $sBuffer[$x] = "" ; clears the buffer because we just used to buffer and did some actions based on them 118 | Next 119 | 120 | Sleep(10) 121 | WEnd 122 | EndFunc 123 | 124 | Func _HTTP_SendHeaders($hSocket, $headers = "", $status = $HTTP_STATUS_200) 125 | $headers = _HTTP_MergeHttpHeaders( _ 126 | "HTTP/1.1 " & $status & @LF & _ 127 | "Server: " & $sServerName & @LF & _ 128 | "Connection: close" & @LF & _ 129 | "Content-Type: text/plain; charset=UTF-8" & @LF, _ 130 | $headers _ 131 | ) 132 | 133 | $headers = $headers & @LF 134 | 135 | _HTTP_SendContent($hSocket, $headers) 136 | EndFunc 137 | 138 | Func _HTTP_SendContent($hSocket, $bData) 139 | Local $a 140 | If Not IsBinary($bData) Then $bData = Binary($bData) 141 | While BinaryLen($bData) ; Send data in chunks (most code by Larry) 142 | $a = TCPSend($hSocket, $bData) ; TCPSend returns the number of bytes sent 143 | If @error <> 0 Then 144 | Return;FIXME: if client disconnects early this line is needed, to avoid endless loop, but need to check "Windows Sockets Error Codes" for potential non exitloop issues, like BUSY state. 145 | EndIf 146 | $bData = BinaryMid($bData, $a+1, BinaryLen($bData)-$a) 147 | WEnd 148 | EndFunc 149 | 150 | Func _HTTP_SendChunk($hSocket, $bData) 151 | If IsBinary($bData) Then $bData = BinaryToString($bData) 152 | _HTTP_SendContent($hSocket, StringRegExpReplace(Hex(BinaryLen($bData)), "^0+", "")&@CRLF&$bData&@CRLF) 153 | EndFunc 154 | 155 | Func _HTTP_EndChunk($hSocket) 156 | _HTTP_SendContent($hSocket, "0"&@CRLF&@CRLF) 157 | EndFunc 158 | 159 | Func _HTTP_SendHTML($hSocket, $sHTML, $sReply = "200 OK") ; sends HTML data on X socket 160 | _HTTP_SendData($hSocket, Binary($sHTML), "text/html", $sReply) 161 | EndFunc 162 | 163 | Func _HTTP_SendFile($hSocket, $sFileLoc, $sMimeType = Default, $sReply = "200 OK", $bLastModified=False) ; Sends a file back to the client on X socket, with X mime-type 164 | Local $hFile, $aFileLastModified 165 | Local Static $wDays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], $months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] 166 | If $sMimeType==Default Then 167 | Local $aRet = DllCall("urlmon.dll", "long", "FindMimeFromData", "ptr", 0, "wstr", $sFileLoc, "ptr", 0, "DWORD", 0, "ptr", 0, "DWORD", 0, "wstr*", 0, "DWORD", $FMFD_URLASFILENAME + $FMFD_RETURNUPDATEDIMGMIMES) 168 | $sMimeType = ((@error <> 0) Or ($aRet[7]=='0')) ? 'application/octet-stream' : $aRet[7] 169 | EndIf 170 | 171 | $hFile = FileOpen($sFileLoc,16) 172 | Local $bFileData = FileRead($hFile) 173 | FileClose($hFile) 174 | 175 | If $bLastModified Then $aFileLastModified = FileGetTime($sFileLoc, 0, 0) 176 | ;Debug($aFileLastModified) 177 | _HTTP_SendData($hSocket, $bFileData, $sMimeType, $sReply, $bLastModified?StringFormat("%s, %s %s %s %s:%s:%s GMT", $wDays[_DateToDayOfWeek($aFileLastModified[0], $aFileLastModified[1], $aFileLastModified[2])-1], $aFileLastModified[2], $months[$aFileLastModified[1]-1], $aFileLastModified[0], $aFileLastModified[3], $aFileLastModified[4], $aFileLastModified[5]):"") 178 | EndFunc 179 | 180 | #cs 181 | # @deprecated 182 | #ce 183 | Func _HTTP_SendData($hSocket, $bData, $sMimeType, $sReply = $HTTP_STATUS_200, $sLastModified = ""); FIXME: currently no headers are sent! 184 | Local $a 185 | Local $sPacket = Binary("HTTP/1.1 " & $sReply & @LF & _ 186 | "Server: " & $sServerName & @LF & _ 187 | "Connection: close" & @LF & _ 188 | "Content-Length: " & BinaryLen($bData) & @LF & _ 189 | "Content-Type: " & $sMimeType & "; charset=UTF-8" & @LF & _ 190 | (($sLastModified="")?"":"Last-Modified: "&$sLastModified&@LF)& _ 191 | @LF) 192 | ;[set non-blocking mode] ;TODO: the blocking mode currently will result in the connection closing before the client getting all data. there is also a concern taht we don't check if the TCP buffer is full while pushing data. Until a good solution for this is found, async data transfer will be disabled. 193 | ;Local $aResult = DllCall("ws2_32.dll", 'int', 'ioctlsocket', 'int', $hSocket, 'long', 0x8004667E, 'ulong*', 1) 194 | ;Local $aResult = DllCall("ws2_32.dll", 'int', 'ioctlsocket', 'int', $hSocket, 'long', 0x4010, 'ulong*', 1);IPX_IMMEDIATESPXACK 195 | 196 | Local $tBuffer = DllStructCreate("BYTE[1000000]"); 1MB 197 | DllStructSetData($tBuffer, 1, $sPacket) 198 | 199 | Local $aResult = DllCall("ws2_32.dll", 'int', 'send', 'int', $hSocket, 'struct*', $tBuffer, 'int', BinaryLen($sPacket), 'int', 0) 200 | ;TCPSend($hSocket,$sPacket) ; Send start of packet 201 | 202 | While BinaryLen($bData) ; Send data in chunks (most code by Larry) 203 | DllStructSetData($tBuffer, 1, $bData) 204 | $aResult = DllCall("ws2_32.dll", 'int', 'send', 'int', $hSocket, 'struct*', $tBuffer, 'int', BinaryLen($bData)>DllStructGetSize($tBuffer)?DllStructGetSize($tBuffer):BinaryLen($bData), 'int', 0) 205 | ;$a = TCPSend($hSocket, $bData) ; TCPSend returns the number of bytes sent 206 | $a = $aResult[0] 207 | $bData = BinaryMid($bData, $a+1, BinaryLen($bData)-$a) 208 | WEnd 209 | 210 | ;[set blocking mode] 211 | ;$aResult = DllCall("ws2_32.dll", 'int', 'ioctlsocket', 'int', $hSocket, 'long', 0x8004667E, 'ulong*', 0) 212 | 213 | ;While True 214 | ; $aResult = DllCall("ws2_32.dll", 'int', 'recv', 'int', $hSocket, 'struct*', $tBuffer, 'int', 1024, 'int', 0) 215 | ;WEnd 216 | 217 | ;$sPacket = Binary(@CRLF & @CRLF) ; Finish the packet 218 | ;TCPSend($hSocket,$sPacket) 219 | EndFunc 220 | 221 | Func _HTTP_SendFileNotFoundError($hSocket) ; Sends back a basic 404 error 222 | Local $s404Loc = $sRootDir & "\404.html" 223 | If (FileExists($s404Loc)) Then 224 | _HTTP_SendFile($hSocket, $s404Loc, "text/html", "404 Not Found") 225 | Else 226 | _HTTP_SendHTML($hSocket, "404 Error: " & @CRLF & @CRLF & "The file you requested could not be found.", "404 Not Found") 227 | EndIf 228 | EndFunc 229 | 230 | #cs 231 | # Parse URI into segments 232 | # 233 | # @param string $uri The URI string to parse. 234 | # 235 | # @return array 236 | #ce 237 | Func _HTTP_ParseURI($uri, $decode = True) 238 | Local Static $define = "(?(DEFINE)(?(?:(?&absoluteURI)|(?&relativeURI))?(?:\#(?&fragment))?)(?(?&scheme)\:(?:(?&hier_part)|(?&opaque_part)))(?(?:(?&net_path)|(?&abs_path)|(?&rel_path))(?:\?(?&query))?)(?(?:(?&net_path)|(?&abs_path))(?:\?(?&query))?)(?(?&uric_no_slash)(?&uric)*)(?(?&unreserved)|(?&escaped)|[;?:@&=+$,])(?\/\/(?&authority)(?&abs_path)?)(?\/(?&path_segments))(?(?&rel_segment)(?&abs_path)?)(?(?:(?&unreserved)|(?&escaped)|[;@&=+$,])+)(?(?&alpha)((?&alpha)|(?&digit)|[+-.])*)(?(?&server)|(?®_name))(?(?:(?&unreserved)|(?&escaped)|[$,;:@&=+])+)(?(?:(?:(?&userinfo)\@)?(?&hostport))?)(?(?:(?&unreserved)|(?&escaped)|[;:&=+$,])*)(?(?&host)(?:\:(?&port))?)(?(?:(?&hostname)|(?&IPv4address)))(?(?:(?&domainlabel)\.)*(?&toplabel)\.?)(?(?:(?&alphanum)|(?&alphanum)(?:(?&alphanum)|\-)*(?&alphanum)))(?(?&alpha)|(?&alpha)((?&alphanum)|-)*(?&alphanum))(?(?&digit)+\.(?&digit)+\.(?&digit)+\.(?&digit)+)(?(?&digit)*)(?((?&abs_path)|(?&opaque_part))?)(?(?&segment)(?:\/(?&segment))*)(?(?&pchar)*(?:;(?¶m))*)(?(?&pchar)*)(?(?&unreserved)|(?&escaped)|[:@&=+$,])(?(?&uric)*)(?(?&uric)*)(?(?&reserved)|(?&unreserved)|(?&escaped))(?[;\/?:@&=+$,])(?(?&alphanum)|(?&mark))(?[-_.!~*'()])(?\%(?&hex)(?&hex))(?(?&digit)|[A-Fa-f])(?(?&alpha)|(?&digit))(?(?&lowalpha)|(?&upalpha))(?[a-z])(?[A-Z])(?[0-9]))" 239 | ;FIXME: add support for absoluteURI (currently having propblems around the -> with the uri "http://www.ics.uci.edu/Test/a/x", following http://www.ietf.org/rfc/rfc2396.txt) 240 | ;Local $aURI = StringRegExp($uri, $define&"");absoluteURI 241 | Local $aRelativeURI = StringRegExp($uri, $define&"((?&net_path)|(?&abs_path)|(?&rel_path))(?:\?((?&query)))?(\#(?&fragment))?", 1);relativeURI 242 | If @error <> 0 Then Return SetError(@error, @extended, Default) 243 | ;_ArrayDisplay($aRelativeURI) 244 | Local $aURI = ["", $aRelativeURI[43], UBound($aRelativeURI)>44?$aRelativeURI[44]:"", UBound($aRelativeURI)>45?$aRelativeURI[45]:""];NOTE: bug where non capturing groups are returned from RegExp @see https://www.autoitscript.com/trac/autoit/ticket/2696 245 | If $decode Then 246 | $aURI[$HttpUri_Path] = decodeURI($aURI[$HttpUri_Path]) 247 | $aURI[$httpUri_Query] = decodeURI(StringRegExpReplace($aURI[$httpUri_Query], "\+", " ")) 248 | EndIf 249 | Return $aURI 250 | EndFunc 251 | 252 | #cs 253 | # Parse HTTP request 254 | # 255 | # @param string $request The raw HTTP request string. 256 | # 257 | # @return array 258 | #ce 259 | Func _HTTP_ParseHttpRequest($request) 260 | Local $requestInfo = StringRegExp($request, "^([A-Z]+) ([^\x0D\x0A\x20]+) ([^\x0A]+)\x0A(?m)((?:^[A-Za-z\-]+\: [^\x0A]+$\x0D?\x0A)*\x0D?\x0A)(?s-m)(.*)$", 1) 261 | If @error <> 0 Then Return SetError(@error, @extended, Default) 262 | Return $requestInfo 263 | EndFunc 264 | 265 | #cs 266 | # Parse HTTP headers 267 | # 268 | # @param string $headers The raw HTTP headers 269 | # 270 | # @return array 271 | #ce 272 | Func _HTTP_ParseHttpHeaders($headers) 273 | Local $aHeaders = StringRegExp($headers, "(?m)^([A-Za-z\-]+)\: (.+)$", 3) 274 | If @error <> 0 Then Return SetError(@error, @extended, Default) 275 | Return $aHeaders 276 | EndFunc 277 | 278 | #cs 279 | # Parse HTTP status line 280 | # @param string $headers The raw HTTP head 281 | # @return string 282 | #ce 283 | Func _HTTP_ParseHttpStatusLine($headers) 284 | Local $aStatusLines = StringRegExp($headers, '(?m)^(HTTP\/[0-9](?:\.[0-9])? [0-9]{3} .*)$', 3) 285 | If @error <> 0 Then Return SetError(@error, @extended, '') 286 | Return UBound($aStatusLines, 1) > 0 ? SetExtended(UBound($aStatusLines, 1), $aStatusLines[UBound($aStatusLines, 1) - 1]) : SetExtended(0, '') 287 | EndFunc 288 | 289 | Func decodeURI($sString) 290 | Local $iLimit = 0 291 | Local $sPattern = "(?:%[0-9a-fA-F]{2})+" 292 | Local $iOffset = 1, $iDone = 0, $iMatchOffset 293 | 294 | Local $aRes, $sRet 295 | While True 296 | $aRes = StringRegExp($sString, $sPattern, 2, $iOffset) 297 | If @error Then ExitLoop 298 | 299 | $sRet = Call("UTF8ToString", $aRes[0]) 300 | If @error Then Return SetError(@error, $iDone, $sString) 301 | 302 | $iOffset = StringInStr($sString, $aRes[0], 1, 1, $iOffset) 303 | $sString = StringLeft($sString, $iOffset - 1) & $sRet & StringMid($sString, $iOffset + StringLen($aRes[0])) 304 | $iOffset += StringLen($sRet) 305 | 306 | $iDone += 1 307 | If $iDone = $iLimit Then ExitLoop 308 | WEnd 309 | 310 | Return SetExtended($iDone, $sString) 311 | EndFunc 312 | 313 | Func UTF8ToString($utf8) 314 | Local $parts = StringRegExp($utf8, "%([0-9a-fA-F]{2})", 3) 315 | Local $char2, $char3 316 | Local $i = 0 317 | Local $len = UBound($parts) 318 | Local $out = "" 319 | Local $c 320 | While $i < $len 321 | $c = Dec($parts[$i], 1) 322 | $i+=1 323 | Switch BitShift($c, 4) 324 | Case 0 To 7 325 | ; 0xxxxxxx 326 | $out &= ChrW($c) 327 | Case 12 To 13 328 | ; 110x xxxx 10xx xxxx 329 | $char2 = Dec($parts[$i], 1) 330 | $i+=1 331 | $out &= ChrW(BitOR(BitShift(BitAND($c, 0x1F), -6), BitAND($char2, 0x3F))) 332 | Case 14 333 | ; 1110 xxxx 10xx xxxx 10xx xxxx 334 | $char2 = Dec($parts[$i], 1) 335 | $i+=1 336 | $char3 = Dec($parts[$i], 1) 337 | $i+=1 338 | $out &= ChrW(BitOR(BitShift(BitAND($c, 0x0F), -12), BitShift(BitAND($char2, 0x3F), -6), BitShift(BitAND($char3, 0x3F), 0))) 339 | EndSwitch 340 | WEnd 341 | return $out 342 | EndFunc 343 | 344 | Func _HTTP_IndexDir($hSocket, $dir) 345 | _HTTP_SendHeaders($hSocket, "Content-Type: text/html"&@CRLF&"Transfer-Encoding: chunked") 346 | Local $title = "Index of "&StringRegExpReplace(StringRegExpReplace(StringTrimLeft($dir, StringLen($sRootDir)), "\\", "/"), "/$", "") 347 | _HTTP_SendChunk($hSocket, ''&$title&'') 348 | _HTTP_SendChunk($hSocket, "") 349 | _HTTP_SendChunk($hSocket, "

"&$title&'

');TODO: replace special charaters in $title within the h1 element with HTML escaped charaters 350 | Local $tData = DllStructCreate($tagWIN32_FIND_DATA) 351 | Local $sFile 352 | Local $hSearch = _WinAPI_FindFirstFile($dir&'*', $tData) 353 | While @error = 0 354 | $sFile = DllStructGetData($tData, 'cFileName') 355 | Switch $sFile 356 | Case '.', '..' 357 | Case Else 358 | If Not BitAND(DllStructGetData($tData, 'dwFileAttributes'), $FILE_ATTRIBUTE_DIRECTORY) Then 359 | _HTTP_SendChunk($hSocket, '') 360 | Else 361 | _HTTP_SendChunk($hSocket, '') 362 | EndIf 363 | EndSwitch 364 | _WinAPI_FindNextFile($hSearch, $tData) 365 | WEnd 366 | _WinAPI_FindClose($hSearch) 367 | _HTTP_SendChunk($hSocket, '
NameSize
..
'&$sFile&''&FileSizeForHumans(_WinAPI_MakeQWord(DllStructGetData($tData, 'nFileSizeLow'), DllStructGetData($tData, 'nFileSizeHigh')))&'
'&$sFile&'
Icons used are from the File Icon Images
') 368 | _HTTP_EndChunk($hSocket) 369 | EndFunc 370 | 371 | Func FileSizeForHumans($iSize) 372 | Local $iSizeGroup = Log($iSize) / log(1024) 373 | Local $iSizeGroupBase = Floor($iSizeGroup) 374 | Local $suffix 375 | Switch ($iSizeGroupBase) 376 | Case 0 377 | $suffix = "B" 378 | Case 1 379 | $suffix = "KiB" 380 | Case 2 381 | $suffix = "MiB" 382 | Case 3 383 | $suffix = "GiB" 384 | Case 4 385 | $suffix = "TiB" 386 | Case 5 387 | $suffix = "PiB" 388 | Case 6 389 | $suffix = "EiB" 390 | case 7 391 | $suffix = "ZiB" 392 | Case 8 393 | $suffix = "YiB" 394 | Case Else 395 | $suffix = "?" 396 | EndSwitch 397 | 398 | return StringFormat("%.2f %s", $iSize/1024^$iSizeGroupBase, $suffix) 399 | EndFunc 400 | 401 | Func _HTTP_CGI($sAppName, $sCommand = Null) 402 | local $stdinRd, $stdinWr 403 | Local $stdoutRd, $stdoutWr 404 | Local Static $stderr = _WinAPI_GetStdHandle(2) 405 | 406 | Local $STARTF_USESTDHANDLES = 0x100 407 | Local $STARTF_FORCEOFFFEEDBACK = 0x00000080 408 | Local $QUERY_STRING = $aUri[$httpUri_Query] 409 | ; Set up security attributes 410 | Local $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) 411 | DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) 412 | DllStructSetData($tSecurity, "InheritHandle", True) 413 | _NamedPipes_CreatePipe($stdinRd, $stdinWr, $tSecurity) 414 | _NamedPipes_CreatePipe($stdoutRd, $stdoutWr, $tSecurity) 415 | Local $tProcess = DllStructCreate($tagPROCESS_INFORMATION) 416 | Local $tStartup = DllStructCreate($tagSTARTUPINFO) 417 | DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) 418 | DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_FORCEOFFFEEDBACK)) 419 | DllStructSetData($tStartup, "StdInput", $stdinRd) 420 | DllStructSetData($tStartup, "StdOutput", $stdoutWr) 421 | DllStructSetData($tStartup, "StdError", $stderr) 422 | 423 | ; Local $tSockaddr = DllStructCreate("ushort sa_family;char sa_data[14];") 424 | Local $tSockaddr = DllStructCreate("short;ushort;uint;char[8]") 425 | Local $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $aSocket[$x], "ptr", DllStructGetPtr($tSockaddr), "int*", DllStructGetSize($tSockaddr)) 426 | Local $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($tSockaddr, 3)) 427 | Local $aPort = DllCall("Ws2_32.dll", "ushort", "htons", "ushort", DllStructGetData($tSockaddr, 2)) 428 | 429 | Local Static $tEnv = GetEnvString() 430 | 431 | Local $sEnviroment = _ 432 | "CONTENT_LENGTH="&StringLen($aRequest[$HttpRequest_BODY])&Chr(0)& _ 433 | "CONTENT_TYPE=application/x-www-form-urlencoded"&Chr(0)& _ 434 | "GATEWAY_INTERFACE=CGI/1.1"&Chr(0)& _ 435 | "QUERY_STRING="&$QUERY_STRING&Chr(0)& _ 436 | "REDIRECT_STATUS=200"&Chr(0)& _ 437 | "REMOTE_ADDR="&$aRet[0]&Chr(0)& _ 438 | "REQUEST_METHOD="&$aRequest[$HttpRequest_METHOD]&Chr(0)& _ 439 | "REQUEST_URI="&$aUri[$HttpUri_Path]&Chr(0)& _ 440 | "SCRIPT_NAME="&StringMid($sLocalPath,StringInStr($sLocalPath, "\", 0, -1)+1)&Chr(0)& _ 441 | "SCRIPT_FILENAME="&$sLocalPath&Chr(0)& _ 442 | "SERVER_ADDR="&$sIP&Chr(0)& _ 443 | "SERVER_PROTOCOL=HTTP/1.1"&Chr(0)& _ 444 | "SERVER_NAME=test"&Chr(0)& _ 445 | "SERVER_SOFTWARE="&$sServerName&Chr(0)& _ 446 | "DOCUMENT_ROOT="&_WinAPI_GetFullPathName($sRootDir & "\")&Chr(0)& _ 447 | "HTTP_ACCEPT="&Chr(0)& _ 448 | "HTTP_HOST="&Chr(0)& _ 449 | "SERVER_PORT="&$iPort&Chr(0)& _ 450 | "REMOTE_PORT="&$aPort[0]&Chr(0)& _ 451 | Chr(0) 452 | 453 | Local $tEnviroment=DllStructCreate("WCHAR["&((DllStructGetSize($tEnv)/2)+StringLen($sEnviroment))&"]") 454 | CopyMemory(DllStructGetPtr($tEnviroment), DllStructGetPtr($tEnv), DllStructGetSize($tEnv)) 455 | Local $tEnviroment2=DllStructCreate("WCHAR["&StringLen($sEnviroment)&"]", DllStructGetPtr($tEnviroment)+DllStructGetSize($tEnv)) 456 | DllStructSetData($tEnviroment2, 1, $sEnviroment) 457 | 458 | _WinAPI_CreateProcess($sAppName, $sCommand, $tSecurity, Null, True, $CREATE_NO_WINDOW+$NORMAL_PRIORITY_CLASS+$CREATE_UNICODE_ENVIRONMENT, DllStructGetPtr($tEnviroment), $sRootDir, DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) 459 | 460 | Local $hProcess = DllStructGetData($tProcess, "hProcess") 461 | _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) 462 | Local $tBuffer = DllStructCreate("char Text[4096]") 463 | Local $pBuffer = DllStructGetPtr($tBuffer) 464 | Local $iBytes 465 | Local $sBuffer = "" 466 | Local $bHeadersSent = False 467 | Local $i, $l 468 | 469 | local $Request_BODY = $aRequest[$HttpRequest_BODY] 470 | Local $Request_BODY_Length = StringLen($Request_BODY) 471 | Local $iToWrite = 4096 472 | Local $iWritten = 0 473 | 474 | While 1 475 | DllStructSetData($tBuffer, "Text", $Request_BODY) 476 | $iToWrite = $iToWrite <= $Request_BODY_Length ? $iToWrite : $Request_BODY_Length 477 | If Not _WinAPI_WriteFile($stdinWr, $pBuffer, $iToWrite, $iWritten) Then ExitLoop 478 | $Request_BODY = StringMid($Request_BODY, 1 + $iWritten) 479 | $Request_BODY_Length = StringLen($Request_BODY) 480 | if $Request_BODY_Length = 0 Then ExitLoop 481 | WEnd 482 | 483 | _WinAPI_CloseHandle($stdinRd) 484 | _WinAPI_CloseHandle($stdinWr) 485 | _WinAPI_CloseHandle($stdoutWr) 486 | While 1 487 | If Not _WinAPI_ReadFile($stdoutRd, $pBuffer, 4096, $iBytes) Then ExitLoop 488 | If $iBytes>0 Then 489 | If $bHeadersSent Then 490 | _HTTP_SendChunk($aSocket[$x], StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes)) 491 | Else 492 | $sBuffer &= StringLeft(DllStructGetData($tBuffer, "Text"), $iBytes) 493 | If StringInStr(StringStripCR($sBuffer),@LF&@LF) Then ; if the response headers are ready .. 494 | $bHeadersSent = True 495 | $l = StringRegExp($sBuffer, "\r?\n\r?\n", 1) 496 | $i = @extended 497 | $l = StringLen($l[0]) 498 | _HTTP_SendHeaders($aSocket[$x], "Cache-Control: no-store, max-age=0"&@LF&"Transfer-Encoding: chunked"&@LF&StringLeft($sBuffer, $i-3)) 499 | if StringLen($sBuffer) > $i Then _HTTP_SendChunk($aSocket[$x], StringMid($sBuffer, $i)) 500 | $sBuffer = Null; to try and free up some space 501 | EndIf 502 | EndIf 503 | EndIf 504 | WEnd 505 | 506 | _HTTP_EndChunk($aSocket[$x]) 507 | TCPCloseSocket($aSocket[$x]) 508 | _WinAPI_CloseHandle($hProcess) 509 | _WinAPI_CloseHandle($stdoutRd) 510 | EndFunc 511 | 512 | Func _HTTP_GCI_PHP() 513 | Return _HTTP_CGI($PHP_Path&"\php-cgi.exe") 514 | EndFunc 515 | 516 | Func _HTTP_GCI_AU3() 517 | Return _HTTP_CGI($AU3_Path&"\AutoIt3.exe", "/ErrorStdOut """ & $sLocalPath & """ >") 518 | EndFunc 519 | 520 | Func Debug($vLog, $nl = True, $ln = @ScriptLineNumber) 521 | Local Static $time = TimerInit() 522 | If @Compiled Then Return 523 | ConsoleWrite(StringFormat("(%04s) %s %+dms%s", $ln, $vLog, TimerDiff($time), $nl ? @CRLF : "")) 524 | EndFunc 525 | 526 | #cs 527 | # Merge two header strings 528 | # 529 | # The header strings are allowed to contain the HTTP status line. 530 | # Likewise this function also returns a header line, if one of the two headers contained one. 531 | # 532 | # @param string $headers1 533 | # @param string $headers2 534 | # 535 | # @return string merged headers 536 | #ce 537 | Func _HTTP_MergeHttpHeaders($headers1, $headers2) 538 | Local $headers = "" 539 | ; NOTE: status line is not part of the "headers" directly, but part of head. 540 | Local $statusLine1 = _HTTP_ParseHttpStatusLine($headers1) 541 | Local $statusLine2 = _HTTP_ParseHttpStatusLine($headers2) 542 | $headers1 = _HTTP_ParseHttpHeaders($headers1) 543 | $headers2 = _HTTP_ParseHttpHeaders($headers2) 544 | For $i=0 To UBound($headers1, 1)-1 Step +2 545 | For $j=0 To UBound($headers2, 1)-1 Step +2 546 | If StringLower($headers1[$i]) = "set-cookie" Then ContinueLoop 1 547 | If StringLower($headers1[$i]) = StringLower($headers2[$j]) Then 548 | $headers &= StringFormat("%s: %s%s", $headers2[$j], $headers2[$j+1], @LF) 549 | ContinueLoop 2 550 | EndIf 551 | If StringLower($headers1[$i]) = "status" Then 552 | $statusLine1 = StringFormat("%s %s", 'HTTP/1.1', $headers1[$i+1]) 553 | ContinueLoop 2 554 | EndIf 555 | Next 556 | $headers &= StringFormat("%s: %s%s", $headers1[$i], $headers1[$i+1], @LF) 557 | Next 558 | 559 | For $i=0 To UBound($headers2, 1)-1 Step +2 560 | For $j=0 To UBound($headers1, 1)-1 Step +2 561 | If StringLower($headers2[$i]) = "set-cookie" Then ContinueLoop 1 562 | If StringLower($headers1[$j]) = StringLower($headers2[$i]) Then ContinueLoop 2 563 | If StringLower($headers2[$i]) = "status" Then 564 | $statusLine2 = StringFormat("%s %s", 'HTTP/1.1', $headers2[$i+1]) 565 | ContinueLoop 2 566 | EndIf 567 | Next 568 | $headers &= StringFormat("%s: %s%s", $headers2[$i], $headers2[$i+1], @LF) 569 | Next 570 | 571 | $statusLine2 = ($statusLine2 == "") ? $statusLine1 : $statusLine2 572 | $statusLine2 = ($statusLine2 == "") ? "HTTP/1.1 "&$HTTP_STATUS_200 : $statusLine2 573 | $headers = StringFormat('%s%s', $statusLine2, @LF) & $headers 574 | 575 | Return $headers 576 | EndFunc 577 | 578 | Func GetEnvString() 579 | Local $len = 0, $t 580 | Local $pEnv = GetEnvironmentStringsW() 581 | Local $pItem = $pEnv 582 | While 1 583 | $len = wcslen($pItem) 584 | If $len <= 0 Then ExitLoop 585 | $pItem = $pItem + $len * 2 + 2 586 | WEnd 587 | 588 | $len = int($pItem, 2)-int($pEnv, 2) 589 | local $tEnv = DllStructCreate("WCHAR["&($len/2)&"]") 590 | 591 | CopyMemory(DllStructGetPtr($tEnv, 1), $pEnv, $len) 592 | 593 | FreeEnvironmentStringsW($pEnv) 594 | 595 | Return $tEnv 596 | EndFunc 597 | 598 | Func GetEnvironmentStringsW() 599 | Local $aRet = DllCall('Kernel32.dll', 'ptr', 'GetEnvironmentStringsW') 600 | 601 | If @error <> 0 Then Return SetError(@error, @extended, 0) 602 | If $aRet[0] = 0 Then Return SetError(1, 0, 0) 603 | 604 | Return $aRet[0] 605 | EndFunc 606 | 607 | Func FreeEnvironmentStringsW($penv) 608 | Local $aRet = DllCall('Kernel32.dll', 'BOOLEAN', 'FreeEnvironmentStringsW', 'ptr', $penv) 609 | 610 | If @error <> 0 Then Return SetError(@error, @extended, 0) 611 | If $aRet[0] = 0 Then Return SetError(1, 0, 0) 612 | 613 | Return $aRet[0] 614 | EndFunc 615 | 616 | Func wcslen($pWString) 617 | Local $aCall = DllCall("ntdll.dll", "dword:cdecl", "wcslen", "ptr", $pWString) 618 | 619 | Return $aCall[0] 620 | EndFunc 621 | 622 | Func CopyMemory($destination, $source, $length) 623 | _MemMoveMemory($source, $destination, $length) 624 | 625 | If @error <> 0 Then Return SetError(@error, @extended, 0) 626 | 627 | Return 1 628 | EndFunc 629 | 630 | Func _HTTP_Server_Request_Handle($hSocket, $sRequest) 631 | $aRequest = _HTTP_ParseHttpRequest($sRequest) 632 | $aHeaders = _HTTP_ParseHttpHeaders($aRequest[$HttpRequest_HEADERS]) 633 | $aUri = _HTTP_ParseURI($aRequest[$HttpRequest_URI]) 634 | 635 | Debug("aUri[Path]: "&$aUri[$HttpUri_Path]) 636 | ;Debug("aUri[Query]: "&$aUri[$httpUri_Query]) 637 | ;Debug("LocalPath: " & _WinAPI_GetFullPathName($sRootDir & "\" & $aUri[$HttpUri_Path])) 638 | 639 | Switch $aRequest[$HttpRequest_METHOD] 640 | ;Case "HEAD" 641 | ;TODO 642 | Case "POST" 643 | ContinueCase 644 | Case "GET" 645 | $sRequest = $aUri[$HttpUri_Path]; let's see what file he actually wants 646 | ;FIXME: if codeblock below: disallows any dot files like .htaccess 647 | If StringInStr(StringReplace($sRequest,"\","/"), "/.") Then ; Disallow any attempts to go back a folder 648 | _HTTP_SendFileNotFoundError($aSocket[$x]) ; sends back an error 649 | Else 650 | $sLocalPath = _WinAPI_GetFullPathName($sRootDir & "\" & $sRequest);TODO: replace every instance of ($sRootDir & "\" & $sRequest) with $sLocalPath 651 | Select 652 | Case StringInStr(FileGetAttrib($sLocalPath),"D")>0 ;user has requested a directory 653 | Local $iStart=1 654 | Local $iEnd=StringInStr($DirectoryIndex, ",")-$iStart 655 | Local $sIndex 656 | If Not (StringRight($sLocalPath, 1)="\") Then $sLocalPath &= "\" 657 | While 1 658 | $sIndex=StringMid($DirectoryIndex, $iStart, $iEnd) 659 | If FileExists($sLocalPath & $sIndex ) Then ExitLoop 660 | If $iEnd<1 Then ExitLoop 661 | $iStart=$iStart+$iEnd+1 662 | $iEnd=StringInStr($DirectoryIndex, ",", 0, 1, $iStart) 663 | $iEnd=$iEnd>0?$iEnd-$iStart:$iEnd-1 664 | WEnd 665 | 666 | If Not FileExists($sLocalPath&$sIndex) Then 667 | If $bAllowIndexes Then;And FileExists(@ScriptDir & "\index.php") Then 668 | _HTTP_IndexDir($aSocket[$x], $sLocalPath) 669 | Else 670 | _HTTP_SendHTML($aSocket[$x], "403 Forbidden", "403 Forbidden") 671 | EndIf 672 | Else 673 | $sLocalPath = $sLocalPath&$sIndex 674 | ContinueCase 675 | EndIf 676 | Case FileExists($sLocalPath) ; makes sure the file that the user wants exists 677 | Local $iFileType = StringInStr($sLocalPath, ".", 0, -1) 678 | Local $sFileType = $iFileType>0 ? StringMid($sLocalPath,$iFileType+1) : "" 679 | If $sFileType = "php" And Not $PHP_Path = "" Then 680 | _HTTP_GCI_PHP() 681 | ElseIf $sFileType = "au3" And Not $AU3_Path = "" Then 682 | _HTTP_GCI_AU3() 683 | Else 684 | _HTTP_SendFile($aSocket[$x], $sLocalPath, Default, "200 OK", True) 685 | EndIf 686 | Case Else 687 | _HTTP_SendFileNotFoundError($aSocket[$x]) ; File does not exist, so we'll send back an error.. 688 | EndSelect 689 | EndIf 690 | Case Else 691 | _HTTP_SendHTML($aSocket[$x], "", "501 Not Implemented") 692 | EndSwitch 693 | EndFunc 694 | -------------------------------------------------------------------------------- /main.au3: -------------------------------------------------------------------------------- 1 | #include "Server.au3" 2 | 3 | Opt("WinWaitDelay", 10) 4 | Opt("GUIOnEventMode", 1) 5 | Opt("TrayAutoPause", 0) 6 | Opt("TrayOnEventMode", 1) 7 | Opt("TrayMenuMode", 2+8) 8 | 9 | ;TODO: add server gui 10 | 11 | LoadSettings() 12 | 13 | ;Setup tray menu items 14 | Global Const $iTrayItemPause = 4 15 | Global Const $iTrayItemExit = 3 16 | Global Const $iTrayItemBrowser = TrayCreateItem("Open in browser") 17 | Global Const $iTrayItemReload = TrayCreateItem("Reload settings") 18 | TrayItemSetText($iTrayItemPause, "Pause") 19 | TrayItemSetText($iTrayItemExit, "Exit") 20 | 21 | TrayItemSetOnEvent($iTrayItemBrowser, "OpenInBrowser") 22 | TrayItemSetOnEvent($iTrayItemReload, "LoadSettings") 23 | 24 | Func OpenInBrowser() 25 | ShellExecute("http://localhost:"&$iPort&"/") 26 | EndFunc 27 | 28 | Func LoadSettings() 29 | Local $sIniFile = _WinAPI_GetFullPathName("settings.ini") 30 | If Not @Compiled Then ConsoleWrite(StringFormat('Reading settings from: "%s"\n', $sIniFile)) 31 | 32 | $sRootDir = _WinAPI_GetFullPathName(IniRead($sIniFile, "core", "RootDir", '.\www\')); The absolute path to the root directory of the server. 33 | $sIP = IniRead($sIniFile, "core", "IP", $sIP); http://localhost/ and more 34 | $iPort = Int(IniRead($sIniFile, "core", "Port", $iPort)); the listening port 35 | $iMaxUsers = Int(IniRead($sIniFile, "core", "MaxUsers", $iMaxUsers)); Maximum number of users who can simultaneously get/post 36 | $DirectoryIndex=IniRead($sIniFile, "core", "DirectoryIndex", $DirectoryIndex) 37 | $bAllowIndexes=IniRead($sIniFile, "core", "AllowIndexes", $bAllowIndexes) 38 | 39 | $PHP_Path = IniRead($sIniFile, "PHP", "Path", $PHP_Path) 40 | $AU3_Path = IniRead($sIniFile, "AU3", "Path", $AU3_Path) 41 | 42 | If $iMaxUsers<1 Then Exit MsgBox(0x10, "AutoIt HTTP Sever", "MaxUsers is less than one."&@CRLF&"The server will now close") 43 | If $DirectoryIndex = "" Then $DirectoryIndex = "index.html" 44 | 45 | If Not ($PHP_Path="") Then 46 | $PHP_Path=_WinAPI_GetFullPathName($PHP_Path&"\") 47 | If Not FileExists($PHP_Path&"php-cgi.exe") Then $PHP_Path="" 48 | EndIf 49 | 50 | If Not ($AU3_Path="") Then 51 | $AU3_Path=_WinAPI_GetFullPathName($AU3_Path&"\") 52 | If Not FileExists($AU3_Path&"AutoIt3.exe") Then $AU3_Path="" 53 | EndIf 54 | 55 | If IsString($bAllowIndexes) Then $bAllowIndexes=((StringLower($bAllowIndexes)=="true")?True : False) 56 | EndFunc 57 | 58 | ; Here we can override the default request handler 59 | ;$_HTTP_Server_Request_Handler = MyHandler 60 | 61 | _HTTP_Server_Start() 62 | 63 | Func MyHandler($hSocket, $sRequest) 64 | If Not StringRegExp($sRequest, "(?i)^GET /auth/? ") Then Return _HTTP_Server_Request_Handle($hSocket, $sRequest) 65 | 66 | ; We reach this part if the uri equals /auth/ 67 | 68 | $aRequest = _HTTP_ParseHttpRequest($sRequest) 69 | $aHeaders = _HTTP_ParseHttpHeaders($aRequest[$HttpRequest_HEADERS]) 70 | ;$aUri = _HTTP_ParseURI($aRequest[$HttpRequest_URI]) 71 | 72 | Local $bAuthenticated = False 73 | Local $bTried = False 74 | Local $i 75 | For $i = 0 To UBound($aHeaders, 1) - 1 Step +2 76 | ConsoleWrite($aHeaders[$i]&@CRLF) 77 | If Not (StringLower($aHeaders[$i]) == "authorization") Then ContinueLoop 78 | $bTried = True 79 | Local $aAuth = StringSplit($aHeaders[$i + 1], " ", 2) 80 | If Not (StringLower($aAuth[0]) == "basic") Then ContinueLoop 81 | If Not ($aAuth[1] == "Z3Vlc3Q6Z3Vlc3Q=") Then ContinueLoop 82 | $bAuthenticated = True 83 | Next 84 | 85 | If $bAuthenticated Then 86 | _HTTP_SendHeaders($hSocket) 87 | _HTTP_SendContent($hSocket, "Valid credentials") 88 | ;ElseIf $bTried Then 89 | ; _HTTP_SendHeaders($hSocket, "", "403 Forbidden") 90 | ; _HTTP_SendContent($hSocket, "Invalid credentials") 91 | Else 92 | _HTTP_SendHeaders($hSocket, 'WWW-Authenticate: Basic realm="user: guest pass: guest", charset="UTF-8"'&@LF, "401 Unauthorized") 93 | _HTTP_SendContent($hSocket, "validation required") 94 | EndIf 95 | EndFunc 96 | -------------------------------------------------------------------------------- /settings.ini: -------------------------------------------------------------------------------- 1 | [core] 2 | IP=0.0.0.0 3 | Port=80 4 | RootDir=www 5 | MaxUsers=15 6 | ErrorDocument404=404.html 7 | DirectoryIndex=index.html,index.php,index.au3 8 | AllowIndexes=True 9 | [PHP] 10 | Path=php-7.2.14-Win32-VC15-x64 11 | [AU3] 12 | Path=autoit-v3.3.14.5 -------------------------------------------------------------------------------- /www/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius257/AutoIt-HTTP-Server/07ed9536ccef9498309747737c7a10c57c10440a/www/favicon.ico -------------------------------------------------------------------------------- /www/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/genius257/AutoIt-HTTP-Server/07ed9536ccef9498309747737c7a10c57c10440a/www/img/logo.png -------------------------------------------------------------------------------- /www/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 18 | 22 | 23 | 27 | 31 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /www/index.au3: -------------------------------------------------------------------------------- 1 | ;$hSTDOUT = DllCall("Kernel32.dll", "ptr", "GetStdHandle", "DWORD", -11) 2 | ;MsgBox(0, "", $hSTDOUT[0]) 3 | ;FileWrite($hSTDOUT[0], "test") 4 | 5 | ConsoleWrite("X-Powered-By: AutoIt/"&@AutoItVersion&@LF) 6 | ConsoleWrite("Content-type: text/html; charset=UTF-8"&@LF) 7 | ConsoleWrite(@LF) 8 | 9 | ConsoleWrite("") 10 | ConsoleWrite("") 11 | ConsoleWrite("") 12 | ConsoleWrite("") 13 | ConsoleWrite("this is a test") 14 | ConsoleWrite("") 15 | ConsoleWrite("") 16 | -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 93 | 94 | 95 |
96 | 113 | 114 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /www/index.php: -------------------------------------------------------------------------------- 1 |