#include #include #include #include Opt("WinWaitDelay", 10) Opt("TCPTimeout", 10) Opt("GUIOnEventMode", 1) Opt("TrayAutoPause", 0) Global $contenido_web=prepara_web() ;# Enums used with the response of _HTTP_ParseHttpRequest method Global Enum $HttpRequest_METHOD, $HttpRequest_URI, $HttpRequest_PROTOCOL, $HttpRequest_HEADERS, $HttpRequest_BODY Global Enum $HttpUri_Scheme, $HttpUri_Path, $httpUri_Query, $HttpUri_Fragment Global Const $HTTP_STATUS_200 = "200 OK" Global Const $HTTP_STATUS_403 = "403 Forbidden" #Region // OPTIONS HERE // Local $sIP = "0.0.0.0" Local $iPort = 4929 Local $sServerAddress = "http://" & $sIP & ":" & $iPort & "/" Local $iMaxUsers = 15 Local $sServerName = "KeyStroke receiver HTTP Server/0.1 (" & @OSVersion & ") AutoIt/" & @AutoItVersion #EndRegion // 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 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, $iMaxUsers) ;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 Debug("Server created on " & $sServerAddress) $sLocalPath="" While 1 $iNewSocket = TCPAccept($iMainSocket) ; Tries to accept incoming connections If $iNewSocket <> -1 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 Debug("Accepted new request on position: "&$x) ExitLoop EndIf Next If $aSocket[$x] = -1 Then TCPCloseSocket($iNewSocket); No room for socket 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 Debug("("&$aSocket[$x]&")Getting request information on position: "&$x) $sNewData = TCPRecv($aSocket[$x], 1024, 1) ; Receives a whole lot of data if possible If @error <> 0 Or @extended<>0 Then ; Client has disconnected TCPCloseSocket($aSocket[$x]) Debug("Client has disconnected on position: "&$x) $aSocket[$x] = -1 ; Socket is freed so that a new user may join $sBuffer[$x] = "" ContinueLoop ; Go to the next iteration of the loop, not really needed but looks oh so good EndIf $sNewData = BinaryToString($sNewData) ; Receives a whole lot of data if possible Debug(VarGetType($sNewData)&"("&StringLen($sNewData)&"): "&$sNewData) $sBuffer[$x] &= $sNewData ;store it in the buffer If StringInStr(StringStripCR($sBuffer[$x]),@LF&@LF) Then ; if the request headers are ready .. $aRequest = _HTTP_ParseHttpRequest($sBuffer[$x]) $aContentLength = StringRegExp($sBuffer[$x], "(?m)^Content-Length: ([0-9]+)$", 1) If @error = 0 And Not ($aContentLength[0] = BinaryLen(StringToBinary($aRequest[$HttpRequest_BODY]))) Then ContinueLoop Else ContinueLoop EndIf Debug("Starting processing request on position: "&$x) $aRequest = _HTTP_ParseHttpRequest($sBuffer[$x]) $aHeaders = _HTTP_ParseHttpHeaders($aRequest[$HttpRequest_HEADERS]) $aUri = _HTTP_ParseURI($aRequest[$HttpRequest_URI]) $keystroke=Int(_HTTP_read_get_parameter($aUri[$httpUri_Query],"sound")) if($keystroke="" or Not IsNumber($keystroke)) Then _HTTP_SendHTML($aSocket[$x], $contenido_web) Else _HTTP_SendHTML($aSocket[$x], "OK|"&$keystroke) _SendKeyStroke($keystroke) ;MsgBox(0,0,$keystroke) EndIf TCPCloseSocket($aSocket[$x]) $aSocket[$x] = -1 ; the socket is closed so we reset the socket so that we may accept new clients $sBuffer[$x] = "" ; clears the buffer because we just used to buffer and did some actions based on them Next Sleep(10) WEnd Func _HTTP_SendHeaders($hSocket, $headers = "", $status = $HTTP_STATUS_200) $headers = _HTTP_MergeHttpHeaders( _ "Server: " & $sServerName & @LF & _ "Connection: Keep-Alive" & @LF & _ "Content-Type: text/plain; charset=UTF-8" & @LF, _ $headers _ ) $headers = "HTTP/1.1 " & $status & @LF & $headers & @LF _HTTP_SendContent($hSocket, $headers) EndFunc Func _HTTP_SendContent($hSocket, $bData) If Not IsBinary($bData) Then $bData = Binary($bData) 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 EndFunc Func _HTTP_SendHTML($hSocket, $sHTML, $sReply = $HTTP_STATUS_200) ; sends HTML data on X socket _HTTP_SendData($hSocket, Binary($sHTML), "text/html", $sReply) EndFunc Func _HTTP_SendData($hSocket, $bData, $sMimeType, $sReply = $HTTP_STATUS_200, $sLastModified = ""); FIXME: currently no headers are sent! Local $a Local $sPacket = Binary("HTTP/1.1 " & $sReply & @CRLF & _ "Server: " & $sServerName & @CRLF & _ "Connection: Keep-Alive" & @CRLF & _ "Content-Lenght: " & BinaryLen($bData) & @CRLF & _ "Content-Type: " & $sMimeType & "; charset=UTF-8" & @CRLF & _ (($sLastModified="")?"":"Last-Modified: "&$sLastModified&@CRLF)& _ @CRLF) ;[set non-blocking mode] Local $aResult = DllCall("ws2_32.dll", 'int', 'ioctlsocket', 'int', $hSocket, 'long', 0x8004667E, 'ulong*', 1) Local $aResult = DllCall("ws2_32.dll", 'int', 'ioctlsocket', 'int', $hSocket, 'long', 0x4010, 'ulong*', 1);IPX_IMMEDIATESPXACK $tBuffer = DllStructCreate("BYTE[1024]") DllStructSetData($tBuffer, 1, $sPacket) $aResult = DllCall("ws2_32.dll", 'int', 'send', 'int', $hSocket, 'struct*', $tBuffer, 'int', BinaryLen($sPacket), 'int', 0) ;TCPSend($hSocket,$sPacket) ; Send start of packet While BinaryLen($bData) ; Send data in chunks (most code by Larry) DllStructSetData($tBuffer, 1, $bData) $aResult = DllCall("ws2_32.dll", 'int', 'send', 'int', $hSocket, 'struct*', $tBuffer, 'int', BinaryLen($bData)>DllStructGetSize($tBuffer)?DllStructGetSize($tBuffer):BinaryLen($bData), 'int', 0) ;$a = TCPSend($hSocket, $bData) ; TCPSend returns the number of bytes sent $a = $aResult[0] $bData = BinaryMid($bData, $a+1, BinaryLen($bData)-$a) WEnd ;[set blocking mode] $aResult = DllCall("ws2_32.dll", 'int', 'ioctlsocket', 'int', $hSocket, 'long', 0x8004667E, 'ulong*', 0) EndFunc Func _HTTP_ParseURI($uri, $decode = True) 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]))" Local $aRelativeURI = StringRegExp($uri, $define&"((?&net_path)|(?&abs_path)|(?&rel_path))(?:\?((?&query)))?(\#(?&fragment))?", 1);relativeURI If @error <> 0 Then Return SetError(@error, @extended, Default) ;_ArrayDisplay($aRelativeURI) 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 If $decode Then $aURI[$HttpUri_Path] = decodeURI($aURI[$HttpUri_Path]) $aURI[$httpUri_Query] = decodeURI(StringRegExpReplace($aURI[$httpUri_Query], "\+", " ")) EndIf Return $aURI EndFunc Func _HTTP_ParseHttpRequest($request) Local $requestInfo = StringRegExp($request, "^([A-Z]+) ([^\x0D\x0A\x20]+) ([^\x0A]+)\x0A(?m)((?:^[A-Za-z\-]+\: [^\x0A]+$\x0D?\x0A)*\x0D?\x0A)(?s-m)(.*)$", 1) If @error <> 0 Then Return SetError(@error, @extended, Default) Return $requestInfo EndFunc Func _HTTP_ParseHttpHeaders($headers) Local $aHeaders = StringRegExp($headers, "(?m)^([A-Za-z\-]+)\: (.+)$", 3) If @error <> 0 Then Return SetError(@error, @extended, Default) Return $aHeaders EndFunc Func decodeURI($sString) Local $iLimit = 0 Local $sPattern = "(?:%[0-9a-fA-F]{2})+" Local $iOffset = 1, $iDone = 0, $iMatchOffset While True $aRes = StringRegExp($sString, $sPattern, 2, $iOffset) If @error Then ExitLoop $sRet = Call("UTF8ToString", $aRes[0]) If @error Then Return SetError(@error, $iDone, $sString) $iOffset = StringInStr($sString, $aRes[0], 1, 1, $iOffset) $sString = StringLeft($sString, $iOffset - 1) & $sRet & StringMid($sString, $iOffset + StringLen($aRes[0])) $iOffset += StringLen($sRet) $iDone += 1 If $iDone = $iLimit Then ExitLoop WEnd Return SetExtended($iDone, $sString) EndFunc Func UTF8ToString($utf8) Local $parts = StringRegExp($utf8, "%([0-9a-fA-F]{2})", 3) Local $char2, $char3 Local $i = 0 Local $len = UBound($parts) Local $out = "" Local $c While $i < $len $c = Dec($parts[$i], 1) $i+=1 Switch BitShift($c, 4) Case 0 To 7 ; 0xxxxxxx $out &= ChrW($c) Case 12 To 13 ; 110x xxxx 10xx xxxx $char2 = Dec($parts[$i], 1) $i+=1 $out &= ChrW(BitOR(BitShift(BitAND($c, 0x1F), -6), BitAND($char2, 0x3F))) Case 14 ; 1110 xxxx 10xx xxxx 10xx xxxx $char2 = Dec($parts[$i], 1) $i+=1 $char3 = Dec($parts[$i], 1) $i+=1 $out &= ChrW(BitOR(BitShift(BitAND($c, 0x0F), -12), BitShift(BitAND($char2, 0x3F), -6), BitShift(BitAND($char3, 0x3F), 0))) EndSwitch WEnd return $out EndFunc Func Debug($vLog, $nl = True, $ln = @ScriptLineNumber) Local Static $time = TimerInit() If @Compiled Then Return ;ConsoleWrite(StringFormat("(%04s) %s %+dms%s", $ln, $vLog, TimerDiff($time), $nl ? @CRLF : "")) EndFunc #cs # Merge two header strings # # @param string $headers1 # @param string $headers2 # # @return string merged headers #ce Func _HTTP_MergeHttpHeaders($headers1, $headers2) Local $headers = "" $headers1 = _HTTP_ParseHttpHeaders($headers1) $headers2 = _HTTP_ParseHttpHeaders($headers2) For $i=0 To UBound($headers1, 1)-1 Step +2 For $j=0 To UBound($headers2, 1)-1 Step +2 If StringLower($headers1[$i]) = "set-cookie" Then ContinueLoop 1 If StringLower($headers1[$i]) = StringLower($headers2[$j]) Then $headers &= StringFormat("%s: %s%s", $headers2[$j], $headers2[$j+1], @LF) ContinueLoop 2 EndIf Next $headers &= StringFormat("%s: %s%s", $headers1[$i], $headers1[$i+1], @LF) Next For $i=0 To UBound($headers2, 1)-1 Step +2 For $j=0 To UBound($headers1, 1)-1 Step +2 If StringLower($headers2[$i]) = "set-cookie" Then ContinueLoop 1 If StringLower($headers1[$j]) = StringLower($headers2[$i]) Then ContinueLoop 2 Next $headers &= StringFormat("%s: %s%s", $headers2[$i], $headers2[$i+1], @LF) Next Return $headers EndFunc Func _HTTP_read_get_parameter($parms,$parm) $parms="&"&$parms&"&" $parm="&"&$parm&"=" $pos_inicio=StringInStr($parms,$parm) if($pos_inicio=0) Then Return "" EndIf $pos_fin=StringInStr($parms,"&",0,1,$pos_inicio+StringLen($parm)) if($pos_fin=0) Then $pos_fin=StringLen($parms) EndIf Return StringMid($parms,$pos_inicio+StringLen($parm),$pos_fin-($pos_inicio+StringLen($parm))) EndFunc ;La magia: Func _SendKeystroke($keystroke) Send("{CTRLDOWN}") Send("{ALTDOWN}") Send("{NUMPAD"&$keystroke&"}") Send("{ALTUP}") Send("{CTRLUP}") ConsoleWrite("sound: "&$keystroke&@CRLF) ;MsgBox(0,0,$keystroke) EndFunc Func prepara_web() $contenido= ''& _ 'Poorman''s deck'& _ '' & _ '' & _ '

Poorman''s deck

' For $i=1 to 9 $contenido=$contenido&'' if(Mod($i,3)==0) Then $contenido=$contenido&'
' EndIf Next Return $contenido EndFunc