PageRenderTime 51ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 2ms

/zina/index.php

https://bitbucket.org/awgh/zina
PHP | 8314 lines | 7321 code | 756 blank | 237 comment | 1906 complexity | 2c50c0399391f1aad5e7e74d201f64dd MD5 | raw file
  1. <?php
  2. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  3. * ZINA (Zina is not Andromeda)
  4. *
  5. * Zina is a graphical interface to your MP3 collection, a personal
  6. * jukebox, an MP3 streamer. It can run on its own, embeded into an
  7. * existing website, or as a Drupal/Joomla/Wordpress/etc. module.
  8. *
  9. * http://www.pancake.org/zina
  10. * Author: Ryan Lathouwers <ryanlath@pacbell.net>
  11. * Support: http://sourceforge.net/projects/zina/
  12. * License: GNU GPL2 <http://www.gnu.org/copyleft/gpl.html>
  13. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  14. define('ZINA_VERSION', '2.0b22');
  15. #TODO:
  16. # - INSTRUCTIONS for cron for caches
  17. #todo
  18. # - uninstall? -> at least delete cache files created by webuser!
  19. # - check settings descriptions...
  20. # - normalize function names
  21. # - organize files
  22. # - comment functions?
  23. # - look and remove unused language crap?
  24. #TODO-EXTRA:
  25. # - if clean urls... drop l=8&m=1 for songs???
  26. # - See Also -> external links?
  27. # - multiple mp3 dirs
  28. # - Check output_buffering php.ini setting for video stuff?
  29. #TEST:
  30. # - pos
  31. function zina($conf) {
  32. global $zc;
  33. zina_init($conf);
  34. $path = isset($_GET['p']) ? zrawurldecode($_GET['p']) : null;
  35. $level = isset($_GET['l']) ? $_GET['l'] : null;
  36. $m = isset($_GET['m']) ? $_GET['m'] : null;
  37. $imgsrc = isset($_GET['img']) ? $_GET['img'] : null;
  38. $playlist = isset($_POST['playlist']) ? $_POST['playlist'] : (isset($_GET['pl']) ? $_GET['pl'] : null);
  39. $songs = isset($_POST['mp3s']) ? $_POST['mp3s'] : (isset($_GET['mp3s']) ? $_GET['mp3s'] : array());
  40. $path = preg_replace("|(/){2,}|",'$1',trim($path,'/'));
  41. $badpath = false;
  42. if (strstr($path,'..') && !zfile_check_location($zc['mp3_dir'].'/'.$path, $zc['mp3_dir'])) {
  43. $badpath = true;
  44. }
  45. if (!$badpath && strstr($imgsrc,'..')) {
  46. $badpath = true;
  47. if ($level == 11) {
  48. $badpath = (!zfile_check_location($zc['mp3_dir'].'/'.$path, $zc['mp3_dir']));
  49. } elseif ($level == 7) {
  50. if (isset($_GET['it'])) {
  51. if ($_GET['it'] == 'genre') {
  52. } elseif (in_array($_GET['it'], array('sub','dir','full','search'))) {
  53. $badpath = (!zfile_check_location($zc['mp3_dir'].'/'.$path, $zc['mp3_dir']));
  54. }
  55. }
  56. }
  57. }
  58. if (!$badpath && strstr($playlist,'..')) $badpath = true;
  59. if (!$badpath && !empty($songs) && is_array($songs)) {
  60. foreach ($songs as $song) {
  61. if (strstr($song,'..') && !zfile_check_location($zc['mp3_dir'].'/'.$path, $zc['mp3_dir'])) {
  62. $badpath = true;
  63. break;
  64. }
  65. }
  66. }
  67. if ($badpath) {
  68. zina_debug(zt('Bad path: @path', array('@path'=>$path)));
  69. return zina_not_found();
  70. }
  71. $zc['cur_dir'] = $zc['mp3_dir']. (!empty($path) ? '/'.$path : '');
  72. if (!empty($path) && !file_exists($zc['cur_dir'])) {
  73. $file_not_found = true;
  74. if (substr($path,-3) == '.lp') {
  75. $tmp_path = substr($path, 0, strlen($path) -3);
  76. if (file_exists($zc['mp3_dir'].'/'.$tmp_path)) {
  77. $file_not_found = false;
  78. $zc['cur_dir'] = $zc['mp3_dir'].'/'.$tmp_path;
  79. }
  80. } elseif ($zc['sitemap'] && $path == $zc['sitemap_file']) {
  81. $level = 51;
  82. $path = '';
  83. $zc['cur_dir'] = $zc['mp3_dir'];
  84. $file_not_found = false;
  85. } elseif ($zc['rss'] && basename($path) == $zc['rss_file']) {
  86. $level = 50;
  87. $path = substr($path,0,-(strlen($zc['rss_file'])+1));
  88. $zc['cur_dir'] = $zc['mp3_dir'].'/'.$path;
  89. if (file_exists($zc['cur_dir'])) $file_not_found = false;
  90. } elseif ($zc['stats_rss'] && $zc['database'] && basename($path) == 'stats.xml') {
  91. zina_stats_feed($path);
  92. } elseif ($zc['playlists'] && $zc['database'] && basename($path) == 'pls.xml') {
  93. $pls_id = dirname($path);
  94. if (zina_validate('int',$pls_id)) {
  95. zina_playlist_feed($pls_id);
  96. }
  97. } elseif ($level == 46 && basename($path) == 'zina_id3_zina.jpg') {
  98. $file_not_found = false;
  99. $tmp_path = dirname($path);
  100. $tmp_path = $zc['mp3_dir'].(!empty($tmp_path) ? '/'.$tmp_path : '');
  101. if (file_exists($tmp_path) && is_dir($tmp_path)) $file_not_found = false;
  102. }
  103. if ($file_not_found) {
  104. $tmp_path = utf8_decode($path);
  105. $tmp_cur_dir = $zc['mp3_dir']. (!empty($tmp_path) ? '/'.$tmp_path : '');
  106. if (file_exists($tmp_cur_dir)) {
  107. $path = $tmp_path;
  108. $zc['cur_dir'] = $tmp_cur_dir;
  109. } else {
  110. if (substr($path,-11) != 'favicon.ico') zina_debug(zt('Path does not exist: @path', array('@path'=>$path)));
  111. return zina_not_found();
  112. }
  113. }
  114. }
  115. #todo: validate?
  116. if ($zc['settings_override']) {
  117. $override_file = $zc['cur_dir'].'/'.$zc['settings_override_file'];
  118. if (file_exists($override_file)) {
  119. $override = false;
  120. if (($dir_xml = file_get_contents($override_file)) !== false) {
  121. $dir_settings = xml_to_array($dir_xml, 'settings');
  122. if (!empty($dir_settings[0])) {
  123. foreach($dir_settings[0] as $key => $val) {
  124. if (isset($zc[$key])) $zc[$key] = $val;
  125. }
  126. $override = true;
  127. }
  128. }
  129. if (!$override) {
  130. zina_set_message(zt('Cannot read override file.'), 'error');
  131. return zina_access_denied();
  132. }
  133. }
  134. }
  135. /*
  136. * MAIN
  137. *
  138. * Determines what zina does.
  139. */
  140. if (in_array($level, array(18,19,20,21,26,27,28,30,31,32,33,34,35,42,45,47,48,49,52,58,59,60,61,62,63,64,67,71,72,73,75,76,78))) {
  141. # ADMIN FUNCTIONS
  142. if (!$zc['is_admin']) return zina_access_denied();
  143. #todo: needed?
  144. #header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
  145. #header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT');
  146. #header('Cache-Control: no-cache, must-revalidate, max-age=0');
  147. #header('Pragma: no-cache');
  148. switch($level) {
  149. Case 18 : # INSTALL OR UPDATE DB
  150. if ($zc['database'] && ($m == 'update' || $m == 'install')) {
  151. $file = $zc['zina_dir_abs'].'/'.$m.'.php';
  152. if ($zc['database'] && file_exists($file)) {
  153. require_once($file);
  154. if ($m == 'install') {
  155. $result = zina_install_database();
  156. } else {
  157. $result = zina_updates_execute();
  158. }
  159. if ($result) {
  160. if ($m == 'install') zvar_set('version', ZINA_VERSION);
  161. zina_set_message(zt('Database @m succeeded!',array('@m'=>$m)));
  162. } else {
  163. zina_set_message(zt('Database @m failed!', array('@m'=>$m)),'error');
  164. }
  165. } else {
  166. zina_set_message(zt('Cannot @m the database...either no database connection or the file does not exist.',array('@m'=>$m)), 'error');
  167. }
  168. zina_goto('', 'l=20');
  169. }
  170. return zina_not_found();
  171. break;
  172. Case 19 : # try to manually submit last.fm queue
  173. if ($zc['lastfm']) {
  174. require_once($zc['zina_dir_abs'].'/extras/scrobbler.class.php');
  175. @set_time_limit($zc['timeout']);
  176. $scrobbler = new scrobbler($zc['lastfm_username'],$zc['lastfm_password']);
  177. $scrobbler->handshake_socket_timeout = 2;
  178. $scrobbler->submit_socket_timeout = 30;
  179. $scrobbler->queued_tracks = zina_set_scrobbler_queue();
  180. if ($scrobbler->submit_tracks()) {
  181. zina_set_message(zt('Queued Last.fm tracks submitted successfully.'));
  182. zina_set_scrobbler_queue(array(), true);
  183. } else {
  184. zina_set_message(zt('Queued Last.fm tracks failed:').$scrobbler->error_msg,'warn');
  185. }
  186. zina_goto('', 'l=20');
  187. }
  188. break;
  189. Case 20 : # CFG
  190. return zina_page_main($path, 'config');
  191. break;
  192. Case 21 : # CFG POST
  193. if (zina_write_settings()) {
  194. zina_set_message(zt('Settings updated.'));
  195. } else {
  196. zina_set_message(zt('Your settings were not saved!'),'error');
  197. }
  198. zina_goto('', 'l=20');
  199. break;
  200. Case 26 : # regen
  201. require_once($zc['zina_dir_abs'].'/batch.php');
  202. @trigger_error('');
  203. $error = false;
  204. if ($m == 1) { # dir/files caches
  205. if ($zc['database']) {
  206. foreach(array('dirs','files_assoc') as $type) {
  207. $operations[] = array('zina_core_cache_batch', array($type, '', array('force'=>true)));
  208. }
  209. if ($zc['low']) {
  210. foreach(array('files_assoc') as $type) {
  211. $operations[] = array('zina_core_cache_batch', array($type, '', array('force'=>true, 'low'=>true)));
  212. }
  213. }
  214. $batch = array(
  215. 'title' => zt('Regenerating directory and file caches.'),
  216. 'finished_message' => zt('Caches generated successfully.'),
  217. 'operations' => $operations,
  218. );
  219. zbatch_set($batch);
  220. zbatch_process();
  221. } else {
  222. foreach(array('dirs','files_assoc') as $type) zina_core_cache($type, '', array('force'=>true));
  223. if ($zc['low']) {
  224. foreach(array('files_assoc') as $type) zina_core_cache($type, '', array('force'=>true,'low'=>true));
  225. }
  226. $message = zt('Cache generated successfully.');
  227. }
  228. } elseif ($m == 2) { # genre cache
  229. #todo: use db or cache but not both? for genres? for dirs/files?
  230. if ($zc['database']) {
  231. $operations = array();
  232. $operations[] = array('zina_core_cache_batch', array('genre', '', array('force'=>true)));
  233. $operations[] = array('zdb_genre_populate', array(time()));
  234. $batch = array(
  235. 'title' => zt('Regenerating genre caches.'),
  236. 'finished_message' => zt('Genre cache generated successfully.'),
  237. 'operations' => $operations,
  238. );
  239. zbatch_set($batch);
  240. zbatch_process();
  241. } else {
  242. $message = zt('Genre cache generated successfully.');
  243. zina_core_cache('genre', '', array('force'=>true));
  244. }
  245. } elseif ($m == 3 || $m == 4) { # populate missing
  246. #TODO: combine 3 & 4... combine 1,3&4?
  247. if ($zc['database']) {
  248. $runtime = time();
  249. $operations = array();
  250. foreach(array('dirs','files_assoc') as $type) {
  251. $operations[] = array('zina_core_cache_batch', array($type, '', array('force'=>true)));
  252. }
  253. if ($m == 3) {
  254. $regen = false;
  255. $title = zt('Populating database with missing entries.');
  256. $finished = zt('Database populated.');
  257. } else { # 4
  258. $regen = true;
  259. $title = zt('Synchronising database');
  260. $finished = zt('Synchronized database.');
  261. }
  262. $operations[] = array('zdb_populate_batch', array($regen));
  263. $operations[] = array('zdb_search_playlist_populate', array($runtime));
  264. $operations[] = array('zdb_genre_populate', array($runtime));
  265. $batch = array(
  266. 'title' => $title,
  267. 'finished_message' => $finished,
  268. 'finished' => 'zdb_populate_finished',
  269. 'operations' => $operations,
  270. );
  271. zbatch_set($batch);
  272. zbatch_process();
  273. }
  274. } elseif ($m == 5) { # image from id3 tags
  275. $operations[] = array('zbatch_extract_images', array());
  276. $batch = array(
  277. 'title' => zt('Extracting images from id3 tags.'),
  278. 'finished_message' => zt('Images extracted successfully.'),
  279. 'operations' => $operations,
  280. 'finished' => 'zbatch_extract_images_finished',
  281. );
  282. zbatch_set($batch);
  283. zbatch_process();
  284. } else {
  285. $error = true;
  286. zina_set_message(zt('Invalid option'), 'error');
  287. }
  288. $e = error_get_last();
  289. if ($error || ($e['type'] < 2048 && !empty($e['message']))) {
  290. #todo: ? zunserialize throws error on older custom_files...
  291. if (!empty($e['message'])) zina_set_message(zt('PHP returned an error[@type]: @message', array('@type'=>$e['type'], '@message'=>$e['message'])), 'error');
  292. } else {
  293. zina_set_message($message);
  294. }
  295. zina_goto('','l=20');
  296. break;
  297. Case 27 : # Find and Clean
  298. if ($zc['database']) {
  299. if ($_POST && !zina_token_sess_check()) return zina_page_main($path);
  300. if (!empty($_POST['zfileids'])) zdb_clean('file',$_POST['zfileids']);
  301. if (!empty($_POST['zdirids'])) zdb_clean('dir',$_POST['zdirids']);
  302. if ($_POST) {
  303. zina_set_message(zt('Database cleaned.'));
  304. zina_goto('', 'l=20');
  305. } else {
  306. return zina_page_main($path, 'clean');
  307. }
  308. }
  309. break;
  310. Case 33 : # DELETE SITEMAP
  311. $file = $zc['cache_dir_public_abs'].'/'.$zc['sitemap_file'];
  312. if (file_exists($file) && @unlink($file)) {
  313. zina_set_message(zt('Sitemap cached file deleted successfully'));
  314. } else {
  315. zina_set_message(zt('Sitemap cached file could not be deleted'),'warn');
  316. }
  317. zina_goto('', 'l=20');
  318. break;
  319. Case 30 :# DELETE TMPL CACHE
  320. Case 31 :# DELETE IMGS CACHE
  321. Case 34 :# DELETE ZIP CACHE
  322. $func = array(
  323. '30'=> array(
  324. 'dir' => $zc['cache_tmpl_dir'],
  325. 'text' => zt('Template cache files deleted.'),
  326. ),
  327. '31'=> array(
  328. 'dir' => $zc['cache_imgs_dir'],
  329. 'text' => zt('Images cache files deleted.'),
  330. ),
  331. '34'=> array(
  332. 'dir' => $zc['cache_zip_dir'],
  333. 'text' => zt('Compressed cache files deleted.'),
  334. ),
  335. );
  336. if (zina_delete_files($func[$level]['dir'])) {
  337. zina_set_message($func[$level]['text']);
  338. }
  339. zina_goto('', 'l=20');
  340. break;
  341. Case 32 : #get language phrases for translation
  342. $files = array('index.php', 'theme.php', 'database.php', 'lang-cfg.php');
  343. $source = '';
  344. foreach($files as $file) {
  345. $source .= file_get_contents($zc['zina_dir_abs'].'/'.$file);
  346. }
  347. if (preg_match_all("/zt\('(.*?)'(\)|,)/is", $source, $matches)) {
  348. $reduced = array_unique($matches[1]);
  349. $instr = array(
  350. zt('These are most of the translation strings currently in Zina.'),
  351. zt('Save this file to LANGCODE.php and modify it.'),
  352. zt('Format: \'english words\' => \'your translation\'')."\n *",
  353. zt('You do not have to do them all (just delete the lines you do not do).'),
  354. zt('If you are making a new translation or completing an older one, move the file to the "lang" directory.'),
  355. zt('If languages.txt file exists in your cache directory, delete it.'),
  356. zt('Or a copy in your theme folder will override the default language file.'),
  357. zt('English users can change wording/phrasings this way.')."\n *",
  358. zt('Test it out.')."\n *",
  359. zt('If you would like it to be included in Zina, please email it: to: <@email>', array('@email'=>'ryanlath@pacbell.net')),
  360. );
  361. $text = '<?php'."\n".
  362. "/*\n * ".zt('Zina Translation Instructions')."\n *\n";
  363. foreach($instr as $i) {
  364. $text .= ' * '.$i."\n";
  365. }
  366. $lang = zina_get_languages();
  367. $language = (isset($lang[$zc['lang']])) ? $lang[$zc['lang']] : zt('Language');
  368. $text .= " */\n\n".'$language = "'.$language.'";'."\n\n";
  369. $text .= '$lang[\''.$zc['lang'].'\'] = array('."\n";
  370. foreach ($reduced as $en) {
  371. $text .= "\t'".$en."' => '";
  372. if ($zc['lang'] != 'en') {
  373. $trans = zt($en);
  374. if ($trans != $en) {
  375. $text .= $trans;
  376. }
  377. }
  378. $text .= "',\n";
  379. }
  380. $text .= ");\n?>";
  381. while(@ob_end_clean());
  382. header('Content-type: text/plain');
  383. if (!$zc['debug']) header('Content-Disposition: attachment; filename="'.$zc['lang'].'.php"');
  384. echo $text;
  385. exit;
  386. } else {
  387. zina_set_message(zt('Nothing Found'),'error');
  388. zina_goto('', 'l=20');
  389. }
  390. break;
  391. Case 42 : # Add Custom Playlist Title
  392. if (!zina_token_sess_check()) return zina_page_main($path);
  393. zina_write_playlist($songs, str_replace('/',' - ',$path).'.m3u', 't');
  394. if ($zc['cache_tmpl']) {
  395. if (!zina_delete_tmpl_file(zina_get_tmpl_cache_file($path)))
  396. zina_debug(zt('Could not delete cache file'));
  397. }
  398. zina_goto($_SERVER['HTTP_REFERER']);
  399. break;
  400. Case 45 : # sync database to mp3 files...
  401. $files_assoc = zina_core_cache('files_assoc', $path);
  402. if (isset($files_assoc[$path])) {
  403. $files = $files_assoc[$path];
  404. foreach($files as $file) {
  405. zdb_log_stat('insertonly', $path, $file, null, true, true);
  406. }
  407. } else {
  408. zdb_log_stat('insertonly', $path, null, null, true, true);
  409. }
  410. zina_goto($path);
  411. break;
  412. Case 47 : # regen statistics
  413. if ($zc['database']) {
  414. zdb_stats_generate(time());
  415. zina_goto('', 'l=20');
  416. }
  417. break;
  418. Case 48 :
  419. if ($zc['genres'] && $zc['database']) {
  420. return zina_page_main($path, 'genre_hierarchy');
  421. }
  422. break;
  423. Case 49 :
  424. if ($zc['genres'] && $zc['database']) {
  425. if (!zina_token_sess_check()) return zina_page_main($path);
  426. zdb_genres_save($_POST);
  427. #todo: check for errors?
  428. zina_set_message(zt('Genre hierarchy saved.'));
  429. zina_goto('', 'l=48');
  430. }
  431. break;
  432. Case 52 :
  433. if ($zc['genres'] && $zc['database']) {
  434. if (zina_validate('int',$m)) {
  435. if (zdb_genre_delete($m)) zina_set_message(zt('Genre deleted.'));
  436. }
  437. zina_goto('', 'l=48');
  438. }
  439. break;
  440. Case 58 :
  441. return zina_page_main($path, 'edit_images');
  442. break;
  443. Case 59 : # ajax return images
  444. @session_write_close();
  445. if (!$zc['debug']) while(@ob_end_clean());
  446. echo zina_content_3rd_images($path, $m);
  447. exit;
  448. break;
  449. Case 60 : # Delete Image
  450. $file = $zc['mp3_dir'] .'/'.$path;
  451. $result = zt('Could not delete file.');
  452. if (preg_match('/\.('.$zc['ext_graphic'].')$/i', $path) && file_exists($file)) {
  453. if (@unlink($file)) {
  454. $result = zt('Deleted: @file', array('@file'=>$file));
  455. $other = zdb_get_others($path);
  456. if (isset($other['image']) && $other['image'] == basename($path)) {
  457. $image = zina_get_dir_item(dirname($path),'/\.('.$zc['ext_graphic'].')$/i');
  458. zdb_update_others(array('image'=>$image), dirname($path));
  459. }
  460. }
  461. }
  462. echo $result;
  463. exit;
  464. break;
  465. Case 61 : # Save Image
  466. $result = zt('Failed');
  467. if (is_writeable($zc['cur_dir'])) {
  468. if (($image = file_get_contents($imgsrc)) !== false) {
  469. $filename = $zc['cur_dir'].'/'.basename($imgsrc);
  470. $i=1;
  471. while (file_exists($filename)) {
  472. $filename = $zc['cur_dir'].'/copy'.$i.'_'.basename($imgsrc);
  473. }
  474. if (file_put_contents($filename, $image)) {
  475. $result = zt('Image Saved: @src -> @dest', array('@src'=> $imgsrc, '@dest' => $filename));
  476. if (isset($_SESSION['zina_missing'][$path])) unset($_SESSION['zina_missing'][$path]);
  477. }
  478. }
  479. }
  480. if (!$zc['debug']) while(@ob_end_clean());
  481. echo $result;
  482. exit;
  483. break;
  484. Case 62 : # Find album art
  485. $missing = zina_search_dirs_for_missing_images();
  486. if (!empty($missing)) {
  487. $_SESSION['zina_missing'] = $missing;
  488. zina_goto(current($missing),'l=58');
  489. } else {
  490. zina_set_message(zt('No missing artist/album artwork.'));
  491. unset($_SESSION['zina_missing']);
  492. zina_goto('', 'l=20');
  493. }
  494. exit;
  495. break;
  496. Case 63 : # Close Album Art
  497. unset($_SESSION['zina_missing']);
  498. zina_goto($path);
  499. break;
  500. Case 64 :
  501. return zina_page_main('', 'help');
  502. break;
  503. Case 67 : # import textfile playlists into database...
  504. #remove in 3.0 / make part of upgrade
  505. if ($zc['database']) {
  506. $playlists = zina_get_playlists_custom();
  507. if (empty($playlists)) {
  508. zina_set_message(zt('No playlists to convert'));
  509. zina_goto('', 'l=20');
  510. }
  511. foreach($playlists as $playlist) {
  512. $filename = $zc['cache_pls_dir'].'/_zina_'.$playlist.'.m3u';
  513. if (file_exists($filename)) {
  514. $pls_id = zdbq_single("SELECT id FROM {playlists} WHERE title = '%s' AND user_id = %d", array($playlist, $zc['user_id']));
  515. if (!empty($pls_id)) {
  516. zina_set_message(zt('Playlist already exists: @pls', array('@pls'=>$playlist)));
  517. continue;
  518. }
  519. $genre_id = null;
  520. $dir_id = zdbq_single("SELECT id FROM {dirs} WHERE path = '%s' AND level = 1", array($playlist));
  521. if ($dir_id) {
  522. $image_type = 1;
  523. } else {
  524. $dir_id = null;
  525. $image_type = 0;
  526. }
  527. $mtime = filemtime($filename);
  528. if (zdbq("INSERT {playlists} (title, user_id, dir_id, genre_id, image_type, date_created, mtime) VALUES ('%s', %d, %d, '%s', '%s', %d, %d)",
  529. array($playlist, $zc['user_id'], $dir_id, $genre_id, $image_type, $mtime, $mtime))) {
  530. $pls_id = zdbq_single("SELECT id FROM {playlists} WHERE title = '%s' AND user_id = %d", array($playlist, $zc['user_id']));
  531. if (!empty($pls_id)) {
  532. $songs = zunserialize_alt(file_get_contents($filename));
  533. zina_playlist_insert($pls_id, $songs, 1);
  534. }
  535. }
  536. } else {
  537. zina_set_message(zt('Cannot open playlist: @pls', array('@pls'=>$playlist)));
  538. }
  539. }
  540. zina_goto('', 'l=20');
  541. }
  542. break;
  543. Case 71 : # edit tags
  544. require_once($zc['zina_dir_abs'].'/extras/tag_editor.php');
  545. return zina_page_main($path, 'edittags');
  546. break;
  547. Case 72 : # tag search
  548. Case 73 : # tag search
  549. require_once($zc['zina_dir_abs'].'/extras/tag_editor.php');
  550. if ($level == 72) {
  551. if (($result = zina_extras_tags_freedb_matches(rawurldecode($playlist))) !== false) {
  552. echo $result;
  553. }
  554. } else {
  555. if (($result = zina_extras_tags_freedb_match($_GET['cat'], $_GET['discid'])) !== false) {
  556. echo $result;
  557. }
  558. }
  559. exit;
  560. break;
  561. Case 75 : # delete file
  562. if (($path = zina_delete_file($zc['cur_dir'])) !== false) {
  563. zina_set_message(zt('Deleted file: @file', array('@file'=>$zc['cur_dir'])));
  564. }
  565. zina_goto($path);
  566. break;
  567. Case 76 : # delete dir
  568. if (!zfile_check_location($zc['cur_dir'], $zc['mp3_dir']) || !is_dir($zc['cur_dir'])) {
  569. zina_set_message(zt('Directory does not exist: @dir', array('@dir'=>$zc['cur_dir'])));
  570. zina_goto('');
  571. }
  572. $dir = zina_get_directory($path);
  573. if (!empty($dir['subdirs'])) {
  574. zina_set_message(zt('Cannot delete directory. Directory has subdirectories.'));
  575. zina_goto($path);
  576. }
  577. if (!empty($dir['files'])) {
  578. foreach($dir['files'] as $file => $xxx) {
  579. if (zina_delete_file($zc['mp3_dir'].'/'.$file)) zina_set_message(zt('Deleted file: @file', array('@file'=>$file)));
  580. }
  581. }
  582. if (zina_delete_directory($zc['cur_dir'])) {
  583. if ($zc['database']) {
  584. $id = zdbq_single("SELECT id FROM {dirs} WHERE path = '%s'", array($path));
  585. if (!empty($id)) zdb_remove('dir', $id);
  586. }
  587. } else {
  588. zina_set_message(zt('Cannot delete directory: @dir', array('@dir'=>$path)), 'error');
  589. }
  590. if (($pos = strrpos($path, '/')) == 0) {
  591. $path = '';
  592. } else {
  593. $path = substr($path, 0, $pos);
  594. }
  595. zina_goto($path);
  596. break;
  597. Case 78 :
  598. if ($path != '') return zina_page_main($path, 'rename_directory');
  599. break;
  600. } # end admin switch
  601. return zina_not_found();
  602. } elseif (in_array($level, array(3,5,6,7,8,10,11,12,16,17,25,53,54,56,57,66,68,70,74))) {
  603. # STREAM FUNCTIONS
  604. switch ($level) {
  605. Case 3 :
  606. if ($zc['cmp_sel']) {
  607. zina_send_zip_selected($songs, (isset($_GET['lf'])));
  608. }
  609. break;
  610. Case 5 :
  611. if ($zc['cmp_sel']) {
  612. zina_send_zip_selected_dir($path, (isset($_GET['c'])), (isset($_GET['lf'])));
  613. }
  614. break;
  615. Case 6 : # Return resampled MP3
  616. if ($zc['resample']) {
  617. if ($zc['database'] && $zc['stats']) zdb_log_stat('play', dirname($path), basename($path));
  618. zina_send_file_music($path, true);
  619. }
  620. break;
  621. Case 7 : # return resized image
  622. $type = isset($_GET['it']) ? $_GET['it'] : null;
  623. if (in_array($type, array('sub','dir','full','search','genre','genresearch','pls','plssearch'))) {
  624. $cache_file = $string = false;
  625. $text = null;
  626. if (empty($imgsrc)) {
  627. if ($type == 'genresearch' || $type == 'plssearch') $type = 'search';
  628. $tmp = $zc['theme_path_abs'].'/images';
  629. $imgsrc = ztheme('missing_image',$type);
  630. $text = ztheme('title',basename($path));
  631. } else {
  632. $res_out_type = ($zc['res_out_type'] == 'jpeg') ? 'jpg' : $zc['res_out_type'];
  633. if ($type == 'genre' || $type == 'genresearch') {
  634. if ($type == 'genresearch') $type = 'search';
  635. $tmp = $zc['theme_path_abs'].'/images';
  636. $genre_file = ztheme('image_genre', $imgsrc);
  637. if (file_exists($tmp.'/'.$genre_file)) {
  638. $imgsrc = $genre_file;
  639. } else {
  640. $text = strtoupper($imgsrc);
  641. $imgsrc = ztheme('missing_image','genre');
  642. }
  643. $cache_file = $zc['cache_imgs_dir'].'/'.$type.md5($tmp.'/'.$genre_file).'.'.$res_out_type;
  644. } elseif ($type == 'pls' || $type == 'plssearch') {
  645. $tmp = $zc['theme_path_abs'].'/images';
  646. $text = strtoupper($imgsrc);
  647. $imgsrc = ztheme('missing_image','playlist');
  648. $type = ($type == 'pls') ? 'sub' : 'search';
  649. #$cache_file = $zc['cache_imgs_dir'].'/'.$type.md5($tmp.'/'.$genre_file).'.'.$res_out_type;
  650. } elseif ($imgsrc == 'zina_id3_zina.jpg') {
  651. $subdir_file = zina_get_dir_item($zc['mp3_dir'].'/'.$path,'/\.('.$zc['ext_mus'].')$/i');
  652. $tmp = $zc['mp3_dir'].'/'.$path;
  653. if (!empty($subdir_file)) {
  654. $info = zina_get_file_info($zc['mp3_dir'].'/'.$path.'/'.$subdir_file, false, true, false, true);
  655. if (isset($info->image)) {
  656. $string = $info->image;
  657. $cache_file = $zc['cache_imgs_dir'].'/'.$type.md5($zc['mp3_dir'].'/'.$path.'/'.$imgsrc).'.'.$res_out_type;
  658. }
  659. }
  660. } else {
  661. $tmp = $zc['mp3_dir'].'/'.$path;
  662. $cache_file = $zc['cache_imgs_dir'].'/'.$type.md5($zc['mp3_dir'].'/'.$path.'/'.$imgsrc).'.'.$res_out_type;
  663. }
  664. if ($zc['cache_imgs'] && $cache_file) {
  665. if (file_exists($cache_file)) {
  666. while(@ob_end_clean());
  667. Header('Content-type: image/'.$zc['res_out_type']);
  668. readfile($cache_file);
  669. exit;
  670. }
  671. }
  672. }
  673. $image_source = $tmp.'/'.$imgsrc;
  674. if (!file_exists($image_source) && !$string) {
  675. $image_source = $zc['theme_path_abs'].'/images/'.ztheme('missing_image',$type);
  676. $text = zt('Error');
  677. $cache_file = $string = false;
  678. }
  679. zina_send_image_resized($image_source, $type, $text, $cache_file, $string);
  680. }
  681. break;
  682. Case 11 : # return img
  683. if ($zc['stream_int'] && preg_match('/\.('.$zc['ext_graphic'].')$/i', $imgsrc)) {
  684. $file = $zc['mp3_dir'].'/'.((!empty($path)) ? $path.'/' : '').$imgsrc;
  685. if (file_exists($file)) {
  686. @ob_end_clean();
  687. readfile($file);
  688. }
  689. }
  690. break;
  691. Case 8 : # RETURN PLAYLISTS
  692. if ($zc['play']) {
  693. if (!isset($m)) $m = isset($_POST['m']) ? $_POST['m'] : null;
  694. $lofi = (isset($_GET['lf']));
  695. $cus = (isset($_GET['c']));
  696. $num = isset($_POST['n']) ? $_POST['n'] : (isset($_GET['n']) ? $_GET['n'] : null);
  697. if (!in_array($num, $zc['ran_opts'])) $num = $zc['ran_opts_def'];
  698. if ($playlist == null && isset($_GET['playlist'])) $playlist = $_GET['playlist'];
  699. $random = (isset($_GET['rand']));
  700. $store = (isset($_GET['store']));
  701. switch($m) {
  702. Case 0 :
  703. zina_send_playlist_title($path, $cus, $lofi);
  704. break;
  705. Case 1 :
  706. zina_send_playlist_song($path, $lofi);
  707. break;
  708. Case 3 :
  709. zina_send_playlist_custom($playlist, $lofi, $random);
  710. break;
  711. Case 4 : # Random Albums
  712. zina_send_playlist_random($num,'t',$lofi, true, null, $playlist);
  713. break;
  714. Case 5 : # Random Songs
  715. zina_send_playlist_random($num,'s',$lofi, true, null, $playlist);
  716. break;
  717. Case 6 : # Random Songs By Year
  718. zina_send_playlist_random($num,'s',$lofi, true, null, null, $playlist);
  719. break;
  720. Case 7 :
  721. zina_send_playlist_selected($songs, $lofi, $store);
  722. break;
  723. Case 8 :
  724. zina_send_playlist_selected_random($songs, $lofi, $store);
  725. break;
  726. Case 10 : # Play Recursively & Recursively Random ($cus = random)
  727. zina_send_playlist_random(0,'s',$lofi,$cus,$path);
  728. break;
  729. Case 11 : # Random Songs via Rated Songs
  730. zina_send_playlist_random($num,'tt',$lofi, true, null, $playlist);
  731. break;
  732. Case 12 : # Random Songs via Rated Artists
  733. zina_send_playlist_random($num,'artist',$lofi, true, null, $playlist);
  734. break;
  735. }
  736. }
  737. break;
  738. Case 10 : # internal streaming
  739. if ($zc['play']) {
  740. if ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $path)) {
  741. $rem = new remoteFile($zc['mp3_dir'].'/'.$path, false, true);
  742. if (isset($rem->url)) {
  743. if ($zc['database'] && $zc['stats']) zdb_log_stat('play', dirname($path), basename($path));
  744. while(@ob_end_clean());
  745. header('Location: '.$rem->url);
  746. exit;
  747. }
  748. } elseif ($zc['play'] && $zc['stream_int']) {
  749. if ($zc['database'] && $zc['stats']) zdb_log_stat('play', dirname($path), basename($path));
  750. zina_send_file_music($path);
  751. }
  752. }
  753. break;
  754. Case 12 : # download mp3
  755. if ($zc['download'] && preg_match('/\.('.$zc['ext_mus'].')$/i', $path, $exts)) {
  756. $file = $zc['mp3_dir'].'/'.$path;
  757. if (file_exists($file)) {
  758. if ($zc['database'] && $zc['stats']) zdb_log_stat('down', dirname($path), basename($path));
  759. if ($zc['stream_int']) {
  760. $filename = html_entity_decode(zina_get_file_artist_title($file, $zc['mp3_id3'])).'.'.$exts[1];
  761. zina_set_header('Content-Type: application/force-download');
  762. zina_set_header('Content-Disposition: inline; filename="'.$filename.'"');
  763. zina_set_header('Content-Length: '.filesize($file));
  764. zina_set_header('Cache-control: private'); #IE seems to need this.
  765. zina_send_file($file);
  766. } else {
  767. zina_goto($path,NULL,NULL,TRUE,TRUE);
  768. }
  769. }
  770. }
  771. break;
  772. Case 16 : # VOTE
  773. if ($zc['database']) {
  774. $num = isset($_POST['n']) ? $_POST['n'] : (isset($_GET['n']) ? $_GET['n'] : null);
  775. if (zina_validate('int',$num) && $num <= 5 && ($num >= 1 || ($zc['user_id'] > 0 && $num == 0))) {
  776. if (preg_match('/\.('.$zc['ext_mus'].')$/i', $path) || ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $path))) {
  777. if ($zc['rating_files']) zdb_log_stat('vote',dirname($path), basename($path), $num);
  778. $path = dirname($path);
  779. } else {
  780. if ($zc['rating_dirs']) zdb_log_stat('vote',$path, null, $num);
  781. }
  782. if ($zc['cache_tmpl']) {
  783. if (!zina_delete_tmpl_file(zina_get_tmpl_cache_file($path))) zina_debug(zt('Cannot delete cache file'));
  784. }
  785. #todo: return 'error' on bad result
  786. echo ($num == 0) ? zt('Deleted') : zt('Thank you');
  787. }
  788. }
  789. break;
  790. Case 68 : # Vote Playlists
  791. if ($zc['database'] && $zc['pls_ratings']) {
  792. $num = isset($_POST['n']) ? $_POST['n'] : (isset($_GET['n']) ? $_GET['n'] : null);
  793. if (zina_validate('int',$num) && $num <= 5 && ($num >= 1 || ($zc['user_id'] > 0 && $num == 0))) {
  794. zdb_log_stat_playlist((int)$playlist, 'votes', $num);
  795. #todo: return 'error' on bad result
  796. echo ($num == 0) ? zt('Deleted') : zt('Thank you');
  797. }
  798. }
  799. break;
  800. Case 25 : # download MM
  801. if ($zc['mm'] && $zc['mm_down'] && preg_match('/\.('.$zc['mm_ext'].')$/i', $path, $exts)) {
  802. $file = $zc['mp3_dir'].'/'.$path;
  803. if (file_exists($file)) {
  804. if ($zc['stream_int']) {
  805. $ext = strtolower($exts[1]);
  806. zina_set_header('Content-Type: '.$zc['mm_types'][$ext]['mime']);
  807. $disposition = (isset($zc['mm_types'][$ext]['disposition'])) ? $zc['mm_types'][$ext]['disposition'] : 'attachment';
  808. zina_set_header('Content-Disposition: '.$disposition.'; filename="'.basename($path).'"');
  809. zina_set_header('Content-Length: '.filesize($file));
  810. zina_set_header('Cache-control: private'); #IE seems to need this.
  811. zina_send_file($file);
  812. } else {
  813. zina_goto($path,NULL,NULL,TRUE,TRUE);
  814. }
  815. }
  816. }
  817. break;
  818. Case 53 : # LIVE SEARCH RETURN
  819. $search_term = (isset($_GET['zinaq'])) ? $_GET['zinaq'] : '';
  820. if (strlen($search_term) >= $zc['search_min_chars']) {
  821. $num = isset($_GET['limit']) ? $_GET['limit'] : $zc['search_live_limit'];
  822. $num = (zina_validate('int', $num) && $num > 0 && $num < $zc['search_live_limit']) ? $num : $zc['search_live_limit'];
  823. if ($zc['db_search']) {
  824. $results = zdbq_array("SELECT i.title, i.type, i.context, i.id, i.path, i.genre ".
  825. ",if(i.type='playlist', p.image_type, FALSE) as image_type ".
  826. ",if(i.type='playlist', pd.path, FALSE) as image_path ".
  827. "FROM {search_index} AS i ".
  828. "LEFT OUTER JOIN {playlists} AS p ON (i.type = 'playlist' AND i.type_id = p.id) ".
  829. "LEFT OUTER JOIN {dirs} AS pd ON (i.type = 'playlist' AND i.type_id = p.id AND p.dir_id = pd.id) ".
  830. "WHERE i.title LIKE '%%%s%%' ".
  831. "ORDER BY i.title LIMIT %d",
  832. array($search_term, $num));
  833. } else {
  834. $results = zina_search_cache($search_term, $num);
  835. }
  836. if (!empty($results)) {
  837. if ($zc['search_images']) {
  838. foreach ($results as $key => $item) {
  839. $results[$key]['image'] = zina_content_search_image($item, 'search');
  840. }
  841. }
  842. foreach ($results as $item) {
  843. unset($item['image_type']);
  844. unset($item['image_path']);
  845. $item['type'] = zt(ucfirst($item['type']));
  846. echo implode('|', $item)."\n";
  847. }
  848. }
  849. }
  850. exit;
  851. break;
  852. Case 54 : # XML file info for flash app
  853. if ($zc['zinamp']) {
  854. $output = zina_get_file_xml($path);
  855. while(@ob_end_clean());
  856. header('Content-type: application/xml');
  857. echo $output;
  858. }
  859. break;
  860. Case 56 :
  861. if ($zc['zinamp'] && $zc['lastfm'] && isset($_GET['n'])) {
  862. zina_play_complete($path, intval($_GET['n']));
  863. }
  864. break;
  865. Case 57 : # 3rd party lyrics
  866. if ($zc['song_extras'] && in_array($m, $zc['song_es_exts'])) {
  867. @session_write_close();
  868. if ($zc['zinamp'] && $playlist == 'zinamp') {
  869. $content = zina_content_blurb($zina, $path, array('type'=>$m, 'return'=>true));
  870. if (isset($content['output']) && !empty($content['output'])) {
  871. if (!$zc['debug']) @ob_end_clean();
  872. echo nl2br($content['output']);
  873. exit;
  874. }
  875. }
  876. if (isset($zc['third_'.$m]) && $zc['third_'.$m]) {
  877. $info = array();
  878. zina_get_file_artist_title($zc['mp3_dir'].'/'.$path, true, $info);
  879. $lyr_opts = zina_get_extras_opts($m);
  880. $opts = explode(',', $zc['third_lyr_order']);
  881. $output = '';
  882. if (!empty($info['artist']) && !empty($info['title'])) {
  883. foreach($opts as $source) {
  884. if (!in_array($source, $lyr_opts)) continue;
  885. require_once($zc['zina_dir_abs'].'/extras/extras_'.$m.'_'.$source.'.php');
  886. $result = array();
  887. if (($result = call_user_func('zina_extras_'.$m.'_'.$source, $info['artist'], $info['title'])) !== false) {
  888. $output .= $result['output'];
  889. if ($zc['third_'.$m.'_save']) {
  890. zina_save_blurb($path, $m, $output, null, false);
  891. }
  892. $output = nl2br($output);
  893. if (isset($result['source'])) $output .= ztheme('extras_source', $result['source']);
  894. break;
  895. }
  896. }
  897. }
  898. if (empty($output)) $output .= zt('No @type found.', array('@type'=>$zc['song_es'][$m]['name']));
  899. if (!$zc['debug']) while(@ob_end_clean());
  900. echo $output;
  901. }
  902. }
  903. break;
  904. Case 66 :
  905. if ($zc['zinamp'] && $zc['lastfm']) {
  906. zina_zinamp_start($path);
  907. }
  908. break;
  909. Case 70 :
  910. if ($zc['playlists'] && $zc['database'] && zina_validate('int',$playlist)) {
  911. zina_playlist_feed($playlist);
  912. }
  913. break;
  914. Case 74:
  915. if (isset($_SESSION['zina_store'])) {
  916. $store = $_SESSION['zina_store'];
  917. unset($_SESSION['zina_store']);
  918. if (!empty($store)) {
  919. zina_send_playlist_content($store['type'], $store['content']);
  920. }
  921. }
  922. break;
  923. }
  924. exit;
  925. } else {
  926. # PAGE DISPLAYS (2,4,9,13,14,15,22,23,24,29,40,41,43,44,50,51,55,69,77,99)
  927. switch ($level) {
  928. Case 2 :
  929. if ($zc['playlists']) return zina_page_main($path, 'playlists', array('pl'=>$playlist, 'id'=>$m));
  930. break;
  931. Case 4 : # SEARCH
  932. if ($zc['search']) return zina_page_main($path, 'search', array('m'=>$m));
  933. break;
  934. Case 9 : # LOGIN
  935. if ($zc['login']) {
  936. if (isset($_POST['un']) && isset($_POST['up'])) {
  937. if (zina_check_password($_POST['un'], $_POST['up'])) {
  938. $_SESSION['za-'.ZINA_VERSION] = true;
  939. if ($zc['session']) { // standalone only
  940. $sess_id = zina_token_sess('1');
  941. setcookie('ZINA_SESSION', $sess_id, time() + (60*60*$zc['session_lifetime']), '/');
  942. $sess_file = $zc['cache_dir_private_abs'].'/sess_'.$sess_id;
  943. @touch($sess_file);
  944. }
  945. zina_goto($path);
  946. } else {
  947. sleep(3);
  948. $_SESSION['za-'.ZINA_VERSION] = false;
  949. zina_set_message(zt('Username and/or password are incorrect.'),'warn');
  950. }
  951. }
  952. return zina_page_main($path, 'login');
  953. }
  954. break;
  955. Case 13 : # Genre Listing
  956. if ($zc['genres']) return zina_page_main($path, 'searchgenre');
  957. break;
  958. Case 14 : # Genres
  959. if ($zc['genres']) return zina_page_main($path, 'genres');
  960. break;
  961. Case 15 : # STATS
  962. if ($zc['database'] && $zc['stats'] && ($zc['stats_public'] || $zc['is_admin'])) {
  963. $period = isset($_POST['period']) ? $_POST['period'] : null;
  964. $type = isset($_POST['type']) ? $_POST['type'] : null;
  965. return zina_page_main($path, 'stats', array('stat'=>$playlist, 'period'=>$period, 'type'=>$type));
  966. }
  967. break;
  968. Case 22 : # VARIOUS EDIT WINDOWS
  969. if ($zc['is_admin'] || (zina_cms_access('editor') && (in_array($m, array(1,2,3,4,6)) || in_array($m, $zc['song_es_exts'])))) {
  970. return zina_page_main($path, 'blurb', array('type'=>$m, 'item'=>$playlist));
  971. } else {
  972. return zina_access_denied();
  973. }
  974. break;
  975. Case 23 : # VARIOUS EDIT WINDOWS SAVE
  976. if (!zina_token_sess_check()) return zina_page_main($path);
  977. if ($zc['is_admin'] || (zina_cms_access('editor') && (in_array($m, array(1,2,3,4,6)) || in_array($m, $zc['song_es_exts'])))) {
  978. zina_save_blurb($path, $m, $songs, $playlist);
  979. } else {
  980. return zina_access_denied();
  981. }
  982. break;
  983. Case 77 :
  984. if ($zc['is_admin'] || (zina_cms_access('editor'))) {
  985. if (isset($_POST) && !empty($_POST) && !zina_token_sess_check()) return zina_access_denied();
  986. return zina_page_main($path, 'dir_opts');
  987. } else {
  988. return zina_access_denied();
  989. }
  990. break;
  991. Case 24 : # PLAY MM
  992. if ($zc['mm']) return zina_page_main($path, 'mm');
  993. break;
  994. Case 29 :# Song Extras
  995. if ($zc['song_extras'] && in_array($m, $zc['song_es_exts'])) {
  996. return zina_page_main($path, 'songextras', array('type'=>$m, 'item'=>null));
  997. }
  998. break;
  999. Case 40 : # Add New Playlist && Add To Playlist
  1000. if (!zina_token_sess_check()) return zina_page_main($path);
  1001. if ($zc['database']) {
  1002. $access = zina_cms_access('edit_playlists', $zc['user_id']);
  1003. if (!($access || ($zc['session_pls'] && $playlist == 'zina_session_playlist'))) {
  1004. zina_set_message(zt('Not authorized'));
  1005. return zina_page_main($path);
  1006. }
  1007. if ($access && $playlist == 'new_zina_list') {
  1008. if (!$zc['is_admin']) {
  1009. $count = zdbq_single("SELECT COUNT(*) FROM {playlists} WHERE user_id = %d", array($zc['user_id']));
  1010. if ($count > $zc['pls_limit']) {
  1011. zina_set_message(zt('Cannot create playlist.').' '.zt('Maximum number of playlists reached.'));
  1012. return zina_page_main($path);
  1013. }
  1014. }
  1015. return zina_page_main($path, 'newplaylist',array('songs'=>$songs));
  1016. } else {
  1017. if (isset($_POST['fromnew'])) {
  1018. if (($pls_id = zina_playlist_form_submit('insert')) !== false) {
  1019. $playlist = $pls_id;
  1020. $start = 1;
  1021. } else {
  1022. $start = false;
  1023. }
  1024. } else {
  1025. if ($playlist == 'zina_session_playlist') {
  1026. $existing = (isset($_SESSION['z_sp'])) ? unserialize_utf8($_SESSION['z_sp']) : array();
  1027. $start = count($existing);
  1028. } else {
  1029. $start = zdbq_single("SELECT MAX(weight) FROM {playlists_map} WHERE playlist_id = %d", array($playlist, $zc['user_id']));
  1030. }
  1031. }
  1032. if ($start !== false) {
  1033. if (zina_playlist_insert($playlist, $songs, $start+1)) {
  1034. zina_set_message(zt('Added to playlist'));
  1035. } else {
  1036. zina_set_message(zt('Could not add to playlist'), 'warn');
  1037. }
  1038. }
  1039. if (isset($_POST['fromnew'])) {
  1040. if (empty($path)) {
  1041. zina_goto('','l=2&pl='.rawurlencode($playlist));
  1042. } else {
  1043. return zina_page_main($path);
  1044. }
  1045. } else {
  1046. echo ztheme('messages');
  1047. exit;
  1048. }
  1049. }
  1050. } elseif ($zc['is_admin'] || $zc['session_pls']) {
  1051. if (!$zc['is_admin']) $playlist = 'zina_session_playlist';
  1052. if ($playlist == 'new_zina_list') {
  1053. return zina_page_main($path, 'newplaylist',array('songs'=>$songs));
  1054. } else {
  1055. zina_write_playlist($songs, '_zina_'.$playlist.'.m3u', 'a');
  1056. zina_set_message(zt('Added to playlist'));
  1057. if (isset($_POST['fromnew'])) {
  1058. if (empty($path)) {
  1059. zina_goto('','l=2&pl='.rawurlencode($playlist));
  1060. } else {
  1061. return zina_page_main($path);
  1062. }
  1063. } else {
  1064. echo ztheme('messages');
  1065. exit;
  1066. }
  1067. }
  1068. }
  1069. break;
  1070. Case 41 : # Update Playlist
  1071. if (!zina_token_sess_check()) return zina_page_main($path);
  1072. $order = isset($_POST['order']) ? $_POST['order'] : null;
  1073. if ($zc['database']) {
  1074. $pls_user_id = zdbq_single("SELECT user_id FROM {playlists} WHERE id = %d", array($playlist));
  1075. $access = zina_cms_access('edit_playlists', $pls_user_id);
  1076. if (!($access || ($zc['session_pls'] && $playlist == 'zina_session_playlist'))) {
  1077. zina_set_message(zt('Not authorized'));
  1078. return zina_page_main($path);
  1079. }
  1080. $songs = zina_reorder_playlist($songs, $order);
  1081. if ($playlist == 'zina_session_playlist') {
  1082. $_SESSION['z_sp'] = utf8_encode(serialize($songs));
  1083. } else {
  1084. zdbq("DELETE FROM {playlists_map} WHERE playlist_id = %d", array($playlist));
  1085. foreach($songs as $weight => $type_id) {
  1086. if (preg_match('/\.lp$/i', $type_id)) {
  1087. $type = 'album';
  1088. $type_id = preg_replace('/\/\.lp$/i','',$type_id);
  1089. } elseif (preg_match('/\.pls$/i', $type_id)) {
  1090. $type = 'playlist';
  1091. $type_id = preg_replace('/\.pls/i','',$type_id);
  1092. } else {
  1093. $type = 'song';
  1094. }
  1095. if (!zdbq("INSERT {playlists_map} (playlist_id, type, type_id, weight) VALUES (%d, '%s', %d, %d)",
  1096. array($playlist, $type, $type_id, $weight+1))) {
  1097. zina_set_message(zt('Could not insert into playlist: @file', array('@file'=>$type_id)));
  1098. }
  1099. }
  1100. if (($sum_items = zdbq_single("SELECT COUNT(*) FROM {playlists_map} WHERE playlist_id = %d", array($playlist))) !== false) {
  1101. zdbq("UPDATE {playlists} SET sum_items = %d WHERE id = $playlist", array($sum_items, $playlist));
  1102. }
  1103. }
  1104. return zina_page_main($path, 'playlists',array('pl'=>$playlist));
  1105. } elseif ($zc['is_admin'] || $zc['session_pls']) {
  1106. if (!$zc['is_admin']) $playlist = 'zina_session_playlist';
  1107. zina_write_playlist(zina_reorder_playlist($songs, $order), '_zina_'.$playlist.'.m3u');
  1108. return zina_page_main($path, 'playlists',array('pl'=>$playlist));
  1109. }
  1110. break;
  1111. Case 43 : # DELETE CUSTOM PLAYLIST
  1112. if ($zc['database'] && $playlist != 'zina_session_playlist') {
  1113. if ($zc['is_admin'] || $zc['pls_user']) {
  1114. if ($zc['is_admin']) {
  1115. $access = true;
  1116. } else {
  1117. $access = zdbq_single("SELECT 1 FROM {playlists} WHERE id = %d AND user_id = %d", array($playlist, $zc['user_id']));
  1118. }
  1119. if ($access) {
  1120. zdbq("DELETE FROM {playlists_map} WHERE playlist_id = %d", array($playlist));
  1121. zdbq("DELETE FROM {playlists} WHERE id = %d", array($playlist));
  1122. zina_set_message(zt('Playlist deleted'));
  1123. zina_goto('','l=2');
  1124. }
  1125. }
  1126. } else {
  1127. if ($zc['is_admin'] || $zc['session_pls']) {
  1128. if (!$zc['is_admin']) $playlist = 'zina_session_playlist';
  1129. zina_delete_playlist_custom($playlist);
  1130. zina_goto('','l=2');
  1131. }
  1132. }
  1133. break;
  1134. Case 44 : # EDIT PLAYLIST
  1135. if ($_POST && !zina_token_sess_check()) return zina_page_main($path);
  1136. if (!($zc['playlists'] && ($zc['is_admin'] || ($zc['pls_user'] && $zc['user_id'] > 0)))) return zina_access_denied();
  1137. $playlist_new = isset($_POST['playlist_new']) ? $_POST['playlist_new'] : '';
  1138. return zina_page_main($path, 'renameplaylist', array('playlist'=>$playlist, 'new'=>$playlist_new));
  1139. break;
  1140. case 46 :
  1141. if ($zc['res_full_img'] && preg_match('/\.('.$zc['ext_graphic'].')$/i', $path)) {
  1142. return zina_page_main($path, 'image');
  1143. }
  1144. break;
  1145. Case 50 : #podcast
  1146. if ($zc['rss']) {
  1147. #TODO: make common output function...
  1148. while(@ob_end_clean());
  1149. header('Content-type: application/xml');
  1150. echo zina_content_rss($path);
  1151. exit;
  1152. }
  1153. break;
  1154. Case 51 : # SITEMAP
  1155. if ($zc['sitemap']) {
  1156. $output = zina_cache('sitemap', 'zina_content_sitemap', null, ($zc['sitemap'] == 2));
  1157. while(@ob_end_clean());
  1158. header('Content-type: text/xml');
  1159. echo $output;
  1160. exit;
  1161. }
  1162. break;
  1163. Case 99 : # logout
  1164. session_unregister('za-'.ZINA_VERSION);
  1165. if ($zc['session']) {
  1166. if (isset($_COOKIE['ZINA_SESSION'])) {
  1167. $sess_file = $zc['cache_dir_private_abs'].'/sess_'.zcheck_plain($_COOKIE['ZINA_SESSION']);
  1168. setcookie('ZINA_SESSION', $_COOKIE['ZINA_SESSION'], time() - 42000, '/');
  1169. if (file_exists($sess_file)) @unlink($sess_file);
  1170. }
  1171. # remove expired sessions
  1172. $old_sessions = glob($zc['cache_dir_private_abs']."/sess_*");
  1173. if (is_array($old_sessions)) {
  1174. foreach ($old_sessions as $filename) {
  1175. if (filemtime($filename) + (60*60*$zc['session_lifetime']) < time()) {
  1176. @unlink($filename);
  1177. }
  1178. }
  1179. }
  1180. }
  1181. zina_set_message(zt('Logged out succesfully.'));
  1182. zina_goto($path);
  1183. break;
  1184. case 55 :
  1185. #todo: move to stream?
  1186. if ($zc['zinamp'] == 2) {
  1187. $content = ztheme('zinamp');
  1188. zina_set_js('inline',
  1189. 'window.onunload = function() {'.
  1190. 'zina_cookie("zinamp_window", "screenX="+window.screenX+",screenY="+window.screenY, {expires:7});'.
  1191. '};');
  1192. $zina = zina_page_simple('zinamp', $content);
  1193. echo ztheme('page_zinamp', $zina);
  1194. exit;
  1195. }
  1196. break;
  1197. Case 65 :
  1198. require_once($zc['zina_dir_abs'].'/batch.php');
  1199. $output = _zbatch_page();
  1200. if ($output === FALSE) {
  1201. return zina_access_denied();
  1202. } elseif (isset($output)) {
  1203. zina_set_css('file', 'extras/progress.css');
  1204. return zina_page_simple(zbatch_set_title(), $output);
  1205. }
  1206. return;
  1207. Case 69 : # Year Listing
  1208. if ($zc['db_search']) return zina_page_main($path, 'searchyear');
  1209. break;
  1210. default : # MAIN PAGE
  1211. # Allows files to stream without l=8 (for RSS and prettiness)
  1212. if (is_file($zc['cur_dir']) && $zc['play'] && (($zc['stream_int'] && preg_match('/\.('.$zc['ext_mus'].')$/i', $path)) ||
  1213. ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $path, $matches)))) {
  1214. if ($zc['database'] && $zc['stats']) zdb_log_stat('play', dirname($path), basename($path));
  1215. zina_send_file_music($path);
  1216. }
  1217. if (is_file($zc['cur_dir']) && $zc['rss'] && basename($path) == $zc['rss_file']) {
  1218. $output = file_get_contents($zc['cur_dir']);
  1219. $output = utf8_decode($output);
  1220. header('Content-type: application/xml');
  1221. echo $output;
  1222. exit;
  1223. }
  1224. if (!is_dir($zc['cur_dir'])) return zina_not_found();
  1225. if ($zc['database']) zdb_log_stat('view', $path);
  1226. return zina_page_main($path);
  1227. }
  1228. return zina_not_found();
  1229. }
  1230. } #END MAIN
  1231. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1232. * PAGES
  1233. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1234. function zina_page_main($path, $type='main', $opts=null) {
  1235. global $zc;
  1236. $page = zina_get_page_opt($path);
  1237. $cat_sort = zina_get_catsort_opt($path);
  1238. if ($zc['cache_tmpl']) {
  1239. $cache_file = $zc['cache_tmpl_dir'].'/'.zina_get_tmpl_cache_file($path);
  1240. if (!$zc['is_admin'] && $_SERVER['REQUEST_METHOD'] == 'GET' && file_exists($cache_file)) {
  1241. $mtime = filemtime($cache_file);
  1242. if ($mtime > filemtime($zc['cur_dir'].'/.') && $mtime + ($zc['cache_tmpl_expire'] * 86400) > time()) {
  1243. $zina = unserialize(implode('', gzfile($cache_file)));
  1244. $zina['cached'] = true;
  1245. return $zina;
  1246. }
  1247. }
  1248. }
  1249. $zina = array();
  1250. $zina['lang']['main_dir_title'] = zt($zc['main_dir_title']);
  1251. $zina['embed'] = $zc['embed'];
  1252. $zina['site_name'] = isset($zc['conf']['site_name']) ? $zc['conf']['site_name'] : '';
  1253. $zina['amg'] = $zc['amg'];
  1254. $zina['theme_path'] = zpath_to_theme();
  1255. $zina['searchform'] = $zina['stats'] = $zina['genres'] = $random = '';
  1256. $zina['charset'] = $zc['charset'];
  1257. $zina['addthis'] = $zc['third_addthis'];
  1258. $zina['addthis_id'] = $zc['third_addthis_id'];
  1259. $zina['addthis_options'] = $zc['third_addthis_options'];
  1260. $zina['addthis_path'] = $path;
  1261. $zina['addthis_query'] = null;
  1262. if ($zc['search']) {
  1263. $search_term = isset($_POST['searchterm']) ? $_POST['searchterm'] : (isset($_GET['pl']) ? $_GET['pl'] : (isset($_GET['searchterm']) ? $_GET['searchterm'] : ''));
  1264. $zina['searchform'] = ztheme('searchform', array(
  1265. 'action' => zurl('','l=4'),
  1266. 'search_min_chars' => $zc['search_min_chars'],
  1267. 'search_live_limit' => $zc['search_live_limit'],
  1268. 'live_url' => zurl('', 'l=53'),
  1269. 'images' => $zc['search_images'],
  1270. ),
  1271. (($type == 'search') ? htmlentities($search_term) : '')
  1272. );
  1273. }
  1274. if ($zc['genres']) {
  1275. if ($type == 'genres' && $path = 'genre') $path = '';
  1276. # not used
  1277. $zina['genres'] = array('path'=>null, 'query'=>'l=14');
  1278. }
  1279. if ($zc['is_admin'] && $type != 'config') {
  1280. $zina['admin_config'] = array('path'=>$path, 'query'=>'l=20');
  1281. }
  1282. if ($zc['login']) {
  1283. if ($zc['is_admin']) {
  1284. $zina['login'] = array('type'=>'logout', 'path'=>$path,'query'=>'l=99');
  1285. } else {
  1286. $zina['login'] = array('type'=>'login', 'path'=>$path,'query'=>'l=9');
  1287. }
  1288. }
  1289. # not used
  1290. if ($zc['database'] && ($zc['is_admin'] || ($zc['stats'] && $zc['stats_public']))) {
  1291. $zina['stats'] = array('path'=>$path, 'query'=>'l=15');
  1292. }
  1293. $zina['zinamp'] = ($zc['zinamp']) ? ztheme('zinamp_embed') : '';
  1294. switch($type) {
  1295. case 'main':
  1296. default:
  1297. $zina['page_type'] = 'main';
  1298. //zina_content_breadcrumb($zina, $path, $zc['main_dir_title']);
  1299. zina_content_main($zina, $path, $page, $cat_sort);
  1300. break;
  1301. case 'playlists';
  1302. zina_content_breadcrumb($zina, $path);
  1303. if ($zc['database']) {
  1304. $id = (isset($opts['id'])) ? $opts['id'] : null;
  1305. zina_content_playlist_db($zina, $path, $opts['pl'], $id);
  1306. } else {
  1307. zina_content_playlists($zina, $path, $opts['pl']);
  1308. }
  1309. break;
  1310. case 'genres':
  1311. zina_content_breadcrumb($zina, '', zt('Genres'));
  1312. $genres = zina_get_genres_list();
  1313. $genre_num = sizeof($genres);
  1314. $full_page_split = $genres_navigation = false;
  1315. $page = isset($_GET['page']) ? $_GET['page'] : 1;
  1316. #todo: combine with cat_split
  1317. if ($zc['genres_split'] == 2 || $zc['genres_split'] == 3) {
  1318. $splits = ztheme('category_alphabet_split', $genres, $zc['dir_si_str']);
  1319. $splits_sum = array_keys($splits);
  1320. if ($zc['genres_split'] == 2) {
  1321. if (!in_array($page, $splits_sum)) $page = $splits_sum[0];
  1322. $genres_navigation = ztheme('category_alphabet',null, $page, $splits_sum, 'l=14&amp;');
  1323. $genres = $splits[$page];
  1324. } else { # $genres_split == 3
  1325. $full_page_split = 0;
  1326. foreach ($splits as $i) { foreach($i as $item) $full_page_split++; }
  1327. $genres_navigation = ztheme('category_alphabet',null, $page, $splits_sum, 'l=14&amp;', true);
  1328. $genres = &$splits;
  1329. }
  1330. } elseif ($zc['genres_split'] && $genre_num > $zc['genres_pp']) {
  1331. $pages_total = ceil($genre_num/$zc['genres_pp']);
  1332. if (!zina_validate('int', $page) || $page < 1 || $page > $pages_total) $page = 1;
  1333. $genres_navigation = ztheme('category_pages',null, $page, $pages_total,'l=14&amp;');
  1334. $cstart = ($page - 1) * $zc['genres_pp'];
  1335. if ($cstart > $genre_num) $cstart = 0;
  1336. $genres = array_slice($genres, $cstart, $zc['genres_pp']);
  1337. }
  1338. $zina['messages'] = ztheme('messages');
  1339. $zina['content'] = ztheme('genres', $genres, $zc['genres_cols'], $zc['genres_images'], $zc['genres_truncate'], $zina, $genres_navigation, $full_page_split);
  1340. break;
  1341. case 'search':
  1342. #todo: move this whole thing somewhere...
  1343. zina_content_breadcrumb($zina, '', zt('Search Results'));
  1344. $mode_opts = array_keys(zina_get_opt_search());
  1345. $mode = (in_array($opts['m'], $mode_opts)) ? $opts['m'] : $zc['search_default'];
  1346. if ($mode == 'play' && !$zc['play']) $mode = 'browse';
  1347. $result = array();
  1348. $search_id = (isset($_POST['searchid'])) ? $_POST['searchid'] : (isset($_GET['searchid']) ? $_GET['searchid'] : false);
  1349. if ($zc['db_search']) {
  1350. if ($search_id && zina_validate('int', $search_id)) {
  1351. $result = zdbq_array_single("SELECT path, type FROM {search_index} WHERE id = %d && title = '%s'", array($search_id, $search_term));
  1352. }
  1353. } else {
  1354. if ($search_id) {
  1355. if ((!strstr($search_id,'..') || zfile_check_location($zc['mp3_dir'].'/'.$search_id, $zc['mp3_dir'])) && file_exists($zc['mp3_dir'].'/'.$search_id)) {
  1356. $result['path'] = $search_id;
  1357. if (preg_match('/\.('.$zc['ext_mus'].')$/i', $search_id)) {
  1358. $result['type'] = 'song';
  1359. } else {
  1360. $result['type'] = 'directory';
  1361. if ($zc['search_structure']) {
  1362. $count = substr_count($path, '/');
  1363. if ($count == 0) {
  1364. $result['type'] = 'artist';
  1365. } elseif ($count == 1) {
  1366. $result['type'] = 'album';
  1367. }
  1368. }
  1369. }
  1370. }
  1371. }
  1372. }
  1373. if (!empty($result)) {
  1374. $search_type = $result['type'];
  1375. $search_path = $result['path'];
  1376. if ($search_type == 'song') {
  1377. if ($mode == 'play') {
  1378. if (file_exists($zc['mp3_dir'].'/'.$search_path)) zina_send_playlist_song($search_path);
  1379. } else {
  1380. $search_dir = dirname($search_path);
  1381. if (file_exists($zc['mp3_dir'].'/'.$search_dir)) zina_goto($search_dir);
  1382. }
  1383. } elseif ($search_type == 'genre') {
  1384. if ($mode == 'play') {
  1385. zina_send_playlist_random($zc['ran_opts_def'], 's', false, true, null, $search_path);
  1386. } else {
  1387. zina_goto('', 'l=13&pl='.rawurlencode($search_path));
  1388. }
  1389. } elseif (in_array($search_type, array('directory', 'artist', 'album'))) {
  1390. if (is_dir($zc['mp3_dir'].'/'.$search_path)) {
  1391. if ($mode == 'play') {
  1392. if ($search_type == 'album') {
  1393. zina_send_playlist_title($search_path, false, false);
  1394. } else {
  1395. zina_send_playlist_random(0,'s',false,true,$search_path);
  1396. }
  1397. } else {
  1398. zina_goto($search_path);
  1399. }
  1400. }
  1401. } elseif ($search_type == 'playlist') {
  1402. if ($mode == 'play') {
  1403. zina_send_playlist_custom($search_path, false);
  1404. } else {
  1405. zina_goto('', 'l=2&pl='.rawurlencode($search_path));
  1406. }
  1407. } else {
  1408. zina_debug(zt('Search type not found in index.'));
  1409. }
  1410. }
  1411. $results = array();
  1412. $count = 0;
  1413. $action = $selected = $search_navigation = false;
  1414. if (strlen($search_term) < $zc['search_min_chars']) {
  1415. zina_set_message(zt('Search term must be longer than @num characters',@array('@num'=>$zc['search_min_chars'])),'warn');
  1416. } else {
  1417. $page = (isset($_GET['page'])) ? '&amp;page='.$_GET['page'] : '';
  1418. $action = zurl('','l=4'.$page);
  1419. $sql = ($zc['db_search']) ? array('where'=>"i.title LIKE '%%%s%%'") : array();
  1420. $results = zina_search_pager_query($search_term, 'l=4', $count, $search_navigation, $sql, false, $selected);
  1421. }
  1422. $checkbox = (($zc['is_admin'] && $zc['cache']) || $zc['session_pls']);
  1423. zina_content_search_list($results, $checkbox, array('highlight'=>$search_term));
  1424. $list = ztheme('search_list', $results, $zc['search_images']);
  1425. $form_id = 'zinasearchresultsform';
  1426. #todo: why m=1?
  1427. $form_attr = 'id="'.$form_id.'" action="'.zurl('','m=1').'"';
  1428. $list_opts = ($zc['playlists']) ? ztheme('search_list_opts', zina_content_song_list_opts(false, false, $checkbox, $form_id, true), $form_id) : null;
  1429. $zina['content'] = ztheme('search_page', $search_term, $results, $count, $search_navigation, $form_attr, $list, $list_opts, $action, $selected, $zina);
  1430. break;
  1431. case 'searchgenre':
  1432. zina_content_search('genres', $zina);
  1433. break;
  1434. case 'searchyear':
  1435. zina_content_search('year', $zina);
  1436. break;
  1437. case 'blurb':
  1438. zina_content_blurb($zina, $path, $opts);
  1439. break;
  1440. case 'dir_opts':
  1441. zina_content_directory_opts($zina, $path);
  1442. break;
  1443. case 'edittags':
  1444. zina_content_edit_tags($zina, $path, $opts);
  1445. break;
  1446. case 'songextras':
  1447. $opts['return'] = true;
  1448. $content = zina_content_blurb($zina, $path, $opts);
  1449. $ajax_url = false;
  1450. if (empty($content['output']) && isset($zc['third_'.$opts['type']]) && $zc['third_'.$opts['type']]) {
  1451. $ajax_url = zurl($path, 'l=57&m='.$opts['type']);
  1452. zina_set_js('file', 'extras/jquery.js');
  1453. }
  1454. $zina['content'] = ztheme('song_extra', $opts['type'], $content['title'], nl2br($content['output']), $ajax_url);
  1455. break;
  1456. case 'image':
  1457. $img_path = dirname($path);
  1458. $dir = zina_get_directory($img_path);
  1459. zina_content_breadcrumb($zina, $img_path, $dir['title'], true);
  1460. $zina['content'] = ztheme('page_image', $zina, $img_path, $dir['images'], basename($path), $dir['captions']);
  1461. break;
  1462. case 'login':
  1463. zina_content_breadcrumb($zina, '', zt('Login'));
  1464. $rows[] = array('label'=>zt('Username'),'item'=>'<input type="text" name="un"/>');
  1465. $rows[] = array('label'=>zt('Password'),'item'=>'<input type="password" name="up"/>');
  1466. $rows[] = array('label'=>null,'item'=>'<input type="submit" value="'.zt('Login').'"/>');
  1467. $form = array(
  1468. 'title'=>zt('Login'),
  1469. 'attr'=>'action="'.zurl($path, 'l=9').'"',
  1470. 'rows'=>$rows
  1471. );
  1472. $zina['content'] = ztheme('login', $form);
  1473. break;
  1474. case 'newplaylist':
  1475. zina_content_breadcrumb($zina, '', zt('New Playlist'));
  1476. if ($zc['database']) {
  1477. $item = array('title'=>'', 'description'=>'', 'genre_id'=> '', 'dir_id'=>'', 'image_type'=>'', 'visible'=>true);
  1478. $rows = zina_content_playlist_form($item);
  1479. } else {
  1480. $rows[] = array('label'=>zt('Playlist Name'),'item'=>'<input name="playlist" type="text" size="25" maxlength="30"/>');
  1481. }
  1482. $rows[] = array('label'=>null,'item'=>'<input type="submit" value="'.zt('Submit').'"/>');
  1483. $hidden = '';
  1484. if (sizeof($opts['songs']) != 0) {
  1485. sort($opts['songs']);
  1486. foreach($opts['songs'] as $song) {
  1487. $hidden .= '<input type="hidden" name="mp3s[]" value="'.$song.'"/>';
  1488. }
  1489. }
  1490. $form = array(
  1491. 'attr' =>'action="'.zurl($path,'l=40').'"',
  1492. 'hidden'=>$hidden.ztheme('form_hidden','fromnew',1),
  1493. 'rows' =>$rows
  1494. );
  1495. $zina['content'] = ztheme('newplaylist',$form);
  1496. break;
  1497. case 'renameplaylist':
  1498. if (!empty($opts['new']) || ($zc['database'] && $_POST)) {
  1499. if ($zc['database']) {
  1500. if (zina_playlist_form_submit('update', $opts['playlist'])) {
  1501. zina_goto('', 'l=2&pl='.$opts['playlist']);
  1502. }
  1503. } else {
  1504. if (zina_rename_playlist($opts['playlist'], $opts['new'])) {
  1505. zina_goto('', 'l=2');
  1506. }
  1507. }
  1508. zina_set_message(zt('Cannot edit playlist.'), 'warn');
  1509. }
  1510. if ($zc['database']) {
  1511. $title = zt('Edit Playlist');
  1512. $item = zdbq_array_single("SELECT title, description, dir_id, user_id, genre_id, image_type, visible FROM {playlists} WHERE id = %d", array($opts['playlist']));
  1513. if (empty($item)) {
  1514. zina_set_message(zt('Cannot edit playlist.'), 'warn');
  1515. zina_goto('', 'l=2');
  1516. }
  1517. $rows = zina_content_playlist_form($item);
  1518. } else {
  1519. $title = zt('Rename');
  1520. $rows[] = array('label'=>zt('Rename').' "'.htmlentities($opts['playlist']).'" '.zt('Playlist'),
  1521. 'item'=>'<input name="playlist_new" type="text" size="25" maxlength="30" value="'.htmlentities($opts['new']).'"/>');
  1522. }
  1523. zina_content_breadcrumb($zina, '', $title);
  1524. $rows[] = array('label'=>null,'item'=>
  1525. '<input type="submit" value="'.zt('Submit').'"/> '.
  1526. '<input type="button" value="'.zt('Cancel').'" onClick="location.href=\''.zurl('', 'l=2&pl='.$opts['playlist']).'\'"/>'
  1527. );
  1528. $form = array(
  1529. 'attr' => 'action="'.zurl('','l=44').'"',
  1530. 'hidden'=> '<input type="hidden" name="playlist" value="'.htmlentities($opts['playlist']).'"/>',
  1531. 'rows' => $rows
  1532. );
  1533. $zina['content'] = ztheme('renameplaylist',$form);
  1534. break;
  1535. case 'stats':
  1536. zina_content_stats($zina, $opts);
  1537. break;
  1538. case 'config':
  1539. zina_content_breadcrumb($zina, '', zt('Settings'));
  1540. $zina['content'] = zina_content_settings($path);
  1541. break;
  1542. case 'genre_hierarchy':
  1543. zina_content_breadcrumb($zina, '', zt('Genres and Hierarchy'));
  1544. $zina['content'] = zina_content_genre_hierarchy();
  1545. break;
  1546. case 'edit_images':
  1547. $zina['content'] = zina_content_edit_images($zina, $path);
  1548. break;
  1549. case 'rename_directory':
  1550. $dir = zina_get_directory($path, false, array('get_files'=>false));
  1551. if ($dir['dir_write']) {
  1552. if (isset($_POST) && !empty($_POST) && zina_token_sess_check() && !empty($_POST['new_directory'])) {
  1553. $new_dir = $_POST['new_directory'];
  1554. $base = dirname($path);
  1555. $new_path = ($base == '.') ? $new_dir : $base.'/'.$new_dir;
  1556. $new_full = $zc['mp3_dir'].'/'.$new_path;
  1557. if (zfile_check_location($new_full, $zc['mp3_dir']) && $zc['cur_dir'] != $new_full) {
  1558. if (rename($zc['cur_dir'], $new_full)) {
  1559. zina_set_message(zt('Directory renamed'));
  1560. if ($zc['database']) {
  1561. if (isset($dir['id']) && !empty($dir['id'])) {
  1562. $dir_id = $dir['id'];
  1563. } else {
  1564. $dir_id = zdbq_single("SELECT id FROM {dirs} WHERE path = '%s'", array($new_path));
  1565. }
  1566. if (!empty($dir_id)) {
  1567. $sql = "SET path = REPLACE(path, '%s', '%s') WHERE path LIKE '%s%%'";
  1568. $vars = array($path, $new_path, $path);
  1569. zdbq("UPDATE {dirs} $sql", $vars);
  1570. zdbq("UPDATE {dirs} SET title = '%s' WHERE id = %d AND title = '%s'", array(basename($new_path), $dir_id, basename($path)));
  1571. zdbq("UPDATE {files} $sql", $vars);
  1572. zdbq("UPDATE {search_index} $sql", $vars);
  1573. zdbq("UPDATE {search_index} SET context = REPLACE(path, '%s', '%s') WHERE context LIKE '%s%%'", $vars);
  1574. zdbq("UPDATE {search_index} SET title = '%s' WHERE type_id = %d AND title = '%s' AND type IN ('artist', 'album', 'directory')", array(basename($new_path), $dir_id, basename($path)));
  1575. $alts = array();
  1576. if (isset($dir['alt_items'])) {
  1577. $alts = $dir['alt_items'];
  1578. } else {
  1579. $alt_file = $new_full.'/'.$zc['alt_file'];
  1580. if (file_exists($alt_file)) {
  1581. $alts = zunserialize_alt(file_get_contents($alt_file));
  1582. }
  1583. }
  1584. if (!empty($alts)) {
  1585. foreach($alts as $alt) {
  1586. # backwards compatibility...strip /
  1587. $alt_path = rtrim($alt, '/');
  1588. $others = zdb_get_others($alt_path);
  1589. $items = array();
  1590. if (!empty($others) && isset($others['alt_items'])) {
  1591. $items = $others['alt_items'];
  1592. } else {
  1593. $alt_file = $zc['mp3_dir'].(!empty($alt_path) ? '/'.$alt_path : '') . '/'.$zc['alt_file'];
  1594. if (file_exists($alt_file)) {
  1595. $items = zunserialize_alt(file_get_contents($alt_file));
  1596. }
  1597. }
  1598. if (!empty($items)) {
  1599. $change = false;
  1600. foreach($items as $key => $item) {
  1601. $item = rtrim($item, '/');
  1602. if ($item == $path) {
  1603. $items[$key] = $new_path;
  1604. $change = true;
  1605. } else {
  1606. $items[$key] = $item;
  1607. }
  1608. }
  1609. if ($change) {
  1610. zdb_update_others(array('alt_items'=>$items), $alt_path);
  1611. }
  1612. }
  1613. }
  1614. }
  1615. zina_set_message(zt('Database updated'));
  1616. } else {
  1617. zina_set_message(zt('Database not updated'), 'warn');
  1618. }
  1619. }
  1620. zina_goto($new_path);
  1621. } else {
  1622. zina_set_message(zt('Could not rename directory: @old to @new', array('@old'=>$path, '@new'=>$new_path)), 'error');
  1623. }
  1624. } else {
  1625. zina_set_message(zt('Cannot rename directory.'), 'error');
  1626. }
  1627. }
  1628. zina_content_breadcrumb($zina, $path, $dir['title'], true);
  1629. $rows[] = array('label'=>zt('New Directory Name'), 'item'=>zina_content_form_helper('new_directory', array('type'=>'textfield', 'def'=>'', 'size'=>30, 'v'=>array('req')), ''));
  1630. $rows[] = array('label'=>0,'item'=>'<input type="Submit" value="'.zt('Submit').'"/>');
  1631. $form = array(
  1632. 'attr'=>'action="'.zurl($path, 'l=78').'"',
  1633. 'rows'=>$rows,
  1634. 'title' => zt('Rename Directory'),
  1635. );
  1636. $zina['content'] = ztheme('form_table', $form);
  1637. } else {
  1638. zina_set_message(zt('Cannot rename directory.').' '.zt('Directory is not writeable.'), 'error');
  1639. zina_goto($path);
  1640. }
  1641. break;
  1642. case 'help':
  1643. require_once($zc['zina_dir_abs'].'/extras/help.php');
  1644. zina_content_breadcrumb($zina, '', zt('Help and Support Information'));
  1645. $zina['content'] = zina_content_help();
  1646. break;
  1647. case 'mm':
  1648. zina_content_breadcrumb($zina, $path);
  1649. if (preg_match('/\.('.$zc['mm_ext'].')$/i', $path, $exts)) {
  1650. $ext = strtolower($exts[1]);
  1651. if (isset($zc['mm_types'][$ext]['player'])) {
  1652. $ext = strtolower($exts[1]);
  1653. if (preg_match('#^'.$_SERVER['DOCUMENT_ROOT'].'#i',$zc['mp3_dir'])) {
  1654. $file = zurl($path, null, null, true, true);
  1655. } else {
  1656. #todo: doesnt work
  1657. $file = zurl($path, 'l=25', NULL, TRUE);
  1658. }
  1659. $zina['content'] = ztheme('mm', strtolower($zc['mm_types'][$ext]['player']), $file);
  1660. }
  1661. }
  1662. break;
  1663. case 'clean':
  1664. zina_content_breadcrumb($zina, '', zt('Clean up database'));
  1665. #todo: THEME?
  1666. $form_id = 'zinacleanform';
  1667. zina_set_js('inline', 'function selAll(x){for(var i=0;i<document.forms.'.$form_id.'.elements.length;i++){var e=document.forms.'.$form_id.'.elements[i];if(e.type==\'select-one\'){e.selectedIndex=x;}}}');
  1668. $rows[] = array('label'=>zt('All'),'item'=>zl(zt('Remove'),'javascript: void 0;',NULL,NULL,FALSE,' onclick="selAll(0);"').' | '.
  1669. zl(zt('Ignore'),'javascript: void 0;',NULL,NULL,FALSE,' onclick="selAll(1);"') );
  1670. $rows[] = array('label'=>-1,'item'=>'<h3>'.zt('Database entries with missing directories').'</h3>');
  1671. $hidden = zina_content_dbclean_select($rows,'zdirids', zdb_clean_find('dir'));
  1672. $rows[] = array('label'=>-1,'item'=>'<h3>'.zt('Database entries with missing files').'</h3>');
  1673. $hidden .= zina_content_dbclean_select($rows,'zfileids', zdb_clean_find('file'));
  1674. $rows[] = array('label'=>-1,'item'=>'<input type="Submit" value="'.zt('Submit').'"/>');
  1675. $form = array(
  1676. 'attr'=>'action="'.zurl($path, 'l=27').'" id="'.$form_id.'"',
  1677. 'rows'=>$rows,
  1678. 'hidden'=>$hidden,
  1679. );
  1680. $zina['content'] = '<p><strong>'.zt('This feature is experimental. It should not hurt anything, but it might not do everything it is supposed to.').'</strong></p>'.ztheme('clean',$form);
  1681. break;
  1682. }
  1683. if ($zc['play'] && $zc['random']) {
  1684. $genres = ($zc['genres']) ? zina_core_cache('genres') : array();
  1685. $random = ztheme('random', $zc, $zc['database'], $genres, zurl('','l=8'), zurl('','l=8&amp;lf'), zurl('','l=8'));
  1686. }
  1687. $zina['randomplayform'] = $random;
  1688. $zina['time'] = $zc['conf']['time'];
  1689. $zina['messages'] = ztheme('messages');
  1690. $zina['head_js'] = zina_get_js();
  1691. $zina['head_css'] = zina_set_css();
  1692. $zina['head_html'] = zina_get_html_head();
  1693. if ($zc['cache_tmpl'] && !$zc['is_admin'] && empty($zina['messages']) && is_writeable($zc['cache_tmpl_dir'])) {
  1694. $fp = gzopen ($cache_file, 'w1');
  1695. gzwrite($fp,serialize($zina));
  1696. gzclose($fp);
  1697. }
  1698. return $zina;
  1699. }
  1700. function zina_page_simple($title, $content) {
  1701. global $zc;
  1702. $zina['charset'] = $zc['charset'];
  1703. $zina['embed'] = $zc['embed'];
  1704. $zina['theme_path'] = zpath_to_theme();
  1705. $zina['head_js'] = zina_get_js();
  1706. $zina['head_css'] = zina_set_css();
  1707. $zina['head_html'] = zina_get_html_head();
  1708. zina_content_breadcrumb($zina, '', $title);
  1709. $zina['searchform'] = false;
  1710. $zina['randomplayform'] = null;
  1711. $zina['content'] = $content;
  1712. $zina['messages'] = ztheme('messages');
  1713. $zina['time'] = $zc['conf']['time'];
  1714. return $zina;
  1715. }
  1716. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1717. * CONTENT
  1718. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1719. function zina_content_main(&$zina, $path, $page, $category_sort) {
  1720. global $zc;
  1721. if ($cat = zina_is_category($zc['cur_dir'])) {
  1722. $category = true;
  1723. } else {
  1724. $category = $cat['images'] = false;
  1725. }
  1726. $dir = zina_get_directory($path, $category, array('cat_images'=>$cat['images']));
  1727. if (empty($path) || $path == '.') $dir['title'] = $zina['lang']['main_dir_title'];
  1728. zina_content_breadcrumb($zina, $path, $dir['title']);
  1729. if ($dir['dir_edit']) {
  1730. $zina['dir_edit_opts']['dir_opts'] = array('path'=>$path, 'query'=>'l=77');
  1731. $zina['dir_edit_opts']['dir'] = array('path'=>$path, 'query'=>'l=22&amp;m=1');
  1732. }
  1733. $zina['description'] = (isset($dir['description'])) ? $dir['description'] : false;
  1734. $zina['subdir_num'] = $subdir_num = sizeof($dir['subdirs']);
  1735. $zina['alt_num'] = 0;
  1736. $zina['pls_included'] = false;
  1737. $files_found = (!empty($dir['files']));
  1738. $subdirs = &$dir['subdirs'];
  1739. $dirinfo = &$dir['info'];
  1740. if ($category) {
  1741. if ($subdir_num > 0) {
  1742. $full_page_split = false;
  1743. # 0 = none, 1 = pages, 2 = alphabet, 3 = full_page_split
  1744. if ($cat['split'] == 2 || $cat['split'] == 3) {
  1745. zina_directory_sort($subdirs);
  1746. $sort_ignore_str = ($zc['dir_sort_ignore']) ? $zc['dir_si_str'] : false;
  1747. $splits = ztheme('category_alphabet_split', $subdirs, $sort_ignore_str);
  1748. if ($zc['cat_various_lookahead'] || $cat['split'] == 3) {
  1749. $count = 0;
  1750. foreach ($splits as $subkey => $i) {
  1751. foreach($i as $itemkey => $item) {
  1752. if (isset($item['category']) && !empty($item['category'])) {
  1753. $cat_dir_tags = (isset($item['category']['override']['dir_tags'])) ? $item['category']['override']['dir_tags'] : $zc['dir_tags'];
  1754. $v = zina_get_directory($item['path'], true, array('get_files'=>false, 'dir_tags'=>$cat_dir_tags));
  1755. $letter = ($subkey == 'zzz') ? $item['title']: $item['path'];
  1756. if (!empty($v['subdirs'])) {
  1757. zina_directory_sort($v['subdirs']);
  1758. foreach($v['subdirs'] as $various_subkey => $vdir) {
  1759. $splits[$letter][$various_subkey] = $vdir;
  1760. $count++;
  1761. }
  1762. if ($subkey == 'zzz') unset($splits[$subkey][$itemkey]);
  1763. } else {
  1764. $count++;
  1765. }
  1766. } else {
  1767. $count++;
  1768. }
  1769. }
  1770. }
  1771. }
  1772. $splits_sum = array_keys($splits);
  1773. if ($cat['split'] == 2) {
  1774. if (!in_array($page, $splits_sum)) $page = $splits_sum[0];
  1775. $zina['category']['navigation'] = ztheme('category_alphabet',$path, $page, $splits_sum);
  1776. $subdirs = $splits[$page];
  1777. } else { # $cat['split'] == 3
  1778. $zina['category']['navigation'] = ztheme('category_alphabet',$path, null, $splits_sum, null, true);
  1779. $full_page_split = $count;
  1780. $subdirs = &$splits;
  1781. }
  1782. } else {
  1783. #todo: won't always be cat sort? or what if catsort == 0
  1784. if ($cat['sort'] && $subdir_num > 1) {
  1785. if ($category_sort == 'ad') { # alpha desc
  1786. zina_directory_sort($subdirs);
  1787. $subdirs = array_reverse($subdirs, true);
  1788. $cat['alpha'] = array('sort'=>'asc','query'=>'zs=a');
  1789. } elseif ($category_sort == 'd') { #date asc
  1790. uasort($subdirs, 'zsort_date');
  1791. $cat['date'] = array('sort'=>'desc','query'=>'zs=dd');
  1792. } elseif ($category_sort == 'dd') { #date desc
  1793. uasort($subdirs, 'zsort_date_desc');
  1794. $cat['date'] = array('sort'=>'asc','query'=>'zs=d');
  1795. } else { # alpha asc
  1796. $category_sort = 'a';
  1797. zina_directory_sort($subdirs);
  1798. $cat['alpha']=array('sort'=>'desc','query'=>'zs=ad');
  1799. }
  1800. if (!empty($cat['alpha'])) {
  1801. $cat['date']=array('sort'=>'desc','query'=>'zs=dd');
  1802. } elseif (!empty($cat['date'])) {
  1803. $cat['alpha']=array('sort'=>'asc','query'=>'zs=a');
  1804. }
  1805. $zina['category']['sort'] = $t_sort = ztheme('category_sort',$path, $cat);
  1806. } else {
  1807. zina_directory_sort($subdirs);
  1808. $zina['category']['sort'] = '';
  1809. }
  1810. if ($cat['split'] && $subdir_num > $cat['pp']) {
  1811. $pages_total = ceil($subdir_num/$cat['pp']);
  1812. if (!zina_validate('int', $page) || $page < 1 || $page > $pages_total) $page = 1;
  1813. $zina['category']['navigation'] = ztheme('category_pages',$path, $page, $pages_total);
  1814. $cstart = ($page - 1) * $cat['pp'];
  1815. if ($cstart > $subdir_num) $cstart = 0;
  1816. $subdirs = array_slice($subdirs, $cstart, $cat['pp']);
  1817. }
  1818. }
  1819. if ($cat['images']) {
  1820. if ($cat['split'] == 3) {
  1821. foreach($subdirs as $key => $val) zina_get_dir_list($subdirs[$key], false);
  1822. } else {
  1823. zina_get_dir_list($subdirs, false);
  1824. }
  1825. }
  1826. $zina['category']['content'] = ztheme('category', $subdirs, $cat['cols'], $cat['images'], $cat['truncate'], $full_page_split);
  1827. }
  1828. } else { # Not Category
  1829. $zina['dir_list'] = $zc['dir_list'];
  1830. $zina['subdir_images'] = $zc['subdir_images'];
  1831. $list = false;
  1832. if ($subdir_num > 0 && ($zc['dir_list'] || $zc['subdir_images'])) {
  1833. $list = true;
  1834. if (!$zc['dir_list_sort']) {
  1835. ($zc['dir_sort_ignore']) ? uksort($subdirs, 'zsort_ignore') : uksort($subdirs, 'strnatcasecmp');
  1836. }
  1837. zina_get_dir_list($subdirs);
  1838. $zina['subdirs'] = $subdirs;
  1839. } else {
  1840. if ($dir['dir_write']) {
  1841. $zina['dir_opts']['delete'] = array('path'=>$path, 'query'=>'l=76');
  1842. }
  1843. }
  1844. $zina['dir_image'] = ztheme('images', 'dir', $zina, $path, $dir['images'], 'l=46', $dir['image'], $dir['captions']);
  1845. $zina['dir_image_sub'] = ztheme('image',zina_get_image_url($path, (isset($dir['images'][0])?$dir['images'][0]:$dir['images']), 'sub'), $zina['title'], $zina['title']);
  1846. $alt_num = 0;
  1847. if ($zc['alt_dirs']) {
  1848. $zina['alt_items'] = array();
  1849. if (isset($dir['alt_items'])) {
  1850. $alts = $dir['alt_items'];
  1851. $list = true;
  1852. } else {
  1853. $alt_file = $zc['cur_dir'].'/'.$zc['alt_file'];
  1854. if (file_exists($alt_file)) {
  1855. $alts = zunserialize_alt(file_get_contents($alt_file));
  1856. $list = true;
  1857. }
  1858. }
  1859. if (!empty($alts)) {
  1860. $alt_num = count($alts);
  1861. $alts_db = array();
  1862. if ($zc['database']) {
  1863. $alts_db = zdbq_assoc_list("SELECT path, other FROM {dirs} WHERE path IN (".substr(str_repeat(",'%s'", $alt_num),1).")", $alts);
  1864. }
  1865. foreach($alts as $alt) {
  1866. # backwards compatibility...strip /
  1867. $alt = rtrim($alt, '/');
  1868. $alt_dirs[$alt] = array('path'=>$alt,'new'=>false, 'lofi'=>1);
  1869. $alt_img = false;
  1870. if (isset($alts_db[$alt])) {
  1871. $temp = unserialize_utf8($alts_db[$alt]);
  1872. if (isset($temp['image']) && $temp['image']) $alt_img = $temp['image'];
  1873. }
  1874. if (!$alt_img) $alt_img = zina_get_dir_item($zc['mp3_dir'].'/'.$alt,'/\.('.$zc['ext_graphic'].')$/i');
  1875. $alt_dirs[$alt]['image'] = $alt_img;
  1876. if ($zc['low_lookahead']) { $alt_dirs[$alt]['lofi'] = zina_get_dir_item($zc['mp3_dir'].'/'.$alt,'/('.$zc['low_suf'].')\.('.$zc['ext_mus'].')$/i'); }
  1877. if (empty($alt)) $alt_dirs[$alt]['title'] = $zc['main_dir_title'];
  1878. }
  1879. zina_get_dir_list($alt_dirs);
  1880. $zina['alt_items'] = $alt_dirs;
  1881. }
  1882. if ($dir['dir_edit']) $zina['alt_list_edit']['query'] = 'l=22&amp;m=2';
  1883. }
  1884. $zina['alt_num'] = $alt_num;
  1885. $zina['pls_included'] = false;
  1886. if ($zc['playlists'] && $zc['database'] && $zc['pls_included'] && isset($dir['id'])) {
  1887. $where = (!$zc['is_admin']) ? (($zc['pls_public']) ? 'AND (p.user_id = %d OR p.visible = 1)' : 'AND p.user_id = %d') : '';
  1888. $dir_playlists = zdbq_array("SELECT p.id, p.title, NULL as path, CONCAT('l=2&amp;pl=',p.id) as query, FALSE as new ".
  1889. "FROM {playlists_map} as pm ".
  1890. "INNER JOIN {playlists} as p ON (pm.playlist_id = p.id) ".
  1891. "LEFT OUTER JOIN {files} AS f ON pm.type = 'song' AND pm.type_id = f.id ".
  1892. "LEFT OUTER JOIN {dirs} AS d ON pm.type = 'album' AND pm.type_id = d.id ".
  1893. "WHERE (d.id = %d OR f.dir_id = %d) $where ".
  1894. "GROUP BY p.id ".
  1895. "ORDER BY p.sum_rating DESC, p.title LIMIT ".$zc['pls_included_limit'], array($dir['id'], $dir['id'], $zc['user_id']));
  1896. if (!empty($dir_playlists)) {
  1897. foreach ($dir_playlists as $key => $pls) {
  1898. $item = &$dir_playlists[$key];
  1899. $item['opts']['play'] = array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$item['id']);
  1900. }
  1901. $zina['pls_included']['items'] = $dir_playlists;
  1902. if (sizeof($dir_playlists) >= $zc['pls_included_limit']) {
  1903. $zina['pls_included']['more'] = array('path'=>null, 'query'=>'l=2&m='.$dir['id']);
  1904. }
  1905. }
  1906. }
  1907. if ($list && $zc['playlists']) {
  1908. $form_id = 'zinadirsform';
  1909. $type = ($subdir_num + $alt_num > 0) ? 'l a x p r q v' : 'l x p r q v';
  1910. $zina['list_form'] = zina_content_playlist_form_opts($form_id, $zina['title'], $type);
  1911. $zina['list_form_opts'] = 'id="'.$form_id.'" action="'.zurl($path).'"';
  1912. } else {
  1913. $zina['list_form'] = $zina['list_form_opts'] = '';
  1914. }
  1915. if ($zc['database']) {
  1916. if ($zc['rating_dirs']) {
  1917. $user_rating = ($zc['user_id'] > 0) ? zdb_get_dir_user_rating($path, $zc['user_id']) : 0;
  1918. $zina['dir_rate'] = ztheme('vote', zina_get_vote_url($path), $user_rating);
  1919. }
  1920. if ($zc['rating_dirs_public'] || $zc['is_admin']) {
  1921. $zina['dir_rating']['sum_views'] = $dir['sum_views'];
  1922. $zina['dir_rating']['sum_votes'] = $dir['sum_votes'];
  1923. $zina['dir_rating']['sum_rating'] = $dir['sum_rating'];
  1924. }
  1925. }
  1926. } #NOT CAT
  1927. if ($files_found) {
  1928. $lofi = ($zc['low'] && ($zc['resample'] || $dir['lofi']));
  1929. $custom_pls = ($zc['cache'] && file_exists($zc['cache_pls_dir'].'/'.str_replace('/',' - ',$path).'.m3u'));
  1930. # Dir Play
  1931. if ($zc['play']) {
  1932. $zina['dir_opts']['play'] = array('path'=>$path, 'query'=>'l=8&amp;m=0', 'class'=>'zinamp');
  1933. if ($custom_pls) {
  1934. $zina['dir_opts']['play_custom'] = array('path'=>$path, 'query'=>'l=8&amp;m=0&amp;c');
  1935. }
  1936. # Recursive Play & Random
  1937. if ($zc['play_rec'] && $subdir_num > 1) {
  1938. $zina['dir_opts']['play_rec'] = array('path'=>$path, 'query'=>'l=8&amp;m=10');
  1939. }
  1940. if ($zc['play_rec_rand'] && $subdir_num > 0) {
  1941. $zina['dir_opts']['play_rec_rand'] = array('path'=>$path, 'query'=>'l=8&amp;m=10&amp;c');
  1942. }
  1943. }
  1944. if ($lofi) {
  1945. $zina['dir_opts']['play_lofi'] = array('path'=>$path, 'query'=>'l=8&amp;m=0&amp;lf');
  1946. if ($custom_pls) {
  1947. $zina['dir_opts']['play_lofi_custom'] = array('path'=>$path, 'query'=>'l=8&amp;m=0&amp;c&amp;lf');
  1948. }
  1949. }
  1950. if ($zc['cmp_sel']) {
  1951. $zina['dir_opts']['download'] = array('path'=>$path.'/.lp', 'query'=>'l=5');
  1952. if ($custom_pls) {
  1953. $zina['dir_opts']['download_custom'] = array('path'=>$path.'/.lp', 'query'=>'l=5&amp;c');
  1954. }
  1955. }
  1956. #todo: this is done twice
  1957. $key = key($dir['files']);
  1958. $dir_year = (isset($dir['year'])) ? $dir['year'] : ((isset($subdirs[$key]['info']->year)) ? $subdirs[$key]['info']->year : false);
  1959. $zina['dir_year'] = ($dir_year && $zc['db_search']) ? zl($dir_year,$path,'l=69&amp;pl='.rawurlencode($dir_year)) : $dir_year;
  1960. $dir_genre = ($zc['genres'] && isset($dir['genre'])) ? $dir['genre'] : ((isset($subdirs[$key]['info']->genre)) ? $subdirs[$key]['info']->genre : false);
  1961. $zina['dir_genre'] = ($dir_genre) ? zl($dir_genre,$path,'l=13&amp;pl='.rawurlencode($dir_genre)) : $dir_genre;
  1962. if ($zc['files_sort'] == 1) {
  1963. krsort($dir['files']);
  1964. } elseif ($zc['files_sort'] == 2) {
  1965. usort($dir['files'],'zsort_date');
  1966. } elseif ($zc['files_sort'] == 3) {
  1967. usort($dir['files'],'zsort_date_desc');
  1968. } elseif ($zc['files_sort'] == 4) {
  1969. usort($dir['files'],'zsort_trackno');
  1970. }
  1971. $songrow = ztheme('song_list', $dir['files'], $dir['various']);
  1972. $check_boxes = (($zc['is_admin'] && $zc['cache']) || ($zc['playlists'] && $zc['session_pls']) || $zc['play_sel'] || $zc['cmp_sel']);
  1973. $form_id = 'zinasongsform';
  1974. $form_attr = 'id="'.$form_id.'" action="'.zurl($path).'"';
  1975. $songopts = ztheme('song_list_opts', zina_content_song_list_opts($custom_pls, $lofi, $check_boxes,$form_id),$form_id);
  1976. $zina['songs'] = ztheme('song_section',$form_attr, $songrow, $songopts);
  1977. if ($zc['rss']) {
  1978. if ($zc['clean_urls']) {
  1979. $zina['podcast']['url'] = (empty($path)) ? $zc['rss_file'] : $path.'/'.$zc['rss_file'];
  1980. $zina['podcast']['query'] = null;;
  1981. } else {
  1982. $zina['podcast']['url'] = $path;
  1983. $zina['podcast']['query'] = 'l=50';
  1984. }
  1985. $zina['podcast']['type'] = ($zc['rss_podcast']) ? 'podcast' : 'rss';
  1986. zina_set_html_head('<link rel="alternate" type="application/rss+xml" title="'.zt('!title Podcast', array('!title'=>$zina['title'])).'" href="'.zurl($zina['podcast']['url'], $zina['podcast']['query']).'"/>');
  1987. if ($dir['dir_edit'] && $zc['is_admin']) {
  1988. $zina['dir_edit_opts']['podcast'] = array('path'=>$path, 'query'=>'l=22&amp;m=5');
  1989. }
  1990. }
  1991. } else { #NO FILES FOUND
  1992. if($zc['dir_genre_look'] && $subdir_num > 0) {
  1993. if (isset($dir['genre'])) {
  1994. $dir_genre = $dir['genre'];
  1995. } else {
  1996. $keys = array_keys($subdirs);
  1997. $key = $keys[0];
  1998. $dir_genre = (isset($subdirs[$key]['info']->genre)) ? $subdirs[$key]['info']->genre : false;
  1999. }
  2000. $zina['dir_genre'] = ($dir_genre) ? zl($dir_genre,$path,'l=13&amp;pl='.rawurlencode($dir_genre)) : $dir_genre;
  2001. }
  2002. # Recursive Play & Random
  2003. if ($zc['play'] && $zc['play_rec'] && $subdir_num > 1) {
  2004. $zina['dir_opts']['play_rec'] = array('path'=>$path, 'query'=>'l=8&amp;m=10');
  2005. }
  2006. if ($zc['play'] && $zc['play_rec_rand'] && $subdir_num > 0) {
  2007. $zina['dir_opts']['play_rec_rand'] = array('path'=>$path, 'query'=>'l=8&amp;m=10&amp;c');
  2008. }
  2009. }
  2010. if ($zc['is_admin']) {
  2011. $zina['dir_edit_opts']['images'] = array('path'=>$path, 'query'=>'l=58');
  2012. if ($dir['dir_edit'] && $files_found) $zina['dir_edit_opts']['tags'] = array('path'=>$path, 'query'=>'l=71');
  2013. }
  2014. if ($zc['mm'] && !empty($dir['mm'])) $zina['multimedia'] = $dir['mm'];
  2015. $zina['subdir_truncate'] = $zc['subdir_truncate'];
  2016. $zina['subdir_cols'] = $zc['subdir_cols'];
  2017. $zina['page_main'] = true;
  2018. $zina['content'] = ztheme('page_main', $zina);
  2019. }
  2020. function zina_content_breadcrumb(&$zina, $path, $alt_title = null, $full = false) {
  2021. $zina['path'] = $path;
  2022. if (!empty($path)) {
  2023. $zina['breadcrumb'] = zina_get_breadcrumb($path, $alt_title, $full);
  2024. $dir_current = zina_get_current_dir();
  2025. $title = ztheme('page_title',zina_get_page_title());
  2026. } else {
  2027. $title = $dir_current = $alt_title;
  2028. $zina['breadcrumb'] = zina_get_breadcrumb($alt_title, null, $full);
  2029. }
  2030. $zina['html_title'] = zcheck_utf8($dir_current);
  2031. $zina['title_raw'] = zdecode_entities($dir_current);
  2032. $zina['title'] = $title;
  2033. }
  2034. function zina_content_search_list(&$results, $checkbox, $opts = array(), $extras = array()) {
  2035. global $zc;
  2036. if (!empty($results)) {
  2037. $ratings = (isset($opts['rating'])) ? $opts['rating'] : ($zc['rating_files'] && $zc['db_search']);
  2038. $images = (isset($opts['images'])) ? $opts['images'] : $zc['search_images'];
  2039. $types = (isset($opts['types'])) ? $opts['types'] : true;
  2040. $genres = (isset($opts['genres'])) ? $opts['genres'] : $zc['genres'];
  2041. $years = (isset($opts['years'])) ? $opts['years'] : true;
  2042. foreach($results as $key=>$item) {
  2043. $play = $zc['play'];
  2044. $download = $zc['download'];
  2045. $rem_title = false;
  2046. $result = &$results[$key];
  2047. $result['new'] = false;
  2048. $result['image'] = (isset($item['image'])) ? $item['image'] : false;
  2049. $result['ratings'] = $ratings;
  2050. if (isset($result['title']) && isset($opts['highlight'])) {
  2051. $result['alt'] = $result['title'];
  2052. $result['title'] = preg_replace("|(".preg_quote($opts['highlight']).")|i",'<span class="ac_match_results">$1</span>',$result['title']);
  2053. }
  2054. #TODO: test ratings w/o DB
  2055. if ($item['type'] == 'song') {
  2056. if ($checkbox) {
  2057. $result['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($item['path']), 'checked'=>false);
  2058. } else {
  2059. $result['checkbox'] = false;
  2060. }
  2061. if (!isset($result['title'])) {
  2062. if (isset($item['id3_info'])) {
  2063. $mp3 = unserialize_utf8($item['id3_info']);
  2064. if (isset($mp3->title)) $result['title'] = ztheme('song_title', $mp3->title, true);
  2065. }
  2066. if (!isset($result['title'])) {
  2067. $result['title'] = zina_content_song_title($item['path']);
  2068. }
  2069. }
  2070. $desc_opts = array();
  2071. if ($types && !empty($item['type'])) $desc_opts['type'] = zt(ucfirst($result['type']));
  2072. if ($years && isset($item['year']) && !empty($item['year'])) $desc_opts['year'] = zl($item['year'],'','l=69&amp;pl='.rawurlencode($item['year']));
  2073. if ($genres && isset($item['genre'])) $desc_opts['genre'] = zl($item['genre'],'','l=13&amp;pl='.rawurlencode($item['genre']));
  2074. #todo: put in "description" if exists?
  2075. $result['description'] = ztheme('search_description', zina_content_pathlinks(dirname($item['path']), 't', false, $rem_title), $desc_opts);
  2076. $dir_path = dirname($item['path']);
  2077. $title_link = (zvalidate_utf8($dir_path)) ? utf8_decode($dir_path) : $dir_path;
  2078. $result['image_link'] = array('path'=>$title_link, 'query'=>null);
  2079. if ($play) {
  2080. $title_link = (zvalidate_utf8($item['path'])) ? utf8_decode($item['path']) : $item['path'];
  2081. $result['title_link'] = $result['opts']['play'] = array('path'=>$title_link, 'query'=>'l=8&amp;m=1', 'attr'=>' class="zinamp"');
  2082. } else {
  2083. $result['title_link'] = array('path'=>$title_link, 'query'=>null);
  2084. }
  2085. if ($download) $result['opts']['download'] = array('path'=>$item['path'], 'query'=>'l=12');
  2086. if (isset($item['id3_info'])) $result['info'] = unserialize_utf8($item['id3_info']);
  2087. } elseif ($item['type'] == 'genre') {
  2088. $result['description'] = ($types) ? ucfirst($item['type']) : '';
  2089. $result['checkbox'] = false;
  2090. if ($play) {
  2091. $result['opts']['play'] = array('path'=>null, 'query'=>'l=8&amp;m=5&amp;pl='.rawurlencode($item['path']));
  2092. }
  2093. $result['image_link'] = $result['title_link'] = array('path'=>null, 'query'=>'l=13&pl='.rawurlencode($item['path']));
  2094. } elseif (in_array($item['type'], array('artist','album','directory'))) {
  2095. zina_content_subdir_opts($result, $item['path'], $checkbox, NULL);
  2096. if (!isset($result['title'])) {
  2097. if ($zc['dir_tags'] && isset($item['id3_info']) && !empty($item['id3_info'])) {
  2098. $title_path = $item['id3_info'];
  2099. } else {
  2100. $title_path = (substr_count($item['path'], '/') > 0) ? substr($item['path'], strrpos($item['path'],'/')+1) : $item['path'];
  2101. if (zvalidate_utf8($title_path)) $title_path = utf8_decode($title_path);
  2102. }
  2103. $result['title'] = ztheme('title', $title_path);
  2104. }
  2105. #todo: redudant with songs
  2106. $desc_opts = array();
  2107. if ($types && !empty($item['type'])) $desc_opts['type'] = zt(ucfirst($result['type']));
  2108. if ($years && isset($item['year']) && !empty($item['year'])) $desc_opts['year'] = zl($item['year'],'','l=69&amp;pl='.rawurlencode($item['year']));
  2109. if ($genres && isset($item['genre'])) $desc_opts['genre'] = zl($item['genre'],'','l=13&amp;pl='.rawurlencode($item['genre']));
  2110. $title_link = (zvalidate_utf8($item['path'])) ? utf8_decode($item['path']) : $item['path'];
  2111. $result['image_link'] = $result['title_link'] = array('path'=>$title_link, 'query'=>null);
  2112. if ($item['type'] == 'album') {
  2113. $result['description'] = ztheme('search_description', zina_content_pathlinks(dirname($item['path']), 't', false, $rem_title), $desc_opts);
  2114. } else {
  2115. if ($item['type'] == 'artist') unset($desc_opts['year']);
  2116. $result['description'] = ztheme('search_description', '', $desc_opts);
  2117. #todo: have '/.art' so artists can be added to playlists...?
  2118. $result['checkbox'] = false;
  2119. }
  2120. } elseif ($item['type'] == 'playlist') {
  2121. if (isset($item['description'])) {
  2122. $result['description'] = zina_url_filter($item['description']);
  2123. } else {
  2124. $result['description'] = ($types) ? ucfirst($item['type']) : '';
  2125. }
  2126. # SEARCH RESULTS
  2127. if ($images && !$result['image']) {
  2128. if (isset($item['image_type']) || !empty($item['image_type'])) {
  2129. if ($item['image_type'] == 1 && isset($item['image_path'])) {
  2130. $tmp = $item['id'];
  2131. $item['id'] = $item['path'];
  2132. $item['path'] = $item['image_path'];
  2133. $item['type'] = 'artist';
  2134. $result['image'] = zina_content_search_image($item, 'search');
  2135. $item['type'] = 'playlist';
  2136. $item['path'] = $item['id'];
  2137. $item['id'] = $tmp;
  2138. }
  2139. }
  2140. }
  2141. $pls = ($zc['database'] && isset($item['id'])) ? $item['id'] : $item['path'];
  2142. if ($zc['database'] && $item['id'] != 'zina_session_playlist') {
  2143. $result['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($item['id']).'.pls', 'checked'=>false);
  2144. } else {
  2145. $result['checkbox'] = false;
  2146. }
  2147. if ($play) {
  2148. $result['opts']['play'] = array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.rawurlencode($pls));
  2149. }
  2150. $result['image_link'] = $result['title_link'] = array('path'=>null, 'query'=>'l=2&pl='.rawurlencode($pls));
  2151. } else {
  2152. $result['description'] = null;
  2153. $result['checkbox'] = false;
  2154. }
  2155. if ($images && !$result['image']) {
  2156. $result['image'] = zina_content_search_image($result, 'search');
  2157. }
  2158. foreach($extras as $key=>$extra) { $result[$key] = $extra; }
  2159. }
  2160. }
  2161. }
  2162. # genre & year search
  2163. function zina_content_search($type, &$zina) {
  2164. global $zc;
  2165. $search_opts = false;
  2166. $count = 0;
  2167. $results = array();
  2168. $selected = false;
  2169. $term = isset($_POST['pl']) ? $_POST['pl'] : (isset($_GET['pl']) ? $_GET['pl'] : null);
  2170. $checkbox = ($zc['playlists'] && (($zc['is_admin'] && $zc['cache']) || $zc['session_pls'] || $zc['pls_public'] || ($zc['pls_user'] && $zc['user_id'] > 0)));
  2171. if ($type == 'year') {
  2172. $query = 'l=69';
  2173. $qp = '6';
  2174. $sql = array('where'=>"i.year = %d", 'orderby'=>"i.title");
  2175. $items = zdbq_array_list("SELECT DISTINCT year, year FROM {dirs} WHERE year IS NOT NULL ORDER BY year DESC");
  2176. $label = zt('Year');
  2177. } else {
  2178. $type = 'genres';
  2179. $query = 'l=13';
  2180. $qp = '5';
  2181. $sql = array('where'=>"i.genre = '%s'", 'orderby'=>"i.title");
  2182. $items = zina_core_cache('genres');
  2183. $label = false;
  2184. if (!$zc['db_search']) $sql = array();
  2185. }
  2186. if (!in_array($term, $items)) {
  2187. zina_set_message(zt('Unknown term: @term', array('@term'=>$term)));
  2188. $bad_query = ($type == 'year') ? '' : 'l=14';
  2189. zina_goto('', $bad_query);
  2190. }
  2191. $navigation = ztheme($type.'_form', $zc['genres'], zurl('',$query), $items, $term, $label);
  2192. $zina['html_title'] = $zina['title'] = htmlentities($term);
  2193. $results = zina_search_pager_query($term, $query, $count, $search_opts, $sql, ($type == 'genres'), $selected);
  2194. if (!empty($results)) {
  2195. zina_content_breadcrumb($zina, '', $term);
  2196. if ($zc['genres_images']) {
  2197. $genre_image = ztheme('image', zina_get_genre_image_path($term), $term, null, 'class="genre-image"');
  2198. } else {
  2199. $genre_image = false;
  2200. }
  2201. } else {
  2202. zina_content_breadcrumb($zina, '', zt('Search Results'));
  2203. }
  2204. zina_content_search_list($results, $checkbox, array('highlight'=>$term, 'genres'=>($zc['genres'] && $type != 'genres'), 'years'=>($zc['db_search'] && $type != 'year')));
  2205. $list = ztheme('search_list', $results, $zc['search_images']);
  2206. $form_id = 'zinasearchresultsform';
  2207. $form_attr = 'id="'.$form_id.'" action="'.zurl('','m=1').'"';
  2208. $list_opts = ($zc['playlists']) ? ztheme('search_list_opts', zina_content_song_list_opts(false, false, $checkbox, $form_id, true), $form_id) : null;
  2209. $opts['image'] = $zc['genres_images'];
  2210. $opts['play_query'] = 'l=8&amp;m='.$qp.'&amp;pl='.rawurlencode($term);
  2211. $opts['genre_edit'] = $opts['description'] = false;
  2212. if ($type == 'genres' && $zc['database']) {
  2213. $page = zdbq_array_single("SELECT * FROM {genres} as g INNER JOIN {genre_tree} as gt ON g.id=gt.id ".
  2214. "WHERE g.genre = '%s'", array($term));
  2215. if ($page['pid'] != 0) {
  2216. $crumbs = explode('/', $page['path']);
  2217. array_pop($crumbs);
  2218. $gs = zdbq_assoc_list("SELECT id, genre FROM {genres} WHERE id IN (".implode(',', $crumbs).")");
  2219. foreach($crumbs as $crumb) {
  2220. $links[] = zl($gs[$crumb],null, 'l=13&pl='.zrawurlencode($gs[$crumb]));
  2221. }
  2222. $zina['breadcrumb'] = zina_get_breadcrumb(null, null, false, $links);
  2223. }
  2224. $children = zdbq_array_list("SELECT genre FROM {genres} AS g INNER JOIN {genre_tree} AS gt ON g.id=gt.id ".
  2225. "WHERE g.pid = %d ORDER BY weight", array($page['id']));
  2226. if (!empty($children)) {
  2227. $children = zina_get_genres_list($children, 'genresearch');
  2228. $zina['subgenres'] = ztheme('genres', $children, $zc['genres_cols']*2, $zc['genres_images'], $zc['genres_truncate'], $zina, false, false);
  2229. }
  2230. if ($zc['is_admin'] && $zc['database']) {
  2231. if (!empty($page['description'])) $opts['description'] = zina_url_filter(nl2br($page['description']));
  2232. $opts['genre_edit'] = array('path'=>'', 'query'=>'l=22&amp;m=6&amp;pl='.rawurlencode($term));
  2233. }
  2234. }
  2235. $zina['search_page_type'] = $type;
  2236. $zina['content'] = ztheme($type.'_page', $term, $results, $count, $search_opts, $navigation, $form_attr, $list, $list_opts, $opts, zurl('', $query.'&amp;pl='.zrawurlencode($term)), $selected, $zina);
  2237. }
  2238. function zina_content_search_image($item, $size = 'sub', $class="search-image", $absolute = false) {
  2239. global $zc;
  2240. # some of these utf8s can be removed in 3.0 when db is installed as utf-8
  2241. if (isset($item['path']) && zvalidate_utf8($item['path'])) $item['path'] = utf8_decode($item['path']);
  2242. $image = $img_url = null;
  2243. if ($item['type'] == 'song') {
  2244. $img_path = dirname($item['path']);
  2245. $img = zina_get_dir_item($zc['mp3_dir'].'/'.$img_path,'/\.('.$zc['ext_graphic'].')$/i');
  2246. $img_url = zina_get_image_url($img_path, $img, $size, $absolute);
  2247. } elseif (in_array($item['type'], array('artist','album','directory'))) {
  2248. $img_path = $item['path'];
  2249. $img = zina_get_dir_item($zc['mp3_dir'].'/'.$img_path,'/\.('.$zc['ext_graphic'].')$/i');
  2250. $img_url = zina_get_image_url($img_path, $img, $size, $absolute);
  2251. } elseif (($item['type'] == 'genre' || $item['type'] == 'genresearch') && $zc['genres_images']) {
  2252. #todo: absolute
  2253. #$img_url = zina_get_genre_image_path($item['path'], 'genresearch');
  2254. if ($size != 'genre') $size = 'genresearch';
  2255. $img_url = zina_get_genre_image_path($item['path'], $size);
  2256. } elseif ($item['type'] == 'playlist') {
  2257. # SEARCH BOX
  2258. if (isset($item['image_type'])) {
  2259. if ($item['image_type'] == 1) {
  2260. $item['type'] = 'artist';
  2261. $item['path'] = $item['image_path'];
  2262. return zina_content_search_image($item, $size, $class, $absolute);
  2263. } elseif ($item['image_type'] == 2) {
  2264. $item['type'] = ($size == 'search') ? 'genresearch' : 'genre';
  2265. $item['path'] = $item['genre'];
  2266. $item['title'] = $item['genre'];
  2267. return zina_content_search_image($item, $item['type'], $class, $absolute);
  2268. } else {
  2269. $size = ($size == 'search') ? 'plssearch' : 'pls';
  2270. if ($zc['res_genre_img']) {
  2271. $img_url = zurl(null,'l=7&amp;it='.$size.'&amp;img='.rawurlencode($item['title']), null, $absolute);
  2272. }
  2273. }
  2274. } else {
  2275. zina_debug(zt('No playlist image info'));
  2276. }
  2277. }
  2278. if (!empty($img_url)) {
  2279. $alt = (isset($item['alt'])) ? $item['alt'] : $item['title'];
  2280. $image = ztheme('image', $img_url, $alt, null, 'class="'.$class.'"');
  2281. }
  2282. return $image;
  2283. }
  2284. function zina_directory_sort(&$subdirs) {
  2285. global $zc;
  2286. if ($zc['dir_tags']) {
  2287. ($zc['dir_sort_ignore']) ? usort($subdirs, 'zsort_title_ignore') : usort($subdirs, 'zsort_title');
  2288. } else {
  2289. ($zc['dir_sort_ignore']) ? uksort($subdirs, 'zsort_ignore') : uksort($subdirs, 'strnatcasecmp');
  2290. }
  2291. }
  2292. function zina_playlist_insert($pls_id, $items, $start) {
  2293. global $zc;
  2294. $weight = $start;
  2295. $error = false;
  2296. foreach($items as $item) {
  2297. if ($weight > $zc['pls_length_limit']) {
  2298. zina_set_message(zt('You cannot have more than @num items per playlist.', array('@num'=>$zc['pls_length_limit'])));
  2299. $error = true;
  2300. break;
  2301. }
  2302. $item = zrawurldecode($item);
  2303. if (preg_match('/\.('.$zc['ext_mus'].')$/i', $item) || ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $item))) {
  2304. $type = 'song';
  2305. if (substr_count($item, '/') > 0) {
  2306. $pos = strrpos($item,'/');
  2307. $file_name = substr($item, $pos+1);
  2308. $file_path = substr($item, 0, $pos);
  2309. } else {
  2310. $file_name = $item;
  2311. $file_path = '';
  2312. }
  2313. if ($file_path == '.') $file_path = '';
  2314. $type_id = zdbq_single("SELECT id FROM {files} WHERE path = '%s' AND file = '%s'", array($file_path, $file_name));
  2315. if (empty($type_id)) {
  2316. if (zfile_check_location($zc['mp3_dir'].'/'.$file_path.'/'.$file_name, $zc['mp3_dir'])) {
  2317. zdb_log_stat('insertonly', $file_path, $file_name);
  2318. $type_id = zdbq_single("SELECT id FROM {files} WHERE path = '%s' AND file = '%s'", array($file_path, $file_name));
  2319. }
  2320. }
  2321. } elseif (preg_match('/\.lp$/i', $item)) {
  2322. $type = 'album';
  2323. $file_path = preg_replace('/\/\.lp$/i','',$item);
  2324. $type_id = zdbq_single("SELECT id FROM {dirs} WHERE path = '%s'", array($file_path));
  2325. if (empty($type_id)) {
  2326. if (zfile_check_location($zc['mp3_dir'].'/'.$file_path, $zc['mp3_dir'])) {
  2327. zdb_log_stat('insertonly', $file_path);
  2328. $type_id = zdbq_single("SELECT id FROM {dirs} WHERE path = '%s'", array($file_path));
  2329. }
  2330. }
  2331. } elseif (preg_match('/\.pls$/i', $item)) {
  2332. $type = 'playlist';
  2333. $pls_id_add = preg_replace('/\.pls/i','',$item);
  2334. $type_id = zdbq_single("SELECT id FROM {playlists} WHERE id = %d", array($pls_id_add));
  2335. } else {
  2336. $type_id = null;
  2337. }
  2338. if (!empty($type_id)) {
  2339. if ($pls_id == 'zina_session_playlist') {
  2340. #$item[] = array('type'=> $type, 'type_id' => $type_id, 'weight'=>$weight);
  2341. $pls_items = array();
  2342. if ($type == 'album') {
  2343. $type_id .= '/.lp';
  2344. } elseif ($type == 'playlist') {
  2345. $type_id .= '.pls';
  2346. }
  2347. $pls_items[] = $type_id;
  2348. $existing = (isset($_SESSION['z_sp'])) ? unserialize_utf8($_SESSION['z_sp']) : array();
  2349. $_SESSION['z_sp'] = utf8_encode(serialize(array_merge($existing, $pls_items)));
  2350. } else {
  2351. if (!zdbq("INSERT {playlists_map} (playlist_id, type, type_id, weight) VALUES (%d, '%s', %d, %d)",
  2352. array($pls_id, $type, $type_id, $weight))) {
  2353. zina_set_message(zt('Could not insert into playlist: @file', array('@file'=>$item)));
  2354. $error = true;
  2355. }
  2356. }
  2357. } else {
  2358. zina_set_message(zt('Could not find item[@pls]: @item', array('@pls'=>$pls_id, '@item'=>$item)));
  2359. $error = true;
  2360. }
  2361. $weight++;
  2362. }
  2363. if (($sum_items = zdbq_single("SELECT COUNT(*) FROM {playlists_map} WHERE playlist_id = %d", array($pls_id))) !== false) {
  2364. zdbq("UPDATE {playlists} SET sum_items = %d WHERE id = %d", array($sum_items, $pls_id));
  2365. }
  2366. return (!$error);
  2367. }
  2368. function zina_playlists_list_helper(&$playlists, $editable = true, $checkbox = false) {
  2369. global $zc;
  2370. foreach($playlists as $key => $playlist) {
  2371. $item = &$playlists[$key];
  2372. $pl = $playlist['id'];
  2373. $edit = ($editable && ($pl == 'zina_session_playlist' || zina_cms_access('edit_playlists', $playlist['user_id'])));
  2374. if ($zc['play']) {
  2375. $item['opts']['play'] = array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$pl);
  2376. if ($zc['play_rec_rand'])
  2377. $item['opts']['play_rec_rand'] = array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$pl.'&amp;rand');
  2378. }
  2379. if ($edit && $pl != 'zina_session_playlist') {
  2380. $item['options'][] = zl(zt("Edit"), null, 'l=44&amp;pl='.$pl);
  2381. $item['options'][] = zl(zt("Delete"), null, 'l=43&amp;pl='.$pl);
  2382. }
  2383. $item['image_link'] = $item['title_link'] = array('path' => null, 'query'=>'l=2&amp;pl='.$pl);
  2384. $item['title'] = htmlentities($playlist['playlist']);
  2385. $item['image'] = false;
  2386. $desc_opts = array();
  2387. if (!empty($item['date_created'])) $desc_opts['date_created'] = $item['date_created'];
  2388. $user = zina_cms_user($item['user_id']);
  2389. if ($user) {
  2390. if ($user['profile_url']) $desc_opts['profile_url'] = $user['profile_url'];
  2391. $desc_opts['username'] = $user['name'];
  2392. }
  2393. if ($zc['genres'] && !empty($item['genre'])) $desc_opts['genre'] = zl($item['genre'],'','l=13&amp;pl='.rawurlencode($item['genre']));
  2394. $stats = array();
  2395. if (isset($item['sum_items']) && !empty($item['sum_items'])) $stats['sum_items'] = $item['sum_items'];
  2396. if (isset($item['sum_views']) && !empty($item['sum_views'])) $stats['sum_views'] = $item['sum_views'];
  2397. if (isset($item['sum_plays']) && !empty($item['sum_plays'])) $stats['sum_plays'] = $item['sum_plays'];
  2398. $item['description'] = ztheme('playlist_description', $item['description'], $desc_opts, $stats, $item);
  2399. $item['new'] = $item['ratings'] = $item['checkbox'] = false;
  2400. # PLAYLIST LIST PAGE
  2401. $item['type'] = 'playlist';
  2402. $item['image'] = zina_content_search_image($item, 'search');
  2403. $item['ratings'] = $zc['pls_ratings'];
  2404. if ($checkbox && $pl != 'zina_session_playlist') {
  2405. $item['checkbox'] = array('name'=>'mp3s[]', 'value'=>$pl.'.pls', 'checked'=>false);
  2406. }
  2407. }
  2408. }
  2409. function zina_content_playlists_db(&$zina, $id = null) {
  2410. global $zc;
  2411. #TODO: need to verify pls access crap throughout
  2412. if (!($zc['playlists'] && ($zc['is_admin'] || $zc['pls_public'] || ($zc['pls_user'] && $zc['user_id'] > 0)))) return zina_access_denied();
  2413. $zina['title'] = zt('Playlists');
  2414. $count = 0;
  2415. $navigation = false;
  2416. $selected = array();
  2417. $page = (isset($_GET['page'])) ? '&amp;page='.$_GET['page'] : '';
  2418. $query = 'l=2'.$page;
  2419. if (!empty($id)) {
  2420. $query.='&amp;m='.$id;
  2421. $path = zdbq_single("SELECT path FROM {dirs} WHERE id = %d", array($id));
  2422. if (empty($path)) {
  2423. zina_set_message(zt('Sorry, there are no playlists'));
  2424. $zina['content'] = '';
  2425. return;
  2426. }
  2427. $title = ztheme('title',$path);
  2428. $title = zt('@album Tracks Appear on These Playlists', array('@album'=>$title));
  2429. #TEST
  2430. zina_content_breadcrumb($zina, '', $title, true);
  2431. }
  2432. $playlists = zina_playlist_pager_query($query, $count, $navigation, $selected, $id);
  2433. if ($zc['session_pls']) {
  2434. if (!isset($_GET['page']) || $_GET['page'] == 1) {
  2435. $results = (isset($_SESSION['z_sp'])) ? unserialize_utf8($_SESSION['z_sp']) : array();
  2436. $zsp = array('id'=>'zina_session_playlist','image_type'=>0,'playlist'=>zt('Session Playlist'),'description'=>'',
  2437. 'user_id' => 0, 'date_created'=>null, 'sum_items'=>sizeof($results), 'sum_votes'=>0,'sum_rating'=>0);
  2438. if (empty($playlists)) {
  2439. $playlists['zina_session_playlist'] = $zsp;
  2440. } else {
  2441. array_unshift($playlists, $zsp);
  2442. }
  2443. }
  2444. $count++;
  2445. }
  2446. if (!empty($playlists)) {
  2447. $checkbox = true;
  2448. zina_playlists_list_helper($playlists, true, $checkbox);
  2449. $form_id = 'pls-form';
  2450. $list_opts = ztheme('search_list_opts', zina_content_song_list_opts(false, false, $checkbox, $form_id, true), $form_id);
  2451. $form_attr = 'id="'.$form_id.'" action="'.zurl('', 'l=2').'"';
  2452. $zina['content'] = ztheme('playlists_list_db', $playlists, $count, $navigation, zurl('', $query), $form_attr, $list_opts, $selected, $checkbox);
  2453. } else {
  2454. zina_set_message(zt('Sorry, there are no playlists'));
  2455. $zina['content'] = '';
  2456. }
  2457. }
  2458. function zina_get_session_playlist() {
  2459. $songs = $dirs = $playlists = array();
  2460. $results = (isset($_SESSION['z_sp'])) ? unserialize_utf8($_SESSION['z_sp']) : array();
  2461. #todo: change .lp & .pls stuff to substr
  2462. foreach($results as $result) {
  2463. if (preg_match('/\.lp$/i', $result)) {
  2464. $dirs[] = preg_replace('/\/\.lp$/i','',$result);
  2465. } elseif (preg_match('/\.pls/i', $result)) {
  2466. $playlists[] = preg_replace('/\.pls/i','',$result);
  2467. } else {
  2468. $songs[] = $result;
  2469. }
  2470. }
  2471. if (!empty($songs)) {
  2472. $sql = "SELECT f.id as type_id, 'song' as type, IF(f.path!='.',CONCAT(f.path,IF(ISNULL(f.path), '','/'),f.file),f.file) AS path, ".
  2473. "f.id3_info, f.year, f.genre, f.sum_votes, f.sum_rating ".
  2474. "FROM {files} AS f ".
  2475. "WHERE f.id IN (".implode(',', $songs).")";
  2476. $result_songs = zdbq_assoc('type_id', $sql);
  2477. }
  2478. if (!empty($dirs)) {
  2479. $sql = "SELECT d.id as type_id, 'album' as type, d.path, ".
  2480. "d.title as id3_info, d.year, d.genre, d.sum_votes, d.sum_rating ".
  2481. "FROM {dirs} AS d ".
  2482. "WHERE d.id IN (".implode(',', $dirs).")";
  2483. $result_dirs = zdbq_assoc('type_id', $sql);
  2484. }
  2485. if (!empty($playlists)) {
  2486. $sql = "SELECT p.id as type_id, 'playlist' as type, p.id as path, p.title as id3_info, p.title, ".
  2487. "d.path as image_path, g.genre, p.image_type, p.id, p.sum_votes, p.sum_rating ".
  2488. "FROM {playlists} AS p ".
  2489. "LEFT OUTER JOIN {dirs} AS d ON (p.dir_id = d.id) ".
  2490. "LEFT OUTER JOIN {genres} AS g ON (p.genre_id = g.id) ".
  2491. "WHERE p.id IN (".implode(',', $playlists).")";
  2492. $result_playlists = zdbq_assoc('type_id', $sql);
  2493. }
  2494. foreach($results as $key => $val) {
  2495. $item = &$results[$key];
  2496. if (preg_match('/\.lp$/i', $val)) {
  2497. $dir_id = preg_replace('/\/\.lp$/i','',$val);
  2498. if (isset($result_dirs[$dir_id])) $item = $result_dirs[$dir_id];
  2499. } elseif (preg_match('/\.pls/i', $val)) {
  2500. $pls_id2 = preg_replace('/\.pls/i','',$val);
  2501. if (isset($result_playlists[$pls_id2])) $item = $result_playlists[$pls_id2];
  2502. } else {
  2503. if (isset($result_songs[$val])) $item = $result_songs[$val];
  2504. }
  2505. }
  2506. return $results;
  2507. }
  2508. function zina_content_playlist_db(&$zina, $path, $pls_id, $id = null) {
  2509. global $zc;
  2510. if (empty($pls_id)) return zina_content_playlists_db($zina, $id);
  2511. if ($pls_id == 'zina_session_playlist') {
  2512. if (!$zc['session_pls']) {
  2513. zina_set_message(zt('Access denied'), 'warn');
  2514. return zina_content_playlists_db($zina);
  2515. }
  2516. $reorder_access = true;
  2517. $edit_access = false;
  2518. $delete_access = true;
  2519. $results = zina_get_session_playlist();
  2520. $page['title'] = zt('Session');
  2521. $page['user_id'] = $zc['user_id'];
  2522. $page['type'] = 'playlist';
  2523. $page['image_type'] = 0;
  2524. $page['date_created'] = time();
  2525. $page['title'] = $title = zt('Session Playlist');
  2526. $page['image'] = zina_content_search_image($page, 'sub', 'genre-image');
  2527. $page['addthis'] = false;
  2528. } else {
  2529. $page = zina_playlist_get_info($pls_id);
  2530. if (!$page) {
  2531. zina_set_message(zt('Playlist not found'), 'warn');
  2532. return zina_content_playlists_db($zina);
  2533. }
  2534. zdb_log_stat_playlist($pls_id, 'views');
  2535. $user_rating = 0;
  2536. if ($zc['pls_ratings']) {
  2537. $page['pls_ratings'] = true;
  2538. $user_ratings = zdbq_assoc('playlist_id',"SELECT playlist_id, stat ".
  2539. "FROM {playlists_stats} ".
  2540. "WHERE playlist_id = %d AND user_id = %d AND stat_type = 3", array($pls_id, $zc['user_id']));
  2541. if (isset($user_ratings[$pls_id])) $user_rating = $user_ratings[$pls_id]['stat'];
  2542. }
  2543. $page['pls_rate_output'] = ztheme('vote', zurl('','l=68&pl='.$pls_id).'&n=', $user_rating);
  2544. # PLAYLIST VIEW PAGE
  2545. $page['type'] = 'playlist';
  2546. if (!empty($page['path'])) $page['image_path'] = $page['path'];
  2547. $page['description'] = zina_url_filter(nl2br($page['description']));
  2548. $page['addthis'] = $zina['addthis'];
  2549. $page['addthis_id'] = $zina['addthis_id'];
  2550. $page['addthis_options'] = $zina['addthis_options'];
  2551. $page['addthis_path'] = null;
  2552. $page['addthis_query'] = 'l=2&amp;pl='.$pls_id;
  2553. $page['site_name'] = $zina['site_name'];
  2554. #TODO:XXX playlist image size???
  2555. $page['image'] = zina_content_search_image($page, 'sub', 'genre-image');
  2556. if ($zc['genres'] && !empty($page['genre'])) {
  2557. $zina['dir_genre'] = zl($page['genre'],$path,'l=13&amp;pl='.rawurlencode($page['genre']));
  2558. }
  2559. $reorder_access = $edit_access = $delete_access = zina_cms_access('edit_playlists', $page['user_id']);
  2560. $results = zina_playlist_get_items($pls_id);
  2561. $title = zt('@title Playlist', array('@title'=>$page['title']));
  2562. }
  2563. $zina['title'] = $title;
  2564. $page['count'] = sizeof($results);
  2565. if ($page['count'] > 0) {
  2566. zina_set_js('file', 'extras/jquery.js');
  2567. zina_set_js('file', 'extras/drupal.js');
  2568. $opts['checkbox'] = $opts['submit'] = ($edit_access || $reorder_access);
  2569. zina_content_search_list($results, $opts['checkbox']);
  2570. if ($opts['checkbox']) {
  2571. foreach($results as $key => $val) {
  2572. $item = &$results[$key];
  2573. if ($val['type'] == 'song') {
  2574. $item['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($val['type_id']), 'checked'=>true);
  2575. } elseif ($val['type'] == 'playlist') {
  2576. $item['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($val['type_id']).'.pls', 'checked'=>true);
  2577. } else {
  2578. $item['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($val['type_id']).'/.lp', 'checked'=>true);
  2579. }
  2580. }
  2581. }
  2582. if ($zc['rss'] && $zc['database'] && $pls_id != 'zina_session_playlist') {
  2583. if ($zc['clean_urls']) {
  2584. $page['podcast']['url'] = $pls_id.'/pls.xml';
  2585. $page['podcast']['query'] = null;;
  2586. } else {
  2587. $page['podcast']['url'] = null;
  2588. $page['podcast']['query'] = 'l=70&amp;pl='.$pls_id;
  2589. }
  2590. $page['podcast']['type'] = ($zc['rss_podcast']) ? 'podcast' : 'rss';
  2591. zina_set_html_head('<link rel="alternate" type="application/rss+xml" title="'.zt('!title Podcast', array('!title'=>$zina['title'])).'" href="'.zurl($page['podcast']['url'], $page['podcast']['query']).'"/>');
  2592. }
  2593. $list = ztheme('playlist_list', $results, $zc['search_images'], $opts['checkbox']);
  2594. } else {
  2595. $list = zt('This playlist is empty.');
  2596. $opts['submit'] = $opts['checkbox'] = false;
  2597. }
  2598. $plopts['user']['play'] = ($zc['play']) ? array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$pls_id, 'attr'=>'class="zinamp"') : false;
  2599. if ($zc['play'] && $zc['play_rec_rand'])
  2600. $plopts['user']['play_rec_rand'] = ($zc['play']) ? array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$pls_id.'&amp;rand', 'attr'=>'class="zinamp"') : false;
  2601. $plopts['admin']['edit'] = $plopts['admin']['delete'] = false;
  2602. $user = zina_cms_user($page['user_id']);
  2603. if ($user) {
  2604. if ($user['profile_url']) $page['profile_url'] = $user['profile_url'];
  2605. $page['username'] = $user['name'];
  2606. }
  2607. if ($edit_access) $plopts['admin']['edit'] = array('path'=>null, 'query'=>'l=44&amp;pl='.$pls_id);
  2608. if ($delete_access) $plopts['admin']['delete'] = array('path'=>null, 'query'=>'l=43&amp;pl='.$pls_id);
  2609. $form_id = 'zinaplaylistform';
  2610. $form_attr = 'id="'.$form_id.'" action="'.zurl($path, 'l=41').'"';
  2611. $list .= '<input type="hidden" name="playlist" value="'.$pls_id.'"/>';
  2612. $list_opts = ztheme('playlist_list_opts', $opts, $form_id);
  2613. $zina['content'] = ztheme('playlists_section', $page, $form_attr, $list, $list_opts, $plopts);
  2614. }
  2615. # NON DB
  2616. function zina_content_playlists_view(&$zina) {
  2617. global $zc;
  2618. $zina['title'] = zt('Playlists');
  2619. $playlists = zina_get_playlists_custom();
  2620. if ($zc['session_pls']) {
  2621. if (empty($playlists)) {
  2622. $playlists[] = 'zina_session_playlist';
  2623. } else {
  2624. array_unshift($playlists, 'zina_session_playlist');
  2625. }
  2626. }
  2627. if (!empty($playlists)) {
  2628. foreach($playlists as $playlist) {
  2629. $item = null;
  2630. $pl = rawurlencode($playlist);
  2631. if ($zc['play']) {
  2632. $item['opts']['play'] = array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$pl);
  2633. }
  2634. $item['opts']['more'] = array('path'=>null, 'query'=>'l=2&amp;pl='.$pl);
  2635. if ($zc['is_admin'] && $zc['cache'] && $playlist != 'zina_session_playlist') {
  2636. $item['opts']['rename'] = array('path'=>null, 'query'=>'l=44&amp;pl='.$pl);
  2637. }
  2638. if ($zc['is_admin'] || ($zc['session_pls'] && $playlist == 'zina_session_playlist')) {
  2639. $item['opts']['delete'] = array('path'=>null, 'query'=>'l=43&amp;pl='.$pl);
  2640. }
  2641. $item['image_link'] = $item['title_link'] = array('path' => null, 'query' => 'l=2&amp;pl='.$pl);
  2642. $item['title'] = ($zc['session_pls'] && $playlist == 'zina_session_playlist') ? zt('Session Playlist') : htmlentities($playlist);
  2643. $items[] = $item;
  2644. }
  2645. $zina['content'] = ztheme('playlists_list',$items, $zina);
  2646. } else {
  2647. zina_set_message(zt('Sorry, there are no playlists'));
  2648. $zina['content'] = '';
  2649. }
  2650. }
  2651. function zina_content_playlists(&$zina, $path, $playlist) {
  2652. global $zc;
  2653. if ($zc['session_pls'] && $playlist == 'zina_session_playlist') {
  2654. $sp = true;
  2655. } else {
  2656. $sp = false;
  2657. $filename = $zc['cache_pls_dir'].'/_zina_'.$playlist.'.m3u';
  2658. $edit = (!empty($playlist) && file_exists($filename));
  2659. }
  2660. if ($sp || $edit) { # Edit Playlist
  2661. if ($sp) {
  2662. $songs = (isset($_SESSION['z_sp'])) ? unserialize_utf8($_SESSION['z_sp']) : array();
  2663. $title = zt('Session Playlist');
  2664. } else {
  2665. $title = zt('@title Playlist', array('@title'=>$playlist));
  2666. $songs = zunserialize_alt(file_get_contents($filename));
  2667. }
  2668. $zina['title'] = $title;
  2669. $count = sizeof($songs);
  2670. if ($count > 0) {
  2671. $download = $zc['download'];
  2672. #todo: similar loop with search...combine?
  2673. foreach($songs as $song) {
  2674. $play = $zc['play'];
  2675. $rem_title = false;
  2676. $item = array();
  2677. $arr = explode('/', $song);
  2678. $num = sizeof($arr);
  2679. $item['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($song), 'checked'=>true);
  2680. $type = (preg_match('/\.('.$zc['ext_mus'].')$/i', $song) || ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $song))) ? 's' : 'a';
  2681. if ($type == 's') {
  2682. if ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $song, $matches)) {
  2683. $rem = new remoteFile($zc['mp3_dir'].'/'.$song, false, true);
  2684. if ($play && isset($rem->url)) {
  2685. $item['opts']['play'] = array('path'=>$song, 'query'=>'l=8&amp;m=1');
  2686. if (isset($rem->title)) $rem_title = $rem->title;
  2687. } else {
  2688. $play = false;
  2689. }
  2690. if ($zc['download'] && isset($rem->download)) {
  2691. $item['opts']['download'] = array('path'=>$song, 'query'=>'l=12');
  2692. }
  2693. } else {
  2694. if ($play) {
  2695. $item['opts']['play'] = array('path'=>$song, 'query'=>'l=8&amp;m=1');
  2696. }
  2697. if ($download) {
  2698. $item['opts']['download'] = array('path'=>$song, 'query'=>'l=12');
  2699. }
  2700. }
  2701. } else {
  2702. zina_content_subdir_opts($item, preg_replace('/\/\.lp$/i','',$song), false, NULL);
  2703. }
  2704. $item['title'] = zina_content_pathlinks($song, $type, $play, $rem_title);
  2705. $items[] = $item;
  2706. }
  2707. zina_set_js('file', 'extras/jquery.js');
  2708. zina_set_js('file', 'extras/drupal.js');
  2709. $list = ztheme('playlists_list',$items, $zina, true);
  2710. $opts['checkbox'] = $opts['submit'] = (($zc['is_admin'] && $zc['cache']) || ($zc['session_pls'] && $playlist == 'zina_session_playlist'));
  2711. } else {
  2712. $list = zt('This playlist is empty.');
  2713. $opts['submit'] = $opts['checkbox'] = false;
  2714. }
  2715. $pl = rawurlencode($playlist);
  2716. $plopts['edit'] = $plopts['delete'] = false;
  2717. $plopts['play'] = ($zc['play']) ? array('path'=>null, 'query'=>'l=8&amp;m=3&amp;pl='.$pl) : false;
  2718. if ($zc['is_admin'] && $zc['cache'] && $playlist != 'zina_session_playlist') {
  2719. $plopts['rename'] = array('path'=>null, 'query'=>'l=44&amp;pl='.$pl);
  2720. }
  2721. if ($zc['is_admin'] || ($zc['session_pls'] && $playlist == 'zina_session_playlist')) {
  2722. $plopts['delete'] = array('path'=>null, 'query'=>'l=43&amp;pl='.$pl);
  2723. }
  2724. $form_id = 'zinaplaylistform';
  2725. $form_attr = 'id="'.$form_id.'" action="'.zurl($path, 'l=41').'"';
  2726. $list .= '<input type="hidden" name="playlist" value="'.$playlist.'"/>';
  2727. $list_opts = ztheme('playlist_list_opts', $opts, $form_id);
  2728. $zina['content'] = ztheme('playlists_section',array('title'=>$title, 'count'=>$count),$form_attr,$list,$list_opts, $plopts);
  2729. } else { # View Playlists
  2730. zina_content_playlists_view($zina);
  2731. }
  2732. }
  2733. function zina_content_blurb(&$zina, $path, $opts) {
  2734. global $zc;
  2735. $alt_title = $hidden = $text = '';
  2736. $set_title = $seed = false;
  2737. $rows = array();
  2738. $type = $opts['type'];
  2739. $return = (isset($opts['return']));
  2740. $label = -1;
  2741. $url = (isset($_SERVER['HTTP_REFERER'])) ? parse_url($_SERVER['HTTP_REFERER']) : false;
  2742. $help = true;
  2743. switch($type) {
  2744. Case 1 : #DIR
  2745. $dir = zina_get_directory($path);
  2746. $title = $dir['title'];
  2747. $file = $zc['dir_file'];
  2748. if (empty($path)) {
  2749. $display_path = $zc['main_dir_title'];
  2750. } else {
  2751. $display_path = $path;
  2752. $alt_title = $title;
  2753. $seed = true;
  2754. }
  2755. if ($zc['database']) {
  2756. #TODO: make empty path be treated like a normal dir...
  2757. if (empty($path)) {
  2758. $text = utf8_decode(zdbq_single("SELECT description FROM {dirs} WHERE path = '.'"));
  2759. } else {
  2760. $text = utf8_decode(zdbq_single("SELECT description FROM {dirs} WHERE path = '%s'", $path));
  2761. }
  2762. }
  2763. $text_file = $zc['cur_dir'].'/'.$file;
  2764. break;
  2765. Case 2 : #ALT
  2766. $seed = true;
  2767. $dir = zina_get_directory($path);
  2768. $alt_title = $title = $dir['title'];
  2769. $lang = zina_get_settings('lang');
  2770. $titles = &$lang['titles'];
  2771. $subs = &$lang['subs'];
  2772. if ($zc['database']) {
  2773. $other = zdb_get_others($path);
  2774. if (isset($other['alt_items']) && !empty($other['alt_items'])) $text = $other['alt_items'];
  2775. }
  2776. if (empty($text)) {
  2777. $file = $zc['alt_file'];
  2778. $text_file = $zc['cur_dir'].'/'.$file;
  2779. $text = (file_exists($text_file)) ? zunserialize_alt(file_get_contents($text_file)) : array();
  2780. }
  2781. $rows[] = array('label'=>-1,'item'=>$subs['alt_dirs']);
  2782. $label = $title = $titles['alt_dirs'];
  2783. $dirs = zina_core_cache('dirs');
  2784. if (!empty($dirs)) {
  2785. $row = '<select size="10" multiple name="mp3s[]">';
  2786. foreach($dirs as $d) {
  2787. $selected = (in_array($d, $text)) ? ' selected="selected"' : '';
  2788. $val = (empty($d)) ? $zc['main_dir_title'] : htmlentities($d);
  2789. $row .= '<option value="'.zrawurlencode($d).'"'.$selected.'>'.$val.'</option>';
  2790. }
  2791. $row .= '</select>';
  2792. $rows[] = array('label'=>$label,'item'=>$row);
  2793. }
  2794. break;
  2795. Case 4 : #MM
  2796. $title = preg_replace('/\.('.$zc['mm_ext'].')$/i', '', basename($path));
  2797. $file = $path.'.txt';
  2798. $text_file = $zc['mp3_dir'].'/'.$file;
  2799. $dir = zina_get_directory(dirname($path));
  2800. $display_path = dirname($path);
  2801. $alt_title = $dir['title'];
  2802. $seed = true;
  2803. $set_title = true;
  2804. break;
  2805. Case 5 : #PODCAST
  2806. $label = zt('Podcast');
  2807. $dir = zina_get_directory($path);
  2808. $alt_title = $title = $dir['title'];
  2809. $seed = true;
  2810. $help = false;
  2811. if ($zc['database']) {
  2812. $other = zdb_get_others($path);
  2813. if (isset($other['rss']) && !empty($other['rss'])) $text = utf8_decode($other['rss']);
  2814. }
  2815. if (empty($text)) {
  2816. $file = $zc['rss_file'];
  2817. $text_file = $zc['cur_dir'].'/'.$file;
  2818. if (!file_exists($text_file)) {
  2819. $text = zina_content_rss($path);
  2820. $text = utf8_decode($text);
  2821. }
  2822. }
  2823. break;
  2824. Case 6 : # GENRE DESC
  2825. $term = $_GET['pl'];
  2826. $text_file = $zc['cache_dir_private_abs'].'/genre_desc_'.rawurlencode($term).'.txt';
  2827. if (!zfile_check_location($zc['cache_dir_private_abs'], $text_file)) $text_file = false;
  2828. $display_path = $title = htmlentities($term);
  2829. $text = zdbq_single("SELECT description FROM {genres} WHERE genre = '%s'", array($term));
  2830. $hidden = ztheme('form_hidden','playlist',$term);
  2831. break;
  2832. Case 3: # songs
  2833. Default: # SONG EXTRAS
  2834. if ($type == 3 || ($zc['song_extras'] && in_array($type, $zc['song_es_exts']))) {
  2835. if ($type != 3) {
  2836. $label = $zc['song_es'][$type]['name'];
  2837. $url['path'] = $path;
  2838. }
  2839. if ($zc['database']) {
  2840. $result = zdbq_array_single("SELECT description, other, id3_info FROM {files} WHERE path = '%s' AND file = '%s'", dirname($path), basename($path));
  2841. if (!empty($result)) {
  2842. if ($type == 3) {
  2843. $text = utf8_decode($result['description']);
  2844. } else {
  2845. $other = unserialize_utf8($result['other']);
  2846. if (isset($other[$type])) $text = $other[$type];
  2847. }
  2848. $mp3 = unserialize_utf8($result['id3_info']);
  2849. if (isset($mp3->title)) $title = ztheme('song_title', $mp3->title, true);
  2850. if ($type == 'lyr' && empty($text) && isset($mp3->lyrics) && !empty($mp3->lyrics)) {
  2851. $text = $mp3->lyrics;
  2852. }
  2853. }
  2854. } elseif ($type == 'lyr') {
  2855. $mp3 = zina_get_file_info($zc['mp3_dir'].'/'.$path);
  2856. if (isset($mp3->lyrics) && !empty($mp3->lyrics)) $text = $mp3->lyrics;
  2857. }
  2858. $id3 = $zc['mp3_id3'];
  2859. if (empty($text)) {
  2860. if ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $path)) {
  2861. $ext = $zc['remote_ext'];
  2862. $id3 = true;
  2863. } elseif ($zc['fake'] && preg_match('/\.('.$zc['fake_ext'].')$/i', $path)) {
  2864. $ext = $zc['fake_ext'];
  2865. } else {
  2866. $ext = $zc['ext_mus'];
  2867. }
  2868. $file_ext = ($type == 3) ? 'txt' : $type;
  2869. $file = preg_replace('/\.('.$ext.')$/i', '.'.$file_ext, $path);
  2870. $text_file = $zc['mp3_dir'].'/'.$file;
  2871. }
  2872. if (empty($title)) {
  2873. $title = zina_content_song_title($zc['mp3_dir'].'/'.$path, $id3);
  2874. }
  2875. $dir = zina_get_directory(dirname($path));
  2876. $display_path = dirname($path);
  2877. $alt_title = $dir['title'];
  2878. $seed = true;
  2879. $set_title = true;
  2880. } else {
  2881. return zina_not_found();
  2882. }
  2883. break;
  2884. }
  2885. if (!isset($display_path)) $display_path = preg_replace('/\.('.$zc['ext_mus'].')$/i', '', $path);
  2886. zina_content_breadcrumb($zina, $display_path, $alt_title, $seed);
  2887. if ($set_title) {
  2888. $zina['title'] = ztheme('page_title', array($zina['title'], $title));
  2889. }
  2890. $ajax_url = false;
  2891. if ($type == 2) {
  2892. } else {
  2893. if (empty($text)) $text = (file_exists($text_file)) ? utf8_decode(file_get_contents($text_file)) : '';
  2894. if ($return) return array('output'=>$text, 'title'=>$title);
  2895. $id = '';
  2896. if (empty($text) && isset($zc['third_'.$type]) && $zc['third_'.$type]) {
  2897. $ajax_url = zurl($path, 'l=57&m='.$type);
  2898. zina_set_js('file', 'extras/jquery.js');
  2899. $id = ' id="zina-'.$type.'"';
  2900. if (!$zc['third_'.$type.'_save']) {
  2901. zina_set_message(zt('If lyrics are present, they have not been saved.'));
  2902. }
  2903. }
  2904. $rows[] = array(
  2905. 'label'=>$label,
  2906. 'item'=>'<textarea name="mp3s" cols="70" rows="20" wrap="virtual"'.$id.'>'.htmlentities($text).'</textarea>',
  2907. 'help'=> ($help) ? zt('HTML tags allowed: @tags', array('@tags' => $zc['cms_tags'])) : false,
  2908. );
  2909. }
  2910. $space = ($label == -1) ? -1 : null;
  2911. $rows[] = array('label'=>$space,'item'=>'<input type="submit" value="'.zt('Submit').'"/>');
  2912. $form = array(
  2913. 'title'=>$title,
  2914. 'attr'=>'action="'.zurl($path, 'l=23&amp;m='.$type).'"',
  2915. 'hidden'=>$hidden,
  2916. 'rows'=>$rows
  2917. );
  2918. $zina['content'] = ztheme('blurb',$form, $type, $ajax_url);
  2919. }
  2920. function zina_save_blurb($path, $m, $songs, $playlist = null, $goto = true) {
  2921. global $zc;
  2922. $success = false;
  2923. $cache_path = $path;
  2924. $query = null;
  2925. $check_loc = $zc['mp3_dir'];
  2926. if ($m == 1) { # DIR
  2927. $cd = $zc['cur_dir'];
  2928. $file = $zc['dir_file'];
  2929. $songs = zina_filter_html($songs, $zc['cms_tags']);
  2930. if ($zc['database']) {
  2931. zdb_log_stat('insertonly', $path);
  2932. if (empty($path)) {
  2933. $success = zdbq("UPDATE {dirs} SET description = '%s' WHERE path = '.' AND parent_id = 0", array($songs));
  2934. } else {
  2935. $success = zdbq("UPDATE {dirs} SET description = '%s' WHERE path = '%s'", array($songs, $path));
  2936. }
  2937. }
  2938. } elseif ($m == 2) { # ALT
  2939. $cd = $zc['cur_dir'];
  2940. $file = $zc['alt_file'];
  2941. $mp3s = array();
  2942. foreach($songs as $song) {
  2943. $fp = $zc['mp3_dir'].'/'.zrawurldecode($song);
  2944. if (file_exists($fp) && is_dir($fp)) {
  2945. $mp3s[] = zrawurldecode($song);
  2946. } else {
  2947. zina_debug(zt('@file does not exist.',array('@file'=>$fp)),'warn');
  2948. }
  2949. }
  2950. $songs = (!empty($mp3s)) ? serialize($mp3s) : '';
  2951. if ($zc['database']) {
  2952. $result = zdb_update_others(array('alt_items'=>$mp3s), $path);
  2953. }
  2954. } elseif ($m == 3 || $m == 4) { # Song or MM
  2955. $cd = dirname($zc['cur_dir']);
  2956. $filename = basename($path);
  2957. $path = dirname($path);
  2958. if ($path == '.') $path = '';
  2959. $songs = zina_filter_html($songs, $zc['cms_tags']);
  2960. if ($m == 3) {
  2961. if ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $filename)) {
  2962. $file = preg_replace('/\.('.$zc['remote_ext'].')$/i', '.txt', $filename);
  2963. } elseif ($zc['fake'] && preg_match('/\.('.$zc['fake_ext'].')$/i', $filename)) {
  2964. $file = preg_replace('/\.('.$zc['fake_ext'].')$/i', '.txt', $filename);
  2965. } else {
  2966. $file = preg_replace('/\.('.$zc['ext_mus'].')$/i', '.txt', $filename);
  2967. }
  2968. } else {
  2969. $file = $filename.'.txt';
  2970. }
  2971. if ($zc['database']) {
  2972. zdb_log_stat('insertonly', $path, $filename);
  2973. #$success = zdbq("UPDATE {files} SET description = '%s', mtime = %d WHERE path = '%s' AND file = '%s'", array($songs, time(), $path, $filename));
  2974. $success = zdbq("UPDATE {files} SET description = '%s' WHERE path = '%s' AND file = '%s'", array($songs, $path, $filename));
  2975. }
  2976. } elseif ($m == 5) { # PODCAST
  2977. $cd = $zc['cur_dir'];
  2978. $file = $zc['rss_file'];
  2979. if ($zc['database']) $result = zdb_update_others(array('rss'=>$songs), $path);
  2980. $songs = utf8_encode($songs);
  2981. } elseif ($m == 6) { # GENRE DESC
  2982. $check_loc = $cd = $zc['cache_dir_private_abs'];
  2983. $file = 'genre_desc_'.rawurlencode($playlist).'.txt';
  2984. $songs = zina_filter_html($songs, $zc['cms_tags']);
  2985. if ($zc['database']) {
  2986. zdbq("UPDATE {genres} SET description = '%s' WHERE genre = '%s'", array($songs, $playlist));
  2987. }
  2988. $query = 'l=13&pl='.rawurlencode($playlist);
  2989. } elseif ($zc['song_extras'] && in_array($m, $zc['song_es_exts'])) {
  2990. #TODO: similar to 3 & 4 (see "entry")
  2991. $cd = dirname($zc['cur_dir']);
  2992. $filename = basename($path);
  2993. $path = dirname($path);
  2994. if ($path == '.') $path = '';
  2995. $songs = zina_filter_html($songs, $zc['cms_tags']);
  2996. if ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $filename)) {
  2997. $file = preg_replace('/\.('.$zc['remote_ext'].')$/i', '.'.$m, $filename);
  2998. } elseif ($zc['fake'] && preg_match('/\.('.$zc['fake_ext'].')$/i', $filename)) {
  2999. $file = preg_replace('/\.('.$zc['fake_ext'].')$/i', '.'.$m, $filename);
  3000. } else {
  3001. $file = preg_replace('/\.('.$zc['ext_mus'].')$/i', '.'.$m, $filename);
  3002. }
  3003. if ($zc['database']) $result = zdb_update_others(array($m=>$songs), $path, $filename);
  3004. } else {
  3005. return zina_not_found();
  3006. }
  3007. $text_file = $cd.'/'.$file;
  3008. if (is_writeable($cd) && zfile_check_location($text_file, $check_loc)) {
  3009. $emptytest = trim($songs);
  3010. if (!empty($emptytest)) {
  3011. if (file_put_contents($text_file, $songs)) {
  3012. if ($goto) zina_set_message(zt('Updated.'));
  3013. $success = true;
  3014. } else {
  3015. zina_set_message(zt('Could not write file.'), 'error');
  3016. }
  3017. } else {
  3018. if (file_exists($text_file)) unlink($text_file);
  3019. }
  3020. } else {
  3021. if (!$zc['database']) {
  3022. zina_set_message(zt('Cannot save. Directory is not writeable.'),'error');
  3023. }
  3024. }
  3025. if ($success && $zc['cache_tmpl']) {
  3026. if (!zina_delete_tmpl_file(zina_get_tmpl_cache_file($cache_path))) {
  3027. zina_set_message(zt('Cannot delete cache file'),'error');
  3028. }
  3029. if ($cache_path != $path) zina_delete_tmpl_file(zina_get_tmpl_cache_file($path));
  3030. }
  3031. if ($goto) {
  3032. zina_goto($path, $query);
  3033. } else {
  3034. return $success;
  3035. }
  3036. }
  3037. function zina_content_directory_opts(&$zina, $path) {
  3038. global $zc;
  3039. $query = 'l=77';
  3040. $lang = zina_get_settings('lang');
  3041. $titles = &$lang['titles'];
  3042. $cats = &$lang['cats'];
  3043. $subs = &$lang['subs'];
  3044. $titles += array(
  3045. 'person' => zt('Person'),
  3046. 'image' => zt('Default Image'),
  3047. 'category' => $cats['categories']['t'],
  3048. 'images' => $titles['cat_images'],
  3049. 'cols' => $titles['cat_cols'],
  3050. 'truncate' => $titles['cat_truncate'],
  3051. 'split' => $titles['cat_split'],
  3052. 'sort' => $titles['cat_sort'],
  3053. 'sort_default' => $titles['cat_sort_default'],
  3054. 'pp' => $titles['cat_pp'],
  3055. );
  3056. $subs['person'] = zt('Assume last name first for sorting');
  3057. $fields = zina_get_settings('directory');
  3058. $dir = zina_get_directory($path);
  3059. $over = true;
  3060. if (empty($path) || $path == '.') {
  3061. $dir['title'] = $zina['lang']['main_dir_title'];
  3062. $over = false;
  3063. }
  3064. $zina['title'] = $dir['title'];
  3065. zina_content_breadcrumb($zina, $path, $zina['title'], $over);
  3066. if (isset($_POST) && !empty($_POST)) { # SAVE SETTINGS
  3067. $settings = array();
  3068. $errors = false;
  3069. $fields['directory_opts']['image'] = array('type'=>'select');
  3070. foreach($fields as $cat => $x) {
  3071. foreach($x as $name => $field) {
  3072. $input = (isset($_POST[$name])) ? $_POST[$name] : null;
  3073. if (isset($field['v'])) {
  3074. foreach($field['v'] as $key => $type) {
  3075. $opts = null;
  3076. if (is_array($type)) {
  3077. $opts = $type;
  3078. $type = $key;
  3079. }
  3080. if (!zina_validate($type, $input, $opts)) {
  3081. $errors = true;
  3082. $title = $titles[$name];
  3083. if ($opts) $type = current($opts);
  3084. zina_validate_error_message($type, $title, $input);
  3085. continue 2;
  3086. }
  3087. }
  3088. } elseif ($name == 'image') {
  3089. if (empty($dir['images'])) {
  3090. continue;
  3091. } else {
  3092. if (!in_array($input, $dir['images'])) {
  3093. $errors = true;
  3094. zina_set_message(zt('Unknown image: @image', array('@image'=>$input)), 'error');
  3095. }
  3096. }
  3097. }
  3098. if (is_array($input)) $input = serialize($input);
  3099. $settings[$name] = $input;
  3100. }
  3101. }
  3102. #dir_tags?
  3103. if ($settings['category']) {
  3104. unset($settings['category']);
  3105. $cat_out = '<category>'."\n";
  3106. foreach(array('images', 'cols', 'truncate', 'split', 'sort', 'sort_default', 'pp') as $cat_item) {
  3107. $settings['category'][$cat_item] = $settings[$cat_item];
  3108. $cat_out .= '<'.$cat_item.'>'.$settings[$cat_item].'</'.$cat_item.'>'."\n";
  3109. unset($settings[$cat_item]);
  3110. }
  3111. $cat_out .= '</category>'."\n";
  3112. } else {
  3113. foreach(array('images', 'cols', 'truncate', 'split', 'sort', 'sort_default', 'pp') as $cat_item) {
  3114. unset($settings[$cat_item]);
  3115. }
  3116. }
  3117. if (!$errors && zdb_update_others($settings, $path)) {
  3118. zina_set_message(zt('Directory Options Updated'));
  3119. if ($dir['dir_write']) {
  3120. $var_file = $zc['cur_dir'].'/'.$zc['various_file'];
  3121. if ($settings['various']) {
  3122. touch($var_file);
  3123. } else {
  3124. if (file_exists($var_file)) unlink($var_file);
  3125. }
  3126. $cat_file = $zc['cur_dir'].'/'.$zc['cat_file'];
  3127. if ($settings['category']) {
  3128. file_put_contents($cat_file, $cat_out);
  3129. } else {
  3130. if (file_exists($cat_file)) unlink($cat_file);
  3131. }
  3132. }
  3133. } else {
  3134. zina_set_message(zt('Directory Options Not Updated'), 'error');
  3135. }
  3136. }
  3137. $category = false;
  3138. $other = zdb_get_others($path);
  3139. $other['various'] = ($dir['various'] || (isset($other['various']) && $other['various']));
  3140. if (isset($other['category']) && $other['category']) {
  3141. $category = $other['category'];
  3142. } else {
  3143. $category = zina_is_category($zc['cur_dir']);
  3144. }
  3145. if ($category) {
  3146. $other['category'] = 1;
  3147. foreach($category as $key => $val) {
  3148. $other[$key] = $val;
  3149. }
  3150. }
  3151. if (!empty($dir['images'])) {
  3152. $images = $dir['images'];
  3153. foreach($images as $key => $item) {
  3154. $images[$item] = $item;
  3155. unset($images[$key]);
  3156. }
  3157. $image = (isset($other['image'])) ? $other['image'] : zina_get_dir_item($zc['mp3_dir'].'/'.$path,'/\.('.$zc['ext_graphic'].')$/i');
  3158. $img = ztheme('image', zina_get_image_url($path, $image,'sub'), $image, null, 'class="dir-image"');
  3159. } else {
  3160. $images = array(''=>zt('None'));
  3161. $image = $img = '';
  3162. }
  3163. $fields['directory_opts']['image'] = array('type'=>'select', 'opts'=>$images, 'def'=>$image);
  3164. $subs['image'] = '<div id="directory-image" class="directory-image">'.$img.'</div>';
  3165. $cats['directory_opts']['t'] = zt('Directory Options');
  3166. $cats['directory_opts']['d'] = '';
  3167. $rows = array();
  3168. foreach($fields as $cat => $x) {
  3169. $items = null;
  3170. foreach($x as $name => $field) {
  3171. $value = isset($other[$name]) ? $other[$name] : null;
  3172. $item = zina_content_form_helper($name, $field, $value);
  3173. $row = array('label'=>$titles[$name], 'item'=>$item);
  3174. if (isset($subs[$name])) $row['desc'] = $subs[$name];
  3175. $items[] = $row;
  3176. if (isset($field['break'])) $items[] = array('label'=>-1,'item'=>'<hr/>');
  3177. }
  3178. $item = ztheme('admin_section_header', $cats[$cat]['t'], $cat, $query);
  3179. /*
  3180. $desc = $cats[$cat]['d'];
  3181. if (!empty($desc)) {
  3182. if (is_array($desc)) {
  3183. $output = '';
  3184. foreach ($desc as $d) $output .= '<p>'.$d.'</p>';
  3185. $item .= $output;
  3186. } else {
  3187. $item .= '<em>'.$desc.'</em>';
  3188. }
  3189. }
  3190. */
  3191. $rows[] = array('label'=>-1, 'item'=>$item);
  3192. $rows = array_merge($rows, $items);
  3193. }
  3194. $rows[] = array('label'=>-1, 'item'=>'<input type="submit" value="'.zt('Update').'"/>', 'class'=>'center');
  3195. $lang_while = zt('This could take a while.');
  3196. $lang_sure = zt('Are your sure you want to do this?');
  3197. $funcs = array();
  3198. if ($zc['is_admin']) {
  3199. if ($zc['database']) {
  3200. $funcs['regen'] = array(
  3201. 'title' => zt('Update Database'),
  3202. 'help' => zt('This will re-synchronize or add directory to the database.').' '.zt('Not usually necessary.'),
  3203. 'path'=>$path,
  3204. 'query'=>'l=45'
  3205. );
  3206. }
  3207. if ($dir['dir_write'] && $path != '') {
  3208. $funcs['dir_rename'] = array(
  3209. 'title' => zt('Rename Directory'),
  3210. 'help' => ($zc['dir_tags']) ? zt('This will have no affect if this is an album and ID3 tags are present.') : '',
  3211. 'path'=>$path,
  3212. 'query'=>'l=78');
  3213. }
  3214. }
  3215. if (!empty($funcs)) {
  3216. $output = '<ul class="zina-list">';
  3217. foreach ($funcs as $i) {
  3218. $output .= '<li class="zina-list">'.zl($i['title'], $i['path'], $i['query']);
  3219. if (isset($i['help']) && !empty($i['help'])) $output .= '<br/><small>'.$i['help'].'</small>';
  3220. $output .= '</li>';
  3221. }
  3222. $output .= '</ul>';
  3223. $row1 = array('label'=>-1, 'item'=> ztheme('admin_section_header', zt('Directory Functions'), 'top').'<br/>'.$output);
  3224. array_unshift($rows,$row1);
  3225. }
  3226. $form = array(
  3227. 'attr'=>'action="'.zurl($path, $query).'" id="zina-dir-form"',
  3228. 'rows'=>$rows,
  3229. );
  3230. $zina['content'] = ztheme('config',$form);
  3231. }
  3232. function zina_content_3rd_images($path, $m) {
  3233. global $zc;
  3234. $extra_opts = zina_get_extras_images_opts();
  3235. if (!empty($path) && in_array($m, array_keys($extra_opts))) {
  3236. $source = $extra_opts[$m];
  3237. require_once($zc['zina_dir_abs'].'/extras/extras_images_'.$source.'.php');
  3238. if (isset($_SESSION['zina_extra_images'][$path])) {
  3239. $artist = $_SESSION['zina_extra_images'][$path]['artist'];
  3240. $album = $_SESSION['zina_extra_images'][$path]['album'];
  3241. } else {
  3242. unset($_SESSION['zina_extra_images']);
  3243. $artist = $album = null;
  3244. $dir = zina_get_directory($path);
  3245. if ($dir['files']) {
  3246. $current = current($dir['files']);
  3247. } elseif ($dir['subdirs']) {
  3248. $current = current($dir['subdirs']);
  3249. } else {
  3250. #EMPTY DIRECTORY...
  3251. $dir['subdirs'] = array('title'=>$path);
  3252. $current = array('title'=>$path);
  3253. }
  3254. if (isset($current['info'])) {
  3255. $mp3 = &$current['info'];
  3256. if ($mp3->tag) {
  3257. if (isset($mp3->artist)) $artist = $mp3->artist;
  3258. if (isset($mp3->album)) $album = $mp3->album;
  3259. }
  3260. }
  3261. if ($dir['subdirs']) { # ARTIST
  3262. if (empty($artist)) $artist = $current['title'];
  3263. $album = null;
  3264. } else { # ALBUM
  3265. if (empty($album)) $album = $current['title'];
  3266. if (empty($artist)) {
  3267. $x = explode('/', $path);
  3268. $len = sizeof($x);
  3269. if ($len > 1) {
  3270. $artist = $x[$len - 2];
  3271. } else {
  3272. echo zt('Error');
  3273. exit;
  3274. }
  3275. }
  3276. }
  3277. $_SESSION['zina_extra_images'][$path]['artist'] = $artist;
  3278. $_SESSION['zina_extra_images'][$path]['album'] = $album;
  3279. }
  3280. $result = false;
  3281. if (isset($_SESSION['zina_images_source'][$path][$source]) && !empty($_SESSION['zina_images_source'][$path][$source])) {
  3282. $result = array_pop($_SESSION['zina_images_source'][$path][$source]);
  3283. } elseif (($results = call_user_func('zina_extras_images_'.$source, $artist, $album)) !== false) {
  3284. $num = sizeof($results);
  3285. if ($num == 1) {
  3286. $result = $results[0];
  3287. } elseif ($num > 1) {
  3288. $result = array_pop($results);
  3289. $_SESSION['zina_images_source'][$path][$source] = $results;
  3290. }
  3291. }
  3292. if ($result) {
  3293. $output = '';
  3294. $src = (isset($result['thumbnail_url'])) ? $result['thumbnail_url'] : $result['image_url'];
  3295. $output .= '<img src="'.$src.'" />';
  3296. #TODO: have opt to display artist summaries...elsewhere
  3297. #if (isset($result['summary'])) echo $result['summary'];
  3298. $save_url = zurl($path, 'l=61&amp;img='.rawurlencode($result['image_url']));
  3299. $class = "zina-newimg-".$m;
  3300. $output .= '<div class="'.$class.'"><a href="'.$result['source_url'].'">'.$source.'</a>';
  3301. if (isset($result['size'])) $output .= ' ('.$result['size'].')';
  3302. if (isset($result['thumbnail_url'])) $output .= ' | <a href="'.$result['image_url'].'">'.zt('View Original').'</a>';
  3303. $output .= ' | <a href="'.$save_url.'" onclick="zinaSaveImage(\''.$save_url.'\',\''.$class.'\'); return false;">'.zt('Save this image').'</a></div>';
  3304. echo $output;
  3305. } else {
  3306. if ($zc['debug']) echo $source.': '.zt('Not found: ').$artist.'->'.$album;
  3307. }
  3308. }
  3309. }
  3310. function zina_content_sitemap() {
  3311. global $zc;
  3312. $dirs = zina_core_cache('dirs');
  3313. $items = array();
  3314. $mp3_dir = $zc['mp3_dir'];
  3315. $item['mtime'] = filemtime($mp3_dir);
  3316. $item['url'] = zurl('',NULL,NULL,TRUE);
  3317. $item['priority'] = .8;
  3318. $items[] = $item;
  3319. foreach($dirs as $dir) {
  3320. $path = $mp3_dir.'/'.$dir;
  3321. if (!empty($dir) && file_exists($path) && is_dir($path)) {
  3322. $item = null;
  3323. $item['path'] = $path;
  3324. $item['mtime'] = filemtime($path);
  3325. $item['url'] = zurl($dir,NULL,NULL,TRUE);
  3326. $items[] = $item;
  3327. }
  3328. }
  3329. if ($items) {
  3330. return ztheme('sitemap', $items);
  3331. }
  3332. return false;
  3333. }
  3334. function zina_content_rss($path) {
  3335. global $zc;
  3336. if ($zc['database']) {
  3337. $other = zdb_get_others($path);
  3338. if (isset($other['rss']) && !empty($other['rss'])) {
  3339. return $other['rss'];
  3340. }
  3341. }
  3342. $rss['page_url'] = preg_replace('/&([^a])/','&amp;${1}', zurl($path,NULL,NULL,TRUE));
  3343. $rss['link_url'] = $rss['page_url'].'/'.$zc['rss_file'];
  3344. $direct = preg_match('#^'.$_SERVER['DOCUMENT_ROOT'].'#i', $zc['mp3_dir']);
  3345. $zina = array();
  3346. zina_content_breadcrumb($zina, $path);
  3347. $rss['title'] = $zina['title'];
  3348. $rss['lang_code'] = $zc['lang'];
  3349. $dir = zina_get_directory($path);
  3350. $rss['desc'] = (isset($dir['description'])) ? $dir['description'] : '';
  3351. if (!empty($dir['images'])) {
  3352. $rss['image_url'] = preg_replace('/&([^a])/','&amp;${1}', zina_get_image_url($path, $dir['images'][0], 'sub', true));
  3353. } else {
  3354. $rss['image_url'] = false;
  3355. }
  3356. if (!empty($dir['files'])) {
  3357. #todo: redudancy with zina_stats_feed()
  3358. foreach ($dir['files'] as $key => $item) {
  3359. if ($item['fake']) continue;
  3360. if (!isset($rss['genre']) && isset($item['genre'])) {
  3361. $rss['genre'] = $item['genre'];
  3362. }
  3363. $info = &$item['info'];
  3364. $i = array();
  3365. $i['title'] = $item['title'];
  3366. $i['url'] = preg_replace('/&([^a])/','&amp;${1}',zurl($key,NULL,NULL,TRUE,$direct));
  3367. $i['url_enc'] = utf8_encode(rawurldecode($i['url']));
  3368. $i['artist'] = (isset($info->artist)) ? $info->artist : false;
  3369. $i['album'] = (isset($info->album)) ? $info->album : false;
  3370. $i['duration'] = (isset($info->time)) ? $info->time : false;
  3371. $i['size'] = (isset($info->filesize)) ? $info->filesize : false;
  3372. $i['pub'] = (isset($dir['files'][$key]['mtime'])) ? date('r',$dir['files'][$key]['mtime']) : false;
  3373. $i['type'] = (preg_match('/\.('.$zc['ext_mus'].')$/i', $key, $exts)) ? $zc['media_types'][strtolower($exts[1])]['mime'] : 'audio/mpeg';
  3374. $i['description'] = (!empty($item['description'])) ? preg_replace('/&([^a])/','&amp;${1}',$item['description']) : false;
  3375. if ($dir['various']) {
  3376. if ($i['artist'] && $i['title']) {
  3377. $i['title'] = ztheme('artist_song', $i['title'], $i['artist']);
  3378. }
  3379. }
  3380. $rss['items'][] = $i;
  3381. }
  3382. }
  3383. if ($zc['mm'] && $zc['rss_mm'] && isset($dir['mm']) && !empty($dir['mm'])) {
  3384. foreach ($dir['mm'] as $key => $item) {
  3385. $i = array();
  3386. $i['title'] = $item['title'];
  3387. $i['url'] = preg_replace('/&([^a])/','&amp;${1}',zurl($key,NULL,NULL,TRUE,$direct));
  3388. $i['url_enc'] = utf8_encode(rawurldecode($i['url']));
  3389. $i['size'] = (isset($item['filesize'])) ? $item['filesize'] : false;
  3390. $i['type'] = (preg_match('/\.('.$zc['mm_ext'].')$/i', $key, $exts)) ? $zc['mm_types'][strtolower($exts[1])]['mime'] : 'audio/mpeg';
  3391. $i['description'] = (!empty($item['description'])) ? preg_replace('/&([^a])/','&amp;${1}',$item['description']) : false;
  3392. $rss['items'][] = $i;
  3393. }
  3394. }
  3395. return ztheme('rss', $rss, $zc['rss_podcast']);
  3396. }
  3397. #move to theme?
  3398. function zina_content_edit_images(&$zina, $path) {
  3399. global $zc;
  3400. $dir = zina_get_directory($path);
  3401. $title = $dir['title'];
  3402. #$title = ztheme('title',basename($path));
  3403. zina_content_breadcrumb($zina, $path, $title, true);
  3404. $js = '';
  3405. if (!is_writeable($zc['cur_dir'])) {
  3406. zina_set_message(zt('Directory is not writeable. You cannot save or delete images.'),'warn');
  3407. $dir_write = false;
  3408. } else {
  3409. $dir_write = true;
  3410. $js2 = 'function zinaDeleteImage(url, imgclass){'.
  3411. 'if (confirm("'.zt('Delete this image?').'")){'.
  3412. '$.get(url, function(data){'.
  3413. '$("div."+imgclass).html(data);'.
  3414. '});'.
  3415. '}'.
  3416. '}';
  3417. $js2 .= 'function zinaSaveImage(url, imgclass){'.
  3418. '$.get(url, function(data){'.
  3419. '$("div."+imgclass).html(data);'.
  3420. '});'.
  3421. '}';
  3422. zina_set_js('inline', $js2);
  3423. }
  3424. $dir = zina_get_directory($path);
  3425. $images = array();
  3426. if (isset($dir['images'])) {
  3427. foreach($dir['images'] as $key=>$image) {
  3428. $img = array();
  3429. $source = $zc['cur_dir'].'/'.$image;
  3430. if ($info = getimagesize($source)) {
  3431. #$img['width'] = $info[0];
  3432. #$img['height'] = $info[1];
  3433. }
  3434. $img_path = (!empty($path) ? $path.'/'.$image : $image);
  3435. $img['image_raw'] = $image_raw = ztheme('image', zina_get_image_url($path, $image,'dir'), $image, null, 'class="dir-image"');
  3436. $img['image'] = zl($image_raw, $img_path, 'l=46');
  3437. $class = 'zina-imginfo-'.$key;
  3438. $img['image'] .= '<div class="'.$class.'">'.$info[0].'x'.$info[1];
  3439. if ($dir_write) {
  3440. $img['image'] .= ' | '.zl(zt('Delete'),$img_path,'l=60',NULL,FALSE, ' onclick="zinaDeleteImage(\''.zurl($img_path,'l=60').'\',\''.$class.'\');return false;"');
  3441. }
  3442. $img['image'] .= '</div>';
  3443. $images[] = $img;
  3444. }
  3445. }
  3446. $holder = array();
  3447. $missing_nav = '';
  3448. if ($zc['third_images'] || isset($_SESSION['zina_missing'])) {
  3449. if (isset($_SESSION['zina_missing'])) {
  3450. if (isset($zc['url_query'])) {
  3451. foreach($zc['url_query'] as $query) {
  3452. $parts = explode('=', $query);
  3453. $queries[$parts[0]] = $parts[1];
  3454. }
  3455. }
  3456. $queries['l'] = 58;
  3457. $select = ztheme('images_missing_form', array('action'=>zurl(''), 'queries'=>$queries), $_SESSION['zina_missing'], $path);
  3458. $missing_nav = ztheme('image_missing_nav',$select, array('path'=>$path, 'query'=>'l=63'));
  3459. }
  3460. zina_set_js('file', 'extras/jquery.js');
  3461. $opts = zina_get_extras_images_opts();
  3462. foreach($opts as $key => $val) {
  3463. $js .= '$(".zina-img-ajax-'.$key.'").load("'.zurl($path, 'l=59&m='.$key).'");';
  3464. $holder[] = array('image'=>'<p class="zina-img-ajax-'.$key.'">'.zt('Loading...').'</p>');
  3465. }
  3466. }
  3467. zina_set_js('jquery', $js);
  3468. return ztheme('edit_images_page', $title, $images, $holder, $missing_nav);
  3469. }
  3470. function zina_content_genre_hierarchy() {
  3471. global $zc;
  3472. zina_set_js('file', 'extras/jquery.js');
  3473. zina_set_js('file', 'extras/drupal.js');
  3474. $hierarchy = zdbq_array("SELECT g.*, gt.path, gt.weight FROM {genres} AS g INNER JOIN {genre_tree} AS gt ON g.id = gt.id ".
  3475. "ORDER BY gt.weight");
  3476. if (empty($hierarchy)) {
  3477. zina_set_message(zt('Please generate genre caches'));
  3478. zina_goto('','l-20');
  3479. }
  3480. $next_id = zdbq_single('SELECT MAX(id) FROM {genres}') + 1;
  3481. foreach($hierarchy as $key => $genre) {
  3482. $g = &$hierarchy[$key];
  3483. $g['view_query'] = 'l=13&pl='.rawurlencode($genre['genre']);
  3484. $g['delete_url'] = zurl('','l=52&amp;m='.$genre['id']);
  3485. }
  3486. return ztheme('genre_hierarchy', $hierarchy, $next_id, 'action="'.zurl('', 'l=49').'"', $zc['genres_custom']);
  3487. }
  3488. function zina_content_settings($path) {
  3489. global $zc;
  3490. if ($zc['cache']) {
  3491. if (zina_check_directory($zc['cache_dir_private_abs'],1)) {
  3492. $key_file = $zc['cache_dir_private_abs'].'/sitekey.txt';
  3493. if (!file_exists($key_file)) {
  3494. file_put_contents($key_file, md5(uniqid(mt_rand(), true)) . md5(uniqid(mt_rand(), true)));
  3495. }
  3496. }
  3497. zina_check_directory($zc['cache_dir_public_abs'],1);
  3498. }
  3499. if ($zc['playlists'])
  3500. zina_check_directory($zc['cache_pls_dir'],1);
  3501. if ($zc['cache_tmpl'])
  3502. zina_check_directory($zc['cache_tmpl_dir'],1);
  3503. if ($zc['cmp_sel'])
  3504. zina_check_directory($zc['cache_zip_dir'],1);
  3505. if ($zc['cache_imgs'])
  3506. zina_check_directory($zc['cache_imgs_dir'],1);
  3507. if ($zc['zinamp']) {
  3508. if ($zc['pos']) zina_set_message(zt('The Flash Player and Play on Server are incompatible options.'), 'warn');
  3509. if (!$zc['stream_int']) zina_set_message(zt('The Flash Player must have Internal Streaming set to true.'), 'warn');
  3510. if ($zc['playlist_format'] != 'xspf') zina_set_message(zt('The Flash Player must use the "xspf" Playlist Format.'), 'warn');
  3511. if ($zc['apache_auth']) zina_set_message(zt('Apache Authentication may be incompatible (and unnecessary) with the Flash Player option.'), 'warn');
  3512. }
  3513. $rows = array();
  3514. $query = 'l=20';
  3515. $fields = zina_get_settings('cfg');
  3516. $lang = zina_get_settings('lang');
  3517. $cats = &$lang['cats'];
  3518. $titles = &$lang['titles'];
  3519. $subs = &$lang['subs'];
  3520. # CRON #
  3521. $cron_row = '';
  3522. #todo: aren't we always admin here?
  3523. if ($zc['is_admin']) {
  3524. $cron_row = 'X: <select><option selected="selected">'.zt('FOR REFERENCE ONLY: NOT ALL THESE OPTIONS MAKE SENSE').'</option>';
  3525. foreach($fields as $cat => $x) {
  3526. foreach($x as $name => $field) {
  3527. if (isset($field['opts']) && $field['opts'] == 'zina_get_opt_tf') {
  3528. $cron_row .= '<option>'.$name.' &nbsp; ('.$titles[$name].')</option>';
  3529. }
  3530. }
  3531. }
  3532. $cron_row .= '</select>';
  3533. }
  3534. # END CRON
  3535. $rows[] = array('label'=>-1, 'item'=>'<input type="submit" value="'.zt('Update').'"/>', 'class'=>'center');
  3536. foreach($fields as $cat => $x) {
  3537. $items = null;
  3538. if (($zc['embed'] != 'standalone') && ($cat == 'auth' || $cat == 'integration' ||
  3539. ($cat == 'db' && $zc['db_cms']))) {
  3540. continue;
  3541. }
  3542. foreach($x as $name => $field) {
  3543. if ($name == 'adm_pwd') {
  3544. $pass_fields = array('adm_pwd_old', 'adm_pwd', 'adm_pwd_con');
  3545. foreach($pass_fields as $pf) {
  3546. $item = zina_content_form_helper($pf, $field, $zc[$name]);
  3547. $items[] = array('label'=>$titles[$pf], 'item'=>$item);
  3548. }
  3549. } else {
  3550. $value = $zc[$name];
  3551. if ($name == 'main_dir_title') $value = zt($value);
  3552. $item = zina_content_form_helper($name, $field, $value);
  3553. $row = array('label'=>$titles[$name], 'item'=>$item);
  3554. if (isset($subs[$name])) {
  3555. $row['desc'] = $subs[$name];
  3556. }
  3557. $items[] = $row;
  3558. }
  3559. if (isset($field['break'])) $items[] = array('label'=>-1,'item'=>'<hr/>');
  3560. }
  3561. $nav[] = zl($cats[$cat]['t'],'','l=20',$cat);
  3562. # CAT HEADER
  3563. $item = ztheme('admin_section_header', $cats[$cat]['t'], $cat, $query);
  3564. $desc = $cats[$cat]['d'];
  3565. if (is_array($desc)) {
  3566. $output = '';
  3567. foreach ($desc as $d) {
  3568. $output .= '<p>'.$d.'</p>';
  3569. }
  3570. $item .= $output;
  3571. } else {
  3572. $item .= '<em>'.$desc.'</em>';
  3573. }
  3574. if ($cat == 'cron') {
  3575. $item = str_replace('%CRON_SELECT%', $cron_row, $item);
  3576. }
  3577. $rows[] = array('label'=>-1, 'item'=>$item);
  3578. $rows = array_merge($rows, $items);
  3579. }
  3580. $nav = ztheme('admin_nav', $nav);
  3581. array_unshift($rows,array('label'=>-1,'item'=>$nav));
  3582. $row = ztheme('admin_section_header', zt('Settings Navigation'), 'settings_nav', 'l=20');
  3583. $rows[] = array('label'=>-1, 'item'=>'<input type="submit" value="'.zt('Update').'"/>', 'class'=>'center');
  3584. array_unshift($rows,array('label'=>-1,'item'=>$row));
  3585. $install = false;
  3586. if ($zc['database'] && file_exists($zc['zina_dir_abs'].'/install.php') && !zdbq('SELECT 1 FROM {file_ratings} LIMIT 0')) {
  3587. $funcs['install']['install_db'] = '<h2>'.zl(zt('Install the database'), $path, 'l=18&amp;m=install').'</h2>';
  3588. $install = true;
  3589. }
  3590. $lang_while = zt('This could take a while.');
  3591. $lang_sure = zt('Are your sure you want to do this?');
  3592. if ($zc['database'] && !$install && file_exists($zc['zina_dir_abs'].'/update.php')) {
  3593. require_once($zc['zina_dir_abs'].'/update.php');
  3594. if ($update = zina_updates_check()) {
  3595. $funcs['install']['update_db'] = '<h2>'.zl(zt('Database Update: ').zt($update), $path, 'l=18&amp;m=update').'</h2>';
  3596. }
  3597. }
  3598. if ($zc['genres'] && $zc['database']) $funcs['general']['genre_hierarchy'] = zl(zt('Genres and Hierarchy'),$path,'l=48');
  3599. $funcs['cron']['regen'] = zl(zt('Regenerate Directory/File Caches'),$path,'l=26&amp;m=1',NULL,FALSE,
  3600. " onclick='return(confirm(\"".$lang_while.'\\n\\n'.$lang_sure."\"))'");
  3601. if ($zc['genres']) {
  3602. $funcs['cron']['regen_genres'] = zl(zt('Regenerate Genre Cache'),$path,'l=26&amp;m=2',NULL,FALSE,
  3603. " onclick='return(confirm(\"".$lang_while.'\\n\\n'.$lang_sure."\"))'");
  3604. }
  3605. if ($zc['database']) {
  3606. $db_search_text = ($zc['db_search']) ? ' / '. zt('Update search index') : '';
  3607. $funcs['cron']['populate_db'] = zl(zt('Populate the database with missing entries'),$path,'l=26&amp;m=3',NULL,FALSE,
  3608. " onclick='return(confirm(\"".$lang_while.' '.zt('Especially the first time!').'\\n\\n'.$lang_sure."\"))'");
  3609. $funcs['adv']['repopulate_db'] = zl(zt('Synchronize database to filesystem').$db_search_text,$path,'l=26&amp;m=4',NULL,FALSE,
  3610. " onclick='return(confirm(\"".$lang_while.'\\n\\n'.$lang_sure."\"))'");
  3611. $help['repopulate_db'] = zt('This will re-populate the database with information from the entire filesystem.').' '.
  3612. zt('It should only be necessary after upgrading your database or if files are changed and their timestamps are not modified for some reason.');
  3613. $funcs['adv']['sync_db'] = zl(zt('Clean up database'),$path,'l=27',NULL,FALSE,
  3614. " onclick='return(confirm(\"".$lang_while.'\\n\\n'.$lang_sure."\"))'");
  3615. $help['sync_db'] = zt('This will find entries in the database that no longer exist in the filesystem and give you an opportunity to delete, ignore or update them.');
  3616. if ($zc['cache_stats']) {
  3617. $funcs['cron']['regen_stats'] = zl(zt('Regenerate Statistics'),$path,'l=47',NULL,FALSE,
  3618. " onclick='return(confirm(\"".$lang_while.'\\n\\n'.$lang_sure."\"))'");
  3619. }
  3620. if (is_writeable($zc['mp3_dir'])) {
  3621. $funcs['general']['extract_images'] = zl(zt('Extract ID3 images'),$path,'l=26&m=5',NULL,FALSE,
  3622. " onclick='return(confirm(\"".$lang_while.'\\n\\n'.$lang_sure."\"))'");
  3623. }
  3624. }
  3625. $funcs['general']['find_images'] = zl(zt('Find Missing Images/Artwork'),null,'l=62');
  3626. if ($zc['cache_tmpl']) {
  3627. $funcs['adv']['delete_cache'] = zl(zt('Delete template and statistics cache files'),$path,'l=30',NULL,FALSE,
  3628. " onclick='return(confirm(\"".$lang_sure."\"))'");
  3629. }
  3630. if ($zc['cache_imgs']) {
  3631. $funcs['adv']['delete_imgs_cache'] = zl(zt('Delete cached images files'),$path,'l=31',NULL,FALSE,
  3632. " onclick='return(confirm(\"".$lang_sure."\"))'");
  3633. }
  3634. if ($zc['cmp_cache'] && is_writeable($zc['cache_zip_dir'])) {
  3635. $funcs['adv']['delete_zip_cache'] = zl(zt('Delete cached compressed files'),$path,'l=34',NULL,FALSE,
  3636. " onclick='return(confirm(\"".$lang_sure."\"))'");
  3637. }
  3638. if ($zc['sitemap']) {
  3639. if (file_exists($zc['cache_dir_public_abs'].'/'.$zc['sitemap_file'])) {
  3640. $funcs['cron']['sitemap'] = zl(zt('Sitemap: Delete cached file'), $path, 'l=33');
  3641. } else {
  3642. $funcs['cron']['sitemap'] = zl(zt('Sitemap: View and generate cached file'), $path, 'l=51');
  3643. }
  3644. }
  3645. $funcs['adv']['getlang'] = zl(zt('Get language phrases for translation or modifications'),$path,'l=32');
  3646. if ($zc['database']) {
  3647. $pls = zina_get_playlists_custom();
  3648. if (!empty($pls)) {
  3649. $funcs['adv']['importpls'] = zl(zt('Import Old Format Playlists'),$path,'l=67');
  3650. }
  3651. }
  3652. $funcs['help']['help'] = zl(zt('Help and Support Information'),$path,'l=64');
  3653. if ($zc['lastfm'] && file_exists($zc['cache_dir_private_abs'].'/scrobbler_queue_'.$zc['user_id'].'.txt')) {
  3654. $funcs['general']['lastfm_queue'] = zl(zt('Manually submit last.fm queue'), $path, 'l=19');
  3655. }
  3656. $lang = array(
  3657. 'install' => array(
  3658. 'title' => zt('Install & Updates'),
  3659. 'desc' => zt('These should be run immediately'),
  3660. ),
  3661. 'general' => array(
  3662. 'title' => zt('General'),
  3663. ),
  3664. 'cron' => array(
  3665. 'title' => zt('Cron'),
  3666. 'desc' => zt('All these functions will be run automatically if your CMSes cron functionality is setup, or if the cron.php file in the zina root directly is setup to run regularly (via cron?). If not, you may manually run them here.'),
  3667. ),
  3668. 'adv' => array(
  3669. 'title' => zt('Advanced'),
  3670. 'desc' => zt('These should not be needed very often.'),
  3671. ),
  3672. 'help' => array(
  3673. 'title' => zt('Help and Support'),
  3674. ),
  3675. );
  3676. $output = '<table><tr>';
  3677. $class = 'zina-list';
  3678. $row = 0;
  3679. foreach($lang as $func => $item) {
  3680. if ($row == 0) $output .= '<td width="50%" valign="top" style="padding-right:10px;">';
  3681. if (isset($funcs[$func])) {
  3682. $output .= '<h3 style="font-weight:bold;font-size:1.1em;">'.$item['title'].'</h3>';
  3683. if (isset($item['desc'])) $output .= '<span>'.$item['desc'].'</span>';
  3684. $output .= '<ul class="zina-list">';
  3685. foreach ($funcs[$func] as $key => $i) {
  3686. $output .= '<li class="zina-list">'.$i;
  3687. if (isset($help[$key])) $output .= '<br/><small>'.$help[$key].'</small>';
  3688. $output .= '</li>';
  3689. }
  3690. $output .= '</ul>';
  3691. unset($funcs[$func]);
  3692. }
  3693. $row = ++$row % 3;
  3694. if ($row == 0) $output .= '</td>';
  3695. }
  3696. if ($row != 0) $output .= '</td>';
  3697. $output .= '</tr></table>';
  3698. $row1 = array('label'=>-1, 'item'=> ztheme('admin_section_header', zt('Administrative Functions'), 'top').'<br/>'.$output);
  3699. array_unshift($rows,$row1);
  3700. $form = array(
  3701. 'attr'=>'action="'.zurl($path, 'l=21').'" name="zinaadminform"',
  3702. 'rows'=>$rows,
  3703. );
  3704. return ztheme('config',$form);
  3705. }
  3706. function zina_content_pathlinks($path, $type, $play, $title = false, $id3 = false) {
  3707. global $zc;
  3708. $arr = explode('/', $path);
  3709. $num = sizeof($arr);
  3710. if (sizeof($arr) == 1 && ($arr[0] == '.' || $arr[0] == '/' || $arr[0] == '\\')) {
  3711. return zl(zt($zc['main_dir_title']), '');
  3712. }
  3713. $titles = array();
  3714. $ppath = '';
  3715. for ($i=0; $i < $num; $i++) {
  3716. $part = $arr[$i];
  3717. if ($ppath != '') $ppath = $ppath.'/';
  3718. if (zvalidate_utf8($part)) $part = utf8_decode($part);
  3719. $ppath .= $part;
  3720. if ($i == $num - 1) {
  3721. if ($type == 's') {
  3722. # Sloooowww... (not used)
  3723. if ($id3) {
  3724. $song = $zc['mp3_dir'].'/'.$path;
  3725. $ft = zina_content_song_title($song, true);
  3726. } else {
  3727. if ($title)
  3728. $ft = zina_content_song_title($title);
  3729. else
  3730. $ft = zina_content_song_title($path);
  3731. }
  3732. $titles[] = ($play) ? zl($ft,$ppath,'l=8&amp;m=1', null, false, 'class="zinamp"') : $ft;
  3733. } else {
  3734. if ($part == '.lp') continue;
  3735. $titles[] = zl(ztheme('title',$part),$ppath);
  3736. }
  3737. } else {
  3738. $titles[] = zl(ztheme('title',$part),$ppath);
  3739. }
  3740. }
  3741. return ztheme('search_song_titles', $titles);
  3742. }
  3743. function zina_content_form_helper($name, $field, $setting, $disable = false) {
  3744. $type = $field['type'];
  3745. $foo = false;
  3746. $value = ($field['def'] == $setting) ? $field['def'] : $setting;
  3747. $disabled = ($disable) ? ' disabled="disabled"' : '';
  3748. $disabled = ($disable) ? ' disabled="disabled" class="disabled"' : '';
  3749. $id = (isset($field['id'])) ? ' id="'.$field['id'].'"' : '';
  3750. $i = 0;
  3751. $item = '';
  3752. if ($type == 'textarea') {
  3753. $cols = (isset($field['cols'])) ? $field['cols'] : 50;
  3754. $rows = (isset($field['rows'])) ? $field['rows'] : 8;
  3755. $item = '<textarea name="'.$name.'" cols="'.$cols.'" rows="'.$rows.'"'.$id.'>'.$value.'</textarea>';
  3756. } elseif ($type == 'radio') {
  3757. $opts = (is_array($field['opts'])) ? $field['opts'] : call_user_func($field['opts']);
  3758. foreach($opts as $key=>$val) {
  3759. $checked = '';
  3760. if ($value == $key) $checked = ' checked="checked"';
  3761. $item .= '<input type="radio" name="'.$name.'" value="'.$key.'"'.$checked.$disabled.$id.' /> '.$val.' ';
  3762. }
  3763. } elseif ($type == 'textfield') {
  3764. $size = (isset($field['size'])) ? $field['size'] : 30;
  3765. if(!empty($value)) {
  3766. if (is_array($value)) $value = implode(',',$value);
  3767. $len = strlen($value);
  3768. if (!isset($field['size'])) {
  3769. $len = strlen($value);
  3770. if ($len < 30) $size = $len+2;
  3771. elseif ($len < 60) $size = $len+10;
  3772. else $size = 60;
  3773. } else {
  3774. if ($len > $size) $size = $len+10;
  3775. }
  3776. if (isset($field['max']) && $size > $field['max']) $size = $field['max'];
  3777. }
  3778. $item = '<input type="text" name="'.$name.'" value="'.$value.'" size="'.$size.'"'.$disabled.$id.'/>';
  3779. if (isset($field['suf'])) $item .= ' '.zt($field['suf']);
  3780. } elseif ($type == 'select') {
  3781. $tmp = $value;
  3782. $opts = (is_array($field['opts'])) ? $field['opts'] : call_user_func($field['opts']);
  3783. $item = '<select name="'.$name.'"'.$disabled.$id.'>';
  3784. foreach($opts as $key=>$val) {
  3785. $sel = '';
  3786. if ($value == $key) $sel = ' selected="selected"';
  3787. $item .= '<option value="'.$key.'"'.$sel.'>'.$val.'</option>';
  3788. }
  3789. $item .= '</select>';
  3790. } elseif ($type == 'password_adm') {
  3791. $item = '<input type="password" name="'.$name.'"'.$disabled.' />';
  3792. } elseif ($type == 'password') {
  3793. $item = '<input type="password" name="'.$name.'" value="'.$value.'"'.$disabled.'/>';
  3794. } elseif ($type == 'checkboxes') {
  3795. $opts = (is_array($field['opts'])) ? $field['opts'] : call_user_func($field['opts']);
  3796. foreach($opts as $key=>$val) {
  3797. $checked = '';
  3798. if (in_array($key, $value)) $checked = ' checked="checked"';
  3799. $item .= '<input type="checkbox" name="'.$name.'[]" value="'.$key.'"'.$checked.$disabled.$id.' /> '.$val.' ';
  3800. }
  3801. } elseif ($type == 'hidden') {
  3802. #todo: use ztheme('form_hidden', $name, $value); #also for all other hiddens
  3803. $item .= '<input type="hidden" name="'.$name.'" value="'.$value.'"'.$id.'/>';
  3804. } elseif ($type == 'checkbox') {
  3805. $checked = (!empty($value)) ? ' checked="checked"' : '';
  3806. $onclick = (isset($field['onclick'])) ? " onClick='".$field['onclick']."'" : '';
  3807. $item .= '<input type="checkbox" name="'.$name.'" '.$checked.$disabled.$id.$onclick.' />';
  3808. }
  3809. # only text, radio, password utilize...
  3810. if ($disable) {
  3811. $field['type'] = 'hidden';
  3812. $item .= zina_content_form_helper($name, $field, $setting);
  3813. }
  3814. return $item;
  3815. }
  3816. function zina_content_subdir_opts(&$item, $path, $checkbox, $opts=null) {
  3817. global $zc;
  3818. if ($zc['play']) {
  3819. if (strpos($path, '/') !== false) {
  3820. $item['opts']['play'] = array('path'=>$path, 'query'=>'l=8&amp;m=0');
  3821. } elseif ($zc['play_rec_rand']) {
  3822. $item['opts']['play_rec_rand'] = array('path'=>$path, 'query'=>'l=8&amp;m=10&amp;c');
  3823. }
  3824. }
  3825. if ($zc['low'] && ($zc['resample'] || (isset($opts['lofi']) && !empty($opts['lofi'])))) {
  3826. $item['opts']['play_lofi'] = array('path'=>$path, 'query'=>'l=8&amp;m=0&amp;lf');
  3827. }
  3828. if ($zc['cmp_sel']) {
  3829. if (!(isset($item['type']) && $item['type'] == 'artist')) {
  3830. $item['opts']['download'] = array('path'=>$path.'/.lp', 'query'=>'l=5');
  3831. }
  3832. }
  3833. if ($checkbox) {
  3834. $item['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($path).'/.lp', 'checked'=>false);
  3835. }
  3836. }
  3837. /*
  3838. * $song must be full path
  3839. */
  3840. function zina_content_song_title($song, $id3 = false) {
  3841. global $zc;
  3842. if ($id3) {
  3843. $mp3 = zina_get_file_info($song, false);
  3844. if ($mp3->tag) return ztheme('song_title', $mp3->title, true);
  3845. }
  3846. $ext = ($zc['remote']) ? $zc['ext_mus'].'|'.$zc['remote_ext'] : $zc['ext_mus'];
  3847. $ext = ($zc['fake']) ? $ext.'|'.$zc['fake_ext'] : $ext;
  3848. $song = preg_replace('/\.('.$ext.')$/i', '', basename($song));
  3849. return ztheme('song_title', $song);
  3850. }
  3851. function zina_content_playlist_form($item) {
  3852. global $zc;
  3853. $rows[] = array('label'=>zt('Title'),
  3854. 'item'=>zina_content_form_helper('title', array('type'=>'textfield', 'def'=>'', 'size'=>30, 'v'=>array('req')), htmlentities($item['title'])));
  3855. $rows[] = array('label'=>zt('Description'),
  3856. 'item'=>zina_content_form_helper('description', array('type'=>'textarea', 'def'=>''), htmlentities($item['description'])),
  3857. 'help'=>zt('HTML tags allowed: @tags', array('@tags' => $zc['pls_tags'])));
  3858. if ($zc['genres']) {
  3859. $genres = zdbq_assoc_list("SELECT id, genre FROM {genres} ORDER BY genre");
  3860. if (!empty($genres)) {
  3861. $row = '<select name="genre_id">'.
  3862. '<option value="">'.zt('None').'</option>';
  3863. foreach($genres as $key => $genre) {
  3864. $selected = ($key == $item['genre_id']) ? ' selected="selected"' : '';
  3865. $row .= '<option value="'.$key.'"'.$selected.'>'.htmlentities($genre).'</option>';
  3866. }
  3867. $row .= '</select>';
  3868. $rows[] = array('label'=>zt('Genre'),'item'=>$row);
  3869. }
  3870. }
  3871. #TODO: if art/tit
  3872. $dirs = zdbq_assoc_list("SELECT id, path FROM {dirs} WHERE level = 1 AND path != '.' ORDER by path");
  3873. if (!empty($dirs)) {
  3874. $row = '<select name="dir_id">';
  3875. $row .= '<option value="">'.zt('None').'</option>';
  3876. foreach($dirs as $key=> $dir) {
  3877. $selected = ($key == $item['dir_id']) ? ' selected="selected"' : '';
  3878. $row .= '<option value="'.$key.'"'.$selected.'>'.htmlentities($dir).'</option>';
  3879. }
  3880. $row .= '</select>';
  3881. $rows[] = array('label'=>zt('Arist'),'item'=>$row);
  3882. }
  3883. $row = '<select name="image_type">';
  3884. $types = array(0=>zt('None'), 1=>zt('Artist'));
  3885. if ($zc['genres']) $types[2] = zt('Genre');
  3886. foreach($types as $key=> $type) {
  3887. $selected = ($key == $item['image_type']) ? ' selected="selected"' : '';
  3888. $row .= '<option value="'.$key.'"'.$selected.'>'.$type.'</option>';
  3889. }
  3890. $row .= '</select>';
  3891. $rows[] = array('label'=>zt('Show Image'),'item'=>$row);
  3892. if ($zc['pls_public']) {
  3893. $rows[] = array('label'=>zt('Public'),
  3894. 'item'=>zina_content_form_helper('visible', array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>true), $item['visible']));
  3895. }
  3896. return $rows;
  3897. }
  3898. #TODO: move
  3899. #$type = insert or update
  3900. function zina_playlist_form_submit($type, $pls_id = null) {
  3901. global $zc;
  3902. if ($type == 'update') {
  3903. $user_id = zdbq_single("SELECT user_id FROM {playlists} WHERE id = $pls_id");
  3904. } else {
  3905. $user_id = $zc['user_id'];
  3906. }
  3907. if (!zina_cms_access('edit_playlists', $user_id)) return zina_access_denied();
  3908. $visible = (isset($_POST['visible'])) ? (int)$_POST['visible'] : 1;
  3909. $where = (!$zc['is_admin']) ? ' AND user_id = %d' : '';
  3910. $dir_id = $genre_id = null;
  3911. if (!empty($_POST['dir_id'])) {
  3912. $exists = zdbq_single("SELECT 1 FROM {dirs} WHERE id = %d", array($_POST['dir_id']));
  3913. if ($exists) $dir_id = $_POST['dir_id'];
  3914. }
  3915. if (!empty($_POST['genre_id'])) {
  3916. $exists = zdbq_single("SELECT 1 FROM {genres} WHERE id = %d", array($_POST['genre_id']));
  3917. if ($exists) $genre_id = $_POST['genre_id'];
  3918. }
  3919. $image_type = (in_array($_POST['image_type'], array(0,1,2))) ? $_POST['image_type'] : 0;
  3920. $title = strip_tags($_POST['title']);
  3921. $desc = strip_tags($_POST['description'], $zc['pls_tags']);
  3922. $time = time();
  3923. if ($type == 'update') {
  3924. if (zdbq("UPDATE {playlists} SET title = '%s', description = '%s', dir_id = %d, genre_id = %d, image_type = %d, visible = %d, mtime = %d ".
  3925. "WHERE id = %d $where",
  3926. array($title, $desc, $dir_id, $genre_id, $image_type, $visible, $time, $pls_id, $zc['user_id']))) {
  3927. return true;
  3928. }
  3929. } else {
  3930. if (zdbq("INSERT {playlists} (title, description, user_id, date_created, visible, mtime, dir_id, genre_id, image_type) ".
  3931. "VALUES ('%s', '%s', %d, %d, %d, %d, %d, %d, %d)",
  3932. array($title, $desc, $zc['user_id'], $time, $visible, $time, $dir_id, $genre_id, $image_type))) {
  3933. return zdb_last_insert_id('playlists', 'id');
  3934. }
  3935. }
  3936. zina_set_message(zt('Cannot @type playlist.', array('@type'=>$type)), 'warn');
  3937. return false;
  3938. }
  3939. function zina_content_playlist_form_opts($form, $playlist_sel='', $type='l a x p r q v') {
  3940. global $zc;
  3941. $options = array_flip(explode(' ', $type));
  3942. $sess = (isset($_SESSION['z_sp']) && strlen($_SESSION['z_sp']) > 0) ? 1 : 0;
  3943. $lang_no = zt('No playlist selected.');
  3944. $opts_url = array(
  3945. 'd' => "javascript:selectCheck('$form','".zurl(null,'l=43')."', '".zt('Nothing to delete.')."', $sess, 'view');",
  3946. 'a' => "javascript:selectCheckAjax('".zurl(null,'l=40')."', '$form', 'zina_messages', '".zt('Nothing to add to playlist.')."');",
  3947. 'v' => "javascript:selectCheck('$form','".zurl(null,'l=2')."','".zt('Nothing to view.')."', $sess, 'view');",
  3948. 'p' => "javascript:selectCheck('$form','".zurl(null,'l=8&amp;m=3')."','".$lang_no."', $sess, 'play');",
  3949. 'r' => "javascript:selectCheck('$form','".zurl(null,'l=8&amp;m=3&amp;rand')."','".$lang_no."', $sess, 'play');",
  3950. 'q' => "javascript:selectCheck('$form','".zurl(null,'l=8&amp;m=3&amp;lf')."','".$lang_no."', $sess, 'play');",
  3951. 'l' => 'l=2'
  3952. );
  3953. if (!$zc['play']) unset($options['p']);
  3954. if (!$zc['low']) unset($options['q']);
  3955. if (!$zc['database']) unset($options['r']);
  3956. if ($zc['database']) {
  3957. unset($options['d']); # let them do it through playlist interface
  3958. $playlists = array();
  3959. $access = false;
  3960. if (zina_cms_access('edit_playlists', $zc['user_id'])) {
  3961. $playlists = zdbq_array("SELECT id, title FROM {playlists} WHERE user_id = %d ORDER BY title", array($zc['user_id']));
  3962. $access = true;
  3963. }
  3964. $display = ($zc['is_admin'] || $zc['session_pls'] || $zc['pls_user'] || !empty($playlists));
  3965. if (!$zc['is_admin'] && !$zc['session_pls'] && !$zc['pls_user']) unset($options['a']);
  3966. $options = array_flip($options);
  3967. $new = ($access && strstr($type,'a'));
  3968. } else {
  3969. $playlists = zina_get_playlists_custom();
  3970. $display = (!$zc['is_admin'] && (empty($playlists) && !$zc['session_pls'])) ? false : true;
  3971. if (!$zc['is_admin'] || !$zc['cache']) {
  3972. unset($options['d']);
  3973. if (!$zc['session_pls']) unset($options['a']);
  3974. }
  3975. $options = array_flip($options);
  3976. $new = ($zc['is_admin'] && strstr($type,'a') && $zc['cache']);
  3977. }
  3978. $pl = ztheme('playlist_form_select', 'playlist', $playlists, $playlist_sel, $new, $zc['session_pls'], $zc['database']);
  3979. return ztheme('playlist_form_elements', $display, $form, $options, $opts_url, $pl);
  3980. }
  3981. function zina_content_song_list_opts($custom_pls, $lofi, $check_boxes, $form, $search = false) {
  3982. global $zc;
  3983. $items = array();
  3984. if (!$search && $zc['is_admin'] && $zc['cache']) {
  3985. $items['submit']['js'] = 'SubmitForm(\''.$form.'\',\'?l=42\', \'add\');';
  3986. $items['submit']['exists'] = $custom_pls;
  3987. }
  3988. if ($check_boxes) {
  3989. $items['checkboxes'] = true;
  3990. $err = zt('At least one song must be selected.');
  3991. if ($zc['play_sel'] || $zc['cmp_sel']) {
  3992. if ($zc['play'] && $zc['play_sel']) {
  3993. $items['opts']['play'] = array('path'=>'javascript:CheckIt(\''.$form.'\',\''.zurl('','l=8&amp;m=7').'\',\''.$err.'\',\'play\');',
  3994. 'query'=>null, 'attr'=>null);
  3995. }
  3996. if ($zc['play'] && $zc['play_rec_rand']) {
  3997. $items['opts']['play_rec_rand'] = array('path'=>'javascript:CheckIt(\''.$form.'\',\''.zurl('','l=8&amp;m=8').'\',\''.$err.'\',\'play\');',
  3998. 'query'=>null, 'attr'=>null);
  3999. }
  4000. if ($lofi) {
  4001. $items['opts']['play_lofi'] = array('path'=>'javascript:CheckIt(\''.$form.'\',\''.zurl('','l=8&amp;m=7&amp;lf').'\',\''.$err.'\',\'play\');',
  4002. 'query'=>null, 'attr'=>null);
  4003. }
  4004. if ($zc['cmp_sel']) {
  4005. $items['opts']['download'] = array('path'=>'javascript:CheckIt(\''.$form.'\',\''.zurl('','l=3').'\',\''.$err.'\',\'download\');',
  4006. 'query'=>null, 'attr'=>null);
  4007. }
  4008. }
  4009. }
  4010. $items['playlist_form_elements'] = zina_content_playlist_form_opts($form);
  4011. return $items;
  4012. }
  4013. #TODO: ADD type = search, genre, year ???
  4014. function zina_search_pager_query($term, $query, &$count, &$navigation, $sql = array(), $genre=false, &$selected = null) {
  4015. global $zc;
  4016. $cstart = 0;
  4017. $per_page = $zc['search_pp'];
  4018. if (!empty($sql)) {
  4019. $type_opts = array_keys(zina_search_opts_type());
  4020. $order_opts = array_keys(zina_search_opts_order());
  4021. $sort_opts = array_keys(zina_search_opts_sort());
  4022. $per_page_opts = array_keys(zina_search_opts_per_page());
  4023. if (isset($_POST['type'])) {
  4024. $type = $_POST['type'];
  4025. } elseif (!empty($_SESSION['zina']['search_type'])) {
  4026. $type = $_SESSION['zina']['search_type'];
  4027. }
  4028. if (isset($_POST['order'])) {
  4029. $order = $_POST['order'];
  4030. } elseif (!empty($_SESSION['zina']['search_order'])) {
  4031. $order = $_SESSION['zina']['search_order'];
  4032. }
  4033. if (isset($_POST['sort'])) {
  4034. $sort = $_POST['sort'];
  4035. } elseif (!empty($_SESSION['zina']['search_sort'])) {
  4036. $sort = $_SESSION['zina']['search_sort'];
  4037. }
  4038. if (isset($_POST['per_page'])) {
  4039. $per_page = $_POST['per_page'];
  4040. } elseif (!empty($_SESSION['zina']['search_per_page'])) {
  4041. $per_page = $_SESSION['zina']['search_per_page'];
  4042. }
  4043. if (!isset($sort) || !in_array($sort, $sort_opts)) $sort = 'title';
  4044. if (!isset($order) || !in_array($order, $order_opts)) $order = 'asc';
  4045. if (!isset($per_page) || !in_array($per_page, $per_page_opts)) $per_page = $zc['search_pp'];
  4046. if (!isset($type) || !in_array($type, $type_opts)) $type = 'album';
  4047. $selected['order'] = $_SESSION['zina']['search_order'] = $order;
  4048. $selected['sort'] = $_SESSION['zina']['search_sort'] = $sort;
  4049. $selected['per_page'] = $_SESSION['zina']['search_per_page'] = $per_page;
  4050. $selected['type'] = $_SESSION['zina']['search_type'] = $type;
  4051. if ($sort != 'title') {
  4052. $pre = (in_array($sort, array('mtime', 'sum_votes', 'sum_rating'))) ? '' : 'i.';
  4053. $sort = "$pre$sort $order, i.title";
  4054. $order = '';
  4055. }
  4056. $sql['orderby'] = "$sort $order";
  4057. $sql['type'] = '';
  4058. if ($_GET['l'] != 4) {
  4059. $sql['type'] = "i.type = '$type' AND ";
  4060. }
  4061. $count = $cend = zdbq_single("SELECT count(*) FROM {search_index} AS i WHERE ".$sql['type'].$sql['where'], array($term));
  4062. } elseif ($genre) {
  4063. $genres = zina_core_cache('genre');
  4064. $found = isset($genres[$term]) ? $genres[$term] : array();
  4065. $count = $cend = sizeof($found);
  4066. } else {
  4067. $results = zina_search_cache($term);
  4068. $count = $cend = count($results);
  4069. }
  4070. if ($count > $per_page) {
  4071. $page = isset($_GET['page']) ? $_GET['page'] : 1;
  4072. $pages_total = ceil($count/$per_page);
  4073. if (!zina_validate('int', $page) || $page < 1 || $page > $pages_total) $page = 1;
  4074. $navigation = ztheme('category_pages', null, $page, $pages_total, $query.'&amp;pl='.rawurlencode($term).'&amp;');
  4075. $cstart = ($page - 1) * $per_page;
  4076. if ($cstart > $count) $cstart = 0;
  4077. $cend = $per_page;
  4078. }
  4079. if (!empty($sql)) {
  4080. return zdbq_array("SELECT i.path, i.type, i.title, i.context, i.genre, i.year, i.file_mtime as mtime, ".
  4081. "if(i.type='song', f.sum_votes, d.sum_votes) as sum_votes, ".
  4082. "if(i.type='song', f.sum_rating, d.sum_rating) as sum_rating, f.id3_info ".
  4083. ",if(i.type='playlist', p.image_type, FALSE) as image_type ".
  4084. ",if(i.type='playlist', pd.path, FALSE) as image_path ".
  4085. ",if(i.type='playlist', p.id, FALSE) as id ".
  4086. "FROM {search_index} as i ".
  4087. "LEFT OUTER JOIN {files} AS f ON (i.type = 'song' AND i.type_id = f.id) ".
  4088. "LEFT OUTER JOIN {dirs} AS d ON (i.type != 'song' AND i.type !='playlist' AND i.type_id = d.id) ".
  4089. "LEFT OUTER JOIN {playlists} AS p ON (i.type = 'playlist' AND i.type_id = p.id) ".
  4090. "LEFT OUTER JOIN {dirs} AS pd ON (i.type = 'playlist' AND i.type_id = p.id AND p.dir_id = pd.id) ".
  4091. "WHERE ".$sql['type'].$sql['where']." ORDER BY ".$sql['orderby']." LIMIT %d OFFSET %d",
  4092. array($term, $cend, $cstart));
  4093. } elseif ($genre) {
  4094. $results = array();
  4095. $found = array_slice($found, $cstart, $cend);
  4096. foreach($found as $path) $results[] = zina_search_dir_helper($path);
  4097. return $results;
  4098. } else {
  4099. return array_slice($results, $cstart, $cend);
  4100. }
  4101. }
  4102. function zina_playlist_pager_query($query, &$count, &$navigation, &$selected = null, $dir_id = false) {
  4103. global $zc;
  4104. $cstart = 0;
  4105. $per_page = $zc['search_pp'];
  4106. $where = '';
  4107. $terms = array();
  4108. if ($zc['pls_user']) {
  4109. $all_opts = array_keys(zina_playlist_opts_all());
  4110. if (isset($_POST['all'])) {
  4111. $all = $_POST['all'];
  4112. } elseif (!empty($_SESSION['zina']['playlist_all'])) {
  4113. $all = $_SESSION['zina']['playlist_all'];
  4114. }
  4115. if (!isset($all) || !in_array($all, $all_opts)) $all = 'all';
  4116. $selected['all'] = $_SESSION['zina']['playlist_all'] = $all;
  4117. if ($all == 'all') {
  4118. if (!$zc['is_admin']) {
  4119. if ($zc['pls_public']) {
  4120. $where = 'p.user_id = %d OR p.visible = 1';
  4121. $terms[] = $zc['user_id'];
  4122. } else {
  4123. $where = 'p.user_id = %d';
  4124. $terms[] = $zc['user_id'];
  4125. }
  4126. }
  4127. } else { #single
  4128. $where = 'p.user_id = %d';
  4129. $terms[] = $zc['user_id'];
  4130. }
  4131. } else { # no user playlists
  4132. if ($zc['pls_public']) {
  4133. $where = 'visible = 1';
  4134. if (!$zc['is_admin']) return array();
  4135. }
  4136. }
  4137. $sort_opts = array_keys(zina_playlist_opts_sort());
  4138. $order_opts = array_keys(zina_search_opts_order());
  4139. if (isset($_POST['sort'])) {
  4140. $sort = $_POST['sort'];
  4141. } elseif (!empty($_SESSION['zina']['playlist_sort'])) {
  4142. $sort = $_SESSION['zina']['playlist_sort'];
  4143. }
  4144. if (isset($_POST['order'])) {
  4145. $order = $_POST['order'];
  4146. } elseif (!empty($_SESSION['zina']['playlist_order'])) {
  4147. $order = $_SESSION['zina']['playlist_order'];
  4148. }
  4149. if (!isset($sort) || !in_array($sort, $sort_opts)) $sort = 'playlist';
  4150. if (!isset($order) || !in_array($order, $order_opts)) $order = 'asc';
  4151. $selected['sort'] = $_SESSION['zina']['playlist_sort'] = $sort;
  4152. $selected['order'] = $_SESSION['zina']['playlist_order'] = $order;
  4153. /*
  4154. $per_page_opts = array_keys(zina_search_opts_per_page());
  4155. if (isset($_POST['per_page'])) {
  4156. $per_page = $_POST['per_page'];
  4157. } elseif (!empty($_SESSION['zina']['search_per_page'])) {
  4158. $per_page = $_SESSION['zina']['search_per_page'];
  4159. }
  4160. if (!isset($per_page) || !in_array($per_page, $per_page_opts)) $per_page = $zc['search_pp'];
  4161. $selected['per_page'] = $_SESSION['zina']['search_per_page'] = $per_page;
  4162. if ($sort != 'title') {
  4163. $pre = (in_array($sort, array('mtime', 'sum_votes', 'sum_rating'))) ? '' : 'i.';
  4164. $sort = "$pre$sort $order, i.title";
  4165. $order = '';
  4166. }
  4167. $sql['orderby'] = "$sort $order";
  4168. */
  4169. if ($dir_id) {
  4170. $where = "WHERE (dd.id = %d OR f.dir_id = %d)". ((!empty($where)) ? " AND ($where)" : '');
  4171. array_unshift($terms, $dir_id);
  4172. array_unshift($terms, $dir_id);
  4173. $count = $cend = zdbq_single("SELECT count(DISTINCT p.id) FROM {playlists} AS p ".
  4174. "INNER JOIN {playlists_map} as pm ON (p.id = pm.playlist_id) ".
  4175. "LEFT OUTER JOIN {files} AS f ON (pm.type = 'song' AND pm.type_id = f.id) ".
  4176. "LEFT OUTER JOIN {dirs} AS dd ON (pm.type = 'album' AND pm.type_id = dd.id) ".
  4177. "$where GROUP BY p.id", $terms);
  4178. } else {
  4179. $joins = '';
  4180. $where = (!empty($where)) ? "WHERE ".$where : '';
  4181. $count = $cend = zdbq_single("SELECT count(*) FROM {playlists} AS p ".$where, $terms);
  4182. }
  4183. if ($sort != 'playlist') {
  4184. if ($sort == 'genre') {
  4185. $sort = "g.genre IS NULL, g.genre $order, playlist";
  4186. } else {
  4187. $sort = "$sort $order, playlist";
  4188. }
  4189. $order = '';
  4190. }
  4191. $orderby = "$sort $order";
  4192. if ($count > $per_page) {
  4193. $page = isset($_GET['page']) ? $_GET['page'] : 1;
  4194. $pages_total = ceil($count/$per_page);
  4195. if (!zina_validate('int', $page) || $page < 1 || $page > $pages_total) $page = 1;
  4196. $navigation = ztheme('category_pages', null, $page, $pages_total, $query.'&amp;');
  4197. $cstart = ($page - 1) * $per_page;
  4198. if ($cstart > $count) $cstart = 0;
  4199. $cend = $per_page;
  4200. }
  4201. if ($dir_id) {
  4202. $sql = "SELECT p.title as playlist, p.*, d.path AS image_path, g.genre ".
  4203. "FROM {playlists} as p ".
  4204. "INNER JOIN {playlists_map} as pm ON (p.id = pm.playlist_id) ".
  4205. "LEFT OUTER JOIN {dirs} AS d ON (p.dir_id = d.id) ".
  4206. "LEFT OUTER JOIN {genres} AS g ON (p.genre_id = g.id) ".
  4207. "LEFT OUTER JOIN {files} AS f ON (pm.type = 'song' AND pm.type_id = f.id) ".
  4208. "LEFT OUTER JOIN {dirs} AS dd ON (pm.type = 'album' AND pm.type_id = dd.id) ".
  4209. "$where ".
  4210. "GROUP BY p.id ".
  4211. "ORDER BY $orderby LIMIT %d OFFSET %d";
  4212. } else {
  4213. $sql = "SELECT p.title as playlist, p.*, d.path AS image_path, g.genre ".
  4214. "FROM {playlists} AS p ".
  4215. "LEFT OUTER JOIN {dirs} AS d ON (p.dir_id = d.id) ".
  4216. "LEFT OUTER JOIN {genres} AS g ON (p.genre_id = g.id) ".
  4217. $where." ORDER BY ".$orderby." LIMIT %d OFFSET %d";
  4218. }
  4219. $terms[] = $cend;
  4220. $terms[] = $cstart;
  4221. return zdbq_array($sql, $terms);
  4222. }
  4223. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4224. * GET functions
  4225. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  4226. /*
  4227. * Almost all of the information for directories and files
  4228. * is done through this function
  4229. *
  4230. * @dir is full path relative to mp3_dir
  4231. * @category is bool
  4232. */
  4233. #todo: could potentially use db for category as opt?
  4234. function zina_get_directory($root, $category = false, $opts = array()) {
  4235. global $zc;
  4236. $opts += array(
  4237. 'cat_images' => false,
  4238. 'get_files' => true,
  4239. 'dir_tags' => $zc['dir_tags']
  4240. );
  4241. $current_full_path = $zc['mp3_dir'].(!empty($root) ? '/'.$root : '');
  4242. $current_path = (!empty($root)) ? $root.'/' : '';
  4243. if (!$result = @scandir($current_full_path)) {
  4244. zina_debug(zt('Could not read directory'));
  4245. return array();
  4246. }
  4247. $mp3_dir = $zc['mp3_dir'];
  4248. $ext_mus = $zc['ext_mus'];
  4249. $dir_skip = $zc['dir_skip'];
  4250. $dir_tags = $opts['dir_tags'];
  4251. $low_look = ($zc['low_lookahead'] && !$category);
  4252. $id3 = ($zc['mp3_id3'] || $zc['mp3_info']);
  4253. $check_boxes = (($zc['is_admin'] && $zc['cache']) || ($zc['playlists'] && $zc['session_pls']) || $zc['play_sel'] || $zc['cmp_sel']);
  4254. $rating = ($zc['database'] && $zc['rating_files']);
  4255. $dir['lofi'] = false;
  4256. $dir['images'] = $dir['subdirs'] = $dir['files'] = $dir['captions'] = $dir = array();
  4257. $dir['image'] = null;
  4258. $dir['dir_write'] = $dir_write = ($zc['is_admin'] && is_writeable($zc['cur_dir']));
  4259. $dir['dir_edit'] = $dir_edit = (zina_cms_access('editor') && ($zc['database'] || ($zc['is_admin'] && $dir_write)));
  4260. $subdirs = &$dir['subdirs'];
  4261. $files = &$dir['files'];
  4262. $db_subdirs = array();
  4263. $db_dir = array();
  4264. $db_files = array();
  4265. $db = false;
  4266. $file_dir_info = false;
  4267. $now = time();
  4268. $diff = $zc['new_time']*86400;
  4269. #todo: cat_sort is overridable...?
  4270. $get_mtime = ($zc['new_highlight'] || $zc['cat_sort']);
  4271. if ($zc['database']) {
  4272. $db_path = (empty($root)) ? '.' : $root;
  4273. $db_dir = zdbq_array("SELECT * FROM {dirs} WHERE path = '%s'", $db_path);
  4274. if (!empty($db_dir)) {
  4275. $db = true;
  4276. $dir = array_merge($dir, $db_dir[0]);
  4277. $dir_other = unserialize_utf8($dir['other']);
  4278. if (!empty($dir_other)) {
  4279. $dir = array_merge($dir, $dir_other);
  4280. }
  4281. if ($opts['get_files']) {
  4282. $db_files = zdbq_assoc('full_path',
  4283. "SELECT *, IF(path != '.', CONCAT(path, IF(ISNULL(path), '', '/'), file), file) AS full_path ".
  4284. "FROM {files} WHERE dir_id = %d", $dir['id']);
  4285. }
  4286. if (!isset($dir['various'])) {
  4287. $dir['various'] = ($zc['various'] && zina_is_various($current_full_path, $root));
  4288. } else {
  4289. $dir['various'] = ($dir['various'] && $zc['various']);
  4290. }
  4291. #TODO: get_files???
  4292. if (!$category || ($dir_tags && $dir['various']) || $opts['cat_images']) {
  4293. $db_subdirs = zdbq_assoc('path',
  4294. "SELECT d.*, f.id3_info FROM {dirs} AS d LEFT OUTER JOIN {files} AS f ON d.id = f.dir_id ".
  4295. "WHERE d.parent_id = %d", $dir['id']);
  4296. } else {
  4297. $db_subdirs = zdbq_assoc('path', "SELECT * FROM {dirs} WHERE parent_id = %d", $dir['id']);
  4298. }
  4299. }
  4300. #todo: logic is old...
  4301. if ($opts['get_files'] && (($zc['rating_files'] && $zc['rating_files_public']) || $zc['is_admin'])) {
  4302. $ratings = true;
  4303. if ($zc['user_id'] > 0) {
  4304. $user_ratings = zdb_get_song_user_ratings($root, $zc['user_id']);
  4305. }
  4306. }
  4307. }
  4308. if (!isset($dir['various'])) {
  4309. $dir['various'] = ($zc['various'] && zina_is_various($current_full_path, $root));
  4310. }
  4311. #TODO: zc['cat_split']? wha about dir overrides???
  4312. $various_lookahead = ($category && $zc['various'] && $zc['cat_various_lookahead'] && ($zc['cat_split'] == 2 || $zc['cat_split'] == 3));
  4313. # Custom Playlists
  4314. $c_pls = $zc['cache_pls_dir'].'/'.str_replace('/',' - ',$root).'.m3u';
  4315. if ($zc['cache'] && $opts['get_files'] && file_exists($c_pls)) {
  4316. $c_pls_arr = zunserialize_alt(file_get_contents($c_pls));
  4317. } else {
  4318. $c_pls_arr = array();
  4319. }
  4320. # will probably fuck up on non-Art/Dir structures? test!
  4321. if ($dir_tags) {
  4322. if (isset($dir['title']) && !$category) {
  4323. if (strpos($root, '/') === false) $dir['title'] = null;
  4324. } else {
  4325. $dir['title'] = null;
  4326. }
  4327. } else {
  4328. $dir['title'] = null;
  4329. }
  4330. foreach($result as $filename) {
  4331. #$dir_tags = $opts['dir_tag'];
  4332. if ($filename == '.' || $filename == '..') continue;
  4333. $full_path = $current_full_path.'/'.$filename;
  4334. $path = $current_path.$filename;
  4335. $path_enc = utf8_encode($path);
  4336. if (isset($db_subdirs[$path_enc]) || is_dir($full_path)) {
  4337. if ($filename[0] == $dir_skip) continue;
  4338. $subdir = &$subdirs[$path];
  4339. $subdir = array(
  4340. 'image' => null,
  4341. 'query' => null,
  4342. 'path' => $path,
  4343. 'new' => false,
  4344. 'various' => null,
  4345. 'person' => false,
  4346. );
  4347. if (isset($db_subdirs[$path_enc]['other'])) {
  4348. $other = unserialize_utf8($db_subdirs[$path_enc]['other']);
  4349. if (isset($other['image'])) {
  4350. if ($other['image']) $subdir['image'] = $other['image'];
  4351. $subdir['various'] = $other['various'];
  4352. $subdir['category'] = $other['category'];
  4353. if (isset($other['person'])) $subdir['person'] = $other['person'];
  4354. }
  4355. }
  4356. if (empty($subdir['image']) && (!$category || $opts['cat_images'])) {
  4357. $subdir['image'] = zina_get_dir_item($full_path,'/\.('.$zc['ext_graphic'].')$/i');
  4358. }
  4359. if (is_null($subdir['various']) && $various_lookahead){
  4360. $subdir['various'] = file_exists($full_path.'/'.$zc['various_file']);
  4361. }
  4362. /*
  4363. * TODO: XXX QQQ try to simply below...
  4364. */
  4365. if (!$category && $id3) {
  4366. if (isset($db_subdirs[$path_enc]['id3_info'])) {
  4367. $subdir['info'] = unserialize_utf8($db_subdirs[$path_enc]['id3_info']);
  4368. } else {
  4369. $subdir_file = zina_get_dir_item($full_path,'/\.('.$ext_mus.')$/i');
  4370. if (!empty($subdir_file)) {
  4371. $subdir['info'] = zina_get_file_info($full_path.'/'.$subdir_file, false, true, $zc['genres']);
  4372. }
  4373. }
  4374. if (isset($db_subdirs[$path_enc]) && !empty($db_subdirs[$path_enc]['title'])) {
  4375. #if ($dir_tags && isset($db_subdirs[$path]) && !empty($db_subdirs[$path]['title'])) {
  4376. $subdir['title'] = $db_subdirs[$path_enc]['title'];
  4377. } else if ($dir_tags && isset($subdir['info']->album)) {
  4378. $subdir_title = trim($subdir['info']->album);
  4379. if (!empty($subdir_title)) $subdir['title'] = $subdir_title;
  4380. }
  4381. } elseif ($dir_tags && $id3) {
  4382. if (isset($db_subdirs[$path_enc]) && !empty($db_subdirs[$path_enc]['title'])) {
  4383. $subdir['title'] = $db_subdirs[$path_enc]['title'];
  4384. } #elseif (isset('id3_onfo? ??? for backward compat?
  4385. if ($dir['various'] && isset($db_subdirs[$path_enc]['id3_info'])) {
  4386. $subdir['info'] = unserialize_utf8($db_subdirs[$path_enc]['id3_info']);
  4387. }
  4388. }
  4389. if (!isset($subdir['title'])) {
  4390. $subdir['title'] = ztheme('title',$filename);
  4391. }
  4392. if ((!$category || $opts['cat_images']) && (empty($subdir['image']) || $subdir['image'] == 'cover_id3_zina.jpg') && isset($subdir['info']->image)) {
  4393. $subdir['image'] = 'zina_id3_zina.jpg';
  4394. }
  4395. if ($low_look) {
  4396. $subdir['lofi'] = zina_get_dir_item($full_path, '/('.$zc['low_suf'].')\.('.$zc['ext_mus'].')$/i');
  4397. }
  4398. if ($get_mtime) {
  4399. $subdir['mtime'] = $mtime = (isset($db_subdirs[$path_enc]['mtime'])) ? $db_subdirs[$path_enc]['mtime'] : filemtime($full_path);
  4400. $subdir['new'] = ($zc['new_highlight'] && $now - $mtime < $diff);
  4401. }
  4402. #TODO: see if can be used elsewhere...e.g. other zina_get_dir()s
  4403. } elseif ($opts['get_files']) { # file
  4404. if (preg_match('/\.('.$ext_mus.')$/i', $filename, $matches)) {
  4405. $file_ext = $matches[1];
  4406. $extras = array();
  4407. if ($zc['low'] && preg_match('/('.$zc['low_suf'].')\.('.$ext_mus.')$/i', $filename)) {
  4408. $lofi_path = $path;
  4409. $path = preg_replace('/('.$zc['low_suf'].')\.('.$ext_mus.')$/i', '.$2', $path);
  4410. $dir['lofi'] = $files[$path]['lofi'] = true;
  4411. $files[$path]['lofi_path'] = $lofi_path;
  4412. continue;
  4413. }
  4414. $file = &$files[$path];
  4415. $file['fake'] = $file['remote'] = false;
  4416. } elseif ($filename == $zc['dir_file']) {
  4417. if (!isset($dir['description'])) $dir['description'] = file_get_contents($full_path);
  4418. } elseif (preg_match('/\.('.$zc['ext_graphic'].')$/i', $filename)) {
  4419. $dir['images'][] = $filename;
  4420. if ($zc['image_captions']) {
  4421. if (file_exists($full_path.'.txt')) {
  4422. $dir['captions'][$filename] = rtrim(file_get_contents($full_path.'.txt'),"\r\n");
  4423. } else {
  4424. $dir['captions'][$filename] = '';
  4425. }
  4426. }
  4427. } elseif ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $filename, $matches)) {
  4428. $file = &$files[$path];
  4429. $file['remote'] = true;
  4430. $file['fake'] = false;
  4431. $file_ext = $matches[1];
  4432. } elseif ($zc['fake'] && preg_match('/\.('.$zc['fake_ext'].')$/i', $filename, $matches)) {
  4433. $file = &$files[$path];
  4434. $file['fake'] = true;
  4435. $file['remote'] = false;
  4436. $file_ext = $matches[1];
  4437. } elseif ($zc['mm'] && preg_match('/\.('.$zc['mm_ext'].')$/i', $filename, $matches)) {
  4438. #todo: consider putting mm in files...
  4439. $mm = &$dir['mm'][$path];
  4440. $mm['full_path'] = $path;
  4441. $mm['path'] = $root;
  4442. $mm['file'] = $filename;
  4443. $mm['filesize'] = filesize($full_path);
  4444. $mm['ext'] = $ext = strtolower($matches[1]);
  4445. $mm['description'] = zina_get_file_desc($zc['song_blurbs'], $full_path.'.txt');
  4446. $mm['new'] = false;
  4447. if ($get_mtime) {
  4448. $mm['mtime'] = $mtime = filemtime($full_path);
  4449. $mm['new'] = ($zc['new_highlight'] && $now - $mtime < $diff);
  4450. }
  4451. $mm['checkbox'] = false;
  4452. $mm['title'] = ztheme('song_title', substr($filename,0,-(strlen($ext)+1)));
  4453. if (isset($zc['mm_types'][$ext]['player'])) {
  4454. $mm['opts']['play'] = array('path'=>$path, 'query'=>'l=24&amp;m=1');
  4455. $mm['opts']['play']['local'] = (!$zc['stream_int'] || preg_match('#^'.$_SERVER['DOCUMENT_ROOT'].'#i',$zc['mp3_dir']));
  4456. $mm['opts']['play']['full_path'] = $full_path;
  4457. }
  4458. if ($zc['mm_down']) $mm['opts']['download'] = array('path'=>$path, 'query'=>'l=25');
  4459. if ($dir_write) $mm['opts_edit']['edit'] = array('path'=>$path, 'query'=>'l=22&amp;m=4');
  4460. }
  4461. if (isset($files[$path])) {
  4462. $db_filepath = zcheck_utf8($path, false);
  4463. #$db_filepath = utf8_encode($path);;
  4464. if (isset($db_files[$db_filepath])) {
  4465. $file = array_merge($file, $db_files[$db_filepath]);
  4466. $file['info'] = unserialize_utf8($files[$path]['id3_info']);
  4467. $extras = unserialize_utf8($files[$path]['other']);
  4468. }
  4469. $file['full_path'] = $path;
  4470. $file['path'] = $root;
  4471. $file['file'] = $filename;
  4472. $file['new'] = $file['checkbox'] = $file['ratings'] = false;
  4473. if ($get_mtime) {
  4474. $file['mtime'] = filemtime($full_path);
  4475. $file['new'] = ($zc['new_highlight'] && $now - $file['mtime'] < $diff);
  4476. }
  4477. if (!isset($file['info']) && ($id3 || $file['remote'])) {
  4478. $file['info'] = zina_get_file_info($full_path, $zc['mp3_info'], ($zc['mp3_id3']|| $file['remote']), $zc['genres']);
  4479. }
  4480. if (!isset($file['description'])) {
  4481. $file['description'] = zina_get_file_desc($zc['song_blurbs'], substr($full_path, 0, -strlen($file_ext)).'txt');
  4482. }
  4483. if (isset($file['description'])) {
  4484. $file['description'] = zina_url_filter($file['description']);
  4485. }
  4486. if (isset($file['info']) && !$file_dir_info && !$db) {
  4487. $dir['info'] = $file['info'];
  4488. if (isset($dir['info']->year)) $dir['year'] = $dir['info']->year;
  4489. if (isset($dir['info']->genre)) $dir['genre'] = $dir['info']->genre;
  4490. $file_dir_info = true;
  4491. }
  4492. if (isset($file['info']->title)) {
  4493. $file['title'] = ztheme('song_title', $file['info']->title, true);
  4494. } else {
  4495. $file['title'] = zina_content_song_title($filename);
  4496. }
  4497. if ($zc['song_extras']) {
  4498. foreach ($zc['song_es_exts'] as $ext) {
  4499. if (isset($extras[$ext]) || file_exists(substr($full_path, 0, -strlen($file_ext)).$ext) || (isset($zc['third_'.$ext]) && $zc['third_'.$ext])) {
  4500. if ($zc['song_es'][$ext]['type'] == 'page_internal') {
  4501. $href = $path;
  4502. $query = 'l=29&amp;m='.$ext;
  4503. $attr = '';
  4504. } elseif ($zc['song_es'][$ext]['type'] == 'page_popup') {
  4505. $href = 'javascript: void 0;';
  4506. $query = NULL;
  4507. $attr = " onclick=\"WindowOpen('".zurl($path, 'l=29&amp;m='.$ext)."','lyrics',".($zc['song_es'][$ext]['page_width']+20).",".$zc['song_es'][$ext]['page_height'].",'no');\"";
  4508. } elseif ($zc['song_es'][$ext]['type'] == 'external') {
  4509. $href = 'javascript: alert(\''.zt('Error').'\');';
  4510. $query = $attr = null;
  4511. $extra_file = substr($full_path, 0, -strlen($file_ext)).$ext;
  4512. $content = trim(file_get_contents($extra_file));
  4513. if (!empty($content)) $href = $content;
  4514. } else {
  4515. $href = 'javascript: alert(\''.zt('Error').'\');';
  4516. $query = $attr = null;
  4517. }
  4518. $file['extras'][$ext] = array('path'=>$href, 'query'=>$query, 'attr'=>$attr,
  4519. 'text'=>$zc['song_es'][$ext]['name'] );
  4520. }
  4521. if ($dir_edit) { #edit
  4522. $file['extras_edit'][$ext] = array('path'=>$path,
  4523. 'query'=>'l=22&amp;m='.$ext,
  4524. 'attr'=>null, 'text'=>zt('Edit @extra', array('@extra'=>$zc['song_es'][$ext]['name']))
  4525. );
  4526. }
  4527. }
  4528. } # end extras
  4529. if ($zc['play'] && !$file['fake'] && (!$file['remote'] || isset($file['info']->url))) {
  4530. $file['title_link'] = $file['opts']['play'] = array('path'=>$path, 'query'=>'l=8&amp;m=1', 'attr'=>' class="zinamp"');
  4531. }
  4532. if ($check_boxes && !$file['fake'] && (!$file['remote'] || isset($file['info']->url))) {
  4533. $file['checkbox'] = array('name'=>'mp3s[]', 'value'=>zrawurlencode($path), 'checked'=>(!empty($c_pls_arr) && in_array($path, $c_pls_arr)));
  4534. }
  4535. if (isset($file['lofi'])) {
  4536. $file['opts']['play_lofi'] = array('path'=>$file['lofi_path'], 'query'=>'l=8&amp;m=1');
  4537. } elseif ($zc['resample'] && preg_match('/\.('.$zc['ext_enc'].')$/i', $filename)) {
  4538. $file['opts']['play_lofi'] = array('path'=>$path, 'query'=>'l=8&amp;m=1&amp;lf');
  4539. }
  4540. if ($zc['download']) {
  4541. if ($file['remote']) {
  4542. if (isset($file['info']->download)) $file['opts']['download'] = array('path'=>$file['info']->download, 'query'=>null);
  4543. } elseif (!$file['fake']) {
  4544. $file['opts']['download'] = array('path'=>$path, 'query'=>'l=12');
  4545. }
  4546. }
  4547. if ($dir_edit) $file['opts_edit']['edit'] = array('path'=>$path, 'query'=>'l=22&amp;m=3');
  4548. if ($dir_write) $file['delete'] = array('path'=>$path, 'query'=>'l=75');
  4549. $file['ratings'] = ($rating && !$file['fake']);
  4550. if (!isset($file['sum_votes'])) {
  4551. $file['sum_votes'] = 0;
  4552. $file['sum_rating'] = 0;
  4553. $file['sum_plays'] = 0;
  4554. $file['sum_downloads'] = 0;
  4555. }
  4556. $file['user_rating'] = (isset($user_ratings[$db_filepath])) ? $user_ratings[$db_filepath]['rating'] : 0;
  4557. } # end isset(file)
  4558. } #end file
  4559. } #end loop
  4560. if (isset($dir['description'])) $dir['description'] = zina_url_filter(nl2br($dir['description']));
  4561. if (empty($dir['images']) && isset($file['info']->image)) {
  4562. $dir['images'][] = 'zina_id3_zina.jpg';
  4563. }
  4564. return $dir;
  4565. }
  4566. function zina_url_filter($input) {
  4567. return preg_replace('/\{internal:(.*?)\}/ie', 'zurl("$1");', $input);
  4568. }
  4569. function zina_get_file_desc($allow, $file) {
  4570. return ($allow && file_exists($file)) ? file_get_contents($file) : false;
  4571. }
  4572. function zina_get_form_token() {
  4573. global $zc;
  4574. return ztheme('form_hidden', 'token', zina_token_sess($zc['user_id']));
  4575. }
  4576. function zina_get_tmpl_cache_file($path) {
  4577. if (empty($path)) {
  4578. $cache_file = md5($_SERVER['REQUEST_URI']).'_'.zina_get_page_opt($path).zina_get_catsort_opt($path);
  4579. } else {
  4580. $cache_file = md5($path);
  4581. }
  4582. return $cache_file;
  4583. }
  4584. function zina_get_catsort_opt($path) {
  4585. global $zc;
  4586. $cat_sort = $zc['cat_sort_default'];
  4587. if ($zc['cat_sort']) {
  4588. if (isset($_GET['zs']) && in_array($_GET['zs'], array('a','ad','d','dd'))) {
  4589. $cat_sort = $_SESSION['zina']['catsort'][$path] = $_GET['zs'];
  4590. } elseif (isset($_SESSION['zina']['catsort'][$path])) {
  4591. $cat_sort = $_SESSION['zina']['catsort'][$path];
  4592. }
  4593. }
  4594. return $cat_sort;
  4595. }
  4596. function zina_get_page_opt($path='') {
  4597. #todo: cat_splits might not honor overrides...
  4598. global $zc;
  4599. $page = ($zc['cat_split'] == 2) ? 'A' : 1;
  4600. if ($zc['cat_split']) {
  4601. if (isset($_GET['page']) && zina_validate('alpha_numeric',$_GET['page'])) {
  4602. $page = $_SESSION['zina'][$path]['page'] = $_GET['page'];
  4603. } elseif (isset($_GET['page']) && $zc['cat_split'] >= 2 && $zc['cat_various_lookahead'] && !strstr($path,'..') && is_dir($zc['mp3_dir'].'/'.$_GET['page'])) {
  4604. $page = $_SESSION['zina'][$path]['page'] = $_GET['page'];
  4605. } elseif (isset($_SESSION['zina'][$path]['page'])) {
  4606. $page = $_SESSION['zina'][$path]['page'];
  4607. }
  4608. }
  4609. return $page;
  4610. }
  4611. function zina_get_genres_list($genres = array(), $image_type = 'genre') {
  4612. global $zc;
  4613. $items = array();
  4614. if (empty($genres)) {
  4615. if ($zc['database']) {
  4616. #TODO:XXX...ordering options? obsolete? integrate? make opt?
  4617. # cant be by weight or cat split wont work?
  4618. $genres = zdbq_array_list("SELECT genre FROM {genres} AS g INNER JOIN {genre_tree} as gt ON g.id=gt.id ".
  4619. "WHERE pid = 0 ORDER BY genre");
  4620. } else {
  4621. $genres = zina_core_cache('genres');
  4622. }
  4623. }
  4624. if (!empty($genres)) {
  4625. foreach ($genres as $g) {
  4626. $items[$g] = array(
  4627. 'path' => null,
  4628. 'query' => 'l=13&amp;pl='.rawurlencode($g),
  4629. 'title' => zcheck_utf8($g),
  4630. 'new' => false,
  4631. );
  4632. if ($zc['genres_images']) {
  4633. $path = zina_get_genre_image_path($g, $image_type);
  4634. $items[$g]['image_raw'] = $image_raw = ztheme('image', $path, $g, null, 'class="genre-image"');
  4635. $items[$g]['image'] = zl($image_raw, null, $items[$g]['query']);
  4636. }
  4637. }
  4638. }
  4639. return $items;
  4640. }
  4641. function zina_get_genre_image_path($g, $type = 'genre') {
  4642. global $zc;
  4643. $genre_file = ztheme('image_genre', $g);
  4644. if ($zc['res_genre_img']) {
  4645. $path = zurl(null,'l=7&amp;it='.$type.'&amp;img='.rawurlencode($g), null);
  4646. } elseif (file_exists($zc['theme_path_abs'].'/images/'.$genre_file)) {
  4647. $path = zpath_to_theme().'/images/'.$genre_file;
  4648. } else {
  4649. $path = zpath_to_theme().'/images/'.ztheme('missing_image','genre');
  4650. }
  4651. return $path;
  4652. }
  4653. #todo: your using this to get images!
  4654. function zina_get_dir_list(&$dirs, $sort = true) {
  4655. global $zc;
  4656. $checkbox = ($zc['is_admin'] || ($zc['playlists'] && $zc['session_pls']));
  4657. $sort = ($zc['dir_list_sort'] && $sort);
  4658. if ($sort) {
  4659. if ($zc['dir_list_sort_asc']) {
  4660. $sort = SORT_ASC;
  4661. $empty = 9000;
  4662. } else {
  4663. $sort = SORT_DESC;
  4664. $empty = 0;
  4665. }
  4666. }
  4667. foreach ($dirs as $key=>$opts) {
  4668. if (empty($key)) {
  4669. } elseif (substr_count($key, '/') < 1) {
  4670. #if ($zc['play'] && $zc['play_rec'] && $subdir_num > 1) {
  4671. # $zina['dir_opts']['play_rec'] = array('path'=>$path, 'query'=>'l=8&amp;m=10');
  4672. #}
  4673. if ($zc['play'] && $zc['play_rec_rand']) {
  4674. $dirs[$key]['opts']['play_rec_rand'] = array('path'=>$opts['path'], 'query'=>'l=8&amp;m=10&amp;c');
  4675. }
  4676. } else {
  4677. zina_content_subdir_opts($dirs[$key], $opts['path'], $checkbox, $opts);
  4678. }
  4679. if (!isset($opts['title'])) {
  4680. $dirs[$key]['title'] = ztheme('title',$opts['path']);
  4681. }
  4682. $dirs[$key]['image_raw'] = $image_raw = ztheme('image', zina_get_image_url($opts['path'], $opts['image'],'sub'), $dirs[$key]['title'], null, 'class="sub-image"');
  4683. $dirs[$key]['image'] = zl($image_raw, $opts['path']);
  4684. if ($sort) {
  4685. $year[$key] = (isset($dirs[$key]['info']->year)) ? $dirs[$key]['info']->year : $empty;
  4686. }
  4687. }
  4688. if ($sort) array_multisort($year, $sort, $dirs);
  4689. }
  4690. function zina_get_image_url($path, $image, $type, $absolute = false) {
  4691. global $zc;
  4692. if (!in_array($type, array('sub','dir','full','search'))) $type = 'dir';
  4693. if (empty($image)) {
  4694. if ($zc['res_'.$type.'_img'] && $zc[$type.'_img_txt']) {
  4695. return zurl($path,'l=7&amp;it='.$type, null, $absolute);
  4696. } else {
  4697. return zpath_to_theme().'/images/'.ztheme('missing_image',$type);
  4698. }
  4699. } else {
  4700. if ($zc['res_'.$type.'_img'] && preg_match('/\.('.$zc['resize_types'].')$/i', $image)) {
  4701. if ($zc['cache_imgs']) {
  4702. $res_out_type = ($zc['res_out_type'] == 'jpeg') ? 'jpg' : $zc['res_out_type'];
  4703. $cache_img = $type.md5($zc['mp3_dir'].'/'.$path.'/'.$image).'.'.$res_out_type;
  4704. if (file_exists($zc['cache_imgs_dir'].'/'.$cache_img)) {
  4705. if ($absolute) {
  4706. $base_root = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
  4707. $base_url = $base_root .= '://'.$zc['auth']. preg_replace('/[^a-z0-9-:._]/i', '', $_SERVER['HTTP_HOST']);
  4708. return $base_url.$zc['zina_dir_rel'].'/'.$zc['cache_imgs_dir_rel'].'/'.$cache_img;
  4709. } else {
  4710. return $zc['zina_dir_rel'].'/'.$zc['cache_imgs_dir_rel'].'/'.$cache_img;
  4711. }
  4712. }
  4713. }
  4714. return zurl($path,'l=7&amp;img='.rawurlencode($image).'&amp;it='.$type, null, $absolute);
  4715. } elseif ($zc['stream_int']) {
  4716. return zurl($path,'l=11&amp;img='.rawurlencode($image), null, $absolute);
  4717. } else { #NORMAL
  4718. return zurl($path.'/'.$image,NULL,NULL,$absolute,TRUE);
  4719. }
  4720. }
  4721. }
  4722. function zina_get_vote_url($path) {
  4723. return zurl($path,'l=16').'&n=';
  4724. }
  4725. function zina_get_page_title($array=null) {
  4726. static $title;
  4727. if ($array) $title = $array;
  4728. return $title;
  4729. }
  4730. function zina_get_current_dir($current=null) {
  4731. static $dir;
  4732. if ($current) $dir = $current;
  4733. return $dir;
  4734. }
  4735. function zina_get_breadcrumb($path, $alt_title = null, $full = false, $links = array()) {
  4736. global $zc;
  4737. if (empty($links)) {
  4738. $tmp_path = '';
  4739. $crumbs = explode('/',$path);
  4740. $size = sizeof($crumbs);
  4741. for($i=0; $i < $size; $i++) {
  4742. if ($tmp_path != '') $tmp_path = $tmp_path.'/';
  4743. $tmp_path .= $crumbs[$i];
  4744. $title = ztheme('title',$crumbs[$i]);
  4745. $links[] = zl($title,$tmp_path);
  4746. $titles[] = $title;
  4747. }
  4748. if (empty($alt_title)) {
  4749. zina_get_current_dir(ztheme('title',$crumbs[$size-1]));
  4750. zina_get_page_title($titles);
  4751. } else {
  4752. array_pop($titles);
  4753. $titles[] = $alt_title;
  4754. if ($full) {
  4755. array_pop($links);
  4756. $links[] = zl($alt_title, $path);
  4757. }
  4758. zina_get_current_dir(ztheme('title',$alt_title));
  4759. zina_get_page_title($titles);
  4760. }
  4761. if (!$full) array_pop($links);
  4762. }
  4763. $home[] = (!empty($path) || isset($_GET['l'])) ? zl(zt($zc['main_dir_title']),'') : zt($zc['main_dir_title']);
  4764. if ($zc['genres'])
  4765. $home[] = (isset($_GET['l']) && $_GET['l'] == '14') ? zt('Genres') : zl(zt('Genres'),null,'l=14');
  4766. if ($zc['playlists'] && ($zc['pls_public'] || $zc['is_admin']))
  4767. $home[] = zl(zt('Playlists'),null,'l=2');
  4768. if ($zc['database'] && $zc['stats'] && ($zc['is_admin'] || $zc['stats_public']))
  4769. $home[] = (isset($_GET['l']) && $_GET['l'] == '15') ? zt('Statistics') : zl(zt('Statistics'),'','l=15');
  4770. array_unshift($links,ztheme('breadcrumb_home', $home));
  4771. return $links;
  4772. }
  4773. /*
  4774. * @path must be full
  4775. */
  4776. function zina_get_file_info($path, $info=true, $id3=true, $genre=false, $image = false) {
  4777. global $zc;
  4778. $mp3 = false;
  4779. if ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $path)) {
  4780. $mp3 = new remoteFile($path, $info, $id3);
  4781. } else {
  4782. $mp3 = new mp3($path, $info, $id3, $zc['mp3_info_faster'], $genre, $image);
  4783. }
  4784. return $mp3;
  4785. }
  4786. function zina_get_file_xml($path) {
  4787. global $zc;
  4788. $output = '<?xml version="1.0" encoding="UTF-8"?><track>';
  4789. $mp3 = null;
  4790. $result = array();
  4791. if ($zc['database']) {
  4792. $result = zdbq_array_single("SELECT * FROM {files} WHERE path = '%s' AND file = '%s'", dirname($path), basename($path));
  4793. if (!empty($result)) {
  4794. /*
  4795. foreach ($result as $key => $val) {
  4796. if (in_array($key, array('file', 'path', 'id3_info', 'other'))) continue;
  4797. $output .= xml_field($key, $val);
  4798. }
  4799. */
  4800. $other = unserialize_utf8($result['other']);
  4801. unset($result['other']);
  4802. $mp3 = unserialize_utf8($result['id3_info']);
  4803. unset($result['id3_info']);
  4804. if ($zc['user_id'] > 0) {
  4805. $result['user_rating'] = zdbq_single("SELECT rating FROM {file_ratings} WHERE file_id = %d AND user_id = %d LIMIT 1", array($result['id'], $zc['user_id']));
  4806. $output .= xml_field('user_rating', $result['user_rating']);
  4807. }
  4808. }
  4809. if ($zc['rating_files']) {
  4810. $output .= xml_field('vote_url', zurl($path,'l=16',null,true).'&n=');
  4811. }
  4812. }
  4813. if (empty($mp3)) {
  4814. $mp3 = zina_get_file_info($zc['mp3_dir'].'/'.$path,true,true,true);
  4815. }
  4816. $result = array_merge($result, get_object_vars($mp3));
  4817. if (empty($result['title'])) $result['title'] = ztheme('song_title', preg_replace('/\.('.$zc['ext_mus'].')$/i', '', $path));
  4818. $items = array('bitrate', 'frequency', 'sum_rating', 'stereo');
  4819. foreach ($items as $item) {
  4820. if (isset($result[$item]) && !empty($result[$item])) {
  4821. $output .= xml_field($item, $result[$item]);
  4822. }
  4823. }
  4824. $img_path = dirname($path);
  4825. $img = zina_get_dir_item($zc['mp3_dir'].'/'.$img_path,'/\.('.$zc['ext_graphic'].')$/i');
  4826. if (empty($img) && isset($mp3->image)) $img = 'zina_id3_zina.jpg';
  4827. #todo: make 'sub' configable?
  4828. $img_url = zina_get_image_url($img_path, $img, 'sub', true);
  4829. $output .= xml_field('image', $img_url);
  4830. if ($zc['zinamp'] && $zc['lastfm']) {
  4831. zina_zinamp_start($path);
  4832. $output .= xml_field('complete_url', zurl($path,'l=56',null,true).'&n=');
  4833. $output .= xml_field('start_url', zurl($path,'l=66',null,true));
  4834. }
  4835. $result['path'] = $path;
  4836. $parts = explode('/', $path);
  4837. if (sizeof($parts) == 3) {
  4838. $result['artist_url'] = zurl($parts[0], null, null, true);
  4839. $result['album_url'] = zurl($parts[0].'/'.$parts[1], null, null, true);
  4840. $output .= xml_field('artist_url', $result['artist_url']);
  4841. $output .= xml_field('album_url', $result['album_url']);
  4842. }
  4843. #todo: genre url?
  4844. if ($zc['song_extras'] && in_array('lyr', $zc['song_es_exts'])) {
  4845. $output .= xml_field('lyric_url', zurl($path,'l=57&m=lyr&pl=zinamp',null,true));
  4846. }
  4847. $output .= "<info>\n<![CDATA[".ztheme('zinamp_song_info',$result)."]]>\n</info>";
  4848. return $output.'</track>';
  4849. }
  4850. function zina_zinamp_start($path) {
  4851. $now = time();
  4852. $_SESSION['zinamp_track'][$path] = $now;
  4853. if (sizeof($_SESSION['zinamp_track']) > 2) {
  4854. foreach($_SESSION['zinamp_track'] as $track => $time) {
  4855. if ($now > $time + (60*60*1)) {
  4856. unset($_SESSION['zinamp_track'][$track]);
  4857. }
  4858. }
  4859. }
  4860. }
  4861. function zina_get_dir_item($path, $regex) {
  4862. global $zc;
  4863. @set_time_limit($zc['timeout']);
  4864. if ($results = @scandir($path)) {
  4865. foreach($results as $file) {
  4866. if (preg_match($regex, $file)) return $file;
  4867. }
  4868. }
  4869. return false;
  4870. /*
  4871. @set_time_limit($zc['timeout']);
  4872. if (is_dir($path) && $dh = opendir($path)) {
  4873. while (($file = readdir($dh)) !== false) {
  4874. if (preg_match($regex, $file)) {
  4875. closedir($dh);
  4876. return $file;
  4877. }
  4878. }
  4879. closedir($dh);
  4880. }
  4881. return false;
  4882. */
  4883. }
  4884. function zina_get_title_playlist($path, $custom = false, $low = false) {
  4885. global $zc;
  4886. $dirs = zina_core_cache('files_assoc', $path, array('low'=>$low,'file_sort'=>$zc['files_sort'],'custom'=>$custom,'force'=>(empty($path))));
  4887. $files = array();
  4888. if (isset($dirs[$path])) {
  4889. foreach($dirs[$path] as $file) {
  4890. $files[] = (empty($path)) ? $file : $path.'/'.$file;
  4891. }
  4892. }
  4893. return zina_get_playlist($files, $low);
  4894. }
  4895. function zina_get_song_url($file, $resample = false) {
  4896. global $zc;
  4897. static $count = 0;
  4898. $format = $zc['playlist_format'];
  4899. $remote = ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $file));
  4900. #if (!$zc['pos'] && !$zc['play_local']) { ???
  4901. if ($zc['stream_int'] || $resample || $remote) {
  4902. if ($remote || ($zc['stream_extinf'] && $zc['mp3_id3'] && $count++ < $zc['stream_extinf_limit'])) {
  4903. $mp3 = zina_get_file_info($zc['mp3_dir'].'/'.$file);
  4904. if ($mp3->tag) {
  4905. $at = ztheme('artist_song', $mp3->title, $mp3->artist);
  4906. } else {
  4907. $at = zina_get_file_artist_title($file, false);
  4908. }
  4909. $length = isset($mp3->length) ? $mp3->length : -1;
  4910. } else {
  4911. $mp3 = false;
  4912. $at = zina_get_file_artist_title($file, false);
  4913. $length = -1;
  4914. }
  4915. $query = ($resample && !$remote) ? 'l=6' : 'l=10';
  4916. if (isset($zc['token'])) $query .= '&'.$zc['token'];
  4917. $url = zurl($file, $query, null, true);
  4918. if ($format == 'm3u') {
  4919. $at = utf8_decode(zdecode_entities($at));
  4920. $playlist = ($zc['stream_extinf']) ? "#EXTINF:$length,$at\n" : '';
  4921. $ext = '';
  4922. if (!$zc['clean_urls']) {
  4923. # winamp
  4924. $match = strtolower(substr($file, strrpos($file, '.')));
  4925. if ($match != '.mp3') $ext = '&ext='.$match;
  4926. }
  4927. return $playlist.$url.$ext."\n";
  4928. } elseif ($format == 'asx') {
  4929. $at = utf8_decode(zdecode_entities($at));
  4930. return '<entry><title>'.$at.'</title><ref href="'.$url.'"><STARTTIME VALUE="00:00:00.0" /></ref></entry>'."\n";
  4931. } elseif ($format == 'xspf') {
  4932. if ($mp3 && $mp3->tag) {
  4933. $meta = '';
  4934. if (isset($mp3->artist) && !empty($mp3->artist)) {
  4935. $meta .= xml_field('creator', $mp3->artist);
  4936. $meta .= xml_field('title', $mp3->title);
  4937. } else {
  4938. $meta .= xml_field('title', $at);
  4939. }
  4940. if ($length > 0) $meta .= xml_field('duration', ($length*1000));
  4941. } else {
  4942. $meta = xml_field('title', $at);
  4943. }
  4944. $meta .= xml_field('link', zurl($file,'l=54',NULL,TRUE));
  4945. $meta .= xml_field('meta', 'audio');
  4946. return '<track><location>'.$url.'</location>'.$meta.'</track>'."\n";
  4947. }
  4948. } else {
  4949. return zurl($file,NULL,NULL,TRUE,TRUE)."\n";
  4950. }
  4951. }
  4952. function zina_get_playlist($songs, $low, $c_pls = false) {
  4953. global $zc;
  4954. static $pls_ids = array();
  4955. $playlist = '';
  4956. if (!empty($songs)) {
  4957. if ($zc['pos'] || $zc['play_local']) {
  4958. foreach($songs as $song) {
  4959. $song = zrawurldecode($song);
  4960. if (preg_match('/\.lp$/i', $song)) {
  4961. $song = preg_replace('/\/\.lp$/i', '', $song);
  4962. $playlist .= zina_get_title_playlist($song, $zc['honor_custom'], $low);
  4963. } elseif (preg_match('/\.pls/i', $song)) {
  4964. $song = preg_replace('/\.pls/i', '', $song);
  4965. if (in_array($song, $pls_ids)) continue '';
  4966. $pls_ids[] = $song;
  4967. $playlist .= zina_get_playlist(zina_get_playlist_custom($song, $zc['honor_custom'], $low), $low);
  4968. } else {
  4969. $playlist .= $zc['mp3_dir'].'/'.$song."\n";
  4970. }
  4971. }
  4972. } else { # NOT POS
  4973. foreach($songs as $song) {
  4974. $song = zrawurldecode($song);
  4975. if (preg_match('/\.lp$/i', $song)) {
  4976. $song = preg_replace('/\/\.lp$/i', '', $song);
  4977. $playlist .= zina_get_title_playlist($song, $zc['honor_custom'], $low);
  4978. } elseif (preg_match('/\.pls$/i', $song)) {
  4979. $song = preg_replace('/\.pls/i', '', $song);
  4980. if (in_array($song, $pls_ids)) continue '';
  4981. $pls_ids[] = $song;
  4982. $playlist .= zina_get_playlist(zina_get_playlist_custom($song, $zc['honor_custom'], $low), $low);
  4983. } elseif ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $song)) {
  4984. $playlist .= zina_get_song_url($song);
  4985. } elseif ($low) {
  4986. $song_lofi = preg_replace('/(\.'.$zc['ext_mus'].')$/i', $zc['low_suf'].'$1', $song);
  4987. if ($c_pls && file_exists($zc['mp3_dir'].'/'.$song_lofi)) {
  4988. $playlist .= zina_get_song_url($song_lofi);
  4989. } elseif (preg_match('/('.$zc['low_suf'].')\.('.$zc['ext_mus'].')$/i', $song)) {
  4990. $playlist .= zina_get_song_url($song);
  4991. } elseif($zc['resample'] && preg_match('/\.('.$zc['ext_enc'].')$/i', $song)) {
  4992. $playlist .= zina_get_song_url($song, true);
  4993. } else {
  4994. $playlist .= zina_get_song_url($song);
  4995. }
  4996. } else {
  4997. $playlist .= zina_get_song_url($song);
  4998. }
  4999. }
  5000. }
  5001. }
  5002. return $playlist;
  5003. }
  5004. function zina_get_playlists_custom() {
  5005. global $zc;
  5006. $custom_playlists = null;
  5007. if (file_exists($zc['cache_pls_dir'])) {
  5008. $d = dir($zc['cache_pls_dir']);
  5009. while($entry = $d->read()) {
  5010. #use last for insteadh of preg
  5011. if (substr($entry,0,6) == '_zina_' && preg_match('/\.m3u$/i', $entry) ) {
  5012. $entry = preg_replace('/^_zina_/i','',$entry);
  5013. $custom_playlists[] = preg_replace('/\.m3u$/i','',$entry);
  5014. }
  5015. }
  5016. $d->close();
  5017. if (!empty($custom_playlists)) natcasesort($custom_playlists);
  5018. }
  5019. return $custom_playlists;
  5020. }
  5021. function zina_core_cache($type, $path = '', $opts = array()) {
  5022. global $zc;
  5023. $serial = true;
  5024. if ($type == 'dirs') {
  5025. $cache_file = $zc['cache_dirs_file'];
  5026. } elseif ($type == 'files') {
  5027. $files = array();
  5028. $files_assoc = zina_core_cache('files_assoc',$path, $opts);
  5029. foreach($files_assoc as $dir=> $array) {
  5030. foreach ($array as $file) {
  5031. $files[] = (empty($dir)) ? $file : $dir.'/'.$file;
  5032. }
  5033. }
  5034. return $files;
  5035. } elseif ($type == 'files_assoc') {
  5036. $cache_file = $zc['cache_files_assoc_file'];
  5037. if (isset($opts['low']) && $opts['low']) $cache_file = preg_replace('/(\.gz)$/i', $zc['low_suf'].'$1', $cache_file);
  5038. } elseif ($type == 'genre') {
  5039. #[genre]=>array(albums)
  5040. $cache_file = $zc['cache_genre_file'];
  5041. } elseif ($type == 'genres') {
  5042. # genre list
  5043. if ($zc['database']) {
  5044. $keys = zdbq_array_list("SELECT genre FROM {genres} ORDER BY genre");
  5045. if (empty($keys)) $keys[] = zt('No genres found.');
  5046. } else {
  5047. $genre = zina_core_cache('genre');
  5048. if (!empty($genre)) {
  5049. $keys = array_keys($genre);
  5050. natcasesort($keys);
  5051. } else {
  5052. $keys[] = zt('No genres found.');
  5053. }
  5054. }
  5055. return $keys;
  5056. } else {
  5057. return array();
  5058. }
  5059. if ($zc['cache'] && !(isset($opts['force']) && $opts['force']) && empty($path) && file_exists($cache_file)) {
  5060. if ($serial) {
  5061. return unserialize(implode('', gzfile($cache_file)));
  5062. } else {
  5063. return gzfile($cache_file);
  5064. }
  5065. }
  5066. $result_array = zina_scandir($type, $path, $opts);
  5067. if ($result_array) {
  5068. if ($zc['cache'] && empty($path)) {
  5069. if ($serial) {
  5070. $result = serialize($result_array);
  5071. } else {
  5072. $result = implode("\n", $result_array);
  5073. }
  5074. if (zina_check_directory(dirname($cache_file),1)) {
  5075. $fp = gzopen($cache_file, 'w1');
  5076. gzwrite($fp,$result);
  5077. gzclose($fp);
  5078. } else {
  5079. zina_debug(zt('Cache directories do not exist. Create them under "Settings."'));
  5080. }
  5081. }
  5082. return $result_array;
  5083. }
  5084. return array();
  5085. }
  5086. /*
  5087. */
  5088. function zina_scandir($type, $root='', $opts = array()) {
  5089. global $zc;
  5090. @set_time_limit($zc['timeout']);
  5091. $root = $zc['mp3_dir'] . ((!empty($root)) ? '/'.$root : '');
  5092. if(!is_dir($root)) return false;
  5093. if ($type == 'genre') {
  5094. $genres = array();
  5095. $files = zina_core_cache('files_assoc');
  5096. $dwm = array_keys($files);
  5097. foreach ($dwm as $dir) {
  5098. $file = $files[$dir][0];
  5099. $path = (!empty($dir)) ? $dir.'/'.$file : $file;
  5100. $path_full = $zc['mp3_dir'].'/'.$path;
  5101. if (file_exists($path_full)) {
  5102. $mp3 = zina_get_file_info($path_full, false, true, true);
  5103. $genre = ($mp3->tag && isset($mp3->genre)) ? $mp3->genre : zt('Unknown');
  5104. $genres[$genre][] = $dir;
  5105. }
  5106. }
  5107. return $genres;
  5108. }
  5109. $dirs_get = ($type == 'dirs');
  5110. $files_get_assoc = ($type == 'files_assoc');
  5111. if (!($dirs_get || $files_get_assoc)) return false;
  5112. $dir_sort = (isset($opts['dir_sort'])) ? $opts['sort'] : 1;
  5113. $file_sort = (isset($opts['file_sort'])) ? $opts['file_sort'] : 0;
  5114. $custom = (isset($opts['custom'])) ? $opts['custom'] : $zc['honor_custom'];
  5115. $low = (isset($opts['low']) && $opts['low']);
  5116. $dirs_all = $files = array();
  5117. $dirs_all[] = '';
  5118. $start = strlen($zc['mp3_dir'])+1;
  5119. $dirs = array($root);
  5120. while(($dir = array_pop($dirs)) !== null) {
  5121. if ($result = @scandir($dir)) {
  5122. @set_time_limit($zc['timeout']);
  5123. $custom_check = false;
  5124. foreach($result as $filename) {
  5125. if ($filename == '.' || $filename == '..') continue;
  5126. $path = $dir . '/' . $filename;
  5127. if (is_dir($path)) {
  5128. if ($filename[0] == $zc['dir_skip']) continue;
  5129. $dirs[] = $path;
  5130. if ($dirs_get) {
  5131. $dirs_all[] = substr($path, $start);
  5132. }
  5133. } elseif ($files_get_assoc && (preg_match('/\.('.$zc['ext_mus'].')$/i', $filename, $matches) ||
  5134. ($zc['remote'] && preg_match('/\.('.$zc['remote_ext'].')$/i', $filename)))) {
  5135. if ($files_get_assoc) {
  5136. $directory = substr($dir, $start);
  5137. if (empty($directory)) $directory = '';
  5138. if ($custom && !$custom_check) {
  5139. $custom_file = $zc['cache_pls_dir'].'/'.str_replace('/', ' - ', $directory).'.m3u';
  5140. if (file_exists($custom_file)) {
  5141. $custom_files = zunserialize_alt(file_get_contents($custom_file));
  5142. foreach($custom_files as $cf) {
  5143. if ($low) {
  5144. $lofi_file = preg_replace('/\.('.$zc['ext_mus'].')$/i', $zc['low_suf'].'.$1', $cf);
  5145. if (file_exists($zc['mp3_dir'].'/'.$lofi_file)) {
  5146. $files[$directory][] = basename($lofi_file);
  5147. if ($file_sort > 1) {
  5148. $mtimes[$directory][] = filemtime($zc['mp3_dir'].'/'.$lofi_file);
  5149. }
  5150. continue;
  5151. }
  5152. }
  5153. $files[$directory][] = basename($cf);
  5154. if ($file_sort > 1) {
  5155. $mtimes[$directory][] = filemtime($zc['mp3_dir'].'/'.$cf);
  5156. }
  5157. }
  5158. continue 2; # go to next dir
  5159. }
  5160. $custom_check = true;
  5161. }
  5162. if ($low) {
  5163. $lofi_file = preg_replace('/\.('.$zc['ext_mus'].')$/i', $zc['low_suf'].'.$1', $filename);
  5164. $lofi_path = (empty($directory)) ? $lofi_file : $directory.'/'.$lofi_file;
  5165. if (file_exists($zc['mp3_dir'].'/'.$lofi_path)) {
  5166. $files[$directory][] = $lofi_file;
  5167. $files_assoc_uniq[$directory] = true;
  5168. continue;
  5169. }
  5170. }
  5171. $files[$directory][] = $filename;
  5172. if ($file_sort > 1) {
  5173. $mtimes[$directory][] = filemtime($path);
  5174. }
  5175. }
  5176. }
  5177. }
  5178. } else {
  5179. zina_debug(zt('Could not read directory: @dir'),array('@dir'=>$dir));
  5180. }
  5181. }
  5182. if ($files_get_assoc) {
  5183. if (!empty($files)) {
  5184. if ($low) {
  5185. foreach ($files_assoc_uniq as $directory => $x) {
  5186. $files[$directory] = array_unique($files[$directory]);
  5187. }
  5188. }
  5189. if ($file_sort) {
  5190. foreach($files as $dir => $contents) {
  5191. if ($file_sort == 1) {
  5192. rsort($files[$dir]);
  5193. } elseif ($file_sort == 2) {
  5194. array_multisort($mtimes[$dir], SORT_ASC, $files[$dir], SORT_DESC);
  5195. } elseif ($file_sort == 3) {
  5196. array_multisort($mtimes[$dir], SORT_DESC, $files[$dir]);
  5197. }
  5198. }
  5199. }
  5200. if ($dir_sort) ($zc['dir_sort_ignore']) ? uksort($files, 'zsort_ignore') : uksort($files, 'strnatcasecmp');
  5201. return $files;
  5202. }
  5203. } else {
  5204. $result = &$dirs_all;
  5205. if (!empty($result)) {
  5206. if ($low) $result = array_unique($result);
  5207. #todo: ???
  5208. #($zc['dir_sort_ignore']) ? uksort($files, 'zsort_ignore') : uksort($files, 'strnatcasecmp');
  5209. if ($dir_sort) natcasesort($result);
  5210. }
  5211. }
  5212. return $result;
  5213. }
  5214. /*
  5215. * only called when generating playlists & stat blocks
  5216. * otherwise, info should already be available
  5217. */
  5218. function zina_get_file_artist_title($file, $id3, &$result = null) {
  5219. global $zc;
  5220. if ($id3) {
  5221. $mp3 = zina_get_file_info($file, false, true);
  5222. if ($mp3->tag) {
  5223. $result['artist'] = $mp3->artist;
  5224. $result['title'] = $mp3->title;
  5225. return ztheme('artist_song', $mp3->title, $mp3->artist);
  5226. }
  5227. }
  5228. $x = explode('/', $file);
  5229. $len = sizeof($x);
  5230. $song = zina_content_song_title($x[$len - 1]);
  5231. if ($len > 2) {
  5232. $artist = ztheme('title',$x[$len - 3]);
  5233. } elseif (!empty($x[$len-2])) {
  5234. $artist = ztheme('title',$x[$len - 2]);
  5235. } else {
  5236. $artist = false;
  5237. }
  5238. $result['artist'] = $artist;
  5239. $result['title'] = $song;
  5240. return ztheme('artist_song', $song, $artist);
  5241. }
  5242. function zina_get_themes() {
  5243. global $zc;
  5244. $dir = $zc['zina_dir_abs'].'/themes';
  5245. if ($d = @dir($dir)) {
  5246. while($entry = $d->read()) {
  5247. if ($entry == '.' || $entry == '..') continue;
  5248. $opts[$entry] = $entry;
  5249. }
  5250. $d->close();
  5251. return $opts;
  5252. }
  5253. zina_set_message(zt('Cannot read themes directory'),'error');
  5254. return array('zinaGarland'=>'zinaGarland');
  5255. }
  5256. function zina_get_languages() {
  5257. global $zc;
  5258. if ($zc['cache']) {
  5259. $lang_file = $zc['cache_dir_private_abs'].'/languages.txt';
  5260. if (file_exists($lang_file)) {
  5261. return unserialize(file_get_contents($lang_file));
  5262. }
  5263. }
  5264. $dir = $zc['zina_dir_abs'].'/lang';
  5265. if ($d = @dir($dir)) {
  5266. while($entry = $d->read()) {
  5267. if ($entry == '.' || $entry == '..') continue;
  5268. $base = basename($entry,'.php');
  5269. if (substr($base,0,1) != '.') {
  5270. $contents = file_get_contents($dir.'/'.$entry);
  5271. if (preg_match('/\$language\s+=\s+[\'"](.*?)[\'"]/si',$contents, $matches)) {
  5272. $opts[$base] = zt('@lang', array('@lang'=> $matches[1]));
  5273. } else {
  5274. $opts[$base] = zt('Unknown: @code', array('@code'=>$base));
  5275. }
  5276. }
  5277. }
  5278. $d->close();
  5279. asort($opts);
  5280. if ($zc['cache']) {
  5281. file_put_contents($lang_file, serialize($opts));
  5282. }
  5283. return $opts;
  5284. }
  5285. zina_debug(zt('Cannot read languages directory'),'error');
  5286. return array('en'=>zt('English'));
  5287. }
  5288. function zina_get_setting($setting, $default = false) {
  5289. global $zc;
  5290. return (isset($zc[$setting])) ? $zc[$setting] : $default;
  5291. }
  5292. function zina_playlist_opts_all() {
  5293. return array(
  5294. 'all'=>zt('All'),
  5295. 'solo'=>zt('Just Mine')
  5296. );
  5297. }
  5298. function zina_playlist_opts_sort() {
  5299. global $zc;
  5300. $opts = array(
  5301. 'date_created'=> zt('Created Date'),
  5302. 'genre' => zt('Genre'),
  5303. 'sum_items' => zt('Items'),
  5304. 'sum_plays' => zt('Plays'),
  5305. 'sum_rating' => zt('Rating'),
  5306. 'playlist' => zt('Title'),
  5307. 'sum_views' => zt('Views'),
  5308. 'sum_votes' => zt('Votes'),
  5309. );
  5310. if (!$zc['genres']) unset($opts['genre']);
  5311. if (!$zc['pls_ratings']) {
  5312. unset($opts['sum_votes']);
  5313. unset($opts['sum_rating']);
  5314. }
  5315. return $opts;
  5316. }
  5317. function zina_search_opts_sort() {
  5318. return array(
  5319. 'title' => zt('Title'),
  5320. #'mtime' => zt('File Date'),
  5321. 'genre' => zt('Genre'),
  5322. 'sum_rating' => zt('Rating'),
  5323. 'type' => zt('Type'),
  5324. 'sum_votes' => zt('Votes'),
  5325. 'year' => zt('Year'),
  5326. );
  5327. }
  5328. function zina_search_opts_order() {
  5329. return array(
  5330. 'asc' => zt('Ascending'),
  5331. 'desc' => zt('Descending'),
  5332. );
  5333. }
  5334. function zina_search_opts_type($type = false) {
  5335. $types = array(
  5336. 'artist' => zt('Artists'),
  5337. 'album' => zt('Albums'),
  5338. 'song' => zt('Songs'),
  5339. 'playlist' => zt('Playlists'),
  5340. );
  5341. if ($type == 'year') {
  5342. unset($types['playlist']);
  5343. unset($types['artist']);
  5344. }
  5345. return $types;
  5346. }
  5347. function zina_search_opts_per_page() {
  5348. global $zc;
  5349. $array = explode(',', $zc['search_pp_opts']);
  5350. return array_combine($array, $array);
  5351. }
  5352. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  5353. * SEND functions
  5354. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  5355. function zina_send_playlist($content, $store = false) {
  5356. #$mem1=memory_get_usage();$time_start=microtime(true);
  5357. #$time=microtime(true)-$time_start;$mem2=memory_get_peak_usage();printf("<pre>db dir info\nMax memory: %0.2f kbytes\nRunning time: %0.3f s</pre>",($mem2-$mem1)/1024.0, $time);
  5358. #zdbg($content,1);
  5359. global $zc;
  5360. if ($zc['pos']) {
  5361. $tmpfname = tempnam('/tmp', 'zina-');
  5362. file_put_contents($tmpfname, $content);
  5363. $temp_file = $tmpfname.'.m3u';
  5364. if (file_exists($temp_file)) unlink($temp_file);
  5365. rename($tmpfname, $temp_file);
  5366. if ($zc['pos_kill']) exec($zc['pos_kill_cmd']);
  5367. $pos_cmd = str_replace('%TEMPFILENAME%', $tmpfname, $zc['pos_cmd']);
  5368. @session_write_close();
  5369. exec($pos_cmd);
  5370. #sleep(2);
  5371. #unlink("$tmpfname.m3u");
  5372. while(@ob_end_clean());
  5373. header('Location: '.$_SERVER['HTTP_REFERER']);
  5374. exit;
  5375. } else {
  5376. $format = $zc['playlist_format'];
  5377. if ($zc['other_media_types']) {
  5378. $content = preg_replace('#.*?://(.*\.)('.$zc['ext_mus'].')(\n|$)#ie', "\$zc['media_types'][strtolower('$2')][\"protocol\"].\"://\".'$1'.'$2'.'$3'", $content);
  5379. if (preg_match_all('/\.('.$zc['ext_mus'].')(\n|$|\?|&)/i', $content, $ext) && isset($zc['media_types'][$ext[1][0]])) {
  5380. $ext = $ext[1][0];
  5381. $playlist_ext = $zc['media_types'][$ext]['playlist_ext'];
  5382. if ($format == 'asx' && $playlist_ext == 'asx') {
  5383. $content = "<ASX VERSION=\"3.0\">\n<title>".zt('Playlist')."</title>\n".$content.'</ASX>';
  5384. } elseif ($playlist_ext == 'm3u' && $zc['stream_extinf']) {
  5385. $content = "#EXTM3U\n".$content;
  5386. } elseif ($playlist_ext == 'xspf') {
  5387. $content = '<?xml version="1.0" encoding="UTF-8"?>'.
  5388. '<playlist version="1" xmlns="http://xspf.org/ns/0/">'.
  5389. xml_field('title', zt('Playlist')).
  5390. '<trackList>'.$content.'</trackList></playlist>';
  5391. }
  5392. while(@ob_end_clean());
  5393. header('Content-type: '.$zc['media_types'][$ext]['playlist_mime']);
  5394. header('Content-Disposition: inline; filename=playlist.'.$playlist_ext);
  5395. } else {
  5396. zina_debug('Bad other media type');
  5397. }
  5398. } else {
  5399. if ($format == 'm3u') {
  5400. if ($zc['stream_extinf']) $content = "#EXTM3U\n".$content;
  5401. } elseif ($format == 'asx') {
  5402. $content = "<ASX VERSION=\"3.0\">\n<title>".zt('Playlist')."</title>\n".$content.'</ASX>';
  5403. } elseif ($format == 'xspf') {
  5404. $content = '<?xml version="1.0" encoding="UTF-8"?>'.
  5405. '<playlist version="1" xmlns="http://xspf.org/ns/0/">'.
  5406. xml_field('title', zt('Playlist')).
  5407. '<trackList>'.$content.'</trackList></playlist>';
  5408. }
  5409. }
  5410. if ($store) {
  5411. $_SESSION['zina_store'] = array('type'=>$format, 'content'=>$content);
  5412. zina_send_playlist_content('store', zurl('','l=74&rand='.time()));
  5413. } else {
  5414. zina_send_playlist_content($format, $content);
  5415. }
  5416. }
  5417. exit;
  5418. }
  5419. function zina_send_playlist_content($type, $content) {
  5420. while(@ob_end_clean());
  5421. if ($type == 'm3u') {
  5422. header("Content-type: audio/mpegurl", true, 200);
  5423. header('Content-Disposition: inline; filename=playlist.m3u');
  5424. } elseif ($type == 'asx') {
  5425. header('Content-type: application/vnd.ms-asx', true, 200);
  5426. header('Content-Disposition: inline; filename=playlist.asx');
  5427. } elseif ($type == 'xspf') {
  5428. header('Content-type: application/xspf+xml', true, 200);
  5429. header('Content-Disposition: inline; filename=playlist.xml');
  5430. }
  5431. header('Cache-control: private'); #IE seems to need this.
  5432. echo $content;
  5433. exit;
  5434. }
  5435. function zina_send_playlist_song($path, $low = false) {
  5436. zina_send_playlist(zina_get_playlist(array($path), $low, false));
  5437. }
  5438. function zina_send_playlist_title($path, $custom, $low = false) {
  5439. zina_send_playlist(zina_get_title_playlist($path, $custom, $low));
  5440. }
  5441. function zina_send_playlist_selected($songs, $low = false, $store = false) {
  5442. zina_send_playlist(zina_get_playlist($songs, $low, true), $store);
  5443. }
  5444. # hack central...fix this
  5445. function zina_send_playlist_selected_random($items, $low = false, $store = false) {
  5446. global $zc;
  5447. $items = zina_get_playlist($items, $low, true);
  5448. if ($zc['stream_extinf']) {
  5449. if ($zc['playlist_format'] == 'xspf') {
  5450. $delim = '<track>';
  5451. } else {
  5452. $delim = '#EXTINF';
  5453. }
  5454. $x = explode($delim, $items);
  5455. array_shift($x);
  5456. zo_shuffle($x);
  5457. $songs = $delim.implode($delim, $x);
  5458. } else {
  5459. $delim = "\n";
  5460. $x = explode($delim, $items);
  5461. array_pop($x);
  5462. zo_shuffle($x);
  5463. $songs = implode($delim, $x).$delim;
  5464. }
  5465. zina_send_playlist($songs, $store);
  5466. }
  5467. function zina_get_playlist_custom($pls_id) {
  5468. global $zc;
  5469. $where = 'p.id = %d';
  5470. if (!$zc['is_admin']) {
  5471. if ($zc['pls_public']) {
  5472. $where .= ' AND (p.user_id = %d OR p.visible = 1)';
  5473. } else {
  5474. $where .= ' AND p.user_id = %d';
  5475. }
  5476. }
  5477. $sql = "SELECT ".
  5478. "CASE pm.type ".
  5479. "WHEN 'song' THEN IF(f.path!='.' && f.path!='',CONCAT(f.path,IF(ISNULL(f.path), '','/'),f.file), f.file) ".
  5480. "WHEN 'album' THEN CONCAT(d.path,'/.lp') ".
  5481. "WHEN 'playlist' THEN CONCAT(pm.type_id,'.pls') ".
  5482. "END AS path ".
  5483. "FROM {playlists_map} as pm ".
  5484. "INNER JOIN {playlists} as p ON (pm.playlist_id = p.id) ".
  5485. "LEFT OUTER JOIN {files} AS f ON pm.type = 'song' AND pm.type_id = f.id ".
  5486. "LEFT OUTER JOIN {dirs} AS d ON pm.type = 'album' AND pm.type_id = d.id ".
  5487. "WHERE $where ".
  5488. "ORDER BY weight";
  5489. return zdbq_array_list($sql, array($pls_id, $zc['user_id']));
  5490. }
  5491. function zina_send_playlist_custom($playlist, $low, $random = false) {
  5492. global $zc;
  5493. $items = array();
  5494. if($zc['session_pls'] && $playlist == 'zina_session_playlist') {
  5495. if ($zc['database']) {
  5496. $results = zina_get_session_playlist();
  5497. foreach($results as $item) {
  5498. if ($item['type'] == 'album') {
  5499. $items[] = $item['path'].'/.lp';
  5500. } elseif ($item['type'] == 'playlist') {
  5501. $items[] = $item['type_id'].'.pls';
  5502. } else {
  5503. $items[] = $item['path'];
  5504. }
  5505. }
  5506. if (!empty($items) && $random) zina_send_playlist_selected_random($items);
  5507. } else {
  5508. if (isset($_SESSION['z_sp'])) $items = unserialize_utf8($_SESSION['z_sp']);
  5509. }
  5510. } else {
  5511. if ($playlist != 'new_zina_list') {
  5512. if ($zc['database']) {
  5513. $items = zina_get_playlist_custom($playlist);
  5514. if (!empty($items)) {
  5515. zdb_log_stat_playlist($playlist, 'plays');
  5516. if ($random) zina_send_playlist_selected_random($items);
  5517. }
  5518. } else {
  5519. $filename = $zc['cache_pls_dir'].'/_zina_'.str_replace('/',' - ',$playlist).'.m3u';
  5520. if (file_exists($filename)) {
  5521. $items = zunserialize_alt(file_get_contents($filename));
  5522. }
  5523. }
  5524. }
  5525. }
  5526. zina_send_playlist(zina_get_playlist($items, $low, true));
  5527. }
  5528. /*
  5529. * Sends various playlists via cache
  5530. * - random by albums, song
  5531. * - directory recursive
  5532. * - directory recursive random
  5533. * - random by song ratings
  5534. * - random by album ratings
  5535. * - random by genre
  5536. * Also, non-cached
  5537. * - above minus genre and db stuff
  5538. *
  5539. * type:
  5540. * 't' => title,
  5541. * 's' => song
  5542. * 's' && num ==0 => resursive & random recursive ($rand = true)
  5543. * 'tt' => songs via rated songs
  5544. * 'artist' => 'songs via rated albums
  5545. */
  5546. function zina_send_playlist_random($num, $type, $low, $rand = true, $path = null, $genre = null, $year = false) {
  5547. global $zc;
  5548. @set_time_limit($zc['timeout']);
  5549. $opts = explode(',',$zc['rating_random_opts']);
  5550. $rating = isset($_POST['rating']) ? $_POST['rating'] : (isset($_GET['rating']) ? $_GET['rating'] : null);
  5551. if ($zc['database'] && $zc['rating_random'] && in_array($rating, $opts)) {
  5552. $random_rating = true;
  5553. } else {
  5554. $random_rating = false;
  5555. if ($type == 'tt' && $rating == 0) $type = 's';
  5556. }
  5557. if ($year) {
  5558. $array = array();
  5559. if ($zc['db_search']) {
  5560. $total = zdbq_single('SELECT COUNT(*) FROM {files} WHERE year = %d', array($year));
  5561. if ($zc['random_least_played'] && $total > $num) {
  5562. $array = zina_least_played($num, 'year = %d AND', array($year));
  5563. } else {
  5564. $array = zdbq_array_list("SELECT IF(path!='.',CONCAT(path,IF(ISNULL(path), '','/'),file),file) as path ".
  5565. "FROM {files} ".
  5566. "WHERE year = %d", array($year));
  5567. }
  5568. #TODO:
  5569. if ($type == 't') {
  5570. } elseif ($type == 'artist') {
  5571. } else { #if ($type == 's') {
  5572. }
  5573. }
  5574. } elseif ($zc['genres'] && !empty($genre) && $genre != 'zina') {
  5575. if ($zc['database']) {
  5576. $array = array();
  5577. $children = zdb_genres_get_children($genre);
  5578. $children[] = $genre;
  5579. $in = str_repeat("'%s',", sizeof($children)-1)."'%s'";
  5580. $vars = $children;
  5581. $vars[] = $num;
  5582. if ($type == 's' || $type == 'artist') {
  5583. $rand = false;
  5584. $array = zdbq_array_list("SELECT CONCAT(path,IF(ISNULL(path), '','/'),file) ".
  5585. "FROM {files} WHERE genre IN ($in) ORDER BY RAND() LIMIT %d", $vars);
  5586. } else {
  5587. $rand = false;
  5588. $array = zdbq_array_list("SELECT path ".
  5589. "FROM {dirs} WHERE genre IN ($in) ORDER BY RAND() LIMIT %d", $vars);
  5590. }
  5591. # probably could make one sql stmt w/ above
  5592. if ($random_rating) { #dir and files?
  5593. #todo: opt to have random honor user_id? pass user_id???
  5594. $files_rated = zdb_get_random_by_rating($type, $rating);
  5595. $array = array_values(array_intersect($array, $files_rated));
  5596. }
  5597. } else {
  5598. $genres = zina_core_cache('genre');
  5599. $array = $genres[$genre];
  5600. if ($type == 's' || $type == 'artist') {
  5601. #todo: could be better artist stuff
  5602. $files = array();
  5603. $dirs = zina_core_cache('files_assoc', $path, array('low'=>$low));
  5604. foreach($array as $title) {
  5605. foreach($dirs[$title] as $file) {
  5606. $files[] = $title.'/'.$file;
  5607. }
  5608. }
  5609. $array = $files;
  5610. }
  5611. }
  5612. } elseif ($random_rating) {
  5613. # artist or tt or s
  5614. if ($type == 't' || $type == 'tt')
  5615. $dirs = zina_core_cache('files_assoc', $path, array('low'=>$low));
  5616. $array = zdb_get_random_by_rating($type, $rating, $num);
  5617. if ($type == 'artist' && $zc['honor_custom']) {
  5618. #todo: by passing $num above && least_played, might return < $num
  5619. $files = zina_core_cache('files', $path, array('low'=>$low));
  5620. $array = array_values(array_intersect($array, $files));
  5621. }
  5622. } else { # normal
  5623. if ($type == 't') {
  5624. $sort = ($rand) ? 0 : $zc['files_sort'];
  5625. $dir_sort = ($rand) ? 0 : 1;
  5626. $dirs = zina_core_cache('files_assoc', $path, array('low'=>$low, 'file_sort'=>$sort, 'dir_sort'=>$dir_sort));
  5627. $array = array_keys($dirs);
  5628. } else {
  5629. $type = 's';
  5630. if ($zc['database'] && $zc['random_least_played']) {
  5631. #todo: doesn't honor "custom"
  5632. $total = zdbq_single('SELECT COUNT(*) FROM {files}');
  5633. if ($total <= $num || $num == 0) {
  5634. $array = zina_core_cache('files', $path, array('low'=>$low));
  5635. } else {
  5636. $array = zina_least_played($num);
  5637. }
  5638. } else {
  5639. $array = zina_core_cache('files', $path, array('low'=>$low));
  5640. }
  5641. }
  5642. }
  5643. # Songs via Rated Albums
  5644. if ($type == 'tt') {
  5645. foreach($array as $title) {
  5646. foreach($dirs[$title] as $file) {
  5647. $files[] = $title.'/'.$file;
  5648. }
  5649. }
  5650. $array = $files;
  5651. }
  5652. if ($rand) zo_shuffle($array);
  5653. $total = sizeof($array);
  5654. if ($num == 0 || $num > $total) $num = $total;
  5655. $array = array_slice($array,0,$num);
  5656. if ($type == 't') {
  5657. foreach($array as $title) {
  5658. foreach($dirs[$title] as $file) {
  5659. $files[] = $title.'/'.$file;
  5660. }
  5661. }
  5662. $array = $files;
  5663. }
  5664. zina_send_playlist(zina_get_playlist($array, $low));
  5665. }
  5666. #TODO: move
  5667. function zina_least_played($total, $where = '', $where_vars = array()) {
  5668. global $zc;
  5669. $result = array();
  5670. $count = 0;
  5671. $floor = $zc['random_lp_floor'];
  5672. $limit = $least = ceil($total*$zc['random_lp_perc']/100);
  5673. while ($count < $least) {
  5674. #todo: by user_id?
  5675. $vars = $where_vars;
  5676. $vars[] = $floor;
  5677. $vars[] = $limit;
  5678. $result += zdbq_assoc_list("SELECT id, CONCAT(path,IF(ISNULL(path), '','/'),file) ".
  5679. "FROM {files} WHERE $where sum_plays = %d ORDER BY RAND() LIMIT %d", $vars);
  5680. $count = sizeof($result);
  5681. if ($count < $least) {
  5682. $limit = $least - $count;
  5683. $floor++;
  5684. }
  5685. }
  5686. if ($count < $total) {
  5687. $vars = $where_vars;
  5688. $vars[] = $floor;
  5689. $vars[] = implode(',', array_keys($result));
  5690. $vars[] = $total - $count;
  5691. $result = array_merge($result, zdbq_array_list("SELECT CONCAT(path,IF(ISNULL(path), '','/'),file) ".
  5692. "FROM {files} WHERE $where sum_plays >= %d AND id NOT IN(%s) ORDER BY RAND() LIMIT %d", $vars));
  5693. }
  5694. return $result;
  5695. }
  5696. function zina_send_zip_selected($songs, $lofi = false, $filename = 'selectedmusic') {
  5697. global $zc;
  5698. #todo: lowfi, baby
  5699. if ($zc['cmp_sel']) {
  5700. $zipfile = $zc['cache_zip_dir'] .'/'. md5(serialize($songs)).'.zip';
  5701. $files = null;
  5702. if ($zc['cmp_sel'] == 1) { #EXTERNAL
  5703. #todo: make opt to limit on number of files??? or dirs??? or opt on search pages?
  5704. foreach ($songs as $song) {
  5705. $song = zrawurldecode($song);
  5706. if ($zc['database'] && $zc['stats']) zdb_log_stat('down', dirname($song), basename($song));
  5707. $files .= '"'.$zc['mp3_dir'].'/'.$song.'" ';
  5708. }
  5709. if ($zc['cmp_cache']) {
  5710. if (zina_send_zip_helper($zipfile, $zc['cmp_mime'], $filename.'.'.$zc['cmp_extension']))
  5711. exit;
  5712. } else {
  5713. $zipfile = '-';
  5714. }
  5715. $opts = str_replace(array('%FILE%','%FILELIST%'), array($zipfile, $files), $zc['cmp_set']);
  5716. $passthru = $zc['cmp_pgm'].' '.$opts;
  5717. zina_send_zip_helper($zipfile, $zc['cmp_mime'], $filename.'.'.$zc['cmp_extension'], $passthru, $zc['cmp_cache']);
  5718. } else { # internal
  5719. if ($zc['cmp_cache']) {
  5720. if (zina_send_zip_helper($zipfile, 'application/zip', $filename.'.zip'))
  5721. exit;
  5722. }
  5723. $zip = new ZipArchive;
  5724. if (($result = $zip->open($zipfile,ZIPARCHIVE::CREATE)) === TRUE) {
  5725. foreach ($songs as $song) {
  5726. $song = zrawurldecode($song);
  5727. if ($zc['database'] && $zc['stats']) zdb_log_stat('down', dirname($song), basename($song));
  5728. $file = $zc['mp3_dir'].'/'.$song;
  5729. $zip->addFile($file, $song);
  5730. }
  5731. $zip->close();
  5732. } else {
  5733. #todo: might be able to redirect...
  5734. zina_debug(zt('Could not open archive file: @err', array('@err'=>$result)), 'error');
  5735. exit;
  5736. }
  5737. zina_send_zip_helper($zipfile, 'application/zip', $filename.'.zip');
  5738. if (!$zc['cmp_cache'] && file_exists($zipfile)) {
  5739. @unlink($zipfile);
  5740. }
  5741. }
  5742. }
  5743. exit;
  5744. }
  5745. function zina_send_zip_selected_dir($dir, $custom, $low) {
  5746. $path = preg_replace('/\/\.lp$/i', '', $dir);
  5747. if (empty($path)) $path = false;
  5748. $dirs = zina_core_cache('files_assoc', $path, array('low'=>$low,'custom'=>$custom,'force'=>(empty($path))));
  5749. $files = array();
  5750. $filename = 'not found';
  5751. if (isset($dirs[$path])) {
  5752. foreach($dirs[$path] as $file) {
  5753. $files[] = (empty($path)) ? $file : $path.'/'.$file;
  5754. }
  5755. $filename = str_replace('/', ' - ', $path);
  5756. }
  5757. zina_send_zip_selected($files, $low, $filename);
  5758. }
  5759. function zina_send_zip_helper($file, $mime, $filename, $passthru = false, $cache = true) {
  5760. zina_set_header('Content-type: '.$mime);
  5761. zina_set_header('Content-Disposition: inline; filename="'.$filename.'"');
  5762. @session_write_close();
  5763. if ($passthru) {
  5764. if (!$cache) {
  5765. while(@ob_end_clean());
  5766. zina_get_headers();
  5767. passthru($passthru);
  5768. return;
  5769. } else {
  5770. passthru($passthru);
  5771. }
  5772. }
  5773. if (file_exists($file)) {
  5774. while(@ob_end_clean());
  5775. header('Content-Length: '.filesize($file));
  5776. if (zina_send_file($file)) {
  5777. return true;
  5778. } else {
  5779. zina_debug(zt('Cannot stream compressed downloads'), 'error');
  5780. }
  5781. }
  5782. return false;
  5783. }
  5784. function zina_send_file_music($path, $resample = false) {
  5785. global $zc;
  5786. if (preg_match('/\.('.$zc['ext_mus'].')$/i', $path, $exts)) {
  5787. $result = false;
  5788. $ext = strtolower($exts[1]);
  5789. $file = $zc['mp3_dir'].'/'.$path;
  5790. if (($zc['lastfm'] || $zc['twitter']) && $zc['user_id'] > 0) {
  5791. if ($zc['lastfm']) require_once($zc['zina_dir_abs'].'/extras/scrobbler.class.php');
  5792. if ($zc['twitter']) require_once($zc['zina_dir_abs'].'/extras/twitter.class.php');
  5793. $mp3 = zina_get_file_info($file);
  5794. if ($mp3->tag && $mp3->info) {
  5795. $icy = ztheme('artist_song', $mp3->title, $mp3->artist);
  5796. $mp3->timestamp = time();
  5797. if (!isset($mp3->track)) $mp3->track = '';
  5798. if (!isset($mp3->album)) $mp3->album = '';
  5799. if ($zc['lastfm']) {
  5800. $scrobbler = new scrobbler($zc['lastfm_username'],$zc['lastfm_password']);
  5801. if (!$scrobbler->now_playing($mp3)) {
  5802. zina_debug('Zina Error: scrobbler cannot submit now playing: '.$scrobbler->error_msg);
  5803. }
  5804. }
  5805. if ($zc['twitter']) {
  5806. $twitter = new twitter($zc['twitter_username'], $zc['twitter_password']);
  5807. if (!$twitter->set_status('Listening to '.$icy)) {
  5808. zina_debug('Zina Error: twitter cannot set status: '.$scrobbler->error_msg);
  5809. }
  5810. }
  5811. } else {
  5812. $icy = zina_get_file_artist_title($path, false);
  5813. }
  5814. }
  5815. if (!isset($icy)) $icy = zina_get_file_artist_title($file, $zc['mp3_id3']);
  5816. if ($resample) {
  5817. if (!preg_match('/\.('.$zc['ext_enc'].')$/i', $path, $exts)) {
  5818. zina_debug('Zina Error: Bad song sent to resample function.');
  5819. exit;
  5820. }
  5821. $type = $zc['encoders'][$ext]['mime'];
  5822. } else {
  5823. $type = $zc['media_types'][$ext]['mime'];
  5824. $filesize = filesize($file);
  5825. }
  5826. $sapi_type = php_sapi_name();
  5827. if (substr($sapi_type, 0, 3) == 'cgi') {
  5828. zina_set_header('HTTP/1.0 200 OK');
  5829. } else {
  5830. zina_set_header('ICY 200 OK');
  5831. }
  5832. zina_set_header('icy-name: '.$icy);
  5833. zina_set_header('Connection: close');
  5834. zina_set_header('Content-type: '.$type);
  5835. zina_set_header('Content-Disposition: inline; filename='.$icy);
  5836. if ($resample) {
  5837. @set_time_limit(0);
  5838. @session_write_close();
  5839. $opts = str_replace('%FILE%', '"'.$file.'"', $zc['encoders'][$ext]['opts']);
  5840. $begin = time();
  5841. while(@ob_end_clean());
  5842. zina_get_headers();
  5843. passthru($zc['encoders'][$ext]['encoder'].' '.$opts);
  5844. if (isset($scrobbler)) {
  5845. $result = (time() - $begin > $mp3->length / 2);
  5846. }
  5847. } else {
  5848. zina_set_header('Content-Length: '.$filesize);
  5849. if ($end = zina_send_file($file)) {
  5850. $result = ($end > $filesize / 3 * 2);
  5851. if ($zc['zinamp'] && isset($scrobbler)) {
  5852. $result = false;
  5853. $_SESSION['zinamp_track'][$path] = time();
  5854. }
  5855. }
  5856. }
  5857. if (isset($scrobbler) && $result) {
  5858. zina_scrobbler_submit($scrobbler, $mp3);
  5859. }
  5860. }
  5861. exit;
  5862. }
  5863. function zina_play_complete($path, $length) {
  5864. global $zc;
  5865. if (preg_match('/\.('.$zc['ext_mus'].')$/i', $path)) {
  5866. if ($zc['lastfm'] && $zc['user_id'] > 0) {
  5867. require_once($zc['zina_dir_abs'].'/extras/scrobbler.class.php');
  5868. if (isset($_SESSION['zinamp_track'][$path])) {
  5869. $mp3 = zina_get_file_info($zc['mp3_dir'].'/'.$path);
  5870. if ($mp3->tag && $mp3->info) {
  5871. $icy = ztheme('artist_song', $mp3->title, $mp3->artist);
  5872. $mp3->timestamp = $_SESSION['zinamp_track'][$path];
  5873. $mp3->length = $length;
  5874. /*
  5875. #TODO: when last.fm allows Love submissions...
  5876. if ($zc['database'] && $zc['stats']) {
  5877. $rating = zdbq_single("SELECT r.rating ".
  5878. "FROM {files} as f INNER JOIN {file_ratings} AS r ON (f.id = r.file_id) ".
  5879. "WHERE file = '%s' AND r.user_id = %d", array($path, $zc['user_id']));
  5880. if (!empty($rating) && $rating == 5) $mp3->love = true;
  5881. }
  5882. */
  5883. $scrobbler = new scrobbler($zc['lastfm_username'],$zc['lastfm_password']);
  5884. zina_scrobbler_submit($scrobbler, $mp3);
  5885. unset($_SESSION['zinamp_track'][$path]);
  5886. }
  5887. } else {
  5888. zina_debug(zt('scrobbler session not set: @path', array('@path'=>$path)), 'error');
  5889. }
  5890. }
  5891. }
  5892. }
  5893. function zina_scrobbler_submit(&$scrobbler, $mp3) {
  5894. $scrobbler->queued_tracks = zina_set_scrobbler_queue();
  5895. if (!isset($mp3->track)) $mp3->track = '';
  5896. if (!isset($mp3->album)) $mp3->album = '';
  5897. if ($scrobbler->submit_track($mp3)) {
  5898. zina_set_scrobbler_queue(array(), true);
  5899. } else {
  5900. zina_debug('scrobbler cannot submit tracks: '.$scrobbler->error_msg);
  5901. zina_set_scrobbler_queue($scrobbler->queued_tracks);
  5902. }
  5903. }
  5904. function zina_send_file($file) {
  5905. @set_time_limit(0);
  5906. @session_write_close();
  5907. $fp = @fopen($file, 'rb');
  5908. if ($fp !== false) {
  5909. ignore_user_abort(true);
  5910. # various embeds
  5911. while(@ob_end_clean());
  5912. zina_get_headers();
  5913. while(!feof($fp)) {
  5914. echo fread($fp, 8192);
  5915. flush();
  5916. #usleep(20000); # XXX
  5917. if (connection_status() != 0) break;
  5918. }
  5919. $end = ftell($fp);
  5920. fclose($fp);
  5921. return $end;
  5922. }
  5923. return false;
  5924. }
  5925. function zina_send_image_resized($source, $type, $txt = null, $cache_file = false, $string = false) {
  5926. global $zc;
  5927. $types = array(1=>'gif', 2=>'jpeg', 3=>'png', 7=>'tiff', 8=>'tiff');
  5928. if ($string || $info = getimagesize($source)) {
  5929. if ($string) {
  5930. $org_image = imagecreatefromstring($string['data']);
  5931. $org_x = imagesx($org_image);
  5932. $org_y = imagesy($org_image);
  5933. $org_type = ($string['type'] == 'jpg') ? 'jpeg' : $string['type'];
  5934. } else {
  5935. $org_type = $types[$info[2]];
  5936. $org_image = call_user_func('imagecreatefrom'.$org_type,$source);
  5937. $org_x = $info[0];
  5938. $org_y = $info[1];
  5939. }
  5940. $new_x = $zc['res_'.$type.'_x'];
  5941. $quality = $zc['res_'.$type.'_qual'];
  5942. $res_out_type = $zc['res_out_type'];
  5943. if (!$zc['res_out_x_lmt'] || $org_x > $new_x) {
  5944. $new_y = intval($org_y * $new_x / $org_x);
  5945. $new_image = imagecreatetruecolor($new_x, $new_y);
  5946. imagecopyresampled($new_image, $org_image, 0, 0, 0, 0, $new_x, $new_y, $org_x, $org_y);
  5947. } else {
  5948. $res_out_type = $org_type;
  5949. $new_image = $org_image;
  5950. $new_x = $org_x;
  5951. $new_y = $org_y;
  5952. }
  5953. $font = (isset($zc[$type.'_img_txt_font'])) ? $zc[$type.'_img_txt_font'] : false;
  5954. if (!empty($txt) && $font && file_exists($font) && function_exists('imagettftext')) {
  5955. $clr_str = $zc[$type.'_img_txt_color'];
  5956. $font_size = $zc[$type.'_img_txt_font_size'];
  5957. $txt = wordwrap(html_entity_decode($txt), $zc[$type.'_img_txt_wrap'], "\r\n");
  5958. $box = imagettfbbox($font_size, 0, $font, $txt);
  5959. $rgb = explode(',',$clr_str);
  5960. $color = imagecolorallocate($new_image, $rgb[0], $rgb[1], $rgb[2]);
  5961. $bx = $box[2] - $box[0];
  5962. $by = $box[5] - $box[3];
  5963. $mod = ($type == 'search') ? 1 : .5;
  5964. $vert = 2 + (substr_count($txt, "\r\n") * $mod);
  5965. $txt_x = ($new_x - $bx)/2;
  5966. $txt_y = ($new_y - $by)/$vert;
  5967. imagettftext($new_image, $font_size, 0, $txt_x, $txt_y, $color, $font, $txt);
  5968. }
  5969. imageinterlace($new_image, true);
  5970. if (function_exists('image'.$res_out_type)) {
  5971. if ($res_out_type == 'png') $quality = round(abs(($quality - 100) / 11.111111));
  5972. if ($zc['cache_imgs'] && $cache_file && is_writeable($zc['cache_imgs_dir'])) {
  5973. call_user_func('image'.$res_out_type,$new_image,$cache_file,$quality);
  5974. }
  5975. while(@ob_end_clean());
  5976. Header('Content-type: image/'.$res_out_type);
  5977. call_user_func('image'.$res_out_type,$new_image,null,$quality);
  5978. }
  5979. @imagedestroy($new_image);
  5980. @imagedestroy($org_image);
  5981. } else {
  5982. zina_debug(zt('Zina Error: Could not open image file: @file', array('@file'=>$source)));
  5983. }
  5984. }
  5985. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  5986. * WRITE/UPDATE/DELETE functions
  5987. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  5988. function zina_write_playlist($songs, $filename, $type = '') {
  5989. global $zc;
  5990. $files = array();
  5991. if (!empty($songs)) {
  5992. foreach ($songs as $song) {
  5993. $files[] = zrawurldecode($song);
  5994. }
  5995. }
  5996. if($zc['session_pls'] && strstr($filename,'zina_session_playlist')) {
  5997. if (empty($files)) {
  5998. unset($_SESSION['z_sp']);
  5999. } else { # new/additions
  6000. if ($type == 'a' && isset($_SESSION['z_sp'])) {
  6001. $existing = unserialize_utf8($_SESSION['z_sp']);
  6002. $files = array_merge($existing, $files);
  6003. }
  6004. if (sizeof($files) > $zc['pls_length_limit']) {
  6005. $files = array_slice($files, 0, 100);
  6006. zina_set_message(zt('Session playlists limited to @num items.', array('@num'=>$zc['pls_length_limit'])), 'warn');
  6007. }
  6008. $_SESSION['z_sp'] = utf8_encode(serialize($files));
  6009. }
  6010. } else {
  6011. $content = serialize($files);
  6012. $filename = $zc['cache_pls_dir'].'/'.$filename;
  6013. if ($type == 'a' && file_exists($filename)) {
  6014. $existing = zunserialize_alt(file_get_contents($filename));
  6015. if (!empty($existing)) $content = serialize(array_merge($existing, $files));
  6016. }
  6017. file_put_contents($filename, $content);
  6018. if (empty($files) && ($type == 't') && file_exists($filename)) unlink($filename);
  6019. }
  6020. }
  6021. function zina_delete_playlist_custom($pls_name) {
  6022. global $zc;
  6023. if ($pls_name == 'zina_session_playlist') {
  6024. unset($_SESSION['z_sp']);
  6025. } elseif ($pls_name != 'new_zina_list') {
  6026. $filename = $zc['cache_pls_dir'].'/_zina_'.$pls_name.'.m3u';
  6027. if (file_exists($filename)) unlink($filename);
  6028. }
  6029. }
  6030. function zina_delete_tmpl_file($file) {
  6031. global $zc;
  6032. if (strstr($file,'..')) return false;
  6033. $cache_file = $zc['cache_tmpl_dir'].'/'.$file;
  6034. if (file_exists($cache_file)) return unlink($cache_file);
  6035. return true;
  6036. }
  6037. function zina_delete_files($path) {
  6038. if (file_exists($path) && is_dir($path) && is_writeable($path)) {
  6039. if ($d = @dir($path)) {
  6040. while($entry = $d->read()) {
  6041. if ($entry != '.' && $entry != '..') unlink($path.'/'.$entry);
  6042. }
  6043. $d->close();
  6044. return true;
  6045. }
  6046. }
  6047. zina_set_message(zt('Cannot open directory to delete files.'));
  6048. return false;
  6049. }
  6050. function zina_write_settings() {
  6051. global $zc;
  6052. $fields = zina_get_settings('cfg');
  6053. $lang = zina_get_settings('lang');
  6054. $titles = &$lang['titles'];
  6055. $errors = false;
  6056. if (!zina_token_sess_check()) {
  6057. zina_debug(zt('Session token does not match.'));
  6058. return false;
  6059. }
  6060. $config = "<?php\n";
  6061. $settings = array();
  6062. foreach($fields as $cat => $x) {
  6063. if (($zc['embed'] != 'standalone') && ($cat == 'auth' || $cat == 'integration' ||
  6064. ($cat == 'db' && (!isset($POST['db']) || !$POST['db'])))) {
  6065. continue;
  6066. }
  6067. foreach($x as $name => $field) {
  6068. if (isset($_POST[$name])) {
  6069. $input = $_POST[$name];
  6070. } else {
  6071. $input = null;
  6072. }
  6073. if ($input != $field['def']) {
  6074. if ($name == 'adm_pwd') {
  6075. if (!empty($input)) {
  6076. if ($input == $_POST['adm_pwd_con']) {
  6077. if (zina_check_password($zc['adm_name'], $_POST['adm_pwd_old'])) {
  6078. $config .= "\$adm_pwd = '".zina_get_hash($_POST['adm_pwd'])."';\n";
  6079. } else {
  6080. $errors = true;
  6081. zina_set_message(zt('Old password is incorrect.').' '.zt('Password not changed'),'warn');
  6082. }
  6083. } else {
  6084. $errors = true;
  6085. zina_set_message(zt('New password and confirmation password do not match.').' '.zt('Password not changed'),'warn');
  6086. }
  6087. } else {
  6088. $config .= "\$adm_pwd = \"".$zc['adm_pwd']."\";\n";
  6089. }
  6090. } else {
  6091. if ($name == 'main_dir_title' && $input == zt('Artists')) continue;
  6092. if (isset($field['v'])) {
  6093. foreach($field['v'] as $key => $type) {
  6094. $opts = null;
  6095. if (is_array($type)) {
  6096. $opts = $type;
  6097. $type = $key;
  6098. }
  6099. if (!zina_validate($type, $input, $opts)) {
  6100. $errors = true;
  6101. $title = $titles[$name];
  6102. if ($opts) $type = current($opts);
  6103. zina_validate_error_message($type, $title, $input);
  6104. continue 2;
  6105. }
  6106. }
  6107. }
  6108. $quote = '"';
  6109. if (is_array($input)) {
  6110. $input = serialize($input);
  6111. $quote = "'";
  6112. }
  6113. $arr = array("\n"=>"\\n","\t"=>"\\t","\r"=>"\\r","\t"=>"\\t");
  6114. $config .= "\$$name = $quote". str_replace(array_keys($arr),array_values($arr),$input)."$quote;\n";
  6115. $settings[$name] = $input;
  6116. }
  6117. }
  6118. }
  6119. }
  6120. $config .= "?>";
  6121. if (!$errors) {
  6122. $file = $zc['zina_dir_abs'].'/zina.ini.php';
  6123. if ($zc['embed'] != 'standalone' && $zc['database'] && (!isset($_POST['db']) || !$_POST['db'])) {
  6124. if (!zvar_set('settings', $settings)) {
  6125. $errors = true;
  6126. zina_set_message(zt('Cannot save settings to cms database'),'error');
  6127. }
  6128. } elseif ((file_exists($file) && is_writeable($file)) || (!file_exists($file) && is_writeable($zc['zina_dir_abs']))) {
  6129. if (!file_put_contents($file, $config)) {
  6130. $errors = true;
  6131. zina_set_message(zt('Cannot write config file'),'error');
  6132. }
  6133. } else {
  6134. $errors = true;
  6135. zina_set_message(zt('Config file or directory is not writeable.'),'error');
  6136. }
  6137. if ($errors) {
  6138. zina_set_message(
  6139. '<p>'.zt('You may manually put the following in %cfg', array('%cfg'=>$zc['zina_dir_abs'].'/zina.ini.php')).
  6140. '<form><textarea cols="80" rows="20">'.$config.'</textarea></form>'
  6141. ,'warn'
  6142. );
  6143. }
  6144. }
  6145. return !$errors;
  6146. }
  6147. function zina_validate_error_message($type, $title, $input) {
  6148. if ($type == 'req') {
  6149. zina_set_message(zt('@title: This option is required', array('@title'=>$title)),'warn');
  6150. } elseif ($type == 'tf') {
  6151. zina_set_message(zt('@title: Must be true or false (this should not happen)', array('@title'=>$title)),'warn');
  6152. } elseif ($type == 'int') {
  6153. zina_set_message(zt('@title: Must be an integer', array('@title'=>$title)),'warn');
  6154. } elseif ($type == 'int_split') {
  6155. zina_set_message(zt('@title: Must be a string of integers separated by ",".', array('@title'=>$title)),'warn');
  6156. } elseif ($type == 'file_exists') {
  6157. zina_set_message(zt('@title: File @file does not exists', array('@file'=>$input, '@title'=>$title)),'warn');
  6158. } elseif ($type == 'dir_exists') {
  6159. zina_set_message(zt('@title: Directory @dir does not exists', array('@dir'=>$input, '@title'=>$title)),'warn');
  6160. } elseif ($type == 'path_relative') {
  6161. zina_set_message(zt('@title: Directory @dir must exist and be relative to the zina directory', array('@dir'=>$input, '@title'=>$title)),'warn');
  6162. } else {
  6163. zina_set_message(zt('Unknown validation error[@type][@title][@input]', array('@type'=>$type, '@title'=>$title,'@input'=>$input)),'warn');
  6164. }
  6165. }
  6166. function zina_set_scrobbler_queue($queue = array(), $clear = false) {
  6167. global $zc;
  6168. if ($zc['cache']) {
  6169. $que_file = $zc['cache_dir_private_abs'].'/scrobbler_queue_'.$zc['user_id'].'.txt';
  6170. if (empty($queue)) {
  6171. if ($clear) {
  6172. if (file_exists($que_file)) unlink($que_file);
  6173. } elseif (file_exists($que_file)) {
  6174. return unserialize(file_get_contents($que_file));
  6175. }
  6176. } else {
  6177. return file_put_contents($que_file, serialize($queue));
  6178. }
  6179. }
  6180. return array();
  6181. }
  6182. function zina_rename_playlist($old, $new) {
  6183. global $zc;
  6184. $filename = $zc['cache_pls_dir'].'/_zina_'.$new.'.m3u';
  6185. if ($new == '') return false;
  6186. if ($new == $old) return true;
  6187. if (file_exists($filename)) return false;
  6188. if (!rename($zc['cache_pls_dir'].'/_zina_'.$old.'.m3u', $filename)) return false;
  6189. return true;
  6190. }
  6191. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  6192. * SEARCH functions
  6193. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  6194. function zina_search_embed($term, $limit = 0) {
  6195. global $zc;
  6196. if ($zc['db_search']) {
  6197. $results = zdbq_array("SELECT path, type, title, context FROM {search_index} WHERE title LIKE '%%%s%%' ORDER BY title LIMIT %d",
  6198. array($term, $limit));
  6199. } else {
  6200. $results = zina_search_cache($term, $limit);
  6201. }
  6202. zina_content_search_list($results, false);
  6203. return $results;
  6204. }
  6205. function zina_search_cache($term, $limit = false) {
  6206. $results = array();
  6207. $num = 0;
  6208. $results = array_merge($results, zina_search_dirs($term, $limit));
  6209. if ($limit) {
  6210. $limit -= sizeof($results);
  6211. if (!$limit) return $results;
  6212. }
  6213. $results = array_merge($results, zina_search_files($term, $limit));
  6214. if (!empty($results)) usort($results, 'zsort_title');
  6215. return $results;
  6216. }
  6217. function zina_search_dirs($term, $limit = false) {
  6218. $found = array();
  6219. $dirs = zina_core_cache('dirs');
  6220. $num = 0;
  6221. if (!empty($dirs)) {
  6222. foreach ($dirs as $path) {
  6223. if (stristr($path, $term)) {
  6224. $found[] = zina_search_dir_helper($path);
  6225. if ($limit && ++$num >= $limit) break;
  6226. }
  6227. }
  6228. }
  6229. return $found;
  6230. }
  6231. function zina_search_dirs_for_missing_images($limit = false) {
  6232. global $zc;
  6233. $missing = array();
  6234. $dirs = zina_core_cache('dirs');
  6235. $num = 0;
  6236. if (!empty($dirs)) {
  6237. foreach ($dirs as $path) {
  6238. if (empty($path)) continue;
  6239. $full_path = $zc['mp3_dir'].(!empty($path) ? '/'.$path : '');
  6240. if (!zina_get_dir_item($full_path,'/\.('.$zc['ext_graphic'].')$/i')) {
  6241. $missing[$path] = $path;
  6242. }
  6243. }
  6244. }
  6245. return $missing;
  6246. }
  6247. function zina_search_dir_helper($path) {
  6248. global $zc;
  6249. $type = 'directory';
  6250. $context = null;
  6251. $count = substr_count($path, '/');
  6252. if ($zc['search_structure']) {
  6253. if ($count == 0) {
  6254. $type = 'artist';
  6255. } elseif ($count == 1) {
  6256. $type = 'album';
  6257. $context = ztheme('title',substr($path, 0, strpos($path,'/')));
  6258. }
  6259. }
  6260. $title = ($count > 0) ? substr($path, strrpos($path,'/')+1) : $path;
  6261. # order is important
  6262. return array(
  6263. 'title' => ztheme('title',$title),
  6264. 'type' => zt($type),
  6265. 'context' => $context,
  6266. 'id' => $path,
  6267. 'path' => $path,
  6268. 'genre' => null,
  6269. 'image' => null,
  6270. 'year' => null,
  6271. 'mtime' => null,
  6272. );
  6273. }
  6274. function zina_search_files($term, $limit = false) {
  6275. global $zc;
  6276. $found = array();
  6277. $num = 0;
  6278. $files = zina_core_cache('files');
  6279. if (!empty($files)) {
  6280. foreach ($files as $path) {
  6281. $file = basename($path);
  6282. if (stristr($file, $term)) {
  6283. $x = explode('/', $path);
  6284. $len = sizeof($x);
  6285. if ($len == 2)
  6286. $context = ztheme('title',$x[0]);
  6287. elseif ($len > 2)
  6288. $context = ztheme('title',$x[$len - 3]);
  6289. else
  6290. $context = null;
  6291. # order is important
  6292. $found[] = array(
  6293. 'title' => ztheme('song_title', preg_replace('/\.('.$zc['ext_mus'].')$/i', '', $file)),
  6294. 'type' => 'song',
  6295. 'context' => $context,
  6296. 'id' => $path,
  6297. 'path' => $path,
  6298. 'genre' => null,
  6299. 'image' => null,
  6300. 'year' => null,
  6301. 'mtime' => null,
  6302. );
  6303. if ($limit && ++$num >= $limit) break;
  6304. }
  6305. }
  6306. }
  6307. return $found;
  6308. }
  6309. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  6310. * MISC functions
  6311. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  6312. #todo: incorp timelimit?
  6313. #todo: private not implemented or used...
  6314. #type sitemap
  6315. function zina_cache($type, $func, $args = null, $gz, $public = true, $force = false) {
  6316. global $zc;
  6317. $cache = $zc[$type.'_cache'];
  6318. $file = $zc[$type.'_file'];
  6319. $cache_file = (($public) ? $zc['cache_dir_public_abs'] : $zc['cache_dir_private_abs']).'/'.$file;
  6320. if ($cache && !$force) {
  6321. if (file_exists($cache_file)) {
  6322. if ($public) {
  6323. while(@ob_end_clean());
  6324. header('Location: '.$zc['zina_dir_rel'].'/'.$zc['cache_dir_public_rel'].'/'.$file);
  6325. exit;
  6326. } else {
  6327. return implode("\n", gzfile($cache_file));
  6328. }
  6329. }
  6330. }
  6331. $output = call_user_func_array($func, $args);
  6332. if (!$output) return false;
  6333. if ($cache || $force) {
  6334. if ($gz) {
  6335. $gz = gzopen($cache_file,'w1');
  6336. gzwrite($gz, $output);
  6337. gzclose($gz);
  6338. } else {
  6339. file_put_contents($cache_file, $output);
  6340. }
  6341. }
  6342. return $output;
  6343. }
  6344. function zina_reorder_playlist($songs, $order) {
  6345. $new = $neworder = array();
  6346. $count = sizeof($songs);
  6347. if ($count == 0) return null;
  6348. for ($i = 0; $i < $count; $i++){
  6349. if (empty($order[$i])) continue; # 0 == delete
  6350. $j = (zina_validate('int', $order[$i])) ? $order[$i] : 99;
  6351. $new[$j][] = $songs[$i];
  6352. }
  6353. ksort($new);
  6354. $songs = array();
  6355. foreach($new as $neworder) {
  6356. foreach($neworder as $song) $songs[] = $song;
  6357. }
  6358. return $songs;
  6359. }
  6360. function zina_is_admin() {
  6361. global $zc;
  6362. if (isset($zc['conf']['is_admin'])) return $zc['conf']['is_admin'];
  6363. if (isset($_SESSION['za-'.ZINA_VERSION]) && $_SESSION['za-'.ZINA_VERSION] == true) return true;
  6364. if ($zc['adm_ip'] && strstr($zc['adm_ips'], $_SERVER['REMOTE_ADDR'])) return true;
  6365. if ($zc['loc_is_adm'] && $_SERVER['SERVER_ADDR'] == $_SERVER['REMOTE_ADDR']) return true;
  6366. if ($zc['session'] && isset($_COOKIE['ZINA_SESSION'])) {
  6367. $sess_file = $zc['cache_dir_private_abs'].'/sess_'.zcheck_plain($_COOKIE['ZINA_SESSION']);
  6368. if (file_exists($sess_file) && filemtime($sess_file) + (60*60*$zc['session_lifetime']) > time()) {
  6369. @touch($sess_file);
  6370. $_SESSION['za-'.ZINA_VERSION] = true;
  6371. return true;
  6372. }
  6373. }
  6374. if (!$_SESSION && isset($_GET['zid']) && isset($_GET['l']) && ($_GET['l'] == '6' || $_GET['l'] == '10')) {
  6375. return (zina_token('verify', $_GET['zid']));
  6376. }
  6377. return false;
  6378. }
  6379. function zina_is_various($cur_dir, $path) {
  6380. global $zc;
  6381. if ($zc['various']) {
  6382. if (file_exists($cur_dir.'/'.$zc['various_file'])) return true;
  6383. if ($zc['various_above'] && !empty($path)) {
  6384. $parts = explode('/', $path);
  6385. $size = sizeof($parts);
  6386. if ($size > 1) {
  6387. $dir_above = preg_replace('/'.preg_quote($parts[($size-1)]).'$/i', '', $cur_dir);
  6388. if (file_exists($dir_above.$zc['various_file'])) return true;
  6389. }
  6390. }
  6391. }
  6392. return false;
  6393. }
  6394. function zina_is_category($path) {
  6395. global $zc;
  6396. $cat_file = $path.'/'.$zc['cat_file'];
  6397. $cat_file_exists = $category = file_exists($cat_file);
  6398. if (!$category && $zc['cat_auto']) {
  6399. $num = $zc['cat_auto_num'];
  6400. $dir_skip = $zc['dir_skip'];
  6401. $i = 1;
  6402. if ($result = scandir($path)) {
  6403. foreach($result as $file) {
  6404. if ($file== "." || $file== '..' || $file[0] == $dir_skip) continue;
  6405. if (is_dir($path.'/'.$file)) {
  6406. if (++$i > $num) {
  6407. $category = true;
  6408. break;
  6409. }
  6410. }
  6411. }
  6412. }
  6413. }
  6414. if ($category) {
  6415. $cat['images'] = $zc['cat_images'];
  6416. $cat['cols'] = $zc['cat_cols'];
  6417. $cat['truncate'] = $zc['cat_truncate'];
  6418. $cat['split'] = $zc['cat_split'];
  6419. $cat['sort'] = $zc['cat_sort'];
  6420. $cat['pp'] = $zc['cat_pp'];
  6421. if ($cat_file_exists) {
  6422. $cat_xml = file_get_contents($cat_file);
  6423. if (!empty($cat_xml)) {
  6424. $cat_settings = xml_to_array($cat_xml, 'category');
  6425. if (!empty($cat_settings)) {
  6426. $cat_settings = $cat_settings[0];
  6427. $cat['images'] = isset($cat_settings['images']) ? $cat_settings['images'] : $cat['images'];
  6428. $cat['cols'] = isset($cat_settings['columns']) ? $cat_settings['columns'] : $cat['cols'];
  6429. $cat['truncate'] = isset($cat_settings['truncate']) ? $cat_settings['truncate'] : $cat['truncate'];
  6430. $cat['split'] = isset($cat_settings['split']) ? $cat_settings['split'] : $cat['split'];
  6431. $cat['pp'] = isset($cat_settings['per_page']) ? $cat_settings['per_page'] : $cat['pp'];
  6432. $cat['sort'] = isset($cat_settings['sort']) ? $cat_settings['sort'] : $cat['sort'];
  6433. }
  6434. $settings = xml_to_array($cat_xml, 'override');
  6435. if (!empty($settings)) {
  6436. $settings = $settings[0];
  6437. foreach($settings as $key => $val) {
  6438. if (in_array($key, array('dir_tags'))) {
  6439. $zc[$key] = $val;
  6440. #$cat['override'][$key] = $val;
  6441. }
  6442. }
  6443. }
  6444. }
  6445. }
  6446. return $cat;
  6447. }
  6448. return false;
  6449. }
  6450. function zina_check_password($un, $up) {
  6451. global $zc;
  6452. $hash = base64_decode($zc['adm_pwd']);
  6453. $new_hash = pack("H*", sha1($up.substr($hash,20)));
  6454. return ($zc['adm_name'] == $un && substr($hash,0,20) == $new_hash);
  6455. }
  6456. function zina_get_hash($password) {
  6457. $salt = substr(pack("H*", sha1( substr(pack('h*', sha1(mt_rand())), 0, 8).$password)), 0, 4);
  6458. return base64_encode( pack("H*", sha1($password.$salt)).$salt);
  6459. }
  6460. function zina_cron_run($opts = array()) {
  6461. global $zc;
  6462. $semaphore = $zc['cache_dir_private_abs'].'/.cron';
  6463. if (file_exists($semaphore)) {
  6464. if (time() - filemtime($semaphore) > 3600) {
  6465. zina_debug(zt('Cron has been running for more than an hour and is most likely stuck.'));
  6466. @unlink($semaphore);
  6467. } else {
  6468. zina_debug(zt('Attempting to re-run cron while it is already running.'));
  6469. }
  6470. } else {
  6471. touch($semaphore);
  6472. if ($zc['database']) {
  6473. require_once($zc['zina_dir_abs'].'/batch.php');
  6474. $operations = array();
  6475. foreach(array('dirs', 'files_assoc', 'genre') as $type) {
  6476. $cache_file = $zc['cache_'.$type.'_file'];
  6477. $mtime = (file_exists($cache_file)) ? filemtime($cache_file) : 0;
  6478. if (time() - $mtime > $zc['cache_expire'] * 86400 ) {
  6479. @set_time_limit($zc['timeout']);
  6480. $operations[] = array('zina_core_cache_batch', array($type, '', array('force'=>true)));
  6481. }
  6482. }
  6483. if ($zc['low']) {
  6484. foreach(array('files_assoc') as $type) {
  6485. @set_time_limit($zc['timeout']);
  6486. $cache_file = $zc['cache_'.$type.'_file'];
  6487. $mtime = (file_exists($cache_file)) ? filemtime($cache_file) : 0;
  6488. if (time() - $mtime > $zc['cache_expire'] * 86400 ) {
  6489. $operations[] = array('zina_core_cache_batch', array($type, '', array('force'=>true, 'low'=>true)));
  6490. }
  6491. }
  6492. }
  6493. zdb_cron_run($operations);
  6494. if ($zc['sitemap']) {
  6495. $cache_file = $zc['cache_dir_public_abs'].'/'.$zc['sitemap_file'];
  6496. $mtime = (file_exists($cache_file)) ? filemtime($cache_file) : 0;
  6497. if (time() - $mtime > $zc['sitemap_cache_expire'] * 86400 ) {
  6498. $operations[] = array('zina_cache', array('sitemap', 'zina_content_sitemap', null, ($zc['sitemap'] == 2), true, true));
  6499. }
  6500. }
  6501. $batch = array(
  6502. 'title' => zt('Cron Run'),
  6503. 'finished_message' => zt('Cron completed successfully.'),
  6504. 'operations' => $operations,
  6505. 'finished' => 'zina_cron_finished',
  6506. );
  6507. zbatch_set($batch);
  6508. $redirect_path = (isset($opts['redirect_path'])) ? $opts['redirect_path'] : null;
  6509. $redirect_query = (isset($opts['redirect_query'])) ? $opts['redirect_query'] : null;
  6510. zbatch_process(null, $redirect_query, $opts);
  6511. } else { # NO DATABASE
  6512. foreach(array('dirs', 'files_assoc', 'genre') as $type) {
  6513. $cache_file = $zc['cache_'.$type.'_file'];
  6514. $mtime = (file_exists($cache_file)) ? filemtime($cache_file) : 0;
  6515. if (time() - $mtime > $zc['cache_expire'] * 86400 ) {
  6516. @set_time_limit($zc['timeout']);
  6517. zina_core_cache($type, '', array('force'=>true));
  6518. }
  6519. }
  6520. if ($zc['low']) {
  6521. foreach(array('files_assoc') as $type) {
  6522. @set_time_limit($zc['timeout']);
  6523. $cache_file = $zc['cache_'.$type.'_file'];
  6524. $mtime = (file_exists($cache_file)) ? filemtime($cache_file) : 0;
  6525. if (time() - $mtime > $zc['cache_expire'] * 86400 ) {
  6526. zina_core_cache($type, '', array('force'=>true,'low'=>true));
  6527. }
  6528. }
  6529. }
  6530. if ($zc['sitemap']) {
  6531. $cache_file = $zc['cache_dir_public_abs'].'/'.$zc['sitemap_file'];
  6532. $mtime = (file_exists($cache_file)) ? filemtime($cache_file) : 0;
  6533. if (time() - $mtime > $zc['sitemap_cache_expire'] * 86400 ) {
  6534. zina_cache('sitemap', 'zina_content_sitemap', null, ($zc['sitemap'] == 2), true, true);
  6535. }
  6536. }
  6537. }
  6538. @unlink($semaphore);
  6539. }
  6540. }
  6541. function zina_cron_feature($cron) {
  6542. global $zc;
  6543. $now = getdate();
  6544. #$now = getdate(mktime ( 8, 45, 0, 12, 29, 2003));
  6545. $n[0] = $now['wday']; # 0-6; 0 = sun
  6546. $n[1] = $now['mon']; # 1-12
  6547. $n[2] = $now['mday']; # 0-31
  6548. $n[3] = ($now['hours'] * 60) + $now['minutes']; #0-23:0-59
  6549. foreach($cron as $feature=>$crontabs) {
  6550. foreach($crontabs as $key=>$crontab) {
  6551. $zc[$feature] = zina_cron_feature_check($crontab, $n);
  6552. }
  6553. }
  6554. }
  6555. #crontab = 'WDAY MON MDAY HH:MM';
  6556. function zina_cron_feature_check($crontab, $now) {
  6557. $tab = explode(' ',$crontab);
  6558. $size = sizeof($tab);
  6559. if ($size != 4) {
  6560. zina_debug(zt('Bad zina_cron_feature_check option'),'warn');
  6561. return false;
  6562. }
  6563. for($i=0; $i<4; $i++) {
  6564. $cur = $tab[$i];
  6565. $n = $now[$i];
  6566. if($cur[0] == '*') continue;
  6567. if(strpos($cur,',') !== false) { #multi
  6568. $multi = explode(',',$cur);
  6569. if (!in_array($n, $multi)) return false;
  6570. } elseif (strpos($cur,'-') !== false) { #range
  6571. $range = explode('-',$cur);
  6572. if ($i == 3) {
  6573. $hm = explode(':',$range[0]);
  6574. $r0 = ($hm[0] * 60) + $hm[1];
  6575. $hm = explode(':',$range[1]);
  6576. $r1 = ($hm[0] * 60) + $hm[1];
  6577. } else {
  6578. $r0 = $range[0];
  6579. $r1 = $range[1];
  6580. }
  6581. if ($r0 < $r1) {
  6582. if($n < $r0 || $n > $r1) return false;
  6583. } else {
  6584. if($n < $r0 && $n > $r1) return false;
  6585. }
  6586. } else { #single
  6587. if ($n != $cur) return false;
  6588. }
  6589. }
  6590. return true;
  6591. }
  6592. class remoteFile {
  6593. function remoteFile($file, $info=false, $tag=false) {
  6594. $this->tag = $this->info = false;
  6595. $this->filesize = 0;
  6596. $this->remote = true;
  6597. $this->genre = 'Unknown';
  6598. $content = file_get_contents($file);
  6599. $arr = xml_to_array($content);
  6600. $arr = (empty($arr)) ? get_meta_tags($file) : $arr[0];
  6601. if (empty($arr)) return;
  6602. $this->url = $arr['url'];
  6603. $this->download = isset($arr['download']) ? $arr['download'] : null;
  6604. if ($info) {
  6605. if (isset($arr['time'])) {
  6606. $this->time = $arr['time'];
  6607. $this->filesize = isset($arr['filesize']) ? $arr['filesize'] : 0;
  6608. $this->bitrate = isset($arr['bitrate']) ? $arr['bitrate'] : 0;
  6609. $this->frequency = isset($arr['frequency']) ? $arr['frequency'] : 0;
  6610. $this->length = isset($arr['length']) ? $arr['length'] : 0;
  6611. $this->stereo = isset($arr['stereo']) ? $arr['stereo'] : 1;
  6612. $this->info = true;
  6613. }
  6614. }
  6615. if ($tag) {
  6616. if (isset($arr['title'])) {
  6617. $this->title = $arr['title'];
  6618. $this->artist = isset($arr['artist']) ? $arr['artist'] : '';
  6619. $this->album = isset($arr['album']) ? $arr['album'] : '';
  6620. $this->year = isset($arr['year']) ? $arr['year'] : '';
  6621. $this->genre = isset($arr['genre']) ? $arr['genre'] : 'Unknown';
  6622. $this->tag = true;
  6623. }
  6624. }
  6625. }
  6626. }
  6627. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  6628. * SETTINGS & INIT
  6629. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  6630. function zina_init($conf) {
  6631. global $zc, $z_dbc, $zina_lang_code, $zina_lang_path;
  6632. if ($conf['embed'] == 'standalone') {
  6633. ini_set('arg_separator.output', '&amp;');
  6634. ini_set('magic_quotes_runtime', 0);
  6635. ini_set('magic_quotes_sybase', 0);
  6636. ini_set('session.cache_expire', 259200); # 3 days
  6637. ini_set('session.cache_limiter', 'none');
  6638. ini_set('session.cookie_lifetime', 1209600); # 14 days
  6639. ini_set('session.gc_maxlifetime', 259200);
  6640. ini_set('session.use_only_cookies', 1);
  6641. ini_set('session.use_trans_sid', 0);
  6642. ini_set('url_rewriter.tags', '');
  6643. session_start();
  6644. $zc['login'] = true;
  6645. } else {
  6646. $zc['login'] = false;
  6647. }
  6648. # FOR IIS
  6649. if (!isset($_SERVER['DOCUMENT_ROOT'])) {
  6650. if (isset($_SERVER['SCRIPT_FILENAME'])) {
  6651. $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF'])));
  6652. } elseif (isset($_SERVER['PATH_TRANSLATED'])) {
  6653. $_SERVER['DOCUMENT_ROOT'] = str_replace( '\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0-strlen($_SERVER['PHP_SELF'])));
  6654. }
  6655. }
  6656. $zc['conf'] = $conf;
  6657. $zc['database'] = $zc['db_cms'] = $zc['is_admin'] = $zc['play_local'] = false;
  6658. $zc['charset'] = (isset($conf['charset'])) ? $conf['charset'] : 'utf-8'; #needed for blocks
  6659. $zc['windows'] = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
  6660. $zc['zina_dir_abs'] = (($zc['windows']) ? str_replace("\\",'/',$conf['index_abs']) : $conf['index_abs']).'/zina';
  6661. # for modules
  6662. if (isset($conf['index_rel'])) {
  6663. $zc['index_rel'] = $conf['index_rel'];
  6664. }
  6665. $settings = zina_get_settings('cfg');
  6666. require_once($zc['zina_dir_abs'].'/common.php');
  6667. require_once($zc['zina_dir_abs'].'/theme.php');
  6668. require_once($zc['zina_dir_abs'].'/mp3.class.php');
  6669. $ini = $zc['zina_dir_abs'].'/zina.ini.php';
  6670. if (file_exists($ini)) require($ini);
  6671. if ($conf['embed'] != 'standalone') {
  6672. if ($z_dbc = zina_get_active_db($db_opts)) {
  6673. if (in_array($db_opts['type'], zina_get_db_types())) {
  6674. $zc['db_pre'] = $db_opts['prefix'].'zina_';
  6675. $zc['db_type'] = $db_opts['type'];
  6676. require_once($zc['zina_dir_abs'].'/database-'.$zc['db_type'].'.php');
  6677. require_once($zc['zina_dir_abs'].'/database.php');
  6678. $zinaini = zvar_get('settings', null);
  6679. if (!empty($zinaini)) extract($zinaini, EXTR_OVERWRITE);
  6680. $zc['database'] = $zc['db_cms'] = true;
  6681. } else {
  6682. zina_debug(zt('Unsupported CMS database type: @type', array($db_opts['type'])));
  6683. }
  6684. }
  6685. }
  6686. if (isset($login)) $zc['login'] = $login;
  6687. foreach($settings as $section => $cat) {
  6688. # dont allow defaults to override cms db settings
  6689. if ($section == 'db' && $zc['db_cms']) continue;
  6690. foreach($cat as $key => $val) {
  6691. if ($key == 'res_in_types') {
  6692. $zc[$key] = isset($$key) ? unserialize($$key) : $val['def'];
  6693. } else {
  6694. $zc[$key] = isset($$key) ? $$key : $val['def'];
  6695. }
  6696. if ($key == 'media_types_cfg') $media_types_default = $val['def'];
  6697. }
  6698. }
  6699. $zina_lang_code = $zc['lang'];
  6700. #TODO: get confirmation this works
  6701. if (!empty($zc['locale'])) {
  6702. if (($locale = setlocale(LC_ALL, $zc['locale'])) === false) {
  6703. if ($_GET['l'] != 21) {
  6704. zina_set_message(zt('Locale setting not supported by your system. Locale is set to @locale.', array('@locale'=> setlocale(LC_ALL,null))),'warn');
  6705. $zc['locale'] = setlocale(LC_ALL,0);
  6706. }
  6707. }
  6708. }
  6709. @date_default_timezone_set($zc['timezone']);
  6710. @set_time_limit($zc['timeout']);
  6711. zpath_to_theme($zc['zina_dir_rel'].'/themes/'.$zc['theme']);
  6712. $zc['theme_path_abs'] = $zc['zina_dir_abs'].'/themes/'.$zc['theme'];
  6713. $zina_lang_path = false;
  6714. $lang_user = $zc['theme_path_abs'].'/'.$zina_lang_code.'.php';
  6715. if (file_exists($lang_user)) {
  6716. $zina_lang_path = $lang_user;
  6717. } elseif (file_exists($zc['zina_dir_abs'].'/lang/'.$zina_lang_code.'.php')) {
  6718. $zina_lang_path = $zc['zina_dir_abs'].'/lang/'.$zina_lang_code.'.php';
  6719. }
  6720. if (function_exists('mb_strlen')) {
  6721. $zc['multibyte'] = true;
  6722. mb_internal_encoding($zc['charset']);
  6723. mb_language('uni');
  6724. } else {
  6725. $zc['multibyte'] = false;
  6726. zina_debug(zt('No multibyte support.'));
  6727. }
  6728. #todo: still needed with new error checking???
  6729. if (!is_dir($zc['mp3_dir'])) {
  6730. $default_music = $zc['zina_dir_abs'].'/demo';
  6731. if (!is_dir($default_music)) $default_music = $zc['zina_dir_abs'];
  6732. zina_set_message(zt('Your music directory does not exist!'),'error');
  6733. $zc['mp3_dir'] = $default_music;
  6734. }
  6735. if ($zc['stream_int'] || !preg_match('#^'.$_SERVER['DOCUMENT_ROOT'].'#i',$zc['mp3_dir'])) {
  6736. $zc['stream_int'] = true;
  6737. } else {
  6738. $zc['www_path'] = preg_replace('#^'.$_SERVER['DOCUMENT_ROOT'].'#i', '', $zc['mp3_dir']);
  6739. }
  6740. $zc['cache_dir_public_abs'] = $zc['zina_dir_abs'].'/'.$zc['cache_dir_public_rel'];
  6741. $zc['cache_imgs_dir'] = $zc['zina_dir_abs'].'/'.$zc['cache_imgs_dir_rel'];
  6742. $zc['cache_tmpl_dir'] = $zc['cache_dir_private_abs'].'/tmpl';
  6743. $zc['cache_pls_dir'] = $zc['cache_dir_private_abs'].'/playlist';
  6744. $zc['cache_zip_dir'] = $zc['cache_dir_private_abs'].'/zip';
  6745. $md5 = md5($zc['mp3_dir']);
  6746. $zc['cache_dirs_file'] = $zc['cache_dir_private_abs'].'/'.$md5.'_dirs.gz';
  6747. $zc['cache_files_assoc_file'] = $zc['cache_dir_private_abs'].'/'.$md5.'_files_assoc.gz';
  6748. $zc['cache_genre_file'] = $zc['cache_dir_private_abs'].'/'.$md5.'_genre.gz';
  6749. $zc['sitemap_file'] = ($zc['sitemap'] == 2) ? 'sitemap.xml.gz' : 'sitemap.xml';
  6750. $zc['encoders'] = zina_parse_ini_string($zc['enc_arr']);
  6751. $zc['ext_enc'] = implode('|',array_keys($zc['encoders']));
  6752. $types = ($zc['other_media_types']) ? $zc['media_types_cfg'] : $media_types_default;
  6753. $zc['media_types'] = zina_parse_ini_string($types);
  6754. $zc['ext_mus'] = implode('|',array_keys($zc['media_types']));
  6755. $zc['ran_opts'] = explode(',', $zc['ran_opts']);
  6756. $zc['auth'] = ($zc['apache_auth'] && isset($_SERVER['PHP_AUTH_USER'])) ? $_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW'].'@' : '';
  6757. $zc['resize_types'] = implode('|',$zc['res_in_types']);
  6758. if ($zc['mm']) {
  6759. $zc['mm_types'] = zina_parse_ini_string($zc['mm_types_cfg']);
  6760. $zc['mm_ext'] = implode('|',array_keys($zc['mm_types']));
  6761. }
  6762. if ($zc['cron']) {
  6763. $zc['cron_options'] = zina_parse_ini_string($zc['cron_opts']);
  6764. if (is_array($zc['cron_options'])) $zc['cron_options'] = current($zc['cron_options']);
  6765. }
  6766. if ($zc['song_extras']) {
  6767. $zc['song_es'] = zina_parse_ini_string($zc['song_extras_opt']);
  6768. $zc['song_es_exts'] = array_keys($zc['song_es']);
  6769. }
  6770. $zc['embed'] = (isset($conf['embed'])) ? $conf['embed'] : 'standalone';
  6771. if (isset($conf['clean_urls'])) {
  6772. $zc['clean_urls'] = $conf['clean_urls'];
  6773. if (isset($conf['clean_urls_hack'])) $zc['clean_urls_hack'] = $conf['clean_urls_hack'];
  6774. }
  6775. if (isset($conf['url_query'])) $zc['url_query'] = $conf['url_query'];
  6776. if (isset($conf['lastfm'])) {
  6777. $zc['lastfm'] = $conf['lastfm'];
  6778. $zc['lastfm_username'] = $conf['lastfm_username'];
  6779. $zc['lastfm_password'] = $conf['lastfm_password'];
  6780. }
  6781. if (isset($conf['twitter'])) {
  6782. $zc['twitter'] = $conf['twitter'];
  6783. $zc['twitter_username'] = $conf['twitter_username'];
  6784. $zc['twitter_password'] = $conf['twitter_password'];
  6785. }
  6786. $theme_file = $zc['theme_path_abs'].'/index.php';
  6787. if (file_exists($theme_file)) require_once($theme_file);
  6788. if (isset($zc['db']) && $zc['db'] && in_array($zc['db_type'], zina_get_db_types())) {
  6789. require_once($zc['zina_dir_abs'].'/database-'.$zc['db_type'].'.php');
  6790. if ($z_dbc = zdb_connect($zc['db_host'], $zc['db_name'], $zc['db_user'], $zc['db_pwd'], ($conf['embed'] != 'standalone'))) {
  6791. require_once($zc['zina_dir_abs'].'/database.php');
  6792. $zc['database'] = true;
  6793. }
  6794. }
  6795. $zc['search'] = ($zc['search'] || $zc['db_search']);
  6796. $zc['db_search'] = ($zc['db_search'] && $zc['search'] && $zc['database']);
  6797. if ($zc['clean_urls'] && $zc['clean_urls_hack']) {
  6798. $zc['index_rel'] = (isset($zc['index_rel'])) ? $zc['index_rel'].'/'.$zc['clean_urls_index'] : $zc['clean_urls_index'];
  6799. if (isset($_GET['p']) && !(strpos($_GET['p'],$zc['clean_urls_index'])===false)) {
  6800. $_GET['p'] = substr($_GET['p'],strlen($zc['index_rel'])+1);
  6801. }
  6802. }
  6803. $zc['session'] = ($zc['cache'] && $zc['embed'] == 'standalone' && $zc['session']);
  6804. $zc['is_admin'] = zina_is_admin();
  6805. if ($_SERVER['SERVER_ADDR'] == $_SERVER['REMOTE_ADDR'] || $zc['pos']) {
  6806. if ($zc['local_path'] || $zc['pos']) {
  6807. $zc['stream_int'] = false;
  6808. $zc['play_local'] = true;
  6809. }
  6810. }
  6811. if (!$zc['is_admin'] && $zc['cron'] && !empty($zc['cron_options'])) zina_cron_feature($zc['cron_options']);
  6812. $zc['user_id'] = (isset($conf['user_id']) && is_numeric($conf['user_id'])) ? (int)$conf['user_id'] : (int)($zc['is_admin']);
  6813. if ($zc['user_id'] > 0 && isset($_SESSION)) {
  6814. if (function_exists('zina_token')) {
  6815. $token_value = (isset($conf['token_value'])) ? $conf['token_value'] : $zc['user_id'];
  6816. if ($token = zina_token('get', $token_value)) $zc['token'] = 'zid='.$token;
  6817. }
  6818. }
  6819. if ($zc['zinamp']) {
  6820. $xml = file_get_contents($zc['zina_dir_abs'].'/zinamp/skins/'.$zc['zinamp_skin'].'/skin.xml');
  6821. $mp_cfg = xml_to_array($xml,'skin');
  6822. $zc['zinamp_width'] = $mp_cfg[0]['width'];
  6823. $zc['zinamp_height'] = $mp_cfg[0]['height'];
  6824. $zc['zinamp_url'] = zurl('','l=55', null, true);
  6825. }
  6826. }
  6827. function zina_get_opt_zip() {
  6828. $opts[0] = zt('None');
  6829. $opts[1] = zt('External');
  6830. if (function_exists('zip_open')) {
  6831. $opts[2] = zt('Internal PHP Zip Library');
  6832. }
  6833. return $opts;
  6834. }
  6835. function zina_get_opt_playlist_format() {
  6836. return array(
  6837. 'm3u' => zt('m3u'),
  6838. 'asx' => zt('asx'),
  6839. 'xspf' => zt('xspf'),
  6840. );
  6841. }
  6842. function zina_get_opt_search() {
  6843. return array(
  6844. 'browse' => zt('Browse'),
  6845. 'play' => zt('Play'),
  6846. );
  6847. }
  6848. function zina_get_opt_filesort() {
  6849. return array(
  6850. 0 => zt('Alphabetically'),
  6851. 1 => zt('Alphabetically Descending'),
  6852. 2 => zt('By Date'),
  6853. 3 => zt('By Date Descending'),
  6854. 4 => zt('ID3 Track Number'),
  6855. );
  6856. }
  6857. # currently only for lyr
  6858. function zina_get_extras_opts($type) {
  6859. #TODO: get from directory... extras/extras_'.$m.'_*
  6860. #$opts = array('lyricwiki', 'lyricsfly');
  6861. return array('lyricwiki', 'chartlyrics', 'lyricsmania');
  6862. }
  6863. function zina_get_extras_lyr() {
  6864. return implode(',', zina_get_extras_opts('lyr'));
  6865. }
  6866. function zina_get_extras_images_opts() {
  6867. #TODO: get from directory...
  6868. #$opts = array( 'amazon' => array('num'=>2, 'artist'=>false, 'album'=> true, 'order'=>0)??, 'lastfm' = > 1);
  6869. return array('amazon', 'amazon', 'lastfm', 'google', 'google', 'google');
  6870. }
  6871. function zina_get_opt_catsplit() {
  6872. return array(
  6873. 0 => zt('Full Page'),
  6874. 3 => zt('Full Page (split Alphabetically)'),
  6875. 1 => zt('Split by Number Per Page'),
  6876. 2 => zt('Split Alphabetically'),
  6877. );
  6878. }
  6879. function zina_get_opt_sitemap() {
  6880. return array(
  6881. 0 => zt('None'),
  6882. 1 => zt('sitemap.xml'),
  6883. 2 => zt('sitemap.xml.gz'),
  6884. );
  6885. }
  6886. function zina_get_cat_sorts() {
  6887. return array(
  6888. 'a' => zt('Alphabetical Ascending'),
  6889. 'ad' => zt('Alphabetical Descending'),
  6890. 'd' => zt('Date Ascending'),
  6891. 'dd' => zt('Date Descending'),
  6892. );
  6893. }
  6894. function zina_get_zinamp() {
  6895. return array(
  6896. 0 => zt('None'),
  6897. 1 => zt('Inline'),
  6898. 2 => zt('Pop-up'),
  6899. );
  6900. }
  6901. function zina_get_zinamp_skins() {
  6902. global $zc;
  6903. $dir = $zc['zina_dir_abs'].'/zinamp/skins';
  6904. if ($d = @dir($dir)) {
  6905. while($entry = $d->read()) {
  6906. if ($entry == '.' || $entry == '..' || !is_dir($dir.'/'.$entry)) continue;
  6907. $opts[$entry] = $entry;
  6908. }
  6909. $d->close();
  6910. return $opts;
  6911. }
  6912. zina_set_message(zt('Cannot read skins directory'),'error');
  6913. return array('WinampClassic'=>'WinampClassic');
  6914. }
  6915. function zina_get_opt_tf() {
  6916. return array(1=>zt('True'), 0=>zt('False'));
  6917. }
  6918. function zina_get_db_types() {
  6919. return array('mysql'=>'mysql','mysqli'=>'mysqli');
  6920. }
  6921. function zina_get_settings($type = '') {
  6922. global $zc;
  6923. if ($type == 'cfg') {
  6924. $len = strlen($_SERVER['DOCUMENT_ROOT']);
  6925. $zina_dir_rel = ($len < strlen($zc['zina_dir_abs'])) ? str_replace('\\','/',substr($zc['zina_dir_abs'], $len)) : '';
  6926. if (function_exists('gd_info')) {
  6927. $gd = gd_info();
  6928. $img_resize = true;
  6929. $freetype = (bool)$gd['FreeType Support'];
  6930. #$freetype = function_exists('imagettftext');
  6931. if ((isset($gd['JPG Support']) && $gd['JPG Support']) ||
  6932. (isset($gd['JPEG Support']) && $gd['JPEG Support'])) {
  6933. $img_ins['jpg'] = 'jpg';
  6934. $img_ins['jpeg'] = 'jpeg';
  6935. $img_outs['jpeg'] = 'jpeg';
  6936. $img_out_def = 'jpeg';
  6937. }
  6938. if ($gd['PNG Support']) {
  6939. $img_ins['png'] = 'png';
  6940. $img_outs['png'] = 'png';
  6941. }
  6942. if ($gd['GIF Read Support']) {
  6943. $img_ins['gif'] = 'gif';
  6944. }
  6945. if ($gd['GIF Create Support']) {
  6946. $img_outs['gif'] = 'gif';
  6947. }
  6948. $img_ins_def = $img_ins;
  6949. } else {
  6950. $img_resize = false;
  6951. $freetype = false;
  6952. $gdno = (function_exists('zt')) ? zt('GD not detected') : 'GD not detected';
  6953. $img_ins = array('none'=>$gdno);
  6954. $img_ins_def = array('none'=>'none');
  6955. $img_outs['none'] = $gdno;
  6956. $img_out_def = 'none';
  6957. }
  6958. if ($zc['conf']['embed'] == 'standalone') {
  6959. $default_theme = 'zinaGarland';
  6960. $cat_cols = 4;
  6961. $cat_pp = 100;
  6962. $clean_url_hack = ($zc['windows']) ? true : false;
  6963. } else {
  6964. $default_theme = 'zinaEmbed';
  6965. $cat_cols = 3;
  6966. $cat_pp = 99;
  6967. $clean_url_hack = false;
  6968. }
  6969. $lyrics = zina_get_extras_lyr();
  6970. return array(
  6971. 'config' => array(
  6972. 'mp3_dir' => array('type'=>'textfield', 'size'=>40, 'def'=>$zc['zina_dir_abs'].'/demo', 'v'=>array('dir_exists')),
  6973. 'clean_urls' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  6974. ),
  6975. 'auth' => array(
  6976. 'adm_name' => array('type'=>'textfield', 'def'=>'admin', 'v'=>array('req')),
  6977. 'adm_pwd' => array('type'=>'password_adm', 'def'=>'1GiuvuvgdFGQwfQkIiZ04Ro6K7s1VWnm'),
  6978. 'loc_is_adm' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  6979. 'adm_ip' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  6980. 'adm_ips' => array('type'=>'textfield', 'def'=>'', 'v'=>array('if'=>array('adm_ip'=>'req'))),
  6981. 'apache_auth' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  6982. 'session' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  6983. 'session_lifetime' => array('type'=>'textfield', 'suf'=>'hours', 'def'=>336, 'v'=>array('if'=>array ('session'=>'int'))),
  6984. ),
  6985. 'db' => array(
  6986. 'db' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  6987. 'db_type' => array('type'=>'select', 'opts'=>'zina_get_db_types', 'def'=>'mysql', 'v'=>array('if'=>array('db'=>'req'))),
  6988. 'db_host' => array('type'=>'textfield', 'def'=>'localhost', 'v'=>array('if'=>array('db'=>'req'))),
  6989. 'db_name' => array('type'=>'textfield', 'def'=>'zina', 'v'=>array('if'=>array('db'=>'req'))),
  6990. 'db_user' => array('type'=>'textfield', 'def'=>'username', 'v'=>array('if'=>array('db'=>'req'))),
  6991. 'db_pwd' => array('type'=>'password', 'def'=>'password', 'v'=>array('if'=>array('db'=>'req'))),
  6992. 'db_pre' => array('type'=>'textfield', 'def'=>'z_'),
  6993. ),
  6994. 'caches' => array(
  6995. 'cache' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  6996. 'cache_dir_abs' => array('type'=>'textfield', 'def'=>$zc['zina_dir_abs'].'/cache', 'v'=>array('if'=>array('cache'=>'dir_writeable'))),
  6997. 'cache_expire' => array('type'=>'textfield', 'def'=>7, 'suf'=> 'days', 'v'=>array('if'=>array('cache'=>'int')),
  6998. 'break'=>1),
  6999. 'cache_tmpl' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7000. 'cache_tmpl_expire' => array('type'=>'textfield', 'def'=>21, 'suf'=>'days', 'v'=>array('if'=>array('cache_tmpl'=>'int'))) ,
  7001. ),
  7002. 'general' => array(
  7003. 'theme' => array('type'=>'select', 'opts'=>'zina_get_themes', 'def'=>$default_theme, 'v'=>array('req')),
  7004. 'lang' => array('type'=>'select', 'opts'=>'zina_get_languages', 'def'=>'en', 'v'=>array('req')),
  7005. 'main_dir_title' => array('type'=>'textfield', 'def'=>'Artists'),
  7006. 'amg' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7007. 'play_sel' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf'),
  7008. 'break'=>1),
  7009. 'random' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7010. 'ran_opts' => array('type'=>'textfield', 'def'=>'1,5,10,25,50,0', 'v'=>array('if'=>array('random'=>'int_split'))),
  7011. #todo: val && in ran_opts...
  7012. 'ran_opts_def' => array('type'=>'textfield', 'def'=>25, 'v'=>array('if'=>array('random'=>'int'))),
  7013. 'play_rec' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7014. 'play_rec_rand' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7015. 'honor_custom' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf'),
  7016. 'break'=>1),
  7017. #todo: make a random section???
  7018. 'random_least_played' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7019. 'random_lp_floor' => array('type'=>'textfield', 'def'=>0, 'v'=>array('if'=>array('random_least_played'=>'int'))),
  7020. 'random_lp_perc' => array('type'=>'textfield', 'def'=>75, 'v'=>array('if'=>array('random_least_played'=>'int')), 'suf'=>'%',
  7021. 'break'=>1),
  7022. 'new_highlight' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7023. 'new_time' => array('type'=>'textfield', 'suf'=>'days', 'def'=>14, 'v'=>array('if'=>array('new_highlight'=>'int'))),
  7024. ),
  7025. 'dirs' => array(
  7026. 'dir_file' => array('type'=>'textfield', 'def'=>'index.txt', 'v'=>array('req')),
  7027. 'ext_graphic' => array('type'=>'textfield', 'def'=>'jpg|gif|png|jpeg', 'v'=>array('req')),
  7028. 'image_captions' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7029. #todo: val if (not empty) strlen == 1
  7030. 'dir_skip' => array('type'=>'textfield', 'def'=>'_'),
  7031. 'dir_sort_ignore' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7032. 'dir_si_str' => array('type'=>'textfield', 'def'=>'the|a|an', 'v'=>array('if'=>array('dir_sort_ignore'=>'req')),
  7033. 'break'=>1),
  7034. 'dir_list' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7035. 'subdir_truncate' => array('type'=>'textfield', 'def'=>25, 'suf'=>'characters', 'v'=>array('int')),
  7036. #TODO: make drop Down title ASC, title DESC, year ASC, year DESC
  7037. 'dir_list_sort' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7038. 'dir_list_sort_asc' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7039. 'subdir_images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7040. 'subdir_cols' => array('type'=>'textfield', 'def'=>3, 'v'=>array('int'),
  7041. 'break'=>1),
  7042. 'alt_dirs' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7043. 'alt_file' => array('type'=>'textfield', 'def'=>'zina_alt', 'v'=>array('if'=>array('alt_dirs'=>'req'))),
  7044. ),
  7045. 'categories' => array(
  7046. 'cat_auto' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7047. 'cat_auto_num' => array('type'=>'textfield', 'def'=>20, 'v'=>array('if'=>array('cat_auto'=>'int'))),
  7048. 'cat_file' => array('type'=>'textfield', 'def'=>'zina_category', 'v'=>array('req')),
  7049. #todo: val: if cat_auto || cat_file
  7050. 'cat_split' => array('type'=>'select', 'opts'=>'zina_get_opt_catsplit', 'def'=>1, 'v'=>array('req')),
  7051. 'cat_various_lookahead' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7052. #todo val: if cat_split == 1
  7053. 'cat_cols' => array('type'=>'textfield', 'def'=>$cat_cols, 'v'=>array('int')),
  7054. 'cat_pp' => array('type'=>'textfield', 'def'=>$cat_pp, 'v'=>array('if'=>array('cat_split'=>'int'))),
  7055. 'cat_sort' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7056. 'cat_sort_default' => array('type'=>'select', 'opts'=>'zina_get_cat_sorts', 'def'=>'a', 'v'=>array('req')),
  7057. 'cat_truncate' => array('type'=>'textfield', 'def'=>25, 'suf'=>'characters', 'v'=>array('int')),
  7058. 'cat_images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7059. ),
  7060. 'files' => array(
  7061. 'play' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7062. 'download' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7063. 'stream_int' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')) ,
  7064. 'playlist_format' => array('type'=>'select', 'opts'=>'zina_get_opt_playlist_format', 'def'=>'m3u', 'v'=>array('req'),
  7065. 'break'=>1),
  7066. # todo: use xml_field for more crap...? must test though =(
  7067. 'zinamp' => array('type'=>'radio', 'opts'=>'zina_get_zinamp', 'def'=>0, 'v'=>array('req')),
  7068. 'zinamp_skin' => array('type'=>'select', 'opts'=>'zina_get_zinamp_skins', 'def'=>'WinampClassic', 'v'=>array('req'),
  7069. 'break'=>1),
  7070. 'files_sort' => array('type'=>'select', 'opts'=>'zina_get_opt_filesort', 'def'=>0, 'v'=>array('req')),
  7071. 'mp3_id3' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7072. 'dir_tags' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7073. 'mp3_info' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7074. 'mp3_info_faster' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7075. 'stream_extinf' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1,'v'=>array('tf')),
  7076. 'stream_extinf_limit' => array('type'=>'textfield', 'def'=>100, 'v'=>array('if'=>array('stream_extinf'=>'int')),'suf'=>'items'),
  7077. 'song_blurbs' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf'), 'break'=>1),
  7078. 'song_extras' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7079. 'song_extras_opt' => array('type'=>'textarea', 'def'=>"[lyr]\r\nname=Lyrics\r\ntype=page_internal\r\n",
  7080. 'rows'=>5, 'v'=>array('if'=>array('song_extras'=>'req')),
  7081. 'break'=>1),
  7082. 'playlists' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7083. 'session_pls' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7084. 'pls_ratings' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7085. 'pls_length_limit' => array('type'=>'textfield', 'def'=>50, 'suf'=>'items', 'v'=>array('int')),
  7086. 'pls_limit' => array('type'=>'textfield', 'def'=>10, 'suf'=>'playlists', 'v'=>array('int')),
  7087. 'pls_public' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7088. 'pls_included' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7089. 'pls_included_limit' => array('type'=>'textfield', 'def'=>5, 'suf'=>'playlists', 'v'=>array('if'=>array('pls_included'=>'int')),
  7090. 'break'=>1),
  7091. 'various' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7092. 'various_file' => array('type'=>'textfield', 'def'=>'zina_various', 'v'=>array('if'=>array('various-'>'req'))),
  7093. 'various_above' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf'),
  7094. 'break'=>1),
  7095. 'low' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7096. 'low_suf' => array('type'=>'textfield', 'def'=>'.lofi', 'v'=>array('if'=>array('low'=>'req'))),
  7097. 'low_lookahead' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf'),
  7098. 'break'=>1),
  7099. 'resample' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7100. 'enc_arr' => array('type'=>'textarea', 'def'=>
  7101. "[mp3]\r\nencoder = lame\r\nopts = --mp3input -f -b56 --lowpass 12.0 --resample 22.05 -S %FILE% -\r\nmime = audio/mpeg\r\n\r\n".
  7102. "[wav]\r\nencoder = lame\r\nopts = -f -b56 --lowpass 12.0 --resample 22.05 -S %FILE% -\r\nmime = audio/mpeg",
  7103. 'v'=>array('if'=>array('resample'=>'req')),
  7104. 'break'=>1),
  7105. 'remote' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7106. 'remote_ext' => array('type'=>'textfield', 'def'=>'rem', 'v'=>array('if'=>array('remote'=>'req')),
  7107. 'break'=>1),
  7108. 'fake' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7109. 'fake_ext' => array('type'=>'textfield', 'def'=>'fake', 'v'=>array('if'=>array('fake'=>'req'))),
  7110. ),
  7111. 'tags' => array(
  7112. 'tags_cddb_server' => array('type'=>'textfield', 'def'=>'freedb.freedb.org', 'v'=>array('req')),
  7113. 'tags_format' => array('type'=>'textfield', 'def'=>'UTF-8'),
  7114. 'tags_keep_existing_data' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7115. 'tags_filemtime' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7116. 'tags_cddb_auto_start' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7117. ),
  7118. 'search' => array(
  7119. 'search' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7120. 'search_images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7121. 'search_min_chars' => array('type'=>'textfield', 'def'=>3, 'v'=>array('if'=>array('search'=>'int'))),
  7122. 'search_live_limit' => array('type'=>'textfield', 'def'=>12, 'v'=>array('if'=>array('db_search'=>'int'))),
  7123. 'search_default' => array('type'=>'select', 'opts'=>'zina_get_opt_search', 'def'=>'browse', 'v'=>array('req')),
  7124. 'search_structure' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7125. 'search_pp' => array('type'=>'textfield', 'def'=>20, 'v'=>array('if'=>array('search'=>'int')),
  7126. 'break'=>1),
  7127. 'db_search' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7128. 'search_pp_opts' => array('type'=>'textfield', 'def'=>'20,50,100', 'v'=>array('if'=>array('search'=>'int_split'))),
  7129. ),
  7130. 'genres' => array(
  7131. 'genres' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7132. 'genres_custom' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7133. 'dir_genre_look' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7134. 'genres_split' => array('type'=>'select', 'opts'=>'zina_get_opt_catsplit', 'def'=>0, 'v'=>array('req')),
  7135. 'genres_cols' => array('type'=>'textfield', 'def'=>4, 'v'=>array('int')),
  7136. 'genres_pp' => array('type'=>'textfield', 'def'=>200, 'v'=>array('if'=>array('genres_split'=>'int'))),
  7137. 'genres_truncate' => array('type'=>'textfield', 'def'=>30, 'suf'=>'characters', 'v'=>array('int')),
  7138. 'genres_images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7139. ),
  7140. 'compress' => array(
  7141. #todo: val cmp_sel value
  7142. 'cmp_sel' => array('type'=>'select', 'opts'=>'zina_get_opt_zip', 'def'=>0, 'v'=>array('int')),
  7143. 'cmp_cache' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7144. 'cmp_pgm' => array('type'=>'textfield', 'def'=>'C:\cygwin\bin\zip', 'v'=>array('if'=>array('cmp_sel'=>'req'))),
  7145. 'cmp_set' => array('type'=>'textfield', 'def'=>'-0 -j -q %FILE% %FILELIST%', 'v'=>array('if'=>array('cmp_sel'=>'req'))),
  7146. 'cmp_extension' => array('type'=>'textfield', 'def'=>'zip', 'v'=>array('if'=>array('cmp_sel'=>'req'))),
  7147. 'cmp_mime' => array('type', 'type'=>'textfield', 'def'=>'application/zip', 'v'=>array('if'=>array('cmp_sel'=>'req'))),
  7148. ),
  7149. 'podcasts' => array(
  7150. #todo: val: if sitemap 1 or 2 tf
  7151. 'sitemap' => array('type'=>'radio', 'opts'=>'zina_get_opt_sitemap', 'def'=>1, 'v'=>array('int')),
  7152. 'sitemap_cache' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('if'=>array('sitemap'=>'tf'))),
  7153. 'sitemap_cache_expire' => array('type'=>'textfield', 'def'=>21, 'suf'=>'days', 'v'=>array('if'=>array('sitemap_cache'=>'int')),
  7154. 'break'=>1),
  7155. 'rss' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7156. 'rss_podcast' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7157. 'rss_file' => array('type'=>'textfield', 'def'=>'rss.xml', 'v'=>array('if'=>array('rss'=>'req'))),
  7158. 'rss_mm' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7159. ),
  7160. #todo: could loop dir, sub, genre
  7161. 'images' => array(
  7162. 'res_in_types' => array('type'=>'checkboxes', 'opts'=>$img_ins, 'def'=>$img_ins_def, 'v'=>array('req')),
  7163. 'res_out_type' => array('type'=>'radio', 'opts'=>$img_outs, 'def'=> $img_out_def, 'v'=>array('req')),
  7164. 'res_out_x_lmt' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7165. 'cache_imgs' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf'),
  7166. 'break' =>1),
  7167. 'res_dir_img' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$img_resize, 'v'=>array('tf')),
  7168. 'res_dir_qual' => array('type'=>'textfield', 'def'=>75, 'v'=>array('int')),
  7169. 'res_dir_x' => array('type'=>'textfield', 'def'=>300, 'v'=>array('if'=>array('res_dir_img'=>'int')),'suf'=>'pixels'),
  7170. 'dir_img_txt' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$freetype, 'v'=>array('tf')),
  7171. 'dir_img_txt_color' => array('type'=>'textfield', 'def'=>'255,255,255', 'v'=>array('if'=>array('dir_img_txt'=>'int_split')),'suf'=>'(R,G,B)'),
  7172. 'dir_img_txt_wrap' => array('type'=>'textfield', 'def'=>20, 'v'=>array('if'=>array('dir_img_txt'=>'int'))),
  7173. 'dir_img_txt_font' => array('type'=>'textfield', 'def'=>$zc['zina_dir_abs'].'/extras/LiberationSans-Bold.ttf',
  7174. 'v'=>array('if'=>array('dir_img_txt'=>'file_exists'))
  7175. ),
  7176. 'dir_img_txt_font_size' => array('type'=>'textfield', 'def'=>12, 'v'=>array('if'=>array('dir_img_txt'=>'int')), 'suf'=>'pt',
  7177. 'break'=>1
  7178. ),
  7179. 'res_sub_img' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$img_resize, 'v'=>array('tf')),
  7180. 'res_sub_qual' => array('type'=>'textfield', 'def'=>75, 'v'=>array('int') ),
  7181. 'res_sub_x' => array('type'=>'textfield', 'def'=>200, 'v'=>array('int'),'suf'=>'pixels'),
  7182. 'sub_img_txt' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$freetype, 'v'=>array('tf')),
  7183. 'sub_img_txt_color' => array('type'=>'textfield', 'def'=>'0,0,0', 'v'=>array('if'=>array('sub_img_txt'=>'int_split')),'suf'=>'(R,G,B)'),
  7184. 'sub_img_txt_wrap' => array('type'=>'textfield', 'def'=>20, 'v'=>array('if'=>array('sub_img_txt'=>'int'))),
  7185. 'sub_img_txt_font' => array('type'=>'textfield', 'def'=>$zc['zina_dir_abs'].'/extras/LiberationSans-Bold.ttf',
  7186. 'v'=>array('if'=>array('sub_img_txt'=>'file_exists'))
  7187. ),
  7188. 'sub_img_txt_font_size' => array('type'=>'textfield', 'def'=>12, 'v'=>array('if'=>array('sub_img_txt'=>'int')),'suf'=>'pt',
  7189. 'break'=>1
  7190. ),
  7191. 'res_full_img' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$img_resize, 'v'=>array('tf')),
  7192. 'res_full_qual' => array('type'=>'textfield', 'def'=>75, 'v'=>array('int') ),
  7193. 'res_full_x' => array('type'=>'textfield', 'def'=>780, 'v'=>array('int'),'suf'=>'pixels',
  7194. 'break'=>1),
  7195. 'res_genre_img' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$img_resize, 'v'=>array('tf')),
  7196. 'res_genre_qual' => array('type'=>'textfield', 'def'=>75, 'v'=>array('int') ),
  7197. 'res_genre_x' => array('type'=>'textfield', 'def'=>200, 'v'=>array('int'),'suf'=>'pixels'),
  7198. 'genre_img_txt' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$freetype, 'v'=>array('tf')),
  7199. 'genre_img_txt_color' => array('type'=>'textfield', 'def'=>'255,255,255', 'v'=>array('if'=>array('genre_img_txt'=>'int_split')),'suf'=>'(R,G,B)'),
  7200. 'genre_img_txt_wrap' => array('type'=>'textfield', 'def'=>16, 'v'=>array('if'=>array('genre_img_txt'=>'int'))),
  7201. 'genre_img_txt_font' => array('type'=>'textfield', 'def'=>$zc['zina_dir_abs'].'/extras/LiberationSans-Bold.ttf',
  7202. 'v'=>array('if'=>array('sub_img_txt'=>'file_exists'))),
  7203. 'genre_img_txt_font_size' => array('type'=>'textfield', 'def'=>14, 'v'=>array('if'=>array('genre_img_txt'=>'int')),'suf'=>'pt',
  7204. 'break'=>1),
  7205. 'res_search_img' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$img_resize, 'v'=>array('tf')),
  7206. 'res_search_qual' => array('type'=>'textfield', 'def'=>100, 'v'=>array('int') ),
  7207. 'res_search_x' => array('type'=>'textfield', 'def'=>65, 'v'=>array('int'),'suf'=>'pixels'),
  7208. 'search_img_txt' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$freetype, 'v'=>array('tf')),
  7209. 'search_img_txt_color' => array('type'=>'textfield', 'def'=>'0,0,0', 'v'=>array('if'=>array('search_img_txt'=>'int_split')),'suf'=>'(R,G,B)'),
  7210. 'search_img_txt_wrap' => array('type'=>'textfield', 'def'=>12, 'v'=>array('if'=>array('search_img_txt'=>'int'))),
  7211. 'search_img_txt_font' => array('type'=>'textfield', 'def'=>$zc['zina_dir_abs'].'/extras/LiberationSans-Bold.ttf',
  7212. 'v'=>array('if'=>array('sub_img_txt'=>'file_exists'))),
  7213. 'search_img_txt_font_size' => array('type'=>'textfield', 'def'=>8, 'v'=>array('if'=>array('search_img_txt'=>'int')),'suf'=>'pt'),
  7214. ),
  7215. 'pos' => array(
  7216. 'pos' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7217. 'pos_cmd' => array('type'=>'textfield', 'def'=>'bgrun.exe C:\Progra~1\Winamp\winamp.exe %TEMPFILENAME%.m3u >NUL',
  7218. 'v'=>array('if'=>array('pos'=>'req'))),
  7219. 'pos_kill' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7220. 'pos_kill_cmd' => array('type'=>'textfield', 'def'=>'killall mpg123', 'v'=>array('if'=>array('pos_kill'=>'req'))),
  7221. ),
  7222. 'other_media' => array(
  7223. 'other_media_types' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7224. 'media_types_cfg' => array('type'=>'textarea', 'def'=>
  7225. "[mp3]\r\nmime = audio/mpeg\r\nprotocol = http\r\nplaylist_ext = m3u\r\nplaylist_mime = audio/mpegurl\r\n\r\n".
  7226. "[ogg]\r\nmime = audio/ogg\r\nprotocol = http\r\nplaylist_ext = m3u\r\nplaylist_mime = audio/mpegurl\r\n\r\n".
  7227. "[m4a]\r\nmime = audio/m4a\r\nprotocol = http\r\nplaylist_ext = m3u\r\nplaylist_mime = audio/mpegurl\r\n\r\n".
  7228. "[wav]\r\nmime = audio/x-wav\r\nprotocol = http\r\nplaylist_ext = m3u\r\nplaylist_mime = audio/mpegurl\r\n\r\n".
  7229. "[wma]\r\nmime = audio/x-ms-wma\r\nprotocol = http\r\nplaylist_ext = m3u\r\nplaylist_mime = audio/mpegurl",
  7230. 'v'=>array('if'=>array('other_media_types'=>'req'))
  7231. ),
  7232. ),
  7233. 'mm' => array(
  7234. 'mm' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7235. 'mm_down' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7236. 'mm_types_cfg' => array('type'=>'textarea', 'def'=>
  7237. "[pdf]\r\nmime = application/pdf\r\ndisposition = inline\r\n\r\n".
  7238. "[avi]\r\nmime = video/msvideo\r\nplayer = WMP\r\n\r\n[mpg]\r\nmime = video/mpeg\r\nplayer = WMP\r\n\r\n".
  7239. "[mpeg]\r\nmime = video/mpeg\r\nplayer = WMP\r\n\r\n[asf]\r\nmime = video/x-ms-asf\r\nplayer = WMP\r\n\r\n".
  7240. "[wmv]\r\nmime = video/x-ms-wmv\r\nplayer = WMP\r\n\r\n[mov]\r\nmime = video/quicktime\r\nplayer = QT",
  7241. 'v'=>array('if'=>array('mm'=>'req'))
  7242. ),
  7243. ),
  7244. 'cron' => array(
  7245. 'cron' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7246. 'cron_opts' => array('type'=>'textarea', 'rows'=>5, 'def'=>'', 'v'=>array('if'=>array('cron'=>'req'))),
  7247. ),
  7248. 'cms' => array(
  7249. 'cms_editor' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7250. 'cms_tags' => array('type'=>'textfield', 'def'=>'<a><strong><em><ul><ol><li><cite><code>',
  7251. 'break'=>1),
  7252. 'pls_user' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7253. 'pls_tags' => array('type'=>'textfield', 'def'=>'<b><i>'),
  7254. ),
  7255. 'integration' => array(
  7256. 'lastfm' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7257. 'lastfm_username' => array('type'=>'textfield', 'def'=>'', 'v'=>array('if'=>array('lastfm'=>'req'))),
  7258. 'lastfm_password' => array('type'=>'password', 'def'=>'', 'v'=>array('if'=>array('lastfm'=>'req')),
  7259. 'break'=>1),
  7260. 'twitter' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7261. 'twitter_username' => array('type'=>'textfield', 'def'=>'', 'v'=>array('if'=>array('twitter'=>'req'))),
  7262. 'twitter_password' => array('type'=>'password', 'def'=>'', 'v'=>array('if'=>array('twitter'=>'req')),
  7263. 'break'=>1),
  7264. ),
  7265. 'third' => array(
  7266. 'third_images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7267. 'third_amazon_private' => array('type'=>'textfield', 'def'=>''),
  7268. 'third_amazon_public' => array('type'=>'textfield', 'def'=>''),
  7269. 'third_amazon_region' => array('type'=>'textfield', 'def'=>'com',
  7270. 'break'=>1),
  7271. 'third_lyr' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7272. 'third_lyr_order' => array('type'=>'textfield', 'def'=>$lyrics),
  7273. 'third_lyr_save' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf'),
  7274. 'break'=>1),
  7275. 'third_addthis' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7276. 'third_addthis_id' => array('type'=>'textfield', 'def'=>'YOUR-ACCOUNT-ID'),
  7277. 'third_addthis_options' => array('type'=>'textfield', 'def'=>'email, favorites, digg, delicious, facebook, google, live, myspace, twitter, more'),
  7278. ),
  7279. 'stats' => array(
  7280. 'stats' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7281. 'stats_public' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7282. 'stats_images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7283. 'stats_rss' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7284. 'stats_limit' => array('type'=>'textfield', 'def'=>'10', 'v'=>array('if'=>array('stats'=>'int'))),
  7285. 'stats_to' => array('type'=>'textfield', 'def'=>'90', 'suf'=>'seconds', 'v'=>array('if'=>array('stats'=>'int'))),
  7286. 'stats_org' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf'),
  7287. 'break'=>1),
  7288. 'rating_dirs' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7289. 'rating_dirs_public' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7290. 'rating_files' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7291. 'rating_files_public' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7292. 'rating_limit' => array('type'=>'textfield', 'def'=>'1,1,1,1,1', 'v'=>array('if'=>array('stats'=>'int_split'))),
  7293. 'rating_random' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>1, 'v'=>array('tf')),
  7294. #todo: val -> if float_split
  7295. 'rating_random_opts' => array('type'=>'textfield', 'def'=>'5,4.5,4', 'v'=>0,
  7296. 'break'=>1),
  7297. 'cache_stats' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7298. 'cache_stats_expire' => array('type'=>'textfield', 'def'=>3, 'suf'=>'hours', 'v'=>array('if'=>array('cache_stats'=>'int'))),
  7299. ),
  7300. 'advanced' => array(
  7301. #todo: val->path_exists? try path_relative?
  7302. 'zina_dir_rel' => array('type'=>'textfield', 'def'=>$zina_dir_rel),
  7303. 'local_path' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7304. 'timeout' => array('type'=>'textfield', 'def'=>120, 'v'=>array('int')),
  7305. 'charset' => array('type'=>'textfield', 'def'=>'utf-8', 'v'=>array('req')),
  7306. 'locale' => array('type'=>'textfield', 'def'=> setlocale(LC_ALL,0)),
  7307. 'timezone' => array('type'=>'textfield', 'def'=>@date_default_timezone_get()),
  7308. 'debug' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf'),
  7309. 'break'=>1),
  7310. 'settings_override' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7311. 'settings_override_file' => array('type'=>'textfield', 'def'=>'zina_settings.xml', 'v'=>array('if'=>array('settings_override'=>'req')),
  7312. 'break'=>1),
  7313. 'cache_dir_private_abs' => array('type'=>'textfield', 'def'=>$zc['zina_dir_abs'].'/cache/private', 'v'=>array('if'=>array('cache'=>'dir_writeable'))),
  7314. 'cache_dir_public_rel' => array('type'=>'textfield', 'def'=>'cache/public', 'v'=>array('if'=>array('cache'=>'dir_writeable'))),
  7315. 'cache_imgs_dir_rel' => array('type'=>'textfield', 'def'=>'cache/public/images', 'v'=>array('if'=>array('cache_imgs'=>'path_relative')),
  7316. 'break'=>1),
  7317. 'clean_urls_hack' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$clean_url_hack, 'v'=>array('tf')),
  7318. 'clean_urls_index' => array('type'=>'textfield', 'def'=>'music', 'v'=>array('if'=>array('clean_urls_hack'=>'req'))),
  7319. ),
  7320. );
  7321. } elseif ($type == 'lang') {
  7322. require_once('lang-cfg.php');
  7323. return array('cats' => $cats, 'titles' => $titles, 'subs' => $subs);
  7324. } elseif ($type == 'directory') {
  7325. return array(
  7326. 'directory_opts' => array(
  7327. 'person' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7328. 'various' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7329. ),
  7330. 'categories' => array(
  7331. 'category' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>0, 'v'=>array('tf')),
  7332. 'split' => array('type'=>'select', 'opts'=>'zina_get_opt_catsplit', 'def'=>$zc['cat_split'], 'v'=>array('req')),
  7333. 'cols' => array('type'=>'textfield', 'def'=>$zc['cat_cols'], 'v'=>array('if'=>array('category'=>'int'))),
  7334. 'pp' => array('type'=>'textfield', 'def'=>$zc['cat_pp'], 'v'=>array('if'=>array('split'=>'int'))),
  7335. 'sort' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$zc['cat_sort'], 'v'=>array('tf')),
  7336. 'sort_default' => array('type'=>'select', 'opts'=>'zina_get_cat_sorts', 'def'=>'a', 'v'=>array('req')),
  7337. 'truncate' => array('type'=>'textfield', 'def'=>$zc['cat_truncate'], 'suf'=>'characters', 'v'=>array('if'=>array('category'=>'int'))),
  7338. 'images' => array('type'=>'radio', 'opts'=>'zina_get_opt_tf', 'def'=>$zc['cat_images'], 'v'=>array('tf')),
  7339. ),
  7340. );
  7341. }
  7342. }
  7343. ?>