diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/SupportedFileTypes.java b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/SupportedFileTypes.java index 48706ff49e..eaee3e6add 100755 --- a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/SupportedFileTypes.java +++ b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/SupportedFileTypes.java @@ -28,6 +28,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.Collections; @@ -96,42 +97,64 @@ public final class SupportedFileTypes { * But none of them was as successful as the linux based command */ public static String detectMimeType(File pres) { - String mimeType = ""; - if (pres != null && pres.isFile()){ - try { - ProcessBuilder processBuilder = new ProcessBuilder(); - processBuilder.command("bash", "-c", "file -b --mime-type " + pres.getAbsolutePath()); - Process process = processBuilder.start(); - StringBuilder output = new StringBuilder(); - BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - output.append(line + "\n"); - } - int exitVal = process.waitFor(); - if (exitVal == 0) { - mimeType = output.toString().trim(); - } else { - log.error("Error while executing command {} for file {}, error: {}", - process.toString(), pres.getAbsolutePath(), process.getErrorStream()); - } - } catch (IOException e) { - log.error("Could not read file [{}]", pres.getAbsolutePath(), e.getMessage()); - } catch (InterruptedException e) { - log.error("Flow interrupted for file [{}]", pres.getAbsolutePath(), e.getMessage()); + try { + if (pres == null) throw new NullPointerException("Presentation is null"); + if (!pres.isFile()) throw new RuntimeException("Presentation is not a file"); + + ProcessBuilder processBuilder = new ProcessBuilder(); + processBuilder.command("bash", "-c", "file -b --mime-type \"" + pres.getAbsolutePath() + "\""); + Process process = processBuilder.start(); + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + output.append(line + "\n"); } + int exitVal = process.waitFor(); + if (exitVal == 0) { + return output.toString().trim(); + } else { + String executedCommand = processBuilder.command().toArray(new String[0])[2]; + + //Read error stream + BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream())); + StringBuilder errorString = new StringBuilder(); + while (stdError.ready()) { + errorString.append(stdError.readLine()); + if (stdError.ready()) { + errorString.append("\n"); + } + } + + log.error("Error while executing command '{}': {}", executedCommand, errorString); + + if (exitVal == 127) { + // 127 - command not found + // use Java method to detect in this case (based on file name) + return URLConnection.getFileNameMap().getContentTypeFor(pres.getAbsolutePath()); + } else { + throw new RuntimeException(errorString.toString()); + } + } + } catch (Exception e) { + log.error("Error while executing detectMimeType: {}", e.getMessage()); } - return mimeType; + + return ""; } public static Boolean isPresentationMimeTypeValid(File pres, String fileExtension) { String mimeType = detectMimeType(pres); - if(mimeType == null || mimeType == "") return false; + if (mimeType == null || mimeType.equals("")) { + return false; + } - if(!mimeTypeUtils.getValidMimeTypes().contains(mimeType)) return false; + if (!mimeTypeUtils.getValidMimeTypes().contains(mimeType)) { + return false; + } - if(!mimeTypeUtils.extensionMatchMimeType(mimeType, fileExtension)) { + if (!mimeTypeUtils.extensionMatchMimeType(mimeType, fileExtension)) { log.error("File with extension [{}] doesn't match with mimeType [{}].", fileExtension, mimeType); return false; } diff --git a/bbb-playback.placeholder.sh b/bbb-playback.placeholder.sh index 40524f8034..92383b10ad 100755 --- a/bbb-playback.placeholder.sh +++ b/bbb-playback.placeholder.sh @@ -1 +1 @@ -git clone --branch v5.0.0-beta.2 --depth 1 https://github.com/bigbluebutton/bbb-playback bbb-playback +git clone --branch v5.0.0-rc.1 --depth 1 https://github.com/bigbluebutton/bbb-playback bbb-playback diff --git a/bigbluebutton-config/bigbluebutton-release b/bigbluebutton-config/bigbluebutton-release index c306c7be18..2bae9790b5 100644 --- a/bigbluebutton-config/bigbluebutton-release +++ b/bigbluebutton-config/bigbluebutton-release @@ -1 +1 @@ -BIGBLUEBUTTON_RELEASE=2.6.0-rc.1 +BIGBLUEBUTTON_RELEASE=2.6.0-rc.2 diff --git a/bigbluebutton-html5/imports/ui/components/polling/component.jsx b/bigbluebutton-html5/imports/ui/components/polling/component.jsx index ee72afa14e..58e1e6828f 100644 --- a/bigbluebutton-html5/imports/ui/components/polling/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/polling/component.jsx @@ -148,7 +148,7 @@ class Polling extends Component { {answers.map((pollAnswer) => { const formattedMessageIndex = pollAnswer?.key?.toLowerCase(); let label = pollAnswer.key; - if (defaultPoll && pollAnswerIds[formattedMessageIndex]) { + if ((defaultPoll || pollType.includes('CUSTOM')) && pollAnswerIds[formattedMessageIndex]) { label = intl.formatMessage(pollAnswerIds[formattedMessageIndex]); } diff --git a/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx index ced33c1f49..3b42cc0b08 100644 --- a/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/presentation/default-content/component.jsx @@ -18,7 +18,7 @@ export default (props) => { timeout={{ enter: 400 }} > - +

{ const MAX_CHAR_LIMIT = 30; diff --git a/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx b/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx index 2ff0f9ebb4..2c75f56fdb 100644 --- a/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx +++ b/bigbluebutton-html5/imports/ui/components/whiteboard/component.jsx @@ -424,7 +424,7 @@ export default function Whiteboard(props) { if (prevFitToWidth !== null && fitToWidth !== prevFitToWidth) { const zoom = calculateZoom(slidePosition.width, slidePosition.height) tldrawAPI?.setCamera([0, 0], zoom); - const viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.width, slidePosition.height); + const viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.height, slidePosition.height); setZoom(HUNDRED_PERCENT); zoomChanger(HUNDRED_PERCENT); zoomSlide(parseInt(curPageId), podId, HUNDRED_PERCENT, viewedRegionH, 0, 0); @@ -508,13 +508,13 @@ export default function Whiteboard(props) { if (fitToWidth) { const zoom = calculateZoom(slidePosition.width, slidePosition.height) tldrawAPI?.setCamera([0, 0], zoom); - const viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.width, slidePosition.height); + const viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.height, slidePosition.height); zoomSlide(parseInt(curPageId), podId, HUNDRED_PERCENT, viewedRegionH, 0, 0); setZoom(HUNDRED_PERCENT); zoomChanger(HUNDRED_PERCENT); } else if (!isMounting) { - let viewedRegionW = SlideCalcUtil.calcViewedRegionWidth(tldrawAPI?.viewport.height, slidePosition.width); - let viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.width, slidePosition.height); + let viewedRegionW = SlideCalcUtil.calcViewedRegionWidth(tldrawAPI?.viewport.width, slidePosition.width); + let viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.height, slidePosition.height); const camera = tldrawAPI?.getPageState()?.camera; const zoomFitSlide = calculateZoom(slidePosition.width, slidePosition.height); if (!fitToWidth && camera.zoom === zoomFitSlide) { @@ -679,8 +679,8 @@ export default function Whiteboard(props) { isPresenter && zoomChanger(zoomToolbar); } - let viewedRegionW = SlideCalcUtil.calcViewedRegionWidth(tldrawAPI?.viewport.height, slidePosition.width); - let viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.width, slidePosition.height); + let viewedRegionW = SlideCalcUtil.calcViewedRegionWidth(tldrawAPI?.viewport.width, slidePosition.width); + let viewedRegionH = SlideCalcUtil.calcViewedRegionHeight(tldrawAPI?.viewport.height, slidePosition.height); if (!fitToWidth && camera.zoom === zoomFitSlide) { viewedRegionW = HUNDRED_PERCENT; @@ -805,7 +805,7 @@ export default function Whiteboard(props) { const webcams = document.getElementById('cameraDock'); const dockPos = webcams?.getAttribute("data-position"); - if(currentTool) tldrawAPI?.selectTool(currentTool); + if (currentTool && !isPanning) tldrawAPI?.selectTool(currentTool); const editableWB = ( diff --git a/bigbluebutton-html5/public/locales/fr.json b/bigbluebutton-html5/public/locales/fr.json index 6f212a934c..0980521f0d 100644 --- a/bigbluebutton-html5/public/locales/fr.json +++ b/bigbluebutton-html5/public/locales/fr.json @@ -247,7 +247,7 @@ "app.presentationUploader.exportingTimeout": "L'export dure trop longtemps...", "app.presentationUploader.export": "Envoi dans la discussion", "app.presentationUploader.export.linkAvailable": "Le lien de téléchargement {0} est disponible dans la discussion publique", - "app.presentationUploader.export.notAccessibleWarning": "peut ne pas être accessible", + "app.presentationUploader.export.notAccessibleWarning": "Probablement non conforme aux règles d'accessibilité", "app.presentationUploader.currentPresentationLabel": "Présentation courante", "app.presentationUploder.extraHint": "IMPORTANT: Le volume d'un fichier ne doit pas excéder {0} MB et {1} pages.", "app.presentationUploder.uploadLabel": "Télécharger", @@ -266,6 +266,7 @@ "app.presentationUploder.rejectedError": "Le(s) fichier(s) sélectionné(s) a (ont) été rejeté()s. Veuillez vérifier leur format.", "app.presentationUploder.connectionClosedError": "Interruption due à une connectivité faible. Veuillez essayer à nouveau.", "app.presentationUploder.upload.progress": "Chargement ({0}%)", + "app.presentationUploder.conversion.204": "Pas de contenu a capturer", "app.presentationUploder.upload.413": "Le fichier est trop volumineux, il dépasse le maximum de {0} Mo", "app.presentationUploder.genericError": "Oups, quelque chose s'est mal passé...", "app.presentationUploder.upload.408": "Le jeton de demande de téléversement a expiré.", @@ -915,6 +916,7 @@ "app.connection-status.no": "Non", "app.connection-status.notification": "Une perte de votre connexion a été détectée", "app.connection-status.offline": "Hors ligne", + "app.connection-status.clientNotRespondingWarning": "Le client ne répond pas", "app.connection-status.audioUploadRate": "Taux d'envoi audio", "app.connection-status.audioDownloadRate": "Taux de réception audio", "app.connection-status.videoUploadRate": "Taux d'envoi vidéo", diff --git a/build/packages-template/bigbluebutton/build.sh b/build/packages-template/bigbluebutton/build.sh index b2f9bd28a5..7f8b408718 100755 --- a/build/packages-template/bigbluebutton/build.sh +++ b/build/packages-template/bigbluebutton/build.sh @@ -21,17 +21,12 @@ bbb-freeswitch-core bbb-freeswitch-sounds bbb-fsesl-akka bbb-html5 -bbb-html5-nodejs bbb-learning-dashboard bbb-libreoffice-docker bbb-mkclean bbb-pads bbb-playback -bbb-playback-notes bbb-playback-presentation -bbb-playback-podcast -bbb-playback-screenshare -bbb-playback-video bbb-record-core bbb-web bbb-webrtc-sfu"