diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
index 743a4894c4acec763614b2f9d50ca560e59ba24b..c393e3d1c5f8eb881a53fcba4b64f89d4a9e1b3e 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
@@ -19,6 +19,8 @@ trait SystemConfiguration extends RedisConfiguration {
   lazy val expireLastUserLeft = Try(config.getInt("expire.lastUserLeft")).getOrElse(60) // 1 minute
   lazy val expireNeverJoined = Try(config.getInt("expire.neverJoined")).getOrElse(5 * 60) // 5 minutes
 
+  lazy val maxRegUserToJoinTime = Try(config.getInt("expire.maxRegUserToJoin")).getOrElse(5 * 60) // 5 minutes
+
   lazy val analyticsChannel = Try(config.getString("eventBus.analyticsChannel")).getOrElse("analytics-channel")
   lazy val meetingManagerChannel = Try(config.getString("eventBus.meetingManagerChannel")).getOrElse("MeetingManagerChannel")
   lazy val outMessageChannel = Try(config.getString("eventBus.outMessageChannel")).getOrElse("OutgoingMessageChannel")
@@ -40,10 +42,9 @@ trait SystemConfiguration extends RedisConfiguration {
   lazy val applyPermissionCheck = Try(config.getBoolean("apps.checkPermissions")).getOrElse(false)
 
   lazy val voiceConfRecordPath = Try(config.getString("voiceConf.recordPath")).getOrElse("/var/freeswitch/meetings")
-  lazy val recordingChapterBreakLenghtInMinutes = Try(config.getInt("recording.chapterBreakLengthInMinutes")).getOrElse(180)
+  lazy val recordingChapterBreakLengthInMinutes = Try(config.getInt("recording.chapterBreakLengthInMinutes")).getOrElse(0)
 
   lazy val endMeetingWhenNoMoreAuthedUsers = Try(config.getBoolean("apps.endMeetingWhenNoMoreAuthedUsers")).getOrElse(false)
   lazy val endMeetingWhenNoMoreAuthedUsersAfterMinutes = Try(config.getInt("apps.endMeetingWhenNoMoreAuthedUsersAfterMinutes")).getOrElse(2)
   lazy val multiUserWhiteboardDefault = Try(config.getBoolean("whiteboard.multiUserDefault")).getOrElse(false)
 }
-
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/CreateBreakoutRoomsCmdMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/CreateBreakoutRoomsCmdMsgHdlr.scala
index e4e4da045a51cb46250b7601fcf01bf1b8ce9154..678dfe94452b7bd92f0da5e4a58549896195ac5b 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/CreateBreakoutRoomsCmdMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/breakout/CreateBreakoutRoomsCmdMsgHdlr.scala
@@ -55,6 +55,7 @@ trait CreateBreakoutRoomsCmdMsgHdlr extends RightsManagementTrait {
         liveMeeting.props.meetingProp.intId,
         breakout.sequence,
         breakout.freeJoin,
+        liveMeeting.props.voiceProp.dialNumber,
         breakout.voiceConf,
         msg.body.durationInMinutes,
         liveMeeting.props.password.moderatorPass,
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala
index 5cce9c4908f83e8d1488a5510b46cb045d65fc6a..12dafc857e63664e905329e5a23f81f650adcd3f 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala
@@ -7,7 +7,18 @@ object RegisteredUsers {
   def create(userId: String, extId: String, name: String, roles: String,
              token: String, avatar: String, guest: Boolean, authenticated: Boolean,
              guestStatus: String): RegisteredUser = {
-    new RegisteredUser(userId, extId, name, roles, token, avatar, guest, authenticated, guestStatus)
+    new RegisteredUser(userId,
+      extId,
+      name,
+      roles,
+      token,
+      avatar,
+      guest,
+      authenticated,
+      guestStatus,
+      System.currentTimeMillis(),
+      false,
+      false)
   }
 
   def findWithToken(token: String, users: RegisteredUsers): Option[RegisteredUser] = {
@@ -18,6 +29,10 @@ object RegisteredUsers {
     users.toVector.find(ru => id == ru.id)
   }
 
+  def findUsersNotJoined(users: RegisteredUsers):Vector[RegisteredUser] = {
+    users.toVector.filter(u => u.joined == false && u.markAsJoinTimedOut == false)
+  }
+
   def getRegisteredUserWithToken(token: String, userId: String, regUsers: RegisteredUsers): Option[RegisteredUser] = {
     def isSameUserId(ru: RegisteredUser, userId: String): Option[RegisteredUser] = {
       if (userId.startsWith(ru.id)) {
@@ -33,14 +48,6 @@ object RegisteredUsers {
     } yield user
   }
 
-  def updateRegUser(uvo: UserVO, users: RegisteredUsers) {
-    for {
-      ru <- RegisteredUsers.findWithUserId(uvo.id, users)
-      regUser = new RegisteredUser(uvo.id, uvo.externalId, uvo.name, uvo.role, ru.authToken,
-        uvo.avatarURL, uvo.guest, uvo.authed, uvo.guestStatus)
-    } yield users.save(regUser)
-  }
-
   def add(users: RegisteredUsers, user: RegisteredUser): Vector[RegisteredUser] = {
     users.save(user)
   }
@@ -63,6 +70,17 @@ object RegisteredUsers {
     u
   }
 
+  def updateUserJoin(users: RegisteredUsers, user: RegisteredUser): RegisteredUser = {
+    val u = user.copy(joined = true)
+    users.save(u)
+    u
+  }
+
+  def markAsUserFailedToJoin(users: RegisteredUsers, user: RegisteredUser): RegisteredUser = {
+    val u = user.copy(markAsJoinTimedOut = true)
+    users.save(u)
+    u
+  }
 }
 
 class RegisteredUsers {
@@ -84,7 +102,16 @@ class RegisteredUsers {
   }
 }
 
-case class RegisteredUser(id: String, externId: String, name: String, role: String,
-                          authToken: String, avatarURL: String, guest: Boolean,
-                          authed: Boolean, guestStatus: String)
+case class RegisteredUser(id: String,
+                          externId: String,
+                          name: String,
+                          role: String,
+                          authToken: String,
+                          avatarURL: String,
+                          guest: Boolean,
+                          authed: Boolean,
+                          guestStatus: String,
+                          registeredOn: Long,
+                          joined: Boolean,
+                          markAsJoinTimedOut: Boolean)
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala
index fd9294e20602e3211a071698ed6ea476f518e386..eb1cd57adaac565b7a9865c976d65c8caf3d78b9 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/HandlerHelpers.scala
@@ -26,12 +26,22 @@ trait HandlerHelpers extends SystemConfiguration {
     outGW.send(event)
   }
 
+  def trackUserJoin(outGW: OutMsgRouter,
+                    liveMeeting: LiveMeeting,
+                    regUser: RegisteredUser): Unit = {
+    if (!regUser.joined) {
+      RegisteredUsers.updateUserJoin(liveMeeting.registeredUsers, regUser)
+    }
+  }
+
   def userJoinMeeting(outGW: OutMsgRouter, authToken: String, clientType: String,
                       liveMeeting: LiveMeeting, state: MeetingState2x): MeetingState2x = {
 
     val nu = for {
       regUser <- RegisteredUsers.findWithToken(authToken, liveMeeting.registeredUsers)
     } yield {
+      trackUserJoin(outGW, liveMeeting, regUser)
+
       UserState(
         intId = regUser.id,
         extId = regUser.externId,
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
index 5cf811b39fed2e549407996a8488b26207171ff2..84741d152da8040e0146fc778461c5f4e12f3ac8 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
@@ -506,7 +506,7 @@ class MeetingActor(
     setRecordingChapterBreak()
 
     processUserInactivityAudit()
-
+    flagRegisteredUsersWhoHasNotJoined()
     checkIfNeetToEndMeetingWhenNoAuthedUsers(liveMeeting)
   }
 
@@ -517,7 +517,8 @@ class MeetingActor(
     val elapsedInMs = now - lastRecBreakSentOn
     val elapsedInMin = TimeUtil.millisToMinutes(elapsedInMs)
 
-    if (elapsedInMin > recordingChapterBreakLenghtInMinutes) {
+    if (recordingChapterBreakLengthInMinutes > 0 &&
+        elapsedInMin > recordingChapterBreakLengthInMinutes) {
       lastRecBreakSentOn = now
       val event = MsgBuilder.buildRecordingChapterBreakSysMsg(props.meetingProp.intId, TimeUtil.timeNowInMs())
       outGW.send(event)
@@ -657,4 +658,19 @@ class MeetingActor(
       }
     }
   }
+
+  def flagRegisteredUsersWhoHasNotJoined(): Unit = {
+    val users = RegisteredUsers.findUsersNotJoined(liveMeeting.registeredUsers)
+    users foreach{ u =>
+      val now = System.currentTimeMillis()
+      if (now - u.registeredOn > TimeUtil.secondsToMillis(maxRegUserToJoinTime)) {
+        RegisteredUsers.markAsUserFailedToJoin(liveMeeting.registeredUsers, u)
+        val event = MsgBuilder.buildRegisteredUserJoinTimeoutMsg(
+          liveMeeting.props.meetingProp.intId,
+          u.id,
+          u.name)
+        outGW.send(event)
+      }
+    }
+  }
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/util/TimeUtil.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/util/TimeUtil.scala
index d24d5dfa101b848ba3d669f8c59963bdd71f4919..3e897cf5d96ebe9d9cd1dbf402bc4253952737d0 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/util/TimeUtil.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/util/TimeUtil.scala
@@ -20,6 +20,10 @@ object TimeUtil {
     TimeUnit.MINUTES.toSeconds(minutes)
   }
 
+  def secondsToMillis(seconds: Long): Long = {
+    TimeUnit.SECONDS.toMillis(seconds)
+  }
+
   def timeNowInMinutes(): Long = TimeUnit.NANOSECONDS.toMinutes(System.nanoTime())
   def timeNowInSeconds(): Long = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime())
   def timeNowInMs(): Long = TimeUnit.NANOSECONDS.toMillis(System.nanoTime())
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala
index 7a4eec74e32c271c10b4bb4af2e6e050b86c123e..44c375a77289a2343e16a55379e9928bbcf6b66a 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/AnalyticsActor.scala
@@ -31,6 +31,7 @@ class AnalyticsActor extends Actor with ActorLogging {
 
     msg.core match {
       case m: RegisterUserReqMsg => logMessage(msg)
+      case m: RegisteredUserJoinTimeoutMsg => logMessage(msg)
       case m: UserRegisteredRespMsg => logMessage(msg)
       case m: DisconnectAllClientsSysMsg => logMessage(msg)
       case m: DisconnectClientSysMsg => logMessage(msg)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
index 220314a53a929a27268d77a6c40eb684c51bee63..ac693a9b1c1dc71a4cad8998a4192d3ed8c53384 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
@@ -317,4 +317,13 @@ object MsgBuilder {
 
     BbbCommonEnvCoreMsg(envelope, event)
   }
+
+  def buildRegisteredUserJoinTimeoutMsg(meetingId: String, userId: String, name: String): BbbCommonEnvCoreMsg = {
+    val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
+    val envelope = BbbCoreEnvelope(RegisteredUserJoinTimeoutMsg.NAME, routing)
+    val header = BbbCoreHeaderWithMeetingId(RegisteredUserJoinTimeoutMsg.NAME, meetingId)
+    val body = RegisteredUserJoinTimeoutMsgBody(meetingId, userId, name)
+    val event = RegisteredUserJoinTimeoutMsg(header, body)
+    BbbCommonEnvCoreMsg(envelope, event)
+  }
 }
diff --git a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala
index 3e57891347a7b653e8fe4392aea6854d7065ddc1..2fcfc442176b2afbf5f40b7f3a95c84c06540371 100755
--- a/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala
+++ b/akka-bbb-apps/src/test/scala/org/bigbluebutton/core/AppsTestFixtures.scala
@@ -26,6 +26,7 @@ trait AppsTestFixtures {
   val userInactivityThresholdInMinutes = 10
   val userActivitySignResponseDelayInMinutes = 5
   val autoStartRecording = false
+  val keepEvents = false
   val allowStartStopRecording = false
   val webcamsOnlyForModerator = false;
   val moderatorPassword = "modpass"
@@ -53,7 +54,7 @@ trait AppsTestFixtures {
     userInactivityInspectTimerInMinutes = userInactivityInspectTimerInMinutes, userInactivityThresholdInMinutes = userInactivityInspectTimerInMinutes, userActivitySignResponseDelayInMinutes = userActivitySignResponseDelayInMinutes)
   val password = PasswordProp(moderatorPass = moderatorPassword, viewerPass = viewerPassword)
   val recordProp = RecordProp(record = record, autoStartRecording = autoStartRecording,
-    allowStartStopRecording = allowStartStopRecording)
+    allowStartStopRecording = allowStartStopRecording, keepEvents = keepEvents )
   val welcomeProp = WelcomeProp(welcomeMsgTemplate = welcomeMsgTemplate, welcomeMsg = welcomeMsg,
     modOnlyMessage = modOnlyMessage)
   val voiceProp = VoiceProp(telVoice = voiceConfId, voiceConf = voiceConfId, dialNumber = dialNumber, muteOnStart = muteOnStart)
diff --git a/akka-bbb-apps/src/universal/conf/application.conf b/akka-bbb-apps/src/universal/conf/application.conf
index 591f22a88f5ef2613020407b8dc6f493bb6cf046..22387092ca02e8dec6eb7e5713500f277b8d670b 100755
--- a/akka-bbb-apps/src/universal/conf/application.conf
+++ b/akka-bbb-apps/src/universal/conf/application.conf
@@ -39,6 +39,7 @@ expire {
   # time in seconds
   lastUserLeft = 60
   neverJoined = 300
+  maxRegUserToJoin = 300
 }
 
 services {
@@ -84,7 +85,8 @@ voiceConf {
 }
 
 recording {
-  chapterBreakLengthInMinutes = 180
+  # set zero to disable chapter break
+  chapterBreakLengthInMinutes = 0
 }
 
 whiteboard {
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/BreakoutMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/BreakoutMsgs.scala
index 0048b8fe85a16ba3a9bdf722cb52fe1c48a274d1..deb7848ece378e2dc3e3afd8fd0d2fb4506bdb83 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/BreakoutMsgs.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/BreakoutMsgs.scala
@@ -39,9 +39,9 @@ package org.bigbluebutton.common2.msgs
   case class CreateBreakoutRoomSysCmdMsg(header: BbbCoreBaseHeader,
                                       body: CreateBreakoutRoomSysCmdMsgBody) extends BbbCoreMsg
   case class CreateBreakoutRoomSysCmdMsgBody(meetingId: String, room: BreakoutRoomDetail)
-  case class BreakoutRoomDetail(breakoutMeetingId: String, name: String, parentId: String, sequence: Integer, freeJoin:Boolean,
-                                voiceConfId: String, durationInMinutes: Int, moderatorPassword: String, viewerPassword: String,
-                                sourcePresentationId: String, sourcePresentationSlide: Int, record: Boolean)
+  case class BreakoutRoomDetail(breakoutMeetingId: String, name: String, parentId: String, sequence: Integer, freeJoin: Boolean,
+                                dialNumber: String, voiceConfId: String, durationInMinutes: Int, moderatorPassword: String,
+                                viewerPassword: String, sourcePresentationId: String, sourcePresentationSlide: Int, record: Boolean)
 
 /**
   * Sent by client to request to create breakout rooms.
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala
index dea63077aa094b6978c12454b3372d0c602a98c8..b3295c269cb9660312f2b61c520521bbb7d51a45 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/UsersMgs.scala
@@ -18,6 +18,11 @@ case class UserRegisteredRespMsg(header: BbbCoreHeaderWithMeetingId,
                               body: UserRegisteredRespMsgBody) extends BbbCoreMsg
 case class UserRegisteredRespMsgBody(meetingId: String, userId: String, name: String, role: String)
 
+object RegisteredUserJoinTimeoutMsg { val NAME = "RegisteredUserJoinTimeoutMsg" }
+case class RegisteredUserJoinTimeoutMsg(header: BbbCoreHeaderWithMeetingId,
+                                 body: RegisteredUserJoinTimeoutMsgBody) extends BbbCoreMsg
+case class RegisteredUserJoinTimeoutMsgBody(meetingId: String, userId: String, name: String)
+
 object ValidateAuthTokenReqMsg {
   val NAME = "ValidateAuthTokenReqMsg"
 
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java
index 95803cc58be22488493aa3891a8e24daafa61d9a..2d3f5cc3a4916c63b7b751cdc8858f1be58a0540 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/MeetingService.java
@@ -474,18 +474,19 @@ public class MeetingService implements MessageListener {
     if (parentMeeting != null) {
 
       Map<String, String> params = new HashMap<>();
-      params.put("name", message.name);
-      params.put("meetingID", message.meetingId);
-      params.put("parentMeetingID", message.parentMeetingId);
-      params.put("isBreakout", "true");
-      params.put("sequence", message.sequence.toString());
-      params.put("freeJoin", message.freeJoin.toString());
-      params.put("attendeePW", message.viewerPassword);
-      params.put("moderatorPW", message.moderatorPassword);
-      params.put("voiceBridge", message.voiceConfId);
-      params.put("duration", message.durationInMinutes.toString());
-      params.put("record", message.record.toString());
-      params.put("welcome", getMeeting(message.parentMeetingId).getWelcomeMessageTemplate());
+      params.put(ApiParams.NAME, message.name);
+      params.put(ApiParams.MEETING_ID, message.meetingId);
+      params.put(ApiParams.PARENT_MEETING_ID, message.parentMeetingId);
+      params.put(ApiParams.IS_BREAKOUT, "true");
+      params.put(ApiParams.SEQUENCE, message.sequence.toString());
+      params.put(ApiParams.FREE_JOIN, message.freeJoin.toString());
+      params.put(ApiParams.ATTENDEE_PW, message.viewerPassword);
+      params.put(ApiParams.MODERATOR_PW, message.moderatorPassword);
+      params.put(ApiParams.DIAL_NUMBER, message.dialNumber);
+      params.put(ApiParams.VOICE_BRIDGE, message.voiceConfId);
+      params.put(ApiParams.DURATION, message.durationInMinutes.toString());
+      params.put(ApiParams.RECORD, message.record.toString());
+      params.put(ApiParams.WELCOME, getMeeting(message.parentMeetingId).getWelcomeMessageTemplate());
 
       Map<String, String> parentMeetingMetadata = parentMeeting.getMetadata();
 
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/CreateBreakoutRoom.java b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/CreateBreakoutRoom.java
index 33915458bf8ab0d93795db61ba1c131423babd2b..df8789d9ddebe2492a3f05608e1b926425b5570f 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/CreateBreakoutRoom.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/api/messaging/messages/CreateBreakoutRoom.java
@@ -6,7 +6,9 @@ public class CreateBreakoutRoom implements IMessage {
     public final String parentMeetingId; // The main meeting internal id
     public final String name; // The name of the breakout room
     public final Integer sequence; // The sequence number of the breakout room
-    public final Boolean freeJoin; // Allow users to freely join the conference in the client
+    public final Boolean freeJoin; // Allow users to freely join the conference
+                                   // in the client
+    public final String dialNumber;
     public final String voiceConfId; // The voice conference id
     public final String viewerPassword;
     public final String moderatorPassword;
@@ -15,16 +17,15 @@ public class CreateBreakoutRoom implements IMessage {
     public final Integer sourcePresentationSlide;
     public final Boolean record;
 
-    public CreateBreakoutRoom(String meetingId, String parentMeetingId,
-            String name, Integer sequence, Boolean freeJoin, String voiceConfId,
-            String viewerPassword, String moderatorPassword, Integer duration,
-            String sourcePresentationId, Integer sourcePresentationSlide,
-            Boolean record) {
+    public CreateBreakoutRoom(String meetingId, String parentMeetingId, String name, Integer sequence, Boolean freeJoin,
+            String dialNumber, String voiceConfId, String viewerPassword, String moderatorPassword, Integer duration,
+            String sourcePresentationId, Integer sourcePresentationSlide, Boolean record) {
         this.meetingId = meetingId;
         this.parentMeetingId = parentMeetingId;
         this.name = name;
         this.sequence = sequence;
         this.freeJoin = freeJoin;
+        this.dialNumber = dialNumber;
         this.voiceConfId = voiceConfId;
         this.viewerPassword = viewerPassword;
         this.moderatorPassword = moderatorPassword;
diff --git a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java
index 06248a30b260584c6d616765014d290c51d03bf0..ecb9dd3c717d9309704528900885f9ee90320b43 100755
--- a/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java
+++ b/bbb-common-web/src/main/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java
@@ -57,6 +57,7 @@ public class PdfToSwfSlidesGenerationService {
   private long MAX_CONVERSION_TIME = 5 * 60 * 1000L * 1000L * 1000L;
   private String BLANK_SLIDE;
   private int MAX_SWF_FILE_SIZE;
+  private boolean swfSlidesRequired;
   private boolean svgImagesRequired;
   private boolean generatePngs;
 
@@ -64,26 +65,30 @@ public class PdfToSwfSlidesGenerationService {
     executor = Executors.newFixedThreadPool(numConversionThreads);
   }
 
-  public void generateSlides(UploadedPresentation pres) {
-    determineNumberOfPages(pres);
-    if (pres.getNumberOfPages() > 0) {
-      convertPdfToSwf(pres);
-      createTextFiles(pres);
-      createThumbnails(pres);
+    public void generateSlides(UploadedPresentation pres) {
+        determineNumberOfPages(pres);
+        if (pres.getNumberOfPages() > 0) {
+            // Only create SWF files if the configuration requires it
+            if (swfSlidesRequired) {
+                convertPdfToSwf(pres);
+                createThumbnails(pres);
+            }
 
-      // only create SVG images if the configuration requires it
-      if (svgImagesRequired) {
-        createSvgImages(pres);
-      }
+            createTextFiles(pres);
+
+            // only create SVG images if the configuration requires it
+            if (svgImagesRequired) {
+                createSvgImages(pres);
+            }
 
-			// only create PNG images if the configuration requires it
-			if (generatePngs) {
-				createPngImages(pres);
-			}
+            // only create PNG images if the configuration requires it
+            if (generatePngs) {
+                createPngImages(pres);
+            }
 
-      notifier.sendConversionCompletedMessage(pres);
+            notifier.sendConversionCompletedMessage(pres);
+        }
     }
-  }
 
   private boolean determineNumberOfPages(UploadedPresentation pres) {
     try {
@@ -331,9 +336,13 @@ public class PdfToSwfSlidesGenerationService {
     this.generatePngs = generatePngs;
   }
 
-	public void setSvgImagesRequired(boolean svg) {
-		this.svgImagesRequired = svg;
-	}
+  public void setSwfSlidesRequired(boolean swf) {
+    this.swfSlidesRequired = swf;
+  }
+
+  public void setSvgImagesRequired(boolean svg) {
+    this.svgImagesRequired = svg;
+  }
 
   public void setThumbnailCreator(ThumbnailCreator thumbnailCreator) {
     this.thumbnailCreator = thumbnailCreator;
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala
index 9a8f00075b244b3d371ad2751bb9b28629f6d7ca..9f4f2cb59af2009936cc911d95e6ebc6e7761255 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/MeetingsManagerActor.scala
@@ -9,8 +9,8 @@ import org.bigbluebutton.common2.msgs.{BbbCommonEnvCoreMsg, MeetingCreatedEvtMsg
 
 sealed trait ApiMsg
 case class CreateBreakoutRoomMsg(meetingId: String, parentMeetingId: String,
-                                 name: String, sequence: Integer, freeJoin: Boolean, voiceConfId: String,
-                                 viewerPassword: String, moderatorPassword: String, duration: Int,
+                                 name: String, sequence: Integer, freeJoin: Boolean, dialNumber: String,
+                                 voiceConfId: String, viewerPassword: String, moderatorPassword: String, duration: Int,
                                  sourcePresentationId: String, sourcePresentationSlide: Int,
                                  record: Boolean) extends ApiMsg
 
diff --git a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala
index a80ea64206f107d6d7ebe35eaa31e0d562e2d3bd..7a7e376c2e54752cb54cf471e3d4bbcef9dae322 100755
--- a/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala
+++ b/bbb-common-web/src/main/scala/org/bigbluebutton/api2/meeting/OldMeetingMsgHdlrActor.scala
@@ -75,6 +75,7 @@ class OldMeetingMsgHdlrActor(val olgMsgGW: OldMessageReceivedGW)
        msg.body.room.name,
        msg.body.room.sequence,
        msg.body.room.freeJoin,
+       msg.body.room.dialNumber,
        msg.body.room.voiceConfId,
        msg.body.room.viewerPassword,
        msg.body.room.moderatorPassword,
diff --git a/bigbluebutton-config/bin/apply-lib.sh b/bigbluebutton-config/bin/apply-lib.sh
index 2073bdc900e1635ca9ab88cbd820585c101a8220..6b6c330aeaf7aa1e0c2d1f3ba6d62fd722f80f0d 100644
--- a/bigbluebutton-config/bin/apply-lib.sh
+++ b/bigbluebutton-config/bin/apply-lib.sh
@@ -89,10 +89,10 @@ notCalled() {
 #!/bin/bash
 
 # Pull in the helper functions for configuring BigBlueButton
-source apply-lib.sh
+source /etc/bigbluebutton/bbb-conf/apply-lib.sh
 
 # Put your custom configuration here
-enableHTML5ClientLog
+# enableHTML5ClientLog
 
 HERE
 chmod +x /etc/bigbluebutton/bbb-conf/apply-config.sh
diff --git a/bigbluebutton-config/bin/bbb-conf b/bigbluebutton-config/bin/bbb-conf
index 1e65db7f213445b0aac145e1965005240d115ec8..cf45462a88b32135ad52077c7f7b9b4e3fadda90 100755
--- a/bigbluebutton-config/bin/bbb-conf
+++ b/bigbluebutton-config/bin/bbb-conf
@@ -1,6 +1,6 @@
-#!/bin/bash 
+#!/bin/bash
 #
-# BlueButton open source conferencing system - http://www.bigbluebutton.org/   
+# BlueButton open source conferencing system - http://www.bigbluebutton.org/
 #
 # Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
 #
@@ -17,20 +17,20 @@
 # with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
 #
 # Author(s):
-#       Fred Dixon <ffdixon@bigbluebutton.org>
-#	Sebastian Schneider <seb.sschneider@gmail.com>
-#	Ghazi Triki <ghazi.nocturne@gmail.com>
+#   Fred Dixon <ffdixon@bigbluebutton.org>
+#   Sebastian Schneider <seb.sschneider@gmail.com>
+#   Ghazi Triki <ghazi.nocturne@gmail.com>
 #
 # Changelog:
-#   2009-10-18 FFD  Inital Version   
-#   2009-11-05 FFD  Updated for 0.62   
-#   2009-12-09 FFD  Updated for 0.63   
-#   2009-12-11 FFD  Added ability to switch conference servers   
-#   2009-12-12 FFD  Added cleaning and watching of log files   
-#   2010-01-05 FFD  Added zipping of log files   
-#   2010-01-18 FFD  Added resetting of environment back to using packages   
-#   2010-03-02 JRT  Added trunk checkout options / fixed bbb-apps instructions   
-#   2010-04-02 FFD  Updated for 0.64   
+#   2009-10-18 FFD  Initial Version
+#   2009-11-05 FFD  Updated for 0.62
+#   2009-12-09 FFD  Updated for 0.63
+#   2009-12-11 FFD  Added ability to switch conference servers
+#   2009-12-12 FFD  Added cleaning and watching of log files
+#   2010-01-05 FFD  Added zipping of log files
+#   2010-01-18 FFD  Added resetting of environment back to using packages
+#   2010-03-02 JRT  Added trunk checkout options / fixed bbb-apps instructions
+#   2010-04-02 FFD  Updated for 0.64
 #   2010-06-21 SEB  Cleaned up some code / Updated for 0.70
 #   2010-06-25 SEB  Added ability to change the security secret
 #   2010-06-30 SEB  Added some extra error checking
@@ -40,15 +40,15 @@
 #   2010-11-06 FFD  Added logic to ensure red5 shuts down
 #   2010-12-12 FFD  Fixed bug #778
 #   2010-12-12 FFD  Added support for Intalio VM
-#   2010-02-28 FFD  Fixed #834 
+#   2010-02-28 FFD  Fixed #834
 #   2011-06-26 FFD  Updates for 0.8
-#   2012-01-14 FFD  Tsting the development environment for 0.8
+#   2012-01-14 FFD  Testing the development environment for 0.8
 #   2012-02-22 FFD  Updates to development environment
 #   2012-04-27 FFD  Added sum of version numbers in --check
 #   2013-02-03 FFD  Updated for changes to parameters for 0.81 in bigbluebutton-sip.properties
 #   2013-11-07 FFD  Finished 0.81
-#   2014-01-13 FFD  Working on updates for 0.9.0 
-#   2014-03-10 GUG  Enable Webrtc
+#   2014-01-13 FFD  Working on updates for 0.9.0
+#   2014-03-10 GUG  Enable WebRTC
 #   2015-03-12 FFD  Added start/stop of HTML5 server
 #   2016-01-13 FFD  Updates for 1.0
 #   2016-02-28 FFD  Updates to support HTTPS configuration
@@ -59,77 +59,76 @@
 #   2018-11-22 MNE  Dynamically detect if sudo is needed
 #   2018-12-09 GTR  More logs cleanup
 #   2019-02-08 GTR  Updates for 2.2 after extracting bbb-web to a standalone server application
+#   2019-03-14 GTR  Refactoring and cleanup for 2.2
 
 #set -x
 #set -e
 
 PATH=$PATH:/sbin
 
-if [ "$(id -u)" != "0" ]; then 
-  if [ -x "$(which sudo)" ]; then 
-    SUDO="$(which sudo)"
-  else 
-    echo "bbb-conf must be ran as root!" && exit 1
-  fi
+if [[ "$(id -u)" != "0" ]]; then
+    if [[ -x "$(which sudo)" ]]; then
+        SUDO="$(which sudo)"
+    else
+        echo "bbb-conf must be ran as root!" && exit 1
+    fi
 fi
 
-if [ ! -f /etc/bigbluebutton/bigbluebutton-release ]; then
-	echo 
-	echo "# BigBlueButton does not appear to be installed.  Could not"
-	echo "# locate: /etc/bigbluebutton/bigbluebutton-release"
-	echo 
-	exit 1
+if [[ ! -f /etc/bigbluebutton/bigbluebutton-release ]]; then
+    echo
+    echo "# BigBlueButton does not appear to be installed.  Could not"
+    echo "# locate: /etc/bigbluebutton/bigbluebutton-release"
+    echo
+    exit 1
 fi
 
+# Load the content of the file as variables
 source /etc/bigbluebutton/bigbluebutton-release
 
 #
 # Figure out our environment (Debian vs. CentOS)
 #
 
-if [ -f /etc/redhat-release ]; then
-  DISTRIB_ID=centos
-  SERVLET_LOGS=/usr/share/tomcat/logs
-  FREESWITCH=freeswitch
-  TOMCAT_SERVICE=tomcat
-  REDIS_SERVICE=redis.service
+if [ -f /etc/centos-release ]; then
+    DISTRIB_ID=centos
+    TOMCAT_SERVICE=tomcat
+    TOMCAT_DIR=/var/lib/$TOMCAT_SERVICE
+    SERVLET_LOGS=/usr/share/tomcat/logs
+    REDIS_SERVICE=redis.service
 else
-  . /etc/lsb-release    # Get value for DISTRIB_ID
-  SERVLET_LOGS=$TOMCAT_DIR/logs
-  FREESWITCH=freeswitch
-  TOMCAT_SERVICE=tomcat7
-  REDIS_SERVICE=redis-server
+    . /etc/lsb-release    # Get value for DISTRIB_ID
+    TOMCAT_SERVICE=tomcat7
+    TOMCAT_DIR=/var/lib/$TOMCAT_SERVICE
+    SERVLET_LOGS=$TOMCAT_DIR/logs
+    REDIS_SERVICE=redis-server
 fi
 
+# Common to Ubuntu and CentOS
+FREESWITCH_VARS=/opt/freeswitch/etc/freeswitch/vars.xml
+FREESWITCH_EXTERNAL=/opt/freeswitch/etc/freeswitch/sip_profiles/external.xml
+FREESWITCH_PID=/opt/freeswitch/var/run/freeswitch/freeswitch.pid
+FREESWITCH_EVENT_SOCKET=/opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml
 
 RED5=red5
 RED5_DIR=/usr/share/$RED5
 
-
-TOMCAT_DIR=/var/lib/$TOMCAT_SERVICE
 LTI_DIR=$TOMCAT_DIR/webapps/lti
 
 if [ -f /usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties ]; then
-  SERVLET_DIR=/usr/share/bbb-web
+    SERVLET_DIR=/usr/share/bbb-web
 else
-  SERVLET_DIR=/var/lib/tomcat7/webapps/bigbluebutton
+    SERVLET_DIR=/var/lib/tomcat7/webapps/bigbluebutton
 fi
 
 PROTOCOL=http
 if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
-  SERVER_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
-  if cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep bigbluebutton.web.serverURL | grep -q https; then
-    PROTOCOL=https
-  fi
+    SERVER_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
+    if cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep bigbluebutton.web.serverURL | grep -q https; then
+        PROTOCOL=https
+    fi
 fi
 PROTOCOL_RTMP=rtmp
 
-FREESWITCH_VARS=/opt/freeswitch/conf/vars.xml
-FREESWITCH_EXTERNAL=/opt/freeswitch/conf/sip_profiles/external.xml
-FREESWITCH_PID=/opt/freeswitch/run/freeswitch.pid
-FREESWITCH_EVENT_SOCKET=/opt/freeswitch/conf/autoload_configs/event_socket.conf.xml
-FREESWITCH_INIT_D="/etc/init.d/freeswitch"
-
 RECORD_CONFIG=/usr/local/bigbluebutton/core/scripts/bigbluebutton.yml
 
 HTML5_CONFIG_OLD=/usr/share/meteor/bundle/programs/server/assets/app/config/settings-production.json
@@ -137,88 +136,64 @@ HTML5_CONFIG=/usr/share/meteor/bundle/programs/server/assets/app/config/settings
 
 KURENTO_CONFIG=/usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml
 
-BBB_WEB_CONFIG=$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties
+BBB_WEB_CONFIG="$SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties"
 NGINX_IP=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/server_name/{s/.*server_name[ ]*//;s/;//;p}' | cut -d' ' -f1 | head -n 1)
 SIP_CONFIG=/etc/bigbluebutton/nginx/sip.nginx
 SIP_NGINX_IP=$(cat $SIP_CONFIG |  grep -v '#' | sed -n '/proxy_pass/{s/.*proxy_pass http[s]*:\/\///;s/:.*//;p}' | head -n 1)
 
-NCPU=`nproc --all`
+NCPU=$(nproc --all)
 
 BBB_USER=bigbluebutton
 
-if [ -f /etc/redhat-release ]; then
-  DISTRIB_ID=centos
-  SERVLET_LOGS=/usr/share/tomcat/logs
-  FREESWITCH=freeswitch
-  FREESWITCH_INIT_D="/etc/init.d/freeswitch"
-  TOMCAT_SERVICE=tomcat
-  REDIS_SERVICE=redis.service
-else
-  . /etc/lsb-release    # Get value for DISTRIB_ID
-  SERVLET_LOGS=$TOMCAT_DIR/logs
-  FREESWITCH=freeswitch
-  FREESWITCH_INIT_D="/etc/init.d/freeswitch"
-  TOMCAT_SERVICE=tomcat7
-  REDIS_SERVICE=redis-server
-
-  FREESWITCH_VARS=/opt/freeswitch/etc/freeswitch/vars.xml
-  FREESWITCH_EXTERNAL=/opt/freeswitch/etc/freeswitch/sip_profiles/external.xml
-  FREESWITCH_PID=/opt/freeswitch/var/run/freeswitch/freeswitch.pid
-  FREESWITCH_EVENT_SOCKET=/opt/freeswitch/etc/freeswitch/autoload_configs/event_socket.conf.xml
-fi
-
 if [ ! -f /usr/share/red5/webapps/bigbluebutton/WEB-INF/red5-web.xml ]; then
-	echo "#"
-	echo "# BigBlueButton does not appear to be installed.  Could not"
-	echo "# locate:"
-	echo "#"
-	echo "# /usr/share/red5/webapps/bigbluebutton/WEB-INF/red5-web.xml"
-	exit 1
+    echo "#"
+    echo "# BigBlueButton does not appear to be installed.  Could not"
+    echo "# locate:"
+    echo "#"
+    echo "# /usr/share/red5/webapps/bigbluebutton/WEB-INF/red5-web.xml"
+    exit 1
 fi
 
 if [ ! -f /var/www/bigbluebutton/client/conf/config.xml ]; then
-	echo "#"
-	echo "# BigBlueButton does not appear to be installed.  Could not"
-	echo "# locate:"
-	echo "#"
-	echo "# /var/www/bigbluebutton/client/conf/config.xml"
-	exit 1
+    echo "#"
+    echo "# BigBlueButton does not appear to be installed.  Could not"
+    echo "# locate:"
+    echo "#"
+    echo "# /var/www/bigbluebutton/client/conf/config.xml"
+    exit 1
 fi
 
 #
 # We're going to give ^bigbluebutton.web.logoutURL a default value (if undefined) so bbb-conf does not give a warning
 #
 if [ -f $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties ]; then
-	if cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -q ^bigbluebutton.web.logoutURL=$; then
-		$SUDO sed -i s/^bigbluebutton.web.logoutURL=$/bigbluebutton.web.logoutURL=default/g $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties
-	fi
+    if cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -q ^bigbluebutton.web.logoutURL=$; then
+        $SUDO sed -i s/^bigbluebutton.web.logoutURL=$/bigbluebutton.web.logoutURL=default/g $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties
+    fi
 fi
 
-VOICE_CONFERENCE="bbb-voice-freeswitch.xml"
-
 #
 # Determine IP so it works on multilingual installations
 #
 
 if LANG=c ifconfig | grep -q 'venet0:0'; then
-  IP=$(ifconfig | grep -v '127.0.0.1' | grep -E "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | tail -1 | cut -d: -f2 | awk '{ print $1}')
+    IP=$(ifconfig | grep -v '127.0.0.1' | grep -E "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | tail -1 | cut -d: -f2 | awk '{ print $1}')
 else
-  IP=$(hostname -I | cut -f1 -d' ')
+    IP=$(hostname -I | cut -f1 -d' ')
 fi
 
 if [ -z "$IP" ]; then
-  if [ -f /etc/redhat-release ]; then
-    IP=$(hostname -I | sed 's/ .*//g')
-  fi
+    if [ $DISTRIB_ID == "centos" ]; then
+        IP=$(hostname -I | sed 's/ .*//g')
+    fi
 fi
 
 #
 # Calculate total memory on this server
 #
-MEM=`grep MemTotal /proc/meminfo | awk '{print $2}'`
+MEM=$(grep MemTotal /proc/meminfo | awk '{print $2}')
 MEM=$((MEM/1000))
 
-
 #
 # Check if the function has a value and, if not, print an error message
 # $1 -- name of value
@@ -226,518 +201,394 @@ MEM=$((MEM/1000))
 # $3 -- value to check
 #
 check_no_value() {
-	if [ -z $3 ]; then
-		echo "# Tried to check $1 in"
-		echo "#    $2"
-		echo "# but value is empty."
-		exit 1
-	fi
+    if [ -z $3 ]; then
+        echo "# Tried to check $1 in"
+        echo "#    $2"
+        echo "# but value is empty."
+        exit 1
+    fi
 }
 
 check_file() {
-	if [ ! -f $1 ]; then
-		echo "# File does not exist: $1"
-	fi
+    if [ ! -f $1 ]; then
+        echo "# File does not exist: $1"
+    fi
 }
 
 print_header() {
-	if [ ! $HEADER ]; then
-		echo
-		echo "** Potential problems described below **"
-		HEADER=1
-	fi
-}
-
-check_root() {
-	if [ $EUID == 0 ]; then
-		echo "This operation should not be run as root."
-		echo 
-		echo "If this operation needs to execute an operation as root, you'll be asked for"
-		echo "your password to execute the operation using sudo."
-		exit 1
-	fi
+    if [ ! $HEADER ]; then
+        echo
+        echo "** Potential problems described below **"
+        HEADER=1
+    fi
 }
 
 need_root() {
-	if [ $EUID != 0 ]; then
-		echo "Need to be root to run this option"
-		exit 1
-	fi
+    if [ $EUID != 0 ]; then
+        echo "Need to be root to run this option"
+        exit 1
+    fi
 }
 
 
 
 usage() {
-	echo "BigBlueButton Configuration Utility - Version $BIGBLUEBUTTON_RELEASE"
-        echo
-        echo "   bbb-conf [options]"
-        echo
-        echo "Configuration:"
-        echo "   --version                        Display BigBlueButton version (packages)"
-        echo "   --setip <IP/hostname>            Set IP/hostname for BigBlueButton"
-        echo "   --setsecret <secret>             Change the shared secret in bigbluebutton.properties"
-        echo
-        echo "Monitoring:"
-        echo "   --check                          Check configuration files and processes for problems"
-        echo "   --debug                          Scan the log files for error messages"
-        echo "   --watch                          Scan the log files for error messages every 2 seconds"
-        echo "   --network                        View network connections on 80 and 1935 by IP address"
-        echo "   --secret                         View the URL and shared secret for the server"
-        echo "   --lti                            View the URL and secret for LTI (if installed)"
-        echo
-        echo "Administration:"
-        echo "   --restart                        Restart BigBlueButton"
-        echo "   --stop                           Stop BigBlueButton"
-        echo "   --start                          Start BigBlueButton"
-        echo "   --clean                          Restart and clean all log files"
-        echo "   --status                         Display running status of components"
-        echo "   --zip                            Zip up log files for reporting an error"
-
-        echo
+    echo "BigBlueButton Configuration Utility - Version $BIGBLUEBUTTON_RELEASE"
+    echo
+    echo "   bbb-conf [options]"
+    echo
+    echo "Configuration:"
+    echo "   --version                        Display BigBlueButton version (packages)"
+    echo "   --setip <IP/hostname>            Set IP/hostname for BigBlueButton"
+    echo "   --setsecret <secret>             Change the shared secret in bigbluebutton.properties"
+    echo
+    echo "Monitoring:"
+    echo "   --check                          Check configuration files and processes for problems"
+    echo "   --debug                          Scan the log files for error messages"
+    echo "   --watch                          Scan the log files for error messages every 2 seconds"
+    echo "   --network                        View network connections on 80 and 1935 by IP address"
+    echo "   --secret                         View the URL and shared secret for the server"
+    echo "   --lti                            View the URL and secret for LTI (if installed)"
+    echo
+    echo "Administration:"
+    echo "   --restart                        Restart BigBlueButton"
+    echo "   --stop                           Stop BigBlueButton"
+    echo "   --start                          Start BigBlueButton"
+    echo "   --clean                          Restart and clean all log files"
+    echo "   --status                         Display running status of components"
+    echo "   --zip                            Zip up log files for reporting an error"
+    echo
 }
 
 # utility function to make a copy of the conf file
 check_and_backup () {
-	# can we write to the configuration file?
-	if [ ! -w $1 ]; then
-		echo "Cannot write to $1!"
-		exit 1
-	fi
-
-	# let's see if we need a copy
-	if [ "$TO_BACKUP" = "Y" ]; then
-		cp $1 $1.bak
-		TO_BACKUP="N"
-	fi
+    # can we write to the configuration file?
+    if [ ! -w $1 ]; then
+        echo "Cannot write to $1!"
+        exit 1
+    fi
+
+    # let's see if we need a copy
+    if [ "$TO_BACKUP" = "Y" ]; then
+        cp $1 $1.bak
+        TO_BACKUP="N"
+    fi
 }
 
 # 3 paramenter: the file, the variable name, the new value
 change_var_value () {
-	check_and_backup $1
-	sed -i "s<^[[:blank:]#]*\(${2}\).*<\1=${3}<" $1
+    check_and_backup $1
+    sed -i "s<^[[:blank:]#]*\(${2}\).*<\1=${3}<" $1
 }
 
 # same as change_var_value but with quotes
 change_var_salt() {
-	check_and_backup $1
-	sed -i "s<^[[:blank:]#]*\(${2}\).*<\1="${3}"<" $1
+    check_and_backup $1
+    sed -i "s<^[[:blank:]#]*\(${2}\).*<\1="${3}"<" $1
 }
 
 # comment lines matching $2 ($1 is the file)
 comment () {
-	check_and_backup $1
-	sed -i "s<^[[:blank:]]*\(${2}.*\)<#\1<" $1
+    check_and_backup $1
+    sed -i "s<^[[:blank:]]*\(${2}.*\)<#\1<" $1
 }
 
 change_yml_value () {
-	sed -i "s<^\([[:blank:]#]*\)\(${2}\): .*<\1\2: ${3}<" $1
+    sed -i "s<^\([[:blank:]#]*\)\(${2}\): .*<\1\2: ${3}<" $1
 }
 
 
 # comment lines matching $2 ($1 is the file)
 uncomment () {
-	check_and_backup $1
-	sed -i "s<^[#[:blank:]]*\(${2}.*\)<\1<" $1
+    check_and_backup $1
+    sed -i "s<^[#[:blank:]]*\(${2}.*\)<\1<" $1
 }
 
 stop_bigbluebutton () {
     echo "Stopping BigBlueButton"
-    if command -v systemctl >/dev/null; then
-       if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
-          HTML5="mongod bbb-html5 bbb-webrtc-sfu kurento-media-server"
-       fi
-       if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
-          WEBHOOKS=bbb-webhooks
-       fi
-       if [ -f /usr/lib/systemd/system/bbb-transcode-akka.service ]; then
-          BBB_TRANSCODE_AKKA=bbb-transcode-akka
-       fi
-       if [ -f /usr/share/etherpad-lite/settings.json ]; then
-          ETHERPAD=etherpad
-       fi
-       if [ -f /lib/systemd/system/bbb-web.service ]; then
-          BBB_WEB=bbb-web
-       fi
-
-       systemctl stop red5 $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka $BBB_TRANSCODE_AKKA bbb-fsesl-akka bbb-rap-archive-worker.service bbb-rap-process-worker.service bbb-rap-publish-worker.service bbb-rap-sanity-worker.service bbb-record-core.timer $HTML5 $WEBHOOKS $ETHERPAD $BBB_WEB
-    else
-	/etc/init.d/monit stop
-
-	/etc/init.d/$RED5 stop
-	/etc/init.d/${TOMCAT_SERVICE} stop
-	/etc/init.d/nginx stop
-        
-	if [ -a $FREESWITCH_PID ]; then
-		$FREESWITCH_INIT_D stop
-	fi
-        
-	if [ -f /etc/init.d/bbb-office ]; then
-		/etc/init.d/bbb-office stop
-	fi
-
-	if [ -f /etc/init.d/bbb-record-core ]; then
-		/etc/init.d/bbb-record-core stop
-	fi
-
-        if [ -f /etc/init/bbb-apps-akka.conf ]; then
-                service bbb-apps-akka stop
-        fi
-        if [ -f /etc/init.d/bbb-apps-akka ]; then
-                /etc/init.d/bbb-apps-akka stop
-        fi
 
-        if [ -f /etc/init/bbb-fsesl-akka.conf ]; then
-                service bbb-fsesl-akka stop
-        fi
-        if [ -f /etc/init.d/bbb-fsesl-akka ]; then
-                /etc/init.d/bbb-fsesl-akka stop
-        fi
+    if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
+        HTML5="mongod bbb-html5 bbb-webrtc-sfu kurento-media-server"
+    fi
 
-        if [ -f /etc/init/bbb-transcode-akka.conf ]; then
-                service bbb-transcode-akka stop
-        fi
-        if [ -f /etc/init.d/bbb-transcode-akka ]; then
-                /etc/init.d/bbb-transcode-akka stop
-        fi
-   fi
+    if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
+        WEBHOOKS=bbb-webhooks
+    fi
+
+    if [ -f /usr/lib/systemd/system/bbb-transcode-akka.service ]; then
+        BBB_TRANSCODE_AKKA=bbb-transcode-akka
+    fi
+
+    if [ -f /usr/share/etherpad-lite/settings.json ]; then
+        ETHERPAD=etherpad
+    fi
+
+    if [ -f /lib/systemd/system/bbb-web.service ]; then
+        BBB_WEB=bbb-web
+    fi
+
+    systemctl stop red5 $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka $BBB_TRANSCODE_AKKA bbb-fsesl-akka bbb-rap-archive-worker.service bbb-rap-process-worker.service bbb-rap-publish-worker.service bbb-rap-sanity-worker.service bbb-record-core.timer $HTML5 $WEBHOOKS $ETHERPAD $BBB_WEB
 }
 
 start_bigbluebutton () {
-        #
-        # Apply any local configuration options (if exists)
-        #
-        if [ -x /etc/bigbluebutton/bbb-conf/apply-config.sh ]; then
-		echo
-                echo "Applying updates in /etc/bigbluebutton/bbb-conf/apply-config.sh: "
-                /etc/bigbluebutton/bbb-conf/apply-config.sh
-                echo
-        fi
-	
-	if [ -f /opt/freeswitch/var/log/freeswitch/freeswitch.log ]; then
-            if grep -q "Failure to connect to CORE_DB sofia_reg_external" /opt/freeswitch/var/log/freeswitch/freeswitch.log; then
-		# See: http://docs.bigbluebutton.org/install/install.html#freeswitch-fails-to-bind-to-ipv4
-                echo "Clearing the FreeSWITCH database."
-		rm -rf /opt/freeswitch/var/lib/freeswitch/db/*
-	    fi
-        fi
-
-	# Clear any previous registration errors
-	if [ -f /usr/share/red5/log/sip.log ]; then
-	  sed -i 's/Failed to register with Sip Server/Failed to register with Sip server/g' /usr/share/red5/log/sip.log
-	fi
+    #
+    # Apply any local configuration options (if exists)
+    #
+    if [ -x /etc/bigbluebutton/bbb-conf/apply-config.sh ]; then
+        echo
+        echo "Applying updates in /etc/bigbluebutton/bbb-conf/apply-config.sh: "
+        /etc/bigbluebutton/bbb-conf/apply-config.sh
+        echo
+    fi
 
-    echo "Starting BigBlueButton"
-    if command -v systemctl >/dev/null; then
-       if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
-          HTML5="mongod bbb-html5 bbb-webrtc-sfu kurento-media-server"
-       fi
-       if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
-          WEBHOOKS=bbb-webhooks
-       fi
-       if [ -f /usr/lib/systemd/system/bbb-transcode-akka.service ]; then
-          BBB_TRANSCODE_AKKA=bbb-transcode-akka
-       fi
-       if [ -f /usr/share/etherpad-lite/settings.json ]; then
-          ETHERPAD=etherpad
-       fi
-       if [ -f /lib/systemd/system/bbb-web.service ]; then
-          BBB_WEB=bbb-web
-       fi
-
-       systemctl start red5 $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka $BBB_TRANSCODE_AKKA bbb-fsesl-akka bbb-record-core.timer $HTML5 $WEBHOOKS $ETHERPAD $BBB_WEB
-       if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
-          systemctl start mongod
-	  sleep 3
-          systemctl start bbb-html5
-       fi
-    else
-	$FREESWITCH_INIT_D start
-	
-	FREESWITCH_ESL_IP=$(cat $FREESWITCH_EVENT_SOCKET | grep 'name="listen-ip"' | cut -d\" -f4  | awk '{print $1}')
-	check_no_value listen-ip $FREESWITCH_EVENT_SOCKET $FREESWITCH_ESL_IP
-
-	echo -n "Waiting for FreeSWITCH to start: "
-
-	if [[ ! -z $FREESWITCH_ESL_IP && $DISTRIB_ID != "centos" ]]; then
-		while ! nc -w 1 $FREESWITCH_ESL_IP 8021 > /dev/null; do
-			echo -n "."
-			sleep 1
-		done
-	fi
-	echo
-
-	/etc/init.d/nginx start
-	/etc/init.d/$RED5 start
-	/etc/init.d/${TOMCAT_SERVICE} start
-
-	# monit will start libreoffice and bbb-rap-worker
-	/etc/init.d/monit start
-	echo
-	echo "Note: monit will automatically start bbb-record-core and LibreOffice within 60 seconds."
-	echo
-
-	BBB_WEB=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
-	if [ -f /etc/init/bbb-html5.conf ]; then
-		echo -n "Waiting for Meteor (HTML5 server) to finish starting up (this may take a minute): "
-		start bbb-html5
-
-        	if ! wget -q -O - http://$BBB_WEB/html5client/check | grep running > /dev/null; then
-                    while ! wget -q -O - http://$BBB_WEB/html5client/check | grep running > /dev/null; do
-                        echo -n "."
-                        sleep 1
-                    done
-		fi
+    if [ -f /opt/freeswitch/var/log/freeswitch/freeswitch.log ]; then
+        if grep -q "Failure to connect to CORE_DB sofia_reg_external" /opt/freeswitch/var/log/freeswitch/freeswitch.log; then
+            # See: http://docs.bigbluebutton.org/install/install.html#freeswitch-fails-to-bind-to-ipv4
+            echo "Clearing the FreeSWITCH database."
+            rm -rf /opt/freeswitch/var/lib/freeswitch/db/*
         fi
+    fi
 
-        if [ -f /etc/init/bbb-apps-akka.conf ]; then
-                service bbb-apps-akka start
-        fi
-        if [ -f /etc/init.d/bbb-apps-akka ]; then
-                /etc/init.d/bbb-apps-akka start
-        fi
+    # Clear any previous registration errors
+    if [ -f /usr/share/red5/log/sip.log ]; then
+        sed -i 's/Failed to register with Sip Server/Failed to register with Sip server/g' /usr/share/red5/log/sip.log
+    fi
 
-        if [ -f /etc/init/bbb-fsesl-akka.conf ]; then
-                service bbb-fsesl-akka start
-        fi
-        if [ -f /etc/init.d/bbb-fsesl-akka ]; then
-                /etc/init.d/bbb-fsesl-akka start
-        fi
+    echo "Starting BigBlueButton"
+    if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
+        HTML5="mongod bbb-html5 bbb-webrtc-sfu kurento-media-server"
+    fi
 
-        if [ -f /etc/init/bbb-transcode-akka.conf ]; then
-                service bbb-transcode-akka start
-        fi
-        if [ -f /etc/init.d/bbb-transcode-akka ]; then
-                /etc/init.d/bbb-transcode-akka start
-        fi
+    if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
+        WEBHOOKS=bbb-webhooks
+    fi
 
+    if [ -f /usr/lib/systemd/system/bbb-transcode-akka.service ]; then
+        BBB_TRANSCODE_AKKA=bbb-transcode-akka
+    fi
 
-	#
-	# At this point the red5 and servlet container applications are starting up.
-	#
-	echo -n "Waiting for BigBlueButton to finish starting up (this may take a minute): "
+    if [ -f /usr/share/etherpad-lite/settings.json ]; then
+        ETHERPAD=etherpad
+    fi
 
-	check_no_value server_name /etc/nginx/sites-available/bigbluebutton $NGINX_IP
+    if [ -f /lib/systemd/system/bbb-web.service ]; then
+        BBB_WEB=bbb-web
+    fi
 
-        #if ! wget http://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS; then
-        #        echo "Startup unsuccessful: could not connect to http://$BBB_WEB/bigbluebutton/api"
-        #        exit 1
-	#fi
+    systemctl start red5 $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka $BBB_TRANSCODE_AKKA bbb-fsesl-akka bbb-record-core.timer $HTML5 $WEBHOOKS $ETHERPAD $BBB_WEB
+    if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
+        systemctl start mongod
+        sleep 3
+        systemctl start bbb-html5
     fi
 
-        #
-        # Look for Starting up context to be recently added to the log files
-        #
-        COUNT=0
-        while [ $COUNT -lt 20 ]; do
-          let COUNT=COUNT+1
-          if [ -f $RED5_DIR/log/sip.log ] && [ -f $RED5_DIR/log/bigbluebutton.log ] && [ -f $RED5_DIR/log/red5.log ] && [ -f $RED5_DIR/log/video.log ] && [ -f $RED5_DIR/log/screenshare-slf.log ]; then
+    #
+    # Look for Starting up context to be recently added to the log files
+    #
+    COUNT=0
+    while [ $COUNT -lt 20 ]; do
+        let COUNT=COUNT+1
+        if [ -f $RED5_DIR/log/sip.log ] && [ -f $RED5_DIR/log/bigbluebutton.log ] && [ -f $RED5_DIR/log/red5.log ] && [ -f $RED5_DIR/log/video.log ] && [ -f $RED5_DIR/log/screenshare-slf.log ]; then
             let COUNT=20
-          else
+        else
             echo -n "."
             sleep 1
-          fi
-        done
-
-
-	#
-	# All the log files exist, now check for the text "Starting up context"
-	#
-	COUNT=0
-	while [ $COUNT -lt 20 ]; do
-	  let COUNT=COUNT+1
-	  if [ -f $RED5_DIR/log/video.log ]; then
-	    if ! cat $RED5_DIR/log/video.log | tail -n100 | grep -q "Starting up context"; then
-	      echo -n "."
-	      sleep 1
-	    else
-	      let COUNT=20
+        fi
+    done
+
+
+     #
+     # All the log files exist, now check for the text "Starting up context"
+     #
+     COUNT=0
+     while [ $COUNT -lt 20 ]; do
+         let COUNT=COUNT+1
+         if [ -f $RED5_DIR/log/video.log ]; then
+             if ! cat $RED5_DIR/log/video.log | tail -n100 | grep -q "Starting up context"; then
+                 echo -n "."
+                 sleep 1
+             else
+                 let COUNT=20
             fi
-	  fi
-	done
-
-	echo
-	BBB_APPS="sip video bigbluebutton screenshare-slf"
-	for bbb_app in $BBB_APPS ; do
-	        if [ -a $RED5_DIR/log/$bbb_app.log ]; then
-	                if ! grep -q "Starting up context" $RED5_DIR/log/$bbb_app.log; then
-	                        echo "#    $bbb_app may not have started properly"
-	                fi
-	        else
-	                echo "#    $RED5_DIR/log/$bbb_app.log not found"
-	        fi
-	done
-
+         fi
+     done
+
+     echo
+     BBB_APPS="sip video bigbluebutton screenshare-slf"
+     for bbb_app in $BBB_APPS ; do
+        if [ -a $RED5_DIR/log/$bbb_app.log ]; then
+            if ! grep -q "Starting up context" $RED5_DIR/log/$bbb_app.log; then
+                echo "#    $bbb_app may not have started properly"
+            fi
+        else
+            echo "#    $RED5_DIR/log/$bbb_app.log not found"
+        fi
+     done
 }
 
 display_bigbluebutton_status () {
-    if command -v systemctl >/dev/null; then
-        units="red5 $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka bbb-transcode-akka bbb-fsesl-akka"
-
-        if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
-            units="$units mongod bbb-html5 bbb-webrtc-sfu kurento-media-server"
-        fi
+    units="red5 $TOMCAT_SERVICE nginx freeswitch $REDIS_SERVICE bbb-apps-akka bbb-transcode-akka bbb-fsesl-akka"
 
-        if [ -f /lib/systemd/system/bbb-web.service ]; then
-            units="$units bbb-web"
-        fi
+    if [ -f /usr/lib/systemd/system/bbb-html5.service ]; then
+        units="$units mongod bbb-html5 bbb-webrtc-sfu kurento-media-server"
+    fi
 
-        line='——————————————————————►'
-        for unit in $units; do
-            status=$(systemctl is-active "$unit")
-            if [ "$status" = "active" ]; then
-                printf "%s %s [✔ - $status]\n" $unit "${line:${#unit}}"
-            else
-                printf "%s %s [✘ - $status]\n" $unit "${line:${#unit}}"
-			fi
-        done 
-    else
-        /etc/init.d/nginx status
-        /etc/init.d/$RED5 status
-        /etc/init.d/${TOMCAT_SERVICE} status
+    if [ -f /lib/systemd/system/bbb-web.service ]; then
+        units="$units bbb-web"
     fi
+
+    line='——————————————————————►'
+    for unit in $units; do
+        status=$(systemctl is-active "$unit")
+        if [ "$status" = "active" ]; then
+            printf "%s %s [✔ - $status]\n" $unit "${line:${#unit}}"
+        else
+            printf "%s %s [✘ - $status]\n" $unit "${line:${#unit}}"
+        fi
+    done
 }
 
 if [ $# -eq 0 ]; then
-	usage
-	exit 1
+    usage
+    exit 1
 fi
 
 # Parse the parameters
 while [ $# -gt 0 ]; do
-	if [ "$1" = "-stop" -o "$1" = "--stop" ]; then
-		need_root
-		stop_bigbluebutton
-		exit 0
-	fi
-
-	if [ "$1" = "-start" -o "$1" = "--start" ]; then
-		need_root
-		start_bigbluebutton
-		exit 0
-	fi
-
-	if [ "$1" = "-check" -o "$1" = "--check" -o "$1" = "-c" ]; then
-		CHECK=1
-		shift;shift 
-		continue
-	fi
-
-	if [ "$1" = "--version" -o "$1" = "-version" -o "$1" = "-v" ]; then
-		VERSION=1
-		shift
-		continue
-	fi		
-
-	if [ "$1" = "--debug" -o "$1" = "-debug" -o "$1" = "-d" ]; then
-		DEBUG=1
-		shift
-		continue
-	fi
-
-	if [ "$1" = "--clean" -o "$1" = "-clean" ]; then
-		CLEAN=1
-		shift
-		continue
-	fi
-
-	if [ "$1" = "--watch" -o "$1" = "-watch" -o "$1" = "-w" ]; then
-		WATCH=1
-		shift
-		continue
-	fi
-
-	if [ "$1" = "--network" -o "$1" = "-network" -o "$1" = "-n" ]; then
-		NETWORK=1
-		shift
-		continue
-	fi
-
-	if [ "$1" = "--zip" -o "$1" = "-zip" -o "$1" = "-z" ]; then
-		ZIP=1
-		shift
-		continue
-	fi
-
-	if [ "$1" = "--status" -o "$1" = "-status" ]; then
-                display_bigbluebutton_status
-		exit 0
+    if [ "$1" = "-stop" -o "$1" = "--stop" ]; then
+        need_root
+        stop_bigbluebutton
+        exit 0
+    fi
+
+    if [ "$1" = "-start" -o "$1" = "--start" ]; then
+        need_root
+        start_bigbluebutton
+        exit 0
+    fi
+
+    if [ "$1" = "-check" -o "$1" = "--check" -o "$1" = "-c" ]; then
+        CHECK=1
+        shift;shift
+        continue
+    fi
+
+    if [ "$1" = "--version" -o "$1" = "-version" -o "$1" = "-v" ]; then
+        VERSION=1
+        shift
+        continue
+    fi
+
+    if [ "$1" = "--debug" -o "$1" = "-debug" -o "$1" = "-d" ]; then
+        DEBUG=1
+        shift
+        continue
+    fi
+
+    if [ "$1" = "--clean" -o "$1" = "-clean" ]; then
+        CLEAN=1
+        shift
+        continue
+    fi
+
+    if [ "$1" = "--watch" -o "$1" = "-watch" -o "$1" = "-w" ]; then
+        WATCH=1
+        shift
+        continue
+    fi
+
+    if [ "$1" = "--network" -o "$1" = "-network" -o "$1" = "-n" ]; then
+        NETWORK=1
+        shift
+        continue
+    fi
+
+    if [ "$1" = "--zip" -o "$1" = "-zip" -o "$1" = "-z" ]; then
+        ZIP=1
+        shift
+        continue
+    fi
+
+    if [ "$1" = "--status" -o "$1" = "-status" ]; then
+        display_bigbluebutton_status
+        exit 0
+    fi
+
+    if [ "$1" = "--restart" -o "$1" = "-restart" ]; then
+        RESTART=1
+        shift
+        continue
+    fi
+
+    #
+    # all other parameters requires at least 1 argument
+    #
+
+    if [ "$1" = "-setip" -o "$1" = "--setip" ]; then
+        HOST="${2}"
+        if [ -z "$HOST" ]; then
+            echo "HOST IP=$IP"
         fi
 
-	if [ "$1" = "--restart" -o "$1" = "-restart" ]; then
-                RESTART=1
-                shift
-                continue
+        if echo $HOST|grep -q ":"; then
+            HOST=$(echo ${2}|cut -d: -f1)
         fi
+        shift; shift
+        continue
+    fi
+
+    if [ "$1" = "--salt" -o "$1" = "-salt" -o "$1" = "--setsalt" -o "$1" = "--secret" -o "$1" = "-secret"  -o "$1" = "--setsecret" ]; then
+        SECRET="${2}"
+        if [ -z "$SECRET" ]; then
+            BBB_WEB_URL=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
+            SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | grep securitySalt | cut -d= -f2);
+            echo
+            echo "    URL: $BBB_WEB_URL/bigbluebutton/"
+            echo "    Secret: $SECRET"
+            echo
+            echo "    Link to the API-Mate:"
+            echo "    http://mconf.github.io/api-mate/#server=$BBB_WEB_URL/bigbluebutton/&sharedSecret=$SECRET"
+            echo
+            exit 0
+        fi
+        shift; shift
+        continue
+    fi
 
-	#
-	# all other parameters requires at least 1 argument
-	#
-	
-	if [ "$1" = "-setip" -o "$1" = "--setip" ]; then
-		HOST="${2}"
-		if [ -z "$HOST" ]; then
-			echo "HOST IP=$IP"
-		fi
-
-		if echo $HOST|grep -q ":"; then
-			HOST=`echo ${2}|cut -d: -f1`
-		fi
-		shift; shift
-		continue
-	fi		
-	
-	if [ "$1" = "--salt" -o "$1" = "-salt" -o "$1" = "--setsalt" -o "$1" = "--secret" -o "$1" = "-secret"  -o "$1" = "--setsecret" ]; then
-		SECRET="${2}"
-		if [ -z "$SECRET" ]; then
-			BBB_WEB_URL=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
-			SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | grep securitySalt | cut -d= -f2);
-			echo
-			echo "       URL: $BBB_WEB_URL/bigbluebutton/"
-			echo "    Secret: $SECRET"
-			echo
-			echo "      Link to the API-Mate:"
-			echo "      http://mconf.github.io/api-mate/#server=$BBB_WEB_URL/bigbluebutton/&sharedSecret=$SECRET"
-			echo
-			exit 0
-		fi
-		shift; shift
-		continue
-	fi
-
-	if [ "$1" = "--lti" -o "$1" = "-lti" ]; then
-		if [ -z "$SECRET" ]; then
-			if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
-				LTI_URL='http://'$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiEndPoint/{s/^.*=//;p}')'/lti/tool'
-				CUSTOMER=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiConsumer/{s/^.*=//;s/:.*//p}')
-				SECRET=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiConsumer/{s/^[^:]*://;p}')
-				echo
-				echo "       URL: $LTI_URL"
-				echo "  Customer: $CUSTOMER"
-				echo "    Secret: $SECRET"
-				echo
-				ICON_URL=$( echo $LTI_URL | sed 's/tool/images\/icon.ico/')
-				echo "  Icon URL: $ICON_URL"
-				echo
-				echo
-				exit 0
-			fi
-		fi
-		shift; shift
-		continue
-	fi
-
-	usage 
-	exit 1
+    if [ "$1" = "--lti" -o "$1" = "-lti" ]; then
+        if [ -z "$SECRET" ]; then
+            if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
+                LTI_URL='http://'$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiEndPoint/{s/^.*=//;p}')'/lti/tool'
+                CUSTOMER=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiConsumer/{s/^.*=//;s/:.*//p}')
+                SECRET=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiConsumer/{s/^[^:]*://;p}')
+                echo
+                echo "       URL: $LTI_URL"
+                echo "  Customer: $CUSTOMER"
+                echo "    Secret: $SECRET"
+                echo
+                ICON_URL=$( echo $LTI_URL | sed 's/tool/images\/icon.ico/')
+                echo "  Icon URL: $ICON_URL"
+                echo
+                echo
+                exit 0
+            fi
+        fi
+        shift; shift
+        continue
+    fi
+
+    usage
+    exit 1
 done
 
 
 #
-# Version 
+# Version
 #
-if [ $VERSION ]; then
-	echo 
-	dpkg -l | grep bbb
-	exit 0
+if [[ $VERSION ]]; then
+    echo
+    dpkg -l | grep bbb
+    exit 0
 fi
 
 
@@ -745,249 +596,198 @@ fi
 # Set Shared Secret
 #
 
-if [ $SECRET ]; then
-	need_root
-	change_var_salt ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties securitySalt $SECRET
+if [[ $SECRET ]]; then
+    need_root
+    change_var_salt ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties securitySalt $SECRET
 
-        if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee ]; then
-                sed -i "s|\(^[ \t]*config.bbb.sharedSecret[ =]*\).*|\1\"$SECRET\"|g" /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee
-        fi
-        if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.js ]; then
-                sed -i "s|\(^[ \t]*config.bbb.sharedSecret[ =]*\).*|\1\"$SECRET\"|g" /usr/local/bigbluebutton/bbb-webhooks/config_local.js
+    if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee ]; then
+        sed -i "s|\(^[ \t]*config.bbb.sharedSecret[ =]*\).*|\1\"$SECRET\"|g" /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee
+    fi
+    if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.js ]; then
+        sed -i "s|\(^[ \t]*config.bbb.sharedSecret[ =]*\).*|\1\"$SECRET\"|g" /usr/local/bigbluebutton/bbb-webhooks/config_local.js
+    fi
+
+    if [ -f /usr/local/bigbluebutton/bbb-webhooks/extra/post_catcher.js ]; then
+        sed -i "s|\(^[ \t]*var shared_secret[ =]*\)[^;]*|\1\"$SECRET\"|g" /usr/local/bigbluebutton/bbb-webhooks/extra/post_catcher.js
+    fi
+
+    if [ -f /usr/share/bbb-apps-akka/conf/application.conf ]; then
+        sed -i "s/sharedSecret[ ]*=[ ]*\"[^\"]*\"/sharedSecret=\"$SECRET\"/g" /usr/share/bbb-apps-akka/conf/application.conf
+    fi
+
+    echo "Changed BigBlueButton's shared secret to $SECRET"
+    echo
+    echo "You must restart BigBlueButton for the changes to take effect"
+    echo "  $SUDO bbb-conf --restart"
+    echo
+fi
+
+check_configuration() {
+    #
+    # Check that freeswtich ESL matches the value in bigbluebutton.properties
+    #
+    if [ -f $FREESWITCH_EVENT_SOCKET ]; then
+        FREESWITCH_ESL_IP=$(cat $FREESWITCH_EVENT_SOCKET | grep 'name="listen-ip"' | cut -d\" -f4  | awk '{print $1}')
+        check_no_value event_socket $FREESWITCH_EVENT_SOCKET $FREESWITCH_ESL_IP
+
+        ESL_HOST=$(cat /usr/share/red5/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties | grep -v '#' | grep esl.host | sed 's/freeswitch.esl.host=//g')
+        check_no_value esl.host /usr/share/red5/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties $ESL_HOST
+
+        if [ "$FREESWITCH_ESL_IP" != "::" ]; then
+            if [ "$FREESWITCH_ESL_IP" != "$ESL_HOST" ]; then
+               echo
+               echo "# The values for listen-ip in   "
+               echo "#     $FREESWITCH_EVENT_SOCKET"
+               echo "# do not match the settings for esl.host in"
+               echo "#     /usr/share/red5/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties"
+               echo
+            fi
         fi
+    fi
+
+    #
+    # Check if BigBlueButton is defined in Nginx
+    #
+    if [ ! -L /etc/nginx/sites-enabled/bigbluebutton ]; then
+        echo "# Nginx: BigBlueButton appears to be disabled"
+        echo "         - no symbolic link in /etc/nginx/sites-enabled/bigbluebutton to /etc/nginx/sites-available/bigbluebutton "
+    fi
 
-	if [ -f /usr/local/bigbluebutton/bbb-webhooks/extra/post_catcher.js ]; then
-		sed -i "s|\(^[ \t]*var shared_secret[ =]*\)[^;]*|\1\"$SECRET\"|g" /usr/local/bigbluebutton/bbb-webhooks/extra/post_catcher.js
-	fi
+    #
+    # Look for properties with no values set
+    #
+    CONFIG_FILES="$RED5_DIR/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties \
+    ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties \
+    $RED5_DIR/webapps/sip/WEB-INF/bigbluebutton-sip.properties"
 
-        if [ -f /usr/share/bbb-apps-akka/conf/application.conf ]; then
-                sed -i "s/sharedSecret[ ]*=[ ]*\"[^\"]*\"/sharedSecret=\"$SECRET\"/g" \
-                        /usr/share/bbb-apps-akka/conf/application.conf
+    for file in $CONFIG_FILES ; do
+        if [ ! -f $file ]; then
+            echo "# Error: File not found: $file"
+        else
+            if cat $file | grep -v redis.pass | grep -q "^[^=]*=[ ]*$"; then
+                echo "# The following properties in $file have no value:"
+                echo "#     $(grep '^[^=#]*=[ ]*$' $file | sed 's/=//g')"
+            fi
         fi
+    done
+
+    #
+    # Check that the supporting applications are installed
+    #
+    VARFolder=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep swfToolsDir | cut -d= -f2)
+    files="pdf2swf jpeg2swf png2swf"
+    for file in $files; do
+    if [ ! -x $VARFolder/$file ]; then
+        echo "# $file is not installed in $VARFolder"
+    fi
+    done
 
-	echo "Changed BigBlueButton's shared secret to $SECRET"
-	echo 
-	echo "You must restart BigBlueButton for the changes to take effect"
-	echo "  $SUDO bbb-conf --restart"
-	echo
-fi
+    VARFolder=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep imageMagickDir | cut -d= -f2)
+    if [ ! -x $VARFolder/convert ]; then
+        echo "# ImageMagick's convert is not installed in $VARFolder"
+    fi
 
-#
-# Setup samba
-#
+    #
+    # Check if the IP resolves to a different host
+    #
+    check_no_value server_name /etc/nginx/sites-available/bigbluebutton $NGINX_IP
+
+    if which host > /dev/null 2>&1; then
+        HOSTS=$(which host)
+        if [ $HOSTS ]; then
+            HOSTS=$($HOSTS $NGINX_IP | awk '{ print $4 }' | head -n 1)
+        fi
+    fi
+
+    if [ "$IP" != "$NGINX_IP" ]; then
+        if [ "$IP" != "$HOSTS" ]; then
+            echo "# IP does not match:"
+            echo "#                           IP from ifconfig: $IP"
+            echo "#   /etc/nginx/sites-available/bigbluebutton: $NGINX_IP"
+        fi
+    fi
 
-if [ $SAMBA ]; then
-	check_root
 
+    if [ -f ${SERVLET_DIR}/demo/bbb_api_conf.jsp ]; then
         #
-        # Instal Samba
+        # Make sure the shared secret for the API matches the server
         #
-        if ! dpkg-query -s samba > /dev/null 2>&1; then
-          $SUDO apt-get install -y --force-yes samba ant
+        SECRET_PROPERTIES=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
+        SECRET_DEMO=$(cat ${SERVLET_DIR}/demo/bbb_api_conf.jsp | grep -v '^//' | tr -d '\r' | sed -n '/salt[ ]*=/{s/.*=[ ]*"//;s/".*//g;p}')
+
+        if [ "$SECRET_PROPERTIES" != "$SECRET_DEMO" ]; then
+            echo "# Warning: API Shared Secret mismatch: "
+            echo "#  ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties  = $SECRET_PROPERTIES"
+            echo "#  ${SERVLET_DIR}/demo/bbb_api_conf.jsp                                   = $SECRET_DEMO"
+            echo
         fi
 
-        #
-        # Add a share to samba
-        #
-        if ! grep -q $USER /etc/samba/smb.conf; then
-
-                echo ";
-; BigBlueButton: Share the development directory
-[$USER]
-   comment = BigBlueButton Development share
-   path = /home/$USER
-   browseable = yes
-   read only = no
-   create mask = 0755
-   directory mask = 0775
-   guest ok = yes
-   force user = $USER
-" | $SUDO tee -a /etc/samba/smb.conf > /dev/null 2>&1
-
-                $SUDO /etc/init.d/smbd restart
-
-        echo "
-You can now access your development folder through:
-
-        \\\\${IP}\\$USER
-
-If you are running a development environment on Windows (such as using Eclipse or FlexBuilder),
-you can map the above path to a drive letter.
-"
-        else
-                echo "Already detected a definition for $USER in /etc/samba/smb.conf"
-                echo "No changes were made to /etc/samba/smb.conf"
+        API_IP=$(cat ${TOMCAT_DIR}/demo/bbb_api_conf.jsp | grep -v '^//' | sed -n '/String BigBlueButtonURL/{s/.*http[s]*:\/\///;s/\/.*//;p}' | tr -d '\015')
+        if [ "$IP" != "$API_IP" ]; then
+            echo "# Warning: API URL IPs do not match host:"
+            echo "#"
+            echo "#                                IP from ifconfig: $IP"
+            echo "#  ${TOMCAT_DIR}/demo/bbb_api_conf.jsp: $API_IP"
+            echo
         fi
-fi
+    fi
 
+    BBB_SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
 
-check_configuration() {
-	#
-	# Check that freeswtich ESL matches the value in bigbluebutton.properties
-	#
-	if [ -f $FREESWITCH_EVENT_SOCKET ]; then 
-		FREESWITCH_ESL_IP=$(cat $FREESWITCH_EVENT_SOCKET | grep 'name="listen-ip"' | cut -d\" -f4  | awk '{print $1}')
-		check_no_value event_socket $FREESWITCH_EVENT_SOCKET $FREESWITCH_ESL_IP
-
-		ESL_HOST=$(cat /usr/share/red5/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties | grep -v '#' | grep esl.host | sed 's/freeswitch.esl.host=//g')
-		check_no_value esl.host /usr/share/red5/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties $ESL_HOST
-
-                if [ "$FREESWITCH_ESL_IP" != "::" ]; then
-                    if [ "$FREESWITCH_ESL_IP" != "$ESL_HOST" ]; then
-			echo 
-			echo "# The values for listen-ip in   "
-			echo "#     $FREESWITCH_EVENT_SOCKET"
-			echo "# do not match the settings for esl.host in"
-			echo "#     /usr/share/red5/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties"
-			echo 
-                    fi
-		fi
-	fi
-
-
-	#
-	# Check if BigBlueButton is defined in Nginx
-	#
-	if [ ! -L /etc/nginx/sites-enabled/bigbluebutton ]; then
-        	echo "# Nginx: BigBlueButton appears to be disabled"
-        	echo "         - no symbolic link in /etc/nginx/sites-enabled/bigbluebutton to /etc/nginx/sites-available/bigbluebutton "
-	fi
-	
-	#
-	# Look for properties with no values set
-	#
-	CONFIG_FILES="$RED5_DIR/webapps/bigbluebutton/WEB-INF/bigbluebutton.properties \
-	${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties \
-	$RED5_DIR/webapps/sip/WEB-INF/bigbluebutton-sip.properties"
-
-	for file in $CONFIG_FILES ; do
-	 	if [ ! -f $file ]; then	
-		 	echo "# Error: File not found: $file"
-		else
-                        if cat $file | grep -v redis.pass | grep -q "^[^=]*=[ ]*$"; then
-        			echo "# The following properties in $file have no value:"
-        			echo "#     $(grep '^[^=#]*=[ ]*$' $file | sed 's/=//g')"
-			fi
-		fi
-	done
-
-	#
-	# Check that the supporting applications are installed
-	#
-	VARFolder=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep swfToolsDir | cut -d= -f2)
-	files="pdf2swf jpeg2swf png2swf"
-	for file in $package; do
-		if [ ! -x $VARFolder/$file ]; then
-			echo "# $file is not installed in $VARFolder"
-		fi
-	done
-
-	VARFolder=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep imageMagickDir | cut -d= -f2)
-	if [ ! -x $VARFolder/convert ]; then
-			echo "# ImageMagick's convert is not installed in $VARFolder"
-	fi
-
-	#
-	# Check if the IP resolves to a different host
-	#
- 	check_no_value server_name /etc/nginx/sites-available/bigbluebutton $NGINX_IP
- 
-	if which host > /dev/null 2>&1; then	
-		HOSTS=$(which host)
-		if [ $HOSTS ]; then
-			HOSTS=`$HOSTS $NGINX_IP | awk '{ print $4 }' | head -n 1`
-		fi
-	fi
-
-	if [ "$IP" != "$NGINX_IP" ]; then
-		if [ "$IP" != "$HOSTS" ]; then
-			echo "# IP does not match:"
-			echo "#                           IP from ifconfig: $IP"
-			echo "#   /etc/nginx/sites-available/bigbluebutton: $NGINX_IP"
-		fi
-	fi
-
-
-	if [ -f ${SERVLET_DIR}/demo/bbb_api_conf.jsp ]; then	
-		#
-		# Make sure the shared secret for the API matches the server
-		#
-		SECRET_PROPERTIES=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
-		SECRET_DEMO=$(cat ${SERVLET_DIR}/demo/bbb_api_conf.jsp | grep -v '^//' | tr -d '\r' | sed -n '/salt[ ]*=/{s/.*=[ ]*"//;s/".*//g;p}')
-
-		if [ "$SECRET_PROPERTIES" != "$SECRET_DEMO" ]; then
-			echo "# Warning: API Shared Secret mismatch: "
-			echo "#  ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties  = $SECRET_PROPERTIES"
-			echo "#  ${SERVLET_DIR}/demo/bbb_api_conf.jsp                                   = $SECRET_DEMO"
-			echo 
-		fi
-
-		API_IP=$(cat ${TOMCAT_DIR}/demo/bbb_api_conf.jsp | grep -v '^//' | sed -n '/String BigBlueButtonURL/{s/.*http[s]*:\/\///;s/\/.*//;p}' | tr -d '\015')
-		if [ "$IP" != "$API_IP" ]; then
-			echo "# Warning: API URL IPs do not match host:"
-			echo "#"
-			echo "#                                IP from ifconfig: $IP"
-			echo "#  ${TOMCAT_DIR}/demo/bbb_api_conf.jsp: $API_IP"
-			echo
-		fi
-	fi
-
-	BBB_SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
-
-        if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
-                if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.js ]; then
-                  WEBHOOKS_SECRET=$(cat /usr/local/bigbluebutton/bbb-webhooks/config_local.js | grep '^[ \t]*config.bbb.sharedSecret[ =]*' | cut -d '"' -f2)
-                  WEBHOOKS_CONF=/usr/local/bigbluebutton/bbb-webhooks/config_local.js
-                fi
-                if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee ]; then
-                  WEBHOOKS_SECRET=$(cat /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee | grep '^[ \t]*config.bbb.sharedSecret[ =]*' | cut -d '"' -f2)
-                  WEBHOOKS_CONF=/usr/local/bigbluebutton/bbb-webhooks/config_local.coffee
-                fi
+    if [ -f /usr/lib/systemd/system/bbb-webhooks.service ]; then
+        if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.js ]; then
+            WEBHOOKS_SECRET=$(cat /usr/local/bigbluebutton/bbb-webhooks/config_local.js | grep '^[ \t]*config.bbb.sharedSecret[ =]*' | cut -d '"' -f2)
+            WEBHOOKS_CONF=/usr/local/bigbluebutton/bbb-webhooks/config_local.js
+        fi
+        if [ -f /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee ]; then
+            WEBHOOKS_SECRET=$(cat /usr/local/bigbluebutton/bbb-webhooks/config_local.coffee | grep '^[ \t]*config.bbb.sharedSecret[ =]*' | cut -d '"' -f2)
+            WEBHOOKS_CONF=/usr/local/bigbluebutton/bbb-webhooks/config_local.coffee
+        fi
 
-                if [ "$BBB_SECRET" != "$WEBHOOKS_SECRET" ]; then
-                        echo "# Warning: Webhooks API Shared Secret mismatch: "
-                        echo "#  ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties = $BBB_SECRET"
-                        echo "#  $WEBHOOKS_CONF                       = $WEBHOOKS_SECRET"
-                        echo
-                fi
+        if [ "$BBB_SECRET" != "$WEBHOOKS_SECRET" ]; then
+            echo "# Warning: Webhooks API Shared Secret mismatch: "
+            echo "#  ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties = $BBB_SECRET"
+            echo "#  $WEBHOOKS_CONF                       = $WEBHOOKS_SECRET"
+            echo
+        fi
 
-                WEBHOOKS_PROXY_PORT=$(cat /etc/bigbluebutton/nginx/webhooks.nginx | grep -v '#' | grep '^[ \t]*proxy_pass[ \t]*' | sed 's|.*http[s]\?://[^:]*:\([^;]*\);.*|\1|g')
-                WEBHOOKS_APP_PORT=$(cat $WEBHOOKS_CONF | grep config.server.port | sed "s/.*config.server.port[ =\"]*//g" | sed 's/[;\"]*//g')
+        WEBHOOKS_PROXY_PORT=$(cat /etc/bigbluebutton/nginx/webhooks.nginx | grep -v '#' | grep '^[ \t]*proxy_pass[ \t]*' | sed 's|.*http[s]\?://[^:]*:\([^;]*\);.*|\1|g')
+        WEBHOOKS_APP_PORT=$(cat $WEBHOOKS_CONF | grep config.server.port | sed "s/.*config.server.port[ =\"]*//g" | sed 's/[;\"]*//g')
 
-                if [ "$WEBHOOKS_PROXY_PORT" != "$WEBHOOKS_APP_PORT" ]; then
-                        echo "# Warning: Webhooks port mismatch: "
-                        echo "#  /etc/bigbluebutton/nginx/webhooks.nginx                   = $WEBHOOKS_PROXY_PORT"
-                        echo "#  $WEBHOOKS_CONF = $WEBHOOKS_APP_PORT"
-                        echo
-                fi
+        if [ "$WEBHOOKS_PROXY_PORT" != "$WEBHOOKS_APP_PORT" ]; then
+            echo "# Warning: Webhooks port mismatch: "
+            echo "#  /etc/bigbluebutton/nginx/webhooks.nginx                   = $WEBHOOKS_PROXY_PORT"
+            echo "#  $WEBHOOKS_CONF = $WEBHOOKS_APP_PORT"
+            echo
         fi
+    fi
 
 
-	if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
-                LTI_SECRET=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | tr -d '\r' | sed -n '/^bigbluebuttonSalt/{s/.*=//;p}')
-                BBB_SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
-
-		if [ "$LTI_SECRET" != "$BBB_SECRET" ]; then
-			echo "# Warning: LTI shared secret mismatch:"
-			echo "#  ${LTI_DIR}/WEB-INF/classes/lti-config.properties                      = $LTI_SECRET"
-			echo "#  ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties  = $BBB_SECRET"
-			echo 
-		fi
-	fi
-
-        PROTOCOL=$(cat /etc/bigbluebutton/nginx/sip.nginx | grep -v \# | sed -n '/proxy_pass/{s/.*proxy_pass [ ]*//;s/:.*//;p}' | head -n 1)
-        if [[ $PROTOCOL == "https" ]]; then
-                if ! grep wss-binding $FREESWITCH_EXTERNAL > /dev/null; then
-			echo "# Warning: Websockets is using HTTPS in /etc/bigbluebutton/nginx/sip.nginx"
-			echo "# but no definition for wss-binding found in "
-			echo "#"
-			echo "#    $FREESWITCH_EXTERNAL"
-			echo 
-		fi
-
-	if [ -f $HTML5_CONFIG_OLD ]; then 
-          if grep \"enableListenOnly\".*true $HTML5_CONFIG_OLD > /dev/null; then
-            if ! grep -q ws-binding $FREESWITCH_EXTERNAL ;  then
+    if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
+        LTI_SECRET=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | tr -d '\r' | sed -n '/^bigbluebuttonSalt/{s/.*=//;p}')
+        BBB_SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | tr -d '\r' | sed -n '/securitySalt/{s/.*=//;p}')
+
+        if [ "$LTI_SECRET" != "$BBB_SECRET" ]; then
+            echo "# Warning: LTI shared secret mismatch:"
+            echo "#  ${LTI_DIR}/WEB-INF/classes/lti-config.properties                      = $LTI_SECRET"
+            echo "#  ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties  = $BBB_SECRET"
+            echo
+        fi
+    fi
+
+    SIP_PROTOCOL=$(cat /etc/bigbluebutton/nginx/sip.nginx | grep -v \# | sed -n '/proxy_pass/{s/.*proxy_pass [ ]*//;s/:.*//;p}' | head -n 1)
+    if [[ $SIP_PROTOCOL == "https" ]]; then
+        if ! grep wss-binding $FREESWITCH_EXTERNAL > /dev/null; then
+            echo "# Warning: Websockets is using HTTPS in /etc/bigbluebutton/nginx/sip.nginx"
+            echo "# but no definition for wss-binding found in "
+            echo "#"
+            echo "#    $FREESWITCH_EXTERNAL"
+            echo
+        fi
+
+        if [ -f $HTML5_CONFIG_OLD ]; then
+            if grep \"enableListenOnly\".*true $HTML5_CONFIG_OLD > /dev/null; then
+                if ! grep -q ws-binding $FREESWITCH_EXTERNAL ;  then
                 echo "# Warning: You have enabled listen-only audio via Kurento"
                 echo "# but FreeSWITCH is not listening on port 5066.  You should edit "
                 echo "#"
@@ -995,607 +795,629 @@ check_configuration() {
                 echo "#"
                 echo "# and add a line that enables ws-binding on port 5066."
                 echo
+                fi
             fi
-          fi
         fi
+    fi
 
-	fi
-
-	if [ $DISTRIB_ID != "centos" ]; then
-          libreoffice_version=`dpkg-query -W --showformat='${Version}\n' libreoffice | sed 's/.*://g' | sed 's/\.[^\.]*$//g'`
-		if [[ "$libreoffice_version" > 1.0 ]]; then
-		    if [[ "$libreoffice_version" < 4.4 ]]; then
-			echo "# Warning: Detected your running an older version of LibreOffice: $libreoffice_version"
-			echo "#"
-			echo "# Recommend updated to the latest version of LibreOffice 4.x (4.4 or later)"
-			echo
-		    fi
-		fi
-	fi
-
-        if [ "$(ls -ld /var/bigbluebutton/screenshare | cut -d' ' -f3)" != "red5" ]; then
-                echo "# Warning: Detected the directory"
-                echo "#    /var/bigbluebutton/screenshare"
-                echo "# is not owned by red5"
+    if [ $DISTRIB_ID != "centos" ]; then
+        libreoffice_version=$(dpkg-query -W --showformat='${Version}\n' libreoffice | sed 's/.*://g' | sed 's/\.[^\.]*$//g')
+        if [[ "$libreoffice_version" > 1.0 ]]; then
+            if [[ "$libreoffice_version" < 4.4 ]]; then
+                echo "# Warning: Detected your running an older version of LibreOffice: $libreoffice_version"
+                echo "#"
+                echo "# Recommend updated to the latest version of LibreOffice 4.x (4.4 or later)"
+                echo
+            fi
         fi
-		
-        if [ "$(ls -ld /usr/share/red5/webapps/video/streams | cut -d' ' -f3)" != "red5" ]; then
-                echo "# Warning: Detected the directory"
-                echo "#    /usr/share/red5/webapps/video/streams"
-                echo "# is not owned by red5"
+    fi
+
+    if [ "$(ls -ld /var/bigbluebutton/screenshare | cut -d' ' -f3)" != "red5" ]; then
+        echo "# Warning: Detected the directory"
+        echo "#    /var/bigbluebutton/screenshare"
+        echo "# is not owned by red5"
+    fi
+
+    if [ "$(ls -ld /usr/share/red5/webapps/video/streams | cut -d' ' -f3)" != "red5" ]; then
+        echo "# Warning: Detected the directory"
+        echo "#    /usr/share/red5/webapps/video/streams"
+        echo "# is not owned by red5"
+    fi
+
+    if [ "$(ls -ld /var/freeswitch/meetings | cut -d' ' -f3)" != "freeswitch" ]; then
+        echo "# Warning: Detected the directory"
+        echo "#    /var/freeswitch/meetings"
+        echo "# is not owned by freeswitch"
+    fi
+
+    if [ "$(ls -ld /var/bigbluebutton | cut -d' ' -f3)" != $BBB_USER ]; then
+        echo "# Warning: Detected the directory"
+        echo "#    /var/bigbluebutton"
+        echo "# is not owned by $BBB_USER"
+    fi
+
+    if [ $PROTOCOL == "https" ]; then
+        if ! grep jnlpUrl /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties | grep -q https; then
+            echo "# Warning: Detected the value for jnlpUrl is not configured for HTTPS"
+            echo "#    /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties"
+            echo "#"
         fi
-		
-        if [ "$(ls -ld /var/freeswitch/meetings | cut -d' ' -f3)" != "freeswitch" ]; then
-                echo "# Warning: Detected the directory"
-                echo "#    /var/freeswitch/meetings"
-                echo "# is not owned by freeswitch"
+    fi
+
+    GUEST_POLICY=$(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^defaultGuestPolicy/{s/.*=//;p}')
+    if [ "$GUEST_POLICY" == "ASK_MODERATOR" ]; then
+        echo
+        echo "# Warning: defaultGuestPolicy is set to ASK_MODERATOR in"
+        echo "#    $BBB_WEB_CONFIG"
+        echo "# This is not yet supported yet the HTML5 client."
+        echo "#"
+        echo "# To revert it to ALWAYS_ALLOW, see"
+        echo "#"
+        echo "#   $SUDO sed -i s/^defaultGuestPolicy=.*$/defaultGuestPolicy=ALWAYS_ALLOW/g $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties"
+        echo "#"
+        echo
+    fi
+
+    if [ -f $HTML5_CONFIG ]; then
+        SVG_IMAGES_REQUIRED=$(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^svgImagesRequired/{s/.*=//;p}')
+        if [ "$SVG_IMAGES_REQUIRED" != "true" ]; then
+            echo
+            echo "# Warning: You have the HTML5 client installed but in"
+            echo "#"
+            echo "#    $BBB_WEB_CONFIG"
+            echo "#"
+            echo "# the setting for svgImagesRequired is false. To fix, run the commnad"
+            echo "#"
+            echo "# sed -i 's/^svgImagesRequired=.*/svgImagesRequired=true/' $BBB_WEB_CONFIG "
+            echo "#"
         fi
+    fi
+}
+
+
+check_state() {
+    echo
+    print_header
+    check_configuration
 
-        if [ "$(ls -ld /var/bigbluebutton | cut -d' ' -f3)" != $BBB_USER ]; then
-                echo "# Warning: Detected the directory"
-                echo "#    /var/bigbluebutton"
-                echo "# is not owned by $BBB_USER"
+    #
+    # Check for potential problems in the BigBlueButton configuration
+    #
+
+    RUNNING_APPS=""
+    NOT_RUNNING_APPS=""
+
+    if ! ps aux | grep -v grep | grep 'org.red5.server.Bootstrap' > /dev/null; then
+        print_header
+        NOT_RUNNING_APPS="${NOT_RUNNING_APPS} red5"
+    else
+        RUNNING_APPS="${RUNNING_APPS} red5"
+    fi
+
+    if [[ -a $FREESWITCH_PID ]]; then
+        if ! ps aux | grep -v grep | grep '[/]opt/freeswitch/bin/freeswitch' > /dev/null; then
+            print_header
+            NOT_RUNNING_APPS="${NOT_RUNNING_APPS} freeswitch"
+        else
+            RUNNING_APPS="${RUNNING_APPS} freeswitch"
         fi
+    fi
 
-        if [ $PROTOCOL == "https" ]; then
-            if ! grep jnlpUrl /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties | grep -q https; then
-                echo "# Warning: Detected the value for jnlpUrl is not configured for HTTPS"
-                echo "#    /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties"
-                echo "#"
-            fi
+    if ! ps aux | grep -v grep | grep '[/]usr/sbin/nginx' > /dev/null; then
+        print_header
+        NOT_RUNNING_APPS="${NOT_RUNNING_APPS} Nginx"
+    else
+        RUNNING_APPS="${RUNNING_APPS} Nginx"
+    fi
+
+    if ! netstat -ant | grep '8090' > /dev/null; then
+        print_header
+        NOT_RUNNING_APPS="${NOT_RUNNING_APPS} ${TOMCAT_SERVICE} or grails"
+    else
+        if ps aux |  ps -aef | grep -v grep | grep grails | grep run-app > /dev/null; then
+        print_header
+        RUNNING_APPS="${RUNNING_APPS} Grails"
+        echo "#   ${TOMCAT_SERVICE}:      noticed you are running grails run-app instead of ${TOMCAT_SERVICE}"
+        else
+            RUNNING_APPS="${RUNNING_APPS} ${TOMCAT_SERVICE}"
         fi
+    fi
 
-	GUEST_POLICY=$(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^defaultGuestPolicy/{s/.*=//;p}')
-	if [ "$GUEST_POLICY" == "ASK_MODERATOR" ]; then
-		echo
-		echo "# Warning: defaultGuestPolicy is set to ASK_MODERATOR in"
-		echo "#    $BBB_WEB_CONFIG"
-		echo "# This is not yet supported yet the HTML5 client."
-		echo "#"
-		echo "# To revert it to ALWAYS_ALLOW, see"
-		echo "#"
-		echo "#   $SUDO sed -i s/^defaultGuestPolicy=.*$/defaultGuestPolicy=ALWAYS_ALLOW/g $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties"
-		echo "#"
-		echo
-	fi
-	if [ -f $HTML5_CONFIG ]; then
-		SVG_IMAGES_REQUIRED=$(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^svgImagesRequired/{s/.*=//;p}')
-	    if [ "$SVG_IMAGES_REQUIRED" != "true" ]; then 
-		echo
-		echo "# Warning: You have the HTML5 client installed but in"
-		echo "#"
-		echo "#    $BBB_WEB_CONFIG"
-		echo "#"
-		echo "# the setting for svgImagesRequired is false. To fix, run the commnad"
-		echo "#"
-		echo "# sed -i 's/^svgImagesRequired=.*/svgImagesRequired=true/' $BBB_WEB_CONFIG "
-		echo "#"
-	    fi
-	fi
-}
+    if ! netstat -ant | grep '8100' > /dev/null; then
+        print_header
+        NOT_RUNNING_APPS="${NOT_RUNNING_APPS} LibreOffice"
+    else
+        RUNNING_APPS="${RUNNING_APPS} LibreOffice"
+    fi
 
+    if ! ps aux | grep -v grep | grep '[/]usr/[s]*bin/redis-server' > /dev/null; then
+        print_header
+        NOT_RUNNING_APPS="${NOT_RUNNING_APPS} redis-server"
+    else
+        RUNNING_APPS="${RUNNING_APPS} redis-server"
+    fi
 
-check_state() {
-	echo 
-	print_header
-	check_configuration
-
-	#
-	# Check for potential problems in the BigBlueButton configuration
-	#
-
-	RUNNING_APPS=""
-	NOT_RUNNING_APPS=""
-
-	if ! ps aux | grep -v grep | grep 'org.red5.server.Bootstrap' > /dev/null; then
-		print_header
-		NOT_RUNNING_APPS="${NOT_RUNNING_APPS} red5"
-	else
-		RUNNING_APPS="${RUNNING_APPS} red5"
-	fi	
-
-	if [ -a $FREESWITCH_PID ]; then
-		if ! ps aux | grep -v grep | grep '[/]opt/freeswitch/bin/freeswitch' > /dev/null; then
-			print_header
-			NOT_RUNNING_APPS="${NOT_RUNNING_APPS} freeswitch"
-		else
-			RUNNING_APPS="${RUNNING_APPS} freeswitch"
-		fi
-	fi
-
-	if ! ps aux | grep -v grep | grep '[/]usr/sbin/nginx' > /dev/null; then
-		print_header
-		NOT_RUNNING_APPS="${NOT_RUNNING_APPS} Nginx"
-	else
-		RUNNING_APPS="${RUNNING_APPS} Nginx"
-	fi	
-
-	if ! netstat -ant | grep '8090' > /dev/null; then
-		print_header
-		NOT_RUNNING_APPS="${NOT_RUNNING_APPS} ${TOMCAT_SERVICE} or grails"
-	else 
-		if ps aux |  ps -aef | grep -v grep | grep grails | grep run-app > /dev/null; then
-			print_header
-			RUNNING_APPS="${RUNNING_APPS} Grails"
-        		echo "#   ${TOMCAT_SERVICE}: 	noticed you are running grails run-app instead of ${TOMCAT_SERVICE}"
-		else
-			RUNNING_APPS="${RUNNING_APPS} ${TOMCAT_SERVICE}"
-		fi
-	fi
-
-	if ! netstat -ant | grep '8100' > /dev/null; then
-                print_header
-		NOT_RUNNING_APPS="${NOT_RUNNING_APPS} LibreOffice"
-	else
-		RUNNING_APPS="${RUNNING_APPS} LibreOffice"
-        fi  
-
-        if ! ps aux | grep -v grep | grep '[/]usr/[s]*bin/redis-server' > /dev/null; then
-                print_header
-                NOT_RUNNING_APPS="${NOT_RUNNING_APPS} redis-server"
+    if [ "$NOT_RUNNING_APPS" != "" ]; then
+        echo "# Not running: ${NOT_RUNNING_APPS}"
+    fi
+
+
+    #
+    # Check if running development environment
+    #
+    if ! grep /var/www/bigbluebutton /etc/bigbluebutton/nginx/client.nginx > /dev/null; then
+        NEW_LOCATION=$(cat  /etc/bigbluebutton/nginx/client.nginx  | grep -v '#' | sed -n '/root/{s/[ \t]*root[ \t]*//;s/;//;p}' | head -n 1)
+        echo "# Warning: nginx is not serving the client from /var/www/bigbluebutton/."
+        echo "# Instead, it's being served from"
+        echo "#"
+        echo "#    $NEW_LOCATION"
+        echo "#"
+        echo "# (This is OK if you have setup a development environment.) "
+        echo
+
+        if [ ! -d $NEW_LOCATION ]; then
+            echo "# Warning: The directory"
+            echo "#"
+            echo "#    $NEW_LOCATION"
+            echo "#"
+            echo "# does not exist.  The BigBlueButton client will not load."
+            echo
+        fi
+    fi
+
+    #
+    # Check if running development environment
+    #
+    if ! grep 8090 /etc/bigbluebutton/nginx/web.nginx > /dev/null; then
+        echo "# Warning: nginx is not serving BigBlueButton's web application"
+        echo "# from port 8090"
+        echo "#"
+        echo "# (This is OK if you have setup a development environment.) "
+        echo
+    fi
+
+
+    #
+    # Check red5 applications
+    #
+    AVAIL_RED5_APPS=""
+    UNAVAIL_RED5_APPS=""
+    DIRECTORIES="bigbluebutton sip video screenshare video-broadcast"
+    for dir in $DIRECTORIES ; do
+        if [ ! -d $RED5_DIR/webapps/$dir ]; then
+            UNAVAIL_RED5_APPS="${UNAVAIL_RED5_APPS} $dir"
         else
-                RUNNING_APPS="${RUNNING_APPS} redis-server"
+            AVAIL_RED5_APPS="${AVAIL_RED5_APPS} $dir"
         fi
+    done
+
+    if [ "$UNAVAIL_RED5_APPS" != "" ]; then
+        echo "# Unavailable red5 apps ($RED5_DIR/webapps/): ${UNAVAIL_RED5_APPS}"
+    fi
+
+    #
+    # Checking red5 apps log
+    #
 
-	if [ "$NOT_RUNNING_APPS" != "" ]; then
-		echo "# Not running: ${NOT_RUNNING_APPS}"
-	fi
-
-
-	#
-	# Check if running development environment
-	#
-	if ! grep /var/www/bigbluebutton /etc/bigbluebutton/nginx/client.nginx > /dev/null; then
-		NEW_LOCATION=$(cat  /etc/bigbluebutton/nginx/client.nginx  | grep -v '#' | sed -n '/root/{s/[ \t]*root[ \t]*//;s/;//;p}' | head -n 1)
-		echo "# Warning: nginx is not serving the client from /var/www/bigbluebutton/."
-		echo "# Instead, it's being served from"
-		echo "#"
-		echo "#    $NEW_LOCATION"
-		echo "#"
-		echo "# (This is OK if you have setup a development environment.) "
-		echo
-
-		if [ ! -d $NEW_LOCATION ]; then
-			echo "# Warning: The directory"
-			echo "#"
-			echo "#    $NEW_LOCATION"
-			echo "#"
-			echo "# does not exist.  The BigBlueButton client will not load."
-			echo
-		fi
-	fi
-
-	#
-	# Check if running development environment
-	#
-	if ! grep 8090 /etc/bigbluebutton/nginx/web.nginx > /dev/null; then
-		echo "# Warning: nginx is not serving BigBlueButton's web application"
-		echo "# from port 8090"
-		echo "#"
-		echo "# (This is OK if you have setup a development environment.) "
-		echo
-	fi
-
-
-	#
-	# Check red5 applications
-	#
-	AVAIL_RED5_APPS=""
-	UNAVAIL_RED5_APPS=""
-	DIRECTORIES="bigbluebutton sip video screenshare"
-	for dir in $DIRECTORIES ; do
-		if [ ! -d $RED5_DIR/webapps/$dir ]; then
-			UNAVAIL_RED5_APPS="${UNAVAIL_RED5_APPS} $dir"
-		else
-			AVAIL_RED5_APPS="${AVAIL_RED5_APPS} $dir"
-		fi
-	done
-
-	if [ "$UNAVAIL_RED5_APPS" != "" ]; then
-		echo "# Unavailable red5 apps ($RED5_DIR/webapps/): ${UNAVAIL_RED5_APPS}"
-	fi
-
-
-	#
-	# Checking red5 apps log
-	#
-
-        # Give the files a chance to be created (in case we got started with a clean)
-        COUNT=0
-        while [ $COUNT -lt 20 ]; do
-          let COUNT=COUNT+1
-          if [ -f $RED5_DIR/log/sip.log ] && [ -f $RED5_DIR/log/bigbluebutton.log ] && [ -f $RED5_DIR/log/red5.log ] && [ -f $RED5_DIR/log/video.log ] && [ -f $RED5_DIR/log/screenshare-slf.log ]; then
+    # Give the files a chance to be created (in case we got started with a clean)
+    COUNT=0
+    while [ $COUNT -lt 20 ]; do
+        let COUNT=COUNT+1
+        if [ -f $RED5_DIR/log/sip.log ] && [ -f $RED5_DIR/log/bigbluebutton.log ] && [ -f $RED5_DIR/log/red5.log ] && [ -f $RED5_DIR/log/video.log ] && [ -f $RED5_DIR/log/screenshare-slf.log ]; then
             let COUNT=20
-          else
+        else
             echo -n "."
             sleep 1
-          fi
-        done
+        fi
+    done
+
+    RED5_LOG_FILES="bigbluebutton red5 sip video screenshare-slf"
+    AVAIL_RED5_LOG=""
+    UNAVAIL_RED5_LOG=""
+    for file in $RED5_LOG_FILES ; do
+        if [ ! -f $RED5_DIR/log/$file.log ]; then
+            UNAVAIL_RED5_LOG="${UNAVAIL_RED5_LOG} $file.log"
+        else
+            AVAIL_RED5_LOG="${AVAIL_RED5_LOG} $file.log"
+        fi
+    done
 
-	RED5_LOG_FILES="bigbluebutton red5 sip video screenshare-slf"
-	AVAIL_RED5_LOG=""
-	UNAVAIL_RED5_LOG=""
-	for file in $RED5_LOG_FILES ; do
-		if [ ! -f $RED5_DIR/log/$file.log ]; then
-			UNAVAIL_RED5_LOG="${UNAVAIL_RED5_LOG} $file.log"
-		else
-			AVAIL_RED5_LOG="${AVAIL_RED5_LOG} $file.log"
-		fi
-	done
-
-	if [ "$UNAVAIL_RED5_LOG" != "" ]; then
-		echo "# Error: Red5 log files not found"
-		echo
-		echo "# Unavailable red5 logs ($RED5_DIR/log): $UNAVAIL_RED5_LOG"
-		echo
-	fi
-
-	#
-	# Check FreeSWITCH
-	#
-
-	if grep -q "Thread ended for mod_event_socket" /opt/freeswitch/var/log/freeswitch/freeswitch.log; then
-		echo
-		echo "# Error: Found text in freeswitch.log:"
-		echo "#"
-		echo "#    Thread ended for mod_event_socket"
-		echo "#"
-		echo "# FreeSWITCH may not be responding to requests on port 8021 (event socket layer)"
-		echo "# and users may have errors joining audio."
-		echo "#"
-	fi
-
-	#
-	# Check FreeSWITCH
-	#
-
-	if ! echo "/quit" | /opt/freeswitch/bin/fs_cli - > /dev/null 2>&1; then
-		echo
-                echo "#"
-                echo "# Error: Unable to connect to the FreeSWITCH Event Socket Layer on port 8021"
-                echo "#"
-	fi
-
-
-	#
-	# Check for required external commands
-	#
-	COMMANDS="ruby gem pdftocairo pdf2swf"
-	for cmd in $COMMANDS ; do
-		if ! which $cmd > /dev/null 2>&1; then
-			echo "#    $cmd command not found"
-		fi
-	done
-
-	#
-	# Check if ffmpeg is installed, and whether it is a supported version
-	#
-	FFMPEG_VERSION=$(ffmpeg -version 2>/dev/null | grep ffmpeg | cut -d ' ' -f3 | sed 's/--.*//g' | tr -d '\n')
-	case "$FFMPEG_VERSION" in
+    if [ "$UNAVAIL_RED5_LOG" != "" ]; then
+        echo "# Error: Red5 log files not found"
+        echo
+        echo "# Unavailable red5 logs ($RED5_DIR/log): $UNAVAIL_RED5_LOG"
+        echo
+    fi
+
+    #
+    # Check FreeSWITCH
+    #
+    if grep -q "Thread ended for mod_event_socket" /opt/freeswitch/var/log/freeswitch/freeswitch.log; then
+        echo
+        echo "# Error: Found text in freeswitch.log:"
+        echo "#"
+        echo "#    Thread ended for mod_event_socket"
+        echo "#"
+        echo "# FreeSWITCH may not be responding to requests on port 8021 (event socket layer)"
+        echo "# and users may have errors joining audio."
+        echo "#"
+    fi
+
+    #
+    # Check FreeSWITCH
+    #
+
+    if ! echo "/quit" | /opt/freeswitch/bin/fs_cli - > /dev/null 2>&1; then
+        echo
+        echo "#"
+        echo "# Error: Unable to connect to the FreeSWITCH Event Socket Layer on port 8021"
+        echo "#"
+    fi
+
+    #
+    # Check for required external commands
+    #
+    COMMANDS="ruby gem pdftocairo pdf2swf"
+    for cmd in $COMMANDS ; do
+        if ! which $cmd > /dev/null 2>&1; then
+            echo "#    $cmd command not found"
+        fi
+    done
+
+    #
+    # Check if ffmpeg is installed, and whether it is a supported version
+    #
+    FFMPEG_VERSION=$(ffmpeg -version 2>/dev/null | grep ffmpeg | cut -d ' ' -f3 | sed 's/--.*//g' | tr -d '\n')
+    case "$FFMPEG_VERSION" in
         4.*.*)
-                # This is the current supported version; OK.
-                ;;
+            # This is the current supported version; OK.
+            ;;
         '')
-                echo "# Warning: No ffmpeg version was found on the system"
-                echo "#          Recording processing will not function"
-                echo
-                ;;
+            echo "# Warning: No ffmpeg version was found on the system"
+            echo "#          Recording processing will not function"
+            echo
+            ;;
         *)
-                echo "# Warning: The installed ffmpeg version '${FFMPEG_VERSION}' is not recommended."
-                echo "# Recommend you update to the 4.0.x version of ffmpeg.  To upgrade, do the following"
-                echo "#"
-                echo "#       $SUDO apt-get install software-properties-common"
-                echo "#       $SUDO add-apt-repository ppa:jonathonf/ffmpeg-4"
-                echo "#       $SUDO apt-get update"
-                echo "#       $SUDO apt-get dist-upgrade"
-                echo "#"
-                echo
-                ;;
-        esac
-
-
-	if [ -f /usr/share/red5/log/sip.log ]; then
-		#
-		# Checking if voice app registered successfully
-		#
-        	if cat /usr/share/red5/log/sip.log | grep -q "Failed to register with Sip Server"; then
-                	echo "# Warning: The voice application may not have registered with the sip server."
-                	echo "#   Try running: "
-                	echo "#"
-                	echo "#     $SUDO bbb-conf --clean"
-                	echo "#"
-        		echo 
-		fi
-
-		#	
-		# check if sip.log has warnings where the user is not registered.  
-		#
-
-		if cat /usr/share/red5/log/sip.log | tail -n1 | grep -q "Call request for default but not registered"; then
-			echo "# Error: The voice app is not registered with SIP server. Audio might not be working correctly."
-        		echo 
-		fi
-	else
-		echo "# Error: The following log file was not found"
-		echo "#   /usr/share/red5/log/sip.log "
-        	echo 
+            echo "# Warning: The installed ffmpeg version '${FFMPEG_VERSION}' is not recommended."
+            echo "# Recommend you update to the 4.0.x version of ffmpeg.  To upgrade, do the following"
+            echo "#"
+            echo "#       $SUDO apt-get install software-properties-common"
+            echo "#       $SUDO add-apt-repository ppa:jonathonf/ffmpeg-4"
+            echo "#       $SUDO apt-get update"
+            echo "#       $SUDO apt-get dist-upgrade"
+            echo "#"
+            echo
+            ;;
+    esac
+
+
+    if [[ -f /usr/share/red5/log/sip.log ]]; then
+        #
+        # Checking if voice app registered successfully
+        #
+        if cat /usr/share/red5/log/sip.log | grep -q "Failed to register with Sip Server"; then
+            echo "# Warning: The voice application may not have registered with the sip server."
+            echo "#   Try running: "
+            echo "#"
+            echo "#     $SUDO bbb-conf --clean"
+            echo "#"
+            echo
+        fi
+
+        #
+        # check if sip.log has warnings where the user is not registered.
+        #
+
+        if cat /usr/share/red5/log/sip.log | tail -n1 | grep -q "Call request for default but not registered"; then
+            echo "# Error: The voice app is not registered with SIP server. Audio might not be working correctly."
+            echo
+        fi
+    else
+        echo "# Error: The following log file was not found"
+        echo "#   /usr/share/red5/log/sip.log "
+        echo
+    fi
+
+    #
+    # Check that the servlet container has started properly and has created log files
+    #
+    if [ -z "$(ls -A $SERVLET_LOGS)" ]; then
+        echo "#                     empty directory: $SERVLET_LOGS contains no logs"
+    fi
+
+    #
+    # Check that bigbluebutton in red5 has started properly (less than 100 lines indicates that it
+    # didn't start)
+    #
+    if [ -f $RED5_DIR/log/bigbluebutton.log ]; then
+        BBB_RED5_LOG=$(stat -c%s $RED5_DIR/log/bigbluebutton.log)
+        if [ $BBB_RED5_LOG -lt 100 ]; then
+            echo "#       Log file too short (less than 100 lines): $RED5_DIR/log/bigbluebutton.log (red5)"
         fi
+    else
+        echo "#      No $RED5_DIR/log/bigbluebutton.log"
+    fi
+
+    #
+    # Check if the user is running their own bbb-web
+    #
+    if grep -q 8888 /etc/bigbluebutton/nginx/web.nginx; then
+        if ! netstat -ant | grep '8888' > /dev/null; then
+            echo "# Warning: There is no application server listening to port 8888."
+            echo
+        fi
+    fi
+
+
+    #
+    # Check if the local server can access the API.  This is a common problem when setting up BigBlueButton behind
+    # a firewall
+    #
+    BBB_WEB=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
+    check_no_value server_name /etc/nginx/sites-available/bigbluebutton $BBB_WEB
 
-	#
-	# Check that the servlet container has started properly and has created log files
-	#
-	if [ -z "$(ls -A $SERVLET_LOGS)" ]; then
-        	echo "#                     empty directory: $SERVLET_LOGS contains no logs"
-	fi
-
-	#
-	# Check that bigbluebutton in red5 has started properly (less than 100 lines indicates that it
-	# didn't start)
-	# 
-	if [ -f $RED5_DIR/log/bigbluebutton.log ]; then
-		BBB_RED5_LOG=$(stat -c%s $RED5_DIR/log/bigbluebutton.log)
-		if [ $BBB_RED5_LOG -lt 100 ]; then
-        		echo "#       Log file too short (less than 100 lines): $RED5_DIR/log/bigbluebutton.log (red5)"
-		fi
-	else
-		echo "#      No $RED5_DIR/log/bigbluebutton.log"
-	fi
-
-	#
-	# Check if the user is running their own bbb-web
-	#
-	if grep -q 8888 /etc/bigbluebutton/nginx/web.nginx; then
-		if ! netstat -ant | grep '8888' > /dev/null; then
-			echo "# Warning: There is no application server listening to port 8888."
-			echo 
-		fi
-	fi	
-
-
-	#
-	# Check if the local server can access the API.  This is a common problem when setting up BigBlueButton behind
-	# a firewall
-	#
-        BBB_WEB=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
- 	check_no_value server_name /etc/nginx/sites-available/bigbluebutton $BBB_WEB
-
-        COUNT=0
-        while [ $COUNT -lt 80 ]; do
-          let COUNT=COUNT+1
-	  timeout 1s wget $PROTOCOL://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS
-	  if [ $? -eq 0 ]; then
+    COUNT=0
+    while [ $COUNT -lt 80 ]; do
+        let COUNT=COUNT+1
+        timeout 1s wget $PROTOCOL://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS
+        if [ $? -eq 0 ]; then
             let COUNT=80
-          else
+        else
             echo -n "."
             sleep 1
-          fi
-        done
-	echo
+        fi
+    done
+    echo
+
+    if ! wget $PROTOCOL://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS; then
+        echo "# Error: Could not connect to the configured hostname/IP address"
+        echo "#"
+        echo "#    $PROTOCOL://$BBB_WEB/"
+        echo "#"
+        echo "# If your BigBlueButton server is behind a firewall, see FAQ."
+        echo
+    fi
 
-        if ! wget $PROTOCOL://$BBB_WEB/bigbluebutton/api -O - --quiet | grep -q SUCCESS; then
-                echo "# Error: Could not connect to the configured hostname/IP address"
-                echo "#"
-                echo "#    $PROTOCOL://$BBB_WEB/"
+    #
+    # Check that BigBlueButton can connect to port 1935
+    #
+    if [[ ! -z $NGINX_IP && $DISTRIB_ID != "centos" ]]; then
+        if ! nc -w 3 $NGINX_IP 1935 > /dev/null; then
+            echo "# Error: Unable to connect to port 1935 (RTMP) on $NGINX_IP"
+            echo
+        fi
+    fi
+
+
+    BBB_SIP_APP_IP=$(cat /usr/share/red5/webapps/sip/WEB-INF/bigbluebutton-sip.properties | grep -v '#' | sed -n '/^bbb.sip.app.ip=/{s/.*=//;s/;//;p}')
+    if [ $BBB_SIP_APP_IP != "127.0.0.1" ]; then
+        if [ "$BBB_SIP_APP_IP" != $IP ]; then
+            echo "# Warning: The setting of $BBB_SIP_APP_IP for bbb.sip.app.ip in"
+            echo "#"
+            echo "#    /usr/share/red5/webapps/sip/WEB-INF/bigbluebutton-sip.properties"
+            echo "#"
+            echo "# does not match the local IP address ($IP)."
+            echo "# (This is OK if you've manually changed the values to an external "
+            echo "# FreeSWITCH server.)"
+            echo
+        fi
+
+        SIP_IP=$(netstat -ant | grep 5060 | head -n1 | awk -F" " '{print $4}' | cut -d: -f1)
+        if [ -z $SIP_IP ]; then
+            echo "# Error: Could not detect FreeSWITCH listening on port 5060"
+            echo
+        else
+            if [ "$BBB_SIP_APP_IP" != $SIP_IP ]; then
+                echo "# Error: FreeSWITCH is listening on IP address $SIP_IP for SIP calls, but "
+                echo "# The IP address ($BBB_SIP_APP_IP) set bbb.sip.app.ip."
                 echo "#"
-                echo "# If your BigBlueButton server is behind a firewall, see FAQ."
                 echo
+            fi
         fi
+    fi
 
-	#
-	# Check that BigBlueButton can connect to port 1935
-	#
-	if [[ ! -z $NGINX_IP && $DISTRIB_ID != "centos" ]]; then
-		if ! nc -w 3 $NGINX_IP 1935 > /dev/null; then
-			echo "# Error: Unable to connect to port 1935 (RTMP) on $NGINX_IP"
-			echo 
-		fi
-	fi
-
-
-	BBB_SIP_APP_IP=$(cat /usr/share/red5/webapps/sip/WEB-INF/bigbluebutton-sip.properties | grep -v '#' | sed -n '/^bbb.sip.app.ip=/{s/.*=//;s/;//;p}')
-	if [ $BBB_SIP_APP_IP != "127.0.0.1" ]; then
-		if [ "$BBB_SIP_APP_IP" != $IP ]; then
-			echo "# Warning: The setting of $BBB_SIP_APP_IP for bbb.sip.app.ip in"
-			echo "#"
-			echo "#    /usr/share/red5/webapps/sip/WEB-INF/bigbluebutton-sip.properties"
-			echo "#"
-			echo "# does not match the local IP address ($IP)."
-			echo "# (This is OK if you've manually changed the values to an external "
-			echo "# FreeSWITCH server.)"
-			echo 
-		fi
-
-		SIP_IP=$(netstat -ant | grep 5060 | head -n1 | awk -F" " '{print $4}' | cut -d: -f1)
-		if [ -z $SIP_IP ]; then
-			echo "# Error: Could not detect FreeSWITCH listening on port 5060"
-			echo 
-		else
-		    if [ "$BBB_SIP_APP_IP" != $SIP_IP ]; then
-			echo "# Error: FreeSWITCH is listening on IP address $SIP_IP for SIP calls, but "
-			echo "# The IP address ($BBB_SIP_APP_IP) set bbb.sip.app.ip."
-			echo "#"
-			echo 
-		    fi
-		fi
-	fi
-
-        if [ "$SIP_NGINX_IP" != $IP ]; then
-           if [ "$SIP_NGINX_IP" != "\$freeswitch_addr" ]; then
-                echo "# Warning: The setting of $SIP_NGINX_IP for proxy_pass in"
-                echo "#"
-                echo "#    /etc/bigbluebutton/nginx/sip.nginx"
-                echo "#"
-                echo "# does not match the local IP address ($IP)."
-                echo "# (This is OK if you've manually changed the values)"
-                echo 
-	    fi
+    if [ "$SIP_NGINX_IP" != $IP ]; then
+        if [ "$SIP_NGINX_IP" != "\$freeswitch_addr" ]; then
+            echo "# Warning: The setting of $SIP_NGINX_IP for proxy_pass in"
+            echo "#"
+            echo "#    /etc/bigbluebutton/nginx/sip.nginx"
+            echo "#"
+            echo "# does not match the local IP address ($IP)."
+            echo "# (This is OK if you've manually changed the values)"
+            echo
         fi
+    fi
 
-        VARS_IP=$(cat $FREESWITCH_VARS | sed -n '/"local_ip_v4/{s/.*local_ip_v4=//;s/".*//;p}')
-        if [[ "$VARS_IP" != "127.0.0.1" ]] && [[ "$VARS_IP" != "auto" ]]; then
-                if [ "$VARS_IP" != $IP ]; then
-                        echo "# Warning: The setting of $VARS_IP for local_ip_v4 in"
-                        echo "#"
-                        echo "#    $FREESWITCH_VARS"
-                        echo "#"
-                        echo "# does not match the local IP address ($IP)."
-                        echo "# (This is OK if you've manually changed the values)"
-                        echo 
-                fi
+    VARS_IP=$(cat $FREESWITCH_VARS | sed -n '/"local_ip_v4/{s/.*local_ip_v4=//;s/".*//;p}')
+    if [[ "$VARS_IP" != "127.0.0.1" ]] && [[ "$VARS_IP" != "auto" ]]; then
+        if [ "$VARS_IP" != $IP ]; then
+            echo "# Warning: The setting of $VARS_IP for local_ip_v4 in"
+            echo "#"
+            echo "#    $FREESWITCH_VARS"
+            echo "#"
+            echo "# does not match the local IP address ($IP)."
+            echo "# (This is OK if you've manually changed the values)"
+            echo
         fi
+    fi
 
-	if [ -d ${LTI_DIR} ]; then
-		if test ${TOMCAT_DIR}/webapps/lti.war -nt ${LTI_DIR}; then 
-			echo "# Error: The updated lti.war did not deploy.  To manually deploy:"
-			echo "#"
-                        echo "#   $SUDO touch ${SERVLET_DIR}/lti.war"
-			echo "#"
-                        echo
-		fi
-	fi
-
-	if [ -d ${TOMCAT_DIR}/webapps/demo ]; then
-		if test ${TOMCAT_DIR}/webapps/demo.war -nt ${TOMCAT_DIR}/webapps/demo; then 
-			echo "# Error: The updated demo.war did not deploy.  To manually deploy:"
-			echo "#"
-                        echo "#   $SUDO touch ${SERVLET_DIR}/demo.war"
-			echo "#"
-                        echo
-		fi
-	fi
-
-        if (( $MEM < 3940 )); then
-		echo "# Warning: You are running BigBlueButton on a server with less than 4G of memory.  Your"
-		echo "# performance may suffer."
-                echo
-	fi
+    if [ -d ${LTI_DIR} ]; then
+        if test ${TOMCAT_DIR}/webapps/lti.war -nt ${LTI_DIR}; then
+            echo "# Error: The updated lti.war did not deploy.  To manually deploy:"
+            echo "#"
+            echo "#   $SUDO touch ${SERVLET_DIR}/lti.war"
+            echo "#"
+            echo
+        fi
+    fi
 
-	if [ -f ${TOMCAT_DIR}/webapps/demo/demo1.jsp ]; then
-                BBB_WEB_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
-		echo "# Warning: The API demos are installed and accessible from:"
-		echo "#"
-                echo "#    $BBB_WEB_URL"
-                echo "#"
-                echo "# and"
-                echo "#"
-                echo "#    $BBB_WEB_URL/demo/demo1.jsp"
-		echo "#"
-		echo "# These API demos allow anyone to access your server without authentication"
-		echo "# to create/manage meetings and recordings. They are for testing purposes only."
-		echo "# If you are running a production system, remove them by running:"
-		echo "#"
-		echo "#   $SUDO apt-get purge bbb-demo"
-		echo 
-	fi
-
-	if [ -f /var/www/bigbluebutton/check/conf/config.xml ]; then
-		CHECK_HOST=$(cat /var/www/bigbluebutton/check/conf/config.xml  | grep "<uri>rtmp" | head -1 | sed  's/.*rtmp[s]*:\/\///g' | sed 's/\/.*//g' | tr -d '\015')
-                BBB_WEB_URL=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
-		echo "# Warning: The client self check is installed and accessible from:"
-		echo "#"
-		echo "#    $BBB_WEB_URL/check"
-		echo "#"
-		echo 
-
-	fi
-
-	if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
-		LTI_URL='http://'$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiEndPoint/{s/^.*=//;p}')'/lti/tool'
-		echo "# Warning: The IMS Learning Tools Integration (LTI) is accessible from:"
-		echo "#"
-		echo "#    $LTI_URL"
-		echo "#"
-		echo "# To get the access parameters for LTI, run the command"
-		echo "#"
-		echo "#    bbb-conf --lti"
-		echo 
-	fi
-
-	BBB_WEB=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
-	DEFAULT_PDF=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^beans.presentationService.defaultUploadedPresentation/{s/.*=//;p}')
-	if echo $DEFAULT_PDF | grep -q "bigbluebutton.web.serverURL"; then
-        	if ! echo "$BBB_WEB$(echo $DEFAULT_PDF | sed 's/${bigbluebutton.web.serverURL}//g')" | xargs wget -q -O /dev/null; then
-			echo "# Error: Unable to reach default URL for presentation:"
-			echo "#"
-			echo "#    $BBB_WEB$(echo $DEFAULT_PDF | sed 's/${bigbluebutton.web.serverURL}//g')"
-			echo "#"
-                	echo "# Check value for beans.presentationService.defaultUploadedPresentation in"
-                	echo "#   ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties"
-        	fi
-	else
-        	if ! echo "$DEFAULT_PDF" | xargs wget -q -O /dev/null; then
-			echo "# Error: Unable to reach default URL for presentation"
-			echo "#"
-			echo "#    $DEFAULT_PDF"
-			echo "#"
-                	echo "# Check value for beans.presentationService.defaultUploadedPresentation in"
-                	echo "#   ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties"
-        	fi
-	fi
-
-	if [ -f /var/run/red5.pid ]; then
-          RED5_PID_PS=$(ps -u red5 | grep java | sed 's/^[ ]*//g' | cut -d" " -f1)
-          RED5_PID_FILE=$(cat /var/run/red5.pid)
-          if [[ "$RED5_PID_PS" != "$RED5_PID_FILE" ]]; then
+    if [ -d ${TOMCAT_DIR}/webapps/demo ]; then
+        if test ${TOMCAT_DIR}/webapps/demo.war -nt ${TOMCAT_DIR}/webapps/demo; then
+            echo "# Error: The updated demo.war did not deploy.  To manually deploy:"
+            echo "#"
+            echo "#   $SUDO touch ${SERVLET_DIR}/demo.war"
+            echo "#"
+            echo
+        fi
+    fi
+
+    if (( $MEM < 3940 )); then
+        echo "# Warning: You are running BigBlueButton on a server with less than 4G of memory.  Your"
+        echo "# performance may suffer."
+        echo
+    fi
+
+    if [ -f ${TOMCAT_DIR}/webapps/demo/demo1.jsp ]; then
+        BBB_WEB_URL=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
+        echo "# Warning: The API demos are installed and accessible from:"
+        echo "#"
+        echo "#    $BBB_WEB_URL"
+        echo "#"
+        echo "# and"
+        echo "#"
+        echo "#    $BBB_WEB_URL/demo/demo1.jsp"
+        echo "#"
+        echo "# These API demos allow anyone to access your server without authentication"
+        echo "# to create/manage meetings and recordings. They are for testing purposes only."
+        echo "# If you are running a production system, remove them by running:"
+        echo "#"
+        echo "#   $SUDO apt-get purge bbb-demo"
+        echo
+    fi
+
+    if [ -f /var/www/bigbluebutton/check/conf/config.xml ]; then
+        CHECK_HOST=$(cat /var/www/bigbluebutton/check/conf/config.xml  | grep "<uri>rtmp" | head -1 | sed  's/.*rtmp[s]*:\/\///g' | sed 's/\/.*//g' | tr -d '\015')
+        BBB_WEB_URL=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
+        echo "# Warning: The client self check is installed and accessible from:"
+        echo "#"
+        echo "#    $BBB_WEB_URL/check"
+        echo "#"
+        echo
+    fi
+
+    if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
+        LTI_URL='http://'$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^ltiEndPoint/{s/^.*=//;p}')'/lti/tool'
+        echo "# Warning: The IMS Learning Tools Integration (LTI) is accessible from:"
+        echo "#"
+        echo "#    $LTI_URL"
+        echo "#"
+        echo "# To get the access parameters for LTI, run the command"
+        echo "#"
+        echo "#    bbb-conf --lti"
+        echo
+    fi
+
+    BBB_WEB=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')
+    DEFAULT_PDF=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^beans.presentationService.defaultUploadedPresentation/{s/.*=//;p}')
+    if echo $DEFAULT_PDF | grep -q "bigbluebutton.web.serverURL"; then
+        if ! echo "$BBB_WEB$(echo $DEFAULT_PDF | sed 's/${bigbluebutton.web.serverURL}//g')" | xargs wget -q -O /dev/null; then
+            echo "# Error: Unable to reach default URL for presentation:"
+            echo "#"
+            echo "#    $BBB_WEB$(echo $DEFAULT_PDF | sed 's/${bigbluebutton.web.serverURL}//g')"
+            echo "#"
+            echo "# Check value for beans.presentationService.defaultUploadedPresentation in"
+            echo "#   ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties"
+        fi
+    else
+        if ! echo "$DEFAULT_PDF" | xargs wget -q -O /dev/null; then
+            echo "# Error: Unable to reach default URL for presentation"
+            echo "#"
+            echo "#    $DEFAULT_PDF"
+            echo "#"
+            echo "# Check value for beans.presentationService.defaultUploadedPresentation in"
+            echo "#   ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties"
+        fi
+    fi
+
+    if [ -f /var/run/red5.pid ]; then
+        RED5_PID_PS=$(ps -u red5 | grep java | sed 's/^[ ]*//g' | cut -d" " -f1)
+        RED5_PID_FILE=$(cat /var/run/red5.pid)
+        if [[ "$RED5_PID_PS" != "$RED5_PID_FILE" ]]; then
             if [ "$(ps -aef | grep "su -p -s /bin/sh red5 " | wc --lines)" == "2" ]; then
                 RED5_PID_PS=$(ps -aef | grep "su -p -s /bin/sh red5 " | head -n 1 | awk '{print $2}')
                 if [[ "$RED5_PID_PS" != "$RED5_PID_FILE" ]]; then
-                        echo "# Error: red5 process ID does not match value in PID file"
-                        echo "#"
-                        echo "#         pid from top: $RED5_PID_PS"
-                        echo "#    /var/run/red5.pid: $RED5_PID_FILE"  
-                        echo "#"
+                    echo "# Error: red5 process ID does not match value in PID file"
+                    echo "#"
+                    echo "#         pid from top: $RED5_PID_PS"
+                    echo "#    /var/run/red5.pid: $RED5_PID_FILE"
+                    echo "#"
                 fi
             else
                 echo "# Error: red5 process ID does not match value in PID file"
                 echo "#"
                 echo "#         pid from top: $RED5_PID_PS"
-                echo "#    /var/run/red5.pid: $RED5_PID_FILE"  
+                echo "#    /var/run/red5.pid: $RED5_PID_FILE"
                 echo "#"
             fi
-          fi
         fi
+   fi
 
-	if [ "$(cat /usr/share/bbb-apps-akka/conf/application.conf | sed -n '/sharedSecret.*/{s/[^"]*"//;s/".*//;p}')" == "changeme" ]; then
-	        BBB_WEB_IP=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
-                echo "# Error: Detected that /usr/share/bbb-apps-akka/conf/application.conf has the default"
-                echo "# configuration values.  To update, run"
-                echo "#"
-                echo "#   $SUDO bbb-conf --setip $BBB_WEB_IP"
-                echo "#"
-	fi
+    if [ "$(cat /usr/share/bbb-apps-akka/conf/application.conf | sed -n '/sharedSecret.*/{s/[^"]*"//;s/".*//;p}')" == "changeme" ]; then
+        BBB_WEB_IP=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
+        echo "# Error: Detected that /usr/share/bbb-apps-akka/conf/application.conf has the default"
+        echo "# configuration values.  To update, run"
+        echo "#"
+        echo "#   $SUDO bbb-conf --setip $BBB_WEB_IP"
+        echo "#"
+    fi
 
-        if [ -z $(cat /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties | tr -d '\r' | sed -n "/useH264[ ]*=[ ]*/{s/useH264[ ]*=[ ]*//;p}") ]; then
-                echo "# Error: Detected there is no value set for useH264 in"
-                echo "#"
-                echo "#   /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties"
-                echo "#"
-        fi
+    if [ -z $(cat /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties | tr -d '\r' | sed -n "/useH264[ ]*=[ ]*/{s/useH264[ ]*=[ ]*//;p}") ]; then
+        echo "# Error: Detected there is no value set for useH264 in"
+        echo "#"
+        echo "#   /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties"
+        echo "#"
+    fi
 
-        if bbb-conf --status | grep -q inactive; then
-                echo "# Error: Detected some processes have not started correctly"
-                echo "#"
-                echo "#   $(bbb-conf --status | grep inactive)"
-                echo "#"
-        fi
+    if bbb-conf --status | grep -q inactive; then
+        echo "# Error: Detected some processes have not started correctly"
+        echo "#"
+        echo "#   $(bbb-conf --status | grep inactive)"
+        echo "#"
+    fi
 
-        if systemctl status freeswitch | grep -q SETSCHEDULER; then
-                echo "# Error: FreeSWITCH failed to start with SETSCHEDULER error, see"
-                echo "#"
-                echo "#   http://docs.bigbluebutton.org/install/install.html#freeswitch-fails-to-start-with-a-setscheduler-error"
-                echo "#"
-        fi
+    if systemctl status freeswitch | grep -q SETSCHEDULER; then
+        echo "# Error: FreeSWITCH failed to start with SETSCHEDULER error, see"
+        echo "#"
+        echo "#   http://docs.bigbluebutton.org/install/install.html#freeswitch-fails-to-start-with-a-setscheduler-error"
+        echo "#"
+    fi
+
+    NCPU=$(nproc --all)
+    if [ "$NCPU" -lt "4" ]; then
+        echo "# Warning: found only $NCPU cores, whereas this sherver should have (at least) 4 CPU cores"
+        echo "# to run BigBlueButton in production."
+        echo "#"
+        echo "#   http://docs.bigbluebutton.org/install/install.html#minimum-server-requirements"
+        echo "#"
+    fi
+
+    if [ "$PROTOCOL" == "https" ]; then
+      if ! cat $SIP_CONFIG |  grep -v '#' | grep proxy_pass | head -n 1 | grep -q https; then
+        echo "# Warning: You have this server defined for https, but in"
+        echo "#"
+        echo "#   $SIP_CONFIG"
+        echo "#"
+        echo "#  did not find the use of https in definition for proxy_pass"
+        echo "#"
+        echo "#    $(cat $SIP_CONFIG |  grep -v '#' | grep proxy_pass | head -n 1)"
+        echo "#"
+      fi
+
+      if ! cat $SIP_CONFIG |  grep -v '#' | grep proxy_pass | head -n 1 | grep -q 7443; then
+        echo
+        echo "# Warning: You have this server defined for https, but in"
+        echo "#"
+        echo "#   $SIP_CONFIG"
+        echo "#"
+        echo "#  did not find the use of port 7443 in definition for proxy_pass"
+        echo "#"
+        echo "#    $(cat $SIP_CONFIG |  grep -v '#' | grep proxy_pass | head -n 1)"
+        echo "#"
+      fi
+    fi
 
-        NCPU=`nproc --all`
-        if [ "$NCPU" -lt "4" ]; then
-                echo "# Warning: found only $NCPU cores, whereas this sherver should have (at least) 4 CPU cores"
-                echo "# to run BigBlueButton in production."
-                echo "#"
-                echo "#   http://docs.bigbluebutton.org/install/install.html#minimum-server-requirements"
-                echo "#"
-        fi
 
-	exit 0
+    exit 0
 }
 
 
@@ -1603,544 +1425,527 @@ check_state() {
 # Print out the status of the current setup and look for configuration issues
 #
 if [ $CHECK ]; then
-	need_root
-	
-	echo 
-        if [ $DISTRIB_ID == "centos" ]; then
-          echo "BigBlueButton Server $BIGBLUEBUTTON_RELEASE ($(rpm -qa | grep bbb | grep -v bbb-demo | grep -v bbb-lti | grep -v bbb-redis | grep -v bbb-tomcat | grep -v freeswitch | sed 's/.*[0-9].[0-9].[0-9]-//g' | sed 's/\..*//g' | awk '{ sum+=$1} END {print sum}'))"
-        else 
-          echo "BigBlueButton Server $BIGBLUEBUTTON_RELEASE ($(dpkg -l | grep bbb | grep -v bbb-demo | grep -v bbb-lti | sed -n '/[0-9].[0-9].[0-9]-/{s/.*[0-9].[0-9].[0-9]-//;s/;//;p}' | awk '{ sum+=$1} END {print sum}'))"
-	fi
-
-	echo "                    Kernel version:" `uname -r`
-
-        if [ $DISTRIB_ID == "centos" ]; then
-                echo -n "                      Distribution: $(cat /etc/redhat-release)"
-        else
-                source /etc/lsb-release;
-                echo -n "                      Distribution: $DISTRIB_DESCRIPTION "
-        fi
+    need_root
 
-	if [ `uname -m` == "x86_64" ]; then
-		echo "(64-bit)"
-	elif [ `uname -m` == "i686" ]; then
-		echo "(32-bit)"
-	fi
-
-	echo "                            Memory: $MEM MB"
-        echo "                         CPU cores: $NCPU"
-
-	echo
-	echo "$BBB_WEB_CONFIG (bbb-web)"
-	echo "       bigbluebutton.web.serverURL: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')"
-	echo "                defaultGuestPolicy: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^defaultGuestPolicy/{s/.*=//;p}')"
-	echo "                 svgImagesRequired: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^svgImagesRequired/{s/.*=//;p}')"
-
-	echo
-	echo "/etc/nginx/sites-available/bigbluebutton (nginx)"
-	echo "                       server name: $NGINX_IP"
-
-        PORT=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/listen/{s/.*listen[ ]*//;s/;//;p}' | grep -v ssl | tr --delete '\n' | sed 's/\[/, \[/g' | sed 's/0$/0\n/g')
-        echo "                              port: $PORT"
-        if cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/listen/{s/.*listen[ ]*//;s/;//;p}' | grep ssl > /dev/null; then
-          echo "                              port: 443 ssl"
-        fi
-	BBB_CLIENT_DOC_ROOT=$(cat /etc/bigbluebutton/nginx/client.nginx | grep -v '#' | grep \/client -A 1 | head -n 2 | grep root | sed -n '{s/[ \t]*root[ ]*//;s/;//;p}')
-	echo "                    bbb-client dir: $BBB_CLIENT_DOC_ROOT"
-
-	echo
-	echo "/var/www/bigbluebutton/client/conf/config.xml (bbb-client)"
-	PORT_IP=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/porttest /{s/.*host="//;s/".*//;p}')
-	echo "  		Port test (tunnel): $PORT_IP"
-
-	RED5_IP=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/uri.*video/{s/.*rtmp[s]*:\/\///;s/\/.*//;p}')
-	WEBRTC_ENABLED_CLIENT=`xmlstarlet sel -t -m "config/modules/module[@name='PhoneModule']" -v @useWebRTCIfAvailable /var/www/bigbluebutton/client/conf/config.xml`
-	echo "                              red5: $RED5_IP"
-	echo "              useWebrtcIfAvailable: $WEBRTC_ENABLED_CLIENT"
-
-	echo
-	echo "$FREESWITCH_VARS (FreeSWITCH)"
-	echo "                       local_ip_v4: $(xmlstarlet sel -t -m '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "local_ip_v4=")]' -v @data $FREESWITCH_VARS | sed 's/local_ip_v4=//g')"
-	echo "                   external_rtp_ip: $(xmlstarlet sel -t -m '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_rtp_ip=")]' -v @data $FREESWITCH_VARS | sed 's/external_rtp_ip=//g')"
-	echo "                   external_sip_ip: $(xmlstarlet sel -t -m '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_sip_ip=")]' -v @data $FREESWITCH_VARS | sed 's/external_sip_ip=//g')"
-
-	echo
-	echo "$FREESWITCH_EXTERNAL (FreeSWITCH)"
-	echo "                        ext-rtp-ip: $(xmlstarlet sel -t -m 'profile/settings/param[@name="ext-rtp-ip"]' -v @value $FREESWITCH_EXTERNAL)"
-	echo "                        ext-sip-ip: $(xmlstarlet sel -t -m 'profile/settings/param[@name="ext-sip-ip"]' -v @value $FREESWITCH_EXTERNAL)"
-	echo "                        ws-binding: $(xmlstarlet sel -t -m 'profile/settings/param[@name="ws-binding"]' -v @value $FREESWITCH_EXTERNAL)"
-	echo "                       wss-binding: $(xmlstarlet sel -t -m 'profile/settings/param[@name="wss-binding"]' -v @value $FREESWITCH_EXTERNAL)"
-
-	if [ -f ${SERVLET_DIR}/demo/bbb_api_conf.jsp ]; then
-		BBB_WEB_URL=$(cat ${SERVLET_DIR}//WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
-		echo
-		echo "${SERVLET_DIR}/demo/bbb_api_conf.jsp (API demos)"
-		echo "                               url: $BBB_WEB_URL"
-	fi
-
-#	if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
-#		LTI_URL=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^bigbluebuttonURL/{s/.*http[s]:\/\///;s/\/.*//;p}' | tr -d '\015')
-#		echo
-#		echo "${LTI_DIR}/WEB-INF/classes/lti-config.properties (LTI integration)"
-#		echo "                           api url: $LTI_URL"
-#	fi
-
-	if [ -f /var/www/bigbluebutton/check/conf/config.xml ]; then
-		CHECK_URL=$(cat /var/www/bigbluebutton/check/conf/config.xml  | grep "<uri>rtmp" | head -1 | sed  's/.*rtmp[s]*:\/\///g' | sed 's/\/.*//g' | tr -d '\015')
-		echo
-		echo "/var/www/bigbluebutton/check/conf/config.xml (client check)"
-		echo "                      client check: $CHECK_URL"
-	fi
-
-	if [ -f $RECORD_CONFIG ]; then
-		echo
-		echo "$RECORD_CONFIG (record and playback)"
-		echo "                     playback_host: $(yq r $RECORD_CONFIG playback_host)"
-		echo "                 playback_protocol: $(yq r $RECORD_CONFIG playback_protocol)"
-                echo "                            ffmpeg: $(ffmpeg -version 2>/dev/null | grep ffmpeg | cut -d ' ' -f3 | sed 's/--.*//g' | tr -d '\n')"
-	fi
-
-        if [ -f $SIP_CONFIG ]; then
-                echo
-                echo "$SIP_CONFIG (sip.nginx)"
-                echo "                        proxy_pass: $SIP_NGINX_IP"
-        fi
+    echo
+    if [ $DISTRIB_ID == "centos" ]; then
+        echo "BigBlueButton Server $BIGBLUEBUTTON_RELEASE ($(rpm -qa | grep bbb | grep -v bbb-demo | grep -v bbb-lti | grep -v bbb-redis | grep -v bbb-tomcat | grep -v freeswitch | sed 's/.*[0-9].[0-9].[0-9]-//g' | sed 's/\..*//g' | awk '{ sum+=$1} END {print sum}'))"
+    else
+        echo "BigBlueButton Server $BIGBLUEBUTTON_RELEASE ($(dpkg -l | grep bbb | grep -v bbb-demo | grep -v bbb-lti | sed -n '/[0-9].[0-9].[0-9]-/{s/.*[0-9].[0-9].[0-9]-//;s/;//;p}' | awk '{ sum+=$1} END {print sum}'))"
+    fi
 
-        if [ -f $KURENTO_CONFIG ]; then
-                echo
-                echo "$KURENTO_CONFIG (Kurento SFU)"
-                echo "                        kurento.ip: $(yq r $KURENTO_CONFIG kurento[0].ip)"
-                echo "                       kurento.url: $(yq r $KURENTO_CONFIG kurento[0].url)"
-                echo "                    localIpAddress: $(yq r $KURENTO_CONFIG localIpAddress)"
-                echo "               recordScreenSharing: $(yq r $KURENTO_CONFIG recordScreenSharing)"
-                echo "                     recordWebcams: $(yq r $KURENTO_CONFIG recordWebcams)"
-                echo "                  codec_video_main: $(yq r $KURENTO_CONFIG conference-media-specs.codec_video_main)"
-                echo "               codec_video_content: $(yq r $KURENTO_CONFIG conference-media-specs.codec_video_content)"
-        fi
+    echo "                    Kernel version:" $(uname -r)
 
-	if [ -f $HTML5_CONFIG ]; then
-                echo
-                echo "/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml (HTML5 client)"
-                echo "                             build: $(yq r $HTML5_CONFIG public.app.html5ClientBuild)"
-                echo "                        kurentoUrl: $(yq r $HTML5_CONFIG public.kurento.wsUrl)"
-                echo "                  enableListenOnly: $(yq r $HTML5_CONFIG public.kurento.enableListenOnly)"
-	fi
+    if [ $DISTRIB_ID == "centos" ]; then
+        echo -n "                      Distribution: $(cat /etc/centos-release)"
+    else
+        source /etc/lsb-release
+        echo -n "                      Distribution: $DISTRIB_DESCRIPTION "
+    fi
+
+    if [ $(uname -m) == "x86_64" ]; then
+        echo "(64-bit)"
+    elif [ $(uname -m) == "i686" ]; then
+        echo "(32-bit)"
+    fi
+
+    echo "                            Memory: $MEM MB"
+    echo "                         CPU cores: $NCPU"
+
+    echo
+    echo "$BBB_WEB_CONFIG (bbb-web)"
+    echo "       bigbluebutton.web.serverURL: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}')"
+    echo "                defaultGuestPolicy: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^defaultGuestPolicy/{s/.*=//;p}')"
+    echo "                 svgImagesRequired: $(cat $BBB_WEB_CONFIG | grep -v '#' | sed -n '/^svgImagesRequired/{s/.*=//;p}')"
+
+    echo
+    echo "/etc/nginx/sites-available/bigbluebutton (nginx)"
+    echo "                       server name: $NGINX_IP"
+
+    PORT=$(cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/listen/{s/.*listen[ ]*//;s/;//;p}' | grep -v ssl | tr --delete '\n' | sed 's/\[/, \[/g' | sed 's/0$/0\n/g')
+    echo "                              port: $PORT"
+    if cat /etc/nginx/sites-available/bigbluebutton | grep -v '#' | sed -n '/listen/{s/.*listen[ ]*//;s/;//;p}' | grep ssl > /dev/null; then
+        echo "                              port: 443 ssl"
+    fi
+    BBB_CLIENT_DOC_ROOT=$(cat /etc/bigbluebutton/nginx/client.nginx | grep -v '#' | grep \/client -A 1 | head -n 2 | grep root | sed -n '{s/[ \t]*root[ ]*//;s/;//;p}')
+    echo "                    bbb-client dir: $BBB_CLIENT_DOC_ROOT"
+
+    echo
+    echo "/var/www/bigbluebutton/client/conf/config.xml (bbb-client)"
+    PORT_IP=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/porttest /{s/.*host="//;s/".*//;p}')
+    echo "                Port test (tunnel): $PORT_IP"
+
+    RED5_IP=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/uri.*video/{s/.*rtmp[s]*:\/\///;s/\/.*//;p}')
+    WEBRTC_ENABLED_CLIENT=$(xmlstarlet sel -t -m "config/modules/module[@name='PhoneModule']" -v @useWebRTCIfAvailable /var/www/bigbluebutton/client/conf/config.xml)
+    echo "                              red5: $RED5_IP"
+    echo "              useWebrtcIfAvailable: $WEBRTC_ENABLED_CLIENT"
+
+    echo
+    echo "$FREESWITCH_VARS (FreeSWITCH)"
+    echo "                       local_ip_v4: $(xmlstarlet sel -t -m '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "local_ip_v4=")]' -v @data $FREESWITCH_VARS | sed 's/local_ip_v4=//g')"
+    echo "                   external_rtp_ip: $(xmlstarlet sel -t -m '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_rtp_ip=")]' -v @data $FREESWITCH_VARS | sed 's/external_rtp_ip=//g')"
+    echo "                   external_sip_ip: $(xmlstarlet sel -t -m '//X-PRE-PROCESS[@cmd="set" and starts-with(@data, "external_sip_ip=")]' -v @data $FREESWITCH_VARS | sed 's/external_sip_ip=//g')"
+
+    echo
+    echo "$FREESWITCH_EXTERNAL (FreeSWITCH)"
+    echo "                        ext-rtp-ip: $(xmlstarlet sel -t -m 'profile/settings/param[@name="ext-rtp-ip"]' -v @value $FREESWITCH_EXTERNAL)"
+    echo "                        ext-sip-ip: $(xmlstarlet sel -t -m 'profile/settings/param[@name="ext-sip-ip"]' -v @value $FREESWITCH_EXTERNAL)"
+    echo "                        ws-binding: $(xmlstarlet sel -t -m 'profile/settings/param[@name="ws-binding"]' -v @value $FREESWITCH_EXTERNAL)"
+    echo "                       wss-binding: $(xmlstarlet sel -t -m 'profile/settings/param[@name="wss-binding"]' -v @value $FREESWITCH_EXTERNAL)"
+
+    if [ -f ${SERVLET_DIR}/demo/bbb_api_conf.jsp ]; then
+        BBB_WEB_URL=$(cat ${SERVLET_DIR}//WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*\///;p}')
+        echo
+        echo "${SERVLET_DIR}/demo/bbb_api_conf.jsp (API demos)"
+        echo "                               url: $BBB_WEB_URL"
+    fi
+
+#     if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
+#          LTI_URL=$(cat ${LTI_DIR}/WEB-INF/classes/lti-config.properties | grep -v '#' | sed -n '/^bigbluebuttonURL/{s/.*http[s]:\/\///;s/\/.*//;p}' | tr -d '\015')
+#          echo
+#          echo "${LTI_DIR}/WEB-INF/classes/lti-config.properties (LTI integration)"
+#          echo "                           api url: $LTI_URL"
+#     fi
+
+    if [ -f /var/www/bigbluebutton/check/conf/config.xml ]; then
+        CHECK_URL=$(cat /var/www/bigbluebutton/check/conf/config.xml  | grep "<uri>rtmp" | head -1 | sed  's/.*rtmp[s]*:\/\///g' | sed 's/\/.*//g' | tr -d '\015')
+        echo
+        echo "/var/www/bigbluebutton/check/conf/config.xml (client check)"
+        echo "                      client check: $CHECK_URL"
+    fi
+
+    if [ -f $RECORD_CONFIG ]; then
+        echo
+        echo "$RECORD_CONFIG (record and playback)"
+        echo "                     playback_host: $(yq r $RECORD_CONFIG playback_host)"
+        echo "                 playback_protocol: $(yq r $RECORD_CONFIG playback_protocol)"
+        echo "                            ffmpeg: $(ffmpeg -version 2>/dev/null | grep ffmpeg | cut -d ' ' -f3 | sed 's/--.*//g' | tr -d '\n')"
+    fi
+
+    if [ -f $SIP_CONFIG ]; then
+        echo
+        echo "$SIP_CONFIG (sip.nginx)"
+        echo "                        proxy_pass: $SIP_NGINX_IP"
+    fi
+
+    if [ -f $KURENTO_CONFIG ]; then
+        echo
+        echo "$KURENTO_CONFIG (Kurento SFU)"
+        echo "                        kurento.ip: $(yq r $KURENTO_CONFIG kurento[0].ip)"
+        echo "                       kurento.url: $(yq r $KURENTO_CONFIG kurento[0].url)"
+        echo "                    localIpAddress: $(yq r $KURENTO_CONFIG localIpAddress)"
+        echo "               recordScreenSharing: $(yq r $KURENTO_CONFIG recordScreenSharing)"
+        echo "                     recordWebcams: $(yq r $KURENTO_CONFIG recordWebcams)"
+        echo "                  codec_video_main: $(yq r $KURENTO_CONFIG conference-media-specs.codec_video_main)"
+        echo "               codec_video_content: $(yq r $KURENTO_CONFIG conference-media-specs.codec_video_content)"
+    fi
 
+     if [ -f $HTML5_CONFIG ]; then
+        echo
+        echo "/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml (HTML5 client)"
+        echo "                             build: $(yq r $HTML5_CONFIG public.app.html5ClientBuild)"
+        echo "                        kurentoUrl: $(yq r $HTML5_CONFIG public.kurento.wsUrl)"
+        echo "                  enableListenOnly: $(yq r $HTML5_CONFIG public.kurento.enableListenOnly)"
+     fi
 
-	check_state
-	echo
+     check_state
+     echo
 
-	exit 0
+     exit 0
 fi
 
 #
 # Zip log files
 #
 if [ $ZIP ]; then
-	need_root
-
-	LOG_FILE="$(date +'%Y%m%d')-$(date +%H)"
-	#
-	# Check log files
-	#
-	rm -f /tmp/$LOG_FILE.tar
-	rm -f /tmp/$LOG_FILE.tar.gz
-	rm -f /tmp/a
-
-	touch /tmp/empty
-	tar cf  /tmp/$LOG_FILE.tar /tmp/empty				> /dev/null 2>&1
-	tar rfh /tmp/$LOG_FILE.tar $RED5_DIR/log			> /dev/null 2>&1
-	tar rfh /tmp/$LOG_FILE.tar $SERVLET_LOGS			> /dev/null 2>&1
-	tar rf  /tmp/$LOG_FILE.tar /var/log/bigbluebutton/*	> /dev/null 2>&1
-	tar rf  /tmp/$LOG_FILE.tar /var/log/bbb-apps-akka	> /dev/null 2>&1
-	tar rf  /tmp/$LOG_FILE.tar /var/log/bbb-transcode-akka	> /dev/null 2>&1
-	tar rf  /tmp/$LOG_FILE.tar /var/log/bbb-fsesl-akka	> /dev/null 2>&1
-	tar rf  /tmp/$LOG_FILE.tar /var/log/nginx/error.log	> /dev/null 2>&1
-	if [ $DISTRIB_ID == "ubuntu" ]; then
-		tar rf /tmp/$LOG_FILE.tar /var/log/syslog		> /dev/null 2>&1
-	fi
-
-	tar tf /tmp/$LOG_FILE.tar
-	gzip /tmp/$LOG_FILE.tar
-	mv /tmp/$LOG_FILE.tar.gz /root/$LOG_FILE.tar.gz
-	echo
-	echo "  Created: /root/$LOG_FILE.tar.gz"
-	echo
+    need_root
+
+    LOG_FILE="$(date +'%Y%m%d')-$(date +%H).tar"
+    TMP_LOG_FILE="/tmp/$LOG_FILE"
+    #
+    # Check log files
+    #
+    rm -f "$LOG_FILE.gz"
+    rm -f /tmp/a
+
+    touch /tmp/empty
+    tar cf  $TMP_LOG_FILE /tmp/empty               > /dev/null 2>&1
+    tar rfh $TMP_LOG_FILE $RED5_DIR/log            > /dev/null 2>&1
+    tar rfh $TMP_LOG_FILE $SERVLET_LOGS            > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/bigbluebutton/* > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/bbb-apps-akka   > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/bbb-transcode-akka     > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/bbb-fsesl-akka         > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/bbb-webrtc-sfu         > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/kurento-media-server > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/mongodb              > /dev/null 2>&1
+    tar rf  $TMP_LOG_FILE /var/log/nginx/error.log      > /dev/null 2>&1
+    if [ $DISTRIB_ID == "ubuntu" ]; then
+        tar rf $TMP_LOG_FILE /var/log/syslog        > /dev/null 2>&1
+    fi
+
+    tar tf $TMP_LOG_FILE
+    gzip $TMP_LOG_FILE
+    $SUDO mv $TMP_LOG_FILE.gz /root/$LOG_FILE.gz
+    echo
+    echo "  Created: /root/$LOG_FILE.gz"
+    echo
 fi
 
 #
 # Check current setup
 #
 if [ $DEBUG ]; then
-	need_root
-	#
-	# Check log files
-	#
-
-	rm -rf /tmp/t
-	grep --directories=skip ERROR /var/log/bigbluebutton/* > /tmp/t
-	if [ -s /tmp/t ]; then
-		echo "  -- ERRORS found in /var/log/bigbluebutton/* -- "
-		cat /tmp/t
-		echo
-	fi
-
-	rm -rf /tmp/t
-	grep --directories=skip Exception /var/log/bigbluebutton/* | grep -v CacheExceptionHandlerFactory > /tmp/t
-        if [ -s /tmp/t ]; then
-                echo "  -- ERRORS found in /var/log/bigbluebutton/* -- "
-                cat /tmp/t
-                echo
-        fi
+    need_root
+    #
+    # Check log files
+    #
+
+    rm -rf /tmp/t
+    grep --directories=skip ERROR /var/log/bigbluebutton/* > /tmp/t
+    if [ -s /tmp/t ]; then
+        echo "  -- ERRORS found in /var/log/bigbluebutton/* -- "
+        cat /tmp/t
+        echo
+    fi
 
+    rm -rf /tmp/t
+    grep --directories=skip Exception /var/log/bigbluebutton/* | grep -v CacheExceptionHandlerFactory > /tmp/t
+    if [ -s /tmp/t ]; then
+        echo "  -- ERRORS found in /var/log/bigbluebutton/* -- "
+        cat /tmp/t
+        echo
+    fi
 
-	rm -rf /tmp/t
-	grep --directories=skip ERROR $RED5_DIR/log/* > /tmp/t 
-	if [ -s /tmp/t ]; then
-		echo "   -- ERRORS found in $RED5_DIR/log/* -- "
-		cat /tmp/t
- 		echo
-	fi
 
+    rm -rf /tmp/t
+    grep --directories=skip ERROR $RED5_DIR/log/* > /tmp/t
+    if [ -s /tmp/t ]; then
+        echo "   -- ERRORS found in $RED5_DIR/log/* -- "
+        cat /tmp/t
+        echo
+    fi
+
+
+    rm -rf /tmp/t
+    grep --directories=skip Exception $RED5_DIR/log/* > /tmp/t
+    if [ -s /tmp/t ]; then
+        echo "   -- Exceptions found in $RED5_DIR/log/* -- "
+        cat /tmp/t
+        echo
+    fi
 
-	rm -rf /tmp/t
-	grep --directories=skip Exception $RED5_DIR/log/* > /tmp/t 
-	if [ -s /tmp/t ]; then
-		echo "   -- Exceptions found in $RED5_DIR/log/* -- "
-		cat /tmp/t
-		echo
-	fi
 
+    rm -rf /tmp/t
+    $SUDO grep --directories=skip Exception $SERVLET_LOGS/* | grep -v CacheExceptionHandlerFactory > /tmp/t
+    if [ -s /tmp/t ]; then
+        echo "   -- Exceptions found in $SERVLET_LOGS/ -- "
+        cat /tmp/t
+        echo
+    fi
 
-	rm -rf /tmp/t
-	$SUDO grep --directories=skip Exception $SERVLET_LOGS/* | grep -v CacheExceptionHandlerFactory > /tmp/t 
-	if [ -s /tmp/t ]; then
-		echo "   -- Exceptions found in $SERVLET_LOGS/ -- "
-		cat /tmp/t
-		echo
-	fi
+    rm -rf /tmp/t
+    if [ -s /var/log/nginx/error.log ]; then
+        cat /var/log/nginx/error.log | grep -v "/fcs/ident2" > /tmp/t
+        if [ -s /tmp/t ]; then
+            echo "   -- Errors found in /var/log/nginx/error.log -- "
+            cat /tmp/t
+            echo
+        fi
+    fi
 
+    if [ $DISTRIB_ID == "Ubuntu" ]; then
         rm -rf /tmp/t
-        if [ -s /var/log/nginx/error.log ]; then
-                cat /var/log/nginx/error.log | grep -v "/fcs/ident2" > /tmp/t
-                if [ -s /tmp/t ]; then
-                        echo "   -- Errors found in /var/log/nginx/error.log -- "
-                        cat /tmp/t
-                        echo
-                fi
+        $SUDO grep --directories=skip -i exception /var/log/syslog > /tmp/t
+        if [ -s /tmp/t ]; then
+            echo "   -- Errors found in /var/log/syslog -- "
+            cat /tmp/t
+            echo
         fi
+    fi
 
-	if [ $DISTRIB_ID == "Ubuntu" ]; then
-		rm -rf /tmp/t
-		$SUDO grep --directories=skip -i exception /var/log/syslog > /tmp/t 
-		if [ -s /tmp/t ]; then
-			echo "   -- Errors found in /var/log/syslog -- "
-			cat /tmp/t
-			echo
-		fi
-	fi
-
-	rm -rf /tmp/t
-	if [ -d /var/log/bigbluebutton ]; then
-		  $SUDO grep --directories=skip ERROR /var/log/bigbluebutton/* > /tmp/t 
-		  if [ -s /tmp/t ]; then
-			echo "   -- Errors found in /var/log/bigbluebutton -- "
-			cat /tmp/t
-			echo
-		  fi
-	fi
-
-	rm -rf /tmp/t
-	if [ -d /var/log/bigbluebutton ]; then
-		  $SUDO grep --directories=skip -i exception /var/log/bigbluebutton/* > /tmp/t 
-		  if [ -s /tmp/t ]; then
-			echo "   -- Exceptions found in /var/log/bigbluebutton -- "
-			cat /tmp/t
-			echo
-		  fi
-	fi
-
-	#
-	# Additional checks for record and playback
-	#
-
-        if [ -f /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml ]; then
-		bbb-record --check
-	fi
-
-	exit 0
+    rm -rf /tmp/t
+    if [ -d /var/log/bigbluebutton ]; then
+        $SUDO grep --directories=skip ERROR /var/log/bigbluebutton/* > /tmp/t
+        if [ -s /tmp/t ]; then
+            echo "   -- Errors found in /var/log/bigbluebutton -- "
+            cat /tmp/t
+            echo
+        fi
+    fi
+
+    rm -rf /tmp/t
+    if [ -d /var/log/bigbluebutton ]; then
+        $SUDO grep --directories=skip -i exception /var/log/bigbluebutton/* > /tmp/t
+        if [ -s /tmp/t ]; then
+            echo "   -- Exceptions found in /var/log/bigbluebutton -- "
+            cat /tmp/t
+            echo
+        fi
+    fi
+
+    #
+    # Additional checks for record and playback
+    #
+
+    if [ -f /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml ]; then
+        bbb-record --check
+    fi
+
+    exit 0
 fi
 
 
 
 # if asked to print the version that's all we do
 if [ -n "$HOST" ]; then
-	#
-	# Just use the IP for port test in /var/www/bigbluebutton/client/conf/config.xml
-	#
-	echo "Assigning $HOST for testing for firewall in /var/www/bigbluebutton/client/conf/config.xml"
-	$SUDO sed -i "s/porttest host=\(\"[^\"]*\"\)/porttest host=\"$PROTOCOL_RTMP:\/\/$HOST\"/g" /var/www/bigbluebutton/client/conf/config.xml
+    #
+    # Just use the IP for port test in /var/www/bigbluebutton/client/conf/config.xml
+    #
+    echo "Assigning $HOST for testing for firewall in /var/www/bigbluebutton/client/conf/config.xml"
+    $SUDO sed -i "s/porttest host=\(\"[^\"]*\"\)/porttest host=\"$PROTOCOL_RTMP:\/\/$HOST\"/g" /var/www/bigbluebutton/client/conf/config.xml
 
-	echo "Assigning $HOST for rtmp:// in /var/www/bigbluebutton/client/conf/config.xml"
-	$SUDO sed -i "s/rtmp[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/$PROTOCOL_RTMP:\/\/$HOST\2/g" /var/www/bigbluebutton/client/conf/config.xml
+    echo "Assigning $HOST for rtmp:// in /var/www/bigbluebutton/client/conf/config.xml"
+    $SUDO sed -i "s/rtmp[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/$PROTOCOL_RTMP:\/\/$HOST\2/g" /var/www/bigbluebutton/client/conf/config.xml
 
-	echo "Assigning $HOST for servername in /etc/nginx/sites-available/bigbluebutton"
-	$SUDO sed -i "s/server_name  .*/server_name  $HOST;/g" /etc/nginx/sites-available/bigbluebutton
+    echo "Assigning $HOST for servername in /etc/nginx/sites-available/bigbluebutton"
+    $SUDO sed -i "s/server_name  .*/server_name  $HOST;/g" /etc/nginx/sites-available/bigbluebutton
 
-	#
-	# Update configuration for BigBlueButton client (and preserve hostname for chromeExtensionLink if exists)
-	#
+    #
+    # Update configuration for BigBlueButton client (and preserve hostname for chromeExtensionLink if exists)
+    #
 
-	# Extract the chrome store URL before updating config.xml. We will be able to restore it.
-	chromeExtensionLinkURL=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/chromeExtensionLink/{s/.*https*:\/\///;s/\/.*//;p}')
-	
-	echo "Assigning $HOST for http[s]:// in /var/www/bigbluebutton/client/conf/config.xml"
-	$SUDO sed -i "s/http[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/$PROTOCOL:\/\/$HOST\2/g" \
-		/var/www/bigbluebutton/client/conf/config.xml
+    # Extract the chrome store URL before updating config.xml. We will be able to restore it.
+    chromeExtensionLinkURL=$(cat /var/www/bigbluebutton/client/conf/config.xml | sed -n '/chromeExtensionLink/{s/.*https*:\/\///;s/\/.*//;p}')
 
-	if ! echo "$chromeExtensionLinkURL" | grep -q '""'; then
-		$SUDO sed -i "s/chromeExtensionLink=\"https:\/\/[^\/]*/chromeExtensionLink=\"https:\/\/$chromeExtensionLinkURL/g" \
-			/var/www/bigbluebutton/client/conf/config.xml
-	fi
+    echo "Assigning $HOST for http[s]:// in /var/www/bigbluebutton/client/conf/config.xml"
+    $SUDO sed -i "s/http[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/$PROTOCOL:\/\/$HOST\2/g" \
+    /var/www/bigbluebutton/client/conf/config.xml
 
-	echo "Assigning $HOST for publishURI in /var/www/bigbluebutton/client/conf/config.xml"
-	$SUDO sed -i "s/publishURI=\"[^\"]*\"/publishURI=\"$HOST\"/" /var/www/bigbluebutton/client/conf/config.xml
+    if ! echo "$chromeExtensionLinkURL" | grep -q '""'; then
+        $SUDO sed -i "s/chromeExtensionLink=\"https:\/\/[^\/]*/chromeExtensionLink=\"https:\/\/$chromeExtensionLinkURL/g" \
+        /var/www/bigbluebutton/client/conf/config.xml
+    fi
 
-	#
-	# Update configuration for BigBlueButton web app
-	#
-	echo "Assigning $HOST for web application URL in ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties"
+    echo "Assigning $HOST for publishURI in /var/www/bigbluebutton/client/conf/config.xml"
+    $SUDO sed -i "s/publishURI=\"[^\"]*\"/publishURI=\"$HOST\"/" /var/www/bigbluebutton/client/conf/config.xml
 
-	$SUDO sed -i "s/bigbluebutton.web.serverURL=http[s]*:\/\/.*/bigbluebutton.web.serverURL=$PROTOCOL:\/\/$HOST/g" \
-				${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties
+    #
+    # Update configuration for BigBlueButton web app
+    #
+    echo "Assigning $HOST for web application URL in ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties"
 
-	$SUDO sed -i "s/screenshareRtmpServer=.*/screenshareRtmpServer=$HOST/g" \
-				${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties
+    $SUDO sed -i "s/bigbluebutton.web.serverURL=http[s]*:\/\/.*/bigbluebutton.web.serverURL=$PROTOCOL:\/\/$HOST/g" \
+            ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties
 
-	change_var_value /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties streamBaseUrl rtmp://$HOST/screenshare
-	change_var_value /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties jnlpUrl $PROTOCOL://$HOST/screenshare
-	change_var_value /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties jnlpFile $PROTOCOL://$HOST/screenshare/screenshare.jnlp
+    $SUDO sed -i "s/screenshareRtmpServer=.*/screenshareRtmpServer=$HOST/g" \
+            ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties
 
-	if ! grep -q server_names_hash_bucket_size /etc/nginx/nginx.conf; then
-		$SUDO sed -i "s/gzip  on;/gzip  on;\n    server_names_hash_bucket_size  64;/g" /etc/nginx/nginx.conf
-	fi
+    change_var_value /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties streamBaseUrl rtmp://$HOST/screenshare
+    change_var_value /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties jnlpUrl $PROTOCOL://$HOST/screenshare
+    change_var_value /usr/share/red5/webapps/screenshare/WEB-INF/screenshare.properties jnlpFile $PROTOCOL://$HOST/screenshare/screenshare.jnlp
 
-        #
-        # Update bbb-apps-akka
-        #
-        echo "Assigning $HOST for web application URL in /usr/share/bbb-apps-akka/conf/application.conf"
-
-        if [ -f /usr/share/bbb-apps-akka/conf/application.conf ]; then
-                sed -i  "s/bbbWebAPI[ ]*=[ ]*\"[^\"]*\"/bbbWebAPI=\"${PROTOCOL}:\/\/$HOST\/bigbluebutton\/api\"/g" \
-                        /usr/share/bbb-apps-akka/conf/application.conf
-                sed -i "s/deskshareip[ ]*=[ ]*\"[^\"]*\"/deskshareip=\"$HOST\"/g" \
-                        /usr/share/bbb-apps-akka/conf/application.conf
-		# Fix to ensure application.conf has the latest shared secret
-                SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | grep securitySalt | cut -d= -f2);
-                sed -i "s/sharedSecret[ ]*=[ ]*\"[^\"]*\"/sharedSecret=\"$SECRET\"/g" \
-                        /usr/share/bbb-apps-akka/conf/application.conf
-        fi
+    if ! grep -q server_names_hash_bucket_size /etc/nginx/nginx.conf; then
+        $SUDO sed -i "s/gzip  on;/gzip  on;\n    server_names_hash_bucket_size  64;/g" /etc/nginx/nginx.conf
+    fi
 
-        #
-        # Update api demos
-        #
-        if [ -f ${TOMCAT_DIR}/webapps/demo/bbb_api_conf.jsp ]; then
-                echo "Assigning $HOST for api demos in ${TOMCAT_DIR}/webapps/demo/bbb_api_conf.jsp"
-                $SUDO sed -i "s/BigBlueButtonURL = \"http[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/BigBlueButtonURL = \"$PROTOCOL:\/\/$HOST\2/g" \
-                        ${TOMCAT_DIR}/webapps/demo/bbb_api_conf.jsp
-        fi
+    #
+    # Update bbb-apps-akka
+    #
+    echo "Assigning $HOST for web application URL in /usr/share/bbb-apps-akka/conf/application.conf"
+
+    if [ -f /usr/share/bbb-apps-akka/conf/application.conf ]; then
+        sed -i  "s/bbbWebAPI[ ]*=[ ]*\"[^\"]*\"/bbbWebAPI=\"${PROTOCOL}:\/\/$HOST\/bigbluebutton\/api\"/g" \
+                /usr/share/bbb-apps-akka/conf/application.conf
+        sed -i "s/deskshareip[ ]*=[ ]*\"[^\"]*\"/deskshareip=\"$HOST\"/g" \
+                /usr/share/bbb-apps-akka/conf/application.conf
+        # Fix to ensure application.conf has the latest shared secret
+        SECRET=$(cat ${SERVLET_DIR}/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | grep securitySalt | cut -d= -f2);
+        sed -i "s/sharedSecret[ ]*=[ ]*\"[^\"]*\"/sharedSecret=\"$SECRET\"/g" \
+                /usr/share/bbb-apps-akka/conf/application.conf
+    fi
 
-	
-
-	if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
-		echo "Assigning $HOST for LTI integration in ${LTI_DIR}/WEB-INF/classes/lti-config.properties"
-		# We don't wat to guess on http/https as the lti endpoint may be a different BigBlueButton server
-        	sed -i "s/bigbluebuttonURL=http:\/\/.*/bigbluebuttonURL=http:\/\/$HOST\/bigbluebutton/g" \
-                	${LTI_DIR}/WEB-INF/classes/lti-config.properties
-        	sed -i "s/bigbluebuttonURL=https:\/\/.*/bigbluebuttonURL=https:\/\/$HOST\/bigbluebutton/g" \
-                	${LTI_DIR}/WEB-INF/classes/lti-config.properties
-        	sed -i "s/ltiEndPoint=.*/ltiEndPoint=$HOST/g" \
-                	${LTI_DIR}/WEB-INF/classes/lti-config.properties
-	fi
-
-
-	if [ -f /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml ]; then
-		echo "Assigning $HOST for record and playback in /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml"
-		change_yml_value /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml $redis_host playback_host $HOST
-	fi
-
-        echo -n "Assigning $HOST for playback of recordings: "
-        for metadata in $(find /var/bigbluebutton/published -name metadata.xml); do
-                echo -n "."
-		# Ensure we update both types of URLs
-                sed -i "/<link>/{s/http:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/http:\/\/$HOST\/playback\/$type\2/g}" $metadata
-                sed -i "/<link>/{s/https:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/https:\/\/$HOST\/playback\/$type\2/g}" $metadata
-        done
+    #
+    # Update api demos
+    #
+    if [ -f ${TOMCAT_DIR}/webapps/demo/bbb_api_conf.jsp ]; then
+        echo "Assigning $HOST for api demos in ${TOMCAT_DIR}/webapps/demo/bbb_api_conf.jsp"
+        $SUDO sed -i "s/BigBlueButtonURL = \"http[s]*:\/\/\([^\"\/]*\)\([\"\/]\)/BigBlueButtonURL = \"$PROTOCOL:\/\/$HOST\2/g" \
+                ${TOMCAT_DIR}/webapps/demo/bbb_api_conf.jsp
+    fi
 
-        for metadata in $(find /var/bigbluebutton/unpublished -name metadata.xml); do
-                echo -n "."
-		# Ensure we update both types of URLs
-                sed -i "/<link>/{s/http:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/http:\/\/$HOST\/playback\/$type\2/g}" $metadata
-                sed -i "/<link>/{s/https:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/https:\/\/$HOST\/playback\/$type\2/g}" $metadata
-        done
-	echo 
 
-	if [ -f /var/www/bigbluebutton/check/conf/config.xml ]; then
-		echo "Assigning $HOST for client self check to /var/www/bigbluebutton/check/conf/config.xml"
-		sed -i "s/rtmp[s]*:\/\/\([^\"\/]*\)\//$PROTOCOL_RTMP:\/\/$HOST\//g" /var/www/bigbluebutton/check/conf/config.xml
-		sed -i "s/rtmpt:\/\/\([^\"\/]*\)\//rtmpt:\/\/$HOST\//g" /var/www/bigbluebutton/check/conf/config.xml
-	fi
 
-        #
-        # Update HTML5 client
-        #
-	if [ -f $HTML5_CONFIG_OLD ]; then
-        	WS=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | sed 's/https/wss/g' | sed s'/http/ws/g')
-        	sed -i "s|\"wsUrl.*|\"wsUrl\": \"$WS/bbb-webrtc-sfu\",|g" $HTML5_CONFIG_OLD
-	fi
+    if [ -f ${LTI_DIR}/WEB-INF/classes/lti-config.properties ]; then
+        echo "Assigning $HOST for LTI integration in ${LTI_DIR}/WEB-INF/classes/lti-config.properties"
+        # We don't wat to guess on http/https as the lti endpoint may be a different BigBlueButton server
+        sed -i "s/bigbluebuttonURL=http:\/\/.*/bigbluebuttonURL=http:\/\/$HOST\/bigbluebutton/g" \
+                ${LTI_DIR}/WEB-INF/classes/lti-config.properties
+        sed -i "s/bigbluebuttonURL=https:\/\/.*/bigbluebuttonURL=https:\/\/$HOST\/bigbluebutton/g" \
+                ${LTI_DIR}/WEB-INF/classes/lti-config.properties
+        sed -i "s/ltiEndPoint=.*/ltiEndPoint=$HOST/g" \
+                ${LTI_DIR}/WEB-INF/classes/lti-config.properties
+    fi
 
-	if [ -f $HTML5_CONFIG ]; then
-        	WS=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | sed 's/https/wss/g' | sed s'/http/ws/g')
 
-		change_yml_value $HTML5_CONFIG wsUrl "$WS/bbb-webrtc-sfu"
+    if [ -f /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml ]; then
+        echo "Assigning $HOST for record and playback in /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml"
+        change_yml_value /usr/local/bigbluebutton/core/scripts/bigbluebutton.yml $redis_host playback_host $HOST
+    fi
 
-                if [ -f $KURENTO_CONFIG ]; then
-                  yq w -i $KURENTO_CONFIG kurento[0].url "ws://$HOST:8888/kurento"
-                  chown bigbluebutton:bigbluebutton $KURENTO_CONFIG
-                fi
-	fi
+    echo -n "Assigning $HOST for playback of recordings: "
+    for metadata in $(find /var/bigbluebutton/published -name metadata.xml); do
+        echo -n "."
+        # Ensure we update both types of URLs
+        sed -i "/<link>/{s/http:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/http:\/\/$HOST\/playback\/$type\2/g}" $metadata
+        sed -i "/<link>/{s/https:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/https:\/\/$HOST\/playback\/$type\2/g}" $metadata
+    done
+
+    for metadata in $(find /var/bigbluebutton/unpublished -name metadata.xml); do
+        echo -n "."
+        # Ensure we update both types of URLs
+        sed -i "/<link>/{s/http:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/http:\/\/$HOST\/playback\/$type\2/g}" $metadata
+        sed -i "/<link>/{s/https:\/\/\([^\"\/]*\)\/playback\/$type\([^<]\)/https:\/\/$HOST\/playback\/$type\2/g}" $metadata
+    done
+    echo
+
+    if [ -f /var/www/bigbluebutton/check/conf/config.xml ]; then
+        echo "Assigning $HOST for client self check to /var/www/bigbluebutton/check/conf/config.xml"
+        sed -i "s/rtmp[s]*:\/\/\([^\"\/]*\)\//$PROTOCOL_RTMP:\/\/$HOST\//g" /var/www/bigbluebutton/check/conf/config.xml
+        sed -i "s/rtmpt:\/\/\([^\"\/]*\)\//rtmpt:\/\/$HOST\//g" /var/www/bigbluebutton/check/conf/config.xml
+    fi
 
-        #
-        # Update thumbnail links
-        #
-        find /var/bigbluebutton/published -name metadata.xml -exec \
-               sed -i "s/<image width=\"\([0-9]*\)\" height=\"\([0-9]*\)\" alt=\"\([^\"]*\)\">\(http[s]*\):\/\/[^\/]*\/\(.*\)/<image width=\"\1\" height=\"\2\" alt=\"\3\">\4:\/\/$HOST\/\5/g" \
-                '{}' \;
+    #
+    # Update HTML5 client
+    #
+    if [ -f $HTML5_CONFIG_OLD ]; then
+        WS=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | sed 's/https/wss/g' | sed s'/http/ws/g')
+        sed -i "s|\"wsUrl.*|\"wsUrl\": \"$WS/bbb-webrtc-sfu\",|g" $HTML5_CONFIG_OLD
+    fi
+
+    if [ -f $HTML5_CONFIG ]; then
+        WS=$(cat $SERVLET_DIR/WEB-INF/classes/bigbluebutton.properties | grep -v '#' | sed -n '/^bigbluebutton.web.serverURL/{s/.*=//;p}' | sed 's/https/wss/g' | sed s'/http/ws/g')
 
-	echo "Restarting the BigBlueButton $BIGBLUEBUTTON_RELEASE ..."
-	stop_bigbluebutton
-	echo
-	start_bigbluebutton
+        yq w -i $HTML5_CONFIG public.kurento.wsUrl "$WS/bbb-webrtc-sfu"
+        yq w -i $HTML5_CONFIG public.note.url      "$PROTOCOL://$HOST/pad"
+        chown meteor:meteor $HTML5_CONFIG
 
-	exit 0
+        if [ -f $KURENTO_CONFIG ]; then
+            yq w -i $KURENTO_CONFIG kurento[0].url "ws://$HOST:8888/kurento"
+            chown bigbluebutton:bigbluebutton $KURENTO_CONFIG
+        fi
+    fi
+
+    #
+    # Update thumbnail links
+    #
+    find /var/bigbluebutton/published -name metadata.xml -exec \
+           sed -i "s/<image width=\"\([0-9]*\)\" height=\"\([0-9]*\)\" alt=\"\([^\"]*\)\">\(http[s]*\):\/\/[^\/]*\/\(.*\)/<image width=\"\1\" height=\"\2\" alt=\"\3\">\4:\/\/$HOST\/\5/g" \
+           '{}' \;
+
+    echo "Restarting the BigBlueButton $BIGBLUEBUTTON_RELEASE ..."
+    stop_bigbluebutton
+    echo
+    start_bigbluebutton
+
+    exit 0
 fi
 
 
 if [ $RESTART ]; then
-	need_root
-	check_configuration
-	
-	echo "Restarting BigBlueButton $BIGBLUEBUTTON_RELEASE ..."
-
-	stop_bigbluebutton
-	start_bigbluebutton
-	check_state
+    need_root
+    check_configuration
+
+    echo "Restarting BigBlueButton $BIGBLUEBUTTON_RELEASE ..."
+
+    stop_bigbluebutton
+    start_bigbluebutton
+    check_state
 fi
 
 if [ $CLEAN ]; then
-	need_root
-	check_configuration
-	
-	echo "Restarting BigBlueButton $BIGBLUEBUTTON_RELEASE (and cleaning out all log files) ..."
-
-	stop_bigbluebutton
-
-	#
-	# Clean log files
-	#
-
-	echo " ... cleaning log files"
-	rm -f /var/log/bigbluebutton/bbb-web.log*
-	rm -f /var/log/bigbluebutton/*.log
-
-	rm -f /opt/freeswitch/var/log/freeswitch/*.log
-
-	#
-	# Clean out the log files for record and playback
-	#
-	rm -f /var/log/bigbluebutton/bbb-rap-worker.log*
-	rm -f /var/log/bigbluebutton/archive.log*
-	if [ -d /var/log/bigbluebutton/html5 ]; then
-		rm -f /var/log/bigbluebutton/html5/*
-	fi
-	
-	if [ -d /var/log/bigbluebutton/podcast ]; then
-		rm -f /var/log/bigbluebutton/podcast/*
-	fi
-	
-	if [ -d /var/log/bigbluebutton/presentation ]; then
-		rm -f /var/log/bigbluebutton/presentation/*
-	fi
-	
-	if [ -d /var/log/bigbluebutton/screenshare ]; then
-		rm -f /var/log/bigbluebutton/screenshare/*
-	fi
-		
-	
-	if [ $RED5_DIR ]; then
-		rm -rf $RED5_DIR/log/*
-	fi
-
-	if [ $SERVLET_LOGS ]; then
-		rm -rf $SERVLET_LOGS/*
-	fi
-
-	rm -rf /var/log/nginx/*
-
-        #if [ $DISTRO == "ubuntu" ]; then
-	#  mv /var/log/syslog /tmp/syslog.$$
-	#  echo "" > /var/log/syslog
-	#  chown syslog:adm /var/log/syslog
-        #fi
-
-	if [ -d /var/log/bbb-fsesl-akka ]; then
-		rm -f /var/log/bbb-fsesl-akka/*
-        fi
+    need_root
+    check_configuration
 
-	if [ -d /var/log/bbb-apps-akka ]; then
-		rm -f /var/log/bbb-apps-akka/*
-        fi
+    echo "Restarting BigBlueButton $BIGBLUEBUTTON_RELEASE (and cleaning out all log files) ..."
+
+    stop_bigbluebutton
 
-	if [ -d /var/log/bbb-transcode-akka ]; then
-		rm -f /var/log/bbb-transcode-akka/*
-	fi
+    #
+    # Clean log files
+    #
 
-	if [ -d /var/log/bbb-webrtc-sfu ]; then
-		rm -f /var/log/bbb-webrtc-sfu/*
-	fi
-	
-	if [ -d /var/log/redis ]; then
-		rm -f /var/log/redis/*
-	fi
+    echo " ... cleaning log files"
+    rm -f /var/log/bigbluebutton/*.log
 
-	if [ -d /var/log/mongodb ]; then
-		rm -f /var/log/mongodb/*
-	fi
+    rm -f /opt/freeswitch/var/log/freeswitch/*.log
 
-	if [ -d /var/log/kurento-media-server ]; then
-		rm -f /var/log/kurento-media-server/*
-	fi
+    #
+    # Clean out the log files for record and playback
+    #
+    rm -f /var/log/bigbluebutton/bbb-rap-worker.log*
+    rm -f /var/log/bigbluebutton/archive.log*
+    if [ -d /var/log/bigbluebutton/html5 ]; then
+        rm -f /var/log/bigbluebutton/html5/*
+    fi
+
+    if [ -d /var/log/bigbluebutton/podcast ]; then
+        rm -f /var/log/bigbluebutton/podcast/*
+    fi
+
+    if [ -d /var/log/bigbluebutton/presentation ]; then
+        rm -f /var/log/bigbluebutton/presentation/*
+    fi
+
+    if [ -d /var/log/bigbluebutton/screenshare ]; then
+        rm -f /var/log/bigbluebutton/screenshare/*
+    fi
 
-	start_bigbluebutton
-	check_state
+
+    if [[ $RED5_DIR ]]; then
+        rm -rf $RED5_DIR/log/*
+    fi
+
+    if [[ $SERVLET_LOGS ]]; then
+        rm -rf $SERVLET_LOGS/*
+    fi
+
+    rm -rf /var/log/nginx/*
+
+    #if [ $DISTRO == "ubuntu" ]; then
+    #  mv /var/log/syslog /tmp/syslog.$$
+    #  echo "" > /var/log/syslog
+    #  chown syslog:adm /var/log/syslog
+    #fi
+
+    log_dirs="bbb-fsesl-akka bbb-apps-akka bbb-transcode-akka bbb-webrtc-sfu redis mongodb kurento-media-server"
+
+    for log_dir in $log_dirs; do
+        if [ -d "/var/log/$log_dir" ]; then
+            rm -f "/var/log/$log_dir/*"
+        fi
+    done
+
+    start_bigbluebutton
+    check_state
 fi
 
 if [ $NETWORK ]; then
-	netstat -ant | egrep ":1935|:80\ " | egrep -v ":::|0.0.0.0" > /tmp/t_net
-	REMOTE=$(cat /tmp/t_net | cut -c 45-68 | cut -d ":" -f1 | sort | uniq)
-
-	if [ "$REMOTE" != "" ]; then
-        	echo -e "netstat\t\t\t80\t1935"
-        	for IP in $REMOTE ; do
-			PORT_1935=$(cat /tmp/t_net | grep :1935 | cut -c 45-68 | cut -d ":" -f1 | grep $IP | wc -l)
-			PORT_80=$(cat /tmp/t_net | grep :80 | cut -c 45-68 | cut -d ":" -f1 | grep $IP | wc -l )
-
-           	echo -e "$IP\t\t$PORT_80\t$PORT_1935"
-        	done
-	fi
+    netstat -ant | egrep ":1935|:80\ " | egrep -v ":::|0.0.0.0" > /tmp/t_net
+    REMOTE=$(cat /tmp/t_net | cut -c 45-68 | cut -d ":" -f1 | sort | uniq)
+
+    if [ "$REMOTE" != "" ]; then
+        echo -e "netstat\t\t\t80\t1935"
+        for IP in $REMOTE ; do
+            PORT_1935=$(cat /tmp/t_net | grep :1935 | cut -c 45-68 | cut -d ":" -f1 | grep $IP | wc -l)
+            PORT_80=$(cat /tmp/t_net | grep :80 | cut -c 45-68 | cut -d ":" -f1 | grep $IP | wc -l )
+
+            echo -e "$IP\t\t$PORT_80\t$PORT_1935"
+        done
+    fi
 fi
 
 if [ $WATCH ]; then
-	need_root
-	watch -n 2 "top -n 1 -b | head -n 5; echo; bbb-conf --network; bbb-conf --debug"
+    need_root
+    watch -n 2 "top -n 1 -b | head -n 5; echo; bbb-conf --network; bbb-conf --debug"
 fi
diff --git a/bigbluebutton-html5/.gitignore b/bigbluebutton-html5/.gitignore
index 535d3f9662258cbd3f8fd64048419b9a2ee85907..56e914594c2d02c8dfede9e22cca61a802abd6e4 100755
--- a/bigbluebutton-html5/.gitignore
+++ b/bigbluebutton-html5/.gitignore
@@ -1,17 +1,5 @@
-app/packages
-app/build/
+.dbshell
 npm-debug.log
 node_modules/
 .meteor/dev_bundle
 
-private/config/server/*
-!private/config/server/app.yaml
-!private/config/server/redis.yaml
-!private/config/server/shell.yaml
-
-private/config/development/server/*
-!private/config/development/server/log.yaml
-
-private/config/production/server/*
-!private/config/production/server/log.yaml
-!private/config/production/server/shell.yaml
diff --git a/bigbluebutton-html5/imports/api/breakouts/server/publishers.js b/bigbluebutton-html5/imports/api/breakouts/server/publishers.js
index 41dade1937c86f23f7a4d0f1d90a0b012305c31e..73c427f421c2cb54d8a6aad5c225a82feabf34f0 100755
--- a/bigbluebutton-html5/imports/api/breakouts/server/publishers.js
+++ b/bigbluebutton-html5/imports/api/breakouts/server/publishers.js
@@ -1,8 +1,9 @@
 import { Meteor } from 'meteor/meteor';
 import Breakouts from '/imports/api/breakouts';
+import Users from '/imports/api/users';
 import Logger from '/imports/startup/server/logger';
 
-function breakouts(credentials, moderator) {
+function breakouts(credentials, moderator = false) {
   const {
     meetingId,
     requesterUserId,
@@ -10,14 +11,17 @@ function breakouts(credentials, moderator) {
   Logger.debug(`Publishing Breakouts for ${meetingId} ${requesterUserId}`);
 
   if (moderator) {
-    const presenterSelector = {
-      $or: [
-        { parentMeetingId: meetingId },
-        { breakoutId: meetingId },
-      ],
-    };
+    const User = Users.findOne({ userId: requesterUserId });
+    if (!!User && User.moderator) {
+      const presenterSelector = {
+        $or: [
+          { parentMeetingId: meetingId },
+          { breakoutId: meetingId },
+        ],
+      };
 
-    return Breakouts.find(presenterSelector);
+      return Breakouts.find(presenterSelector);
+    }
   }
 
   const selector = {
diff --git a/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js b/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js
index acc656abb290929dfe3bfa7c7c8ac4a57c304a93..e5aeea22f9dc408e00d0f97153ded1015bbf8011 100644
--- a/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js
+++ b/bigbluebutton-html5/imports/api/group-chat-msg/server/eventHandlers.js
@@ -2,8 +2,9 @@ import RedisPubSub from '/imports/startup/server/redis';
 import handleGroupChatsMsgs from './handlers/groupChatsMsgs';
 import handleGroupChatMsgBroadcast from './handlers/groupChatMsgBroadcast';
 import handleClearPublicGroupChat from './handlers/clearPublicGroupChat';
+import { processForHTML5ServerOnly } from '/imports/api/common/server/helpers';
 
-RedisPubSub.on('GetGroupChatMsgsRespMsg', handleGroupChatsMsgs);
+RedisPubSub.on('GetGroupChatMsgsRespMsg', processForHTML5ServerOnly(handleGroupChatsMsgs));
 RedisPubSub.on('GroupChatMessageBroadcastEvtMsg', handleGroupChatMsgBroadcast);
 RedisPubSub.on('ClearPublicChatHistoryEvtMsg', handleClearPublicGroupChat);
 RedisPubSub.on('SyncGetGroupChatMsgsRespMsg', handleGroupChatsMsgs);
diff --git a/bigbluebutton-html5/imports/api/group-chat/server/eventHandlers.js b/bigbluebutton-html5/imports/api/group-chat/server/eventHandlers.js
index 8d9b08f80e0930e726c9ed831c4a605fc44c3e33..c676a06732ad0516ec9cbac3c154e4d051c46f4d 100644
--- a/bigbluebutton-html5/imports/api/group-chat/server/eventHandlers.js
+++ b/bigbluebutton-html5/imports/api/group-chat/server/eventHandlers.js
@@ -2,8 +2,9 @@ import RedisPubSub from '/imports/startup/server/redis';
 import handleGroupChats from './handlers/groupChats';
 import handleGroupChatCreated from './handlers/groupChatCreated';
 import handleGroupChatDestroyed from './handlers/groupChatDestroyed';
+import { processForHTML5ServerOnly } from '/imports/api/common/server/helpers';
 
-RedisPubSub.on('GetGroupChatsRespMsg', handleGroupChats);
+RedisPubSub.on('GetGroupChatsRespMsg', processForHTML5ServerOnly(handleGroupChats));
 RedisPubSub.on('GroupChatCreatedEvtMsg', handleGroupChatCreated);
 RedisPubSub.on('GroupChatDestroyedEvtMsg', handleGroupChatDestroyed);
 RedisPubSub.on('SyncGetGroupChatsRespMsg', handleGroupChats);
diff --git a/bigbluebutton-html5/imports/api/meetings/server/publishers.js b/bigbluebutton-html5/imports/api/meetings/server/publishers.js
index 9bd0bf3ae8e2e57e236099e0f95b51c4c69a37c2..b263a5eb3e8bad28fc2deeadb73f1d035d1d4ecc 100755
--- a/bigbluebutton-html5/imports/api/meetings/server/publishers.js
+++ b/bigbluebutton-html5/imports/api/meetings/server/publishers.js
@@ -1,9 +1,10 @@
 import { Meteor } from 'meteor/meteor';
 import { check } from 'meteor/check';
 import Meetings from '/imports/api/meetings';
+import Users from '/imports/api/users';
 import Logger from '/imports/startup/server/logger';
 
-function meetings(credentials) {
+function meetings(credentials, isModerator = false) {
   const { meetingId, requesterUserId, requesterToken } = credentials;
 
   check(meetingId, String);
@@ -15,13 +16,19 @@ function meetings(credentials) {
   const selector = {
     $or: [
       { meetingId },
-      {
-        'meetingProp.isBreakout': true,
-        'breakoutProps.parentId': meetingId,
-      },
     ],
   };
 
+  if (isModerator) {
+    const User = Users.findOne({ userId: requesterUserId });
+    if (!!User && User.moderator) {
+      selector.$or.push({
+        'meetingProp.isBreakout': true,
+        'breakoutProps.parentId': meetingId,
+      });
+    }
+  }
+
   const options = {
     fields: {
       password: false,
diff --git a/bigbluebutton-html5/imports/api/screenshare/server/modifiers/clearScreenshare.js b/bigbluebutton-html5/imports/api/screenshare/server/modifiers/clearScreenshare.js
index 21e2353f689def41992920e5ae72b8138109d39a..0b7265a69716656b8ef3ac7c5407fc2973ef9acc 100644
--- a/bigbluebutton-html5/imports/api/screenshare/server/modifiers/clearScreenshare.js
+++ b/bigbluebutton-html5/imports/api/screenshare/server/modifiers/clearScreenshare.js
@@ -2,9 +2,16 @@ import Logger from '/imports/startup/server/logger';
 import Screenshare from '/imports/api/screenshare';
 
 export default function clearScreenshare(meetingId, screenshareConf) {
+  const cb = (err) => {
+    if (err) {
+      return Logger.error(`removing screenshare to collection: ${err}`);
+    }
+
+    return Logger.info(`removed screenshare meetingId=${meetingId} id=${screenshareConf}`);
+  };
+
   if (meetingId && screenshareConf) {
-    return Screenshare.remove({ meetingId, 'screenshare.screenshareConf': screenshareConf }, Logger.info(`Cleared Screenshare (${meetingId}) , (${screenshareConf})`));
+    return Screenshare.remove({ meetingId, 'screenshare.screenshareConf': screenshareConf }, cb);
   }
-
-  return Screenshare.remove({}, Logger.info('Cleared Screenshare (all)'));
+  return Screenshare.remove({}, cb);
 }
diff --git a/bigbluebutton-html5/imports/api/users/server/eventHandlers.js b/bigbluebutton-html5/imports/api/users/server/eventHandlers.js
index 8889f998475338980db3f80baa938c6d38c7a218..7af6c464e6488eaf1a69a87f536ec872d1ad30e6 100644
--- a/bigbluebutton-html5/imports/api/users/server/eventHandlers.js
+++ b/bigbluebutton-html5/imports/api/users/server/eventHandlers.js
@@ -17,4 +17,4 @@ RedisPubSub.on('UserEmojiChangedEvtMsg', handleEmojiStatus);
 RedisPubSub.on('SyncGetUsersMeetingRespMsg', handleGetUsers);
 RedisPubSub.on('UserEjectedFromMeetingEvtMsg', handleUserEjected);
 RedisPubSub.on('UserRoleChangedEvtMsg', handleChangeRole);
-RedisPubSub.on('UserInactivityInspectMsg', handleUserInactivityInspect);
\ No newline at end of file
+RedisPubSub.on('UserInactivityInspectMsg', handleUserInactivityInspect);
diff --git a/bigbluebutton-html5/imports/api/users/server/handlers/userEjected.js b/bigbluebutton-html5/imports/api/users/server/handlers/userEjected.js
index 56ee89ae7e1582086b3e65cddf766dbc4eb4a45a..95568f555fc2eced0027f077873afbcd26861e43 100644
--- a/bigbluebutton-html5/imports/api/users/server/handlers/userEjected.js
+++ b/bigbluebutton-html5/imports/api/users/server/handlers/userEjected.js
@@ -1,7 +1,8 @@
 import userEjected from '../modifiers/userEjected';
 
-export default function handleEjectedUser({ header }) {
+export default function handleEjectedUser({ header, body }) {
   const { meetingId, userId } = header;
+  const { reasonCode } = body;
 
-  return userEjected(meetingId, userId);
+  return userEjected(meetingId, userId, reasonCode);
 }
diff --git a/bigbluebutton-html5/imports/api/users/server/modifiers/userEjected.js b/bigbluebutton-html5/imports/api/users/server/modifiers/userEjected.js
index ebca105c2ba4b5c6acb2e7e61f01a49966435459..cbe59a0ea5cd129a6bd0ab4375350627689eca52 100644
--- a/bigbluebutton-html5/imports/api/users/server/modifiers/userEjected.js
+++ b/bigbluebutton-html5/imports/api/users/server/modifiers/userEjected.js
@@ -2,9 +2,10 @@ import { check } from 'meteor/check';
 import Logger from '/imports/startup/server/logger';
 import Users from '/imports/api/users';
 
-export default function userEjected(meetingId, userId) {
+export default function userEjected(meetingId, userId, ejectedReason) {
   check(meetingId, String);
   check(userId, String);
+  check(ejectedReason, String);
 
   const selector = {
     meetingId,
@@ -14,6 +15,7 @@ export default function userEjected(meetingId, userId) {
   const modifier = {
     $set: {
       ejected: true,
+      ejectedReason,
     },
   };
 
@@ -23,7 +25,7 @@ export default function userEjected(meetingId, userId) {
     }
 
     if (numChanged) {
-      return Logger.info(`Ejected user id=${userId} meeting=${meetingId}`);
+      return Logger.info(`Ejected user id=${userId} meeting=${meetingId} reason=${ejectedReason}`);
     }
 
     return null;
diff --git a/bigbluebutton-html5/imports/api/users/server/publishers.js b/bigbluebutton-html5/imports/api/users/server/publishers.js
index c6692046f59ef930feb859b409687afa7d77234c..e26190a1f1d9cda67948d4514883c16df8924bc4 100644
--- a/bigbluebutton-html5/imports/api/users/server/publishers.js
+++ b/bigbluebutton-html5/imports/api/users/server/publishers.js
@@ -57,11 +57,14 @@ function users(credentials, isModerator = false) {
   };
 
   if (isModerator) {
-    selector.$or.push({
-      'breakoutProps.isBreakoutUser': true,
-      'breakoutProps.parentId': meetingId,
-      connectionStatus: 'online',
-    });
+    const User = Users.findOne({ userId: requesterUserId });
+    if (!!User && User.moderator) {
+      selector.$or.push({
+        'breakoutProps.isBreakoutUser': true,
+        'breakoutProps.parentId': meetingId,
+        connectionStatus: 'online',
+      });
+    }
   }
 
   const options = {
diff --git a/bigbluebutton-html5/imports/api/voice-users/server/modifiers/updateVoiceUser.js b/bigbluebutton-html5/imports/api/voice-users/server/modifiers/updateVoiceUser.js
index 518010b0c08903ea8a9a2889f96c3e2d0d78e263..226a4087fc4426ac935dfa3166f48be8423ad690 100644
--- a/bigbluebutton-html5/imports/api/voice-users/server/modifiers/updateVoiceUser.js
+++ b/bigbluebutton-html5/imports/api/voice-users/server/modifiers/updateVoiceUser.js
@@ -33,7 +33,7 @@ export default function updateVoiceUser(meetingId, voiceUser) {
       return Logger.error(`Update voiceUser=${intId}: ${err}`);
     }
 
-    return Logger.info(`Update voiceUser=${intId} meeting=${meetingId}`);
+    return Logger.debug(`Update voiceUser=${intId} meeting=${meetingId}`);
   };
 
   return VoiceUsers.update(selector, modifier, cb);
diff --git a/bigbluebutton-html5/imports/startup/client/base.jsx b/bigbluebutton-html5/imports/startup/client/base.jsx
index 72c639cdfcc90430a0cfadcd96111ba71f32125f..4faee3bb804283944286d3df07ee62c357506f69 100755
--- a/bigbluebutton-html5/imports/startup/client/base.jsx
+++ b/bigbluebutton-html5/imports/startup/client/base.jsx
@@ -144,6 +144,8 @@ class Base extends Component {
     const { updateLoadingState } = this;
     const stateControls = { updateLoadingState };
 
+    const { ejected } = this.props;
+
     const { loading, meetingExisted } = this.state;
 
     const codeError = Session.get('codeError');
@@ -152,7 +154,13 @@ class Base extends Component {
       meetingExist,
     } = this.props;
 
-    if (meetingExisted && !meetingExist) {
+    if (ejected && ejected.ejectedReason) {
+      const { ejectedReason } = ejected;
+      AudioManager.exitAudio();
+      return (<MeetingEnded code={ejectedReason} />);
+    }
+
+    if ((meetingExisted && !meetingExist)) {
       AudioManager.exitAudio();
       return (<MeetingEnded code={Session.get('codeError')} />);
     }
@@ -201,6 +209,7 @@ const BaseContainer = withTracker(() => {
   const { credentials, loggedIn } = Auth;
   const { meetingId, requesterUserId } = credentials;
   let breakoutRoomSubscriptionHandler;
+  let meetingModeratorSubscriptionHandler;
   let userSubscriptionHandler;
 
   const subscriptionErrorHandler = {
@@ -238,6 +247,7 @@ const BaseContainer = withTracker(() => {
     // override meteor subscription to verify if is moderator
     userSubscriptionHandler = Meteor.subscribe('users', credentials, mappedUser.isModerator, subscriptionErrorHandler);
     breakoutRoomSubscriptionHandler = Meteor.subscribe('breakouts', credentials, mappedUser.isModerator, subscriptionErrorHandler);
+    breakoutRoomSubscriptionHandler = Meteor.subscribe('meetings', credentials, mappedUser.isModerator, subscriptionErrorHandler);
   }
 
   const annotationsHandler = Meteor.subscribe('annotations', credentials, {
@@ -265,6 +275,7 @@ const BaseContainer = withTracker(() => {
     groupChatMessageHandler,
     userSubscriptionHandler,
     breakoutRoomSubscriptionHandler,
+    meetingModeratorSubscriptionHandler,
     animations,
     meetingExist: !!Meetings.find({ meetingId }).count(),
     User,
diff --git a/bigbluebutton-html5/imports/ui/components/activity-check/component.jsx b/bigbluebutton-html5/imports/ui/components/activity-check/component.jsx
index fc182c17eced6cfa551e71a90b7be7515bb17fc5..ce8e41ec6f43e984920d84081ee1b406b9e52bee 100644
--- a/bigbluebutton-html5/imports/ui/components/activity-check/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/activity-check/component.jsx
@@ -42,9 +42,11 @@ class ActivityCheck extends Component {
 
     this.stopRemainingTime = this.stopRemainingTime.bind(this);
     this.updateRemainingTime = this.updateRemainingTime.bind(this);
+    this.playAudioAlert = this.playAudioAlert.bind(this);
   }
 
   componentDidMount() {
+    this.playAudioAlert();
     this.interval = this.updateRemainingTime();
   }
 
@@ -72,6 +74,11 @@ class ActivityCheck extends Component {
     clearInterval(this.interval);
   }
 
+  playAudioAlert() {
+    this.alert = new Audio(`${Meteor.settings.public.app.basename}/resources/sounds/notify.mp3`);
+    this.alert.play();
+  }
+
   render() {
     const { intl } = this.props;
 
@@ -80,6 +87,7 @@ class ActivityCheck extends Component {
     return (
       <Modal
         hideBorder
+        onRequestClose={handleInactivityDismiss}
         shouldCloseOnOverlayClick={false}
         shouldShowCloseButton={false}
       >
diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx
index 50fcc12a52ab026aa9f143a7f579237800a7abb6..7d956987442b2bde7cd9cfa32c7ebf52226a9a54 100755
--- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/component.jsx
@@ -62,6 +62,7 @@ class AudioControls extends Component {
       listenOnly,
       intl,
       shortcuts,
+      currentUser,
     } = this.props;
 
     let joinIcon = 'audio_off';
@@ -75,25 +76,23 @@ class AudioControls extends Component {
 
     return (
       <span className={styles.container}>
-        {showMute
-          ? (
-            <Button
-              className={cx(styles.button, !talking || styles.glow, !muted || styles.btn)}
-              onClick={handleToggleMuteMicrophone}
-              disabled={disable}
-              hideLabel
-              label={muted ? intl.formatMessage(intlMessages.unmuteAudio)
-                : intl.formatMessage(intlMessages.muteAudio)}
-              aria-label={muted ? intl.formatMessage(intlMessages.unmuteAudio)
-                : intl.formatMessage(intlMessages.muteAudio)}
-              color={!muted ? 'primary' : 'default'}
-              ghost={muted}
-              icon={muted ? 'mute' : 'unmute'}
-              size="lg"
-              circle
-              accessKey={shortcuts.toggleMute}
-            />
-          ) : null}
+        {showMute && currentUser.isVoiceUser ?
+          <Button
+            className={cx(styles.button, !talking || styles.glow, !muted || styles.btn)}
+            onClick={handleToggleMuteMicrophone}
+            disabled={disable}
+            hideLabel
+            label={muted ? intl.formatMessage(intlMessages.unmuteAudio)
+              : intl.formatMessage(intlMessages.muteAudio)}
+            aria-label={muted ? intl.formatMessage(intlMessages.unmuteAudio)
+              : intl.formatMessage(intlMessages.muteAudio)}
+            color={!muted ? 'primary' : 'default'}
+            ghost={muted}
+            icon={muted ? 'mute' : 'unmute'}
+            size="lg"
+            circle
+            accessKey={shortcuts.toggleMute}
+          /> : null}
         <Button
           className={cx(styles.button, inAudio || styles.btn)}
           onClick={inAudio ? handleLeaveAudio : handleJoinAudio}
diff --git a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx
index b4666a77912f3e32b15784eae52aa09535f70742..aa795e0ffd7879424d681e902ec435c27e24409a 100755
--- a/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/audio/audio-controls/container.jsx
@@ -39,6 +39,7 @@ export default withModalMounter(withTracker(({ mountModal }) => ({
   listenOnly: Service.isConnected() && Service.isListenOnly(),
   disable: Service.isConnecting() || Service.isHangingUp(),
   talking: Service.isTalking() && !Service.isMuted(),
+  currentUser: Service.currentUser(),
   handleToggleMuteMicrophone: () => Service.toggleMuteMicrophone(),
   handleJoinAudio: () => (Service.isConnected() ? Service.joinListenOnly() : mountModal(<AudioModalContainer />)),
   handleLeaveAudio: () => Service.exitAudio(),
diff --git a/bigbluebutton-html5/imports/ui/components/audio/service.js b/bigbluebutton-html5/imports/ui/components/audio/service.js
index 027b83f8bd7d25bda2a8b37ca0f9e4d4cc58959f..2338fec7a1f2681732cbaea398fc08ae89eacb45 100755
--- a/bigbluebutton-html5/imports/ui/components/audio/service.js
+++ b/bigbluebutton-html5/imports/ui/components/audio/service.js
@@ -41,6 +41,8 @@ const audioLocked = () => {
   return audioLock && User.isLocked;
 };
 
+const currentUser = () => mapUser(Users.findOne({ intId: Auth.userID }));
+
 export default {
   init,
   exitAudio: () => AudioManager.exitAudio(),
@@ -65,4 +67,5 @@ export default {
   error: () => AudioManager.error,
   isUserModerator: () => Users.findOne({ userId: Auth.userID }).moderator,
   audioLocked,
+  currentUser,
 };
diff --git a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx
index 9608eff88588820680fb3fcecaa5abcd1c94ecb7..543d0d52d4cd21662b36252cbc25026e6fbd11cc 100644
--- a/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/breakout-room/component.jsx
@@ -98,7 +98,11 @@ class BreakoutRoom extends Component {
     const hasUser = breakoutRoomUser(breakoutId);
     if (!hasUser && !waiting) {
       this.setState(
-        { waiting: true, requestedBreakoutId: breakoutId },
+        {
+          waiting: true,
+          requestedBreakoutId: breakoutId,
+          generated: false,
+        },
         () => requestJoinURL(breakoutId),
       );
     }
@@ -196,7 +200,7 @@ class BreakoutRoom extends Component {
           {intl.formatMessage(intlMessages.breakoutRoom, breakout.sequence.toString())}
           <span className={styles.usersAssignedNumberLabel}>
             (
-            {breakout.users.length}
+            {new Set(breakout.users.map(user => user.intId)).size}
             )
           </span>
         </span>
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx
index ea6f8cc4056d46428e1257baa46cd3cb0422886d..51d6bd93261fe8703e38c56f724b95b983593428 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx
@@ -26,6 +26,10 @@ const intlMessages = defineMessages({
     id: 'app.externalVideo.input',
     description: 'Video URL',
   },
+  urlInput: {
+    id: 'app.externalVideo.urlInput',
+    description: 'URL input field placeholder',
+  },
   title: {
     id: 'app.externalVideo.title',
     description: 'Modal title',
@@ -34,6 +38,10 @@ const intlMessages = defineMessages({
     id: 'app.externalVideo.close',
     description: 'Close',
   },
+  note: {
+    id: 'app.externalVideo.noteLabel',
+    description: 'provides hint about Shared YouTube videos',
+  },
 });
 
 class ExternalVideoModal extends Component {
@@ -124,8 +132,12 @@ class ExternalVideoModal extends Component {
                 onChange={this.updateVideoUrlHandler}
                 name="video-modal-input"
                 value={url}
+                placeholder={intl.formatMessage(intlMessages.urlInput)}
               />
             </label>
+            <div className={styles.youtubeNote}>
+              {intl.formatMessage(intlMessages.note)}
+            </div>
           </div>
 
           <div className={styles.content}>
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss
index ea4aabf9561e33866e1183e3f07cf0334b8d54ea..f13935f0585b5a3a2398450f9358bc0bbca2d478 100755
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss
@@ -1,5 +1,6 @@
 @import "/imports/ui/stylesheets/variables/_all";
 @import "/imports/ui/components/modal/simple/styles";
+@import "/imports/ui/stylesheets/mixins/focus";
 
 .header {
   margin: 0;
@@ -114,32 +115,30 @@
 }
 
 .videoUrl {
+  margin: 0 var(--border-size) 0 var(--border-size);
+
   label {
     display: block;
   }
 
   input {
+    @include inputFocus(var(--color-blue-light));
     display: block;
     margin: 10px 0 10px 0;
     padding: 0.4em;
-    background-color: #F1F8FF;
+    color: var(--color-text);
     line-height: 2rem;
     width: 100%;
     font-family: inherit;
     font-weight: inherit;
-    border: none;
-    border-radius: 0.4rem;
+    border: 1px solid var(--color-gray-lighter);
+    border-radius: var(--border-radius);
 
     [style~="--enableAnimation:1;"] & {
       transition: box-shadow .2s;
     }
   }
 
-  input:focus {
-    outline: none;
-    box-shadow: 0.2rem 0.8rem 1.6rem 600;
-  }
-
   span {
     font-weight: 600;
   }
@@ -154,3 +153,9 @@
   }
 }
 
+.youtubeNote {
+  color: var(--color-gray);
+  font-size: var(--font-size-small);
+  font-style: italic;
+  padding-top: var(--sm-padding-x);
+}
diff --git a/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx b/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx
index d7d28ba5c665ee0f02de7e5f8dadf64571d39069..13349df55566569977a0d942efe28fabb3c87bee 100755
--- a/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/meeting-ended/component.jsx
@@ -59,6 +59,26 @@ const intlMessage = defineMessages({
     id: 'app.feedback.sendFeedbackDesc',
     description: 'adds context to send feedback option',
   },
+  duplicate_user_in_meeting_eject_reason: {
+    id: 'app.meeting.logout.duplicateUserEjectReason',
+    description: 'message for duplicate users',
+  },
+  not_enough_permission_eject_reason: {
+    id: 'app.meeting.logout.permissionEjectReason',
+    description: 'message for whom was kicked by doing something without permission',
+  },
+  user_requested_eject_reason: {
+    id: 'app.meeting.logout.ejectedFromMeeting',
+    description: 'message when the user is removed by someone',
+  },
+  validate_token_failed_eject_reason: {
+    id: 'app.meeting.logout.validateTokenFailedEjectReason',
+    description: 'invalid auth token',
+  },
+  user_inactivity_eject_reason: {
+    id: 'app.meeting.logout.userInactivityEjectReason',
+    description: 'message for whom was kicked by inactivity',
+  },
 });
 
 const propTypes = {
diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx
index c6892e84f4617966d55d7caba28900eb73ef1386..57d08d3e7051955731114121939356abde3e2d85 100755
--- a/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/component.jsx
@@ -161,12 +161,19 @@ class NavBar extends PureComponent {
     }
 
     breakouts.forEach((breakout) => {
+      const userOnMeeting = breakout.users.filter(u => u.userId === Auth.userID).length;
+      if (breakout.freeJoin
+        && !didSendBreakoutInvite
+        && !userOnMeeting
+        && !isBreakoutRoom) {
+        this.inviteUserToBreakout(breakout);
+        this.setState({ didSendBreakoutInvite: true });
+      }
+
       if (!breakout.users) {
         return;
       }
 
-      const userOnMeeting = breakout.users.filter(u => u.userId === Auth.userID).length;
-
       if (!userOnMeeting) return;
 
       if ((!didSendBreakoutInvite && !isBreakoutRoom) ) {
diff --git a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx
index ff61bf45c0e0a94a0c737c0882ae753e13e35a2e..2ef6b417ed3d4aa271ee17a7c9641299f2360377 100755
--- a/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/nav-bar/settings-dropdown/component.jsx
@@ -163,8 +163,8 @@ class SettingsDropdown extends PureComponent {
   }
 
   leaveSession() {
+    document.dispatchEvent(new Event('exitVideo'));
     const { mountModal } = this.props;
-
     const LOGOUT_CODE = '430';
     // we don't check askForFeedbackOnLogout here,
     // it is checked in meeting-ended component
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
index 32ca1461b9aa80ed21c9d44ba5450de284a8fcf5..29cb7a69c9195d67e2e29b02128ed581d0c7bf37 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/component.jsx
@@ -47,6 +47,18 @@ class PresentationArea extends Component {
     this.fitToWidthHandler = this.fitToWidthHandler.bind(this);
   }
 
+  componentDidUpdate(prevProps, prevState) {
+    if (prevState.fitToWidth) {
+      // When presenter is changed or slide changed we reset fitToWidth
+      if ((prevProps.userIsPresenter && !this.props.userIsPresenter) ||
+          (prevProps.currentSlide.id !== this.props.currentSlide.id)) {
+        this.setState({
+          fitToWidth: false,
+        });
+      }
+    }
+  }
+
   componentDidMount() {
     // adding an event listener to scale the whiteboard on 'resize' events sent by chat/userlist etc
     window.addEventListener('resize', () => {
@@ -129,7 +141,7 @@ class PresentationArea extends Component {
   }
 
   calculateSize() {
-    const { presentationHeight, presentationWidth } = this.state;
+    const { presentationHeight, presentationWidth, fitToWidth } = this.state;
     const { currentSlide } = this.props;
 
     const originalWidth = currentSlide.calculatedData.width;
@@ -138,25 +150,30 @@ class PresentationArea extends Component {
     let adjustedWidth;
     let adjustedHeight;
 
-    // Slide has a portrait orientation
-    if (originalWidth <= originalHeight) {
-      adjustedWidth = (presentationHeight * originalWidth) / originalHeight;
-      if (presentationWidth < adjustedWidth) {
-        adjustedHeight = (presentationHeight * presentationWidth) / adjustedWidth;
-        adjustedWidth = presentationWidth;
-      } else {
-        adjustedHeight = presentationHeight;
-      }
-
+    if (!fitToWidth) {
+      // Slide has a portrait orientation
+      if (originalWidth <= originalHeight) {
+        adjustedWidth = (presentationHeight * originalWidth) / originalHeight;
+        if (presentationWidth < adjustedWidth) {
+          adjustedHeight = (presentationHeight * presentationWidth) / adjustedWidth;
+          adjustedWidth = presentationWidth;
+        } else {
+          adjustedHeight = presentationHeight;
+        }
       // Slide has a landscape orientation
-    } else {
-      adjustedHeight = (presentationWidth * originalHeight) / originalWidth;
-      if (presentationHeight < adjustedHeight) {
-        adjustedWidth = (presentationWidth * presentationHeight) / adjustedHeight;
-        adjustedHeight = presentationHeight;
       } else {
-        adjustedWidth = presentationWidth;
+        adjustedHeight = (presentationWidth * originalHeight) / originalWidth;
+        if (presentationHeight < adjustedHeight) {
+          adjustedWidth = (presentationWidth * presentationHeight) / adjustedHeight;
+          adjustedHeight = presentationHeight;
+        } else {
+          adjustedWidth = presentationWidth;
+        }
       }
+    } else {
+      adjustedWidth = presentationWidth;
+      adjustedHeight = (adjustedWidth * originalHeight) / originalWidth;
+      if (adjustedHeight > presentationHeight) adjustedHeight = presentationHeight;
     }
     return {
       width: adjustedWidth,
@@ -164,6 +181,24 @@ class PresentationArea extends Component {
     };
   }
 
+  // TODO: This could be replaced if we synchronize the fit-to-width state between users
+  checkFitToWidth() {
+    const { userIsPresenter, currentSlide } = this.props;
+    const { fitToWidth } = this.state;
+    if (userIsPresenter) {
+      return fitToWidth;
+    } else {
+      const { width, height, viewBoxWidth, viewBoxHeight } = currentSlide.calculatedData;
+      const slideSizeRatio = width / height;
+      const viewBoxSizeRatio = viewBoxWidth / viewBoxHeight;
+      if (slideSizeRatio !== viewBoxSizeRatio) {
+        return true;
+      } else {
+        return false;
+      }
+    }
+  }
+
   zoomChanger(incomingZoom) {
     const { zoom } = this.state;
     let newZoom = incomingZoom;
@@ -284,7 +319,7 @@ class PresentationArea extends Component {
 
   // renders the whole presentation area
   renderPresentationArea() {
-    const { fitToWidth } = this.state;
+    const { presentationWidth } = this.state;
     const { podId, currentSlide } = this.props;
     if (!this.isPresentationAccessible()) return null;
 
@@ -306,7 +341,7 @@ class PresentationArea extends Component {
       imageUri,
     } = slideObj.calculatedData;
 
-    const svgAreaDimensions = fitToWidth
+    const svgAreaDimensions = this.checkFitToWidth()
       ? {
         position: 'absolute',
         width: 'inherit',
@@ -351,7 +386,7 @@ class PresentationArea extends Component {
               version="1.1"
               xmlns="http://www.w3.org/2000/svg"
               className={styles.svgStyles}
-              style={fitToWidth
+              style={this.checkFitToWidth()
                 ? {
                   position: 'absolute',
                 }
@@ -380,10 +415,9 @@ class PresentationArea extends Component {
                   podId={podId}
                   whiteboardId={slideObj.id}
                   widthRatio={slideObj.widthRatio}
-                  physicalWidthRatio={adjustedSizes.width / width}
+                  physicalWidthRatio={this.checkFitToWidth() ? (presentationWidth / width) : (adjustedSizes.width / width)}
                   slideWidth={width}
                   slideHeight={height}
-                  radius={fitToWidth ? 2 : 5}
                 />
               </g>
               {this.renderOverlays(slideObj, adjustedSizes)}
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx
index ada7003b6f496ee917c7f809d4de1b69e4566f83..b64f67cd72a0c863c9beba78bda525252eea268c 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/cursor/component.jsx
@@ -40,6 +40,8 @@ export default class Cursor extends Component {
   }
 
   static getScaledSizes(props) {
+    // TODO: This might need to change for the use case of fit-to-width portrait
+    //       slides in non-presenter view. Some elements are still shrinking.
     const scaleFactor = props.widthRatio / 100 / props.physicalWidthRatio;
 
     return {
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-close-button/styles.scss b/bigbluebutton-html5/imports/ui/components/presentation/presentation-close-button/styles.scss
index 2c3384c4cd6fd8ddf103a4a3068f6a820f2779e3..9764bcfb537e14ccb12daef35f191952056d8561 100644
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-close-button/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-close-button/styles.scss
@@ -1,5 +1,6 @@
 
 .button {
+  z-index: 1;
   position: absolute;
   top: 0;
   right: 0;
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx
index f6fe1a45c806cfa6b8299ff3a4d49bf65a4d90c5..d95b52b5c30f3a6d6d91c64f81b01cf75ba6b35b 100755
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-overlay/component.jsx
@@ -70,8 +70,6 @@ export default class PresentationOverlay extends Component {
       presentationSize,
     } = props;
 
-    this.fitToPage = false;
-
     this.viewportW = slideWidth;
     this.viewportH = slideHeight;
 
@@ -107,6 +105,7 @@ export default class PresentationOverlay extends Component {
     const zoomPercentage = (Math.round((100 / realZoom) * 100));
     const roundedUpToFive = Math.round(zoomPercentage / 5) * 5;
     zoomChanger(roundedUpToFive);
+    this.doZoomCall(HUNDRED_PERCENT, 0, 0);
   }
 
   componentDidUpdate(prevProps) {
@@ -117,6 +116,7 @@ export default class PresentationOverlay extends Component {
       presentationSize,
       slideHeight,
       slideWidth,
+      fitToWidth,
     } = this.props;
     const isDifferent = zoom !== this.state.zoom && !touchZoom;
     const moveSLide = ((delta.x !== prevProps.delta.x)
@@ -134,21 +134,28 @@ export default class PresentationOverlay extends Component {
       this.toolbarZoom();
     }
 
-    if (!prevProps.fitToWidth && this.props.fitToWidth) {
-      this.parentH = presentationSize.presentationHeight;
-      this.parentW = presentationSize.presentationWidth;
-      this.viewportH = this.parentH;
-      this.viewportW = this.parentW;
-      this.doZoomCall(HUNDRED_PERCENT, 0, 0);
-    }
-
-    if (!this.props.fitToWidth && prevProps.fitToWidth) {
+    if (fitToWidth) {
+      if (!prevProps.fitToWidth || this.checkResize(prevProps.presentationSize)) {
+        this.parentH = presentationSize.presentationHeight;
+        this.parentW = presentationSize.presentationWidth;
+        this.viewportH = this.parentH;
+        this.viewportW = this.parentW;
+        this.doZoomCall(HUNDRED_PERCENT, 0, 0);
+      }
+    } else if (prevProps.fitToWidth) {
       this.viewportH = slideHeight;
       this.viewportW = slideWidth;
       this.doZoomCall(HUNDRED_PERCENT, 0, 0);
     }
   }
 
+  checkResize(prevPresentationSize) {
+    const { presentationSize } = this.props;
+    const heightChanged = prevPresentationSize.presentationHeight !== presentationSize.presentationHeight;
+    const widthChanged = prevPresentationSize.presentationWidth !== presentationSize.presentationWidth;
+    return heightChanged || widthChanged;
+  }
+
   onZoom(zoomValue, mouseX, mouseY) {
     let absXcoordInPage = (Math.abs(this.calcPageX) * MYSTERY_NUM) + mouseX;
     let absYcoordInPage = (Math.abs(this.calcPageY) * MYSTERY_NUM) + mouseY;
@@ -156,15 +163,22 @@ export default class PresentationOverlay extends Component {
     const relXcoordInPage = absXcoordInPage / this.calcPageW;
     const relYcoordInPage = absYcoordInPage / this.calcPageH;
 
-    if (this.isPortraitDoc() && this.fitToPage) {
-      this.calcPageH = (this.viewportH * zoomValue) / HUNDRED_PERCENT;
-      this.calcPageW = (this.pageOrigW / this.pageOrigH) * this.calcPageH;
-    } else if (!this.isPortraitDoc() && this.fitToPage) {
-      this.calcPageW = (this.viewportW * zoomValue) / HUNDRED_PERCENT;
-      this.calcPageH = (this.viewportH * zoomValue) / HUNDRED_PERCENT;
+    if (this.isPortraitDoc()) {
+      if (this.props.fitToWidth) {
+        this.calcPageW = (this.viewportW * zoomValue) / HUNDRED_PERCENT;
+        this.calcPageH = (this.calcPageW / this.pageOrigW) * this.pageOrigH;
+      } else {
+        this.calcPageH = (this.viewportH * zoomValue) / HUNDRED_PERCENT;
+        this.calcPageW = (this.pageOrigW / this.pageOrigH) * this.calcPageH;
+      }
     } else {
-      this.calcPageW = (this.viewportW * zoomValue) / HUNDRED_PERCENT;
-      this.calcPageH = (this.calcPageW / this.pageOrigW) * this.pageOrigH;
+      if (this.props.fitToWidth) {
+        this.calcPageW = (this.viewportW * zoomValue) / HUNDRED_PERCENT;
+        this.calcPageH = (this.calcPageW / this.pageOrigW) * this.pageOrigH;
+      } else {
+        this.calcPageW = (this.viewportW * zoomValue) / HUNDRED_PERCENT;
+        this.calcPageH = (this.viewportH * zoomValue) / HUNDRED_PERCENT;
+      }
     }
 
     absXcoordInPage = relXcoordInPage * this.calcPageW;
@@ -181,6 +195,8 @@ export default class PresentationOverlay extends Component {
 
   getTransformedSvgPoint(clientX, clientY) {
     const svgObject = this.props.getSvgRef();
+    // If svgObject is not ready, return origin
+    if (!svgObject) return { x: 0, y: 0 };
     const screenPoint = svgObject.createSVGPoint();
     screenPoint.x = clientX;
     screenPoint.y = clientY;
diff --git a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
index c65fe63bc7114eea3ad192cf6b1b122ae3e1565d..bbd7b03d3123134758de5c27309fd1003f6f1a77 100755
--- a/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/presentation/presentation-uploader/component.jsx
@@ -23,7 +23,7 @@ const propTypes = {
   fileSizeMax: PropTypes.number.isRequired,
   handleSave: PropTypes.func.isRequired,
   dispatchTogglePresentationDownloadable: PropTypes.func.isRequired,
-  fileValidMimeTypes: PropTypes.arrayOf(PropTypes.string).isRequired,
+  fileValidMimeTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
   presentations: PropTypes.arrayOf(PropTypes.shape({
     id: PropTypes.string.isRequired,
     filename: PropTypes.string.isRequired,
@@ -268,8 +268,9 @@ class PresentationUploader extends Component {
 
   handleFiledrop(files, files2) {
     const { fileValidMimeTypes, intl } = this.props;
+    const mimeTypes = fileValidMimeTypes.map(fileValid => fileValid.mime);
     const [accepted, rejected] = _.partition(files
-      .concat(files2), f => fileValidMimeTypes.includes(f.type));
+      .concat(files2), f => mimeTypes.includes(f.type));
 
     const presentationsToUpload = accepted.map((file) => {
       const id = _.uniqueId(file.name);
@@ -605,7 +606,7 @@ class PresentationUploader extends Component {
         className={styles.dropzone}
         activeClassName={styles.dropzoneActive}
         rejectClassName={styles.dropzoneReject}
-        accept={isMobileBrowser ? '' : fileValidMimeTypes.join()}
+        accept={isMobileBrowser ? '' : fileValidMimeTypes.map(fileValid => fileValid.extension)}
         minSize={fileSizeMin}
         maxSize={fileSizeMax}
         disablepreview="true"
diff --git a/bigbluebutton-html5/imports/ui/components/recording/component.jsx b/bigbluebutton-html5/imports/ui/components/recording/component.jsx
index 72266f5a935769c4144d89698ac18699f6daddd9..f7b26ae8caa9d0fad9f1ca1d80129de5b8eeb57d 100755
--- a/bigbluebutton-html5/imports/ui/components/recording/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/recording/component.jsx
@@ -14,6 +14,10 @@ const intlMessages = defineMessages({
     id: 'app.recording.stopTitle',
     description: 'stop recording title',
   },
+  resumeTitle: {
+    id: 'app.recording.resumeTitle',
+    description: 'resume recording title',
+  },
   startDescription: {
     id: 'app.recording.startDescription',
     description: 'start recording description',
@@ -36,11 +40,13 @@ const propTypes = {
   intl: intlShape.isRequired,
   closeModal: PropTypes.func.isRequired,
   toggleRecording: PropTypes.func.isRequired,
+  recordingTime: PropTypes.number,
   recordingStatus: PropTypes.bool,
   amIModerator: PropTypes.bool,
 };
 
 const defaultProps = {
+  recordingTime: -1,
   recordingStatus: false,
   amIModerator: false,
 };
@@ -50,11 +56,21 @@ class RecordingComponent extends React.PureComponent {
     const {
       intl,
       recordingStatus,
+      recordingTime,
       amIModerator,
       closeModal,
       toggleRecording,
     } = this.props;
 
+    let title;
+
+    if (!recordingStatus) {
+      title = recordingTime >= 0 ? intl.formatMessage(intlMessages.resumeTitle)
+        : intl.formatMessage(intlMessages.startTitle);
+    } else {
+      title = intl.formatMessage(intlMessages.stopTitle);
+    }
+
     if (!amIModerator) return null;
     return (
       <Modal
@@ -66,11 +82,7 @@ class RecordingComponent extends React.PureComponent {
         <div className={styles.container}>
           <div className={styles.header}>
             <div className={styles.title}>
-              {
-                intl.formatMessage(!recordingStatus
-                  ? intlMessages.startTitle
-                  : intlMessages.stopTitle)
-              }
+              {title}
             </div>
           </div>
           <div className={styles.description}>
diff --git a/bigbluebutton-html5/imports/ui/components/recording/container.jsx b/bigbluebutton-html5/imports/ui/components/recording/container.jsx
index 72815e90b48c75dd0b6de05b8b33a670ddd54460..4c212cfc179467440f56df4bcb233c49bd45385c 100755
--- a/bigbluebutton-html5/imports/ui/components/recording/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/recording/container.jsx
@@ -8,16 +8,19 @@ import RecordingComponent from './component';
 
 const RecordingContainer = props => <RecordingComponent {...props} />;
 
-export default withModalMounter(withTracker(({ mountModal }) => ({
-  closeModal() {
-    mountModal(null);
-  },
+export default withModalMounter(withTracker(({ mountModal }) => {
+  const { recording, time } = Meetings.findOne({ meetingId: Auth.meetingID }).recordProp;
 
-  toggleRecording: () => {
-    makeCall('toggleRecording');
-    mountModal(null);
-  },
+  return ({
+    closeModal: () => mountModal(null),
 
-  recordingStatus: (Meetings.findOne({ meetingId: Auth.meetingID }).recordProp.recording),
+    toggleRecording: () => {
+      makeCall('toggleRecording');
+      mountModal(null);
+    },
 
-}))(RecordingContainer));
+    recordingStatus: recording,
+    recordingTime: time,
+
+  });
+})(RecordingContainer));
diff --git a/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx b/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx
index 7fecf629a68c86ba9f464930eb567775fccd7ca5..52f712f7716d393b0949f9624bd6c519711b321c 100644
--- a/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-preview/component.jsx
@@ -154,7 +154,7 @@ class VideoPreview extends Component {
       video: VIDEO_CONSTRAINTS,
     };
 
-    navigator.mediaDevices.enumerateDevices().then((devices) => {
+    navigator.mediaDevices.enumerateDevices().then(async (devices) => {
       const { isInitialDeviceSet } = this.state;
       const webcams = [];
 
@@ -175,9 +175,10 @@ class VideoPreview extends Component {
 
       constraints.video.deviceId = { exact: this.state.webcamDeviceId };
 
-      const iOS = ['iPad', 'iPhone', 'iPod'].indexOf(navigator.platform) >= 0;
-      
-      if (iOS) {
+      try {
+        await navigator.mediaDevices.getUserMedia(constraints);
+      } catch (exception) {
+        logger.info({ logCode: 'insufficient_constraints' }, 'No webcam found for constraint values, increasing constraints.', exception);
         constraints.video.width = { max: 640 };
         constraints.video.height = { max: 480 };
       }
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx
index 58afa06db3260f164ead950ea86555b5bf7a20f4..1fa16e4871a70c18351238a901f9b687916233e0 100644
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/component.jsx
@@ -169,6 +169,7 @@ class VideoList extends Component {
           })}
         >
           <VideoListItem
+            numOfUsers={users.length}
             user={user}
             actions={actions}
             onMount={(videoRef) => {
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss
index 4e0943178bc91699f98a9f00789590b230de088a..ab0b95117713bce2e94e8cb27ed7ca77e47a3cc6 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/styles.scss
@@ -144,12 +144,16 @@
 .dropdownTrigger, .userName {
   @extend %text-elipsis;
   position: relative;
-  background-color: rgba(var(--color-gray), .5);
+  background-color: var(--color-black);
+  opacity: .5;
   color: var(--color-white);
   font-size: 80%;
   border-radius: 15px;
   padding: 0 1rem 0 .5rem !important;
+}
 
+.noMenu {
+  padding: 0 .5rem 0 .5rem !important;
 }
 
 .dropdownTrigger {
diff --git a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
index 183b70fde313a71f3ea7fa3b9dbbca8864fa0eea..5b64b591fc8b10868e8cce746fe6bcdc72793b68 100755
--- a/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-provider/video-list/video-list-item/component.jsx
@@ -1,8 +1,9 @@
 import React, { Component } from 'react';
 import browser from 'browser-detect';
 import { Meteor } from 'meteor/meteor';
+import PropTypes from 'prop-types';
 import cx from 'classnames';
-import { defineMessages, injectIntl } from 'react-intl';
+import { defineMessages, injectIntl, intlShape } from 'react-intl';
 import Dropdown from '/imports/ui/components/dropdown/component';
 import DropdownTrigger from '/imports/ui/components/dropdown/trigger/component';
 import DropdownContent from '/imports/ui/components/dropdown/content/component';
@@ -121,7 +122,7 @@ class VideoListItem extends Component {
 
   render() {
     const { showStats, stats } = this.state;
-    const { user } = this.props;
+    const { user, numOfUsers } = this.props;
     const availableActions = this.getAvailableActions();
     const enableVideoMenu = Meteor.settings.public.kurento.enableVideoMenu || false;
 
@@ -162,7 +163,13 @@ class VideoListItem extends Component {
               <div className={isFirefox ? styles.dropdownFireFox
                 : styles.dropdown}
               >
-                <span className={styles.userName}>{user.name}</span>
+                <span className={cx({
+                  [styles.userName]: true,
+                  [styles.noMenu]: numOfUsers < 3,
+                })}
+                >
+                  {user.name}
+                </span>
               </div>
             )
           }
@@ -177,3 +184,20 @@ class VideoListItem extends Component {
 }
 
 export default injectIntl(VideoListItem);
+
+VideoListItem.defaultProps = {
+  numOfUsers: 0,
+};
+
+VideoListItem.propTypes = {
+  intl: intlShape.isRequired,
+  enableVideoStats: PropTypes.bool.isRequired,
+  actions: PropTypes.arrayOf(PropTypes.func).isRequired,
+  user: PropTypes.objectOf(PropTypes.oneOfType([
+    PropTypes.bool,
+    PropTypes.number,
+    PropTypes.object,
+    PropTypes.string,
+  ])).isRequired,
+  numOfUsers: PropTypes.number,
+};
diff --git a/bigbluebutton-html5/private/config/settings.yml b/bigbluebutton-html5/private/config/settings.yml
index e20b176fc56d9e9b8d677c98220f3ef89aa527c8..b5b9219d0cd9d594c0a3b21eafe49b2c67245f97 100755
--- a/bigbluebutton-html5/private/config/settings.yml
+++ b/bigbluebutton-html5/private/config/settings.yml
@@ -148,24 +148,40 @@ public:
     uploadSizeMin: 0
     uploadSizeMax: 50000000
     uploadValidMimeTypes:
-    - application/vnd.ms-excel
-    - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
-    - application/msword
-    - application/vnd.openxmlformats-officedocument.wordprocessingml.document
-    - application/vnd.ms-powerpoint
-    - application/vnd.openxmlformats-officedocument.presentationml.presentation
-    - application/vnd.oasis.opendocument.text
-    - application/rtf
-    - text/plain
-    - application/vnd.oasis.opendocument.spreadsheet
-    - application/vnd.oasis.opendocument.presentation
-    - application/vnd.oasis.opendocument.text
-    - application/vnd.oasis.opendocument.graphics
-    - application/vnd.oasis.opendocument.chart
-    - application/vnd.oasis.opendocument.image
-    - application/pdf
-    - image/jpeg
-    - image/png
+    - extension: .pdf
+      mime: application/pdf
+    - extension: .doc
+      mime: application/msword
+    - extension: .docx
+      mime: application/vnd.openxmlformats-officedocument.wordprocessingml.document
+    - extension: .xls
+      mime: application/vnd.ms-excel
+    - extension: .xlsx
+      mime: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
+    - extension: .ppt
+      mime: application/vnd.ms-powerpoint
+    - extension: .pptx
+      mime: application/vnd.openxmlformats-officedocument.presentationml.presentation
+    - extension: .txt
+      mime: text/plain
+    - extension: .rtf
+      mime: application/rtf
+    - extension: .odt
+      mime: application/vnd.oasis.opendocument.text
+    - extension: .ods
+      mime: application/vnd.oasis.opendocument.spreadsheet
+    - extension: .odp
+      mime: application/vnd.oasis.opendocument.presentation
+    - extension: .odg
+      mime: application/vnd.oasis.opendocument.graphics
+    - extension: .odc
+      mime: application/vnd.oasis.opendocument.chart
+    - extension: .odi
+      mime: application/vnd.oasis.opendocument.image
+    - extension: .jpg
+      mime: image/jpeg
+    - extension: .png
+      mime: image/png
   user:
     role_moderator: MODERATOR
     role_viewer: VIEWER
diff --git a/bigbluebutton-html5/private/locales/cs_CZ.json b/bigbluebutton-html5/private/locales/cs_CZ.json
index 67cad8e46e81445189ce0bb9e75ad81a1146358e..7e69fb024a27434990fc942f5177646cc165c781 100644
--- a/bigbluebutton-html5/private/locales/cs_CZ.json
+++ b/bigbluebutton-html5/private/locales/cs_CZ.json
@@ -393,7 +393,6 @@
     "app.lock-viewers.PrivateChatLable": "Soukromý chat",
     "app.lock-viewers.Layout": "Rozložení obrazovky",
     "app.recording.startTitle": "Zahájit nahrávání",
-    "app.recording.stopTitle": "Zastavit nahrávání",
     "app.recording.startDescription": "(Můžete využít nahrávací tlačítko později pro pozastavení nahrávání.)",
     "app.recording.stopDescription": "Jste si jist, že chcete pozastavit nahrávání? (Později můžete pokračovat v nahrávání opakovaným stiskem nahrávacího tlačítka.)",
     "app.videoPreview.cameraLabel": "Kamera",
@@ -509,7 +508,6 @@
     "app.createBreakoutRoom.doneLabel": "Hotovo",
     "app.createBreakoutRoom.nextLabel": "Další",
     "app.createBreakoutRoom.minusRoomTime": "Prodloužit čas vedlejší místnosti",
-    "app.createBreakoutRoom.addRoomTime": "Zkrátit čas vedlejší místnosti",
     "app.createBreakoutRoom.addParticipantLabel": "+ Přidat posluchače",
     "app.createBreakoutRoom.freeJoin": "Dovolit posluchačům, aby si sami vybrali, do které vedlejší místnosti se připojí",
     "app.createBreakoutRoom.leastOneWarnBreakout": "Do vedlejší místnosti musíte přiřadit alespoň jednoho posluchače",
diff --git a/bigbluebutton-html5/private/locales/de.json b/bigbluebutton-html5/private/locales/de.json
index 5b91671f0e1be375b0cb9211f4cb84a1c936ffcd..17d994a83f4b3cf18b0dd9263e2e78061f8b8297 100644
--- a/bigbluebutton-html5/private/locales/de.json
+++ b/bigbluebutton-html5/private/locales/de.json
@@ -21,6 +21,9 @@
     "app.note.title": "Geteilte Notizen",
     "app.note.label": "Notiz",
     "app.note.hideNoteLabel": "Notiz verbergen",
+    "app.user.activityCheck": "Nutzeraktivitätsprüfung",
+    "app.user.activityCheck.label": "Prüfen ob Nutzer noch in der Konferenz ist ({0})",
+    "app.user.activityCheck.check": "Prüfen",
     "app.note.tipLabel": "Drücken Sie Esc um die Editorwerkzeugliste auszuwählen",
     "app.userList.usersTitle": "Teilnehmer",
     "app.userList.participantsTitle": "Teilnehmer",
@@ -72,6 +75,7 @@
     "app.presentation.startSlideContent": "Beginn des Folieninhalts",
     "app.presentation.endSlideContent": "Ende des Folieninhalts",
     "app.presentation.emptySlideContent": "Kein Inhalt für aktuelle Folie",
+    "app.presentation.presentationToolbar.selectLabel": "Folie auswählen",
     "app.presentation.presentationToolbar.prevSlideLabel": "Vorherige Folie",
     "app.presentation.presentationToolbar.prevSlideDesc": "Präsentation zur vorherigen Folie wechseln",
     "app.presentation.presentationToolbar.nextSlideLabel": "Nächste Folie",
@@ -91,6 +95,7 @@
     "app.presentation.presentationToolbar.zoomReset": "Zoom zurücksetzen",
     "app.presentation.presentationToolbar.zoomIndicator": "Aktuelle Zoom-Stufe",
     "app.presentation.presentationToolbar.fitToWidth": "An Breite anpassen",
+    "app.presentation.presentationToolbar.fitToPage": "An Seite anpassen",
     "app.presentation.presentationToolbar.goToSlide": "Folie {0}",
     "app.presentationUploder.title": "Präsentation",
     "app.presentationUploder.message": "Als Präsentator in BigBlueButton haben sie die Möglichkeit Office-Dokumente oder PDF-Dateien hochzuladen. PDF-Dateien haben dabei die bessere Qualität.",
@@ -132,6 +137,8 @@
     "app.poll.closeLabel": "Schließen",
     "app.poll.ariaInputCount": "Eingabe {0} von {1}",
     "app.poll.customPlaceholder": "Umfrageoption hinzufügen",
+    "app.poll.noPresentationSelected": "Keine Präsentation ausgewählt! Bitte eine auswählen.",
+    "app.poll.clickHereToSelect": "Zum Auswählen hier klicken",
     "app.poll.t": "Wahr",
     "app.poll.f": "Falsch",
     "app.poll.tf": "Richtig / Falsch",
@@ -376,6 +383,16 @@
     "app.error.400": "Ungültige Anfrage",
     "app.error.leaveLabel": "Erneut einloggen",
     "app.guest.waiting": "Warte auf Erlaubnis zur Konferenzteilnahme",
+    "app.userList.guest.waitingUsers": "Wartende Teilnehmer",
+    "app.userList.guest.waitingUsersTitle": "Teilnehmerverwaltung",
+    "app.userList.guest.optionTitle": "Unbearbeitete Teilnehmer überprüfen",
+    "app.userList.guest.allowAllAuthenticated": "Alle Autorisierten erlauben",
+    "app.userList.guest.allowAllGuests": "Alle Gäste erlauben",
+    "app.userList.guest.allowEveryone": "Alle erlauben",
+    "app.userList.guest.denyEveryone": "Alle verweigern",
+    "app.userList.guest.pendingUsers": "{0} unbearbeitete Teilnehmer",
+    "app.userList.guest.pendingGuestUsers": "{0} unbearbeitete Gäste",
+    "app.userList.guest.pendingGuestAlert": "Ist der Konferenz beigetreten und wartet auf Ihre Teilnahmeerlaubnis",
     "app.toast.breakoutRoomEnded": "Breakout-Raum wurde beendet. Bitte treten Sie der Audiokonferenz erneut bei.",
     "app.toast.chat.public": "Neue öffentliche Chatnachricht",
     "app.toast.chat.private": "Neue private Chatnachricht",
@@ -400,15 +417,15 @@
     "app.lock-viewers.title": "Zuschauerrechte einschränken",
     "app.lock-viewers.description": "Diese Optionen ermöglichen es, bestimmte Funktionen für Zuschauer einzuschränken, wie z.B. die Nutzung des privaten Chats. (Diese Einschränkungen gelten nicht für Moderatoren)",
     "app.lock-viewers.featuresLable": "Funktion",
-    "app.lock-viewers.lockStatusLabel": "Sperrstatus",
+    "app.lock-viewers.lockStatusLabel": "Gesperrt",
     "app.lock-viewers.webcamLabel": "Webcam",
     "app.lock-viewers.otherViewersWebcamLabel": "Nur Moderatoren sehen Webcams",
-    "app.lock-viewers.microphoneLable": "Mit Mikrofon",
+    "app.lock-viewers.microphoneLable": "Mikrofon",
     "app.lock-viewers.PublicChatLabel": "Öffentlicher Chat",
     "app.lock-viewers.PrivateChatLable": "Privater Chat",
     "app.lock-viewers.Layout": "Layout",
     "app.recording.startTitle": "Aufzeichnung starten",
-    "app.recording.stopTitle": "Aufzeichnung stoppen",
+    "app.recording.stopTitle": "Aufzeichnung pausieren",
     "app.recording.startDescription": "(Sie können den Aufnahmeknopf erneut drücken, um die Aufzeichnung zu pausieren)",
     "app.recording.stopDescription": "Sind Sie sicher, dass die die Aufnahme pausieren wollen? (Sie können die Aufnahme fortsetzen, in dem Sie auf den Aufnahmeknopf drücken)",
     "app.videoPreview.cameraLabel": "Kamera",
@@ -524,7 +541,7 @@
     "app.createBreakoutRoom.doneLabel": "Fertig",
     "app.createBreakoutRoom.nextLabel": "Nächster",
     "app.createBreakoutRoom.minusRoomTime": "Breakout-Raum Zeit erhöhen",
-    "app.createBreakoutRoom.addRoomTime": "Breakout-Raum Zeit reduzieren",
+    "app.createBreakoutRoom.addRoomTime": "Breakout Raum Zeit verringern",
     "app.createBreakoutRoom.addParticipantLabel": "+ Teilnehmer hinzufügen",
     "app.createBreakoutRoom.freeJoin": "Den Teilnehmern erlauben, sich selber einen Breakout-Raum auszusuchen.",
     "app.createBreakoutRoom.leastOneWarnBreakout": "Jedem Breakout-Raum muss wenigstens ein Teilnehmer zugeordnet sein.",
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index 977b9c23b38331392a6476b1de7f7c29c98b5941..977b389855ed9f89454e55b9c13442ef686824ea 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -98,7 +98,7 @@
     "app.presentation.presentationToolbar.fitToPage": "Fit to page",
     "app.presentation.presentationToolbar.goToSlide": "Slide {0}",
     "app.presentationUploder.title": "Presentation",
-    "app.presentationUploder.message": "As a presenter in BigBlueButton, you have the ability of uploading any office document or PDF file.  We recommend PDF file for best results.",
+    "app.presentationUploder.message": "As a presenter you have the ability of uploading any office document or PDF file.  We recommend PDF file for best results.",
     "app.presentationUploder.confirmLabel": "Start",
     "app.presentationUploder.confirmDesc": "Save your changes and start the presentation",
     "app.presentationUploder.dismissLabel": "Cancel",
@@ -375,6 +375,11 @@
     "app.audio.permissionsOverlay.hint": "We need you to allow us to use your media devices in order to join you to the voice conference :)",
     "app.error.removed": "You have been removed from the conference",
     "app.error.meeting.ended": "You have logged out of the conference",
+    "app.meeting.logout.duplicateUserEjectReason": "Duplicate user trying to join meeting",
+    "app.meeting.logout.permissionEjectReason": "Ejected due to permission violation",
+    "app.meeting.logout.ejectedFromMeeting": "You have been removed from the meeting",
+    "app.meeting.logout.validateTokenFailedEjectReason": "Failed to validate authorization token",
+    "app.meeting.logout.userInactivityEjectReason": "User inactive for too long",
     "app.dropdown.close": "Close",
     "app.error.500": "Ops, something went wrong",
     "app.error.404": "Not found",
@@ -426,6 +431,7 @@
     "app.lock-viewers.Layout": "Layout",
     "app.recording.startTitle": "Start recording",
     "app.recording.stopTitle": "Pause recording",
+    "app.recording.resumeTitle": "Resume recording",
     "app.recording.startDescription": "(You can select the record button again later to pause the recording.)",
     "app.recording.stopDescription": "Are you sure you want to pause the recording?  (You can resume by selecting the record button again.)",
     "app.videoPreview.cameraLabel": "Camera",
@@ -550,8 +556,10 @@
     "app.externalVideo.stop": "Stop sharing video",
     "app.externalVideo.title": "Share a YouTube video",
     "app.externalVideo.input": "YouTube video URL",
+    "app.externalVideo.urlInput": "Add YouTube URL",
     "app.externalVideo.urlError": "This URL isn't a valid YouTube video",
     "app.externalVideo.close": "Close",
-    "app.actionsBar.actionsDropdown.shareExternalVideo": "Share Youtube video",
-    "app.actionsBar.actionsDropdown.stopShareExternalVideo": "Stop sharing video"
+    "app.externalVideo.noteLabel": "Note: Shared YouTube videos will not appear in the recording",
+    "app.actionsBar.actionsDropdown.shareExternalVideo": "Share YouTube video",
+    "app.actionsBar.actionsDropdown.stopShareExternalVideo": "Stop sharing YouTube video"
 }
diff --git a/bigbluebutton-html5/private/locales/es.json b/bigbluebutton-html5/private/locales/es.json
index c1148ba9d5a40fbc35b54f4cbdd8f570201f2903..fef8b665d4782fa9c329eb279aa7aa9db2119dde 100644
--- a/bigbluebutton-html5/private/locales/es.json
+++ b/bigbluebutton-html5/private/locales/es.json
@@ -378,7 +378,6 @@
     "app.lock-viewers.PrivateChatLable": "Chat privado",
     "app.lock-viewers.Layout": "Diseño de pantalla",
     "app.recording.startTitle": "Iniciar grabación",
-    "app.recording.stopTitle": "Finalizar grabación",
     "app.recording.startDescription": "(Puedes hacer click en el icono nuevamente para detener la grabación)",
     "app.recording.stopDescription": "¿Quieres detener la grabación de la sesión? (Puedes continuar la grabación en cualquier momento haciendo click en el icono de iniciar grabación.)",
     "app.videoPreview.cameraLabel": "Webcam",
diff --git a/bigbluebutton-html5/private/locales/es_MX.json b/bigbluebutton-html5/private/locales/es_MX.json
index 887728be9b845a86e2adbc8c76298f136fe9ada3..51ed8ca076f7a522b7f6442eb3ea6b7b8a55465d 100644
--- a/bigbluebutton-html5/private/locales/es_MX.json
+++ b/bigbluebutton-html5/private/locales/es_MX.json
@@ -378,7 +378,6 @@
     "app.lock-viewers.PrivateChatLable": "Chat privado",
     "app.lock-viewers.Layout": "Diseño de pantalla",
     "app.recording.startTitle": "Iniciar grabación",
-    "app.recording.stopTitle": "Finalizar grabación",
     "app.recording.startDescription": "(Puedes hacer click en el icono nuevamente para detener la grabación)",
     "app.recording.stopDescription": "¿Quieres detener la grabación de la sesión? (Puedes continuar la grabación en cualquier momento haciendo click en el icono de iniciar grabación.)",
     "app.videoPreview.cameraLabel": "Webcam",
diff --git a/bigbluebutton-html5/private/locales/id.json b/bigbluebutton-html5/private/locales/id.json
index 8ae5109770cc70463fddf6de06f737f7a3c10e55..836480ce1e9371eb854c21a28feaadfeef10df0e 100644
--- a/bigbluebutton-html5/private/locales/id.json
+++ b/bigbluebutton-html5/private/locales/id.json
@@ -29,6 +29,8 @@
     "app.userList.menu.removeUser.label": "Hapus pengguna",
     "app.userList.menu.muteUserAudio.label": "Diamkan pengguna",
     "app.userList.menu.unmuteUserAudio.label": "Aktifkan pengguna",
+    "app.userList.menu.lockUser.label": "Kunci {0}",
+    "app.userList.userOptions.muteAllLabel": "Diamkan semua Pengguna",
     "app.media.label": "Media",
     "app.media.screenshare.start": "Berbagi layar sudah mulai",
     "app.media.screenshare.end": "Berbagi layar sudah berakhir",
diff --git a/bigbluebutton-html5/private/locales/pt_BR.json b/bigbluebutton-html5/private/locales/pt_BR.json
index efaf96b7605d1a59783529b549c48cf33eecba0e..e816cb9fc5e2182c01d363951c15837ef9aeaa4f 100644
--- a/bigbluebutton-html5/private/locales/pt_BR.json
+++ b/bigbluebutton-html5/private/locales/pt_BR.json
@@ -21,6 +21,10 @@
     "app.note.title": "Notas compartilhadas",
     "app.note.label": "Nota",
     "app.note.hideNoteLabel": "Ocultar nota",
+    "app.user.activityCheck": "Verificação de atividade do usuário",
+    "app.user.activityCheck.label": "Verifica se o usuário ainda está na sala ({0})",
+    "app.user.activityCheck.check": "Verificar",
+    "app.note.tipLabel": "Pressione Esc para focar na barra de ferramentas do editor",
     "app.userList.usersTitle": "Usuários",
     "app.userList.participantsTitle": "Participantes",
     "app.userList.messagesTitle": "Mensagens",
@@ -67,6 +71,10 @@
     "app.meeting.alertMeetingEndsUnderOneMinute": "Sessão será fechada em um minuto.",
     "app.meeting.alertBreakoutEndsUnderOneMinute": "Sala de apoio será fechada em um minuto.",
     "app.presentation.close": "Fechar apresentação",
+    "app.presentation.slideContent": "Conteúdo do slide",
+    "app.presentation.startSlideContent": "Início do conteúdo do slide",
+    "app.presentation.endSlideContent": "Fim do conteúdo do slide",
+    "app.presentation.emptySlideContent": "Nenhum conteúdo no slide atual",
     "app.presentation.presentationToolbar.prevSlideLabel": "Slide anterior",
     "app.presentation.presentationToolbar.prevSlideDesc": "Mudar a apresentação para o slide anterior",
     "app.presentation.presentationToolbar.nextSlideLabel": "Próximo slide",
@@ -83,8 +91,10 @@
     "app.presentation.presentationToolbar.zoomInDesc": "Aproximar a apresentação",
     "app.presentation.presentationToolbar.zoomOutLabel": "Afastar",
     "app.presentation.presentationToolbar.zoomOutDesc": "Afastar a apresentação",
+    "app.presentation.presentationToolbar.zoomReset": "Restaurar zoom",
     "app.presentation.presentationToolbar.zoomIndicator": "Percentual atual de zoom",
     "app.presentation.presentationToolbar.fitToWidth": "Ajustar à largura",
+    "app.presentation.presentationToolbar.fitToPage": "Ajustar à página",
     "app.presentation.presentationToolbar.goToSlide": "Slide {0}",
     "app.presentationUploder.title": "Apresentação",
     "app.presentationUploder.message": "Como apresentador, você tem a capacidade de carregar qualquer documento do Office ou arquivo PDF. Para melhores resultados, recomendamos o formato PDF.",
@@ -109,7 +119,12 @@
     "app.presentationUploder.conversion.generatingSvg": "Gerando imagens SVG...",
     "app.presentationUploder.conversion.pageCountExceeded": "Ops, a contagem de páginas excedeu o limite",
     "app.presentationUploder.conversion.timeout": "Ops, a conversão levou tempo demais",
+    "app.presentationUploder.isDownloadableLabel": "Não permitir download da apresentação",
+    "app.presentationUploder.isNotDownloadableLabel": "Permitir download da apresentação",
+    "app.presentationUploder.removePresentationLabel": "Remover apresentação",
+    "app.presentationUploder.setAsCurrentPresentation": "Usar apresentação",
     "app.poll.pollPaneTitle": "Enquete",
+    "app.poll.quickPollTitle": "Enquete rápida",
     "app.poll.hidePollDesc": "Ocultar menu de enquetes",
     "app.poll.customPollInstruction": "Para criar uma enquete personalizada, selecione o botão abaixo e digite as opções.",
     "app.poll.quickPollInstruction": "Selecione uma opção abaixo para iniciar uma enquete.",
@@ -119,7 +134,12 @@
     "app.poll.publishLabel": "Publicar resultados da enquete",
     "app.poll.backLabel": "Voltar para opções de enquete",
     "app.poll.closeLabel": "Fechar",
+    "app.poll.ariaInputCount": "Entrada {0} de {1}",
     "app.poll.customPlaceholder": "Adicionar opção na enquete",
+    "app.poll.noPresentationSelected": "Nenhuma apresentação selecionada! Por favor, selecione uma.",
+    "app.poll.clickHereToSelect": "Clique aqui para selecionar",
+    "app.poll.t": "Verdadeiro",
+    "app.poll.f": "Falso",
     "app.poll.tf": "Verdadeiro / Falso",
     "app.poll.y": "Sim",
     "app.poll.n": "Não",
@@ -134,7 +154,9 @@
     "app.polling.pollAnswerLabel": "Resposta da enquete {0}",
     "app.polling.pollAnswerDesc": "Selecione esta opção para votar em {0}",
     "app.failedMessage": "Desculpe-nos, estamos com problemas na conexão com o servidor",
+    "app.downloadPresentationButton.label": "Download da apresentação original",
     "app.connectingMessage": "Conectando ...",
+    "app.waitingMessage": "Desconectado. Reconectando em {0} segundos ...",
     "app.navBar.settingsDropdown.optionsLabel": "Opções",
     "app.navBar.settingsDropdown.fullscreenLabel": "Alternar para tela cheia",
     "app.navBar.settingsDropdown.settingsLabel": "Abrir configurações",
@@ -153,6 +175,7 @@
     "app.navBar.settingsDropdown.endMeetingDesc": "Encerra a sessão atual",
     "app.navBar.settingsDropdown.endMeetingLabel": "Encerrar sessão",
     "app.navBar.userListToggleBtnLabel": "Alternar lista de usuários",
+    "app.navBar.toggleUserList.ariaLabel": "Alternar usuários e mensagens",
     "app.navBar.toggleUserList.newMessages": "com notificação para novas mensagens",
     "app.navBar.recording": "Esta conferência está sendo gravada",
     "app.navBar.recording.on": "A gravação está em andamento",
@@ -173,15 +196,21 @@
     "app.actionsBar.changeStatusLabel": "Alterar status",
     "app.actionsBar.muteLabel": "Silenciar",
     "app.actionsBar.unmuteLabel": "Falar",
+    "app.actionsBar.camOffLabel": "Câmera desligada",
     "app.actionsBar.raiseLabel": "Levantar a mão",
+    "app.actionsBar.label": "Barra de ações",
+    "app.actionsBar.actionsDropdown.restorePresentationLabel": "Restaurar apresentação",
     "app.actionsBar.actionsDropdown.restorePresentationDesc": "Restaura a apresentação depois que ela foi fechada",
+    "app.screenshare.screenShareLabel" : "Compartilhamento de tela",
     "app.submenu.application.applicationSectionTitle": "Aplicação",
+    "app.submenu.application.animationsLabel": "Animações",
     "app.submenu.application.audioAlertLabel": "Alertas de áudio para bate-papo",
     "app.submenu.application.pushAlertLabel": "Alertas de pop-up para bate-papo",
     "app.submenu.application.fontSizeControlLabel": "Tamanho da fonte",
     "app.submenu.application.increaseFontBtnLabel": "Aumentar o tamanho da fonte da aplicação",
     "app.submenu.application.decreaseFontBtnLabel": "Diminuir o tamanho da fonte da aplicação",
     "app.submenu.application.languageLabel": "Idioma da aplicação",
+    "app.submenu.application.ariaLanguageLabel": "Alterar idioma da aplicação",
     "app.submenu.application.languageOptionLabel": "Escolha o idioma",
     "app.submenu.application.noLocaleOptionLabel": "Não existem esquemas de idiomas disponíveis",
     "app.submenu.audio.micSourceLabel": "Seleção do microfone",
@@ -190,18 +219,29 @@
     "app.submenu.video.title": "Vídeo",
     "app.submenu.video.videoSourceLabel": "Seleção do vídeo",
     "app.submenu.video.videoOptionLabel": "Selecione a entrada de vídeo",
+    "app.submenu.video.videoQualityLabel": "Qualidade do vídeo",
     "app.submenu.video.qualityOptionLabel": "Escolha a qualidade do vídeo",
     "app.submenu.video.participantsCamLabel": "Visualizando webcams dos participantes",
+    "app.submenu.closedCaptions.closedCaptionsLabel": "Legendas",
     "app.submenu.closedCaptions.takeOwnershipLabel": "Assumir o controle",
     "app.submenu.closedCaptions.languageLabel": "Idioma",
     "app.submenu.closedCaptions.localeOptionLabel": "Escolha o idioma",
     "app.submenu.closedCaptions.noLocaleOptionLabel": "Nenhum esquema de idioma ativo",
     "app.submenu.closedCaptions.fontFamilyLabel": "Família da fonte",
+    "app.submenu.closedCaptions.fontFamilyOptionLabel": "Selecionar família da fonte",
     "app.submenu.closedCaptions.fontSizeLabel": "Tamanho da fonte",
+    "app.submenu.closedCaptions.fontSizeOptionLabel": "Escolha o tamanho da fonte",
     "app.submenu.closedCaptions.backgroundColorLabel": "Cor de fundo",
     "app.submenu.closedCaptions.fontColorLabel": "Cor da fonte",
     "app.submenu.closedCaptions.noLocaleSelected": "Idioma não selecionado",
     "app.submenu.participants.muteAllLabel": "Silenciar todos exceto o apresentador",
+    "app.submenu.participants.lockAllLabel": "Restringir todos os participantes",
+    "app.submenu.participants.lockItemLabel": "Participantes {0}",
+    "app.submenu.participants.lockMicDesc": "Desativa o microfone para todos os participantes bloqueados",
+    "app.submenu.participants.lockCamDesc": "Desativa a webcam para todos os participantes bloqueados",
+    "app.submenu.participants.lockPublicChatDesc": "Desativa o bate-papo público para todos os participantes bloqueados",
+    "app.submenu.participants.lockPrivateChatDesc": "Desativa o bate-papo privado para todos os participantes bloqueados",
+    "app.submenu.participants.lockLayoutDesc": "Bloqueia o layout para todos os participantes bloqueados",
     "app.submenu.participants.lockMicAriaLabel": "Bloqueia o microfone",
     "app.submenu.participants.lockCamAriaLabel": "Bloqueia a webcam",
     "app.submenu.participants.lockPublicChatAriaLabel": "Bloqueia o bate-papo público",
@@ -209,16 +249,22 @@
     "app.submenu.participants.lockLayoutAriaLabel": "Bloqueia o layout",
     "app.submenu.participants.lockMicLabel": "Microfone",
     "app.submenu.participants.lockCamLabel": "Webcam",
+    "app.submenu.participants.lockPublicChatLabel": "Bate-papo público",
+    "app.submenu.participants.lockPrivateChatLabel": "Bate-papo privado",
     "app.submenu.participants.lockLayoutLabel": "Layout",
     "app.settings.applicationTab.label": "Aplicação",
     "app.settings.audioTab.label": "Áudio",
     "app.settings.videoTab.label": "Vídeo",
+    "app.settings.closedcaptionTab.label": "Legendas",
     "app.settings.usersTab.label": "Participantes",
     "app.settings.main.label": "Configurações",
     "app.settings.main.cancel.label": "Cancelar",
     "app.settings.main.cancel.label.description": "Descartar as alterações e fechar o menu de configurações",
     "app.settings.main.save.label": "Salvar",
     "app.settings.main.save.label.description": "Salvar as alterações e fechar o menu de configurações",
+    "app.settings.dataSavingTab.label": "Economia de dados",
+    "app.settings.dataSavingTab.webcam": "Ativar webcams",
+    "app.settings.dataSavingTab.screenShare": "Ativar o compartilhamento de tela",
     "app.settings.dataSavingTab.description": "Para economizar o volume de transferência de dados, ajuste o que está sendo exibido no momento.",
     "app.switch.onLabel": "Ligar",
     "app.switch.offLabel": "Desligar",
@@ -237,6 +283,7 @@
     "app.actionsBar.actionsDropdown.createBreakoutRoomDesc": "Cria salas de apoio para dividir a sessão atual em grupos",
     "app.actionsBar.actionsDropdown.takePresenter": "Assumir papel de apresentador",
     "app.actionsBar.actionsDropdown.takePresenterDesc": "Assume o papel de apresentador",
+    "app.actionsBar.emojiMenu.statusTriggerLabel": "Definir status",
     "app.actionsBar.emojiMenu.awayLabel": "Ausente",
     "app.actionsBar.emojiMenu.awayDesc": "Mudar seu status para ausente",
     "app.actionsBar.emojiMenu.raiseHandLabel": "Levantar a mão",
@@ -261,6 +308,7 @@
     "app.audioNotification.audioFailedError1001": "Erro 1001: WebSocket desconectou",
     "app.audioNotification.audioFailedError1002": "Erro 1002: Não foi possível estabelecer a conexão WebSocket",
     "app.audioNotification.audioFailedError1003": "Erro 1003: Versão do navegador não suportada",
+    "app.audioNotification.audioFailedError1004": "Erro 1004: Falha na chamada (causa={0})",
     "app.audioNotification.audioFailedError1005": "Erro 1005: Chamada encerrada inesperadamente",
     "app.audioNotification.audioFailedError1006": "Erro 1006: Tempo de espera da chamada expirou",
     "app.audioNotification.audioFailedError1007": "Erro 1007: Negociação ICE falhou",
@@ -268,14 +316,25 @@
     "app.audioNotification.audioFailedError1009": "Erro 1009: Não foi possível recuperar as informações do servidor STUN/TURN",
     "app.audioNotification.audioFailedError1010": "Erro 1010: Negociação ICE expirou",
     "app.audioNotification.audioFailedError1011": "Erro 1011: Coleta de candidatos ICE expirou",
+    "app.audioNotification.audioFailedError1012": "Erro 1012: Conexão ICE fechou",
     "app.audioNotification.audioFailedMessage": "Conexão de áudio não pôde ser estabelecida",
+    "app.audioNotification.mediaFailedMessage": "getUserMicMedia falhou, somente origens seguras são permitidas",
     "app.audioNotification.closeLabel": "Fechar",
+    "app.audioNotificaion.reconnectingAsListenOnly": "O microfone foi bloqueado para participantes, você está sendo conectado como ouvinte",
+    "app.breakoutJoinConfirmation.title": "Entrar na sala de apoio",
     "app.breakoutJoinConfirmation.message": "Gostaria de participar",
     "app.breakoutJoinConfirmation.confirmLabel": "Entrar",
+    "app.breakoutJoinConfirmation.confirmDesc": "Entrar na sala de apoio",
     "app.breakoutJoinConfirmation.dismissLabel": "Cancelar",
+    "app.breakoutJoinConfirmation.dismissDesc": "Fechar e rejeitar o convite a sala de apoio",
+    "app.breakoutJoinConfirmation.freeJoinMessage": "Escolha uma sala de apoio para entrar",
+    "app.breakoutTimeRemainingMessage": "Tempo restante na sala de apoio: {0}",
+    "app.breakoutWillCloseMessage": "Tempo expirado. A sala de apoio será fechada em breve",
+    "app.calculatingBreakoutTimeRemaining": "Calculando o tempo restante...",
     "app.audioModal.microphoneLabel": "Microfone",
     "app.audioModal.listenOnlyLabel": "Somente ouvir",
     "app.audioModal.audioChoiceLabel": "Como você gostaria de se juntar ao áudio?",
+    "app.audioModal.iOSBrowser": "Áudio/Vídeo não é suportado",
     "app.audioModal.iOSErrorDescription": "No momento, o Chrome não suporta áudio e vídeo para iOS.",
     "app.audioModal.iOSErrorRecommendation": "Recomendamos o Safari para usar o iOS.",
     "app.audioModal.audioChoiceDesc": "Selecione como se juntar ao áudio nesta reunião",
@@ -287,6 +346,7 @@
     "app.audioModal.echoTestTitle": "Este é um teste de som privado. Fale algumas palavras. Você consegue escutar o som?",
     "app.audioModal.settingsTitle": "Alterar as configurações de áudio",
     "app.audioModal.helpTitle": "Houve um problema com seus dispositivos de mídia",
+    "app.audioModal.helpText": "Você autorizou o acesso ao seu microfone? Observe que uma caixa de diálogo deve abrir assim que você tentar habilitar o microfone solicitando permissão de acesso aos dispositivos de mídia. Por favor autorize para que a aplicação tenha acesso ao seu microfone. Se isso não funcionar, tente alterar a permissão do microfone nas configurações do seu navegador.",
     "app.audioModal.connecting": "Conectando",
     "app.audioModal.connectingEchoTest": "Conectando ao teste de áudio",
     "app.audioManager.joinedAudio": "Você se juntou à conferência de áudio",
@@ -299,6 +359,8 @@
     "app.audioManager.mediaError": "Erro: Houve um problema ao consultar seus dispositivos de mídia",
     "app.audio.joinAudio": "Ativar áudio",
     "app.audio.leaveAudio": "Desativar áudio",
+    "app.audio.enterSessionLabel": "Entrar na sessão",
+    "app.audio.playSoundLabel": "Tocar som de teste",
     "app.audio.backLabel": "Voltar",
     "app.audio.audioSettings.titleLabel": "Configurações de áudio",
     "app.audio.audioSettings.descriptionLabel": "Uma caixa de diálogo aparecerá em seu navegador, onde você deve concordar em compartilhar o seu microfone.",
@@ -309,6 +371,7 @@
     "app.audio.listenOnly.backLabel": "Voltar",
     "app.audio.listenOnly.closeLabel": "Fechar",
     "app.audio.permissionsOverlay.title": "Permitir que o BigBlueButton acesse seus dispositivos de mídia",
+    "app.audio.permissionsOverlay.hint": "Precisamos que você nos permita acessar seus dispositivos de mídia habilitar seu microfone",
     "app.error.removed": "Você foi removido da conferência",
     "app.error.meeting.ended": "Você saiu da conferência",
     "app.dropdown.close": "Fechar",
@@ -319,12 +382,25 @@
     "app.error.400": "400 Solicitação incorreta",
     "app.error.leaveLabel": "Faça o login novamente",
     "app.guest.waiting": "Esperando aprovação para participar",
+    "app.userList.guest.waitingUsers": "Usuários aguardando",
+    "app.userList.guest.waitingUsersTitle": "Gerenciamento de usuários",
+    "app.userList.guest.optionTitle": "Usuários aguardando revisão",
+    "app.userList.guest.allowAllAuthenticated": "Permitir todos os usuários autorizados",
+    "app.userList.guest.allowAllGuests": "Permitir todos os convidados",
+    "app.userList.guest.allowEveryone": "Permitir todos",
+    "app.userList.guest.denyEveryone": "Rejeitar todos",
+    "app.userList.guest.pendingUsers": "{0} usuários aguardando",
+    "app.userList.guest.pendingGuestUsers": "{0} usuários convidados aguardando",
+    "app.userList.guest.pendingGuestAlert": "entrou na sessão e está aguardando sua permissão.",
+    "app.toast.breakoutRoomEnded": "A sala de apoio encerrou. Por favor, acione o áudio novamente.",
     "app.toast.chat.public": "Nova mensagem de Bate-papo público",
     "app.toast.chat.private": "Nova mensagem de Bate-papo privado",
     "app.toast.chat.system": "Sistema",
     "app.notification.recordingStart": "Esta reunião está sendo gravada",
     "app.notification.recordingStop": "Esta reunião não está mais sendo gravada",
+    "app.notification.recordingAriaLabel": "Tempo de gravação",
     "app.shortcut-help.title": "Atalhos de teclado",
+    "app.shortcut-help.accessKeyNotAvailable": "Chaves de acesso não estão disponíveis",
     "app.shortcut-help.comboLabel": "Combo",
     "app.shortcut-help.functionLabel": "Função",
     "app.shortcut-help.closeLabel": "Fechar",
@@ -332,14 +408,25 @@
     "app.shortcut-help.openOptions": "Abrir Configurações",
     "app.shortcut-help.toggleUserList": "Abrir / fechar a lista de usuários",
     "app.shortcut-help.toggleMute": "Mudo / Falar",
+    "app.shortcut-help.togglePublicChat": "Alternar bate-papo público (a lista de usuários deve estar aberta)",
+    "app.shortcut-help.hidePrivateChat": "Esconder bate-papo privado",
+    "app.shortcut-help.closePrivateChat": "Fechar bate-papo privado",
+    "app.shortcut-help.openActions": "Abrir menu de ações",
+    "app.shortcut-help.openStatus": "Abrir menu de status",
     "app.lock-viewers.title": "Restringir participantes",
+    "app.lock-viewers.description": "Estas opções permitem que você restrinja aos participantes o acesso a funcionalidades específicas (as restrições não se aplicam aos moderadores)",
     "app.lock-viewers.featuresLable": "Funcionalidade",
+    "app.lock-viewers.lockStatusLabel": "Status de restrição",
     "app.lock-viewers.webcamLabel": "Webcam",
     "app.lock-viewers.otherViewersWebcamLabel": "Ver webcam de outros participantes",
     "app.lock-viewers.microphoneLable": "Microfone",
+    "app.lock-viewers.PublicChatLabel": "Bate-papo público",
+    "app.lock-viewers.PrivateChatLable": "Bate-papo privado",
     "app.lock-viewers.Layout": "Layout",
     "app.recording.startTitle": "Iniciar gravação",
-    "app.recording.stopTitle": "Parar gravação",
+    "app.recording.stopTitle": "Pausar gravação",
+    "app.recording.startDescription": "(Você pode clicar novamente no botão de gravação para pausar a gravação)",
+    "app.recording.stopDescription": "Você tem certeza que deseja pausar a gravação? (Você pode retomar a gravação a qualquer momento clicando novamente no botão de gravação)",
     "app.videoPreview.cameraLabel": "Câmera",
     "app.videoPreview.cancelLabel": "Cancelar",
     "app.videoPreview.closeLabel": "Fechar",
@@ -350,6 +437,7 @@
     "app.videoPreview.webcamNotFoundLabel": "Webcam não encontrada",
     "app.video.joinVideo": "Compartilhar webcam",
     "app.video.leaveVideo": "Parar de compartilhar webcam",
+    "app.video.iceCandidateError": "Erro ao adicionar o candidato ICE",
     "app.video.iceConnectionStateError": "Erro 1107: Negociação ICE falhou",
     "app.video.permissionError": "Erro ao compartilhar webcam. Por favor verifique as permissões",
     "app.video.sharingError": "Erro ao compartilhar a webcam",
@@ -363,8 +451,10 @@
     "app.video.videoDisabled": "Webcam está desabilitada",
     "app.video.videoButtonDesc": "Botão de habilitar vídeo",
     "app.video.videoMenu": "Menu de vídeo",
+    "app.video.videoMenuDisabled": "Webcam desativada nas configurações",
     "app.video.videoMenuDesc": "Abra o menu de vídeo",
     "app.video.chromeExtensionError": "Você deve instalar o seguinte:",
+    "app.video.chromeExtensionErrorLink": "esta extensão do Chrome",
     "app.video.stats.title": "Estatísticas de conexão",
     "app.video.stats.packetsReceived": "Pacotes recebidos",
     "app.video.stats.packetsSent": "Pacotes enviados",
@@ -378,6 +468,7 @@
     "app.video.stats.rtt": "RTT",
     "app.video.stats.encodeUsagePercent": "Uso de codificação",
     "app.video.stats.currentDelay": "Atraso atual",
+    "app.fullscreenButton.label": "Alternar {0} para tela cheia",
     "app.deskshare.iceConnectionStateError": "Erro 1108: Falha na conexão ICE ao compartilhar a tela",
     "app.sfu.mediaServerConnectionError2000": "Erro 2000: Não foi possível conectar ao servidor de mídia",
     "app.sfu.mediaServerOffline2001": "Erro 2001: Servidor de mídia está offline. Por favor, tente novamente mais tarde.",
@@ -397,13 +488,18 @@
     "app.whiteboard.toolbar.tools.ellipse": "Elipse",
     "app.whiteboard.toolbar.tools.line": "Linha",
     "app.whiteboard.toolbar.tools.text": "Texto",
+    "app.whiteboard.toolbar.thickness": "Espessura da linha",
+    "app.whiteboard.toolbar.thicknessDisabled": "A espessura da linha está desativada",
     "app.whiteboard.toolbar.color": "Cores",
+    "app.whiteboard.toolbar.colorDisabled": "As cores estão desativadas",
     "app.whiteboard.toolbar.color.black": "Preto",
     "app.whiteboard.toolbar.color.white": "Branco",
     "app.whiteboard.toolbar.color.red": "Vermelho",
     "app.whiteboard.toolbar.color.orange": "Laranja",
+    "app.whiteboard.toolbar.color.eletricLime": "Verde limão",
     "app.whiteboard.toolbar.color.lime": "Verde",
     "app.whiteboard.toolbar.color.cyan": "Ciano",
+    "app.whiteboard.toolbar.color.dodgerBlue": "Azul dodger",
     "app.whiteboard.toolbar.color.blue": "Azul",
     "app.whiteboard.toolbar.color.violet": "Violeta",
     "app.whiteboard.toolbar.color.magenta": "Magenta",
@@ -412,10 +508,12 @@
     "app.whiteboard.toolbar.clear": "Limpar todas as anotações",
     "app.whiteboard.toolbar.multiUserOn": "Iniciar o modo multiusuário",
     "app.whiteboard.toolbar.multiUserOff": "Sair do modo multiusuário",
+    "app.whiteboard.toolbar.fontSize": "Lista de tamanhos de fonte",
     "app.feedback.title": "Você saiu da conferência",
     "app.feedback.subtitle": "Adoraríamos ouvir sobre sua experiência com o BigBlueButton (opcional)",
     "app.feedback.textarea": "Como podemos melhorar o BigBlueButton?",
     "app.feedback.sendFeedback": "Enviar feedback",
+    "app.feedback.sendFeedbackDesc": "Enviar um feedback e deixar a sessão",
     "app.videoDock.webcamFocusLabel": "Focar",
     "app.videoDock.webcamFocusDesc": "Focar a webcam selecionada",
     "app.videoDock.webcamUnfocusLabel": "Desfocar",
@@ -423,24 +521,37 @@
     "app.invitation.title": "Convite para sala de apoio",
     "app.invitation.confirm": "Convidar",
     "app.createBreakoutRoom.title": "Salas de apoio",
+    "app.createBreakoutRoom.ariaTitle": "Esconder salas de apoio",
     "app.createBreakoutRoom.breakoutRoomLabel": "Salas de apoio {0}",
     "app.createBreakoutRoom.generatingURL": "Gerando URL",
     "app.createBreakoutRoom.generatedURL": "Gerada",
     "app.createBreakoutRoom.duration": "Duração {0}",
     "app.createBreakoutRoom.room": "Sala {0}",
+    "app.createBreakoutRoom.notAssigned": "Não atribuído ({0})",
+    "app.createBreakoutRoom.join": "Entrar na sala",
     "app.createBreakoutRoom.joinAudio": "Ativar áudio",
     "app.createBreakoutRoom.returnAudio": "Retornar áudio",
     "app.createBreakoutRoom.confirm": "Criar",
+    "app.createBreakoutRoom.numberOfRooms": "Número de salas",
     "app.createBreakoutRoom.durationInMinutes": "Duração (minutos)",
+    "app.createBreakoutRoom.randomlyAssign": "Atribuir aleatoriamente",
+    "app.createBreakoutRoom.endAllBreakouts": "Encerrar todas as salas de apoio",
     "app.createBreakoutRoom.roomName": "{0} (Sala - {1})",
     "app.createBreakoutRoom.doneLabel": "Pronto",
     "app.createBreakoutRoom.nextLabel": "Próximo",
+    "app.createBreakoutRoom.minusRoomTime": "Aumentar tempo de sala de apoio",
     "app.createBreakoutRoom.addParticipantLabel": "+ adicionar participante",
     "app.createBreakoutRoom.freeJoin": "Permitir que os usuários escolham uma sala de apoio para entrar",
     "app.createBreakoutRoom.leastOneWarnBreakout": "Você precisa atribuir pelo menos um usuário a uma sala de apoio",
     "app.createBreakoutRoom.modalDesc": "Complete os passos abaixo para criar salas de apoio na sessão",
     "app.externalVideo.start": "Compartilhar vídeo",
-    "app.externalVideo.close": "Fechar"
+    "app.externalVideo.stop": "Interromper compartilhamento do vídeo",
+    "app.externalVideo.title": "Compartilhar um vídeo do YouTube",
+    "app.externalVideo.input": "URL do vídeo no YouTube",
+    "app.externalVideo.urlError": "Esta não é uma URL válida para um vídeo no YouTube",
+    "app.externalVideo.close": "Fechar",
+    "app.actionsBar.actionsDropdown.shareExternalVideo": "Compartilhar vídeo do YouTube",
+    "app.actionsBar.actionsDropdown.stopShareExternalVideo": "Interromper compartilhamento do vídeo"
 
 }
 
diff --git a/bigbluebutton-html5/private/locales/uk_UA.json b/bigbluebutton-html5/private/locales/uk_UA.json
index 10d7b86b10d821763edf625a14b443124569320f..679ed82a26a2d2b35b1ce507f377e70212bd48ee 100644
--- a/bigbluebutton-html5/private/locales/uk_UA.json
+++ b/bigbluebutton-html5/private/locales/uk_UA.json
@@ -404,7 +404,6 @@
     "app.lock-viewers.PrivateChatLable": "Приватний чат",
     "app.lock-viewers.Layout": "Розміщення вікон",
     "app.recording.startTitle": "Почати запис",
-    "app.recording.stopTitle": "Зупинити запис",
     "app.recording.startDescription": "(Ви зможете натиснути цю кнопку пізніше, щоб зробити паузу запису.)",
     "app.recording.stopDescription": "Ви впевнені що хочете зробити паузу запису?  (Ви зможете відновити запис, натиснувши кнопку запису знову.)",
     "app.videoPreview.cameraLabel": "Камера",
@@ -520,7 +519,6 @@
     "app.createBreakoutRoom.doneLabel": "Готово",
     "app.createBreakoutRoom.nextLabel": "Далі",
     "app.createBreakoutRoom.minusRoomTime": "Збільшити час кімнати",
-    "app.createBreakoutRoom.addRoomTime": "Зменшити час кімнати",
     "app.createBreakoutRoom.addParticipantLabel": "+ Додати учасника",
     "app.createBreakoutRoom.freeJoin": "Дозволити користувачам обирати кімнату самостійно",
     "app.createBreakoutRoom.leastOneWarnBreakout": "Щонайменш один користувач повинен бути в кімнаті.",
diff --git a/bigbluebutton-html5/private/locales/zh_CN.json b/bigbluebutton-html5/private/locales/zh_CN.json
index b1df5952508d6f49fa5ae640439dd7903ad024cd..9f819a1fc9cf8a3e9900b125545aa7af0b8fc2ae 100644
--- a/bigbluebutton-html5/private/locales/zh_CN.json
+++ b/bigbluebutton-html5/private/locales/zh_CN.json
@@ -404,7 +404,6 @@
     "app.lock-viewers.PrivateChatLable": "私聊",
     "app.lock-viewers.Layout": "页面布局",
     "app.recording.startTitle": "开始录制",
-    "app.recording.stopTitle": "结束录制",
     "app.recording.startDescription": "(您稍后可以再一次点击录制按钮以暂停录制。)",
     "app.recording.stopDescription": "您确定要暂停录制吗?(您可以再一次点击录制按钮以重新录制。)",
     "app.videoPreview.cameraLabel": "摄像头",
@@ -520,7 +519,6 @@
     "app.createBreakoutRoom.doneLabel": "完成",
     "app.createBreakoutRoom.nextLabel": "下一步",
     "app.createBreakoutRoom.minusRoomTime": "延长分组讨论时间",
-    "app.createBreakoutRoom.addRoomTime": "缩短分组讨论时间",
     "app.createBreakoutRoom.addParticipantLabel": "+ 添加参会人",
     "app.createBreakoutRoom.freeJoin": "允许人员选择并加入分组讨论",
     "app.createBreakoutRoom.leastOneWarnBreakout": "您必须至少指派一位人员到每一个分组讨论",
diff --git a/bigbluebutton-web/.gitignore b/bigbluebutton-web/.gitignore
index 753212053b60654efaecbc7d3668aef5edf182c1..3b68951979812d13e426a2f88ae69034ac39a1ed 100755
--- a/bigbluebutton-web/.gitignore
+++ b/bigbluebutton-web/.gitignore
@@ -7,3 +7,6 @@ target/*
 bin/*
 plugins/*
 /bin/
+build/
+logs/
+
diff --git a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
index eb3dbcc3c44a6588c9f7666d0e9876b78f7946c1..c69ac37b87ed2e46f7b94c965a5264f83bc1b50d 100755
--- a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
+++ b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties
@@ -84,6 +84,11 @@ defineTextThreshold=2000
 #------------------------------------
 numConversionThreads=2
 
+#----------------------------------------------------
+# Conversion of the presentation slides to SWF to be
+# used in the Flash client
+swfSlidesRequired=true
+
 #----------------------------------------------------
 # Additional conversion of the presentation slides to SVG
 # to be used in the HTML5 client
diff --git a/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml b/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml
index 7f8f2a6d6934a128199e119b96e87b75036a0af8..3de17fe5a92d06685a7b27783c9214349c59d7e8 100755
--- a/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml
+++ b/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml
@@ -99,6 +99,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
         <property name="maxSwfFileSize" value="${MAX_SWF_FILE_SIZE}"/>
         <property name="maxConversionTime" value="${maxConversionTime}"/>
         <property name="swfSlidesGenerationProgressNotifier" ref="swfSlidesGenerationProgressNotifier"/>
+        <property name="swfSlidesRequired" value="${swfSlidesRequired}"/>
         <property name="svgImagesRequired" value="${svgImagesRequired}"/>
         <property name="generatePngs" value="${generatePngs}"/>
     </bean>