URL decoding
This task (the reverse of URL encoding and distinct from URL parser) is to provide a function or mechanism to convert an URL-encoded string into its original unencoded form.
You are encouraged to solve this task according to the task description, using any language you may know.
- Test cases
- The encoded string "
http%3A%2F%2Ffoo%20bar%2F
" should be reverted to the unencoded form "http://foo bar/
".
- The encoded string "
google.com/search?q=%60Abdu%27l-Bah%C3%A1
" should revert to the unencoded form "google.com/search?q=`Abdu'l-Bahá
".
ABAP
<lang ABAP>REPORT Z_DECODE_URL.
DATA: lv_encoded_url TYPE string VALUE 'http%3A%2F%2Ffoo%20bar%2F',
lv_decoded_url TYPE string.
CALL METHOD CL_HTTP_UTILITY=>UNESCAPE_URL
EXPORTING ESCAPED = lv_encoded_url RECEIVING UNESCAPED = lv_decoded_url.
WRITE: 'Encoded URL: ', lv_encoded_url, /, 'Decoded URL: ', lv_decoded_url.</lang>
Ada
<lang Ada>with AWS.URL; with Ada.Text_IO; use Ada.Text_IO; procedure Decode is
Encoded : constant String := "http%3A%2F%2Ffoo%20bar%2F";
begin
Put_Line (AWS.URL.Decode (Encoded));
end Decode; </lang>
Without external libraries:
<lang Ada>package URL is
function Decode (URL : in String) return String;
end URL;</lang>
<lang Ada>package body URL is
function Decode (URL : in String) return String is Buffer : String (1 .. URL'Length); Filled : Natural := 0; Position : Positive := URL'First; begin while Position in URL'Range loop Filled := Filled + 1; case URL (Position) is when '+' => Buffer (Filled) := ' '; Position := Position + 1; when '%' => Buffer (Filled) := Character'Val (Natural'Value ("16#" & URL (Position + 1 .. Position + 2) & "#")); Position := Position + 3; when others => Buffer (Filled) := URL (Position); Position := Position + 1; end case; end loop;
return Buffer (1 .. Filled); end Decode;
end URL;</lang>
<lang Ada>with Ada.Command_Line,
Ada.Text_IO;
with URL;
procedure Test_URL_Decode is
use Ada.Command_Line, Ada.Text_IO;
begin
if Argument_Count = 0 then Put_Line (URL.Decode ("http%3A%2F%2Ffoo%20bar%2F")); else for I in 1 .. Argument_Count loop Put_Line (URL.Decode (Argument (I))); end loop; end if;
end Test_URL_Decode;</lang>
Apex
<lang apex>EncodingUtil.urlDecode('http%3A%2F%2Ffoo%20bar%2F', 'UTF-8'); EncodingUtil.urlDecode('google.com/search?q=%60Abdu%27l-Bah%C3%A1', 'UTF-8');</lang>
http://foo bar/ google.com/search?q=`Abdu'l-Bahá
AppleScript
<lang AppleScript>AST URL decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"</lang>
AutoHotkey
<lang AutoHotkey>encURL := "http%3A%2F%2Ffoo%20bar%2F" SetFormat, Integer, hex Loop Parse, encURL
If A_LoopField = `% reading := 2, read := "" else if reading { read .= A_LoopField, --reading if not reading out .= Chr("0x" . read) } else out .= A_LoopField
MsgBox % out ; http://foo bar/ </lang>
AWK
<lang AWK>
- syntax:
awk ' BEGIN {
str = "http%3A%2F%2Ffoo%20bar%2F" # "http://foo bar/" printf("%s\n",str) len=length(str) for (i=1;i<=len;i++) { if ( substr(str,i,1) == "%") { L = substr(str,1,i-1) # chars to left of "%" M = substr(str,i+1,2) # 2 chars to right of "%" R = substr(str,i+3) # chars to right of "%xx" str = sprintf("%s%c%s",L,hex2dec(M),R) } } printf("%s\n",str) exit(0)
} function hex2dec(s, num) {
num = index("0123456789ABCDEF",toupper(substr(s,length(s)))) - 1 sub(/.$/,"",s) return num + (length(s) ? 16*hex2dec(s) : 0)
} ' </lang>
- Output:
http%3A%2F%2Ffoo%20bar%2F http://foo bar/
BBC BASIC
<lang bbcbasic> PRINT FNurldecode("http%3A%2F%2Ffoo%20bar%2F")
END DEF FNurldecode(url$) LOCAL i% REPEAT i% = INSTR(url$, "%", i%+1) IF i% THEN url$ = LEFT$(url$,i%-1) + \ \ CHR$EVAL("&"+FNupper(MID$(url$,i%+1,2))) + \ \ MID$(url$,i%+3) ENDIF UNTIL i% = 0 = url$ DEF FNupper(A$) LOCAL A%,C% FOR A% = 1 TO LEN(A$) C% = ASCMID$(A$,A%) IF C% >= 97 IF C% <= 122 MID$(A$,A%,1) = CHR$(C%-32) NEXT = A$</lang>
- Output:
http://foo bar/
Bracmat
<lang bracmat>( ( decode
= decoded hexcode notencoded . :?decoded & whl ' ( @(!arg:?notencoded "%" (% %:?hexcode) ?arg) & !decoded !notencoded chr$(x2d$!hexcode):?decoded ) & str$(!decoded !arg) ) & out$(decode$http%3A%2F%2Ffoo%20bar%2F)
);</lang>
- Output:
http://foo bar/
C
<lang c>#include <stdio.h>
- include <string.h>
inline int ishex(int x) { return (x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'); }
int decode(const char *s, char *dec) { char *o; const char *end = s + strlen(s); int c;
for (o = dec; s <= end; o++) { c = *s++; if (c == '+') c = ' '; else if (c == '%' && ( !ishex(*s++) || !ishex(*s++) || !sscanf(s - 2, "%2x", &c))) return -1;
if (dec) *o = c; }
return o - dec; }
int main() { const char *url = "http%3A%2F%2ffoo+bar%2fabcd"; char out[strlen(url) + 1];
printf("length: %d\n", decode(url, 0)); puts(decode(url, out) < 0 ? "bad string" : out);
return 0; }</lang>
C++
<lang cpp>#include <string>
- include "Poco/URI.h"
- include <iostream>
int main( ) {
std::string encoded( "http%3A%2F%2Ffoo%20bar%2F" ) ; std::string decoded ; Poco::URI::decode ( encoded , decoded ) ; std::cout << encoded << " is decoded: " << decoded << " !" << std::endl ; return 0 ;
}</lang>
- Output:
http%3A%2F%2Ffoo%20bar%2F is decoded: http://foo bar/ !
C#
<lang csharp>using System;
namespace URLEncode {
internal class Program { private static void Main(string[] args) { Console.WriteLine(Decode("http%3A%2F%2Ffoo%20bar%2F")); }
private static string Decode(string uri) { return Uri.UnescapeDataString(uri); } }
}</lang>
- Output:
http://foo bar/
Caché ObjectScript
USER>Write $ZConvert("http%3A%2F%2Ffoo%20bar%2F", "I", "URL") http://foo bar/
Clojure
<lang clojure>(java.net.URLDecoder/decode "http%3A%2F%2Ffoo%20bar%2F")</lang>
CoffeeScript
<lang coffeescript> console.log decodeURIComponent "http%3A%2F%2Ffoo%20bar%2F?name=Foo%20Barson" </lang>
<lang> > coffee foo.coffee http://foo bar/?name=Foo Barson </lang>
Common Lisp
<lang lisp>(defun decode (string &key start)
(assert (char= (char string start) #\%)) (if (>= (length string) (+ start 3)) (multiple-value-bind (code pos) (parse-integer string :start (1+ start) :end (+ start 3) :radix 16 :junk-allowed t) (if (= pos (+ start 3)) (values (code-char code) pos) (values #\% (1+ start)))) (values #\% (1+ start))))
(defun url-decode (url)
(loop with start = 0 for pos = (position #\% url :start start) collect (subseq url start pos) into chunks when pos collect (multiple-value-bind (decoded next) (decode url :start pos) (setf start next) (string decoded)) into chunks while pos finally (return (apply #'concatenate 'string chunks))))
(url-decode "http%3A%2F%2Ffoo%20bar%2F")</lang>
- Output:
"http://foo bar/"
D
<lang d>import std.stdio, std.uri;
void main() {
writeln(decodeComponent("http%3A%2F%2Ffoo%20bar%2F"));
}</lang>
http://foo bar/
Delphi
<lang Delphi>program URLEncoding;
{$APPTYPE CONSOLE}
uses IdURI;
begin
Writeln(TIdURI.URLDecode('http%3A%2F%2Ffoo%20bar%2F'));
end.</lang>
Elixir
<lang elixir>IO.inspect URI.decode("http%3A%2F%2Ffoo%20bar%2F") IO.inspect URI.decode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</lang>
- Output:
"http://foo bar/" "google.com/search?q=`Abdu'l-Bahá"
Erlang
Built in.
34> http_uri:decode("http%3A%2F%2Ffoo%20bar%2F"). "http://foo bar/"
F#
<lang fsharp>open System
let decode uri = Uri.UnescapeDataString(uri)
[<EntryPoint>] let main argv =
printfn "%s" (decode "http%3A%2F%2Ffoo%20bar%2F") 0</lang>
Go
<lang go>package main
import ( "fmt" "log" "net/url" )
func main() { for _, escaped := range []string{ "http%3A%2F%2Ffoo%20bar%2F", "google.com/search?q=%60Abdu%27l-Bah%C3%A1", } { u, err := url.QueryUnescape(escaped) if err != nil { log.Println(err) continue } fmt.Println(u) } }</lang>
- Output:
http://foo bar/ google.com/search?q=`Abdu'l-Bahá
Groovy
<lang groovy>assert URLDecoder.decode('http%3A%2F%2Ffoo%20bar%2F') == 'http://foo bar/'</lang>
Haskell
<lang Haskell>import qualified Data.Char as Char
urlDecode :: String -> Maybe String urlDecode [] = Just [] urlDecode ('%':xs) =
case xs of (a:b:xss) -> urlDecode xss >>= return . ((Char.chr . read $ "0x" ++ [a,b]) :) _ -> Nothing
urlDecode ('+':xs) = urlDecode xs >>= return . (' ' :) urlDecode (x:xs) = urlDecode xs >>= return . (x :)
main :: IO () main = putStrLn . maybe "Bad decode" id $ urlDecode "http%3A%2F%2Ffoo%20bar%2F"</lang>
- Output:
http://foo bar/
Another approach: <lang haskell>import Data.Char (chr) import Data.List.Split (splitOn)
deCode :: String -> String deCode url =
let ps = splitOn "%" url in concat $ head ps : ((\(a, b) -> (chr . read) (mappend "0x" a) : b) <$> (splitAt 2 <$> tail ps))
-- TEST ------------------------------------------------------------------------ main :: IO () main = putStrLn $ deCode "http%3A%2F%2Ffoo%20bar%2F"</lang>
- Output:
http://foo bar/
Icon and Unicon
<lang Icon>link hexcvt
procedure main() ue := "http%3A%2F%2Ffoo%20bar%2F" ud := decodeURL(ue) | stop("Improperly encoded string ",image(ue)) write("encoded = ",image(ue)) write("decoded = ",image(ue)) end
procedure decodeURL(s) #: decode URL/URI encoded data static de initial { # build lookup table for everything
de := table() every de[hexstring(ord(c := !string(&ascii)),2)] := c }
c := "" s ? until pos(0) do # decode every %xx or fail
c ||:= if ="%" then \de[move(2)] | fail else move(1)
return c end</lang>
- Output:
encoded = "http%3A%2F%2Ffoo%20bar%2F" decoded = "http://foo bar/"
J
J does not have a native urldecode (until version 7 when the jhs
ide addon includes a jurldecode).
Here is an implementation:
<lang j>require'strings convert' urldecode=: rplc&(~.,/;"_1&a."2(,:tolower)'%',.toupper hfd i.#a.)</lang>
Example use:
<lang j> urldecode 'http%3A%2F%2Ffoo%20bar%2F' http://foo bar/</lang>
Note that an earlier implementation assumed the j6 implementation of hfd
which where hexadecimal letters resulting from hfd
were upper case. J8, in contrast, provides a lower case result from hfd. The addition of toupper
guarantees the case insensitivity required by RFC 3986 regardless of which version of J you are using. As the parenthesized expression containing hfd
is only evaluated at definition time, there's no performance penalty from the use of toupper
.
Example use:
<lang j> urldecode 'google.com/search?q=%60Abdu%27l-Bah%C3%A1' google.com/search?q=`Abdu'l-Bahá</lang>
Java
<lang java>import java.io.UnsupportedEncodingException; import java.net.URLDecoder;
public class Main {
public static void main(String[] args) throws UnsupportedEncodingException { String encoded = "http%3A%2F%2Ffoo%20bar%2F"; String normal = URLDecoder.decode(encoded, "utf-8"); System.out.println(normal); }
}</lang>
- Output:
http://foo bar/
JavaScript
<lang javascript>decodeURIComponent("http%3A%2F%2Ffoo%20bar%2F")</lang>
jq
If your jq already has "until", then the definition given below may be omitted. <lang jq># Emit . and stop as soon as "condition" is true. def until(condition; next):
def u: if condition then . else (next|u) end; u;
def url_decode:
# The helper function converts the input string written in the given # "base" to an integer def to_i(base): explode | reverse | map(if 65 <= . and . <= 90 then . + 32 else . end) # downcase | map(if . > 96 then . - 87 else . - 48 end) # "a" ~ 97 => 10 ~ 87 | reduce .[] as $c # base: [power, ans] ([1,0]; (.[0] * base) as $b | [$b, .[1] + (.[0] * $c)]) | .[1];
. as $in | length as $length | [0, ""] # i, answer | until ( .[0] >= $length; .[0] as $i | if $in[$i:$i+1] == "%" then [ $i + 3, .[1] + ([$in[$i+1:$i+3] | to_i(16)] | implode) ] else [ $i + 1, .[1] + $in[$i:$i+1] ] end) | .[1]; # answer</lang>
Example: <lang jq>"http%3A%2F%2Ffoo%20bar%2F" | url_decode</lang>
- Output:
<lang sh> "http://foo bar/"</lang>
Julia
<lang Julia> using URIParser
enc = "http%3A%2F%2Ffoo%20bar%2F"
dcd = unescape(enc)
println(enc, " => ", dcd) </lang>
- Output:
http%3A%2F%2Ffoo%20bar%2F => http://foo bar/
Kotlin
<lang scala>// version 1.1.2
import java.net.URLDecoder
fun main(args: Array<String>) {
val encoded = arrayOf("http%3A%2F%2Ffoo%20bar%2F", "google.com/search?q=%60Abdu%27l-Bah%C3%A1") for (e in encoded) println(URLDecoder.decode(e, "UTF-8"))
}</lang>
- Output:
http://foo bar/ google.com/search?q=`Abdu'l-Bahá
Lasso
<lang Lasso>bytes('http%3A%2F%2Ffoo%20bar%2F') -> decodeurl</lang> -> http://foo bar/
Liberty BASIC
<lang lb>
dim lookUp$( 256)
for i =0 to 256 lookUp$( i) ="%" +dechex$( i) next i
url$ ="http%3A%2F%2Ffoo%20bar%2F"
print "Supplied URL '"; url$; "'" print "As string '"; url2string$( url$); "'"
end
function url2string$( i$)
for j =1 to len( i$) c$ =mid$( i$, j, 1) if c$ ="%" then nc$ =chr$( hexdec( mid$( i$, j +1, 2))) url2string$ =url2string$ +nc$ j =j +2 else url2string$ =url2string$ +c$ end if next j
end function </lang>
Supplied URL 'http%3A%2F%2Ffoo%20bar%2F' As string 'http://foo bar/'
LiveCode
<lang LiveCode>put urlDecode("http%3A%2F%2Ffoo%20bar%2F") & cr & \
urlDecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</lang>Results<lang>http://foo bar/
google.com/search?q=`Abdu'l-Bah√°</lang>
Lua
<lang lua>function decodeChar(hex) return string.char(tonumber(hex,16)) end
function decodeString(str) local output, t = string.gsub(str,"%%(%x%x)",decodeChar) return output end
-- will print "http://foo bar/" print(decodeString("http%3A%2F%2Ffoo%20bar%2F"))</lang>
Maple
<lang Maple>StringTools:-Decode("http%3A%2F%2Ffoo%20bar%2F", encoding=percent);</lang>
- Output:
"http://foo bar/"
Mathematica
<lang mathematica>URLDecoding[url_] :=
StringReplace[url, "%" ~~ x_ ~~ y_ :> FromDigits[x ~~ y, 16]] //. StringExpression[x___, Longest[n__Integer], y___] :> StringExpression[x, FromCharacterCode[{n}, "UTF8"], y]</lang>
Example use:
<lang mathematica>URLDecoding["http%3A%2F%2Ffoo%20bar%2F"]</lang>
- Output:
http://foo bar/
MATLAB / Octave
<lang MATLAB>function u = urldecoding(s)
u = ; k = 1; while k<=length(s) if s(k) == '%' && k+2 <= length(s) u = sprintf('%s%c', u, char(hex2dec(s((k+1):(k+2))))); k = k + 3; else u = sprintf('%s%c', u, s(k)); k = k + 1; end end
end</lang> Usage:
octave:3> urldecoding('http%3A%2F%2Ffoo%20bar%2F') ans = http://foo bar/
NetRexx
<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols nobinary
url = [ -
'http%3A%2F%2Ffoo%20bar%2F', - 'mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E', - '%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E' - ]
loop u_ = 0 to url.length - 1
say url[u_] say DecodeURL(url[u_]) say end u_
return
method DecodeURL(arg) public static
Parse arg encoded decoded = PCT = '%'
loop label e_ while encoded.length() > 0 parse encoded head (PCT) +1 code +2 tail decoded = decoded || head select when code.strip('T').length() = 2 & code.datatype('X') then do code = code.x2c() decoded = decoded || code end when code.strip('T').length() \= 0 then do decoded = decoded || PCT tail = code || tail end otherwise do nop end end encoded = tail end e_
return decoded
</lang>
- Output:
http%3A%2F%2Ffoo%20bar%2F http://foo bar/ mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E mailto:"Ivan Aim" <ivan.aim@email.com> %6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E mailto:"Irma User" <irma.user@mail.com>
NewLISP
<lang NewLISP>;; universal decoder, works for ASCII and UTF-8
(define (url-decode url (opt nil))
(if opt (replace "+" url " ")) (replace "%([0-9a-f][0-9a-f])" url (pack "b" (int $1 0 16)) 1))
(url-decode "http%3A%2F%2Ffoo%20bar%2F")</lang>
Nim
<lang nim>import cgi
echo decodeUrl("http%3A%2F%2Ffoo%20bar%2F")</lang>
Oberon-2
<lang oberon2> MODULE URLDecoding; IMPORT
URI := URI:String, Out := NPCT:Console;
BEGIN
Out.String(URI.Unescape("http%3A%2F%2Ffoo%20bar%2F"));Out.Ln; Out.String(URI.Unescape("google.com/search?q=%60Abdu%27l-Bah%C3%A1"));Out.Ln;
END URLDecoding. </lang>
- Output:
http://foo bar/ google.com/search?q=`Abdu'l-Bahá
Objeck
<lang objeck> class UrlDecode {
function : Main(args : String[]) ~ Nil { Net.UrlUtility->Decode("http%3A%2F%2Ffoo%20bar%2F")->PrintLine(); }
} </lang>
Objective-C
<lang objc>NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F"; NSString *normal = [encoded stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSLog(@"%@", normal);</lang>
<lang objc>NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F"; NSString *normal = [encoded stringByRemovingPercentEncoding]; NSLog(@"%@", normal);</lang>
OCaml
Using the library ocamlnet from the interactive loop:
<lang ocaml>$ ocaml
- #use "topfind";;
- #require "netstring";;
- Netencoding.Url.decode "http%3A%2F%2Ffoo%20bar%2F" ;;
- : string = "http://foo bar/"</lang>
ooRexx
While the implementation shown for Rexx will also work with ooRexx, this version uses ooRexx syntax to invoke the built-in functions. <lang ooRexx>/* Rexx */
X = 0 url. = X = X + 1; url.0 = X; url.X = 'http%3A%2F%2Ffoo%20bar%2F' X = X + 1; url.0 = X; url.X = 'mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E' X = X + 1; url.0 = X; url.X = '%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E'
Do u_ = 1 to url.0 Say url.u_ Say DecodeURL(url.u_) Say End u_
Exit
DecodeURL: Procedure
Parse Arg encoded decoded = PCT = '%'
Do label e_ while encoded~length() > 0 Parse Var encoded head (PCT) +1 code +2 tail decoded = decoded || head Select when code~strip('T')~length() = 2 & code~datatype('X') then Do code = code~x2c() decoded = decoded || code End when code~strip('T')~length() \= 0 then Do decoded = decoded || PCT tail = code || tail End otherwise Nop End encoded = tail End e_
Return decoded</lang>
- Output:
http%3A%2F%2Ffoo%20bar%2F http://foo bar/ mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E mailto:"Ivan Aim" <ivan.aim@email.com> %6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E mailto:"Irma User" <irma.user@mail.com>
Perl
<lang Perl>sub urldecode {
my $s = shift; $s =~ tr/\+/ /; $s =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/eg; return $s;
}
print urldecode('http%3A%2F%2Ffoo+bar%2F')."\n"; </lang>
<lang Perl>#!/usr/bin/perl -w use strict ; use URI::Escape ;
my $encoded = "http%3A%2F%2Ffoo%20bar%2F" ; my $unencoded = uri_unescape( $encoded ) ; print "The unencoded string is $unencoded !\n" ;</lang>
Perl 6
<lang perl6>my $url = "http%3A%2F%2Ffoo%20bar%2F";
say $url.subst: :g,
/'%'(<:hexdigit>**2)/, -> ($ord ) { chr(:16(~$ord)) }</lang>
Alternately, you can use an in-place substitution: <lang perl6>$url ~~ s:g[ '%' (<:hexdigit> ** 2) ] = chr :16(~$0); say $url;</lang>
Phix
<lang Phix>-- -- demo\rosetta\decode_url.exw -- =========================== -- function decode_url(string s) integer skip = 0 string res = ""
for i=1 to length(s) do if skip then skip -= 1 else integer ch = s[i] if ch='%' then sequence scanres = {} if i+2<=length(s) then scanres = scanf("#"&s[i+1..i+2],"%x") end if if length(scanres)!=1 then return "decode error" end if skip = 2 ch = scanres[1][1] elsif ch='+' then ch = ' ' end if res &= ch end if end for return res
end function
printf(1,"%s\n",{decode_url("http%3A%2F%2Ffoo%20bar%2F")}) printf(1,"%s\n",{decode_url("google.com/search?q=%60Abdu%27l-Bah%C3%A1")})</lang>
- Output:
http://foo bar/ google.com/search?q=`Abdu'l-Bahá
PHP
<lang php><?php $encoded = "http%3A%2F%2Ffoo%20bar%2F"; $unencoded = rawurldecode($encoded); echo "The unencoded string is $unencoded !\n"; ?></lang>
PicoLisp
: (ht:Pack (chop "http%3A%2F%2Ffoo%20bar%2F") T) -> "http://foo bar/"
PowerShell
<lang PowerShell> [System.Web.HttpUtility]::UrlDecode("http%3A%2F%2Ffoo%20bar%2F") </lang>
- Output:
http://foo bar/
PureBasic
<lang PureBasic>URL$ = URLDecoder("http%3A%2F%2Ffoo%20bar%2F")
Debug URL$ ; http://foo bar/</lang>
Python
<lang Python>import urllib print urllib.unquote("http%3A%2F%2Ffoo%20bar%2F")</lang>
R
<lang R>URLdecode("http%3A%2F%2Ffoo%20bar%2F")</lang>
Racket
<lang racket>
- lang racket
(require net/uri-codec) (uri-decode "http%3A%2F%2Ffoo%20bar%2F") </lang>
Retro
This is provided by the casket library (used for web app development).
<lang Retro>create buffer 32000 allot
{{
create bit 5 allot : extract ( $c-$a ) drop @+ bit ! @+ bit 1+ ! bit ; : render ( $c-$n ) dup '+ = [ drop 32 ] ifTrue dup 13 = [ drop 32 ] ifTrue dup 10 = [ drop 32 ] ifTrue dup '% = [ extract hex toNumber decimal ] ifTrue ; : <decode> ( $-$ ) repeat @+ 0; render ^buffer'add again ;
---reveal---
: decode ( $- ) buffer ^buffer'set <decode> drop ;
}}
"http%3A%2F%2Ffoo%20bar%2F" decode buffer puts</lang>
REXX
version 1
Tested with the ooRexx and Regina interpreters. <lang REXX>/* Rexx */
Do
X = 0 url. = X = X + 1; url.0 = X; url.X = 'http%3A%2F%2Ffoo%20bar%2F' X = X + 1; url.0 = X; url.X = 'mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E' X = X + 1; url.0 = X; url.X = '%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E'
Do u_ = 1 to url.0 Say url.u_ Say DecodeURL(url.u_) Say End u_
Return
End Exit
DecodeURL: Procedure Do
Parse Arg encoded decoded = PCT = '%'
Do while length(encoded) > 0 Parse Var encoded head (PCT) +1 code +2 tail decoded = decoded || head Select When length(strip(code, 'T')) = 2 & datatype(code, 'X') then Do code = x2c(code) decoded = decoded || code End When length(strip(code, 'T')) \= 0 then Do decoded = decoded || PCT tail = code || tail End Otherwise Do Nop End End encoded = tail End
Return decoded
End Exit </lang>
- Output:
http%3A%2F%2Ffoo%20bar%2F http://foo bar/ mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E mailto:"Ivan Aim" <ivan.aim@email.com> %6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E mailto:"Irma User" <irma.user@mail.com>
version 2
This REXX version is identical to version 1, but with superfluous and dead code removed. <lang REXX>/*REXX program converts an URL─encoded string ──► its original unencoded form.*/ url.1='http%3A%2F%2Ffoo%20bar%2F' url.2='mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E' url.3='%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E' URLs=3
do j=1 for URLs say url.j say decodeURL(url.j) say end /*j*/
exit /*────────────────────────────────────────────────────────────────────────────*/ decodeURL: procedure; parse arg encoded; decoded= encoded=translate(encoded,,'+') /*special case for encoded blank.*/
do while length(encoded)\==0 parse var encoded head '%' +1 code +2 tail decoded=decoded || head
select when length(strip(code,'T'))==2 &, datatype(code,'X') then decoded=decoded || x2c(code) when length(strip(code,'T'))\==0 then do decoded=decoded'%' tail=code || tail end otherwise nop end /*select*/ encoded=tail end /*while*/
return decoded</lang>
- output is identical to the 1st REXX version.
version 3
This REXX version is a shorter version of version 2. <lang REXX>/*REXX program converts & displays an URL─encoded string ──► its original unencoded form*/ url.1='http%3A%2F%2Ffoo%20bar%2F' url.2='mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E' url.3='%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E' URLs=3
do j=1 for URLs; say /*process each URL; display blank line.*/ say url.j /*display the original URL. */ say URLdecode(url.j) /* " " decoded " */ end /*j*/
exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ URLdecode: procedure; parse arg yyy /*get encoded URL from argument list. */
yyy=translate(yyy, , '+') /*a special case for an encoded blank. */ URL= do until yyy= parse var yyy plain '%' +1 code +2 yyy URL=URL || plain if datatype(code, 'X') then URL=URL || x2c(code) else URL=URL'%'code end /*until*/ return URL</lang>
- output is identical to the 1st REXX version.
Ruby
Use any one of CGI.unescape
or URI.decode_www_form_component
. These methods also convert "+" to " ".
<lang ruby>require 'cgi' puts CGI.unescape("http%3A%2F%2Ffoo%20bar%2F")
- => "http://foo bar/"</lang>
<lang ruby>require 'uri' puts URI.decode_www_form_component("http%3A%2F%2Ffoo%20bar%2F")
- => "http://foo bar/"</lang>
URI.unescape
(alias URI.unencode
) still works. URI.unescape
is obsolete since Ruby 1.9.2 because of problems with its sibling URI.escape
.
Scala
<lang scala>import java.net.{URLDecoder, URLEncoder}
import scala.compat.Platform.currentTime
object UrlCoded extends App {
val original = """http://foo bar/""" val encoded: String = URLEncoder.encode(original, "UTF-8")
assert(encoded == "http%3A%2F%2Ffoo+bar%2F", s"Original: $original not properly encoded: $encoded")
val percentEncoding = encoded.replace("+", "%20") assert(percentEncoding == "http%3A%2F%2Ffoo%20bar%2F", s"Original: $original not properly percent-encoded: $percentEncoding")
assert(URLDecoder.decode(encoded, "UTF-8") == URLDecoder.decode(percentEncoding, "UTF-8"))
println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")
}</lang>
Seed7
The library encoding.s7i defines functions to handle URL respectively percent encoding. The function fromPercentEncoded decodes a percend-encoded string. The function fromUrlEncoded works like fromPercentEncoded and additionally decodes '+' with a space. Both functions return byte sequences. To decode Unicode characters it is necessary to convert them from UTF-8 with utf8ToStri afterwards. <lang seed7>$ include "seed7_05.s7i";
include "encoding.s7i";
const proc: main is func
begin writeln(fromPercentEncoded("http%3A%2F%2Ffoo%20bar%2F")); writeln(fromUrlEncoded("http%3A%2F%2Ffoo+bar%2F")); end func;</lang>
- Output:
http://foo bar/ http://foo bar/
Sidef
<lang ruby>func urldecode(str) {
str.gsub!('+', ' '); str.gsub!(/\%([A-Fa-f0-9]{2})/, {|a| 'C'.pack(a.hex)}); return str;
}
say urldecode('http%3A%2F%2Ffoo+bar%2F'); # => "http://foo bar/"</lang>
Swift
<lang swift>import Foundation
let encoded = "http%3A%2F%2Ffoo%20bar%2F" if let normal = encoded.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
println(normal)
}</lang>
Tcl
This code is careful to ensure that any untoward metacharacters in the input string still do not cause any problems. <lang tcl>proc urlDecode {str} {
set specialMap {"[" "%5B" "]" "%5D"} set seqRE {%([0-9a-fA-F]{2})} set replacement {[format "%c" [scan "\1" "%2x"]]} set modStr [regsub -all $seqRE [string map $specialMap $str] $replacement] return [encoding convertfrom utf-8 [subst -nobackslash -novariable $modStr]]
}</lang> Demonstrating: <lang tcl>puts [urlDecode "http%3A%2F%2Ffoo%20bar%2F"]</lang>
- Output:
http://foo bar/
TUSCRIPT
<lang tuscript> $$ MODE TUSCRIPT url_encoded="http%3A%2F%2Ffoo%20bar%2F" BUILD S_TABLE hex=":%><:><2<>2<%:" hex=STRINGS (url_encoded,hex), hex=SPLIT(hex) hex=DECODE (hex,hex) url_decoded=SUBSTITUTE(url_encoded,":%><2<>2<%:",0,0,hex) PRINT "encoded: ", url_encoded PRINT "decoded: ", url_decoded </lang>
- Output:
encoded: http%3A%2F%2Ffoo%20bar%2F decoded: http://foo bar/
UNIX Shell
<lang bash>function urldecode {
typeset encoded=$1 decoded= rest= c= c1= c2= typeset rest2= bug='rest2=${rest}'
if [[ -z ${BASH_VERSION:-} ]]; then typeset -i16 hex=0; typeset -i8 oct=0
# bug /usr/bin/sh HP-UX 11.00 typeset _encoded='xyz%26xyz' rest="${_encoded#?}" c="${_encoded%%${rest}}" if (( ${#c} != 1 )); then typeset qm='????????????????????????????????????????????????????????????????????????' typeset bug='(( ${#rest} > 0 )) && typeset -L${#rest} rest2="${qm}" || rest2=${rest}' fi fi
rest="${encoded#?}" eval ${bug} c="${encoded%%${rest2}}" encoded="${rest}"
while [[ -n ${c} ]]; do if [[ ${c} = '%' ]]; then rest="${encoded#?}" eval ${bug} c1="${encoded%%${rest2}}" encoded="${rest}"
rest="${encoded#?}" eval ${bug} c2="${encoded%%${rest2}}" encoded="${rest}"
if [[ -z ${c1} || -z ${c2} ]]; then c="%${c1}${c2}" echo "WARNING: invalid % encoding: ${c}" >&2 elif [[ -n ${BASH_VERSION:-} ]]; then c="\\x${c1}${c2}" c=$(\echo -e "${c}") else hex="16#${c1}${c2}"; oct=hex c="\\0${oct#8\#}" c=$(print -- "${c}") fi elif [[ ${c} = '+' ]]; then c=' ' fi
decoded="${decoded}${c}"
rest="${encoded#?}" eval ${bug} c="${encoded%%${rest2}}" encoded="${rest}" done
if [[ -n ${BASH_VERSION:-} ]]; then \echo -E "${decoded}" else print -r -- "${decoded}" fi } </lang>
VBScript
<lang VBScript>Function UrlDecode(s) For i = 1 To Len(s) If Mid(s,i,1) = "%" Then UrlDecode = UrlDecode & Chr("&H" & Mid(s,i+1,2)) i = i + 2 Else UrlDecode = UrlDecode & Mid(s,i,1) End If Next End Function
url = "http%3A%2F%2Ffoo%20bar%2F" WScript.Echo "Encoded URL: " & url & vbCrLf &_ "Decoded URL: " & UrlDecode(url)</lang>
- Output:
Encoded URL: http%3A%2F%2Ffoo%20bar%2F Decoded URL: http://foo bar/
XPL0
<lang XPL0>code Text=12; string 0; \use zero-terminated strings
func Decode(S0); \Decode URL string and return its address char S0; char S1(80); \BEWARE: very temporary string space returned int C, N, I, J; [I:= 0; J:= 0; repeat C:= S0(I); I:= I+1; \get char
if C=^% then \convert hex to char [C:= S0(I); I:= I+1; if C>=^a then C:= C & ~$20; \convert to uppercase N:= C - (if C<=^9 then ^0 else ^A-10); C:= S0(I); I:= I+1; if C>=^a then C:= C & ~$20; C:= N*16 + C - (if C<=^9 then ^0 else ^A-10); ]; S1(J):= C; J:= J+1; \put char in output string
until C=0; return S1; ];
Text(0, Decode("http%3A%2F%2Ffoo%20bar%2f"))</lang>
- Output:
http://foo bar/
zkl
<lang zkl>"http%3A%2F%2Ffoo%20bar%2F".pump(String, // push each char through these fcns:
fcn(c){ if(c=="%") return(Void.Read,2); return(Void.Skip,c) },// %-->read 2 chars else pass through fcn(_,b,c){ (b+c).toInt(16).toChar() }) // "%" (ignored) "3"+"1"-->0x31-->"1"</lang>
- Output:
http://foo bar/
or use libCurl: <lang zkl>var Curl=Import("zklCurl"); Curl.urlDecode("http%3A%2F%2Ffoo%20bar%2F");</lang>
- Output:
http://foo bar/