diff --git a/app/assets/javascripts/app/helpers/text_formatter.js b/app/assets/javascripts/app/helpers/text_formatter.js index 5543ed83d..fe4069911 100644 --- a/app/assets/javascripts/app/helpers/text_formatter.js +++ b/app/assets/javascripts/app/helpers/text_formatter.js @@ -36,9 +36,9 @@ (!addr.pass ? '' : ':'+addr.pass) + '@') + punycode.toASCII(addr.host) + (!addr.port ? '' : ':' + addr.port) + - (!addr.path ? '' : addr.path) + - (!addr.query ? '' : '?' + addr.query) + - (!addr.fragment ? '' : '#' + addr.fragment); + (!addr.path ? '' : encodeURI(addr.path) ) + + (!addr.query ? '' : '?' + encodeURI(addr.query) ) + + (!addr.fragment ? '' : '#' + encodeURI(addr.fragment) ); if( !arguments[1] || arguments[1] == "") { // inline link if(arguments[2] == "<") return "["+unicodeUrl+"]("+asciiUrl+")"; // without link text else return arguments[2]+asciiUrl+arguments[5]; // with link text diff --git a/spec/javascripts/app/helpers/text_formatter_spec.js b/spec/javascripts/app/helpers/text_formatter_spec.js index 9c976ac26..aa1da7e31 100644 --- a/spec/javascripts/app/helpers/text_formatter_spec.js +++ b/spec/javascripts/app/helpers/text_formatter_spec.js @@ -44,7 +44,59 @@ describe("app.helpers.textFormatter", function(){ expect(linkElement.text()).toContain(link); expect(linkElement.attr("target")).toContain("_blank"); }) - }) + }); + + context("non-ascii urls", function() { + beforeEach(function() { + this.evilUrls = [ + "http://www.bürgerentscheid-krankenhäuser.de", // example from issue #2665 + "http://bündnis-für-krankenhäuser.de/wp-content/uploads/2011/11/cropped-logohp.jpg", + "http://موقع.وزارة-الاتصالات.مصر/", // example from #3082 + "http:///scholar.google.com/citations?view_op=top_venues", + "http://lyricstranslate.com/en/someone-you-നിന്നെ-പോലൊരാള്‍.html" // example from #3063 + ]; + this.asciiUrls = [ + "http://www.xn--brgerentscheid-krankenhuser-xkc78d.de", + "http://xn--bndnis-fr-krankenhuser-i5b27cha.de/wp-content/uploads/2011/11/cropped-logohp.jpg", + "http://xn--4gbrim.xn----ymcbaaajlc6dj7bxne2c.xn--wgbh1c/", + "http:///scholar.google.com/citations?view_op=top_venues", + "http://lyricstranslate.com/en/someone-you-%E0%B4%A8%E0%B4%BF%E0%B4%A8%E0%B5%8D%E0%B4%A8%E0%B5%86-%E0%B4%AA%E0%B5%8B%E0%B4%B2%E0%B5%8A%E0%B4%B0%E0%B4%BE%E0%B4%B3%E0%B5%8D%E2%80%8D.html" + ]; + }); + + it("correctly encode to punycode", function() { + _.each(this.evilUrls, function(url, num) { + var text = this.formatter.markdownify( "<" + url + ">" ); + expect(text).toContain(this.asciiUrls[num]); + }, this); + }); + + it("don't break link texts", function() { + var linkText = "check out this awesome link!"; + var text = this.formatter.markdownify( "["+linkText+"]("+this.evilUrls[0]+")" ); + + expect(text).toContain(this.asciiUrls[0]); + expect(text).toContain(linkText); + }); + + it("don't break reference style links", function() { + var postContent = "blabla blab [my special link][1] bla blabla\n\n[1]: "+this.evilUrls[0]+" and an optional title)"; + var text = this.formatter.markdownify(postContent); + + expect(text).not.toContain(this.evilUrls[0]); + expect(text).toContain(this.asciiUrls[0]); + }); + + it("can be used as img src", function() { + var postContent = "![logo]("+ this.evilUrls[1] +")"; + var niceImg = '"'+ this.asciiUrls[1] +'"'; // the "" are from src="" + var text = this.formatter.markdownify(postContent); + + expect(text).toContain(niceImg); + }); + + }); + }) describe(".hashtagify", function(){ diff --git a/spec/javascripts/app/views/post_view_spec.js b/spec/javascripts/app/views/post_view_spec.js index c0d299df5..8f705e65a 100644 --- a/spec/javascripts/app/views/post_view_spec.js +++ b/spec/javascripts/app/views/post_view_spec.js @@ -1,80 +1,3 @@ describe("app.views.Post", function(){ - context("markdown rendering", function() { - beforeEach(function() { - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); - Diaspora.I18n.loadLocale({stream : { - reshares : { - one : "<%= count %> reshare", - other : "<%= count %> reshares" - }, - likes : { - zero : "<%= count %> Likes", - one : "<%= count %> Like", - other : "<%= count %> Likes" - } - }}) - - var posts = $.parseJSON(spec.readFixture("stream_json"))["posts"]; - - this.collection = new app.collections.Posts(posts); - this.statusMessage = this.collection.models[0]; - this.reshare = this.collection.models[1]; - - // example from issue #2665 - this.evilUrl = "http://www.bürgerentscheid-krankenhäuser.de"; - this.asciiUrl = "http://www.xn--brgerentscheid-krankenhuser-xkc78d.de"; - }); - - it("correctly handles non-ascii characters in urls", function() { - this.statusMessage.set({text: "<"+this.evilUrl+">"}); - var view = new app.views.StreamPost({model : this.statusMessage}).render(); - - expect($(view.el).html()).toContain(this.asciiUrl); - expect($(view.el).html()).toContain(this.evilUrl); - }); - - it("doesn't break link texts for non-ascii urls", function() { - var linkText = "check out this awesome link!"; - this.statusMessage.set({text: "["+linkText+"]("+this.evilUrl+")"}); - var view = new app.views.StreamPost({model: this.statusMessage}).render(); - - expect($(view.el).html()).toContain(this.asciiUrl); - expect($(view.el).html()).toContain(linkText); - }); - - it("doesn't break reference style links for non-ascii urls", function() { - var postContent = "blabla blab [my special link][1] bla blabla\n\n[1]: "+this.evilUrl+" and an optional title)"; - this.statusMessage.set({text: postContent}); - var view = new app.views.StreamPost({model: this.statusMessage}).render(); - - expect($(view.el).html()).not.toContain(this.evilUrl); - expect($(view.el).html()).toContain(this.asciiUrl); - }); - - it("correctly handles images with non-ascii urls", function() { - var postContent = "![logo](http://bündnis-für-krankenhäuser.de/wp-content/uploads/2011/11/cropped-logohp.jpg)"; - var niceImg = '"http://xn--bndnis-fr-krankenhuser-i5b27cha.de/wp-content/uploads/2011/11/cropped-logohp.jpg"'; - this.statusMessage.set({text: postContent}); - var view = new app.views.StreamPost({model: this.statusMessage}).render(); - - expect($(view.el).html()).toContain(niceImg); - }); - - it("correctly handles even more special links", function() { - var specialLink = "http://موقع.وزارة-الاتصالات.مصر/"; // example from #3082 - var normalLink = "http://xn--4gbrim.xn----ymcbaaajlc6dj7bxne2c.xn--wgbh1c/"; - this.statusMessage.set({text: specialLink }); - var view = new app.views.StreamPost({model: this.statusMessage}).render(); - - expect($(view.el).html()).toContain(specialLink); - expect($(view.el).html()).toContain(normalLink); - }); - it("works when three slashes are present in the url", function(){ - var badURL = "http:///scholar.google.com/citations?view_op=top_venues" - this.statusMessage.set({text : badURL}); - var view = new app.views.StreamPost({model: this.statusMessage}).render(); - - }) - - }); + // see: StreamPost });