cleanup + file store path sanitization...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2022-09-04 11:06:19 +03:00
parent d0a607f2b6
commit b4c319585e
5 changed files with 44 additions and 37 deletions

View File

@ -44,7 +44,6 @@ function(name){
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX PATH_VARS
// XXX FUNC need to handle functions in store...
var BasePage =
module.BasePage =
@ -88,7 +87,6 @@ object.Constructor('BasePage', {
// other places path variables can be resolved:
// - navigation (below)
// - macro expansion...
// XXX EXPERIMENTAL...
path_vars: {
NOW: function(){
return Date.timeStamp() },
@ -607,7 +605,6 @@ function(spec, func){
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX PATH_VARS need to handle path variables...
// XXX filters (and macros?) should be features for simpler plugin handlng (???)
// XXX STUB filters...
// XXX rename to pWikiPage???
@ -1552,23 +1549,6 @@ object.Constructor('CachedPage', Page, {
return getCachedProp(this, 'text') },
set text(value){
return setCachedProp(this, 'text', value) },
/*/ XXX PREVIEW EXPERIMENTAL...
// ...this can be usefull for partial rendering and then on the
// js level filling in the details...
__preview_size__: 100,
get preview(){
var text = this.text
if(text instanceof Promise){
text.then(function(text){
this.onPreviewReady() })
// return a placeholder for the upcoming data...
return '...' }
return text.slice(0, this.__preview_size__ || 100) },
onPreviewReady: types.event.Event('onPreviewReady'),
//*/
})

View File

@ -129,6 +129,22 @@ module = {
: path.join('/'))
: path },
//*/
sanitize: function(path, format='auto'){
format = format == 'auto' ?
(path instanceof Array ?
'array'
: 'string')
: format
path = this.split(path)
;(path[0] == ''
|| path[0] == '.'
|| path[0] == '..')
&& path.shift()
path.at(-1) == ''
&& path.pop()
return format == 'string' ?
path.join('/')
: path },
split: function(path){
return this.normalize(path, 'array') },
join: function(...parts){

View File

@ -137,7 +137,7 @@ function(name, get, update, ...args){
var BaseStore =
module.BaseStore = {
// XXX NEXT revise naming...
// XXX revise naming...
next: undefined,
// NOTE: .data is not part of the spec and can be implementation-specific,
@ -236,24 +236,35 @@ module.BaseStore = {
return path in this.data
&& path },
exists: async function(path){
// XXX SANITIZE...
path = pwpath.sanitize(path, 'string')
/*/
path = pwpath.normalize(path, 'string')
//*/
return (await this.__exists__(path))
// NOTE: all paths at this point and in store are
// absolute, so we check both with the leading
// '/' and without it to make things a bit more
// relaxed and return the actual matching path...
// XXX SANITIZE...
|| (await this.__exists__('/'+ path))
/*/
|| (await this.__exists__(
path[0] == '/' ?
path.slice(1)
: ('/'+ path)))
// XXX NEXT
//*/
// delegate to .next...
|| ((this.next || {}).__exists__
&& (await this.next.__exists__(path)
// XXX SANITIZE...
|| await this.next.__exists__('/'+path)))
/*/
|| await this.next.__exists__(
path[0] == '/' ?
path.slice(1)
: ('/'+ path))))
//*/
// normalize the output...
|| false },
// find the closest existing alternative path...
@ -405,6 +416,9 @@ module.BaseStore = {
/* XXX ENERGETIC...
path = await this.resolve(path, strict)
/*/
// XXX SANITIZE...
path = pwpath.sanitize(path, 'string')
//*/
path = path.includes('*')
&& (energetic == true ?
await this.find(path)
@ -420,7 +434,6 @@ module.BaseStore = {
// and returning a a/b which can be undefined...
return that.get(p, strict) })
: (await this.__get__(path)
// XXX NEXT
?? ((this.next || {}).__get__
&& this.next.get(path, strict))) },
@ -473,7 +486,11 @@ module.BaseStore = {
return this }
var exists = await this.exists(path)
path = exists
// XXX SANITIZE...
|| pwpath.sanitize(path, 'string')
/*/
|| pwpath.normalize(path, 'string')
//*/
data = data instanceof Promise ?
await data
: data
@ -568,16 +585,6 @@ module.BaseStore = {
&& typeof(res) != 'string') ?
JSON.stringify(res, options.replacer, options.space)
: res },
/*/ XXX NEXT EXPERIMENTAL...
nest: function(base){
return {
__proto__: base
?? BaseStore,
next: this,
data: {}
} },
//*/
}

View File

@ -80,6 +80,7 @@ async function(base, sub, options){
base = null }
var {index} = getOpts(options)
sub = pwpath.sanitize(sub)
var target = encode(
base ?
pwpath.join(base, sub)
@ -99,6 +100,7 @@ async function(base, sub, options){
base = null }
var {index} = getOpts(options)
sub = pwpath.sanitize(sub)
var target = encode(
base ?
pwpath.join(base, sub)
@ -124,6 +126,7 @@ async function(base, sub, options){
base = null }
var {index, verbose} = getOpts(options)
sub = pwpath.sanitize(sub)
var levels = pwpath.split(sub)
for(var level of levels){
base = encode(
@ -147,7 +150,6 @@ async function(base, sub, options){
await fs.promises.mkdir(base, {recursive: true})
await fs.promises.rename(base +'.pwiki-bak', base +'/'+ index) }
return base }
// XXX metadata???
var update =
module.update =
async function(base, sub, data, options){
@ -158,6 +160,7 @@ async function(base, sub, data, options){
base = null }
var {index} = getOpts(options)
sub = pwpath.sanitize(sub)
var target = encode(
base ?
pwpath.join(base, sub)
@ -196,6 +199,7 @@ async function(base, sub, options){
base = '' }
var {index} = getOpts(options)
sub = pwpath.sanitize(sub)
// remove leaf...
var target = encode(
base == '' ?
@ -264,8 +268,7 @@ async function(base, options){
await fs.promises.rename(path +'/'+ index, path+'.pwiki-bak')
await fs.promises.rmdir(path)
await fs.promises.rename(path +'.pwiki-bak', path)
continue }
} } }) }
continue } } } }) }
// XXX backup metadata...
// - date

View File

@ -28,7 +28,7 @@
* example:
* @include(./path ..)
* -> <span pwiki="@include(/full/path ..)"/>
* XXX FILE prevent paths from using reserved chars like: ":", "#", ...
* XXX 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 **
@ -165,6 +165,7 @@
* XXX DEPENDS/CACHE @macro(..) introduces a dependency on count (pattern)
* ...not sure how we track these...
* XXX revise how we handle .strict mode in page's .raw and .text...
* XXX NEXT might be a good idea to add an API to restore page(s) from .next...
*
*
*