Skip to content
Snippets Groups Projects
Commit c03443ea authored by srosse's avatar srosse
Browse files

OO-4655: support audio and video files in wiki

parent a1362e1e
No related branches found
No related tags found
No related merge requests found
Showing
with 105 additions and 116 deletions
......@@ -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>
......
......@@ -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")
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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());
}
}
......@@ -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;
}
}
......@@ -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>");
}
}
......@@ -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;
}
}
}
......@@ -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;
}
}
}
......@@ -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;
}
}
}
......@@ -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
......
......@@ -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
});
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment