From 39810e61962e6e1eb1300c1b852ebbf4f416009a Mon Sep 17 00:00:00 2001
From: Florian Staudacher <florian_staudacher@yahoo.de>
Date: Sat, 21 Sep 2013 15:23:30 +0200
Subject: [PATCH] decode URLs before processing them (fixes #4507)

---
 .../javascripts/app/helpers/text_formatter.js  |  6 ++++++
 .../app/helpers/text_formatter_spec.js         | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/app/assets/javascripts/app/helpers/text_formatter.js b/app/assets/javascripts/app/helpers/text_formatter.js
index 57c7a5d57e..3e122d87a2 100644
--- a/app/assets/javascripts/app/helpers/text_formatter.js
+++ b/app/assets/javascripts/app/helpers/text_formatter.js
@@ -43,6 +43,12 @@ $(function() {
           unicodeUrl += ')';
           urlSuffix = '>';
         }
+
+        // url*DE*code as much as possible
+        while( unicodeUrl.indexOf("%") !== -1 && unicodeUrl != decodeURI(unicodeUrl) ) {
+          unicodeUrl = decodeURI(unicodeUrl);
+        }
+
         // markdown doesn't like '(' or ')' anywhere, except where it wants
         var workingUrl = unicodeUrl.replace(/\(/, "%28").replace(/\)/, "%29");
 
diff --git a/spec/javascripts/app/helpers/text_formatter_spec.js b/spec/javascripts/app/helpers/text_formatter_spec.js
index 1a95c0c3ad..29aec511e9 100644
--- a/spec/javascripts/app/helpers/text_formatter_spec.js
+++ b/spec/javascripts/app/helpers/text_formatter_spec.js
@@ -158,6 +158,24 @@ describe("app.helpers.textFormatter", function(){
         expect(parsed).toContain(text);
       });
 
+      context("percent-encoded input url", function() {
+        beforeEach(function() {
+          this.input = "http://www.soilandhealth.org/01aglibrary/010175.tree%20crops.pdf"  // #4507
+          this.correctHref = 'href="'+this.input+'"';
+        });
+
+        it("doesn't get double-encoded", function(){
+          var parsed = this.formatter.markdownify(this.input);
+          expect(parsed).toContain(this.correctHref);
+        });
+
+        it("gets correctly decoded, even when multiply encoded", function() {
+          var uglyUrl = encodeURI(encodeURI(encodeURI(this.input)));
+          var parsed = this.formatter.markdownify(uglyUrl);
+          expect(parsed).toContain(this.correctHref);
+        });
+      });
+
       it("tests a bunch of benchmark urls", function(){
         var self = this;
         $.ajax({
-- 
GitLab