diskscan: tamed the recursive symlink beast scanner
This commit is contained in:
parent
7276561d6b
commit
6a14efeba6
3 changed files with 87 additions and 80 deletions
|
|
@ -96,6 +96,7 @@ app --
|
||||||
res.items = {}
|
res.items = {}
|
||||||
local match = function(a,b) return util.stripPath(a) == util.stripPath(b) end
|
local match = function(a,b) return util.stripPath(a) == util.stripPath(b) end
|
||||||
if urlpath:match("^"..rootpath) then
|
if urlpath:match("^"..rootpath) then
|
||||||
|
local redirect = false
|
||||||
if not app.cache.url[ urlpath ] then
|
if not app.cache.url[ urlpath ] then
|
||||||
foreach( app.cache.items, function(k,v)
|
foreach( app.cache.items, function(k,v)
|
||||||
if v.parent then
|
if v.parent then
|
||||||
|
|
@ -105,9 +106,8 @@ app --
|
||||||
)
|
)
|
||||||
if match(v.path, urlpath) then -- show parent folder if any
|
if match(v.path, urlpath) then -- show parent folder if any
|
||||||
local parent = app.cache.items[ v.parent.id ]
|
local parent = app.cache.items[ v.parent.id ]
|
||||||
if v.dir then
|
if v.portal then
|
||||||
res.items[ parent.id ] = parent.portal or parent -- portal = symlinked item
|
redirect = v.portal.url
|
||||||
print("222222222")
|
|
||||||
end
|
end
|
||||||
if match(parent.path, app.opts.plugin_diskscan_dir) then -- add rootfolder if needed
|
if match(parent.path, app.opts.plugin_diskscan_dir) then -- add rootfolder if needed
|
||||||
local root = app.cache.items[ app.opts.plugin_diskscan_dir ]
|
local root = app.cache.items[ app.opts.plugin_diskscan_dir ]
|
||||||
|
|
@ -133,10 +133,18 @@ app --
|
||||||
end)
|
end)
|
||||||
app.cache.url[ urlpath ] = util.template( LoadAsset("page/dir.html"), data)
|
app.cache.url[ urlpath ] = util.template( LoadAsset("page/dir.html"), data)
|
||||||
end
|
end
|
||||||
res.status(200)
|
if redirect then
|
||||||
res.header('content-type','text/html; charset=utf-8')
|
print("REDIRECT! " .. redirect )
|
||||||
res.body( app.cache.url[ urlpath ] )
|
res.status(303)
|
||||||
next()
|
res.header('Location', redirect )
|
||||||
|
print_r(res)
|
||||||
|
next()
|
||||||
|
else
|
||||||
|
res.status(200)
|
||||||
|
res.header('content-type','text/html; charset=utf-8')
|
||||||
|
res.body( app.cache.url[ urlpath ] )
|
||||||
|
next()
|
||||||
|
end
|
||||||
else
|
else
|
||||||
next()
|
next()
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ sb = {
|
||||||
res._header[k] = v
|
res._header[k] = v
|
||||||
sb.pub('res.header',{key=k,value=v})
|
sb.pub('res.header',{key=k,value=v})
|
||||||
end
|
end
|
||||||
res.header("content-type","text/html")
|
--res.header("content-type","text/html")
|
||||||
-- run middleware
|
-- run middleware
|
||||||
next = function()
|
next = function()
|
||||||
k = k+1
|
k = k+1
|
||||||
|
|
@ -150,7 +150,7 @@ sb = {
|
||||||
|
|
||||||
response = function()
|
response = function()
|
||||||
return function(req,res,next)
|
return function(req,res,next)
|
||||||
if res._body ~= nil and res._status ~= nil and res._header['content-type'] ~= nil then
|
if res._status ~= nil then
|
||||||
SetStatus(res._status)
|
SetStatus(res._status)
|
||||||
for k,v in pairs(res._header) do
|
for k,v in pairs(res._header) do
|
||||||
if k == "content-type" then v = v .. "; charset=" .. sb.charset end
|
if k == "content-type" then v = v .. "; charset=" .. sb.charset end
|
||||||
|
|
|
||||||
|
|
@ -27,88 +27,33 @@ return {
|
||||||
or name == "result" -- repository
|
or name == "result" -- repository
|
||||||
end,
|
end,
|
||||||
|
|
||||||
scan = function(scandir,parent,seen)
|
scan = function(scandir)
|
||||||
local seen = seen or {}
|
|
||||||
local me = app.plugin.diskscan
|
local me = app.plugin.diskscan
|
||||||
|
local seen = {symlinks={}}
|
||||||
-- ensure rootdir as experience
|
-- ensure rootdir as experience
|
||||||
app.cache.items[ scandir ] = {
|
app.cache.items[ scandir ] = {
|
||||||
path = scandir,
|
path = scandir,
|
||||||
url = util.stripPath(scandir),
|
url = "/" .. util.stripPath(scandir),
|
||||||
name = scandir:gsub(".*/",""),
|
name = scandir:gsub(".*/",""),
|
||||||
title = scandir:gsub(".*/",""),
|
title = scandir:gsub(".*/",""),
|
||||||
file = { ino = scandir },
|
file = { ino = scandir },
|
||||||
id = scandir
|
id = scandir
|
||||||
}
|
}
|
||||||
parent = parent or app.cache.items[scandir]
|
me.scanDir(scandir, nil, seen )
|
||||||
-- scan dirs
|
-- deal with (circular) symlinks
|
||||||
local scanFile = function(symlinksOnly)
|
foreach( seen.symlinks, function(ino,experience)
|
||||||
return function(path,stat,state,name,kind,ino,off,attr,fullpath)
|
if not me.shouldHideFile(experience.name) then
|
||||||
if seen[ino] then return end
|
local refItem = seen[experience.id_target]
|
||||||
|
if refItem then
|
||||||
local experience = {
|
print("ℹ️ ".. experience.path )
|
||||||
path = fullpath,
|
print("✅ └─ plugin/diskscan: detected symlink..creating portal")
|
||||||
url = util.stripPath(fullpath),
|
experience.file = refItem.file
|
||||||
name = name,
|
experience.portal = refItem
|
||||||
title = name,
|
|
||||||
sidecarfile = {},
|
|
||||||
tag = {},
|
|
||||||
id = ino,
|
|
||||||
file = {stat=stat,state=state,kind=kind,ino=ino,off=off,attr=attr,fullpath=fullpath,name=name,path=path}
|
|
||||||
}
|
|
||||||
experience.parent = parent
|
|
||||||
|
|
||||||
if (symlinksOnly and kind == unix.DT_LNK)
|
|
||||||
and not me.shouldHideFile(name) then
|
|
||||||
--seen[ino] = experience.file -- prevent recursion with symlinks
|
|
||||||
local stat, err = unix.stat(fullpath)
|
|
||||||
local refItem = seen[stat:ino()]
|
|
||||||
if refItem then
|
|
||||||
print("ℹ️ ".. fullpath)
|
|
||||||
print("✅ └─ plugin/diskscan: detected circular symlink..creating portal")
|
|
||||||
experience.file = refItem.file
|
|
||||||
experience.portal = refItem
|
|
||||||
app.pub("scan_experience", nil, experience)
|
|
||||||
app.cache.items[ino] = experience
|
|
||||||
else
|
|
||||||
print(":(")
|
|
||||||
print("symlink: " .. fullpath)
|
|
||||||
print_r(experience)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if symlinksOnly then return end
|
|
||||||
|
|
||||||
-- found directory
|
|
||||||
if (kind == unix.DT_DIR and kind ~= unix.DT_LNK)
|
|
||||||
and not me.shouldHideFile(name) then
|
|
||||||
seen[ino] = experience -- prevent recursion with symlinks
|
|
||||||
print("✅ ".. fullpath)
|
|
||||||
experience.dir = true
|
|
||||||
app.pub("scan_experience", nil, experience)
|
app.pub("scan_experience", nil, experience)
|
||||||
app.cache.items[ino] = experience
|
app.cache.items[experience.id] = experience
|
||||||
me.scan(fullpath,experience,seen)
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
---- found file
|
end)
|
||||||
if (kind ~= unix.DT_DIR and kind ~= unix.DT_LNK)
|
|
||||||
and not me.shouldHideFile(name) then
|
|
||||||
seen[ino] = experience.file -- prevent recursion with symlinks
|
|
||||||
trace("ℹ️ ".. fullpath)
|
|
||||||
experience.tag.file = true
|
|
||||||
app.pub("scan_experience_file", nil, experience)
|
|
||||||
local size = attr:size()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- first we scan real files, afterwards symlinks (to deal with circular symlinks)
|
|
||||||
local dref, derr;
|
|
||||||
print("--- no symlink")
|
|
||||||
dref, derr = dir.foreach( scandir, scanFile(false) )
|
|
||||||
if not derr then dref:close() end
|
|
||||||
print("--- symlink")
|
|
||||||
dref, derr = dir.foreach( scandir, scanFile(true) )
|
|
||||||
if not derr then dref:close() end
|
|
||||||
|
|
||||||
-- cleanup file handles
|
-- cleanup file handles
|
||||||
foreach( app.cache.items, function(k,v)
|
foreach( app.cache.items, function(k,v)
|
||||||
-- remove file attributes (which are closed already)
|
-- remove file attributes (which are closed already)
|
||||||
|
|
@ -116,6 +61,60 @@ return {
|
||||||
v.file.attr = nil
|
v.file.attr = nil
|
||||||
v.file.state = nil
|
v.file.state = nil
|
||||||
end)
|
end)
|
||||||
|
end,
|
||||||
|
|
||||||
|
scanDir = function(scandir,parent,seen)
|
||||||
|
local me = app.plugin.diskscan
|
||||||
|
parent = parent or app.cache.items[scandir]
|
||||||
|
-- scan dirs
|
||||||
|
local scanFile = function(path,stat,state,name,kind,ino,off,attr,fullpath)
|
||||||
|
|
||||||
|
local experience = {
|
||||||
|
path = fullpath,
|
||||||
|
url = "/" .. util.stripPath(fullpath),
|
||||||
|
name = name,
|
||||||
|
title = name,
|
||||||
|
sidecarfile = {},
|
||||||
|
tag = {},
|
||||||
|
id = ino,
|
||||||
|
file = {stat=stat,state=state,kind=kind,ino=ino,off=off,attr=attr,fullpath=fullpath,name=name,path=path}
|
||||||
|
}
|
||||||
|
experience.parent = parent
|
||||||
|
|
||||||
|
if seen[ino] then return end -- dont process dirs/files twice
|
||||||
|
|
||||||
|
if (kind == unix.DT_LNK) then
|
||||||
|
local stat, err = unix.stat(fullpath)
|
||||||
|
experience.id_target = stat:ino()
|
||||||
|
seen.symlinks[ ino ] = experience
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- found directory
|
||||||
|
if (kind == unix.DT_DIR and kind ~= unix.DT_LNK)
|
||||||
|
and not me.shouldHideFile(name) then
|
||||||
|
seen[ino] = experience -- prevent recursion with symlinks
|
||||||
|
print("✅ ".. fullpath .. " " ..ino)
|
||||||
|
experience.dir = true
|
||||||
|
app.pub("scan_experience", nil, experience)
|
||||||
|
app.cache.items[ino] = experience
|
||||||
|
me.scanDir(fullpath,experience,seen,symlinks)
|
||||||
|
end
|
||||||
|
|
||||||
|
---- found file
|
||||||
|
if (kind ~= unix.DT_DIR and kind ~= unix.DT_LNK)
|
||||||
|
and not me.shouldHideFile(name) then
|
||||||
|
seen[ino] = experience.file -- prevent recursion with symlinks
|
||||||
|
trace("ℹ️ ".. fullpath)
|
||||||
|
experience.tag.file = true
|
||||||
|
app.pub("scan_experience_file", nil, experience)
|
||||||
|
local size = attr:size()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dref, derr;
|
||||||
|
dref, derr = dir.foreach( scandir, scanFile )
|
||||||
|
if not derr then dref:close() end
|
||||||
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue