From dc16742a2f42b5e1cf6ea18bdee566fa13ef2c80 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 4 Sep 2022 03:20:47 +0300 Subject: [PATCH] added filename encoding... Signed-off-by: Alex A. Naanou --- pwiki/store/file.js | 61 ++++++++++++++++++++++++++++++--------------- pwiki2.js | 38 ++++++++++++++++------------ 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/pwiki/store/file.js b/pwiki/store/file.js index 6bf9c15..285b456 100755 --- a/pwiki/store/file.js +++ b/pwiki/store/file.js @@ -15,12 +15,10 @@ var object = require('ig-object') var types = require('ig-types') var pwpath = require('../path') - var base = require('./base') - //--------------------------------------------------------------------- // @@ -40,6 +38,7 @@ var FILESTORE_OPTIONS = { verbose: true, } + var getOpts = function(opts){ return { @@ -47,6 +46,22 @@ function(opts){ ...(opts ?? {}), } } + +var encode = +module.encode = +function(str){ + return str.replace(/[^\w .\\\/_\-]/gi, + function(c){ + return `%${c + .charCodeAt(0) + .toString(16) + .toUpperCase()}` }) } +var decode = +module.decode = +function(str){ + return decodeURIComponent(str) } + + // func(base[, options]) // -> true/false // @@ -65,9 +80,10 @@ async function(base, sub, options){ base = null } var {index} = getOpts(options) - var target = base ? - pwpath.join(base, sub) - : sub + var target = encode( + base ? + pwpath.join(base, sub) + : sub) if(!fs.existsSync(target)){ return false } var stat = await fs.promises.stat(target) @@ -83,9 +99,10 @@ async function(base, sub, options){ base = null } var {index} = getOpts(options) - var target = base ? - pwpath.join(base, sub) - : sub + var target = encode( + base ? + pwpath.join(base, sub) + : sub) if(!fs.existsSync(target)){ return undefined } // handle dir text... @@ -109,9 +126,10 @@ async function(base, sub, options){ var levels = pwpath.split(sub) for(var level of levels){ - base = base == null ? - level - : pwpath.join(base, level) + base = encode( + base == null ? + level + : pwpath.join(base, level)) // nothing exists -- create dir and continue... if(!fs.existsSync(base)){ verbose @@ -140,9 +158,10 @@ async function(base, sub, data, options){ base = null } var {index} = getOpts(options) - var target = base ? - pwpath.join(base, sub) - : sub + var target = encode( + base ? + pwpath.join(base, sub) + : sub) // path already exists... if(fs.existsSync(target)){ var stat = await fs.promises.stat(target) @@ -176,9 +195,10 @@ async function(base, sub, options){ var {index} = getOpts(options) // remove leaf... - var target = base == '' ? - sub - : pwpath.join(base, sub) + var target = encode( + base == '' ? + sub + : pwpath.join(base, sub)) // dir... if(fs.existsSync(target)){ var stat = await fs.promises.stat(target) @@ -198,8 +218,9 @@ async function(base, sub, options){ } else { await fs.promises.rm(target) } } // cleanup path -- remove empty dirs... (XXX ???) - var levels = pwpath.split(sub) + var levels = pwpath.split(encode(sub)) .slice(0, -1) + base = encode(base) while(levels.length > 0){ var cur = pwpath.join(base, ...levels) if(fs.existsSync(cur)){ @@ -216,7 +237,7 @@ module.cleanup = async function(base, options){ var {index, clearEmptyDir, dirToFile, verbose} = getOpts(options) - glob(pwpath.join(base, '**/*')) + glob(pwpath.join(encode(base), '**/*')) .on('end', async function(paths){ paths .sort(function(a, b){ @@ -548,7 +569,7 @@ module.FileStoreRO = { Promise.all(paths .map(async function(path){ return await module.exists(path) ? - path + decode(path) .slice(that.__path__.length) : [] })) .then(function(paths){ diff --git a/pwiki2.js b/pwiki2.js index 8056f11..7f178e3 100755 --- a/pwiki2.js +++ b/pwiki2.js @@ -1,17 +1,6 @@ /********************************************************************** * * -* XXX might be fun to push the async parts of the render to the dom... -* ...i.e. return a partially rendered DOM with handlers to fill -* in the blanks wen they are ready... -* XXX UI/UX: add a cached/sync page.preview with ready events... -* XXX Q: empty title??? -* - special default name -* a timestamp or some thing similar -* this can be hidden until changed by user -* XXX FILE prevent paths from using reserved chars like: ":", "#", ... -* XXX do we need something like /System/Actions/.. for fast actions called -* in the same way as direct page actions??? * XXX FEATURE tags and accompanying API... * - add tags to page -- macro/filter * - .text -> .tags (cached on .update(..)) @@ -27,14 +16,34 @@ * - path integration... * i.e. a way to pass tags through path... * /some/path:tags=a,b,c +* XXX might be fun to push the async parts of the render to the dom... +* ...i.e. return a partially rendered DOM with handlers to fill +* in the blanks wen they are ready... +* something like: +* place placeholder element +* -> on visible / close to visible +* -> trigger load (set id) +* -> on load +* -> fill content (on id) +* example: +* @include(./path ..) +* -> +* XXX FILE prevent paths from using reserved chars like: ":", "#", ... +* XXX OPTIMIZE CACHE match pattern paths -- to catch page creation... +* 1) explicit subpath matching -- same as .match(..) +* 2) identify recursive patterns -- same as ** +* XXX Q: empty title??? +* - special default name +* a timestamp or some thing similar +* this can be hidden until changed by user +* XXX do we need something like /System/Actions/.. for fast actions called +* in the same way as direct page actions??? * XXX FEATURE list macro paging... * ...should this be macro level or handled in .each() * what mode? * - count + block-offset (preferred) * - count + elem-offset * - from + to -* XXX TITLE revise how title is handled... -* ...do we need a separate title and path??? * XXX fs: handle odd file names... * - we need '*' and '**' * - would be nice to be able to name files without @@ -81,9 +90,6 @@ * e.g. when searching for xxx/tree the only "tree" available is * System/tree, and if it is overloaded it's now a question of * picking one out of two and not out of tens generated by .paths() -* XXX OPTIMIZE CACHE match pattern paths -- to catch page creation... -* 1) explicit subpath matching -- same as .match(..) -* 2) identify recursive patterns -- same as ** * XXX OPTIMIZE CACHE track store changes... * XXX OPTIMIZE CACHE/DEPENDS might be a good idea to add a dependencyUpdated event... * ...and use it for cache invalidation...