file_manager: remove restriction that file paths must be in HOME
Instead make sure that the supplied path is not the system root and check that moonraker has the appropriate privileges to access the directory. Also track visited directories when retreiving a full file list to prevent infinite recursion. Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
77c483ea0f
commit
1814a11a8d
|
@ -15,7 +15,6 @@ from tornado.locks import Event
|
||||||
|
|
||||||
VALID_GCODE_EXTS = ['.gcode', '.g', '.gco']
|
VALID_GCODE_EXTS = ['.gcode', '.g', '.gco']
|
||||||
FULL_ACCESS_ROOTS = ["gcodes", "config"]
|
FULL_ACCESS_ROOTS = ["gcodes", "config"]
|
||||||
ETC_DIR = "/etc/moonraker"
|
|
||||||
METADATA_SCRIPT = os.path.normpath(os.path.join(
|
METADATA_SCRIPT = os.path.normpath(os.path.join(
|
||||||
os.path.dirname(__file__), "../../scripts/extract_metadata.py"))
|
os.path.dirname(__file__), "../../scripts/extract_metadata.py"))
|
||||||
|
|
||||||
|
@ -84,14 +83,21 @@ class FileManager:
|
||||||
def register_directory(self, root, path):
|
def register_directory(self, root, path):
|
||||||
if path is None:
|
if path is None:
|
||||||
return False
|
return False
|
||||||
home = os.path.expanduser('~')
|
|
||||||
path = os.path.normpath(os.path.expanduser(path))
|
path = os.path.normpath(os.path.expanduser(path))
|
||||||
if not os.path.isdir(path) or path == home or \
|
if os.path.islink(path):
|
||||||
not (path.startswith(home) or path.startswith(ETC_DIR)):
|
path = os.path.realpath(path)
|
||||||
|
if not os.path.isdir(path) or path == "/":
|
||||||
logging.info(
|
logging.info(
|
||||||
f"\nSupplied path ({path}) for ({root}) not valid. Please\n"
|
f"\nSupplied path ({path}) for ({root}) a valid. Make sure\n"
|
||||||
"check that the path exists and is a subfolder in the HOME\n"
|
"that the path exists and is not the file system root.")
|
||||||
"directory. Note that the path may not BE the home directory.")
|
return False
|
||||||
|
permissions = os.R_OK
|
||||||
|
if root in FULL_ACCESS_ROOTS:
|
||||||
|
permissions |= os.W_OK
|
||||||
|
if not os.access(path, permissions):
|
||||||
|
logging.info(
|
||||||
|
f"\nMoonraker does not have permission to access path "
|
||||||
|
f"({path}) for ({root}).")
|
||||||
return False
|
return False
|
||||||
if path != self.file_paths.get(root, ""):
|
if path != self.file_paths.get(root, ""):
|
||||||
self.file_paths[root] = path
|
self.file_paths[root] = path
|
||||||
|
@ -448,12 +454,24 @@ class FileManager:
|
||||||
logging.info(msg)
|
logging.info(msg)
|
||||||
raise self.server.error(msg)
|
raise self.server.error(msg)
|
||||||
logging.info(f"Updating File List <{root}>...")
|
logging.info(f"Updating File List <{root}>...")
|
||||||
for root_path, dirs, files in os.walk(path, followlinks=True):
|
st = os.stat(path)
|
||||||
|
visited_dirs = {(st.st_dev, st.st_ino)}
|
||||||
|
for dir_path, dir_names, files in os.walk(path, followlinks=True):
|
||||||
|
scan_dirs = []
|
||||||
|
# Filter out directories that have already been visted. This
|
||||||
|
# prevents infinite recrusion "followlinks" is set to True
|
||||||
|
for dname in dir_names:
|
||||||
|
st = os.stat(os.path.join(dir_path, dname))
|
||||||
|
key = (st.st_dev, st.st_ino)
|
||||||
|
if key not in visited_dirs:
|
||||||
|
visited_dirs.add(key)
|
||||||
|
scan_dirs.append(dname)
|
||||||
|
dir_names[:] = scan_dirs
|
||||||
for name in files:
|
for name in files:
|
||||||
ext = os.path.splitext(name)[-1].lower()
|
ext = os.path.splitext(name)[-1].lower()
|
||||||
if root == 'gcodes' and ext not in VALID_GCODE_EXTS:
|
if root == 'gcodes' and ext not in VALID_GCODE_EXTS:
|
||||||
continue
|
continue
|
||||||
full_path = os.path.join(root_path, name)
|
full_path = os.path.join(dir_path, name)
|
||||||
fname = full_path[len(path) + 1:]
|
fname = full_path[len(path) + 1:]
|
||||||
finfo = self._get_path_info(full_path)
|
finfo = self._get_path_info(full_path)
|
||||||
filelist[fname] = finfo
|
filelist[fname] = finfo
|
||||||
|
|
Loading…
Reference in New Issue