mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 08:36:12 +01:00
fix: tag urls getting double escaped (#13306)
* fix: tag urls getting double escaped get rid of weird decodeURIComponent($.param()) usage $.param returns a string suitable for use in query param string * add a new test
This commit is contained in:
committed by
GitHub
parent
bf243e0778
commit
3526c937cc
@@ -620,7 +620,7 @@ define('admin/manage/users', [
|
||||
params.query = query.query;
|
||||
params.page = query.page;
|
||||
params.sortBy = params.sortBy || 'lastonline';
|
||||
const qs = decodeURIComponent($.param(params));
|
||||
const qs = $.param(params);
|
||||
$.get(config.relative_path + '/api/admin/manage/users?' + qs, function (data) {
|
||||
renderSearchResults(data);
|
||||
const url = config.relative_path + '/admin/manage/users?' + qs;
|
||||
@@ -673,7 +673,7 @@ define('admin/manage/users', [
|
||||
delete params.searchBy;
|
||||
}
|
||||
|
||||
return decodeURIComponent($.param(params));
|
||||
return $.param(params);
|
||||
}
|
||||
|
||||
function handleSort() {
|
||||
|
||||
@@ -59,7 +59,7 @@ define('forum/login', ['hooks', 'translator', 'jquery-form'], function (hooks, t
|
||||
const params = utils.params({ url: data.next });
|
||||
params.loggedin = true;
|
||||
delete params.register; // clear register message incase it exists
|
||||
const qs = decodeURIComponent($.param(params));
|
||||
const qs = $.param(params);
|
||||
|
||||
window.location.href = pathname + '?' + qs;
|
||||
},
|
||||
|
||||
@@ -85,7 +85,7 @@ define('forum/register', [
|
||||
|
||||
const params = utils.params({ url: data.next });
|
||||
params.registered = true;
|
||||
const qs = decodeURIComponent($.param(params));
|
||||
const qs = $.param(params);
|
||||
|
||||
window.location.href = pathname + '?' + qs;
|
||||
} else if (data.message) {
|
||||
|
||||
@@ -72,12 +72,12 @@ define('forum/search', [
|
||||
let labelText = '[[search:tags]]';
|
||||
if (selectedTags.length) {
|
||||
labelText = translator.compile(
|
||||
'search:tags-x', selectedTags.map(u => u.valueEscaped).join(', ')
|
||||
'search:tags-x', selectedTags.map(u => u.value).join(', ')
|
||||
);
|
||||
}
|
||||
$('[component="tag/filter/button"]').toggleClass(
|
||||
'active-filter', isActive
|
||||
).find('.filter-label').translateText(labelText);
|
||||
).find('.filter-label').translateHtml(labelText);
|
||||
}
|
||||
|
||||
function updateTimeFilter() {
|
||||
@@ -326,7 +326,7 @@ define('forum/search', [
|
||||
return {
|
||||
value: value,
|
||||
valueEscaped: escapedTag,
|
||||
valueEncoded: encodeURIComponent(escapedTag),
|
||||
valueEncoded: encodeURIComponent(value),
|
||||
class: escapedTag.replace(/\s/g, '-'),
|
||||
};
|
||||
}
|
||||
@@ -353,7 +353,7 @@ define('forum/search', [
|
||||
result.tags = result.tags.slice(0, 20);
|
||||
const tagMap = {};
|
||||
result.tags.forEach((tag) => {
|
||||
tagMap[tag.valueEscaped] = tag;
|
||||
tagMap[tag.value] = tag;
|
||||
});
|
||||
|
||||
const html = await app.parseAndTranslate('partials/search-filters', 'tagFilterResults', {
|
||||
@@ -374,7 +374,7 @@ define('forum/search', [
|
||||
|
||||
el.on('click', '[component="tag/filter/delete"]', function () {
|
||||
const deleteTag = $(this).attr('data-tag');
|
||||
selectedTags = selectedTags.filter(tag => tag.valueEscaped !== deleteTag);
|
||||
selectedTags = selectedTags.filter(tag => tag.value !== deleteTag);
|
||||
renderSelectedTags();
|
||||
});
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ define('categoryFilter', ['categorySearch', 'api', 'hooks'], function (categoryS
|
||||
|
||||
delete currentParams.page;
|
||||
if (Object.keys(currentParams).length) {
|
||||
url += '?' + decodeURIComponent($.param(currentParams));
|
||||
url += '?' + $.param(currentParams);
|
||||
}
|
||||
ajaxify.go(url);
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ define('search', [
|
||||
data: data,
|
||||
});
|
||||
|
||||
return decodeURIComponent($.param(query));
|
||||
return $.param(query);
|
||||
}
|
||||
|
||||
Search.getSearchPreferences = function () {
|
||||
|
||||
@@ -17,7 +17,7 @@ define('sort', ['components'], function (components) {
|
||||
const newSetting = $(this).attr('data-sort');
|
||||
const urlParams = utils.params();
|
||||
urlParams.sort = newSetting;
|
||||
const qs = decodeURIComponent($.param(urlParams));
|
||||
const qs = $.param(urlParams);
|
||||
ajaxify.go(gotoOnSave + (qs ? '?' + qs : ''));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -98,7 +98,7 @@ define('tagFilter', ['hooks', 'alerts', 'bootstrap'], function (hooks, alerts, b
|
||||
}
|
||||
delete currentParams.page;
|
||||
if (Object.keys(currentParams).length) {
|
||||
url += '?' + decodeURIComponent($.param(currentParams));
|
||||
url += '?' + $.param(currentParams);
|
||||
}
|
||||
ajaxify.go(url);
|
||||
}
|
||||
@@ -159,7 +159,7 @@ define('tagFilter', ['hooks', 'alerts', 'bootstrap'], function (hooks, alerts, b
|
||||
function renderList(tags) {
|
||||
const selectedTags = options.selectedTags;
|
||||
tags.forEach(function (tag) {
|
||||
tag.selected = selectedTags.includes(tag.valueEscaped);
|
||||
tag.selected = selectedTags.includes(tag.value);
|
||||
});
|
||||
|
||||
app.parseAndTranslate(options.template, {
|
||||
|
||||
@@ -6,7 +6,7 @@ window.overrides = window.overrides || {};
|
||||
|
||||
function translate(elements, type, str) {
|
||||
return elements.each(function () {
|
||||
var el = $(this);
|
||||
const el = $(this);
|
||||
translator.translate(str, function (translated) {
|
||||
el[type](translated);
|
||||
});
|
||||
|
||||
@@ -362,11 +362,11 @@ helpers.getSelectedTag = function (tags) {
|
||||
tags = [tags];
|
||||
}
|
||||
tags = tags || [];
|
||||
const tagData = tags.map(t => validator.escape(String(t)));
|
||||
const tagData = tags.map(t => String(t));
|
||||
let selectedTag = null;
|
||||
if (tagData.length) {
|
||||
selectedTag = {
|
||||
label: tagData.join(', '),
|
||||
label: validator.escape(tagData.join(', ')),
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -41,8 +41,8 @@ tagsController.getTag = async function (req, res) {
|
||||
const stop = start + settings.topicsPerPage - 1;
|
||||
|
||||
const [topicCount, tids] = await Promise.all([
|
||||
topics.getTagTopicCount(tag, cids),
|
||||
topics.getTagTidsByCids(tag, cids, start, stop),
|
||||
topics.getTagTopicCount(req.params.tag, cids),
|
||||
topics.getTagTidsByCids(req.params.tag, cids, start, stop),
|
||||
]);
|
||||
|
||||
templateData.topics = await topics.getTopics(tids, req.uid);
|
||||
|
||||
@@ -134,7 +134,7 @@ function modifyTopic(topic, fields) {
|
||||
return {
|
||||
value: tag,
|
||||
valueEscaped: escaped,
|
||||
valueEncoded: encodeURIComponent(escaped),
|
||||
valueEncoded: encodeURIComponent(tag),
|
||||
class: escaped.replace(/\s/g, '-'),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -323,7 +323,7 @@ module.exports = function (Topics) {
|
||||
}
|
||||
tags.forEach((tag) => {
|
||||
tag.valueEscaped = validator.escape(String(tag.value));
|
||||
tag.valueEncoded = encodeURIComponent(tag.valueEscaped);
|
||||
tag.valueEncoded = encodeURIComponent(tag.value);
|
||||
tag.class = tag.valueEscaped.replace(/\s/g, '-');
|
||||
});
|
||||
return tags;
|
||||
|
||||
@@ -1432,6 +1432,7 @@ describe('Topic\'s', () => {
|
||||
before(async () => {
|
||||
await topics.post({ uid: adminUid, tags: ['php', 'nosql', 'psql', 'nodebb', 'node icon'], title: 'topic title 1', content: 'topic 1 content', cid: topic.categoryId });
|
||||
await topics.post({ uid: adminUid, tags: ['javascript', 'mysql', 'python', 'nodejs'], title: 'topic title 2', content: 'topic 2 content', cid: topic.categoryId });
|
||||
await topics.post({ uid: adminUid, tags: ['signal & slot', 'node & c++'], title: 'topic title 3', content: 'topic 3 content', cid: topic.categoryId });
|
||||
});
|
||||
|
||||
it('should return empty array if query is falsy', (done) => {
|
||||
@@ -1483,10 +1484,11 @@ describe('Topic\'s', () => {
|
||||
it('should search and load tags', (done) => {
|
||||
socketTopics.searchAndLoadTags({ uid: adminUid }, { query: 'no' }, (err, data) => {
|
||||
assert.ifError(err);
|
||||
assert.equal(data.matchCount, 4);
|
||||
assert.equal(data.matchCount, 5);
|
||||
assert.equal(data.pageCount, 1);
|
||||
const tagData = [
|
||||
{ value: 'nodebb', valueEscaped: 'nodebb', valueEncoded: 'nodebb', score: 3, class: 'nodebb' },
|
||||
{ value: 'node & c++', valueEscaped: 'node & c++', valueEncoded: 'node%20%26%20c%2B%2B', score: 1, class: 'node-&-c++' },
|
||||
{ value: 'node icon', valueEscaped: 'node icon', valueEncoded: 'node%20icon', score: 1, class: 'node-icon' },
|
||||
{ value: 'nodejs', valueEscaped: 'nodejs', valueEncoded: 'nodejs', score: 1, class: 'nodejs' },
|
||||
{ value: 'nosql', valueEscaped: 'nosql', valueEncoded: 'nosql', score: 1, class: 'nosql' },
|
||||
|
||||
Reference in New Issue
Block a user