initial import

This commit is contained in:
Steffen Vogel 2010-08-17 01:22:49 +02:00
commit eea2a9a4b2
43 changed files with 3242 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.settings
.cproject
.project
.classpath

29
README Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

BIN
Server/arrow_left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

BIN
Server/arrow_right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

BIN
Server/arrow_up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

30
Server/config.php Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

25
Server/del.php Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

BIN
Server/directory.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

BIN
Server/display.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

46
Server/edit.php Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

11
Server/functions.php Normal file
View 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
View 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
View 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 '&nbsp;&nbsp;';
echo '<img src="' . $row['type'] . '.png" />&nbsp;' . $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
View file

@ -0,0 +1,8 @@
<?php
require 'config.php';
require 'functions.php';
init_mysql();
?>

94
Server/rsdb.php Normal file
View 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
View file

@ -0,0 +1,3 @@
<?php
?>

1
Server/sql.sql Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

15
Server/stylesheet.css Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

147
ampache/Noxon.plugin.php Normal file
View 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
?>

View 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);
}
}
?>

View 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&timestamp=$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;
}
}
?>

View 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"] );
}
}
?>

View 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());
}
}
?>

View 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
View 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
View 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
View 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 "...";
}
}
?>

View 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";
}
}
?>

View 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";
}
}
?>

View 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";
}
}
?>

View 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();
}
?>

View 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

File diff suppressed because it is too large Load diff

View 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
View 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&amp;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
View 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>