client: escape periods in tag names

Merges PR #390
This commit is contained in:
Shyam Sunder 2021-04-22 13:43:21 -04:00
commit ca77149597
10 changed files with 14 additions and 13 deletions

View file

@ -92,7 +92,7 @@
--></a><!-- --></a><!--
--><% } %><!-- --><% } %><!--
--><% if (ctx.canListPosts) { %><!-- --><% if (ctx.canListPosts) { %><!--
--><a href='<%- ctx.formatClientLink('posts', {query: ctx.escapeColons(tag.names[0])}) %>' class='<%= ctx.makeCssName(tag.category, 'tag') %>'><!-- --><a href='<%- ctx.formatClientLink('posts', {query: ctx.escapeTagName(tag.names[0])}) %>' class='<%= ctx.makeCssName(tag.category, 'tag') %>'><!--
--><% } %><!-- --><% } %><!--
--><%- ctx.getPrettyName(tag.names[0]) %>&#32;<!-- --><%- ctx.getPrettyName(tag.names[0]) %>&#32;<!--
--><% if (ctx.canListPosts) { %><!-- --><% if (ctx.canListPosts) { %><!--

View file

@ -1,6 +1,6 @@
<div class='tag-delete'> <div class='tag-delete'>
<form> <form>
<p>This tag has <a href='<%- ctx.formatClientLink('posts', {query: ctx.escapeColons(ctx.tag.names[0])}) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p> <p>This tag has <a href='<%- ctx.formatClientLink('posts', {query: ctx.escapeTagName(ctx.tag.names[0])}) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p>
<ul class='input'> <ul class='input'>
<li> <li>

View file

@ -36,6 +36,6 @@
<section class='description'> <section class='description'>
<hr/> <hr/>
<%= ctx.makeMarkdown(ctx.tag.description || 'This tag has no description yet.') %> <%= ctx.makeMarkdown(ctx.tag.description || 'This tag has no description yet.') %>
<p>This tag has <a href='<%- ctx.formatClientLink('posts', {query: ctx.escapeColons(ctx.tag.names[0])}) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p> <p>This tag has <a href='<%- ctx.formatClientLink('posts', {query: ctx.escapeTagName(ctx.tag.names[0])}) %>'><%- ctx.tag.postCount %> usage(s)</a>.</p>
</section> </section>
</div> </div>

View file

@ -52,7 +52,7 @@ class PoolController {
canMerge: api.hasPrivilege("pools:merge"), canMerge: api.hasPrivilege("pools:merge"),
canDelete: api.hasPrivilege("pools:delete"), canDelete: api.hasPrivilege("pools:delete"),
categories: categories, categories: categories,
escapeColons: uri.escapeColons, escapeTagName: uri.escapeTagName,
}); });
this._view.addEventListener("change", (e) => this._view.addEventListener("change", (e) =>

View file

@ -26,7 +26,7 @@ class PoolCreateController {
this._view = new PoolCreateView({ this._view = new PoolCreateView({
canCreate: api.hasPrivilege("pools:create"), canCreate: api.hasPrivilege("pools:create"),
categories: categories, categories: categories,
escapeColons: uri.escapeColons, escapeTagName: uri.escapeTagName,
}); });
this._view.addEventListener("submit", (e) => this._view.addEventListener("submit", (e) =>

View file

@ -56,7 +56,7 @@ class TagController {
canMerge: api.hasPrivilege("tags:merge"), canMerge: api.hasPrivilege("tags:merge"),
canDelete: api.hasPrivilege("tags:delete"), canDelete: api.hasPrivilege("tags:delete"),
categories: categories, categories: categories,
escapeColons: uri.escapeColons, escapeTagName: uri.escapeTagName,
}); });
this._view.addEventListener("change", (e) => this._view.addEventListener("change", (e) =>

View file

@ -28,7 +28,7 @@ class PostReadonlySidebarControl extends events.EventTarget {
canListPosts: api.hasPrivilege("posts:list"), canListPosts: api.hasPrivilege("posts:list"),
canEditPosts: api.hasPrivilege("posts:edit"), canEditPosts: api.hasPrivilege("posts:edit"),
canViewTags: api.hasPrivilege("tags:view"), canViewTags: api.hasPrivilege("tags:view"),
escapeColons: uri.escapeColons, escapeTagName: uri.escapeTagName,
extractRootDomain: uri.extractRootDomain, extractRootDomain: uri.extractRootDomain,
getPrettyName: misc.getPrettyName, getPrettyName: misc.getPrettyName,
}) })

View file

@ -163,7 +163,8 @@ class TagInputControl extends events.EventTarget {
addTagByName(name, source) { addTagByName(name, source) {
name = name.trim(); name = name.trim();
if (!name) { // Tags `.` and `..` are not allowed, see https://github.com/rr-/szurubooru/pull/390
if (!name || name == "." || name == "..") {
return; return;
} }
return Tag.get(name).then( return Tag.get(name).then(
@ -305,7 +306,7 @@ class TagInputControl extends events.EventTarget {
searchLinkNode.setAttribute( searchLinkNode.setAttribute(
"href", "href",
uri.formatClientLink("posts", { uri.formatClientLink("posts", {
query: uri.escapeColons(tag.names[0]), query: uri.escapeTagName(tag.names[0]),
}) })
); );
searchLinkNode.textContent = tag.names[0] + " "; searchLinkNode.textContent = tag.names[0] + " ";

View file

@ -187,7 +187,7 @@ function arraysDiffer(source1, source2, orderImportant) {
} }
function escapeSearchTerm(text) { function escapeSearchTerm(text) {
return text.replace(/([a-z_-]):/g, "$1\\:"); return text.replace(/([a-z_-]):/g, "$1\\:").replace(/\./g, "\\.");
} }
function dataURItoBlob(dataURI) { function dataURItoBlob(dataURI) {

View file

@ -85,14 +85,14 @@ function extractRootDomain(url) {
return domain; return domain;
} }
function escapeColons(text) { function escapeTagName(text) {
return text.replace(new RegExp(":", "g"), "\\:"); return text.replace(/:/g, "\\:").replace(/\./g, "\\.");
} }
module.exports = { module.exports = {
formatClientLink: formatClientLink, formatClientLink: formatClientLink,
formatApiLink: formatApiLink, formatApiLink: formatApiLink,
escapeColons: escapeColons, escapeTagName: escapeTagName,
escapeParam: escapeParam, escapeParam: escapeParam,
unescapeParam: unescapeParam, unescapeParam: unescapeParam,
extractHostname: extractHostname, extractHostname: extractHostname,