KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Utility Method to Decode URLs
PRODUCT: 4D | VERSION: 21 | PLATFORM: Mac & Win
Published On: March 2, 2026
This utility method provides a manual implementation of URL decoding in 4D, as no native command exists. It processes an encoded string by replacing %XX hexadecimal sequences with their corresponding characters, converting + to spaces, and preserving invalid or incomplete sequences as-is. UTF-8 multi-byte characters are supported through byte-level assembly in a BLOB, ensuring accurate reconstruction.
#DECLARE($encoded :Text) -> $result :Text

var $pos :Integer
var $len :Integer
var $char :Text
var $hex :Text
var $code :Integer
var $blob :Blob

SET BLOB SIZE($blob; 0)

$len := Length($encoded)
$pos := 1

While ($pos <= $len)
  $char := $encoded[[$pos]]

  Case of
    : ($char = "+")
      SET BLOB SIZE($blob; BLOB size($blob) + 1; 0x0020)

    : ($char = "%")
      If ($pos + 2 <= $len)
        $hex := $encoded[[$pos + 1]] + $encoded[[$pos + 2]]

        If (Match regex("^[0-9a-fA-F]{2}$"; $hex; 1))
          $code := Num($hex; 16)
          SET BLOB SIZE($blob; BLOB size($blob) + 1; $code)
          $pos := $pos + 2
        Else
          SET BLOB SIZE($blob; BLOB size($blob) + 1; 0x0025)
        End if

      Else
        SET BLOB SIZE($blob; BLOB size($blob) + 1; 0x0025)
      End if

    Else
      SET BLOB SIZE($blob; BLOB size($blob) + 1; Character code($char))
  End case

  $pos := $pos + 1
End while

$result := BLOB to text($blob; UTF8 text without length)
return $result

Test examples:

//example:1 UTF-8 encoded characters:


var $encoded; $decoded; $expected : Text
var $ok : Boolean



$encoded:="q=Caf%C3%A9+Paris+%F0%9F%8C%B6"
$decoded:=URL_DECODE($encoded)
$expected:="q=Café Paris 🌶"
$ok:=($decoded=$expected)
ALERT(Choose($ok; "OK UTF-8"; "FAIL UTF-8")+" => "+$decoded)


//example 2: Normal everyday URL parameters

$encoded:="name=John+Doe&email=john.doe%40example.com&message=Hello+there%21"
$decoded:=URL_DECODE($encoded)
$expected:="name=John Doe&email=john.doe@example.com&message=Hello there!"
$ok:=($decoded=$expected)
ALERT(Choose($ok; "OK"; "FAIL")+" => "+$decoded)

//exampe 3: Malformed / malicious input

$encoded:="%20SELECT%20*%20FROM%20users--"
$decoded:=URL_DECODE($encoded)
$expected:=" SELECT * FROM users--"
$ok:=($decoded=$expected)
ALERT(Choose($ok; "OK SQL-like"; "FAIL SQL")+" => "+$decoded)

$encoded:="payload=%3Cscript%3Ealert(1)%3C/script%3E"
$decoded:=URL_DECODE($encoded)
$expected:="payload=<script>alert(1)</script>"
$ok:=($decoded=$expected)
ALERT(Choose($ok; "OK XSS"; "FAIL XSS")+" => "+$decoded)