Rework presentation download and upload

- verify presentation and meeting id formats
 - construct presentation file path making sure that they are valid
 - add "downloadable" flag to check if presentation can be downloaded or not
 - collect presentation upload errors so we can send to the client in the future
This commit is contained in:
Richard Alam 2020-05-01 14:16:42 -07:00
parent 1297819518
commit f876ce01c2
8 changed files with 370 additions and 193 deletions

View File

@ -32,7 +32,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
@ -70,54 +69,42 @@ public class RecordingService {
}
public void processMakePresentationDownloadableMsg(MakePresentationDownloadableMsg msg) {
File presDir = Util.getPresentationDir(presentationBaseDir, msg.meetingId, msg.presId);
File downloadableFile = new File(presDir.getAbsolutePath() + File.separatorChar + msg.presFilename);
if (presDir != null) {
if (msg.downloadable) {
String fileExt = FilenameUtils.getExtension(msg.presFilename);
File presFile = new File(presDir.getAbsolutePath() + File.separatorChar + msg.presId + "." + fileExt);
log.info("Make file downloadable. {}", downloadableFile.getAbsolutePath());
copyPresentationFile(presFile, downloadableFile);
} else {
if (downloadableFile.exists()) {
if(downloadableFile.delete()) {
log.info("File deleted. {}", downloadableFile.getAbsolutePath());
} else {
log.warn("Failed to delete. {}", downloadableFile.getAbsolutePath());
}
}
}
try {
Util.makePresentationDownloadable(presentationBaseDir, msg.meetingId, msg.presId, msg.downloadable);
} catch (IOException e) {
log.error("Failed to make presentation downloadable: {}", e);
}
}
public File getDownloadablePresentationFile(String meetingId, String presId, String presFilename) {
log.info("Find downloadable presentation for meetingId={} presId={} filename={}", meetingId, presId,
presFilename);
Matcher metaMatcher = PRESENTATION_ID_PATTERN.matcher(presFilename);
if (metaMatcher.matches()) {
File presDir = Util.getPresentationDir(presentationBaseDir, meetingId, presId);
// Build file to presFilename
// Get canonicalPath and make sure it starts with
// /var/bigbluebutton/<meetingid-pattern>
// If so return file, if not return null
try {
File presFile = new File(presDir.getAbsolutePath() + File.separatorChar + presFilename);
String presFileCanonical = presFile.getCanonicalPath();
log.debug("Requested presentation name file full path {}",presFileCanonical);
if (presFileCanonical.startsWith(presentationBaseDir)) {
return presFile;
}
} catch (IOException e) {
log.error("Exception getting canonical path for {}.\n{}", presFilename, e);
return null;
}
}
log.error("Cannot find file for {}.", presFilename);
log.info("Find downloadable presentation for meetingId={} presId={} filename={}", meetingId, presId,
presFilename);
if (! Util.isPresFileIdValidFormat(presFilename)) {
log.error("Invalid presentation filename for meetingId={} presId={} filename={}", meetingId, presId,
presFilename);
return null;
}
String presFilenameExt = FilenameUtils.getExtension(presFilename);
File presDir = Util.getPresentationDir(presentationBaseDir, meetingId, presId);
File downloadMarker = Util.getPresFileDownloadMarker(presentationBaseDir, meetingId, presId);
if (presDir != null && downloadMarker != null && downloadMarker.exists()) {
String safePresFilename = presId.concat(".").concat(presFilenameExt);
File presFile = new File(presDir.getAbsolutePath() + File.separatorChar + safePresFilename);
if (presFile.exists()) {
return presFile;
}
log.error("Presentation file missing for meetingId={} presId={} filename={}", meetingId, presId,
presFilename);
return null;
}
log.error("Invalid presentation directory for meetingId={} presId={} filename={}", meetingId, presId,
presFilename);
return null;
}
public void kickOffRecordingChapterBreak(String meetingId, Long timestamp) {

View File

@ -1,49 +1,132 @@
package org.bigbluebutton.api;
import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
public final class Util {
private Util() {
throw new IllegalStateException("Utility class");
}
public static String generatePresentationId(String name) {
long timestamp = System.currentTimeMillis();
return DigestUtils.sha1Hex(name) + "-" + timestamp;
private static final Pattern MEETING_ID_PATTERN = Pattern.compile("^[a-z0-9-]+$");
private static final Pattern PRES_ID_PATTERN = Pattern.compile("^[a-z0-9-]+$");
private static final Pattern PRES_FILE_ID_PATTERN = Pattern.compile("^[a-z0-9-]+.[a-zA-Z]{3,4}$");
private Util() {
throw new IllegalStateException("Utility class");
}
public static boolean isMeetingIdValidFormat(String id) {
Matcher matcher = MEETING_ID_PATTERN.matcher(id);
if (matcher.matches()) {
return true;
}
return false;
}
public static boolean isPresIdValidFormat(String id) {
Matcher matcher = PRES_ID_PATTERN.matcher(id);
if (matcher.matches()) {
return true;
}
return false;
}
public static boolean isPresFileIdValidFormat(String id) {
Matcher matcher = PRES_FILE_ID_PATTERN.matcher(id);
if (matcher.matches()) {
return true;
}
return false;
}
public static String generatePresentationId(String presFilename) {
long timestamp = System.currentTimeMillis();
return DigestUtils.sha1Hex(presFilename) + "-" + timestamp;
}
public static String createNewFilename(String presId, String fileExt) {
return presId + "." + fileExt;
}
public static String createNewFilename(String presId, String fileExt) {
return presId + "." + fileExt;
}
public static File createPresentationDir(String meetingId, String presentationDir, String presentationId) {
String meetingPath = presentationDir + File.separatorChar + meetingId + File.separatorChar + meetingId;
String presPath = meetingPath + File.separatorChar + presentationId;
File dir = new File(presPath);
if (dir.mkdirs()) {
return dir;
if (Util.isMeetingIdValidFormat(meetingId) && Util.isPresIdValidFormat(presentationId)) {
String meetingPath = presentationDir + File.separatorChar + meetingId + File.separatorChar + meetingId;
String presPath = meetingPath + File.separatorChar + presentationId;
File dir = new File(presPath);
if (dir.mkdirs()) {
return dir;
}
}
return null;
}
public static File getMeetingDirPath(String presentationBaseDir, String meetingId) {
if (Util.isMeetingIdValidFormat(meetingId)) {
String meetingPath = presentationBaseDir + File.separatorChar + meetingId + File.separatorChar + meetingId;
File dir = new File(meetingPath);
if (dir.isDirectory() && dir.exists()) {
return dir;
}
}
return null;
}
public static File getPresentationDir(String presentationBaseDir, String meetingId, String presentationId) {
String meetingPath = presentationBaseDir + File.separatorChar + meetingId + File.separatorChar + meetingId;
String presPath = meetingPath + File.separatorChar + presentationId;
File dir = new File(presPath);
if (dir.isDirectory() && dir.exists()) {
return dir;
if (Util.isMeetingIdValidFormat(meetingId) && Util.isPresIdValidFormat(presentationId)) {
String meetingPath = presentationBaseDir + File.separatorChar + meetingId + File.separatorChar + meetingId;
String presPath = meetingPath + File.separatorChar + presentationId;
File dir = new File(presPath);
if (dir.isDirectory() && dir.exists()) {
return dir;
}
}
return null;
}
public String stripPresBaseDirFromPath(String presentationBaseDir, String path) {
if (path.startsWith(presentationBaseDir)) {
String presBaseDir = presentationBaseDir;
if (! presBaseDir.endsWith("/")) {
presBaseDir = presBaseDir.concat("/");
return StringUtils.removeStart(path, presBaseDir);
} else {
return StringUtils.removeStart(path, presBaseDir);
}
}
return path;
}
public static File getPresFileDownloadMarker(String presBaseDir, String meetingId, String presId) {
File presDir = Util.getPresentationDir(presBaseDir, meetingId, presId);
if (presDir != null) {
String downloadMarker = presId.concat(".downloadable");
return new File(presDir.getAbsolutePath() + File.separatorChar + downloadMarker);
}
return null;
}
public static File downloadPresentationDirectory(String uploadDirectory) {
File dir = new File(uploadDirectory + File.separatorChar + "download");
if (dir.mkdirs()) {
return dir;
public static void makePresentationDownloadable(
String presBaseDir,
String meetingId,
String presId,
boolean downloadable
) throws IOException {
File downloadMarker = Util.getPresFileDownloadMarker(presBaseDir, meetingId, presId);
if (downloadable) {
if (downloadMarker != null && ! downloadMarker.exists()) {
downloadMarker.createNewFile();
}
} else {
if (downloadMarker != null && downloadMarker.exists()) {
downloadMarker.delete();
}
}
return null;
}
}

View File

@ -44,6 +44,14 @@ public class DocumentConversionServiceImp implements DocumentConversionService {
public void processDocument(UploadedPresentation pres) {
if (pres.isUploadFailed()) {
// We should send a message to the client in the future.
// ralam may 1, 2020
log.error("Presentation upload failed for meetingId={} presId={}", pres.getMeetingId(), pres.getId());
log.error("Presentation upload fail reasons {}", pres.getUploadFailReason());
return;
}
SupportedDocumentFilter sdf = new SupportedDocumentFilter(gw);
sendDocConversionRequestReceived(pres);

View File

@ -6,12 +6,14 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
@ -59,10 +61,19 @@ public class PresentationUrlDownloadService {
}
public void processUploadedFile(String podId, String meetingId, String presId,
String filename, File presFile, Boolean current, String authzToken) {
String filename, File presFile, Boolean current, String authzToken,
Boolean uploadFailed, ArrayList<String> uploadFailReasons) {
// TODO add podId
UploadedPresentation uploadedPres = new UploadedPresentation(podId, meetingId,
presId, filename, presentationBaseURL, current, authzToken);
UploadedPresentation uploadedPres = new UploadedPresentation(
podId,
meetingId,
presId,
filename,
presentationBaseURL,
current,
authzToken,
uploadFailed,
uploadFailReasons);
uploadedPres.setUploadedFile(presFile);
processUploadedPresentation(uploadedPres);
}
@ -84,6 +95,9 @@ public class PresentationUrlDownloadService {
private void extractPage(final String sourceMeetingId, final String presentationId,
final Integer presentationSlide, final String destinationMeetingId) {
Boolean uploadFailed = false;
ArrayList<String> uploadFailedReasons = new ArrayList<String>();
// Build the source meeting path
File sourceMeetingPath = new File(presentationDir + File.separatorChar
+ sourceMeetingId + File.separatorChar + sourceMeetingId
@ -118,13 +132,13 @@ public class PresentationUrlDownloadService {
} else {
sourcePresentationFile = matches[0];
}
// Build the target meeting path
String filenameExt = FilenameUtils.getExtension(sourcePresentationFile
.getName());
String presId = generatePresentationId(presentationId);
String filenameExt = FilenameUtils.getExtension(sourcePresentationFile.getName());
String presId = Util.generatePresentationId(presentationId);
String newFilename = Util.createNewFilename(presId, filenameExt);
File uploadDir = createPresentationDirectory(destinationMeetingId,
File uploadDir = Util.createPresentationDir(destinationMeetingId,
presentationDir, presId);
String newFilePath = uploadDir.getAbsolutePath() + File.separatorChar
+ newFilename;
@ -143,27 +157,15 @@ public class PresentationUrlDownloadService {
}
// Hardcode pre-uploaded presentation for breakout room to the default presentation window
processUploadedFile("DEFAULT_PRESENTATION_POD", destinationMeetingId, presId, "default-"
+ presentationSlide.toString() + "." + filenameExt,
newPresentation, true, "breakout-authz-token");
}
public String generatePresentationId(String name) {
long timestamp = System.currentTimeMillis();
return DigestUtils.sha1Hex(name) + "-" + timestamp;
}
public File createPresentationDirectory(String meetingId,
String presentationDir, String presentationId) {
String meetingPath = presentationDir + File.separatorChar + meetingId
+ File.separatorChar + meetingId;
String presPath = meetingPath + File.separatorChar + presentationId;
File dir = new File(presPath);
log.debug("Creating dir [{}]", presPath);
if (dir.mkdirs()) {
return dir;
}
return null;
processUploadedFile("DEFAULT_PRESENTATION_POD",
destinationMeetingId,
presId,
"default-" + presentationSlide.toString() + "." + filenameExt,
newPresentation,
true,
"breakout-authz-token",
uploadFailed,
uploadFailedReasons);
}
private String followRedirect(String meetingId, String redirectUrl,

View File

@ -20,12 +20,15 @@
package org.bigbluebutton.presentation;
import java.io.File;
import java.util.ArrayList;
public final class UploadedPresentation {
private final String podId;
private final String meetingId;
private final String id;
private final String name;
private final boolean uploadFailed;
private final ArrayList<String> uploadFailReason;
private File uploadedFile;
private String fileType = "unknown";
private int numberOfPages = 0;
@ -36,13 +39,16 @@ public final class UploadedPresentation {
private String authzToken;
private boolean conversionStarted = false;
public UploadedPresentation(String podId,
String meetingId,
String id,
String name,
String baseUrl,
Boolean current,
String authzToken) {
String authzToken,
Boolean uploadFailed,
ArrayList<String> uploadFailReason) {
this.podId = podId;
this.meetingId = meetingId;
this.id = id;
@ -51,6 +57,8 @@ public final class UploadedPresentation {
this.isDownloadable = false;
this.current = current;
this.authzToken = authzToken;
this.uploadFailed = uploadFailed;
this.uploadFailReason = uploadFailReason;
}
public File getUploadedFile() {
@ -132,4 +140,12 @@ public final class UploadedPresentation {
public boolean isConversionStarted() {
return conversionStarted;
}
public boolean isUploadFailed() {
return uploadFailed;
}
public ArrayList<String> getUploadFailReason() {
return uploadFailReason;
}
}

View File

@ -1,6 +1,7 @@
package org.bigbluebutton.presentation.imp;
import com.google.gson.Gson;
import org.bigbluebutton.api.Util;
import org.bigbluebutton.presentation.*;
import org.bigbluebutton.presentation.messages.DocPageConversionStarted;
import org.bigbluebutton.presentation.messages.DocPageCountExceeded;
@ -10,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
@ -53,6 +55,19 @@ public class PresentationFileProcessor {
}
public synchronized void process(UploadedPresentation pres) {
if (pres.isDownloadable()) {
try {
Util.makePresentationDownloadable(
pres.getUploadedFile().getParent(),
pres.getMeetingId(),
pres.getId(),
pres.isDownloadable()
);
} catch (IOException e) {
log.error("Failed to make presentation downloadable: {}", e);
}
}
Runnable messageProcessor = new Runnable() {
public void run() {
processUploadedPresentation(pres);

View File

@ -2017,68 +2017,110 @@ class ApiController {
}
}
def processDocumentFromRawBytes(bytes, presFilename, meetingId, current) {
def filenameExt = FilenameUtils.getExtension(presFilename);
String presentationDir = presentationService.getPresentationDir()
def presId = Util.generatePresentationId(presFilename)
File uploadDir = presDownloadService.createPresentationDirectory(meetingId, presentationDir, presId)
if (uploadDir != null) {
def newFilename = Util.createNewFilename(presId, filenameExt)
def pres = new File(uploadDir.absolutePath + File.separatorChar + newFilename);
def processDocumentFromRawBytes(bytes, presOrigFilename, meetingId, current) {
def uploadFailed = false
def uploadFailReasons = new ArrayList<String>()
FileOutputStream fos = new java.io.FileOutputStream(pres)
fos.write(bytes)
fos.flush()
fos.close()
// Gets the name minus the path from a full fileName.
// a/b/c.txt --> c.txt
def presFilename = FilenameUtils.getName(presOrigFilename)
def filenameExt = FilenameUtils.getExtension(presOrigFilename)
def pres = null
def presId = null
// Hardcode pre-uploaded presentation to the default presentation window
processUploadedFile("DEFAULT_PRESENTATION_POD",
if (presFilename == "" || filenameExt == "") {
log.debug("Upload failed. Invalid filename " + presOrigFilename)
uploadFailReasons.add("invalid_filename")
uploadFailed = true
} else {
String presentationDir = presentationService.getPresentationDir()
presId = Util.generatePresentationId(presFilename)
File uploadDir = Util.createPresentationDir(meetingId, presentationDir, presId)
if (uploadDir != null) {
def newFilename = Util.createNewFilename(presId, filenameExt)
pres = new File(uploadDir.absolutePath + File.separatorChar + newFilename);
FileOutputStream fos = new java.io.FileOutputStream(pres)
fos.write(bytes)
fos.flush()
fos.close()
} else {
log.warn "Upload failed. File Empty."
uploadFailReasons.add("failed_to_download_file")
uploadFailed = true
}
}
// Hardcode pre-uploaded presentation to the default presentation window
processUploadedFile("DEFAULT_PRESENTATION_POD",
meetingId,
presId,
presFilename,
pres,
current,
"preupload-raw-authz-token");
}
"preupload-raw-authz-token",
uploadFailed,
uploadFailReasons)
}
def downloadAndProcessDocument(address, meetingId, current, fileName) {
log.debug("ApiController#downloadAndProcessDocument(${address}, ${meetingId}, ${fileName})");
String presFilename;
String presOrigFilename;
if (StringUtils.isEmpty(fileName)) {
presFilename = address.tokenize("/")[-1];
presOrigFilename = address.tokenize("/")[-1];
} else {
presFilename = fileName;
presOrigFilename = fileName;
}
def filenameExt = FilenameUtils.getExtension(presFilename);
String presentationDir = presentationService.getPresentationDir()
def uploadFailed = false
def uploadFailReasons = new ArrayList<String>()
def presId = presDownloadService.generatePresentationId(presFilename)
File uploadDir = presDownloadService.createPresentationDirectory(meetingId, presentationDir, presId)
if (uploadDir != null) {
def newFilename = Util.createNewFilename(presId, filenameExt)
def newFilePath = uploadDir.absolutePath + File.separatorChar + newFilename
// Gets the name minus the path from a full fileName.
// a/b/c.txt --> c.txt
def presFilename = FilenameUtils.getName(presOrigFilename)
def filenameExt = FilenameUtils.getExtension(presOrigFilename)
def pres = null
def presId
if (presDownloadService.savePresentation(meetingId, newFilePath, address)) {
def pres = new File(newFilePath)
// Hardcode pre-uploaded presentation to the default presentation window
processUploadedFile("DEFAULT_PRESENTATION_POD",
meetingId,
presId,
presFilename,
pres,
current,
"preupload-download-authz-token");
} else {
log.error("Failed to download presentation=[${address}], meeting=[${meetingId}], fileName=[${fileName}]")
if (presFilename == "" || filenameExt == "") {
log.debug("Upload failed. Invalid filename " + presOrigFilename)
uploadFailReasons.add("invalid_filename")
uploadFailed = true
} else {
String presentationDir = presentationService.getPresentationDir()
presId = Util.generatePresentationId(presFilename)
File uploadDir = Util.createPresentationDir(meetingId, presentationDir, presId)
if (uploadDir != null) {
def newFilename = Util.createNewFilename(presId, filenameExt)
def newFilePath = uploadDir.absolutePath + File.separatorChar + newFilename
if (presDownloadService.savePresentation(meetingId, newFilePath, address)) {
pres = new File(newFilePath)
} else {
log.error("Failed to download presentation=[${address}], meeting=[${meetingId}], fileName=[${fileName}]")
uploadFailReasons.add("failed_to_download_file")
uploadFailed = true
}
}
}
// Hardcode pre-uploaded presentation to the default presentation window
processUploadedFile(
"DEFAULT_PRESENTATION_POD",
meetingId,
presId,
presFilename,
pres,
current,
"preupload-download-authz-token",
uploadFailed,
uploadFailReasons
)
}
def processUploadedFile(podId, meetingId, presId, filename, presFile, current, authzToken) {
def processUploadedFile(podId, meetingId, presId, filename, presFile, current, authzToken, uploadFailed, uploadFailReasons ) {
def presentationBaseUrl = presentationService.presentationBaseUrl
// TODO add podId
UploadedPresentation uploadedPres = new UploadedPresentation(podId,
@ -2087,7 +2129,9 @@ class ApiController {
filename,
presentationBaseUrl,
current,
authzToken);
authzToken,
uploadFailed,
uploadFailReasons)
uploadedPres.setUploadedFile(presFile);
presentationService.processUploadedPresentation(uploadedPres);
}

View File

@ -76,73 +76,95 @@ class PresentationController {
// check if the authorization token provided is valid
if (null == params.authzToken || !meetingService.authzTokenIsValidAndExpired(params.authzToken)) {
log.debug "WARNING! AuthzToken=" + params.authzToken + " was not valid in meetingId=" + params.conference
response.addHeader("Cache-Control", "no-cache")
response.contentType = 'plain/text'
response.outputStream << 'invalid auth token'
return
}
def meetingId = params.conference
def meeting = meetingService.getNotEndedMeetingWithId(meetingId);
if (meeting == null) {
flash.message = 'meeting is not running'
log.debug("Upload failed. No meeting running " + meetingId)
if (Util.isMeetingIdValidFormat(meetingId)) {
def meeting = meetingService.getNotEndedMeetingWithId(meetingId)
if (meeting == null) {
log.debug("Upload failed. No meeting running " + meetingId)
response.addHeader("Cache-Control", "no-cache")
response.contentType = 'plain/text'
response.outputStream << 'no-meeting'
return
}
} else {
log.debug("Upload failed. Invalid meeting id format " + meetingId)
response.addHeader("Cache-Control", "no-cache")
response.contentType = 'plain/text'
response.outputStream << 'no-meeting';
return
}
def isDownloadable = params.boolean('is_downloadable') //instead of params.is_downloadable
def podId = params.pod_id
log.debug "@Default presentation pod" + podId
def uploadFailed = false
def uploadFailReasons = new ArrayList<String>()
def presOrigFilename = ""
def presFilename = ""
def filenameExt = ""
def presId = ""
def pres = null
def file = request.getFile('fileUpload')
if (file && !file.empty) {
flash.message = 'Your file has been uploaded'
def presFilename = file.getOriginalFilename()
def filenameExt = FilenameUtils.getExtension(presFilename);
String presentationDir = presentationService.getPresentationDir()
def presId = Util.generatePresentationId(presFilename)
File uploadDir = Util.createPresentationDir(meetingId, presentationDir, presId)
if (uploadDir != null) {
def newFilename = Util.createNewFilename(presId, filenameExt)
def pres = new File(uploadDir.absolutePath + File.separatorChar + newFilename)
file.transferTo(pres)
def isDownloadable = params.boolean('is_downloadable') //instead of params.is_downloadable
def podId = params.pod_id
log.debug "@Default presentation pod" + podId
if (isDownloadable) {
log.debug "@Creating download directory..."
File downloadDir = Util.downloadPresentationDirectory(uploadDir.absolutePath)
if (downloadDir != null) {
def notValidCharsRegExp = /[^0-9a-zA-Z_\.]/
def downloadableFileName = presFilename.replaceAll(notValidCharsRegExp, '-')
def downloadableFile = new File(downloadDir.absolutePath + File.separatorChar + downloadableFileName)
downloadableFile << pres.newInputStream()
}
}
log.debug("processing file upload " + presFilename)
def presentationBaseUrl = presentationService.presentationBaseUrl
UploadedPresentation uploadedPres = new UploadedPresentation(podId, meetingId, presId,
presFilename, presentationBaseUrl, false /* default presentation */,
params.authzToken);
if (isDownloadable) {
log.debug "@Setting file to be downloadable..."
uploadedPres.setDownloadable();
}
uploadedPres.setUploadedFile(pres);
presentationService.processUploadedPresentation(uploadedPres)
log.debug("file upload success " + presFilename)
response.addHeader("Cache-Control", "no-cache")
response.contentType = 'plain/text'
response.outputStream << 'upload-success'
}
presOrigFilename = file.getOriginalFilename()
// Gets the name minus the path from a full fileName.
// a/b/c.txt --> c.txt
presFilename = FilenameUtils.getName(presOrigFilename)
filenameExt = FilenameUtils.getExtension(presFilename)
} else {
log.warn "Upload failed. File Empty."
flash.message = 'file cannot be empty'
response.addHeader("Cache-Control", "no-cache")
response.contentType = 'plain/text'
response.outputStream << 'file-empty'
uploadFailReasons.add("uploaded_file_empty")
uploadFailed = true
}
if (presFilename == "" || filenameExt == "") {
log.debug("Upload failed. Invalid filename " + presOrigFilename)
uploadFailReasons.add("invalid_filename")
uploadFailed = true
} else {
String presentationDir = presentationService.getPresentationDir()
presId = Util.generatePresentationId(presFilename)
File uploadDir = Util.createPresentationDir(meetingId, presentationDir, presId)
if (uploadDir != null) {
def newFilename = Util.createNewFilename(presId, filenameExt)
pres = new File(uploadDir.absolutePath + File.separatorChar + newFilename)
file.transferTo(pres)
}
}
log.debug("processing file upload " + presFilename)
def presentationBaseUrl = presentationService.presentationBaseUrl
UploadedPresentation uploadedPres = new UploadedPresentation(
podId,
meetingId,
presId,
presFilename,
presentationBaseUrl,
false /* default presentation */,
params.authzToken,
uploadFailed,
uploadFailReasons
)
if (isDownloadable) {
log.debug "@Setting file to be downloadable..."
uploadedPres.setDownloadable();
}
uploadedPres.setUploadedFile(pres);
presentationService.processUploadedPresentation(uploadedPres)
log.debug("file upload success " + presFilename)
response.addHeader("Cache-Control", "no-cache")
response.contentType = 'plain/text'
response.outputStream << 'upload-success'
}
def testConversion = {