From 415f1774ac8c8fa371e39895aae5ddfad5efaeac Mon Sep 17 00:00:00 2001
From: gnaegi <none@none>
Date: Thu, 19 May 2016 14:55:30 +0200
Subject: [PATCH] OO-725 make sure only supported video files are recognized as
 video resources

---
 .../commons/services/video/MovieService.java  |  8 ++++
 .../services/video/MovieServiceImpl.java      | 47 +++++++++++++++++--
 .../fileresource/types/VideoFileResource.java | 14 ++++--
 3 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/src/main/java/org/olat/core/commons/services/video/MovieService.java b/src/main/java/org/olat/core/commons/services/video/MovieService.java
index b22d0a5c943..88169d176eb 100644
--- a/src/main/java/org/olat/core/commons/services/video/MovieService.java
+++ b/src/main/java/org/olat/core/commons/services/video/MovieService.java
@@ -49,4 +49,12 @@ public interface MovieService {
 	 */
 	public long getDuration(VFSLeaf media, String suffix);
 
+	/**
+	 * Checks if a file is really an mp4 file we can handle
+	 * @param media
+	 * @param fileName
+	 * @return 
+	 */
+	public boolean isMP4(VFSLeaf media, String fileName);
+	
 }
diff --git a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java
index ee7d9034486..521fa596a53 100644
--- a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java
+++ b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java
@@ -40,6 +40,7 @@ import org.olat.core.commons.services.thumbnail.ThumbnailSPI;
 import org.olat.core.commons.services.video.spi.FLVParser;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.util.FileUtils;
 import org.olat.core.util.WorkThreadInformations;
 import org.olat.core.util.vfs.LocalFileImpl;
 import org.olat.core.util.vfs.VFSLeaf;
@@ -58,12 +59,22 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 	private static final OLog log = Tracing.createLoggerFor(MovieServiceImpl.class);
 
 	private static final List<String> extensions = new ArrayList<>();
+	private static final List<String> fourCCs = new ArrayList<>();
 	static {
+		// supported file extensions
 		extensions.add("mp4");
-		extensions.add("mov");
 		extensions.add("m4v");
+		extensions.add("mov");
+		// supported fourCC for H264 codec
+		fourCCs.add("avc1");
+		fourCCs.add("davc");
+		fourCCs.add("h264");
+		fourCCs.add("x264");
+		fourCCs.add("vssh");
 	}
 	
+	
+	
 	@Override
 	public List<String> getExtensions() {
 		return extensions;
@@ -82,7 +93,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 			return null;
 		}
 
-		if(suffix.equals("mp4") || suffix.equals("m4v")) {
+		if(extensions.contains(suffix)) {
 			try(RandomAccessFile accessFile = new RandomAccessFile(file, "r")) {
 				FileChannel ch = accessFile.getChannel();
 				FileChannelWrapper in = new FileChannelWrapper(ch);
@@ -124,7 +135,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 			return -1;
 		}
 
-		if(suffix.equals("mp4") || suffix.equals("m4v")) {
+		if(extensions.contains(suffix)) {
 			try(RandomAccessFile accessFile = new RandomAccessFile(file, "r")) {
 				FileChannel ch = accessFile.getChannel();
 				FileChannelWrapper in = new FileChannelWrapper(ch);
@@ -145,6 +156,36 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI {
 		return -1;
 	}
 
+	@Override
+	public boolean isMP4(VFSLeaf media, String fileName) {
+		File file = null;
+		if(media instanceof VFSCPNamedItem) {
+			media = ((VFSCPNamedItem)media).getDelegate();
+		}
+		if(media instanceof LocalFileImpl) {
+			file = ((LocalFileImpl)media).getBasefile();
+		}
+		if(file == null) {
+			return false;
+		}
+		String suffix = FileUtils.getFileSuffix(fileName);
+		if(extensions.contains(suffix)) {
+			try(RandomAccessFile accessFile = new RandomAccessFile(file, "r")) {
+				FileChannel ch = accessFile.getChannel();
+				FileChannelWrapper in = new FileChannelWrapper(ch);
+				MP4Demuxer demuxer1 = new MP4Demuxer(in);
+				String fourCC = demuxer1.getVideoTrack().getFourcc();
+				if (fourCCs.contains(fourCC)) {
+					return true;
+				} 
+				log.info("Movie file::" + fileName + " has correct suffix::" + suffix + " but fourCC::" + fourCC + " not in our list of supported codecs.");
+			} catch (Exception | Error e) {
+				// anticipated exception, is not an mp4 file
+			}
+		}
+		return false;
+	}
+
 	
 	@Override
 	public FinalSize generateThumbnail(VFSLeaf file, VFSLeaf thumbnailFile, int maxWidth, int maxHeight, boolean fill)
diff --git a/src/main/java/org/olat/fileresource/types/VideoFileResource.java b/src/main/java/org/olat/fileresource/types/VideoFileResource.java
index d763f4132ff..6d43a14cc50 100644
--- a/src/main/java/org/olat/fileresource/types/VideoFileResource.java
+++ b/src/main/java/org/olat/fileresource/types/VideoFileResource.java
@@ -20,8 +20,12 @@
 package org.olat.fileresource.types;
 
 import java.io.File;
+import java.util.Date;
 
 import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.services.video.MovieService;
+import org.olat.core.util.Formatter;
+import org.olat.core.util.vfs.LocalFileImpl;
 import org.olat.modules.video.VideoManager;
 import org.olat.modules.video.VideoModule;
 
@@ -35,6 +39,7 @@ public class VideoFileResource extends FileResource {
 
 	private static VideoModule videomodule = CoreSpringFactory.getImpl(VideoModule.class);
 	private static VideoManager videoManager = CoreSpringFactory.getImpl(VideoManager.class);
+	private static MovieService movieService = CoreSpringFactory.getImpl(MovieService.class);
 
 	/**
 	 * Movie file resource identifier.
@@ -57,11 +62,12 @@ public class VideoFileResource extends FileResource {
 		if (!videomodule.isEnabled()) {
 			return;
 		}
-		fileName = fileName.toLowerCase();
-		if (fileName.endsWith(".mp4")|| fileName.endsWith(".mov")) {
-			// accept raw mp4 files
-			// accept also mov files as iOS saves mp4 movis as mov
+		// accept raw mp4 files
+		// accept also mov files as iOS saves mp4 movis as mov, but check if the file can be parsed as mp4 file
+		boolean isMP4 = movieService.isMP4(new LocalFileImpl(file), fileName);
+		if (isMP4) {			
 			eval.setValid(true);
+			eval.setDisplayname(fileName + " - " + Formatter.formatShortDateFilesystem(new Date()));
 		} else if (fileName.endsWith(".zip")) {
 			// check if zip contains an exported video resource
 			videoManager.validateVideoExportArchive(file, eval);
-- 
GitLab