Skip to content

Commit

Permalink
Disallow converting PDF files that have at least one big weighted page.
Browse files Browse the repository at this point in the history
  • Loading branch information
GhaziTriki committed Oct 16, 2019
1 parent bcbb527 commit ba10953
Show file tree
Hide file tree
Showing 17 changed files with 257 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.bigbluebutton.core.apps.presentationpod

import org.bigbluebutton.common2.msgs._
import org.bigbluebutton.core.bus.MessageBus
import org.bigbluebutton.core.domain.MeetingState2x
import org.bigbluebutton.core.running.LiveMeeting

trait PdfConversionInvalidErrorSysPubMsgHdlr {
this: PresentationPodHdlrs =>

def handle(
msg: PdfConversionInvalidErrorSysPubMsg, state: MeetingState2x,
liveMeeting: LiveMeeting, bus: MessageBus
): MeetingState2x = {

def broadcastEvent(msg: PdfConversionInvalidErrorSysPubMsg): Unit = {
val routing = Routing.addMsgToClientRouting(
MessageTypes.BROADCAST_TO_MEETING,
liveMeeting.props.meetingProp.intId, msg.header.userId
)
val envelope = BbbCoreEnvelope(PdfConversionInvalidErrorSysPubMsg.NAME, routing)
val header = BbbClientMsgHeader(
PdfConversionInvalidErrorSysPubMsg.NAME,
liveMeeting.props.meetingProp.intId, msg.header.userId
)

val body = PdfConversionInvalidErrorSysPubMsgBody(msg.body.podId, msg.body.messageKey, msg.body.code, msg.body.presentationId, msg.body.bigPageNumber, msg.body.bigPageSize, msg.body.presName)
val event = PdfConversionInvalidErrorSysPubMsg(header, body)
val msgEvent = BbbCommonEnvCoreMsg(envelope, event)
bus.outGW.send(msgEvent)
}

broadcastEvent(msg)
state
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class PresentationPodHdlrs(implicit val context: ActorContext)
with GetAllPresentationPodsReqMsgHdlr
with SetCurrentPresentationPubMsgHdlr
with PresentationConversionCompletedSysPubMsgHdlr
with PdfConversionInvalidErrorSysPubMsgHdlr
with SetCurrentPagePubMsgHdlr
with SetPresenterInPodReqMsgHdlr
with RemovePresentationPubMsgHdlr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ class ReceivedJsonMsgHandlerActor(
routeGenericMsg[PresentationPageGeneratedSysPubMsg](envelope, jsonNode)
case PresentationConversionCompletedSysPubMsg.NAME =>
routeGenericMsg[PresentationConversionCompletedSysPubMsg](envelope, jsonNode)
case PdfConversionInvalidErrorSysPubMsg.NAME =>
routeGenericMsg[PdfConversionInvalidErrorSysPubMsg](envelope, jsonNode)
case AssignPresenterReqMsg.NAME =>
routeGenericMsg[AssignPresenterReqMsg](envelope, jsonNode)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ class MeetingActor(
case m: GetAllPresentationPodsReqMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: SetCurrentPresentationPubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: PresentationConversionCompletedSysPubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: PdfConversionInvalidErrorSysPubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: SetCurrentPagePubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: SetPresenterInPodReqMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
case m: RemovePresentationPubMsg => state = presentationPodsApp.handle(m, state, liveMeeting, msgBus)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class AnalyticsActor extends Actor with ActorLogging {

// Presentation
case m: PresentationConversionCompletedSysPubMsg => logMessage(msg)
case m: PdfConversionInvalidErrorSysPubMsg => logMessage(msg)
case m: SetCurrentPresentationPubMsg => logMessage(msg)
case m: SetCurrentPresentationEvtMsg => logMessage(msg)
case m: SetPresentationDownloadablePubMsg => logMessage(msg)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ case class PresentationPageCountErrorSysPubMsg(
case class PresentationPageCountErrorSysPubMsgBody(podId: String, messageKey: String, code: String, presentationId: String,
numberOfPages: Int, maxNumberPages: Int, presName: String)

object PdfConversionInvalidErrorSysPubMsg { val NAME = "PdfConversionInvalidErrorSysPubMsg" }
case class PdfConversionInvalidErrorSysPubMsg(
header: BbbClientMsgHeader,
body: PdfConversionInvalidErrorSysPubMsgBody
) extends StandardMsg
case class PdfConversionInvalidErrorSysPubMsgBody(podId: String, messageKey: String, code: String, presentationId: String,
bigPageNumber: Int, bigPageSize: Int, presName: String)

object PresentationPageGeneratedSysPubMsg { val NAME = "PresentationPageGeneratedSysPubMsg" }
case class PresentationPageGeneratedSysPubMsg(
header: BbbClientMsgHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class ConversionMessageConstants {
public static final String UNSUPPORTED_DOCUMENT_KEY = "UNSUPPORTED_DOCUMENT";
public static final String PAGE_COUNT_FAILED_KEY = "PAGE_COUNT_FAILED";
public static final String PAGE_COUNT_EXCEEDED_KEY = "PAGE_COUNT_EXCEEDED";
public static final String PDF_HAS_BIG_PAGE = "PDF_HAS_BIG_PAGE";
public static final String GENERATED_SLIDE_KEY = "GENERATED_SLIDE";
public static final String GENERATING_THUMBNAIL_KEY = "GENERATING_THUMBNAIL";
public static final String GENERATED_THUMBNAIL_KEY = "GENERATED_THUMBNAIL";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2019 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.presentation.imp;

@SuppressWarnings("serial")
public class BigPdfException extends Exception {

private final int bigPageNumber;
private final long bigPageSize;
private final ExceptionType exceptionType;

public BigPdfException(BigPdfException.ExceptionType type, int bigPageNumber, long bigPageSize) {
super("Exception while converting PDF that has at least one big page.");
this.bigPageNumber = bigPageNumber;
this.bigPageSize = bigPageSize;
exceptionType = type;
}

public int getBigPageNumber() {
return bigPageNumber;
}

public BigPdfException.ExceptionType getExceptionType() {
return exceptionType;
}

public long getBigPageSize() {
return bigPageSize;
}

public enum ExceptionType {
PDF_HAS_BIG_PAGE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@

package org.bigbluebutton.presentation.imp;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
Expand All @@ -37,6 +40,7 @@
import org.bigbluebutton.presentation.ConversionUpdateMessage.MessageBuilder;
import org.bigbluebutton.presentation.messages.DocPageCountExceeded;
import org.bigbluebutton.presentation.messages.DocPageCountFailed;
import org.bigbluebutton.presentation.messages.PdfConversionInvalid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -54,6 +58,9 @@ public class PdfToSwfSlidesGenerationService {

private TextFileCreator textFileCreator;
private SvgImageCreator svgImageCreator;
private long bigPdfSize;
private long maxBigPdfPageSize;
private PageExtractor pageExtractor;
private long MAX_CONVERSION_TIME = 5 * 60 * 1000L * 1000L * 1000L;
private String BLANK_SLIDE;
private int MAX_SWF_FILE_SIZE;
Expand All @@ -68,6 +75,15 @@ public PdfToSwfSlidesGenerationService(int numConversionThreads) {
public void generateSlides(UploadedPresentation pres) {
determineNumberOfPages(pres);
if (pres.getNumberOfPages() > 0) {
if (pres.getUploadedFile().length() > bigPdfSize) {
try {
hasBigPage(pres);
} catch (BigPdfException e) {
sendFailedToConvertBigPdfMessage(e, pres);
return;
}
}

// Only create SWF files if the configuration requires it
if (swfSlidesRequired) {
convertPdfToSwf(pres);
Expand Down Expand Up @@ -100,6 +116,40 @@ private boolean determineNumberOfPages(UploadedPresentation pres) {
}
return false;
}

private boolean hasBigPage(UploadedPresentation pres) throws BigPdfException {
long lastPageSize = 0;
int currentPage = 1;
String basePresentationame = UUID.randomUUID().toString();
if (pres.getNumberOfPages() > 1) {
while(currentPage < pres.getNumberOfPages()) {
File tempPage;
try {
tempPage = File.createTempFile(basePresentationame + "-" + currentPage, ".pdf");
pageExtractor.extractPage(pres.getUploadedFile(), tempPage, currentPage);
lastPageSize = tempPage.length();
// Delete the temporary file
tempPage.delete();
} catch (IOException e) {
e.printStackTrace();
}

if (lastPageSize > maxBigPdfPageSize) {
throw new BigPdfException(BigPdfException.ExceptionType.PDF_HAS_BIG_PAGE, currentPage, lastPageSize);
}

lastPageSize = 0;
currentPage++;
}
} else {
if ((int)pres.getUploadedFile().length() > bigPdfSize) {
throw new BigPdfException(BigPdfException.ExceptionType.PDF_HAS_BIG_PAGE, 1, pres.getUploadedFile().length());
}
}


return false;
}

private void sendFailedToCountPageMessage(CountingPageException e, UploadedPresentation pres) {
MessageBuilder builder = new ConversionUpdateMessage.MessageBuilder(pres);
Expand Down Expand Up @@ -153,6 +203,34 @@ private void sendFailedToCountPageMessage(CountingPageException e, UploadedPrese
}

}

private void sendFailedToConvertBigPdfMessage(BigPdfException e, UploadedPresentation pres) {
MessageBuilder builder = new ConversionUpdateMessage.MessageBuilder(pres);

builder.messageKey(ConversionMessageConstants.PDF_HAS_BIG_PAGE);

Map<String, Object> logData = new HashMap<>();
logData.put("podId", pres.getPodId());
logData.put("meetingId", pres.getMeetingId());
logData.put("presId", pres.getId());
logData.put("filename", pres.getName());
logData.put("pdfSize", pres.getUploadedFile().length());
logData.put("bigPageNumber", e.getBigPageNumber());
logData.put("bigPageSize", e.getBigPageSize());
logData.put("logCode", "big_pdf_has_a_big_page");
logData.put("message", "The PDF contains a big page.");
Gson gson = new Gson();
String logStr = gson.toJson(logData);
log.error(" --analytics-- data={}", logStr, e);

PdfConversionInvalid progress = new PdfConversionInvalid(pres.getPodId(), pres.getMeetingId(),
pres.getId(), pres.getId(),
pres.getName(), "notUsedYet", "notUsedYet",
pres.isDownloadable(), e.getBigPageNumber(), (int)e.getBigPageSize(),
ConversionMessageConstants.PDF_HAS_BIG_PAGE);

notifier.sendDocConversionProgress(progress);
}

private void createThumbnails(UploadedPresentation pres) {
notifier.sendCreatingThumbnailsUpdateMessage(pres);
Expand Down Expand Up @@ -337,12 +415,24 @@ public void setGeneratePngs(boolean generatePngs) {
this.generatePngs = generatePngs;
}

public void setSwfSlidesRequired(boolean swf) {
this.swfSlidesRequired = swf;
public void setSwfSlidesRequired(boolean swfSlidesRequired) {
this.swfSlidesRequired = swfSlidesRequired;
}

public void setSvgImagesRequired(boolean svg) {
this.svgImagesRequired = svg;
public void setBigPdfSize(long bigPdfSize) {
this.bigPdfSize = bigPdfSize;
}

public void setMaxBigPdfPageSize(long maxBigPdfPageSize) {
this.maxBigPdfPageSize = maxBigPdfPageSize;
}

public void setPageExtractor(PageExtractor extractor) {
this.pageExtractor = extractor;
}

public void setSvgImagesRequired(boolean svgImagesRequired) {
this.svgImagesRequired = svgImagesRequired;
}

public void setThumbnailCreator(ThumbnailCreator thumbnailCreator) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.bigbluebutton.presentation.messages;

public class PdfConversionInvalid implements IDocConversionMsg {
public final String podId;
public final String meetingId;
public final String presId;
public final String presInstance;
public final String filename;
public final String uploaderId;
public final String authzToken;
public final Boolean downloadable;
public final String key;
public final Integer bigPageNumber;
public final Integer bigPageSize;

public PdfConversionInvalid(String podId, String meetingId, String presId, String presInstance,
String filename, String uploaderId, String authzToken,
Boolean downloadable, Integer bigPageNumber, Integer bigPageSize, String key) {
this.podId = podId;
this.meetingId = meetingId;
this.presId = presId;
this.presInstance = presInstance;
this.filename = filename;
this.uploaderId = uploaderId;
this.authzToken = authzToken;
this.downloadable = downloadable;
this.bigPageNumber = bigPageNumber;
this.bigPageSize = bigPageSize;
this.key = key;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ class BbbWebApiGWApp(
} else if (msg.isInstanceOf[DocPageCountExceeded]) {
val event = MsgBuilder.buildPresentationPageCountExceededSysPubMsg(msg.asInstanceOf[DocPageCountExceeded])
msgToAkkaAppsEventBus.publish(MsgToAkkaApps(toAkkaAppsChannel, event))
} else if (msg.isInstanceOf[PdfConversionInvalid]) {
val event = MsgBuilder.buildPdfConversionInvalidErrorSysPubMsg(msg.asInstanceOf[PdfConversionInvalid])
msgToAkkaAppsEventBus.publish(MsgToAkkaApps(toAkkaAppsChannel, event))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,17 @@ object MsgBuilder {
BbbCommonEnvCoreMsg(envelope, req)
}

def buildPdfConversionInvalidErrorSysPubMsg(msg: PdfConversionInvalid): BbbCommonEnvCoreMsg ={
val routing = collection.immutable.HashMap("sender" -> "bbb-web")
val envelope = BbbCoreEnvelope(PdfConversionInvalidErrorSysPubMsg.NAME, routing)
val header = BbbClientMsgHeader(PdfConversionInvalidErrorSysPubMsg.NAME, msg.meetingId, msg.authzToken)

val body = PdfConversionInvalidErrorSysPubMsgBody(podId = msg.podId, messageKey = msg.key,
code = msg.key, msg.presId, msg.bigPageNumber.intValue(), msg.bigPageSize.intValue(), msg.filename)
val req = PdfConversionInvalidErrorSysPubMsg(header, body)
BbbCommonEnvCoreMsg(envelope, req)
}

def buildPublishedRecordingSysMsg(msg: PublishedRecordingMessage): BbbCommonEnvCoreMsg = {
val routing = collection.immutable.HashMap("sender" -> "bbb-web")
val envelope = BbbCoreEnvelope(PublishedRecordingSysMsg.NAME, routing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const SUPPORTED_DOCUMENT_KEY = 'SUPPORTED_DOCUMENT';
const UNSUPPORTED_DOCUMENT_KEY = 'UNSUPPORTED_DOCUMENT';
const PAGE_COUNT_FAILED_KEY = 'PAGE_COUNT_FAILED';
const PAGE_COUNT_EXCEEDED_KEY = 'PAGE_COUNT_EXCEEDED';
const PDF_HAS_BIG_PAGE_KEY = 'PDF_HAS_BIG_PAGE';
const GENERATED_SLIDE_KEY = 'GENERATED_SLIDE';
// const GENERATING_THUMBNAIL_KEY = 'GENERATING_THUMBNAIL';
// const GENERATED_THUMBNAIL_KEY = 'GENERATED_THUMBNAIL';
Expand Down Expand Up @@ -47,6 +48,7 @@ export default function handlePresentationConversionUpdate({ body }, meetingId)
case OFFICE_DOC_CONVERSION_INVALID_KEY:
case PAGE_COUNT_FAILED_KEY:
case PAGE_COUNT_EXCEEDED_KEY:
case PDF_HAS_BIG_PAGE_KEY:
statusModifier.id = presentationId;
statusModifier.name = presentationName;
statusModifier['conversion.error'] = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ const intlMessages = defineMessages({
id: 'app.presentationUploder.conversion.pageCountExceeded',
description: 'warns the user that the conversion failed because of the page count',
},
PDF_HAS_BIG_PAGE: {
id: 'app.presentationUploder.conversion.pdfHasBigPage',
description: 'warns the user that the conversion failed because of the pdf page siz that exceeds the allowed limit',
},
isDownloadable: {
id: 'app.presentationUploder.isDownloadableLabel',
description: 'presentation is available for downloading by all viewers',
Expand Down
1 change: 1 addition & 0 deletions bigbluebutton-html5/private/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
"app.presentationUploder.conversion.generatedSlides": "Slides generated ...",
"app.presentationUploder.conversion.generatingSvg": "Generating SVG images ...",
"app.presentationUploder.conversion.pageCountExceeded": "Ops, the page count exceeded the limit of 200 pages",
"app.presentationUploder.conversion.pdfHasBigPage": "We could not convert the PDF file, please try optimizing it",
"app.presentationUploder.conversion.timeout": "Ops, the conversion took too long",
"app.presentationUploder.isDownloadableLabel": "Do not allow presentation to be downloaded",
"app.presentationUploder.isNotDownloadableLabel": "Allow presentation to be downloaded",
Expand Down
Loading

0 comments on commit ba10953

Please sign in to comment.