Add sorting prefix "[0-9]+_"
[noxon-gateway.git] / www / index.php
1 <?php
2 set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/../src/');
3 $fullUri = $_SERVER['REQUEST_URI'];
4 if (isset($_SERVER['REDIRECT_URL'])) {
5     $path    = $_SERVER['REDIRECT_URL'];
6 } else {
7     $path = '/';
8 }
9 $dataDir = __DIR__ . '/../data/';
10 $varDir  = realpath(__DIR__ . '/../var') . '/';
11 $host1 = 'http://radio567.vtuner.com/';
12 $host2 = 'http://radio5672.vtuner.com/';
13 if ($_SERVER['HTTP_HOST'] !== '') {
14     $host1 = 'http://' . $_SERVER['HTTP_HOST'] . '/';
15     $host2 = 'http://' . $_SERVER['HTTP_HOST'] . '/';
16 }
17 $cfgFile = $dataDir . 'config.php';
18 if (file_exists($cfgFile)) {
19     include $cfgFile;
20 }
21
22 if (strtolower($fullUri) == '/setupapp/radio567/asp/browsexpa/loginxml.asp?token=0') {
23     //initial login for "internet radio" and podcasts
24     //lowercase tags
25     header('Content-type: text/html');
26     readfile($dataDir . 'initial-login.xml');
27     exit();
28 } else if ($fullUri == '/RadioNativeLogin.php') {
29     //initial login for "My noxon"
30     //this one wants CamelCased tags
31     header('Content-type: text/html');
32     readfile($dataDir . 'login-mynoxon.xml');
33     exit();
34 } else if ($path == '/setupapp/radio567/asp/BrowseXPA/LoginXML.asp') {
35     //"Internet Radio"
36     $path = '/internetradio/';
37 } else if ($path == '/setupapp/radio567/asp/BrowseXPA/navXML.asp') {
38     //"Podcasts"
39     $path = '/podcasts/';
40 } else if ($path == '/RadioNative.php') {
41     //"My Noxon"
42     $path = '/mynoxon/';
43     $path = '/internetradio/';
44 } else if ($path == '/setupapp/radio567/asp/BrowseXML/FavXML.asp') {
45     //Internet Radio Station favorites favorited on device
46     sendMessage('Unsupported');
47 } else if ($path == '/RadioNativeFavorites.php') {
48     //Favorites, defined via web interface
49     sendMessage('Unsupported');
50 } else if (substr($path, 0, 9) == '/play-url') {
51     //play a given URL, but first follow all redirects
52     //noxon iRadio Cube does not like too many redirections
53     // 3 redirects did not work.
54     $url = $_GET['url'];
55     header('HTTP/1.0 301 Moved Permanently');
56     header('Location: ' . getFinalUrl($url));
57     exit();
58 }
59
60 handleRequest(ltrim($path, '/'));
61
62 function handleRequest($path)
63 {
64     global $varDir;
65     if (strpos($path, '..') !== false) {
66         sendMessage('No');
67         return;
68     }
69
70     if (substr($path, 0, 14) == 'internetradio/') {
71         require_once 'mediatomb.php';
72         handleRequestMediatomb($path, 'internetradio/');
73         return;
74     }
75
76
77     $fullPath = $varDir . $path;
78     if (!file_exists($fullPath)) {
79         sendMessage('Not found: ' . $path);
80         return;
81     }
82
83     $ext = pathinfo($path, PATHINFO_EXTENSION);
84     if (is_dir($fullPath)) {
85         sendDir($path);
86     } else if ($ext == 'url') {
87         require_once 'podcasts.php';
88         sendPodcast($path);
89     } else if ($ext == 'txt') {
90         sendTextFile($path);
91     } else if ($ext == 'sh') {
92         sendScript($path);
93     } else {
94         sendMessage('Unknown file type');
95     }
96 }
97
98 function pathEncode($urlPath)
99 {
100     return str_replace('%2F', '/', rawurlencode($urlPath));
101 }
102
103 function sendDir($path)
104 {
105     global $varDir;
106
107     $listItems = array();
108     addPreviousItem($listItems, $path);
109
110     $entries = glob(str_replace('//', '/', $varDir . rtrim($path, '/') . '/*'));
111     $count = 0;
112     foreach ($entries as $entry) {
113         $urlPath = pathEncode(substr($entry, strlen($varDir)));
114         $ext = pathinfo($entry, PATHINFO_EXTENSION);
115
116         $titleBase = basename($entry);
117         $titleBase = preg_replace('#^[0-9]+_#', '', $titleBase);
118         if (is_dir($entry)) {
119             ++$count;
120             $listItems[] = getDirItem($titleBase, $urlPath . '/');
121         } else if ($ext == 'url') {
122             //podcast
123             ++$count;
124             $listItems[] = getPodcastItem(basename($titleBase, '.url'), $urlPath);
125         } else if (substr($entry, -8) == '.auto.sh') {
126             //automatically execute script while listing this directory
127             addScriptOutput($listItems, $entry);
128         } else if ($ext == 'txt' || $ext == 'sh') {
129             //plain text file
130             ++$count;
131             $listItems[] = getDirItem(basename($titleBase, '.' . $ext), $urlPath);
132         }
133     }
134     if (!$count) {
135         $listItems[] = getMessageItem('No files or folders');
136     }
137     sendListItems($listItems);
138 }
139
140 function sendScript($path)
141 {
142     global $varDir;
143
144     $listItems = array();
145     addPreviousItem($listItems, $path);
146
147     $fullPath = $varDir . $path;
148     addScriptOutput($listItems, $fullPath);
149     sendListItems($listItems);
150 }
151
152 function addScriptOutput(&$listItems, $fullPath)
153 {
154     exec($fullPath . ' 2>&1', $output, $retVal);
155
156     if ($retVal == 0) {
157         addTextLines($listItems, $output);
158     } else {
159         $listItems[] = getMessageItem('Error executing script');
160         addTextLines($listItems, $output);
161     }
162 }
163
164 function sendTextFile($path)
165 {
166     global $varDir;
167     $listItems = array();
168     addPreviousItem($listItems, $path);
169
170     $lines = file($varDir . $path);
171     addTextLines($listItems, $lines);
172     sendListItems($listItems);
173 }
174
175 function addTextLines(&$listItems, $lines)
176 {
177     foreach ($lines as $line) {
178         $line = trim($line);
179         if ($line != '') {
180             $listItems[] = getDisplayItem($line);
181         }
182     }
183 }
184
185 function getDisplayItem($line)
186 {
187     $line = preg_replace('#\s+#', ' ', $line);
188     return '<Item>'
189         . '<ItemType>Display</ItemType>'
190         . '<Display>' . utf8_decode(htmlspecialchars($line)) . '</Display>'
191         . '</Item>';
192 }
193
194 function getDirItem($title, $urlPath)
195 {
196     global $host1, $host2;
197     return '<Item>'
198         . '<ItemType>Dir</ItemType>'
199         . '<Title>' . utf8_decode(htmlspecialchars($title)) . '</Title>'
200         . '<UrlDir>' . $host1 . utf8_decode(htmlspecialchars($urlPath)) . '</UrlDir>'
201         . '<UrlDirBackUp>' . $host2 . utf8_decode(htmlspecialchars($urlPath)) . '</UrlDirBackUp>'
202         . '</Item>';
203 }
204
205 function getEpisodeItem($title, $fullUrl, $desc, $type)
206 {
207     return '<Item>'
208         . '<ItemType>ShowEpisode</ItemType>'
209         . '<ShowEpisodeName>' . utf8_decode(htmlspecialchars($title)) . '</ShowEpisodeName>'
210         . '<ShowEpisodeURL>' . $fullUrl . '</ShowEpisodeURL>'
211         . '<ShowDesc>' . utf8_decode(htmlspecialchars($desc)) . '</ShowDesc>'
212         . '<ShowMime>' . $type . '</ShowMime>'
213         . '</Item>';
214 }
215
216 function getPodcastItem($title, $urlPath)
217 {
218     global $host1;
219     return '<Item>'
220         . '<ItemType>ShowOnDemand</ItemType>'
221         . '<ShowOnDemandName>' . utf8_decode(htmlspecialchars($title)) . '</ShowOnDemandName>'
222         . '<ShowOnDemandURL>' . $host1 . utf8_decode(htmlspecialchars($urlPath)) . '</ShowOnDemandURL>'
223         . '</Item>';
224 }
225
226 function getMessageItem($msg)
227 {
228     return '<Item>'
229         . '<ItemType>Message</ItemType>'
230         . '<Message>' . utf8_decode(htmlspecialchars($msg)) . '</Message>'
231         . '</Item>';
232 }
233
234 function getPreviousItem($urlPath)
235 {
236     global $host1, $host2;
237     return '<Item>'
238         . '<ItemType>Previous</ItemType>'
239         . '<UrlPrevious>' . $host1 . utf8_decode(htmlspecialchars($urlPath)) . '</UrlPrevious>'
240         . '<UrlPreviousBackUp>' . $host1 . utf8_decode(htmlspecialchars($urlPath)) . '</UrlPreviousBackUp>'
241         . '</Item>';
242 }
243
244 function addPreviousItem(&$listItems, $urlPath)
245 {
246     $parentDir = dirname($urlPath) . '/';
247     if ($parentDir == '/') {
248         return;
249     }
250     $listItems[] = getPreviousItem($parentDir);
251 }
252
253 function getFinalUrl($url)
254 {
255     $ctx = stream_context_set_default(
256         array('http' => array('method' => 'HEAD'))
257     );
258     //get_headers follows redirects automatically
259     $headers = get_headers($url, 1);
260     if ($headers !== false && isset($headers['Location'])) {
261         return end($headers['Location']);
262     }
263     return $url;
264 }
265
266 function sendMessage($msg)
267 {
268     sendListItems(array(getMessageItem($msg)));
269 }
270
271 function sendListItems($listItems)
272 {
273     $startitems = 1;
274     $enditems = 10;
275     if (isset($_GET['startitems'])) {
276         $startitems = (int) $_GET['startitems'];
277     }
278     if (isset($_GET['enditems'])) {
279         $enditems = (int) $_GET['enditems'];
280     }
281     //TODO: limit list
282
283     $xml = '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
284     $xml .= '<?xml-stylesheet type="text/xsl" href="/html.xsl"?>' . "\n";
285     $xml .= '<ListOfItems>' . "\n";
286     foreach ($listItems as $item) {
287         $xml .= $item . "\n";
288     }
289     $xml .= "</ListOfItems>\n";
290
291     header('Content-type: text/xml');
292     echo $xml;
293 }
294 ?>