diff --git a/app/assets/javascripts/discourse/components/utilities.js b/app/assets/javascripts/discourse/components/utilities.js
index a2eff614be1..f13533865c7 100644
--- a/app/assets/javascripts/discourse/components/utilities.js
+++ b/app/assets/javascripts/discourse/components/utilities.js
@@ -49,20 +49,23 @@ Discourse.Utilities = {
avatarUrl: function(username, size, template) {
if (!username) return "";
- size = Discourse.Utilities.translateSize(size);
- var rawSize = (size * (window.devicePixelRatio || 1)).toFixed();
+ var rawSize = (Discourse.Utilities.translateSize(size) * (window.devicePixelRatio || 1)).toFixed();
+
+ if (username.match(/[^A-Za-z0-9_]/)) { return ""; }
if (template) return template.replace(/\{size\}/g, rawSize);
- return Discourse.getURL("/users/") + (username.toLowerCase()) + "/avatar/" + rawSize + "?__ws=" + (encodeURIComponent(Discourse.BaseUrl || ""));
+ return Discourse.getURL("/users/") + username.toLowerCase() + "/avatar/" + rawSize + "?__ws=" + encodeURIComponent(Discourse.BaseUrl || "");
},
avatarImg: function(options) {
- var extraClasses, size, title, url;
- size = Discourse.Utilities.translateSize(options.size);
- title = options.title || "";
- extraClasses = options.extraClasses || "";
- url = Discourse.Utilities.avatarUrl(options.username, options.size, options.avatarTemplate);
- return "";
+ var size = Discourse.Utilities.translateSize(options.size);
+ var url = Discourse.Utilities.avatarUrl(options.username, options.size, options.avatarTemplate);
+
+ // We won't render an invalid url
+ if (Em.isEmpty(url)) { return ""; }
+
+ var classes = "avatar" + (options.extraClasses ? " " + options.extraClasses : "");
+ var title = (options.title) ? " title='" + Handlebars.Utils.escapeExpression(options.title || "") + "'" : "";
+ return "
";
},
tinyAvatar: function(username) {
diff --git a/app/assets/javascripts/discourse/models/composer.js b/app/assets/javascripts/discourse/models/composer.js
index be48bd408c5..8f471d9ce9c 100644
--- a/app/assets/javascripts/discourse/models/composer.js
+++ b/app/assets/javascripts/discourse/models/composer.js
@@ -469,7 +469,6 @@ Discourse.Composer = Discourse.Model.extend({
}
}
- // Save callback
var composer = this;
return Ember.Deferred.promise(function(promise) {
createdPost.save(function(result) {
diff --git a/app/assets/javascripts/discourse/views/post_view.js b/app/assets/javascripts/discourse/views/post_view.js
index 6c05a8f6d4b..961d5fad116 100644
--- a/app/assets/javascripts/discourse/views/post_view.js
+++ b/app/assets/javascripts/discourse/views/post_view.js
@@ -115,7 +115,7 @@ Discourse.PostView = Discourse.View.extend({
// If it's the same topic as ours, build the URL from the topic object
if (topic && topic.get('id') === topicId) {
- navLink = "";
+ navLink = "";
} else {
// Made up slug should be replaced with canonical URL
navLink = "";
@@ -123,7 +123,7 @@ Discourse.PostView = Discourse.View.extend({
} else if (topic = this.get('controller.content')) {
// assume the same topic
- navLink = "";
+ navLink = "";
}
}
// Only add the expand/contract control if it's not a full post
diff --git a/test/javascripts/components/utilities_test.js b/test/javascripts/components/utilities_test.js
index a7c3b1afbd7..20b4b1f2a0f 100644
--- a/test/javascripts/components/utilities_test.js
+++ b/test/javascripts/components/utilities_test.js
@@ -110,3 +110,35 @@ test("isAnImage", function() {
ok(!utils.isAnImage("http://foo.bar/path/to/file.txt"));
ok(!utils.isAnImage(""));
});
+
+test("avatarUrl", function() {
+ blank(Discourse.Utilities.avatarUrl('', 'tiny'), "no avatar url returns blank");
+ blank(Discourse.Utilities.avatarUrl('this is not a username', 'tiny'), "invalid username returns blank");
+
+ equal(Discourse.Utilities.avatarUrl('eviltrout', 'tiny'), "/users/eviltrout/avatar/20?__ws=", "simple avatar url");
+ equal(Discourse.Utilities.avatarUrl('eviltrout', 'large'), "/users/eviltrout/avatar/45?__ws=", "different size");
+ equal(Discourse.Utilities.avatarUrl('EvilTrout', 'tiny'), "/users/eviltrout/avatar/20?__ws=", "lowercases username");
+ equal(Discourse.Utilities.avatarUrl('eviltrout', 'tiny', 'test{size}'), "test20", "replaces the size in a template");
+});
+
+test("avatarUrl with a baseUrl", function() {
+ Discourse.BaseUrl = "http://try.discourse.org";
+ equal(Discourse.Utilities.avatarUrl('eviltrout', 'tiny'), "/users/eviltrout/avatar/20?__ws=http%3A%2F%2Ftry.discourse.org", "simple avatar url");
+});
+
+test("avatarImg", function() {
+ equal(Discourse.Utilities.avatarImg({username: 'eviltrout', size: 'tiny'}),
+ "
",
+ "it returns the avatar html");
+
+ equal(Discourse.Utilities.avatarImg({username: 'eviltrout', size: 'tiny', title: 'evilest trout'}),
+ "
",
+ "it adds a title if supplied");
+
+ equal(Discourse.Utilities.avatarImg({username: 'eviltrout', size: 'tiny', extraClasses: 'evil fish'}),
+ "
",
+ "it adds extra classes if supplied");
+
+ blank(Discourse.Utilities.avatarImg({username: 'weird*username', size: 'tiny'}),
+ "it doesn't render avatars for invalid usernames");
+});
\ No newline at end of file
diff --git a/test/javascripts/test_helper.js b/test/javascripts/test_helper.js
index 075110661e3..376d89d7feb 100644
--- a/test/javascripts/test_helper.js
+++ b/test/javascripts/test_helper.js
@@ -81,5 +81,6 @@ QUnit.testStart(function() {
// Allow our tests to change site settings and have them reset before the next test
Discourse.SiteSettings = jQuery.extend(true, {}, Discourse.SiteSettingsOriginal);
Discourse.BaseUri = "/";
+ Discourse.BaseUrl = "";
})