Replicated change ielashi made with demo4 so we can use GetMeetingInfo + GetMeetings API. Courtesy of ielashi for all jscript part.

git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@4065 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
DJP 2010-03-29 22:58:05 +00:00
parent 8255c58d7e
commit e08308b4df
10 changed files with 848 additions and 22 deletions

View File

@ -1,5 +1,5 @@
<!--
<?
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
@ -18,8 +18,7 @@ with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: DJP <DJP@architectes.org>
-->
<?
*/
require('bbb_api_conf.inc.php');
/*
@ -95,4 +94,65 @@ function isMeetingRunning($meetingToken, $meetingID)
else
return (false);
}
/*
* getURLMeetingInfo() -- return a URL to get MeetingInfo
* Beware : check that BIGBLUEBUTTONURL is reachable internally from your PHP Web Application Server. (Hosts, firewall...)
*/
function getURLMeetingInfo($meetingID, $moderatorPW)
{
$base_url = BIGBLUEBUTTONURL."api/getMeetingInfo?";
$params = 'meetingID='.urlencode($meetingID).'&password='.$moderatorPW;
return ($base_url.$params.'&checksum='.sha1($params.SALT));
}
/*
* getMeetings() -- Calls getMeetingInfo to obtain information on a given meeting.
*/
function getMeetingInfo($meetingID, $moderatorPW)
{
$xml = bbb_wrap_simplexml_load_file(getURLMeetingInfo($meetingID, $moderatorPW));
return (str_replace('</response>', '', str_replace("<?xml version=\"1.0\"?>\n<response>", '', $xml->asXML())));
}
/*
* getURLMeetings() -- return a URL for listing all running meetings
* Beware : check that BIGBLUEBUTTONURL is reachable internally from your PHP Web Application Server. (Hosts, firewall...)
*/
function getURLMeetings()
{
$base_url = BIGBLUEBUTTONURL."api/getMeetings?";
$params = 'random='.(rand() * 1000);
return ($base_url.$params.'&checksum='.sha1($params.SALT));
}
/*
* getMeetings() -- Calls getMeetings to obtain the list of meetings, then calls getMeetingInfo for each meeting and concatenates the result.
*/
function getMeetings()
{
$xml = bbb_wrap_simplexml_load_file(getURLMeetings());
if ($xml && $xml->returncode == 'SUCCESS')
{
if ($xml->messageKey)
return ($xml->message->asXML());
ob_start();
echo '<meetings>';
if (count($xml->meetings) && count($xml->meetings->meeting))
{
foreach ($xml->meetings->meeting as $meeting)
{
echo '<meeting>';
echo getMeetingInfo($meeting->meetingID, $meeting->moderatorPW);
echo '</meeting>';
}
}
echo '</meetings>';
return (ob_get_clean());
}
else
return (false);
}
?>

View File

@ -1,5 +1,5 @@
<!--
<?
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
@ -18,8 +18,8 @@ with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: DJP <DJP@architectes.org>
-->
<?
*/
require('bbb_api.inc.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@ -60,9 +60,8 @@ Error: getJoinURL() failed
}
else
{
include('demo_header.php');
?>
<a href="demo1.php">Join a Course</a> | <a href="demo2.php">Join a Selected Course</a> | <a href="demo3.php">Create Your Own Meeting</a> | <a href="/">Home</a>
<h2>Demo #1: Join a Course</h2>
<form name="form1" method="get">

View File

@ -1,5 +1,5 @@
<!--
<?
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
@ -18,8 +18,8 @@ with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: DJP <DJP@architectes.org>
-->
<?
*/
require('bbb_api.inc.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@ -56,9 +56,8 @@ Error: getJoinURL() failed
}
else
{
include('demo_header.php');
?>
<a href="demo1.php">Join a Course</a> | <a href="demo2.php">Join a Selected Course</a> | <a href="demo3.php">Create Your Own Meeting</a> | <a href="/">Home</a>
<h2>Demo #2: Join a Selected Course</h2>
<form name="form1" method="get">

View File

@ -1,5 +1,5 @@
<!--
<?
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
@ -18,8 +18,8 @@ with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: DJP <DJP@architectes.org>
-->
<?
*/
require('bbb_api.inc.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@ -137,9 +137,8 @@ switch ($_REQUEST['action'])
switch ($step)
{
case '1':
include('demo_header.php');
?>
<a href="demo1.php">Join a Course</a> | <a href="demo2.php">Join a Selected Course</a> | <a href="demo3.php">Create Your Own Meeting</a> | <a href="/">Home</a>
<h2>Demo #3: Create Your Own Meeting</h2>
<form name="form1" method="get">

147
bbb-api-examples/PHP/demo4.js Executable file
View File

@ -0,0 +1,147 @@
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
BigBlueButton is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
BigBlueButton 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: Islam El-Ashi <ielashi@gmail.com>
*/
var meetings; // will hold the meetings data
$(document).ready(function(){
updateMeetingInfo(); // update the available meeting information as soon as the page is loaded.
setInterval("updateMeetingInfo()", 15000); // update the meeting information every 15 seconds
});
// For each active meeting, create a table listing the participants and insert it into the page.
function createMeetings() {
var nOfMeetings = 0;
if (meetings.meeting) {
for (var i in meetings.meeting) {
// this variable is to work around the JSON nuance of having a variable instead of an array of one member.
// if we detect there is more than one meeting use the array, otherwise use the variable
var meeting = (meetings.meeting[i].attendees != null) ? meetings.meeting[i] : meetings.meeting;
createMeetingTable(meeting);
if (meeting.participantCount != "0") nOfMeetings++;
// this is also to work around the JSON nuance, if we previously detected that there is only
// one element (i.e. a variable) then we shouldn't loop again.
if (meeting == meetings.meeting) break;
}
}
// if there are no meetings then display a message to the user.
if (nOfMeetings == 0) {
$("#no_meetings").text("No meetings currently running.");
$("#meetings").text('');
}
else
$("#no_meetings").text('');
}
// creates div tags for each meeting to be able to insert the meeting table into the DOM afterwards
function initializeDivTags() {
if (meetings.meeting) {
var meetingID;
var meeting;
var encodedMeetingID;
for (var i in meetings.meeting) {
meeting = (meetings.meeting[i].attendees != null) ? meetings.meeting[i] : meetings.meeting;
meetingID = meeting.meetingID;
encodedMeeting = encode(meetingID);
if ($("#" + encodedMeeting).length == 0) {
// assign the div tag an id unique to each meeting
// the id assigned is the encoded value of the meeting id, the encoding is to avoid
// special characters and spaces in the id
$("#meetings").append('<div id="' + encodedMeeting + '" class="hiddenDiv"></div>');
}
if (meeting == meetings.meeting) break;
}
}
}
// call the demo4 helper page to fetch the updated data, this is executed every 15 seconds.
function updateMeetingInfo() {
$.ajax({
type: "GET",
url: 'demo4_helper.php?getxml=true',
dataType: "text/xml",
cache: false,
success: function(xml) {
meetings = $.xml2json(xml);
initializeDivTags();
createMeetings();
},
error: function() {
$("#no_meetings").text("Failed to connect to API.");
$("#meetings").text("");
}
});
}
function getMeetingsInfoURL(meetingID, password, checksum) {
return '../api/getMeetingInfo?meetingID=' + meetingID + '&password=' + password + '&checksum=' + checksum;
}
function createMeetingTable(meeting) {
var tableContent = '<table name="' + meeting.meetingID + '" class="hor-minimalist-b" cellspacing="0" summary="The current participants in a meeting"><caption>' + meeting.meetingID + '</caption><tr><th scope="col" abbr="Participants">Participants</th><th scope="col" abbr="Name">Name</th><th scope="col" abbr="Role">Role</th></tr>';
var encodedMeetingID = encode(meeting.meetingID);
var tableRowId;
var newRows = new Array();
var numberOfRows = 0;
if (meeting.attendees.attendee) {
for (var i in meeting.attendees.attendee) {
var attendee = (meeting.attendees.attendee[i].userID != null) ? meeting.attendees.attendee[i] : meeting.attendees.attendee;
tableRowId = encodedMeetingID + '_' + attendee.userID;
tableContent += '<tr id="' + tableRowId + '"><td>' + attendee.userID + '<td>' + attendee.fullName + '</td><td>' + attendee.role + '</td></tr>'
// if there is a new row to be added, then add to the new rows array to display it with a flash effect.
if ($("#" + tableRowId).length == 0) {
newRows[newRows.length] = tableRowId;
}
numberOfRows++;
if (attendee == meeting.attendees.attendee) break;
}
}
tableContent += '</table>';
if (numberOfRows > 0) {
$("#" + encodedMeetingID).html(tableContent);
$("#" + encodedMeetingID).show("fast");
}
else {
$("#" + encodedMeetingID).hide("fast");
}
for (var i = 0; i < newRows.length; i++) {
$("#" + newRows[i]).effect("highlight", {}, 3000);
}
}
// the encoding hashes the string to an md5, which ensures - to a great extent - that the encoded string will be
// 1. unique per the original string
// 2. has no spaces and/or special characters
function encode(string) {
return hex_md5(string);
}

54
bbb-api-examples/PHP/demo4.php Executable file
View File

@ -0,0 +1,54 @@
<?
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
BigBlueButton is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
BigBlueButton 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: DJP <DJP@architectes.org>
*/
require('bbb_api.inc.php');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<title>Get Meeting Info</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="demo4.js"></script>
<script type="text/javascript" src="md5.js"></script>
<script type="text/javascript" src="jquery.xml2json.js"></script>
<style type="text/css">
.hiddenDiv {display:none;}
.hor-minimalist-b{font-family:"Lucida Sans Unicode", "Lucida Grande", Sans-Serif;font-size:12px;background:#fff;width:480px;border-collapse:collapse;text-align:left;margin:20px;}.hor-minimalist-b th{font-size:14px;font-weight:normal;color:#039;border-bottom:2px solid #6678b1;padding:10px 8px;}.hor-minimalist-b td{border-bottom:1px solid #ccc;color:#669;padding:6px 8px;width:100px;}.hor-minimalist-b tbody tr:hover td{color:#009;}</style>
</head>
<body>
<br />
<?
include('demo_header.php');
?>
<h2>Demo #4: Activity Monitor</h2>
<p id="no_meetings"></p>
<div id="meetings"></div>
<?
include('demo_footer.php');
?>
</body>
</html>

View File

@ -0,0 +1,28 @@
<?
/*
BigBlueButton - http://www.bigbluebutton.org
Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
BigBlueButton is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.
BigBlueButton 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with BigBlueButton; if not, If not, see <http://www.gnu.org/licenses/>.
Author: DJP <DJP@architectes.org>
*/
require('bbb_api.inc.php');
echo '<?xml version="1.0"?>'."\r\n";
header('content-type: text/xml');
echo getMeetings();
?>

View File

@ -0,0 +1 @@
<a href="demo1.php">Join a Course</a> | <a href="demo2.php">Join a Selected Course</a> | <a href="demo3.php">Create Your Own Meeting</a> | <a href="demo4.php">Activity Monitor</a> | <a href="/">Home</a>

View File

@ -0,0 +1,160 @@
/*
### jQuery XML to JSON Plugin v1.0 - 2008-07-01 ###
* http://www.fyneworks.com/ - diego@fyneworks.com
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
###
Website: http://www.fyneworks.com/jquery/xml-to-json/
*//*
# INSPIRED BY: http://www.terracoder.com/
AND: http://www.thomasfrank.se/xml_to_json.html
AND: http://www.kawa.net/works/js/xml/objtree-e.html
*//*
This simple script converts XML (document of code) into a JSON object. It is the combination of 2
'xml to json' great parsers (see below) which allows for both 'simple' and 'extended' parsing modes.
*/
// Avoid collisions
;if(window.jQuery) (function($){
// Add function to jQuery namespace
$.extend({
// converts xml documents and xml text to json object
xml2json: function(xml, extended) {
if(!xml) return {}; // quick fail
//### PARSER LIBRARY
// Core function
function parseXML(node, simple){
if(!node) return null;
var txt = '', obj = null, att = null;
var nt = node.nodeType, nn = jsVar(node.localName || node.nodeName);
var nv = node.text || node.nodeValue || '';
/*DBG*/ //if(window.console) console.log(['x2j',nn,nt,nv.length+' bytes']);
if(node.childNodes){
if(node.childNodes.length>0){
/*DBG*/ //if(window.console) console.log(['x2j',nn,'CHILDREN',node.childNodes]);
$.each(node.childNodes, function(n,cn){
var cnt = cn.nodeType, cnn = jsVar(cn.localName || cn.nodeName);
var cnv = cn.text || cn.nodeValue || '';
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>a',cnn,cnt,cnv]);
if(cnt == 8){
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>b',cnn,'COMMENT (ignore)']);
return; // ignore comment node
}
else if(cnt == 3 || cnt == 4 || !cnn){
// ignore white-space in between tags
if(cnv.match(/^\s+$/)){
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>c',cnn,'WHITE-SPACE (ignore)']);
return;
};
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>d',cnn,'TEXT']);
txt += cnv.replace(/^\s+/,'').replace(/\s+$/,'');
// make sure we ditch trailing spaces from markup
}
else{
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>e',cnn,'OBJECT']);
obj = obj || {};
if(obj[cnn]){
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>f',cnn,'ARRAY']);
if(!obj[cnn].length) obj[cnn] = myArr(obj[cnn]);
obj[cnn][ obj[cnn].length ] = parseXML(cn, true/* simple */);
obj[cnn].length = obj[cnn].length;
}
else{
/*DBG*/ //if(window.console) console.log(['x2j',nn,'node>g',cnn,'dig deeper...']);
obj[cnn] = parseXML(cn);
};
};
});
};//node.childNodes.length>0
};//node.childNodes
if(node.attributes){
if(node.attributes.length>0){
/*DBG*/ //if(window.console) console.log(['x2j',nn,'ATTRIBUTES',node.attributes])
att = {}; obj = obj || {};
$.each(node.attributes, function(a,at){
var atn = jsVar(at.name), atv = at.value;
att[atn] = atv;
if(obj[atn]){
/*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'ARRAY']);
if(!obj[atn].length) obj[atn] = myArr(obj[atn]);//[ obj[ atn ] ];
obj[atn][ obj[atn].length ] = atv;
obj[atn].length = obj[atn].length;
}
else{
/*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'TEXT']);
obj[atn] = atv;
};
});
//obj['attributes'] = att;
};//node.attributes.length>0
};//node.attributes
if(obj){
obj = $.extend( (txt!='' ? new String(txt) : {}),/* {text:txt},*/ obj || {}/*, att || {}*/);
txt = (obj.text) ? (typeof(obj.text)=='object' ? obj.text : [obj.text || '']).concat([txt]) : txt;
if(txt) obj.text = txt;
txt = '';
};
var out = obj || txt;
//console.log([extended, simple, out]);
if(extended){
if(txt) out = {};//new String(out);
txt = out.text || txt || '';
if(txt) out.text = txt;
if(!simple) out = myArr(out);
};
return out;
};// parseXML
// Core Function End
// Utility functions
var jsVar = function(s){ return String(s || '').replace(/-/g,"_"); };
var isNum = function(s){ return (typeof s == "number") || String((s && typeof s == "string") ? s : '').test(/^((-)?([0-9]*)((\.{0,1})([0-9]+))?$)/); };
var myArr = function(o){
if(!o.length) o = [ o ]; o.length=o.length;
// here is where you can attach additional functionality, such as searching and sorting...
return o;
};
// Utility functions End
//### PARSER LIBRARY END
// Convert plain text to xml
if(typeof xml=='string') xml = $.text2xml(xml);
// Quick fail if not xml (or if this is a node)
if(!xml.nodeType) return;
if(xml.nodeType == 3 || xml.nodeType == 4) return xml.nodeValue;
// Find xml root node
var root = (xml.nodeType == 9) ? xml.documentElement : xml;
// Convert xml to json
var out = parseXML(root, true /* simple */);
// Clean-up memory
xml = null; root = null;
// Send output
return out;
},
// Convert text to XML DOM
text2xml: function(str) {
// NOTE: I'd like to use jQuery for this, but jQuery makes all tags uppercase
//return $(xml)[0];
var out;
try{
var xml = ($.browser.msie)?new ActiveXObject("Microsoft.XMLDOM"):new DOMParser();
xml.async = false;
}catch(e){ throw new Error("XML Parser could not be instantiated") };
try{
if($.browser.msie) out = (xml.loadXML(str))?xml:false;
else out = xml.parseFromString(str, "text/xml");
}catch(e){ throw new Error("Error parsing XML string") };
return out;
}
}); // extend $
})(jQuery);

379
bbb-api-examples/PHP/md5.js Executable file
View File

@ -0,0 +1,379 @@
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
function hex_hmac_md5(k, d)
{ return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function b64_hmac_md5(k, d)
{ return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function any_hmac_md5(k, d, e)
{ return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of a raw string
*/
function rstr_md5(s)
{
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstr_hmac_md5(key, data)
{
var bkey = rstr2binl(key);
if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
function rstr2hex(input)
{
try { hexcase } catch(e) { hexcase=0; }
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var output = "";
var x;
for(var i = 0; i < input.length; i++)
{
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F)
+ hex_tab.charAt( x & 0x0F);
}
return output;
}
/*
* Convert a raw string to a base-64 string
*/
function rstr2b64(input)
{
try { b64pad } catch(e) { b64pad=''; }
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var output = "";
var len = input.length;
for(var i = 0; i < len; i += 3)
{
var triplet = (input.charCodeAt(i) << 16)
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > input.length * 8) output += b64pad;
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
}
}
return output;
}
/*
* Convert a raw string to an arbitrary string encoding
*/
function rstr2any(input, encoding)
{
var divisor = encoding.length;
var i, j, q, x, quotient;
/* Convert to an array of 16-bit big-endian values, forming the dividend */
var dividend = Array(Math.ceil(input.length / 2));
for(i = 0; i < dividend.length; i++)
{
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
}
/*
* Repeatedly perform a long division. The binary array forms the dividend,
* the length of the encoding is the divisor. Once computed, the quotient
* forms the dividend for the next step. All remainders are stored for later
* use.
*/
var full_length = Math.ceil(input.length * 8 /
(Math.log(encoding.length) / Math.log(2)));
var remainders = Array(full_length);
for(j = 0; j < full_length; j++)
{
quotient = Array();
x = 0;
for(i = 0; i < dividend.length; i++)
{
x = (x << 16) + dividend[i];
q = Math.floor(x / divisor);
x -= q * divisor;
if(quotient.length > 0 || q > 0)
quotient[quotient.length] = q;
}
remainders[j] = x;
dividend = quotient;
}
/* Convert the remainders to the output string */
var output = "";
for(i = remainders.length - 1; i >= 0; i--)
output += encoding.charAt(remainders[i]);
return output;
}
/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
function str2rstr_utf8(input)
{
var output = "";
var i = -1;
var x, y;
while(++i < input.length)
{
/* Decode utf-16 surrogate pairs */
x = input.charCodeAt(i);
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
{
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
i++;
}
/* Encode output as utf-8 */
if(x <= 0x7F)
output += String.fromCharCode(x);
else if(x <= 0x7FF)
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
0x80 | ( x & 0x3F));
else if(x <= 0xFFFF)
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
else if(x <= 0x1FFFFF)
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
0x80 | ((x >>> 12) & 0x3F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
}
return output;
}
/*
* Encode a string as utf-16
*/
function str2rstr_utf16le(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
(input.charCodeAt(i) >>> 8) & 0xFF);
return output;
}
function str2rstr_utf16be(input)
{
var output = "";
for(var i = 0; i < input.length; i++)
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
input.charCodeAt(i) & 0xFF);
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl(input)
{
var output = Array(input.length >> 2);
for(var i = 0; i < output.length; i++)
output[i] = 0;
for(var i = 0; i < input.length * 8; i += 8)
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
return output;
}
/*
* Convert an array of little-endian words to a string
*/
function binl2rstr(input)
{
var output = "";
for(var i = 0; i < input.length * 32; i += 8)
output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
return output;
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binl_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}