URL decoding: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Raku}}: added output)
 
(33 intermediate revisions by 17 users not shown)
Line 10: Line 10:


* &nbsp; The encoded string &nbsp; "<code><nowiki>google.com/search?q=%60Abdu%27l-Bah%C3%A1</nowiki></code>" &nbsp; should revert to the unencoded form &nbsp; "<code><nowiki>google.com/search?q=`Abdu'l-Bahá</nowiki></code>".
* &nbsp; The encoded string &nbsp; "<code><nowiki>google.com/search?q=%60Abdu%27l-Bah%C3%A1</nowiki></code>" &nbsp; should revert to the unencoded form &nbsp; "<code><nowiki>google.com/search?q=`Abdu'l-Bahá</nowiki></code>".

* &nbsp; The encoded string &nbsp; "<code><nowiki>%25%32%35</nowiki></code>" &nbsp; should revert to the unencoded form &nbsp; "<code><nowiki>%25</nowiki></code>" and '''not''' "<code><nowiki>%</nowiki></code>".
<br><br>
<br><br>


=={{header|11l}}==
=={{header|11l}}==
<lang 11l>F url_decode(s)
<syntaxhighlight lang="11l">F url_decode(s)
V r = ‘’
V r = ‘’
V i = 0
V i = 0
Line 30: Line 32:


print(url_decode(‘http%3A%2F%2Ffoo%20bar%2F’))
print(url_decode(‘http%3A%2F%2Ffoo%20bar%2F’))
print(url_decode(‘https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80’))</lang>
print(url_decode(‘https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80’))</syntaxhighlight>


{{out}}
{{out}}
Line 40: Line 42:
=={{header|ABAP}}==
=={{header|ABAP}}==


<lang ABAP>REPORT Z_DECODE_URL.
<syntaxhighlight lang="abap">REPORT Z_DECODE_URL.


DATA: lv_encoded_url TYPE string VALUE 'http%3A%2F%2Ffoo%20bar%2F',
DATA: lv_encoded_url TYPE string VALUE 'http%3A%2F%2Ffoo%20bar%2F',
Line 51: Line 53:
UNESCAPED = lv_decoded_url.
UNESCAPED = lv_decoded_url.


WRITE: 'Encoded URL: ', lv_encoded_url, /, 'Decoded URL: ', lv_decoded_url.</lang>
WRITE: 'Encoded URL: ', lv_encoded_url, /, 'Decoded URL: ', lv_decoded_url.</syntaxhighlight>

=={{header|Action!}}==
<syntaxhighlight lang="action!">PROC Append(CHAR ARRAY s CHAR c)
s(0)==+1
s(s(0))=c
RETURN

CHAR FUNC GetCharFromHex(CHAR c1,c2)
CHAR ARRAY hex=['0 '1 '2 '3 '4 '5 '6 '7 '8 '9 'A 'B 'C 'D 'E 'F]
BYTE i,res

res=0
FOR i=0 TO 15
DO
IF c1=hex(i) THEN res==+i LSH 4 FI
IF c2=hex(i) THEN res==+i FI
OD
RETURN (res)

PROC Decode(CHAR ARRAY in,out)
BYTE i
CHAR c

out(0)=0
i=1
WHILE i<=in(0)
DO
c=in(i)
i==+1
IF c='+ THEN
Append(out,' )
ELSEIF c='% THEN
c=GetCharFromHex(in(i),in(i+1))
i==+2
Append(out,c)
ELSE
Append(out,c)
FI
OD
RETURN

PROC PrintInv(CHAR ARRAY a)
BYTE i

IF a(0)>0 THEN
FOR i=1 TO a(0)
DO
Put(a(i)%$80)
OD
FI
RETURN

PROC Test(CHAR ARRAY in)
CHAR ARRAY out(256)

PrintInv("input ")
PrintF(" %S%E",in)

Decode(in,out)
PrintInv("decoded")
PrintF(" %S%E%E",out)
RETURN

PROC Main()
Test("http%3A%2F%2Ffoo%20bar%2F")
Test("http%3A%2F%2Ffoo+bar%2F*_-.html")
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/URL_decoding.png Screenshot from Atari 8-bit computer]
<pre>
input http%3A%2F%2Ffoo%20bar%2F
decoded http://foo bar/

input http%3A%2F%2Ffoo+bar%2F*_-.html
decoded http://foo bar/*_-.html
</pre>


=={{header|Ada}}==
=={{header|Ada}}==
{{libheader|AWS}}
{{libheader|AWS}}
<lang Ada>with AWS.URL;
<syntaxhighlight lang="ada">with AWS.URL;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
procedure Decode is
procedure Decode is
Line 62: Line 140:
Put_Line (AWS.URL.Decode (Encoded));
Put_Line (AWS.URL.Decode (Encoded));
end Decode;
end Decode;
</syntaxhighlight>
</lang>


Without external libraries:
Without external libraries:


<lang Ada>package URL is
<syntaxhighlight lang="ada">package URL is
function Decode (URL : in String) return String;
function Decode (URL : in String) return String;
end URL;</lang>
end URL;</syntaxhighlight>


<lang Ada>package body URL is
<syntaxhighlight lang="ada">package body URL is
function Decode (URL : in String) return String is
function Decode (URL : in String) return String is
Buffer : String (1 .. URL'Length);
Buffer : String (1 .. URL'Length);
Line 97: Line 175:
return Buffer (1 .. Filled);
return Buffer (1 .. Filled);
end Decode;
end Decode;
end URL;</lang>
end URL;</syntaxhighlight>


<lang Ada>with Ada.Command_Line,
<syntaxhighlight lang="ada">with Ada.Command_Line,
Ada.Text_IO;
Ada.Text_IO;


Line 114: Line 192:
end loop;
end loop;
end if;
end if;
end Test_URL_Decode;</lang>
end Test_URL_Decode;</syntaxhighlight>


=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
Line 121: Line 199:
<br>
<br>
For the second task example, this outputs the encoded UTF-8 characters, what you see depends on what you look at it with...
For the second task example, this outputs the encoded UTF-8 characters, what you see depends on what you look at it with...
<lang algol68># returns c decoded as a hex digit #
<syntaxhighlight lang="algol68"># returns c decoded as a hex digit #
PROC hex value = ( CHAR c )INT: IF c >= "0" AND c <= "9" THEN ABS c - ABS "0"
PROC hex value = ( CHAR c )INT: IF c >= "0" AND c <= "9" THEN ABS c - ABS "0"
ELIF c >= "A" AND c <= "F" THEN 10 + ( ABS c - ABS "A" )
ELIF c >= "A" AND c <= "F" THEN 10 + ( ABS c - ABS "A" )
Line 156: Line 234:
# test the url decode procedure #
# test the url decode procedure #
print( ( url decode( "http%3A%2F%2Ffoo%20bar%2F" ), newline ) );
print( ( url decode( "http%3A%2F%2Ffoo%20bar%2F" ), newline ) );
print( ( url decode( "google.com/search?q=%60Abdu%27l-Bah%C3%A1" ), newline ) )</lang>
print( ( url decode( "google.com/search?q=%60Abdu%27l-Bah%C3%A1" ), newline ) )</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 164: Line 242:


=={{header|Apex}}==
=={{header|Apex}}==
<lang apex>EncodingUtil.urlDecode('http%3A%2F%2Ffoo%20bar%2F', 'UTF-8');
<syntaxhighlight 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>
EncodingUtil.urlDecode('google.com/search?q=%60Abdu%27l-Bah%C3%A1', 'UTF-8');</syntaxhighlight>
<pre>http://foo bar/
<pre>http://foo bar/
google.com/search?q=`Abdu'l-Bahá</pre>
google.com/search?q=`Abdu'l-Bahá</pre>
Line 171: Line 249:
=={{header|AppleScript}}==
=={{header|AppleScript}}==
{{libheader|AppleScript Toolbox}}
{{libheader|AppleScript Toolbox}}
<lang AppleScript>AST URL decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"</lang>
<syntaxhighlight lang="applescript">AST URL decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"</syntaxhighlight>


=={{header|Arturo}}==
=={{header|Arturo}}==


<lang rebol>print decode.url "http%3A%2F%2Ffoo%20bar%2F"
<syntaxhighlight lang="rebol">print decode.url "http%3A%2F%2Ffoo%20bar%2F"
print decode.url "google.com/search?q=%60Abdu%27l-Bah%C3%A1"</lang>
print decode.url "google.com/search?q=%60Abdu%27l-Bah%C3%A1"</syntaxhighlight>


{{out}}
{{out}}
Line 184: Line 262:


=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">
<lang AutoHotkey>encURL := "http%3A%2F%2Ffoo%20bar%2F"
UriDecode(Uri) {
SetFormat, Integer, hex
LoopOffset := 0
Loop Parse, encURL
If A_LoopField = `%
VarLength := 0
VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0)
reading := 2, read := ""
else if reading
Loop Parse, Uri
{
{
If (A_Index < LoopOffset) {
read .= A_LoopField, --reading
if not reading
Continue
out .= Chr("0x" . read)
}
If (A_LoopField = Chr(37)) {
}
Number := "0x" . SubStr(Uri, A_Index + 1, 2)
else out .= A_LoopField
LoopOffset := A_Index + 3
MsgBox % out ; http://foo bar/
}
</lang>
Else {
Number := Ord(A_LoopField)
}
NumPut(Number, Var, VarLength++, "UChar")
}
Return StrGet(&Var, VarLength, "UTF-8")
}
MsgBox % UriDecode("http%3A%2F%2Ffoo%20bar%2F")
MsgBox % UriDecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
MsgBox % UriDecode("%25%32%35")
</syntaxhighlight>


=={{header|AWK}}==
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax:
# syntax:
awk '
awk '
Line 223: Line 312:
return num + (length(s) ? 16*hex2dec(s) : 0)
return num + (length(s) ? 16*hex2dec(s) : 0)
} '
} '
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
http%3A%2F%2Ffoo%20bar%2F
http%3A%2F%2Ffoo%20bar%2F
http://foo bar/
</pre>

OR:

<syntaxhighlight lang="awk">
LC_ALL=C
echo "http%3A%2F%2Ffoo%20bar%2F" | gawk -vRS='%[[:xdigit:]]{2}' '
RT {RT = sprintf("%c",strtonum("0x" substr(RT, 2)))}
{gsub(/+/," ");printf "%s", $0 RT}'
</syntaxhighlight>

{{out}}
<pre>
http://foo bar/
http://foo bar/
</pre>
</pre>


=={{header|BaCon}}==
=={{header|BaCon}}==
<lang freebasic>FUNCTION Url_Decode$(url$)
<syntaxhighlight lang="freebasic">FUNCTION Url_Decode$(url$)


LOCAL result$
LOCAL result$
Line 244: Line 347:


PRINT Url_Decode$("http%3A%2F%2Ffoo%20bar%2F")
PRINT Url_Decode$("http%3A%2F%2Ffoo%20bar%2F")
PRINT Url_Decode$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</lang>
PRINT Url_Decode$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 250: Line 353:
google.com/search?q=`Abdu'l-Bahá
google.com/search?q=`Abdu'l-Bahá
</pre>
</pre>

=={{header|Bash}}==
See [[#UNIX Shell]]


=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
<lang bbcbasic> PRINT FNurldecode("http%3A%2F%2Ffoo%20bar%2F")
<syntaxhighlight lang="bbcbasic"> PRINT FNurldecode("http%3A%2F%2Ffoo%20bar%2F")
END
END
Line 274: Line 380:
IF C% >= 97 IF C% <= 122 MID$(A$,A%,1) = CHR$(C%-32)
IF C% >= 97 IF C% <= 122 MID$(A$,A%,1) = CHR$(C%-32)
NEXT
NEXT
= A$</lang>
= A$</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 281: Line 387:


=={{header|Bracmat}}==
=={{header|Bracmat}}==
<lang bracmat>( ( decode
<syntaxhighlight lang="bracmat">( ( decode
= decoded hexcode notencoded
= decoded hexcode notencoded
. :?decoded
. :?decoded
Line 291: Line 397:
)
)
& out$(decode$http%3A%2F%2Ffoo%20bar%2F)
& out$(decode$http%3A%2F%2Ffoo%20bar%2F)
);</lang>
);</syntaxhighlight>
{{out}}
{{out}}
<pre>http://foo bar/</pre>
<pre>http://foo bar/</pre>


=={{header|C}}==
=={{header|C}}==
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
#include <string.h>


Line 335: Line 441:


return 0;
return 0;
}</lang>
}</syntaxhighlight>


=={{header|C sharp}}==
=={{header|C sharp}}==


<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


namespace URLEncode
namespace URLEncode
Line 355: Line 461:
}
}
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 365: Line 471:
{{libheader|Poco}}
{{libheader|Poco}}
{{works with|g++}}
{{works with|g++}}
<lang cpp>#include <string>
<syntaxhighlight lang="cpp">#include <string>
#include "Poco/URI.h"
#include "Poco/URI.h"
#include <iostream>
#include <iostream>
Line 375: Line 481:
std::cout << encoded << " is decoded: " << decoded << " !" << std::endl ;
std::cout << encoded << " is decoded: " << decoded << " !" << std::endl ;
return 0 ;
return 0 ;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>http%3A%2F%2Ffoo%20bar%2F is decoded: http://foo bar/ !</pre>
<pre>http%3A%2F%2Ffoo%20bar%2F is decoded: http://foo bar/ !</pre>
Line 386: Line 492:
=={{header|Clojure}}==
=={{header|Clojure}}==


<lang clojure>(java.net.URLDecoder/decode "http%3A%2F%2Ffoo%20bar%2F")</lang>
<syntaxhighlight lang="clojure">(java.net.URLDecoder/decode "http%3A%2F%2Ffoo%20bar%2F")</syntaxhighlight>


=={{header|CoffeeScript}}==
=={{header|CoffeeScript}}==


<lang coffeescript>
<syntaxhighlight lang="coffeescript">
console.log decodeURIComponent "http%3A%2F%2Ffoo%20bar%2F?name=Foo%20Barson"
console.log decodeURIComponent "http%3A%2F%2Ffoo%20bar%2F?name=Foo%20Barson"
</syntaxhighlight>
</lang>


<lang>
<syntaxhighlight lang="text">
> coffee foo.coffee
> coffee foo.coffee
http://foo bar/?name=Foo Barson
http://foo bar/?name=Foo Barson
</syntaxhighlight>
</lang>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
<lang lisp>(defun decode (string &key start)
<syntaxhighlight lang="lisp">(defun decode (string &key start)
(assert (char= (char string start) #\%))
(assert (char= (char string start) #\%))
(if (>= (length string) (+ start 3))
(if (>= (length string) (+ start 3))
Line 422: Line 528:
finally (return (apply #'concatenate 'string chunks))))
finally (return (apply #'concatenate 'string chunks))))


(url-decode "http%3A%2F%2Ffoo%20bar%2F")</lang>
(url-decode "http%3A%2F%2Ffoo%20bar%2F")</syntaxhighlight>
{{out}}
{{out}}
<pre>"http://foo bar/"</pre>
<pre>"http://foo bar/"</pre>

=={{header|Crystal}}==
<syntaxhighlight lang="crystal">require "uri"

puts URI.decode "http%3A%2F%2Ffoo%20bar%2F"
puts URI.decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"</syntaxhighlight>
{{out}}
<pre>http://foo bar/
google.com/search?q=`Abdu'l-Bahá</pre>


=={{header|D}}==
=={{header|D}}==
<lang d>import std.stdio, std.uri;
<syntaxhighlight lang="d">import std.stdio, std.uri;


void main() {
void main() {
writeln(decodeComponent("http%3A%2F%2Ffoo%20bar%2F"));
writeln(decodeComponent("http%3A%2F%2Ffoo%20bar%2F"));
}</lang>
}</syntaxhighlight>
<pre>http://foo bar/</pre>
<pre>http://foo bar/</pre>


=={{header|Delphi}}==
=={{header|Delphi}}==
<lang Delphi>program URLEncoding;
<syntaxhighlight lang="delphi">program URLEncoding;


{$APPTYPE CONSOLE}
{$APPTYPE CONSOLE}
Line 443: Line 558:
begin
begin
Writeln(TIdURI.URLDecode('http%3A%2F%2Ffoo%20bar%2F'));
Writeln(TIdURI.URLDecode('http%3A%2F%2Ffoo%20bar%2F'));
end.</lang>
end.</syntaxhighlight>


=={{header|Elixir}}==
=={{header|Elixir}}==
<lang elixir>IO.inspect URI.decode("http%3A%2F%2Ffoo%20bar%2F")
<syntaxhighlight 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>
IO.inspect URI.decode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</syntaxhighlight>


{{out}}
{{out}}
Line 464: Line 579:
=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
{{trans|C#}}
{{trans|C#}}
<lang fsharp>open System
<syntaxhighlight lang="fsharp">open System


let decode uri = Uri.UnescapeDataString(uri)
let decode uri = Uri.UnescapeDataString(uri)
Line 471: Line 586:
let main argv =
let main argv =
printfn "%s" (decode "http%3A%2F%2Ffoo%20bar%2F")
printfn "%s" (decode "http%3A%2F%2Ffoo%20bar%2F")
0</lang>
0</syntaxhighlight>


=={{header|Factor}}==
=={{header|Factor}}==
<lang factor>USING: io kernel urls.encoding ;
<syntaxhighlight lang="factor">USING: io kernel urls.encoding ;
IN: rosetta-code.url-decoding
IN: rosetta-code.url-decoding


"http%3A%2F%2Ffoo%20bar%2F"
"http%3A%2F%2Ffoo%20bar%2F"
"google.com/search?q=%60Abdu%27l-Bah%C3%A1"
"google.com/search?q=%60Abdu%27l-Bah%C3%A1"
[ url-decode print ] bi@</lang>
[ url-decode print ] bi@</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 488: Line 603:
=={{header|Free Pascal}}==
=={{header|Free Pascal}}==


<lang pascal>function urlDecode(data: String): AnsiString;
<syntaxhighlight lang="pascal">function urlDecode(data: String): AnsiString;
var
var
ch: Char;
ch: Char;
Line 513: Line 628:
pos := pos +1;
pos := pos +1;
end;
end;
end;</lang>
end;</syntaxhighlight>




Line 519: Line 634:
{{trans|Liberty BASIC}}
{{trans|Liberty BASIC}}
{{trans|Pascal}}
{{trans|Pascal}}
<lang freebasic>
<syntaxhighlight lang="freebasic">
Const alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"
Const alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"


Line 559: Line 674:
Print "URL decoding '"; url2string(URL); "'"
Print "URL decoding '"; url2string(URL); "'"
Sleep
Sleep
</syntaxhighlight>
</lang>


=={{header|Frink}}==
While the default is to decode parameters as UTF-8 (which is the W3C recommendation,) the characters may have been encoded in another encoding scheme, and this can be handled correctly.
<syntaxhighlight lang="frink">URLDecode["google.com/search?q=%60Abdu%27l-Bah%C3%A1","UTF8"]</syntaxhighlight>


=={{header|Go}}==
=={{header|Go}}==
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 583: Line 701:
fmt.Println(u)
fmt.Println(u)
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 591: Line 709:


=={{header|Groovy}}==
=={{header|Groovy}}==
<lang groovy>assert URLDecoder.decode('http%3A%2F%2Ffoo%20bar%2F') == 'http://foo bar/'</lang>
<syntaxhighlight lang="groovy">assert URLDecoder.decode('http%3A%2F%2Ffoo%20bar%2F') == 'http://foo bar/'</syntaxhighlight>


=={{header|Haskell}}==
=={{header|Haskell}}==
<lang Haskell>import qualified Data.Char as Char
<syntaxhighlight lang="haskell">import qualified Data.Char as Char


urlDecode :: String -> Maybe String
urlDecode :: String -> Maybe String
Line 608: Line 726:


main :: IO ()
main :: IO ()
main = putStrLn . maybe "Bad decode" id $ urlDecode "http%3A%2F%2Ffoo%20bar%2F"</lang>
main = putStrLn . maybe "Bad decode" id $ urlDecode "http%3A%2F%2Ffoo%20bar%2F"</syntaxhighlight>
{{out}}
{{out}}
<pre>http://foo bar/</pre>
<pre>http://foo bar/</pre>


Another approach:
Another approach:
<lang haskell>import Data.Char (chr)
<syntaxhighlight lang="haskell">import Data.Char (chr)
import Data.List.Split (splitOn)
import Data.List.Split (splitOn)


Line 625: Line 743:
-- TEST ------------------------------------------------------------------------
-- TEST ------------------------------------------------------------------------
main :: IO ()
main :: IO ()
main = putStrLn $ deCode "http%3A%2F%2Ffoo%20bar%2F"</lang>
main = putStrLn $ deCode "http%3A%2F%2Ffoo%20bar%2F"</syntaxhighlight>
{{Out}}
{{Out}}
<pre>http://foo bar/</pre>
<pre>http://foo bar/</pre>


=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==
<lang Icon>link hexcvt
<syntaxhighlight lang="icon">link hexcvt


procedure main()
procedure main()
Line 651: Line 769:
else move(1)
else move(1)
return c
return c
end</lang>
end</syntaxhighlight>


{{libheader|Icon Programming Library}}
{{libheader|Icon Programming Library}}
Line 665: Line 783:
Here is an implementation:
Here is an implementation:


<lang j>require'strings convert'
<syntaxhighlight lang="j">require'strings convert'
urldecode=: rplc&(~.,/;"_1&a."2(,:tolower)'%',.toupper hfd i.#a.)</lang>
urldecode=: rplc&(~.,/;"_1&a."2(,:tolower)'%',.toupper hfd i.#a.)</syntaxhighlight>


Example use:
Example use:


<lang j> urldecode 'http%3A%2F%2Ffoo%20bar%2F'
<syntaxhighlight lang="j"> urldecode 'http%3A%2F%2Ffoo%20bar%2F'
http://foo bar/</lang>
http://foo bar/</syntaxhighlight>


Note that an earlier implementation assumed the j6 implementation of <code>hfd</code> which where hexadecimal letters resulting from <code>hfd</code> were upper case. J8, in contrast, provides a lower case result from hfd. The addition of <code>toupper</code> guarantees the case insensitivity required by [http://tools.ietf.org/html/rfc3986#section-2.1 RFC 3986] regardless of which version of J you are using. As the parenthesized expression containing <code>hfd</code> is only evaluated at definition time, there's no performance penalty from the use of <code>toupper</code>.
Note that an earlier implementation assumed the j6 implementation of <code>hfd</code> which where hexadecimal letters resulting from <code>hfd</code> were upper case. J8, in contrast, provides a lower case result from hfd. The addition of <code>toupper</code> guarantees the case insensitivity required by [http://tools.ietf.org/html/rfc3986#section-2.1 RFC 3986] regardless of which version of J you are using. As the parenthesized expression containing <code>hfd</code> is only evaluated at definition time, there's no performance penalty from the use of <code>toupper</code>.
Line 677: Line 795:
Example use:
Example use:


<lang j> urldecode 'google.com/search?q=%60Abdu%27l-Bah%C3%A1'
<syntaxhighlight lang="j"> urldecode 'google.com/search?q=%60Abdu%27l-Bah%C3%A1'
google.com/search?q=`Abdu'l-Bahá</lang>
google.com/search?q=`Abdu'l-Bahá</syntaxhighlight>


=={{header|Java}}==
=={{header|Java}}==
Java offers the ''URLDecoder'' and ''URLEncoder'' classes for this specific task.

<syntaxhighlight lang="java">
<lang java>import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

</syntaxhighlight>
public class Main
<syntaxhighlight lang="java">
{
URLDecoder.decode("http%3A%2F%2Ffoo%20bar%2F", StandardCharsets.UTF_8)
public static void main(String[] args) throws UnsupportedEncodingException
</syntaxhighlight>
{
Alternately, you could use a regular expression capture
String encoded = "http%3A%2F%2Ffoo%20bar%2F";
<syntaxhighlight lang="java">
String normal = URLDecoder.decode(encoded, "utf-8");
import java.util.regex.Matcher;
System.out.println(normal);
import java.util.regex.Pattern;
</syntaxhighlight>
<syntaxhighlight lang="java">
String decode(String string) {
Pattern pattern = Pattern.compile("%([A-Za-z\\d]{2})");
Matcher matcher = pattern.matcher(string);
StringBuilder decoded = new StringBuilder(string);
char character;
int start, end, offset = 0;
while (matcher.find()) {
character = (char) Integer.parseInt(matcher.group(1), 16);
/* offset the matched index since were adjusting the string */
start = matcher.start() - offset;
end = matcher.end() - offset;
decoded.replace(start, end, String.valueOf(character));
offset += 2;
}
}
return decoded.toString();
}</lang>
}

</syntaxhighlight>
{{out}}
<pre>
<pre>http://foo bar/</pre>
http://foo bar/
google.com/search?q=`Abdu'l-Bahá
</pre>


=={{header|JavaScript}}==
=={{header|JavaScript}}==
<lang javascript>decodeURIComponent("http%3A%2F%2Ffoo%20bar%2F")</lang>
<syntaxhighlight lang="javascript">decodeURIComponent("http%3A%2F%2Ffoo%20bar%2F")</syntaxhighlight>


=={{header|jq}}==
=={{header|jq}}==
{{works with|jq|1.4}}
{{works with|jq|1.4}}
If your jq already has "until", then the definition given below may be omitted.
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.
<syntaxhighlight lang="jq"># Emit . and stop as soon as "condition" is true.
def until(condition; next):
def until(condition; next):
def u: if condition then . else (next|u) end;
def u: if condition then . else (next|u) end;
Line 730: Line 867:
else [ $i + 1, .[1] + $in[$i:$i+1] ]
else [ $i + 1, .[1] + $in[$i:$i+1] ]
end)
end)
| .[1]; # answer</lang>
| .[1]; # answer</syntaxhighlight>
'''Example''':
'''Example''':
<lang jq>"http%3A%2F%2Ffoo%20bar%2F" | url_decode</lang>
<syntaxhighlight lang="jq">"http%3A%2F%2Ffoo%20bar%2F" | url_decode</syntaxhighlight>
{{out}}
{{out}}
<syntaxhighlight lang="sh">
<lang sh>
"http://foo bar/"</lang>
"http://foo bar/"</syntaxhighlight>


=={{header|Julia}}==
=={{header|Julia}}==
<syntaxhighlight lang="julia">
<lang Julia>
using URIParser
using URIParser


Line 746: Line 883:


println(enc, " => ", dcd)
println(enc, " => ", dcd)
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 754: Line 891:


=={{header|Kotlin}}==
=={{header|Kotlin}}==
<lang scala>// version 1.1.2
<syntaxhighlight lang="scala">// version 1.1.2


import java.net.URLDecoder
import java.net.URLDecoder
Line 761: Line 898:
val encoded = arrayOf("http%3A%2F%2Ffoo%20bar%2F", "google.com/search?q=%60Abdu%27l-Bah%C3%A1")
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"))
for (e in encoded) println(URLDecoder.decode(e, "UTF-8"))
}</lang>
}</syntaxhighlight>

{{out}}
<pre>
http://foo bar/
google.com/search?q=`Abdu'l-Bahá
</pre>

=={{header|Ksh}}==
<syntaxhighlight lang="ksh">
url_decode()
{
decode="${*//+/ }"
eval print -r -- "\$'${decode//'%'@(??)/'\'x\1"'\$'"}'" 2>/dev/null
}

url_decode "http%3A%2F%2Ffoo%20bar%2F"
url_decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
</syntaxhighlight>


{{out}}
{{out}}
Line 771: Line 926:
=={{header|Lambdatalk}}==
=={{header|Lambdatalk}}==
Currently lambdatalk has no builtin primitive for decoding URLs. Let's define it using Javascript.
Currently lambdatalk has no builtin primitive for decoding URLs. Let's define it using Javascript.
<lang scheme>
<syntaxhighlight lang="scheme">
1) define a new javascript primitive:
1) define a new javascript primitive:
{script
{script
Line 785: Line 940:




</syntaxhighlight>
</lang>


=={{header|langur}}==
<syntaxhighlight lang="langur">val .finish = fn(.s) { b2s map fn(.x) { number(.x, 16) }, rest split "%", .s }
val .decode = fn(.s) { replace .s, re/(%[0-9A-Fa-f]{2})+/, .finish }

writeln .decode("http%3A%2F%2Ffoo%20bar%2F")
writeln .decode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
</syntaxhighlight>

{{out}}
<pre>http://foo bar/
google.com/search?q=`Abdu'l-Bahá
</pre>


=={{header|Lasso}}==
=={{header|Lasso}}==
<lang Lasso>bytes('http%3A%2F%2Ffoo%20bar%2F') -> decodeurl</lang>
<syntaxhighlight lang="lasso">bytes('http%3A%2F%2Ffoo%20bar%2F') -> decodeurl</syntaxhighlight>
-> http://foo bar/
-> http://foo bar/


=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
dim lookUp$( 256)
dim lookUp$( 256)


Line 818: Line 987:
next j
next j
end function
end function
</syntaxhighlight>
</lang>
Supplied URL 'http%3A%2F%2Ffoo%20bar%2F'
Supplied URL 'http%3A%2F%2Ffoo%20bar%2F'
As string 'http://foo bar/'
As string 'http://foo bar/'


=={{header|Lingo}}==
=={{header|Lingo}}==
<lang Lingo>----------------------------------------
<syntaxhighlight lang="lingo">----------------------------------------
-- URL decodes a string
-- URL decodes a string
-- @param {string} str
-- @param {string} str
Line 846: Line 1,015:
ba.position = 1
ba.position = 1
return ba.readRawString(ba.length)
return ba.readRawString(ba.length)
end</lang>
end</syntaxhighlight>
<lang Lingo>put urldecode("http%3A%2F%2Ffoo%20bar%2F")
<syntaxhighlight lang="lingo">put urldecode("http%3A%2F%2Ffoo%20bar%2F")
put urldecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</lang>
put urldecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</syntaxhighlight>
{{Out}}
{{Out}}
<pre>
<pre>
Line 856: Line 1,025:


=={{header|LiveCode}}==
=={{header|LiveCode}}==
<lang LiveCode>put urlDecode("http%3A%2F%2Ffoo%20bar%2F") & cr & \
<syntaxhighlight 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/
urlDecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</syntaxhighlight>Results<syntaxhighlight lang="text">http://foo bar/
google.com/search?q=`Abdu'l-Bah√°</lang>
google.com/search?q=`Abdu'l-Bah√°</syntaxhighlight>


=={{header|Lua}}==
=={{header|Lua}}==
<lang lua>function decodeChar(hex)
<syntaxhighlight lang="lua">function decodeChar(hex)
return string.char(tonumber(hex,16))
return string.char(tonumber(hex,16))
end
end
Line 871: Line 1,040:


-- will print "http://foo bar/"
-- will print "http://foo bar/"
print(decodeString("http%3A%2F%2Ffoo%20bar%2F"))</lang>
print(decodeString("http%3A%2F%2Ffoo%20bar%2F"))</syntaxhighlight>


=={{header|M2000 Interpreter}}==
=={{header|M2000 Interpreter}}==
Line 881: Line 1,050:


b$=chr$(a$) revert bytes to words adding zeroes after each character
b$=chr$(a$) revert bytes to words adding zeroes after each character
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module CheckIt {
Module CheckIt {
Function decodeUrl$(a$) {
Function decodeUrl$(a$) {
Line 907: Line 1,076:
}
}
CheckIt
CheckIt
</syntaxhighlight>
</lang>


=={{header|Maple}}==
=={{header|Maple}}==
<lang Maple>StringTools:-Decode("http%3A%2F%2Ffoo%20bar%2F", encoding=percent);</lang>
<syntaxhighlight lang="maple">StringTools:-Decode("http%3A%2F%2Ffoo%20bar%2F", encoding=percent);</syntaxhighlight>


{{Out}}
{{Out}}
<pre> "http://foo bar/"</pre>
<pre> "http://foo bar/"</pre>


=={{header|Mathematica}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<lang mathematica>URLDecoding[url_] :=
<syntaxhighlight lang="mathematica">URLDecoding[url_] :=
StringReplace[url, "%" ~~ x_ ~~ y_ :> FromDigits[x ~~ y, 16]] //.
StringReplace[url, "%" ~~ x_ ~~ y_ :> FromDigits[x ~~ y, 16]] //.
StringExpression[x___, Longest[n__Integer], y___] :>
StringExpression[x___, Longest[n__Integer], y___] :>
StringExpression[x, FromCharacterCode[{n}, "UTF8"], y]</lang>
StringExpression[x, FromCharacterCode[{n}, "UTF8"], y]</syntaxhighlight>

Example use:
Example use:
<syntaxhighlight lang="mathematica">URLDecoding["http%3A%2F%2Ffoo%20bar%2F"]</syntaxhighlight>
{{out}}
<pre>http://foo bar/</pre>


----
<lang mathematica>URLDecoding["http%3A%2F%2Ffoo%20bar%2F"]</lang>


Using the built-in URLDecode (http://reference.wolfram.com/language/ref/URLDecode.html) function:
{{out}}
{{out}}
<pre>
<pre>http://foo bar/</pre>
In[]:= URLDecode["http%3A%2F%2Ffoo%20bar%2F"]
Out[]= "http://foo bar/"

In[]:= URLDecode["google.com/search?q=%60Abdu%27l-Bah%C3%A1"]
Out[]= "google.com/search?q=`Abdu'l-Bahá"

In[]:= URLDecode[{"Kurt+G%C3%B6del", "Paul+Erd%C5%91s"}]
Out[]= {"Kurt Gödel", "Paul Erdős"}
</pre>


=={{header|MATLAB}} / {{header|Octave}}==
=={{header|MATLAB}} / {{header|Octave}}==
<lang MATLAB>function u = urldecoding(s)
<syntaxhighlight lang="matlab">function u = urldecoding(s)
u = '';
u = '';
k = 1;
k = 1;
Line 941: Line 1,122:
end
end
end
end
end</lang>
end</syntaxhighlight>
Usage:
Usage:
<pre>octave:3> urldecoding('http%3A%2F%2Ffoo%20bar%2F')
<pre>octave:3> urldecoding('http%3A%2F%2Ffoo%20bar%2F')
Line 947: Line 1,128:


=={{header|NetRexx}}==
=={{header|NetRexx}}==
<lang NetRexx>/* NetRexx */
<syntaxhighlight lang="netrexx">/* NetRexx */
options replace format comments java crossref savelog symbols nobinary
options replace format comments java crossref savelog symbols nobinary


Line 990: Line 1,171:


return decoded
return decoded
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,005: Line 1,186:


=={{header|NewLISP}}==
=={{header|NewLISP}}==
<lang NewLISP>;; universal decoder, works for ASCII and UTF-8
<syntaxhighlight lang="newlisp">;; universal decoder, works for ASCII and UTF-8
;; (source http://www.newlisp.org/index.cgi?page=Code_Snippets)
;; (source http://www.newlisp.org/index.cgi?page=Code_Snippets)
(define (url-decode url (opt nil))
(define (url-decode url (opt nil))
Line 1,011: Line 1,192:
(replace "%([0-9a-f][0-9a-f])" url (pack "b" (int $1 0 16)) 1))
(replace "%([0-9a-f][0-9a-f])" url (pack "b" (int $1 0 16)) 1))


(url-decode "http%3A%2F%2Ffoo%20bar%2F")</lang>
(url-decode "http%3A%2F%2Ffoo%20bar%2F")</syntaxhighlight>


=={{header|Nim}}==
=={{header|Nim}}==
<lang nim>import cgi
<syntaxhighlight lang="nim">import cgi


echo decodeUrl("http%3A%2F%2Ffoo%20bar%2F")</lang>
echo decodeUrl("http%3A%2F%2Ffoo%20bar%2F")</syntaxhighlight>


{{out}}
{{out}}
Line 1,023: Line 1,204:
=={{header|Oberon-2}}==
=={{header|Oberon-2}}==
{{works with|oo2c}}
{{works with|oo2c}}
<lang oberon2>
<syntaxhighlight lang="oberon2">
MODULE URLDecoding;
MODULE URLDecoding;
IMPORT
IMPORT
Line 1,032: Line 1,213:
Out.String(URI.Unescape("google.com/search?q=%60Abdu%27l-Bah%C3%A1"));Out.Ln;
Out.String(URI.Unescape("google.com/search?q=%60Abdu%27l-Bah%C3%A1"));Out.Ln;
END URLDecoding.
END URLDecoding.
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,040: Line 1,221:


=={{header|Objeck}}==
=={{header|Objeck}}==
<lang objeck>
<syntaxhighlight lang="objeck">
class UrlDecode {
class UrlDecode {
function : Main(args : String[]) ~ Nil {
function : Main(args : String[]) ~ Nil {
Line 1,046: Line 1,227:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|Objective-C}}==
=={{header|Objective-C}}==
<lang objc>NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F";
<syntaxhighlight lang="objc">NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F";
NSString *normal = [encoded stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *normal = [encoded stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", normal);</lang>
NSLog(@"%@", normal);</syntaxhighlight>
{{works with|Mac OS X|10.9+}}{{works with|iOS|7+}}
{{works with|Mac OS X|10.9+}}{{works with|iOS|7+}}
<lang objc>NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F";
<syntaxhighlight lang="objc">NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F";
NSString *normal = [encoded stringByRemovingPercentEncoding];
NSString *normal = [encoded stringByRemovingPercentEncoding];
NSLog(@"%@", normal);</lang>
NSLog(@"%@", normal);</syntaxhighlight>


=={{header|OCaml}}==
=={{header|OCaml}}==
Line 1,061: Line 1,242:
Using the library [http://projects.camlcity.org/projects/ocamlnet.html ocamlnet] from the interactive loop:
Using the library [http://projects.camlcity.org/projects/ocamlnet.html ocamlnet] from the interactive loop:


<lang ocaml>$ ocaml
<syntaxhighlight lang="ocaml">$ ocaml
# #use "topfind";;
# #use "topfind";;
# #require "netstring";;
# #require "netstring";;


# Netencoding.Url.decode "http%3A%2F%2Ffoo%20bar%2F" ;;
# Netencoding.Url.decode "http%3A%2F%2Ffoo%20bar%2F" ;;
- : string = "http://foo bar/"</lang>
- : string = "http://foo bar/"</syntaxhighlight>


=={{header|ooRexx}}==
=={{header|ooRexx}}==
While the implementation shown for [[#REXX|Rexx]] will also work with ooRexx, this version uses ooRexx syntax to invoke the built-in functions.
While the implementation shown for [[#REXX|Rexx]] will also work with ooRexx, this version uses ooRexx syntax to invoke the built-in functions.
<lang ooRexx>/* Rexx */
<syntaxhighlight lang="oorexx">/* Rexx */
X = 0
X = 0
url. = ''
url. = ''
Line 1,109: Line 1,290:
End e_
End e_


Return decoded</lang>
Return decoded</syntaxhighlight>


{{out}}
{{out}}
Line 1,125: Line 1,306:
=={{header|Perl}}==
=={{header|Perl}}==


<lang Perl>sub urldecode {
<syntaxhighlight lang="perl">sub urldecode {
my $s = shift;
my $s = shift;
$s =~ tr/\+/ /;
$s =~ tr/\+/ /;
Line 1,133: Line 1,314:


print urldecode('http%3A%2F%2Ffoo+bar%2F')."\n";
print urldecode('http%3A%2F%2Ffoo+bar%2F')."\n";
</syntaxhighlight>
</lang>


<lang Perl>#!/usr/bin/perl -w
<syntaxhighlight lang="perl">#!/usr/bin/perl -w
use strict ;
use strict ;
use URI::Escape ;
use URI::Escape ;
Line 1,141: Line 1,322:
my $encoded = "http%3A%2F%2Ffoo%20bar%2F" ;
my $encoded = "http%3A%2F%2Ffoo%20bar%2F" ;
my $unencoded = uri_unescape( $encoded ) ;
my $unencoded = uri_unescape( $encoded ) ;
print "The unencoded string is $unencoded !\n" ;</lang>
print "The unencoded string is $unencoded !\n" ;</syntaxhighlight>


=={{header|Phix}}==
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>--
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\decode_url.exw
-- demo\rosetta\decode_url.exw
-- ===========================
-- ===========================
--
--</span>
function decode_url(string s)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer skip = 0
<span style="color: #008080;">function</span> <span style="color: #000000;">decode_url</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
string res = ""
<span style="color: #004080;">integer</span> <span style="color: #000000;">skip</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
for i=1 to length(s) do
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
if skip then
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
skip -= 1
<span style="color: #008080;">if</span> <span style="color: #000000;">skip</span> <span style="color: #008080;">then</span>
else
<span style="color: #000000;">skip</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
integer ch = s[i]
if ch='%' then
<span style="color: #008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
sequence scanres = {}
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'%'</span> <span style="color: #008080;">then</span>
if i+2<=length(s) then
<span style="color: #004080;">sequence</span> <span style="color: #000000;">scanres</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
scanres = scanf("#"&s[i+1..i+2],"%x")
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">scanres</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">scanf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"#"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"%x"</span><span style="color: #0000FF;">)</span>
if length(scanres)!=1 then
return "decode error"
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">scanres</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
end if
<span style="color: #008080;">return</span> <span style="color: #008000;">"decode error"</span>
skip = 2
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ch = scanres[1][1]
<span style="color: #000000;">skip</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
elsif ch='+' then
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">scanres</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
ch = ' '
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'+'</span> <span style="color: #008080;">then</span>
end if
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">' '</span>
res &= ch
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">ch</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
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>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">decode_url</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"http%3A%2F%2Ffoo%20bar%2F"</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">decode_url</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"google.com/search?q=%60Abdu%27l-Bah%C3%A1"</span><span style="color: #0000FF;">)})</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,184: Line 1,370:


=={{header|PHP}}==
=={{header|PHP}}==
<lang php><?php
<syntaxhighlight lang="php"><?php
$encoded = "http%3A%2F%2Ffoo%20bar%2F";
$encoded = "http%3A%2F%2Ffoo%20bar%2F";
$unencoded = rawurldecode($encoded);
$unencoded = rawurldecode($encoded);
echo "The unencoded string is $unencoded !\n";
echo "The unencoded string is $unencoded !\n";
?></lang>
?></syntaxhighlight>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
Line 1,195: Line 1,381:


=={{header|Pike}}==
=={{header|Pike}}==
<syntaxhighlight lang="pike">
<lang Pike>
void main()
void main()
{
{
Line 1,209: Line 1,395:
}
}
}
}
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,217: Line 1,403:


=={{header|PowerShell}}==
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
[System.Web.HttpUtility]::UrlDecode("http%3A%2F%2Ffoo%20bar%2F")
[System.Web.HttpUtility]::UrlDecode("http%3A%2F%2Ffoo%20bar%2F")
</syntaxhighlight>
</lang>
{{Out}}
{{Out}}
<pre>
<pre>
Line 1,226: Line 1,412:


=={{header|PureBasic}}==
=={{header|PureBasic}}==
<lang PureBasic>URL$ = URLDecoder("http%3A%2F%2Ffoo%20bar%2F")
<syntaxhighlight lang="purebasic">URL$ = URLDecoder("http%3A%2F%2Ffoo%20bar%2F")


Debug URL$ ; http://foo bar/</lang>
Debug URL$ ; http://foo bar/</syntaxhighlight>


=={{header|Python}}==
=={{header|Python}}==
<syntaxhighlight lang="python">
<lang Python>
#Python 2.X
#Python 2.X
import urllib
import urllib
Line 1,238: Line 1,424:
from urllib.parse import unquote
from urllib.parse import unquote
print(unquote('http%3A%2F%2Ffoo%20bar%2F'))
print(unquote('http%3A%2F%2Ffoo%20bar%2F'))
</syntaxhighlight>
</lang>


=={{header|R}}==
=={{header|R}}==


<lang R>URLdecode("http%3A%2F%2Ffoo%20bar%2F")</lang>
<syntaxhighlight lang="r">URLdecode("http%3A%2F%2Ffoo%20bar%2F")</syntaxhighlight>


=={{header|Racket}}==
=={{header|Racket}}==


<lang racket>
<syntaxhighlight lang="racket">
#lang racket
#lang racket
(require net/uri-codec)
(require net/uri-codec)
(uri-decode "http%3A%2F%2Ffoo%20bar%2F")
(uri-decode "http%3A%2F%2Ffoo%20bar%2F")
</syntaxhighlight>
</lang>


=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
<lang perl6>my @urls = < http%3A%2F%2Ffoo%20bar%2F
<syntaxhighlight lang="raku" line>my @urls = < http%3A%2F%2Ffoo%20bar%2F
google.com/search?q=%60Abdu%27l-Bah%C3%A1 >;
google.com/search?q=%60Abdu%27l-Bah%C3%A1 >;


say .subst( :g,
say .subst( :g,
/ [ '%' ( <:hexdigit> ** 2 ) ]+ / ,
/ [ '%' ( <xdigit> ** 2 ) ]+ / ,
{ Blob.new((:16(~$_) for $0)).decode }
{ Blob.new((:16(~$_) for $0)).decode }
) for @urls;</lang>
) for @urls;</syntaxhighlight>
{{out}}
{{out}}
<pre>http://foo bar/
<pre>http://foo bar/
Line 1,267: Line 1,453:
=={{header|Red}}==
=={{header|Red}}==


<lang rebol>>> dehex "http%3A%2F%2Ffoo%20bar%2F"
<syntaxhighlight lang="rebol">>> dehex "http%3A%2F%2Ffoo%20bar%2F"
== "http://foo bar/"
== "http://foo bar/"
>> dehex "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
>> dehex "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
== "google.com/search?q=`Abdu'l-Bahá"</lang>
== "google.com/search?q=`Abdu'l-Bahá"</syntaxhighlight>


=={{header|Retro}}==
=={{header|Retro}}==
This is provided by the '''casket''' library (used for web app development).
This is provided by the '''casket''' library (used for web app development).


<lang Retro>create buffer 32000 allot
<syntaxhighlight lang="retro">create buffer 32000 allot


{{
{{
Line 1,290: Line 1,476:
}}
}}


"http%3A%2F%2Ffoo%20bar%2F" decode buffer puts</lang>
"http%3A%2F%2Ffoo%20bar%2F" decode buffer puts</syntaxhighlight>


=={{header|REXX}}==
=={{header|REXX}}==
Line 1,296: Line 1,482:
{{Trans|ooRexx}}
{{Trans|ooRexx}}
Tested with the ooRexx and Regina interpreters.
Tested with the ooRexx and Regina interpreters.
<lang REXX>/* Rexx */
<syntaxhighlight lang="rexx">/* Rexx */


Do
Do
Line 1,344: Line 1,530:
End
End
Exit
Exit
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,360: Line 1,546:
===version 2===
===version 2===
This REXX version is identical to version 1, but with superfluous and dead code removed.
This REXX version is identical to version 1, but with superfluous and dead code removed.
<lang REXX>/*REXX program converts a URL─encoded string ──► its original unencoded form. */
<syntaxhighlight lang="rexx">/*REXX program converts a URL─encoded string ──► its original unencoded form. */
url.1='http%3A%2F%2Ffoo%20bar%2F'
url.1='http%3A%2F%2Ffoo%20bar%2F'
url.2='mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E'
url.2='mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E'
Line 1,388: Line 1,574:
end /*while*/
end /*while*/


return decoded</lang>
return decoded</syntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}}
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}}


===version 3===
===version 3===
This REXX version is a shorter version of version 2.
This REXX version is a shorter version of version 2.
<lang REXX>/*REXX program converts & displays a URL─encoded string ──► its original unencoded form.*/
<syntaxhighlight lang="rexx">/*REXX program converts & displays a URL─encoded string ──► its original unencoded form.*/
url. =
url. =
url.1='http%3A%2F%2Ffoo%20bar%2F'
url.1='http%3A%2F%2Ffoo%20bar%2F'
Line 1,414: Line 1,600:
else URL= URL'%'code
else URL= URL'%'code
end /*until*/
end /*until*/
return URL</lang>
return URL</syntaxhighlight>
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}}
{{out|output|text=&nbsp; is identical to the 1<sup>st</sup> REXX version.}}


Line 1,420: Line 1,606:
Use any one of <code>CGI.unescape</code> or <code>URI.decode_www_form_component</code>. These methods also convert "+" to " ".
Use any one of <code>CGI.unescape</code> or <code>URI.decode_www_form_component</code>. These methods also convert "+" to " ".


<lang ruby>require 'cgi'
<syntaxhighlight lang="ruby">require 'cgi'
puts CGI.unescape("http%3A%2F%2Ffoo%20bar%2F")
puts CGI.unescape("http%3A%2F%2Ffoo%20bar%2F")
# => "http://foo bar/"</lang>
# => "http://foo bar/"</syntaxhighlight>


{{works with|Ruby|1.9.2}}
{{works with|Ruby|1.9.2}}
<lang ruby>require 'uri'
<syntaxhighlight lang="ruby">require 'uri'
puts URI.decode_www_form_component("http%3A%2F%2Ffoo%20bar%2F")
puts URI.decode_www_form_component("http%3A%2F%2Ffoo%20bar%2F")
# => "http://foo bar/"</lang>
# => "http://foo bar/"</syntaxhighlight>


<code>URI.unescape</code> (alias <code>URI.unencode</code>) still works. <code>URI.unescape</code> is obsolete since Ruby 1.9.2 because of problems with its sibling <code>URI.escape</code>.
<code>URI.unescape</code> (alias <code>URI.unencode</code>) still works. <code>URI.unescape</code> is obsolete since Ruby 1.9.2 because of problems with its sibling <code>URI.escape</code>.


=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>const INPUT1: &str = "http%3A%2F%2Ffoo%20bar%2F";
<syntaxhighlight lang="rust">const INPUT1: &str = "http%3A%2F%2Ffoo%20bar%2F";
const INPUT2: &str = "google.com/search?q=%60Abdu%27l-Bah%C3%A1";
const INPUT2: &str = "google.com/search?q=%60Abdu%27l-Bah%C3%A1";


Line 1,467: Line 1,653:
println!("{}", decode(INPUT1));
println!("{}", decode(INPUT1));
println!("{}", decode(INPUT2));
println!("{}", decode(INPUT2));
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,475: Line 1,661:


=={{header|Scala}}==
=={{header|Scala}}==
{{libheader|Scala}}<lang scala>import java.net.{URLDecoder, URLEncoder}
{{libheader|Scala}}<syntaxhighlight lang="scala">import java.net.{URLDecoder, URLEncoder}
import scala.compat.Platform.currentTime
import scala.compat.Platform.currentTime


Line 1,490: Line 1,676:


println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")
println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")
}</lang>
}</syntaxhighlight>


=={{header|Seed7}}==
=={{header|Seed7}}==
Line 1,500: Line 1,686:
works like ''fromPercentEncoded'' and additionally decodes '+' with a space.
works like ''fromPercentEncoded'' and additionally decodes '+' with a space.
Both functions return byte sequences.
Both functions return byte sequences.
To decode Unicode characters it is necessary to convert them from UTF-8 with ''utf8ToStri'' afterwards.
To decode Unicode characters it is necessary to convert them from UTF-8 with [https://seed7.sourceforge.net/libraries/unicode.htm#fromUtf8(in_string) fromUtf8] afterwards.
<lang seed7>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "encoding.s7i";
include "encoding.s7i";


Line 1,508: Line 1,694:
writeln(fromPercentEncoded("http%3A%2F%2Ffoo%20bar%2F"));
writeln(fromPercentEncoded("http%3A%2F%2Ffoo%20bar%2F"));
writeln(fromUrlEncoded("http%3A%2F%2Ffoo+bar%2F"));
writeln(fromUrlEncoded("http%3A%2F%2Ffoo+bar%2F"));
end func;</lang>
end func;</syntaxhighlight>


{{out}}
{{out}}
Line 1,518: Line 1,704:
=={{header|Sidef}}==
=={{header|Sidef}}==
{{trans|Perl}}
{{trans|Perl}}
<lang ruby>func urldecode(str) {
<syntaxhighlight lang="ruby">func urldecode(str) {
str.gsub!('+', ' ');
str.gsub!('+', ' ');
str.gsub!(/\%([A-Fa-f0-9]{2})/, {|a| 'C'.pack(a.hex)});
str.gsub!(/\%([A-Fa-f0-9]{2})/, {|a| 'C'.pack(a.hex)});
Line 1,524: Line 1,710:
}
}


say urldecode('http%3A%2F%2Ffoo+bar%2F'); # => "http://foo bar/"</lang>
say urldecode('http%3A%2F%2Ffoo+bar%2F'); # => "http://foo bar/"</syntaxhighlight>


=={{header|Swift}}==
=={{header|Swift}}==
<lang swift>import Foundation
<syntaxhighlight lang="swift">import Foundation


let encoded = "http%3A%2F%2Ffoo%20bar%2F"
let encoded = "http%3A%2F%2Ffoo%20bar%2F"
if let normal = encoded.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
if let normal = encoded.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
println(normal)
println(normal)
}</lang>
}</syntaxhighlight>


=={{header|Tcl}}==
=={{header|Tcl}}==
This code is careful to ensure that any untoward metacharacters in the input string still do not cause any problems.
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} {
<syntaxhighlight lang="tcl">proc urlDecode {str} {
set specialMap {"[" "%5B" "]" "%5D"}
set specialMap {"[" "%5B" "]" "%5D"}
set seqRE {%([0-9a-fA-F]{2})}
set seqRE {%([0-9a-fA-F]{2})}
Line 1,542: Line 1,728:
set modStr [regsub -all $seqRE [string map $specialMap $str] $replacement]
set modStr [regsub -all $seqRE [string map $specialMap $str] $replacement]
return [encoding convertfrom utf-8 [subst -nobackslash -novariable $modStr]]
return [encoding convertfrom utf-8 [subst -nobackslash -novariable $modStr]]
}</lang>
}</syntaxhighlight>
Demonstrating:
Demonstrating:
<lang tcl>puts [urlDecode "http%3A%2F%2Ffoo%20bar%2F"]</lang>
<syntaxhighlight lang="tcl">puts [urlDecode "http%3A%2F%2Ffoo%20bar%2F"]</syntaxhighlight>
{{out}}
{{out}}
<pre>http://foo bar/</pre>
<pre>http://foo bar/</pre>


=={{header|TUSCRIPT}}==
=={{header|TUSCRIPT}}==
<lang tuscript>
<syntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
$$ MODE TUSCRIPT
url_encoded="http%3A%2F%2Ffoo%20bar%2F"
url_encoded="http%3A%2F%2Ffoo%20bar%2F"
Line 1,558: Line 1,744:
PRINT "encoded: ", url_encoded
PRINT "encoded: ", url_encoded
PRINT "decoded: ", url_decoded
PRINT "decoded: ", url_decoded
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,570: Line 1,756:
{{works with|ksh}}
{{works with|ksh}}


<lang bash>urldecode() { local u="${1//+/ }"; printf '%b' "${u//%/\\x}"; }</lang>
<syntaxhighlight lang="bash">urldecode() { local u="${1//+/ }"; printf '%b' "${u//%/\\x}"; }</syntaxhighlight>

Alternative: Replace <code>printf '%b' "${u//%/\\x}"</code> with <code>echo -e "${u//%/\\x}"</code>


Example:
Example:


<lang bash>urldecode http%3A%2F%2Ffoo%20bar%2F
<syntaxhighlight lang="bash">urldecode http%3A%2F%2Ffoo%20bar%2F
http://foo bar/
http://foo bar/


urldecode google.com/search?q=%60Abdu%27l-Bah%C3%A1
urldecode google.com/search?q=%60Abdu%27l-Bah%C3%A1
google.com/search?q=`Abdu'l-Bahároot@
google.com/search?q=`Abdu'l-Bahároot@
</syntaxhighlight>
</lang>




<lang bash>function urldecode
<syntaxhighlight lang="bash">function urldecode
{
{
typeset encoded=$1 decoded= rest= c= c1= c2=
typeset encoded=$1 decoded= rest= c= c1= c2=
Line 1,647: Line 1,833:
fi
fi
}
}
</syntaxhighlight>
</lang>


=={{header|VBScript}}==
=={{header|VBScript}}==
<lang VBScript>Function RegExTest(str,patrn)
<syntaxhighlight lang="vbscript">Function RegExTest(str,patrn)
Dim regEx
Dim regEx
Set regEx = New RegExp
Set regEx = New RegExp
Line 1,694: Line 1,880:
url = "http%3A%2F%2Ffoo%20bar%C3%A8%2F"
url = "http%3A%2F%2Ffoo%20bar%C3%A8%2F"
WScript.Echo "Encoded URL: " & url & vbCrLf &_
WScript.Echo "Encoded URL: " & url & vbCrLf &_
"Decoded URL: " & UrlDecode(url)</lang>
"Decoded URL: " & UrlDecode(url)</syntaxhighlight>
{{out}}
{{out}}
<pre>Encoded URL: http%3A%2F%2Ffoo%20bar%C3%A8%2F
<pre>Encoded URL: http%3A%2F%2Ffoo%20bar%C3%A8%2F
Decoded URL: http://foo barè/</pre>
Decoded URL: http://foo barè/</pre>

=={{header|V (Vlang)}}==
<syntaxhighlight lang="v (vlang)">import net.urllib
fn main() {
for escaped in [
"http%3A%2F%2Ffoo%20bar%2F",
"google.com/search?q=%60Abdu%27l-Bah%C3%A1",
] {
u := urllib.query_unescape(escaped)?
println(u)
}
}</syntaxhighlight>
{{out}}
<pre>
http://foo bar/
google.com/search?q=`Abdu'l-Bahá
</pre>


=={{header|Wren}}==
=={{header|Wren}}==
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
<lang ecmascript>import "/fmt" for Conv
<syntaxhighlight lang="wren">import "./fmt" for Conv


var urlDecode = Fn.new { |enc|
var urlDecode = Fn.new { |enc|
Line 1,726: Line 1,929:
"google.com/search?q=\%60Abdu\%27l-Bah\%C3\%A1"
"google.com/search?q=\%60Abdu\%27l-Bah\%C3\%A1"
]
]
for (enc in encs)System.print(urlDecode.call(enc))</lang>
for (enc in encs)System.print(urlDecode.call(enc))</syntaxhighlight>


{{out}}
{{out}}
Line 1,735: Line 1,938:


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>code Text=12;
<syntaxhighlight lang="xpl0">code Text=12;
string 0; \use zero-terminated strings
string 0; \use zero-terminated strings


Line 1,757: Line 1,960:
];
];


Text(0, Decode("http%3A%2F%2Ffoo%20bar%2f"))</lang>
Text(0, Decode("http%3A%2F%2Ffoo%20bar%2f"))</syntaxhighlight>


{{out}}
{{out}}
Line 1,766: Line 1,969:
=={{header|Yabasic}}==
=={{header|Yabasic}}==
{{trans|Phix}}
{{trans|Phix}}
<lang Yabasic>sub decode_url$(s$)
<syntaxhighlight lang="yabasic">sub decode_url$(s$)
local res$, ch$
local res$, ch$
Line 1,784: Line 1,987:


print decode_url$("http%3A%2F%2Ffoo%20bar%2F")
print decode_url$("http%3A%2F%2Ffoo%20bar%2F")
print decode_url$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</lang>
print decode_url$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</syntaxhighlight>


=={{header|zkl}}==
=={{header|zkl}}==
<lang zkl>"http%3A%2F%2Ffoo%20bar%2F".pump(String, // push each char through these fcns:
<syntaxhighlight 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(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>
fcn(_,b,c){ (b+c).toInt(16).toChar() }) // "%" (ignored) "3"+"1"-->0x31-->"1"</syntaxhighlight>
{{out}}
{{out}}
<pre>http://foo bar/</pre>
<pre>http://foo bar/</pre>
or use libCurl:
or use libCurl:
<lang zkl>var Curl=Import.lib("zklCurl");
<syntaxhighlight lang="zkl">var Curl=Import.lib("zklCurl");
Curl.urlDecode("http%3A%2F%2Ffoo%20bar%2F");</lang>
Curl.urlDecode("http%3A%2F%2Ffoo%20bar%2F");</syntaxhighlight>
{{out}}<pre>http://foo bar/</pre>
{{out}}<pre>http://foo bar/</pre>

Latest revision as of 19:38, 1 May 2024

Task
URL decoding
You are encouraged to solve this task according to the task description, using any language you may know.

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.


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á".
  •   The encoded string   "%25%32%35"   should revert to the unencoded form   "%25" and not "%".



11l

F url_decode(s)
   V r = ‘’
   V i = 0
   L i < s.len
      I s[i] == ‘%’
         [Byte] b
         L i < s.len & s[i] == ‘%’
            i++
            b.append(Int(s[i.+2], radix' 16))
            i += 2
         r ‘’= b.decode(‘utf-8’)
      E
         r ‘’= s[i]
         i++
   R r

print(url_decode(‘http%3A%2F%2Ffoo%20bar%2F’))
print(url_decode(‘https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D1%81%D0%BF%D0%B0%D0%B9%D0%BB%D0%B5%D1%80’))
Output:
http://foo bar/
https://ru.wikipedia.org/wiki/Транспайлер

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.

Action!

PROC Append(CHAR ARRAY s CHAR c)
  s(0)==+1
  s(s(0))=c
RETURN

CHAR FUNC GetCharFromHex(CHAR c1,c2)
  CHAR ARRAY hex=['0 '1 '2 '3 '4 '5 '6 '7 '8 '9 'A 'B 'C 'D 'E 'F]
  BYTE i,res

  res=0
  FOR i=0 TO 15
  DO
    IF c1=hex(i) THEN res==+i LSH 4 FI
    IF c2=hex(i) THEN res==+i FI
  OD
RETURN (res)

PROC Decode(CHAR ARRAY in,out)
  BYTE i
  CHAR c

  out(0)=0
  i=1
  WHILE i<=in(0)
  DO
    c=in(i)
    i==+1
    IF c='+ THEN
      Append(out,' )
    ELSEIF c='% THEN
      c=GetCharFromHex(in(i),in(i+1))
      i==+2
      Append(out,c)
    ELSE
      Append(out,c)
    FI
  OD
RETURN

PROC PrintInv(CHAR ARRAY a)
  BYTE i

  IF a(0)>0 THEN
    FOR i=1 TO a(0)
    DO
      Put(a(i)%$80)
    OD
  FI
RETURN

PROC Test(CHAR ARRAY in)
  CHAR ARRAY out(256)

  PrintInv("input  ")
  PrintF(" %S%E",in)

  Decode(in,out)
  PrintInv("decoded")
  PrintF(" %S%E%E",out)
RETURN

PROC Main()
  Test("http%3A%2F%2Ffoo%20bar%2F")
  Test("http%3A%2F%2Ffoo+bar%2F*_-.html")
RETURN
Output:

Screenshot from Atari 8-bit computer

input   http%3A%2F%2Ffoo%20bar%2F
decoded http://foo bar/

input   http%3A%2F%2Ffoo+bar%2F*_-.html
decoded http://foo bar/*_-.html

Ada

Library: AWS
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;

Without external libraries:

package URL is
   function Decode (URL : in String) return String;
end URL;
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;
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;

ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32

Note: See the discussion page re displaying the results (which is mostly focused on the AWK solution but will apply elsewhere too).
For the second task example, this outputs the encoded UTF-8 characters, what you see depends on what you look at it with...

# returns c decoded as a hex digit #
PROC hex value = ( CHAR c )INT: IF   c >= "0" AND c <= "9" THEN        ABS c - ABS "0"
                                ELIF c >= "A" AND c <= "F" THEN 10 + ( ABS c - ABS "A" )
                                ELSE                            10 + ( ABS c - ABS "a" )
                                FI;

# returns the URL encoded string decoded - minimal error handling #
PROC url decode = ( STRING encoded )STRING:
     BEGIN
         [ LWB encoded : UPB encoded ]CHAR result;
         INT result pos  := LWB encoded;
         INT pos         := LWB encoded;
         INT max pos     := UPB encoded;
         INT max encoded := max pos - 3;
         WHILE pos <= UPB encoded
         DO
             IF encoded[ pos ] /= "%" AND pos <= max encoded
             THEN
                 # not a coded character #
                 result[ result pos ] := encoded[ pos ];
                 pos +:= 1
             ELSE
                 # have an encoded character # 
                 result[ result pos ] := REPR ( ( 16 * hex value( encoded[ pos + 1 ] ) )
                                              +        hex value( encoded[ pos + 2 ] )
                                             );
                 pos +:= 3
             FI;
             result pos +:= 1
         OD;
         result[ LWB result : result pos - 1 ]
     END # url decode # ;

# test the url decode procedure #
print( ( url decode( "http%3A%2F%2Ffoo%20bar%2F" ),                 newline ) );
print( ( url decode( "google.com/search?q=%60Abdu%27l-Bah%C3%A1" ), newline ) )
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Apex

EncodingUtil.urlDecode('http%3A%2F%2Ffoo%20bar%2F', 'UTF-8');
EncodingUtil.urlDecode('google.com/search?q=%60Abdu%27l-Bah%C3%A1', 'UTF-8');
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

AppleScript

AST URL decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"

Arturo

print decode.url "http%3A%2F%2Ffoo%20bar%2F"
print decode.url "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

AutoHotkey

UriDecode(Uri) {
    LoopOffset := 0
    VarLength := 0
    VarSetCapacity(Var, StrPut(Uri, "UTF-8"), 0)
    Loop Parse, Uri
    {
        If (A_Index < LoopOffset) {
            Continue
        }
        If (A_LoopField = Chr(37)) {
            Number := "0x" . SubStr(Uri, A_Index + 1, 2)
            LoopOffset := A_Index + 3
        }
        Else {
            Number := Ord(A_LoopField)
        }
        NumPut(Number, Var, VarLength++, "UChar")
    }
    Return StrGet(&Var, VarLength, "UTF-8")
}
MsgBox % UriDecode("http%3A%2F%2Ffoo%20bar%2F")
MsgBox % UriDecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
MsgBox % UriDecode("%25%32%35")

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)
} '
Output:
http%3A%2F%2Ffoo%20bar%2F
http://foo bar/

OR:

LC_ALL=C 
  echo "http%3A%2F%2Ffoo%20bar%2F" | gawk -vRS='%[[:xdigit:]]{2}' '
  RT {RT = sprintf("%c",strtonum("0x" substr(RT, 2)))}
  {gsub(/+/," ");printf "%s", $0 RT}'
Output:
http://foo bar/

BaCon

FUNCTION Url_Decode$(url$)

    LOCAL result$

    SPLIT url$ BY "%" TO item$ SIZE total
    FOR x = 1 TO total-1
        result$ = result$ & CHR$(DEC(LEFT$(item$[x], 2))) & MID$(item$[x], 3)
    NEXT
    RETURN item$[0] & result$

END FUNCTION

PRINT Url_Decode$("http%3A%2F%2Ffoo%20bar%2F")
PRINT Url_Decode$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Bash

See #UNIX Shell

BBC BASIC

      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$
Output:
http://foo bar/

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)
);
Output:
http://foo bar/

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;
}

C#

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);
        }
    }
}
Output:
http://foo bar/

C++

Library: Poco
Works with: g++
#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 ;
}
Output:
http%3A%2F%2Ffoo%20bar%2F is decoded: http://foo bar/ !

Caché ObjectScript

USER>Write $ZConvert("http%3A%2F%2Ffoo%20bar%2F", "I", "URL")
http://foo bar/

Clojure

(java.net.URLDecoder/decode "http%3A%2F%2Ffoo%20bar%2F")

CoffeeScript

console.log decodeURIComponent "http%3A%2F%2Ffoo%20bar%2F?name=Foo%20Barson"
> coffee foo.coffee 
http://foo bar/?name=Foo Barson

Common 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")
Output:
"http://foo bar/"

Crystal

require "uri"

puts URI.decode "http%3A%2F%2Ffoo%20bar%2F"
puts URI.decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

D

import std.stdio, std.uri;

void main() {
    writeln(decodeComponent("http%3A%2F%2Ffoo%20bar%2F"));
}
http://foo bar/

Delphi

program URLEncoding;

{$APPTYPE CONSOLE}

uses IdURI;

begin
  Writeln(TIdURI.URLDecode('http%3A%2F%2Ffoo%20bar%2F'));
end.

Elixir

IO.inspect URI.decode("http%3A%2F%2Ffoo%20bar%2F")
IO.inspect URI.decode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
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#

Translation of: C#
open System

let decode uri = Uri.UnescapeDataString(uri)

[<EntryPoint>]
let main argv =
    printfn "%s" (decode "http%3A%2F%2Ffoo%20bar%2F")
    0

Factor

USING: io kernel urls.encoding ;
IN: rosetta-code.url-decoding

"http%3A%2F%2Ffoo%20bar%2F"
"google.com/search?q=%60Abdu%27l-Bah%C3%A1"
[ url-decode print ] bi@
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Free Pascal

function urlDecode(data: String): AnsiString;
var
  ch: Char;
  pos, skip: Integer;

begin
  pos := 0;
  skip := 0;
  Result := '';

  for ch in data do begin
    if skip = 0 then begin
      if (ch = '%') and (pos < data.length -2) then begin
        skip := 2;
        Result := Result + AnsiChar(Hex2Dec('$' + data[pos+2] + data[pos+3]));

      end else begin
        Result := Result + ch;
      end;

    end else begin
      skip := skip - 1;
    end;
    pos := pos +1;
  end;
end;


FreeBASIC

Translation of: Liberty BASIC
Translation of: Pascal
Const alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"

Function ToDecimal (cadena As String, base_ As Uinteger) As Uinteger 
    Dim As Uinteger i, n, result = 0
    Dim As Uinteger inlength = Len(cadena)
    
    For i = 1 To inlength
        n = Instr(alphanum, Mid(Lcase(cadena),i,1)) - 1
        n *= (base_^(inlength-i))
        result += n
    Next 
    Return result
End Function

Function url2string(cadena As String) As String
    Dim As String c, nc, res
    
    For j As Integer = 1 To Len(cadena)
        c = Mid(cadena, j, 1)
        If c = "%" Then
            nc = Chr(ToDecimal((Mid(cadena, j+1, 2)), 16))
            res &= nc
            j += 2
        Else
            res &= c
        End If
    Next j
    Return res
End Function

Dim As String URL = "http%3A%2F%2Ffoo%20bar%2F"

Print "Supplied URL '"; URL; "'"
Print "URL decoding '"; url2string(URL); "'"

URL = "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
Print !"\nSupplied URL '"; URL; "'"
Print "URL decoding '"; url2string(URL); "'"
Sleep

Frink

While the default is to decode parameters as UTF-8 (which is the W3C recommendation,) the characters may have been encoded in another encoding scheme, and this can be handled correctly.

URLDecode["google.com/search?q=%60Abdu%27l-Bah%C3%A1","UTF8"]

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)
	}
}
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Groovy

assert URLDecoder.decode('http%3A%2F%2Ffoo%20bar%2F') == 'http://foo bar/'

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"
Output:
http://foo bar/

Another approach:

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"
Output:
http://foo bar/

Icon and Unicon

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

hexcvt provides hexstring

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:

require'strings convert'
urldecode=: rplc&(~.,/;"_1&a."2(,:tolower)'%',.toupper hfd i.#a.)

Example use:

   urldecode 'http%3A%2F%2Ffoo%20bar%2F'
http://foo bar/

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:

   urldecode 'google.com/search?q=%60Abdu%27l-Bah%C3%A1'
google.com/search?q=`Abdu'l-Bahá

Java

Java offers the URLDecoder and URLEncoder classes for this specific task.

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
URLDecoder.decode("http%3A%2F%2Ffoo%20bar%2F", StandardCharsets.UTF_8)

Alternately, you could use a regular expression capture

import java.util.regex.Matcher;
import java.util.regex.Pattern;
String decode(String string) {
    Pattern pattern = Pattern.compile("%([A-Za-z\\d]{2})");
    Matcher matcher = pattern.matcher(string);
    StringBuilder decoded = new StringBuilder(string);
    char character;
    int start, end, offset = 0;
    while (matcher.find()) {
        character = (char) Integer.parseInt(matcher.group(1), 16);
        /* offset the matched index since were adjusting the string */
        start = matcher.start() - offset;
        end = matcher.end() - offset;
        decoded.replace(start, end, String.valueOf(character));
        offset += 2;
    }
    return decoded.toString();
}
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

JavaScript

decodeURIComponent("http%3A%2F%2Ffoo%20bar%2F")

jq

Works with: jq version 1.4

If your jq already has "until", then the definition given below may be omitted.

# 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

Example:

"http%3A%2F%2Ffoo%20bar%2F" |  url_decode
Output:
"http://foo bar/"

Julia

using URIParser

enc = "http%3A%2F%2Ffoo%20bar%2F"

dcd = unescape(enc)

println(enc, " => ", dcd)
Output:
http%3A%2F%2Ffoo%20bar%2F => http://foo bar/

Kotlin

// 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"))
}
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Ksh

url_decode()
{
        decode="${*//+/ }"
        eval print -r -- "\$'${decode//'%'@(??)/'\'x\1"'\$'"}'"  2>/dev/null
}

url_decode "http%3A%2F%2Ffoo%20bar%2F"
url_decode "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Lambdatalk

Currently lambdatalk has no builtin primitive for decoding URLs. Let's define it using Javascript.

1) define a new javascript primitive:
{script 
  LAMBDATALK.DICT['decodeURIComponent'] = function() {
    return decodeURIComponent( arguments[0].trim() );
  };
}

2) and use it:
{decodeURIComponent http%3A%2F%2Ffoo%20bar%2F}
-> http://foo bar/


langur

val .finish = fn(.s) { b2s map fn(.x) { number(.x, 16) }, rest split "%", .s }
val .decode = fn(.s) { replace .s, re/(%[0-9A-Fa-f]{2})+/, .finish }

writeln .decode("http%3A%2F%2Ffoo%20bar%2F")
writeln .decode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Lasso

bytes('http%3A%2F%2Ffoo%20bar%2F') -> decodeurl

-> http://foo bar/

Liberty BASIC

    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
Supplied URL 'http%3A%2F%2Ffoo%20bar%2F'
As string 'http://foo bar/'

Lingo

----------------------------------------
-- URL decodes a string
-- @param {string} str
-- @return {string}
----------------------------------------
on urldecode (str)
    res = ""
    ba = bytearray()
    len = str.length
    repeat with i = 1 to len
        c = str.char[i]
        if (c = "%") then
            -- fastest hex-to-dec conversion hack based on Lingo's rgb object
            ba.writeInt8(rgb(str.char[i+1..i+2]).blue)
            i = i + 2
        else if (c = "+") then
            ba.writeInt8(32)
        else
            ba.writeInt8(chartonum(c))
        end if
    end repeat
    ba.position = 1
    return ba.readRawString(ba.length)
end
put urldecode("http%3A%2F%2Ffoo%20bar%2F")
put urldecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
Output:
-- "http://foo bar/"
-- "google.com/search?q=`Abdu'l-Bahá"

LiveCode

put urlDecode("http%3A%2F%2Ffoo%20bar%2F") & cr & \
    urlDecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")

Results

http://foo bar/
google.com/search?q=`Abdu'l-Bah√°

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"))

M2000 Interpreter

Function Len(string) return length in words, so a value 1.5 means 3 bytes

We can add strings with half word at the end of a series of words.

A$=str$("A") has a length of 0.5

b$=chr$(a$) revert bytes to words adding zeroes after each character

Module CheckIt {
      Function decodeUrl$(a$) {
            DIM a$()
            a$()=Piece$(a$, "%")
            if len(a$())=1 then =str$(a$):exit
            k=each(a$(),2)
            \\ convert to one byte per character using str$(string)
            acc$=str$(a$(0))
            While k {
                        \\ chr$() convert to UTF16LE 
                        \\ str$()  convert to ANSI using locale (can be 1033 we can set it before as Locale 1033)
                        \\ so chr$(0x93) give 0x201C
                        \\ str$(chr$(0x93)) return one byte 93 in ANSI as string of one byte length
                        \\ numbers are for UTF-8 so we have to preserve them
                  acc$+=str$(Chr$(Eval("0x"+left$(a$(k^),2)))+Mid$(a$(k^),3))
            }
            =acc$
      }
      \\ decode from utf8
      final$=DecodeUrl$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")
      Print string$(final$ as utf8dec)="google.com/search?q=`Abdu'l-Bahá"
      final$=DecodeUrl$("http%3A%2F%2Ffoo%20bar%2F")
      Print string$(final$ as utf8dec)="http://foo bar/"
}
CheckIt

Maple

StringTools:-Decode("http%3A%2F%2Ffoo%20bar%2F", encoding=percent);
Output:
                           "http://foo bar/"

Mathematica/Wolfram Language

URLDecoding[url_] := 
 StringReplace[url, "%" ~~ x_ ~~ y_ :> FromDigits[x ~~ y, 16]] //. 
  StringExpression[x___, Longest[n__Integer], y___] :> 
   StringExpression[x, FromCharacterCode[{n}, "UTF8"], y]

Example use:

URLDecoding["http%3A%2F%2Ffoo%20bar%2F"]
Output:
http://foo bar/

Using the built-in URLDecode (http://reference.wolfram.com/language/ref/URLDecode.html) function:

Output:
In[]:= URLDecode["http%3A%2F%2Ffoo%20bar%2F"]
Out[]= "http://foo bar/"

In[]:= URLDecode["google.com/search?q=%60Abdu%27l-Bah%C3%A1"]
Out[]= "google.com/search?q=`Abdu'l-Bahá"

In[]:= URLDecode[{"Kurt+G%C3%B6del", "Paul+Erd%C5%91s"}]
Out[]= {"Kurt Gödel", "Paul Erdős"}

MATLAB / Octave

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

Usage:

octave:3> urldecoding('http%3A%2F%2Ffoo%20bar%2F')
ans = http://foo bar/

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
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

;; universal decoder, works for ASCII and UTF-8
;; (source http://www.newlisp.org/index.cgi?page=Code_Snippets)
(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")

Nim

import cgi

echo decodeUrl("http%3A%2F%2Ffoo%20bar%2F")
Output:
http://foo bar/

Oberon-2

Works with: oo2c
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.
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Objeck

class UrlDecode {
  function : Main(args : String[]) ~ Nil {
    Net.UrlUtility->Decode("http%3A%2F%2Ffoo%20bar%2F")->PrintLine();
  }
}

Objective-C

NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F";
NSString *normal = [encoded stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", normal);
Works with: Mac OS X version 10.9+
Works with: iOS version 7+
NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F";
NSString *normal = [encoded stringByRemovingPercentEncoding];
NSLog(@"%@", normal);

OCaml

Using the library ocamlnet from the interactive loop:

$ ocaml
# #use "topfind";;
# #require "netstring";;

# Netencoding.Url.decode "http%3A%2F%2Ffoo%20bar%2F" ;;
- : string = "http://foo bar/"

ooRexx

While the implementation shown for Rexx will also work with ooRexx, this version uses ooRexx syntax to invoke the built-in functions.

/* 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
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

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";
#!/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" ;

Phix

--
-- demo\rosetta\decode_url.exw
-- ===========================
--
with javascript_semantics
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")})

{} = wait_key()
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

PHP

<?php
$encoded = "http%3A%2F%2Ffoo%20bar%2F";
$unencoded = rawurldecode($encoded);
echo "The unencoded string is $unencoded !\n";
?>

PicoLisp

: (ht:Pack (chop "http%3A%2F%2Ffoo%20bar%2F") T)
-> "http://foo bar/"

Pike

void main()
{
    array encoded_urls = ({
        "http%3A%2F%2Ffoo%20bar%2F",
        "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
    });


    foreach(encoded_urls, string url) {
        string decoded = Protocols.HTTP.uri_decode( url );
        write( string_to_utf8(decoded) +"\n" ); // Assume sink does UTF8
    }
}
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

PowerShell

[System.Web.HttpUtility]::UrlDecode("http%3A%2F%2Ffoo%20bar%2F")
Output:
http://foo bar/

PureBasic

URL$ = URLDecoder("http%3A%2F%2Ffoo%20bar%2F")

Debug URL$  ; http://foo bar/

Python

#Python 2.X
import urllib
print urllib.unquote("http%3A%2F%2Ffoo%20bar%2F")
#Python 3.5+
from urllib.parse import unquote
print(unquote('http%3A%2F%2Ffoo%20bar%2F'))

R

URLdecode("http%3A%2F%2Ffoo%20bar%2F")

Racket

#lang racket
(require net/uri-codec)
(uri-decode "http%3A%2F%2Ffoo%20bar%2F")

Raku

(formerly Perl 6)

my @urls = < http%3A%2F%2Ffoo%20bar%2F
             google.com/search?q=%60Abdu%27l-Bah%C3%A1 >;

say .subst( :g,
    / [ '%' ( <xdigit> ** 2 ) ]+ / ,
    { Blob.new((:16(~$_) for $0)).decode }
    ) for @urls;
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Red

>> dehex "http%3A%2F%2Ffoo%20bar%2F"
== "http://foo bar/"
>> dehex "google.com/search?q=%60Abdu%27l-Bah%C3%A1"
== "google.com/search?q=`Abdu'l-Bahá"

Retro

This is provided by the casket library (used for web app development).

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

REXX

version 1

Translation of: ooRexx

Tested with the ooRexx and Regina interpreters.

/* 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
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.

/*REXX program converts a   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= ''

              do  while encoded\==''
              parse var encoded   head  '%'  +1  code  +2  tail
              decoded= decoded || head
              L= length( strip( code, 'T') )
                 select
                 when L==2 & datatype(code, "X")  then       decoded= decoded || x2c(code)
                 when L\==0                       then do;   decoded= decoded'%'
                                                             tail= code || tail
                                                       end
                 otherwise nop
                 end    /*select*/
              encoded= tail
              end   /*while*/

            return decoded
output   is identical to the 1st REXX version.

version 3

This REXX version is a shorter version of version 2.

/*REXX program converts & displays a URL─encoded string ──► its original unencoded form.*/
url. =
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'

            do j=1  until url.j=='';   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
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 " ".

require 'cgi'
puts CGI.unescape("http%3A%2F%2Ffoo%20bar%2F")
# => "http://foo bar/"
Works with: Ruby version 1.9.2
require 'uri'
puts URI.decode_www_form_component("http%3A%2F%2Ffoo%20bar%2F")
# => "http://foo bar/"

URI.unescape (alias URI.unencode) still works. URI.unescape is obsolete since Ruby 1.9.2 because of problems with its sibling URI.escape.

Rust

const INPUT1: &str = "http%3A%2F%2Ffoo%20bar%2F";
const INPUT2: &str = "google.com/search?q=%60Abdu%27l-Bah%C3%A1";

fn append_frag(text: &mut String, frag: &mut String) {
    if !frag.is_empty() {
        let encoded = frag.chars()
            .collect::<Vec<char>>()
            .chunks(2)
            .map(|ch| {
                u8::from_str_radix(&ch.iter().collect::<String>(), 16).unwrap()
            }).collect::<Vec<u8>>();
        text.push_str(&std::str::from_utf8(&encoded).unwrap());
        frag.clear();
    }
}

fn decode(text: &str) -> String {
    let mut output = String::new();
    let mut encoded_ch = String::new();
    let mut iter = text.chars();
    while let Some(ch) = iter.next() {
        if ch == '%' {
            encoded_ch.push_str(&format!("{}{}", iter.next().unwrap(), iter.next().unwrap()));
        } else {
            append_frag(&mut output, &mut encoded_ch);
            output.push(ch);
        }
    }
    append_frag(&mut output, &mut encoded_ch);
    output
}

fn main() {
    println!("{}", decode(INPUT1));
    println!("{}", decode(INPUT2));
}
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Scala

Library: 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]")
}

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 fromUtf8 afterwards.

$ 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;
Output:
http://foo bar/
http://foo bar/

Sidef

Translation of: Perl
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/"

Swift

import Foundation

let encoded = "http%3A%2F%2Ffoo%20bar%2F"
if let normal = encoded.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
  println(normal)
}

Tcl

This code is careful to ensure that any untoward metacharacters in the input string still do not cause any problems.

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]]
}

Demonstrating:

puts [urlDecode "http%3A%2F%2Ffoo%20bar%2F"]
Output:
http://foo bar/

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
Output:
encoded: http%3A%2F%2Ffoo%20bar%2F
decoded: http://foo bar/

UNIX Shell

Works with: bash
Works with: ksh
urldecode() { local u="${1//+/ }"; printf '%b' "${u//%/\\x}"; }

Alternative: Replace printf '%b' "${u//%/\\x}" with echo -e "${u//%/\\x}"

Example:

urldecode http%3A%2F%2Ffoo%20bar%2F
http://foo bar/

urldecode google.com/search?q=%60Abdu%27l-Bah%C3%A1
google.com/search?q=`Abdu'l-Bahároot@
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
}

VBScript

Function RegExTest(str,patrn)
    Dim regEx
    Set regEx = New RegExp
    regEx.IgnoreCase = True
    regEx.Pattern = patrn
    RegExTest = regEx.Test(str)
End Function

Function URLDecode(sStr)
    Dim str,code,a0
    str=""
    code=sStr
    code=Replace(code,"+"," ")
    While len(code)>0
        If InStr(code,"%")>0 Then
            str = str & Mid(code,1,InStr(code,"%")-1)
            code = Mid(code,InStr(code,"%"))
            a0 = UCase(Mid(code,2,1))
            If a0="U" And RegExTest(code,"^%u[0-9A-F]{4}") Then
                str = str & ChrW((Int("&H" & Mid(code,3,4))))
                code = Mid(code,7)
            ElseIf a0="E" And RegExTest(code,"^(%[0-9A-F]{2}){3}") Then
                str = str & ChrW((Int("&H" & Mid(code,2,2)) And 15) * 4096 + (Int("&H" & Mid(code,5,2)) And 63) * 64 + (Int("&H" & Mid(code,8,2)) And 63))
                code = Mid(code,10)
            ElseIf a0>="C" And a0<="D" And RegExTest(code,"^(%[0-9A-F]{2}){2}") Then
                str = str & ChrW((Int("&H" & Mid(code,2,2)) And 3) * 64 + (Int("&H" & Mid(code,5,2)) And 63))
                code = Mid(code,7)
            ElseIf (a0<="B" Or a0="F") And RegExTest(code,"^%[0-9A-F]{2}") Then
                str = str & Chr(Int("&H" & Mid(code,2,2)))
                code = Mid(code,4)
            Else
                str = str & "%"
                code = Mid(code,2)
            End If
        Else
            str = str & code
            code = ""
        End If
    Wend
    URLDecode = str
End Function

url = "http%3A%2F%2Ffoo%20bar%C3%A8%2F"
WScript.Echo "Encoded URL: " & url & vbCrLf &_
	"Decoded URL: " & UrlDecode(url)
Output:
Encoded URL: http%3A%2F%2Ffoo%20bar%C3%A8%2F
Decoded URL: http://foo barè/

V (Vlang)

import net.urllib
fn main() {
	for escaped in [
		"http%3A%2F%2Ffoo%20bar%2F",
		"google.com/search?q=%60Abdu%27l-Bah%C3%A1",
     ] {
		u := urllib.query_unescape(escaped)?
		println(u)
	}
}
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

Wren

Library: Wren-fmt
import "./fmt" for Conv

var urlDecode = Fn.new { |enc|
    var res = ""
    var i = 0
    while (i < enc.count) {
        var c = enc[i]
        if (c == "\%") {
            var b = Conv.atoi(enc[i+1..i+2], 16)
            res = res + String.fromByte(b)
            i = i + 3
        } else {
            res = res + c
            i = i + 1
        }
    }
    return res
}

// We need to escape % characters in Wren as % is otherwise used for string interpolation.
var encs = [
    "http\%3A\%2F\%2Ffoo\%20bar\%2F",
    "google.com/search?q=\%60Abdu\%27l-Bah\%C3\%A1"
]
for (enc in encs)System.print(urlDecode.call(enc))
Output:
http://foo bar/
google.com/search?q=`Abdu'l-Bahá

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"))
Output:
http://foo bar/

Yabasic

Translation of: Phix
sub decode_url$(s$)
    local res$, ch$
	
    while(s$ <> "")
        ch$ = left$(s$, 1)
        if ch$ = "%" then
            ch$ = chr$(dec(mid$(s$, 2, 2)))
            s$ = right$(s$, len(s$) - 3)
        else
            if ch$ = "+" ch$ = " "
            s$ = right$(s$, len(s$) - 1)
	endif
        res$ = res$ + ch$
    wend
    return res$
end sub

print decode_url$("http%3A%2F%2Ffoo%20bar%2F")
print decode_url$("google.com/search?q=%60Abdu%27l-Bah%C3%A1")

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"
Output:
http://foo bar/

or use libCurl:

var Curl=Import.lib("zklCurl");
Curl.urlDecode("http%3A%2F%2Ffoo%20bar%2F");
Output:
http://foo bar/