diff --git a/API/Backend/Draw/routes/files.js b/API/Backend/Draw/routes/files.js index 426abdd4..1e185e3a 100644 --- a/API/Backend/Draw/routes/files.js +++ b/API/Backend/Draw/routes/files.js @@ -517,19 +517,19 @@ router.post("/change", function (req, res, next) { router.post("/modifykeyword", function (req, res, next) { let Table = req.body.test === "true" ? UserfilesTEST : Userfiles; - const keyword = req.body.keyword; + let keyword = req.body.keyword; const type = req.body.type; const newKeyword = req.body.newKeyword; let symbol = null; switch (type.toLowerCase()) { case "tags": - symbol = "#"; + symbol = "~#"; break; case "folders": - symbol = "@"; + symbol = "~@"; break; case "efolders": - symbol = "^"; + symbol = "~^"; break; default: break; @@ -538,12 +538,16 @@ router.post("/modifykeyword", function (req, res, next) { if ( symbol == null || keyword == null || - keyword.match(/^[a-z0-9_]+$/i) == null || - (newKeyword != null && newKeyword.match(/^[a-z0-9_]+$/i) == null) + (keyword != null && + (keyword.indexOf(" ") > -1 || keyword.indexOf("~") > -1)) || + (newKeyword != null && + (newKeyword.indexOf(" ") > -1 || + newKeyword.indexOf("~") > -1 || + newKeyword.indexOf("$") > -1)) ) { res.send({ status: "failure", - message: `Bad Input. Either: no 'keyword', no 'type', 'keyword' or 'newKeyword' contains non-alphanumerics.`, + message: `Bad Input. Either: no 'keyword', no 'type', 'keyword' or 'newKeyword' contains spaces, dollar-signs, tildes.`, body: {}, }); return; @@ -564,7 +568,14 @@ router.post("/modifykeyword", function (req, res, next) { }, { where: { - file_description: { [Sequelize.Op.iRegexp]: `[${existing}]` }, + file_description: { + // Escape special chars so that regex works + [Sequelize.Op.like]: sequelize.literal( + `'%${existing + .replaceAll("%", "$%") + .replaceAll("_", "$_")}%' ESCAPE '$'` + ), + }, }, } ) diff --git a/src/essence/Tools/Draw/DrawTool.js b/src/essence/Tools/Draw/DrawTool.js index 9106c818..51440a46 100644 --- a/src/essence/Tools/Draw/DrawTool.js +++ b/src/essence/Tools/Draw/DrawTool.js @@ -925,17 +925,17 @@ var DrawTool = { } if (typeof file_description !== 'string') return [] - const tags = file_description.match(/~#\w+/g) || [] + const tags = file_description.match(/~#([^\s])+/g) || [] const uniqueTags = [...tags] // remove '#'s tagFolders.tags = uniqueTags.map((t) => t.substring(2)) || [] - const folders = file_description.match(/~@\w+/g) || [] + const folders = file_description.match(/~@([^\s])+/g) || [] const uniqueFolders = [...folders] // remove '@'s tagFolders.folders = uniqueFolders.map((t) => t.substring(2)) || [] - const efolders = file_description.match(/~\^\w+/g) || [] + const efolders = file_description.match(/~\^([^\s])+/g) || [] const uniqueEFolders = [...efolders] // remove '^'s tagFolders.efolders = uniqueEFolders.map((t) => t.substring(2)) || [] @@ -975,15 +975,14 @@ var DrawTool = { .concat(tagFolders.folders) .concat(tagFolders.efolders) } - return tagFolders }, stripTagsFromDescription(file_description) { if (typeof file_description !== 'string') return '' return file_description - .replaceAll(/~#\w+/g, '') - .replaceAll(/~@\w+/g, '') - .replaceAll(/~\^\w+/g, '') + .replaceAll(/~#([^\s])+/g, '') + .replaceAll(/~@([^\s])+/g, '') + .replaceAll(/~\^([^\s])+/g, '') .trimStart() .trimEnd() }, @@ -1015,6 +1014,8 @@ var DrawTool = { // Add tags and folders for (let i = 0; i < DrawTool.files.length; i++) { + DrawTool.files[i].file_description = + DrawTool.files[i].file_description || '' DrawTool.files[i]._tagFolders = DrawTool.getTagsFoldersFromFileDescription( DrawTool.files[i] diff --git a/src/essence/Tools/Draw/DrawTool_Files.js b/src/essence/Tools/Draw/DrawTool_Files.js index 845f5630..240d241f 100644 --- a/src/essence/Tools/Draw/DrawTool_Files.js +++ b/src/essence/Tools/Draw/DrawTool_Files.js @@ -41,6 +41,7 @@ var Files = { 'type' ) const filesInGroupOrder = JSON.parse(JSON.stringify(DrawTool.files)) + if (groupingType != 'none') { filesInGroupOrder.sort((a, b) => { if ( @@ -414,22 +415,23 @@ var Files = { } else { if (file._tagFolders[groupingType]) { file._tagFolders[groupingType].forEach((g) => { + const gEnc = encodeURIComponent(g) + const group = d3.select( - `#drawToolDrawFilesList > .drawToolDrawFilesGroupElem[group_name="${g}"]` + `#drawToolDrawFilesList > .drawToolDrawFilesGroupElem[group_name="${gEnc}"]` ) let iconClass = Files.getGroupingIcons(groupingType).closed - if (group.size() === 0) { // prettier-ignore d3.select('#drawToolDrawFilesList') .append('div') .attr('class', `drawToolDrawFilesGroupElem`) - .attr('group_name', g) + .attr('group_name', gEnc) .html( [ - `
`, + `
`, `
`, `
`, `
${groupingType === 'alphabetical' ? g.substring(1) : g}
`, @@ -442,11 +444,11 @@ var Files = { } if ( $( - `.drawToolDrawFilesGroupElem[group_name="${g}"] .drawToolDrawFilesGroupListElem > .drawToolDrawFilesListElem[file_id="${file.id}"]` + `.drawToolDrawFilesGroupElem[group_name="${gEnc}"] .drawToolDrawFilesGroupListElem > .drawToolDrawFilesListElem[file_id="${file.id}"]` ).length === 0 ) { d3.select( - `.drawToolDrawFilesGroupElem[group_name="${g}"] .drawToolDrawFilesGroupListElem` + `.drawToolDrawFilesGroupElem[group_name="${gEnc}"] .drawToolDrawFilesGroupListElem` ) .append('li') .attr( @@ -515,7 +517,9 @@ var Files = { if (Files.currentOpenFolderName != null) $( - `.drawToolDrawFilesGroupElemHead[group_name=${Files.currentOpenFolderName}]` + `.drawToolDrawFilesGroupElemHead[group_name="${decodeURIComponent( + Files.currentOpenFolderName + )}"]` ).trigger('click') //Li Elem Context Menu @@ -528,23 +532,25 @@ var Files = { e.preventDefault() let elm = $(this) const isPub = elm.attr('id') === 'drawToolDrawPublished' - const activeTagFolType = $( + let activeTagFolType = $( '#drawToolDrawGroupingDiv > div.active' ).attr('type') const isHead = elm.hasClass('drawToolDrawFilesGroupElemHead') - const headGroup = elm.attr('group_name') + if (isHead) activeTagFolType = elm.attr('groupingtype') + const headGroup = decodeURIComponent(elm.attr('group_name')) const isLead = DrawTool.userGroups.indexOf('mmgis-group') != -1 + const leadIsEdit = isLead && DrawTool.vars.leadsCanEditFileInfo === true if ( isHead && - (!( + !( activeTagFolType === 'tags' || activeTagFolType === 'folders' - ) || - !leadIsEdit) + ) && + !leadIsEdit ) return @@ -1271,11 +1277,15 @@ var Files = { if (newTag.length === 0) return // not alphanumeric - if (newTag.match(/^[a-z0-9_]+$/i) == null) { + if ( + newTag.indexOf(' ') > -1 || + newTag.indexOf('~') > -1 || + newTag.indexOf('$') > -1 + ) { CursorInfo.update( `${ type === 'tag' ? 'Tags' : 'Folders' - } may only contain alphanumerics and underscores!`, + } may not contain spaces, dollar-signs or tildes!`, 3500, true, { @@ -1421,7 +1431,6 @@ var Files = { if (!description.replace(/\s/g, '').length) { description = '' } - var body = { id: fileid, file_name: filename,