diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java b/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java index 8cc58b77b91c756cae58f2baecf8d338d2e2e69d..e44be4aef6e4c0b0d30aa0bff805b6c34f6a7331 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java +++ b/src/main/java/org/olat/core/commons/modules/bc/FileCopyController.java @@ -364,11 +364,11 @@ public class FileCopyController extends LinkChooserController { String description = translate("ul.tooManyRevisions.description", new String[]{Integer.toString(maxNumOfRevisions), Integer.toString(versions.getRevisions().size())}); removeAsListenerAndDispose(revisionListCtr); - revisionListCtr = new RevisionListController(ureq, getWindowControl(), versionable, title, description, false); + revisionListCtr = new RevisionListController(ureq, getWindowControl(), versionable, null, description, false); listenTo(revisionListCtr); removeAsListenerAndDispose(revisionListDialogBox); - revisionListDialogBox = new CloseableModalController(getWindowControl(), translate("delete"), revisionListCtr.getInitialComponent()); + revisionListDialogBox = new CloseableModalController(getWindowControl(), translate("delete"), revisionListCtr.getInitialComponent(), true, title); listenTo(revisionListDialogBox); revisionListDialogBox.activate(); diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileSelection.java b/src/main/java/org/olat/core/commons/modules/bc/FileSelection.java index 604a4c6c8313b17d8fa1923f920671a111f4fdc0..88f5aec34f12b43f1791b5045b9bbf6aabaa5f23 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/FileSelection.java +++ b/src/main/java/org/olat/core/commons/modules/bc/FileSelection.java @@ -28,11 +28,11 @@ package org.olat.core.commons.modules.bc; import java.util.ArrayList; import java.util.Arrays; -import java.util.Iterator; import java.util.List; import org.olat.core.gui.UserRequest; import org.olat.core.util.FileUtils; +import org.olat.core.util.StringHelper; public class FileSelection { @@ -86,12 +86,12 @@ public class FileSelection { * @return HTML Fragment. */ public String renderAsHtml() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(255); sb.append("<ul>"); - for (Iterator<String> iter = files.iterator(); iter.hasNext();) { - sb.append("<li>"); - sb.append(currentContainerRelPath + "/" + iter.next()); - sb.append("</li>"); + for (String filename:files) { + sb.append("<li>") + .append(currentContainerRelPath).append("/").append(StringHelper.escapeHtml(filename)) + .append("</li>"); } sb.append("</ul>"); return sb.toString(); diff --git a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java index 0a361a0dd2c5df13749420b7505f9c33e3eb7e1b..b0ea5085283d073e5215612e50949172db68e481 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java +++ b/src/main/java/org/olat/core/commons/modules/bc/FileUploadController.java @@ -30,14 +30,12 @@ import static java.util.Arrays.asList; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Set; import java.util.regex.Pattern; -import org.olat.core.CoreSpringFactory; import org.olat.core.commons.modules.bc.commands.FolderCommandStatus; import org.olat.core.commons.modules.bc.meta.MetaInfo; import org.olat.core.commons.modules.bc.meta.MetaInfoFactory; @@ -47,6 +45,7 @@ import org.olat.core.commons.modules.bc.version.VersionCommentController; import org.olat.core.commons.modules.bc.vfs.OlatRootFileImpl; import org.olat.core.commons.services.image.ImageService; import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FileElement; import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; @@ -54,6 +53,7 @@ import org.olat.core.gui.components.form.flexible.elements.StaticTextElement; import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.Form; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; @@ -78,6 +78,7 @@ import org.olat.core.util.vfs.VFSLockManager; import org.olat.core.util.vfs.VFSManager; import org.olat.core.util.vfs.version.Versionable; import org.olat.core.util.vfs.version.Versions; +import org.springframework.beans.factory.annotation.Autowired; /** * <h3>Description</h3> @@ -113,12 +114,11 @@ public class FileUploadController extends FormBasicController { private VersionCommentController unlockCtr; private DialogBoxController overwriteDialog; private DialogBoxController lockedFileDialog; - private VFSLeaf newFile = null; - private VFSItem existingVFSItem = null; + private VFSLeaf newFile; + private VFSItem existingVFSItem; private long uploadLimitKB; private long remainingQuotKB; private Set<String> mimeTypes; - private FilesInfoMBean fileInfoMBean; // // Form elements private FileElement fileEl; @@ -139,9 +139,15 @@ public class FileUploadController extends FormBasicController { private static Pattern imageExtPattern = Pattern.compile("\\b.(jpg|jpeg|png)\\b"); private static final Pattern validSubPathPattern = Pattern.compile("[\\p{Alnum}-_\\./]*"); - - private final VFSLockManager vfsLockManager; + @Autowired + private ImageService imageHelper; + @Autowired + private FilesInfoMBean fileInfoMBean; + @Autowired + private VFSLockManager vfsLockManager; + @Autowired + private MetaInfoFactory metaInfoFactory; private String subfolderPath; private TextElement targetSubPath ; @@ -176,17 +182,13 @@ public class FileUploadController extends FormBasicController { public FileUploadController(WindowControl wControl, VFSContainer curContainer, UserRequest ureq, long upLimitKB, long remainingQuotKB, Set<String> mimeTypesRestriction, boolean showTargetPath, boolean showMetadata, boolean resizeImg, boolean showCancel, boolean showTitle, String subfolderPath) { super(ureq, wControl, "file_upload"); - vfsLockManager = CoreSpringFactory.getImpl(VFSLockManager.class); setVariables(curContainer, upLimitKB, remainingQuotKB, mimeTypesRestriction, showTargetPath, showMetadata, resizeImg, showCancel, showTitle, subfolderPath); initForm(ureq); } - - private void setVariables(VFSContainer curContainer, long upLimitKB, long remainingQuotKB, Set<String> mimeTypesRestriction, boolean showTargetPath, boolean showMetadata, boolean resizeImg, boolean showCancel, boolean showTitle, String subfolderPath) { this.currentContainer = curContainer; - this.fileInfoMBean = (FilesInfoMBean) CoreSpringFactory.getBean(FilesInfoMBean.class.getCanonicalName()); this.mimeTypes = mimeTypesRestriction; this.showTitle = showTitle; this.showTargetPath = showTargetPath; @@ -239,8 +241,8 @@ public class FileUploadController extends FormBasicController { } } - fileEl = uifactory.addFileElement(getWindowControl(), "fileEl", "ul.file", fileUpload); + fileEl.addActionListener(FormEvent.ONCHANGE); setMaxUploadSizeKB((uploadLimitKB < remainingQuotKB ? uploadLimitKB : remainingQuotKB)); fileEl.setMandatory(true, "NoFileChoosen"); @@ -295,162 +297,28 @@ public class FileUploadController extends FormBasicController { } } + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if(fileEl == source) { + if(metaDataCtr != null) { + String filename = fileEl.getUploadFileName(); + metaDataCtr.setFilename(filename); + } + } + super.formInnerEvent(ureq, source, event); + } + @Override protected void formOK(UserRequest ureq) { if(targetSubPath != null) setUploadRelPath(targetSubPath.getValue()); if ( fileEl.isUploadSuccess()) { - // check for available space - if (remainingQuotKB != -1) { - if (fileEl.getUploadFile().length() / 1024 > remainingQuotKB) { - fileEl.setErrorKey("QuotaExceeded", null); - fileEl.getUploadFile().delete(); - return; - } - } - String fileName = fileEl.getUploadFileName(); - - File uploadedFile = fileEl.getUploadFile(); - if(resizeImg && fileName != null && imageExtPattern.matcher(fileName.toLowerCase()).find() - && resizeEl.isSelected(0)) { - String extension = FileUtils.getFileSuffix(fileName); - File imageScaled = new File(uploadedFile.getParentFile(), "scaled_" + uploadedFile.getName() + "." + extension); - ImageService imageHelper = CoreSpringFactory.getImpl(ImageService.class); - if(imageHelper.scaleImage(uploadedFile, extension, imageScaled, 1280, 1280, false) != null) { - //problem happen, special GIF's (see bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6358674) - //don't try to scale if not all ok - uploadedFile = imageScaled; - } - } - - // check if such a filename does already exist - existingVFSItem = uploadVFSContainer.resolve(fileName); - if (existingVFSItem == null) { - // save file and finish - newFile = uploadVFSContainer.createChildLeaf(fileName); - - boolean success = true; - if(newFile == null) { - // FXOLAT-409 somehow "createChildLeaf" did not succeed... - // if so, there is alread a error-msg in log (vfsContainer.createChildLeaf) - success = false; - } else { - try(InputStream in = new FileInputStream(uploadedFile); - OutputStream out = newFile.getOutputStream(false)) { - FileUtils.bcopy(in, out, "uploadTmpFileToDestFile"); - uploadedFile.delete(); - } catch (IOException e) { - success = false; - } - } - - if (success) { - String filePath = (uploadRelPath == null ? "" : uploadRelPath + "/") + newFile.getName(); - finishSuccessfullUpload(filePath, newFile, ureq); - fileInfoMBean.logUpload(newFile.getSize()); - fireEvent(ureq, Event.DONE_EVENT); - } else { - showError("failed"); - status = FolderCommandStatus.STATUS_FAILED; - fireEvent(ureq, Event.FAILED_EVENT); - } - } else { - // file already exists... upload anyway with new filename and - // in the folder manager status. - // rename file and ask user what to do - if ( ! (existingVFSItem instanceof LocalImpl)) { - throw new AssertException("Can only LocalImpl VFS items, don't know what to do with file of type::" + existingVFSItem.getClass().getCanonicalName()); - } - - String renamedFilename = VFSManager.rename(uploadVFSContainer, existingVFSItem.getName()); - newFile = uploadVFSContainer.createChildLeaf(renamedFilename); - - // Copy content to tmp file - InputStream in = null; - BufferedOutputStream out = null; - boolean success = false; - try { - in = new FileInputStream(uploadedFile); - out = new BufferedOutputStream(newFile.getOutputStream(false)); - if (in != null) { - success = FileUtils.copy(in, out); - } - uploadedFile.delete(); - } catch (FileNotFoundException e) { - success = false; - } finally { - FileUtils.closeSafely(in); - FileUtils.closeSafely(out); - } - - if (success) { - boolean locked = vfsLockManager.isLockedForMe(existingVFSItem, getIdentity(), ureq.getUserSession().getRoles()); - if (locked) { - //the file is locked and cannot be overwritten - removeAsListenerAndDispose(lockedFileDialog); - lockedFileDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), translate("ul.lockedFile.title"), translate("ul.lockedFile.text", new String[] {existingVFSItem.getName(), renamedFilename} ), asList(translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); - listenTo(lockedFileDialog); - - lockedFileDialog.activate(); - } - else if (existingVFSItem instanceof Versionable && ((Versionable)existingVFSItem).getVersions().isVersioned()) { - Versionable versionable = (Versionable)existingVFSItem; - Versions versions = versionable.getVersions(); - String relPath = null; - if(existingVFSItem instanceof OlatRootFileImpl) { - relPath = ((OlatRootFileImpl)existingVFSItem).getRelPath(); - } - int maxNumOfRevisions = FolderConfig.versionsAllowed(relPath); - if(maxNumOfRevisions == 0) { - //it's possible if someone change the configuration - // let calling method decide what to do. - removeAsListenerAndDispose(overwriteDialog); - overwriteDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), translate("ul.overwrite.threeoptions.title"), translate("ul.overwrite.threeoptions.text", new String[] {existingVFSItem.getName(), renamedFilename} ), asList(translate("ul.overwrite.threeoptions.overwrite"), translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); - listenTo(overwriteDialog); - - overwriteDialog.activate(); - - } else if(versions.getRevisions().isEmpty() || maxNumOfRevisions < 0 || maxNumOfRevisions > versions.getRevisions().size()) { - // let calling method decide what to do. - removeAsListenerAndDispose(overwriteDialog); - overwriteDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), translate("ul.overwrite.threeoptions.title"), translate("ul.versionoroverwrite", new String[] {existingVFSItem.getName(), renamedFilename} ), asList(translate("ul.overwrite.threeoptions.newVersion"), translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); - listenTo(overwriteDialog); - - overwriteDialog.activate(); - - } else { - - String title = translate("ul.tooManyRevisions.title", new String[]{Integer.toString(maxNumOfRevisions), Integer.toString(versions.getRevisions().size())}); - String description = translate("ul.tooManyRevisions.description", new String[]{Integer.toString(maxNumOfRevisions), Integer.toString(versions.getRevisions().size())}); - - removeAsListenerAndDispose(revisionListCtr); - revisionListCtr = new RevisionListController(ureq, getWindowControl(), versionable, title, description, false); - listenTo(revisionListCtr); - - removeAsListenerAndDispose(revisionListDialogBox); - revisionListDialogBox = new CloseableModalController(getWindowControl(), translate("delete"), revisionListCtr.getInitialComponent()); - listenTo(revisionListDialogBox); - - revisionListDialogBox.activate(); - } - } else { - // let calling method decide what to do. - // for this, we put a list with "existing name" and "new name" - overwriteDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), translate("ul.overwrite.threeoptions.title"), translate("ul.overwrite.threeoptions.text", new String[] {existingVFSItem.getName(), renamedFilename} ), asList(translate("ul.overwrite.threeoptions.overwrite"), translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); - listenTo(overwriteDialog); - overwriteDialog.activate(); - } - } else { - showError("failed"); - status = FolderCommandStatus.STATUS_FAILED; - fireEvent(ureq, Event.FAILED_EVENT); - } - } + doUpload(ureq); } else { if (mainForm.getLastRequestError() == Form.REQUEST_ERROR_GENERAL ) { showError("failed"); } else if (mainForm.getLastRequestError() == Form.REQUEST_ERROR_FILE_EMPTY ) { showError("failed"); - }else if (mainForm.getLastRequestError() == Form.REQUEST_ERROR_UPLOAD_LIMIT_EXCEEDED) { + } else if (mainForm.getLastRequestError() == Form.REQUEST_ERROR_UPLOAD_LIMIT_EXCEEDED) { showError("QuotaExceeded"); } status = FolderCommandStatus.STATUS_FAILED; @@ -473,120 +341,35 @@ public class FileUploadController extends FormBasicController { @Override public void event(UserRequest ureq, Controller source, Event event) { if (source == overwriteDialog) { - if (event instanceof ButtonClickedEvent) { ButtonClickedEvent buttonClickedEvent = (ButtonClickedEvent) event; if (buttonClickedEvent.getPosition() == 0) { //ok - if (existingVFSItem instanceof Versionable && ((Versionable)existingVFSItem).getVersions().isVersioned()) { - //new version - String relPath = null; - if(existingVFSItem instanceof OlatRootFileImpl) { - relPath = ((OlatRootFileImpl)existingVFSItem).getRelPath(); - } - int maxNumOfRevisions = FolderConfig.versionsAllowed(relPath); - if(maxNumOfRevisions == 0) { - //someone play with the configuration - // Overwrite... - String fileName = existingVFSItem.getName(); - existingVFSItem.delete(); - newFile.rename(fileName); - - // ... and notify listeners. - finishUpload(ureq); - } else { - removeAsListenerAndDispose(commentVersionCtr); - removeAsListenerAndDispose(commentVersionDialogBox); - - boolean locked = vfsLockManager.isLocked(existingVFSItem); - commentVersionCtr = new VersionCommentController(ureq, getWindowControl(), locked, true); - listenTo(commentVersionCtr); - commentVersionDialogBox = new CloseableModalController(getWindowControl(), translate("save"), commentVersionCtr.getInitialComponent()); - listenTo(commentVersionDialogBox); - commentVersionDialogBox.activate(); - } - } else { - //if the file is locked, ask for unlocking it - if(vfsLockManager.isLocked(existingVFSItem)) { - removeAsListenerAndDispose(unlockCtr); - unlockCtr = new VersionCommentController(ureq,getWindowControl(), true, false); - listenTo(unlockCtr); - - removeAsListenerAndDispose(unlockDialogBox); - unlockDialogBox = new CloseableModalController(getWindowControl(), translate("ok"), unlockCtr.getInitialComponent()); - listenTo(unlockDialogBox); - - unlockDialogBox.activate(); - - } else { - // Overwrite... - String fileName = existingVFSItem.getName(); - existingVFSItem.delete(); - newFile.rename(fileName); - - // ... and notify listeners. - finishUpload(ureq); - } - } + doFinishOverwrite(ureq); } else if (buttonClickedEvent.getPosition() == 1) { //not ok // Upload renamed. Since we've already uploaded the file with a changed name, don't do anything much here... - this.fileOverwritten = true; - + fileOverwritten = true; // ... and notify listeners. finishUpload(ureq); } else if (buttonClickedEvent.getPosition() == 2) { // cancel // Cancel. Remove the new file since it has already been uploaded. Note that we don't have to explicitly close the // dialog box since it closes itself whenever something gets clicked. - newFile.deleteSilently(); - } else { - throw new RuntimeException("Unknown button number " + buttonClickedEvent.getPosition()); + doCancel(ureq); } } } else if (source == lockedFileDialog) { - if (event instanceof ButtonClickedEvent) { ButtonClickedEvent buttonClickedEvent = (ButtonClickedEvent) event; - switch(buttonClickedEvent.getPosition()) { - case 0: { - //upload the file with a new name - this.fileOverwritten = true; - // ... and notify listeners. - finishUpload(ureq); - break; - } - case 1: {//cancel - newFile.deleteSilently(); - fireEvent(ureq, Event.CANCELLED_EVENT); - break; - } - default: - throw new RuntimeException("Unknown button number " + buttonClickedEvent.getPosition()); + if(buttonClickedEvent.getPosition() == 0) { + //upload the file with a new name + fileOverwritten = true; + // ... and notify listeners. + finishUpload(ureq); + } else if(buttonClickedEvent.getPosition() == 1) { + doCancel(ureq); } } } else if (source == commentVersionCtr) { - String comment = commentVersionCtr.getComment(); - - Roles roles = ureq.getUserSession().getRoles(); - boolean locked = vfsLockManager.isLocked(existingVFSItem); - if(locked && !commentVersionCtr.keepLocked()) { - vfsLockManager.unlock(existingVFSItem, getIdentity(), roles); - } - - commentVersionDialogBox.deactivate(); - if(revisionListDialogBox != null) { - revisionListDialogBox.deactivate(); - } - - //ok, new version of the file - Versionable existingVersionableItem = (Versionable)existingVFSItem; - boolean ok = existingVersionableItem.getVersions().addVersion(ureq.getIdentity(), comment, newFile.getInputStream()); - if(ok) { - newFile.deleteSilently(); - //what can i do if existingVFSItem is a container - if(existingVFSItem instanceof VFSLeaf) { - newFile = (VFSLeaf)existingVFSItem; - } - } - finishUpload(ureq); + doFinishComment(ureq); } else if (source == unlockCtr) { // Overwrite... String fileName = existingVFSItem.getName(); @@ -597,7 +380,6 @@ public class FileUploadController extends FormBasicController { existingVFSItem.delete(); newFile.rename(fileName); - // ... and notify listeners. finishUpload(ureq); @@ -606,61 +388,304 @@ public class FileUploadController extends FormBasicController { revisionListCtr = null; removeAsListenerAndDispose(revisionListDialogBox); revisionListDialogBox = null; - - //remove the file - newFile.deleteSilently(); + doCancel(ureq); } else if (source == revisionListCtr) { + revisionListDialogBox.deactivate(); + removeAsListenerAndDispose(revisionListDialogBox); + revisionListDialogBox = null; + if(FolderCommandStatus.STATUS_CANCELED == revisionListCtr.getStatus()) { - - revisionListDialogBox.deactivate(); - removeAsListenerAndDispose(revisionListDialogBox); - revisionListDialogBox = null; - //don't want to delete revisions, clean the temporary file - if(newFile != null) { - newFile.deleteSilently(); - } + doCancel(ureq); + } else if (existingVFSItem instanceof Versionable && ((Versionable)existingVFSItem).getVersions().isVersioned()) { + doFinishRevisionList(ureq); + } + } + } + + /** + * Delete the uploaded file and send cancel event + * @param ureq + */ + private void doCancel(UserRequest ureq) { + if(newFile != null) { + newFile.deleteSilently(); + } + fireEvent(ureq, Event.CANCELLED_EVENT); + } + + private void doFinishOverwrite(UserRequest ureq) { + if (existingVFSItem instanceof Versionable && ((Versionable)existingVFSItem).getVersions().isVersioned()) { + //new version + int maxNumOfRevisions = getMaxNumOfRevisionsOfExistingVFSItem(); + if(maxNumOfRevisions == 0) { + //someone play with the configuration + // Overwrite... + String fileName = existingVFSItem.getName(); + existingVFSItem.delete(); + newFile.rename(fileName); + + // ... and notify listeners. + finishUpload(ureq); } else { - if (existingVFSItem instanceof Versionable && ((Versionable)existingVFSItem).getVersions().isVersioned()) { - - revisionListDialogBox.deactivate(); - removeAsListenerAndDispose(revisionListDialogBox); - revisionListDialogBox = null; - - if(existingVFSItem.getParentContainer() != null) { - existingVFSItem = existingVFSItem.getParentContainer().resolve(existingVFSItem.getName()); - } - - Versionable versionable = (Versionable)existingVFSItem; - Versions versions = versionable.getVersions(); - int maxNumOfRevisions = FolderConfig.versionsAllowed(null); - if(maxNumOfRevisions < 0 || maxNumOfRevisions > versions.getRevisions().size()) { - removeAsListenerAndDispose(commentVersionCtr); - removeAsListenerAndDispose(commentVersionDialogBox); + askForComment(ureq); + } + } else { + //if the file is locked, ask for unlocking it + if(vfsLockManager.isLocked(existingVFSItem)) { + askForUnlock(ureq); + + } else { + // Overwrite... + String fileName = existingVFSItem.getName(); + existingVFSItem.delete(); + newFile.rename(fileName); + + // ... and notify listeners. + finishUpload(ureq); + } + } + } + + private void doFinishComment(UserRequest ureq) { + String comment = commentVersionCtr.getComment(); + + Roles roles = ureq.getUserSession().getRoles(); + boolean locked = vfsLockManager.isLocked(existingVFSItem); + if(locked && !commentVersionCtr.keepLocked()) { + vfsLockManager.unlock(existingVFSItem, getIdentity(), roles); + } + + commentVersionDialogBox.deactivate(); + if(revisionListDialogBox != null) { + revisionListDialogBox.deactivate(); + } + + //ok, new version of the file + Versionable existingVersionableItem = (Versionable)existingVFSItem; + boolean ok = existingVersionableItem.getVersions().addVersion(ureq.getIdentity(), comment, newFile.getInputStream()); + if(ok) { + newFile.deleteSilently(); + //what can i do if existingVFSItem is a container + if(existingVFSItem instanceof VFSLeaf) { + newFile = (VFSLeaf)existingVFSItem; + } + } + finishUpload(ureq); + } + + private void doFinishRevisionList(UserRequest ureq) { + if(existingVFSItem.getParentContainer() != null) { + existingVFSItem = existingVFSItem.getParentContainer().resolve(existingVFSItem.getName()); + } + + Versionable versionable = (Versionable)existingVFSItem; + Versions versions = versionable.getVersions(); + int maxNumOfRevisions = getMaxNumOfRevisionsOfExistingVFSItem(); + if(maxNumOfRevisions < 0 || maxNumOfRevisions > versions.getRevisions().size()) { + askForComment(ureq); + } else { + askToReduceRevisionList(ureq, versionable); + } + } + + private int getMaxNumOfRevisionsOfExistingVFSItem() { + String relPath = null; + if(existingVFSItem instanceof OlatRootFileImpl) { + relPath = ((OlatRootFileImpl)existingVFSItem).getRelPath(); + } + return FolderConfig.versionsAllowed(relPath); + } + + private void askToReduceRevisionList(UserRequest ureq, Versionable versionable) { + removeAsListenerAndDispose(revisionListCtr); + removeAsListenerAndDispose(revisionListDialogBox); + + Versions versions = versionable.getVersions(); + int maxNumOfRevisions = getMaxNumOfRevisionsOfExistingVFSItem(); + String[] params = new String[]{ Integer.toString(maxNumOfRevisions), Integer.toString(versions.getRevisions().size()) }; + String title = translate("ul.tooManyRevisions.title", params); + String description = translate("ul.tooManyRevisions.description", params); + + revisionListCtr = new RevisionListController(ureq, getWindowControl(), versionable, null, description, false); + listenTo(revisionListCtr); + + revisionListDialogBox = new CloseableModalController(getWindowControl(), translate("delete"), revisionListCtr.getInitialComponent(), true, title); + listenTo(revisionListDialogBox); + revisionListDialogBox.activate(); + } + + private void askForUnlock(UserRequest ureq) { + removeAsListenerAndDispose(unlockCtr); + removeAsListenerAndDispose(unlockDialogBox); + + unlockCtr = new VersionCommentController(ureq,getWindowControl(), true, false); + listenTo(unlockCtr); + String title = unlockCtr.getAndRemoveFormTitle(); + unlockDialogBox = new CloseableModalController(getWindowControl(), translate("ok"), unlockCtr.getInitialComponent(), true, title); + listenTo(unlockDialogBox); + unlockDialogBox.activate(); + } + + private void askForComment(UserRequest ureq) { + removeAsListenerAndDispose(commentVersionCtr); + removeAsListenerAndDispose(commentVersionDialogBox); + + boolean locked = vfsLockManager.isLocked(existingVFSItem); + commentVersionCtr = new VersionCommentController(ureq, getWindowControl(), locked, true); + listenTo(commentVersionCtr); + String title = commentVersionCtr.getAndRemoveFormTitle(); + commentVersionDialogBox = new CloseableModalController(getWindowControl(), translate("save"), commentVersionCtr.getInitialComponent(), true, title); + listenTo(commentVersionDialogBox); + commentVersionDialogBox.activate(); + } + + private void doUpload(UserRequest ureq) { + // check for available space + if (remainingQuotKB != -1 && (fileEl.getUploadFile().length() / 1024 > remainingQuotKB)) { + fileEl.setErrorKey("QuotaExceeded", null); + fileEl.getUploadFile().delete(); + return; + } + + String fileName = fileEl.getUploadFileName(); + if(metaDataCtr != null && StringHelper.containsNonWhitespace(metaDataCtr.getFilename())) { + fileName = metaDataCtr.getFilename(); + } + + File uploadedFile = fileEl.getUploadFile(); + if(resizeImg && fileName != null && imageExtPattern.matcher(fileName.toLowerCase()).find() + && resizeEl.isSelected(0)) { + String extension = FileUtils.getFileSuffix(fileName); + File imageScaled = new File(uploadedFile.getParentFile(), "scaled_" + uploadedFile.getName() + "." + extension); + if(imageHelper.scaleImage(uploadedFile, extension, imageScaled, 1280, 1280, false) != null) { + //problem happen, special GIF's (see bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6358674) + //don't try to scale if not all ok + uploadedFile = imageScaled; + } + } + + // check if such a filename does already exist + existingVFSItem = uploadVFSContainer.resolve(fileName); + if (existingVFSItem == null) { + uploadNewFile(ureq, uploadedFile, fileName); + } else { + // file already exists... upload anyway with new filename and + // in the folder manager status. + // rename file and ask user what to do + if ( ! (existingVFSItem instanceof LocalImpl)) { + throw new AssertException("Can only LocalImpl VFS items, don't know what to do with file of type::" + existingVFSItem.getClass().getCanonicalName()); + } - boolean locked = vfsLockManager.isLocked(existingVFSItem); - commentVersionCtr = new VersionCommentController(ureq,getWindowControl(), locked, true); - listenTo(commentVersionCtr); - commentVersionDialogBox = new CloseableModalController(getWindowControl(), translate("save"), commentVersionCtr.getInitialComponent()); - listenTo(commentVersionDialogBox); - commentVersionDialogBox.activate(); - } else { - - removeAsListenerAndDispose(revisionListCtr); - revisionListCtr = new RevisionListController(ureq,getWindowControl(),versionable, false); - listenTo(revisionListCtr); - - removeAsListenerAndDispose(revisionListDialogBox); - revisionListDialogBox = new CloseableModalController(getWindowControl(), translate("delete"), revisionListCtr.getInitialComponent()); - listenTo(revisionListDialogBox); - - revisionListDialogBox.activate(); - } + String renamedFilename = VFSManager.rename(uploadVFSContainer, existingVFSItem.getName()); + newFile = uploadVFSContainer.createChildLeaf(renamedFilename); + + // Copy content to tmp file + boolean success = false; + try(InputStream in = new FileInputStream(uploadedFile); + BufferedOutputStream out = new BufferedOutputStream(newFile.getOutputStream(false))) { + success = FileUtils.copy(in, out); + uploadedFile.delete(); + } catch (IOException e) { + success = false; + } + + if (success) { + boolean locked = vfsLockManager.isLockedForMe(existingVFSItem, getIdentity(), ureq.getUserSession().getRoles()); + if (locked) { + //the file is locked and cannot be overwritten + lockedFileDialog(ureq, renamedFilename); + } else if (existingVFSItem instanceof Versionable && ((Versionable)existingVFSItem).getVersions().isVersioned()) { + uploadVersionedFile(ureq, renamedFilename); + } else { + askOverwriteOrRename(ureq, renamedFilename); } + } else { + showError("failed"); + status = FolderCommandStatus.STATUS_FAILED; + fireEvent(ureq, Event.FAILED_EVENT); } } } + private void lockedFileDialog(UserRequest ureq, String renamedFilename) { + removeAsListenerAndDispose(lockedFileDialog); + String title = translate("ul.lockedFile.title"); + String text = translate("ul.lockedFile.text", new String[] { existingVFSItem.getName(), renamedFilename} ); + lockedFileDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), title, text, + asList(translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); + listenTo(lockedFileDialog); + lockedFileDialog.activate(); + } + + private void uploadVersionedFile(UserRequest ureq, String renamedFilename) { + Versionable versionable = (Versionable)existingVFSItem; + Versions versions = versionable.getVersions(); + int maxNumOfRevisions = getMaxNumOfRevisionsOfExistingVFSItem(); + if(maxNumOfRevisions == 0) { + //it's possible if someone change the configuration + // let calling method decide what to do. + askOverwriteOrRename(ureq, renamedFilename); + } else if(versions.getRevisions().isEmpty() || maxNumOfRevisions < 0 || maxNumOfRevisions > versions.getRevisions().size()) { + // let calling method decide what to do. + askNewVersionOrRename(ureq, renamedFilename); + } else { + //too many revisions + askToReduceRevisionList(ureq, versionable); + } + } + + private void askOverwriteOrRename(UserRequest ureq, String renamedFilename) { + removeAsListenerAndDispose(overwriteDialog); + // let calling method decide what to do. + // for this, we put a list with "existing name" and "new name" + overwriteDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), + translate("ul.overwrite.threeoptions.title"), translate("ul.overwrite.threeoptions.text", new String[] {existingVFSItem.getName(), renamedFilename} ), + asList(translate("ul.overwrite.threeoptions.overwrite"), translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); + listenTo(overwriteDialog); + overwriteDialog.activate(); + } + + private void askNewVersionOrRename(UserRequest ureq, String renamedFilename) { + removeAsListenerAndDispose(overwriteDialog); + overwriteDialog = DialogBoxUIFactory.createGenericDialog(ureq, getWindowControl(), + translate("ul.overwrite.threeoptions.title"), translate("ul.versionoroverwrite", new String[] {existingVFSItem.getName(), renamedFilename} ), + asList(translate("ul.overwrite.threeoptions.newVersion"), translate("ul.overwrite.threeoptions.rename", renamedFilename), translate("ul.overwrite.threeoptions.cancel"))); + listenTo(overwriteDialog); + overwriteDialog.activate(); + } + + private void uploadNewFile(UserRequest ureq, File uploadedFile, String filename) { + // save file and finish + newFile = uploadVFSContainer.createChildLeaf(filename); + + boolean success = true; + if(newFile == null) { + // FXOLAT-409 somehow "createChildLeaf" did not succeed... + // if so, there is alread a error-msg in log (vfsContainer.createChildLeaf) + success = false; + } else { + try(InputStream in = new FileInputStream(uploadedFile); + OutputStream out = newFile.getOutputStream(false)) { + FileUtils.bcopy(in, out, "uploadTmpFileToDestFile"); + uploadedFile.delete(); + } catch (IOException e) { + success = false; + } + } + + if (success) { + String filePath = (uploadRelPath == null ? "" : uploadRelPath + "/") + newFile.getName(); + finishSuccessfullUpload(filePath, newFile, ureq); + fileInfoMBean.logUpload(newFile.getSize()); + fireEvent(ureq, Event.DONE_EVENT); + } else { + showError("failed"); + status = FolderCommandStatus.STATUS_FAILED; + fireEvent(ureq, Event.FAILED_EVENT); + } + } + private void finishUpload(UserRequest ureq) { // in both cases the upload must be finished and notified with a FolderEvent String filePath = (uploadRelPath == null ? "" : uploadRelPath + "/") + newFile.getName(); @@ -681,11 +706,11 @@ public class FileUploadController extends FormBasicController { if (item instanceof OlatRootFileImpl) { OlatRootFileImpl relPathItem = (OlatRootFileImpl) item; // create meta data - MetaInfo meta = CoreSpringFactory.getImpl(MetaInfoFactory.class).createMetaInfoFor(relPathItem); + MetaInfo meta = metaInfoFactory.createMetaInfoFor(relPathItem); if (metaDataCtr != null) { meta = metaDataCtr.getMetaInfo(meta); } - meta.setAuthor(ureq.getIdentity()); + meta.setAuthor(getIdentity()); meta.clearThumbnails();//if overwrite an older file meta.write(); } @@ -836,27 +861,37 @@ public class FileUploadController extends FormBasicController { targetSubPath.clearError(); } } - // Check file name - String fileName = fileEl.getUploadFileName(); - if (!StringHelper.containsNonWhitespace(fileName)) { - fileEl.setErrorKey("NoFileChosen", null); - return false; + if(metaDataCtr != null && StringHelper.containsNonWhitespace(metaDataCtr.getFilename())) { + return validateFilename(metaDataCtr.getFilename(), metaDataCtr.getFilenameEl()); + } + String filename = fileEl.getUploadFileName(); + return validateFilename(filename, fileEl); + } + + private boolean validateFilename(String filename, FormItem itemEl) { + itemEl.clearError(); + + + boolean allOk = true; + if (!StringHelper.containsNonWhitespace(filename)) { + itemEl.setErrorKey("NoFileChosen", null); + allOk &= false; } - boolean isFilenameValid = FileUtils.validateFilename(fileName); + boolean isFilenameValid = FileUtils.validateFilename(filename); if(!isFilenameValid) { - fileEl.setErrorKey("cfile.name.notvalid", null); - return false; + itemEl.setErrorKey("cfile.name.notvalid", null); + allOk &= false; } if (remainingQuotKB != -1 && fileEl.getUploadFile().length() / 1024 > remainingQuotKB) { - fileEl.clearError(); String supportAddr = WebappHelper.getMailConfig("mailQuota"); getWindowControl().setError(translate("ULLimitExceeded", new String[] { Formatter.roundToString((uploadLimitKB+0f) / 1000, 1), supportAddr })); - return false; + allOk &= false; } - return true; + + return allOk; } } diff --git a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdUpload.java b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdUpload.java index b782e332be93468a63a0d0f7dbfb8925ff4228e2..f8d16350649da824299dff2b3c93c09756b33736 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/commands/CmdUpload.java +++ b/src/main/java/org/olat/core/commons/modules/bc/commands/CmdUpload.java @@ -75,7 +75,7 @@ public class CmdUpload extends BasicController implements FolderCommand { private String uploadFileName; private VFSLeaf vfsNewFile; private long quotaKB; - private int uploadLimitKB; + private long uploadLimitKB; private boolean overwritten = false; private FileUploadController fileUploadCtr; private boolean cancelResetsForm; @@ -93,13 +93,14 @@ public class CmdUpload extends BasicController implements FolderCommand { this.showMetadata = showMetadata; } + @Override public Controller execute(FolderComponent fc, UserRequest ureq, WindowControl windowControl, Translator trans) { return execute(fc, ureq, trans, false); } - public Controller execute(FolderComponent fc, UserRequest ureq, Translator trans, boolean cancelResetsForm) { + public Controller execute(FolderComponent fc, UserRequest ureq, Translator trans, boolean cancelResetsButton) { this.folderComponent = fc; - this.cancelResetsForm = cancelResetsForm; + this.cancelResetsForm = cancelResetsButton; setTranslator(trans); currentContainer = folderComponent.getCurrentContainer(); @@ -130,21 +131,25 @@ public class CmdUpload extends BasicController implements FolderCommand { } } // set wether we have a quota on this folder - if (quotaKB == Quota.UNLIMITED) ubar.setIsNoMax(true); - else ubar.setMax(quotaKB / 1024); + if (quotaKB == Quota.UNLIMITED) { + ubar.setIsNoMax(true); + } else { + ubar.setMax(quotaKB / 1024); + } // set default ulLimit if none is defined... - if (uploadLimitKB == Quota.UNLIMITED) - uploadLimitKB = (int) QuotaManager.getInstance().getDefaultQuotaDependingOnRole(ureq.getIdentity()).getUlLimitKB().longValue(); + if (uploadLimitKB == Quota.UNLIMITED) { + uploadLimitKB = QuotaManager.getInstance().getDefaultQuotaDependingOnRole(ureq.getIdentity()).getUlLimitKB().longValue(); + } // Add file upload form - int remainingQuotaKB = (int) quotaKB - (int) actualUsage; - if (quotaKB == Quota.UNLIMITED) remainingQuotaKB = (int) quotaKB; + long remainingQuotaKB = quotaKB - actualUsage; + if (quotaKB == Quota.UNLIMITED) remainingQuotaKB = quotaKB; else if (quotaKB - actualUsage < 0) remainingQuotaKB = 0; - else remainingQuotaKB = (int) quotaKB - (int) actualUsage; + else remainingQuotaKB = quotaKB - actualUsage; + removeAsListenerAndDispose(fileUploadCtr); - fileUploadCtr = new FileUploadController(getWindowControl(), currentContainer, ureq, uploadLimitKB, remainingQuotaKB, null, - true, showMetadata, true, showCancel, true); + true, showMetadata, true, showCancel, false); listenTo(fileUploadCtr); mainVC.put("fileUploadCtr", fileUploadCtr.getInitialComponent()); mainVC.contextPut("showFieldset", Boolean.TRUE); @@ -201,7 +206,7 @@ public class CmdUpload extends BasicController implements FolderCommand { @Override public String getModalTitle() { - return translate("ul.quote"); + return translate("ul"); } public void event(UserRequest ureq, Component source, Event event) { diff --git a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java index 7e41c6e7a546563557830c6c684b559be3c4c46e..d1b606f3a4735ab95ef6b90bb778336220526e3d 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java +++ b/src/main/java/org/olat/core/commons/modules/bc/meta/MetaInfoFormController.java @@ -56,6 +56,7 @@ import org.olat.core.util.vfs.VFSLeaf; import org.olat.core.util.vfs.VFSLockManager; import org.olat.core.util.vfs.lock.LockInfo; import org.olat.user.UserManager; +import org.springframework.beans.factory.annotation.Autowired; /** * This is the metadata flexiform controller with or without upload capability. @@ -78,9 +79,13 @@ public class MetaInfoFormController extends FormBasicController { private String resourceUrl; private final Roles roles; - private final UserManager userManager; - private final VFSLockManager vfsLockManager; - private final MetaInfoFactory metaInfoFactory; + + @Autowired + private UserManager userManager; + @Autowired + private VFSLockManager vfsLockManager; + @Autowired + private MetaInfoFactory metaInfoFactory; /** * Use this controller for editing meta data of an existing file. @@ -95,9 +100,6 @@ public class MetaInfoFormController extends FormBasicController { this.resourceUrl = resourceUrl; // load the metainfo roles = ureq.getUserSession().getRoles(); - userManager = CoreSpringFactory.getImpl(UserManager.class); - vfsLockManager = CoreSpringFactory.getImpl(VFSLockManager.class); - metaInfoFactory = CoreSpringFactory.getImpl(MetaInfoFactory.class); initForm(ureq); } @@ -112,9 +114,6 @@ public class MetaInfoFormController extends FormBasicController { public MetaInfoFormController(UserRequest ureq, WindowControl control, Form parentForm) { super(ureq, control, FormBasicController.LAYOUT_DEFAULT, null, parentForm); roles = ureq.getUserSession().getRoles(); - userManager = CoreSpringFactory.getImpl(UserManager.class); - vfsLockManager = CoreSpringFactory.getImpl(VFSLockManager.class); - metaInfoFactory = CoreSpringFactory.getImpl(MetaInfoFactory.class); isSubform = true; initForm(ureq); } @@ -132,9 +131,6 @@ public class MetaInfoFormController extends FormBasicController { isSubform = true; this.item = vfsItem; roles = ureq.getUserSession().getRoles(); - userManager = CoreSpringFactory.getImpl(UserManager.class); - vfsLockManager = CoreSpringFactory.getImpl(VFSLockManager.class); - metaInfoFactory = CoreSpringFactory.getImpl(MetaInfoFactory.class); initForm(ureq); } @@ -189,21 +185,19 @@ public class MetaInfoFormController extends FormBasicController { setFormTitle("mf.metadata.title"); } setFormContextHelp("Folders#_metadata"); - - // filename - if (!isSubform) { - initialFilename = item.getName(); - filename = uifactory.addTextElement("filename", "mf.filename", -1, item.getName(), formLayout); - filename.setEnabled(item.canRename() == VFSConstants.YES); - filename.setNotEmptyCheck("mf.error.empty"); - filename.setMandatory(true); - } MetaInfo meta = item instanceof OlatRelPathImpl ? metaInfoFactory.createMetaInfoFor((OlatRelPathImpl)item) : null; // title String titleVal = (meta != null ? meta.getTitle() : null); title = uifactory.addTextElement("title", "mf.title", -1, titleVal, formLayout); + + // filename + initialFilename = (item == null ? null : item.getName()); + filename = uifactory.addTextElement("filename", "mf.filename", -1, initialFilename, formLayout); + filename.setEnabled(item == null || item.canRename() == VFSConstants.YES); + filename.setNotEmptyCheck("mf.error.empty"); + filename.setMandatory(true); // comment/description String commentVal = (meta != null ? meta.getComment() : null); @@ -405,6 +399,14 @@ public class MetaInfoFormController extends FormBasicController { return filename.getValue(); } + public TextElement getFilenameEl() { + return filename; + } + + public void setFilename(String name) { + filename.setValue(name); + } + public MetaInfo getMetaInfo(MetaInfo meta) { meta.setCreator(creator.getValue()); meta.setComment(comment.getValue()); diff --git a/src/main/java/org/olat/core/commons/modules/bc/version/VersionCommentController.java b/src/main/java/org/olat/core/commons/modules/bc/version/VersionCommentController.java index a3687157edd48341bd7f1267ed067a96bb023b0b..b844f1224f4ef1c94acdd06d0e8ab01d4cc433f1 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/version/VersionCommentController.java +++ b/src/main/java/org/olat/core/commons/modules/bc/version/VersionCommentController.java @@ -60,7 +60,7 @@ public class VersionCommentController extends FormBasicController { initForm(ureq); } - + @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { if(comment && lock) { diff --git a/src/main/java/org/olat/core/commons/modules/bc/version/_content/revisions.html b/src/main/java/org/olat/core/commons/modules/bc/version/_content/revisions.html index 1dfcf16e55486f39f44170b14fcd723a7bdb4ab3..cf46480a75b14198b8676913f93d6399a5d78f75 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/version/_content/revisions.html +++ b/src/main/java/org/olat/core/commons/modules/bc/version/_content/revisions.html @@ -2,6 +2,6 @@ <h5>$title</h5> #end #if ($description) - <p>$description</p> + <p class="o_info">$description</p> #end $r.render("revisionList") \ No newline at end of file diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java index 574ced700c0591e091b07b7988256a627c181eea..bb7cfc19ad0c9c7f469dc33453a873daab137595 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/FormBasicController.java @@ -433,6 +433,14 @@ public abstract class FormBasicController extends BasicController implements IFo } } } + + public String getAndRemoveFormTitle() { + String title = (String)flc.contextGet("off_title"); + if(title != null) { + flc.contextRemove("off_title"); + } + return title; + } /** * Set an optional form title that is rendered as a fieldset legend. If you