diff --git a/plugin/bbb/lang/english.php b/plugin/bbb/lang/english.php index f835c67cbc..bf8e25c898 100644 --- a/plugin/bbb/lang/english.php +++ b/plugin/bbb/lang/english.php @@ -49,4 +49,6 @@ $strings['big_blue_button_record_and_store'] = 'Record and store sessions'; $strings['plugin_tool_bbb'] = 'Video'; +$strings['ThereAreNotRecordingsForTheMeetings'] = 'There are not recordings for the meetings'; + diff --git a/plugin/bbb/lang/spanish.php b/plugin/bbb/lang/spanish.php index 0aac0f5980..4f34f64a68 100644 --- a/plugin/bbb/lang/spanish.php +++ b/plugin/bbb/lang/spanish.php @@ -2,4 +2,6 @@ //Needed in order to show the plugin title $strings['plugin_title'] = "Videoconferencia"; -$strings['plugin_comment'] = "Agrega una videoconferencia en un curso usando BigBlueButton (BBB)"; \ No newline at end of file +$strings['plugin_comment'] = "Agrega una videoconferencia en un curso usando BigBlueButton (BBB)"; + +$strings['ThereAreNotRecordingsForTheMeetings'] = 'No existen grabaciones'; \ No newline at end of file diff --git a/plugin/bbb/lib/bbb.lib.php b/plugin/bbb/lib/bbb.lib.php index e05eee9cca..770826d0db 100644 --- a/plugin/bbb/lib/bbb.lib.php +++ b/plugin/bbb/lib/bbb.lib.php @@ -24,9 +24,9 @@ class bbb { $bbb_host = $plugin->get('host'); $bbb_salt = $plugin->get('salt'); - $course_code = api_get_course_id(); + //$course_code = api_get_course_id(); - $this->logout_url = api_get_course_url($course_code); + $this->logout_url = api_get_path(WEB_PLUGIN_PATH).'bbb/listing.php'; $this->table = Database::get_main_table('plugin_bbb_meeting'); if ($bbb_plugin == true) { @@ -39,6 +39,12 @@ class bbb { $this->protocol = $info['scheme'].'://'; $this->url = str_replace($this->protocol, '', $this->url); } + + // Setting BBB api + define(CONFIG_SECURITY_SALT, $this->salt); + define(CONFIG_SERVER_BASE_URL, $this->url); + + $this->api = new BigBlueButtonBN(); $this->plugin_enabled = true; } } @@ -47,16 +53,46 @@ class bbb { return api_is_course_admin() || api_is_coach() || api_is_platform_admin(); } + /* + * See this file in you BBB to set up default values + + /var/lib/tomcat6/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties + * + More record information: + http://code.google.com/p/bigbluebutton/wiki/RecordPlaybackSpecification + + # Default maximum number of users a meeting can have. + # Doesn't get enforced yet but is the default value when the create + # API doesn't pass a value. + defaultMaxUsers=20 + + # Default duration of the meeting in minutes. + # Current default is 0 (meeting doesn't end). + defaultMeetingDuration=0 + + # Remove the meeting from memory when the end API is called. + # This allows 3rd-party apps to recycle the meeting right-away + # instead of waiting for the meeting to expire (see below). + removeMeetingWhenEnded=false + + # The number of minutes before the system removes the meeting from memory. + defaultMeetingExpireDuration=1 + + # The number of minutes the system waits when a meeting is created and when + # a user joins. If after this period, a user hasn't joined, the meeting is + # removed from memory. + defaultMeetingCreateJoinDuration=5 + * + */ function create_meeting($params) { $params['c_id'] = api_get_course_int_id(); $course_code = api_get_course_id(); $attende_password = $params['attendee_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : api_get_course_id(); - $moderator_password = $params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : api_get_course_id().'mod'; + $moderator_password = $params['moderator_pw'] = isset($params['moderator_pw']) ? $params['moderator_pw'] : $this->get_mod_meeting_password(); $params['record'] = api_get_course_setting('big_blue_button_record_and_store', $course_code) == 1 ? true : false; $max = api_get_course_setting('big_blue_button_max_students_allowed', $course_code); - $max = isset($max) ? $max : -1; $params['status'] = 1; @@ -72,16 +108,30 @@ class bbb { $welcome_msg = isset($params['welcome_msg']) ? $params['welcome_msg'] : null; $record = isset($params['record']) && $params['record'] ? 'true' : 'false'; $duration = isset($params['duration']) ? intval($params['duration']) : 0; - - // ?? - $voiceBridge = 0; - $metadata = array('maxParticipants' => $max); - $result = $this->protocol.BigBlueButtonBN::createMeetingAndGetJoinURL( - $this->user_complete_name, $meeting_name, $id, $welcome_msg, $moderator_password, $attende_password, - $this->salt, $this->url, $this->logout_url, $record, $duration, $voiceBridge, $metadata + $duration = 30; + + $bbb_params = array( + 'meetingId' => $id, // REQUIRED + 'meetingName' => $meeting_name, // REQUIRED + 'attendeePw' => $attende_password, // Match this value in getJoinMeetingURL() to join as attendee. + 'moderatorPw' => $moderator_password, // Match this value in getJoinMeetingURL() to join as moderator. + 'welcomeMsg' => $welcome_msg, // ''= use default. Change to customize. + 'dialNumber' => '', // The main number to call into. Optional. + 'voiceBridge' => '0', // PIN to join voice. Optional. + 'webVoice' => '', // Alphanumeric to join voice. Optional. + 'logoutUrl' => $this->logout_url, + 'maxParticipants' => $max, // Optional. -1 = unlimitted. Not supported in BBB. [number] + 'record' => $record, // New. 'true' will tell BBB to record the meeting. + 'duration' => $duration, // Default = 0 which means no set duration in minutes. [number] + //'meta_category' => '', // Use to pass additional info to BBB server. See API docs. ); - if ($this->debug) error_log("create_meeting result: ".print_r($result,1)); - return $result; + if ($this->debug) error_log("create_meeting params: ".print_r($bbb_params,1)); + $result = $this->api->createMeetingWithXmlResponseArray($bbb_params); + if (isset($result) && (string)$result['returncode'] == 'SUCCESS') { + if ($this->debug) error_log("create_meeting result: ".print_r($result,1)); + return $this->join_meeting($meeting_name); + } + return $this->logout; } } @@ -101,32 +151,56 @@ class bbb { */ function join_meeting($meeting_name) { $pass = $this->get_user_meeting_password(); - $mod_pass = $this->get_mod_meeting_password(); $meeting_data = Database::select('*', $this->table, array('where' => array('meeting_name = ? AND status = 1 ' => $meeting_name)), 'first'); if (empty($meeting_data)) { if ($this->debug) error_log("meeting does not exist: $meeting_name "); return false; } - $meeting_is_running = BigBlueButtonBN::isMeetingRunning($meeting_data['id'], $this->url, $this->salt); - $meeting_info = BigBlueButtonBN::getMeetingInfoArray($meeting_data['id'], $mod_pass, $this->url, $this->salt); - $meeting_info_exists = false; - - if ($meeting_info['returncode'] != 'FAILED') { - $meeting_info_exists = true; - } + $meeting_is_running_info = $this->api->isMeetingRunningWithXmlResponseArray($meeting_data['id']); + $meeting_is_running = $meeting_is_running_info['running'] == 'true' ? true : false; - $url = false; if ($this->debug) error_log("meeting is running: ".$meeting_is_running); - if ($this->debug) error_log("meeting is running:getMeetingInfoArray ".print_r($meeting_info, 1)); + + $params = array( + 'meetingId' => $meeting_data['id'], // -- REQUIRED - The unique id for the meeting + 'password' => $this->get_mod_meeting_password() // -- REQUIRED - The moderator password for the meeting + ); + + $meeting_info_exists = $this->get_meeting_info($params); if (isset($meeting_is_running) && $meeting_info_exists) { - $url = $this->protocol.BigBlueButtonBN::joinURL($meeting_data['id'], $this->user_complete_name, $pass, $this->salt, $this->url); + $joinParams = array( + 'meetingId' => $meeting_data['id'], // -- REQUIRED - A unique id for the meeting + 'username' => $this->user_complete_name, //-- REQUIRED - The name that will display for the user in the meeting + 'password' => $pass, //-- REQUIRED - The attendee or moderator password, depending on what's passed here + //'createTime' => api_get_utc_datetime(), //-- OPTIONAL - string. Leave blank ('') unless you set this correctly. + 'userID' => api_get_user_id(), //-- OPTIONAL - string + 'webVoiceConf' => '' // -- OPTIONAL - string + ); + $url = $this->api->getJoinMeetingURL($joinParams); + $url = $this->protocol.$url; + } else { + $url = $this->logout_url; } if ($this->debug) error_log("return url :".$url); return $url; } + function get_meeting_info($params) { + try { + $result = $this->api->getMeetingInfoWithXmlResponseArray($params); + if ($result == null) { + if ($this->debug) error_log("Failed to get any response. Maybe we can't contact the BBB server."); + } else { + return $result; + } + } catch (Exception $e) { + if ($this->debug) error_log('Caught exception: ', $e->getMessage(), "\n"); + } + return false; + } + /** * Gets all the course meetings saved in the plugin_bbb_meeting table * @return string @@ -139,42 +213,72 @@ class bbb { $item = array(); foreach ($meeting_list as $meeting_db) { - $meeting_bbb = BigBlueButtonBN::getMeetingInfoArray($meeting_db['id'], $pass, $this->url, $this->salt); - if ($meeting_bbb['returncode'] == 'FAILED') { + $meeting_bbb = $this->get_meeting_info(array('meetingId' => $meeting_db['id'], 'password' => $pass)); + + $meeting_bbb['end_url'] = api_get_self().'?action=end&id='.$meeting_db['id']; + + if ((string)$meeting_bbb['returncode'] == 'FAILED') { + if ($meeting_db['status'] == 1) { + $this->end_meeting($meeting_db['id']); + } } else { - $meeting_bbb['end_url'] = api_get_self().'?action=end&id='.$meeting_db['id']; $meeting_bbb['add_to_calendar_url'] = api_get_self().'?action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']); } $record_array = array(); if ($meeting_db['record'] == 1) { - $records = BigBlueButtonBN::getRecordingsArray($meeting_db['id'], $this->url, $this->salt); - //var_dump($meeting['id']); + $recordingParams = array( + 'meetingId' => $meeting_db['id'], //-- OPTIONAL - comma separate if multiple ids + ); + + //To see the recording list in your BBB server do: bbb-record --list + $records = $this->api->getRecordingsWithXmlResponseArray($recordingParams); if (!empty($records)) { $count = 1; - foreach ($records as $record) { - if (is_array($record) && isset($record['recordID']) && isset($record['playbacks'])) { - - //Fix the bbb timestamp - //$record['startTime'] = substr($record['startTime'], 0, strlen($record['startTime']) -3); - //$record['endTime'] = substr($record['endTime'], 0, strlen($record['endTime']) -3); - //.' - '.api_convert_and_format_date($record['startTime']).' - '.api_convert_and_format_date($record['endTime']) - foreach ($record['playbacks'] as $item) { - $url = Display::url(get_lang('ViewRecord'), $item['url'], array('target' => '_blank')); - //$url .= Display::url(get_lang('DeleteRecord'), api_get_self().'?action=delete_record&'.$record['recordID']); + if (isset($records['message']) && !empty($records['message'])) { + if ($records['messageKey'] == 'noRecordings') { + //$record_array[] = get_lang('ThereAreNotRecordingsForTheMeetings'); + } else { + //$record_array[] = $records['message']; + } + } else { + foreach ($records as $record) { + if (is_array($record) && isset($record['recordId'])) { + $url = Display::url(get_lang('ViewRecord'), $record['playbackFormatUrl'], array('target' => '_blank')); if ($this->is_teacher()) { - $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meeting_db['id'].'&record_id='.$record['recordID']); - $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']).'&url='.$item['url']); - $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordID']); + $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meeting_db['id'].'&record_id='.$record['recordId']); + $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']).'&url='.$record['playbackFormatUrl']); + $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordId']); } //$url .= api_get_self().'?action=publish&id='.$record['recordID']; $count++; $record_array[] = $url; + } else { + /*if (is_array($record) && isset($record['recordID']) && isset($record['playbacks'])) { + + //Fix the bbb timestamp + //$record['startTime'] = substr($record['startTime'], 0, strlen($record['startTime']) -3); + //$record['endTime'] = substr($record['endTime'], 0, strlen($record['endTime']) -3); + //.' - '.api_convert_and_format_date($record['startTime']).' - '.api_convert_and_format_date($record['endTime']) + foreach($record['playbacks'] as $item) { + $url = Display::url(get_lang('ViewRecord'), $item['url'], array('target' => '_blank')); + //$url .= Display::url(get_lang('DeleteRecord'), api_get_self().'?action=delete_record&'.$record['recordID']); + if ($this->is_teacher()) { + $url .= Display::url(Display::return_icon('link.gif',get_lang('CopyToLinkTool')), api_get_self().'?action=copy_record_to_link_tool&id='.$meeting_db['id'].'&record_id='.$record['recordID']); + $url .= Display::url(Display::return_icon('agenda.png',get_lang('AddToCalendar')), api_get_self().'?action=add_to_calendar&id='.$meeting_db['id'].'&start='.api_strtotime($meeting_db['created_at']).'&url='.$item['url']); + $url .= Display::url(Display::return_icon('delete.png',get_lang('Delete')), api_get_self().'?action=delete_record&id='.$record['recordID']); + } + //$url .= api_get_self().'?action=publish&id='.$record['recordID']; + $count++; + $record_array[] = $url; + } + }*/ } } } } + //var_dump($record_array); $item['show_links'] = implode('
', $record_array); } @@ -185,7 +289,15 @@ class bbb { $item['unpublish_url'] = api_get_self().'?action=unpublish&id='.$meeting_db['id']; if ($meeting_db['status'] == 1) { - $item['go_url'] = $this->protocol.BigBlueButtonBN::joinURL($meeting_db['id'], $this->user_complete_name, $pass, $this->salt, $this->url); + $joinParams = array( + 'meetingId' => $meeting_db['id'], //-- REQUIRED - A unique id for the meeting + 'username' => $this->user_complete_name, //-- REQUIRED - The name that will display for the user in the meeting + 'password' => $pass, //-- REQUIRED - The attendee or moderator password, depending on what's passed here + 'createTime' => '', //-- OPTIONAL - string. Leave blank ('') unless you set this correctly. + 'userID' => '', // -- OPTIONAL - string + 'webVoiceConf' => '' // -- OPTIONAL - string + ); + $item['go_url'] = $this->protocol.$this->api->getJoinMeetingURL($joinParams); } $item = array_merge($item, $meeting_db, $meeting_bbb); $new_meeting_list[] = $item; @@ -194,22 +306,26 @@ class bbb { } function publish_meeting($id) { - return BigBlueButtonBN::setPublishRecordings($id, 'true', $this->url, $this->salt); + //return BigBlueButtonBN::setPublishRecordings($id, 'true', $this->url, $this->salt); } function unpublish_meeting($id) { - return BigBlueButtonBN::setPublishRecordings($id, 'false', $this->url, $this->salt); + //return BigBlueButtonBN::setPublishRecordings($id, 'false', $this->url, $this->salt); } function end_meeting($id) { $pass = $this->get_user_meeting_password(); - BigBlueButtonBN::endMeeting($id, $pass, $this->url, $this->salt); - Database::update($this->table, array('status' => 0), array('id = ? ' => $id)); + $endParams = array( + 'meetingId' => $id, // REQUIRED - We have to know which meeting to end. + 'password' => $pass, // REQUIRED - Must match moderator pass for meeting. + ); + $this->api->endMeetingWithXmlResponseArray($endParams); + Database::update($this->table, array('status' => 0, 'closed_at' => api_get_utc_datetime()), array('id = ? ' => $id)); } function get_user_meeting_password() { if ($this->is_teacher()) { - return api_get_course_id().'mod'; + return $this->get_mod_meeting_password(); } else { return api_get_course_id(); } @@ -229,8 +345,7 @@ class bbb { return 0; } $pass = $this->get_mod_meeting_password(); - //$meeting_is_running = BigBlueButtonBN::isMeetingRunning($meeting_data['id'], $this->url, $this->salt); - $info = BigBlueButtonBN::getMeetingInfoArray($meeting_data['id'], $pass, $this->url, $this->salt); + $info = $this->get_meeting_info(array('meetingId' => $meeting_data['id'], 'password' => $pass)); if (!empty($info) && isset($info['participantCount'])) { return $info['participantCount']; @@ -240,7 +355,17 @@ class bbb { } function delete_record($ids) { - return BigBlueButtonBN::deleteRecordings($ids, $this->url, $this->salt); + $recordingParams = array( + /* + * NOTE: Set the recordId below to a valid id after you have created a recorded meeting, + * and received back a real recordID back from your BBB server using the + * getRecordingsWithXmlResponseArray method. + */ + + // REQUIRED - We have to know which recording: + 'recordId' => $ids, + ); + return $this->api->deleteRecordingsWithXmlResponseArray($recordingParams); } function copy_record_to_link_tool($id, $record_id) { @@ -266,6 +391,7 @@ class bbb { } function is_server_running() { - return BigBlueButtonBN::isServerRunning($this->protocol.$this->url); + return true; + //return BigBlueButtonBN::isServerRunning($this->protocol.$this->url); } } \ No newline at end of file diff --git a/plugin/bbb/lib/bbb_api.php b/plugin/bbb/lib/bbb_api.php index 367c1af74e..20c20b53ae 100644 --- a/plugin/bbb/lib/bbb_api.php +++ b/plugin/bbb/lib/bbb_api.php @@ -1,720 +1,577 @@ = 6) { - $this->userName = func_get_arg(0); - $this->meetingID = func_get_arg(1); - $this->welcomeString = func_get_arg(2); - $this->modPW = func_get_arg(3); - $this->attPW = func_get_arg(4); - $this->securitySalt = func_get_arg(5); - $this->URL = func_get_arg(6); - - - $arg_list = func_get_args(); - }// end else if - } - - //------------------------------------------------GET URLs------------------------------------------------- - /** - * This method returns the url to join the specified meeting. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param username -- the display name to be used when the user joins the meeting - * @param PW -- the attendee or moderator password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return The url to join the meeting - */ - public static function joinURL($meetingID, $userName, $PW, $SALT, $URL) { - $url_join = $URL."api/join?"; - $params = 'meetingID='.urlencode($meetingID).'&fullName='.urlencode($userName).'&password='.urlencode($PW); - return ($url_join.$params.'&checksum='.sha1("join".$params.$SALT) ); - } - - /** - * This method returns the url to join the specified meeting. - * - * @param name -- a name fot the meeting - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param attendeePW -- the attendee of the meeting - * @param moderatorPW -- the moderator of the meeting - * @param welcome -- the welcome message that gets displayed on the chat window - * @param logoutURL -- the URL that the bbb client will go to after users logouut - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * @param record -- the flag which indicate if the meetings will be recorded or not record=true|false, default false - * @param duration -- this value indicate the duration of a meeting to be recorded. Duration is represented in munutes - * - * @return The url to join the meeting - */ - public static function createMeetingURL($name, $meetingID, $attendeePW, $moderatorPW, $welcome, $logoutURL, $SALT, $URL, $record = 'false', $duration = 0, $voiceBridge = 0, $metadata = array()) { - $url_create = $URL."api/create?"; - if ($voiceBridge == 0) - $voiceBridge = 70000 + rand(0, 9999); - - $meta = ''; - while ($data = current($metadata)) { - $meta = $meta.'&'.key($metadata).'='.urlencode($data); - next($metadata); - } - - - $params = 'name='.urlencode($name).'&meetingID='.urlencode($meetingID).'&attendeePW='.urlencode($attendeePW).'&moderatorPW='.urlencode($moderatorPW).'&voiceBridge='.$voiceBridge.'&logoutURL='.urlencode($logoutURL).'&record='.$record.$meta; - - $duration = intval($duration); - if ($duration > 0) - $params .= '&duration='.$duration; - - if (trim($welcome)) - $params .= '&welcome='.urlencode($welcome); - - return ( $url_create.$params.'&checksum='.sha1("create".$params.$SALT) ); - } - - /** - * This method returns the url to check if the specified meeting is running. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return The url to check if the specified meeting is running. - */ - public static function isMeetingRunningURL($meetingID, $URL, $SALT) { - $base_url = $URL."api/isMeetingRunning?"; - $params = 'meetingID='.urlencode($meetingID); - return ($base_url.$params.'&checksum='.sha1("isMeetingRunning".$params.$SALT) ); - } - - /** - * This method returns the url to getMeetingInfo of the specified meeting. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return The url to check if the specified meeting is running. - */ - public static function getMeetingInfoURL($meetingID, $modPW, $URL, $SALT) { - $base_url = $URL."api/getMeetingInfo?"; - $params = 'meetingID='.urlencode($meetingID).'&password='.urlencode($modPW); - return ( $base_url.$params.'&checksum='.sha1("getMeetingInfo".$params.$SALT)); - } - - /** - * This method returns the url for listing all meetings in the bigbluebuttonbn server. - * - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return The url of getMeetings. - */ - public static function getMeetingsURL($URL, $SALT) { - $base_url = $URL."api/getMeetings?"; - $params = ''; - return ( $base_url.$params.'&checksum='.sha1("getMeetings".$params.$SALT)); - } - - /** - * This method returns the url to end the specified meeting. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return The url to end the specified meeting. - */ - public static function endMeetingURL($meetingID, $modPW, $URL, $SALT) { - $base_url = $URL."api/end?"; - $params = 'meetingID='.urlencode($meetingID).'&password='.urlencode($modPW); - return ( $base_url.$params.'&checksum='.sha1("end".$params.$SALT) ); - } - - //-----------------------------------------------CREATE---------------------------------------------------- - /** - * This method creates a meeting and returnS the join url for moderators. - * - * @param username - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param welcomeString -- the welcome message to be displayed when a user logs in to the meeting - * @param mPW -- the moderator password of the meeting - * @param aPW -- the attendee password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * @param logoutURL -- the url the user should be redirected to when they logout of bigbluebuttonbn - * @param record -- the flag which indicate if the meetings will be recorded or not record=true|false, default false - * - * @return The joinURL if successful or an error message if unsuccessful - */ - public static function createMeetingAndGetJoinURL($username, $meeting_name, $meetingID, $welcomeString, $mPW, $aPW, $SALT, $URL, $logoutURL, $record = 'false', $duration = 0, $voiceBridge = 0, $metadata = array()) { - - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::createMeetingURL($meeting_name, $meetingID, $aPW, $mPW, $welcomeString, $logoutURL, $SALT, $URL, $record, $duration, $voiceBridge, $metadata)); - - if ($xml && $xml->returncode == 'SUCCESS') { - return ( BigBlueButtonBN::joinURL($meetingID, $username, $mPW, $SALT, $URL) ); - } else if ($xml) { - return ( $xml->messageKey.' : '.$xml->message ); - } else { - return ('Unable to fetch URL '.$url_create.$params.'&checksum='.sha1("create".$params.$SALT) ); - } - } - - /** - * This method creates a meeting and return an array of the xml packet - * - * @param username - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param welcomeString -- the welcome message to be displayed when a user logs in to the meeting - * @param mPW -- the moderator password of the meeting - * @param aPW -- the attendee password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * @param logoutURL -- the url the user should be redirected to when they logout of bigbluebuttonbn - * @param record -- the flag which indicate if the meetings will be recorded or not record=true|false, default false - * - * @return - * - Null if unable to reach the bigbluebuttonbn server - * - If failed it returns an array containing a returncode, messageKey, message. - * - If success it returns an array containing a returncode, messageKey, message, meetingID, attendeePW, moderatorPW, hasBeenForciblyEnded. - */ - public static function createMeetingArray($username, $meetingID, $welcomeString, $mPW, $aPW, $SALT, $URL, $logoutURL, $record = 'false', $duration = 0, $voiceBridge = 0, $metadata = array()) { - - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::createMeetingURL($username, $meetingID, $aPW, $mPW, $welcomeString, $logoutURL, $SALT, $URL, $record, $duration, $voiceBridge, $metadata)); - - if ($xml) { - if ($xml->meetingID) - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey, 'meetingID' => $xml->meetingID, 'attendeePW' => $xml->attendeePW, 'moderatorPW' => $xml->moderatorPW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded); - else - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } - else { - return null; - } - } - - //-------------------------------------------getMeetingInfo--------------------------------------------------- - /** - * This method calls the getMeetingInfo on the bigbluebuttonbn server and returns an xml packet. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return An xml packet. - * If failed it returns an xml packet containing a returncode, messagekey, and message. - * If success it returnsan xml packet containing a returncode, - */ - public static function getMeetingInfo($meetingID, $modPW, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingInfoURL($meetingID, $modPW, $URL, $SALT)); - if ($xml) { - return ( str_replace('', '', str_replace("\n", '', $xml->asXML()))); - } - return false; - } - - /** - * This method calls the getMeetingInfo on the bigbluebuttonbn server and returns an array. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return An Array. - * - Null if unable to reach the bigbluebuttonbn server - * - If failed it returns an array containing a returncode, messagekey, message. - * - If success it returns an array containing a meetingID, moderatorPW, attendeePW, hasBeenForciblyEnded, running, startTime, endTime, - participantCount, moderatorCount, attendees. - */ - public static function getMeetingInfoArray($meetingID, $modPW, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingInfoURL($meetingID, $modPW, $URL, $SALT)); - - if ($xml && $xml->returncode == 'SUCCESS' && $xml->messageKey == null) {//The meetings were returned - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } else if ($xml && $xml->returncode == 'SUCCESS') { //If there were meetings already created - return array('meetingID' => $xml->meetingID, 'moderatorPW' => $xml->moderatorPW, 'attendeePW' => $xml->attendeePW, 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded, 'running' => $xml->running, 'recording' => $xml->recording, 'startTime' => $xml->startTime, 'endTime' => $xml->endTime, 'participantCount' => $xml->participantCount, 'moderatorCount' => $xml->moderatorCount, 'attendees' => $xml->attendees, 'metadata' => $xml->metadata); - } else if (($xml && $xml->returncode == 'FAILED') || $xml) { //If the xml packet returned failure it displays the message to the user - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - //return array('returncode' => $xml->returncode, 'message' => $xml->errors->error['message'], 'messageKey' => $xml->errors->error['key']); //For API version 0.8 - } else { //If the server is unreachable, then prompts the user of the necessary action - return null; - } - } - - //-----------------------------------------------getMeetings------------------------------------------------------ - /** - * This method calls getMeetings on the bigbluebuttonbn server, then calls getMeetingInfo for each meeting and concatenates the result. - * - * @param URL -- the url of the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * - * @return - * - If failed then returns a boolean of false. - * - If succeeded then returns an xml of all the meetings. - */ - public static function getMeetings($URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingsURL($URL, $SALT)); - if ($xml && $xml->returncode == 'SUCCESS') { - if ($xml->messageKey) - return ( $xml->message->asXML() ); - ob_start(); - echo ''; - if (count($xml->meetings) && count($xml->meetings->meeting)) { - foreach ($xml->meetings->meeting as $meeting) { - echo ''; - echo BigBlueButtonBN::getMeetingInfo($meeting->meetingID, $meeting->moderatorPW, $URL, $SALT); - echo ''; - } - } - echo ''; - return (ob_get_clean()); - } else { - return (false); - } - } - - /** - * This method calls getMeetings on the bigbluebuttonbn server, then calls getMeetingInfo for each meeting and concatenates the result. - * - * @param URL -- the url of the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * - * @return - * - Null if the server is unreachable - * - If FAILED then returns an array containing a returncode, messageKey, message. - * - If SUCCESS then returns an array of all the meetings. Each element in the array is an array containing a meetingID, - moderatorPW, attendeePW, hasBeenForciblyEnded, running. - */ - public static function getMeetingsArray($URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingsURL($URL, $SALT)); - - if ($xml && $xml->returncode == 'SUCCESS' && $xml->messageKey) {//The meetings were returned - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } else if ($xml && $xml->returncode == 'SUCCESS') { //If there were meetings already created - foreach ($xml->meetings->meeting as $meeting) { - $meetings[] = array('meetingID' => $meeting->meetingID, 'moderatorPW' => $meeting->moderatorPW, 'attendeePW' => $meeting->attendeePW, 'hasBeenForciblyEnded' => $meeting->hasBeenForciblyEnded, 'running' => $meeting->running); - } - - return $meetings; - } else if ($xml) { //If the xml packet returned failure it displays the message to the user - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } else { //If the server is unreachable, then prompts the user of the necessary action - return null; - } - } - - //----------------------------------------------getUsers--------------------------------------- - /** - * This method prints the usernames of the attendees in the specified conference. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param URL -- the url of the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param UNAME -- is a boolean to determine how the username is formatted when printed. Default if false. - * - * @return A boolean of true if the attendees were printed successfully and false otherwise. - */ - public static function getUsers($meetingID, $modPW, $URL, $SALT, $UNAME = false) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingInfoURL($meetingID, $modPW, $URL, $SALT)); - if ($xml && $xml->returncode == 'SUCCESS') { - ob_start(); - if (count($xml->attendees) && count($xml->attendees->attendee)) { - foreach ($xml->attendees->attendee as $attendee) { - if ($UNAME == true) { - echo "User name: ".$attendee->fullName.'
'; - } else { - echo $attendee->fullName.'
'; - } - } - } - return (ob_end_flush()); - } else { - return (false); - } - } - - /** - * This method returns an array of the attendees in the specified meeting. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param URL -- the url of the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * - * @return - * - Null if the server is unreachable. - * - If FAILED, returns an array containing a returncode, messageKey, message. - * - If SUCCESS, returns an array of array containing the userID, fullName, role of each attendee - */ - public static function getUsersArray($meetingID, $modPW, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingInfoURL($meetingID, $modPW, $URL, $SALT)); - - if ($xml && $xml->returncode == 'SUCCESS' && $xml->messageKey == null) {//The meetings were returned - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } else if ($xml && $xml->returncode == 'SUCCESS') { //If there were meetings already created - foreach ($xml->attendees->attendee as $attendee) { - $users[] = array('userID' => $attendee->userID, 'fullName' => $attendee->fullName, 'role' => $attendee->role); - } - return $users; - } else if ($xml) { //If the xml packet returned failure it displays the message to the user - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } else { //If the server is unreachable, then prompts the user of the necessary action - return null; - } - } - - //------------------------------------------------Other Methods------------------------------------ - /** - * This method calls end meeting on the specified meeting in the bigbluebuttonbn server. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param modPW -- the moderator password of the meeting - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return - * - Null if the server is unreachable - * - An array containing a returncode, messageKey, message. - */ - public static function endMeeting($meetingID, $modPW, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::endMeetingURL($meetingID, $modPW, $URL, $SALT)); - - if ($xml) { //If the xml packet returned failure it displays the message to the user - return array('returncode' => $xml->returncode, 'message' => $xml->message, 'messageKey' => $xml->messageKey); - } else { //If the server is unreachable, then prompts the user of the necessary action - return null; - } - } - - /** - * This method check the BigBlueButton server to see if the meeting is running (i.e. there is someone in the meeting) - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return A boolean of true if the meeting is running and false if it is not running - */ - public static function isMeetingRunning($meetingID, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::isMeetingRunningURL($meetingID, $URL, $SALT)); - if ($xml && $xml->returncode == 'SUCCESS') - return ( ( $xml->running == 'true' ) ? true : false); - else - return ( false ); - } - - /** - * This method calls isMeetingRunning on the BigBlueButton server. - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return - * - If SUCCESS it returns an xml packet - * - If the FAILED or the server is unreachable returns a string of 'false' - */ - public static function getMeetingXML($meetingID, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::isMeetingRunningURL($meetingID, $URL, $SALT)); - if ($xml && $xml->returncode == 'SUCCESS') - return ( str_replace('
', '', str_replace("\n", '', $xml->asXML()))); - else - return 'false'; - } - - // TODO: WRITE AN ITERATOR WHICH GOES OVER WHATEVER IT IS BEING TOLD IN THE API AND LIST INFORMATION - /* we have to define at least 2 variable fields for getInformation to read out information at any position - The first is: An identifier to chose if we look for attendees or the meetings or something else - The second is: An identifier to chose what integrated functions are supposed to be used - - @param IDENTIFIER -- needs to be put in for the function to identify the information to print out - current values which can be used are 'attendee' and 'meetings' - @param meetingID -- needs to be put in to identify the meeting - @param modPW -- needs to be put in if the users are supposed to be shown or to retrieve information about the meetings - @param URL -- needs to be put in the URL to the bigbluebuttonbn server - @param SALT -- needs to be put in for the security salt calculation - - Note: If 'meetings' is used, then only the parameters URL and SALT needs to be used - If 'attendee' is used, then all the parameters needs to be used - */ - public static function getInformation($IDENTIFIER, $meetingID, $modPW, $URL, $SALT) { - // if the identifier is null or '', then return false - if ($IDENTIFIER == "" || $IDENTIFIER == null) { - echo "You need to type in a valid value into the identifier."; - return false; - } - // if the identifier is attendee, call getUsers - else if ($IDENTIFIER == 'attendee') { - return BigBlueButtonBN::getUsers($meetingID, $modPW, $URL, $SALT); - } - // if the identifier is meetings, call getMeetings - else if ($IDENTIFIER == 'meetings') { - return BigBlueButtonBN::getMeetings($URL, $SALT); - } - // return nothing - else { - return true; - } - } - - function getServerIP() { - // get the server url - $sIP = $_SERVER['SERVER_ADDR']; - return $serverIP = 'http://'.$sIP.'/bigbluebuttonbn/'; - } - - /** - * This method check the BigBlueButton server to see if the meeting has been created - * - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * - * @return A boolean of true if the meeting has been created, doesn't matter if is running or not and false if it does not exist - */ - public static function isMeetingCreated($meetingID, $URL, $SALT) { - - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getMeetingsURL($URL, $SALT)); - if ($xml && $xml->returncode == 'SUCCESS') - foreach ($xml->meetings->meeting as $meeting) - if ($meeting->meetingID == $meetingID && $meeting->hasBeenForciblyEnded == 'false') - return true; - return false; - } - - /** - * This method creates a new meeting room in the BigBlueButton server - * - * @param name -- a name fot the meeting - * @param meetingID -- the unique meeting identifier used to store the meeting in the bigbluebuttonbn server - * @param attendeePW -- the attendee of the meeting - * @param moderatorPW -- the moderator of the meeting - * @param welcome -- the welcome message that gets displayed on the chat window - * @param logoutURL -- the URL that the bbb client will go to after users logouut - * @param SALT -- the security salt of the bigbluebuttonbn server - * @param URL -- the url of the bigbluebuttonbn server - * @param record -- the flag which indicate if the meetings will be recorded or not record=true|false, default false - * - * @return A boolean of true if the meeting has been created, doesn't matter if is running or not and false if it was an error - */ - public static function createMeeting($name, $meetingID, $attendeePW, $moderatorPW, $welcome, $logoutURL, $SALT, $URL, $record = 'false', $duration = 0, $voiceBridge = 0, $metadata = array()) { - - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::createMeetingURL($name, $meetingID, $attendeePW, $moderatorPW, $welcome, $logoutURL, $SALT, $URL, $record, $duration, $voiceBridge, $metadata)); - if ($xml && $xml->returncode == 'SUCCESS') - return true; - else - return false; - } - -////////////////////////TO DO: CHANGE THE DESCRIPTION OF THE NEW METHODS - - public static function getRecordingsURL($meetingID, $URL, $SALT) { - $base_url_record = $URL."api/getRecordings?"; - $params = "meetingID=".urlencode($meetingID); - - return ($base_url_record.$params."&checksum=".sha1("getRecordings".$params.$SALT) ); - } - - /** - * This method calls getMeetings on the bigbluebuttonbn server, then calls getMeetingInfo for each meeting and concatenates the result. - * - * @param URL -- the url of the bigbluebuttonbn server - * @param SALT -- the security salt of the bigbluebuttonbn server - * - * @return - * - Null if the server is unreachable - * - If FAILED then returns an array containing a returncode, messageKey, message. - * - If SUCCESS then returns an array of all the meetings. Each element in the array is an array containing a meetingID, - moderatorPW, attendeePW, hasBeenForciblyEnded, running. - */ - public static function getRecordingsArray($meetingID, $URL, $SALT) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::getRecordingsURL($meetingID, $URL, $SALT)); - if ($xml && $xml->returncode == 'SUCCESS' && $xml->messageKey) {//The meetings were returned - return array('returncode' => (string) $xml->returncode, 'message' => (string) $xml->message, 'messageKey' => (string) $xml->messageKey); - } else if ($xml && $xml->returncode == 'SUCCESS') { //If there were meetings already created - $recordings = array(); - - foreach ($xml->recordings->recording as $recording) { - $recordings[(string) $recording->recordID] = array('recordID' => (string) $recording->recordID, 'meetingID' => (string) $recording->meetingID, 'meetingName' => (string) $recording->name, 'published' => (string) $recording->published, 'startTime' => (string) $recording->startTime, 'endTime' => (string) $recording->endTime); - $recordings[(string) $recording->recordID]['playbacks'] = array(); - foreach ($recording->playback->format as $format) { - $recordings[(string) $recording->recordID]['playbacks'][(string) $format->type] = array('type' => (string) $format->type, 'url' => (string) $format->url); - } - // THIS IS FOR TESTING MULTIPLE FORMATS, DO REMOVE IT FOR FINAL RELEASE - //$recordings[(string) $recording->recordID]['playbacks']['desktop'] = array( 'type' => 'desktop', 'url' => (string) $recording->playback->format->url ); - //Add the metadata to the recordings array - $metadata = get_object_vars($recording->metadata); - while ($data = current($metadata)) { - $recordings[(string) $recording->recordID]['meta_'.key($metadata)] = $data; - next($metadata); - } - } - - ksort($recordings); - - return $recordings; - } else if ($xml) { //If the xml packet returned failure it displays the message to the user - return array('returncode' => (string) $xml->returncode, 'message' => (string) $xml->message, 'messageKey' => (string) $xml->messageKey); - } else { //If the server is unreachable, then prompts the user of the necessary action - return NULL; - } - } - - public static function deleteRecordingsURL($recordID, $URL, $SALT) { - $url_delete = $URL."api/deleteRecordings?"; - $params = 'recordID='.urlencode($recordID); - return ($url_delete.$params.'&checksum='.sha1("deleteRecordings".$params.$SALT) ); - } - - public static function deleteRecordings($recordIDs, $URL, $SALT) { - - $ids = explode(",", $recordIDs); - foreach ($ids as $id) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::deleteRecordingsURL($id, $URL, $SALT)); - if ($xml && $xml->returncode != 'SUCCESS') - return false; - } - return true; - } - - public static function setPublishRecordingsURL($recordID, $set, $URL, $SALT) { - $url_delete = $URL."api/publishRecordings?"; - $params = 'recordID='.$recordID."&publish=".$set; - return ($url_delete.$params.'&checksum='.sha1("publishRecordings".$params.$SALT) ); - } - - public static function setPublishRecordings($recordIDs, $set, $URL, $SALT) { - - $ids = explode(",", $recordIDs); - foreach ($ids as $id) { - $xml = BigBlueButtonBN::_wrap_simplexml_load_file(BigBlueButtonBN::setPublishRecordingsURL($id, $set, $URL, $SALT)); - if ($xml && $xml->returncode != 'SUCCESS') - return false; - } - return true; - } - - public static function getServerVersion($URL) { - $base_url_record = $URL."api"; - - $xml = BigBlueButtonBN::_wrap_simplexml_load_file($base_url_record); - if ($xml && $xml->returncode == 'SUCCESS') - return $xml->version; - else - return NULL; - } - - public static function isServerRunning($URL) { - $base_url_record = $URL."api"; - - $xml = BigBlueButtonBN::_wrap_simplexml_load_file($base_url_record); - if ($xml && $xml->returncode == 'SUCCESS') - return true; - else - return false; - } - - public function _wrap_simplexml_load_file($url) { - - if (extension_loaded('curl')) { - $ch = curl_init() or die(curl_error()); - $timeout = 10; - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); - $data = curl_exec($ch); - curl_close($ch); - - if ($data) { - try { - $res = new SimpleXMLElement($data, LIBXML_NOCDATA); - } catch (Exception $e) { - return false; - } - return $res; - } else { - return false; - } - } - - return (simplexml_load_file($url, 'SimpleXMLElement', LIBXML_NOCDATA)); - } - -} \ No newline at end of file +Copyright 2010 Blindside Networks + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Versions: + 1.0 -- Initial version written by DJP + (email: djp [a t ] architectes DOT .org) + 1.1 -- Updated by Omar Shammas and Sebastian Schneider + (email : omar DOT shammas [a t ] g m ail DOT com) + (email : seb DOT sschneider [ a t ] g m ail DOT com) + 1.2 -- Updated by Omar Shammas + (email : omar DOT shammas [a t ] g m ail DOT com) + 1.3 -- Refactored by Peter Mentzer + (email : peter@petermentzerdesign.com) + - This update will BREAK your external existing code if + you've used the previous versions <= 1.2 already so: + -- update your external code to use new method names if needed + -- update your external code to pass new parameters to methods + - Working example of joinIfRunning.php now included + - Added support for BBB 0.8b recordings + - Now using Zend coding, naming and style conventions + - Refactored methods to accept standardized parameters & match BBB API structure + -- See included samples for usage examples +*/ + +/* _______________________________________________________________________*/ + +/* get the config values */ +//require_once "config.php"; + +class BigBlueButtonBN { + + private $_securitySalt; + private $_bbbServerBaseUrl; + + /* ___________ General Methods for the BigBlueButton Class __________ */ + + function __construct() { + /* + Establish just our basic elements in the constructor: + */ + // BASE CONFIGS - set these for your BBB server in config.php and they will + // simply flow in here via the constants: + $this->_securitySalt = CONFIG_SECURITY_SALT; + $this->_bbbServerBaseUrl = CONFIG_SERVER_BASE_URL; + } + + private function _processXmlResponse($url){ + /* + A private utility method used by other public methods to process XML responses. + */ + if (extension_loaded('curl')) { + $ch = curl_init() or die ( curl_error() ); + $timeout = 10; + curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt( $ch, CURLOPT_URL, $url ); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout); + $data = curl_exec( $ch ); + curl_close( $ch ); + + if($data) + return (new SimpleXMLElement($data)); + else + return false; + } + return (simplexml_load_file($url)); + } + + private function _requiredParam($param) { + /* Process required params and throw errors if we don't get values */ + if ((isset($param)) && ($param != '')) { + return $param; + } + elseif (!isset($param)) { + throw new Exception('Missing parameter.'); + } + else { + throw new Exception(''.$param.' is required.'); + } + } + + private function _optionalParam($param) { + /* Pass most optional params through as set value, or set to '' */ + /* Don't know if we'll use this one, but let's build it in case. */ + if ((isset($param)) && ($param != '')) { + return $param; + } + else { + $param = ''; + return $param; + } + } + + /* __________________ BBB ADMINISTRATION METHODS _________________ */ + /* The methods in the following section support the following categories of the BBB API: + -- create + -- join + -- end + */ + + public function getCreateMeetingUrl($creationParams) { + /* + USAGE: + (see $creationParams array in createMeetingArray method.) + */ + $this->_meetingId = $this->_requiredParam($creationParams['meetingId']); + $this->_meetingName = $this->_requiredParam($creationParams['meetingName']); + // Set up the basic creation URL: + $creationUrl = $this->_bbbServerBaseUrl."api/create?"; + // Add params: + $params = + 'name='.urlencode($this->_meetingName). + '&meetingID='.urlencode($this->_meetingId). + '&attendeePW='.urlencode($creationParams['attendeePw']). + '&moderatorPW='.urlencode($creationParams['moderatorPw']). + '&dialNumber='.urlencode($creationParams['dialNumber']). + '&voiceBridge='.urlencode($creationParams['voiceBridge']). + '&webVoice='.urlencode($creationParams['webVoice']). + '&logoutURL='.urlencode($creationParams['logoutUrl']). + '&maxParticipants='.urlencode($creationParams['maxParticipants']). + '&record='.urlencode($creationParams['record']). + '&duration='.urlencode($creationParams['duration']); + //'&meta_category='.urlencode($creationParams['meta_category']); + $welcomeMessage = $creationParams['welcomeMsg']; + if(trim($welcomeMessage)) + $params .= '&welcome='.urlencode($welcomeMessage); + // Return the complete URL: + return ( $creationUrl.$params.'&checksum='.sha1("create".$params.$this->_securitySalt) ); + } + + public function createMeetingWithXmlResponseArray($creationParams) { + /* + USAGE: + $creationParams = array( + 'name' => 'Meeting Name', -- A name for the meeting (or username) + 'meetingId' => '1234', -- A unique id for the meeting + 'attendeePw' => 'ap', -- Set to 'ap' and use 'ap' to join = no user pass required. + 'moderatorPw' => 'mp', -- Set to 'mp' and use 'mp' to join = no user pass required. + 'welcomeMsg' => '', -- ''= use default. Change to customize. + 'dialNumber' => '', -- The main number to call into. Optional. + 'voiceBridge' => '', -- PIN to join voice. Optional. + 'webVoice' => '', -- Alphanumeric to join voice. Optional. + 'logoutUrl' => '', -- Default in bigbluebutton.properties. Optional. + 'maxParticipants' => '-1', -- Optional. -1 = unlimitted. Not supported in BBB. [number] + 'record' => 'false', -- New. 'true' will tell BBB to record the meeting. + 'duration' => '0', -- Default = 0 which means no set duration in minutes. [number] + 'meta_category' => '', -- Use to pass additional info to BBB server. See API docs to enable. + ); + */ + $xml = $this->_processXmlResponse($this->getCreateMeetingURL($creationParams)); + + if($xml) { + if($xml->meetingID) + return array( + 'returncode' => $xml->returncode, + 'message' => $xml->message, + 'messageKey' => $xml->messageKey, + 'meetingId' => $xml->meetingID, + 'attendeePw' => $xml->attendeePW, + 'moderatorPw' => $xml->moderatorPW, + 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded, + 'createTime' => $xml->createTime + ); + else + return array( + 'returncode' => $xml->returncode, + 'message' => $xml->message, + 'messageKey' => $xml->messageKey + ); + } + else { + return null; + } + } + + public function getJoinMeetingURL($joinParams) { + /* + NOTE: At this point, we don't use a corresponding joinMeetingWithXmlResponse here because the API + doesn't respond on success, but you can still code that method if you need it. Or, you can take the URL + that's returned from this method and simply send your users off to that URL in your code. + USAGE: + $joinParams = array( + 'meetingId' => '1234', -- REQUIRED - A unique id for the meeting + 'username' => 'Jane Doe', -- REQUIRED - The name that will display for the user in the meeting + 'password' => 'ap', -- REQUIRED - The attendee or moderator password, depending on what's passed here + 'createTime' => '', -- OPTIONAL - string. Leave blank ('') unless you set this correctly. + 'userID' => '', -- OPTIONAL - string + 'webVoiceConf' => '' -- OPTIONAL - string + ); + */ + $this->_meetingId = $this->_requiredParam($joinParams['meetingId']); + $this->_username = $this->_requiredParam($joinParams['username']); + $this->_password = $this->_requiredParam($joinParams['password']); + // Establish the basic join URL: + $joinUrl = $this->_bbbServerBaseUrl."api/join?"; + // Add parameters to the URL: + $params = + 'meetingID='.urlencode($this->_meetingId). + '&fullName='.urlencode($this->_username). + '&password='.urlencode($this->_password). + '&userID='.urlencode($joinParams['userId']). + '&webVoiceConf='.urlencode($joinParams['webVoiceConf']); + // Only use createTime if we really want to use it. If it's '', then don't pass it: + if (((isset($joinParams['createTime'])) && ($joinParams['createTime'] != ''))) { + $params .= '&createTime='.urlencode($joinParams['createTime']); + } + // Return the URL: + return ($joinUrl.$params.'&checksum='.sha1("join".$params.$this->_securitySalt)); + } + + public function getEndMeetingURL($endParams) { + /* USAGE: + $endParams = array ( + 'meetingId' => '1234', -- REQUIRED - The unique id for the meeting + 'password' => 'mp' -- REQUIRED - The moderator password for the meeting + ); + */ + $this->_meetingId = $this->_requiredParam($endParams['meetingId']); + $this->_password = $this->_requiredParam($endParams['password']); + $endUrl = $this->_bbbServerBaseUrl."api/end?"; + $params = + 'meetingID='.urlencode($this->_meetingId). + '&password='.urlencode($this->_password); + return ($endUrl.$params.'&checksum='.sha1("end".$params.$this->_securitySalt)); + } + + public function endMeetingWithXmlResponseArray($endParams) { + /* USAGE: + $endParams = array ( + 'meetingId' => '1234', -- REQUIRED - The unique id for the meeting + 'password' => 'mp' -- REQUIRED - The moderator password for the meeting + ); + */ + $xml = $this->_processXmlResponse($this->getEndMeetingURL($endParams)); + if($xml) { + return array( + 'returncode' => $xml->returncode, + 'message' => $xml->message, + 'messageKey' => $xml->messageKey + ); + } + else { + return null; + } + + } + + /* __________________ BBB MONITORING METHODS _________________ */ + /* The methods in the following section support the following categories of the BBB API: + -- isMeetingRunning + -- getMeetings + -- getMeetingInfo + */ + + public function getIsMeetingRunningUrl($meetingId) { + /* USAGE: + $meetingId = '1234' -- REQUIRED - The unique id for the meeting + */ + $this->_meetingId = $this->_requiredParam($meetingId); + $runningUrl = $this->_bbbServerBaseUrl."api/isMeetingRunning?"; + $params = + 'meetingID='.urlencode($this->_meetingId); + return ($runningUrl.$params.'&checksum='.sha1("isMeetingRunning".$params.$this->_securitySalt)); + } + + public function isMeetingRunningWithXmlResponseArray($meetingId) { + /* USAGE: + $meetingId = '1234' -- REQUIRED - The unique id for the meeting + */ + $xml = $this->_processXmlResponse($this->getIsMeetingRunningUrl($meetingId)); + if($xml) { + return array( + 'returncode' => $xml->returncode, + 'running' => $xml->running // -- Returns true/false. + ); + } + else { + return null; + } + + } + + public function getGetMeetingsUrl() { + /* Simply formulate the getMeetings URL + We do this in a separate function so we have the option to just get this + URL and print it if we want for some reason. + */ + $getMeetingsUrl = $this->_bbbServerBaseUrl."api/getMeetings?checksum=".sha1("getMeetings".$this->_securitySalt); + return $getMeetingsUrl; + } + + public function getMeetingsWithXmlResponseArray() { + /* USAGE: + We don't need to pass any parameters with this one, so we just send the query URL off to BBB + and then handle the results that we get in the XML response. + */ + $xml = $this->_processXmlResponse($this->getGetMeetingsUrl()); + if($xml) { + // If we don't get a success code, stop processing and return just the returncode: + if ($xml->returncode != 'SUCCESS') { + $result = array( + 'returncode' => $xml->returncode + ); + return $result; + } + elseif ($xml->messageKey == 'noMeetings') { + /* No meetings on server, so return just this info: */ + $result = array( + 'returncode' => $xml->returncode, + 'messageKey' => $xml->messageKey, + 'message' => $xml->message + ); + return $result; + } + else { + // In this case, we have success and meetings. First return general response: + $result = array( + 'returncode' => $xml->returncode, + 'messageKey' => $xml->messageKey, + 'message' => $xml->message + ); + // Then interate through meeting results and return them as part of the array: + foreach ($xml->meetings->meeting as $m) { + $result[] = array( + 'meetingId' => $m->meetingID, + 'meetingName' => $m->meetingName, + 'createTime' => $m->createTime, + 'attendeePw' => $m->attendeePW, + 'moderatorPw' => $m->moderatorPW, + 'hasBeenForciblyEnded' => $m->hasBeenForciblyEnded, + 'running' => $m->running + ); + } + return $result; + } + } + else { + return null; + } + + } + + public function getMeetingInfoUrl($infoParams) { + /* USAGE: + $infoParams = array( + 'meetingId' => '1234', -- REQUIRED - The unique id for the meeting + 'password' => 'mp' -- REQUIRED - The moderator password for the meeting + ); + */ + $this->_meetingId = $this->_requiredParam($infoParams['meetingId']); + $this->_password = $this->_requiredParam($infoParams['password']); + $infoUrl = $this->_bbbServerBaseUrl."api/getMeetingInfo?"; + $params = + 'meetingID='.urlencode($this->_meetingId). + '&password='.urlencode($this->_password); + return ($infoUrl.$params.'&checksum='.sha1("getMeetingInfo".$params.$this->_securitySalt)); + } + + public function getMeetingInfoWithXmlResponseArray($infoParams) { + /* USAGE: + $infoParams = array( + 'meetingId' => '1234', -- REQUIRED - The unique id for the meeting + 'password' => 'mp' -- REQUIRED - The moderator password for the meeting + ); + */ + $xml = $this->_processXmlResponse($this->getMeetingInfoUrl($infoParams)); + if($xml) { + // If we don't get a success code or messageKey, find out why: + if (($xml->returncode != 'SUCCESS') || ($xml->messageKey == null)) { + $result = array( + 'returncode' => $xml->returncode, + 'messageKey' => $xml->messageKey, + 'message' => $xml->message + ); + return $result; + } + else { + // In this case, we have success and meeting info: + $result = array( + 'returncode' => $xml->returncode, + 'meetingName' => $xml->meetingName, + 'meetingId' => $xml->meetingID, + 'createTime' => $xml->createTime, + 'voiceBridge' => $xml->voiceBridge, + 'attendeePw' => $xml->attendeePW, + 'moderatorPw' => $xml->moderatorPW, + 'running' => $xml->running, + 'recording' => $xml->recording, + 'hasBeenForciblyEnded' => $xml->hasBeenForciblyEnded, + 'startTime' => $xml->startTime, + 'endTime' => $xml->endTime, + 'participantCount' => $xml->participantCount, + 'maxUsers' => $xml->maxUsers, + 'moderatorCount' => $xml->moderatorCount, + ); + // Then interate through attendee results and return them as part of the array: + foreach ($xml->attendees->attendee as $a) { + $result[] = array( + 'userId' => $a->userID, + 'fullName' => $a->fullName, + 'role' => $a->role + ); + } + return $result; + } + } + else { + return null; + } + + } + + /* __________________ BBB RECORDING METHODS _________________ */ + /* The methods in the following section support the following categories of the BBB API: + -- getRecordings + -- publishRecordings + -- deleteRecordings + */ + + public function getRecordingsUrl($recordingParams) { + /* USAGE: + $recordingParams = array( + 'meetingId' => '1234', -- OPTIONAL - comma separate if multiple ids + ); + */ + $recordingsUrl = $this->_bbbServerBaseUrl."api/getRecordings?"; + $params = + 'meetingID='.urlencode($recordingParams['meetingId']); + return ($recordingsUrl.$params.'&checksum='.sha1("getRecordings".$params.$this->_securitySalt)); + + } + + public function getRecordingsWithXmlResponseArray($recordingParams) { + /* USAGE: + $recordingParams = array( + 'meetingId' => '1234', -- OPTIONAL - comma separate if multiple ids + ); + NOTE: 'duration' DOES work when creating a meeting, so if you set duration + when creating a meeting, it will kick users out after the duration. Should + probably be required in user code when 'recording' is set to true. + */ + $xml = $this->_processXmlResponse($this->getRecordingsUrl($recordingParams)); + if($xml) { + // If we don't get a success code or messageKey, find out why: + if (($xml->returncode != 'SUCCESS') || ($xml->messageKey == null)) { + $result = array( + 'returncode' => $xml->returncode, + 'messageKey' => $xml->messageKey, + 'message' => $xml->message + ); + return $result; + } + else { + // In this case, we have success and recording info: + $result = array( + 'returncode' => $xml->returncode, + 'messageKey' => $xml->messageKey, + 'message' => $xml->message + ); + + foreach ($xml->recordings->recording as $r) { + $result[] = array( + 'recordId' => $r->recordID, + 'meetingId' => $r->meetingID, + 'name' => $r->name, + 'published' => $r->published, + 'startTime' => $r->startTime, + 'endTime' => $r->endTime, + 'playbackFormatType' => $r->playback->format->type, + 'playbackFormatUrl' => $r->playback->format->url, + 'playbackFormatLength' => $r->playback->format->length, + 'metadataTitle' => $r->metadata->title, + 'metadataSubject' => $r->metadata->subject, + 'metadataDescription' => $r->metadata->description, + 'metadataCreator' => $r->metadata->creator, + 'metadataContributor' => $r->metadata->contributor, + 'metadataLanguage' => $r->metadata->language, + // Add more here as needed for your app depending on your + // use of metadata when creating recordings. + ); + } + return $result; + } + } + else { + return null; + } + } + + public function getPublishRecordingsUrl($recordingParams) { + /* USAGE: + $recordingParams = array( + 'recordId' => '1234', -- REQUIRED - comma separate if multiple ids + 'publish' => 'true', -- REQUIRED - boolean: true/false + ); + */ + $recordingsUrl = $this->_bbbServerBaseUrl."api/publishRecordings?"; + $params = + 'recordID='.urlencode($recordingParams['recordId']). + '&publish='.urlencode($recordingParams['publish']); + return ($recordingsUrl.$params.'&checksum='.sha1("publishRecordings".$params.$this->_securitySalt)); + + } + + public function publishRecordingsWithXmlResponseArray($recordingParams) { + /* USAGE: + $recordingParams = array( + 'recordId' => '1234', -- REQUIRED - comma separate if multiple ids + 'publish' => 'true', -- REQUIRED - boolean: true/false + ); + */ + $xml = $this->_processXmlResponse($this->getPublishRecordingsUrl($recordingParams)); + if($xml) { + return array( + 'returncode' => $xml->returncode, + 'published' => $xml->published // -- Returns true/false. + ); + } + else { + return null; + } + + + } + + public function getDeleteRecordingsUrl($recordingParams) { + /* USAGE: + $recordingParams = array( + 'recordId' => '1234', -- REQUIRED - comma separate if multiple ids + ); + */ + $recordingsUrl = $this->_bbbServerBaseUrl."api/deleteRecordings?"; + $params = + 'recordID='.urlencode($recordingParams['recordId']); + return ($recordingsUrl.$params.'&checksum='.sha1("deleteRecordings".$params.$this->_securitySalt)); + } + + public function deleteRecordingsWithXmlResponseArray($recordingParams) { + /* USAGE: + $recordingParams = array( + 'recordId' => '1234', -- REQUIRED - comma separate if multiple ids + ); + */ + + $xml = $this->_processXmlResponse($this->getDeleteRecordingsUrl($recordingParams)); + if($xml) { + return array( + 'returncode' => $xml->returncode, + 'deleted' => $xml->deleted // -- Returns true/false. + ); + } + else { + return null; + } + + } + + + +} // END OF BIGBLUEBUTTON CLASS + +?> \ No newline at end of file diff --git a/plugin/bbb/lib/bbb_plugin.class.php b/plugin/bbb/lib/bbb_plugin.class.php index 0d6c714f28..c95ba20c8f 100644 --- a/plugin/bbb/lib/bbb_plugin.class.php +++ b/plugin/bbb/lib/bbb_plugin.class.php @@ -36,6 +36,7 @@ class BBBPlugin extends Plugin record INT NOT NULL DEFAULT 0, status INT NOT NULL DEFAULT 0, created_at VARCHAR(255) NOT NULL, + closed_at VARCHAR(255) NOT NULL, calendar_id INT DEFAULT 0, welcome_msg VARCHAR(255) NOT NULL DEFAULT '')"; Database::query($sql); diff --git a/plugin/bbb/listing.php b/plugin/bbb/listing.php index c7edd5df37..1e4aa67362 100644 --- a/plugin/bbb/listing.php +++ b/plugin/bbb/listing.php @@ -17,6 +17,8 @@ $action = isset($_GET['action']) ? $_GET['action'] : null; $teacher = api_is_course_admin() || api_is_coach() || api_is_platform_admin(); +api_protect_course_script(true); + if ($teacher) { switch ($action) { case 'add_to_calendar':