<?php
/**
* Copyright (C) 2022, 2024 Double Bastion LLC
*
* This file is part of Roundpin, which is licensed under the
* GNU Affero General Public License Version 3.0. The license terms
* are detailed in the "LICENSE.txt" file located in the root directory.
*
* This is a modified version of the original file "index.html",
* first modified in 2020. The copyright notice for the original
* content follows:
/*
Cyber Mega Phone 2K
Copyright (C) 2017 Digium, Inc.
This program is free software, distributed under the terms of the
MIT License. See the LICENSE file at the top of the source tree.
*/
session_start();
header('Set-Cookie: PHPSESSID= ' . session_id() . '; SameSite=strict; Secure=true; HttpOnly=true;');
$retrievedstringinit = $_GET['param'];
$retrievedstring = hex2bin($retrievedstringinit);
if ($retrievedstring != '') {
define('ACCESSCONST', TRUE);
require('../src/db-connect.php');
// Extract the secret from the configuration file
$configfilestring = file_get_contents('../src/roundpin-config.php');
if (preg_match_all('[include|include_once|require|require_once]', $configfilestring) != 0) {
if (strpos($configfilestring, "'") !== false) {
$continit = explode("'", $configfilestring);
$configfilepath = $continit[1];
} elseif (strpos($configfilestring, "\"") !== false) {
$continit = explode("\"", $configfilestring);
$configfilepath = $continit[1];
}
$configfilelines = file($configfilepath);
if (count($configfilelines) != 0) {
foreach ($configfilelines as $keyfile => $valuefile) {
if (strpos($valuefile, "\$secret") !== false) {
$secret_init = explode("'", $valuefile);
$secretfin = $secret_init[1];
}
}
}
} else {
$configfilelines = file('../src/roundpin-config.php');
if (count($configfilelines) != 0) {
foreach ($configfilelines as $keyfile => $valuefile) {
if (strpos($valuefile, "\$secret") !== false) {
$secretinit = explode("'", $valuefile);
$secretfin = $secretinit[1];
}
}
}
}
// Decrypt the extension used for external access to conference and the username of the user who created the link
$componentuserext = explode(':', $retrievedstring);
$encpwdinusext = $componentuserext[0];
$ivkey = $componentuserext[1];
$userExtDec = openssl_decrypt($encpwdinusext, 'AES-256-CBC', $secretfin, false, $ivkey);
$userExtDecComp = explode("|", $userExtDec);
$userName = $userExtDecComp[0];
$extForExtern = $userExtDecComp[1];
$retrievedVideoConfExt = $userExtDecComp[2];
$rtrvdVidConferenceTag = $userExtDecComp[3];
$retrievedWebSocketPath = $userExtDecComp[4];
$retrievedSipUsername = $extForExtern;
// Get the relevant information for the user who created the external access link
$query0 = $mysqli->query("SELECT id, userrole, username, wss_server, stun_server, enabled FROM app_users WHERE (userrole = 'admin' OR userrole = 'superadmin') AND BINARY username = '$userName' AND enabled = 1");
$queryres = $query0->fetch_array();
$userID = $queryres[0];
$retrievedWssServer = $queryres[3];
$retrievedStunServer = $queryres[4];
$enabled = 1;
$query1 = $mysqli->prepare("SELECT id, userrole, username, enabled FROM app_users WHERE (userrole = 'admin' OR userrole = 'superadmin')
AND BINARY username = ? AND enabled = ?");
$query1->bind_param("si", $userName, $enabled);
$query1->execute();
$query1res = $query1->get_result()->fetch_assoc();
if (!$query1res) { exit(); }
// Get the SIP password from the 'external_users' table
$query2 = $mysqli->prepare("SELECT id, userid, exten_for_external, exten_for_ext_pass FROM external_users WHERE userid = ? AND exten_for_external = ? AND conf_extension = ?");
$query2->bind_param("iss", $userID, $extForExtern, $retrievedVideoConfExt);
$query2->execute();
// $extqueryres = $query2->get_result()->fetch_array();
$extqueryres = $query2->get_result()->fetch_assoc();
if (!$extqueryres) { exit(); }
$extensionPass = $extqueryres['exten_for_ext_pass'];
// Decrypt the SIP password
$componentpkey = explode(':', $extensionPass);
$psswdaddedkey = file_get_contents('../restr/'.$userName.'/externalext/'.$extForExtern);
$encpwdinsip = $componentpkey[0];
$ivkeysip = $componentpkey[1];
$retrievedSipPassword = openssl_decrypt($encpwdinsip, 'AES-256-CBC', $psswdaddedkey, false, $ivkeysip);
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Roundpin Video Conference</title>
<link rel="stylesheet" type="text/css" href="css/conference-phone.css">
<link rel="stylesheet" type="text/css" href="../fonts/font-awesome-4.7.0/css/font-awesome.min.css"/>
<link rel="stylesheet" type="text/css" href="../css/jeegoo-1.0.0.min.css"/>
<link rel="shortcut icon" type="image/svg" href="../images/favicon.svg" />
<script type="text/javascript" src="js/sdp-interop-sl-1.4.0.min.js"></script>
<script type="text/javascript" src="js/jssip-3.9.1.min.js"></script>
<script type="text/javascript" src="js/utils.min.js"></script>
<script type="text/javascript" src="../js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="js/conference-phone-external.js"></script>
<script type="text/javascript" src="../js/moment-with-locales-2.24.0.min.js"></script>
<script type="text/javascript" src="../js/jquery.jeegoopopup.1.0.0.min.js"></script>
<script type="text/javascript" src="../js/fix-webm-duration.js"></script>
<script type="text/javascript" src="../js/crypto-js-4.1.1.min.js"></script>
<script type="text/javascript" src="../js/jsencrypt.min.js"></script>
<script type="text/javascript">
//JsSIP.debug.enable('*');
let sip_username = "<?php print_r($retrievedSipUsername); ?>";
let sip_password = "<?php print_r($retrievedSipPassword); ?>";
let wss_server = "<?php print_r($retrievedWssServer); ?>";
let websocketpath = "<?php print_r($retrievedWebSocketPath); ?>";
let stun_server = "<?php print_r($retrievedStunServer); ?>";
let videoConfExtension = "<?php print_r($retrievedVideoConfExt); ?>";
let videoConfTag = "<?php print_r($rtrvdVidConferenceTag); ?>";
let encExtenPass = "<?php print_r($extensionPass); ?>";
let encExtenPassEnc = encodeURIComponent(encExtenPass);
let showConfUNames = 0;
let profileName = '';
let userRole = 'regular_user';
let userNameDisplay = 0;
let userDescription = '';
// Check if window is visible to hide notifications, if needed
document.addEventListener('visibilitychange', function() { if (document.hidden) { vcDocIsVisible = false; } else { vcDocIsVisible = true; }});
window.onload = function() {
var remoteCheck = 0;
var sipPassDec = '';
// Check if the current external participant is banned from the current video conference
$.ajax({
type: "POST",
url: "../src/get-external-user-video-conf-restrictions.php",
dataType: "JSON",
data: {
crvconfextension: videoConfExtension,
crsipusername: sip_username,
encextenpass: encExtenPass
},
success: function(response) {
if (response.notbanned == 'success') {
$.jeegoopopup.close();
var html = "<div id=\"enterVConfUName\">";
html += "<div id=\"extVConfNameDesc\"><img id=\"vConfPrefLogo\" src=\"../images/small-logo.svg\" />";
html += "<div id=\"vcPopupTitle\"><i class=\"fa fa-video-camera\" aria-hidden=\"true\"></i> Roundpin Video Conference</div>";
html += "<div id=\"vcPopupText\">Enter the name that the other participants to the conference will see under your video window (you can leave this empty if you prefer):</div></div>";
html += "<div><input type=\"text\" id=\"extVConfName\"></div>";
html += "<div id=\"showVCPNchckbx\"><input type=\"checkbox\" id=\"showVCPartNames\"><label id=\"showVCPNmlabel\" for=\"showVCPartNames\">Show participants' names under their video windows.</label></div>";
html += "</div>";
$.jeegoopopup.open({
html: html,
width: 300,
height: 310,
center: true,
scrolling: 'no',
skinClass: 'jg_popup_basic',
contentClass: 'enterVConfUser',
overlay: true,
opacity: 50,
draggable: true,
resizable: false,
fadeIn: 0
});
$("#jg_popup_b").append("<div id=\"saveVConfName\"><button id=\"ConfirmSaveBtn\">Save</button></div>");
$("#extVConfName").focus();
$("#ConfirmSaveBtn").click(function () {
var showUserNames = ($("#showVCPartNames").is(':checked')) ? "1" : "0";
showConfUNames = parseInt(showUserNames);
var eVConfDisplayName = $("#extVConfName").val();
if (/^[a-zA-Z0-9\_\-\'\s]*$/.test(eVConfDisplayName)) {
profileName = eVConfDisplayName;
if (profileName != '') { userNameDisplay = 1; } else { userNameDisplay = 0; }
} else {
profileName = '';
alert("The name that you entered is not valid. Valid characters are a-z, A-Z, 0-9, _, -, ', empty space and the empty string (no characters).");
}
if (profileName == '') { return false; }
$.ajax({
type: "POST",
url: "../src/save-external-user-preferences.php",
dataType: "JSON",
data: {
vconfextension: sip_username,
encextenpass: encExtenPass,
conferenceext: videoConfExtension,
evconfdisplayname: profileName,
showusernames: showConfUNames
},
success: function(response) {
// Generate a new text chat key pair for the current video conference participant
var cryptousr = new JSEncrypt({default_key_size: 1024});
cryptousr.getKey();
var crVConfUserPubKey = cryptousr.getPublicKey();
crVConfUserPrivKey = cryptousr.getPrivateKey();
$.ajax({
type: "POST",
url: "../src/save-text-chat-pub-key-ext.php",
dataType: "JSON",
data: {
currentextension: sip_username,
currentchatpubkey: crVConfUserPubKey,
vconfextension: sip_username,
encextenpass: encExtenPass,
conferenceext: videoConfExtension
},
success: function() {
},
error: function() {
alert("An error occurred while attempting to save the new text chat public key!");
}
});
// Generate a RSA key pair for the video conference extension if it hasn't been already generated by a participant who entered the conference earlier
var crypto = new JSEncrypt({default_key_size: 1024});
crypto.getKey();
var crVConfChatPubKey = crypto.getPublicKey();
var crVConfChatPrivKey = crypto.getPrivateKey();
$.ajax({
type: "POST",
url: "../src/save-text-chat-vconf-keys-ext.php",
dataType: "JSON",
data: {
currentvconfext: videoConfExtension,
currentvconfpubkey: crVConfChatPubKey,
currentvconfprivkey: crVConfChatPrivKey,
vconfextension: sip_username,
encextenpass: encExtenPass
},
success: function() {
},
error: function() {
alert("An error occurred while trying to save the new text chat public key!");
}
});
// Remove the files received during text chat, from the 'uploads' directory of the current user
$.ajax({
type: "POST",
url: "../src/remove-text-chat-uploaded-files-vconf-external.php",
dataType: "JSON",
data: {
vidconfextension: videoConfExtension,
vconfextension: sip_username,
encextenpass: encExtenPass
},
success: function(resresult) {
if (resresult.note != 'success') {
alert("An error occurred while trying to empty the 'uploads' directory!");
}
},
error: function(resresult) {
alert("An error occurred while attempting to empty the 'uploads' directory!");
}
});
// Show dialpad
function dtmfMenuShow() {
$.jeegoopopup.close();
var leftPos = event.pageX - 90;
var topPos = event.pageY + 28;
if ($(window).width() < 680) {
leftPos = event.pageX - 50;
}
var html = "<div id=\"sendPinDialPad\">";
html += "<div><input type=\"text\" id=\"dialText\" class=\"dialTextInput\"></div>";
html += "<table cellspacing=10 cellpadding=0 style=\"margin-left:auto; margin-right: auto\">";
html += "<tr><td><button class=dtmfButtons onclick=\"phone.dtmfSend('1');new Audio('../sounds/dtmf.ogg').play();\"><div>1</div><span> </span></button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('2');new Audio('../sounds/dtmf.ogg').play();\"><div>2</div><span>ABC</span></button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('3');new Audio('../sounds/dtmf.ogg').play();\"><div>3</div><span>DEF</span></button></td></tr>";
html += "<tr><td><button class=dtmfButtons onclick=\"phone.dtmfSend('4');new Audio('../sounds/dtmf.ogg').play();\"><div>4</div><span>GHI</span></button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('5');new Audio('../sounds/dtmf.ogg').play();\"><div>5</div><span>JKL</span></button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('6');new Audio('../sounds/dtmf.ogg').play();\"><div>6</div><span>MNO</span></button></td></tr>";
html += "<tr><td><button class=dtmfButtons onclick=\"phone.dtmfSend('7');new Audio('../sounds/dtmf.ogg').play();\"><div>7</div><span>PQRS</span></button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('8');new Audio('../sounds/dtmf.ogg').play();\"><div>8</div><span>TUV</span></button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('9');new Audio('../sounds/dtmf.ogg').play();\"><div>9</div><span>WXYZ</span></button></td></tr>";
html += "<tr><td><button class=dtmfButtons onclick=\"phone.dtmfSend('*');new Audio('../sounds/dtmf.ogg').play();\">*</button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('0');new Audio('../sounds/dtmf.ogg').play();\">0</button></td>";
html += "<td><button class=dtmfButtons onclick=\"phone.dtmfSend('#');new Audio('../sounds/dtmf.ogg').play();\">#</button></td></tr>";
html += "</table>";
html += "</div>";
$.jeegoopopup.open({
html: html,
width: 165,
height: 270,
left: leftPos,
top: topPos,
scrolling: 'no',
skinClass: 'jg_popup_basic',
overlay: true,
opacity: 0,
draggable: true,
resizable: false,
fadeIn: 0
});
$(window).resize(function() {
$.jeegoopopup.width(175).height(280);
$.jeegoopopup.center();
});
$("#jg_popup_overlay").click(function() { $.jeegoopopup.close(); });
$(window).on('keydown', function(event) { if (event.key == "Escape") { $.jeegoopopup.close(); } });
}
// Create media control buttons
function createMediaControls(video, strid) {
let controls = document.createElement("div");
controls.className = "media-controls";
// Hangup
if (video.srcObject.local == true) {
let hangupBtn = document.createElement("button");
hangupBtn.className = "mediaControlBtn";
hangupBtn.id = "hangupConf";
hangupBtn.innerHTML = '<i class="fa fa-power-off" aria-hidden="true" title="Hangup"></i>';
hangupBtn.onclick = function() {
if (confirm("Do you really want to leave the conference ?")) {
try { phone.disconnect(); } catch(e) { return; }
window.close();
document.getElementsByTagName("body")[0].innerHTML = '<h4 style="text-align:center;color:#595959;">You have closed the video conference call !</h4>';
}
}
controls.appendChild(hangupBtn);
}
// Open keypad
if (video.srcObject.local == true) {
let sendPin = document.createElement("button");
sendPin.className = "mediaControlBtn";
sendPin.id = "sendPinBtn";
sendPin.innerHTML = '<i class="fa fa-keyboard-o" aria-hidden="true" title="Show Keypad"></i>';
sendPin.onclick = function() { dtmfMenuShow(); }
controls.appendChild(sendPin);
}
// Public conference messaging
if (video.srcObject.local == true) {
let textChat = document.createElement("button");
textChat.className = "mediaControlBtn";
textChat.id = "textChatBtn";
textChat.innerHTML = '<i class="fa fa-commenting-o" aria-hidden="true" title="Send Public Message..."></i>';
textChat.onclick = function() {
if (messageWindowState != 'closed') { alert("The public messaging window is already open!"); return; }
var chathtml = "<div id=\"publicTextMessages\">";
chathtml += "<div id=\"windowCtrls\"><img id=\"closeImg\" src=\"../images/3_close.svg\" title=\"Close\"><img id=\"maximizeImg\" src=\"../images/2_maximize.svg\" title=\"Maximize\"><img id=\"restoreImg\" src=\"../images/4_restore.svg\" title=\"Restore\"><img id=\"minimizeImg\" src=\"../images/1_minimize.svg\" title=\"Minimize\"><img id=\"publicMessageImg\" src=\"../images/PublicMessage.svg\" title=\"Public Message\"></div>";
chathtml += "<div id=\"dragPubMessageWindow\" style=\"display:block;position:absolute;width:100%;height:10px;top:4px;text-align:center;z-index:20;\"><i id=\"dragPublicMWindow\" class=\"fa fa-ellipsis-h\" aria-hidden=\"true\" title=\"Drag Button\" style=\"display:block;position:relative;margin: 0px auto;color:#d0d0d0;font-size:17px;cursor:grab;\"></i></div>";
chathtml += "<div id='pubMTopBar' style='display:block;margin: 8px auto;text-align:center;padding-bottom: 6px;'><img src='../images/small-logo.svg' style='display:block;position:relative;margin: 7px auto 0px auto;padding-left:80px;user-select: none;pointer-events: none;' draggable='false'><span style='display:inline-block;margin: -6px 0px 0px 0px;font-weight:600;color:#224573;user-select: none;'>Public Text Messaging - Room: <span style='color:#379b77'>"+ videoConfTag +"</span> ("+ videoConfExtension +")</span></div>";
chathtml += "<div id=\"receiveTextMessage\"><div id='downloadVConfHst' title='Download Text Conversation'><i class='fa fa-download'></i></div></div>";
chathtml += "<div id=\"emojiMenu\" style=\"display:none\"></div>";
chathtml += "<div id=\"sendTMessage\"><table cellspacing=\"0\" cellpadding=\"0\" id=\"sendMessageTbl\"><tr><td style=\"height: 100%;width: 100%;\"><textarea id=\"sendTextMessage\" class=\"chatMessage\" placeholder=\"Type the message here, then click the paper plane button or press Ctrl + Enter to send it.\"></textarea></td>";
chathtml += "<td style=\"display:block;width:36px;margin:0px;\"><button id=\"sendTextChatBtn\" class=\"roundButtonsSpec\" title=\"Send Message\"><i class=\"fa fa-paper-plane-o\" aria-hidden=\"true\"></i></button>";
chathtml += "<button id=\"selectEmoticon\" class=\"roundButtonsSpec\" title=\"Select Emoticon\"><i class=\"fa fa-smile-o\"></i></button>";
chathtml += "<button id=\"sendFileVC\" class=\"roundButtonsSpec\" title=\"Send File\"><i class=\"fa fa-file-text-o\"></i></button></td></tr></table></div>";
chathtml += "</div>";
$("#media-views").append(chathtml);
$("#publicTextMessages").css("display", "block");
$("#restoreImg").hide();
$("#sendTextMessage").focus();
messageWindowState = 'restored';
// Bring window forward when clicking on it
$("#publicTextMessages").click(function (e) {
if (!$(e.target).hasClass('recMessageBtn')) {
$("#publicTextMessages").css("z-index", 21);
}
});
// Make the window draggable
function makePubWndDraggable(e){
window.pmdragging = {};
pmdragging.pageX0 = e.pageX;
pmdragging.pageY0 = e.pageY;
pmdragging.elem = $("#publicTextMessages");
pmdragging.offset0 = $("#publicTextMessages").offset();
function handle_dragging(e){
var left = pmdragging.offset0.left + (e.pageX - pmdragging.pageX0);
var top = pmdragging.offset0.top + (e.pageY - pmdragging.pageY0);
$(pmdragging.elem).offset({top: top, left: left});
}
function handle_mouseup(e){
$('body').off('mousemove', handle_dragging).off('mouseup', handle_mouseup);
}
$('body').on('mouseup', handle_mouseup).on('mousemove', handle_dragging);
}
$("#dragPubMessageWindow").mousedown(makePubWndDraggable);
// Open private message window when clicking on username in received message
$("#receiveTextMessage").on("click", ".recMessageBtn", function() {
var messageDestPre = $(this).text();
var messageDest = messageDestPre.slice(0, -2);
var crntExtenfirst = messageDest.split("(");
var crntExtensec = crntExtenfirst[1].split(")");
var crntTgtExten = crntExtensec[0];
if (messageWindowStatePM[crntTgtExten] == 'minimized' || messageWindowStatePM[crntTgtExten] == 'restored') {
alert("The private messaging window for this conference participant is already open!");
} else {
phone.openPrivateMessageWindow(messageDest, crntTgtExten);
}
});
// Select emoticon
$("#selectEmoticon").click(function() {
var messageContainer = $("#emojiMenu");
var textarea = $("#sendTextMessage");
if (messageContainer.is(":visible")) { messageContainer.hide(); } else { messageContainer.show(); }
var menuBar = $("<div>");
menuBar.prop("class", "emojiButton");
var emojis = ["๐","๐","๐","๐","๐","๐
","๐","๐","๐ฆ","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐","๐ ","๐ก","๐ข","๐ฃ","๐ค","๐ฅ","๐ฆ","๐ง","๐จ","๐ฉ","๐ช","๐ซ","๐ฌ","๐ญ","๐ฎ","๐ฏ","๐ฐ","๐ฑ","๐ฒ","๐ณ","๐ด","๐ต","๐ถ","๐ท","๐","๐","๐","๐","๐ค","๐ค","๐ค","๐ค","๐ค","๐ค","๐ค ","๐คก","๐คข","๐คฃ","๐คค","๐คฅ","๐คง","๐คจ","๐คฉ","๐คช","๐คซ","๐คฌ","๐คญ","๐คฏ","๐ค","๐ง"];
$.each(emojis, function(i,e){
var emoji = $("<button>");
emoji.html(e);
emoji.on('click', function() {
var i = textarea.prop('selectionStart');
var v = textarea.val();
textarea.val(v.substring(0, i) + " " + $(this).html() + v.substring(i, v.length) + " ");
messageContainer.hide();
textarea.focus();
});
menuBar.append(emoji);
});
$("#sendTextMessage,#receiveTextMessage").on('click', function(){
messageContainer.hide();
});
messageContainer.empty();
messageContainer.append(menuBar);
});
// Show the 'Download Text Conversation' button
$("#receiveTextMessage").mouseenter(function() {
$("#downloadVConfHst").css("display", "block");
});
$("#receiveTextMessage").mouseleave(function() {
$("#downloadVConfHst").css("display", "none");
});
// Download chat history
$("#downloadVConfHst").click(function() { phone.DownloadChatHistoryVC(videoConfExtension, videoConfTag); });
// Send message to video conference participants
function SendPubChatMessage() {
let textToSendRaw = $("#sendTextMessage").val().trim();
let textToSend = phone.ReformatVCMessage(textToSendRaw);
let targetUser = '';
// When a file is sent
if (sendFileCheckVC == 1) {
// $("#receiveTextMessage").after("<span id='sendFileLoaderVC'></span>");
$("#receiveTextMessage").append("<span id='sendFileLoaderVC'></span>");
sendFileChatErrVC = '';
$("#sendFileFormChatVC").on('submit', function(ev) {
ev.preventDefault();
$.ajax({
type: 'POST',
url: '../src/text-chat-vconf-upload-file-ext.php',
data: new FormData(this),
dataType: "JSON",
contentType: false,
cache: false,
processData:false,
success: function(respdata) {
var mserrorcheck = false;
if (respdata.error != '') {
sendFileChatErrVC = respdata.error;
$("#sendFileFormChatVC").remove();
$("#sendFileLoaderVC").remove();
sendFileCheckVC = 0;
alert("Error: " + respdata.error);
} else {
// Send the text message
phone.sendConfMessage(textToSendRaw, { From: profileName + " (" + sip_username + "): ", To: targetUser, handlers: {
onSuccessResponse(response) {
console.log("Message Sent: " + response);
},
onErrorResponse(response) {
mserrorcheck = true;
console.log("Message ERROR: " + response);
alert("The message couldn't be sent. Message ERROR: " + response);
},
onTransportError() {
console.log("Could not send message");
},
onRequestTimeout() {
console.log("Timeout sending message");
},
onDialogError() {
console.log("Dialog Error sending message");
},
}});
if (mserrorcheck == false) {
$("#sendTextMessage").val("");
let currentTime = new Date().toLocaleTimeString();
// Append the sent message
if (textToSend != '') {
$("#receiveTextMessage").append("<div class='textMessageSent textMsgVConf'><span class='sentMessageBtn'>"+ profileName +" ("+ sip_username +"):</span><div class='srMsgVConfcont'>"+ textToSend +"</div><div class='messageDate'>"+ currentTime +"<i class='fa fa-check sentMsTick'></i></div></div>");
}
// Append the 'Download file' section
let currentflTime = new Date().toLocaleTimeString();
$("#receiveTextMessage").append("<div class='textMessageSent textMsgVConf'><span class='sentMessageBtn'>"+ profileName +" ("+ sip_username +"):</span><div class='srMsgVConfcont'>Download file: <a href='../src/download-sent-chat-file-ext.php?sipusername="+ sip_username +"&encextenpass="+ encExtenPassEnc +"&destSipUser="+ videoConfExtension +"&sentFlNm="+ upFileNameVC +"' target='_blank'>"+ upFileNameVC +"</a></div><div class='messageDate'>"+ currentflTime +"</div></div>");
}
$("#sendFileFormChatVC").remove();
$("#sendFileLoaderVC").remove();
}
},
error: function(respdata) {
$("#sendFileFormChatVC").remove();
$("#sendFileLoaderVC").remove();
alert("An error occurred while sending the file!");
}
});
});
$("#sendFileFormChatVC").submit();
} else {
var mserrorcheckwf = false;
// Send the text message
phone.sendConfMessage(textToSendRaw, { From: profileName + " (" + sip_username + "): ", To: targetUser, handlers: {
onSuccessResponse(response) {
console.log("Message Sent: " + response);
},
onErrorResponse(response) {
mserrorcheckwf = true;
console.log("Message ERROR: " + response);
alert("The message couldn't be sent. Message ERROR: " + response);
},
onTransportError() {
console.log("Could not send message");
},
onRequestTimeout() {
console.log("Timeout sending message");
},
onDialogError() {
console.log("Dialog Error sending message");
},
}});
if (mserrorcheckwf == false) {
$("#sendTextMessage").val("");
let currentTime = new Date().toLocaleTimeString();
// Append the sent message
if (textToSend != '') {
$("#receiveTextMessage").append("<div class='textMessageSent textMsgVConf'><span class='sentMessageBtn'>"+ profileName +" ("+ sip_username +"):</span><div class='srMsgVConfcont'>"+ textToSend +"</div><div class='messageDate'>"+ currentTime +"<i class='fa fa-check sentMsTick'></i></div></div>");
}
}
}
$("#receiveTextMessage").scrollTop($("#receiveTextMessage")[0].scrollHeight);
}
// Send the message when clicking on the 'Send Message' button
$("#sendTextChatBtn").click(function() { SendPubChatMessage(); });
// Send the message when pressing Ctrl + Enter
$("#sendTextMessage").keydown(function() {
var keycode = (event.keyCode ? event.keyCode : event.which);
if (keycode == '13') {
if (event.ctrlKey) {
SendPubChatMessage();
return false;
}
}
});
// Select the file to send
$("#sendFileVC").click(function() {
$('#selectedFileVC').val('');
$("#upFileVC").empty();
var uploadfilevc = '<form id="sendFileFormChatVC" enctype="multipart/form-data">';
uploadfilevc += '<input type="hidden" name="MAX_FILE_SIZE" value="786432000" />';
uploadfilevc += '<input type="hidden" name="vcextension" value="'+ videoConfExtension +'" />';
uploadfilevc += '<input type="hidden" name="sipusername" value="'+ sip_username +'" />';
uploadfilevc += '<input type="hidden" name="encextenpass" value="'+ encExtenPass +'" />';
uploadfilevc += '<label for="selectedFileVC" class="customBrowseButtonVC">Select File</label>';
uploadfilevc += '<span id="upFileVC"></span>';
uploadfilevc += '<input type="file" id="selectedFileVC" name="uploadedFileVC" />';
uploadfilevc += '<input type="submit" id="submitFileChatVC" value="Send File" style="visibility:hidden;"/>';
uploadfilevc += '</form>';
if ($("#sendFileFormChatVC").is(":visible")) {
$("#sendFileFormChatVC").remove();
sendFileCheckVC = 0;
} else {
sendFileCheckVC = 1;
$("#sendTextMessage").before(uploadfilevc);
$("#sendFileFormChatVC").css("display", "block");
$("#selectedFileVC").bind("change", function() {
upFileNameVC = $(this).val().split('\\').pop();
if (/^[a-zA-Z0-9\-\_\.]+$/.test(upFileNameVC)) {
$("#upFileVC").css("display", "inline-block");
$("#upFileVC").html(upFileNameVC);
} else {
$("#sendFileFormChatVC").remove();
sendFileCheckVC = 0;
alert("The name of the uploaded file is not valid!");
}
});
}
});
// Position the window
let maxHeight = parseInt(0.88 * $(window).height());
let maxWidth = parseInt(maxHeight * 1.24);
let wTop = parseInt( ($(window).height() / 2) - 290 );
let wLeft = parseInt( ($(window).width() / 2) - 280 );
$("#publicMessageImg").hide();
if (maxWidth < 620 || maxHeight < 500) {
$("#publicTextMessages").css({ "width": maxWidth, "height": maxHeight, "top": wTop, "left": wLeft });
$("#maximizeImg").hide();
$("#restoreImg").hide();
} else {
$("#publicTextMessages").css({ "width": 620, "height": 500, "top": wTop, "left": wLeft });
$("#minimizeImg").show();
$("#maximizeImg").show();
$("#restoreImg").hide();
}
// Handle window position when resizing browser window
$(window).resize(function() {
let maxHeight = parseInt(0.88 * $(window).height());
let maxWidth = parseInt(maxHeight * 1.24);
let wTop = parseInt( ($(window).height() / 2) - 290 );
let wLeft = parseInt( ($(window).width() / 2) - 280 );
$("#receiveTextMessage").show();
$("#sendTMessage").show();
$("#pubMTopBar").show();
$("#publicMessageImg").hide();
if (maxWidth < 620 || maxHeight < 500) {
$("#publicTextMessages").css({ "width": maxWidth, "height": maxHeight, "top": wTop, "left": wLeft });
$("#maximizeImg").hide();
$("#restoreImg").hide();
} else {
$("#publicTextMessages").css({ "width": 620, "height": 500, "top": wTop, "left": wLeft });
$("#minimizeImg").show();
$("#maximizeImg").show();
$("#restoreImg").hide();
}
});
// Handle clicking on window control buttons
$("#maximizeImg").click(function() { messageWindowState = 'maximized'; $("#publicTextMessages").css({ "width": maxWidth, "height": maxHeight, "top": wTop - 40, "left": wLeft - 40 }); $("#maximizeImg,#publicMessageImg").hide(); $("#minimizeImg,#pubMTopBar,#restoreImg,#receiveTextMessage,#sendTMessage").show(); $("#receiveTextMessage").css("height", "64%"); $("#recPubMessage").remove(); });
$("#minimizeImg").click(function() { messageWindowState = 'minimized'; $("#publicTextMessages").css({ "display": "block", "position": "fixed", "width": 215, "height": 34, "inset": "auto auto 1px 3px" }); $("#minimizeImg,#pubMTopBar,#receiveTextMessage,#sendTMessage").hide(); $("#maximizeImg,#restoreImg,#publicMessageImg").show(); $("#windowCtrls").css("margin", "10px 10px 0px 0px"); $("#dragPubMessageWindow").css("top", "-1px"); });
$("#restoreImg").click(function() { messageWindowState = 'restored'; $("#publicTextMessages").css({ "width": 620, "height": 500, "top": wTop, "left": wLeft }); $("#restoreImg,#publicMessageImg").hide(); $("#maximizeImg,#pubMTopBar,#minimizeImg,#receiveTextMessage,#sendTMessage").show(); $("#receiveTextMessage").css("height", "54%"); $("#dragPubMessageWindow").css("top", "4px"); $("#recPubMessage").remove(); });
$("#closeImg").click(function() { messageWindowState = 'closed'; $("#publicTextMessages").remove(); $("#recPubMessage").remove(); });
$(window).on('keydown', function(event) { if (event.key == "Escape") { messageWindowState = 'closed'; $("#publicTextMessages").remove(); $("#recPubMessage").remove(); } });
}
controls.appendChild(textChat);
}
// Private conference messaging
if (video.srcObject.local == false) {
let pmtextChat = document.createElement("button");
pmtextChat.className = "mediaControlBtn";
pmtextChat.id = "textChatBtnPM";
pmtextChat.innerHTML = '<i class="fa fa-commenting-o" aria-hidden="true" title="Send private message to this user"></i>';
pmtextChat.onclick = function() {
let currentMView = document.getElementById("new-media-view"+strid);
let crMViewName = currentMView.getAttribute("name");
let targetCnfExt = crMViewName.slice(4);
let currentVidView = document.getElementById("video-view"+strid);
let destName = currentVidView.getAttribute("name") + " ("+ targetCnfExt +")";
if (messageWindowStatePM[targetCnfExt] == 'minimized' || messageWindowStatePM[targetCnfExt] == 'restored') {
alert("The private message window for this conference participant is already open!");
} else {
phone.openPrivateMessageWindow(destName, targetCnfExt);
}
}
controls.appendChild(pmtextChat);
}
// Record conference
if (video.srcObject.local == true) {
let recordConf = document.createElement("button");
recordConf.className = "mediaControlBtn";
recordConf.id = "recordConfBtnStart";
recordConf.innerHTML = '<i class="fa fa-dot-circle-o" aria-hidden="true" title="Record Conference..."></i>';
recordConf.onclick = function() {
phone.recordVideoConference();
}
controls.appendChild(recordConf);
}
// Mute/Unmute audio
let audioTracks = video.srcObject.getAudioTracks();
if (audioTracks.length > 0) {
let muteAudio = document.createElement("button");
muteAudio.className = "mediaControlBtn";
muteAudio.innerHTML = '<i class="fa fa-microphone" aria-hidden="true" title="Mute Audio"></i>';
muteAudio.setAttribute("state", "Unmute");
muteAudio.onclick = function() {
let state = this.getAttribute("state");
if (state == "Mute") {
this.setAttribute("state", "Unmute");
this.innerHTML = '<i class="fa fa-microphone" aria-hidden="true" title="Mute Audio"></i>';
} else if (state == "Unmute") {
this.setAttribute("state", "Mute");
this.innerHTML = '<i class="fa fa-microphone redmic" aria-hidden="true" title="Unmute Audio"></i>';
}
mute(video.srcObject, {audio: this.getAttribute("state") == "Mute"});
};
controls.appendChild(muteAudio);
}
let videoTracks = video.srcObject.getVideoTracks();
if (videoTracks.length > 0) {
// Mute/Unmute video
let muteVideo = document.createElement("button");
muteVideo.className = "mediaControlBtn";
muteVideo.innerHTML = '<i class="fa fa-camera" aria-hidden="true" title="Mute Video"></i>';
muteVideo.setAttribute("state", "Unmute");
muteVideo.onclick = function() {
let state = this.getAttribute("state");
if (state == "Mute") {
this.setAttribute("state", "Unmute");
this.innerHTML = '<i class="fa fa-camera" aria-hidden="true" title="Mute Video"></i>';
} else if (state == "Unmute") {
this.setAttribute("state", "Mute");
this.innerHTML = '<i class="fa fa-camera redcam" aria-hidden="true" title="Unmute Video"></i>';
}
mute(video.srcObject, {video: this.getAttribute("state") == "Mute"});
};
controls.appendChild(muteVideo);
if (video.srcObject.local == true) {
// Share screen
let ScreenShare = document.createElement("button");
ScreenShare.className = "mediaControlBtn";
ScreenShare.innerHTML = '<i class="fa fa-desktop" aria-hidden="true" title="Share Screen..."></i>';
ScreenShare.onclick = function() {
phone.ShareScreen();
};
controls.appendChild(ScreenShare);
// Reshare camera
let VideoShare = document.createElement("button");
VideoShare.className = "mediaControlBtn";
VideoShare.innerHTML = '<i class="fa fa-video-camera" aria-hidden="true" title="Reshare Camera"></i>';
VideoShare.onclick = function() {
phone.ShareVideo();
};
controls.appendChild(VideoShare);
// View all video windows in full screen
let allFullScreen = document.createElement("button");
allFullScreen.className = "mediaControlBtn";
allFullScreen.id = "fullscreen";
allFullScreen.innerHTML = '<i class="fa fa-arrows-alt" aria-hidden="true" title="Full Screen"></i>';
allFullScreen.onclick = function() { toggleFullScreen(document.body); }
controls.appendChild(allFullScreen);
}
// View this video window in full screen
let fullScreen = document.createElement("button");
fullScreen.className = "mediaControlBtn";
fullScreen.innerHTML = '<i class="fa fa-window-maximize" aria-hidden="true" title="Expand Window"></i>';
fullScreen.onclick = function() {
this.fullScreen.request();
};
fullScreen.fullScreen = new FullScreen(video);
controls.appendChild(fullScreen);
}
return controls;
}
function createMediaView(stream) {
var mediaView = document.createElement("div");
mediaView.className = "media-view";
mediaView.id = "new-media-view"+stream.id;
let videoView = document.createElement("div");
videoView.className = "video-view";
videoView.id = "video-view"+stream.id;
videoView.setAttribute("name", profileName);
let video = document.createElement("video");
video.className = "videoElem";
video.id = "locVideo"+stream.id;
video.autoplay = true;
video.srcObject = stream;
video.onloadedmetadata = function() {
let tracks = stream.getVideoTracks();
for (let i = 0; i < tracks.length; ++i) {
tracks[i].enabled = true;
}
};
// Add participant's name at the bottom of the video window
var userDesc = document.createElement("div");
userDesc.className = "user-desc";
// Add the video conference room label at the bottom-right corner of the video window
var confRoomLabel = document.createElement("div");
confRoomLabel.className = "vidConfLabel";
confRoomLabel.innerHTML = "Room: "+ videoConfTag;
// Add a green border over the video window of the person who is talking
var talkSignal = document.createElement("div");
talkSignal.className = "talkDetect";
if (stream.local == false) {
let userDescCheck = 0;
function checkForVideo() {
mediaView.style.display = 'inline-block';
// Get the profile name/user description from the database
var StreamID = stream.id;
if (userDescCheck < 4 && StreamID != '' && StreamID != 'undefined' && StreamID != null) {
let gotChannelId = '';
for (let i = 0; i < StreamChanTbl.length; i++) {
if (StreamChanTbl[i].streamId == StreamID) { gotChannelId = StreamChanTbl[i].channelId; }
}
let gotExtension = '';
for (let k = 0; k < ExtProNmTbl.length; k++) {
if (ExtProNmTbl[k].channelId == gotChannelId) { gotExtension = ExtProNmTbl[k].extension; }
}
if (gotExtension != '') {
mediaView.setAttribute("name", "cmv_" + gotExtension);
talkSignal.id = "talk-detect-" + gotExtension;
$.ajax({
type: "POST",
url: "../src/get-conf-user-description-ext.php",
dataType: "JSON",
data: {
clrextension: gotExtension,
vconfextension: sip_username,
encextenpass: encExtenPass,
conferenceext: videoConfExtension
},
success: function(response) {
if (response.result == 'success') {
userDescription = response.userdescription;
videoView.setAttribute("name", userDescription);
if (userDescription != 'undefined' && userDescription != null) {
userNameDisplay = response.namedisplay;
if (userNameDisplay == 1 && showConfUNames == 1 && userDescription != '' && userDescription != null) {
userDesc.innerHTML = '<span>' + userDescription + '</span>';
videoView.appendChild(userDesc);
++userDescCheck;
}
}
}
},
error: function(response) {
alert("An error occurred while attempting to retrieve the profile name/user description from the database!");
}
});
}
}
}
checkForVideo();
setInterval(checkForVideo, 1000);
if (remoteCheck == 0) {
// Hide our own remote video track
remoteCheck = 1;
document.getElementById(mediaView.id).style.display = 'none';
}
}
// Video elements connected to local streams will by default
// echo both the video and the audio back to ourselves. Since
// we don't want to hear ourselves we mute it, which mutes only
// the audio portion.
if (stream.local == true) {
video.muted = true;
if (showConfUNames == 1) {
userDesc.innerHTML = '<span>' + profileName + '</span>';
videoView.appendChild(userDesc);
}
videoView.appendChild(confRoomLabel);
mediaView.id = "new-media-view" + stream.id;
mediaView.setAttribute("name", "cmv_" + sip_username);
}
videoView.appendChild(video);
mediaView.appendChild(talkSignal);
mediaView.appendChild(videoView);
mediaView.appendChild(createMediaControls(video, stream.id));
return mediaView;
}
phone = new ConferencePhone(sip_username, sip_username, sip_password, wss_server, websocketpath, stun_server, true);
sip_password = '';
phone.handle("registrationFailed", function () {
phone.disconnect();
});
phone.handle("streamAdded", function (stream) {
try { document.getElementById("media-views").appendChild(createMediaView(stream)); } catch(e) { return; }
++userCount;
phone.resizeVideo(userCount);
});
phone.connect();
let constraints = { audio: true, video: true };
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
phone.call(videoConfExtension);
}).catch(function(err) { alert("Error getting media devices!"); });
document.addEventListener("fullscreenchange", onFullScreenChange, false);
document.addEventListener("webkitfullscreenchange", onFullScreenChange, false);
document.addEventListener("mozfullscreenchange", onFullScreenChange, false);
function onFullScreenChange() {
if (document.mozFullScreenElement != null || document.webkitFullscreenElement != null || document.fullscreenElement != null) {
document.getElementById("fullscreen").style = "color: #0d60e1";
} else {
document.getElementById("fullscreen").style = "color: #000000";
}
}
// Get the private key of the current video conference extension, since it may have been created previously by another conference participant
$.ajax({
type: "POST",
url: "../src/get-text-chat-vconf-priv-key-ext.php",
dataType: "JSON",
data: {
crntvconfext: videoConfExtension,
vconfextension: sip_username,
encextenpass: encExtenPass
},
success: function(result) {
if (result.resmessage == 'success') {
currentVconfPrivKey = "`" + result.chatprivkey.join("") + "`";
} else {
alert('An error occurred while retrieving the private key for text chat!');
}
},
error: function(result) {
alert('An error occurred while attempting to retrieve the private key for text chat!');
}
});
},
error: function(response) {
alert("An error occurred while attempting to save the data to the database!");
}
});
$.jeegoopopup.close();
$("#jg_popup_b").empty();
$("#windowCtrls").empty();
});
$(window).resize(function() {
$.jeegoopopup.width(300).height(310);
$.jeegoopopup.center();
});
} else { alert("You are still banned from this video conference!"); }
},
error: function(response) { alert("Error while trying to get video conference restrictions data!"); }
});
}; // window.onload
window.onbeforeunload = function() {
phone.terminate();
};
window.onunload = function() {
if (phone) {
phone.disconnect();
}
}; // window.onunload
</script>
</head>
<body>
<input type="button" id="connect" class="connect" value="Connect" style="display: none;" />
<div id="media-frame"><div id="media-views" class="media-views"></div></div>
<script type="text/javascript">
FullScreen.prototype.request = function() {
if (this.is()) {
return;
}
if (this._obj.requestFullscreen) {
this._obj.requestFullscreen();
} else if (this._obj.mozRequestFullScreen) {
this._obj.mozRequestFullScreen();
} else if (this._obj.webkitRequestFullScreen) {
this._obj.webkitRequestFullScreen();
} else if (this._obj.msRequestFullscreen) {
this._obj.msRequestFullscreen();
}
this.setData(true);
};
function toggleFullScreen(elem) {
if ((document.fullScreenElement !== undefined && document.fullScreenElement === null) || (document.msFullscreenElement !== undefined && document.msFullscreenElement === null) ||
(document.mozFullScreen !== undefined && !document.mozFullScreen) || (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen)) {
if (elem.requestFullScreen) {
elem.requestFullScreen();
} else if (elem.mozRequestFullScreen) {
elem.mozRequestFullScreen();
} else if (elem.webkitRequestFullScreen) {
elem.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen();
}
} else {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
}
</script>
</body>
</html>
<?php
} else {
header("Location: ../login.php");
}
?>