diff --git a/src/octoprint/printer/__init__.py b/src/octoprint/printer/__init__.py index 08aca1de..e26a80e4 100644 --- a/src/octoprint/printer/__init__.py +++ b/src/octoprint/printer/__init__.py @@ -292,11 +292,15 @@ class PrinterInterface(object): Optionally can also directly start the print after selecting the file. Arguments: - path (str): The path to select for printing. Either an absolute path (local file) or a - filename (SD card). - sd (boolean): Indicates whether the file is on the SD card or not. + path (str): The path to select for printing. Either an absolute path or relative path to a local file in + the uploads folder or a filename on the printer's SD card. + sd (boolean): Indicates whether the file is on the printer's SD card or not. printAfterSelect (boolean): Indicates whether a print should be started after the file is selected. + + Raises: + InvalidFileLocation: if an absolute path was provided and not contained within local storage or + doesn't exist """ raise NotImplementedError() @@ -586,3 +590,6 @@ class PrinterCallback(object): class UnknownScript(Exception): def __init__(self, name, *args, **kwargs): self.name = name + +class InvalidFileLocation(Exception): + pass diff --git a/src/octoprint/printer/standard.py b/src/octoprint/printer/standard.py index 77acb1b6..57dda584 100644 --- a/src/octoprint/printer/standard.py +++ b/src/octoprint/printer/standard.py @@ -19,7 +19,7 @@ from octoprint import util as util from octoprint.events import eventManager, Events from octoprint.filemanager import FileDestinations, NoSuchStorage from octoprint.plugin import plugin_manager, ProgressPlugin -from octoprint.printer import PrinterInterface, PrinterCallback, UnknownScript +from octoprint.printer import PrinterInterface, PrinterCallback, UnknownScript, InvalidFileLocation from octoprint.printer.estimation import TimeEstimationHelper from octoprint.settings import settings from octoprint.util import comm as comm @@ -386,6 +386,8 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): self._logger.info("Cannot load file: printer not connected or currently busy") return + self._validateJob(path, sd) + recovery_data = self._fileManager.get_recovery_data() if recovery_data: # clean up recovery data if we just selected a different file than is logged in that @@ -842,6 +844,16 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): self._stateMonitor.add_temperature(data) + def _validateJob(self, filename, sd): + if sd: + return + + path_on_disk = self._fileManager.path_on_disk(FileDestinations.LOCAL, filename) + if os.path.isabs(filename) and not filename == path_on_disk: + raise InvalidFileLocation("{} is not located within local storage, cannot select for printing".format(filename)) + if not os.path.isfile(path_on_disk): + raise InvalidFileLocation("{} does not exist in local storage, cannot select for printing".format(filename)) + def _setJobData(self, filename, filesize, sd): with self._selectedFileMutex: if filename is not None: