james3mg Posted November 21, 2008 Share Posted November 21, 2008 I've updated the source code fixing the security flaw you pointed out in your PM along with some other things that I've fixed previously. Added some mime-types and updated with extensive comments.All in all, it's worth downloading again.Thanks so much for finding the security hole, james! I'm glad you found it before anyone got hurt.Glad it helped And nice script "There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110 Link to comment Share on other sites More sharing options...
Xwolf Posted November 21, 2008 Share Posted November 21, 2008 Haha, no problem. I am glad we have it all sorted out ... 8) I've done a line-by-line comment on this code. I hope it'll help you understand it better. Sorry I haven't documented the functions just as extensive. I couldn't really explain the POST functions in as much detail. If you have any specific questions or requests, just ask me. expandcollapse popup#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 ; // OPTIONS HERE // Dim $sRootDir = @ScriptDir & "\www\" ; The absolute path to the root directory of the server. Dim $sIP = @IPAddress1 ; ip address as defined by AutoIt Dim $iPort = 80 ; the listening port Dim $iMaxUsers = 15 ; Maximum number of users who can simultaneously get/post ; // END OF OPTIONS // Dim $aSocket[$iMaxUsers] ; Creates an array to store all the possible users Dim $sBuffer[$iMaxUsers] ; All these users have buffers when sending/receiving, so we need a place to store those 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 http://" & $sIP & "/" & @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 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 $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 If FileExists($sRootDir & "\" & $sRequest) Then ;; makes sure the file that the user wants exists :D $sFileType = StringRight($sRequest,4) ;; determines the file type, so that we may choose what mine type to use Switch $sFileType Case "html", ".htm" ;; in case of normal HTML files _SendFile($sRootDir & "\" & $sRequest, "text/html", $aSocket[$x]) Case ".css" ;; in case of style sheets _SendFile($sRootDir & "\" & $sRequest, "text/css", $aSocket[$x]) Case ".jpg", "jpeg" ;; for common images _SendFile($sRootDir & "\" & $sRequest, "image/jpeg", $aSocket[$x]) Case ".png" ;; another common image format _SendFile($sRootDir & "\" & $sRequest, "image/png", $aSocket[$x]) Case Else ; this is for .exe, .zip, or anything else that is not supported is downloaded to the client using a application/octet-stream _SendFile($sRootDir & "\" & $sRequest, "application/octet-stream", $aSocket[$x]) EndSwitch Else _SendError($aSocket[$x]) ;; File does not exist, so we'll send back an error.. 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 = _Get_Post($sBuffer[$x]) ;; parses the post data $sName = _POST("Name",$aPOST) ; Like PHPs _POST, but it requires the second parameter to be the return value from _Get_Post $sComment = _POST("Comment",$aPOST) ;; Gets the comment _POST_ConvertString($sName) ;; Needs to convert the POST HTTP string into a normal string _POST_ConvertString($sComment) ;; same .. FileWrite($sRootDir & "\index.html", FileRead($sRootDir & "\index.html") & "<br />" & $sName & " made comment: " & $sComment) ;Ofcourse, in real situations you have to prevent people to use HTML/PHP/Javascript etc. in their comments. ;; The last line adds whatever Name:Comment said in the root file .. this creates some sort of chatty effect _SendFile($sRootDir & "\index.html", "text/html", $aSocket[$x]) ; 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 TCPCloseSocket($aSocket[$x]) ;; we have defined connection: close, so we close the connection $aSocket[$x] = -1 ;; reset the socket so that we may accept new clients EndIf EndIf Next Sleep(10) WEnd Func _POST_ConvertString(ByRef $sString) ;; converts any characters like %20 into space 8) $sString = StringReplace($sString, '+', ' ') StringReplace($sString, '%', '') For $t = 0 To @extended $Find_Char = StringLeft( StringTrimLeft($sString, StringInStr($sString, '%')) ,2) $sString = StringReplace($sString, '%' & $Find_Char, Chr(Dec($Find_Char))) Next EndFunc Func _SendHTML($sHTML,$sSocket) ;; sends HTML data back to the client on X socket Local $iLen, $sPacket, $sSplit $iLen = StringLen($sHTML) $sPacket = Binary("HTTP/1.1 200 OK" & @CRLF & _ "Server: ManadarX/1.0 (" & @OSVersion & ") AutoIt " & @AutoItVersion & @CRLF & _ "Connection: close" & @CRLF & _ "Content-Lenght: " & $iLen & @CRLF & _ "Content-Type: text/html" & @CRLF & _ @CRLF & _ $sHTML) $sSplit = StringSplit($sPacket,"") $sPacket = "" For $i = 1 to $sSplit[0] If Asc($sSplit[$i]) <> 0 Then ; Just make sure we don't send any null bytes, because they show up as ???? in your browser. $sPacket = $sPacket & $sSplit[$i] EndIf Next TCPSend($sSocket,$sPacket) EndFunc Func _SendFile($sAddress, $sType, $sSocket) ;; Sends a file back to the client on X socket, with X mime-type Local $hFile, $sImgBuffer, $sPacket, $a $hFile = FileOpen($sAddress,16) $sImgBuffer = FileRead($hFile) FileClose($hFile) $sPacket = Binary("HTTP/1.1 200 OK" & @CRLF & _ "Server: ManadarX/1.3.26 (" & @OSVersion & ") AutoIt " & @AutoItVersion & @CRLF & _ "Connection: close" & @CRLF & _ "Content-Type: " & $sType & @CRLF & _ @CRLF) TCPSend($sSocket,$sPacket) While BinaryLen($sImgbuffer) ;LarryDaLooza's idea to send in chunks to reduce stress on the application $a = TCPSend($sSocket,$sImgbuffer) $sImgbuffer = BinaryMid($sImgbuffer,$a+1,BinaryLen($sImgbuffer)-$a) WEnd $sPacket = Binary(@CRLF & _ @CRLF) TCPSend($sSocket,$sPacket) TCPCloseSocket($sSocket) EndFunc Func _SendError($sSocket) ;; Sends back a basic 404 error _SendHTML("404 Error: " & @CRLF & @CRLF & "The file you requested could not be found.", $sSocket) EndFunc Func _Get_Post($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 Func _POST($sName,$sArray) ;; Returns a POST variable based on their name and not their array index. This function basically makes up for the lack of associative arrays in Au3 For $i = 1 to UBound($sArray)-1 If $sArray[$i][0] = $sName Then Return $sArray[$i][1] EndIf Next Return "" EndFuncOK Thanks all the same. Link to comment Share on other sites More sharing options...
jvanegmond Posted November 21, 2008 Author Share Posted November 21, 2008 Good script, Manadar. Hows it hold up, performance wise? Have you done any stress tests?Pretty good, actually. I haven't done any time measurements, because I had no reference material. I'm positive that at least 15 users can GET pages at the same time. POST might be a little slower because it relies on FileWrite in my example, but in a real situation where you're going to be using this you can delete POST all together. github.com/jvanegmond Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 How about storing POST in a variable? Is that possible? and call the variable $IPaddress-POSTname.. or something like that.. Just adding my 2 cents in ideas ;-) [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
jvanegmond Posted November 21, 2008 Author Share Posted November 21, 2008 How about storing POST in a variable? Is that possible? and call the variable $IPaddress-POSTname.. or something like that.. Just adding my 2 cents in ideas ;-)I don't think I fully understand what you're saying .. Maybe you could rephrase it in Dutch and I'll be able to understand.Storing the POST in a separate global variable is a bad thing though. You should try to avoid globals where you can. github.com/jvanegmond Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 Ik had een idee om de POST in een variable op te slaan, dit werkt immers sneller dan filewrite... Dan noem je de variabele $IPADDRESS-POSTNAME, bijvoorbeeld als je een form hebt waarin je de inputbox genaamd 'username' hebt, en degene die de form submit heeft IP address 81.154.12.64 (random IP address) dan sla je de waarde die hij in 'username' heeft ingevuld op in de variabele $81.154.12.64-username. Maar als je zegt dat het opslaan van die variabele een slecht idee is, dan zou ik dat beter niet doen.. (care to explain why it is a bad thing?) [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
jvanegmond Posted November 21, 2008 Author Share Posted November 21, 2008 (edited) Ik had een idee om de POST in een variable op te slaan, dit werkt immers sneller dan filewrite...Dan noem je de variabele $IPADDRESS-POSTNAME, bijvoorbeeld als je een form hebt waarin je de inputbox genaamd 'username' hebt, en degene die de form submit heeft IP address 81.154.12.64 (random IP address) dan sla je de waarde die hij in 'username' heeft ingevuld op in de variabele $81.154.12.64-username.Maar als je zegt dat het opslaan van die variabele een slecht idee is, dan zou ik dat beter niet doen.. (care to explain why it is a bad thing?)Ik snap nu wat je bedoelt. Het zou ook kunnen zonder FileWrite en het dan inderdaad opslaan in een variabele. In dit geval is het toegestaan om een global te gebruiken, omdat je dit niet met een local variabele kan doen.Ik heb echt gekozen om het in een bestand op te slaan omdat het 1) Sneller te maken was, en 2) omdat het opgeslagen blijft ook als de server crashed.In principe word POST altijd in een variabele opgeslagen, maar de implementatie van POST hier gebruikt FileWrite. Als je zelf met deze server aan de slag gaat, zul je allereerst de bestaande POST code moeten verwijderen, omdat het totaal geen nut heeft. 8) Edited November 21, 2008 by Manadar github.com/jvanegmond Link to comment Share on other sites More sharing options...
BrettF Posted November 21, 2008 Share Posted November 21, 2008 (edited) Hey Manadar! How bout a translation! I'm trying to follow on with whats happening : Oh and is there are way to have like htpasswd or something? Edited November 21, 2008 by BrettF Vist my blog!UDFs: Opens The Default Mail Client | _LoginBox | Convert Reg to AU3 | BASS.au3 (BASS.dll) (Includes various BASS Libraries) | MultiLang.au3 (Multi-Language GUIs!)Example Scripts: Computer Info Telnet Server | "Secure" HTTP Server (Based on Manadar's Server)Software: AAMP- Advanced AutoIt Media Player | WorldCam | AYTU - Youtube Uploader Tutorials: Learning to Script with AutoIt V3Projects (Hardware + AutoIt): ArduinoUseful Links: AutoIt 1-2-3 | The AutoIt Downloads Section: | SciTE4AutoIt3 Full Version! Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 Maar als de server crasht, dan Maakt het toch niet uit of de post variabele wordt behouden, je bent je sessionid immers toch al kwijt. Zou ik zo zeggen. [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
JRowe Posted November 21, 2008 Share Posted November 21, 2008 Ik snap nu wat je bedoelt. Het zou ook kunnen zonder FileWrite en het dan inderdaad opslaan in een variabele. In dit geval is het toegestaan om een global te gebruiken, omdat je dit niet met een local variabele kan doen.Ik heb echt gekozen om het in een bestand op te slaan omdat het 1) Sneller te maken was, en 2) omdat het opgeslagen blijft ook als de server crashed.In principe word POST altijd in een variabele opgeslagen, maar de implementatie van POST hier gebruikt FileWrite. Als je zelf met deze server aan de slag gaat, zul je allereerst de bestaande POST code moeten verwijderen, omdat het totaal geen nut heeft. 8) I now understand what you mean. It could also be without WriteSHIELD File and then save it in fact a variable. In this case it is permissible for global use, because you do not with a local variable can do.I've really taken to it in a file because it is 1) to make faster, and 2) because it remains stored even when the server crashed.In principle POST always be stored in a variable, but the implementation of POST used here File Write. If you own this server by using it, you will first of all the existing POST code should remove, because it has no usefulness [center]However, like ninjas, cyber warriors operate in silence.AutoIt Chat Engine (+Chatbot) , Link Grammar for AutoIt , Simple Speech RecognitionArtificial Neural Networks UDF , Bayesian Networks UDF , Pattern Matching UDFTransparent PNG GUI Elements , Au3Irrlicht 2Advanced Mouse Events MonitorGrammar Database GeneratorTransitions & Tweening UDFPoker Hand Evaluator[/center] Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 Google translation ;-)? I was suggesting storing the POST in a variable which is includes the IP Address and the name of the <input> in the html. But manadar replied that this was not such a good idea, since if the server crashed, you would lose the POST. Then I replied, but if the server crashes, you lose the session anyways, so it's not that big of a deal. [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
jvanegmond Posted November 21, 2008 Author Share Posted November 21, 2008 Google translation ;-)?I was suggesting storing the POST in a variable which is includes the IP Address and the name of the <input> in the html. But manadar replied that this was not such a good idea, since if the server crashed, you would lose the POST. Then I replied, but if the server crashes, you lose the session anyways, so it's not that big of a deal.All very true. But you see have to realise that the actual POST data, and handling/storing the data that comes out of POST are two separate things. The incoming POST data is parsed, which is the standard part that is the same for all web-servers. The FileWrite part is the implementation of the POST, to show how you could use POST in a code example.So, that being out of the way. If you store the posted data in on a variable, instead of on a file, you can no longer retreive old messages when the server starts up. Look at it like this in a linear way:1) Manadar posts a message2) toonboom posts a message3) Server crashes4) Manadar posts a messageThe server now holds 3 messages.If you were to use a variable you'd only keep 1 message, because the previously posted data hasn't been stored anywhere and is lost with the server crashing. github.com/jvanegmond Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 That's not the exact use of a POST function though, what you are referring to is database-like storage. and that, indeed should be written to a file. I am referring to this: <form name="input" action="formprocess.php" method="post"> Username: <input type="text" name="user"> <input type="submit" value="Submit"> </form> Then formprocess.php would contain something along these lines: Welcome to AutoIt <?echo($_POST["username"]);! <BR> Enjoy your stay! [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
BrettF Posted November 21, 2008 Share Posted November 21, 2008 But there is no php support... Vist my blog!UDFs: Opens The Default Mail Client | _LoginBox | Convert Reg to AU3 | BASS.au3 (BASS.dll) (Includes various BASS Libraries) | MultiLang.au3 (Multi-Language GUIs!)Example Scripts: Computer Info Telnet Server | "Secure" HTTP Server (Based on Manadar's Server)Software: AAMP- Advanced AutoIt Media Player | WorldCam | AYTU - Youtube Uploader Tutorials: Learning to Script with AutoIt V3Projects (Hardware + AutoIt): ArduinoUseful Links: AutoIt 1-2-3 | The AutoIt Downloads Section: | SciTE4AutoIt3 Full Version! Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 Ok.. Ok.. my bad xD I confused it with another autoit webserver I saw... silly clear-minded aussie (no offense, just joking) [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
jvanegmond Posted November 21, 2008 Author Share Posted November 21, 2008 That's not the exact use of a POST function though, what you are referring to is database-like storage. and that, indeed should be written to a file.Seriously, read what I said.THERE IS A DIFFERENCE BETWEEN THE POST FUNCTIONS AND THE IMPLEMENTATION. github.com/jvanegmond Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 Yes I am sorry.. I misunderstood a big part of it.. I'm at home, my stomach hurts, I ate something wrong three days ago and I'm still sick of it (literally) the only thing I can do now is sit behing my computer and read forums, and code some autoit snippets... I sometimes misinterpret things I read the last few days. I am sorry. [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
jvanegmond Posted November 21, 2008 Author Share Posted November 21, 2008 Yes I am sorry.. I misunderstood a big part of it.. I'm at home, my stomach hurts, I ate something wrong three days ago and I'm still sick of it (literally) the only thing I can do now is sit behing my computer and read forums, and code some autoit snippets... I sometimes misinterpret things I read the last few days. I am sorry.Get well soon so that we may engage in intelligent conversation some other time. github.com/jvanegmond Link to comment Share on other sites More sharing options...
BrettF Posted November 21, 2008 Share Posted November 21, 2008 silly clear-minded aussie (no offense, just joking)I'm not sure where to take offense, the fact that you said i was silly or clear-minded... Vist my blog!UDFs: Opens The Default Mail Client | _LoginBox | Convert Reg to AU3 | BASS.au3 (BASS.dll) (Includes various BASS Libraries) | MultiLang.au3 (Multi-Language GUIs!)Example Scripts: Computer Info Telnet Server | "Secure" HTTP Server (Based on Manadar's Server)Software: AAMP- Advanced AutoIt Media Player | WorldCam | AYTU - Youtube Uploader Tutorials: Learning to Script with AutoIt V3Projects (Hardware + AutoIt): ArduinoUseful Links: AutoIt 1-2-3 | The AutoIt Downloads Section: | SciTE4AutoIt3 Full Version! Link to comment Share on other sites More sharing options...
toonboon Posted November 21, 2008 Share Posted November 21, 2008 nevermind. [right]~What can I say, I'm a Simplistic person[/right] Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now