initial import
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
.settings
|
||||
.cproject
|
||||
.project
|
||||
.classpath
|
||||
|
29
README
Normal file
|
@ -0,0 +1,29 @@
|
|||
Here are the urls which i extracted out of the Noxon firmware:
|
||||
|
||||
RadioNativeEntries
|
||||
RadioNative01
|
||||
RootName Podcasts
|
||||
RootUrl http://radio567.vtuner.com/setupapp/radio567/asp/BrowseXML/navXML.asp?gofile=S-ByLocation
|
||||
LoginUrl http://radio567.vtuner.com/setupapp/radio567/asp/BrowseXML/loginXML.asp?token=0
|
||||
RetrieveFavsURL http://radio567.vtuner.com/setupapp/radio567/asp/BrowseXML/FavXML.asp?empty=&sFavName=My%5F%5FFavorites
|
||||
|
||||
RadioNative02
|
||||
RootName My NOXON
|
||||
RootUrl http://gatekeeper.my-noxon.net/RadioNative.php
|
||||
LoginUrl http://gatekeeper.my-noxon.net/RadioNativeLogin.php
|
||||
RetrieveFavsURL http://gatekeeper.my-noxon.net/RadioNativeFavorites.php
|
||||
|
||||
RadioNative03
|
||||
RootName StarXed Services
|
||||
RootUrl http://starxed.homelinux.org/radionative-multi/index.xml
|
||||
LoginUrl http://noxonserver.de/RadioNativeLogin.php
|
||||
RetrieveFavsURL http://starxed.homelinux.org/radionative-multi/favs.php
|
||||
|
||||
MultiRadioStationDB
|
||||
MRSDB01
|
||||
UserFriendlyName Internet Radio
|
||||
url0 http://www.radio579.com/setupapp/bluewin/asp/rsdb/update.asp
|
||||
|
||||
Here a sample url request to vtuner for the rsdb (mac and uid changed):
|
||||
|
||||
http://www.radio579.com/setupapp/bluewin/asp/rsdb/update.asp?mac=############&uid=############################&ver=EMPTY&xml=2.0&mime=audio/mpeg-url&sw=24.6392&bl=6166&hw=158.0&up=13693&lang=ger&st=15167&rel=0
|
45
Server/add.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
require 'init.php';
|
||||
|
||||
if ($_POST) {
|
||||
$result = mysql_query('SELECT lft, rgt FROM tree WHERE id = ' . (int) $_GET['after'] . ' LIMIT 1', $site['db']['connection']);
|
||||
$row = mysql_fetch_assoc($result);
|
||||
mysql_query('UPDATE tree SET rgt=rgt+2 WHERE rgt >= ' . $row['rgt'] , $site['db']['connection']);
|
||||
mysql_query('UPDATE tree SET lft=lft+2 WHERE lft > ' . $row['rgt'] , $site['db']['connection']);
|
||||
mysql_query('INSERT INTO nodes SET
|
||||
name = \'' . $_POST['name'] . '\',
|
||||
type = \'' . $_POST['type'] . '\',
|
||||
description = \'' . $_POST['description'] . '\',
|
||||
bitrate = ' . (int) $_POST['bitrate'] . ',
|
||||
url = \'' . $_POST['url'] . '\',
|
||||
mime_type = \'' . $_POST['mime_type'] . '\',
|
||||
location = \'' . $_POST['location'] . '\',
|
||||
bookmark = \'' . $_POST['bookmark'] . '\'', $site['db']['connection']);
|
||||
mysql_query('INSERT INTO tree (node_id, lft, rgt) VALUES (' . mysql_insert_id() . ', ' . $row['rgt'] . ', ' . $row['rgt'] . ' + 1)' , $site['db']['connection']);
|
||||
echo 'Node added successfully!<br />
|
||||
<a href="javascript:history.go(-2)">back</a>';
|
||||
}
|
||||
else {
|
||||
echo '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?after=' . (int) $_GET['after'] . '">
|
||||
<table>
|
||||
<tr><td>Type</td><td><select size="1" name="type">
|
||||
<option value="directory">Directory</option>
|
||||
<option value="station" >Station</option>
|
||||
<option value="display" >Display text</option>
|
||||
</select></td></tr>
|
||||
<tr><td>Name</td><td><input type="text" name="name" /></td></tr>
|
||||
<tr><td>Description</td><td><input type="text" name="description" /></td></tr>
|
||||
<tr><td>Bitrate</td><td><input type="text" name="bitrate" /></td></tr>
|
||||
<tr><td>URL</td><td><input type="text" name="url" value="http://" /></td></tr>
|
||||
<tr><td>Mime Type</td><td><select size="1" name="mime_type">
|
||||
<option value="m3u">MP3</option>
|
||||
<option value="wma"> Windows Media Audio</option>
|
||||
</select></td></tr>
|
||||
<tr><td>Location</td><td><input type="text" name="location" /></td></tr>
|
||||
<tr><td>Bookmark</td><td><input type="text" name="bookmark" /></td></tr>
|
||||
</table>
|
||||
<input type="submit" value="Add" />
|
||||
</form>';
|
||||
}
|
||||
?>
|
BIN
Server/arrow_down.png
Normal file
After Width: | Height: | Size: 379 B |
BIN
Server/arrow_left.png
Normal file
After Width: | Height: | Size: 345 B |
BIN
Server/arrow_right.png
Normal file
After Width: | Height: | Size: 349 B |
BIN
Server/arrow_up.png
Normal file
After Width: | Height: | Size: 372 B |
30
Server/config.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
$config['db']['user'] = 'user';
|
||||
$config['db']['pw'] = 'pw';
|
||||
$config['db']['host'] = 'localhost';
|
||||
$config['db']['db'] = 'noxon';
|
||||
|
||||
$config['db']['tables']['nodes'] = 'nodes';
|
||||
$config['db']['tables']['tree'] = 'tree';
|
||||
|
||||
|
||||
// Default values (may be updated automatically)
|
||||
$config['noxon']['mac'] = 0x000000000000;
|
||||
$config['noxon']['sw'] = 24.6392;
|
||||
$config['noxon']['bl'] = 6166;
|
||||
$config['noxon']['hw'] = 158.0;
|
||||
$config['noxon']['ip'] = '192.168.1.36';
|
||||
//up=13693
|
||||
//lang=ger
|
||||
//st=15167
|
||||
|
||||
$config['vtuner']['url'] = 'http://www.radio579.com/setupapp/bluewin/asp/rsdb/update.asp';
|
||||
$config['vtuner']['uid'] = 'C089E7AE6153F372B20EB7A5FD0E263B';
|
||||
$config['vtuner']['lang'] = 'ger';
|
||||
|
||||
$config['rsdb']['service'] = 'Experimental';
|
||||
$config['rsdb']['format_version'] = '2.0';
|
||||
$config['rsdb']['name'] = 'Noxon Server';
|
||||
|
||||
?>
|
BIN
Server/control_play.png
Normal file
After Width: | Height: | Size: 592 B |
25
Server/del.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
require 'init.php';
|
||||
|
||||
if ($_GET['id'] == 'all') {
|
||||
mysql_query('TRUNCATE tree', $site['db']['connection']);
|
||||
mysql_query('TRUNCATE nodes', $site['db']['connection']);
|
||||
echo 'Everything has been deleted!<br />';
|
||||
}
|
||||
else {
|
||||
$result = mysql_query('SELECT lft, rgt, node_id FROM tree WHERE id = ' . (int) $_GET['id'] . ' LIMIT 1', $site['db']['connection']);
|
||||
$row = mysql_fetch_assoc($result);
|
||||
|
||||
if (mysql_num_rows($result) < 2)
|
||||
mysql_query('DELETE FROM nodes WHERE id = ' . (int) $row['node_id'], $site['db']['connection']);
|
||||
mysql_query('DELETE FROM tree WHERE lft BETWEEN ' . $row['lft'] . ' AND ' . $row['rgt'], $site['db']['connection']);
|
||||
mysql_query('UPDATE tree SET lft=lft-ROUND((' . $row['rgt'] . ' - ' . $row['lft'] . ' + 1)) WHERE lft > ' . $row['rgt'], $site['db']['connection']);
|
||||
mysql_query('UPDATE tree SET rgt=rgt-ROUND((' . $row['rgt'] . ' - ' . $row['lft'] . ' + 1)) WHERE rgt > ' . $row['rgt'], $site['db']['connection']);
|
||||
|
||||
echo 'Node successfully deleted!<br />';
|
||||
}
|
||||
|
||||
echo '<a href="javascript:history.back()">back</a>';
|
||||
|
||||
?>
|
BIN
Server/delete.png
Normal file
After Width: | Height: | Size: 715 B |
BIN
Server/directory.png
Normal file
After Width: | Height: | Size: 537 B |
BIN
Server/display.png
Normal file
After Width: | Height: | Size: 294 B |
46
Server/edit.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
require 'init.php';
|
||||
|
||||
if($_POST) {
|
||||
mysql_query('UPDATE nodes SET
|
||||
name = \'' . $_POST['name'] . '\',
|
||||
type = \'' . $_POST['type'] . '\',
|
||||
description = \'' . $_POST['description'] . '\',
|
||||
bitrate = ' . (int) $_POST['bitrate'] . ',
|
||||
url = \'' . $_POST['url'] . '\',
|
||||
mime_type = \'' . $_POST['mime_type'] . '\',
|
||||
location = \'' . $_POST['location'] . '\',
|
||||
bookmark = \'' . $_POST['bookmark'] . '\'
|
||||
WHERE id = ' . (int) $_GET['id'], $site['db']['connection']);
|
||||
echo mysql_error();
|
||||
echo 'Node edited successfully!<br />
|
||||
<a href="' . $_SERVER['PHP_SELF'] . '">back</a>';
|
||||
}
|
||||
else {
|
||||
$result = mysql_query('SELECT * FROM nodes WHERE id = ' . (int) $_GET['id'], $site['db']['connection']);
|
||||
$row = mysql_fetch_assoc($result);
|
||||
|
||||
echo '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?cmd=edit&id=' . (int) $_GET['id'] . '">
|
||||
<table>
|
||||
<tr><td>Type</td><td><select size="1" name="type">
|
||||
<option ' . (($row['type'] == 'directory') ? 'selected="selected" ' : '') . 'value="directory">Directory</option>
|
||||
<option ' . (($row['type'] == 'station') ? 'selected="selected" ' : '') . 'value="station">Station</option>
|
||||
<option ' . (($row['type'] == 'display') ? 'selected="selected" ' : '') . 'value="display">Display text</option>
|
||||
</select></td></tr>
|
||||
<tr><td>Name</td><td><input type="text" name="name" value="' . $row['name'] . '" /></td></tr>
|
||||
<tr><td>Description</td><td><input type="text" name="description" value="' . $row['description'] . '" /></td></tr>
|
||||
<tr><td>Bitrate</td><td><input type="text" name="bitrate" value="' . $row['bitrate'] . '" /></td></tr>
|
||||
<tr><td>URL</td><td><input type="text" name="url" value="' . $row['url'] . '" /></td></tr>
|
||||
<tr><td>Mime Type</td><td><select size="1" name="mime_type">
|
||||
<option ' . (($row['mime_type'] == 'm3u') ? 'selected="selected" ' : '') . 'value="mp3">MP3</option>
|
||||
<option ' . (($row['mime_type'] == 'wma') ? 'selected="selected" ' : '') . 'value="wma"> Windows Media Audio</option>
|
||||
</select></td></tr>
|
||||
<tr><td>Location</td><td><input type="text" name="location" value="' . $row['location'] . '" /></td></tr>
|
||||
<tr><td>Bookmark</td><td><input type="text" name="bookmark" value="' . $row['bookmark'] . '" /></td></tr>
|
||||
</table>
|
||||
<input type="submit" value="Edit" />
|
||||
</form>';
|
||||
}
|
||||
|
||||
?>
|
BIN
Server/edit.png
Normal file
After Width: | Height: | Size: 450 B |
11
Server/functions.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
function init_mysql() {
|
||||
global $site;
|
||||
global $config;
|
||||
|
||||
$site['db']['connection'] = mysql_connect($config['db']['host'], $config['db']['user'], $config['db']['pw']);
|
||||
mysql_select_db($config['db']['db'], $site['db']['connection']);
|
||||
}
|
||||
|
||||
?>
|
156
Server/import_vtuner.php
Normal file
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
|
||||
require 'config.php';
|
||||
|
||||
$site['db']['connection'] = mysql_connect($config['db']['host'], $config['db']['user'], $config['db']['pw']);
|
||||
mysql_select_db($config['db']['db'], $site['db']['connection']);
|
||||
|
||||
echo '<?xml version="1.0" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>VTuner.com Importer</title>
|
||||
<link rel="stylesheet" type="text/css" href="stylesheet.css">
|
||||
</head>
|
||||
<body>
|
||||
<h2>VTuner.com Importer</h2>';
|
||||
|
||||
//$rsdb_xml = file_get_contents($config['vtuner']['url'] . '?mac=' . $config['noxon']['mac'] . '&uid=' . $config['vtuner']['uid'] . '&lang=' . $config['vtuner']['lang']);
|
||||
$rsdb_xml = file_get_contents('../full_rsdb.xml');
|
||||
|
||||
$rsdb_dom = new DOMDocument();
|
||||
$rsdb_dom->preserveWhiteSpace = false;
|
||||
$rsdb_dom->loadXML($rsdb_xml);
|
||||
|
||||
if ($_GET['cmd'] == 'import') {
|
||||
// Stations
|
||||
$stationList = $rsdb_dom->getElementsByTagName('station_list')->item(0);
|
||||
echo $stationList->getElementsByTagName('station')->length . ' Stationen';
|
||||
|
||||
$counter = 0;
|
||||
$sql_pre = 'REPLACE INTO nodes (id, type, name, description, bitrate, url, mime_type) VALUES ' . "\n";
|
||||
|
||||
foreach ($stationList->getElementsByTagName('station') as $station) {
|
||||
if($counter % 50 == 0) {
|
||||
$sql = substr($sql, 0, -3);
|
||||
mysql_query($sql, $site['db']['connection']);
|
||||
echo '.'; flush();
|
||||
$sql = $sql_pre;
|
||||
}
|
||||
$sql .= '(' . (int) $station->getElementsByTagName('id')->item(0)->nodeValue . ', \'station\', \'' . mysql_real_escape_string($station->getElementsByTagName('station_name')->item(0)->nodeValue) . '\', \'' . mysql_real_escape_string($station->getElementsByTagName('station_description')->item(0)->nodeValue) . '\', ' . (int) $station->getElementsByTagName('bw')->item(0)->nodeValue . ', \'' . mysql_real_escape_string($station->getElementsByTagName('url')->item(0)->nodeValue) . '\', \'' . mysql_real_escape_string($station->getElementsByTagName('mime_type')->item(0)->nodeValue) . '\'), ' . "\n";
|
||||
$counter++;
|
||||
}
|
||||
|
||||
if(mysql_affected_rows() > 0) {
|
||||
echo '<p>' . $counter . ' stations successfully imported!</p>';
|
||||
}
|
||||
else {
|
||||
echo '<p>Sorry we had a problem during the importing process:<br />' . mysql_error() . '</p>';
|
||||
echo '<pre>' . $sql . '</pre>';
|
||||
}
|
||||
|
||||
//Structure
|
||||
$dirList = $rsdb_dom->getElementsByTagName('directory_list')->item(0);
|
||||
|
||||
$sql = 'REPLACE INTO tree (node_id, lft, rgt) VALUES ' . "\n";
|
||||
|
||||
$curNode = $dirList;
|
||||
$counter = 0;
|
||||
$level = 0;
|
||||
$lft[$level] = 0;
|
||||
|
||||
while($curNode) {
|
||||
switch ($curNode->nodeName) {
|
||||
case 'dir':
|
||||
mysql_query('REPLACE INTO nodes (type, name) VALUES (\'directory\', \'' . mysql_real_escape_string($curNode->attributes->getNamedItem('name')->nodeValue) . '\')');
|
||||
$id[$level] = mysql_insert_id();
|
||||
|
||||
//echo 'found dir: ' . $curNode->getAttribute('name') . ' and added to nodes with id: ' . mysql_insert_id() . '<br />';
|
||||
|
||||
break;
|
||||
case 'station':
|
||||
$id[$level] = (int) $curNode->nodeValue;
|
||||
|
||||
//echo 'found station: ' . $curNode->nodeValue . '<br />';
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ($curNode->hasChildNodes() && strpos($curNode->nodeName, 'dir') !== false) {
|
||||
$curNode = $curNode->firstChild;
|
||||
$level++;
|
||||
$lft[$level] = $lft[$level - 1] + 1;
|
||||
|
||||
//echo 'entering subtree (level: ' . $level . ')<br />';
|
||||
}
|
||||
else {
|
||||
$rgt[$level] = $lft[$level] + 1;
|
||||
$sql .= '(' . $id[$level] . ', ' . $lft[$level] . ', ' . $rgt[$level] . '), ' . "\n";
|
||||
echo 'next node (level: ' . $level . '): (' . $id[$level] . ', ' . $lft[$level] . ', ' . $rgt[$level] . ') <br />';
|
||||
$lft[$level] = $rgt[$level] + 1;
|
||||
|
||||
if ($curNode->nextSibling) {
|
||||
$curNode = $curNode->nextSibling;
|
||||
}
|
||||
else {
|
||||
do {
|
||||
$level--;
|
||||
$rgt[$level] = $rgt[$level + 1] + 1;
|
||||
$sql .= '(' . $id[$level] . ', ' . $lft[$level] . ', ' . $rgt[$level] . '), ' . "\n";
|
||||
echo 'leave subtree (level: ' . $level . '): (' . $id[$level] . ', ' . $lft[$level] . ', ' . $rgt[$level] . ') <br />';
|
||||
$lft[$level] = $rgt[$level] + 1;
|
||||
|
||||
if ($level == 1) break 2;
|
||||
|
||||
$curNode = $curNode->parentNode;
|
||||
} while (!$curNode->nextSibling);
|
||||
|
||||
$curNode = $curNode->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*if($counter % 50 == 0 && $sql != '') {
|
||||
$sql = substr($sql, 0, -3);
|
||||
mysql_query($sql, $site['db']['connection']);
|
||||
echo '.'; flush();
|
||||
$sql = $sql_pre;
|
||||
echo mysql_error();
|
||||
}*/
|
||||
$counter++;
|
||||
}
|
||||
|
||||
$sql = substr($sql, 0, -3);
|
||||
mysql_query($sql, $site['db']['connection']);
|
||||
|
||||
if(mysql_affected_rows() > 0) {
|
||||
echo '<p>' . $counter . ' nodes successfully imported!</p>';
|
||||
}
|
||||
else {
|
||||
echo '<p>Sorry we had a problem during the importing process:<br />' . mysql_error() . '</p>';
|
||||
}
|
||||
|
||||
echo '<pre>' . $sql . '</pre>';
|
||||
|
||||
}
|
||||
else {
|
||||
echo '<h4> Database Info</h4>
|
||||
<table>
|
||||
<tr><td>Version</td><td>' . $rsdb_dom->firstChild->attributes->getNamedItem('version')->nodeValue . '</td></tr>
|
||||
<tr><td>Stationen</td><td>' . $rsdb_dom->firstChild->attributes->getNamedItem('station_count')->nodeValue . '</td></tr>
|
||||
<tr><td>Format Version</td><td>' . $rsdb_dom->firstChild->attributes->getNamedItem('format_version')->nodeValue . '</td></tr>
|
||||
<tr><td>Server URL</td><td>' . $rsdb_dom->getElementsByTagName('database_info')->item(0)->getElementsByTagName('server_url')->item(0)->nodeValue . '</td></tr>
|
||||
<tr><td>Name</td><td>' . $rsdb_dom->getElementsByTagName('database_info')->item(0)->getElementsByTagName('name')->item(0)->nodeValue . '</td></tr>
|
||||
<tr><td>Service</td><td>' . $rsdb_dom->getElementsByTagName('database_info')->item(0)->getElementsByTagName('service')->item(0)->nodeValue . '</td></tr>
|
||||
</table>
|
||||
<p>Do you really want to import ' . $rsdb_dom->firstChild->attributes->getNamedItem('station_count')->nodeValue . ' Station to your DB?<br/>
|
||||
<a href="' . $_SERVER['PHP_SELF'] . '?cmd=import">YES</a></p>';
|
||||
}
|
||||
|
||||
echo '</body>
|
||||
</html>';
|
||||
|
||||
?>
|
39
Server/index.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
require 'init.php';
|
||||
|
||||
echo '<?xml version="1.0" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Noxon Remote Radio Database Manager 1.0</title>
|
||||
<link rel="stylesheet" type="text/css" href="stylesheet.css">
|
||||
</head>
|
||||
<body>
|
||||
<h2>Noxon Remote Radio Database Manager</h2>';
|
||||
|
||||
$result = mysql_query('SELECT * FROM (SELECT child.id, child.node_id, COUNT(*)-1 AS level, ROUND((child.rgt - child.lft - 1) / 2) AS offspring FROM tree AS child, tree AS parent WHERE child.lft BETWEEN parent.lft AND parent.rgt GROUP BY child.lft ORDER BY child.lft) tmptree INNER JOIN nodes ON nodes.id = tmptree.node_id', $site['db']['connection']);
|
||||
//$result = mysql_query('SELECT * FROM (SELECT id, node_id FROM tree WHERE rgt = lft + 1 ORDER BY lft) tmptree LEFT JOIN nodes ON nodes.id = tmptree.node_id', $site['db']['connection']);
|
||||
|
||||
|
||||
|
||||
echo '<table>
|
||||
<tr class="tree_table_head"><td>Name</td><td>Level</td><td>Substations</td><td>Actions</td></tr>';
|
||||
while ($row = mysql_fetch_assoc($result)) {
|
||||
echo '<tr><td>';
|
||||
for ($i = 0; $i < $row['level'] + 1; $i++)
|
||||
echo ' ';
|
||||
|
||||
echo '<img src="' . $row['type'] . '.png" /> ' . $row['name'] . '</td><td>' . $row['level'] . '</td><td>' . $row['offspring'] . '</td><td style="text-align: right;"l>' . (($row['type'] == 'station') ? '<a href="' . $row['url'] . '"><img class="button" alt="play" src="control_play.png" /></a>' : '') . '<a href="del.php?id=' . $row['id'] . '"><img class="button" alt="delete" src="delete.png" /></a><a href="edit.php?id=' . $row['node_id'] . '"><img class="button" alt="edit" src="edit.png" /></a></td>';
|
||||
|
||||
echo '<tr class="add_space" onclick="window.location = \'add.php?after=' . $row['id'] . '\';"><td colspan="4"></td></tr>' ;
|
||||
}
|
||||
echo '</table>';
|
||||
|
||||
echo '<a href="del.php?id=all">delete all</a>';
|
||||
|
||||
echo '</body>
|
||||
</html>'
|
||||
|
||||
?>
|
8
Server/init.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
require 'config.php';
|
||||
require 'functions.php';
|
||||
|
||||
init_mysql();
|
||||
|
||||
?>
|
94
Server/rsdb.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
require 'init.php';
|
||||
|
||||
$dom = new DOMDocument('1.0', 'iso-8859-1');
|
||||
$stationDb = $dom->createElement('station_db');
|
||||
|
||||
$databaseInfo = $dom->createElement('database_info');
|
||||
$databaseInfo->appendChild($dom->createElement('format', $config['rsdb']['format_version']));
|
||||
$databaseInfo->appendChild($dom->createElement('name', $config['rsdb']['name']));
|
||||
$databaseInfo->appendChild($dom->createElement('server_url', 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']));
|
||||
$databaseInfo->appendChild($dom->createElement('service', $config['rsdb']['service']));
|
||||
|
||||
$stationList = new StationList($dom);
|
||||
|
||||
$stationDb->appendChild($databaseInfo);
|
||||
$stationDb->appendChild($stationList->getNode());
|
||||
|
||||
|
||||
$result = mysql_query('SELECT child.id, child.node_id, COUNT(*)-1 AS level FROM tree AS child, tree AS parent WHERE child.lft BETWEEN parent.lft AND parent.rgt GROUP BY child.lft ORDER BY child.lft', $site['db']['connection']);
|
||||
|
||||
$directoryList = $dom->createElement('directory_list');
|
||||
|
||||
|
||||
$dom->appendChild($stationDb);
|
||||
|
||||
echo $dom->saveXML();
|
||||
|
||||
class Station {
|
||||
public $dom;
|
||||
public $id = 0;
|
||||
public $name;
|
||||
public $description;
|
||||
public $bitrate;
|
||||
public $url;
|
||||
public $mime_type;
|
||||
|
||||
function Station($dom, $id, $name, $description, $bitrate, $url, $mime_type) {
|
||||
$this->dom = $dom;
|
||||
$this->id = $id;
|
||||
$this->name = $name;
|
||||
$this->description = $description;
|
||||
$this->bitrate = $bitrate;
|
||||
$this->url = $url;
|
||||
$this->mime_type = $mime_type;
|
||||
}
|
||||
|
||||
function getNode() {
|
||||
$station = $this->dom->createElement('station');
|
||||
$station->appendChild($this->dom->createElement('id', $this->id));
|
||||
$station->appendChild($this->dom->createElement('station_name', $this->name));
|
||||
$station->appendChild($this->dom->createElement('description', $this->description));
|
||||
$station->appendChild($this->dom->createElement('bw', $this->bitrate));
|
||||
$station->appendChild($this->dom->createElement('url', $this->url));
|
||||
$station->appendChild($this->dom->createElement('mime_type', $this->mime_type));
|
||||
|
||||
return $station;
|
||||
}
|
||||
}
|
||||
|
||||
class StationList {
|
||||
public $stations = array();
|
||||
private $dom;
|
||||
|
||||
function StationList($dom) {
|
||||
$this->dom = $dom;
|
||||
}
|
||||
|
||||
function getStations() {
|
||||
global $config;
|
||||
global $site;
|
||||
|
||||
$stations = array();
|
||||
|
||||
$result = mysql_query('SELECT * FROM ' . $config['db']['tables']['nodes'] . ' WHERE type = \'station\'', $site['db']['connection']);
|
||||
|
||||
while ($row = mysql_fetch_assoc($result)) {
|
||||
array_push($stations, new Station($this->dom, $row['id'], $row['name'], $row['description'], $row['bitrate'], $row['url'], $row['mime_type']));
|
||||
}
|
||||
return $stations;
|
||||
}
|
||||
|
||||
function getNode() {
|
||||
$stationList = $this->dom->createElement('station_list');
|
||||
|
||||
foreach ($this->getStations() as $station) {
|
||||
$stationList->appendChild($station->getNode());
|
||||
}
|
||||
|
||||
return $stationList;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
3
Server/services.php
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
?>
|
1
Server/sql.sql
Normal file
|
@ -0,0 +1 @@
|
|||
SELECT nodes.name, nodes.type, tmptree.id, tmptree.level FROM (SELECT child.id, child.node_id, COUNT(*)-1 AS level FROM tree AS child, tree AS parent WHERE child.lft BETWEEN parent.lft AND parent.rgt GROUP BY child.lft ORDER BY child.lft) tmptree LEFT JOIN nodes ON nodes.id = tmptree.node_id;
|
BIN
Server/station.png
Normal file
After Width: | Height: | Size: 749 B |
15
Server/stylesheet.css
Normal file
|
@ -0,0 +1,15 @@
|
|||
.button {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.tree_table_head {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.add_space {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.add_space:hover {
|
||||
background-color: #4BEC4E;
|
||||
}
|
BIN
Server/up.png
Normal file
After Width: | Height: | Size: 372 B |
147
ampache/Noxon.plugin.php
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
require_once 'Noxon/RegisterMyNoxon.php';
|
||||
|
||||
class AmpacheNoxon {
|
||||
|
||||
public $name = 'Noxon';
|
||||
public $description = 'Listen to Ampache on your Noxon !';
|
||||
public $url = 'http://www.my-noxon.com';
|
||||
public $version = '000002';
|
||||
public $min_ampache = '340000';
|
||||
public $max_ampache = '349999';
|
||||
|
||||
// Error String
|
||||
private $_errorStr = "";
|
||||
|
||||
// These are internal settings used by this class, run this->load to
|
||||
// fill em out
|
||||
private $user;
|
||||
private $pass;
|
||||
private $serverCaption;
|
||||
private $strAmpacheServerURL;
|
||||
private $strAmpacheServerLANURL;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* This function does nothing...
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
return true;
|
||||
} // PluginNoxon
|
||||
|
||||
/**
|
||||
* install
|
||||
* This is a required plugin function it inserts the required preferences
|
||||
* into Ampache
|
||||
*/
|
||||
public function install() {
|
||||
|
||||
Preference::insert('noxon_user','Noxon Username','','25','string','plugins');
|
||||
Preference::insert('noxon_pass','Noxon Password','','25','string','plugins');
|
||||
Preference::insert('noxon_serverCaption','Noxon Server Caption','My ampache Server','25','string','plugins');
|
||||
Preference::insert('noxon_strAmpacheServerURL','Noxon Ampache URL',$this->getLocalNetworkURL(),'25','string','plugins');
|
||||
Preference::insert('noxon_strAmpacheServerLANURL','Noxon Ampache LAN URL (optional)',$this->getLocalNetworkURL(),'25','string','plugins');
|
||||
} // install
|
||||
|
||||
/**
|
||||
* uninstall
|
||||
* This is a required plugin function it removes the required preferences from
|
||||
* the database returning it to its origional form
|
||||
*/
|
||||
public function uninstall() {
|
||||
|
||||
Preference::delete('noxon_user');
|
||||
Preference::delete('noxon_pass');
|
||||
Preference::delete('noxon_serverCaption');
|
||||
Preference::delete('noxon_strAmpacheServerURL');
|
||||
Preference::delete('noxon_strAmpacheServerLANURL');
|
||||
} // uninstall
|
||||
|
||||
/**
|
||||
* Error management
|
||||
*/
|
||||
public function _setError( $str ) {
|
||||
$this->_errorStr = "<br>".$str;
|
||||
}
|
||||
|
||||
public function getError() {
|
||||
return $this->_errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* load
|
||||
* This loads up the data we need into this object, this stuff comes from the "Server Config plugins"
|
||||
* it's passed as a key'd array
|
||||
*/
|
||||
public function load() {
|
||||
|
||||
if (! $this->user = Config::get('noxon_user')) {
|
||||
$this->_setError( "Error Noxon plugin: User Config not set" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->pass = Config::get('noxon_pass')) {
|
||||
$this->_setError( "Error Noxon plugin: Password Config not set" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->serverCaption = ereg_replace( "[^0-9a-zA-Z_]", " ", Config::get('noxon_serverCaption'))) {
|
||||
$this->_setError( "Error Noxon plugin: Server Caption Config not set" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->strAmpacheServerURL = Config::get('noxon_strAmpacheServerURL')) {
|
||||
$this->_setError( "Error Noxon plugin: Ampache Server URL Config not set" );
|
||||
return false;
|
||||
}
|
||||
|
||||
/* optional */
|
||||
|
||||
$this->strAmpacheServerLANURL = Config::get('noxon_strAmpacheServerLANURL');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function register() {
|
||||
|
||||
if ($this->load()) {
|
||||
|
||||
$register = new RegisterMyNoxon($this->user, $this->pass, $this->strAmpacheServerURL, $this->strAmpacheServerLANURL, $this->serverCaption);
|
||||
|
||||
if (! $ret = $register->register()) {
|
||||
$this->_setError( $register->getError() );
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function unregister() {
|
||||
|
||||
if ($this->load()) {
|
||||
|
||||
$register = new RegisterMyNoxon($this->user, $this->pass, $this->strAmpacheServerURL, $this->strAmpacheServerLANURL, $this->serverCaption);
|
||||
|
||||
if (! $ret = $register->unregister()) {
|
||||
$this->_setError( $register->getError() );
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* SX: Get the expected URL of the Ampache Server in order to get a probably valid default
|
||||
*/
|
||||
private function getLocalNetworkURL() {
|
||||
$strFileName = explode("admin/modules.php",$_SERVER['SCRIPT_NAME']);
|
||||
return "http://".$_SERVER['HTTP_HOST'].":".$_SERVER['SERVER_PORT'].$strFileName[0]."modules/plugins/Noxon_xml.server.php";
|
||||
}
|
||||
|
||||
} // end AmpacheNoxon
|
||||
|
||||
?>
|
264
ampache/Noxon/AmpacheConnectorLocal.php
Normal file
|
@ -0,0 +1,264 @@
|
|||
<?php
|
||||
|
||||
class AmpacheConnectorLocal {
|
||||
|
||||
// Error String
|
||||
private $_errorStr = "";
|
||||
|
||||
/**
|
||||
CONSTRUCTOR
|
||||
**/
|
||||
|
||||
public function __construct() {
|
||||
|
||||
define('NO_SESSION','1');
|
||||
require_once '../../lib/init.php';
|
||||
}
|
||||
|
||||
/**
|
||||
PUBLIC FUNCTIONS
|
||||
**/
|
||||
|
||||
public function artists($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
Browse::reset_filters();
|
||||
Browse::set_type('artist');
|
||||
Browse::set_sort('name','ASC');
|
||||
|
||||
if ($filter) {
|
||||
Browse::set_filter('alpha_match',$filter);
|
||||
}
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
|
||||
$artists = Browse::get_objects();
|
||||
$xml = xmlData::artists($artists);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("name"));
|
||||
}
|
||||
|
||||
public function artist_albums($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$artist = new Artist($filter);
|
||||
|
||||
$albums = $artist->get_albums();
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::albums($albums);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("name", "artist", "year", "tracks", "disk", "art"));
|
||||
}
|
||||
|
||||
public function artist_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$artist = new Artist($filter);
|
||||
$songs = $artist->get_songs();
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::songs($songs);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
|
||||
public function albums($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
Browse::reset_filters();
|
||||
Browse::set_type('album');
|
||||
Browse::set_sort('name','ASC');
|
||||
|
||||
if ($filter) {
|
||||
Browse::set_filter('alpha_match',$filter);
|
||||
}
|
||||
$albums = Browse::get_objects();
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::albums($albums);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("name", "artist", "year", "tracks", "disk", "art"));
|
||||
}
|
||||
|
||||
public function album_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$album = new Album($filter);
|
||||
$songs = $album->get_songs();
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::songs($songs);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
|
||||
public function genres($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
Browse::reset_filters();
|
||||
Browse::set_type('genre');
|
||||
Browse::set_sort('name','ASC');
|
||||
|
||||
if ($filter) {
|
||||
Browse::set_filter('alpha_match',$filter);
|
||||
}
|
||||
$genres = Browse::get_objects();
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::genres($genres);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("name", "songs", "albums", "artists"));
|
||||
}
|
||||
|
||||
public function genre_artists($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$genre = new Genre($filter);
|
||||
$artists = $genre->get_artists();
|
||||
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::artists($artists);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("name"));
|
||||
}
|
||||
|
||||
public function genre_albums($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$genre = new Genre($filter);
|
||||
$albums = $genre->get_albums();
|
||||
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::albums($albums);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("name", "artist", "year", "tracks", "disk", "art"));
|
||||
}
|
||||
|
||||
public function genre_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$genre = new Genre($filter);
|
||||
$songs = $genre->get_songs();
|
||||
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::songs($songs);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
|
||||
public function songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
Browse::reset_filters();
|
||||
Browse::set_type('song');
|
||||
Browse::set_sort('title','ASC');
|
||||
|
||||
if ($filter) {
|
||||
Browse::set_filter('alpha_match',$filter);
|
||||
}
|
||||
$songs = Browse::get_objects();
|
||||
|
||||
// Set the offset
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::songs($songs);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
|
||||
public function playlists($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
Browse::reset_filters();
|
||||
Browse::set_type('playlist');
|
||||
Browse::set_sort('name','ASC');
|
||||
|
||||
if ($filter) {
|
||||
Browse::set_filter('alpha_match',$filter);
|
||||
}
|
||||
|
||||
$playlist_ids = Browse::get_objects();
|
||||
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::playlists($playlist_ids);
|
||||
return $this->_XMLStr2Array($xml, "id", array("name", "owner", "items"));
|
||||
}
|
||||
|
||||
public function playlist_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
$playlist = new Playlist($filter);
|
||||
$items = $playlist->get_items();
|
||||
|
||||
foreach ($items as $object) {
|
||||
if ($object['type'] == 'song') {
|
||||
$songs[] = $object['object_id'];
|
||||
}
|
||||
} // end foreach
|
||||
|
||||
xmlData::set_offset($offset);
|
||||
xmlData::set_limit($limit);
|
||||
$xml = xmlData::songs($songs);
|
||||
|
||||
return $this->_XMLStr2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
|
||||
public function isConnected() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error management
|
||||
*/
|
||||
public function _setError( $str ) {
|
||||
$this->_errorStr = "<br>".$str;
|
||||
}
|
||||
|
||||
public function getError() {
|
||||
return $this->_errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
PRIVATE FUNCTIONS
|
||||
**/
|
||||
|
||||
private function _XMLStr2Array($xmlStr, $key, $fieldsList) {
|
||||
// Repair a possibly broken XML String when the config Item is set
|
||||
if (NoxonConfig::$repairXML) {
|
||||
$xmlStr = str_replace("]]</","]]></",$xmlStr);
|
||||
}
|
||||
//SX:End of QnD Fix
|
||||
|
||||
// XML Data ?
|
||||
$xml = @simplexml_load_string($xmlStr);
|
||||
if ($xml === false) {
|
||||
$this->_setError("BAD_XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
// valid request ?
|
||||
if (isset($xml->error) === true) {
|
||||
$this->_setError("INVALID_REQUEST");
|
||||
return false;
|
||||
}
|
||||
|
||||
$arr = array();
|
||||
foreach ($xml as $val) {
|
||||
$tmp = array();
|
||||
foreach ($fieldsList as $field) {
|
||||
$tmp[$field] = strval($val->$field);
|
||||
}
|
||||
$arr[strval($val[$key])] = $tmp;
|
||||
}
|
||||
|
||||
return ($arr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
207
ampache/Noxon/AmpacheConnectorRemote.php
Normal file
|
@ -0,0 +1,207 @@
|
|||
<?php
|
||||
|
||||
class AmpacheConnectorRemote {
|
||||
|
||||
/**
|
||||
VAR
|
||||
**/
|
||||
private $_isConnected = false;
|
||||
private $_errorStr = null;
|
||||
private $_key = null;
|
||||
private $_auth = null;
|
||||
private $_serverUrl = null;
|
||||
|
||||
/**
|
||||
CONSTRUCTOR
|
||||
**/
|
||||
|
||||
public function __construct($serverUrl, $key) {
|
||||
|
||||
$this->_serverUrl = $serverUrl;
|
||||
$this->_key = $key;
|
||||
|
||||
$xml = $this->_requestServer("handshake");
|
||||
|
||||
// valid login ?
|
||||
if (isset($xml->auth) === false) {
|
||||
$this->_setError("BAD_LOGIN");
|
||||
return;
|
||||
}
|
||||
|
||||
// Yeah, we are connected !
|
||||
$this->_isConnected = true;
|
||||
// we keep the authorized key
|
||||
$this->_auth = $xml->auth;
|
||||
}
|
||||
|
||||
/**
|
||||
PUBLIC FUNCTIONS
|
||||
**/
|
||||
|
||||
public function artists($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("artists", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function artist_albums($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("artist_albums", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name", "artist", "year", "tracks", "disk", "art"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function artist_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("artist_songs", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function albums($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("albums", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name", "artist", "year", "tracks", "disk", "art"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function album_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("album_songs", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function genres($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("genres", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name", "songs", "albums", "artists"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function genre_artists($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("genre_artists", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function genre_albums($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("genre_albums", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name", "artist", "year", "tracks", "disk", "art"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function genre_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("genre_songs", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("songs", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function playlists($filter = null, $offset = null, $limit = null) {
|
||||
if ($xml = $this->_requestServer("playlists", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("name", "owner", "items"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function playlist_songs($filter = null, $offset = null, $limit = null) {
|
||||
|
||||
if ($xml = $this->_requestServer("playlist_songs", $filter, $offset, $limit)) {
|
||||
return $this->_XML2Array($xml, "id", array("title", "artist", "album", "genre", "track", "time", "url"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isConnected() {
|
||||
return $this->_isConnected;
|
||||
}
|
||||
|
||||
public function getError() {
|
||||
return $this->_errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
PRIVATE FUNCTIONS
|
||||
**/
|
||||
|
||||
private function _requestServer( $action, $filter = null, $offset = null, $limit = null ) {
|
||||
|
||||
if ($action == "handshake") {
|
||||
|
||||
$timestamp = time();
|
||||
$passphrase = md5($timestamp . $this->_key);
|
||||
$url = $this->_serverUrl."?action=handshake&auth=$passphrase×tamp=$timestamp";
|
||||
}
|
||||
else {
|
||||
|
||||
$filter = ( $filter ) ? "&filter=".intval( $filter ) : "";
|
||||
$offset = ( $offset ) ? "&offset=".intval( $offset ) : "";
|
||||
$limit = ( $limit ) ? "&limit=".intval( $limit ) : "";
|
||||
|
||||
$url = $this->_serverUrl."?action=".$action."&auth=".$this->_auth.$filter.$offset.$limit;
|
||||
}
|
||||
|
||||
// URL corrects ?
|
||||
$xmlData = @file_get_contents($url);
|
||||
if ($xmlData === false) {
|
||||
$this->_setError("BAD_URL");
|
||||
return false;
|
||||
}
|
||||
|
||||
// XML Data ?
|
||||
$xml = @simplexml_load_string($xmlData);
|
||||
if ($xml === false) {
|
||||
$this->_setError("BAD_XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
// valid request ?
|
||||
if (isset($xml->error) === true) {
|
||||
$this->_setError("INVALID_REQUEST");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ($xml);
|
||||
}
|
||||
|
||||
private function _XML2Array($xml, $key, $fieldsList) {
|
||||
|
||||
$arr = array();
|
||||
foreach ($xml as $val) {
|
||||
$tmp = array();
|
||||
foreach ($fieldsList as $field) {
|
||||
$tmp[$field] = strval($val->$field);
|
||||
}
|
||||
$arr[strval($val[$key])] = $tmp;
|
||||
}
|
||||
|
||||
return ($arr);
|
||||
}
|
||||
|
||||
private function _setError($errorStr) {
|
||||
$this->_errorStr = $errorStr;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
71
ampache/Noxon/NoxonConfig.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Config Class for Noxon Ampache Installation
|
||||
* Please configure the behaviour of your Ampache NOXON Plugin here
|
||||
*
|
||||
* @author Manfred Dreese / TTEG
|
||||
*/
|
||||
class NoxonConfig {
|
||||
/******************************************************
|
||||
* Basic Configuration
|
||||
******************************************************/
|
||||
/**
|
||||
* The token protects your server against guessed URLs.
|
||||
* Please enter up to 256 here.
|
||||
*
|
||||
* Example :
|
||||
* static $token = "My ampache is my Ampache";
|
||||
*/
|
||||
static $token = "secret token";
|
||||
|
||||
/**
|
||||
* www.my-noxon.com User
|
||||
*/
|
||||
static $myNoxonUser = "user@example.com";
|
||||
|
||||
/**
|
||||
* www.my-noxon.com Password
|
||||
*/
|
||||
static $myNoxonPass = "userpw";
|
||||
|
||||
/**
|
||||
* Service Caption on the Noxon
|
||||
*/
|
||||
static $serverCaption = "Test";
|
||||
|
||||
/**
|
||||
* URL for the XML Server
|
||||
*
|
||||
* $XMLUrl = URL of your Ampache server on the internet
|
||||
* i.E. http://lalala.dyndns.org/ampache/....Noxon_xml.server.php
|
||||
*
|
||||
* $XMLLANUrl = URL of your Ampache server on your LAN (optional)
|
||||
* i.E. http://192.168.241.78/ampache/....Noxon_xml.server.php
|
||||
*/
|
||||
static $XMLUrl = "http://192.168.1.31/workspace/Noxon/xml_server.php";
|
||||
static $XMLLANUrl = "http://192.168.1.31/workspace/Noxon/xml_server.php";
|
||||
|
||||
// End of user configurable section
|
||||
|
||||
|
||||
/******************************************************
|
||||
* Functions
|
||||
******************************************************
|
||||
* Please do not touch anything below this line.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the Token, mangled with some Serverdata to provide a basic
|
||||
* security solution
|
||||
* SHR13 the Unix timestamp to make the token change every 8192 sec
|
||||
*
|
||||
* @param $data : String : Some data to modify the result
|
||||
*/
|
||||
public static function getToken($data="") {
|
||||
return md5($data.NoxonConfig::$token.$_SERVER["DOCUMENT_ROOT"] );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
289
ampache/Noxon/NoxonUIHandler.php
Normal file
|
@ -0,0 +1,289 @@
|
|||
<?php
|
||||
|
||||
require_once("AmpacheConnectorRemote.php");
|
||||
require_once("AmpacheConnectorLocal.php");
|
||||
|
||||
require_once("xml/RnDir.php");
|
||||
require_once("xml/RnListOfItems.php");
|
||||
require_once("xml/RnStation.php");
|
||||
require_once("NoxonConfig.php");
|
||||
require_once("Speller.php");
|
||||
require_once("internat.php");
|
||||
|
||||
/**
|
||||
* Noxon UI Handler for Noxon Ampache Installation
|
||||
*
|
||||
* @author Manfred Dreese / TTEG
|
||||
*/
|
||||
class NoxonUIHandler {
|
||||
private $HTTPEvent;
|
||||
private $amcConnector = null;
|
||||
private $strBaseURL="";
|
||||
private $mySpeller;
|
||||
|
||||
/** Construction */
|
||||
function NoxonUIHandler () {
|
||||
|
||||
if ( $_REQUEST['token'] != NoxonConfig::getToken() ) {
|
||||
throw new Exception("NoxonUIHandler::AmpacheConnector::ConnectionFailed");
|
||||
}
|
||||
|
||||
if ( NoxonConfig::useAmpacheConfig() ) {
|
||||
$this->amcConnector = new AmpacheConnectorLocal();
|
||||
}
|
||||
else {
|
||||
$this->amcConnector = new AmpacheConnectorRemote(NoxonConfig::$ampacheUrl."/server/xml.server.php", NoxonConfig::$passphrase);
|
||||
}
|
||||
if (!$this->amcConnector->isConnected()) {
|
||||
throw new Exception("NoxonUIHandler::AmpacheConnector::ConnectionFailed");
|
||||
}
|
||||
|
||||
$this->mySpeller = new Speller(NoxonConfig::$spellerCriticalMass);
|
||||
|
||||
}
|
||||
|
||||
function isConnected() {
|
||||
return $this->amcConnector->isConnected();
|
||||
}
|
||||
|
||||
private function initGETData(&$inArray=null, $index, $inDefault) {
|
||||
if ($inArray!=null)
|
||||
if (!isset($inArray[$index]) || $inArray[$index]==null) {
|
||||
$inArray[$index]=$inDefault;
|
||||
}
|
||||
}
|
||||
|
||||
/** Standard Receiver for GETData */
|
||||
function processRequest($rhs) {
|
||||
// Any base URL provided ?
|
||||
if (isset($rhs["script.baseURL"])) {
|
||||
$this->strBaseURL = $rhs["script.baseURL"];
|
||||
|
||||
$result = new RnListOfItems();
|
||||
foreach (Array("filter","action","speller_filter","dlang") as $ele) {
|
||||
$this->initGETData($rhs, $ele, "");
|
||||
}
|
||||
|
||||
/*
|
||||
* SX: Substitute the Country code for an Element of the
|
||||
* Internationalization Set.
|
||||
*
|
||||
* "Belangrijke" Fix for Noxon3.7 bug : Device reports "jpn"
|
||||
* when device language set to dutch.
|
||||
*/
|
||||
$rhs["dlang"] = Internat::substituteCountryCode(($rhs["dlang"]=="jpn")?"NL" : $rhs["dlang"]);
|
||||
|
||||
switch ($rhs["action"]) {
|
||||
|
||||
case "artists" :
|
||||
case "speller" :
|
||||
$artists = $this->amcConnector->artists($rhs["filter"]);
|
||||
|
||||
/*
|
||||
* The Speller is used when :
|
||||
* - it is enabled in the configuration AND the user selected the speller menuitem
|
||||
* - in any case if the list length is above the devices critical mass
|
||||
*/
|
||||
|
||||
if ( (NoxonConfig::$blUseSpeller && $rhs["action"]=="speller") || sizeof($artists) > 400 ) {
|
||||
// If Artist Count is above Noxons Critical mass, ignore the user setting
|
||||
// and use the speller anyway.
|
||||
|
||||
// Start Speller
|
||||
if ( $this->mySpeller->isBelowCriticalMass($rhs["speller_filter"],$artists,"name") ) {
|
||||
// If current scope is below critical mass
|
||||
foreach ($this->mySpeller->getFilteredSubset() as $id => $artist ) {
|
||||
$result->addToList($this->AmpElement2DirElement($id,
|
||||
$artist['name'] , "artist_albums"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Our Subset is above the critical mass. Prepare another run.
|
||||
foreach ($this->mySpeller->getNextRunElements() as $id => $dummy ) {
|
||||
$result->addToList($this->AmpElement2DirElement("",
|
||||
$id."..." , "speller","&speller_filter=".urlencode($id)) );
|
||||
}
|
||||
}
|
||||
} // Speller activated ?
|
||||
else{
|
||||
// No Speller
|
||||
foreach ($artists as $id => $artist ) {
|
||||
$result->addToList($this->AmpElement2DirElement($id,
|
||||
$artist['name'] , "artist_albums"));
|
||||
}
|
||||
} // No Speller
|
||||
|
||||
break;
|
||||
case "artist_albums":
|
||||
$albums= $this->amcConnector->artist_albums($rhs["filter"]);
|
||||
foreach ($albums as $id => $album ) {
|
||||
$result->addToList($this->AmpElement2DirElement($id,
|
||||
$album['name'] , "album_songs"));
|
||||
}
|
||||
break;
|
||||
|
||||
case "playlist_songs":
|
||||
$songs = $this->amcConnector->playlist_songs($rhs["filter"]);
|
||||
// fall through
|
||||
|
||||
case "similar_songs":
|
||||
// Check whether it is a fall-through or not
|
||||
if (!isset ($songs)) {
|
||||
$songs = $this->amcConnector->genre_songs($rhs["filter"]);
|
||||
// Create a subset if structure is too large
|
||||
$arrSize = sizeof($songs);
|
||||
if ($arrSize >= NoxonConfig::$maxSimilarSongItems ) {
|
||||
shuffle($songs);
|
||||
$arrSize = NoxonConfig::$maxSimilarSongItems;
|
||||
$songs = array_slice($songs,0,$arrSize);
|
||||
}
|
||||
} // fi isset songs
|
||||
// fall through
|
||||
|
||||
case "album_songs":
|
||||
// Check whether it is a fall-through or not
|
||||
if (!isset ($songs)) {
|
||||
$songs = $this->amcConnector->album_songs($rhs["filter"]);
|
||||
} // fi isset songs
|
||||
|
||||
foreach ($songs as $id => $song ) {
|
||||
$strBkm = "&aid="."0"."&gid=".$song["genre"];
|
||||
if (isset($rhs["server.httpHostname"])
|
||||
&& NoxonConfig::$remapStreamingURLs==true) {
|
||||
$result->addToList($this->AmpSongToStationElement($id,
|
||||
$song , $rhs["server.httpHostname"], $strBkm) );
|
||||
}
|
||||
else {
|
||||
$result->addToList($this->AmpSongToStationElement($id,
|
||||
$song, null, $strBkm ));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "song_smiley":
|
||||
$menuItems = $this->getMenu("cna_song",$rhs["dlang"]);
|
||||
foreach ($menuItems as $index => $MenuItem) {
|
||||
$result->addToList($this->AmpElement2DirElement($rhs["gid"],
|
||||
$MenuItem["caption"], $index , $MenuItem["getdata"] ));
|
||||
}
|
||||
break;
|
||||
|
||||
case "genres":
|
||||
$genres = $this->amcConnector->genres($rhs["filter"]);
|
||||
foreach ($genres as $id => $playlist ) {
|
||||
$result->addToList($this->AmpElement2DirElement($id,
|
||||
$playlist['name']." (".$playlist['artists']." Artists)" , "genre_artists"));
|
||||
}
|
||||
break;
|
||||
|
||||
case "genre_artists":
|
||||
$artists = $this->amcConnector->genre_artists($rhs["filter"]);
|
||||
foreach ($artists as $id => $artist ) {
|
||||
$result->addToList($this->AmpElement2DirElement($id,
|
||||
$artist['name'] , "artist_albums"));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case "playlists":
|
||||
$playlists = $this->amcConnector->playlists($rhs["filter"]);
|
||||
foreach ($playlists as $id => $playlist ) {
|
||||
$result->addToList($this->AmpElement2DirElement($id,
|
||||
$playlist['name'] , "playlist_songs"));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Present Main Menu;
|
||||
$menuItems = $this->getMenu("root",$rhs["dlang"]);
|
||||
foreach ($menuItems as $index => $MenuItem) {
|
||||
$result->addToList($this->AmpElement2DirElement("", $MenuItem["caption"], $index , $MenuItem["getdata"] ));
|
||||
}
|
||||
break;
|
||||
|
||||
} // esac action
|
||||
return ($result->toString());
|
||||
|
||||
}
|
||||
else {
|
||||
//TODO : Throw Exception here
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Ampache Menus
|
||||
*
|
||||
* @param string $inMnuID
|
||||
* @param string $inLang
|
||||
* @return menu Array
|
||||
*/
|
||||
function getMenu($inMnuID, $inLang) {
|
||||
$result = Array();
|
||||
if ($this->isConnected()) {
|
||||
switch ($inMnuID) {
|
||||
case "root":
|
||||
$result["artists"]["caption"] = Internat::getString($inLang,"artistalbums");
|
||||
$result["artists"]["getdata"] = "";
|
||||
// Add the Speller menuentry when activated in config
|
||||
if (NoxonConfig::$blUseSpeller) {
|
||||
$result["speller"]["caption"] = Internat::getString($inLang,"artistssearch");
|
||||
$result["speller"]["getdata"] = "";
|
||||
}
|
||||
$result["genres"]["caption"] = Internat::getString($inLang,"genres");
|
||||
$result["genres"]["getdata"] = "";
|
||||
$result["playlists"]["caption"] = Internat::getString($inLang,"playlists");
|
||||
$result["playlists"]["getdata"] = "";
|
||||
break;
|
||||
|
||||
case "cna_song":
|
||||
$result["genre_artists"]["caption"] = Internat::getString($inLang,"similar_artists");
|
||||
$result["genre_artists"]["getdata"] = "";
|
||||
$result["similar_songs"]["caption"] = Internat::getString($inLang,"similar_titles");
|
||||
$result["similar_songs"]["getdata"] = "";
|
||||
break;
|
||||
|
||||
} // esac
|
||||
|
||||
} // fi isConnected ?
|
||||
return $result;
|
||||
}
|
||||
|
||||
function AmpElement2DirElement ($inId, $inName ,$inFilialAction ,$getData="") {
|
||||
$result = new RnDir();
|
||||
$result->Title = utf8_decode($inName);
|
||||
$result->Url = $this->strBaseURL."?action=".$inFilialAction."&filter=".$inId.$getData."&token=".NoxonConfig::getToken();
|
||||
return $result;
|
||||
}
|
||||
|
||||
function AmpSongToStationElement ($inId, $inSong, $inRemap=null, $inBookmarkGETData=null) {
|
||||
$result = new RnStation();
|
||||
// Remap URL to non-Local Address if Ampache Server is on local machine
|
||||
if ($inRemap) {
|
||||
$url = str_replace("http://127.0.0.1", $inRemap, $inSong['url']);
|
||||
}
|
||||
else $url = $inSong['url'];
|
||||
$result->Name = utf8_decode($inSong['title']);
|
||||
$result->Url = $url;
|
||||
if ( true || $inBookmarkGETData!=null) {
|
||||
$result->Bookmark = $this->strBaseURL."?action=song_smiley&".$inBookmarkGETData."&token=".NoxonConfig::getToken();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function AmpElement2MessageElement ($inMessage) {
|
||||
$result = new RnDir();
|
||||
$result->Title = $inMessage;
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function getNoxonError ($inStrErrorMsg) {
|
||||
$result = new RnListOfItems();
|
||||
$result->addToList(NoxonUIHandler::AmpElement2MessageElement($inStrErrorMsg));
|
||||
return ($result->toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
118
ampache/Noxon/RegisterMyNoxon.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
//SX: Load NoxonConfig in order to have access to Token seed
|
||||
require_once("NoxonConfig.php");
|
||||
|
||||
class RegisterMyNoxon {
|
||||
|
||||
private $_errorStr = "";
|
||||
|
||||
// Static strings
|
||||
private $strApplication = "AMPACHE00";
|
||||
private $inStrBFishKey = "7657BCD78698DE875FFF572481ABD626";
|
||||
private $inStrBFishIV = "264912875DEC9658";
|
||||
private $inStrToken = "aAhcDg";
|
||||
private $strRegistrationURL = "http://gatekeeper.my-noxon.net/remote/UDSRegistration/RegisterUDS.php";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($user, $pass, $strAmpacheServerURL, $strAmpacheServerLANURL, $serverCaption) {
|
||||
|
||||
$this->user = $user;
|
||||
$this->pass = $pass;
|
||||
$this->strAmpacheServerURL = $strAmpacheServerURL;
|
||||
$this->strAmpacheServerLANURL = $strAmpacheServerLANURL;
|
||||
$this->serverCaption = $serverCaption;
|
||||
}
|
||||
|
||||
/**
|
||||
* register to the my-noxon site
|
||||
*/
|
||||
public function register() {
|
||||
$ret = $this->_request_my_noxon("add");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* unregister to the my-noxon site
|
||||
*/
|
||||
public function unregister() {
|
||||
$ret = $this->_request_my_noxon("remove");
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error management
|
||||
*/
|
||||
public function _setError( $str ) {
|
||||
$this->_errorStr = "<br>".$str;
|
||||
}
|
||||
|
||||
public function getError() {
|
||||
return $this->_errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* private function to request the my-noxon site
|
||||
*/
|
||||
private function _request_my_noxon($strAction) {
|
||||
|
||||
// include needed class
|
||||
require_once 'UDSAuth.php';
|
||||
|
||||
if ( ! in_array( $strAction, array( "add", "remove" ) ) ) {
|
||||
$this->_setError( "Error RegisterMyNoxon class: action must be 'add' or 'remove'" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a new Instance of Auth with Blowfish Keys for Ampache
|
||||
$myHash = new UDSAuth($this->inStrBFishKey, $this->inStrBFishIV, $this->inStrToken);
|
||||
// Encrypt username and password
|
||||
$encryptedHash = $myHash->encryptHash($this->user, UDSAuth::createPasswordHash($this->pass, $this->user) );
|
||||
|
||||
//SX: Retrieve the Token
|
||||
$strGETToken = "?token=".NoxonConfig::getToken();
|
||||
|
||||
if (! $this->strAmpacheServerLANURL) {
|
||||
$this->strAmpacheServerLANURL = $this->strAmpacheServerURL;
|
||||
}
|
||||
|
||||
$request = $this->strRegistrationURL."?action=".$strAction
|
||||
."&AuthHash=".$myHash->hex2string($encryptedHash)
|
||||
."&destinationURL=".urlencode($this->strAmpacheServerURL.$strGETToken)
|
||||
."&destinationLANURL=".urlencode($this->strAmpacheServerLANURL.$strGETToken)
|
||||
."&displayname=".urlencode($this->serverCaption)
|
||||
."&family=".urlencode($this->strApplication);
|
||||
|
||||
echo 'Request URL: ' . $request;
|
||||
|
||||
|
||||
|
||||
// URL corrects ?
|
||||
$xmlData = @file_get_contents($request);
|
||||
|
||||
if ($xmlData === false) {
|
||||
$this->_setError( "Error RegisterMyNoxon class: URL not corrects" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// XML Data ?
|
||||
$xml = @simplexml_load_string($xmlData);
|
||||
if ($xml === false) {
|
||||
$this->_setError( "Error RegisterMyNoxon class: Response is not XML" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// valid request ?
|
||||
if (strval($xml->ActionResult) != 'true') {
|
||||
$this->_setError( "Error RegisterMyNoxon class: Invalid request : '".strval($xml->ErrorCode)."'" );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
98
ampache/Noxon/Speller.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/*
|
||||
* Speller
|
||||
*
|
||||
* General Speller class for use on small display devices
|
||||
*
|
||||
* See the NoxonServer Project Documentation for further infos
|
||||
*
|
||||
* @author Manfred Dreese / TTEG
|
||||
*/
|
||||
class Speller {
|
||||
/**
|
||||
* Integer.
|
||||
* Is set during the construction and represents the number
|
||||
* or items the speller terminates below.
|
||||
*/
|
||||
private $criticalMass;
|
||||
// private $strAlphaScope;
|
||||
|
||||
/** Filters for next Speller run */
|
||||
private $strNextRunElements;
|
||||
/** Input Data Subset, filtered by Speller imputdata */
|
||||
private $strFilterSubset;
|
||||
|
||||
/*
|
||||
* Construction
|
||||
*/
|
||||
function Speller ($inCriticalMass) {
|
||||
$this->criticalMass = $inCriticalMass;
|
||||
}
|
||||
|
||||
/*
|
||||
* IsBelowCriticalMass
|
||||
*
|
||||
* Populates the Search Index and starts the Speller
|
||||
*
|
||||
* Parametres:
|
||||
* $inStrFilter : Current Filter Text ("A".."JEA")
|
||||
* $inData : Reference to Array with Data for the speller
|
||||
* $strAlphaIndex : Alpha-Index Column of the Array for Sorting
|
||||
*
|
||||
* Returns:
|
||||
* (bool) TRUE : filtered resultset size is below critical mass,
|
||||
* FALSE: more items than critical mass.
|
||||
* One more run should be made in application logic
|
||||
*
|
||||
* Post-Run Actions in Application Logic :
|
||||
* getNextRunElements : Returns the Stringlets for the Next Run
|
||||
* i.E. A -> AB, AC, AX
|
||||
*
|
||||
* getFilteredSubset : Returns a copy of the $inData with only
|
||||
* the entries that match the filter.
|
||||
* Should be used if result below critical mass
|
||||
*/
|
||||
function isBelowCriticalMass ($inStrFilter, &$inData, $strAlphaIndex) {
|
||||
if (isset($inStrFilter)) {
|
||||
$ipos = strlen($inStrFilter)+1;
|
||||
// Output Items
|
||||
$this->strFilterSubset = Array();
|
||||
// Speller next Run Items
|
||||
$this->strNextRunElements = Array();
|
||||
$inStrFilter = strtoupper($inStrFilter);
|
||||
|
||||
// Generate Wordbook with current Input Filter
|
||||
|
||||
$this->strAlphaItems = Array();
|
||||
foreach ($inData as $arrayIndex => $data) {
|
||||
$strSpellerLength = trim(strtoupper(substr($data[$strAlphaIndex],0,$ipos)));
|
||||
if (substr($strSpellerLength,0,$ipos-1) == $inStrFilter) {
|
||||
$this->strNextRunElements[$strSpellerLength] = true;
|
||||
$this->strFilterSubset[$arrayIndex] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
// Is result below critical mass ?
|
||||
if (sizeof($this->strFilterSubset) <= $this->criticalMass) {
|
||||
// Future: Try to recurse into getSpellerData to look if we can go deeper
|
||||
return true;
|
||||
} // fi
|
||||
else {
|
||||
// Still more possibilities than wanted, return input filters for next run.
|
||||
// Sort NextElements Array only here to increase speed
|
||||
ksort($this->strNextRunElements);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNextRunElements() {
|
||||
return ($this->strNextRunElements);
|
||||
}
|
||||
|
||||
function getFilteredSubset() {
|
||||
return ($this->strFilterSubset);
|
||||
}
|
||||
} // Speller
|
||||
|
||||
?>
|
89
ampache/Noxon/UDSAuth.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Crypto Backend for UDS Authentication
|
||||
* Shared Client/Server Library, Keys are set during instanciation.
|
||||
*
|
||||
* @author Manfred Dreese / TTEG
|
||||
*/
|
||||
class UDSAuth {
|
||||
private $strBFishKey = "";
|
||||
private $strBFishIV = "";
|
||||
private $strToken = "";
|
||||
private $blValidToken = false;
|
||||
|
||||
/**
|
||||
* Hex to String conversion
|
||||
*/
|
||||
function hex2string($str)
|
||||
{
|
||||
if (trim($str)!="")
|
||||
{
|
||||
$hex="";
|
||||
$length=strlen($str);
|
||||
for ($i=0; $i<$length; $i++)
|
||||
{
|
||||
$hex.=str_pad(dechex(ord($str[$i])), 2, 0, STR_PAD_LEFT);
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String to Hex Conversion
|
||||
* ( "FF" -> \0xf \0xf
|
||||
*/
|
||||
function string2hex($str) {
|
||||
$ret="";
|
||||
for($i=0;$i<strlen($str);$i+=2) {
|
||||
$h=chr(hexdec(substr($str,$i,2)));
|
||||
$ret.=$h;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data destruction function for password.
|
||||
*
|
||||
* This is supposed for open-source CPAs or any other CPA where the
|
||||
* Blowfish keys are stored in cleartext. This function creates a
|
||||
* hash from the password which is not reversible to the original data.
|
||||
*
|
||||
* The handler will try to compare the hashes of the passwords when
|
||||
* cleartext comparism failed.
|
||||
*
|
||||
* To provide a safe encryption of short passwords without
|
||||
* having issues with wordbook/rainbowtable attacks,
|
||||
* a dual-md5 is used.
|
||||
*/
|
||||
static function createPasswordHash ($inStrPassword, $inStrUserName="") {
|
||||
return md5(md5($inStrPassword)+$inStrUserName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Is usually called from the Handler with Keys loaded
|
||||
* from the database according to the CPA.
|
||||
*/
|
||||
function UDSAuth ( $inStrBFishKey, $inStrBFishIV, $inStrToken) {
|
||||
$this->strBFishKey = $this->string2hex($inStrBFishKey);
|
||||
$this->strBFishIV = $this->string2hex($inStrBFishIV);
|
||||
$this->strToken = $inStrToken;
|
||||
} // construct
|
||||
|
||||
function isValidToken() {
|
||||
return $this->blValidToken;
|
||||
}
|
||||
|
||||
function encryptHash ($inStrUser, $inStrPassword, $inBlDestroyPassword = false ) {
|
||||
$strUnencryptedHash = $inStrUser
|
||||
.chr(10).chr(13).$inStrPassword
|
||||
.chr(10).chr(13).$this->strToken
|
||||
.chr(10).chr(13);
|
||||
|
||||
$strEncHash = mcrypt_cbc(MCRYPT_BLOWFISH,$this->strBFishKey, $strUnencryptedHash,MCRYPT_ENCRYPT,$this->strBFishIV);
|
||||
return $strEncHash;
|
||||
}
|
||||
|
||||
} // class UDSAuth
|
||||
?>
|
127
ampache/Noxon/internat.php
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
/**
|
||||
* Q&E PHP Internationalization
|
||||
*
|
||||
* @author Manfred Dreese / TTEG
|
||||
*/
|
||||
class Internat {
|
||||
/**
|
||||
* Static String Table
|
||||
*/
|
||||
static $stbl=Array("artistalbums"
|
||||
=> Array( "EN"=> "Artist/Albums",
|
||||
"DE"=> "Interpret/Alben",
|
||||
"FR"=> "Artiste/Album",
|
||||
"NL"=> "Artiest/Album",
|
||||
"IT"=> "Artista/Album",
|
||||
"ES"=> "Artista/Album" ),
|
||||
"artistssearch"
|
||||
=> Array( "EN"=> "Artists (Search)",
|
||||
"DE"=> "Interpret (Suche) ",
|
||||
"FR"=> "Artistes (Chercher)",
|
||||
"NL"=> "Artiest (Zoek)",
|
||||
"IT"=> "Artista (Cerca)",
|
||||
"ES"=> "Artista (búsqueda)" ),
|
||||
"genres"
|
||||
=> Array( "EN"=> "Genres",
|
||||
"DE"=> "Musikrichtungen",
|
||||
"FR"=> "Genres",
|
||||
"NL"=> "Genres",
|
||||
"IT"=> "Genere",
|
||||
"ES"=> "Genero" ),
|
||||
"playlists"
|
||||
=> Array( "EN"=> "Playlists",
|
||||
"DE"=> "Wiedergabelisten",
|
||||
"FR"=> "Listes de lecture",
|
||||
"NL"=> "Playlists",
|
||||
"IT"=> "Playlist",
|
||||
"ES"=> "Lista de reproducción" ),
|
||||
"similar_artists"
|
||||
=> Array( "EN"=> "Similar Artists",
|
||||
"DE"=> "Ähnliche Interpreten",
|
||||
"FR"=> "Interprètes semblables",
|
||||
"NL"=> "Vergelijkbare Artiesten",
|
||||
"IT"=> "Artisti simili",
|
||||
"ES"=> "Artistas similares" ),
|
||||
"similar_titles"
|
||||
=> Array( "EN"=> "Similar Titles",
|
||||
"DE"=> "Ähnliche Titel",
|
||||
"FR"=> "Titres semblables",
|
||||
"NL"=> "Vergelijkbare Titels",
|
||||
"IT"=> "Titoli simili",
|
||||
"ES"=> "Títulos similares" )
|
||||
|
||||
);
|
||||
|
||||
/**
|
||||
* Substitutes various Country Codes to the ones used in this class
|
||||
*
|
||||
* @param string $rhs
|
||||
* @return string
|
||||
*/
|
||||
static function substituteCountryCode ($rhs="") {
|
||||
switch (strtolower($rhs)) {
|
||||
case "49":
|
||||
case "ger":
|
||||
case "deu":
|
||||
return "DE";
|
||||
break;
|
||||
|
||||
case "01":
|
||||
case "44":
|
||||
case "eng":
|
||||
return "EN";
|
||||
break;
|
||||
|
||||
case "33":
|
||||
case "fre":
|
||||
case "fra":
|
||||
return "FR";
|
||||
break;
|
||||
|
||||
case "31":
|
||||
case "nld":
|
||||
case "dut":
|
||||
return "NL";
|
||||
break;
|
||||
|
||||
case "ita":
|
||||
case "itl":
|
||||
return "IT";
|
||||
break;
|
||||
|
||||
case "esp":
|
||||
case "spa":
|
||||
case "spn":
|
||||
case "cas":
|
||||
case "cat":
|
||||
return "ES";
|
||||
break;
|
||||
default:
|
||||
return $rhs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request internationalized String
|
||||
*
|
||||
* If language is not found, english will be used as default.
|
||||
*
|
||||
* input : $inLang = Target Language
|
||||
* $inIndex = Target Item
|
||||
*/
|
||||
static function getString($inLang, $inIndex) {
|
||||
$inLang = strtoupper($inLang);
|
||||
if (isset(Internat::$stbl[$inIndex])) {
|
||||
if (isset(Internat::$stbl[$inIndex][$inLang])
|
||||
&& Internat::$stbl[$inIndex][$inLang]!="" ) {
|
||||
return Internat::$stbl[$inIndex][$inLang];
|
||||
}
|
||||
else return Internat::$stbl[$inIndex]["EN"];
|
||||
}
|
||||
else return "...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
14
ampache/Noxon/xml/RnDir.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
class RnDir {
|
||||
public $Title, $Url, $BackUrl, $BookmarkShow;
|
||||
public $NoAudioContent = "true";
|
||||
public $Type = "Dir";
|
||||
|
||||
public function __toString() {
|
||||
return "<ItemType>".$this->Type."</ItemType>\r\n<Title>".$this->Title."</Title>\r\n<UrlDir>".$this->Url."</UrlDir>\r\n<NoAudioContent>".$this->NoAudioContent."</NoAudioContent>\r\n<UrlDirBackUp>".$this->BackUrl."</UrlDirBackUp>\r\n<BookmarkShow>".$this->BookmarkShow."</BookmarkShow>\r\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
29
ampache/Noxon/xml/RnListOfItems.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
class RnListOfItems {
|
||||
|
||||
private $items = Array();
|
||||
private $NoCache = false;
|
||||
|
||||
function RnListOfItems() {
|
||||
|
||||
}
|
||||
|
||||
function addToList ($rhs) {
|
||||
if(in_array(get_class($rhs), Array("RnDir","RnStation","RnMessage","RnDisplay"))) {
|
||||
array_push($this->items,$rhs);
|
||||
}
|
||||
}
|
||||
|
||||
function toString() {
|
||||
$elements = Array();
|
||||
foreach($this->items as $element) {
|
||||
array_push($elements,"<Item>\r\n".$element->__toString()."</Item>");
|
||||
}
|
||||
$cache = ($this->NoCache) ? "<NoCache>Yes</NoCache>\r\n" : "";
|
||||
return "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\r\n<ListOfItems>\r\n".$cache.implode("\r\n",$elements)."\r\n</ListOfItems>\r\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
14
ampache/Noxon/xml/RnStation.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
class RnStation {
|
||||
|
||||
public $Id, $Name, $Url, $Description, $Format, $Location, $Bandwidth, $Mine, $Bookmark;
|
||||
public $Type = "Station";
|
||||
|
||||
public function __toString() {
|
||||
return "<ItemType>".$this->Type."</ItemType>\r\n<StationId>".$this->Id."</StationId>\r\n<StationName>".$this->Name."</StationName>\n<StationUrl>".$this->Url."</StationUrl>\r\n<StationDesc>".$this->Description."</StationDesc>\r\n<StationFormat>".$this->Format."</StationFormat>\r\n<StationLocation>".$this->Location."</StationLocation>\r\n<StationBandWidth>".$this->Bandwidth."</StationBandWidth>\r\n<StationMime>".$this->Mine."</StationMime>\r\n<Bookmark>".$this->Bookmark."</Bookmark>\r\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
25
ampache/Noxon_register.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
require_once 'Noxon/NoxonConfig.php';
|
||||
|
||||
/**
|
||||
* Noxon Config File : Read config into NoxonConfig.php and use the RegisterMyNoxon.php class
|
||||
*/
|
||||
require_once 'Noxon/RegisterMyNoxon.php';
|
||||
$noxon = new RegisterMyNoxon( NoxonConfig::$myNoxonUser,
|
||||
NoxonConfig::$myNoxonPass,
|
||||
NoxonConfig::$XMLUrl,
|
||||
NoxonConfig::$XMLLANUrl,
|
||||
NoxonConfig::$serverCaption
|
||||
);
|
||||
|
||||
|
||||
if ($noxon->register()) {
|
||||
echo "Registration Successful";
|
||||
}
|
||||
else {
|
||||
echo "Registration Failed :<br>";
|
||||
echo $noxon->getError();
|
||||
}
|
||||
|
||||
?>
|
66
ampache/Noxon_xml.server.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/*
|
||||
* HTTP Service Receiver for Noxon Ampache Service
|
||||
*
|
||||
* @author Manfred Dreese / TTEG
|
||||
*/
|
||||
// Include
|
||||
require_once("Noxon/NoxonUIHandler.php");
|
||||
|
||||
// Variables
|
||||
/** Array to be passed to UIHandler */
|
||||
$NoxonUIRequest = Array();
|
||||
|
||||
// Utility functions
|
||||
/**
|
||||
* SX:Read a Value from the GET request
|
||||
* inStrGETIdx = Index of PHP GET
|
||||
* inArrTarget = Reference to target array (PGP CbR)
|
||||
*/
|
||||
function readGETData( $inStrGETIdx , &$inArrTarget ) {
|
||||
if ( isset($inArrTarget) ) {
|
||||
|
||||
// Does the index exist ?
|
||||
if (isset($_GET[$inStrGETIdx])) {
|
||||
|
||||
// Any fancy stuff ? In this case, drop the data
|
||||
if ( $_GET[$inStrGETIdx] == mysql_escape_string($_GET[$inStrGETIdx]) ) {
|
||||
$inArrTarget[$inStrGETIdx] = $_GET[$inStrGETIdx];
|
||||
}
|
||||
}
|
||||
} // fi Target exists?
|
||||
return null;
|
||||
} // readGETData
|
||||
|
||||
/*
|
||||
* Create NoxonUIHandler Object
|
||||
*/
|
||||
/** Create Instance of NoxonUIHandler */
|
||||
try {
|
||||
$myNoxon = new NoxonUIHandler();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
die(NoxonUIHandler::getNoxonError("Connection to Ampache failed!"));
|
||||
}
|
||||
|
||||
/*
|
||||
* HTTP Request Handler Code
|
||||
*/
|
||||
|
||||
// Read base URL for this script. Please feel free to overwrite this value in case of an advanced VHost Configuration
|
||||
// Luc : Changed from SCRIPT_URL to SCRIPT_NAME
|
||||
$NoxonUIRequest["script.baseURL"] = "http://".$_SERVER['HTTP_HOST'].":".$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
|
||||
|
||||
// Read called Hostname of this server to remap Streaming URLs to this server when this script is run on the Ampache Server
|
||||
$NoxonUIRequest["server.httpHostname"] = "http://".$_SERVER['HTTP_HOST'];
|
||||
|
||||
// Read Data from HTTP Request
|
||||
$strExpectedGetData = Array ("action","filter","speller_filter","token","spellerCMass","aid","gid","token","dlang");
|
||||
|
||||
foreach ($strExpectedGetData as $expectedGet) {
|
||||
readGETData ($expectedGet, $NoxonUIRequest);
|
||||
}
|
||||
|
||||
echo ($myNoxon->processRequest($NoxonUIRequest));
|
||||
|
||||
?>
|
1088
full_rsdb.xml
Normal file
33
http_basic_auth_main.py.patch
Normal file
|
@ -0,0 +1,33 @@
|
|||
--- main.py 2008-09-09 21:44:07.000000000 +0200
|
||||
+++ main.py.new 2008-09-09 21:47:28.000000000 +0200
|
||||
@@ -8,6 +8,7 @@
|
||||
import cgi
|
||||
import os
|
||||
import string
|
||||
+import base64
|
||||
|
||||
import config
|
||||
import lastfm
|
||||
@@ -112,6 +113,22 @@
|
||||
clientsock.close()
|
||||
return
|
||||
|
||||
+ # Check for authentification
|
||||
+ if not http.has_key("Authorization") or string.split(http["Authorization"], " ")[1] != base64.b64encode(self.username + ":" + self.password):
|
||||
+ cont = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\r\n<html>\r\n<head>\r\n<title>Error</title>\r\n<meat http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">\r\n</head>\r\n<body>\r\n<h1>401 Unauthorised.</h1>\r\n</body>\r\n</html>\r\n"
|
||||
+ print "Wrong or missing authentification"
|
||||
+ try:
|
||||
+ clientsock.sendall("HTTP/1.0 401 UNAUTHORIZED\r\n");
|
||||
+ clientsock.sendall("Content-Type: text/html\r\n")
|
||||
+ clientsock.sendall("WWW-Authenticate: Basic realm=\"Private Stream\"\r\n")
|
||||
+ clientsock.sendall("Allow: GET\r\n")
|
||||
+ clientsock.sendall("\r\n")
|
||||
+ clientsock.sendall(cont)
|
||||
+ clientsock.close()
|
||||
+ except socket.error:
|
||||
+ clientsock.close()
|
||||
+ return
|
||||
+
|
||||
tmp = string.split(req[0][1], "?", 1)
|
||||
station = tmp[0]
|
||||
if len(tmp) > 1:
|
28
rsdb_format.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
|
||||
<station_db version="2008-09-10T11:00:50Z" format_version="2.0" station_count="11337">
|
||||
<database_info>
|
||||
<format_version>2.0</format_version>
|
||||
<name>vTuner</name>
|
||||
<server_url>http://www.radio579.com/setupapp/bluewin/asp/rsdb/update.asp</server_url>
|
||||
<service>PREMIUM</service>
|
||||
</database_info>
|
||||
<station_list>
|
||||
<station>
|
||||
<id>1</id>
|
||||
<station_name size_limit="off">Last.fm Proxy</station_name>
|
||||
<description>Just a Proxy for the Social Music Network Last.fm</description>
|
||||
<bw>96</bw>
|
||||
<url>http://87.230.33.74:2944/lastfm.mp3?pw=qU4rK5m1n1m4l&user=steffenvogel</url>
|
||||
<mime_type>m3u</mime_type>
|
||||
</station>
|
||||
</station_list>
|
||||
<directory_list>
|
||||
<dir name="Internet Radio" subdir_count="1" station_count="0" >
|
||||
<dir name="Dir" subdir_count="1" station_count="0" >
|
||||
<dir name="Subdir" subdir_count="0" station_count="1" >
|
||||
<station>1</station>
|
||||
</dir>
|
||||
</dir>
|
||||
</dir>
|
||||
</directory_list>
|
||||
</station_db>
|
28
service_format.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
|
||||
<ListOfItems>
|
||||
<Item>
|
||||
<ItemType>Display</ItemType>
|
||||
<Display>Your Streaming device is unknown! Please register at www.besonic.com!</Display>
|
||||
</Item>
|
||||
<Item>
|
||||
<ItemType>Dir</ItemType>
|
||||
<Title>Demo playlists</Title>
|
||||
<UrlDir>http://gatekeeper.my-noxon.net/RadioNative.php?service=1&node=playlist&token=215385555997023</UrlDir>
|
||||
<NoAudioContent>true</NoAudioContent>
|
||||
<UrlDirBackUp></UrlDirBackUp>
|
||||
<BookmarkShow></BookmarkShow>
|
||||
</Item>
|
||||
<Item>
|
||||
<ItemType>Station</ItemType>
|
||||
<StationId></StationId>
|
||||
<StationName>Ellen_Klinghammer - Mess - live *sample*</StationName>
|
||||
<StationUrl>http://webservices.besonic.com/audio/00-1b-9e-22-e9-ec/124122.mp3</StationUrl>
|
||||
<StationDesc></StationDesc>
|
||||
<StationFormat></StationFormat>
|
||||
<StationLocation></StationLocation>
|
||||
<StationBandWidth></StationBandWidth>
|
||||
<StationMime></StationMime>
|
||||
<Bookmark>http://gatekeeper.my-noxon.net/RadioNative.php?service=10002&node=21cb40ef2acb0b15e2eea1c731de4472&token=08920a9358128a9</Bookmark>
|
||||
</Item>
|
||||
</ListOfItems>
|
||||
|