URL decoding: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Haskell}}: another approach)
(→‎{{header|Haskell}}: Reduced dual fmap to one)
Line 427: Line 427:
deCode :: String -> String
deCode :: String -> String
deCode url =
deCode url =
concat $ head ps : ((\(a, b) -> (chr . fst . head . readHex) a : b) <$> xs)
concat $
head ps : zipWith (:) ((chr . fst . head . readHex . fst) <$> xs) (snd <$> xs)
where
where
xs = splitAt 2 <$> tail ps
xs = splitAt 2 <$> tail ps

Revision as of 12:40, 4 April 2017

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á".



ABAP

<lang ABAP>REPORT Z_DECODE_URL.

DATA: lv_encoded_url TYPE string VALUE 'http%3A%2F%2Ffoo%20bar%2F',

     lv_decoded_url TYPE string.

CALL METHOD CL_HTTP_UTILITY=>UNESCAPE_URL

 EXPORTING
   ESCAPED   = lv_encoded_url
 RECEIVING
   UNESCAPED = lv_decoded_url.

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

Ada

Library: AWS

<lang Ada>with AWS.URL; with Ada.Text_IO; use Ada.Text_IO; procedure Decode is

  Encoded : constant String := "http%3A%2F%2Ffoo%20bar%2F";

begin

  Put_Line (AWS.URL.Decode (Encoded));

end Decode; </lang>

Without external libraries:

<lang Ada>package URL is

  function Decode (URL : in String) return String;

end URL;</lang>

<lang Ada>package body URL is

  function Decode (URL : in String) return String is
     Buffer   : String (1 .. URL'Length);
     Filled   : Natural := 0;
     Position : Positive := URL'First;
  begin
     while Position in URL'Range loop
        Filled := Filled + 1;

       case URL (Position) is
           when '+' =>
              Buffer (Filled) := ' ';
              Position := Position + 1;
           when '%' =>
              Buffer (Filled) :=
                Character'Val
                  (Natural'Value
                     ("16#" & URL (Position + 1 .. Position + 2) & "#"));
              Position := Position + 3;
           when others =>
              Buffer (Filled) := URL (Position);
              Position := Position + 1;
        end case;
     end loop;
     return Buffer (1 .. Filled);
  end Decode;

end URL;</lang>

<lang Ada>with Ada.Command_Line,

    Ada.Text_IO;

with URL;

procedure Test_URL_Decode is

  use Ada.Command_Line, Ada.Text_IO;

begin

  if Argument_Count = 0 then
     Put_Line (URL.Decode ("http%3A%2F%2Ffoo%20bar%2F"));
  else
     for I in 1 .. Argument_Count loop
        Put_Line (URL.Decode (Argument (I)));
     end loop;
  end if;

end Test_URL_Decode;</lang>

Apex

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

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

AppleScript

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

AutoHotkey

<lang AutoHotkey>encURL := "http%3A%2F%2Ffoo%20bar%2F" SetFormat, Integer, hex Loop Parse, encURL

  If A_LoopField = `%
     reading := 2, read := ""
  else if reading
  {
     read .= A_LoopField, --reading
     if not reading
        out .= Chr("0x" . read)
  }
  else out .= A_LoopField

MsgBox % out ; http://foo bar/ </lang>

AWK

<lang AWK>

  1. syntax:

awk ' BEGIN {

   str = "http%3A%2F%2Ffoo%20bar%2F" # "http://foo bar/"
   printf("%s\n",str)
   len=length(str)
   for (i=1;i<=len;i++) {
     if ( substr(str,i,1) == "%") {
       L = substr(str,1,i-1) # chars to left of "%"
       M = substr(str,i+1,2) # 2 chars to right of "%"
       R = substr(str,i+3)   # chars to right of "%xx"
       str = sprintf("%s%c%s",L,hex2dec(M),R)
     }
   }
   printf("%s\n",str)
   exit(0)

} function hex2dec(s, num) {

   num = index("0123456789ABCDEF",toupper(substr(s,length(s)))) - 1
   sub(/.$/,"",s)
   return num + (length(s) ? 16*hex2dec(s) : 0)

} ' </lang>

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

BBC BASIC

<lang bbcbasic> PRINT FNurldecode("http%3A%2F%2Ffoo%20bar%2F")

     END
     
     DEF FNurldecode(url$)
     LOCAL i%
     REPEAT
       i% = INSTR(url$, "%", i%+1)
       IF i% THEN
         url$ = LEFT$(url$,i%-1) + \
         \      CHR$EVAL("&"+FNupper(MID$(url$,i%+1,2))) + \
         \      MID$(url$,i%+3)
       ENDIF
     UNTIL i% = 0
     = url$
     
     DEF FNupper(A$)
     LOCAL A%,C%
     FOR A% = 1 TO LEN(A$)
       C% = ASCMID$(A$,A%)
       IF C% >= 97 IF C% <= 122 MID$(A$,A%,1) = CHR$(C%-32)
     NEXT
     = A$</lang>
Output:
http://foo bar/

Bracmat

<lang bracmat>( ( decode

     =   decoded hexcode notencoded
       .   :?decoded
         &   whl
           ' ( @(!arg:?notencoded "%" (% %:?hexcode) ?arg)
             & !decoded !notencoded chr$(x2d$!hexcode):?decoded
             )
         & str$(!decoded !arg)
     )
   & out$(decode$http%3A%2F%2Ffoo%20bar%2F)

);</lang>

Output:
http://foo bar/

C

<lang c>#include <stdio.h>

  1. include <string.h>

inline int ishex(int x) { return (x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'); }

int decode(const char *s, char *dec) { char *o; const char *end = s + strlen(s); int c;

for (o = dec; s <= end; o++) { c = *s++; if (c == '+') c = ' '; else if (c == '%' && ( !ishex(*s++) || !ishex(*s++) || !sscanf(s - 2, "%2x", &c))) return -1;

if (dec) *o = c; }

return o - dec; }

int main() { const char *url = "http%3A%2F%2ffoo+bar%2fabcd"; char out[strlen(url) + 1];

printf("length: %d\n", decode(url, 0)); puts(decode(url, out) < 0 ? "bad string" : out);

return 0; }</lang>

C++

Library: Poco
Works with: g++

<lang cpp>#include <string>

  1. include "Poco/URI.h"
  2. include <iostream>

int main( ) {

  std::string encoded( "http%3A%2F%2Ffoo%20bar%2F" ) ;
  std::string decoded ;
  Poco::URI::decode ( encoded , decoded ) ;
  std::cout << encoded << " is decoded: " << decoded << " !" << std::endl ;
  return 0 ;

}</lang>

Output:
http%3A%2F%2Ffoo%20bar%2F is decoded: http://foo bar/ !

C#

<lang csharp>using System;

namespace URLEncode {

   internal class Program
   {
       private static void Main(string[] args)
       {
           Console.WriteLine(Decode("http%3A%2F%2Ffoo%20bar%2F"));
       }
       private static string Decode(string uri)
       {
           return Uri.UnescapeDataString(uri);
       }
   }

}</lang>

Output:
http://foo bar/

Caché ObjectScript

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

Clojure

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

CoffeeScript

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

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

Common Lisp

<lang lisp>(defun decode (string &key start)

 (assert (char= (char string start) #\%))
 (if (>= (length string) (+ start 3))
     (multiple-value-bind (code pos)
         (parse-integer string :start (1+ start) :end (+ start 3) :radix 16 :junk-allowed t)
       (if (= pos (+ start 3))
           (values (code-char code) pos)
           (values #\% (1+ start))))
     (values #\% (1+ start))))

(defun url-decode (url)

 (loop with start = 0
       for pos = (position #\% url :start start)
       collect (subseq url start pos) into chunks
       when pos
         collect (multiple-value-bind (decoded next) (decode url :start pos)
                   (setf start next)
                   (string decoded))
           into chunks
       while pos
       finally (return (apply #'concatenate 'string chunks))))

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

Output:
"http://foo bar/"

D

<lang d>import std.stdio, std.uri;

void main() {

   writeln(decodeComponent("http%3A%2F%2Ffoo%20bar%2F"));

}</lang>

http://foo bar/

Delphi

<lang Delphi>program URLEncoding;

{$APPTYPE CONSOLE}

uses IdURI;

begin

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

end.</lang>

Elixir

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

Output:
"http://foo bar/"
"google.com/search?q=`Abdu'l-Bahá"

Erlang

Built in.

34> http_uri:decode("http%3A%2F%2Ffoo%20bar%2F").
"http://foo bar/"

F#

Translation of: C#

<lang fsharp>open System

let decode uri = Uri.UnescapeDataString(uri)

[<EntryPoint>] let main argv =

   printfn "%s" (decode "http%3A%2F%2Ffoo%20bar%2F")
   0</lang>


Go

<lang go>package main

import ( "fmt" "log" "net/url" )

func main() { for _, escaped := range []string{ "http%3A%2F%2Ffoo%20bar%2F", "google.com/search?q=%60Abdu%27l-Bah%C3%A1", } { u, err := url.QueryUnescape(escaped) if err != nil { log.Println(err) continue } fmt.Println(u) } }</lang>

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

Groovy

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

Haskell

<lang Haskell>import qualified Data.Char as Char

urlDecode :: String -> Maybe String urlDecode [] = Just [] urlDecode ('%':xs) =

 case xs of
   (a:b:xss) ->
     urlDecode xss
     >>= return . ((Char.chr . read $ "0x" ++ [a,b]) :)
   _ -> Nothing

urlDecode ('+':xs) = urlDecode xs >>= return . (' ' :) urlDecode (x:xs) = urlDecode xs >>= return . (x :)

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

Output:
http://foo bar/

Another approach: <lang haskell>import Data.Char (chr) import Numeric (readHex) import Data.List.Split (splitOn)

deCode :: String -> String deCode url =

 concat $ head ps : ((\(a, b) -> (chr . fst . head . readHex) a : b) <$> xs)
 where
   xs = splitAt 2 <$> tail ps
   ps = splitOn "%" url

-- TEST ------------------------------------------------------------------------ main :: IO () main = putStrLn $ deCode "http%3A%2F%2Ffoo%20bar%2F"</lang>

Output:
http://foo bar/

Icon and Unicon

<lang Icon>link hexcvt

procedure main() ue := "http%3A%2F%2Ffoo%20bar%2F" ud := decodeURL(ue) | stop("Improperly encoded string ",image(ue)) write("encoded = ",image(ue)) write("decoded = ",image(ue)) end

procedure decodeURL(s) #: decode URL/URI encoded data static de initial { # build lookup table for everything

 de := table()
 every de[hexstring(ord(c := !string(&ascii)),2)] := c
 }

c := "" s ? until pos(0) do # decode every %xx or fail

  c ||:= if ="%" then \de[move(2)] | fail
  else move(1)

return c end</lang>

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:

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

Example use:

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

Note that an earlier implementation assumed the j6 implementation of hfd which where hexadecimal letters resulting from hfd were upper case. J8, in contrast, provides a lower case result from hfd. The addition of toupper guarantees the case insensitivity required by RFC 3986 regardless of which version of J you are using. As the parenthesized expression containing hfd is only evaluated at definition time, there's no performance penalty from the use of toupper.

Example use:

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

Java

<lang java>import java.io.UnsupportedEncodingException; import java.net.URLDecoder;

public class Main {

   public static void main(String[] args) throws UnsupportedEncodingException
   {
       String encoded = "http%3A%2F%2Ffoo%20bar%2F";
       String normal = URLDecoder.decode(encoded, "utf-8");
       System.out.println(normal);
   }

}</lang>

Output:
http://foo bar/

JavaScript

<lang javascript>decodeURIComponent("http%3A%2F%2Ffoo%20bar%2F")</lang>

jq

Works with: jq version 1.4

If your jq already has "until", then the definition given below may be omitted. <lang jq># Emit . and stop as soon as "condition" is true. def until(condition; next):

 def u: if condition then . else (next|u) end;
 u;

def url_decode:

 # The helper function converts the input string written in the given
 # "base" to an integer
 def to_i(base):
   explode
   | reverse
   | map(if 65 <= . and . <= 90 then . + 32  else . end)   # downcase
   | map(if . > 96  then . - 87 else . - 48 end)  # "a" ~ 97 => 10 ~ 87
   | reduce .[] as $c
       # base: [power, ans]
       ([1,0]; (.[0] * base) as $b | [$b, .[1] + (.[0] * $c)]) | .[1];
 .  as $in
 | length as $length
 | [0, ""]  # i, answer
 | until ( .[0] >= $length;
     .[0] as $i
     |  if $in[$i:$i+1] == "%"
        then [ $i + 3, .[1] + ([$in[$i+1:$i+3] | to_i(16)] | implode) ]
        else [ $i + 1, .[1] + $in[$i:$i+1] ]
        end)
 | .[1];  # answer</lang>

Example: <lang jq>"http%3A%2F%2Ffoo%20bar%2F" | url_decode</lang>

Output:

<lang sh> "http://foo bar/"</lang>

Julia

<lang Julia> using URIParser

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

dcd = unescape(enc)

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

Output:
http%3A%2F%2Ffoo%20bar%2F => http://foo bar/

Lasso

<lang Lasso>bytes('http%3A%2F%2Ffoo%20bar%2F') -> decodeurl</lang> -> http://foo bar/

Liberty BASIC

<lang lb>

   dim lookUp$( 256)
   for i =0 to 256
       lookUp$( i) ="%" +dechex$( i)
   next i
   url$ ="http%3A%2F%2Ffoo%20bar%2F"
   print "Supplied URL '"; url$; "'"
   print "As string    '"; url2string$( url$); "'"
   end

function url2string$( i$)

   for j =1 to len( i$)
       c$ =mid$( i$, j, 1)
       if c$ ="%" then
           nc$         =chr$( hexdec( mid$( i$, j +1, 2)))
           url2string$ =url2string$ +nc$ 
           j =j +2
       else
           url2string$ =url2string$ +c$
       end if
   next j

end function </lang>

Supplied URL 'http%3A%2F%2Ffoo%20bar%2F'
As string 'http://foo bar/'


LiveCode

<lang LiveCode>put urlDecode("http%3A%2F%2Ffoo%20bar%2F") & cr & \

   urlDecode("google.com/search?q=%60Abdu%27l-Bah%C3%A1")</lang>Results<lang>http://foo bar/

google.com/search?q=`Abdu'l-Bah√°</lang>

Lua

<lang lua>function decodeChar(hex) return string.char(tonumber(hex,16)) end

function decodeString(str) local output, t = string.gsub(str,"%%(%x%x)",decodeChar) return output end

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

Maple

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

Output:
                           "http://foo bar/"

Mathematica

<lang mathematica>URLDecoding[url_] :=

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

Example use:

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

Output:
http://foo bar/

MATLAB / Octave

<lang MATLAB>function u = urldecoding(s)

   u = ;
   k = 1;
   while k<=length(s)
       if s(k) == '%' && k+2 <= length(s)
           u = sprintf('%s%c', u, char(hex2dec(s((k+1):(k+2)))));
           k = k + 3;
       else
           u = sprintf('%s%c', u, s(k));
           k = k + 1;
       end        
   end

end</lang> Usage:

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

NetRexx

<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols nobinary

url = [ -

 'http%3A%2F%2Ffoo%20bar%2F', -
 'mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E', -
 '%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E' -
 ]

loop u_ = 0 to url.length - 1

 say url[u_]
 say DecodeURL(url[u_])
 say
 end u_

return

method DecodeURL(arg) public static

 Parse arg encoded
 decoded = 
 PCT = '%'
 loop label e_ while encoded.length() > 0
   parse encoded head (PCT) +1 code +2 tail
   decoded = decoded || head
   select
     when code.strip('T').length() = 2 & code.datatype('X') then do
       code = code.x2c()
       decoded = decoded || code
       end
     when code.strip('T').length() \= 0 then do
       decoded = decoded || PCT
       tail = code || tail
       end
     otherwise do
       nop
       end
     end
   encoded = tail
   end e_
 return decoded

</lang>

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

mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E
mailto:"Ivan Aim" <ivan.aim@email.com>

%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E
mailto:"Irma User" <irma.user@mail.com>

NewLISP

<lang NewLISP>;; universal decoder, works for ASCII and UTF-8

(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")</lang>

Nim

<lang nim>import cgi

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

Oberon-2

Works with: oo2c

<lang oberon2> MODULE URLDecoding; IMPORT

 URI := URI:String,
 Out := NPCT:Console;

BEGIN

 Out.String(URI.Unescape("http%3A%2F%2Ffoo%20bar%2F"));Out.Ln;
 Out.String(URI.Unescape("google.com/search?q=%60Abdu%27l-Bah%C3%A1"));Out.Ln;  

END URLDecoding. </lang>

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

Objeck

<lang objeck> class UrlDecode {

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

} </lang>

Objective-C

<lang objc>NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F"; NSString *normal = [encoded stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSLog(@"%@", normal);</lang>

Works with: Mac OS X version 10.9+
Works with: iOS version 7+

<lang objc>NSString *encoded = @"http%3A%2F%2Ffoo%20bar%2F"; NSString *normal = [encoded stringByRemovingPercentEncoding]; NSLog(@"%@", normal);</lang>

OCaml

Using the library ocamlnet from the interactive loop:

<lang ocaml>$ ocaml

  1. #use "topfind";;
  2. #require "netstring";;
  1. Netencoding.Url.decode "http%3A%2F%2Ffoo%20bar%2F" ;;

- : string = "http://foo bar/"</lang>

ooRexx

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

 X = 0
 url. = 
 X = X + 1; url.0 = X; url.X = 'http%3A%2F%2Ffoo%20bar%2F'
 X = X + 1; url.0 = X; url.X = 'mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E'
 X = X + 1; url.0 = X; url.X = '%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E'
 Do u_ = 1 to url.0
   Say url.u_
   Say DecodeURL(url.u_)
   Say
   End u_

Exit

DecodeURL: Procedure

 Parse Arg encoded
 decoded = 
 PCT = '%'
 Do label e_ while encoded~length() > 0
   Parse Var encoded head (PCT) +1 code +2 tail
   decoded = decoded || head
   Select
     when code~strip('T')~length() = 2 & code~datatype('X') then Do
       code = code~x2c()
       decoded = decoded || code
       End
     when code~strip('T')~length() \= 0 then Do
       decoded = decoded || PCT
       tail = code || tail
       End
     otherwise 
       Nop
     End
   encoded = tail
   End e_
 Return decoded</lang>
Output:
http%3A%2F%2Ffoo%20bar%2F
http://foo bar/

mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E
mailto:"Ivan Aim" <ivan.aim@email.com>

%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E
mailto:"Irma User" <irma.user@mail.com>

Perl

<lang Perl>sub urldecode {

   my $s = shift;
   $s =~ tr/\+/ /;
   $s =~ s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/eg;
   return $s;

}

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

<lang Perl>#!/usr/bin/perl -w use strict ; use URI::Escape ;

my $encoded = "http%3A%2F%2Ffoo%20bar%2F" ; my $unencoded = uri_unescape( $encoded ) ; print "The unencoded string is $unencoded !\n" ;</lang>

Perl 6

<lang perl6>my $url = "http%3A%2F%2Ffoo%20bar%2F";

say $url.subst: :g,

   /'%'(<:hexdigit>**2)/,
   ->  ($ord          ) { chr(:16(~$ord)) }</lang>

Alternately, you can use an in-place substitution: <lang perl6>$url ~~ s:g[ '%' (<:hexdigit> ** 2) ] = chr :16(~$0); say $url;</lang>

Phix

<lang Phix>-- -- demo\rosetta\decode_url.exw -- =========================== -- function decode_url(string s) integer skip = 0 string res = ""

   for i=1 to length(s) do
       if skip then
           skip -= 1
       else
           integer ch = s[i]
           if ch='%' then
               sequence scanres = {}
               if i+2<=length(s) then
                   scanres = scanf("#"&s[i+1..i+2],"%x")
               end if
               if length(scanres)!=1 then
                   return "decode error"
               end if
               skip = 2
               ch = scanres[1][1]
           elsif ch='+' then
               ch = ' '
           end if
           res &= ch
       end if
   end for
   return res

end function

printf(1,"%s\n",{decode_url("http%3A%2F%2Ffoo%20bar%2F")}) printf(1,"%s\n",{decode_url("google.com/search?q=%60Abdu%27l-Bah%C3%A1")})</lang>

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

PHP

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

PicoLisp

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

PowerShell

<lang PowerShell> [System.Web.HttpUtility]::UrlDecode("http%3A%2F%2Ffoo%20bar%2F") </lang>

Output:
http://foo bar/

PureBasic

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

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

Python

<lang Python>import urllib print urllib.unquote("http%3A%2F%2Ffoo%20bar%2F")</lang>

R

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

Racket

<lang racket>

  1. lang racket

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

Retro

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

<lang Retro>create buffer 32000 allot

{{

 create bit 5 allot
 : extract  ( $c-$a ) drop @+ bit ! @+ bit 1+ ! bit ;
 : render   ( $c-$n )
   dup '+ = [ drop 32 ] ifTrue
   dup 13 = [ drop 32 ] ifTrue
   dup 10 = [ drop 32 ] ifTrue
   dup '% = [ extract hex toNumber decimal ] ifTrue ;
 : <decode> (  $-$  ) repeat @+ 0; render ^buffer'add again ;

---reveal---

 : decode   (  $-   ) buffer ^buffer'set <decode> drop ;

}}

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

REXX

version 1

Translation of: ooRexx

Tested with the ooRexx and Regina interpreters. <lang REXX>/* Rexx */

Do

 X = 0
 url. = 
 X = X + 1; url.0 = X; url.X = 'http%3A%2F%2Ffoo%20bar%2F'
 X = X + 1; url.0 = X; url.X = 'mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E'
 X = X + 1; url.0 = X; url.X = '%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E'
 Do u_ = 1 to url.0
   Say url.u_
   Say DecodeURL(url.u_)
   Say
   End u_
 Return

End Exit

DecodeURL: Procedure Do

 Parse Arg encoded
 decoded = 
 PCT = '%'
 Do while length(encoded) > 0
   Parse Var encoded head (PCT) +1 code +2 tail
   decoded = decoded || head
   Select
     When length(strip(code, 'T')) = 2 & datatype(code, 'X') then Do
       code = x2c(code)
       decoded = decoded || code
       End
     When length(strip(code, 'T')) \= 0 then Do
       decoded = decoded || PCT
       tail = code || tail
       End
     Otherwise Do
       Nop
       End
     End
   encoded = tail
   End
 Return decoded

End Exit </lang>

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

mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E
mailto:"Ivan Aim" <ivan.aim@email.com>

%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E
mailto:"Irma User" <irma.user@mail.com>

version 2

This REXX version is identical to version 1, but with superfluous and dead code removed. <lang REXX>/*REXX program converts an URL─encoded string ──► its original unencoded form.*/ url.1='http%3A%2F%2Ffoo%20bar%2F' url.2='mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E' url.3='%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E' URLs=3

           do j=1  for URLs
           say url.j
           say decodeURL(url.j)
           say
           end   /*j*/

exit /*────────────────────────────────────────────────────────────────────────────*/ decodeURL: procedure; parse arg encoded; decoded= encoded=translate(encoded,,'+') /*special case for encoded blank.*/

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

return decoded</lang> output is identical to version 1.

version 3

This REXX version is a shorter version of version 2. <lang REXX>/*REXX program converts an URL─encoded string ──► its original unencoded form.*/ url.1='http%3A%2F%2Ffoo%20bar%2F' url.2='mailto%3A%22Ivan%20Aim%22%20%3Civan%2Eaim%40email%2Ecom%3E' url.3='%6D%61%69%6C%74%6F%3A%22%49%72%6D%61%20%55%73%65%72%22%20%3C%69%72%6D%61%2E%75%73%65%72%40%6D%61%69%6C%2E%63%6F%6D%3E' URLs=3

           do j=1  for URLs;     say  /*process each URL; display blank line.*/
           say           url.j        /*display the original URL.            */
           say URLdecode(url.j)       /*   "     "  decoded   "              */
           end   /*j*/

exit /*stick a fork in it, we're all done. */ /*────────────────────────────────────────────────────────────────────────────*/ URLdecode: procedure; parse arg yyy /*get encoded URL from argument list. */ yyy=translate(yyy,,'+') /*a special case for an encoded blank. */ URL=

               do  until yyy=
               parse var yyy plain '%' +1 code +2 yyy
               URL=URL || plain
               if datatype(code,'X') then URL=URL || x2c(code)
                                     else URL=URL'%'code
               end   /*until*/

return URL</lang> output is identical to version 1.

Ruby

Use any one of CGI.unescape or URI.decode_www_form_component. These methods also convert "+" to " ".

<lang ruby>require 'cgi' puts CGI.unescape("http%3A%2F%2Ffoo%20bar%2F")

  1. => "http://foo bar/"</lang>
Works with: Ruby version 1.9.2

<lang ruby>require 'uri' puts URI.decode_www_form_component("http%3A%2F%2Ffoo%20bar%2F")

  1. => "http://foo bar/"</lang>

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

Scala

Library: Scala

<lang scala>import java.net.{URLDecoder, URLEncoder}

import scala.compat.Platform.currentTime

object UrlCoded extends App {

 val original = """http://foo bar/"""
 val encoded: String = URLEncoder.encode(original, "UTF-8")
 assert(encoded == "http%3A%2F%2Ffoo+bar%2F", s"Original: $original not properly encoded: $encoded")
 val percentEncoding = encoded.replace("+", "%20")
 assert(percentEncoding == "http%3A%2F%2Ffoo%20bar%2F", s"Original: $original not properly percent-encoded: $percentEncoding")
 assert(URLDecoder.decode(encoded, "UTF-8") == URLDecoder.decode(percentEncoding, "UTF-8"))
 println(s"Successfully completed without errors. [total ${currentTime - executionStart} ms]")

}</lang>

Seed7

The library encoding.s7i defines functions to handle URL respectively percent encoding. The function fromPercentEncoded decodes a percend-encoded string. The function fromUrlEncoded works like fromPercentEncoded and additionally decodes '+' with a space. Both functions return byte sequences. To decode Unicode characters it is necessary to convert them from UTF-8 with utf8ToStri afterwards. <lang seed7>$ include "seed7_05.s7i";

 include "encoding.s7i";

const proc: main is func

 begin
   writeln(fromPercentEncoded("http%3A%2F%2Ffoo%20bar%2F"));
   writeln(fromUrlEncoded("http%3A%2F%2Ffoo+bar%2F"));
 end func;</lang>
Output:
http://foo bar/
http://foo bar/

Sidef

Translation of: Perl

<lang ruby>func urldecode(str) {

   str.gsub!('+', ' ');
   str.gsub!(/\%([A-Fa-f0-9]{2})/, {|a| 'C'.pack(a.hex)});
   return str;

}

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

Swift

<lang swift>import Foundation

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

 println(normal)

}</lang>

Tcl

This code is careful to ensure that any untoward metacharacters in the input string still do not cause any problems. <lang tcl>proc urlDecode {str} {

   set specialMap {"[" "%5B" "]" "%5D"}
   set seqRE {%([0-9a-fA-F]{2})}
   set replacement {[format "%c" [scan "\1" "%2x"]]}
   set modStr [regsub -all $seqRE [string map $specialMap $str] $replacement]
   return [encoding convertfrom utf-8 [subst -nobackslash -novariable $modStr]]

}</lang> Demonstrating: <lang tcl>puts [urlDecode "http%3A%2F%2Ffoo%20bar%2F"]</lang>

Output:
http://foo bar/

TUSCRIPT

<lang tuscript> $$ MODE TUSCRIPT url_encoded="http%3A%2F%2Ffoo%20bar%2F" BUILD S_TABLE hex=":%><:><2<>2<%:" hex=STRINGS (url_encoded,hex), hex=SPLIT(hex) hex=DECODE (hex,hex) url_decoded=SUBSTITUTE(url_encoded,":%><2<>2<%:",0,0,hex) PRINT "encoded: ", url_encoded PRINT "decoded: ", url_decoded </lang>

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

UNIX Shell

Works with: bash
Works with: ksh

<lang bash>function urldecode {

       typeset encoded=$1 decoded= rest= c= c1= c2=
       typeset rest2= bug='rest2=${rest}'
       if [[ -z ${BASH_VERSION:-} ]]; then
               typeset -i16 hex=0; typeset -i8 oct=0
               # bug /usr/bin/sh HP-UX 11.00
               typeset _encoded='xyz%26xyz'
               rest="${_encoded#?}"
               c="${_encoded%%${rest}}"
               if (( ${#c} != 1 )); then
                       typeset qm='????????????????????????????????????????????????????????????????????????'
                       typeset bug='(( ${#rest} > 0 )) && typeset -L${#rest} rest2="${qm}" || rest2=${rest}'
               fi
       fi

rest="${encoded#?}" eval ${bug} c="${encoded%%${rest2}}" encoded="${rest}"

while [[ -n ${c} ]]; do if [[ ${c} = '%' ]]; then rest="${encoded#?}" eval ${bug} c1="${encoded%%${rest2}}" encoded="${rest}"

rest="${encoded#?}" eval ${bug} c2="${encoded%%${rest2}}" encoded="${rest}"

if [[ -z ${c1} || -z ${c2} ]]; then c="%${c1}${c2}" echo "WARNING: invalid % encoding: ${c}" >&2 elif [[ -n ${BASH_VERSION:-} ]]; then c="\\x${c1}${c2}" c=$(\echo -e "${c}") else hex="16#${c1}${c2}"; oct=hex c="\\0${oct#8\#}" c=$(print -- "${c}") fi elif [[ ${c} = '+' ]]; then c=' ' fi

decoded="${decoded}${c}"

rest="${encoded#?}" eval ${bug} c="${encoded%%${rest2}}" encoded="${rest}" done

if [[ -n ${BASH_VERSION:-} ]]; then \echo -E "${decoded}" else print -r -- "${decoded}" fi } </lang>

VBScript

<lang VBScript>Function UrlDecode(s) For i = 1 To Len(s) If Mid(s,i,1) = "%" Then UrlDecode = UrlDecode & Chr("&H" & Mid(s,i+1,2)) i = i + 2 Else UrlDecode = UrlDecode & Mid(s,i,1) End If Next End Function

url = "http%3A%2F%2Ffoo%20bar%2F" WScript.Echo "Encoded URL: " & url & vbCrLf &_ "Decoded URL: " & UrlDecode(url)</lang>

Output:
Encoded URL: http%3A%2F%2Ffoo%20bar%2F
Decoded URL: http://foo bar/

XPL0

<lang XPL0>code Text=12; string 0; \use zero-terminated strings

func Decode(S0); \Decode URL string and return its address char S0; char S1(80); \BEWARE: very temporary string space returned int C, N, I, J; [I:= 0; J:= 0; repeat C:= S0(I); I:= I+1; \get char

       if C=^% then                            \convert hex to char
               [C:= S0(I);  I:= I+1;
               if C>=^a then C:= C & ~$20;     \convert to uppercase
               N:= C - (if C<=^9 then ^0 else ^A-10);
               C:= S0(I);  I:= I+1;
               if C>=^a then C:= C & ~$20;
               C:= N*16 + C - (if C<=^9 then ^0 else ^A-10);
               ];
       S1(J):= C;  J:= J+1;                    \put char in output string

until C=0; return S1; ];

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

Output:
http://foo bar/


zkl

<lang zkl>"http%3A%2F%2Ffoo%20bar%2F".pump(String, // push each char through these fcns:

  fcn(c){ if(c=="%") return(Void.Read,2); return(Void.Skip,c) },// %-->read 2 chars else pass through
  fcn(_,b,c){ (b+c).toInt(16).toChar() })  // "%" (ignored)  "3"+"1"-->0x31-->"1"</lang>
Output:
http://foo bar/

or use libCurl: <lang zkl>var Curl=Import("zklCurl"); Curl.urlDecode("http%3A%2F%2Ffoo%20bar%2F");</lang>

Output:
http://foo bar/