-7

This is my simple extension:

extension String {
    var urlDecoded: String? {
        replacingOccurrences(of: "+", with: "%20").removingPercentEncoding
    }
}

And here is my string:

let string = "https%253A%252F%252Fplz.pl"

After I call

let firstDecoded = string.urlDecoded

// "https%3A%2F%2Fplz.pl"

let secondDecoded = string.urlDecoded?.urlDecoded

// "https://plz.pl"

Why do I have to call it twice? How can I do it correctly and quickly?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
  • Where does that string come from? Where and why has it been decoded twice? – Martin R Feb 17 '23 at 10:29
  • 2
    Related question from the question author yesterday: [Why removingPercentEncoding does not replace + like it does with %20?](https://stackoverflow.com/questions/75473592/why-removingpercentencoding-does-not-replace-like-it-does-with-20) – halfer Feb 17 '23 at 12:09
  • 1
    The answer should be obvious by *looking at the data*. Did you expect, for example, that a single call would translate `%253A` to `:`? Why? (Hint: do you know what the encoding is for `:`? Or for `%`? If you have a question about what the code for an encoder or decoder is doing, the first thing should be to make sure you *understand the encoding*.) – Karl Knechtel Feb 23 '23 at 13:01
  • A lead is that [ASCII "%"](https://en.wikipedia.org/wiki/ASCII#Printable_characters) is 0x25. – Peter Mortensen Feb 23 '23 at 15:36

2 Answers2

3

Why do you have to decode it twice? Because it's been encoded twice.

The ASCII code point for the percent symbol is 0x25. So %25 in an encoded URL encodes a percent symbol. Thus:

https%253A%252F%252Fplz.pl
     └┬┘  └┬┘  └┬┘
https % 3A % 2F % 2Fplz.pl
      └┬─┘ └┬─┘ └┬─┘
https  :    /    /  plz.pl
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
2

Because the input is encoded twice.

%253A: %25 is an encoded % meaning it results in %3A after the first decoding and : after the second decoding.

luk2302
  • 55,258
  • 23
  • 97
  • 137