From 7d2843e018c49a79a91e0a2dac35dbbaaf6f26a1 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Wed, 12 Apr 2017 14:09:11 +0200 Subject: [PATCH] OO-2693: add stricter validation for the upload in QTI 2.1 editor --- .../LinkFileCombiCalloutController.java | 2 +- .../FileLinkChooserController.java | 8 +- .../linkchooser/LinkChooserController.java | 5 +- .../linkchooser/MediaChooserController.java | 2 +- .../modules/bc/FileCopyController.java | 2 +- .../modules/bc/FileUploadController.java | 85 ++++++++++++++----- .../bc/_i18n/LocalStrings_de.properties | 1 + .../bc/_i18n/LocalStrings_en.properties | 1 + .../modules/bc/commands/CmdUpload.java | 2 +- .../form/flexible/FormUIFactory.java | 4 +- .../richText/RichTextConfiguration.java | 15 +++- .../richText/RichTextElementComponent.java | 5 +- .../ims/qti21/pool/QTI12To21Converter.java | 11 ++- .../ims/qti21/pool/QTI12To21HtmlHandler.java | 14 +++ .../dialog/DialogElementsController.java | 4 +- .../wiki/WikiFileUploadController.java | 2 +- 16 files changed, 125 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/olat/core/commons/controllers/filechooser/LinkFileCombiCalloutController.java b/src/main/java/org/olat/core/commons/controllers/filechooser/LinkFileCombiCalloutController.java index 0256f6f0210..eb3515865c5 100644 --- a/src/main/java/org/olat/core/commons/controllers/filechooser/LinkFileCombiCalloutController.java +++ b/src/main/java/org/olat/core/commons/controllers/filechooser/LinkFileCombiCalloutController.java @@ -300,7 +300,7 @@ public class LinkFileCombiCalloutController extends BasicController { // remove file name from relFilePath to represent directory path folderPath = relFilePath.substring(0, relFilePath.lastIndexOf("/")); } - toolCtr = new FileUploadController(getWindowControl(), baseContainer, ureq, quotaLeftKB, quotaLeftKB, null, true, false, false, true, true, folderPath); + toolCtr = new FileUploadController(getWindowControl(), baseContainer, ureq, quotaLeftKB, quotaLeftKB, null, false, true, false, false, true, true, folderPath); } displayModal(toolCtr); } diff --git a/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java b/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java index 64cf8755bf5..4a2980e052f 100644 --- a/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java +++ b/src/main/java/org/olat/core/commons/controllers/linkchooser/FileLinkChooserController.java @@ -90,13 +90,15 @@ public class FileLinkChooserController extends BasicController { * @param rootDir The VFS root directory from which the linkable files should be read * @param uploadRelPath The relative path within the rootDir where uploaded * files should be put into. If NULL, the root Dir is used + * @param absolutePath * @param suffixes Array of allowed file types + * @param uriValidation Set to true if the filename need to be a valid URI * @param fileName the path of the file currently edited (in order to compute * the correct relative paths for links), e.g. bla/blu.html or * index.html */ public FileLinkChooserController(UserRequest ureq, WindowControl wControl, - VFSContainer rootDir, String uploadRelPath, String absolutePath, String[] suffixes, String fileName) { + VFSContainer rootDir, String uploadRelPath, String absolutePath, String[] suffixes, boolean uriValidation, String fileName) { super(ureq, wControl); this.fileName = fileName; this.suffixes = suffixes; @@ -167,8 +169,8 @@ public class FileLinkChooserController extends BasicController { } } - uploadCtr = new FileUploadController(wControl, fileUploadBase, ureq, uploadLimit, remainingSpace, mimeTypes, - true, false, true, true, false); + uploadCtr = new FileUploadController(wControl, fileUploadBase, ureq, uploadLimit, remainingSpace, + mimeTypes, uriValidation, true, false, true, true, false); listenTo(uploadCtr); // set specific upload path uploadCtr.setUploadRelPath(uploadRelPath); diff --git a/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java b/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java index fc074917857..88d2b5cf4ec 100644 --- a/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java +++ b/src/main/java/org/olat/core/commons/controllers/linkchooser/LinkChooserController.java @@ -63,6 +63,7 @@ public class LinkChooserController extends BasicController { * @param uploadRelPath The relative path within the rootDir where uploaded * files should be put into. If NULL, the root Dir is used * @param suffixes Supported file suffixes for file-chooser. + * @param uriValidation Set to true if the filename need to be a valid URI * @param fileName Base file-path for file-chooser. * @param userActivityLogger * @param internalLinkTreeModel Model with internal links e.g. course-node @@ -70,7 +71,7 @@ public class LinkChooserController extends BasicController { * internalLinkTreeModel is null. */ public LinkChooserController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir, - String uploadRelPath, String absolutPath, String[] suffixes, String fileName, + String uploadRelPath, String absolutPath, String[] suffixes, boolean uriValidation, String fileName, CustomLinkTreeModel customLinkTreeModel, boolean allowCustomMediaChooserFactory) { super(ureq, wControl); @@ -79,7 +80,7 @@ public class LinkChooserController extends BasicController { linkChooserTabbedPane = new TabbedPane("linkChooserTabbedPane", ureq.getLocale()); tabbedPaneViewVC.put("linkChooserTabbedPane", linkChooserTabbedPane); - fileLinkChooserController = new FileLinkChooserController(ureq, wControl, rootDir, uploadRelPath, absolutPath, suffixes, fileName); + fileLinkChooserController = new FileLinkChooserController(ureq, wControl, rootDir, uploadRelPath, absolutPath, suffixes, uriValidation, fileName); listenTo(fileLinkChooserController); linkChooserTabbedPane.addTab(translate("linkchooser.tabbedpane.label.filechooser"), fileLinkChooserController.getInitialComponent()); diff --git a/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java b/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java index 3a75162fc81..120db398b52 100644 --- a/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java +++ b/src/main/java/org/olat/core/commons/controllers/linkchooser/MediaChooserController.java @@ -64,7 +64,7 @@ public class MediaChooserController extends LinkChooserController { */ public MediaChooserController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir, String uploadRelPath, String[] suffixes, String fileName, CustomLinkTreeModel customLinkTreeModel, boolean allowCustomMediaFactory) { - super(ureq, wControl, rootDir, uploadRelPath, null, suffixes, fileName, customLinkTreeModel, allowCustomMediaFactory); + super(ureq, wControl, rootDir, uploadRelPath, null, suffixes, false, fileName, customLinkTreeModel, allowCustomMediaFactory); } /** 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 e44be4aef6e..8a33a38a43d 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 @@ -87,7 +87,7 @@ public class FileCopyController extends LinkChooserController { public FileCopyController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir, FolderComponent folderComponent) { - super(ureq, wControl, rootDir, null, null, null, "", null, true); + super(ureq, wControl, rootDir, null, null, null, false, "", null, true); this.folderComponent = folderComponent; vfsLockManager = CoreSpringFactory.getImpl(VFSLockManager.class); } 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 99c36669dbb..06ca204f17f 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 @@ -33,6 +33,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -123,6 +124,7 @@ public class FileUploadController extends FormBasicController { private long uploadLimitKB; private long remainingQuotKB; private Set<String> mimeTypes; + private boolean uriValidation; // // Form elements private FileElement fileEl; @@ -174,23 +176,23 @@ public class FileUploadController extends FormBasicController { */ public FileUploadController(WindowControl wControl, VFSContainer curContainer, UserRequest ureq, long upLimitKB, long remainingQuotKB, Set<String> mimeTypesRestriction, boolean showTargetPath) { - this(wControl, curContainer, ureq, upLimitKB, remainingQuotKB, mimeTypesRestriction, showTargetPath, false, true, true, true); + this(wControl, curContainer, ureq, upLimitKB, remainingQuotKB, mimeTypesRestriction, false, showTargetPath, false, true, true, true); } 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) { + Set<String> mimeTypesRestriction, boolean uriValidation, boolean showTargetPath, boolean showMetadata, boolean resizeImg, boolean showCancel, boolean showTitle) { this(wControl,curContainer, ureq, upLimitKB, remainingQuotKB, - mimeTypesRestriction, showTargetPath, showMetadata, resizeImg, showCancel, showTitle,null); + mimeTypesRestriction, uriValidation, showTargetPath, showMetadata, resizeImg, showCancel, showTitle,null); } 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) { + Set<String> mimeTypesRestriction, boolean uriValidation, boolean showTargetPath, boolean showMetadata, boolean resizeImg, boolean showCancel, boolean showTitle, String subfolderPath) { super(ureq, wControl, "file_upload"); - setVariables(curContainer, upLimitKB, remainingQuotKB, mimeTypesRestriction, showTargetPath, showMetadata, resizeImg, showCancel, showTitle, subfolderPath); + setVariables(curContainer, upLimitKB, remainingQuotKB, mimeTypesRestriction, uriValidation, showTargetPath, showMetadata, resizeImg, showCancel, showTitle, subfolderPath); initForm(ureq); } - private void setVariables(VFSContainer curContainer, long upLimitKB, long remainingQuotKB, Set<String> mimeTypesRestriction, boolean showTargetPath, + private void setVariables(VFSContainer curContainer, long upLimitKB, long remainingQuotKB, Set<String> mimeTypesRestriction, boolean uriValidation, boolean showTargetPath, boolean showMetadata, boolean resizeImg, boolean showCancel, boolean showTitle, String subfolderPath) { this.currentContainer = curContainer; this.mimeTypes = mimeTypesRestriction; @@ -198,6 +200,7 @@ public class FileUploadController extends FormBasicController { this.showTargetPath = showTargetPath; // set remaining quota and max upload size this.uploadLimitKB = upLimitKB; + this.uriValidation = uriValidation; this.remainingQuotKB = remainingQuotKB; // use base container as upload dir this.uploadRelPath = null; @@ -883,13 +886,42 @@ public class FileUploadController extends FormBasicController { if(metaDataCtr != null && StringHelper.containsNonWhitespace(metaDataCtr.getFilename())) { return validateFilename(metaDataCtr.getFilename(), metaDataCtr.getFilenameEl()); } - String filename = fileEl.getUploadFileName(); - - boolean allOk = validateFilename(filename, fileEl); + + boolean allOk = validateFilename(fileEl); + return allOk; + } + + private boolean validateFilename(FileElement itemEl) { + boolean allOk = true; + // validate clean the errors List<ValidationStatus> fileStatus = new ArrayList<>(); - fileEl.validate(fileStatus);//revalidate because we clear the error - fileEl.setDeleteEnabled(fileStatus.size() > 0); - return allOk && fileStatus.isEmpty(); + // revalidate + itemEl.validate(fileStatus); + + if(fileStatus.isEmpty()) { + String filename = itemEl.getUploadFileName(); + if (!StringHelper.containsNonWhitespace(filename)) { + itemEl.setErrorKey("NoFileChosen", null); + allOk &= false; + } + + if(uriValidation) { + try { + new URI(filename); + } catch(Exception e) { + itemEl.setErrorKey("cfile.name.notvalid.uri", null); + allOk &= false; + } + } + if(!FileUtils.validateFilename(filename)) { + itemEl.setErrorKey("cfile.name.notvalid", null); + allOk &= false; + } + allOk &= validateQuota(itemEl); + } + + itemEl.setDeleteEnabled(!allOk); + return allOk; } private boolean validateFilename(String filename, FormItem itemEl) { @@ -900,20 +932,31 @@ public class FileUploadController extends FormBasicController { itemEl.setErrorKey("NoFileChosen", null); allOk &= false; } - - boolean isFilenameValid = FileUtils.validateFilename(filename); - if(!isFilenameValid) { + + if(uriValidation) { + try { + new URI(filename); + } catch(Exception e) { + itemEl.setErrorKey("cfile.name.notvalid.uri", null); + allOk &= false; + } + } + if(!FileUtils.validateFilename(filename)) { itemEl.setErrorKey("cfile.name.notvalid", null); allOk &= false; } - if (remainingQuotKB != -1 && fileEl.getUploadFile() != null - && fileEl.getUploadFile().length() / 1024 > remainingQuotKB) { - fileEl.clearError(); + + allOk &= validateQuota(fileEl); + return allOk; + } + + private boolean validateQuota(FileElement itemEl) { + if (remainingQuotKB != -1 && itemEl.getUploadFile() != null + && itemEl.getUploadFile().length() / 1024 > remainingQuotKB) { String supportAddr = WebappHelper.getMailConfig("mailQuota"); getWindowControl().setError(translate("ULLimitExceeded", new String[] { Formatter.roundToString((uploadLimitKB+0f) / 1000, 1), supportAddr })); - allOk &= false; + return false; } - - return allOk; + return true; } } diff --git a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties index ff4b9658c21..af0b600ef24 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_de.properties @@ -45,6 +45,7 @@ cfile.name.nodir=Ein Verzeichnis kann nicht als Dateiname verwendet werden. cfile.name.noextension=Diese Datei enth\u00E4lt keine Erweiterung. Bitte f\u00FCgen Sie eine Erweiterung an bevor Sie die Datei erneut hochladen. cfile.name.noname=Kein Dateiname angegeben. cfile.name.notvalid=Dieser Dateiname enth\u00E4lt unzul\u00E4ssige Zeichen, bitte entfernen Sie alle Sonderzeichen wie /,\:, etc. +cfile.name.notvalid.uri=Dieser Dateiname enth\u00E4lt unzul\u00E4ssige Zeichen, bitte entfernen Sie alle Sonderzeichen wie /,\:, Leerzeichen etc. cfile.name.notvalid.cannot.edit.metadata=Dieser Dateiname enth\u00E4lt unzul\u00E4ssige Zeichen, Sie k\u00F6nnen die Metadaten daher nicht editieren. cfile.name.notvalidchars=Dieser Dateiname enth\u00E4lt die unzul\u00E4ssigen Zeichen "{0}". Bitte entfernen Sie diese bevor Sie die Datei erneut hochladen. checkall=Alle ausw\u00E4hlen diff --git a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties index cdbea214a9d..73911c3423c 100644 --- a/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/core/commons/modules/bc/_i18n/LocalStrings_en.properties @@ -45,6 +45,7 @@ cfile.name.nodir=Can't use a directory as a file name. cfile.name.noextension=This file name contains no extension. Please add a file extension before uploading the file. cfile.name.noname=No file name given. cfile.name.notvalid=This file name contains invalid characters. Please remove these special characters before uploading the file again. +cfile.name.notvalid.uri=This file name contains invalid characters. Please remove these special characters like /,\:, blank... before uploading the file again. cfile.name.notvalid.cannot.edit.metadata=This file name contains invalid characters. Metadata cannot be edited. cfile.name.notvalidchars=This file name contains the invalid characters "{0}". Please remove them before uploading the file again. checkall=Select all 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 f8d16350649..eb630687a0e 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 @@ -148,7 +148,7 @@ public class CmdUpload extends BasicController implements FolderCommand { else remainingQuotaKB = quotaKB - actualUsage; removeAsListenerAndDispose(fileUploadCtr); - fileUploadCtr = new FileUploadController(getWindowControl(), currentContainer, ureq, uploadLimitKB, remainingQuotaKB, null, + fileUploadCtr = new FileUploadController(getWindowControl(), currentContainer, ureq, uploadLimitKB, remainingQuotaKB, null, false, true, showMetadata, true, showCancel, false); listenTo(fileUploadCtr); mainVC.put("fileUploadCtr", fileUploadCtr.getInitialComponent()); diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java b/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java index ba5ea347a8b..857012b711e 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/FormUIFactory.java @@ -767,7 +767,7 @@ public class FormUIFactory { /** * * This is a version with olat media only. The tiny media is disabled because we need to catch the object - * tag use by QTI and interpret it as a olat video. + * tag use by QTI and interpret it as a olat video. It enable the strict uri validation for file names. * * @param name * @param i18nLabel @@ -791,6 +791,7 @@ public class FormUIFactory { rte.getEditorConfiguration().setInvalidElements(RichTextConfiguration.INVALID_ELEMENTS_FORM_FULL_VALUE_UNSAVE_WITH_SCRIPT); rte.getEditorConfiguration().setExtendedValidElements("script[src|type|defer]"); rte.getEditorConfiguration().disableTinyMedia(); + rte.getEditorConfiguration().setFilenameUriValidation(true); // Add to form and finish formLayout.add(rte); return rte; @@ -807,6 +808,7 @@ public class FormUIFactory { rte.getEditorConfiguration().setInvalidElements(RichTextConfiguration.INVALID_ELEMENTS_FORM_FULL_VALUE_UNSAVE_WITH_SCRIPT); rte.getEditorConfiguration().setExtendedValidElements("script[src|type|defer]"); rte.getEditorConfiguration().disableTinyMedia(); + rte.getEditorConfiguration().setFilenameUriValidation(true); // Add to form and finish formLayout.add(rte); return rte; diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java index 5c434a6300b..4e0541b0871 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextConfiguration.java @@ -156,6 +156,7 @@ public class RichTextConfiguration implements Disposable { private boolean inline = false; private boolean sendOnBlur; private boolean readOnly; + private boolean filenameUriValidation = false; private CustomLinkTreeModel linkBrowserCustomTreeModel; // DOM ID of the flexi form element private String domID; @@ -882,8 +883,20 @@ public class RichTextConfiguration implements Disposable { public void enableEditorHeight() { setNonQuotedConfigValue(RichTextConfiguration.HEIGHT, "b_initialEditorHeight()"); } - + public boolean isFilenameUriValidation() { + return filenameUriValidation; + } + + /** + * Enable the validation of the URI for filename base on java.net.URI + * + * @param filenameUriValidation + */ + public void setFilenameUriValidation(boolean filenameUriValidation) { + this.filenameUriValidation = filenameUriValidation; + } + /** * Get the image suffixes that are supported * diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java index 58ad6a686e4..4836447aac7 100644 --- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java +++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/richText/RichTextElementComponent.java @@ -136,6 +136,7 @@ class RichTextElementComponent extends FormBaseComponentImpl { // Get allowed suffixes from configuration and requested media browser type from event final RichTextConfiguration config = element.getEditorConfiguration(); final boolean allowCustomMediaFactory = config.isAllowCustomMediaFactory(); + final boolean uriValidation = config.isFilenameUriValidation(); final String[] suffixes; if(type.equals(CMD_FILEBROWSER)) { suffixes = null; @@ -162,10 +163,10 @@ class RichTextElementComponent extends FormBaseComponentImpl { CustomLinkTreeModel linkBrowserCustomTreeModel = config.getLinkBrowserCustomLinkTreeModel(); if (type.equals(CMD_FILEBROWSER)) { // when in file mode we include the internal links to the selection - myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, fileName, linkBrowserCustomTreeModel, allowCustomMediaFactory); + myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, uriValidation, fileName, linkBrowserCustomTreeModel, allowCustomMediaFactory); } else { // in media or image mode, internal links make no sense here - myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, fileName, null, allowCustomMediaFactory); + myLinkChooserController = new LinkChooserController(lureq, lwControl, baseContainer, uploadRelPath, absolutePath, suffixes, uriValidation, fileName, null, allowCustomMediaFactory); } return new LayoutMain3ColsController(lureq, lwControl, myLinkChooserController); } diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java index 72fdff1e92a..85452ea9f3d 100644 --- a/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java +++ b/src/main/java/org/olat/ims/qti21/pool/QTI12To21Converter.java @@ -29,9 +29,11 @@ import java.io.Writer; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.DoubleAdder; @@ -137,6 +139,7 @@ public class QTI12To21Converter { private final ManifestBuilder manifest; private List<String> materialPath = new ArrayList<>(); + private Map<String,String> materialMappings = new HashMap<>(); private List<String> errors = new ArrayList<>(); private final DoubleAdder atomicMaxScore = new DoubleAdder(); @@ -298,6 +301,9 @@ public class QTI12To21Converter { VFSItem materialItem = originalContainer.resolve(material); if(materialItem instanceof VFSLeaf) { try(InputStream in = ((VFSLeaf) materialItem).getInputStream()) { + if(materialMappings.containsKey(material)) { + material = materialMappings.get(material); + } File dest = new File(unzippedDirRoot, material); FileUtils.copyToFile(in, dest, ""); } catch(Exception e) { @@ -721,10 +727,12 @@ public class QTI12To21Converter { XMLStreamWriter xtw = xof.createXMLStreamWriter(out); SAXParser parser = new SAXParser(); - parser.setContentHandler(new QTI12To21HtmlHandler(xtw)); + QTI12To21HtmlHandler handler = new QTI12To21HtmlHandler(xtw); + parser.setContentHandler(handler); parser.parse(new InputSource(new StringReader(trimmedText))); String blockedHtml = out.toString(); text = blockedHtml.replace("<start>", "").replace("</start>", ""); + materialMappings.putAll(handler.getMaterialsMapping()); } catch (FactoryConfigurationError | XMLStreamException | SAXException | IOException e) { log.error("", e); } @@ -733,6 +741,7 @@ public class QTI12To21Converter { text = StringEscapeUtils.unescapeHtml(text); } } + System.out.println(text); return text; } diff --git a/src/main/java/org/olat/ims/qti21/pool/QTI12To21HtmlHandler.java b/src/main/java/org/olat/ims/qti21/pool/QTI12To21HtmlHandler.java index 76c03abd74f..f1b086190d8 100644 --- a/src/main/java/org/olat/ims/qti21/pool/QTI12To21HtmlHandler.java +++ b/src/main/java/org/olat/ims/qti21/pool/QTI12To21HtmlHandler.java @@ -21,6 +21,8 @@ package org.olat.ims.qti21.pool; import java.util.ArrayDeque; import java.util.Deque; +import java.util.HashMap; +import java.util.Map; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; @@ -47,6 +49,7 @@ class QTI12To21HtmlHandler extends DefaultHandler { private int subLevel = 0; private Deque<String> skipTags = new ArrayDeque<String>(); + private Map<String,String> materialsMapping = new HashMap<>(); private boolean envelopP = false; private boolean started = false; @@ -54,6 +57,10 @@ class QTI12To21HtmlHandler extends DefaultHandler { public QTI12To21HtmlHandler(XMLStreamWriter xtw) { this.xtw = xtw; } + + public Map<String,String> getMaterialsMapping() { + return materialsMapping; + } @Override public void startDocument() throws SAXException { @@ -120,6 +127,13 @@ class QTI12To21HtmlHandler extends DefaultHandler { //ignore align } else if("xmlns".equals(attrQName) && !StringHelper.containsNonWhitespace(attrValue)) { //ignore empty schema + } else if("src".equals(attrQName)) { + if(attrValue.contains(" ")) { + String newValue = attrValue.replace(' ', '_'); + materialsMapping.put(attrValue, newValue); + attrValue = newValue; + } + xtw.writeAttribute(attrQName, attrValue); } else { xtw.writeAttribute(attrQName, attrValue); } diff --git a/src/main/java/org/olat/modules/dialog/DialogElementsController.java b/src/main/java/org/olat/modules/dialog/DialogElementsController.java index 9b6972d24bf..e3ec5ea6527 100644 --- a/src/main/java/org/olat/modules/dialog/DialogElementsController.java +++ b/src/main/java/org/olat/modules/dialog/DialogElementsController.java @@ -415,7 +415,7 @@ public class DialogElementsController extends BasicController { OlatRootFolderImpl forumContainer = getForumContainer(forum.getKey()); removeAsListenerAndDispose(fileUplCtr); - fileUplCtr = new FileUploadController(getWindowControl(),forumContainer, ureq, (int)FolderConfig.getLimitULKB(), Quota.UNLIMITED, null, false, false, false, true, false); + fileUplCtr = new FileUploadController(getWindowControl(),forumContainer, ureq, (int)FolderConfig.getLimitULKB(), Quota.UNLIMITED, null, false, false, false, false, true, false); listenTo(fileUplCtr); recentDialogElement = new DialogElement(); @@ -472,7 +472,7 @@ public class DialogElementsController extends BasicController { private class MyLinkChooserController extends LinkChooserController { public MyLinkChooserController(UserRequest ureq, WindowControl wControl, VFSContainer rootDir, String uploadRelPath) { - super(ureq, wControl, rootDir, uploadRelPath, null, null, "", null, true); + super(ureq, wControl, rootDir, uploadRelPath, null, null, false, "", null, true); } @Override diff --git a/src/main/java/org/olat/modules/wiki/WikiFileUploadController.java b/src/main/java/org/olat/modules/wiki/WikiFileUploadController.java index ee510144b7b..166dfc02e6b 100644 --- a/src/main/java/org/olat/modules/wiki/WikiFileUploadController.java +++ b/src/main/java/org/olat/modules/wiki/WikiFileUploadController.java @@ -49,7 +49,7 @@ public class WikiFileUploadController extends BasicController { VelocityContainer mainVC = this.createVelocityContainer("upload_file"); fileUplCtr = new FileUploadController(getWindowControl(), mediaFolder, ureq, - (int)FolderConfig.getLimitULKB(), Quota.UNLIMITED, null, false, false, true, true, false); + (int)FolderConfig.getLimitULKB(), Quota.UNLIMITED, null, false, false, false, true, true, false); listenTo(fileUplCtr); mainVC.put("fileUpload", fileUplCtr.getInitialComponent()); putInitialPanel(mainVC); -- GitLab