diff --git a/snprc_ehr/src/org/labkey/snprc_ehr/controllers/FeeScheduleController.java b/snprc_ehr/src/org/labkey/snprc_ehr/controllers/FeeScheduleController.java index cd8512f6f..dc85e57c2 100644 --- a/snprc_ehr/src/org/labkey/snprc_ehr/controllers/FeeScheduleController.java +++ b/snprc_ehr/src/org/labkey/snprc_ehr/controllers/FeeScheduleController.java @@ -29,18 +29,24 @@ import org.labkey.api.security.RequiresPermission; import org.labkey.api.security.permissions.AdminPermission; import org.labkey.api.util.PageFlowUtil; +import org.labkey.api.util.Path; +import org.labkey.api.util.URIUtil; import org.labkey.api.util.URLHelper; import org.labkey.api.view.ActionURL; import org.labkey.api.view.JspView; import org.labkey.api.view.NavTree; +import org.labkey.api.view.NotFoundException; import org.labkey.snprc_ehr.pipeline.FeeScheduleExcelParser; import org.labkey.snprc_ehr.pipeline.FeeScheduleImportForm; import org.labkey.snprc_ehr.pipeline.FeeSchedulePipelineJob; +import org.labkey.vfs.FileLike; +import org.labkey.vfs.FileSystemLike; import org.springframework.validation.BindException; import org.springframework.validation.Errors; import org.springframework.web.servlet.ModelAndView; import java.io.File; +import java.net.URI; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; @@ -108,7 +114,8 @@ public ModelAndView getView(FeeScheduleImportForm form, boolean reshow, BindExce FeeScheduleExcelParser fsep; if (form.getFilePath() != null) { - file = new File(form.getFilePath()); + //file path here is constructed from the pipeline, and contains pipeline root + file. + file = getVerifiedFile(form.getFilePath()); } if (file != null && file.exists()) { @@ -146,16 +153,45 @@ public ModelAndView getView(FeeScheduleImportForm form, boolean reshow, BindExce return new JspView<>("/org/labkey/snprc_ehr/pipeline/FeeScheduleImport.jsp", form, errors); } + private File getVerifiedFile(String filePath) + { + File fileToVerify = new File(filePath); + + PipeRoot pipeRoot = PipelineService.get().findPipelineRoot(getContainer()); + if (pipeRoot == null) + { + throw new NotFoundException("Could not find a pipeline root for '" + getContainer().getPath() + "'"); + } + + FileLike allowedRoot = pipeRoot.getRootFileLike(); + URI relativeURI = URIUtil.relativize(allowedRoot.toURI(), fileToVerify.toURI()); // if root = /a/b/c/ and file = /a/b/c/d/e/f.xlsx, relativeURI = d/e/f.xlsx + + if (relativeURI == null) + { + throw new IllegalArgumentException("File '" + fileToVerify.toURI().getPath() + "' is outside the allowed root '" + allowedRoot.toURI().getPath() + "'"); + } + + if (allowedRoot.isDescendant(fileToVerify.toURI())) // if root = /a/b/c/ and file = /a/b/c/d/e/f.xlsx - among other things, this essentially checks if '/a/b/c/d/e/f.xlsx' starts with '/a/b/c/' + { + return FileSystemLike.toFile(allowedRoot.resolveFile(new Path(relativeURI.getPath()))); + } + else + { + throw new IllegalArgumentException("File '" + relativeURI.getPath() + "' is not a descendent of '" + allowedRoot.toURI().getPath() + "'"); + } + } + @Override public void validateCommand(FeeScheduleImportForm form, Errors errors) { - _fsFile = new File(form.getFilePath()); + _fsFile = getVerifiedFile(form.getFilePath()); // Be sure that the referenced file exists - if (_fsFile == null || !_fsFile.exists()) + if (!_fsFile.exists()) { errors.reject(ERROR_MSG, "Could not find file at path: " + form.getFilePath()); } } + @Override public boolean handlePost(FeeScheduleImportForm form, BindException errors) { @@ -163,7 +199,7 @@ public boolean handlePost(FeeScheduleImportForm form, BindException errors) try { PipeRoot pipelineRoot = PipelineService.get().findPipelineRoot(getContainer()); - PipelineService.get().queueJob(new FeeSchedulePipelineJob(getContainer(), getUser(), getViewContext().getActionURL(), pipelineRoot, _fsFile, form)); + PipelineService.get().queueJob(new FeeSchedulePipelineJob(getContainer(), getUser(), getViewContext().getActionURL(), pipelineRoot, getVerifiedFile(_fsFile.getAbsolutePath()), form)); _url = PageFlowUtil.urlProvider(PipelineStatusUrls.class).urlBegin(getContainer().getProject()); _url.addParameter("StatusFiles.containerFilterName", ContainerFilter.Type.CurrentAndSubfolders.name()); diff --git a/snprc_ehr/src/org/labkey/snprc_ehr/pipeline/FeeSchedulePipelineJob.java b/snprc_ehr/src/org/labkey/snprc_ehr/pipeline/FeeSchedulePipelineJob.java index 57b3d79e0..ef08d2c19 100644 --- a/snprc_ehr/src/org/labkey/snprc_ehr/pipeline/FeeSchedulePipelineJob.java +++ b/snprc_ehr/src/org/labkey/snprc_ehr/pipeline/FeeSchedulePipelineJob.java @@ -22,9 +22,12 @@ import org.labkey.api.pipeline.PipelineJobException; import org.labkey.api.security.User; import org.labkey.api.util.FileUtil; +import org.labkey.api.util.Path; import org.labkey.api.util.URLHelper; import org.labkey.api.view.ActionURL; import org.labkey.api.view.ViewBackgroundInfo; +import org.labkey.vfs.FileLike; +import org.labkey.vfs.FileSystemLike; import java.io.File; @@ -47,7 +50,8 @@ public FeeSchedulePipelineJob(Container c, User user, ActionURL url, PipeRoot pi { super(null, new ViewBackgroundInfo(c, user, url), pipeRoot); _importFile = importFile; - setLogFile(new File(pipeRoot.getRootPath(), FileUtil.makeFileNameWithTimestamp("FeeSchedulePipeline", "log"))); + FileLike logFile = pipeRoot.getLogDirectoryFileLike(true).resolveChild(FileUtil.makeFileNameWithTimestamp("FeeSchedulePipeline", "log")); + setLogFile(logFile.toNioPathForWrite()); _form = form; _container = c; _user = user;