diff --git a/pom.xml b/pom.xml index 566cc0b05650d512b59063589d054fb9c5c936db..0d1feb20cb18fbe5fefc425df43fbac48509083c 100644 --- a/pom.xml +++ b/pom.xml @@ -1647,7 +1647,7 @@ <dependency> <groupId>org.openolat.jamwiki</groupId> <artifactId>jamwiki-core</artifactId> - <version>1.0.2</version> + <version>1.0.3</version> </dependency> <dependency> <groupId>org.openolat</groupId> diff --git a/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java b/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java index 7260236861f1fe3d845ff0a5a0180b729de363fd..154eb132926087fa88a3e9cea3d3a3e44b533736 100644 --- a/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java +++ b/src/main/java/org/olat/core/util/filter/impl/OpenOLATPolicy.java @@ -67,7 +67,7 @@ public class OpenOLATPolicy { .matching(Pattern.compile("[a-zA-Z]{2,20}")).globally() .allowUrlProtocols("mailto", "http", "https") - .allowElements("img", "a") + .allowElements("img", "a", "video", "audio") // Fix::dir .allowAttributes("charoff") .matching(Pattern.compile("numberOrPercent")) @@ -102,6 +102,15 @@ public class OpenOLATPolicy { .matching(NUMBER).onElements("img") .allowAttributes("width") .matching(NUMBERORPERCENT).onElements("img") + // video, audio + .allowAttributes("src") + .matching(new Patterns(ONSITEURL, OFFSITEURL)).onElements("audio", "video") + .allowAttributes("class") + .matching(HTMLCLASS).onElements("audio", "video") + .allowAttributes("height") + .matching(NUMBER).onElements("video") + .allowAttributes("width") + .matching(NUMBER).onElements("video") // edu-sharing .allowAttributes("data-es_identifier") .matching(Pattern.compile("[a-zA-Z0-9_\\-\\:]+")).onElements("img") @@ -239,7 +248,7 @@ public class OpenOLATPolicy { .allowElements("dd","tbody","dl","caption","hr","div","dt","ul","init","blockquote","pre","em","figcaption","sub", "strong","img","thead","h1","h2","h3","h4","h5","h6","sup","ol","table","b","figure","strike","i","p", - "tfoot","td","s","th","u","li","tr", "span") + "tfoot","td","s","th","u","li","tr", "span", "video", "audio") .allowElements("hr") .allowWithoutAttributes("hr") diff --git a/src/main/java/org/olat/core/util/vfs/VFSContainerMapper.java b/src/main/java/org/olat/core/util/vfs/VFSContainerMapper.java index 1c9d943856c6bf6f942eb3980c4046447669d88a..f52149bdfa272a7deb8ed0dc908341f0573d2cb1 100644 --- a/src/main/java/org/olat/core/util/vfs/VFSContainerMapper.java +++ b/src/main/java/org/olat/core/util/vfs/VFSContainerMapper.java @@ -44,13 +44,14 @@ public class VFSContainerMapper implements Mapper { this.container = container; } + @Override public MediaResource handle(String relPath, HttpServletRequest request) { VFSItem vfsItem = container.resolve(relPath); MediaResource mr; - if (vfsItem == null || !(vfsItem instanceof VFSLeaf)) { - mr = new NotFoundMediaResource(); - } else { + if (vfsItem instanceof VFSLeaf) { mr = new VFSMediaResource((VFSLeaf) vfsItem); + } else { + mr = new NotFoundMediaResource(); } return mr; } diff --git a/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java b/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java index 31aa8f78b42e6556b1a948119ef9fa0d42691bd3..d5c940ac90e3e8f7e5fc52021692dd1bee15e45b 100644 --- a/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java +++ b/src/main/java/org/olat/modules/video/ui/VideoTrackUploadForm.java @@ -19,7 +19,7 @@ */ package org.olat.modules.video.ui; -import java.text.SimpleDateFormat; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -69,7 +69,7 @@ public class VideoTrackUploadForm extends FormBasicController { protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { List<String> langs = new ArrayList<>(); List<String> dispLangs = new ArrayList<>(); - for(Locale locale : SimpleDateFormat.getAvailableLocales()){ + for(Locale locale : DateFormat.getAvailableLocales()){ if(locale.hashCode() != 0){ langs.add(locale.getLanguage()); dispLangs.add(locale.getDisplayLanguage(getTranslator().getLocale())); @@ -95,7 +95,7 @@ public class VideoTrackUploadForm extends FormBasicController { @Override protected boolean validateFormLogic(UserRequest ureq) { - boolean allOk = true; + boolean allOk = super.validateFormLogic(ureq); fileEl.clearError(); if (fileEl.isUploadSuccess()) { @@ -109,7 +109,7 @@ public class VideoTrackUploadForm extends FormBasicController { allOk &= false; } - return allOk & super.validateFormLogic(ureq); + return allOk; } @Override diff --git a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/OlatWikiDataHandler.java b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/OlatWikiDataHandler.java index b8bd857be2ec9060fef61003c0e94ccf713980ef..5a6f580695572391064145322003c31ab058e0bd 100644 --- a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/OlatWikiDataHandler.java +++ b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/OlatWikiDataHandler.java @@ -24,17 +24,25 @@ */ package org.olat.modules.wiki.gui.components.wikiToHtml; +import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import org.apache.logging.log4j.Logger; import org.jamwiki.DataHandler; +import org.jamwiki.WikiMediaDimension; import org.jamwiki.model.Topic; import org.jamwiki.model.WikiFile; import org.jamwiki.utils.InterWikiHandler; import org.jamwiki.utils.PseudoTopicHandler; +import org.olat.core.CoreSpringFactory; +import org.olat.core.commons.services.image.ImageService; +import org.olat.core.commons.services.image.Size; +import org.olat.core.commons.services.video.MovieService; import org.olat.core.id.OLATResourceable; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; +import org.olat.core.util.vfs.LocalFileImpl; +import org.olat.core.util.vfs.VFSLeaf; import org.olat.modules.wiki.Wiki; import org.olat.modules.wiki.WikiManager; import org.springframework.util.StringUtils; @@ -52,8 +60,8 @@ public class OlatWikiDataHandler implements DataHandler { private OLATResourceable ores; private String imageUri; - private final String IMAGE_NAMESPACE = "Image:"; - private final String MEDIA_NAMESPACE = "Media:"; + private static final String IMAGE_NAMESPACE = "Image:"; + private static final String MEDIA_NAMESPACE = "Media:"; /** * @param ores @@ -64,10 +72,6 @@ public class OlatWikiDataHandler implements DataHandler { this.imageUri = imageUri; } - /** - * @see org.jamwiki.DataHandler#lookupTopic(java.lang.String, - * java.lang.String, boolean, java.lang.Object) - */ @Override public Topic lookupTopic(String virtualWiki, String topicName, boolean deleteOK, Object transactionObject) throws Exception { String decodedName = null; @@ -79,17 +83,20 @@ public class OlatWikiDataHandler implements DataHandler { // } if (log.isDebugEnabled()) { - log.debug("page name not normalized: " + topicName); - log.debug("page name normalized: " + FilterUtil.normalizeWikiLink(topicName)); + log.debug("page name not normalized: {}", topicName); + log.debug("page name normalized: {}", FilterUtil.normalizeWikiLink(topicName)); try { - log.debug("page name urldecoded name: " + URLDecoder.decode(topicName, "utf-8")); - log.debug("page name urldecoded and normalized: " + FilterUtil.normalizeWikiLink(URLDecoder.decode(topicName, "utf-8"))); - log.debug("page name urldecoded normalized and transformed to id: " - + wiki.generatePageId(FilterUtil.normalizeWikiLink(decodedName))); + log.debug("page name urldecoded name: {}", URLDecoder.decode(topicName, "utf-8")); + log.debug("page name urldecoded and normalized: {}", FilterUtil.normalizeWikiLink(URLDecoder.decode(topicName, "utf-8"))); + log.debug("page name urldecoded normalized and transformed to id: {}", wiki.generatePageId(FilterUtil.normalizeWikiLink(decodedName))); } catch (UnsupportedEncodingException e) { // } } + if(decodedName == null) { + return null; + } + Topic topic = new Topic(); if (decodedName.startsWith(IMAGE_NAMESPACE)) { String imageName = topicName.substring(IMAGE_NAMESPACE.length()); @@ -99,9 +106,19 @@ public class OlatWikiDataHandler implements DataHandler { return topic; } else if (decodedName.startsWith(MEDIA_NAMESPACE)) { String mediaName = topicName.substring(MEDIA_NAMESPACE.length(), topicName.length()); - if (!wiki.mediaFileExists(mediaName)) return null; + if (!wiki.mediaFileExists(mediaName)) { + return null; + } topic.setName(mediaName); - topic.setTopicType(Topic.TYPE_FILE); + + String type = mediaName.toLowerCase(); + if(type.endsWith(".mp4") || type.endsWith(".m4v") || type.endsWith(".mov")) { + topic.setTopicType(Topic.TYPE_VIDEO); + } else if(type.endsWith(".mp3") || type.endsWith(".aac") || type.endsWith(".m4a")) { + topic.setTopicType(Topic.TYPE_AUDIO); + } else { + topic.setTopicType(Topic.TYPE_FILE); + } return topic; } if (wiki.pageExists(wiki.generatePageId(FilterUtil.normalizeWikiLink(decodedName)))) { @@ -111,10 +128,6 @@ public class OlatWikiDataHandler implements DataHandler { return null; } - /** - * @see org.jamwiki.DataHandler#lookupWikiFile(java.lang.String, - * java.lang.String) - */ @Override public WikiFile lookupWikiFile(String virtualWiki, String topicName) throws Exception { WikiFile wikifile = new WikiFile(); @@ -130,9 +143,6 @@ public class OlatWikiDataHandler implements DataHandler { return wikifile; } - /** - * @see org.jamwiki.DataHandler#exists(java.lang.String, java.lang.String) - */ @Override public boolean exists(String virtualWiki, String topic) { if (!StringUtils.hasText(topic)) { @@ -158,4 +168,22 @@ public class OlatWikiDataHandler implements DataHandler { return wiki.pageExists(pageId); } + @Override + public WikiMediaDimension getImageDimension(File file) { + Size size = CoreSpringFactory.getImpl(ImageService.class).getSize(file, null); + if(size == null) { + return null; + } + return new WikiMediaDimension(size.getWidth(), size.getHeight()); + } + + @Override + public WikiMediaDimension getVideoDimension(File file) { + VFSLeaf leaf = new LocalFileImpl(file); + Size size = CoreSpringFactory.getImpl(MovieService.class).getSize(leaf, "mp4"); + if(size == null) { + return null; + } + return new WikiMediaDimension(size.getWidth(), size.getHeight()); + } } diff --git a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/StaticExportWikiDataHandler.java b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/StaticExportWikiDataHandler.java index 8daca320462436a5c796b62caf35997ac9e20598..2fec995e774acb6907bbd31afc5424524830b1f2 100644 --- a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/StaticExportWikiDataHandler.java +++ b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/StaticExportWikiDataHandler.java @@ -25,7 +25,7 @@ package org.olat.modules.wiki.gui.components.wikiToHtml; -import org.jamwiki.DataHandler; +import org.jamwiki.DefaultDataHandler; import org.jamwiki.model.Topic; import org.jamwiki.model.WikiFile; import org.jamwiki.utils.NamespaceHandler; @@ -39,7 +39,7 @@ import org.olat.modules.wiki.WikiManager; * * @author guido */ -public class StaticExportWikiDataHandler implements DataHandler { +public class StaticExportWikiDataHandler extends DefaultDataHandler { private OLATResourceable ores; @@ -75,12 +75,4 @@ public class StaticExportWikiDataHandler implements DataHandler { wikifile.setAbsUrl(WikiManager.getInstance().getMediaFolder(ores).getBasefile().getAbsolutePath()); return wikifile; } - - - - public boolean exists(String virtualWiki, String topic) { - return true; - } - - } diff --git a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java index 7c52378314edc8718f71f55c23b7cdaba6ff779c..a492d9ee21f7c6d9dd3822f8b9bb560b77f41af3 100644 --- a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java +++ b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java @@ -117,6 +117,7 @@ public class WikiMarkupRenderer extends DefaultComponentRenderer { //set targets of media, image and external links to target "_blank" sb.append("<script>") .append("changeAnchorTargets('").append(uniqueId).append("','").append(Settings.getServerContextPathURI()).append("');") + .append("wikiMediaPlayer('").append(uniqueId).append("','").append(Settings.getServerContextPathURI()).append("');") .append("</script>"); } } diff --git a/src/main/java/org/olat/modules/wiki/portfolio/WikiArtefactDetailsController.java b/src/main/java/org/olat/modules/wiki/portfolio/WikiArtefactDetailsController.java index da6caacd5d443a8786265e5ffaae903521a48066..e01c6c29e901cb22456679bf91cca9be6c383b7a 100644 --- a/src/main/java/org/olat/modules/wiki/portfolio/WikiArtefactDetailsController.java +++ b/src/main/java/org/olat/modules/wiki/portfolio/WikiArtefactDetailsController.java @@ -21,9 +21,8 @@ package org.olat.modules.wiki.portfolio; import java.util.Locale; -import org.jamwiki.DataHandler; -import org.jamwiki.model.Topic; -import org.jamwiki.model.WikiFile; +import org.apache.logging.log4j.Logger; +import org.jamwiki.DefaultDataHandler; import org.jamwiki.parser.AbstractParser; import org.jamwiki.parser.ParserDocument; import org.jamwiki.parser.ParserInput; @@ -35,7 +34,6 @@ import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.filter.FilterFactory; import org.olat.portfolio.manager.EPFrontendManager; @@ -80,14 +78,14 @@ public class WikiArtefactDetailsController extends BasicController { try { ParserInput input = new ParserInput(); input.setWikiUser(null); - input.setAllowSectionEdit(false); - input.setDepth(2); - input.setContext(""); - input.setLocale(Locale.ENGLISH); - input.setTopicName("dummy"); - input.setUserIpAddress("0.0.0.0"); - input.setDataHandler(new DummyDataHandler()); - input.setVirtualWiki("/olat"); + input.setAllowSectionEdit(false); + input.setDepth(2); + input.setContext(""); + input.setLocale(Locale.ENGLISH); + input.setTopicName("dummy"); + input.setUserIpAddress("0.0.0.0"); + input.setDataHandler(new DefaultDataHandler()); + input.setVirtualWiki("/olat"); AbstractParser parser = new JFlexParser(input); ParserDocument parsedDoc = parser.parseHTML(content); @@ -98,23 +96,5 @@ public class WikiArtefactDetailsController extends BasicController { return content; } } - - public static class DummyDataHandler implements DataHandler { - - @Override - public boolean exists(String virtualWiki, String topic) { - return true; - } - - @Override - public Topic lookupTopic(String virtualWiki, String topicName, boolean deleteOK, Object transactionObject) throws Exception { - return null; - } - - @Override - public WikiFile lookupWikiFile(String virtualWiki, String topicName) throws Exception { - return null; - } - } } diff --git a/src/main/java/org/olat/modules/wiki/portfolio/WikiPageMediaController.java b/src/main/java/org/olat/modules/wiki/portfolio/WikiPageMediaController.java index 6a71a48be179b8e4016d9586666e5a90ca98f7d2..69dc81e083d631199df50ed0e152a0941d42d687 100644 --- a/src/main/java/org/olat/modules/wiki/portfolio/WikiPageMediaController.java +++ b/src/main/java/org/olat/modules/wiki/portfolio/WikiPageMediaController.java @@ -21,9 +21,8 @@ package org.olat.modules.wiki.portfolio; import java.util.Locale; -import org.jamwiki.DataHandler; -import org.jamwiki.model.Topic; -import org.jamwiki.model.WikiFile; +import org.apache.logging.log4j.Logger; +import org.jamwiki.DefaultDataHandler; import org.jamwiki.parser.AbstractParser; import org.jamwiki.parser.ParserDocument; import org.jamwiki.parser.ParserInput; @@ -34,7 +33,6 @@ import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.controller.BasicController; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; @@ -103,7 +101,7 @@ public class WikiPageMediaController extends BasicController { input.setLocale(Locale.ENGLISH); input.setTopicName("dummy"); input.setUserIpAddress("0.0.0.0"); - input.setDataHandler(new DummyDataHandler()); + input.setDataHandler(new DefaultDataHandler()); input.setVirtualWiki("/olat"); AbstractParser parser = new JFlexParser(input); @@ -115,23 +113,5 @@ public class WikiPageMediaController extends BasicController { return content; } } - - public static class DummyDataHandler implements DataHandler { - - @Override - public boolean exists(String virtualWiki, String topic) { - return true; - } - - @Override - public Topic lookupTopic(String virtualWiki, String topicName, boolean deleteOK, Object transactionObject) throws Exception { - return null; - } - - @Override - public WikiFile lookupWikiFile(String virtualWiki, String topicName) throws Exception { - return null; - } - } } diff --git a/src/main/java/org/olat/search/service/document/WikiPageDocument.java b/src/main/java/org/olat/search/service/document/WikiPageDocument.java index 5ddb726e37663f9f36ea6d61704a08cf9ab72255..59ea94bbeb30c0481280843c164cd99d932d2c5d 100644 --- a/src/main/java/org/olat/search/service/document/WikiPageDocument.java +++ b/src/main/java/org/olat/search/service/document/WikiPageDocument.java @@ -31,8 +31,7 @@ import java.util.Locale; import org.apache.logging.log4j.Logger; import org.apache.lucene.document.Document; import org.jamwiki.DataHandler; -import org.jamwiki.model.Topic; -import org.jamwiki.model.WikiFile; +import org.jamwiki.DefaultDataHandler; import org.jamwiki.parser.AbstractParser; import org.jamwiki.parser.ParserDocument; import org.jamwiki.parser.ParserInput; @@ -54,7 +53,7 @@ public class WikiPageDocument extends OlatDocument { private static final long serialVersionUID = -1210392466207248182L; private static final Logger log = Tracing.createLoggerFor(WikiPageDocument.class); - private static final DummyDataHandler DUMMY_DATA_HANDLER = new DummyDataHandler(); + private static final DataHandler DUMMY_DATA_HANDLER = new DefaultDataHandler(); public WikiPageDocument() { @@ -107,22 +106,4 @@ public class WikiPageDocument extends OlatDocument { return wikiPage.getContent(); } } - - private static class DummyDataHandler implements DataHandler { - - @Override - public boolean exists(String virtualWiki, String topic) { - return true; - } - - @Override - public Topic lookupTopic(String virtualWiki, String topicName, boolean deleteOK, Object transactionObject) throws Exception { - return null; - } - - @Override - public WikiFile lookupWikiFile(String virtualWiki, String topicName) throws Exception { - return null; - } - } } diff --git a/src/main/webapp/static/js/openolat/wiki.js b/src/main/webapp/static/js/openolat/wiki.js index 21178fcdc8b879f41ede3368c99bc150f62f4445..134497007fdaf290cc5631a26efdc4f49d14fed4 100644 --- a/src/main/webapp/static/js/openolat/wiki.js +++ b/src/main/webapp/static/js/openolat/wiki.js @@ -51,6 +51,19 @@ function changeAnchorTargets(id, hostUrl) { }); } +function wikiMediaPlayer(id, hostUrl) { + jQuery(".wikivideo").each(function(index, el) { + var spanEl = jQuery(el); + var url = hostUrl + spanEl.children("video").attr('src'); + BPlayer.insertPlayer(url, spanEl.attr('id'), 320, 240, 0, null, "video", undefined, false, false, true, null, undefined); + }); + + jQuery(".wikiaudio").each(function(index, el) { + var spanEl = jQuery(el); + var url = hostUrl + spanEl.children("audio").attr('src'); + BPlayer.insertPlayer(url, spanEl.attr('id'), 320, 24, 0, null, "audio", undefined, false, false, true, null, undefined); + }); +} // apply tagOpen/tagClose to selection in textarea, // use sampleText instead of selection if there is none diff --git a/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java b/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java index a8c8d968de69deb6315fc6afe453e6d18b678230..b0a00f63597eb38c89f11cdd3b9357a9f45cabdf 100644 --- a/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java +++ b/src/test/java/org/olat/core/util/filter/impl/XSSFilterParamTest.java @@ -193,6 +193,10 @@ public class XSSFilterParamTest { { "<a href=\"#Title_1\">Title 1</a>", "<a href=\"#Title_1\">Title 1</a>" }, { "<a href=\"#Title 1\">Title with space</a>", "<a>Title with space</a>" }, { "<a href=\"#Title#1\">Title with #</a>", "<a>Title with #</a>" }, + // video tag + { "<video src=\"http://localhost/win/video.mp4\" width=\"320\" height=\"240\"></video>", "<video src=\"http://localhost/win/video.mp4\" width=\"320\" height=\"240\"></video>" }, + { "<audio src=\"http://localhost/win/video.mp4\"></audio>", "<audio src=\"http://localhost/win/video.mp4\"></audio>" }, + { null, "" } // be tolerant }); }