B4R Library rURL - UrlEncode and UrlDecode

This library was developed by @Erel and me. He lead the way (as always) and I followed. It allows you to UrlEncode and UrlDecode strings in order to use them in URLs. Here is how to use it:

B4X:
    Dim sToURLEncode As String = "Αυτή είναι μία πρόταση στα Ελληνικά. Για να δούμε πόσο καλά θα την κωδικοποιήσει"
    Dim bEnc(sToURLEncode.Length * 3) As Byte
    URL.Encode(sToURLEncode, bEnc)
    Log(bEnc)
    Dim bDec(sToURLEncode.Length * 3) As Byte
    URL.Decode(bEnc, bDec)
    Log(bDec)
 

Attachments

  • rURL.b4xlib
    1 KB · Views: 448
Last edited:

peacemaker

Expert
Licensed User
Longtime User
I had troubles with the lib, but with this code, seems, now better, try:

B4X:
'v.1.1 fix: bounding check

Private Sub Process_Globals
    Private bc As ByteConverter
End Sub

Sub Encode(StringToURLEncode() As Byte, EncodedURL() As Byte)
    Log("URL.Encode: Starting encoding, input length: ", StringToURLEncode.Length)
    Dim buffer(StringToURLEncode.Length * 3) As Byte
    Dim length As Int = UrlEncode(StringToURLEncode, buffer)
    Log("URL.Encode: Encoded length: ", length)
    bc.ArrayCopy(bc.SubString2(buffer, 0, length), EncodedURL)
    Log("URL.Encode: Encoding completed")
End Sub

Sub Decode(StringToURLDecode() As Byte, DecodedURL() As Byte)
    Log("URL.Decode: Starting decoding, input length: ", StringToURLDecode.Length)
    Dim buffer(StringToURLDecode.Length) As Byte
    Dim length As Int = UrlDecode(StringToURLDecode, buffer)
    Log("URL.Decode: Decoded length: ", length)
    bc.ArrayCopy(bc.SubString2(buffer, 0, length), DecodedURL)
    Log("URL.Decode: Decoding completed")
End Sub

Private Sub UrlEncode (s() As Byte, Buffer() As Byte) As Int
    Log("UrlEncode: Starting, input length: ", s.Length, ", buffer size: ", Buffer.Length)
    Dim index As Int = 0
    For i = 0 To s.Length - 1
        Dim c As Byte = s(i)
        
        If c = 32 Then
            Buffer(index) = Asc("+")
            index = index + 1
            Log("UrlEncode: Space encoded as + at position: ", i)
        Else if (c >= Asc("0") And c <= Asc("9")) Or (c >= Asc("A") And c <= Asc("Z")) Or (c >= Asc("a") And c <= Asc("z")) Then
            Buffer(index) = c
            index = index + 1
            'Log("UrlEncode: Regular character at position: ", i)
        Else
            Dim code1 As Byte = Bit.And(c, 0xf) + Asc("0")
            If Bit.And(c, 0xf) > 9 Then
                code1 = Bit.And(c, 0xf) - 10 + Asc("A")
            End If
            c = Bit.And(Bit.ShiftRight(c, 4), 0xf)
            Dim code0 As Byte = c + Asc("0")
            If c > 9 Then
                code0 = c - 10 + Asc("A")
            End If
            Buffer(index) = Asc("%")
            index = index + 1
            Buffer(index) = code0
            index = index + 1
            Buffer(index) = code1
            index = index + 1
            Log("UrlEncode: Special character encoded as %", code0, ",", code1, " at position: ", i)
        End If
        
        ' Buffer overflow check
        If index >= Buffer.Length - 3 Then
            Log("UrlEncode: WARNING - Buffer almost full at position: ", i)
            Exit
        End If
    Next
    Log("UrlEncode: Completed, total encoded length: ", index)
    Return index
End Sub

Private Sub UrlDecode(s() As Byte, Buffer() As Byte) As Int
    Log("UrlDecode: Starting, input length: ", s.Length, ", buffer size: ", Buffer.Length)
    Dim index As Int = 0
    
    For i = 0 To s.Length - 1
        Dim c As Byte = s(i)
        
        If c = Asc("+") Then
            ' Convert + to space
            If index < Buffer.Length Then
                Buffer(index) = Asc(" ")
                index = index + 1
                Log("UrlDecode: + decoded as space at position: ", i)
            Else
                Log("UrlDecode: ERROR - Buffer full at + position: ", i)
                Exit
            End If
        Else If c = Asc("%") Then
            ' Check if there are enough characters after %
            If i + 2 >= s.Length Then
                ' Not enough data for decoding, keep % as is
                Log("UrlDecode: WARNING - Not enough characters after % at position: ", i)
                If index < Buffer.Length Then
                    Buffer(index) = Asc("%")
                    index = index + 1
                Else
                    Log("UrlDecode: ERROR - Buffer full at % position: ", i)
                    Exit
                End If
                Continue
            End If
            
            ' Get the two hex characters after %
            Dim code0 As Byte = s(i + 1)
            Dim code1 As Byte = s(i + 2)
            Log("UrlDecode: Found % sequence at position ", i, ": bytes ", code0, ", ", code1)
            
            ' Skip the two processed characters
            i = i + 2
            
            ' Convert first hex character to numeric value
            If code0 >= Asc("0") And code0 <= Asc("9") Then
                code0 = code0 - Asc("0")
                Log("UrlDecode: code0 is digit: ", code0)
            Else If code0 >= Asc("a") And code0 <= Asc("f") Then
                code0 = code0 - Asc("a") + 10
                Log("UrlDecode: code0 is lowercase hex: ", code0)
            Else If code0 >= Asc("A") And code0 <= Asc("F") Then
                code0 = code0 - Asc("A") + 10
                Log("UrlDecode: code0 is uppercase hex: ", code0)
            Else
                code0 = 0
                Log("UrlDecode: WARNING - Invalid hex character for code0: byte ", code0)
            End If
            
            ' Convert second hex character to numeric value
            If code1 >= Asc("0") And code1 <= Asc("9") Then
                code1 = code1 - Asc("0")
                Log("UrlDecode: code1 is digit: ", code1)
            Else If code1 >= Asc("a") And code1 <= Asc("f") Then
                code1 = code1 - Asc("a") + 10
                Log("UrlDecode: code1 is lowercase hex: ", code1)
            Else If code1 >= Asc("A") And code1 <= Asc("F") Then
                code1 = code1 - Asc("A") + 10
                Log("UrlDecode: code1 is uppercase hex: ", code1)
            Else
                code1 = 0
                Log("UrlDecode: WARNING - Invalid hex character for code1: byte ", code1)
            End If
            
            ' Combine the two hex values into one byte
            Dim decodedByte As Byte = Bit.Or(Bit.ShiftLeft(code0,4), code1)
            
            ' Check if there's space in the buffer
            If index < Buffer.Length Then
                Buffer(index) = decodedByte
                index = index + 1
                Log("UrlDecode: Decoded byte: ", decodedByte)
            Else
                Log("UrlDecode: ERROR - Buffer full at decoded byte position: ", i)
                Exit
            End If
        Else
            ' Regular character, copy as is
            If index < Buffer.Length Then
                Buffer(index) = c
                index = index + 1
                'Log("UrlDecode: Regular character at position: ", i)
            Else
                Log("UrlDecode: ERROR - Buffer full at regular character position: ", i)
                Exit
            End If
        End If
    Next
    
    Log("UrlDecode: Completed, total decoded length: ", index)
    Return index
End Sub

Sub SafeURLDecode(input() As Byte, output() As Byte) As Boolean
    Log("SafeURLDecode: Starting, input length: ", input.Length)
    
    If input.Length = 0 Then
        output = Array As Byte()
        Log("SafeURLDecode: Empty input")
        Return True
    End If
    
    ' Use a larger buffer for safety
    Dim buffer(input.Length + 10) As Byte
    Dim length As Int = UrlDecode(input, buffer)
    
    If length > 0 Then
        ' FIX: Ensure data is copied correctly
        If length <= buffer.Length Then
            output = bc.SubString2(buffer, 0, length)
            Log("SafeURLDecode: Success, output length: ", output.Length)
            Return True
        Else
            Log("SafeURLDecode: ERROR - Length exceeds buffer")
            output = input
            Return False
        End If
    Else
        Log("SafeURLDecode: ERROR - Decoding failed")
        output = input
        Return False
    End If
End Sub
 
Top