for readability and maintainability splitted lsp files
This commit is contained in:
parent
d7a0a60053
commit
1d2ff96f6e
7 changed files with 1721 additions and 1667 deletions
372
lsp/functions.js
Normal file
372
lsp/functions.js
Normal file
|
@ -0,0 +1,372 @@
|
|||
|
||||
/**
|
||||
* Show a confirm dialog
|
||||
* @param question the question displayed
|
||||
*/
|
||||
function confirmDelete(question)
|
||||
{
|
||||
return confirm(question);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format a date to mm/dd/yyyy hh:mm:ss format
|
||||
* @param date the date to format (timestamp)
|
||||
*/
|
||||
function formatDate(date)
|
||||
{
|
||||
var d = new Date(date * 1000);
|
||||
|
||||
return [
|
||||
('00' + d.getMonth()).slice(-2),
|
||||
('00' + d.getDate()).slice(-2),
|
||||
d.getFullYear()
|
||||
].join('/') + ' ' + [
|
||||
('00' + d.getHours()).slice(-2),
|
||||
('00' + d.getMinutes()).slice(-2),
|
||||
('00' + d.getSeconds()).slice(-2)
|
||||
].join(':');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find out what kind of resource an URI is
|
||||
* @param uri the URI to check. If it start with a protocol (ebut not file://) return 'Live', else 'Recorded'
|
||||
*/
|
||||
function TypeofResource(uri)
|
||||
{
|
||||
var protocol = /([a-zA-Z]+):\/\//.exec(uri);
|
||||
|
||||
if(protocol === null || (protocol[1] && protocol[1] === 'file'))
|
||||
{
|
||||
return 'Recorded';
|
||||
}else{
|
||||
return 'Live';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* convert a short limit name to a long one using the table above
|
||||
* @param name the short name of a limit
|
||||
*/
|
||||
function shortToLongLimit(name)
|
||||
{
|
||||
var i;
|
||||
|
||||
for(i = 0; i < ltypes.length; i++)
|
||||
{
|
||||
if(name == ltypes[i][0])
|
||||
{
|
||||
return ltypes[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* forse the server to save to the config file
|
||||
* @param callback function to call after the command is send
|
||||
*/
|
||||
function forceJSONSave(callback)
|
||||
{
|
||||
// build the object to send to the server
|
||||
var data =
|
||||
{
|
||||
'authorize':
|
||||
{
|
||||
'username': settings.credentials.username,
|
||||
'password': (settings.credentials.authstring != "" ? MD5(MD5(settings.credentials.password) + settings.credentials.authstring) : "" )
|
||||
},
|
||||
'save': 1
|
||||
};
|
||||
|
||||
// make the XHR call
|
||||
$.ajax(
|
||||
{
|
||||
'url': settings.server,
|
||||
'data':
|
||||
{
|
||||
"command": JSON.stringify(data)
|
||||
},
|
||||
'dataType': 'jsonp',
|
||||
'timeout': 10000,
|
||||
'error': function(){},
|
||||
'success': function(){}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* retrieves data from the server ;)
|
||||
* note: does not authenticate first. Assumes user is logged in.
|
||||
* @param callback the function to call when the data has been retrieved. This callback has 1 parameter, the data retrieved.
|
||||
*/
|
||||
function getData(callback)
|
||||
{
|
||||
var data =
|
||||
{
|
||||
'authorize':
|
||||
{
|
||||
'username': settings.credentials.username,
|
||||
'password': (settings.credentials.authstring != "" ? MD5(MD5(settings.credentials.password) + settings.credentials.authstring) : "" )
|
||||
}
|
||||
};
|
||||
|
||||
$.ajax(
|
||||
{
|
||||
'url': settings.server,
|
||||
'data':
|
||||
{
|
||||
"command": JSON.stringify(data)
|
||||
},
|
||||
'dataType': 'jsonp',
|
||||
'timeout': 10000,
|
||||
'error': function(){},
|
||||
'success': function(d)
|
||||
{
|
||||
|
||||
var ret = $.extend(true,
|
||||
{
|
||||
"streams": {},
|
||||
"statistics": {}
|
||||
}, d);
|
||||
|
||||
console.log('[651] RECV', ret);
|
||||
|
||||
if(callback)
|
||||
{
|
||||
callback(ret);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* retrieved the status and number of viewers from all streams
|
||||
* @param callback function that is called when the data is collected. Has one parameter, the data retrieved
|
||||
*/
|
||||
function getStreamsData(callback)
|
||||
{
|
||||
|
||||
getData(function(data)
|
||||
{
|
||||
var streams = {}; // streamID: [status, numViewers];
|
||||
var cnt = 0;
|
||||
|
||||
for(var stream in data.streams)
|
||||
{
|
||||
streams[stream] = [data.streams[stream].online, 0];
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if(cnt === 0)
|
||||
{
|
||||
return; // if there are no streams, don't collect data and just return
|
||||
}
|
||||
|
||||
for(stream in data.statistics)
|
||||
{
|
||||
if(data.statistics[stream].curr)
|
||||
{
|
||||
for(var viewer in data.statistics[stream].curr)
|
||||
{
|
||||
streams[stream][1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback(streams);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* parses an url and returns the parts of it.
|
||||
* @return object containing the parts of the URL: protocol, host and port.
|
||||
*/
|
||||
function parseURL(url)
|
||||
{
|
||||
var pattern = /(https?)\:\/\/([^:\/]+)\:(\d+)?/;
|
||||
|
||||
var retobj = {protocol: '', host: '', port: ''};
|
||||
var results = url.match(pattern);
|
||||
|
||||
if(results != null)
|
||||
{
|
||||
retobj.protocol = results[1];
|
||||
retobj.host = results[2];
|
||||
retobj.port = results[3];
|
||||
}
|
||||
|
||||
return retobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* go figure.
|
||||
* @return true if there is a HTTP connector... and false if there isn't.
|
||||
*/
|
||||
function isThereAHTTPConnector()
|
||||
{
|
||||
var i,
|
||||
len = (settings.settings.config.protocols ? settings.settings.config.protocols.length : 0);
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
if(settings.settings.config.protocols[i].connector == 'HTTP')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* retrieves the stream status (online and total number of streams) and viewer info (total number of viewers).
|
||||
* @param callback function that is called when data is retrieved. Has one parameter, the retrieved data.
|
||||
*/
|
||||
function getStatData(callback)
|
||||
{
|
||||
getData(function(data)
|
||||
{
|
||||
var svr, viewer, ret,
|
||||
numstr = 0,
|
||||
numvwr = 0,
|
||||
numtotstr = 0;
|
||||
|
||||
for(svr in data.statistics)
|
||||
{
|
||||
if(data.statistics[svr].curr)
|
||||
{
|
||||
for(viewer in data.statistics[svr].curr)
|
||||
{
|
||||
numvwr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(svr in data.streams)
|
||||
{
|
||||
numtotstr++;
|
||||
|
||||
if(data.streams[svr].online && data.streams[svr].online == 1)
|
||||
{
|
||||
numstr++;
|
||||
}
|
||||
}
|
||||
|
||||
ret = {streams: [numstr, numtotstr], viewers: numvwr};
|
||||
callback(ret);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to the server and retrieve the data
|
||||
* @param callback the function to call when connected. Has one parameter, an optional error string.
|
||||
*/
|
||||
function loadSettings(callback)
|
||||
{
|
||||
// display 'loading, please wait' while retrieving data
|
||||
$('body').append( $('<div>').attr('id', 'shield').text('Loading, please wait...') );
|
||||
|
||||
var errorstr = '',
|
||||
data = $.extend(settings.settings,
|
||||
{
|
||||
'authorize':
|
||||
{
|
||||
'username': settings.credentials.username,
|
||||
'password': (settings.credentials.authstring != "" ? MD5(MD5(settings.credentials.password) + settings.credentials.authstring) : "" )
|
||||
}
|
||||
});
|
||||
|
||||
delete data.log; // don't send the logs back to the server
|
||||
delete data.statistics; // same goes for the stats
|
||||
|
||||
console.log('[763] SEND', data);
|
||||
|
||||
$.ajax(
|
||||
{
|
||||
'url': settings.server,
|
||||
'data':
|
||||
{
|
||||
"command": JSON.stringify(data)
|
||||
},
|
||||
'dataType': 'jsonp',
|
||||
|
||||
'timeout': 5000,
|
||||
|
||||
'error': function()
|
||||
{
|
||||
showTab('disconnect');
|
||||
$('#shield').remove(); // remove loading display
|
||||
},
|
||||
'success': function(d)
|
||||
{
|
||||
$('#shield').remove(); // remove loading display
|
||||
|
||||
console.log('[785] RECV', d);
|
||||
|
||||
if(d && d['authorize'] && d['authorize']['challenge'])
|
||||
{
|
||||
if (settings.credentials.authstring != d['authorize']['challenge'])
|
||||
{
|
||||
settings.credentials.authstring = d['authorize']['challenge'];
|
||||
loadSettings(callback);
|
||||
return;
|
||||
}else{
|
||||
errorstr = 'wrong credentials';
|
||||
}
|
||||
}else{
|
||||
settings.settings = $.extend(true, {
|
||||
"config":
|
||||
{
|
||||
"host": "",
|
||||
"limits": [],
|
||||
"name": "",
|
||||
"protocols": [],
|
||||
"status": "",
|
||||
"version": ""
|
||||
},
|
||||
"streams": {},
|
||||
"log": {},
|
||||
"statistics": {}
|
||||
}, d);
|
||||
}
|
||||
|
||||
if(callback)
|
||||
{
|
||||
callback(errorstr);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the page's header text (loging in, connected, disconnected), title and pretty colors (!)
|
||||
* @param state the state of the header. Possible are 'logingin', 'disconnected' or 'connected'.
|
||||
*/
|
||||
function setHeaderState(state)
|
||||
{
|
||||
var text, cname, title;
|
||||
|
||||
switch(state)
|
||||
{
|
||||
case 'logingin': text = 'connecting...'; cname = 'loggingin'; title = 'connecting to ' + settings.server; break;
|
||||
case 'disconnected': text = 'disconnected'; cname = 'disconnected'; title = 'disconnected'; break;
|
||||
case 'connected': text = 'connected'; cname = 'connected'; title = 'connected to ' + settings.server; break;
|
||||
}
|
||||
|
||||
document.title = 'Mistserver Manager - ' + title;
|
||||
|
||||
$('#header-connection').attr('class', cname);
|
||||
$('#header-connection').text(text);
|
||||
$('#header-host').text(settings.server.replace('HTTP://', ''));
|
||||
}
|
||||
|
1667
server.html → lsp/jquery.js
vendored
1667
server.html → lsp/jquery.js
vendored
File diff suppressed because one or more lines are too long
915
lsp/main.js
Normal file
915
lsp/main.js
Normal file
|
@ -0,0 +1,915 @@
|
|||
|
||||
|
||||
/* WERKLOG todolist
|
||||
// TODO FIXME remove deze comment als het klaar is
|
||||
settings.settings.statistics[streamID].log (zelfde als curr maar log = gesloten connecties, dus ex-users
|
||||
TODO als server het stuurt
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Local settings page
|
||||
* DDVTECH
|
||||
* for more information, see http://mistserver.org/index.php?title=Stand-alone_Configuration_Page
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Store a local copy of the data send by the server.
|
||||
* server is the URL, credentials hold the username, password and authstring and settings is the local copy.
|
||||
*/
|
||||
var settings =
|
||||
{
|
||||
server: '',
|
||||
credentials:
|
||||
{
|
||||
username: "",
|
||||
password: "",
|
||||
authstring: ""
|
||||
},
|
||||
settings: {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Table for long/short limit names
|
||||
*/
|
||||
var ltypes =
|
||||
[
|
||||
['kb_total', 'Total bandwidth'],
|
||||
['kbps_max', 'Current bandwidth'],
|
||||
['users', 'Concurrent users'],
|
||||
['streams', 'Cocurrent streams'],
|
||||
['geo', 'Geolimited'],
|
||||
['host', 'Hostlimited'],
|
||||
['time', 'Timelimited'],
|
||||
['duration', 'Duration'],
|
||||
['str_kbps_min', 'Minimum bitrate'],
|
||||
['str_kbps_max', 'Maximum bitrate']
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* When the page loads, fix the menu and show the correct tab
|
||||
*/
|
||||
$(document).ready(function()
|
||||
{
|
||||
$('#nav').children().each(function()
|
||||
{
|
||||
$(this).click(function()
|
||||
{
|
||||
// remove currently selected' class
|
||||
$('#nav').children().each(function()
|
||||
{
|
||||
$(this).attr('class', '');
|
||||
});
|
||||
|
||||
// select this one
|
||||
$(this).attr('class', 'selected');
|
||||
|
||||
// show correct tab
|
||||
showTab($(this).text());
|
||||
});
|
||||
});
|
||||
|
||||
// show login 'tab' and hide menu
|
||||
showTab('login');
|
||||
$('#nav').css('visibility', 'hidden');
|
||||
});
|
||||
|
||||
|
||||
|
||||
// used on the overview and streams page. cleared when switching to another 'tab'.
|
||||
var sinterval = null;
|
||||
|
||||
// what kind of streams should be displayed? Format is [recorded, live];
|
||||
var streamsdisplay = [true, true];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Display a certain page. It contains a (giant) switch-statement, that builds a page depending on the tab requested
|
||||
* @param name the name of the tab
|
||||
* @param streamname only used when editing streams, the name of the edited (or new) stream. Also used with the 'embed' tab
|
||||
*/
|
||||
function showTab(name, streamname)
|
||||
{
|
||||
// clear page and refresh interval
|
||||
$('#page').html('');
|
||||
clearInterval(sinterval);
|
||||
|
||||
switch(name)
|
||||
{
|
||||
case 'login':
|
||||
|
||||
var host = $('<input>').attr('type', 'text').attr('placeholder', 'HTTP://LOCALHOST:4242');
|
||||
var user = $('<input>').attr('type', 'text').attr('placeholder', 'USERNAME');
|
||||
var pass = $('<input>').attr('type', 'password').attr('placeholder', 'PASSWORD');
|
||||
var conn = $('<button>').click(function()
|
||||
{
|
||||
// get login info
|
||||
settings.credentials.username = user.val();
|
||||
settings.credentials.password = pass.val();
|
||||
settings.server = host.val() || host.attr('placeholder');
|
||||
|
||||
// save username, URL in address
|
||||
location.hash = user.val() + '@' + host.val();
|
||||
|
||||
// try to login
|
||||
setHeaderState('logingin');
|
||||
|
||||
loadSettings(function(errorstr)
|
||||
{
|
||||
if(errorstr == '')
|
||||
{
|
||||
setHeaderState('connected');
|
||||
|
||||
$('#nav').css('visibility', 'visible');
|
||||
|
||||
showTab('overview');
|
||||
|
||||
// show overview as current tab - this only happens when logging out and then in
|
||||
$('#nav').children().each(function()
|
||||
{
|
||||
if($(this).text() != 'overview')
|
||||
{
|
||||
$(this).attr('class', '');
|
||||
}else{
|
||||
$(this).attr('class', 'selected');
|
||||
}
|
||||
});
|
||||
|
||||
}else{
|
||||
setHeaderState('disconnected');
|
||||
$('#header-host').text('');
|
||||
}
|
||||
});
|
||||
}).text('login');
|
||||
|
||||
$('#page').append(
|
||||
$('<div>').attr('id', 'login').append(host).append(user).append(pass).append(conn)
|
||||
);
|
||||
|
||||
// if we 'enter' in host, user or pass we should try to login.
|
||||
function hand(e)
|
||||
{
|
||||
if(e.keyCode == 13)
|
||||
{
|
||||
conn.trigger('click'); // conn = login button
|
||||
}
|
||||
}
|
||||
|
||||
host.keypress(hand);
|
||||
user.keypress(hand);
|
||||
pass.keypress(hand);
|
||||
|
||||
// retrieve address hash from URL
|
||||
var adr = location.hash.replace('#', '').split('@');
|
||||
|
||||
if(adr.length == 2)
|
||||
{
|
||||
// put it in the page
|
||||
host.val(adr[1]);
|
||||
user.val(adr[0]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case 'overview':
|
||||
|
||||
$('#page').append(
|
||||
$('<div>').attr('id', 'editserver').append(
|
||||
$('<label>').attr('for', 'config-host').text('host').append(
|
||||
$('<input>').attr('type', 'text').attr('placeholder', 'HOST').attr('id', 'config-host').attr('value', settings.settings.config.host)
|
||||
)
|
||||
).append(
|
||||
$('<label>').attr('for', 'config-name').text('name').append(
|
||||
$('<input>').attr('type', 'text').attr('placeholder', 'NAME').attr('id', 'config-name').attr('value', settings.settings.config.name)
|
||||
)
|
||||
).append(
|
||||
$('<label>').text('version').append(
|
||||
$('<span>').text(settings.settings.config.version)
|
||||
)
|
||||
).append(
|
||||
$('<label>').text('time').append(
|
||||
$('<span>').text( formatDate(settings.settings.config.time) )
|
||||
)
|
||||
).append(
|
||||
$('<label>').text('Streams').append(
|
||||
$('<span>').attr('id', 'cur_streams_online').text('retrieving data...')
|
||||
)
|
||||
).append(
|
||||
$('<label>').text('Viewers').append(
|
||||
$('<span>').attr('id', 'cur_num_viewers').text('retrieving data...')
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
function showStats()
|
||||
{
|
||||
getStatData(function(data)
|
||||
{
|
||||
$('#cur_streams_online').html('').text(data.streams[0] + ' of ' + data.streams[1] + ' online');
|
||||
$('#cur_num_viewers').html('').text(data.viewers);
|
||||
});
|
||||
}
|
||||
|
||||
// refresh the stream status + viewers
|
||||
sinterval = setInterval(function()
|
||||
{
|
||||
showStats();
|
||||
}, 10000);
|
||||
|
||||
showStats();
|
||||
|
||||
|
||||
$('#editserver').append(
|
||||
$('<button>').attr('class', 'floatright').click(function()
|
||||
{
|
||||
var host = $('#config-host').val();
|
||||
var name = $('#config-name').val();
|
||||
|
||||
settings.settings.config.host = host;
|
||||
settings.settings.config.name = name;
|
||||
|
||||
loadSettings(function()
|
||||
{
|
||||
showTab('overview');
|
||||
});
|
||||
}).text( 'save' )
|
||||
);
|
||||
|
||||
|
||||
var forcesave = $('<div>').attr('id', 'forcesave');
|
||||
|
||||
forcesave.append(
|
||||
$('<p>').text('Click the button below to force an immediate settings save. This differs from a regular save to memory and file save on exit by saving directly to file while operating. This may slow server processes for a short period of time.')
|
||||
).append(
|
||||
$('<button>').click(function()
|
||||
{
|
||||
if(confirmDelete('Are you sure you want to force a JSON save?') == true)
|
||||
{
|
||||
forceJSONSave();
|
||||
}
|
||||
}).text( 'force save to JSON file' )
|
||||
);
|
||||
|
||||
$('#page').append(forcesave);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case 'protocols':
|
||||
|
||||
$table = $('<table>');
|
||||
$table.html("<thead><th>Protocol</th><th>Port</th><th>Interface</th><th></th></thead>");
|
||||
$tbody = $('<tbody>');
|
||||
|
||||
var tr, i, protocol,
|
||||
len = (settings.settings.config.protocols ? settings.settings.config.protocols.length : 0);
|
||||
|
||||
$tbody.html('');
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
protocol = settings.settings.config.protocols[i]; // local copy
|
||||
|
||||
tr = $('<tr>').attr('id', 'protocol-' + i);
|
||||
|
||||
tr.append( $('<td>').text( protocol.connector ) );
|
||||
tr.append( $('<td>').text( protocol.port ) );
|
||||
|
||||
tr.append( $('<td>').text( protocol['interface'] ) ); // interface is a reserved JS keyword
|
||||
|
||||
tr.append( $('<td>').attr('class', 'center').append( $('<button>').click(function()
|
||||
{
|
||||
if(confirmDelete('Are you sure you want to delete this protocol?') == true)
|
||||
{
|
||||
var id = $(this).parent().parent().attr('id').replace('protocol-', '');
|
||||
settings.settings.config.protocols.splice(id, 1);
|
||||
$(this).parent().parent().remove();
|
||||
loadSettings();
|
||||
}
|
||||
}).text('delete') ) );
|
||||
|
||||
$tbody.append(tr);
|
||||
}
|
||||
|
||||
|
||||
// add new protocol!
|
||||
$nprot = $('<tr>').attr('class', 'outsidetable');
|
||||
// protocol select
|
||||
$pname = $('<select>').attr('id', 'new-protocol-name');
|
||||
$pname.append( $('<option>').attr('value', 'HTTP').text('HTTP') );
|
||||
$pname.append( $('<option>').attr('value', 'RTMP').text('RTMP') );
|
||||
|
||||
$nprot.append( $('<td>').append($pname) );
|
||||
// the port value
|
||||
$nprot.append( $('<td>').append( $('<input>').attr('type', 'number').attr('id', 'new-protocol-val') ) );
|
||||
|
||||
// interface
|
||||
$nprot.append( $('<td>').append( $('<input>').attr('type', 'text').attr('id', 'new-protocol-interface') ) );
|
||||
|
||||
$nprot.append(
|
||||
$('<td>').attr('class', 'center').append(
|
||||
$('<button>').click(function()
|
||||
{
|
||||
if($('#new-protocol-val').val() == '')
|
||||
{
|
||||
$('#new-protocol-val').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!settings.settings.config.protocols)
|
||||
{
|
||||
settings.settings.config.protocols = [];
|
||||
}
|
||||
|
||||
var nobj =
|
||||
{
|
||||
connector: $('#new-protocol-name :selected').val(),
|
||||
port: Math.abs($('#new-protocol-val').val()),
|
||||
};
|
||||
|
||||
nobj['interface'] = $('#new-protocol-interface').val();
|
||||
|
||||
settings.settings.config.protocols.push(nobj);
|
||||
|
||||
loadSettings(function()
|
||||
{
|
||||
showTab('protocols');
|
||||
});
|
||||
|
||||
}).text('add new')
|
||||
)
|
||||
);
|
||||
|
||||
$tbody.append($nprot);
|
||||
$table.append($tbody);
|
||||
$('#page').append($table);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case 'streams':
|
||||
|
||||
// the filter element containr
|
||||
$div = $('<div>').attr('id', 'streams-filter');
|
||||
|
||||
// filters the table. uses the streamsdisplay
|
||||
function filterTable()
|
||||
{
|
||||
$('#streams-list-tbody').children().each(function(k, v)
|
||||
{
|
||||
var type = $($(v).children()[0]).text().toLowerCase();
|
||||
|
||||
$(v).show();
|
||||
|
||||
if(type == 'recorded' && streamsdisplay[0] == false)
|
||||
{
|
||||
$(v).hide();
|
||||
}
|
||||
|
||||
if(type == 'live' && streamsdisplay[1] == false)
|
||||
{
|
||||
$(v).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function filterOn(event, elem)
|
||||
{
|
||||
if(event.target.id == '')
|
||||
{
|
||||
return; // label click goes bubbles on checkbox, so ignore it
|
||||
}
|
||||
|
||||
var what = $(elem).text();
|
||||
|
||||
if(what == 'recorded')
|
||||
{
|
||||
streamsdisplay[0] = !streamsdisplay[0];
|
||||
$('#stream-filter-recorded').attr('checked', streamsdisplay[0]);
|
||||
}else{
|
||||
streamsdisplay[1] = !streamsdisplay[1];
|
||||
$('#stream-filter-live').attr('checked', streamsdisplay[1]);
|
||||
}
|
||||
|
||||
filterTable();
|
||||
}
|
||||
|
||||
$div.append(
|
||||
$('<label>').attr('for', 'stream-filter-recorded').text('recorded').append(
|
||||
$('<input>').attr('type', 'checkbox').attr('id', 'stream-filter-recorded').attr('checked', streamsdisplay[0])
|
||||
).click(function(event)
|
||||
{
|
||||
filterOn(event, this);
|
||||
})
|
||||
);
|
||||
$div.append(
|
||||
$('<label>').attr('for', 'stream-filter-live').text('live').append(
|
||||
$('<input>').attr('type', 'checkbox').attr('id', 'stream-filter-live').attr('checked', streamsdisplay[1])
|
||||
).click(function(event)
|
||||
{
|
||||
filterOn(event, this);
|
||||
})
|
||||
);
|
||||
|
||||
$('#page').append($div);
|
||||
|
||||
// refresh every streams' data (status and viewer count)
|
||||
function refreshStreams()
|
||||
{
|
||||
getStreamsData(function(streams)
|
||||
{
|
||||
for(stream in streams)
|
||||
{
|
||||
if( $('stream-' + stream) )
|
||||
{
|
||||
var row = $('#stream-' + stream);
|
||||
var status = streams[stream][0];
|
||||
|
||||
if(status == 1)
|
||||
{
|
||||
$(row.children()[3]).html("<span class='green'>Running</span>");
|
||||
}else{
|
||||
$(row.children()[3]).html("<span class='red'>" + (status ? status : 'Offline') + "</span>");
|
||||
}
|
||||
|
||||
$(row.children()[4]).text(streams[stream][1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
sinterval = setInterval(function()
|
||||
{
|
||||
refreshStreams();
|
||||
}, 10000);
|
||||
|
||||
refreshStreams();
|
||||
|
||||
$table = $('<table>');
|
||||
$table.html("<thead><th>Type</th><th>Embed</th><th>Name</th><th>Status</th><th>Viewers</th><th>Edit</th></thead>");
|
||||
$tbody = $('<tbody>');
|
||||
|
||||
var stream, cstr, $tr;
|
||||
|
||||
$tbody.html('').attr('id', 'streams-list-tbody');
|
||||
|
||||
for(stream in settings.settings.streams)
|
||||
{
|
||||
var cstr = settings.settings.streams[stream];
|
||||
|
||||
$tr = $('<tr>').attr('id', 'stream-' + stream);
|
||||
|
||||
$tr.append( $('<td>').text( TypeofResource( cstr.channel.URL ) ) );
|
||||
|
||||
$tr.append( $('<td>').append( $('<button>').text('embed').click(function()
|
||||
{
|
||||
var sname = $(this).parent().parent().attr('id').replace('stream-', '');
|
||||
showTab('embed', sname);
|
||||
}) ) ); // end function, end click(), end append(), end append(). Huzzah jQuery.
|
||||
|
||||
$tr.append( $('<td>').text(cstr.name) );
|
||||
|
||||
if(cstr.online && cstr.online == 1)
|
||||
{
|
||||
$tr.append( $('<td>').html("<span class='green'>Running</span>") );
|
||||
}else{
|
||||
$tr.append( $('<td>').html("<span class='red'>" + (cstr.online ? cstr.online : 'Offline') + "</span>") );
|
||||
}
|
||||
|
||||
var cviewers = 0;
|
||||
|
||||
if(settings.settings.statistics && settings.settings.statistics[stream])
|
||||
{
|
||||
if(settings.settings.statistics[stream] && settings.settings.statistics[stream].curr)
|
||||
{
|
||||
for(viewer in settings.settings.statistics[stream].curr)
|
||||
{
|
||||
cviewers++;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
cviewers = 0;
|
||||
}
|
||||
|
||||
$tr.append( $('<td>').text( cviewers ) );
|
||||
|
||||
$tr.append( $('<td>').append( $('<button>').text('edit').click(function()
|
||||
{
|
||||
var sname = $(this).parent().parent().attr('id').replace('stream-', '');
|
||||
|
||||
showTab('editstream', sname);
|
||||
}) ) ); // end function, end click, end append, end append.
|
||||
|
||||
$tbody.append($tr);
|
||||
}
|
||||
|
||||
$table.append($tbody);
|
||||
$('#page').append($table);
|
||||
|
||||
// on page load, also filter with the (users' defined) stream filter
|
||||
filterTable();
|
||||
|
||||
$('#page').append(
|
||||
$('<button>').attr('class', 'floatright').click(function()
|
||||
{
|
||||
showTab('editstream', 'new');
|
||||
}).text('add new')
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case 'editstream':
|
||||
|
||||
var sdata, title;
|
||||
|
||||
if(streamname == 'new')
|
||||
{
|
||||
sdata =
|
||||
{
|
||||
name: '',
|
||||
channel:
|
||||
{
|
||||
URL: ''
|
||||
},
|
||||
limits: [],
|
||||
preset:
|
||||
{
|
||||
cmd: ''
|
||||
}
|
||||
};
|
||||
title = 'add new stream';
|
||||
}else{
|
||||
sdata = settings.settings.streams[streamname];
|
||||
title = 'edit stream "' + sdata.name + '"';
|
||||
}
|
||||
|
||||
$('#page').append( $('<p>').text(title) );
|
||||
|
||||
$('#page').append(
|
||||
$('<div>').attr('id', 'editserver').append(
|
||||
$('<label>').attr('for', 'stream-edit-name').text('name').append(
|
||||
$('<input>').attr('type', 'text').attr('placeholder', 'NAME').attr('id', 'stream-edit-name').attr('value', sdata.name)
|
||||
)
|
||||
).append(
|
||||
$('<label>').attr('for', 'stream-edit-source').text('source').append(
|
||||
$('<input>').attr('type', 'text').attr('placeholder', 'SOURCE').attr('id', 'stream-edit-source').attr('value', sdata.channel.URL).keyup(function()
|
||||
{
|
||||
var text = $(this).val();
|
||||
|
||||
if(text.charAt(0) == '/' || text.substr(0, 7) == 'push://')
|
||||
{
|
||||
$('#stream-edit-preset').val('');
|
||||
$('#stream-edit-preset').hide();
|
||||
$('#stream-edit-preset-label').hide();
|
||||
}else{
|
||||
$('#stream-edit-preset').show();
|
||||
$('#stream-edit-preset-label').show();
|
||||
}
|
||||
})
|
||||
)
|
||||
).append(
|
||||
$('<label>').attr('id', 'stream-edit-preset-label').attr('for', 'stream-edit-preset').text('preset').append(
|
||||
$('<input>').attr('type', 'text').attr('placeholder', 'PRESET').attr('id', 'stream-edit-preset').attr('value', sdata.preset.cmd)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// if the source is push or file, don't do a preset
|
||||
var text = $('#stream-edit-source').val();
|
||||
|
||||
if(text.charAt(0) == '/' || text.substr(0, 7) == 'push://')
|
||||
{
|
||||
$('#stream-edit-preset').hide();
|
||||
$('#stream-edit-preset-label').hide();
|
||||
}else{
|
||||
$('#stream-edit-preset').show();
|
||||
$('#stream-edit-preset-label').show();
|
||||
}
|
||||
|
||||
|
||||
$('#editserver').append(
|
||||
$('<button>').attr('class', 'floatright').click(function()
|
||||
{
|
||||
if(streamname == 'new')
|
||||
{
|
||||
showTab('streams');
|
||||
}else{
|
||||
if(confirmDelete('Are you sure you want to delete the stream "' + settings.settings.streams[streamname].name + '"?') == true)
|
||||
{
|
||||
delete settings.settings.streams[streamname];
|
||||
loadSettings(function()
|
||||
{
|
||||
showTab('streams');
|
||||
});
|
||||
}
|
||||
}
|
||||
}).text( streamname == 'new' ? 'cancel' : 'delete' )
|
||||
);
|
||||
|
||||
$('#editserver').append(
|
||||
$('<button>').attr('class', 'floatright').click(function()
|
||||
{
|
||||
var n = $('#stream-edit-name');
|
||||
var s = $('#stream-edit-source');
|
||||
var p = $('#stream-edit-preset');
|
||||
|
||||
if(n.val() == ''){ n.focus(); return; }
|
||||
if(s.val() == ''){ s.focus(); return; }
|
||||
|
||||
sdata.name = n.val();
|
||||
sdata.channel.URL = s.val();
|
||||
sdata.preset.cmd = p.val();
|
||||
|
||||
if(streamname == 'new')
|
||||
{
|
||||
streamname = n.val().replace(/ /g, '-');
|
||||
}
|
||||
|
||||
if(!settings.settings.streams)
|
||||
{
|
||||
settings.settings.streams = {};
|
||||
}
|
||||
|
||||
settings.settings.streams[streamname] = sdata;
|
||||
|
||||
loadSettings(function()
|
||||
{
|
||||
showTab('streams');
|
||||
});
|
||||
|
||||
}).text('save')
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case 'embed':
|
||||
|
||||
if(isThereAHTTPConnector())
|
||||
{
|
||||
var embed = 'http://' + parseURL(settings.server).host + ':8080/embed_' + streamname + '.js';
|
||||
|
||||
$('#page').append( $('<p>').attr('class', 'nocapitals').text('The embed URL is "' + embed + '".') );
|
||||
|
||||
$('#page').append( $('<button>').text('preview').click(function()
|
||||
{
|
||||
showTab('preview', streamname);
|
||||
} ) );
|
||||
|
||||
}else{
|
||||
$('#page').append( $('<p>').attr('class', 'nocapitals').text('Could\'t find a HTTP connector. Please add a HTTP connector on the "protocol" page.') );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'preview':
|
||||
|
||||
var embed = 'http://' + parseURL(settings.server).host + ':8080/embed_' + streamname + '.js';
|
||||
|
||||
$('#page').append( $('<div>').html( "<script src='" + embed + "'></script>" ) );
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case 'limits':
|
||||
$table = $('<table>');
|
||||
$table.html("<thead><th>Type</th><th>Hard/soft</th><th>Value</th><th>applies to</th><th>Action</th></thead>");
|
||||
$tbody = $('<tbody>');
|
||||
|
||||
var i, tr, limit, stream, clims,
|
||||
alllimits = settings.settings.config.limits;
|
||||
|
||||
for(stream in settings.settings.streams)
|
||||
{
|
||||
clims = settings.settings.streams[stream].limits;
|
||||
|
||||
$.each(clims, function(k, v)
|
||||
{
|
||||
this.appliesto = stream;
|
||||
this.appliesi = k;
|
||||
});
|
||||
|
||||
alllimits = alllimits.concat(clims);
|
||||
}
|
||||
|
||||
len = alllimits.length;
|
||||
|
||||
// remove old items
|
||||
$tbody.html('');
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
tr = $('<tr>').attr('id', 'limits-' + i);
|
||||
limit = alllimits[i];
|
||||
|
||||
tr.append( $('<td>').text( shortToLongLimit(limit.name) ) );
|
||||
tr.append( $('<td>').text( limit.type ) );
|
||||
tr.append( $('<td>').text( limit.val ) );
|
||||
|
||||
|
||||
if(limit.appliesto)
|
||||
{
|
||||
tr.append( $('<td>').text( settings.settings.streams[limit.appliesto].name ).attr('id', 'limit-at-' + limit.appliesto + '-' + limit.appliesi) );
|
||||
}else{
|
||||
tr.append( $('<td>').text( 'server' ) );
|
||||
}
|
||||
|
||||
delete limit.appliesto;
|
||||
delete limit.appliesi;
|
||||
|
||||
tr.append( $('<td>').attr('class', 'center').append( $('<button>').click(function()
|
||||
{
|
||||
if(confirmDelete('Are you sure you want to delete this limit?') == true)
|
||||
{
|
||||
var id = $(this).parent().parent().attr('id').replace('limits-', '');
|
||||
var at = $($(this).parent().parent().children()[3]).attr('id');
|
||||
|
||||
if(at == undefined)
|
||||
{
|
||||
settings.settings.config.limits.splice(id, 1);
|
||||
}else{
|
||||
var data = at.replace('limit-at-', '').split('-');
|
||||
var loc = data.pop();
|
||||
data = data.join('-');
|
||||
|
||||
settings.settings.streams[data].limits.splice(loc, 1);
|
||||
}
|
||||
|
||||
$(this).parent().parent().remove();
|
||||
|
||||
loadSettings();
|
||||
}
|
||||
}).text('delete') ) );
|
||||
|
||||
$tbody.append(tr);
|
||||
}
|
||||
|
||||
// add new limit
|
||||
$nltr = $('<tr>').attr('class', 'outsidetable');
|
||||
|
||||
// type selector
|
||||
$ltype = $('<select>').attr('id', 'new-limit-type');
|
||||
for(i = 0; i < ltypes.length; i++)
|
||||
{
|
||||
$ltype.append( $('<option>').attr('value', ltypes[i][0]).text(ltypes[i][1]) );
|
||||
}
|
||||
$nltr.append( $('<td>').append( $ltype ) );
|
||||
// hard/soft limit
|
||||
$nltr.append( $('<td>').append( $('<select>').attr('id', 'new-limit-hs').append( $('<option>').attr('value', 'hard').text('Hard limit') ).append( $('<option>').attr('value', 'soft').text('Soft limit') ) ) );
|
||||
// value
|
||||
$nltr.append( $('<td>').append( $('<input>').attr('type', 'text').attr('id', 'new-limit-val') ) );
|
||||
|
||||
// applies to (stream)
|
||||
var $appliesto = $('<select>').attr('id', 'new-limit-appliesto').append( $('<option>').attr('value', 'server').text('Server') );
|
||||
|
||||
for(var strm in settings.settings.streams)
|
||||
{
|
||||
$appliesto.append(
|
||||
$('<option>').attr('value', strm).text(settings.settings.streams[strm].name)
|
||||
);
|
||||
}
|
||||
$nltr.append( $('<td>').append( $appliesto ) );
|
||||
|
||||
$nltr.append(
|
||||
$('<td>').attr('class', 'center').append(
|
||||
$('<button>').click(function()
|
||||
{
|
||||
var obj =
|
||||
{
|
||||
name: $('#new-limit-type :selected').val(),
|
||||
type: $('#new-limit-hs :selected').val(),
|
||||
val: $('#new-limit-val').val()
|
||||
};
|
||||
|
||||
if( $('#new-limit-appliesto').val() == 'server')
|
||||
{
|
||||
settings.settings.config.limits.push(obj);
|
||||
}else{
|
||||
settings.settings.streams[ $('#new-limit-appliesto').val() ].limits.push(obj);
|
||||
}
|
||||
|
||||
loadSettings(function()
|
||||
{
|
||||
showTab('limits');
|
||||
});
|
||||
|
||||
}).text('add new')
|
||||
)
|
||||
);
|
||||
$tbody.append($nltr);
|
||||
|
||||
$table.append($tbody);
|
||||
$('#page').append($table);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'logs':
|
||||
$table = $('<table>');
|
||||
$table.html("<thead><th>Date<span class='theadinfo'>(MM/DD/YYYY)</span></th><th>Type</th><th>Message</th></thead>");
|
||||
$tbody = $('<tbody>');
|
||||
|
||||
if(!settings.settings.log)
|
||||
{
|
||||
return; // no logs, so just bail
|
||||
}
|
||||
var i, cur, $tr,
|
||||
logs = settings.settings.log,
|
||||
len = logs.length;
|
||||
|
||||
if(len >= 2 && settings.settings.log[0][0] < settings.settings.log[len - 1][0])
|
||||
{
|
||||
logs.reverse();
|
||||
}
|
||||
|
||||
$tbody.html('');
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
cur = settings.settings.log[i];
|
||||
|
||||
$tr = $('<tr>').append(
|
||||
$('<td>').text(formatDate(cur[0]))
|
||||
).append(
|
||||
$('<td>').text(cur[1])
|
||||
).append(
|
||||
$('<td>').text(cur[2])
|
||||
);
|
||||
|
||||
$tbody.append($tr);
|
||||
}
|
||||
|
||||
$table.append($tbody);
|
||||
$('#page').append($table);
|
||||
|
||||
$('#page').append(
|
||||
$('<button>').attr('class', 'floatright').click(function()
|
||||
{
|
||||
settings.settings.clearstatlogs = 1;
|
||||
loadSettings(function()
|
||||
{
|
||||
showTab('logs');
|
||||
});
|
||||
}).text('Purge logs')
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case 'disconnect':
|
||||
showTab('login');
|
||||
setHeaderState('disconnected');
|
||||
$('#nav').css('visibility', 'hidden');
|
||||
|
||||
settings =
|
||||
{
|
||||
server: '',
|
||||
credentials:
|
||||
{
|
||||
username: "",
|
||||
password: "",
|
||||
authstring: ""
|
||||
},
|
||||
settings: {}
|
||||
};
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
|
||||
//placeholder for older browsers
|
||||
$('input[placeholder]').placeholder();
|
||||
|
||||
}
|
||||
|
2
lsp/md5.js
Normal file
2
lsp/md5.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
var MD5=function(j){function RotateLeft(a,b){return(a<<b)|(a>>>(32-b))}function AddUnsigned(a,b){var c,lY4,lX8,lY8,lResult;lX8=(a&0x80000000);lY8=(b&0x80000000);c=(a&0x40000000);lY4=(b&0x40000000);lResult=(a&0x3FFFFFFF)+(b&0x3FFFFFFF);if(c&lY4){return(lResult^0x80000000^lX8^lY8)}if(c|lY4){if(lResult&0x40000000){return(lResult^0xC0000000^lX8^lY8)}else{return(lResult^0x40000000^lX8^lY8)}}else{return(lResult^lX8^lY8)}}function F(x,y,z){return(x&y)|((~x)&z)}function G(x,y,z){return(x&z)|(y&(~z))}function H(x,y,z){return(x^y^z)}function I(x,y,z){return(y^(x|(~z)))}function FF(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(F(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function GG(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(G(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function HH(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(H(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function II(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(I(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function ConvertToWordArray(a){var b;var c=a.length;var d=c+8;var e=(d-(d%64))/64;var f=(e+1)*16;var g=Array(f-1);var h=0;var i=0;while(i<c){b=(i-(i%4))/4;h=(i%4)*8;g[b]=(g[b]|(a.charCodeAt(i)<<h));i++}b=(i-(i%4))/4;h=(i%4)*8;g[b]=g[b]|(0x80<<h);g[f-2]=c<<3;g[f-1]=c>>>29;return g};function WordToHex(a){var b="",WordToHexValue_temp="",lByte,lCount;for(lCount=0;lCount<=3;lCount++){lByte=(a>>>(lCount*8))&255;WordToHexValue_temp="0"+lByte.toString(16);b=b+WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2)}return b};function Utf8Encode(a){a=a.replace(/\r\n/g,"\n");var b="";for(var n=0;n<a.length;n++){var c=a.charCodeAt(n);if(c<128){b+=String.fromCharCode(c)}else if((c>127)&&(c<2048)){b+=String.fromCharCode((c>>6)|192);b+=String.fromCharCode((c&63)|128)}else{b+=String.fromCharCode((c>>12)|224);b+=String.fromCharCode(((c>>6)&63)|128);b+=String.fromCharCode((c&63)|128)}}return b};var x=Array();var k,AA,BB,CC,DD,a,b,c,d;var l=7,S12=12,S13=17,S14=22;var m=5,S22=9,S23=14,S24=20;var o=4,S32=11,S33=16,S34=23;var p=6,S42=10,S43=15,S44=21;j=Utf8Encode(j);x=ConvertToWordArray(j);a=0x67452301;b=0xEFCDAB89;c=0x98BADCFE;d=0x10325476;for(k=0;k<x.length;k+=16){AA=a;BB=b;CC=c;DD=d;a=FF(a,b,c,d,x[k+0],l,0xD76AA478);d=FF(d,a,b,c,x[k+1],S12,0xE8C7B756);c=FF(c,d,a,b,x[k+2],S13,0x242070DB);b=FF(b,c,d,a,x[k+3],S14,0xC1BDCEEE);a=FF(a,b,c,d,x[k+4],l,0xF57C0FAF);d=FF(d,a,b,c,x[k+5],S12,0x4787C62A);c=FF(c,d,a,b,x[k+6],S13,0xA8304613);b=FF(b,c,d,a,x[k+7],S14,0xFD469501);a=FF(a,b,c,d,x[k+8],l,0x698098D8);d=FF(d,a,b,c,x[k+9],S12,0x8B44F7AF);c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);a=FF(a,b,c,d,x[k+12],l,0x6B901122);d=FF(d,a,b,c,x[k+13],S12,0xFD987193);c=FF(c,d,a,b,x[k+14],S13,0xA679438E);b=FF(b,c,d,a,x[k+15],S14,0x49B40821);a=GG(a,b,c,d,x[k+1],m,0xF61E2562);d=GG(d,a,b,c,x[k+6],S22,0xC040B340);c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);b=GG(b,c,d,a,x[k+0],S24,0xE9B6C7AA);a=GG(a,b,c,d,x[k+5],m,0xD62F105D);d=GG(d,a,b,c,x[k+10],S22,0x2441453);c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);b=GG(b,c,d,a,x[k+4],S24,0xE7D3FBC8);a=GG(a,b,c,d,x[k+9],m,0x21E1CDE6);d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);c=GG(c,d,a,b,x[k+3],S23,0xF4D50D87);b=GG(b,c,d,a,x[k+8],S24,0x455A14ED);a=GG(a,b,c,d,x[k+13],m,0xA9E3E905);d=GG(d,a,b,c,x[k+2],S22,0xFCEFA3F8);c=GG(c,d,a,b,x[k+7],S23,0x676F02D9);b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);a=HH(a,b,c,d,x[k+5],o,0xFFFA3942);d=HH(d,a,b,c,x[k+8],S32,0x8771F681);c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);a=HH(a,b,c,d,x[k+1],o,0xA4BEEA44);d=HH(d,a,b,c,x[k+4],S32,0x4BDECFA9);c=HH(c,d,a,b,x[k+7],S33,0xF6BB4B60);b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);a=HH(a,b,c,d,x[k+13],o,0x289B7EC6);d=HH(d,a,b,c,x[k+0],S32,0xEAA127FA);c=HH(c,d,a,b,x[k+3],S33,0xD4EF3085);b=HH(b,c,d,a,x[k+6],S34,0x4881D05);a=HH(a,b,c,d,x[k+9],o,0xD9D4D039);d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);b=HH(b,c,d,a,x[k+2],S34,0xC4AC5665);a=II(a,b,c,d,x[k+0],p,0xF4292244);d=II(d,a,b,c,x[k+7],S42,0x432AFF97);c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);b=II(b,c,d,a,x[k+5],S44,0xFC93A039);a=II(a,b,c,d,x[k+12],p,0x655B59C3);d=II(d,a,b,c,x[k+3],S42,0x8F0CCC92);c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);b=II(b,c,d,a,x[k+1],S44,0x85845DD1);a=II(a,b,c,d,x[k+8],p,0x6FA87E4F);d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);c=II(c,d,a,b,x[k+6],S43,0xA3014314);b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);a=II(a,b,c,d,x[k+4],p,0xF7537E82);d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);c=II(c,d,a,b,x[k+2],S43,0x2AD7D2BB);b=II(b,c,d,a,x[k+9],S44,0xEB86D391);a=AddUnsigned(a,AA);b=AddUnsigned(b,BB);c=AddUnsigned(c,CC);d=AddUnsigned(d,DD)}var q=WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);return q.toLowerCase()};
|
||||
|
8
lsp/placeholder.js
Normal file
8
lsp/placeholder.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Placeholder plugin for jQuery
|
||||
* ---
|
||||
* Copyright 2010, Daniel Stocks (http://webcloud.se)
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*/
|
||||
(function(b){function d(a){this.input=a;a.attr("type")=="password"&&this.handlePassword();b(a[0].form).submit(function(){if(a.hasClass("placeholder")&&a[0].value==a.attr("placeholder"))a[0].value=""})}d.prototype={show:function(a){if(this.input[0].value===""||a&&this.valueIsPlaceholder()){if(this.isPassword)try{this.input[0].setAttribute("type","text")}catch(b){this.input.before(this.fakePassword.show()).hide()}this.input.addClass("placeholder");this.input[0].value=this.input.attr("placeholder")}},hide:function(){if(this.valueIsPlaceholder()&&this.input.hasClass("placeholder")&&(this.input.removeClass("placeholder"),this.input[0].value="",this.isPassword)){try{this.input[0].setAttribute("type","password")}catch(a){}this.input.show();this.input[0].focus()}},valueIsPlaceholder:function(){return this.input[0].value==this.input.attr("placeholder")},handlePassword:function(){var a=this.input;a.attr("realType","password");this.isPassword=!0;if(b.browser.msie&&a[0].outerHTML){var c=b(a[0].outerHTML.replace(/type=(['"])?password\1/gi,"type=$1text$1"));this.fakePassword=c.val(a.attr("placeholder")).addClass("placeholder").focus(function(){a.trigger("focus");b(this).hide()});b(a[0].form).submit(function(){c.remove();a.show()})}}};var e=!!("placeholder"in document.createElement("input"));b.fn.placeholder=function(){return e?this:this.each(function(){var a=b(this),c=new d(a);c.show(!0);a.focus(function(){c.hide()});a.blur(function(){c.show(!1)});b.browser.msie&&(b(window).load(function(){a.val()&&a.removeClass("placeholder");c.show(!0)}),a.focus(function(){if(this.value==""){var a=this.createTextRange();a.collapse(!0);a.moveStart("character",0);a.select()}}))})}})(jQuery);
|
||||
|
49
lsp/server.html
Normal file
49
lsp/server.html
Normal file
|
@ -0,0 +1,49 @@
|
|||
<!doctype html>
|
||||
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset='utf-8' />
|
||||
|
||||
<title>Mistserver Manager - not connected</title>
|
||||
|
||||
<script src='jquery.js'></script>
|
||||
<script src='placeholder.js'></script>
|
||||
<script src='md5.js'></script>
|
||||
<script src='main.js'></script>
|
||||
<script src='functions.js'></script>
|
||||
|
||||
<link rel='stylesheet' href='style.css' />
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id='header'>
|
||||
|
||||
<div id='header-title'>
|
||||
<span>Mistserver Manager</span>
|
||||
</div>
|
||||
|
||||
<div id='header-status'>
|
||||
<span id='header-connection' class='disconnected'>Disconnected</span>
|
||||
<span id='header-host'></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ul id='nav'>
|
||||
<li class='selected'>overview</li>
|
||||
<li>protocols</li>
|
||||
<li>streams</li>
|
||||
<li>limits</li>
|
||||
<li>logs</li>
|
||||
<li id='logoutbutton'>disconnect</li>
|
||||
</ul>
|
||||
|
||||
<div id='page'></div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
375
lsp/style.css
Normal file
375
lsp/style.css
Normal file
|
@ -0,0 +1,375 @@
|
|||
|
||||
|
||||
body
|
||||
{
|
||||
background-color: #fafafa;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#page
|
||||
{
|
||||
overflow: hidden;
|
||||
margin: 10px -170px 0 230px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.floatright
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* content - tables */
|
||||
|
||||
table
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border-spacing: 0 4px;
|
||||
}
|
||||
|
||||
table thead
|
||||
{
|
||||
background-color: #c8c8c8;
|
||||
}
|
||||
|
||||
table th, table td
|
||||
{
|
||||
height: 30px;
|
||||
padding: 0 0 0 30px;
|
||||
}
|
||||
|
||||
table th
|
||||
{
|
||||
color: #505050;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table td
|
||||
{
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
|
||||
tbody tr:nth-child(even)
|
||||
{
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
tbody tr:nth-child(odd)
|
||||
{
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* login stuff */
|
||||
|
||||
#login
|
||||
{
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
#login > input
|
||||
{
|
||||
display: block;
|
||||
margin: 5px 0 13px 0;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
/* connect button */
|
||||
|
||||
#login > button
|
||||
{
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* input general */
|
||||
input, select
|
||||
{
|
||||
padding: 5px;
|
||||
color: #505050;
|
||||
border: 1px solid #b4b4b4;
|
||||
}
|
||||
|
||||
button
|
||||
{
|
||||
height: 30px;
|
||||
background-color: #505050;
|
||||
color: #fff;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
tbody button,
|
||||
tbody select,
|
||||
tbody input
|
||||
{
|
||||
height: 22px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
tbody td button
|
||||
{
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
padding: 2px 7px 2px 7px;
|
||||
}
|
||||
|
||||
tbody td.center
|
||||
{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
#page > button
|
||||
{
|
||||
margin: 12px 0 6px 0;
|
||||
}
|
||||
|
||||
|
||||
/* header */
|
||||
|
||||
#header
|
||||
{
|
||||
margin: 30px 0 0 0;
|
||||
width: 100%;
|
||||
background-color: #b4b4b4;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#header-title
|
||||
{
|
||||
padding: 0 0 0 30px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#header-status
|
||||
{
|
||||
float: right;
|
||||
padding: 0 30px 0 0;
|
||||
}
|
||||
|
||||
#header-title, #header-status
|
||||
{
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.disconnected, .red
|
||||
{
|
||||
color: #cc3333;
|
||||
}
|
||||
|
||||
.connected, .green
|
||||
{
|
||||
color: #14991a;
|
||||
}
|
||||
|
||||
.loggingin
|
||||
{
|
||||
color: #ee8833;
|
||||
}
|
||||
|
||||
#header
|
||||
{
|
||||
color: #fafafa;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* navigation */
|
||||
|
||||
#nav
|
||||
{
|
||||
float: left;
|
||||
width: 200px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
#nav li
|
||||
{
|
||||
display: block;
|
||||
color: #b4b4b4;
|
||||
line-height: 30px;
|
||||
padding: 0 0 0 30px;
|
||||
margin: 5px 0 5px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#nav li:hover, #nav .selected
|
||||
{
|
||||
color: #505050;
|
||||
background-color: #c8c8c8;
|
||||
}
|
||||
|
||||
li#logoutbutton
|
||||
{
|
||||
color: #cc3333;
|
||||
}
|
||||
|
||||
|
||||
p, label
|
||||
{
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
p
|
||||
{
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
label
|
||||
{
|
||||
display: block;
|
||||
margin: 6px 0 9px 0;
|
||||
padding: 8px 0 0 0;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
label input
|
||||
{
|
||||
float: right;
|
||||
margin: -8px 0 0 0;
|
||||
width: 225px;
|
||||
}
|
||||
|
||||
label span
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
#editserver
|
||||
{
|
||||
width: 400px;
|
||||
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
|
||||
thead th .theadinfo
|
||||
{
|
||||
color: #848484;
|
||||
padding: 0 0 0 10px;
|
||||
font: normal normal 9pt Arial, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* fonts */
|
||||
|
||||
#header-title > span, #header-connection, #header-host,
|
||||
#nav,
|
||||
th,
|
||||
#login > button,
|
||||
p,
|
||||
label,
|
||||
#page label input,
|
||||
#page > button,
|
||||
#editserver > button, #forcesave > button
|
||||
{
|
||||
font: normal bold 11pt Arial, sans-serif;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
||||
.nocapitals
|
||||
{
|
||||
text-transform: none ;
|
||||
}
|
||||
|
||||
#editserver label input
|
||||
{
|
||||
text-transform: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#login > input
|
||||
{
|
||||
font: normal bold 11pt Arial, sans-serif;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
font: normal normal 10pt Arial, sans-serif;
|
||||
}
|
||||
|
||||
#streams-filter
|
||||
{
|
||||
height: 30px;
|
||||
margin: 5px 0 0 0;
|
||||
|
||||
text-align: right;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
#streams-filter label
|
||||
{
|
||||
margin: 0 15px 0 25px;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#streams-filter input
|
||||
{
|
||||
float: none;
|
||||
margin: 0 0 0 10px;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#forcesave
|
||||
{
|
||||
width: 400px;
|
||||
float: left;
|
||||
margin: 0 0 0 100px;
|
||||
}
|
||||
|
||||
#forcesave button
|
||||
{
|
||||
float: right;
|
||||
}
|
||||
|
||||
#forcesave p
|
||||
{
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
|
||||
#shield
|
||||
{
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
left: 0;
|
||||
top: 60px;
|
||||
z-index: 5;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
color: #505050;
|
||||
font: normal bold 11pt Arial, sans-serif;
|
||||
text-align: center;
|
||||
padding: 50px 0 0 0;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue