Jump to content

Websocket unmask/decode received data (Websocket framing) - SOLVED


milos83
 Share

Go to solution Solved by milos83,

Recommended Posts

I created a WebSocket server and Google Chrome addon is connecting to it.

Handshake works and the server can send messages to the addon just fine.

The problem are messages that the addon is sending to the server.

The data is received but, I just can't decrypt the received data and I tried a lot of different solutions.

The add-on part is working as it should because in one of my tests, I ran a simplest c# WebSocket server(see end of the post) on the same port and it gets the data properly.

 

Whatever I tried, I always get gibberish output.

eg: ÊÍÌÉ/

Does anyone knows how to unframe/unmask the WebSocket data properly?

These are some of my tries:

$bytes = TCPRecv($socket, 4096)
ConsoleWrite(unmask($bytes))

Func unmask($text)
    Local $length = StringToBinary(StringMid($text, 2, 1))
    $length = BitAND(Number($length), 127)
ConsoleWrite($length & @CRLF)
    Local $masks, $data

    If $length = 126 Then
        $masks = StringMid($text, 5, 4)
        $data = StringMid($text, 9)
    ElseIf $length = 127 Then
        $masks = StringMid($text, 11, 4)
        $data = StringMid($text, 15)
    Else
        $masks = StringMid($text, 3, 4)
        $data = StringMid($text, 7)
    EndIf

    Local $result = ""

    For $i = 0 To StringLen($data) - 1
        $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i,  4) + 1, 1))))
    Next

    Return $result
EndFunc

Another try:

Func WebSocketReceive($socket)
    Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed
    If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data

    ConsoleWrite(unmask(BinaryToString($bytes)) & @CRLF); another try (function unmask = line ~190)

    ; Convert binary to byte array
    Local $byteArray = $bytes

    Local $fin = BitAND(BinaryMid($byteArray, 1, 1), 0x80) <> 0
          $mask = BitAND(BinaryMid($byteArray, 2, 1), 0x80) <> 0 ; must be true, "All messages from the client to the server have this bit set"
    Local $opcode = BitAND(BinaryMid($byteArray, 1, 1), 0x0F) ; expecting 1 - text message
          $offset = 2
    Local $msglen = BitAND(BinaryMid($byteArray, 2, 1), 0x7F)

    If $msglen == 126 Then
        ; bytes are reversed because the WebSocket will print them in Big-Endian
        ; whereas BitConverter will want them arranged in little-endian on Windows
        $msglen = BitShift(BitOR(BinaryMid($byteArray, 4, 1), BitShift(BinaryMid($byteArray, 3, 1), 8)), 0)
        $offset = 4
    ElseIf $msglen == 127 Then
        ; To test the below code, we need to manually buffer larger messages
        $msglen = BitOR(BitShift(BinaryMid($byteArray, 10, 1), 56), BitShift(BinaryMid($byteArray, 9, 1), 48), _
                        BitShift(BinaryMid($byteArray, 8, 1), 40), BitShift(BinaryMid($byteArray, 7, 1), 32), _
                        BitShift(BinaryMid($byteArray, 6, 1), 24), BitShift(BinaryMid($byteArray, 5, 1), 16), _
                        BitShift(BinaryMid($byteArray, 4, 1), 8), BinaryMid($byteArray, 3, 1))
        $offset = 10
    EndIf

    If $msglen == 0 Then
        ConsoleWrite("msglen == 0" & @CRLF)
    ElseIf $mask Then
        Local $decoded[$msglen]
        Local $masks[4] = [BinaryMid($byteArray, $offset, 1), BinaryMid($byteArray, $offset + 1, 1), _
                           BinaryMid($byteArray, $offset + 2, 1), BinaryMid($byteArray, $offset + 3, 1)]
        $offset += 4

        For $i = 0 To $msglen - 1
            $decoded[$i] = BitXOR(BinaryMid($byteArray, $offset + $i, 1), $masks[Mod($i, 4)])
        Next

        Local $text = BinaryToString(Binary($decoded))
        ConsoleWrite($text & @CRLF)
        Return $text
    Else
        ConsoleWrite("mask bit not set" & @CRLF)
    EndIf

    Return SetError(1, 0, "")
EndFunc

 

And the whole code:

#include <Array.au3>
#include <Crypt.au3>
#include <WinHttp.au3>
#include <APIErrorsConstants.au3>
#include <AutoItConstants.au3>


TCPStartup()

Global $gSocket = TCPListen("127.0.0.1", 65432)

While True
    Local $client = TCPAccept($gSocket)
    If $client <> -1 Then
        Local $data = TCPRecv($client, 1024)
        If StringInStr($data, "Sec-WebSocket-Key:") Then
            ; Perform WebSocket handshake
            Local $key = StringRegExp($data, "Sec-WebSocket-Key: (.+)", 1)[0]
            ConsoleWrite($data & @CRLF)
            ConsoleWrite("$key:" & $key & @CRLF)
            Local $responseKey = base64(_Crypt_HashData($key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", $CALG_SHA1))
            Local $response = "HTTP/1.1 101 Switching Protocols" & @CRLF & _
                             "Upgrade: websocket" & @CRLF & _
                             "Connection: Upgrade" & @CRLF & _
                             "Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover" & @CRLF & _
                             "Sec-WebSocket-Accept: " & $responseKey & @CRLF & @CRLF

                             ;
                             ;"Sec-WebSocket-Extensions: no-masking" & @CRLF & _
            TCPSend($client, $response)

            Sleep(1000)
            WebSocketSend($client, "Hello!"); This works
            Sleep(1000)

            ; Now the connection is upgraded to WebSocket, handle communication
            While True
                Local $message = WebSocketReceive($client)
                If @error Then ContinueLoop ; Connection closed
                If $message <> "" Then
                    ; Handle the received message
                    ConsoleWrite("Received message: " & $message & @CRLF)
                    ConsoleWrite("Received message: " & BinaryToString($message) & @CRLF)
                EndIf
            WEnd
        EndIf
    EndIf
WEnd




Func WebSocketReceive($socket)
    Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed
    If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data

    ConsoleWrite(unmask(BinaryToString($bytes)) & @CRLF); another try (function unmask = line ~190)

    ; Convert binary to byte array
    Local $byteArray = $bytes

    Local $fin = BitAND(BinaryMid($byteArray, 1, 1), 0x80) <> 0
          $mask = BitAND(BinaryMid($byteArray, 2, 1), 0x80) <> 0 ; must be true, "All messages from the client to the server have this bit set"
    Local $opcode = BitAND(BinaryMid($byteArray, 1, 1), 0x0F) ; expecting 1 - text message
          $offset = 2
    Local $msglen = BitAND(BinaryMid($byteArray, 2, 1), 0x7F)

    If $msglen == 126 Then
        ; bytes are reversed because the WebSocket will print them in Big-Endian
        ; whereas BitConverter will want them arranged in little-endian on Windows
        $msglen = BitShift(BitOR(BinaryMid($byteArray, 4, 1), BitShift(BinaryMid($byteArray, 3, 1), 8)), 0)
        $offset = 4
    ElseIf $msglen == 127 Then
        ; To test the below code, we need to manually buffer larger messages
        $msglen = BitOR(BitShift(BinaryMid($byteArray, 10, 1), 56), BitShift(BinaryMid($byteArray, 9, 1), 48), _
                        BitShift(BinaryMid($byteArray, 8, 1), 40), BitShift(BinaryMid($byteArray, 7, 1), 32), _
                        BitShift(BinaryMid($byteArray, 6, 1), 24), BitShift(BinaryMid($byteArray, 5, 1), 16), _
                        BitShift(BinaryMid($byteArray, 4, 1), 8), BinaryMid($byteArray, 3, 1))
        $offset = 10
    EndIf

    If $msglen == 0 Then
        ConsoleWrite("msglen == 0" & @CRLF)
    ElseIf $mask Then
        Local $decoded[$msglen]
        Local $masks[4] = [BinaryMid($byteArray, $offset, 1), BinaryMid($byteArray, $offset + 1, 1), _
                           BinaryMid($byteArray, $offset + 2, 1), BinaryMid($byteArray, $offset + 3, 1)]
        $offset += 4

        For $i = 0 To $msglen - 1
            $decoded[$i] = BitXOR(BinaryMid($byteArray, $offset + $i, 1), $masks[Mod($i, 4)])
        Next

        Local $text = BinaryToString(Binary($decoded))
        ConsoleWrite($text & @CRLF)
        Return $text
    Else
        ConsoleWrite("mask bit not set" & @CRLF)
    EndIf

    Return SetError(1, 0, "")
EndFunc





Func WebSocketSend($socket, $message)
    Local $length = StringLen($message)
    Local $header = Chr(BitOR(0x80, 0x01)) ; FIN, Opcode Text

    If $length <= 125 Then
        $header &= Chr($length)
    ElseIf $length <= 65535 Then
        $header &= Chr(126) & Chr(BitShift($length, 8)) & Chr(BitAND($length, 0xFF))
    Else
        $header &= Chr(127)
        For $i = 7 To 0 Step -1
            $header &= Chr(BitShift($length, 8 * $i))
        Next
    EndIf

;~  ConsoleWrite("send:" & $header & $message & @CRLF)

    TCPSend($socket, $header & $message)
EndFunc



;==============================================================================================================================
; Function:         base64($vCode [, $bEncode = True [, $bUrl = False]])
;
; Description:      Decode or Encode $vData using Microsoft.XMLDOM to Base64Binary or Base64Url.
;                   IMPORTANT! Encoded base64url is without @LF after 72 lines. Some websites may require this.
;
; Parameter(s):     $vData      - string or integer | Data to encode or decode.
;                   $bEncode    - boolean           | True - encode, False - decode.
;                   $bUrl       - boolean           | True - output is will decoded or encoded using base64url shema.
;
; Return Value(s):  On Success - Returns output data
;                   On Failure - Returns 1 - Failed to create object.
;
; Author (s):       (Ghads on Wordpress.com), Ascer
;===============================================================================================================================
Func base64($vCode, $bEncode = True, $bUrl = False)

    Local $oDM = ObjCreate("Microsoft.XMLDOM")
    If Not IsObj($oDM) Then Return SetError(1, 0, 1)

    Local $oEL = $oDM.createElement("Tmp")
    $oEL.DataType = "bin.base64"

    If $bEncode then
        $oEL.NodeTypedValue = Binary($vCode)
        If Not $bUrl Then Return $oEL.Text
        Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "")
    Else
        If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/")
        $oEL.Text = $vCode
        Return $oEL.NodeTypedValue
    EndIf

EndFunc ;==>base64





Func unmask($text)
    Local $length = StringToBinary(StringMid($text, 2, 1))
    $length = BitAND(Number($length), 127)
ConsoleWrite($length & @CRLF)
    Local $masks, $data

    If $length = 126 Then
        $masks = StringMid($text, 5, 4)
        $data = StringMid($text, 9)
    ElseIf $length = 127 Then
        $masks = StringMid($text, 11, 4)
        $data = StringMid($text, 15)
    Else
        $masks = StringMid($text, 3, 4)
        $data = StringMid($text, 7)
    EndIf

    Local $result = ""

    For $i = 0 To StringLen($data) - 1
        $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i,  4) + 1, 1))))
    Next

    Return $result
EndFunc

 

There is no place I haven't searched.

 

Perfectly working c# server

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;

class Server
{
    public static void Main()
    {
        string ip = "127.0.0.1";
        int port = 65432;
        var server = new TcpListener(IPAddress.Parse(ip), port);

        server.Start();
        Console.WriteLine("Server has started on {0}:{1}, Waiting for a connection…", ip, port);

        TcpClient client = server.AcceptTcpClient();
        Console.WriteLine("A client connected.");

        NetworkStream stream = client.GetStream();

        // enter to an infinite cycle to be able to handle every change in stream
        while (true)
        {
            while (!stream.DataAvailable) ;
            while (client.Available < 3) ; // match against "get"

            byte[] bytes = new byte[client.Available];
            stream.Read(bytes, 0, bytes.Length);
            string s = Encoding.UTF8.GetString(bytes);

            if (Regex.IsMatch(s, "^GET", RegexOptions.IgnoreCase))
            {
                Console.WriteLine("=====Handshaking from client=====\n{0}", s);

                // 1. Obtain the value of the "Sec-WebSocket-Key" request header without any leading or trailing whitespace
                // 2. Concatenate it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (a special GUID specified by RFC 6455)
                // 3. Compute SHA-1 and Base64 hash of the new value
                // 4. Write the hash back as the value of "Sec-WebSocket-Accept" response header in an HTTP response
                string swk = Regex.Match(s, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim();
                string swka = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                byte[] swkaSha1 = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka));
                string swkaSha1Base64 = Convert.ToBase64String(swkaSha1);

                // HTTP/1.1 defines the sequence CR LF as the end-of-line marker
                byte[] response = Encoding.UTF8.GetBytes(
                    "HTTP/1.1 101 Switching Protocols\r\n" +
                    "Connection: Upgrade\r\n" +
                    "Upgrade: websocket\r\n" +
                    "Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n");

                stream.Write(response, 0, response.Length);
            }
            else
            {
                bool fin = (bytes[0] & 0b10000000) != 0,
                    mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set"
                Console.WriteLine(mask);
                int opcode = bytes[0] & 0b00001111, // expecting 1 - text message
                    offset = 2;
                ulong msglen = bytes[1] & (ulong)0b01111111;

                Console.WriteLine(msglen);

                if (msglen == 126)
                {
                    // bytes are reversed because websocket will print them in Big-Endian, whereas
                    // BitConverter will want them arranged in little-endian on windows
                    msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
                    offset = 4;
                }
                else if (msglen == 127)
                {
                    // To test the below code, we need to manually buffer larger messages — since the NIC's autobuffering
                    // may be too latency-friendly for this code to run (that is, we may have only some of the bytes in this
                    // websocket frame available through client.Available).
                    msglen = BitConverter.ToUInt64(new byte[] { bytes[9], bytes[8], bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2] }, 0);
                    offset = 10;
                }

                if (msglen == 0)
                {
                    Console.WriteLine("msglen == 0");
                }
                else if (mask)
                {
                    byte[] decoded = new byte[msglen];
                    byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] };
                    offset += 4;

                    for (ulong i = 0; i < msglen; ++i)
                        decoded[i] = (byte)(bytes[(ulong)offset + i] ^ masks[i % 4]);

                    string text = Encoding.UTF8.GetString(decoded);
                    Console.WriteLine("{0}", text);
                }
                else
                    Console.WriteLine("mask bit not set");

                Console.WriteLine();
            }
        }
    }
}

If someone has a suggestion, please help

Thanks in advance!

 

Link to comment
Share on other sites

  • Solution

Thank buddy for looking at it!

I managed to solve it finally!

The issue was what I already suspected and played with before, the

Sec-WebSocket-Extensions

Just leaving it out will make the client post messages without compression!

Here is the fixed code that works!

#include <Array.au3>
#include <Crypt.au3>

TCPStartup()

Global $gSocket = TCPListen("127.0.0.1", 65432)

While True
    Local $client = TCPAccept($gSocket)
    If $client <> -1 Then
        Local $data = TCPRecv($client, 1024)
        If StringInStr($data, "Sec-WebSocket-Key:") Then
            ; Perform WebSocket handshake
            Local $key = StringRegExp($data, "Sec-WebSocket-Key: (.+)", 1)[0]
            ConsoleWrite($data & @CRLF)
            ConsoleWrite("$key:" & $key & @CRLF)
            Local $responseKey = base64(_Crypt_HashData($key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", $CALG_SHA1))
            Local $response = "HTTP/1.1 101 Switching Protocols" & @CRLF & _
                             "Upgrade: websocket" & @CRLF & _
                             "Connection: Upgrade" & @CRLF & _
                             "Sec-WebSocket-Accept: " & $responseKey & @CRLF & @CRLF
            TCPSend($client, $response)

            Sleep(1000)
            WebSocketSend($client, "Hello!"); This works
            Sleep(1000)

            ; Now the connection is upgraded to WebSocket, handle communication
            While True
                Local $message = WebSocketReceive($client)
                If @error Then ContinueLoop
                If $message <> "" Then
                    ; Handle the received message
                    ConsoleWrite("Received message: " & $message & @CRLF)
                EndIf
            WEnd
        EndIf
    EndIf
WEnd




Func WebSocketReceive($socket)

    Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed
    If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data

    Return unmask(BinaryToString($bytes))
    
EndFunc





Func WebSocketSend($socket, $message)
    Local $length = StringLen($message)
    Local $header = Chr(BitOR(0x80, 0x01)) ; FIN, Opcode Text

    If $length <= 125 Then
        $header &= Chr($length)
    ElseIf $length <= 65535 Then
        $header &= Chr(126) & Chr(BitShift($length, 8)) & Chr(BitAND($length, 0xFF))
    Else
        $header &= Chr(127)
        For $i = 7 To 0 Step -1
            $header &= Chr(BitShift($length, 8 * $i))
        Next
    EndIf

    TCPSend($socket, $header & $message)
EndFunc



;==============================================================================================================================
; Function:         base64($vCode [, $bEncode = True [, $bUrl = False]])
;
; Description:      Decode or Encode $vData using Microsoft.XMLDOM to Base64Binary or Base64Url.
;                   IMPORTANT! Encoded base64url is without @LF after 72 lines. Some websites may require this.
;
; Parameter(s):     $vData      - string or integer | Data to encode or decode.
;                   $bEncode    - boolean           | True - encode, False - decode.
;                   $bUrl       - boolean           | True - output is will decoded or encoded using base64url shema.
;
; Return Value(s):  On Success - Returns output data
;                   On Failure - Returns 1 - Failed to create object.
;
; Author (s):       (Ghads on Wordpress.com), Ascer
;===============================================================================================================================
Func base64($vCode, $bEncode = True, $bUrl = False)

    Local $oDM = ObjCreate("Microsoft.XMLDOM")
    If Not IsObj($oDM) Then Return SetError(1, 0, 1)

    Local $oEL = $oDM.createElement("Tmp")
    $oEL.DataType = "bin.base64"

    If $bEncode then
        $oEL.NodeTypedValue = Binary($vCode)
        If Not $bUrl Then Return $oEL.Text
        Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "")
    Else
        If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/")
        $oEL.Text = $vCode
        Return $oEL.NodeTypedValue
    EndIf

EndFunc ;==>base64





Func unmask($text)
    Local $length = StringToBinary(StringMid($text, 2, 1))
    $length = BitAND(Number($length), 127)
    Local $masks, $data

    If $length = 126 Then
        $masks = StringMid($text, 5, 4)
        $data = StringMid($text, 9)
    ElseIf $length = 127 Then
        $masks = StringMid($text, 11, 4)
        $data = StringMid($text, 15)
    Else
        $masks = StringMid($text, 3, 4)
        $data = StringMid($text, 7)
    EndIf

    Local $result = ""

    For $i = 0 To StringLen($data) - 1
        $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i,  4) + 1, 1))))
    Next

    Return $result
EndFunc

 

Edited by milos83
removed unused includes
Link to comment
Share on other sites

  • milos83 changed the title to Websocket unmask/decode received data (Websocket framing) - SOLVED
3 minutes ago, Danp2 said:

Glad you were able to solve your own problem. :thumbsup: FWIW, there is already some websocket UDFs on the forum that you may want to check out. This post has details on the original source and my modification.

I have gone through every single forum post I could find (that one included).

All of them are WebSocket client codes or using an external dll or tool.

None of them helped with my situation.

Link to comment
Share on other sites

  • 4 weeks later...
On 12/8/2023 at 7:12 AM, milos83 said:

Thank buddy for looking at it!

I managed to solve it finally!

The issue was what I already suspected and played with before, the

Sec-WebSocket-Extensions

Just leaving it out will make the client post messages without compression!

Here is the fixed code that works!

#include <Array.au3>
#include <Crypt.au3>

TCPStartup()

Global $gSocket = TCPListen("127.0.0.1", 65432)

While True
    Local $client = TCPAccept($gSocket)
    If $client <> -1 Then
        Local $data = TCPRecv($client, 1024)
        If StringInStr($data, "Sec-WebSocket-Key:") Then
            ; Perform WebSocket handshake
            Local $key = StringRegExp($data, "Sec-WebSocket-Key: (.+)", 1)[0]
            ConsoleWrite($data & @CRLF)
            ConsoleWrite("$key:" & $key & @CRLF)
            Local $responseKey = base64(_Crypt_HashData($key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", $CALG_SHA1))
            Local $response = "HTTP/1.1 101 Switching Protocols" & @CRLF & _
                             "Upgrade: websocket" & @CRLF & _
                             "Connection: Upgrade" & @CRLF & _
                             "Sec-WebSocket-Accept: " & $responseKey & @CRLF & @CRLF
            TCPSend($client, $response)

            Sleep(1000)
            WebSocketSend($client, "Hello!"); This works
            Sleep(1000)

            ; Now the connection is upgraded to WebSocket, handle communication
            While True
                Local $message = WebSocketReceive($client)
                If @error Then ContinueLoop
                If $message <> "" Then
                    ; Handle the received message
                    ConsoleWrite("Received message: " & $message & @CRLF)
                EndIf
            WEnd
        EndIf
    EndIf
WEnd




Func WebSocketReceive($socket)

    Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed
    If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data

    Return unmask(BinaryToString($bytes))
    
EndFunc





Func WebSocketSend($socket, $message)
    Local $length = StringLen($message)
    Local $header = Chr(BitOR(0x80, 0x01)) ; FIN, Opcode Text

    If $length <= 125 Then
        $header &= Chr($length)
    ElseIf $length <= 65535 Then
        $header &= Chr(126) & Chr(BitShift($length, 8)) & Chr(BitAND($length, 0xFF))
    Else
        $header &= Chr(127)
        For $i = 7 To 0 Step -1
            $header &= Chr(BitShift($length, 8 * $i))
        Next
    EndIf

    TCPSend($socket, $header & $message)
EndFunc



;==============================================================================================================================
; Function:         base64($vCode [, $bEncode = True [, $bUrl = False]])
;
; Description:      Decode or Encode $vData using Microsoft.XMLDOM to Base64Binary or Base64Url.
;                   IMPORTANT! Encoded base64url is without @LF after 72 lines. Some websites may require this.
;
; Parameter(s):     $vData      - string or integer | Data to encode or decode.
;                   $bEncode    - boolean           | True - encode, False - decode.
;                   $bUrl       - boolean           | True - output is will decoded or encoded using base64url shema.
;
; Return Value(s):  On Success - Returns output data
;                   On Failure - Returns 1 - Failed to create object.
;
; Author (s):       (Ghads on Wordpress.com), Ascer
;===============================================================================================================================
Func base64($vCode, $bEncode = True, $bUrl = False)

    Local $oDM = ObjCreate("Microsoft.XMLDOM")
    If Not IsObj($oDM) Then Return SetError(1, 0, 1)

    Local $oEL = $oDM.createElement("Tmp")
    $oEL.DataType = "bin.base64"

    If $bEncode then
        $oEL.NodeTypedValue = Binary($vCode)
        If Not $bUrl Then Return $oEL.Text
        Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "")
    Else
        If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/")
        $oEL.Text = $vCode
        Return $oEL.NodeTypedValue
    EndIf

EndFunc ;==>base64





Func unmask($text)
    Local $length = StringToBinary(StringMid($text, 2, 1))
    $length = BitAND(Number($length), 127)
    Local $masks, $data

    If $length = 126 Then
        $masks = StringMid($text, 5, 4)
        $data = StringMid($text, 9)
    ElseIf $length = 127 Then
        $masks = StringMid($text, 11, 4)
        $data = StringMid($text, 15)
    Else
        $masks = StringMid($text, 3, 4)
        $data = StringMid($text, 7)
    EndIf

    Local $result = ""

    For $i = 0 To StringLen($data) - 1
        $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i,  4) + 1, 1))))
    Next

    Return $result
EndFunc

 

hi,milos83

ConsoleWrite("ConsoleWrite:"&$message)

ConsoleWrite:亞5蠨?醬??

After I tested the script, the data sent back by the client was a bunch of garbled code. Can you talk about your proposal? Thank you!

Edited by AndSoW
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...