Merge pull request #12877 from antobinary/merge-23-july-30
Merge 2.3.9 into 'develop'
This commit is contained in:
commit
92e932b5cd
@ -19,8 +19,12 @@
|
||||
|
||||
package org.bigbluebutton.presentation.imp;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -28,57 +32,63 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* A wrapper class the executes an external command.
|
||||
*
|
||||
* See http://kylecartmell.com/?p=9
|
||||
*
|
||||
* @author Richard Alam
|
||||
*
|
||||
* @author Marcel Hellkamp
|
||||
*/
|
||||
public class ExternalProcessExecutor {
|
||||
private static Logger log = LoggerFactory.getLogger(ExternalProcessExecutor.class);
|
||||
// Replace with ProcessBuilder.Redirect.DISCARD in java 9+
|
||||
private static File DISCARD = new File(
|
||||
System.getProperty("os.name").startsWith("Windows") ? "NUL" : "/dev/null");
|
||||
|
||||
/**
|
||||
* Run COMMAND for at most timeoutMillis while ignoring any output.
|
||||
*
|
||||
* @deprecated The COMMAND string is split on whitespace to create an argument
|
||||
* list. This won't work for arguments that contain whitespace. Use
|
||||
* {@link #exec(List, Duration)} instead.
|
||||
*
|
||||
* @param COMMAND A single command or whitespace separated list of
|
||||
* arguments.
|
||||
* @param timeoutMillis Timeout in milliseconds.
|
||||
* @return true if the command terminated in time with an exit value of 0.
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean exec(String COMMAND, long timeoutMillis) {
|
||||
Timer timer = new Timer(false);
|
||||
Process p = null;
|
||||
return exec(Arrays.asList(COMMAND.split("[ \\t\\n\\r\\f]+")), Duration.ofMillis(timeoutMillis));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a command for a limited amount of time while ignoring any output.
|
||||
*
|
||||
* @param cmd List containing the program and its arguments.
|
||||
* @param timeout Maximum execution time.
|
||||
* @return true if the command terminated in time with an exit value of 0.
|
||||
*/
|
||||
public boolean exec(List<String> cmd, Duration timeout) {
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd);
|
||||
pb.redirectError(DISCARD);
|
||||
pb.redirectOutput(DISCARD);
|
||||
|
||||
Process proc;
|
||||
try {
|
||||
InterruptTimerTask interrupter = new InterruptTimerTask(Thread.currentThread());
|
||||
timer.schedule(interrupter, timeoutMillis);
|
||||
p = Runtime.getRuntime().exec(COMMAND);
|
||||
int result = p.waitFor();
|
||||
if (result == 0) {
|
||||
return true;
|
||||
} else {
|
||||
proc = pb.start();
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to execute: {}", String.join(" ", cmd), e);
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
log.info("TIMEDOUT excuting : {}", COMMAND);
|
||||
if (p != null) {
|
||||
p.destroy();
|
||||
}
|
||||
} finally {
|
||||
timer.cancel(); // If the process returns within the timeout period, we have to stop the interrupter
|
||||
// so that it does not unexpectedly interrupt some other code later.
|
||||
|
||||
Thread.interrupted(); // We need to clear the interrupt flag on the current thread just in case
|
||||
// interrupter executed after waitFor had already returned but before timer.cancel
|
||||
// took effect.
|
||||
//
|
||||
// Oh, and there's also Sun bug 6420270 to worry about here.
|
||||
try {
|
||||
if (!proc.waitFor(timeout.toMillis(), TimeUnit.MILLISECONDS)) {
|
||||
log.warn("TIMEDOUT excuting: {}", String.join(" ", cmd));
|
||||
proc.destroy();
|
||||
}
|
||||
return !proc.isAlive() && proc.exitValue() == 0;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
proc.destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class InterruptTimerTask extends TimerTask {
|
||||
private Thread thread;
|
||||
|
||||
public InterruptTimerTask(Thread t) {
|
||||
this.thread = t;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
thread.interrupt();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1 @@
|
||||
BIGBLUEBUTTON_RELEASE=2.4-beta-1
|
||||
|
||||
|
@ -45,7 +45,28 @@ function breakouts(role) {
|
||||
],
|
||||
};
|
||||
|
||||
return Breakouts.find(selector);
|
||||
const fields = {
|
||||
fields: {
|
||||
users: {
|
||||
$elemMatch: {
|
||||
// do not allow users to obtain 'redirectToHtml5JoinURL' for others
|
||||
userId,
|
||||
},
|
||||
},
|
||||
breakoutId: 1,
|
||||
externalId: 1,
|
||||
freeJoin: 1,
|
||||
isDefaultName: 1,
|
||||
joinedUsers: 1,
|
||||
name: 1,
|
||||
parentMeetingId: 1,
|
||||
sequence: 1,
|
||||
shortName: 1,
|
||||
timeRemaining: 1,
|
||||
},
|
||||
};
|
||||
|
||||
return Breakouts.find(selector, fields);
|
||||
}
|
||||
|
||||
function publish(...args) {
|
||||
|
@ -11,8 +11,6 @@ const logConnectionStatus = (meetingId, userId, status, type, value) => {
|
||||
Logger.info(`Connection status updated: meetingId=${meetingId} userId=${userId} status=${status} type=${type}`);
|
||||
break;
|
||||
case 'warning':
|
||||
// Skip
|
||||
break;
|
||||
case 'danger':
|
||||
case 'critical':
|
||||
switch (type) {
|
||||
|
@ -25,7 +25,7 @@ function groupChatMsg(chatsIds) {
|
||||
timestamp: { $gte: User.authTokenValidatedTime },
|
||||
$or: [
|
||||
{ meetingId, chatId: { $eq: PUBLIC_GROUP_CHAT_ID } },
|
||||
{ chatId: { $in: chatsIds } },
|
||||
{ meetingId, chatId: { $in: chatsIds } },
|
||||
],
|
||||
};
|
||||
return GroupChatMsg.find(selector);
|
||||
|
@ -1,18 +1,30 @@
|
||||
import GuestUsers from '/imports/api/guest-users/';
|
||||
import Users from '/imports/api/users';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import AuthTokenValidation, { ValidationStates } from '/imports/api/auth-token-validation';
|
||||
|
||||
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
||||
|
||||
function guestUsers() {
|
||||
const tokenValidation = AuthTokenValidation.findOne({ connectionId: this.connection.id });
|
||||
|
||||
if (!tokenValidation || tokenValidation.validationStatus !== ValidationStates.VALIDATED) {
|
||||
Logger.warn(`Publishing GuestUsers was requested by unauth connection ${this.connection.id}`);
|
||||
Logger.warn(`Publishing GuestUser was requested by unauth connection ${this.connection.id}`);
|
||||
return GuestUsers.find({ meetingId: '' });
|
||||
}
|
||||
|
||||
const { meetingId, userId } = tokenValidation;
|
||||
|
||||
const User = Users.findOne({ userId, meetingId }, { fields: { role: 1 } });
|
||||
if (!User || User.role !== ROLE_MODERATOR) {
|
||||
Logger.warn(
|
||||
'Publishing current-poll was requested by non-moderator connection',
|
||||
{ meetingId, userId, connectionId: this.connection.id },
|
||||
);
|
||||
return GuestUsers.find({ meetingId: '' });
|
||||
}
|
||||
|
||||
Logger.debug(`Publishing GuestUsers for ${meetingId} ${userId}`);
|
||||
|
||||
return GuestUsers.find({ meetingId });
|
||||
|
@ -1,18 +1,39 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import Logger from '/imports/startup/server/logger';
|
||||
import Users from '/imports/api/users';
|
||||
import Polls from '/imports/api/polls';
|
||||
import AuthTokenValidation, { ValidationStates } from '/imports/api/auth-token-validation';
|
||||
import AuthTokenValidation, {
|
||||
ValidationStates,
|
||||
} from '/imports/api/auth-token-validation';
|
||||
|
||||
const ROLE_MODERATOR = Meteor.settings.public.user.role_moderator;
|
||||
|
||||
function currentPoll(secretPoll) {
|
||||
const tokenValidation = AuthTokenValidation.findOne({ connectionId: this.connection.id });
|
||||
const tokenValidation = AuthTokenValidation.findOne({
|
||||
connectionId: this.connection.id,
|
||||
});
|
||||
|
||||
if (!tokenValidation || tokenValidation.validationStatus !== ValidationStates.VALIDATED) {
|
||||
Logger.warn(`Publishing Polls was requested by unauth connection ${this.connection.id}`);
|
||||
if (
|
||||
!tokenValidation ||
|
||||
tokenValidation.validationStatus !== ValidationStates.VALIDATED
|
||||
) {
|
||||
Logger.warn(
|
||||
`Publishing Polls was requested by unauth connection ${this.connection.id}`
|
||||
);
|
||||
return Polls.find({ meetingId: '' });
|
||||
}
|
||||
|
||||
const { meetingId, userId } = tokenValidation;
|
||||
|
||||
const User = Users.findOne({ userId, meetingId }, { fields: { role: 1 } });
|
||||
if (!User || User.role !== ROLE_MODERATOR) {
|
||||
Logger.warn(
|
||||
'Publishing current-poll was requested by non-moderator connection',
|
||||
{ meetingId, userId, connectionId: this.connection.id }
|
||||
);
|
||||
return Polls.find({ meetingId: '' });
|
||||
}
|
||||
|
||||
Logger.debug('Publishing Polls', { meetingId, userId });
|
||||
|
||||
const selector = {
|
||||
@ -38,10 +59,17 @@ function publishCurrentPoll(...args) {
|
||||
Meteor.publish('current-poll', publishCurrentPoll);
|
||||
|
||||
function polls() {
|
||||
const tokenValidation = AuthTokenValidation.findOne({ connectionId: this.connection.id });
|
||||
const tokenValidation = AuthTokenValidation.findOne({
|
||||
connectionId: this.connection.id,
|
||||
});
|
||||
|
||||
if (!tokenValidation || tokenValidation.validationStatus !== ValidationStates.VALIDATED) {
|
||||
Logger.warn(`Publishing Polls was requested by unauth connection ${this.connection.id}`);
|
||||
if (
|
||||
!tokenValidation ||
|
||||
tokenValidation.validationStatus !== ValidationStates.VALIDATED
|
||||
) {
|
||||
Logger.warn(
|
||||
`Publishing Polls was requested by unauth connection ${this.connection.id}`
|
||||
);
|
||||
return Polls.find({ meetingId: '' });
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,7 @@ class Pad extends PureComponent {
|
||||
this.toggleListen = this.toggleListen.bind(this);
|
||||
this.handleListen = this.handleListen.bind(this);
|
||||
|
||||
if (this.recognition) {
|
||||
this.recognition.addEventListener('end', () => {
|
||||
const { listening } = this.state;
|
||||
if (listening) {
|
||||
@ -94,6 +95,7 @@ class Pad extends PureComponent {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
const {
|
||||
@ -103,8 +105,13 @@ class Pad extends PureComponent {
|
||||
} = this.props;
|
||||
|
||||
if (this.recognition) {
|
||||
if (ownerId !== currentUserId) {
|
||||
this.recognition.stop();
|
||||
} else if (this.state.listening && this.recognition.lang !== locale) {
|
||||
this.recognition.stop();
|
||||
this.stopListen();
|
||||
}
|
||||
this.recognition.lang = locale;
|
||||
if (ownerId !== currentUserId) this.recognition.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user