Jump to content
jvanegmond

Powerful HTTP Server in Pure AutoIt

Recommended Posts

That's not correct. 2001:5c0:1400:b::95bf is a IPv6 address.

You are right, but the posted IP address is what should work for the given A record.

Jos :x


SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

Sup,

Could you by any chance add the sessions server to the first spot?

I use your server allot and i have to look for the sessions server everytime.

Not really needed would appreciated though...

And well of course thanks allot for making this Webserver!!

Share this post


Link to post
Share on other sites

Hi Manadar,

FYI

I have taken the liberty of modifying the source and added anti-ddos module, this one is for a personal project. For Anti-DDOS Module it still under development , moreover initial tests were conducted using LOIC with satisfactory results.

Regards

Deltarocked.

[EDIT]

Note: Apache crashed within 2 seconds and messed up my system too

Edited by DeltaRocked

Share this post


Link to post
Share on other sites

Hi trancexx,

the code hasn't been uploaded yet - integration of essentials are still remaining eg. IP blocking. Content Verification and Request Validation completed. Previous Post was an informative one.

Re: Apache: it crashes , hangs up the system , it just cannot handle and this for me is a system mess. Presently testing Apache with mod_evasive module enabled and with correct configuration.

NOTE:

1: LOIC Config : 1000 threads with Full Throttle enabled.

2: System Specs: Pentium Dual core with 4 GB Physical RAM

Regards

Deltarocked

Edited by DeltaRocked

Share this post


Link to post
Share on other sites

But are you running Apache or Manadar's server? ...and I meant what system? Like what system. Like Windows 95, Windows 7, 8, etc...

Do you plan to show the code for the rest of us to benefit? I find the subject very interesting.

Edited by trancexx

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Hi Trancexx,

System is Windows 2003 Server --> thats the testing platform and its not a production server.

Am using both the Apache and Manadar's http server for testing , but one at a time.

Source-Code : will share it as soon as its finished (like all my other source-codes which you will find in this forum :)

PS: I have also implemented multiple web-site hoisting using Manadar's  code

To Do this :

Grab the HTTP response received from the Client ie. Browser
 

GET / HTTP/1.1
Host: x0x0.yoyo.com
User-Agent: Mozilla/5.0 (Windows NT 5.2; rv:22.0) Gecko/20100101 Firefox/22.0

.....

 

"Host:" is the FQDN requested by the client. hence essentially, you need to create an array of domains currently hosted on the server and then modify the $sRootdir within the loop to correspond with the requested FQDN and its associated path on the file system. So small modification will allow you to host multiple domains on a single server

Anti-DDOS Method in a gist:

Before using TcpRecv to receive the HTTP content, grab the IP using SocketToIP() (picked up from TCPRecv eg) store the IP and kick in the DDOS Module. In Apache, after the headers are received the DDOS kicks into action. Over here we simply do this task at time of Socket creation.

After TCPRecv receive we validate the headers - if found incorrect -- simply close the socket and proceed ahead. This way you are skipping a lot of code processing and saving time.

The ideology is similar to manner in which we handle exceptions.

Secondly, how we perceive a DDOS attack differs from person to person. This above method doesn't stop DNS R-DDOS  (reflective DDOS) as the ports are different and services running on these ports are different.

Any other questions / queries , please ask.

regards

DeltaRocked

Share this post


Link to post
Share on other sites

Any other questions / queries , please ask.

Oh I have plethora of questions, but before the questions I would like to see some code so that I can confirm your credibility. Words are just words.

♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Added: Multiple web-hosting

#cs
    Resources:
    Internet Assigned Number Authority - all Content-Types: http://www.iana.org/assignments/media-types/
    World Wide Web Consortium - An overview of the HTTP protocol: http://www.w3.org/Protocols/

    Credits:
    Manadar for starting on the webserver.
    Alek for adding POST and some fixes
    Creator for providing the "application/octet-stream" MIME type.
#ce

#include <Misc.au3> ; Only used for _Iif
#include <Array.au3>

; // OPTIONS HERE //
Local $sRootDir = @ScriptDir & "\" ; The absolute path to the root directory of the server.
Local $sIP = @IPAddress1 ; ip address as defined by AutoIt
Local $iPort = 80 ; the listening port
Local $sServerAddress = "http://" & $sIP & ":" & $iPort & "/"
Local $iMaxUsers = 15 ; Maximum number of users who can simultaneously get/post
Local $sServerName = "ManadarX/1.1 (" & @OSVersion & ") AutoIt " & @AutoItVersion
; // END OF OPTIONS //

Local $aSocket[$iMaxUsers] ; Creates an array to store all the possible users
Local $sBuffer[$iMaxUsers] ; All these users have buffers when sending/receiving, so we need a place to store those
Local $sDomain = '' ;which domain has been requested by the client

For $x = 0 To UBound($aSocket) - 1 ; Fills the entire socket array with -1 integers, so that the server knows they are empty.
    $aSocket[$x] = -1
Next

TCPStartup() ; AutoIt needs to initialize the TCP functions

$iMainSocket = TCPListen($sIP, $iPort) ;create main listening socket
If @error Then ; if you fail creating a socket, exit the application
    MsgBox(0x20, "AutoIt Webserver", "Unable to create a socket on port " & $iPort & ".") ; notifies the user that the HTTP server will not run
    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.
EndIf


ConsoleWrite("Server created on " & $sServerAddress & @CRLF) ; If you're in SciTE,

While 1
    $iNewSocket = TCPAccept($iMainSocket) ; Tries to accept incoming connections

    If $iNewSocket >= 0 Then ; Verifies that there actually is an incoming connection
        For $x = 0 To UBound($aSocket) - 1 ; Attempts to store the incoming connection
            If $aSocket[$x] = -1 Then
                $aSocket[$x] = $iNewSocket ;store the new socket
                ExitLoop
            EndIf
        Next
    EndIf

    For $x = 0 To UBound($aSocket) - 1 ; A big loop to receive data from everyone connected
        If $aSocket[$x] = -1 Then ContinueLoop ; if the socket is empty, it will continue to the next iteration, doing nothing
        $sNewData = TCPRecv($aSocket[$x], 1024) ; Receives a whole lot of data if possible
;~      ConsoleWrite($sNewData & @CRLF)
        If @error Then ; Client has disconnected
            $aSocket[$x] = -1 ; Socket is freed so that a new user may join
            ContinueLoop ; Go to the next iteration of the loop, not really needed but looks oh so good
        ElseIf $sNewData Then ; data received
            $sBuffer[$x] &= $sNewData ;store it in the buffer
            If StringInStr(StringStripCR($sBuffer[$x]), @LF & @LF) Then ; if the request has ended ..
                $sFirstLine = StringLeft($sBuffer[$x], StringInStr($sBuffer[$x], @LF)) ; helps to get the type of the request
                $sRequestType = StringLeft($sFirstLine, StringInStr($sFirstLine, " ") - 1) ; gets the type of the request
                If $sRequestType = "GET" Then ; user wants to download a file or whatever ..
                    $sRequest = StringTrimRight(StringTrimLeft($sFirstLine, 4), 11) ; let's see what file he actually wants
                    If StringInStr(StringReplace($sRequest, "\", "/"), "/.") Then ; Disallow any attempts to go back a folder
                        _HTTP_SendFileNotFoundError($aSocket[$x]) ; sends back an error
                    Else
                        If $sRequest = "/" Then ; user has requested the root
                            $sRequest = "/index.html" ; instead of root we'll give him the index page
                        EndIf
                        $sRequest = StringReplace($sRequest, "/", "\") ; convert HTTP slashes to windows slashes, not really required because windows accepts both
                        $sDomain = StringRegExp($sNewData, '(?i)host:(.*)', 3) ; extract the fqdn from the client request
                        $sRootDir &= IniRead('hosts.ini', 'hosts', StringStripWS($sDomain[0], 3), 'www') ; construct the path
                        ConsoleWrite('$sRootDir ' & $sRootDir & @CRLF)
                        If FileExists($sRootDir & $sRequest) Then ; makes sure the file that the user wants exists
                            $sFileType = StringRight($sRequest, 4) ; determines the file type, so that we may choose what mine type to use
                            ConsoleWrite($sRootDir & $sRequest & @CRLF)
                            Switch $sFileType
                                Case "html", ".htm" ; in case of normal HTML files
                                    _HTTP_SendFile($aSocket[$x], $sRootDir & $sRequest, "text/html")
                                Case ".css" ; in case of style sheets
                                    _HTTP_SendFile($aSocket[$x], $sRootDir & $sRequest, "text/css")
                                Case ".jpg", "jpeg" ; for common images
                                    _HTTP_SendFile($aSocket[$x], $sRootDir & $sRequest, "image/jpeg")
                                Case ".png" ; another common image format
                                    _HTTP_SendFile($aSocket[$x], $sRootDir & $sRequest, "image/png")
                                Case Else ; this is for .exe, .zip, or anything else that is not supported is downloaded to the client using a application/octet-stream
                                    _HTTP_SendFile($aSocket[$x], $sRootDir & $sRequest, "application/octet-stream")
                            EndSwitch
                        Else
                            _HTTP_SendFileNotFoundError($aSocket[$x]) ; File does not exist, so we'll send back an error..
                        EndIf
                    EndIf
                ElseIf $sRequestType = "POST" Then ; user has come to us with data, we need to parse that data and based on that do something special

                    $aPOST = _HTTP_GetPost($sBuffer[$x]) ; parses the post data

                    $sComment = _HTTP_POST("wintext", $aPOST) ; Like PHPs _POST, but it requires the second parameter to be the return value from _Get_Post

                    _HTTP_ConvertString($sComment) ; Needs to convert the POST HTTP string into a normal string

                    ConsoleWrite($sComment)
                    $sDomain = StringRegExp($sNewData, '(?i)host:(.*)', 3)
                    $sRootDir &= IniRead('hosts.ini', 'hosts', StringStripWS($sDomain[0], 3), 'www')
                    ConsoleWrite('$sRootDir ' & $sRootDir & @CRLF)
                    $data = FileRead($sRootDir & "\template.html")
                    $data = StringReplace($data, "<?au3 Replace me ?>", $sComment)
                    $h = FileOpen($sRootDir & "\index.html", 2)
                    FileWrite($h, $data)
                    FileClose($h)
                    $h = FileOpen($sRootDir & "\clean.html", 2)
                    FileWrite($h, $sComment)
                    FileClose($h)
                    _HTTP_SendFile($aSocket[$x], $sRootDir & "\index.html", "text/html") ; Sends back the new file we just created
                EndIf

                $sBuffer[$x] = "" ; clears the buffer because we just used to buffer and did some actions based on them
                $aSocket[$x] = -1 ; the socket is automatically closed so we reset the socket so that we may accept new clients

            EndIf
        EndIf
        $sRootDir = @ScriptDir & "\" ; since this is one huge loop where one socket is handled at a time , we have to reinitialise the path
    Next
    Sleep(10)
WEnd

Func _HTTP_ConvertString(ByRef $sInput) ; converts any characters like %20 into space 8)
    $sInput = StringReplace($sInput, '+', ' ')
    StringReplace($sInput, '%', '')
    For $t = 0 To @extended
        $Find_Char = StringLeft(StringTrimLeft($sInput, StringInStr($sInput, '%')), 2)
        $sInput = StringReplace($sInput, '%' & $Find_Char, Chr(Dec($Find_Char)))
    Next
EndFunc   ;==>_HTTP_ConvertString

Func _HTTP_SendHTML($hSocket, $sHTML, $sReply = "200 OK") ; sends HTML data on X socket
    _HTTP_SendData($hSocket, Binary($sHTML), "text/html", $sReply)
EndFunc   ;==>_HTTP_SendHTML

Func _HTTP_SendFile($hSocket, $sFileLoc, $sMimeType, $sReply = "200 OK") ; Sends a file back to the client on X socket, with X mime-type
    Local $hFile, $sImgBuffer, $sPacket, $a

    ConsoleWrite("Sending " & $sFileLoc & @CRLF)

    $hFile = FileOpen($sFileLoc, 16)
    $bFileData = FileRead($hFile)
    FileClose($hFile)

    _HTTP_SendData($hSocket, $bFileData, $sMimeType, $sReply)
EndFunc   ;==>_HTTP_SendFile

Func _HTTP_SendData($hSocket, $bData, $sMimeType, $sReply = "200 OK")
    $sPacket = Binary("HTTP/1.1 " & $sReply & @CRLF & _
            "Server: " & $sServerName & @CRLF & _
            "Connection: close" & @CRLF & _
            "Content-Lenght: " & BinaryLen($bData) & @CRLF & _
            "Content-Type: " & $sMimeType & @CRLF & _
            @CRLF)
    TCPSend($hSocket, $sPacket) ; Send start of packet

    While BinaryLen($bData) ; Send data in chunks (most code by Larry)
        $a = TCPSend($hSocket, $bData) ; TCPSend returns the number of bytes sent
        $bData = BinaryMid($bData, $a + 1, BinaryLen($bData) - $a)
    WEnd

    $sPacket = Binary(@CRLF & @CRLF) ; Finish the packet
    TCPSend($hSocket, $sPacket)

    TCPCloseSocket($hSocket)
EndFunc   ;==>_HTTP_SendData

Func _HTTP_SendFileNotFoundError($hSocket) ; Sends back a basic 404 error
    Local $s404Loc = $sRootDir & "\404.html"
    If (FileExists($s404Loc)) Then
        _HTTP_SendFile($hSocket, $s404Loc, "text/html")
    Else
        _HTTP_SendHTML($hSocket, "404 Error: " & @CRLF & @CRLF & "The file you requested could not be found.")
    EndIf
EndFunc   ;==>_HTTP_SendFileNotFoundError

Func _HTTP_GetPost($s_Buffer) ; parses incoming POST data
    Local $sTempPost, $sLen, $sPostData, $sTemp

    ; Get the lenght of the data in the POST
    $sTempPost = StringTrimLeft($s_Buffer, StringInStr($s_Buffer, "Content-Length:"))
    $sLen = StringTrimLeft($sTempPost, StringInStr($sTempPost, ": "))

    ; Create the base struck
    $sPostData = StringSplit(StringRight($s_Buffer, $sLen), "&")

    Local $sReturn[$sPostData[0] + 1][2]

    For $t = 1 To $sPostData[0]
        $sTemp = StringSplit($sPostData[$t], "=")
        If $sTemp[0] >= 2 Then
            $sReturn[$t][0] = $sTemp[1]
            $sReturn[$t][1] = $sTemp[2]
        EndIf
    Next

    Return $sReturn
EndFunc   ;==>_HTTP_GetPost

Func _HTTP_Post($sName, $sArray) ; Returns a POST variable like a associative array.
    For $i = 1 To UBound($sArray) - 1
        If $sArray[$i][0] = $sName Then
            Return $sArray[$i][1]
        EndIf
    Next
    Return ""
EndFunc   ;==>_HTTP_Post

The Hosts.ini - which is needed to define the domain-name and its associated path wrt @ScriptDir. ie. all the hosted domain folders should reside in the @ScriptDir path

[Hosts]
yoyo.com=yoyo
www.yoyo.com=yoyo
subdomain.yoyo.com=sub_yoyo
gogo.co.uk=gogo

Directory Structure

Directory of D:\webserver_011\Post_Server
<DIR>          gogo
<DIR>          sub_yoyo
<DIR>          www
<DIR>          yoyo
hosts.ini
server.au3

In order to successfully test this , you will have to modify the hosts file or add records for these domains in your DNS server.

eg.

192.168.93.145  localhost yoyo.com www.yoyo.com subdomain.yoyo.com gogo.co.uk

Re: Anti-DDOS -- some things are still remaining.

Edited by DeltaRocked

Share this post


Link to post
Share on other sites

Server sessions are broke in the code provided.  This is due to something wrong with requesting the cookie. May want to look into it.  I have got the script that does not have session and am implementing my own. When done i will post. The script is a little much for me to just look through and find what the issue is from a glance.  

 

 

Edit: Fixed some spelling. 

Edited by Kendall

Share this post


Link to post
Share on other sites

Hi,

Thanks Manadar and the other helpers who made all the perfect stuff.

I'm a hardware engineer and getting hard to understand how the web server works.

My main purpose is to build a simple function that gets TCP info from a server ( a cisco router ) and display it at the html.

I've tried to understand the topology of the SEND DATA function, but i really don't understand how i can insert Autoit variables to the HTML i see on the browser or how may I call the autoit function setting a "Button" at the HTML.

Your advice is welcomed,

Share this post


Link to post
Share on other sites
I have a script code like this (I took from VB6), if can convert to the input into autoit???
thanks
Option Explicit
Dim dataLokal(255) As String
Dim dataInject As String
Dim i, cek As Integer
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Sub Form_Load()
dataInject = "DELETE http://lowerping.com/ HTTP/1.1" & vbCr & "Host: lowerping.com" & vbCr & vbCr
End Sub

Private Sub sockLokal_ConnectionRequest(Index As Integer, ByVal requestID As Long)
i = i + 1
Load sockLokal(i)
Load sockProxy(i)
Load Timer1(i)
sockLokal(i).Close
sockLokal(i).Accept requestID
End Sub
Private Sub sockLokal_DataArrival(Index As Integer, ByVal bytesTotal As Long)
sockLokal(Index).GetData dataLokal(Index)
If InStr(dataLokal(Index), "GET ") > 0 Then
sockLokal(Index).Close
Exit Sub
End If
If sockProxy(Index).State = 0 Then
    sockProxy(Index).RemoteHost = "202.152.240.50"
    sockProxy(Index).RemotePort = 8080
    sockProxy(Index).Connect
End If
If sockProxy(Index).State = 7 Then
    sockProxy(Index).SendData dataLokal(Index)
End If
End Sub
Private Sub sockProxy_Connect(Index As Integer)
sockProxy(Index).SendData dataInject
cek = 0
Timer1(Index).Enabled = True
End Sub
Private Sub Timer1_Timer(Index As Integer)
If cek = 0 Then
    If sockProxy(Index).State = 7 Then
    Dim ubah As String
    ubah = Replace(dataLokal(Index), vbCrLf, vbCr)
        sockProxy(Index).SendData ubah
    End If
End If
Timer1(Index).Enabled = False
End Sub
Private Sub sockProxy_DataArrival(Index As Integer, ByVal bytesTotal As Long)
Dim dataProxy As String
sockProxy(Index).GetData dataProxy
If cek = 1 Then
    If sockLokal(Index).State = 7 Then
        sockLokal(Index).SendData dataProxy
    End If
Else
    cek = 1
End If
End Sub
Private Sub sockProxy_Close(Index As Integer)
sockProxy(Index).Close
sockLokal(Index).Close
End Sub
Private Sub tombol_Click()
Dim totalLokal As Integer
If tombol.Caption = "ON" Then
    tombol.Caption = "OFF"
    sockLokal(0).LocalPort = listenport.Text
    sockLokal(0).Listen
Else
    tombol.Caption = "ON"
    For totalLokal = 0 To sockLokal.Count - 1
    sockLokal(totalLokal).Close
    Next totalLokal
End If
End Sub

Share this post


Link to post
Share on other sites

Thanks for this, I needed a very simple server for a project and had no experience with http servers and this was very useful for me.

I think found a few random bugs?

Your "Content-Length" header is misspelled as "Content-Lenght" in all three of your servers. Also for some reason when I corrected this misspelling and ran your server through fiddler web debugger I get a warning that the content length is always incorrectly under-reported by 4 bytes. I am not sure exactly why except that maybe the last 2 @CRLF's are supposed to be included in the length which would be the 4 missing bytes?

In your basic server _HTTP_SendError() is not defined. Maybe it was supposed to be _HTTP_SendFileNotFoundError() ?

Edited by garbb

Share this post


Link to post
Share on other sites

After I found this very interesting web server, I did come up with an idea, ... :idea:
I think it would be very interesting to be able to use this little web server, in a way similar to PHP, but using AutoIt as embedded language instead.
for example, with PHP you can build on the server, the "final" web page that will be send to the browser by using PHP code embedded in the web page in a way like this:

<html>
 <head>
  <title>PHP Test</title>
 </head>
 <body>
 <?php echo '<p>Hello World</p>'; ?> // this will be replaced by the result of this php statements
 </body>
</html>

all the code between <?php and ?> , will be executed on the server by the php interpreter and the result of that code will replace the code itself, so the final web page that will be send to the browser will be this:

<html>
 <head>
  <title>PHP Test</title>
 </head>
 <body>
 <p>Hello World</p> // code generated on the server by php
 </body>
</html>

well, I'm wondering if it could be used AutoIt code in a way similar to php and make this web server capable of execute the code delimited by <?au3 and ?> for example.

just an idea (for now). Does someone have any suggestion if and how this purpose could be achieved?

Thanks

Edited by Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

After I found this very interesting web server, I did come up with an idea, ... :idea:

I think it would be very interesting to be able to use this little web server, in a way similar to PHP, but using AutoIt as embedded language instead.

for example, with PHP you can build on the server, the "final" web page that will be send to the browser by using PHP code embedded in the web page in a way like this:

<html>
 <head>
  <title>PHP Test</title>
 </head>
 <body>
 <?php echo '<p>Hello World</p>'; ?> // this will be replaced by the result of this php statements
 </body>
</html>

all the code between <?php and ?> , will be executed on the server by the php interpreter and the result of that code will replace the code itself, so the final web page that will be send to the browser will be this:

<html>
 <head>
  <title>PHP Test</title>
 </head>
 <body>
 <p>Hello World</p> // code generated on the server by php
 </body>
</html>

well, I'm wondering if it could be used AutoIt code in a way similar to php and make this web server capable of execute the code delimited by <?au3 and ?> for example.

just an idea (for now). Does someone have any suggestion if and how this purpose could be achieved?

Thanks

 

Look up AuCGI in the example script forum.


Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

Look up AuCGI in the example script forum.

 

Thanks SmOke_N for that link

AuCGI should give the functionality that I thought,

unfortunately, as from posts> #32 and >#33 in that >topic, it can't be used with this web server.

Anyway, I think that some parts of the AuCGI.au3 file could be useful to be ported here and adapted to this server...

expecially the _parseSource() function that extract from the source page the autoit code embedded between the <au3 and ?> tags.

I think that the pages with embedded autoit code should have an extension different from .htm or .html.

Maybe .au3 or something like that (as for php pages that has .php as extension), so that them could be

catched by Switch $sFileType in this server, parsed by the  _parseSource() function and merged/rebuilded again

with the resulting output of the embedded autoit code.

I will look into the matter to see if I will came out some idea (and some result)...

thanks again

edit:

p.s.

I really would like to be able to use this server with web pages with AutoIt+SQLite code embedded....

Edited by Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

Seems like a cool idea, Chimp! Implementation sounds good too.

I'm going to be putting this on GitHub. Seems like a good idea to. You can fork the project easily once I do that.

All the best and have fun. : )

Edited by Manadar

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...