podcasts work
authorChristian Weiske <cweiske@cweiske.de>
Thu, 12 Nov 2015 00:11:03 +0000 (01:11 +0100)
committerChristian Weiske <cweiske@cweiske.de>
Thu, 12 Nov 2015 00:11:03 +0000 (01:11 +0100)
.gitignore [new file with mode: 0644]
README.rst [new file with mode: 0644]
data/initial-login.xml [new file with mode: 0644]
data/list-test.xml [new file with mode: 0644]
data/login-mynoxon.xml [new file with mode: 0644]
src/podcasts.php [new file with mode: 0644]
var/podcasts/.keep [new file with mode: 0644]
www/.htaccess [new file with mode: 0644]
www/index.php [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d0c3275
--- /dev/null
@@ -0,0 +1 @@
+/var/podcasts/*
diff --git a/README.rst b/README.rst
new file mode 100644 (file)
index 0000000..42e09fa
--- /dev/null
@@ -0,0 +1,30 @@
+********************
+Noxon iRadio gateway
+********************
+Push your own content onto Noxon iRadio devices.
+
+This tool makes it possible to push own data into the menu
+entries
+- Internet Radio
+- Podcasts
+- My Noxon
+
+
+================
+Adding a podcast
+================
+Create a file "Title.url" in ``var/podcasts/`` and write
+the URL of the podcast MP3 RSS feed into it.
+
+=====
+Setup
+=====
+
+Hosts
+=====
+The following hosts must point to your server and be handled
+by this tool::
+
+    radio567.vtuner.com
+    radio5672.vtuner.com
+    gatekeeper.my-noxon.net
diff --git a/data/initial-login.xml b/data/initial-login.xml
new file mode 100644 (file)
index 0000000..2206537
--- /dev/null
@@ -0,0 +1 @@
+<encryptedtoken>a6703ded78821be5</encryptedtoken>
diff --git a/data/list-test.xml b/data/list-test.xml
new file mode 100644 (file)
index 0000000..af308cd
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<ListOfItems>
+  <ItemCount>-1</ItemCount>
+  <Item>
+    <ItemType>Dir</ItemType>
+    <Title>Hallo!</Title>
+    <UrlDir>http://radio567.vtuner.com/test</UrlDir>
+    <UrlDirBackUp>http://radio5672.vtuner.com/test</UrlDirBackUp>
+  </Item>
+</ListOfItems>
diff --git a/data/login-mynoxon.xml b/data/login-mynoxon.xml
new file mode 100644 (file)
index 0000000..e88d339
--- /dev/null
@@ -0,0 +1 @@
+<EncryptedToken>a6703ded78821be5</EncryptedToken>
diff --git a/src/podcasts.php b/src/podcasts.php
new file mode 100644 (file)
index 0000000..9948af4
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+function sendPodcastList()
+{
+    $files = glob(__DIR__ . '/../var/podcasts/*.url');
+    if (count($files) == 0) {
+        sendMessage('Keine Podcasts');
+        return;
+    }
+
+    $listItems = array();
+    foreach ($files as $file) {
+        $title = basename($file, '.url');
+        $listItems[] = '<Item>'
+            . '<ItemType>ShowOnDemand</ItemType>'
+            . '<ShowOnDemandName>' . htmlspecialchars($title) . '</ShowOnDemandName>'
+            . '<ShowOnDemandURL>http://radio567.vtuner.com/podcasts/' . urlencode(basename($file)) . '</ShowOnDemandURL>'
+            . '</Item>';
+    }
+    sendListItems($listItems);
+}
+
+function sendPodcast($file)
+{
+    //strip /podcasts/
+    $file = substr(urldecode($file), 10);
+    if (strpos($file, '..') !== false) {
+        sendMessage('No');
+        return;
+    }
+
+    $path = __DIR__ . '/../var/podcasts/' . $file;
+    if (!file_exists($path)) {
+        return sendMessage('File does not exist: ' . $file);
+    }
+
+    $url = trim(file_get_contents($path));
+
+    $cacheFile = '/tmp/podcast-' . md5($file) . '.xml';
+    downloadIfNewer($url, $cacheFile);
+    
+    $sx = simplexml_load_file($cacheFile);
+    $listItems = array();
+    foreach ($sx->channel->item as $item) {
+        $title = (string) $item->title;
+        $desc = (string) $item->description;
+        $url = $item->enclosure['url'];
+
+        $listItems[] = '<Item>'
+            . '<ItemType>ShowEpisode</ItemType>'
+            . '<ShowEpisodeName>' . utf8_decode(htmlspecialchars($title)) . '</ShowEpisodeName>'
+            . '<ShowEpisodeURL>http://radio567.vtuner.com/play-url?url=' . urlencode($url) . '</ShowEpisodeURL>'
+            //. '<ShowEpisodeURL>' . htmlspecialchars($url) . '</ShowEpisodeURL>'
+            . '<ShowDesc>' . utf8_decode(htmlspecialchars($desc)) . '</ShowDesc>'
+            . '<ShowMime>MP3</ShowMime>' 
+            . '</Item>';
+    }
+    sendListItems($listItems);
+}
+
+
+function downloadIfNewer($url, $file)
+{
+    $lastModified = 0;
+    if (file_exists($file)) {
+        $lastModified = filemtime($file);
+    }
+
+    $ctx = stream_context_create(
+        array(
+            'http' => array(
+                'header' => 'If-Modified-Since: ' . date('r', $lastModified)
+            )
+        )
+    );
+    $content = file_get_contents($url, false, $ctx);
+    //unfortunately, redirects require manual parsing of this array
+    for ($n = count($http_response_header) - 1; $n >= 0; --$n) {
+        if (substr($http_response_header[$n], 0, 5) == 'HTTP/') {
+            list(, $code) = explode(' ', $http_response_header[$n]);
+            break;
+        }
+    }
+    if ($code == 200) {
+        file_put_contents($file, $content);
+    }
+}
+
+?>
\ No newline at end of file
diff --git a/var/podcasts/.keep b/var/podcasts/.keep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/www/.htaccess b/www/.htaccess
new file mode 100644 (file)
index 0000000..4fb1fbe
--- /dev/null
@@ -0,0 +1,3 @@
+RewriteEngine On
+RewriteBase /
+RewriteRule ^.*$ index.php
diff --git a/www/index.php b/www/index.php
new file mode 100644 (file)
index 0000000..cc0be0e
--- /dev/null
@@ -0,0 +1,129 @@
+<?php
+set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/../src/');
+$fullUri = $_SERVER['REQUEST_URI'];
+$path    = $_SERVER['REDIRECT_URL'];
+$dataDir = __DIR__ . '/../data/';
+
+if (strtolower($fullUri) == '/setupapp/radio567/asp/browsexpa/loginxml.asp?token=0') {
+    //initial login for "internet radio" and podcasts
+    //lowercase tags
+    header('Content-type: text/html');
+    readfile($dataDir . 'initial-login.xml');
+    exit();
+} else if ($fullUri == '/RadioNativeLogin.php') {
+    //initial login for "My noxon"
+    //this one wants CamelCased tags
+    header('Content-type: text/html');
+    readfile($dataDir . 'login-mynoxon.xml');
+    exit();
+} else if ($path == '/setupapp/radio567/asp/BrowseXPA/LoginXML.asp') {
+    //"Internet Radio"
+    header('Content-type: text/xml');
+    sendList('internetradio');
+    exit();
+} else if ($path == '/setupapp/radio567/asp/BrowseXPA/navXML.asp') {
+    //"Podcasts"
+    require_once 'podcasts.php';
+    sendPodcastList();
+    exit();
+} else if (substr($path, 0, 9) == '/podcasts') {
+    require_once 'podcasts.php';
+    sendPodcast($path);
+    exit();    
+} else if ($path == '/RadioNative.php') {
+    //"My Noxon"
+    header('Content-type: text/xml');
+    sendList('mynoxon');
+    exit();
+} else if ($path == '/setupapp/radio567/asp/BrowseXML/FavXML.asp') {
+    //Internet Radio Station favorites favorited on device
+} else if ($path == '/RadioNativeFavorites.php') {
+    //Favorites, defined via web interface
+} else if (substr($path, 0, 9) == '/play-url') {
+    //play a given URL, but first follow all redirects
+    //noxon iRadio Cube does not like too many redirections
+    // 3 redirects did not work.
+    $url = $_GET['url'];
+    header('HTTP/1.0 301 Moved Permanently');
+    header('Location: ' . getFinalUrl($url));
+    exit();
+} else {
+    sendList(ltrim($path, '/'));
+}
+
+
+function getFinalUrl($url)
+{
+    $ctx = stream_context_set_default(
+        array('http' => array('method' => 'HEAD'))
+    );
+    //get_headers follows redirects automatically
+    $headers = get_headers($url, 1);
+    if ($headers !== false && isset($headers['Location'])) {
+        return end($headers['Location']);
+    }
+    return $url;
+}
+
+
+function sendList($path)
+{
+    $startitems = 1;
+    $enditems = 10;
+    if (isset($_GET['startitems'])) {
+        $startitems = (int) $_GET['startitems'];
+    }
+    if (isset($_GET['enditems'])) {
+        $enditems = (int) $_GET['enditems'];
+    }
+
+    header('Content-type: text/xml');
+    echo <<<XML
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<ListOfItems>
+  <ItemCount>-1</ItemCount>
+  <Item>
+    <ItemType>Message</ItemType>
+    <Message>$path</Message>
+  </Item>
+  <Item>
+    <ItemType>Dir</ItemType>
+    <Title>$path</Title>
+    <UrlDir>http://radio567.vtuner.com/$path</UrlDir>
+    <UrlDirBackUp>http://radio5672.vtuner.com/$path</UrlDirBackUp>
+  </Item>
+</ListOfItems>
+
+XML;
+}
+
+function sendMessage($msg)
+{
+    header('Content-type: text/xml');
+    $xMsg = htmlspecialchars($msg);
+    echo <<<XML
+<?xml version="1.0" encoding="iso-8859-1" standalone="yes" ?>
+<ListOfItems>
+  <Item>
+    <ItemType>Message</ItemType>
+    <Message>$xMsg</Message>
+  </Item>
+</ListOfItems>
+
+XML;
+}
+
+function sendListItems($listItems)
+{
+    $xml = '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
+    $xml .= '<ListOfItems>' . "\n";
+    foreach ($listItems as $item) {
+        $xml .= $item . "\n";
+    }
+    $xml .= "</ListOfItems>\n";
+    
+    header('Content-type: text/xml');
+    echo $xml;
+}
+
+?>