diff --git a/admin/access.php b/admin/access.php index 60e86d62f8..3945d174d0 100644 --- a/admin/access.php +++ b/admin/access.php @@ -1,5 +1,5 @@ name, - 'admin/access.php?action=delete_record&access_id=' . $access->id,1,'delete_access'); - break; - case 'add_host': + case 'delete_record': + if (!Core::form_verify('delete_access')) { + UI::access_denied(); + exit; + } + Access::delete($_REQUEST['access_id']); + $url = Config::get('web_path') . '/admin/access.php'; + show_confirmation(T_('Deleted'), T_('Your Access List Entry has been removed'),$url); + break; + case 'show_delete_record': + if (Config::get('demo_mode')) { break; } + $access = new Access($_GET['access_id']); + show_confirmation(T_('Deletion Request'), T_('Are you sure you want to permanently delete') . ' ' . $access->name, + 'admin/access.php?action=delete_record&access_id=' . $access->id,1,'delete_access'); + break; + case 'add_host': - // Make sure we've got a valid form submission - if (!Core::form_verify('add_acl','post')) { - UI::access_denied(); - exit; - } + // Make sure we've got a valid form submission + if (!Core::form_verify('add_acl','post')) { + UI::access_denied(); + exit; + } - Access::create($_POST); + Access::create($_POST); - // Create Additional stuff based on the type - if ($_POST['addtype'] == 'stream' || - $_POST['addtype'] == 'all' - ) { - $_POST['type'] = 'stream'; - Access::create($_POST); - } - if ($_POST['addtype'] == 'all') { - $_POST['type'] = 'interface'; - Access::create($_POST); - } + // Create Additional stuff based on the type + if ($_POST['addtype'] == 'stream' || + $_POST['addtype'] == 'all' + ) { + $_POST['type'] = 'stream'; + Access::create($_POST); + } + if ($_POST['addtype'] == 'all') { + $_POST['type'] = 'interface'; + Access::create($_POST); + } - if (!Error::occurred()) { - $url = Config::get('web_path') . '/admin/access.php'; - show_confirmation(T_('Added'), T_('Your new Access Control List(s) have been created'),$url); - } - else { - $action = 'show_add_' . $_POST['type']; - require_once Config::get('prefix') . '/templates/show_add_access.inc.php'; - } - break; - case 'update_record': - if (!Core::form_verify('edit_acl')) { - UI::access_denied(); - exit; - } - $access = new Access($_REQUEST['access_id']); - $access->update($_POST); - if (!Error::occurred()) { - show_confirmation(T_('Updated'), T_('Access List Entry updated'), Config::get('web_path').'/admin/access.php'); - } - else { - $access->format(); - require_once Config::get('prefix') . '/templates/show_edit_access.inc.php'; - } - break; - case 'show_add_current': - case 'show_add_rpc': - case 'show_add_local': - case 'show_add_advanced': - $action = $_REQUEST['action']; - require_once Config::get('prefix') . '/templates/show_add_access.inc.php'; - break; - case 'show_edit_record': - $access = new Access($_REQUEST['access_id']); - $access->format(); - require_once Config::get('prefix') . '/templates/show_edit_access.inc.php'; - break; - default: - $list = array(); - $list = Access::get_access_lists(); - require_once Config::get('prefix') .'/templates/show_access_list.inc.php'; - break; + if (!Error::occurred()) { + $url = Config::get('web_path') . '/admin/access.php'; + show_confirmation(T_('Added'), T_('Your new Access Control List(s) have been created'),$url); + } + else { + $action = 'show_add_' . $_POST['type']; + require_once Config::get('prefix') . '/templates/show_add_access.inc.php'; + } + break; + case 'update_record': + if (!Core::form_verify('edit_acl')) { + UI::access_denied(); + exit; + } + $access = new Access($_REQUEST['access_id']); + $access->update($_POST); + if (!Error::occurred()) { + show_confirmation(T_('Updated'), T_('Access List Entry updated'), Config::get('web_path').'/admin/access.php'); + } + else { + $access->format(); + require_once Config::get('prefix') . '/templates/show_edit_access.inc.php'; + } + break; + case 'show_add_current': + case 'show_add_rpc': + case 'show_add_local': + case 'show_add_advanced': + $action = $_REQUEST['action']; + require_once Config::get('prefix') . '/templates/show_add_access.inc.php'; + break; + case 'show_edit_record': + $access = new Access($_REQUEST['access_id']); + $access->format(); + require_once Config::get('prefix') . '/templates/show_edit_access.inc.php'; + break; + default: + $list = array(); + $list = Access::get_access_lists(); + require_once Config::get('prefix') .'/templates/show_access_list.inc.php'; + break; } // end switch on action UI::show_footer(); ?> diff --git a/admin/catalog.php b/admin/catalog.php index 472ee8ced9..936b39a85a 100644 --- a/admin/catalog.php +++ b/admin/catalog.php @@ -1,5 +1,5 @@ get_catalog_ids(); - case 'add_to_catalog': - toggle_visible('ajax-loading'); - ob_end_flush(); - if (Config::get('demo_mode')) { break; } - if ($_REQUEST['catalogs'] ) { - foreach ($_REQUEST['catalogs'] as $catalog_id) { - $catalog = new Catalog($catalog_id); - $catalog->add_to_catalog(); - } - } - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Catalog Updated'); - $body = ''; - show_confirmation($title,$body,$url); - toggle_visible('ajax-loading'); - break; - case 'update_all_catalogs': - $_REQUEST['catalogs'] = Catalog::get_catalog_ids(); - case 'update_catalog': - toggle_visible('ajax-loading'); - ob_end_flush(); - /* If they are in demo mode stop here */ - if (Config::get('demo_mode')) { break; } - - if (isset($_REQUEST['catalogs'])) { - foreach ($_REQUEST['catalogs'] as $catalog_id) { - $catalog = new Catalog($catalog_id); - $catalog->verify_catalog(); - } - } - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Catalog Updated'); - $body = ''; - show_confirmation($title,$body,$url); - toggle_visible('ajax-loading'); - break; - case 'full_service': - toggle_visible('ajax-loading'); - ob_end_flush(); - /* Make sure they aren't in demo mode */ - if (Config::get('demo_mode')) { UI::access_denied(); break; } - - if (!$_REQUEST['catalogs']) { - $_REQUEST['catalogs'] = Catalog::get_catalog_ids(); - } - - /* This runs the clean/verify/add in that order */ - foreach ($_REQUEST['catalogs'] as $catalog_id) { - $catalog = new Catalog($catalog_id); - $catalog->clean_catalog(); - $catalog->count = 0; - $catalog->verify_catalog(); - $catalog->count = 0; - $catalog->add_to_catalog(); - } - Dba::optimize_tables(); - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Catalog Updated'); - $body = ''; - show_confirmation($title,$body,$url); - toggle_visible('ajax-loading'); - break; - case 'delete_catalog': - /* Make sure they aren't in demo mode */ - if (Config::get('demo_mode')) { break; } - - if (!Core::form_verify('delete_catalog')) { - UI::access_denied(); - exit; - } - - /* Delete the sucker, we don't need to check perms as thats done above */ - Catalog::delete($_GET['catalog_id']); - $next_url = Config::get('web_path') . '/admin/catalog.php'; - show_confirmation(T_('Catalog Deleted'), T_('The Catalog and all associated records have been deleted'),$next_url); - break; - case 'show_delete_catalog': - $catalog_id = scrub_in($_GET['catalog_id']); - - $next_url = Config::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalog_id=' . scrub_out($catalog_id); - show_confirmation(T_('Catalog Delete'), T_('Confirm Deletion Request'),$next_url,1,'delete_catalog'); - break; - case 'remove_disabled': - if (Config::get('demo_mode')) { break; } - - $song = $_REQUEST['song']; - - if (count($song)) { - $catalog->remove_songs($song); - $body = T_ngettext('Song Removed', 'Songs Removed', count($song)); - } - else { - $body = T_('No Songs Removed'); - } - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_ngettext('Disabled Song Processed','Disabled Songs Processed',count($song)); - show_confirmation($title,$body,$url); - break; - case 'clean_all_catalogs': - $catalog = new Catalog(); - $_REQUEST['catalogs'] = Catalog::get_catalog_ids(); - case 'clean_catalog': - toggle_visible('ajax-loading'); - ob_end_flush(); - /* If they are in demo mode stop them here */ - if (Config::get('demo_mode')) { break; } - - // Make sure they checked something - if (isset($_REQUEST['catalogs'])) { - foreach($_REQUEST['catalogs'] as $catalog_id) { - $catalog = new Catalog($catalog_id); - $catalog->clean_catalog(); - } // end foreach catalogs - Dba::optimize_tables(); - } - - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Catalog Cleaned'); - $body = ''; - show_confirmation($title,$body,$url); - toggle_visible('ajax-loading'); - break; - case 'update_catalog_settings': - /* No Demo Here! */ - if (Config::get('demo_mode')) { break; } - - /* Update the catalog */ - Catalog::update_settings($_POST); - - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Catalog Updated'); - $body = ''; - show_confirmation($title,$body,$url); - break; - case 'update_from': - if (Config::get('demo_mode')) { break; } - - // First see if we need to do an add - if ($_POST['add_path'] != '/' AND strlen($_POST['add_path'])) { - if ($catalog_id = Catalog::get_from_path($_POST['add_path'])) { - $catalog = new Catalog($catalog_id); - $catalog->run_add(array('subdirectory'=>$_POST['add_path'])); - } - } // end if add - - // Now check for an update - if ($_POST['update_path'] != '/' AND strlen($_POST['update_path'])) { - if ($catalog_id = Catalog::get_from_path($_POST['update_path'])) { - $songs = Song::get_from_path($_POST['update_path']); - foreach ($songs as $song_id) { Catalog::update_single_item('song',$song_id); } - } - } // end if update - - break; - case 'add_catalog': - /* Wah Demo! */ - if (Config::get('demo_mode')) { break; } - - ob_end_flush(); - - if (!strlen($_POST['path']) || !strlen($_POST['name'])) { - Error::add('general', T_('Error: Name and path not specified')); - } - - if (substr($_POST['path'],0,7) != 'http://' && $_POST['type'] == 'remote') { - Error::add('general', T_('Error: Remote selected, but path is not a URL')); - } - if ($POST['type'] == 'remote' AND (!strlen($POST['remote_username']) OR !strlen($POST['remote_password']))) { - Error::add('general', T_('Error: Username and Password Required for Remote Catalogs')); - } - - if (!Core::form_verify('add_catalog','post')) { - UI::access_denied(); - exit; - } - - // Make sure that there isn't a catalog with a directory above this one - if (Catalog::get_from_path($_POST['path'])) { - Error::add('general', T_('Error: Defined Path is inside an existing catalog')); - } - - // If an error hasn't occured - if (!Error::occurred()) { - - $catalog_id = Catalog::create($_POST); - - if (!$catalog_id) { - require Config::get('prefix') . '/templates/show_add_catalog.inc.php'; - break; - } - - $catalog = new Catalog($catalog_id); - - // Run our initial add - $catalog->run_add($_POST); - - UI::show_box_top(T_('Catalog Created'), 'box box_catalog_created'); - echo "

" . T_('Catalog Created') . "

"; - Error::display('general'); - Error::display('catalog_add'); - UI::show_box_bottom(); - - show_confirmation('','', Config::get('web_path').'/admin/catalog.php'); - - } - else { - require Config::get('prefix') . '/templates/show_add_catalog.inc.php'; - } - break; - case 'clear_stats': - if (Config::get('demo_mode')) { UI::access_denied(); break; } - Stats::clear(); - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Catalog statistics cleared'); - $body = ''; - show_confirmation($title, $body, $url); - break; - default: - case 'show_catalogs': - require_once Config::get('prefix') . '/templates/show_manage_catalogs.inc.php'; - break; - case 'show_add_catalog': - require Config::get('prefix') . '/templates/show_add_catalog.inc.php'; - break; - case 'clear_now_playing': - if (Config::get('demo_mode')) { UI::access_denied(); break; } - Stream::clear_now_playing(); - show_confirmation(T_('Now Playing Cleared'), T_('All now playing data has been cleared'),Config::get('web_path') . '/admin/catalog.php'); - break; - case 'show_disabled': - /* Stop the demo hippies */ - if (Config::get('demo_mode')) { break; } - - $songs = Song::get_disabled(); - if (count($songs)) { - require Config::get('prefix') . '/templates/show_disabled_songs.inc.php'; - } - else { - echo "
" . T_('No Disabled songs found') . "
"; - } - break; - case 'show_delete_catalog': - /* Stop the demo hippies */ - if (Config::get('demo_mode')) { UI::access_denied(); break; } - - $catalog = new Catalog($_REQUEST['catalog_id']); - $nexturl = Config::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalog_id=' . scrub_out($_REQUEST['catalog_id']); - show_confirmation(T_('Delete Catalog'), T_('Do you really want to delete this catalog?') . " -- $catalog->name ($catalog->path)",$nexturl,1); - break; - case 'show_customize_catalog': - $catalog = new Catalog($_REQUEST['catalog_id']); - require_once Config::get('prefix') . '/templates/show_edit_catalog.inc.php'; - break; - case 'gather_album_art': - toggle_visible('ajax-loading'); - ob_end_flush(); - - $catalogs = $_REQUEST['catalogs'] ? $_REQUEST['catalogs'] : Catalog::get_catalogs(); - - // Itterate throught the catalogs and gather as needed - foreach ($catalogs as $catalog_id) { - $catalog = new Catalog($catalog_id); - require Config::get('prefix') . '/templates/show_gather_art.inc.php'; - flush(); - $catalog->get_art('',1); - } - $url = Config::get('web_path') . '/admin/catalog.php'; - $title = T_('Album Art Search Finished'); - $body = ''; - show_confirmation($title,$body,$url); - break; + case 'fixed': + /* Does this use now? */ + delete_flagged($flag); + $type = 'show_flagged_songs'; + require Config::get('prefix') . '/templates/flag.inc'; + break; + case 'add_to_all_catalogs': + $catalog = new Catalog(); + $_REQUEST['catalogs'] = $catalog->get_catalog_ids(); + case 'add_to_catalog': + toggle_visible('ajax-loading'); + ob_end_flush(); + if (Config::get('demo_mode')) { break; } + if ($_REQUEST['catalogs'] ) { + foreach ($_REQUEST['catalogs'] as $catalog_id) { + $catalog = new Catalog($catalog_id); + $catalog->add_to_catalog(); + } + } + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Catalog Updated'); + $body = ''; + show_confirmation($title,$body,$url); + toggle_visible('ajax-loading'); + break; + case 'update_all_catalogs': + $_REQUEST['catalogs'] = Catalog::get_catalog_ids(); + case 'update_catalog': + toggle_visible('ajax-loading'); + ob_end_flush(); + /* If they are in demo mode stop here */ + if (Config::get('demo_mode')) { break; } + + if (isset($_REQUEST['catalogs'])) { + foreach ($_REQUEST['catalogs'] as $catalog_id) { + $catalog = new Catalog($catalog_id); + $catalog->verify_catalog(); + } + } + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Catalog Updated'); + $body = ''; + show_confirmation($title,$body,$url); + toggle_visible('ajax-loading'); + break; + case 'full_service': + toggle_visible('ajax-loading'); + ob_end_flush(); + /* Make sure they aren't in demo mode */ + if (Config::get('demo_mode')) { UI::access_denied(); break; } + + if (!$_REQUEST['catalogs']) { + $_REQUEST['catalogs'] = Catalog::get_catalog_ids(); + } + + /* This runs the clean/verify/add in that order */ + foreach ($_REQUEST['catalogs'] as $catalog_id) { + $catalog = new Catalog($catalog_id); + $catalog->clean_catalog(); + $catalog->count = 0; + $catalog->verify_catalog(); + $catalog->count = 0; + $catalog->add_to_catalog(); + } + Dba::optimize_tables(); + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Catalog Updated'); + $body = ''; + show_confirmation($title,$body,$url); + toggle_visible('ajax-loading'); + break; + case 'delete_catalog': + /* Make sure they aren't in demo mode */ + if (Config::get('demo_mode')) { break; } + + if (!Core::form_verify('delete_catalog')) { + UI::access_denied(); + exit; + } + + /* Delete the sucker, we don't need to check perms as thats done above */ + Catalog::delete($_GET['catalog_id']); + $next_url = Config::get('web_path') . '/admin/catalog.php'; + show_confirmation(T_('Catalog Deleted'), T_('The Catalog and all associated records have been deleted'),$next_url); + break; + case 'show_delete_catalog': + $catalog_id = scrub_in($_GET['catalog_id']); + + $next_url = Config::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalog_id=' . scrub_out($catalog_id); + show_confirmation(T_('Catalog Delete'), T_('Confirm Deletion Request'),$next_url,1,'delete_catalog'); + break; + case 'remove_disabled': + if (Config::get('demo_mode')) { break; } + + $song = $_REQUEST['song']; + + if (count($song)) { + $catalog->remove_songs($song); + $body = T_ngettext('Song Removed', 'Songs Removed', count($song)); + } + else { + $body = T_('No Songs Removed'); + } + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_ngettext('Disabled Song Processed','Disabled Songs Processed',count($song)); + show_confirmation($title,$body,$url); + break; + case 'clean_all_catalogs': + $catalog = new Catalog(); + $_REQUEST['catalogs'] = Catalog::get_catalog_ids(); + case 'clean_catalog': + toggle_visible('ajax-loading'); + ob_end_flush(); + /* If they are in demo mode stop them here */ + if (Config::get('demo_mode')) { break; } + + // Make sure they checked something + if (isset($_REQUEST['catalogs'])) { + foreach($_REQUEST['catalogs'] as $catalog_id) { + $catalog = new Catalog($catalog_id); + $catalog->clean_catalog(); + } // end foreach catalogs + Dba::optimize_tables(); + } + + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Catalog Cleaned'); + $body = ''; + show_confirmation($title,$body,$url); + toggle_visible('ajax-loading'); + break; + case 'update_catalog_settings': + /* No Demo Here! */ + if (Config::get('demo_mode')) { break; } + + /* Update the catalog */ + Catalog::update_settings($_POST); + + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Catalog Updated'); + $body = ''; + show_confirmation($title,$body,$url); + break; + case 'update_from': + if (Config::get('demo_mode')) { break; } + + // First see if we need to do an add + if ($_POST['add_path'] != '/' AND strlen($_POST['add_path'])) { + if ($catalog_id = Catalog::get_from_path($_POST['add_path'])) { + $catalog = new Catalog($catalog_id); + $catalog->run_add(array('subdirectory'=>$_POST['add_path'])); + } + } // end if add + + // Now check for an update + if ($_POST['update_path'] != '/' AND strlen($_POST['update_path'])) { + if ($catalog_id = Catalog::get_from_path($_POST['update_path'])) { + $songs = Song::get_from_path($_POST['update_path']); + foreach ($songs as $song_id) { Catalog::update_single_item('song',$song_id); } + } + } // end if update + + break; + case 'add_catalog': + /* Wah Demo! */ + if (Config::get('demo_mode')) { break; } + + ob_end_flush(); + + if (!strlen($_POST['path']) || !strlen($_POST['name'])) { + Error::add('general', T_('Error: Name and path not specified')); + } + + if (substr($_POST['path'],0,7) != 'http://' && $_POST['type'] == 'remote') { + Error::add('general', T_('Error: Remote selected, but path is not a URL')); + } + if ($POST['type'] == 'remote' AND (!strlen($POST['remote_username']) OR !strlen($POST['remote_password']))) { + Error::add('general', T_('Error: Username and Password Required for Remote Catalogs')); + } + + if (!Core::form_verify('add_catalog','post')) { + UI::access_denied(); + exit; + } + + // Make sure that there isn't a catalog with a directory above this one + if (Catalog::get_from_path($_POST['path'])) { + Error::add('general', T_('Error: Defined Path is inside an existing catalog')); + } + + // If an error hasn't occured + if (!Error::occurred()) { + + $catalog_id = Catalog::create($_POST); + + if (!$catalog_id) { + require Config::get('prefix') . '/templates/show_add_catalog.inc.php'; + break; + } + + $catalog = new Catalog($catalog_id); + + // Run our initial add + $catalog->run_add($_POST); + + UI::show_box_top(T_('Catalog Created'), 'box box_catalog_created'); + echo "

" . T_('Catalog Created') . "

"; + Error::display('general'); + Error::display('catalog_add'); + UI::show_box_bottom(); + + show_confirmation('','', Config::get('web_path').'/admin/catalog.php'); + + } + else { + require Config::get('prefix') . '/templates/show_add_catalog.inc.php'; + } + break; + case 'clear_stats': + if (Config::get('demo_mode')) { UI::access_denied(); break; } + Stats::clear(); + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Catalog statistics cleared'); + $body = ''; + show_confirmation($title, $body, $url); + break; + default: + case 'show_catalogs': + require_once Config::get('prefix') . '/templates/show_manage_catalogs.inc.php'; + break; + case 'show_add_catalog': + require Config::get('prefix') . '/templates/show_add_catalog.inc.php'; + break; + case 'clear_now_playing': + if (Config::get('demo_mode')) { UI::access_denied(); break; } + Stream::clear_now_playing(); + show_confirmation(T_('Now Playing Cleared'), T_('All now playing data has been cleared'),Config::get('web_path') . '/admin/catalog.php'); + break; + case 'show_disabled': + /* Stop the demo hippies */ + if (Config::get('demo_mode')) { break; } + + $songs = Song::get_disabled(); + if (count($songs)) { + require Config::get('prefix') . '/templates/show_disabled_songs.inc.php'; + } + else { + echo "
" . T_('No Disabled songs found') . "
"; + } + break; + case 'show_delete_catalog': + /* Stop the demo hippies */ + if (Config::get('demo_mode')) { UI::access_denied(); break; } + + $catalog = new Catalog($_REQUEST['catalog_id']); + $nexturl = Config::get('web_path') . '/admin/catalog.php?action=delete_catalog&catalog_id=' . scrub_out($_REQUEST['catalog_id']); + show_confirmation(T_('Delete Catalog'), T_('Do you really want to delete this catalog?') . " -- $catalog->name ($catalog->path)",$nexturl,1); + break; + case 'show_customize_catalog': + $catalog = new Catalog($_REQUEST['catalog_id']); + require_once Config::get('prefix') . '/templates/show_edit_catalog.inc.php'; + break; + case 'gather_album_art': + toggle_visible('ajax-loading'); + ob_end_flush(); + + $catalogs = $_REQUEST['catalogs'] ? $_REQUEST['catalogs'] : Catalog::get_catalogs(); + + // Itterate throught the catalogs and gather as needed + foreach ($catalogs as $catalog_id) { + $catalog = new Catalog($catalog_id); + require Config::get('prefix') . '/templates/show_gather_art.inc.php'; + flush(); + $catalog->get_art('',1); + } + $url = Config::get('web_path') . '/admin/catalog.php'; + $title = T_('Album Art Search Finished'); + $body = ''; + show_confirmation($title,$body,$url); + break; } // end switch /* Show the Footer */ diff --git a/admin/duplicates.php b/admin/duplicates.php index fe518bd573..fbaa29b86e 100644 --- a/admin/duplicates.php +++ b/admin/duplicates.php @@ -1,5 +1,5 @@ export('itunes'); - break; - case 'csv': - header("Content-Type: application/vnd.ms-excel"); - header("Content-Disposition: filename=\"ampache-export-$date.csv\""); - $catalog->export('csv'); - break; - } // end switch on format + switch($_REQUEST['export_format']) { + case 'itunes': + header("Content-Type: application/itunes+xml; charset=utf-8"); + header("Content-Disposition: attachment; filename=\"ampache-itunes-$date.xml\""); + $catalog->export('itunes'); + break; + case 'csv': + header("Content-Type: application/vnd.ms-excel"); + header("Content-Disposition: filename=\"ampache-export-$date.csv\""); + $catalog->export('csv'); + break; + } // end switch on format - // We don't want the footer so we're done here - exit; + // We don't want the footer so we're done here + exit; - break; - default: - require_once Config::get('prefix') . '/templates/show_export.inc.php'; - break; + break; + default: + require_once Config::get('prefix') . '/templates/show_export.inc.php'; + break; } // end switch on action UI::show_footer(); diff --git a/admin/flag.php b/admin/flag.php index bb3e64aace..fe12baa439 100644 --- a/admin/flag.php +++ b/admin/flag.php @@ -1,5 +1,5 @@ title = unhtmlentities(scrub_in($_REQUEST['title'])); - $new_song->track = unhtmlentities(scrub_in($_REQUEST['track'])); - $new_song->year = unhtmlentities(scrub_in($_REQUEST['year'])); - $new_song->comment = unhtmlentities(scrub_in($_REQUEST['comment'])); + /* Setup the vars so we can use the update_song function */ + $new_song->title = unhtmlentities(scrub_in($_REQUEST['title'])); + $new_song->track = unhtmlentities(scrub_in($_REQUEST['track'])); + $new_song->year = unhtmlentities(scrub_in($_REQUEST['year'])); + $new_song->comment = unhtmlentities(scrub_in($_REQUEST['comment'])); - /* If no change in string take Drop down */ - if (strcasecmp(stripslashes($_REQUEST['album_string']),$song->get_album_name()) == 0) { - $album = $song->get_album_name($_REQUEST['album']); - } - else { - $album = scrub_in($_REQUEST['album_string']); - } + /* If no change in string take Drop down */ + if (strcasecmp(stripslashes($_REQUEST['album_string']),$song->get_album_name()) == 0) { + $album = $song->get_album_name($_REQUEST['album']); + } + else { + $album = scrub_in($_REQUEST['album_string']); + } - if (strcasecmp(stripslashes($_REQUEST['artist_string']),$song->get_artist_name()) == 0) { - $artist = $song->get_artist_name($_REQUEST['artist']); - } - else { - $artist = scrub_in($_REQUEST['artist_string']); - } + if (strcasecmp(stripslashes($_REQUEST['artist_string']),$song->get_artist_name()) == 0) { + $artist = $song->get_artist_name($_REQUEST['artist']); + } + else { + $artist = scrub_in($_REQUEST['artist_string']); + } - /* Use the check functions to get / create ids for this info */ - $new_song->album = $catalog->check_album(unhtmlentities($album)); - $new_song->artist = $catalog->check_artist(unhtmlentities($artist)); + /* Use the check functions to get / create ids for this info */ + $new_song->album = $catalog->check_album(unhtmlentities($album)); + $new_song->artist = $catalog->check_artist(unhtmlentities($artist)); - /* Update this mofo, store an old copy for cleaning */ - $old_song = new Song(); - $old_song->artist = $song->artist; - $old_song->album = $song->album; - $song->update_song($song->id,$new_song); + /* Update this mofo, store an old copy for cleaning */ + $old_song = new Song(); + $old_song->artist = $song->artist; + $old_song->album = $song->album; + $song->update_song($song->id,$new_song); - /* Now that it's been updated clean old junk entries */ - $catalog = new Catalog(); - $cleaned = $catalog->clean_single_song($old_song); + /* Now that it's been updated clean old junk entries */ + $catalog = new Catalog(); + $cleaned = $catalog->clean_single_song($old_song); - /* Add a tagging record of this so we can fix the file */ - if ($_REQUEST['flag']) { - $flag = new Flag(); - $flag->add($song->id,'song','retag','Edited Song, auto-tag'); - } + /* Add a tagging record of this so we can fix the file */ + if ($_REQUEST['flag']) { + $flag = new Flag(); + $flag->add($song->id,'song','retag','Edited Song, auto-tag'); + } - if (isset($cleaned['artist']) || isset($cleaned['album'])) { $_SESSION['source'] = Config::get('web_path') . '/index.php'; } + if (isset($cleaned['artist']) || isset($cleaned['album'])) { $_SESSION['source'] = Config::get('web_path') . '/index.php'; } - show_confirmation(T_('Song Updated'), T_('The requested song has been updated'),$_SESSION['source']); - break; - // Show the page for editing a full album - case 'show_edit_album': + show_confirmation(T_('Song Updated'), T_('The requested song has been updated'),$_SESSION['source']); + break; + // Show the page for editing a full album + case 'show_edit_album': - $album = new Album($_REQUEST['album_id']); + $album = new Album($_REQUEST['album_id']); - require_once Config::get('prefix') . '/templates/show_edit_album.inc.php'; + require_once Config::get('prefix') . '/templates/show_edit_album.inc.php'; - break; - // Update all songs from this album - case 'edit_album': + break; + // Update all songs from this album + case 'edit_album': - // Build the needed album - $album = new Album($_REQUEST['album_id']); + // Build the needed album + $album = new Album($_REQUEST['album_id']); - // Create the needed catalog object cause we can't do - // static class methods :( - $catalog = new Catalog(); - $flag = new Flag(); + // Create the needed catalog object cause we can't do + // static class methods :( + $catalog = new Catalog(); + $flag = new Flag(); - /* Check the new Name */ - $album_id = $catalog->check_album($_REQUEST['name'],$_REQUEST['year']); + /* Check the new Name */ + $album_id = $catalog->check_album($_REQUEST['name'],$_REQUEST['year']); - $songs = $album->get_songs(); + $songs = $album->get_songs(); - foreach ($songs as $song) { - // Make that copy and change the album - $new_song = $song; - $new_song->album = $album_id; + foreach ($songs as $song) { + // Make that copy and change the album + $new_song = $song; + $new_song->album = $album_id; - $song->update_song($song->id,$new_song); + $song->update_song($song->id,$new_song); - if ($_REQUEST['flag'] == '1') { - $flag->add($song->id,'song','retag','Edited Song, auto-tag'); - } + if ($_REQUEST['flag'] == '1') { + $flag->add($song->id,'song','retag','Edited Song, auto-tag'); + } - } // end foreach songs + } // end foreach songs - // Clean out the old album - Album::gc(); + // Clean out the old album + Album::gc(); - show_confirmation(T_('Album Updated'),'',Config::get('web_path') . '/admin/index.php'); + show_confirmation(T_('Album Updated'),'',Config::get('web_path') . '/admin/index.php'); - break; - // Show the page for editing a full artist - case 'show_edit_artist': + break; + // Show the page for editing a full artist + case 'show_edit_artist': - $artist = new Artist($_REQUEST['artist_id']); + $artist = new Artist($_REQUEST['artist_id']); - require_once Config::get('prefix') . '/templates/show_edit_artist.inc.php'; + require_once Config::get('prefix') . '/templates/show_edit_artist.inc.php'; - break; - // Update all songs by this artist - case 'edit_artist': + break; + // Update all songs by this artist + case 'edit_artist': - // Build the needed artist - $artist = new Artist($_REQUEST['artist_id']); - - // Create the needed objects, a pox on PHP4 - $catalog = new Catalog(); - $flag = new Flag(); + // Build the needed artist + $artist = new Artist($_REQUEST['artist_id']); + + // Create the needed objects, a pox on PHP4 + $catalog = new Catalog(); + $flag = new Flag(); - /* Check the new Name */ - $artist_id = $catalog->check_artist($_REQUEST['name']); - - $songs = $artist->get_songs(); - - foreach ($songs as $song) { - // Make that copy and change the artist - $new_song = $song; - $new_song->artist = $artist_id; - - $song->update_song($song->id,$new_song); - - if ($_REQUEST['flag'] == '1') { - $flag->add($song->id,'song','retag','Edited Song, auto-tag'); - } - - } // end foreach songs - - // Clean out the old artist(s) - Artist::gc(); - - show_confirmation(T_('Artist Updated'),'',Config::get('web_path') . '/admin/index.php'); - - break; - /* Done by 'Select' code passes array of song ids */ - case 'mass_update': - $songs = $_REQUEST['song']; - $catalog = new Catalog(); - $object = $_REQUEST['update_field']; - $flag = new Flag(); - - /* If this is an album we need to pull the songs */ - if ($_REQUEST['type'] == 'album') { - - // Define the results array - $results = array(); - - foreach ($songs as $album_id) { - $album = new Album($album_id); - $results = array_merge($results,$album->get_song_ids()); - } // end foreach albums - - // Re-assign the variable... HACK ALERT :( - $songs = $results; - - } // is album - - /* Foreach the songs we need to update */ - foreach ($songs as $song_id) { - - $new_song = new Song($song_id); - $old_song = new Song(); - $old_song->artist = $new_song->artist; - $old_song->album = $new_song->album; - - /* Restrict which fields can be updated */ - switch ($object) { - case 'album': - $new_song->album = $catalog->check_album(unhtmlentities($_REQUEST['update_value'])); - break; - case 'artist': - $new_song->artist = $catalog->check_artist(unhtmlentities($_REQUEST['update_value'])); - break; - case 'year': - $new_song->year = intval($_REQUEST['update_value']); - break; - default: - // Rien a faire - break; - } // end switch - - /* Update this mofo, store an old copy for cleaning */ - $new_song->update_song($song_id,$new_song); - - /* Now that it's been updated clean old junk entries */ - $cleaned = $catalog->clean_single_song($old_song); - - $flag->add($song_id,'song','retag','Edited Song, auto-tag'); - - } // end foreach songs - - // Show a confirmation that this worked - show_confirmation(T_('Songs Updated'),'',return_referer()); - break; - case 'reject_flag': - $flag_id = scrub_in($_REQUEST['flag_id']); - $flag = new Flag($flag_id); - $flag->delete_flag(); - $flag->format_name(); - $url = return_referer(); - $title = T_('Flag Removed'); - $body = T_('Flag Removed from') . " " . $flag->name; - show_confirmation($title,$body,$url); - break; - case 'reject_flags': - $flags = $_REQUEST['song']; - - foreach ($flags as $flag_id) { - $flag = new Flag($flag_id); - if ($_REQUEST['update_action'] == 'reject') { - $flag->delete_flag(); - } - else { - $flag->approve(); - } - } // end foreach flags - $title = T_('Flags Updated'); - show_confirmation($title,'',return_referer()); - break; - case 'show_edit_song': - $_SESSION['source'] = return_referer(); - $song = new Song($_REQUEST['song']); - $song->fill_ext_info(); - $song->format_song(); - require_once Config::get('prefix') . '/templates/show_edit_song.inc.php'; - break; - case 'disable': - $song_obj = new Song(); - // If we pass just one, make it still work - if (!is_array($_REQUEST['song_ids'])) { $song_obj->update_enabled(0,$_REQUEST['song_ids']); } - else { - foreach ($_REQUEST['song_ids'] as $song_id) { - $song_obj->update_enabled(0,$song_id); - } // end foreach - } // end else - show_confirmation(T_('Songs Disabled'), T_('The requested song(s) have been disabled'),return_referer()); - break; - case 'enabled': - $song_obj = new Song(); - // If we pass just one, make it still work - if (!is_array($_REQUEST['song_ids'])) { $song_obj->update_enabled(1,$_REQUEST['song_ids']); } - else { - foreach ($_REQUEST['song_ids'] as $song_id) { - $song_obj->update_enabled(1,$song_id); - } // end foreach - } // end else - show_confirmation(T_('Songs Enabled'), T_('The requested song(s) have been enabled'),return_referer()); - break; - case 'show_disabled': - $disabled = Flag::get_disabled(); - $browse = new Browse(); - $browse->set_type('song'); - $browse->set_static_content(true); - $browse->save_objects($disabled); - $browse->show_objects($disabled); - $browse->store(); - break; - default: - case 'show_flagged': - $flagged = Flag::get_all(); - Flag::build_cache($flagged); - $browse = new Browse(); - $browse->set_type('flagged'); - $browse->set_static_content(true); - $browse->save_objects($flagged); - $browse->show_objects($flagged); - $browse->store(); - break; + /* Check the new Name */ + $artist_id = $catalog->check_artist($_REQUEST['name']); + + $songs = $artist->get_songs(); + + foreach ($songs as $song) { + // Make that copy and change the artist + $new_song = $song; + $new_song->artist = $artist_id; + + $song->update_song($song->id,$new_song); + + if ($_REQUEST['flag'] == '1') { + $flag->add($song->id,'song','retag','Edited Song, auto-tag'); + } + + } // end foreach songs + + // Clean out the old artist(s) + Artist::gc(); + + show_confirmation(T_('Artist Updated'),'',Config::get('web_path') . '/admin/index.php'); + + break; + /* Done by 'Select' code passes array of song ids */ + case 'mass_update': + $songs = $_REQUEST['song']; + $catalog = new Catalog(); + $object = $_REQUEST['update_field']; + $flag = new Flag(); + + /* If this is an album we need to pull the songs */ + if ($_REQUEST['type'] == 'album') { + + // Define the results array + $results = array(); + + foreach ($songs as $album_id) { + $album = new Album($album_id); + $results = array_merge($results,$album->get_song_ids()); + } // end foreach albums + + // Re-assign the variable... HACK ALERT :( + $songs = $results; + + } // is album + + /* Foreach the songs we need to update */ + foreach ($songs as $song_id) { + + $new_song = new Song($song_id); + $old_song = new Song(); + $old_song->artist = $new_song->artist; + $old_song->album = $new_song->album; + + /* Restrict which fields can be updated */ + switch ($object) { + case 'album': + $new_song->album = $catalog->check_album(unhtmlentities($_REQUEST['update_value'])); + break; + case 'artist': + $new_song->artist = $catalog->check_artist(unhtmlentities($_REQUEST['update_value'])); + break; + case 'year': + $new_song->year = intval($_REQUEST['update_value']); + break; + default: + // Rien a faire + break; + } // end switch + + /* Update this mofo, store an old copy for cleaning */ + $new_song->update_song($song_id,$new_song); + + /* Now that it's been updated clean old junk entries */ + $cleaned = $catalog->clean_single_song($old_song); + + $flag->add($song_id,'song','retag','Edited Song, auto-tag'); + + } // end foreach songs + + // Show a confirmation that this worked + show_confirmation(T_('Songs Updated'),'',return_referer()); + break; + case 'reject_flag': + $flag_id = scrub_in($_REQUEST['flag_id']); + $flag = new Flag($flag_id); + $flag->delete_flag(); + $flag->format_name(); + $url = return_referer(); + $title = T_('Flag Removed'); + $body = T_('Flag Removed from') . " " . $flag->name; + show_confirmation($title,$body,$url); + break; + case 'reject_flags': + $flags = $_REQUEST['song']; + + foreach ($flags as $flag_id) { + $flag = new Flag($flag_id); + if ($_REQUEST['update_action'] == 'reject') { + $flag->delete_flag(); + } + else { + $flag->approve(); + } + } // end foreach flags + $title = T_('Flags Updated'); + show_confirmation($title,'',return_referer()); + break; + case 'show_edit_song': + $_SESSION['source'] = return_referer(); + $song = new Song($_REQUEST['song']); + $song->fill_ext_info(); + $song->format_song(); + require_once Config::get('prefix') . '/templates/show_edit_song.inc.php'; + break; + case 'disable': + $song_obj = new Song(); + // If we pass just one, make it still work + if (!is_array($_REQUEST['song_ids'])) { $song_obj->update_enabled(0,$_REQUEST['song_ids']); } + else { + foreach ($_REQUEST['song_ids'] as $song_id) { + $song_obj->update_enabled(0,$song_id); + } // end foreach + } // end else + show_confirmation(T_('Songs Disabled'), T_('The requested song(s) have been disabled'),return_referer()); + break; + case 'enabled': + $song_obj = new Song(); + // If we pass just one, make it still work + if (!is_array($_REQUEST['song_ids'])) { $song_obj->update_enabled(1,$_REQUEST['song_ids']); } + else { + foreach ($_REQUEST['song_ids'] as $song_id) { + $song_obj->update_enabled(1,$song_id); + } // end foreach + } // end else + show_confirmation(T_('Songs Enabled'), T_('The requested song(s) have been enabled'),return_referer()); + break; + case 'show_disabled': + $disabled = Flag::get_disabled(); + $browse = new Browse(); + $browse->set_type('song'); + $browse->set_static_content(true); + $browse->save_objects($disabled); + $browse->show_objects($disabled); + $browse->store(); + break; + default: + case 'show_flagged': + $flagged = Flag::get_all(); + Flag::build_cache($flagged); + $browse = new Browse(); + $browse->set_type('flagged'); + $browse->set_static_content(true); + $browse->save_objects($flagged); + $browse->show_objects($flagged); + $browse->store(); + break; } // end switch UI::show_footer(); diff --git a/admin/index.php b/admin/index.php index e79e28ace1..860033264b 100644 --- a/admin/index.php +++ b/admin/index.php @@ -1,5 +1,5 @@ set_type('catalog'); - $browse->set_static_content(true); - $browse->save_objects($catalog_ids); - $browse->show_objects($catalog_ids); - $browse->store(); - break; + default: + // Show Catalogs + $catalog_ids = Catalog::get_catalogs(); + $browse = new Browse(); + $browse->set_type('catalog'); + $browse->set_static_content(true); + $browse->save_objects($catalog_ids); + $browse->show_objects($catalog_ids); + $browse->store(); + break; } UI::show_footer(); diff --git a/admin/mail.php b/admin/mail.php index 6ed43fd828..b5f9c8025f 100644 --- a/admin/mail.php +++ b/admin/mail.php @@ -1,5 +1,5 @@ subject = $_REQUEST['subject']; - $mailer->message = $_REQUEST['message']; + // Set the vars on the object + $mailer->subject = $_REQUEST['subject']; + $mailer->message = $_REQUEST['message']; - if ($_REQUEST['from'] == 'system') { - $mailer->set_default_sender(); - } - else { - $mailer->sender = $GLOBALS['user']->email; - $mailer->sender_name = $GLOBALS['user']->fullname; - } + if ($_REQUEST['from'] == 'system') { + $mailer->set_default_sender(); + } + else { + $mailer->sender = $GLOBALS['user']->email; + $mailer->sender_name = $GLOBALS['user']->fullname; + } - if($mailer->send_to_group($_REQUEST['to'])) { - $title = T_('E-mail Sent'); - $body = T_('Your E-mail was successfully sent.'); - } - else { - $title = T_('E-mail Not Sent'); - $body = T_('Your E-mail was not sent.'); - } - $url = Config::get('web_path') . '/admin/mail.php'; - show_confirmation($title,$body,$url); + if($mailer->send_to_group($_REQUEST['to'])) { + $title = T_('E-mail Sent'); + $body = T_('Your E-mail was successfully sent.'); + } + else { + $title = T_('E-mail Not Sent'); + $body = T_('Your E-mail was not sent.'); + } + $url = Config::get('web_path') . '/admin/mail.php'; + show_confirmation($title,$body,$url); - break; - default: - require_once Config::get('prefix') . '/templates/show_mail_users.inc.php'; - break; + break; + default: + require_once Config::get('prefix') . '/templates/show_mail_users.inc.php'; + break; } // end switch UI::show_footer(); diff --git a/admin/modules.php b/admin/modules.php index 33ec00e656..382f326aa8 100644 --- a/admin/modules.php +++ b/admin/modules.php @@ -1,5 +1,5 @@ has_access(100)) { - UI::access_denied(); - exit(); + UI::access_denied(); + exit(); } @@ -32,125 +32,125 @@ UI::show_header(); switch ($_REQUEST['action']) { - case 'install_localplay': - $localplay = new Localplay($_REQUEST['type']); - if (!$localplay->player_loaded()) { - Error::add('general', T_('Install Failed, Controller Error')); - Error::display('general'); - break; - } - // Install it! - $localplay->install(); + case 'install_localplay': + $localplay = new Localplay($_REQUEST['type']); + if (!$localplay->player_loaded()) { + Error::add('general', T_('Install Failed, Controller Error')); + Error::display('general'); + break; + } + // Install it! + $localplay->install(); - // Go ahead and enable Localplay (Admin->System) as we assume they want to do that - // if they are enabling this - Preference::update('allow_localplay_playback','-1','1'); - Preference::update('localplay_level',$GLOBALS['user']->id,'100'); - Preference::update('localplay_controller',$GLOBALS['user']->id,$localplay->type); + // Go ahead and enable Localplay (Admin->System) as we assume they want to do that + // if they are enabling this + Preference::update('allow_localplay_playback','-1','1'); + Preference::update('localplay_level',$GLOBALS['user']->id,'100'); + Preference::update('localplay_controller',$GLOBALS['user']->id,$localplay->type); - header("Location:" . Config::get('web_path') . '/admin/modules.php?action=show_localplay'); - break; - case 'confirm_uninstall_localplay': - $type = scrub_in($_REQUEST['type']); - $url = Config::get('web_path') . '/admin/modules.php?action=uninstall_localplay&type=' . $type; - $title = T_('Are you sure you want to remove this plugin?'); - $body = ''; - show_confirmation($title,$body,$url,1); - break; - case 'uninstall_localplay': - $type = scrub_in($_REQUEST['type']); + header("Location:" . Config::get('web_path') . '/admin/modules.php?action=show_localplay'); + break; + case 'confirm_uninstall_localplay': + $type = scrub_in($_REQUEST['type']); + $url = Config::get('web_path') . '/admin/modules.php?action=uninstall_localplay&type=' . $type; + $title = T_('Are you sure you want to remove this plugin?'); + $body = ''; + show_confirmation($title,$body,$url,1); + break; + case 'uninstall_localplay': + $type = scrub_in($_REQUEST['type']); - $localplay = new Localplay($type); - $localplay->uninstall(); + $localplay = new Localplay($type); + $localplay->uninstall(); - /* Show Confirmation */ - $url = Config::get('web_path') . '/admin/modules.php?action=show_localplay'; - $title = T_('Plugin Deactivated'); - $body = ''; - show_confirmation($title,$body,$url); - break; - case 'install_plugin': - /* Verify that this plugin exists */ - $plugins = Plugin::get_plugins(); - if (!array_key_exists($_REQUEST['plugin'],$plugins)) { - debug_event('plugins','Error: Invalid Plugin: ' . $_REQUEST['plugin'] . ' selected','1'); - break; - } - $plugin = new Plugin($_REQUEST['plugin']); - if (!$plugin->install()) { - debug_event('plugins','Error: Plugin Install Failed, ' . $_REQUEST['plugin'],'1'); - $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; - $title = T_('Unable to Install Plugin'); - $body = ''; - show_confirmation($title,$body,$url); - break; - } + /* Show Confirmation */ + $url = Config::get('web_path') . '/admin/modules.php?action=show_localplay'; + $title = T_('Plugin Deactivated'); + $body = ''; + show_confirmation($title,$body,$url); + break; + case 'install_plugin': + /* Verify that this plugin exists */ + $plugins = Plugin::get_plugins(); + if (!array_key_exists($_REQUEST['plugin'],$plugins)) { + debug_event('plugins','Error: Invalid Plugin: ' . $_REQUEST['plugin'] . ' selected','1'); + break; + } + $plugin = new Plugin($_REQUEST['plugin']); + if (!$plugin->install()) { + debug_event('plugins','Error: Plugin Install Failed, ' . $_REQUEST['plugin'],'1'); + $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; + $title = T_('Unable to Install Plugin'); + $body = ''; + show_confirmation($title,$body,$url); + break; + } - // Don't trust the plugin to this stuff - User::rebuild_all_preferences(); + // Don't trust the plugin to this stuff + User::rebuild_all_preferences(); - /* Show Confirmation */ - $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; - $title = T_('Plugin Activated'); - $body = ''; - show_confirmation($title,$body,$url); - break; - case 'confirm_uninstall_plugin': - $plugin = scrub_in($_REQUEST['plugin']); - $url = Config::get('web_path') . '/admin/modules.php?action=uninstall_plugin&plugin=' . $plugin; - $title = T_('Are you sure you want to remove this plugin?'); - $body = ''; - show_confirmation($title,$body,$url,1); - break; - case 'uninstall_plugin': - /* Verify that this plugin exists */ - $plugins = Plugin::get_plugins(); - if (!array_key_exists($_REQUEST['plugin'],$plugins)) { - debug_event('plugins','Error: Invalid Plugin: ' . $_REQUEST['plugin'] . ' selected','1'); - break; - } - $plugin = new Plugin($_REQUEST['plugin']); - $plugin->uninstall(); + /* Show Confirmation */ + $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; + $title = T_('Plugin Activated'); + $body = ''; + show_confirmation($title,$body,$url); + break; + case 'confirm_uninstall_plugin': + $plugin = scrub_in($_REQUEST['plugin']); + $url = Config::get('web_path') . '/admin/modules.php?action=uninstall_plugin&plugin=' . $plugin; + $title = T_('Are you sure you want to remove this plugin?'); + $body = ''; + show_confirmation($title,$body,$url,1); + break; + case 'uninstall_plugin': + /* Verify that this plugin exists */ + $plugins = Plugin::get_plugins(); + if (!array_key_exists($_REQUEST['plugin'],$plugins)) { + debug_event('plugins','Error: Invalid Plugin: ' . $_REQUEST['plugin'] . ' selected','1'); + break; + } + $plugin = new Plugin($_REQUEST['plugin']); + $plugin->uninstall(); - // Don't trust the plugin to do it - User::rebuild_all_preferences(); + // Don't trust the plugin to do it + User::rebuild_all_preferences(); - /* Show Confirmation */ - $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; - $title = T_('Plugin Deactivated'); - $body = ''; - show_confirmation($title,$body,$url); - break; - case 'upgrade_plugin': - /* Verify that this plugin exists */ - $plugins = Plugin::get_plugins(); - if (!array_key_exists($_REQUEST['plugin'],$plugins)) { - debug_event('plugins','Error: Invalid Plugin: ' . $_REQUEST['plugin'] . ' selected','1'); - break; - } - $plugin = new Plugin($_REQUEST['plugin']); - $plugin->upgrade(); - User::rebuild_all_preferences(); - $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; - $title = T_('Plugin Upgraded'); - $body = ''; - show_confirmation($title, $body, $url); - break; - case 'show_plugins': - $plugins = Plugin::get_plugins(); - UI::show_box_top(T_('Plugins'), 'box box_localplay_plugins'); - require_once Config::get('prefix') . '/templates/show_plugins.inc.php'; - UI::show_box_bottom(); - break; - case 'show_localplay': - $controllers = Localplay::get_controllers(); - UI::show_box_top(T_('Localplay Controllers'), 'box box_localplay_controllers'); - require_once Config::get('prefix') . '/templates/show_localplay_controllers.inc.php'; - UI::show_box_bottom(); - break; - default: - // Rien a faire - break; + /* Show Confirmation */ + $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; + $title = T_('Plugin Deactivated'); + $body = ''; + show_confirmation($title,$body,$url); + break; + case 'upgrade_plugin': + /* Verify that this plugin exists */ + $plugins = Plugin::get_plugins(); + if (!array_key_exists($_REQUEST['plugin'],$plugins)) { + debug_event('plugins','Error: Invalid Plugin: ' . $_REQUEST['plugin'] . ' selected','1'); + break; + } + $plugin = new Plugin($_REQUEST['plugin']); + $plugin->upgrade(); + User::rebuild_all_preferences(); + $url = Config::get('web_path') . '/admin/modules.php?action=show_plugins'; + $title = T_('Plugin Upgraded'); + $body = ''; + show_confirmation($title, $body, $url); + break; + case 'show_plugins': + $plugins = Plugin::get_plugins(); + UI::show_box_top(T_('Plugins'), 'box box_localplay_plugins'); + require_once Config::get('prefix') . '/templates/show_plugins.inc.php'; + UI::show_box_bottom(); + break; + case 'show_localplay': + $controllers = Localplay::get_controllers(); + UI::show_box_top(T_('Localplay Controllers'), 'box box_localplay_controllers'); + require_once Config::get('prefix') . '/templates/show_localplay_controllers.inc.php'; + UI::show_box_bottom(); + break; + default: + // Rien a faire + break; } // end switch UI::show_footer(); diff --git a/admin/shout.php b/admin/shout.php index ca6933ac1a..d34160b3ce 100644 --- a/admin/shout.php +++ b/admin/shout.php @@ -1,5 +1,5 @@ object_type,$shout->object_id); - $object->format(); - $client = new User($shout->user); - $client->format(); - require_once Config::get('prefix') . '/templates/show_edit_shout.inc.php'; - break; - case 'delete': - $shout_id = Shoutbox::delete($_REQUEST['shout_id']); - show_confirmation(T_('Shoutbox Post Deleted'),'',Config::get('web_path').'/admin/shout.php'); - break; - default: - $browse = new Browse(); - $browse->set_type('shoutbox'); - $browse->set_simple_browse(true); - $shoutbox_ids = $browse->get_objects(); - $browse->show_objects($shoutbox_ids); - $browse->store(); - break; + case 'edit_shout': + $shout_id = $_POST['shout_id']; + $update = Shoutbox::update($_POST); + show_confirmation(T_('Shoutbox Post Updated'),'',Config::get('web_path').'/admin/shout.php'); + break; + case 'show_edit': + $shout = new Shoutbox($_REQUEST['shout_id']); + $object = Shoutbox::get_object($shout->object_type,$shout->object_id); + $object->format(); + $client = new User($shout->user); + $client->format(); + require_once Config::get('prefix') . '/templates/show_edit_shout.inc.php'; + break; + case 'delete': + $shout_id = Shoutbox::delete($_REQUEST['shout_id']); + show_confirmation(T_('Shoutbox Post Deleted'),'',Config::get('web_path').'/admin/shout.php'); + break; + default: + $browse = new Browse(); + $browse->set_type('shoutbox'); + $browse->set_simple_browse(true); + $shoutbox_ids = $browse->get_objects(); + $browse->show_objects($shoutbox_ids); + $browse->store(); + break; } // end switch on action UI::show_footer(); diff --git a/admin/system.php b/admin/system.php index e98f592d33..7b12385d44 100644 --- a/admin/system.php +++ b/admin/system.php @@ -1,5 +1,5 @@ downloadHeaders('ampache.cfg.php','text/plain',false,filesize(Config::get('prefix') . '/config/ampache.cfg.php.dist')); - echo $final; - exit; - break; - case 'reset_db_charset': - Dba::reset_db_charset(); - show_confirmation(T_('Database Charset Updated'), T_('Your Database and associated tables have been updated to match your currently configured charset'), Config::get('web_path').'/admin/system.php?action=show_debug'); - break; - case 'show_debug': - $configuration = Config::get_all(); - require_once Config::get('prefix') . '/templates/show_debug.inc.php'; - break; - default: - // Rien a faire - break; + /* This re-generates the config file comparing + * /config/ampache.cfg to .cfg.dist + */ + case 'generate_config': + ob_end_clean(); + $current = parse_ini_file(Config::get('prefix') . '/config/ampache.cfg.php'); + $final = generate_config($current); + $browser = new Horde_Browser(); + $browser->downloadHeaders('ampache.cfg.php','text/plain',false,filesize(Config::get('prefix') . '/config/ampache.cfg.php.dist')); + echo $final; + exit; + break; + case 'reset_db_charset': + Dba::reset_db_charset(); + show_confirmation(T_('Database Charset Updated'), T_('Your Database and associated tables have been updated to match your currently configured charset'), Config::get('web_path').'/admin/system.php?action=show_debug'); + break; + case 'show_debug': + $configuration = Config::get_all(); + require_once Config::get('prefix') . '/templates/show_debug.inc.php'; + break; + default: + // Rien a faire + break; } // end switch UI::show_footer(); diff --git a/admin/users.php b/admin/users.php index 84d19938ca..e8aecb767f 100644 --- a/admin/users.php +++ b/admin/users.php @@ -1,5 +1,5 @@ access) { - $client->update_access($access); - } - if ($email != $client->email) { - $client->update_email($email); - } - if ($username != $client->username) { - $client->update_username($username); - } - if ($fullname != $client->fullname) { - $client->update_fullname($fullname); - } - if ($pass1 == $pass2 && strlen($pass1)) { - $client->update_password($pass1); - } - - show_confirmation(T_('User Updated'), $client->fullname . "(" . $client->username . ")" . T_('updated'), Config::get('web_path'). '/admin/users.php'); - break; - case 'add_user': - if (Config::get('demo_mode')) { break; } - - if (!Core::form_verify('add_user','post')) { - UI::access_denied(); - exit; - } - - $username = scrub_in($_POST['username']); - $fullname = scrub_in($_POST['fullname']); - $email = scrub_in($_POST['email']); - $access = scrub_in($_POST['access']); - $pass1 = $_POST['password_1']; - $pass2 = $_POST['password_2']; - - if ($pass1 !== $pass2 || !strlen($pass1)) { - Error::add('password', T_("Error Passwords don't match")); - } - - if (empty($username)) { - Error::add('username', T_('Error Username Required')); - } - - /* make sure the username doesn't already exist */ - if (!User::check_username($username)) { - Error::add('username', T_('Error Username already exists')); - } - - if (!Error::occurred()) { - /* Attempt to create the user */ - $user_id = User::create($username, $fullname, $email, $pass1, $access); - if (!$user_id) { - Error::add('general', T_("Error: Insert Failed")); - } - - } // if no errors - else { - $_REQUEST['action'] = 'show_add_user'; - break; - } - if ($access == 5){ $access = T_('Guest');} - elseif ($access == 25){ $access = T_('User');} - elseif ($access == 100){ $access = T_('Admin');} - - /* HINT: %1 Username, %2 Access num */ - show_confirmation(T_('New User Added'),sprintf(T_('%1$s has been created with an access level of %2$s'), $username, $access), Config::get('web_path').'/admin/users.php'); - break; - case 'enable': - $client = new User($_REQUEST['user_id']); - $client->enable(); - show_confirmation(T_('User Enabled'),$client->fullname . ' (' . $client->username . ')', Config::get('web_path'). '/admin/users.php'); - break; - case 'disable': - $client = new User($_REQUEST['user_id']); - if ($client->disable()) { - show_confirmation(T_('User Disabled'),$client->fullname . ' (' . $client->username . ')', Config::get('web_path'). '/admin/users.php'); - } - else { - show_confirmation(T_('Error'), T_('Unable to Disabled last Administrator'), Config::get('web_path').'/admin/users.php'); - } - break; - case 'show_edit': - if (Config::get('demo_mode')) { break; } - $client = new User($_REQUEST['user_id']); - require_once Config::get('prefix') . '/templates/show_edit_user.inc.php'; - break; - case 'confirm_delete': - if (Config::get('demo_mode')) { break; } - if (!Core::form_verify('delete_user')) { - UI::access_denied(); - exit; - } - $client = new User($_REQUEST['user_id']); - if ($client->delete()) { - show_confirmation(T_('User Deleted'), sprintf(T_('%s has been Deleted'), $client->username), Config::get('web_path'). "/admin/users.php"); - } - else { - show_confirmation(T_('Delete Error'), T_("Unable to delete last Admin User"), Config::get('web_path')."/admin/users.php"); - } - break; - case 'delete': - if (Config::get('demo_mode')) { break; } - $client = new User($_REQUEST['user_id']); - show_confirmation(T_('Deletion Request'), - sprintf(T_('Are you sure you want to permanently delete %s?'), $client->fullname), - Config::get('web_path')."/admin/users.php?action=confirm_delete&user_id=" . $_REQUEST['user_id'],1,'delete_user'); - break; - /* Show IP History for the Specified User */ - case 'show_ip_history': - /* get the user and their history */ - $working_user = new User($_REQUEST['user_id']); - - if (!isset($_REQUEST['all'])){ - $history = $working_user->get_ip_history(0,1); - } - else { - $history = $working_user->get_ip_history(); - } - require Config::get('prefix') . '/templates/show_ip_history.inc.php'; - break; - case 'show_add_user': - if (Config::get('demo_mode')) { break; } - require_once Config::get('prefix') . '/templates/show_add_user.inc.php'; - break; - case 'show_preferences': - $client = new User($_REQUEST['user_id']); - $preferences = Preference::get_all($client->id); - require_once Config::get('prefix') . '/templates/show_user_preferences.inc.php'; - break; - default: - $browse = new Browse(); - $browse->reset_filters(); - $browse->set_type('user'); - $browse->set_simple_browse(1); - $browse->set_sort('name','ASC'); - $user_ids = $browse->get_objects(); - $browse->show_objects($user_ids); - $browse->store(); - break; + case 'update_user': + if (Config::get('demo_mode')) { break; } + + if (!Core::form_verify('edit_user','post')) { + UI::access_denied(); + exit; + } + + /* Clean up the variables */ + $user_id = scrub_in($_POST['user_id']); + $username = scrub_in($_POST['username']); + $fullname = scrub_in($_POST['fullname']); + $email = scrub_in($_POST['email']); + $access = scrub_in($_POST['access']); + $pass1 = $_POST['password_1']; + $pass2 = $_POST['password_2']; + + /* Setup the temp user */ + $client = new User($user_id); + + /* Verify Input */ + if (empty($username)) { + Error::add('username', T_("Error Username Required")); + } + if ($pass1 !== $pass2 && !empty($pass1)) { + Error::add('password', T_("Error Passwords don't match")); + } + + /* If we've got an error then break! */ + if (Error::occurred()) { + $_REQUEST['action'] = 'show_edit'; + break; + } // if we've had an oops! + + if ($access != $client->access) { + $client->update_access($access); + } + if ($email != $client->email) { + $client->update_email($email); + } + if ($username != $client->username) { + $client->update_username($username); + } + if ($fullname != $client->fullname) { + $client->update_fullname($fullname); + } + if ($pass1 == $pass2 && strlen($pass1)) { + $client->update_password($pass1); + } + + show_confirmation(T_('User Updated'), $client->fullname . "(" . $client->username . ")" . T_('updated'), Config::get('web_path'). '/admin/users.php'); + break; + case 'add_user': + if (Config::get('demo_mode')) { break; } + + if (!Core::form_verify('add_user','post')) { + UI::access_denied(); + exit; + } + + $username = scrub_in($_POST['username']); + $fullname = scrub_in($_POST['fullname']); + $email = scrub_in($_POST['email']); + $access = scrub_in($_POST['access']); + $pass1 = $_POST['password_1']; + $pass2 = $_POST['password_2']; + + if ($pass1 !== $pass2 || !strlen($pass1)) { + Error::add('password', T_("Error Passwords don't match")); + } + + if (empty($username)) { + Error::add('username', T_('Error Username Required')); + } + + /* make sure the username doesn't already exist */ + if (!User::check_username($username)) { + Error::add('username', T_('Error Username already exists')); + } + + if (!Error::occurred()) { + /* Attempt to create the user */ + $user_id = User::create($username, $fullname, $email, $pass1, $access); + if (!$user_id) { + Error::add('general', T_("Error: Insert Failed")); + } + + } // if no errors + else { + $_REQUEST['action'] = 'show_add_user'; + break; + } + if ($access == 5){ $access = T_('Guest');} + elseif ($access == 25){ $access = T_('User');} + elseif ($access == 100){ $access = T_('Admin');} + + /* HINT: %1 Username, %2 Access num */ + show_confirmation(T_('New User Added'),sprintf(T_('%1$s has been created with an access level of %2$s'), $username, $access), Config::get('web_path').'/admin/users.php'); + break; + case 'enable': + $client = new User($_REQUEST['user_id']); + $client->enable(); + show_confirmation(T_('User Enabled'),$client->fullname . ' (' . $client->username . ')', Config::get('web_path'). '/admin/users.php'); + break; + case 'disable': + $client = new User($_REQUEST['user_id']); + if ($client->disable()) { + show_confirmation(T_('User Disabled'),$client->fullname . ' (' . $client->username . ')', Config::get('web_path'). '/admin/users.php'); + } + else { + show_confirmation(T_('Error'), T_('Unable to Disabled last Administrator'), Config::get('web_path').'/admin/users.php'); + } + break; + case 'show_edit': + if (Config::get('demo_mode')) { break; } + $client = new User($_REQUEST['user_id']); + require_once Config::get('prefix') . '/templates/show_edit_user.inc.php'; + break; + case 'confirm_delete': + if (Config::get('demo_mode')) { break; } + if (!Core::form_verify('delete_user')) { + UI::access_denied(); + exit; + } + $client = new User($_REQUEST['user_id']); + if ($client->delete()) { + show_confirmation(T_('User Deleted'), sprintf(T_('%s has been Deleted'), $client->username), Config::get('web_path'). "/admin/users.php"); + } + else { + show_confirmation(T_('Delete Error'), T_("Unable to delete last Admin User"), Config::get('web_path')."/admin/users.php"); + } + break; + case 'delete': + if (Config::get('demo_mode')) { break; } + $client = new User($_REQUEST['user_id']); + show_confirmation(T_('Deletion Request'), + sprintf(T_('Are you sure you want to permanently delete %s?'), $client->fullname), + Config::get('web_path')."/admin/users.php?action=confirm_delete&user_id=" . $_REQUEST['user_id'],1,'delete_user'); + break; + /* Show IP History for the Specified User */ + case 'show_ip_history': + /* get the user and their history */ + $working_user = new User($_REQUEST['user_id']); + + if (!isset($_REQUEST['all'])){ + $history = $working_user->get_ip_history(0,1); + } + else { + $history = $working_user->get_ip_history(); + } + require Config::get('prefix') . '/templates/show_ip_history.inc.php'; + break; + case 'show_add_user': + if (Config::get('demo_mode')) { break; } + require_once Config::get('prefix') . '/templates/show_add_user.inc.php'; + break; + case 'show_preferences': + $client = new User($_REQUEST['user_id']); + $preferences = Preference::get_all($client->id); + require_once Config::get('prefix') . '/templates/show_user_preferences.inc.php'; + break; + default: + $browse = new Browse(); + $browse->reset_filters(); + $browse->set_type('user'); + $browse->set_simple_browse(1); + $browse->set_sort('name','ASC'); + $user_ids = $browse->get_objects(); + $browse->show_objects($user_ids); + $browse->store(); + break; } // end switch on action /* Show the footer */ diff --git a/albums.php b/albums.php index f7413ac968..0c0d157853 100644 --- a/albums.php +++ b/albums.php @@ -1,5 +1,5 @@ has_access('75')) { UI::access_denied(); } - $art = new Art($_GET['album_id'],'album'); - $art->reset(); - show_confirmation(T_('Album Art Cleared'), T_('Album Art information has been removed from the database'),"/albums.php?action=show&album=" . $art->uid); - break; - // Upload album art - case 'upload_art': - - // we didn't find anything - if (empty($_FILES['file']['tmp_name'])) { - show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id); - break; - } - - $album = new Album($_REQUEST['album_id']); - // Pull the image information - $data = array('file'=>$_FILES['file']['tmp_name']); - $image_data = Art::get_from_source($data, 'album'); - - // If we got something back insert it - if ($image_data) { - $art = new Art($album->id,'album'); - $art->insert($image_data,$_FILES['file']['type']); - show_confirmation(T_('Album Art Inserted'),'',"/albums.php?action=show&album=" . $album->id); - } - // Else it failed - else { - show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id); - } - - break; - case 'find_art': - // If not a user then kick em out - if (!Access::check('interface','25')) { UI::access_denied(); exit; } - - // get the Album information - $album = new Album($_GET['album_id']); - $album->format(); - $art = new Art($album->id,'album'); - $images = array(); - $cover_url = array(); - - // If we've got an upload ignore the rest and just insert it - if (!empty($_FILES['file']['tmp_name'])) { - $path_info = pathinfo($_FILES['file']['name']); - $upload['file'] = $_FILES['file']['tmp_name']; - $upload['mime'] = 'image/' . $path_info['extension']; - $image_data = Art::get_from_source($upload, 'album'); - - if ($image_data) { - $art->insert($image_data,$upload['0']['mime']); - show_confirmation(T_('Album Art Inserted'),'',"/albums.php?action=show&album=" . $_REQUEST['album_id']); - break; - - } // if image data - - } // if it's an upload - - // Build the options for our search - if (isset($_REQUEST['artist_name'])) { - $artist = scrub_in($_REQUEST['artist_name']); - } - elseif ($album->artist_count == '1') { - $artist = $album->f_artist_name; - } - if (isset($_REQUEST['album_name'])) { - $album_name = scrub_in($_REQUEST['album_name']); - } - else { - $album_name = $album->full_name; - } - - $options['artist'] = $artist; - $options['album_name'] = $album_name; - $options['keyword'] = $artist . " " . $album_name; - - // Attempt to find the art. - $images = $art->gather($options,'6'); - - if (!empty($_REQUEST['cover'])) { - $path_info = pathinfo($_REQUEST['cover']); - $cover_url[0]['url'] = scrub_in($_REQUEST['cover']); - $cover_url[0]['mime'] = 'image/' . $path_info['extension']; - } - $images = array_merge($cover_url,$images); - - // If we've found anything then go for it! - if (count($images)) { - // We don't want to store raw's in here so we need to strip them out into a seperate array - foreach ($images as $index=>$image) { - if ($image['raw']) { - unset($images[$index]['raw']); - } - } // end foreach - // Store the results for further use - $_SESSION['form']['images'] = $images; - require_once Config::get('prefix') . '/templates/show_album_art.inc.php'; - } - // Else nothing - else { - show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id); - } - - $albumname = $album->name; - $artistname = $artist; - - // Remember the last typed entry, if there was one - if (!empty($_REQUEST['album_name'])) { $albumname = scrub_in($_REQUEST['album_name']); } - if (!empty($_REQUEST['artist_name'])) { $artistname = scrub_in($_REQUEST['artist_name']); } - - require_once Config::get('prefix') . '/templates/show_get_albumart.inc.php'; - - break; - case 'select_art': - - /* Check to see if we have the image url still */ - $image_id = $_REQUEST['image']; - $album_id = $_REQUEST['album_id']; - $art = new Art($album_id,'album'); - - $image = Art::get_from_source($_SESSION['form']['images'][$image_id], 'album'); - $mime = $_SESSION['form']['images'][$image_id]['mime']; - - $art->insert($image,$mime); - - header("Location:" . Config::get('web_path') . "/albums.php?action=show&album=" . $art->uid); - break; - case 'update_from_tags': - // Make sure they are a 'power' user at least - if (!Access::check('interface','75')) { - UI::access_denied(); - exit; - } - - $type = 'album'; - $object_id = intval($_REQUEST['album_id']); - $target_url = Config::get('web_path') . '/albums.php?action=show&album=' . $object_id; - require_once Config::get('prefix') . '/templates/show_update_items.inc.php'; - break; - // Browse by Album - default: - case 'show': - $album = new Album($_REQUEST['album']); - $album->format(); - require Config::get('prefix') . '/templates/show_album.inc.php'; - - break; + case 'clear_art': + if (!$GLOBALS['user']->has_access('75')) { UI::access_denied(); } + $art = new Art($_GET['album_id'],'album'); + $art->reset(); + show_confirmation(T_('Album Art Cleared'), T_('Album Art information has been removed from the database'),"/albums.php?action=show&album=" . $art->uid); + break; + // Upload album art + case 'upload_art': + + // we didn't find anything + if (empty($_FILES['file']['tmp_name'])) { + show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id); + break; + } + + $album = new Album($_REQUEST['album_id']); + // Pull the image information + $data = array('file'=>$_FILES['file']['tmp_name']); + $image_data = Art::get_from_source($data, 'album'); + + // If we got something back insert it + if ($image_data) { + $art = new Art($album->id,'album'); + $art->insert($image_data,$_FILES['file']['type']); + show_confirmation(T_('Album Art Inserted'),'',"/albums.php?action=show&album=" . $album->id); + } + // Else it failed + else { + show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id); + } + + break; + case 'find_art': + // If not a user then kick em out + if (!Access::check('interface','25')) { UI::access_denied(); exit; } + + // get the Album information + $album = new Album($_GET['album_id']); + $album->format(); + $art = new Art($album->id,'album'); + $images = array(); + $cover_url = array(); + + // If we've got an upload ignore the rest and just insert it + if (!empty($_FILES['file']['tmp_name'])) { + $path_info = pathinfo($_FILES['file']['name']); + $upload['file'] = $_FILES['file']['tmp_name']; + $upload['mime'] = 'image/' . $path_info['extension']; + $image_data = Art::get_from_source($upload, 'album'); + + if ($image_data) { + $art->insert($image_data,$upload['0']['mime']); + show_confirmation(T_('Album Art Inserted'),'',"/albums.php?action=show&album=" . $_REQUEST['album_id']); + break; + + } // if image data + + } // if it's an upload + + // Build the options for our search + if (isset($_REQUEST['artist_name'])) { + $artist = scrub_in($_REQUEST['artist_name']); + } + elseif ($album->artist_count == '1') { + $artist = $album->f_artist_name; + } + if (isset($_REQUEST['album_name'])) { + $album_name = scrub_in($_REQUEST['album_name']); + } + else { + $album_name = $album->full_name; + } + + $options['artist'] = $artist; + $options['album_name'] = $album_name; + $options['keyword'] = $artist . " " . $album_name; + + // Attempt to find the art. + $images = $art->gather($options,'6'); + + if (!empty($_REQUEST['cover'])) { + $path_info = pathinfo($_REQUEST['cover']); + $cover_url[0]['url'] = scrub_in($_REQUEST['cover']); + $cover_url[0]['mime'] = 'image/' . $path_info['extension']; + } + $images = array_merge($cover_url,$images); + + // If we've found anything then go for it! + if (count($images)) { + // We don't want to store raw's in here so we need to strip them out into a seperate array + foreach ($images as $index=>$image) { + if ($image['raw']) { + unset($images[$index]['raw']); + } + } // end foreach + // Store the results for further use + $_SESSION['form']['images'] = $images; + require_once Config::get('prefix') . '/templates/show_album_art.inc.php'; + } + // Else nothing + else { + show_confirmation(T_('Album Art Not Located'), T_('Album Art could not be located at this time. This may be due to write access error, or the file is not received correctly.'),"/albums.php?action=show&album=" . $album->id); + } + + $albumname = $album->name; + $artistname = $artist; + + // Remember the last typed entry, if there was one + if (!empty($_REQUEST['album_name'])) { $albumname = scrub_in($_REQUEST['album_name']); } + if (!empty($_REQUEST['artist_name'])) { $artistname = scrub_in($_REQUEST['artist_name']); } + + require_once Config::get('prefix') . '/templates/show_get_albumart.inc.php'; + + break; + case 'select_art': + + /* Check to see if we have the image url still */ + $image_id = $_REQUEST['image']; + $album_id = $_REQUEST['album_id']; + $art = new Art($album_id,'album'); + + $image = Art::get_from_source($_SESSION['form']['images'][$image_id], 'album'); + $mime = $_SESSION['form']['images'][$image_id]['mime']; + + $art->insert($image,$mime); + + header("Location:" . Config::get('web_path') . "/albums.php?action=show&album=" . $art->uid); + break; + case 'update_from_tags': + // Make sure they are a 'power' user at least + if (!Access::check('interface','75')) { + UI::access_denied(); + exit; + } + + $type = 'album'; + $object_id = intval($_REQUEST['album_id']); + $target_url = Config::get('web_path') . '/albums.php?action=show&album=' . $object_id; + require_once Config::get('prefix') . '/templates/show_update_items.inc.php'; + break; + // Browse by Album + default: + case 'show': + $album = new Album($_REQUEST['album']); + $album->format(); + require Config::get('prefix') . '/templates/show_album.inc.php'; + + break; } // switch on view UI::show_footer(); diff --git a/artists.php b/artists.php index f893328a13..b649633965 100644 --- a/artists.php +++ b/artists.php @@ -1,5 +1,5 @@ format(); - $object_ids = $artist->get_albums($_REQUEST['catalog']); - $object_type = 'album'; - require_once Config::get('prefix') . '/templates/show_artist.inc.php'; - if (Config::get('show_similar')) { - if ($object_ids = Recommendation::get_artists_like($artist->id)) { - // Ugly code to grab the relevant entries. - // Almost looks like Perl. - $object_ids = array_map(create_function('$i', 'return $i[\'id\'];'), $object_ids); - require_once Config::get('prefix') . '/templates/show_recommended_artists.inc.php'; - } - } - break; - case 'show_all_songs': - $artist = new Artist($_REQUEST['artist']); - $artist->format(); - $object_type = 'song'; - $object_ids = $artist->get_songs(); - require_once Config::get('prefix') . '/templates/show_artist.inc.php'; + case 'show': + $artist = new Artist($_REQUEST['artist']); + $artist->format(); + $object_ids = $artist->get_albums($_REQUEST['catalog']); + $object_type = 'album'; + require_once Config::get('prefix') . '/templates/show_artist.inc.php'; + if (Config::get('show_similar')) { + if ($object_ids = Recommendation::get_artists_like($artist->id)) { + // Ugly code to grab the relevant entries. + // Almost looks like Perl. + $object_ids = array_map(create_function('$i', 'return $i[\'id\'];'), $object_ids); + require_once Config::get('prefix') . '/templates/show_recommended_artists.inc.php'; + } + } break; - case 'update_from_tags': - $type = 'artist'; - $object_id = intval($_REQUEST['artist']); - $target_url = Config::get('web_path') . "/artists.php?action=show&artist=" . $object_id; - require_once Config::get('prefix') . '/templates/show_update_items.inc.php'; - break; - case 'rename_similar': - if (!$user->has_access('100')) { UI::access_denied(); } - $count = 0; - if (isset($_REQUEST['artist']) && is_numeric($_REQUEST['artist']) && isset($_REQUEST['artists']) && is_array($_REQUEST['artists'])) { - $artist = new Artist($_REQUEST['artist']); - if ($artist->id) - foreach ($_REQUEST['artists'] as $artist_id) { - if (is_numeric($artist_id)) { - $that_artist = new Artist($artist_id); - if ($that_artist->id) { - $that_artist->merge($artist->id); - $count++; - } else - $GLOBALS['error']->add_error('general', sprintf(T_('Error: No such artist \'%s\''), $artist_id)); - } else { - $GLOBALS['error']->add_error('general', sprintf(T_('Error: \'%s\' is not a valid ID'), $artist_id)); - } - } - else - $GLOBALS['error']->add_error('general', sprintf(T_('Error: No such artist \'%s\''), $_REQUEST['artist'])); - } else { - $GLOBALS['error']->add_error('general', T_("Error: Errenous request")); - } - if ($count > 0) { - show_confirmation ( - T_('Renamed artist(s)'), - sprintf(T_('%1$s artists have been merged with %2$s'), $count, $artist->name), - Config::get('web_path') . '/artists.php?action=show&artist=' . $artist->id - ); - } else { - $GLOBALS['error']->print_error('general'); - } - - break; - case 'show_similar': - if (!$GLOBALS['user']->has_access('75')) { - UI::access_denied(); - exit; - } - - $artist = new Artist($_REQUEST['artist']); - //options - $similar_artists = $artist->get_similar_artists( - make_bool($_POST['n_rep_uml']), - $_POST['n_filter'], - $_POST['n_ignore'], - $_POST['c_mode'], - $_POST['c_count_w'], - $_POST['c_percent_w'], - $_POST['c_distance_l'], - make_bool($_POST['c_ignins_l'])); - $artist_id = $artist->id; - $artist_name = $artist->name; - require Config::get('prefix') . '/templates/show_similar_artists.inc.php'; - - break; - case 'rename': - //die if not enough permissions - if (!$user->has_access('100')) { UI::access_denied(); } - - /* Get the artist */ - $artist = new Artist($_REQUEST['artist']); - $catalog = new Catalog(); - - //check if we've been given a target - if ((isset($_POST['artist_id']) && $_POST['artist_id'] != $artist->id ) || (isset($_POST['artist_name']) && $_POST['artist_name'] != "")) { - - //if we want to update id3 tags, then get the array of ids now, it's too late afterwards - if (make_bool($_POST['update_id3'])) - $songs = $artist->get_songs(); - - $ret = 0; - //the manual rename takes priority, but if they tested out the insert thing ignore - if ($_POST['artist_name'] != "" && $_POST['artist_name'] != $artist->name) { - //then just change the name of the artist in the db - $ret = $artist->rename($_POST['artist_name']); - $newid = $ret; - $newname = $_POST['artist_name']; - } - //new id? - elseif ($_POST['artist_id'] != $artist->id) { - //merge with other artist - $ret = $artist->merge($_POST['artist_id']); - $newid = $_POST['artist_id']; - $newname = $ret; - } // elseif different artist and id - //if no changes, no changes - - //now flag for id3tag update if selected, and something actually happaned - if ($ret && make_bool($_POST['update_id3'])) { - - /* Set the rename information in the db */ - foreach ($songs as $song) { - $flag = new Flag(); - $flag->add($song->id,"song","retag","Renamed artist, retag"); - $flag_qstring = "REPLACE INTO flagged " . - "SET type = 'setid3', song = '" . $song->id . "', date = '" . time() . "', user = '" . $GLOBALS['user']->username . "'"; - Dba::write($flag_qstring); - } - - } // end if they wanted to update - - // show something other than a blank screen after this - if ($ret) { - show_confirmation ( - T_('Renamed artist'), - sprintf(T_('%1$s is now known as %2$s'), $artist->name, $newname), - Config::get('web_path') . "/artists.php?action=show&artist=" . $newid - ); - } - - } // if we've got the needed variables - - /* Else we've got an error! But be lenient, and just show the form again */ - else { - require Config::get('prefix') . '/templates/show_rename_artist.inc.php'; - } - break; - case 'show_rename': - $artist = new Artist($_REQUEST['artist']); - require Config::get('prefix') . '/templates/show_rename_artist.inc.php'; - break; - case 'match': - case 'Match': - $match = scrub_in($_REQUEST['match']); - if ($match == "Browse" || $match == "Show_all") { $chr = ""; } - else { $chr = $match; } - /* Enclose this in the purty box! */ - require Config::get('prefix') . '/templates/show_box_top.inc.php'; - show_alphabet_list('artists','artists.php',$match); - show_alphabet_form($chr, T_('Show Artists starting with'),"artists.php?action=match"); - require Config::get('prefix') . '/templates/show_box_bottom.inc.php'; - - if ($match === "Browse") { - show_artists(); - } - elseif ($match === "Show_all") { - $offset_limit = 999999; - show_artists(); - } - else { - if ($chr == '') { - show_artists('A'); - } - else { - show_artists($chr); - } - } - break; + case 'show_all_songs': + $artist = new Artist($_REQUEST['artist']); + $artist->format(); + $object_type = 'song'; + $object_ids = $artist->get_songs(); + require_once Config::get('prefix') . '/templates/show_artist.inc.php'; + break; + case 'update_from_tags': + $type = 'artist'; + $object_id = intval($_REQUEST['artist']); + $target_url = Config::get('web_path') . "/artists.php?action=show&artist=" . $object_id; + require_once Config::get('prefix') . '/templates/show_update_items.inc.php'; + break; + case 'rename_similar': + if (!$user->has_access('100')) { UI::access_denied(); } + $count = 0; + if (isset($_REQUEST['artist']) && is_numeric($_REQUEST['artist']) && isset($_REQUEST['artists']) && is_array($_REQUEST['artists'])) { + $artist = new Artist($_REQUEST['artist']); + if ($artist->id) + foreach ($_REQUEST['artists'] as $artist_id) { + if (is_numeric($artist_id)) { + $that_artist = new Artist($artist_id); + if ($that_artist->id) { + $that_artist->merge($artist->id); + $count++; + } else + $GLOBALS['error']->add_error('general', sprintf(T_('Error: No such artist \'%s\''), $artist_id)); + } else { + $GLOBALS['error']->add_error('general', sprintf(T_('Error: \'%s\' is not a valid ID'), $artist_id)); + } + } + else + $GLOBALS['error']->add_error('general', sprintf(T_('Error: No such artist \'%s\''), $_REQUEST['artist'])); + } else { + $GLOBALS['error']->add_error('general', T_("Error: Errenous request")); + } + if ($count > 0) { + show_confirmation ( + T_('Renamed artist(s)'), + sprintf(T_('%1$s artists have been merged with %2$s'), $count, $artist->name), + Config::get('web_path') . '/artists.php?action=show&artist=' . $artist->id + ); + } else { + $GLOBALS['error']->print_error('general'); + } + + break; + case 'show_similar': + if (!$GLOBALS['user']->has_access('75')) { + UI::access_denied(); + exit; + } + + $artist = new Artist($_REQUEST['artist']); + //options + $similar_artists = $artist->get_similar_artists( + make_bool($_POST['n_rep_uml']), + $_POST['n_filter'], + $_POST['n_ignore'], + $_POST['c_mode'], + $_POST['c_count_w'], + $_POST['c_percent_w'], + $_POST['c_distance_l'], + make_bool($_POST['c_ignins_l'])); + $artist_id = $artist->id; + $artist_name = $artist->name; + require Config::get('prefix') . '/templates/show_similar_artists.inc.php'; + + break; + case 'rename': + //die if not enough permissions + if (!$user->has_access('100')) { UI::access_denied(); } + + /* Get the artist */ + $artist = new Artist($_REQUEST['artist']); + $catalog = new Catalog(); + + //check if we've been given a target + if ((isset($_POST['artist_id']) && $_POST['artist_id'] != $artist->id ) || (isset($_POST['artist_name']) && $_POST['artist_name'] != "")) { + + //if we want to update id3 tags, then get the array of ids now, it's too late afterwards + if (make_bool($_POST['update_id3'])) + $songs = $artist->get_songs(); + + $ret = 0; + //the manual rename takes priority, but if they tested out the insert thing ignore + if ($_POST['artist_name'] != "" && $_POST['artist_name'] != $artist->name) { + //then just change the name of the artist in the db + $ret = $artist->rename($_POST['artist_name']); + $newid = $ret; + $newname = $_POST['artist_name']; + } + //new id? + elseif ($_POST['artist_id'] != $artist->id) { + //merge with other artist + $ret = $artist->merge($_POST['artist_id']); + $newid = $_POST['artist_id']; + $newname = $ret; + } // elseif different artist and id + //if no changes, no changes + + //now flag for id3tag update if selected, and something actually happaned + if ($ret && make_bool($_POST['update_id3'])) { + + /* Set the rename information in the db */ + foreach ($songs as $song) { + $flag = new Flag(); + $flag->add($song->id,"song","retag","Renamed artist, retag"); + $flag_qstring = "REPLACE INTO flagged " . + "SET type = 'setid3', song = '" . $song->id . "', date = '" . time() . "', user = '" . $GLOBALS['user']->username . "'"; + Dba::write($flag_qstring); + } + + } // end if they wanted to update + + // show something other than a blank screen after this + if ($ret) { + show_confirmation ( + T_('Renamed artist'), + sprintf(T_('%1$s is now known as %2$s'), $artist->name, $newname), + Config::get('web_path') . "/artists.php?action=show&artist=" . $newid + ); + } + + } // if we've got the needed variables + + /* Else we've got an error! But be lenient, and just show the form again */ + else { + require Config::get('prefix') . '/templates/show_rename_artist.inc.php'; + } + break; + case 'show_rename': + $artist = new Artist($_REQUEST['artist']); + require Config::get('prefix') . '/templates/show_rename_artist.inc.php'; + break; + case 'match': + case 'Match': + $match = scrub_in($_REQUEST['match']); + if ($match == "Browse" || $match == "Show_all") { $chr = ""; } + else { $chr = $match; } + /* Enclose this in the purty box! */ + require Config::get('prefix') . '/templates/show_box_top.inc.php'; + show_alphabet_list('artists','artists.php',$match); + show_alphabet_form($chr, T_('Show Artists starting with'),"artists.php?action=match"); + require Config::get('prefix') . '/templates/show_box_bottom.inc.php'; + + if ($match === "Browse") { + show_artists(); + } + elseif ($match === "Show_all") { + $offset_limit = 999999; + show_artists(); + } + else { + if ($chr == '') { + show_artists('A'); + } + else { + show_artists($chr); + } + } + break; } // end switch UI::show_footer(); diff --git a/batch.php b/batch.php index 9dbabaf265..6a975c0f1f 100644 --- a/batch.php +++ b/batch.php @@ -1,5 +1,5 @@ playlist->get_items(); - $name = $GLOBALS['user']->username . ' - Playlist'; - break; - case 'playlist': - $playlist = new Playlist($_REQUEST['id']); - $media_ids = $playlist->get_songs(); - $name = $playlist->name; - break; - case 'smartplaylist': - $search = new Search('song', $_REQUEST['id']); - $sql = $search->to_sql(); - $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . - $sql['where_sql']; - $db_results = Dba::read($sql); - $media_ids = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $media_ids[] = $row['id']; - } - $name = $search->name; - break; - case 'album': - $album = new Album($_REQUEST['id']); - $media_ids = $album->get_songs(); - $name = $album->name; - break; - case 'artist': - $artist = new Artist($_REQUEST['id']); - $media_ids = $artist->get_songs(); - $name = $artist->name; - break; - case 'browse': - $id = scrub_in($_REQUEST['browse_id']); - $browse = new Browse($id); - $browse_media_ids = $browse->get_saved(); - $media_ids = array(); - foreach ($browse_media_ids as $media_id) { - switch ($_REQUEST['type']) { - case 'album': - $album = new Album($media_id); - $media_ids = array_merge($media_ids, $album->get_songs()); - break; - case 'song': - $media_ids[] = $media_id; - break; - case 'video': - $media_ids[] = array('Video', $media_id); - break; - } // switch on type - } // foreach media_id - $name = 'Batch-' . date("dmY",time()); - default: - // Rien a faire - break; + case 'tmp_playlist': + $media_ids = $GLOBALS['user']->playlist->get_items(); + $name = $GLOBALS['user']->username . ' - Playlist'; + break; + case 'playlist': + $playlist = new Playlist($_REQUEST['id']); + $media_ids = $playlist->get_songs(); + $name = $playlist->name; + break; + case 'smartplaylist': + $search = new Search('song', $_REQUEST['id']); + $sql = $search->to_sql(); + $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . + $sql['where_sql']; + $db_results = Dba::read($sql); + $media_ids = array(); + while ($row = Dba::fetch_assoc($db_results)) { + $media_ids[] = $row['id']; + } + $name = $search->name; + break; + case 'album': + $album = new Album($_REQUEST['id']); + $media_ids = $album->get_songs(); + $name = $album->name; + break; + case 'artist': + $artist = new Artist($_REQUEST['id']); + $media_ids = $artist->get_songs(); + $name = $artist->name; + break; + case 'browse': + $id = scrub_in($_REQUEST['browse_id']); + $browse = new Browse($id); + $browse_media_ids = $browse->get_saved(); + $media_ids = array(); + foreach ($browse_media_ids as $media_id) { + switch ($_REQUEST['type']) { + case 'album': + $album = new Album($media_id); + $media_ids = array_merge($media_ids, $album->get_songs()); + break; + case 'song': + $media_ids[] = $media_id; + break; + case 'video': + $media_ids[] = array('Video', $media_id); + break; + } // switch on type + } // foreach media_id + $name = 'Batch-' . date("dmY",time()); + default: + // Rien a faire + break; } // action switch // Take whatever we've got and send the zip diff --git a/bin/catalog_update.inc b/bin/catalog_update.inc index 126bfb7879..6a5ab033fe 100644 --- a/bin/catalog_update.inc +++ b/bin/catalog_update.inc @@ -1,5 +1,5 @@ 1) { - for ($x = 1; $x < count($_SERVER['argv']); $x++) { - - if ($_SERVER['argv'][$x] == "-c") { - $operations_string .= "\n\t" . T_('- Catalog Clean'); - $catclean = 1; - } - elseif ($_SERVER['argv'][$x] == "-v") { - $operations_string .= "\n\t" . T_('- Catalog Verify'); - $catverify = 1; - } - elseif ($_SERVER['argv'][$x] == "-a") { - $operations_string .= "\n\t" . T_('- Catalog Add'); - $catadd = 1; - } - elseif ($_SERVER['argv'][$x] == "-g") { - $operations_string .= "\n\t" . T_('- Catalog Art Gather'); - $artadd = 1; - } - elseif ($_SERVER['argv'][$x] == '-t') { - $operations_string .= "\n\t" . T_('- Generate Thumbnails'); - $thumbadd = 1; - } - else { - if ($where) $where .= " OR "; - $where .= "name LIKE '%" . Dba::escape(preg_replace("/[^a-z0-9\. -]/i", "", $_SERVER['argv'][$x])) . "%'"; - } - } + for ($x = 1; $x < count($_SERVER['argv']); $x++) { + + if ($_SERVER['argv'][$x] == "-c") { + $operations_string .= "\n\t" . T_('- Catalog Clean'); + $catclean = 1; + } + elseif ($_SERVER['argv'][$x] == "-v") { + $operations_string .= "\n\t" . T_('- Catalog Verify'); + $catverify = 1; + } + elseif ($_SERVER['argv'][$x] == "-a") { + $operations_string .= "\n\t" . T_('- Catalog Add'); + $catadd = 1; + } + elseif ($_SERVER['argv'][$x] == "-g") { + $operations_string .= "\n\t" . T_('- Catalog Art Gather'); + $artadd = 1; + } + elseif ($_SERVER['argv'][$x] == '-t') { + $operations_string .= "\n\t" . T_('- Generate Thumbnails'); + $thumbadd = 1; + } + else { + if ($where) $where .= " OR "; + $where .= "name LIKE '%" . Dba::escape(preg_replace("/[^a-z0-9\. -]/i", "", $_SERVER['argv'][$x])) . "%'"; + } + } } if (count($_SERVER['argv']) != 1 AND $artadd != 1 && $catclean != 1 && $catverify != 1 && $catadd != 1 && $thumbadd != 1) { usage(); - exit; + exit; } -if ($thumbadd == 0 && $artadd == 0 && $catclean == 0 && $catverify == 0 && $catadd == 0) { //didn't pass any clean/verify/add arguments - $catclean = 1; //set them all to on - $catverify = 1; - $catadd = 1; - $artadd = 1; - $thumbadd = 1; +if ($thumbadd == 0 && $artadd == 0 && $catclean == 0 && $catverify == 0 && $catadd == 0) { //didn't pass any clean/verify/add arguments + $catclean = 1; //set them all to on + $catverify = 1; + $catadd = 1; + $artadd = 1; + $thumbadd = 1; } echo T_("Starting Catalog Operations...") . $operations_string . "\n"; @@ -95,49 +95,49 @@ ob_start("ob_html_strip",'1024',true); while ($row = Dba::fetch_row($db_results)) { - $catalog = new Catalog($row['0']); - printf(T_('Reading: %s'), $catalog->name); - ob_flush(); - echo "\n"; - if ($catclean == 1) { - // Clean out dead files - echo T_("- Starting Clean - "); - echo "\n"; - $catalog->clean_catalog(); - echo "------------------\n\n"; - } - - if ($catverify == 1) { - // Verify Existing - echo T_("- Starting Verify - "); - echo "\n"; - $catalog->verify_catalog($row['0']); - echo "-------------------\n\n"; - } - - if ($catadd == 1) { - // Look for new files - echo T_("- Starting Add - "); - echo "\n"; - $catalog->add_to_catalog(); - echo "----------------\n\n"; - } - - if ($artadd == 1) { - // Look for album art - echo T_('Starting Album Art Search'); - echo "\n"; - $catalog->get_art('',1); - echo "----------------\n\n"; - } - - if ($thumbadd == 1) { - // Generate the thumbnails - echo T_('Generating Thumbnails'); - echo "\n"; - $catalog->generate_thumbnails(); - echo "----------------\n\n"; - } + $catalog = new Catalog($row['0']); + printf(T_('Reading: %s'), $catalog->name); + ob_flush(); + echo "\n"; + if ($catclean == 1) { + // Clean out dead files + echo T_("- Starting Clean - "); + echo "\n"; + $catalog->clean_catalog(); + echo "------------------\n\n"; + } + + if ($catverify == 1) { + // Verify Existing + echo T_("- Starting Verify - "); + echo "\n"; + $catalog->verify_catalog($row['0']); + echo "-------------------\n\n"; + } + + if ($catadd == 1) { + // Look for new files + echo T_("- Starting Add - "); + echo "\n"; + $catalog->add_to_catalog(); + echo "----------------\n\n"; + } + + if ($artadd == 1) { + // Look for album art + echo T_('Starting Album Art Search'); + echo "\n"; + $catalog->get_art('',1); + echo "----------------\n\n"; + } + + if ($thumbadd == 1) { + // Generate the thumbnails + echo T_('Generating Thumbnails'); + echo "\n"; + $catalog->generate_thumbnails(); + echo "----------------\n\n"; + } } // end foreach @@ -148,36 +148,36 @@ echo "\n"; function ob_html_strip($string) { - //$string = preg_replace("/update_txt\('.+'\);update_txt\('(.+)','.+'\);/","$1",$string); - //$string = preg_replace("/update_.+/","",$string); - $string = str_replace('
', "\n", $string); - $string = strip_tags($string); - $string = html_entity_decode($string); - $string = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/","\n",$string); - $string = trim($string); - return $string; + //$string = preg_replace("/update_txt\('.+'\);update_txt\('(.+)','.+'\);/","$1",$string); + //$string = preg_replace("/update_.+/","",$string); + $string = str_replace('
', "\n", $string); + $string = strip_tags($string); + $string = html_entity_decode($string); + $string = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/","\n",$string); + $string = trim($string); + return $string; } // ob_html_strip function usage() { - echo T_("- Catalog Update -"); - echo "\n"; - echo T_("Usage: catalog_update.inc [CATALOG NAME] [-c|-v|-a|-g|-t]"); - echo "\n\t"; - echo T_("Default behavior is to do all"); - echo "\n-c\t"; - echo T_('Clean Catalogs'); - echo "\n-v\t"; - echo T_('Verify Catalogs'); - echo "\n-a\t"; - echo T_('Add to Catalogs'); - echo "\n-g\t"; - echo T_('Gather Art'); - echo "\n-t\t"; - echo T_('Generate Thumbnails'); - echo "\n"; - echo "----------------------------------------------------------"; - echo "\n"; + echo T_("- Catalog Update -"); + echo "\n"; + echo T_("Usage: catalog_update.inc [CATALOG NAME] [-c|-v|-a|-g|-t]"); + echo "\n\t"; + echo T_("Default behavior is to do all"); + echo "\n-c\t"; + echo T_('Clean Catalogs'); + echo "\n-v\t"; + echo T_('Verify Catalogs'); + echo "\n-a\t"; + echo T_('Add to Catalogs'); + echo "\n-g\t"; + echo T_('Gather Art'); + echo "\n-t\t"; + echo T_('Generate Thumbnails'); + echo "\n"; + echo "----------------------------------------------------------"; + echo "\n"; } ?> diff --git a/bin/delete_disabled.inc b/bin/delete_disabled.inc index 7a6df7fc42..01a498ce40 100644 --- a/bin/delete_disabled.inc +++ b/bin/delete_disabled.inc @@ -1,5 +1,5 @@ diff --git a/bin/dump_album_art.inc b/bin/dump_album_art.inc index 32740b13c4..ebf520d32d 100644 --- a/bin/dump_album_art.inc +++ b/bin/dump_album_art.inc @@ -1,5 +1,5 @@ 1) { - $meta = ($_SERVER['argv']['1'] == 'windows') ? 'windows' : 'linux'; + $meta = ($_SERVER['argv']['1'] == 'windows') ? 'windows' : 'linux'; } $catalogs = Catalog::get_catalogs(); foreach ($catalogs as $catalog_id) { - Catalog::dump_album_art($catalog_id,array('metadata'=>$meta)); + Catalog::dump_album_art($catalog_id,array('metadata'=>$meta)); } diff --git a/bin/fix_filenames.inc b/bin/fix_filenames.inc index 94531b89de..402569fa97 100644 --- a/bin/fix_filenames.inc +++ b/bin/fix_filenames.inc @@ -1,5 +1,5 @@ [ -l ] [ -p ] [ -n ]\n"; - exit(1); + echo "Usage: add_user.inc -u [ -l ] [ -p ] [ -n ]\n"; + exit(1); } $username = $options['u']; @@ -46,12 +46,12 @@ $email = isset($options['e']) ? $options['e'] : ''; $name = isset($options['n']) ? $options['n'] : ''; if (User::create($username, $name, $email, $password, $access)) { - printf(T_('Created %s user %s with password %s'), T_($access), $username, $password); - echo "\n"; + printf(T_('Created %s user %s with password %s'), T_($access), $username, $password); + echo "\n"; } else { - echo T_('User creation failed'), "\n"; - exit(1); + echo T_('User creation failed'), "\n"; + exit(1); } User::fix_preferences('-1'); diff --git a/bin/install/install_db.inc b/bin/install/install_db.inc index ec64de6bc1..44b0c9555a 100644 --- a/bin/install/install_db.inc +++ b/bin/install/install_db.inc @@ -1,5 +1,5 @@ diff --git a/bin/install/update_db.inc b/bin/install/update_db.inc index 6dc8f3a42a..4930cb16ef 100644 --- a/bin/install/update_db.inc +++ b/bin/install/update_db.inc @@ -1,5 +1,5 @@ 'mysql', - 'tag_order'=>'id3v2,id3v1,vorbiscomment,quicktime,ape,asf', - 'album_art_order'=>'db,id3,folder,lastfm,amazon', - 'amazon_base_urls'=>'http://webservices.amazon.com'); + 'tag_order'=>'id3v2,id3v1,vorbiscomment,quicktime,ape,asf', + 'album_art_order'=>'db,id3,folder,lastfm,amazon', + 'amazon_base_urls'=>'http://webservices.amazon.com'); $translate = array('local_host'=>'database_hostname', - 'local_db'=>'database_name', - 'local_username'=>'database_username', - 'local_pass'=>'database_password', - 'local_length'=>'session_length', - 'stream_cmd_flac'=>'transcode_cmd_flac', - 'stream_cmd_mp3'=>'transcode_cmd_mp3', - 'stream_cmd_m4a'=>'transcode_cmd_m4a', - 'stream_cmd_ogg'=>'transcode_cmd_ogg', - 'stream_cmd_mpc'=>'transcode_cmd_mpc', - 'sess_name'=>'session_name', - 'sess_cookielife'=>'session_cookielife', - 'sess_cookiesecure'=>'session_cookiesecure'); + 'local_db'=>'database_name', + 'local_username'=>'database_username', + 'local_pass'=>'database_password', + 'local_length'=>'session_length', + 'stream_cmd_flac'=>'transcode_cmd_flac', + 'stream_cmd_mp3'=>'transcode_cmd_mp3', + 'stream_cmd_m4a'=>'transcode_cmd_m4a', + 'stream_cmd_ogg'=>'transcode_cmd_ogg', + 'stream_cmd_mpc'=>'transcode_cmd_mpc', + 'sess_name'=>'session_name', + 'sess_cookielife'=>'session_cookielife', + 'sess_cookiesecure'=>'session_cookiesecure'); $path = dirname(__FILE__); $prefix = realpath($path . '/../'); @@ -52,28 +52,28 @@ echo "\n"; foreach ($data as $line) { - // Replace a # with ; - if ($line['0'] == '#') { - $line = substr_replace($line,";",0,1); - } - - foreach ($unmigratable as $option=>$default) { - if (strstr($line,$option) AND !$migrated[$option]) { - $line = $option . " = \"$default\""; - $migrated[$option] = true; - } - elseif (strstr($line,$option)) { - $line = ';' . $line; - } - } - - foreach ($translate as $old=>$new) { - if (strstr($line,$old)) { - $line = str_replace($old,$new,$line); - } - } - - $new_config .= $line . "\n"; + // Replace a # with ; + if ($line['0'] == '#') { + $line = substr_replace($line,";",0,1); + } + + foreach ($unmigratable as $option=>$default) { + if (strstr($line,$option) AND !$migrated[$option]) { + $line = $option . " = \"$default\""; + $migrated[$option] = true; + } + elseif (strstr($line,$option)) { + $line = ';' . $line; + } + } + + foreach ($translate as $old=>$new) { + if (strstr($line,$old)) { + $line = str_replace($old,$new,$line); + } + } + + $new_config .= $line . "\n"; } // end foreach lines @@ -85,12 +85,12 @@ $handle = fopen($prefix . '/config/ampache.cfg.php','w'); $worked = fwrite($handle,$new_config); if ($worked) { - echo T_("Write success, config migrated"); - echo "\n"; + echo T_("Write success, config migrated"); + echo "\n"; } else { - echo T_("Access Denied, config migration failed"); - echo "\n"; + echo T_("Access Denied, config migration failed"); + echo "\n"; } ?> diff --git a/bin/print_tags.inc b/bin/print_tags.inc index 1c92cec454..ed0722440c 100644 --- a/bin/print_tags.inc +++ b/bin/print_tags.inc @@ -1,5 +1,5 @@ rename_pattern; $info = new vainfo($filename, '', '', '', $dir_pattern, $file_pattern); if(isset($dir_pattern) || isset($file_pattern)) { - printf(T_('Using: %s AND %s for file pattern matching'), $dir_pattern, $file_pattern); - print "\n"; + printf(T_('Using: %s AND %s for file pattern matching'), $dir_pattern, $file_pattern); + print "\n"; } $info->get_info(); $results = $info->tags; @@ -73,16 +73,16 @@ echo "\n\n"; print_r($ampache_results); function usage() { - global $version; + global $version; - $text = sprintf(T_('%s Version %s'), 'print_tags.inc', $version); - $text .= "\n\n"; - $text .= T_('Usage:'); - $text .= "\n"; - $text .= T_('php print_tags.inc '); - $text .= "\n\n"; + $text = sprintf(T_('%s Version %s'), 'print_tags.inc', $version); + $text .= "\n\n"; + $text .= T_('Usage:'); + $text .= "\n"; + $text .= T_('php print_tags.inc '); + $text .= "\n\n"; - return print $text; + return print $text; }// usage() diff --git a/bin/sort_files.inc b/bin/sort_files.inc index a80200404a..5eb95f1003 100644 --- a/bin/sort_files.inc +++ b/bin/sort_files.inc @@ -1,5 +1,5 @@ get_catalog_files(); - - printf (T_('Starting Catalog: %s'), stripslashes($catalog->name)); - echo "\n"; - - /* Foreach through each file and find it a home! */ - foreach ($songs as $song) { - /* Find this poor song a home */ - $song->format(); - $song->format_pattern(); - $directory = sort_find_home($song,$catalog->sort_pattern,$catalog->path); - $filename = $song->f_file; - $fullpath = $directory . "/" . $filename; - - /* Check for Demo Mode */ - if ($test_mode) { - /* We're just talking here... no work */ - echo T_("Moving File..."); - echo "\n\t"; - printf (T_('Source: %s'), $song->file); - echo "\n\t"; - printf (T_('Dest: %s'), $fullpath); - echo "\n"; - flush(); - } - /* We need to actually do the moving (fake it if we are testing) - * Don't try to move it, if it's already the same friggin thing! - */ - if ($song->file != $fullpath && strlen($fullpath)) { - sort_move_file($song,$fullpath); - } - - } // end foreach song + $catalog = new Catalog($r['0']); + $songs = $catalog->get_catalog_files(); + + printf (T_('Starting Catalog: %s'), stripslashes($catalog->name)); + echo "\n"; + + /* Foreach through each file and find it a home! */ + foreach ($songs as $song) { + /* Find this poor song a home */ + $song->format(); + $song->format_pattern(); + $directory = sort_find_home($song,$catalog->sort_pattern,$catalog->path); + $filename = $song->f_file; + $fullpath = $directory . "/" . $filename; + + /* Check for Demo Mode */ + if ($test_mode) { + /* We're just talking here... no work */ + echo T_("Moving File..."); + echo "\n\t"; + printf (T_('Source: %s'), $song->file); + echo "\n\t"; + printf (T_('Dest: %s'), $fullpath); + echo "\n"; + flush(); + } + /* We need to actually do the moving (fake it if we are testing) + * Don't try to move it, if it's already the same friggin thing! + */ + if ($song->file != $fullpath && strlen($fullpath)) { + sort_move_file($song,$fullpath); + } + + } // end foreach song } // end foreach catalogs @@ -100,47 +100,47 @@ while ($r = Dba::fetch_row($db_results)) { */ function sort_find_home($song,$sort_pattern,$base) { - $home = rtrim($base,"\/"); - $home = rtrim($home,"\\"); + $home = rtrim($base,"\/"); + $home = rtrim($home,"\\"); - /* Create the filename that this file should have */ - $album = sort_clean_name($song->f_album_full); - $artist = sort_clean_name($song->f_artist_full); - $track = sort_clean_name($song->track); - $title = sort_clean_name($song->title); - $year = sort_clean_name($song->year); - $comment = sort_clean_name($song->comment); + /* Create the filename that this file should have */ + $album = sort_clean_name($song->f_album_full); + $artist = sort_clean_name($song->f_artist_full); + $track = sort_clean_name($song->track); + $title = sort_clean_name($song->title); + $year = sort_clean_name($song->year); + $comment = sort_clean_name($song->comment); - /* Do the various check */ - $album_object = new Album($song->album); - $album_object->format(); - if ($album_object->artist_count != '1') { - $artist = "Various"; - } + /* Do the various check */ + $album_object = new Album($song->album); + $album_object->format(); + if ($album_object->artist_count != '1') { + $artist = "Various"; + } - /* IF we want a,b,c,d we need to know the first element */ - if ($GLOBALS['alphabet_prefix']) { - $sort_pattern = preg_replace("/\/?%o\//","",$sort_pattern); - $first_element = substr($sort_pattern,0,2); - $element = sort_element_name($first_element); - if (!$element) { $alphabet = 'ZZ'; } - else { $alphabet = strtoupper(substr(${$element},0,1)); } - $alphabet = preg_replace("/[^A-Za-z0-9]/","ZZ",$alphabet); + /* IF we want a,b,c,d we need to know the first element */ + if ($GLOBALS['alphabet_prefix']) { + $sort_pattern = preg_replace("/\/?%o\//","",$sort_pattern); + $first_element = substr($sort_pattern,0,2); + $element = sort_element_name($first_element); + if (!$element) { $alphabet = 'ZZ'; } + else { $alphabet = strtoupper(substr(${$element},0,1)); } + $alphabet = preg_replace("/[^A-Za-z0-9]/","ZZ",$alphabet); - $home .= "/$alphabet"; - } + $home .= "/$alphabet"; + } - /* Replace everything we can find */ - $replace_array = array('%a','%A','%t','%T','%y','%c'); - $content_array = array($artist,$album,$title,$track,$year,$comment); - $sort_pattern = str_replace($replace_array,$content_array,$sort_pattern); + /* Replace everything we can find */ + $replace_array = array('%a','%A','%t','%T','%y','%c'); + $content_array = array($artist,$album,$title,$track,$year,$comment); + $sort_pattern = str_replace($replace_array,$content_array,$sort_pattern); - /* Remove non A-Z0-9 chars */ - $sort_pattern = preg_replace("[^\\\/A-Za-z0-9\-\_\ \'\,\(\)]","_",$sort_pattern); + /* Remove non A-Z0-9 chars */ + $sort_pattern = preg_replace("[^\\\/A-Za-z0-9\-\_\ \'\,\(\)]","_",$sort_pattern); - $home .= "/$sort_pattern"; + $home .= "/$sort_pattern"; - return $home; + return $home; } // sort_find_home @@ -150,27 +150,27 @@ function sort_find_home($song,$sort_pattern,$base) { */ function sort_element_name($key) { - switch ($key) { - case '%t': - return 'title'; - break; - case '%T': - return 'track'; - break; - case '%a': - return 'artist'; - break; - case '%A': - return 'album'; - break; - case '%y': - return 'year'; - break; - default: - break; - } // switch on key - - return false; + switch ($key) { + case '%t': + return 'title'; + break; + case '%T': + return 'track'; + break; + case '%a': + return 'artist'; + break; + case '%A': + return 'album'; + break; + case '%y': + return 'year'; + break; + default: + break; + } // switch on key + + return false; } // sort_element_name @@ -183,14 +183,14 @@ function sort_element_name($key) { */ function sort_clean_name($string) { - /* First remove any / or \ chars */ - $string = preg_replace('/[\/\\\]/','-',$string); + /* First remove any / or \ chars */ + $string = preg_replace('/[\/\\\]/','-',$string); - $string = str_replace(':',' ',$string); + $string = str_replace(':',' ',$string); - $string = preg_replace('/[\!\:\*]/','_',$string); + $string = preg_replace('/[\!\:\*]/','_',$string); - return $string; + return $string; } // sort_clean_name @@ -206,102 +206,102 @@ function sort_clean_name($string) { */ function sort_move_file($song,$fullname) { - $old_dir = dirname($song->file); - - $info = pathinfo($fullname); - - $directory = $info['dirname']; - $file = $info['basename']; - $data = preg_split("/[\/\\\]/",$directory); - $path = ''; - - /* We not need the leading / */ - unset($data[0]); - - foreach ($data as $dir) { - - $dir = sort_clean_name($dir); - $path .= "/" . $dir; - - /* We need to check for the existance of this directory */ - if (!is_dir($path)) { - if ($GLOBALS['test_mode']) { - echo "\t"; - printf (T_('Making %s Directory'), $path); - echo "\n"; - } - else { - debug_event('mkdir',"Creating $path directory",'5'); - $results = mkdir($path); - if (!$results) { - printf (T_('Error: Unable to create %s move failed'), $path); - echo "\n"; - return false; - } - } // else we aren't in test mode - } // if it's not a dir - - } // foreach dir - - /* Now that we've got the correct directory structure let's try to copy it */ - if ($GLOBALS['test_mode']) { - echo "\t"; - // HINT: %1$s: file, %2$s: directory - printf (T_('Copying %1$s to %2$s'), $file, $directory); - echo "\n"; - $sql = "UPDATE song SET file='" . Dba::escape($fullname) . "' WHERE id='" . Dba::escape($song->id) . "'"; - echo "\tSQL: $sql\n"; - flush(); - } - else { - - /* Check for file existance */ - if (file_exists($fullname)) { - debug_event('file exists','Error: $fullname already exists','1'); - printf (T_('Error: %s already exists'), $filename); - echo "\n"; - return false; - } - - $results = copy($song->file,$fullname); - debug_event('copy','Copied ' . $song->file . ' to ' . $fullname,'5'); - - /* Look for the folder art and copy that as well */ - if (!Config::get('album_art_preferred_filename') OR strstr(Config::get('album_art_preferred_filename'),"%")) { - $folder_art = $directory . '/folder.jpg'; - $old_art = $old_dir . '/folder.jpg'; - } - else { - $folder_art = $directory . "/" . sort_clean_name(Config::get('album_art_preferred_filename')); - $old_art = $old_dir . "/" . sort_clean_name(Config::get('album_art_preferred_filename')); - } - - debug_event('copy_art','Copied ' . $old_art . ' to ' . $folder_art,'5'); - @copy($old_art,$folder_art); - - if (!$results) { printf (T_('Error: Unable to copy file to %s'), $fullname); echo "\n"; return false; } - - /* Check the filesize */ - $new_sum = filesize($fullname); - $old_sum = filesize($song->file); - - if ($new_sum != $old_sum OR !$new_sum) { - printf (T_('Error: Size Inconsistency, not deleting %s'), $song->file); - echo "\n"; - return false; - } // end if sum's don't match - - /* If we've made it this far it should be safe */ - $results = unlink($song->file); - if (!$results) { printf (T_('Error: Unable to delete %s'), $song->file); echo "\n"; } - - /* Update the catalog */ - $sql = "UPDATE song SET file='" . Dba::escape($fullname) . "' WHERE id='" . Dba::escape($song->id) . "'"; - $db_results = Dba::write($sql); - - } // end else - - return true; + $old_dir = dirname($song->file); + + $info = pathinfo($fullname); + + $directory = $info['dirname']; + $file = $info['basename']; + $data = preg_split("/[\/\\\]/",$directory); + $path = ''; + + /* We not need the leading / */ + unset($data[0]); + + foreach ($data as $dir) { + + $dir = sort_clean_name($dir); + $path .= "/" . $dir; + + /* We need to check for the existance of this directory */ + if (!is_dir($path)) { + if ($GLOBALS['test_mode']) { + echo "\t"; + printf (T_('Making %s Directory'), $path); + echo "\n"; + } + else { + debug_event('mkdir',"Creating $path directory",'5'); + $results = mkdir($path); + if (!$results) { + printf (T_('Error: Unable to create %s move failed'), $path); + echo "\n"; + return false; + } + } // else we aren't in test mode + } // if it's not a dir + + } // foreach dir + + /* Now that we've got the correct directory structure let's try to copy it */ + if ($GLOBALS['test_mode']) { + echo "\t"; + // HINT: %1$s: file, %2$s: directory + printf (T_('Copying %1$s to %2$s'), $file, $directory); + echo "\n"; + $sql = "UPDATE song SET file='" . Dba::escape($fullname) . "' WHERE id='" . Dba::escape($song->id) . "'"; + echo "\tSQL: $sql\n"; + flush(); + } + else { + + /* Check for file existance */ + if (file_exists($fullname)) { + debug_event('file exists','Error: $fullname already exists','1'); + printf (T_('Error: %s already exists'), $filename); + echo "\n"; + return false; + } + + $results = copy($song->file,$fullname); + debug_event('copy','Copied ' . $song->file . ' to ' . $fullname,'5'); + + /* Look for the folder art and copy that as well */ + if (!Config::get('album_art_preferred_filename') OR strstr(Config::get('album_art_preferred_filename'),"%")) { + $folder_art = $directory . '/folder.jpg'; + $old_art = $old_dir . '/folder.jpg'; + } + else { + $folder_art = $directory . "/" . sort_clean_name(Config::get('album_art_preferred_filename')); + $old_art = $old_dir . "/" . sort_clean_name(Config::get('album_art_preferred_filename')); + } + + debug_event('copy_art','Copied ' . $old_art . ' to ' . $folder_art,'5'); + @copy($old_art,$folder_art); + + if (!$results) { printf (T_('Error: Unable to copy file to %s'), $fullname); echo "\n"; return false; } + + /* Check the filesize */ + $new_sum = filesize($fullname); + $old_sum = filesize($song->file); + + if ($new_sum != $old_sum OR !$new_sum) { + printf (T_('Error: Size Inconsistency, not deleting %s'), $song->file); + echo "\n"; + return false; + } // end if sum's don't match + + /* If we've made it this far it should be safe */ + $results = unlink($song->file); + if (!$results) { printf (T_('Error: Unable to delete %s'), $song->file); echo "\n"; } + + /* Update the catalog */ + $sql = "UPDATE song SET file='" . Dba::escape($fullname) . "' WHERE id='" . Dba::escape($song->id) . "'"; + $db_results = Dba::write($sql); + + } // end else + + return true; } // sort_move_file diff --git a/bin/write_playlists.inc b/bin/write_playlists.inc index 4342d20aa4..0fed1643e1 100644 --- a/bin/write_playlists.inc +++ b/bin/write_playlists.inc @@ -1,5 +1,5 @@ - $desc1 - $desc2 - default $desc3 - playlists $desc4 - artist $desc5\n\n"; + $desc1 + $desc2 + default $desc3 + playlists $desc4 + artist $desc5\n\n"; - exit($string); + exit($string); } // useage ?> diff --git a/bin/write_tags.inc b/bin/write_tags.inc index cb389bcaca..6ced898e37 100644 --- a/bin/write_tags.inc +++ b/bin/write_tags.inc @@ -1,5 +1,5 @@ object_id); + $flag = new Flag($flagged); + $song = new Song($flag->object_id); - // Decide on what type of tag format to use, base on song type(a better way maybe?) - switch($song->type) { - case 'mp3': - case 'mp2': - case 'mp1': - $tagWriter = new getid3_write_apetag($song->file); - Flag::fill_tags( &$tagWriter, &$song, 'comment' ); - break; - case 'ogg': - $tagWriter = new getid3_write_vorbis($song->file); - Flag::fill_tags( &$tagWriter, &$song, 'comment' ); - break; - case 'flac': - $tagWriter = new getid3_write_flac($song->file); - Flag::fill_tags( &$tagWriter, &$song, 'comment' ); - break; - default: - echo T_('No Tag'); - } // end switch - - if ( isset($tagWriter) ) { + // Decide on what type of tag format to use, base on song type(a better way maybe?) + switch($song->type) { + case 'mp3': + case 'mp2': + case 'mp1': + $tagWriter = new getid3_write_apetag($song->file); + Flag::fill_tags( &$tagWriter, &$song, 'comment' ); + break; + case 'ogg': + $tagWriter = new getid3_write_vorbis($song->file); + Flag::fill_tags( &$tagWriter, &$song, 'comment' ); + break; + case 'flac': + $tagWriter = new getid3_write_flac($song->file); + Flag::fill_tags( &$tagWriter, &$song, 'comment' ); + break; + default: + echo T_('No Tag'); + } // end switch + + if ( isset($tagWriter) ) { - // Write out the tag - try { - $tagWriter->write(); - // HINT: %1$s: title, %2$s: artist_name - printf (T_('Updated song %1$s by %2$s'), $song->title, $song->get_artist_name()); - echo "\n"; - flush(); - $flag->delete(); - } - catch ( Exception $e ) { - print_r( $e->message() ); - } - } + // Write out the tag + try { + $tagWriter->write(); + // HINT: %1$s: title, %2$s: artist_name + printf (T_('Updated song %1$s by %2$s'), $song->title, $song->get_artist_name()); + echo "\n"; + flush(); + $flag->delete(); + } + catch ( Exception $e ) { + print_r( $e->message() ); + } + } - // Unset objects between iterations. getID3 seems to need this - unset($tagWriter,$song,$flag); + // Unset objects between iterations. getID3 seems to need this + unset($tagWriter,$song,$flag); } diff --git a/browse.php b/browse.php index b503bac99e..ed8b94be78 100644 --- a/browse.php +++ b/browse.php @@ -1,5 +1,5 @@ set_type($_REQUEST['action']); - $browse->set_simple_browse(true); - break; + case 'tag': + case 'file': + case 'album': + case 'artist': + case 'playlist': + case 'smartplaylist': + case 'live_stream': + case 'video': + case 'song': + $browse->set_type($_REQUEST['action']); + $browse->set_simple_browse(true); + break; } // end switch UI::show_header(); switch($_REQUEST['action']) { - case 'file': - break; - case 'album': - $browse->set_filter('catalog',$_SESSION['catalog']); - $browse->set_sort('name','ASC'); - $browse->show_objects(); - break; - case 'tag': - $browse->set_sort('count','ASC'); - // This one's a doozy - $browse->set_simple_browse(false); - $browse->save_objects(Tag::get_tags(Config::get('offset_limit'),array())); - $object_ids = $browse->get_saved(); - $keys = array_keys($object_ids); - Tag::build_cache($keys); - UI::show_box_top(T_('Tag Cloud'), 'box box_tag_cloud'); - $browse2 = new Browse(); - $browse2->set_type('song'); - $browse2->store(); - require_once Config::get('prefix') . '/templates/show_tagcloud.inc.php'; - UI::show_box_bottom(); - require_once Config::get('prefix') . '/templates/browse_content.inc.php'; - break; - case 'artist': - $browse->set_filter('catalog',$_SESSION['catalog']); - $browse->set_sort('name','ASC'); - $browse->show_objects(); - break; - case 'song': - $browse->set_filter('catalog',$_SESSION['catalog']); - $browse->set_sort('title','ASC'); - $browse->show_objects(); - break; - case 'live_stream': - $browse->set_sort('name','ASC'); - $browse->show_objects(); - break; - case 'catalog': + case 'file': + break; + case 'album': + $browse->set_filter('catalog',$_SESSION['catalog']); + $browse->set_sort('name','ASC'); + $browse->show_objects(); + break; + case 'tag': + $browse->set_sort('count','ASC'); + // This one's a doozy + $browse->set_simple_browse(false); + $browse->save_objects(Tag::get_tags(Config::get('offset_limit'),array())); + $object_ids = $browse->get_saved(); + $keys = array_keys($object_ids); + Tag::build_cache($keys); + UI::show_box_top(T_('Tag Cloud'), 'box box_tag_cloud'); + $browse2 = new Browse(); + $browse2->set_type('song'); + $browse2->store(); + require_once Config::get('prefix') . '/templates/show_tagcloud.inc.php'; + UI::show_box_bottom(); + require_once Config::get('prefix') . '/templates/browse_content.inc.php'; + break; + case 'artist': + $browse->set_filter('catalog',$_SESSION['catalog']); + $browse->set_sort('name','ASC'); + $browse->show_objects(); + break; + case 'song': + $browse->set_filter('catalog',$_SESSION['catalog']); + $browse->set_sort('title','ASC'); + $browse->show_objects(); + break; + case 'live_stream': + $browse->set_sort('name','ASC'); + $browse->show_objects(); + break; + case 'catalog': - break; - case 'playlist': - $browse->set_sort('type','ASC'); - $browse->set_filter('playlist_type','1'); - $browse->show_objects(); - break; - case 'smartplaylist': - $browse->set_sort('type', 'ASC'); - $browse->set_filter('playlist_type','1'); - $browse->show_objects(); - break; - case 'video': - $browse->set_sort('title','ASC'); - $browse->show_objects(); - break; - default: + break; + case 'playlist': + $browse->set_sort('type','ASC'); + $browse->set_filter('playlist_type','1'); + $browse->show_objects(); + break; + case 'smartplaylist': + $browse->set_sort('type', 'ASC'); + $browse->set_filter('playlist_type','1'); + $browse->show_objects(); + break; + case 'video': + $browse->set_sort('title','ASC'); + $browse->show_objects(); + break; + default: - break; + break; } // end Switch $action $browse->store(); diff --git a/democratic.php b/democratic.php index a31aa0e7d1..a712d844da 100644 --- a/democratic.php +++ b/democratic.php @@ -1,5 +1,5 @@ set_parent(); $democratic->format(); - case 'show_create': - if (!Access::check('interface','75')) { - UI::access_denied(); - break; - } - - // Show the create page - require_once Config::get('prefix') . '/templates/show_create_democratic.inc.php'; - break; - case 'delete': - if (!Access::check('interface','75')) { - UI::access_denied(); - break; - } - - Democratic::delete($_REQUEST['democratic_id']); - - $title = ''; - $text = T_('The Requested Playlist has been deleted.'); - $url = Config::get('web_path') . '/democratic.php?action=manage_playlists'; - show_confirmation($title,$text,$url); - break; - case 'create': - // Only power users here - if (!Access::check('interface','75')) { - UI::access_denied(); - break; - } - - if (!Core::form_verify('create_democratic')) { - UI::access_denied(); - exit; - } - - $democratic = Democratic::get_current_playlist(); - - // If we don't have anything currently create something - if (!$democratic->id) { - // Create the playlist - Democratic::create($_POST); - $democratic = Democratic::get_current_playlist(); - } - else { - $democratic->update($_POST); - } - - // Now check for additional things we might have to do - if ($_POST['force_democratic']) { - Democratic::set_user_preferences(); - } - - header("Location: " . Config::get('web_path') . "/democratic.php?action=show"); - break; - case 'manage_playlists': - if (!Access::check('interface','75')) { - UI::access_denied(); - break; - } - // Get all of the non-user playlists - $playlists = Democratic::get_playlists(); - - require_once Config::get('prefix') . '/templates/show_manage_democratic.inc.php'; - - break; - case 'show_playlist': - default: - $democratic = Democratic::get_current_playlist(); - if (!$democratic->id) { - require_once Config::get('prefix') . '/templates/show_democratic.inc.php'; - break; - } - - $democratic->set_parent(); - $democratic->format(); - require_once Config::get('prefix') . '/templates/show_democratic.inc.php'; - $objects = $democratic->get_items(); - Song::build_cache($democratic->object_ids); - Democratic::build_vote_cache($democratic->vote_ids); - $browse = new Browse(); - $browse->set_type('democratic'); - $browse->set_static_content(true); - $browse->show_objects($objects); - $browse->store(); - break; + case 'show_create': + if (!Access::check('interface','75')) { + UI::access_denied(); + break; + } + + // Show the create page + require_once Config::get('prefix') . '/templates/show_create_democratic.inc.php'; + break; + case 'delete': + if (!Access::check('interface','75')) { + UI::access_denied(); + break; + } + + Democratic::delete($_REQUEST['democratic_id']); + + $title = ''; + $text = T_('The Requested Playlist has been deleted.'); + $url = Config::get('web_path') . '/democratic.php?action=manage_playlists'; + show_confirmation($title,$text,$url); + break; + case 'create': + // Only power users here + if (!Access::check('interface','75')) { + UI::access_denied(); + break; + } + + if (!Core::form_verify('create_democratic')) { + UI::access_denied(); + exit; + } + + $democratic = Democratic::get_current_playlist(); + + // If we don't have anything currently create something + if (!$democratic->id) { + // Create the playlist + Democratic::create($_POST); + $democratic = Democratic::get_current_playlist(); + } + else { + $democratic->update($_POST); + } + + // Now check for additional things we might have to do + if ($_POST['force_democratic']) { + Democratic::set_user_preferences(); + } + + header("Location: " . Config::get('web_path') . "/democratic.php?action=show"); + break; + case 'manage_playlists': + if (!Access::check('interface','75')) { + UI::access_denied(); + break; + } + // Get all of the non-user playlists + $playlists = Democratic::get_playlists(); + + require_once Config::get('prefix') . '/templates/show_manage_democratic.inc.php'; + + break; + case 'show_playlist': + default: + $democratic = Democratic::get_current_playlist(); + if (!$democratic->id) { + require_once Config::get('prefix') . '/templates/show_democratic.inc.php'; + break; + } + + $democratic->set_parent(); + $democratic->format(); + require_once Config::get('prefix') . '/templates/show_democratic.inc.php'; + $objects = $democratic->get_items(); + Song::build_cache($democratic->object_ids); + Democratic::build_vote_cache($democratic->vote_ids); + $browse = new Browse(); + $browse->set_type('democratic'); + $browse->set_static_content(true); + $browse->show_objects($objects); + $browse->store(); + break; } // end switch on action UI::show_footer(); diff --git a/flag.php b/flag.php index 5ae3f143c9..20f698f307 100644 --- a/flag.php +++ b/flag.php @@ -1,5 +1,5 @@ add($id,$type,$flag_type,$comment); - show_confirmation(T_('Item Flagged'), T_('The specified item has been flagged'),$_SESSION['source_page']); - break; - case 'show_flag': - /* Store where they came from */ - $_SESSION['source_page'] = return_referer(); - require Config::get('prefix') . '/templates/show_flag.inc.php'; - break; - case 'show_remove_flag': - - break; - default: - - break; + case 'remove_flag': + break; + case 'flag': + $id = scrub_in($_REQUEST['id']); + $type = scrub_in($_REQUEST['type']); + $flag_type = scrub_in($_REQUEST['flag_type']); + $comment = scrub_in($_REQUEST['comment']); + $flag->add($id,$type,$flag_type,$comment); + show_confirmation(T_('Item Flagged'), T_('The specified item has been flagged'),$_SESSION['source_page']); + break; + case 'show_flag': + /* Store where they came from */ + $_SESSION['source_page'] = return_referer(); + require Config::get('prefix') . '/templates/show_flag.inc.php'; + break; + case 'show_remove_flag': + + break; + default: + + break; } // end action switch UI::show_footer(); diff --git a/image.php b/image.php index 4a1dcbedf2..243fd26935 100644 --- a/image.php +++ b/image.php @@ -1,5 +1,5 @@ name; + case 'popup': + require_once Config::get('prefix') . '/templates/show_big_art.inc.php'; + break; + // If we need to pull the data out of the session + case 'session': + vauth::check_session(); + $filename = scrub_in($_REQUEST['image_index']); + $image = Art::get_from_source($_SESSION['form']['images'][$filename], 'album'); + $mime = $_SESSION['form']['images'][$filename]['mime']; + break; + default: + $media = new $type($_GET['id']); + $filename = $media->name; - $art = new Art($media->id,$type); - $art->get_db(); + $art = new Art($media->id,$type); + $art->get_db(); - if (!$art->raw_mime) { - $mime = 'image/jpeg'; - $image = file_get_contents(Config::get('prefix') . - Config::get('theme_path') . - '/images/blankalbum.jpg'); - } - else { - if ($_GET['thumb']) { - $thumb_data = $art->get_thumb($size); - } - - $mime = $thumb_data - ? $thumb_data['thumb_mime'] - : $art->raw_mime; - $image = $thumb_data - ? $thumb_data['thumb'] - : $art->raw; - } - break; + if (!$art->raw_mime) { + $mime = 'image/jpeg'; + $image = file_get_contents(Config::get('prefix') . + Config::get('theme_path') . + '/images/blankalbum.jpg'); + } + else { + if ($_GET['thumb']) { + $thumb_data = $art->get_thumb($size); + } + + $mime = $thumb_data + ? $thumb_data['thumb_mime'] + : $art->raw_mime; + $image = $thumb_data + ? $thumb_data['thumb'] + : $art->raw; + } + break; } // end switch type if ($image) { - $extension = Art::extension($mime); - $filename = scrub_out($filename . '.' . $extension); + $extension = Art::extension($mime); + $filename = scrub_out($filename . '.' . $extension); - // Send the headers and output the image - $browser = new Horde_Browser(); - $browser->downloadHeaders($filename, $mime, true); - echo $image; + // Send the headers and output the image + $browser = new Horde_Browser(); + $browser->downloadHeaders($filename, $mime, true); + echo $image; } ?> diff --git a/index.php b/index.php index a1d2d3a4b3..0fd66f30dd 100644 --- a/index.php +++ b/index.php @@ -1,5 +1,5 @@ 5) { - $refresh_limit = Config::get('refresh_limit'); - $ajax_url = '?page=index&action=reloadnp'; - require_once Config::get('prefix') . '/templates/javascript_refresh.inc.php'; + $refresh_limit = Config::get('refresh_limit'); + $ajax_url = '?page=index&action=reloadnp'; + require_once Config::get('prefix') . '/templates/javascript_refresh.inc.php'; } require_once Config::get('prefix') . '/templates/show_index.inc.php'; diff --git a/install.php b/install.php index b78d31ef5f..ed16ea5f0d 100644 --- a/install.php +++ b/install.php @@ -1,5 +1,5 @@ $username, - 'database_password' => $password, - 'database_hostname' => $hostname - ), true - ); - if (!Dba::check_database()) { - Error::add('config', T_('Error: Unable to make Database Connection: ') . Dba::error()); - } - - // Was download pressed? - $download = (!isset($_POST['write'])); - - if (!Error::occurred()) { - $created_config = install_create_config($web_path,$username,$password,$hostname,$database,$download); - } - - require_once 'templates/show_install_config.inc.php'; - break; - case 'show_create_config': + case 'create_db': + /* Get the variables for the language */ + $htmllang = $_REQUEST['htmllang']; + $charset = $_REQUEST['charset']; + + // Set the lang in the conf array + Config::set('lang', $htmllang, true); + Config::set('site_charset', $charset, true); + load_gettext(); + + if (!install_insert_db($username,$password,$hostname,$database)) { + require_once 'templates/show_install.inc.php'; + break; + } + + // Now that it's inserted save the lang preference + Preference::update('lang','-1',$htmllang); + + header ("Location: " . WEB_PATH . "?action=show_create_config&local_db=$database&local_host=$hostname&htmllang=$htmllang&charset=$charset"); + + break; + case 'create_config': + + $htmllang = $_REQUEST['htmllang']; + $charset = $_REQUEST['charset']; + // Test and make sure that the values they give us actually work + Config::set_by_array(array( + 'database_username' => $username, + 'database_password' => $password, + 'database_hostname' => $hostname + ), true + ); + if (!Dba::check_database()) { + Error::add('config', T_('Error: Unable to make Database Connection: ') . Dba::error()); + } + + // Was download pressed? + $download = (!isset($_POST['write'])); + + if (!Error::occurred()) { + $created_config = install_create_config($web_path,$username,$password,$hostname,$database,$download); + } + + require_once 'templates/show_install_config.inc.php'; + break; + case 'show_create_config': /* Attempt to Guess the Web_path */ - $web_path = dirname($_SERVER['PHP_SELF']); - $web_path = rtrim($web_path,"\/"); - - /* Get the variables for the language */ - $htmllang = $_REQUEST['htmllang']; - $charset = $_REQUEST['charset']; - - // Set the lang in the conf array - Config::set('lang', $htmllang, true); - - // We need the charset for the different languages - $charsets = array( - 'ar_SA' => 'UTF-8', - 'de_DE' => 'ISO-8859-15', - 'en_US' => 'iso-8859-1', - 'en_GB' => 'UTF-8', - 'ja_JP' => 'UTF-8', - 'es_ES' => 'iso-8859-1', - 'fr_FR' => 'iso-8859-1', - 'el_GR' => 'el_GR.utf-8', - 'it_IT' => 'UTF-8', - 'nl_NL' => 'ISO-8859-15', - 'tr_TR' => 'iso-8859-9', - 'zh_CN' => 'GBK'); - $charset = $charsets[$_REQUEST['htmllang']]; - - // Set the site_charset in the conf array - Config::set('site_charset', $charsets[$_REQUEST['htmllang']], true); - - /* load_gettext mojo */ - load_gettext(); - header ("Content-Type: text/html; charset=" . Config::get('site_charset')); - - require_once 'templates/show_install_config.inc.php'; - break; - case 'create_account': - - $results = parse_ini_file($configfile); - Config::set_by_array($results, true); - - /* Get the variables for the language */ - $htmllang = $_REQUEST['htmllang']; - $charset = $_REQUEST['charset']; - - // Set the lang in the conf array - Config::set('lang', $htmllang, true); - Config::set('site_charset', $charset, true); - load_gettext(); - - $password2 = scrub_in($_REQUEST['local_pass2']); - - if (!install_create_account($username,$password,$password2)) { - require_once Config::get('prefix') . '/templates/show_install_account.inc.php'; - break; - } - - header ("Location: " . WEB_ROOT . "/login.php"); - break; - case 'show_create_account': - - $results = parse_ini_file($configfile); - - /* Get the variables for the language */ - $htmllang = $_REQUEST['htmllang']; - $charset = $_REQUEST['charset']; - - // Set the lang in the conf array - Config::set('lang', $htmllang, true); - Config::set('site_charset', $charset, true); - load_gettext(); - - /* Make sure we've got a valid config file */ - if (!check_config_values($results)) { - Error::add('general', T_('Error: Config file not found or Unreadable')); - require_once Config::get('prefix') . '/templates/show_install_config.inc.php'; - break; - } - - /* Get the variables for the language */ - $htmllang = $_REQUEST['htmllang']; - $charset = $_REQUEST['charset']; - - // Set the lang in the conf array - Config::set('lang', $htmllang, true); - - // We need the charset for the different languages - $charsets = array( - 'ar_SA' => 'UTF-8', - 'de_DE' => 'ISO-8859-15', - 'en_US' => 'iso-8859-1', - 'ja_JP' => 'UTF-8', - 'en_GB' => 'UTF-8', - 'es_ES' => 'iso-8859-1', - 'fr_FR' => 'iso-8859-1', - 'it_IT' => 'UTF-8', - 'nl_NL' => 'ISO-8859-15', - 'tr_TR' => 'iso-8859-9', - 'zh_CN' => 'GBK'); - $charset = $charsets[$_REQUEST['htmllang']]; - - // Set the site_charset in the conf array - Config::set('site_charset', $charsets[$_REQUEST['htmllang']], true); - - /* load_gettext mojo */ - load_gettext(); - header ("Content-Type: text/html; charset=" . Config::get('site_charset')); - - require_once Config::get('prefix') . '/templates/show_install_account.inc.php'; - break; + $web_path = dirname($_SERVER['PHP_SELF']); + $web_path = rtrim($web_path,"\/"); + + /* Get the variables for the language */ + $htmllang = $_REQUEST['htmllang']; + $charset = $_REQUEST['charset']; + + // Set the lang in the conf array + Config::set('lang', $htmllang, true); + + // We need the charset for the different languages + $charsets = array( + 'ar_SA' => 'UTF-8', + 'de_DE' => 'ISO-8859-15', + 'en_US' => 'iso-8859-1', + 'en_GB' => 'UTF-8', + 'ja_JP' => 'UTF-8', + 'es_ES' => 'iso-8859-1', + 'fr_FR' => 'iso-8859-1', + 'el_GR' => 'el_GR.utf-8', + 'it_IT' => 'UTF-8', + 'nl_NL' => 'ISO-8859-15', + 'tr_TR' => 'iso-8859-9', + 'zh_CN' => 'GBK'); + $charset = $charsets[$_REQUEST['htmllang']]; + + // Set the site_charset in the conf array + Config::set('site_charset', $charsets[$_REQUEST['htmllang']], true); + + /* load_gettext mojo */ + load_gettext(); + header ("Content-Type: text/html; charset=" . Config::get('site_charset')); + + require_once 'templates/show_install_config.inc.php'; + break; + case 'create_account': + + $results = parse_ini_file($configfile); + Config::set_by_array($results, true); + + /* Get the variables for the language */ + $htmllang = $_REQUEST['htmllang']; + $charset = $_REQUEST['charset']; + + // Set the lang in the conf array + Config::set('lang', $htmllang, true); + Config::set('site_charset', $charset, true); + load_gettext(); + + $password2 = scrub_in($_REQUEST['local_pass2']); + + if (!install_create_account($username,$password,$password2)) { + require_once Config::get('prefix') . '/templates/show_install_account.inc.php'; + break; + } + + header ("Location: " . WEB_ROOT . "/login.php"); + break; + case 'show_create_account': + + $results = parse_ini_file($configfile); + + /* Get the variables for the language */ + $htmllang = $_REQUEST['htmllang']; + $charset = $_REQUEST['charset']; + + // Set the lang in the conf array + Config::set('lang', $htmllang, true); + Config::set('site_charset', $charset, true); + load_gettext(); + + /* Make sure we've got a valid config file */ + if (!check_config_values($results)) { + Error::add('general', T_('Error: Config file not found or Unreadable')); + require_once Config::get('prefix') . '/templates/show_install_config.inc.php'; + break; + } + + /* Get the variables for the language */ + $htmllang = $_REQUEST['htmllang']; + $charset = $_REQUEST['charset']; + + // Set the lang in the conf array + Config::set('lang', $htmllang, true); + + // We need the charset for the different languages + $charsets = array( + 'ar_SA' => 'UTF-8', + 'de_DE' => 'ISO-8859-15', + 'en_US' => 'iso-8859-1', + 'ja_JP' => 'UTF-8', + 'en_GB' => 'UTF-8', + 'es_ES' => 'iso-8859-1', + 'fr_FR' => 'iso-8859-1', + 'it_IT' => 'UTF-8', + 'nl_NL' => 'ISO-8859-15', + 'tr_TR' => 'iso-8859-9', + 'zh_CN' => 'GBK'); + $charset = $charsets[$_REQUEST['htmllang']]; + + // Set the site_charset in the conf array + Config::set('site_charset', $charsets[$_REQUEST['htmllang']], true); + + /* load_gettext mojo */ + load_gettext(); + header ("Content-Type: text/html; charset=" . Config::get('site_charset')); + + require_once Config::get('prefix') . '/templates/show_install_account.inc.php'; + break; case 'init': - /* First step of installation */ - // Get the language - $htmllang = $_POST['htmllang']; - - // Set the lang in the conf array - Config::set('lang', $htmllang, true); - - // We need the charset for the different languages - $charsets = array( - 'ar_SA' => 'UTF-8', - 'de_DE' => 'ISO-8859-15', - 'en_US' => 'iso-8859-1', - 'cs_CZ' => 'UTF-8', - 'ja_JP' => 'UTF-8', - 'en_GB' => 'UTF-8', - 'es_ES' => 'iso-8859-1', - 'fr_FR' => 'iso-8859-1', - 'it_IT' => 'UTF-8', - 'nl_NL' => 'ISO-8859-15', - 'tr_TR' => 'iso-8859-9', - 'zh_CN' => 'GBK'); - $charset = $charsets[$_POST['htmllang']]; - - // Set the site_charset in the conf array - Config::set('site_charset', $charsets[$_POST['htmllang']], true); - - // Now we make voodoo with the Load gettext mojo - load_gettext(); - - // Page ready :) - header ("Content-Type: text/html; charset=$charset"); - require_once 'templates/show_install.inc.php'; - break; + /* First step of installation */ + // Get the language + $htmllang = $_POST['htmllang']; + + // Set the lang in the conf array + Config::set('lang', $htmllang, true); + + // We need the charset for the different languages + $charsets = array( + 'ar_SA' => 'UTF-8', + 'de_DE' => 'ISO-8859-15', + 'en_US' => 'iso-8859-1', + 'cs_CZ' => 'UTF-8', + 'ja_JP' => 'UTF-8', + 'en_GB' => 'UTF-8', + 'es_ES' => 'iso-8859-1', + 'fr_FR' => 'iso-8859-1', + 'it_IT' => 'UTF-8', + 'nl_NL' => 'ISO-8859-15', + 'tr_TR' => 'iso-8859-9', + 'zh_CN' => 'GBK'); + $charset = $charsets[$_POST['htmllang']]; + + // Set the site_charset in the conf array + Config::set('site_charset', $charsets[$_POST['htmllang']], true); + + // Now we make voodoo with the Load gettext mojo + load_gettext(); + + // Page ready :) + header ("Content-Type: text/html; charset=$charset"); + require_once 'templates/show_install.inc.php'; + break; default: - if ($_ENV['LANG']) { - $lang = $_ENV['LANG']; - } else { - $lang = "en_US"; - } - if(strpos($lang, ".")) { - $langtmp = explode(".", $lang); - $htmllang = $langtmp[0]; - $charset = $langtmp[1]; - } else { - $htmllang = $lang; - $charset = "UTF-8"; - } - Config::set('lang', $htmllang, true); - Config::set('site_charset', $charset, true); - load_gettext(); - - /* Show the language options first */ - require_once 'templates/show_install_lang.inc.php'; - break; + if ($_ENV['LANG']) { + $lang = $_ENV['LANG']; + } else { + $lang = "en_US"; + } + if(strpos($lang, ".")) { + $langtmp = explode(".", $lang); + $htmllang = $langtmp[0]; + $charset = $langtmp[1]; + } else { + $htmllang = $lang; + $charset = "UTF-8"; + } + Config::set('lang', $htmllang, true); + Config::set('site_charset', $charset, true); + load_gettext(); + + /* Show the language options first */ + require_once 'templates/show_install_lang.inc.php'; + break; } // end action switch ?> diff --git a/lib/batch.lib.php b/lib/batch.lib.php index b9f208757d..bd6be0a1c6 100644 --- a/lib/batch.lib.php +++ b/lib/batch.lib.php @@ -1,5 +1,5 @@ enabled) { - $total_size += sprintf("%.2f",($media->size/1048576)); - array_push($media_files, $media->file); - } + foreach ($media_ids as $element) { + if (is_array($element)) { + $type = array_shift($element); + $media = new $type(array_shift($element)); + } + else { + $media = new Song($element); + } + if ($media->enabled) { + $total_size += sprintf("%.2f",($media->size/1048576)); + array_push($media_files, $media->file); + } } return array($media_files,$total_size); @@ -54,51 +54,51 @@ function get_song_files($media_ids) { * takes array of full paths to songs * zips them and sends them * - * @param string $name name of the zip file to be created - * @param string $song_files array of full paths to songs to zip create w/ call to get_song_files + * @param string $name name of the zip file to be created + * @param string $song_files array of full paths to songs to zip create w/ call to get_song_files */ function send_zip( $name, $song_files ) { - // Check if they want to save it to a file, if so then make sure they've - // got a defined path as well and that it's writable. - if (Config::get('file_zip_download') && Config::get('file_zip_path')) { - // Check writeable - if (!is_writable(Config::get('file_zip_path'))) { - $in_memory = '1'; - debug_event('Error','File Zip Path:' . Config::get('file_zip_path') . ' is not writable','1'); - } - else { - $in_memory = '0'; - $basedir = Config::get('file_zip_path'); - } + // Check if they want to save it to a file, if so then make sure they've + // got a defined path as well and that it's writable. + if (Config::get('file_zip_download') && Config::get('file_zip_path')) { + // Check writeable + if (!is_writable(Config::get('file_zip_path'))) { + $in_memory = '1'; + debug_event('Error','File Zip Path:' . Config::get('file_zip_path') . ' is not writable','1'); + } + else { + $in_memory = '0'; + $basedir = Config::get('file_zip_path'); + } - } else { - $in_memory = '1'; - } // if file downloads + } else { + $in_memory = '1'; + } // if file downloads - /* Require needed library */ + /* Require needed library */ require_once Config::get('prefix') . '/modules/archive/archive.lib.php'; $arc = new zip_file( $name . ".zip" ); $options = array( 'inmemory' => $in_memory, // create archive in memory - 'basedir' => $basedir, + 'basedir' => $basedir, 'storepaths' => 0, // only store file name, not full path 'level' => 0, // no compression - 'comment' => Config::get('file_zip_comment') + 'comment' => Config::get('file_zip_comment') ); $arc->set_options( $options ); $arc->add_files( $song_files ); - if (count($arc->error)) { - debug_event('archive',"Error: unable to add songs",'3'); - return false; - } // if failed to add songs + if (count($arc->error)) { + debug_event('archive',"Error: unable to add songs",'3'); + return false; + } // if failed to add songs if (!$arc->create_archive()) { - debug_event('archive',"Error: unable to create archive",'3'); - return false; - } // if failed to create archive + debug_event('archive',"Error: unable to create archive",'3'); + return false; + } // if failed to create archive $arc->download_file(); diff --git a/lib/class/access.class.php b/lib/class/access.class.php index ad4f41628c..b72b7f3ae6 100644 --- a/lib/class/access.class.php +++ b/lib/class/access.class.php @@ -1,5 +1,5 @@ id = intval($access_id); - - $info = $this->_get_info(); - foreach ($info as $key=>$value) { - $this->$key = $value; - } - - return true; - - } // Constructor - - /** - * _get_info - * - * get's the vars for $this out of the database - * Taken from the object - * - * @return resource - */ - private function _get_info() { - - /* Grab the basic information from the catalog and return it */ - $sql = "SELECT * FROM `access_list` WHERE `id`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - - return $results; - - } // _get_info - - /** - * format - * - * This makes the Access object a nice fuzzy human readable object, spiffy ain't it. - * - * @return void - */ - public function format() { - - $this->f_start = inet_ntop($this->start); - $this->f_end = inet_ntop($this->end); - - $this->f_user = $this->get_user_name(); - $this->f_level = $this->get_level_name(); - $this->f_type = $this->get_type_name(); - - } // format - - /** - * update - * - * This function takes a named array as a datasource and updates the current access list entry - * - * @param array $data xxx - * @return boolean - */ - public function update($data) { - - /* We need to verify the incomming data a littlebit */ - $start = @inet_pton($data['start']); - $end = @inet_pton($data['end']); - - if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') { - Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered')); - return false; - } - if (!$end) { - Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered')); - return false; - } - - if (strlen(bin2hex($start)) != strlen(bin2hex($end))) { - Error::add('start', T_('IP Address Version Mismatch')); - Error::add('end', T_('IP Address Version Mismatch')); - return false; - } - - $name = Dba::escape($data['name']); - $type = self::validate_type($data['type']); - $start = Dba::escape(inet_pton($data['start'])); - $end = Dba::escape(inet_pton($data['end'])); - $level = Dba::escape($data['level']); - $user = $data['user'] ? Dba::escape($data['user']) : '-1'; - $enabled = make_bool($data['enabled']) ? 1 : 0; - - $sql = "UPDATE `access_list` " . - "SET `start`='$start', `end`='$end', `level`='$level', `user`='$user', " . - "`name`='$name', `type`='$type',`enabled`='$enabled' WHERE `id`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::write($sql); - - return true; - - } // update - - /** - * create - * - * This takes a key'd array of data and trys to insert it as a - * new ACL entry - * - * @param array $data xxx - * @return boolean - */ - public static function create($data) { - - /* We need to verify the incomming data a littlebit */ - $start = @inet_pton($data['start']); - $end = @inet_pton($data['end']); - - if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') { - Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered')); - return false; - } - if (!$end) { - Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered')); - return false; - } - - if (strlen(bin2hex($start)) != strlen(bin2hex($end))) { - Error::add('start', T_('IP Address Version Mismatch')); - Error::add('end', T_('IP Address Version Mismatch')); - return false; - } - - // Check existing ACL's to make sure we're not duplicating values here - if (self::exists($data)) { - debug_event('ACL Create','Error: An ACL equal to the created one does already exist. Not adding another one: ' . $data['start'] . ' - ' . $data['end'],'1'); - Error::add('general', T_('Duplicate ACL defined')); - return false; - } - - $start = Dba::escape($start); - $end = Dba::escape($end); - $name = Dba::escape($data['name']); - $user = $data['user'] ? Dba::escape($data['user']) : '-1'; - $level = intval($data['level']); - $type = self::validate_type($data['type']); - $enabled = make_bool($data['enabled']) ? 1 : 0; - - $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`user`,`type`,`enabled`) " . - "VALUES ('$name','$level','$start','$end','$user','$type','$enabled')"; - $db_results = Dba::write($sql); - - return true; - - } // create - - /** - * exists - * - * this sees if the ACL that we've specified already exists, prevent duplicates. This ignores the name - * - * @param array $data xxx - * @return boolean - */ - public static function exists($data) { - - $start = Dba::escape(inet_pton($data['start'])); - $end = Dba::escape(inet_pton($data['end'])); - $type = self::validate_type($data['type']); - $user = $data['user'] ? Dba::escape($data['user']) : '-1'; - - $sql = "SELECT * FROM `access_list` WHERE `start`='$start' AND `end` = '$end' " . - "AND `type`='$type' AND `user`='$user'"; - $db_results = Dba::read($sql); - - if (Dba::fetch_assoc($db_results)) { - return true; - } - - return false; - - } // exists - - /** - * delete - * - * deletes the specified access_list entry - * - * @param integer $access_id xxx - * @return void - */ - public static function delete($access_id) { - - $sql = "DELETE FROM `access_list` WHERE `id`='" . Dba::escape($access_id) . "'"; - $db_results = Dba::write($sql); - - } // delete - - /** - * check_function - * - * This checks if a specific functionality is enabled - * it takes a type only - * - * @param string $type check type xxx - * @return mixed boolean or config - */ - public static function check_function($type) { - - switch ($type) { - case 'download': - return Config::get('download'); - break ; - case 'batch_download': - if (!function_exists('gzcompress')) { - debug_event('gzcompress','ZLIB Extensions not loaded, batch download disabled','3'); - return false; - } - if (Config::get('allow_zip_download') AND $GLOBALS['user']->has_access('25')) { - return Config::get('download'); - } - break; - default: - return false; - break; - } // end switch - - } // check_function - - /** - * check_network - * - * This takes a type, ip, user, level and key - * and then returns true or false if they have access to this - * the IP is passed as a dotted quad - * - * @param string $type Check type. - * @param string $user User name. - * @param integer $level Access level. - * @param string $ip IP Address. - * @return boolean - */ - public static function check_network($type, $user, $level, $ip=null) { - - if (!Config::get('access_control')) { - switch ($type) { - case 'interface': - case 'stream': - return true; - break; - default: - return false; - } // end switch - } // end if access control is turned off - - // Clean incoming variables - $ip = $ip - ? Dba::escape(inet_pton($ip)) - : Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])); - $user = Dba::escape($user); - $level = Dba::escape($level); - - switch ($type) { - case 'init-api': - if ($user) { - $user = User::get_from_username($user); - $user = $user->id; - } - case 'api': - $type = 'rpc'; - case 'network': - case 'interface': - case 'stream': - break; - default: - return false; - break; - } // end switch on type - - $sql = 'SELECT `id` FROM `access_list` ' . - "WHERE `start` <= '$ip' AND `end` >= '$ip' " . - "AND `level` >= '$level' AND `type` = '$type'"; - - if (strlen($user) && $user != '-1') { - $sql .= " AND `user` IN('$user', '-1')"; - } - else { - $sql .= " AND `user` = '-1'"; - } - - $db_results = Dba::read($sql); - - if (Dba::fetch_row($db_results)) { - // Yah they have access they can use the mojo - return true; - } - - return false; - } // check_network - - /** - * check_access - * This is the global 'has_access' function it can check for any 'type' - * of object. - * Everything uses the global 0,5,25,50,75,100 stuff. GLOBALS['user'] is - * always used. - */ - public static function check($type,$level) { - - if (Config::get('demo_mode')) { return true; } - if (defined('INSTALL')) { return true; } - - $level = intval($level); - - // Switch on the type - switch ($type) { - case 'localplay': - // Check their localplay_level - if (Config::get('localplay_level') >= $level OR $GLOBALS['user']->access >= '100') { - return true; - } - else { - return false; - } - break; - case 'interface': - // Check their standard user level - if ($GLOBALS['user']->access >= $level) { - return true; - } - else { - return false; - } - break; - default: - return false; - break; - } // end switch on type - - // Default false - return false; - - } // check - - /** - * validate_type - * This cleans up and validates the specified type - */ - public static function validate_type($type) { - - switch($type) { - case 'rpc': - case 'interface': - case 'network': - return $type; - break; - case 'xml-rpc': - return 'rpc'; - break; - default: - return 'stream'; - break; - } // end switch - - } // validate_type - - /** - * get_access_lists - * returns a full listing of all access rules on this server - */ - public static function get_access_lists() { - - $sql = "SELECT `id` FROM `access_list`"; - $db_results = Dba::read($sql); - - $results = array(); - - // Man this is the wrong way to do it... - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } // end while access list mojo - - return $results; - - } // get_access_lists - - - /** - * get_level_name - * take the int level and return a named level - */ - public function get_level_name() { - - if ($this->level >= '75') { - return T_('All'); - } - if ($this->level == '5') { - return T_('View'); - } - if ($this->level == '25') { - return T_('Read'); - } - if ($this->level == '50') { - return T_('Read/Write'); - } - - } // get_level_name - - /** - * get_user_name - * Take a user and return their full name - */ - public function get_user_name() { - - if ($this->user == '-1') { return T_('All'); } - - $user = new User($this->user); - return $user->fullname . " (" . $user->username . ")"; - - } // get_user_name - - /** - * get_type_name - * This function returns the pretty name for our current type - */ - public function get_type_name() { - - switch ($this->type) { - case 'xml-rpc': - case 'rpc': - return T_('API/RPC'); - break; - case 'network': - return T_('Local Network Definition'); - break; - case 'interface': - return T_('Web Interface'); - break; - case 'stream': - default: - return T_('Stream Access'); - break; - } // end switch - - } // get_type_name - - /** - * session_exists - * This checks to see if the specified session of the specified type - * exists, it also provides an array of key'd data that may be required - * based on the type - */ - public static function session_exists($data,$key,$type) { - - // Switch on the type they pass - switch ($type) { - case 'api': - $key = Dba::escape($key); - $time = time(); - $sql = "SELECT * FROM `session_api` WHERE `id`='$key' AND `expire` > '$time'"; - $db_results = Dba::read($sql); - - if (Dba::num_rows($db_results)) { - $time = $time + 3600; - $sql = "UPDATE `session_api` WHERE `id`='$key' SET `expire`='$time'"; - $db_results = Dba::write($sql); - return true; - } - - return false; - - break; - case 'stream': - - break; - case 'interface': - - break; - default: - return false; - break; - } // type - - - } // session_exists + // Variables from DB + + /** + * User ID + * + * @var integer + */ + public $id; + + /** + * + */ + public $name; + + /** + * + */ + public $start; + + /** + * + */ + public $end; + + /** + * + */ + public $level; + + /** + * + */ + public $user; + + /** + * + */ + public $type; + + /** + * + */ + public $enabled; + + /** + * constructor + * + * Takes an ID of the access_id dealie :) + * + * @param integer $access_id ID of the access_id + * @return boolean + */ + public function __construct($access_id='') { + + if (!$access_id) { return false; } + + /* Assign id for use in get_info() */ + $this->id = intval($access_id); + + $info = $this->_get_info(); + foreach ($info as $key=>$value) { + $this->$key = $value; + } + + return true; + + } // Constructor + + /** + * _get_info + * + * get's the vars for $this out of the database + * Taken from the object + * + * @return resource + */ + private function _get_info() { + + /* Grab the basic information from the catalog and return it */ + $sql = "SELECT * FROM `access_list` WHERE `id`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + + return $results; + + } // _get_info + + /** + * format + * + * This makes the Access object a nice fuzzy human readable object, spiffy ain't it. + * + * @return void + */ + public function format() { + + $this->f_start = inet_ntop($this->start); + $this->f_end = inet_ntop($this->end); + + $this->f_user = $this->get_user_name(); + $this->f_level = $this->get_level_name(); + $this->f_type = $this->get_type_name(); + + } // format + + /** + * update + * + * This function takes a named array as a datasource and updates the current access list entry + * + * @param array $data xxx + * @return boolean + */ + public function update($data) { + + /* We need to verify the incomming data a littlebit */ + $start = @inet_pton($data['start']); + $end = @inet_pton($data['end']); + + if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') { + Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered')); + return false; + } + if (!$end) { + Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered')); + return false; + } + + if (strlen(bin2hex($start)) != strlen(bin2hex($end))) { + Error::add('start', T_('IP Address Version Mismatch')); + Error::add('end', T_('IP Address Version Mismatch')); + return false; + } + + $name = Dba::escape($data['name']); + $type = self::validate_type($data['type']); + $start = Dba::escape(inet_pton($data['start'])); + $end = Dba::escape(inet_pton($data['end'])); + $level = Dba::escape($data['level']); + $user = $data['user'] ? Dba::escape($data['user']) : '-1'; + $enabled = make_bool($data['enabled']) ? 1 : 0; + + $sql = "UPDATE `access_list` " . + "SET `start`='$start', `end`='$end', `level`='$level', `user`='$user', " . + "`name`='$name', `type`='$type',`enabled`='$enabled' WHERE `id`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::write($sql); + + return true; + + } // update + + /** + * create + * + * This takes a key'd array of data and trys to insert it as a + * new ACL entry + * + * @param array $data xxx + * @return boolean + */ + public static function create($data) { + + /* We need to verify the incomming data a littlebit */ + $start = @inet_pton($data['start']); + $end = @inet_pton($data['end']); + + if (!$start AND $data['start'] != '0.0.0.0' AND $data['start'] != '::') { + Error::add('start', T_('Invalid IPv4 / IPv6 Address Entered')); + return false; + } + if (!$end) { + Error::add('end', T_('Invalid IPv4 / IPv6 Address Entered')); + return false; + } + + if (strlen(bin2hex($start)) != strlen(bin2hex($end))) { + Error::add('start', T_('IP Address Version Mismatch')); + Error::add('end', T_('IP Address Version Mismatch')); + return false; + } + + // Check existing ACL's to make sure we're not duplicating values here + if (self::exists($data)) { + debug_event('ACL Create','Error: An ACL equal to the created one does already exist. Not adding another one: ' . $data['start'] . ' - ' . $data['end'],'1'); + Error::add('general', T_('Duplicate ACL defined')); + return false; + } + + $start = Dba::escape($start); + $end = Dba::escape($end); + $name = Dba::escape($data['name']); + $user = $data['user'] ? Dba::escape($data['user']) : '-1'; + $level = intval($data['level']); + $type = self::validate_type($data['type']); + $enabled = make_bool($data['enabled']) ? 1 : 0; + + $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`user`,`type`,`enabled`) " . + "VALUES ('$name','$level','$start','$end','$user','$type','$enabled')"; + $db_results = Dba::write($sql); + + return true; + + } // create + + /** + * exists + * + * this sees if the ACL that we've specified already exists, prevent duplicates. This ignores the name + * + * @param array $data xxx + * @return boolean + */ + public static function exists($data) { + + $start = Dba::escape(inet_pton($data['start'])); + $end = Dba::escape(inet_pton($data['end'])); + $type = self::validate_type($data['type']); + $user = $data['user'] ? Dba::escape($data['user']) : '-1'; + + $sql = "SELECT * FROM `access_list` WHERE `start`='$start' AND `end` = '$end' " . + "AND `type`='$type' AND `user`='$user'"; + $db_results = Dba::read($sql); + + if (Dba::fetch_assoc($db_results)) { + return true; + } + + return false; + + } // exists + + /** + * delete + * + * deletes the specified access_list entry + * + * @param integer $access_id xxx + * @return void + */ + public static function delete($access_id) { + + $sql = "DELETE FROM `access_list` WHERE `id`='" . Dba::escape($access_id) . "'"; + $db_results = Dba::write($sql); + + } // delete + + /** + * check_function + * + * This checks if a specific functionality is enabled + * it takes a type only + * + * @param string $type check type xxx + * @return mixed boolean or config + */ + public static function check_function($type) { + + switch ($type) { + case 'download': + return Config::get('download'); + break ; + case 'batch_download': + if (!function_exists('gzcompress')) { + debug_event('gzcompress','ZLIB Extensions not loaded, batch download disabled','3'); + return false; + } + if (Config::get('allow_zip_download') AND $GLOBALS['user']->has_access('25')) { + return Config::get('download'); + } + break; + default: + return false; + break; + } // end switch + + } // check_function + + /** + * check_network + * + * This takes a type, ip, user, level and key + * and then returns true or false if they have access to this + * the IP is passed as a dotted quad + * + * @param string $type Check type. + * @param string $user User name. + * @param integer $level Access level. + * @param string $ip IP Address. + * @return boolean + */ + public static function check_network($type, $user, $level, $ip=null) { + + if (!Config::get('access_control')) { + switch ($type) { + case 'interface': + case 'stream': + return true; + break; + default: + return false; + } // end switch + } // end if access control is turned off + + // Clean incoming variables + $ip = $ip + ? Dba::escape(inet_pton($ip)) + : Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])); + $user = Dba::escape($user); + $level = Dba::escape($level); + + switch ($type) { + case 'init-api': + if ($user) { + $user = User::get_from_username($user); + $user = $user->id; + } + case 'api': + $type = 'rpc'; + case 'network': + case 'interface': + case 'stream': + break; + default: + return false; + break; + } // end switch on type + + $sql = 'SELECT `id` FROM `access_list` ' . + "WHERE `start` <= '$ip' AND `end` >= '$ip' " . + "AND `level` >= '$level' AND `type` = '$type'"; + + if (strlen($user) && $user != '-1') { + $sql .= " AND `user` IN('$user', '-1')"; + } + else { + $sql .= " AND `user` = '-1'"; + } + + $db_results = Dba::read($sql); + + if (Dba::fetch_row($db_results)) { + // Yah they have access they can use the mojo + return true; + } + + return false; + } // check_network + + /** + * check_access + * This is the global 'has_access' function it can check for any 'type' + * of object. + * Everything uses the global 0,5,25,50,75,100 stuff. GLOBALS['user'] is + * always used. + */ + public static function check($type,$level) { + + if (Config::get('demo_mode')) { return true; } + if (defined('INSTALL')) { return true; } + + $level = intval($level); + + // Switch on the type + switch ($type) { + case 'localplay': + // Check their localplay_level + if (Config::get('localplay_level') >= $level OR $GLOBALS['user']->access >= '100') { + return true; + } + else { + return false; + } + break; + case 'interface': + // Check their standard user level + if ($GLOBALS['user']->access >= $level) { + return true; + } + else { + return false; + } + break; + default: + return false; + break; + } // end switch on type + + // Default false + return false; + + } // check + + /** + * validate_type + * This cleans up and validates the specified type + */ + public static function validate_type($type) { + + switch($type) { + case 'rpc': + case 'interface': + case 'network': + return $type; + break; + case 'xml-rpc': + return 'rpc'; + break; + default: + return 'stream'; + break; + } // end switch + + } // validate_type + + /** + * get_access_lists + * returns a full listing of all access rules on this server + */ + public static function get_access_lists() { + + $sql = "SELECT `id` FROM `access_list`"; + $db_results = Dba::read($sql); + + $results = array(); + + // Man this is the wrong way to do it... + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } // end while access list mojo + + return $results; + + } // get_access_lists + + + /** + * get_level_name + * take the int level and return a named level + */ + public function get_level_name() { + + if ($this->level >= '75') { + return T_('All'); + } + if ($this->level == '5') { + return T_('View'); + } + if ($this->level == '25') { + return T_('Read'); + } + if ($this->level == '50') { + return T_('Read/Write'); + } + + } // get_level_name + + /** + * get_user_name + * Take a user and return their full name + */ + public function get_user_name() { + + if ($this->user == '-1') { return T_('All'); } + + $user = new User($this->user); + return $user->fullname . " (" . $user->username . ")"; + + } // get_user_name + + /** + * get_type_name + * This function returns the pretty name for our current type + */ + public function get_type_name() { + + switch ($this->type) { + case 'xml-rpc': + case 'rpc': + return T_('API/RPC'); + break; + case 'network': + return T_('Local Network Definition'); + break; + case 'interface': + return T_('Web Interface'); + break; + case 'stream': + default: + return T_('Stream Access'); + break; + } // end switch + + } // get_type_name + + /** + * session_exists + * This checks to see if the specified session of the specified type + * exists, it also provides an array of key'd data that may be required + * based on the type + */ + public static function session_exists($data,$key,$type) { + + // Switch on the type they pass + switch ($type) { + case 'api': + $key = Dba::escape($key); + $time = time(); + $sql = "SELECT * FROM `session_api` WHERE `id`='$key' AND `expire` > '$time'"; + $db_results = Dba::read($sql); + + if (Dba::num_rows($db_results)) { + $time = $time + 3600; + $sql = "UPDATE `session_api` WHERE `id`='$key' SET `expire`='$time'"; + $db_results = Dba::write($sql); + return true; + } + + return false; + + break; + case 'stream': + + break; + case 'interface': + + break; + default: + return false; + break; + } // type + + + } // session_exists } //end of access class diff --git a/lib/class/ajax.class.php b/lib/class/ajax.class.php index 0409886133..e19301bf96 100644 --- a/lib/class/ajax.class.php +++ b/lib/class/ajax.class.php @@ -1,5 +1,5 @@ "; - $observe .= "Event.observe($source_txt,'$method',function(e){" . $action . ";});"; - $observe .= ""; + $observe = ""; - return $observe; + return $observe; - } // observe + } // observe - /** - * url - * This takes a string and makes an URL - */ - public static function url($action) { - return Config::get('ajax_url') . $action; - } + /** + * url + * This takes a string and makes an URL + */ + public static function url($action) { + return Config::get('ajax_url') . $action; + } - /** - * action - * This takes the action, the source and the post (if passed) and - * generates the full ajax link - */ - public static function action($action,$source,$post='') { + /** + * action + * This takes the action, the source and the post (if passed) and + * generates the full ajax link + */ + public static function action($action,$source,$post='') { - $url = self::url($action); + $url = self::url($action); - $non_quoted = array('document','window'); + $non_quoted = array('document','window'); - if (in_array($source,$non_quoted)) { - $source_txt = $source; - } - else { - $source_txt = "'$source'"; - } + if (in_array($source,$non_quoted)) { + $source_txt = $source; + } + else { + $source_txt = "'$source'"; + } - if ($post) { - $ajax_string = "ajaxPost('$url','$post',$source_txt)"; - } - else { - $ajax_string = "ajaxPut('$url',$source_txt)"; - } - - return $ajax_string; + if ($post) { + $ajax_string = "ajaxPost('$url','$post',$source_txt)"; + } + else { + $ajax_string = "ajaxPut('$url',$source_txt)"; + } + + return $ajax_string; - } // action + } // action - /** - * button - * This prints out an img of the specified icon with the specified alt - * text and then sets up the required ajax for it. - */ - public static function button($action,$icon,$alt,$source='',$post='',$class='') { + /** + * button + * This prints out an img of the specified icon with the specified alt + * text and then sets up the required ajax for it. + */ + public static function button($action,$icon,$alt,$source='',$post='',$class='') { - // Get the correct action - $ajax_string = self::action($action,$source,$post); + // Get the correct action + $ajax_string = self::action($action,$source,$post); - // If they passed a span class - if ($class) { - $class = ' class="' . $class . '"'; - } + // If they passed a span class + if ($class) { + $class = ' class="' . $class . '"'; + } - $string = UI::get_icon($icon,$alt); + $string = UI::get_icon($icon,$alt); - // Generate an so that it's more compliant with older - // browsers (ie :hover actions) and also to unify linkbuttons - // (w/o ajax) display - $string = "".$string."\n"; + // Generate an so that it's more compliant with older + // browsers (ie :hover actions) and also to unify linkbuttons + // (w/o ajax) display + $string = "".$string."\n"; - $string .= self::observe($source,'click',$ajax_string); + $string .= self::observe($source,'click',$ajax_string); - return $string; + return $string; - } // button + } // button - /** - * text - * This prints out the specified text as a link and sets up the required - * ajax for the link so it works correctly - */ - public static function text($action,$text,$source,$post='',$class='') { + /** + * text + * This prints out the specified text as a link and sets up the required + * ajax for the link so it works correctly + */ + public static function text($action,$text,$source,$post='',$class='') { - // Format the string we wanna use - $ajax_string = self::action($action,$source,$post); + // Format the string we wanna use + $ajax_string = self::action($action,$source,$post); - // If they passed a span class - if ($class) { - $class = ' class="' . $class . '"'; - } + // If they passed a span class + if ($class) { + $class = ' class="' . $class . '"'; + } - // If we pass a source put it in the ID - $string = "$text\n"; + // If we pass a source put it in the ID + $string = "$text\n"; - $string .= self::observe($source,'click',$ajax_string); + $string .= self::observe($source,'click',$ajax_string); - return $string; + return $string; - } // text + } // text - /** - * run - * This runs the specified action no questions asked - */ - public static function run($action) { + /** + * run + * This runs the specified action no questions asked + */ + public static function run($action) { - echo ""; + echo ""; - } // run + } // run - /** - * set_include_override - * This sets the including div override, used only one place. Kind of a - * hack. - */ - public static function set_include_override($value) { + /** + * set_include_override + * This sets the including div override, used only one place. Kind of a + * hack. + */ + public static function set_include_override($value) { - self::$include_override = make_bool($value); + self::$include_override = make_bool($value); - } // set_include_override + } // set_include_override - /** - * start_container - * This checks to see if we're AJAXin'. If we aren't then it echoes out - * the html needed to start a container that can be replaced by Ajax. - */ - public static function start_container($name) { + /** + * start_container + * This checks to see if we're AJAXin'. If we aren't then it echoes out + * the html needed to start a container that can be replaced by Ajax. + */ + public static function start_container($name) { - if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; } + if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; } - echo '
'; + echo '
'; - } // start_container + } // start_container - /** - * end_container - * This ends the container if we're not doing the AJAX thing - */ - public static function end_container() { + /** + * end_container + * This ends the container if we're not doing the AJAX thing + */ + public static function end_container() { - if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; } + if (defined('AJAX_INCLUDE') && !self::$include_override) { return true; } - echo "
"; + echo "
"; - self::$include_override = false; + self::$include_override = false; - } // end_container + } // end_container } // end Ajax class ?> diff --git a/lib/class/album.class.php b/lib/class/album.class.php index c7b88dcf04..56e458e85b 100644 --- a/lib/class/album.class.php +++ b/lib/class/album.class.php @@ -1,5 +1,5 @@ get_info($id); - - // Foreach what we've got - foreach ($info as $key=>$value) { - $this->$key = $value; - } - - // Little bit of formatting here - $this->full_name = trim(trim($info['prefix']) . ' ' . trim($info['name'])); - - return true; - - } // constructor - - /** - * construct_from_array - * This is often used by the metadata class, it fills out an album object from a - * named array, _fake is set to true - */ - public static function construct_from_array($data) { - - $album = new Album(0); - foreach ($data as $key=>$value) { - $album->$key = $value; - } - - // Make sure that we tell em it's fake - $album->_fake = true; - - return $album; - - } // construct_from_array - - /** - * gc - * - * Cleans out unused albums - */ - public static function gc() { - Dba::write('DELETE FROM `album` USING `album` LEFT JOIN `song` ON `song`.`album` = `album`.`id` WHERE `song`.`id` IS NULL'); - } - - /** - * build_cache - * This takes an array of object ids and caches all of their information - * with a single query - */ - public static function build_cache($ids,$extra=false) { - - // Nothing to do if they pass us nothing - if (!is_array($ids) OR !count($ids)) { return false; } - - $idlist = '(' . implode(',', $ids) . ')'; - - $sql = "SELECT * FROM `album` WHERE `id` IN $idlist"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('album',$row['id'],$row); - } - - // If we're extra'ing cache the extra info as well - if ($extra) { - $sql = "SELECT COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " . - "COUNT(`song`.`id`) AS `song_count`, " . - "`artist`.`name` AS `artist_name`, " . - "`artist`.`prefix` AS `artist_prefix`, " . - "`artist`.`id` AS `artist_id`, `song`.`album`" . - "FROM `song` " . - "INNER JOIN `artist` ON `artist`.`id`=`song`.`artist` " . - "WHERE `song`.`album` IN $idlist GROUP BY `song`.`album`"; - - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $art = new Art($row['album'], 'album'); - $art->get_db(); - $row['has_art'] = make_bool($art->raw); - $row['has_thumb'] = make_bool($art->thumb); - parent::add_to_cache('album_extra',$row['album'],$row); - } // while rows - } // if extra - - return true; - - } // build_cache - - /** - * _get_extra_info - * This pulls the extra information from our tables, this is a 3 table join, which is why we don't normally - * do it - */ - private function _get_extra_info() { - - if (parent::is_cached('album_extra',$this->id)) { - return parent::get_from_cache('album_extra',$this->id); - } - - $sql = "SELECT " . - "COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " . - "COUNT(`song`.`id`) AS `song_count`, " . - "`artist`.`name` AS `artist_name`, " . - "`artist`.`prefix` AS `artist_prefix`, " . - "`artist`.`id` AS `artist_id` " . - "FROM `song` INNER JOIN `artist` " . - "ON `artist`.`id`=`song`.`artist` " . - "WHERE `song`.`album`='$this->id' " . - "GROUP BY `song`.`album`"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - - $art = new Art($this->id, 'album'); - $art->get_db(); - $results['has_art'] = make_bool($art->raw); - $results['has_thumb'] = make_bool($art->thumb); - - parent::add_to_cache('album_extra',$this->id,$results); - - return $results; - - } // _get_extra_info - - /** - * get_songs - * gets the songs for this album takes an optional limit - * and an optional artist, if artist is passed it only gets - * songs with this album + specified artist - */ - public function get_songs($limit = 0,$artist='') { - - $results = array(); - - $artist = Dba::escape($artist); - - $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' "; - if ($artist) { - $sql .= "AND `artist`='$artist'"; - } - $sql .= "ORDER BY `track`, `title`"; - if ($limit) { - $sql .= " LIMIT $limit"; - } - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['id']; - } - - return $results; - - } // get_songs - - /** - * has_track - * This checks to see if this album has a track of the specified title - */ - public function has_track($title) { - - $title = Dba::escape($title); - - $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' AND `title`='$title'"; - $db_results = Dba::read($sql); - - $data = Dba::fetch_assoc($db_results); - - return $data; - - } // has_track - - /** - * format - * This is the format function for this object. It sets cleaned up - * album information with the base required - * f_link, f_name - */ - public function format() { - - $web_path = Config::get('web_path'); - - /* Pull the advanced information */ - $data = $this->_get_extra_info(); - foreach ($data as $key=>$value) { $this->$key = $value; } - - /* Truncate the string if it's to long */ - $this->f_name = UI::truncate($this->full_name,Config::get('ellipse_threshold_album')); - - $this->f_name_link = "id) . "\" title=\"" . scrub_out($this->full_name) . "\">" . scrub_out($this->f_name); - // If we've got a disk append it - if ($this->disk) { - $this->f_name_link .= " disk. "\">[" . T_('Disk') . " " . $this->disk . "]"; - } - $this->f_name_link .=""; - - $this->f_link = $this->f_name_link; - $this->f_title = $this->full_name; // FIXME: Legacy? - if ($this->artist_count == '1') { - $artist = trim(trim($this->artist_prefix) . ' ' . trim($this->artist_name)); - $this->f_artist_name = $artist; - $artist = scrub_out(UI::truncate($artist), Config::get('ellipse_threshold_artist')); - $this->f_artist_link = "artist_id . "\" title=\"" . scrub_out($this->artist_name) . "\">" . $artist . ""; - $this->f_artist = $artist; - } - else { - $this->f_artist_link = "artist_count " . T_('Artists') . "\">" . T_('Various') . ""; - $this->f_artist = T_('Various'); - $this->f_artist_name = $this->f_artist; - } - - if ($this->year == '0') { - $this->year = "N/A"; - } - - $tags = Tag::get_top_tags('album',$this->id); - $this->tags = $tags; - - $this->f_tags = Tag::get_display($tags,$this->id,'album'); - - } // format - - /** - * get_random_songs - * gets a random number, and a random assortment of songs from this album - */ - function get_random_songs() { - - $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' ORDER BY RAND()"; - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_row($db_results)) { - $results[] = $r['0']; - } - - return $results; - - } // get_random_songs - - /** - * update - * This function takes a key'd array of data and updates this object - * as needed, and then throws down with a flag - */ - public function update($data) { - - $year = $data['year']; - $artist = $data['artist']; - $name = $data['name']; - $disk = $data['disk']; - $mbid = $data['mbid']; - - $current_id = $this->id; - - if ($artist != $this->artist_id AND $artist) { - // Update every song - $songs = $this->get_songs(); - foreach ($songs as $song_id) { - Song::update_artist($artist,$song_id); - } - $updated = 1; - Artist::gc(); - } - - $album_id = Catalog::check_album($name,$year,$disk,$mbid); - if ($album_id != $this->id) { - if (!is_array($songs)) { $songs = $this->get_songs(); } - foreach ($songs as $song_id) { - Song::update_album($album_id,$song_id); - Song::update_year($year,$song_id); - } - $current_id = $album_id; - $updated = 1; - self::gc(); - } - - if ($updated) { - // Flag all songs - foreach ($songs as $song_id) { - Flag::add($song_id,'song','retag','Interface Album Update'); - Song::update_utime($song_id); - } // foreach song of album - Stats::gc(); - Rating::gc(); - } // if updated - - - return $current_id; - - } // update - - /** - * get_random_albums - * This returns a random number of albums from the catalogs - * this is used by the index to return some 'potential' albums to play - */ - public static function get_random_albums($count=6) { - - $sql = 'SELECT `id` FROM `album` ORDER BY RAND() LIMIT ' . ($count*2); - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $art = new Art($row['id'], 'album'); - $art->get_db(); - if ($art->raw) { - $results[] = $row['id']; - } - } - - if (count($results) < $count) { return false; } - - $results = array_slice($results, 0, $count); - - return $results; - - } // get_random_albums + /* Variables from DB */ + public $id; + public $name; + public $disk; + public $year; + public $prefix; + public $mbid; // MusicBrainz ID + + public $full_name; // Prefix + Name, generated + + // cached information + public $_songs=array(); + + /** + * __construct + * Album constructor it loads everything relating + * to this album from the database it does not + * pull the album or thumb art by default or + * get any of the counts. + */ + public function __construct($id='') { + + if (!$id) { return false; } + + /* Get the information from the db */ + $info = $this->get_info($id); + + // Foreach what we've got + foreach ($info as $key=>$value) { + $this->$key = $value; + } + + // Little bit of formatting here + $this->full_name = trim(trim($info['prefix']) . ' ' . trim($info['name'])); + + return true; + + } // constructor + + /** + * construct_from_array + * This is often used by the metadata class, it fills out an album object from a + * named array, _fake is set to true + */ + public static function construct_from_array($data) { + + $album = new Album(0); + foreach ($data as $key=>$value) { + $album->$key = $value; + } + + // Make sure that we tell em it's fake + $album->_fake = true; + + return $album; + + } // construct_from_array + + /** + * gc + * + * Cleans out unused albums + */ + public static function gc() { + Dba::write('DELETE FROM `album` USING `album` LEFT JOIN `song` ON `song`.`album` = `album`.`id` WHERE `song`.`id` IS NULL'); + } + + /** + * build_cache + * This takes an array of object ids and caches all of their information + * with a single query + */ + public static function build_cache($ids,$extra=false) { + + // Nothing to do if they pass us nothing + if (!is_array($ids) OR !count($ids)) { return false; } + + $idlist = '(' . implode(',', $ids) . ')'; + + $sql = "SELECT * FROM `album` WHERE `id` IN $idlist"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('album',$row['id'],$row); + } + + // If we're extra'ing cache the extra info as well + if ($extra) { + $sql = "SELECT COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " . + "COUNT(`song`.`id`) AS `song_count`, " . + "`artist`.`name` AS `artist_name`, " . + "`artist`.`prefix` AS `artist_prefix`, " . + "`artist`.`id` AS `artist_id`, `song`.`album`" . + "FROM `song` " . + "INNER JOIN `artist` ON `artist`.`id`=`song`.`artist` " . + "WHERE `song`.`album` IN $idlist GROUP BY `song`.`album`"; + + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $art = new Art($row['album'], 'album'); + $art->get_db(); + $row['has_art'] = make_bool($art->raw); + $row['has_thumb'] = make_bool($art->thumb); + parent::add_to_cache('album_extra',$row['album'],$row); + } // while rows + } // if extra + + return true; + + } // build_cache + + /** + * _get_extra_info + * This pulls the extra information from our tables, this is a 3 table join, which is why we don't normally + * do it + */ + private function _get_extra_info() { + + if (parent::is_cached('album_extra',$this->id)) { + return parent::get_from_cache('album_extra',$this->id); + } + + $sql = "SELECT " . + "COUNT(DISTINCT(`song`.`artist`)) AS `artist_count`, " . + "COUNT(`song`.`id`) AS `song_count`, " . + "`artist`.`name` AS `artist_name`, " . + "`artist`.`prefix` AS `artist_prefix`, " . + "`artist`.`id` AS `artist_id` " . + "FROM `song` INNER JOIN `artist` " . + "ON `artist`.`id`=`song`.`artist` " . + "WHERE `song`.`album`='$this->id' " . + "GROUP BY `song`.`album`"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + + $art = new Art($this->id, 'album'); + $art->get_db(); + $results['has_art'] = make_bool($art->raw); + $results['has_thumb'] = make_bool($art->thumb); + + parent::add_to_cache('album_extra',$this->id,$results); + + return $results; + + } // _get_extra_info + + /** + * get_songs + * gets the songs for this album takes an optional limit + * and an optional artist, if artist is passed it only gets + * songs with this album + specified artist + */ + public function get_songs($limit = 0,$artist='') { + + $results = array(); + + $artist = Dba::escape($artist); + + $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' "; + if ($artist) { + $sql .= "AND `artist`='$artist'"; + } + $sql .= "ORDER BY `track`, `title`"; + if ($limit) { + $sql .= " LIMIT $limit"; + } + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['id']; + } + + return $results; + + } // get_songs + + /** + * has_track + * This checks to see if this album has a track of the specified title + */ + public function has_track($title) { + + $title = Dba::escape($title); + + $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' AND `title`='$title'"; + $db_results = Dba::read($sql); + + $data = Dba::fetch_assoc($db_results); + + return $data; + + } // has_track + + /** + * format + * This is the format function for this object. It sets cleaned up + * album information with the base required + * f_link, f_name + */ + public function format() { + + $web_path = Config::get('web_path'); + + /* Pull the advanced information */ + $data = $this->_get_extra_info(); + foreach ($data as $key=>$value) { $this->$key = $value; } + + /* Truncate the string if it's to long */ + $this->f_name = UI::truncate($this->full_name,Config::get('ellipse_threshold_album')); + + $this->f_name_link = "id) . "\" title=\"" . scrub_out($this->full_name) . "\">" . scrub_out($this->f_name); + // If we've got a disk append it + if ($this->disk) { + $this->f_name_link .= " disk. "\">[" . T_('Disk') . " " . $this->disk . "]"; + } + $this->f_name_link .=""; + + $this->f_link = $this->f_name_link; + $this->f_title = $this->full_name; // FIXME: Legacy? + if ($this->artist_count == '1') { + $artist = trim(trim($this->artist_prefix) . ' ' . trim($this->artist_name)); + $this->f_artist_name = $artist; + $artist = scrub_out(UI::truncate($artist), Config::get('ellipse_threshold_artist')); + $this->f_artist_link = "artist_id . "\" title=\"" . scrub_out($this->artist_name) . "\">" . $artist . ""; + $this->f_artist = $artist; + } + else { + $this->f_artist_link = "artist_count " . T_('Artists') . "\">" . T_('Various') . ""; + $this->f_artist = T_('Various'); + $this->f_artist_name = $this->f_artist; + } + + if ($this->year == '0') { + $this->year = "N/A"; + } + + $tags = Tag::get_top_tags('album',$this->id); + $this->tags = $tags; + + $this->f_tags = Tag::get_display($tags,$this->id,'album'); + + } // format + + /** + * get_random_songs + * gets a random number, and a random assortment of songs from this album + */ + function get_random_songs() { + + $sql = "SELECT `id` FROM `song` WHERE `album`='$this->id' ORDER BY RAND()"; + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_row($db_results)) { + $results[] = $r['0']; + } + + return $results; + + } // get_random_songs + + /** + * update + * This function takes a key'd array of data and updates this object + * as needed, and then throws down with a flag + */ + public function update($data) { + + $year = $data['year']; + $artist = $data['artist']; + $name = $data['name']; + $disk = $data['disk']; + $mbid = $data['mbid']; + + $current_id = $this->id; + + if ($artist != $this->artist_id AND $artist) { + // Update every song + $songs = $this->get_songs(); + foreach ($songs as $song_id) { + Song::update_artist($artist,$song_id); + } + $updated = 1; + Artist::gc(); + } + + $album_id = Catalog::check_album($name,$year,$disk,$mbid); + if ($album_id != $this->id) { + if (!is_array($songs)) { $songs = $this->get_songs(); } + foreach ($songs as $song_id) { + Song::update_album($album_id,$song_id); + Song::update_year($year,$song_id); + } + $current_id = $album_id; + $updated = 1; + self::gc(); + } + + if ($updated) { + // Flag all songs + foreach ($songs as $song_id) { + Flag::add($song_id,'song','retag','Interface Album Update'); + Song::update_utime($song_id); + } // foreach song of album + Stats::gc(); + Rating::gc(); + } // if updated + + + return $current_id; + + } // update + + /** + * get_random_albums + * This returns a random number of albums from the catalogs + * this is used by the index to return some 'potential' albums to play + */ + public static function get_random_albums($count=6) { + + $sql = 'SELECT `id` FROM `album` ORDER BY RAND() LIMIT ' . ($count*2); + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $art = new Art($row['id'], 'album'); + $art->get_db(); + if ($art->raw) { + $results[] = $row['id']; + } + } + + if (count($results) < $count) { return false; } + + $results = array_slice($results, 0, $count); + + return $results; + + } // get_random_albums } //end of album class diff --git a/lib/class/ampache_mail.class.php b/lib/class/ampache_mail.class.php index 8c1d363b28..6b8bc20f52 100644 --- a/lib/class/ampache_mail.class.php +++ b/lib/class/ampache_mail.class.php @@ -1,5 +1,5 @@ sender = $user . '@' . $domain; - $this->sender_name = $fromname; - } // set_default_sender - - /** - * get_users - * This returns an array of userids for people who have e-mail - * addresses based on the passed filter - */ - public static function get_users($filter) { - - switch ($filter) { - default: - case 'all': - $sql = "SELECT * FROM `user` WHERE `email` IS NOT NULL"; - break; - case 'users': - $sql = "SELECT * FROM `user` WHERE `access`='25' AND `email` IS NOT NULL"; - break; - case 'admins': - $sql = "SELECT * FROM `user` WHERE `access`='100' AND `email` IS NOT NULL"; - break ; - case 'inactive': - $inactive = time() - (30*86400); - $sql = "SELECT * FROM `user` WHERE `last_seen` <= '$inactive' AND `email` IS NOT NULL"; - break; - } // end filter switch - - $db_results = Dba::read($sql); - - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = array('id'=>$row['id'],'fullname'=>$row['fullname'],'email'=>$row['email']); - } - - return $results; - - } // get_users - - /** - * add_statistics - * This should be run if we want to add some statistics to this e-mail, - * appends to self::$message - */ - public function add_statistics($methods) { - - - - } // add_statistics - - /** - * send - * This actually sends the mail, how amazing - */ - public function send($phpmailer = null) { - - $mailtype = Config::get('mail_type'); - - if ($phpmailer == null) { - $mail = new PHPMailer(); - - $recipient_name = $this->recipient_name; - if(function_exists('mb_encode_mimeheader')) { - $recipient_name = mb_encode_mimeheader($recipient_name); - } - $mail->AddAddress($this->recipient, $recipient_name); - } - else { - $mail = $phpmailer; - } - - $mail->CharSet = Config::get('site_charset'); - $mail->Encoding = 'base64'; - $mail->From = $this->sender; - $mail->Sender = $this->sender; - $mail->FromName = $this->sender_name; - $mail->Subject = $this->subject; - - if(function_exists('mb_eregi_replace')) { - $this->message = mb_eregi_replace("\r\n", "\n", $this->message); - } - $mail->Body = $this->message; - - $sendmail = Config::get('sendmail_path'); - $sendmail = $sendmail ? $sendmail : '/usr/sbin/sendmail'; - $mailhost = Config::get('mail_host'); - $mailhost = $mailhost ? $mailhost : 'localhost'; - $mailport = Config::get('mail_port'); - $mailport = $mailport ? $mailport : 25; - $mailauth = Config::get('mail_auth'); - $mailuser = Config::get('mail_auth_user'); - $mailuser = $mailuser ? $mailuser : ''; - $mailpass = Config::get('mail_auth_pass'); - $mailpass = $mailpass ? $mailpass : ''; - - switch($mailtype) { - case 'smtp': - $mail->IsSMTP(); - $mail->Host = $mailhost; - $mail->Port = $mailport; - if($mailauth == true) { - $mail->SMTPAuth = true; - $mail->Username = $mailuser; - $mail->Password = $mailpass; - } - if ($mailsecure = Config::get('mail_secure_smtp')) { - $mail->SMTPSecure = ($mailsecure == 'ssl') ? 'ssl' : 'tls'; - } - break; - case 'sendmail': - $mail->IsSendmail(); - $mail->Sendmail = $sendmail; - break; - case 'php': - default: - $mail->IsMail(); - break; - } - - $retval = $mail->send(); - if( $retval == true ) { - return true; - } else { - return false; - } - } // send - - public function send_to_group($group_name) { - $mail = new PHPMailer(); - - foreach(self::get_users($group_name) as $member) { - if(function_exists('mb_encode_mimeheader')) { - $member['fullname'] = mb_encode_mimeheader($member['fullname']); - } - $mail->AddBCC($member['email'], $member['fullname']); - } - - return $this->send($mail); - } + // The message, recipient and from + public $message; + public $subject; + public $recipient; + public $recipient_name; + public $sender; + public $sender_name; + + /** + * Constructor + * + * This does nothing. Much like goggles. + */ + public function __construct() { + + // Eh bien. + + } // Constructor + + /** + * set_default_sender + * + * Does the config magic to figure out the "system" email sender and + * sets it as the sender. + */ + public function set_default_sender() { + $user = Config::get('mail_user'); + if (!$user) { + $user = 'info'; + } + + $domain = Config::get('mail_domain'); + if (!$domain) { + $domain = 'example.com'; + } + + $fromname = Config::get('mail_name'); + if (!$fromname) { + $fromname = 'Ampache'; + } + + $this->sender = $user . '@' . $domain; + $this->sender_name = $fromname; + } // set_default_sender + + /** + * get_users + * This returns an array of userids for people who have e-mail + * addresses based on the passed filter + */ + public static function get_users($filter) { + + switch ($filter) { + default: + case 'all': + $sql = "SELECT * FROM `user` WHERE `email` IS NOT NULL"; + break; + case 'users': + $sql = "SELECT * FROM `user` WHERE `access`='25' AND `email` IS NOT NULL"; + break; + case 'admins': + $sql = "SELECT * FROM `user` WHERE `access`='100' AND `email` IS NOT NULL"; + break ; + case 'inactive': + $inactive = time() - (30*86400); + $sql = "SELECT * FROM `user` WHERE `last_seen` <= '$inactive' AND `email` IS NOT NULL"; + break; + } // end filter switch + + $db_results = Dba::read($sql); + + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = array('id'=>$row['id'],'fullname'=>$row['fullname'],'email'=>$row['email']); + } + + return $results; + + } // get_users + + /** + * add_statistics + * This should be run if we want to add some statistics to this e-mail, + * appends to self::$message + */ + public function add_statistics($methods) { + + + + } // add_statistics + + /** + * send + * This actually sends the mail, how amazing + */ + public function send($phpmailer = null) { + + $mailtype = Config::get('mail_type'); + + if ($phpmailer == null) { + $mail = new PHPMailer(); + + $recipient_name = $this->recipient_name; + if(function_exists('mb_encode_mimeheader')) { + $recipient_name = mb_encode_mimeheader($recipient_name); + } + $mail->AddAddress($this->recipient, $recipient_name); + } + else { + $mail = $phpmailer; + } + + $mail->CharSet = Config::get('site_charset'); + $mail->Encoding = 'base64'; + $mail->From = $this->sender; + $mail->Sender = $this->sender; + $mail->FromName = $this->sender_name; + $mail->Subject = $this->subject; + + if(function_exists('mb_eregi_replace')) { + $this->message = mb_eregi_replace("\r\n", "\n", $this->message); + } + $mail->Body = $this->message; + + $sendmail = Config::get('sendmail_path'); + $sendmail = $sendmail ? $sendmail : '/usr/sbin/sendmail'; + $mailhost = Config::get('mail_host'); + $mailhost = $mailhost ? $mailhost : 'localhost'; + $mailport = Config::get('mail_port'); + $mailport = $mailport ? $mailport : 25; + $mailauth = Config::get('mail_auth'); + $mailuser = Config::get('mail_auth_user'); + $mailuser = $mailuser ? $mailuser : ''; + $mailpass = Config::get('mail_auth_pass'); + $mailpass = $mailpass ? $mailpass : ''; + + switch($mailtype) { + case 'smtp': + $mail->IsSMTP(); + $mail->Host = $mailhost; + $mail->Port = $mailport; + if($mailauth == true) { + $mail->SMTPAuth = true; + $mail->Username = $mailuser; + $mail->Password = $mailpass; + } + if ($mailsecure = Config::get('mail_secure_smtp')) { + $mail->SMTPSecure = ($mailsecure == 'ssl') ? 'ssl' : 'tls'; + } + break; + case 'sendmail': + $mail->IsSendmail(); + $mail->Sendmail = $sendmail; + break; + case 'php': + default: + $mail->IsMail(); + break; + } + + $retval = $mail->send(); + if( $retval == true ) { + return true; + } else { + return false; + } + } // send + + public function send_to_group($group_name) { + $mail = new PHPMailer(); + + foreach(self::get_users($group_name) as $member) { + if(function_exists('mb_encode_mimeheader')) { + $member['fullname'] = mb_encode_mimeheader($member['fullname']); + } + $mail->AddBCC($member['email'], $member['fullname']); + } + + return $this->send($mail); + } } // Ampache_Mail class ?> diff --git a/lib/class/ampache_rss.class.php b/lib/class/ampache_rss.class.php index 3056e9cf73..8006d8be99 100644 --- a/lib/class/ampache_rss.class.php +++ b/lib/class/ampache_rss.class.php @@ -1,5 +1,5 @@ type = self::validate_type($type); + $this->type = self::validate_type($type); - } // constructor + } // constructor - /** - * get_xml - * This returns the xmldocument for the current rss type, it calls a sub function that gathers the data - * and then uses the xmlDATA class to build the document - */ - public function get_xml() { + /** + * get_xml + * This returns the xmldocument for the current rss type, it calls a sub function that gathers the data + * and then uses the xmlDATA class to build the document + */ + public function get_xml() { - // Function call name - $data_function = 'load_' . $this->type; - $pub_date_function = 'pubdate_' . $this->type; + // Function call name + $data_function = 'load_' . $this->type; + $pub_date_function = 'pubdate_' . $this->type; - $data = call_user_func(array('Ampache_RSS',$data_function)); - $pub_date = call_user_func(array('Ampache_RSS',$pub_date_function)); - - XML_Data::set_type('rss'); - $xml_document = XML_Data::rss_feed($data,$this->get_title(),$this->get_description(),$pub_date); - - return $xml_document; - - } // get_xml + $data = call_user_func(array('Ampache_RSS',$data_function)); + $pub_date = call_user_func(array('Ampache_RSS',$pub_date_function)); + + XML_Data::set_type('rss'); + $xml_document = XML_Data::rss_feed($data,$this->get_title(),$this->get_description(),$pub_date); + + return $xml_document; + + } // get_xml - /** - * get_title - * This returns the standardized title for the rss feed based on this->type - */ - public function get_title() { - - $titles = array('now_playing' => T_('Now Playing'), - 'recently_played' => T_('Recently Played'), - 'latest_album' => T_('Newest Albums'), - 'latest_artist' => T_('Newest Artists')); + /** + * get_title + * This returns the standardized title for the rss feed based on this->type + */ + public function get_title() { + + $titles = array('now_playing' => T_('Now Playing'), + 'recently_played' => T_('Recently Played'), + 'latest_album' => T_('Newest Albums'), + 'latest_artist' => T_('Newest Artists')); - return scrub_out(Config::get('site_title')) . ' - ' . $titles[$this->type]; + return scrub_out(Config::get('site_title')) . ' - ' . $titles[$this->type]; - } // get_title + } // get_title - /** - * get_description - * This returns the standardized description for the rss feed based on this->type - */ - public function get_description() { + /** + * get_description + * This returns the standardized description for the rss feed based on this->type + */ + public function get_description() { - //FIXME: For now don't do any kind of translating - return 'Ampache RSS Feeds'; + //FIXME: For now don't do any kind of translating + return 'Ampache RSS Feeds'; - } // get_description + } // get_description - /** - * validate_type - * this returns a valid type for an rss feed, if the specified type is invalid it returns a default value - */ - public static function validate_type($type) { + /** + * validate_type + * this returns a valid type for an rss feed, if the specified type is invalid it returns a default value + */ + public static function validate_type($type) { - $valid_types = array('now_playing','recently_played','latest_album','latest_artist','latest_song', - 'popular_song','popular_album','popular_artist'); + $valid_types = array('now_playing','recently_played','latest_album','latest_artist','latest_song', + 'popular_song','popular_album','popular_artist'); - if (!in_array($type,$valid_types)) { - return 'now_playing'; - } + if (!in_array($type,$valid_types)) { + return 'now_playing'; + } - return $type; - - } // validate_type - - /** - * get_display - * This dumps out some html and an icon for the type of rss that we specify - */ - public static function get_display($type='now_playing') { - - // Default to now playing - $type = self::validate_type($type); - - $string = '' . UI::get_icon('feed', T_('RSS Feed')) . ''; - - return $string; - - } // get_display - - // type specific functions below, these are called semi-dynamically based on the current type // - - /** - * load_now_playing - * This loads in the now playing information. This is just the raw data with key=>value pairs that could be turned - * into an xml document if we so wished - */ - public static function load_now_playing() { - - $data = Stream::get_now_playing(); - - $results = array(); - $format = Config::get('rss_format') ?: '%t - %a - %A'; - $string_map = array( - '%t' => 'title', - '%a' => 'artist', - '%A' => 'album' - ); - foreach ($data as $element) { - $song = $element['media']; - $client = $element['user']; - $title = $format; - $description = $format; - foreach($string_map as $search => $replace) { - $trep = 'f_' . $replace; - $drep = 'f_' . $replace . '_full'; - $title = str_replace($search, $song->$trep, $title); - $description = str_replace($search, $song->$drep, $description); - } - $xml_array = array( - 'title' => $title, - 'link' => $song->link, - 'description' => $description, - 'comments' => $client->fullname . ' - ' . $element['agent'], - 'pubDate' => date('r', $element['expire']) - ); - $results[] = $xml_array; - } // end foreach - - return $results; - - } // load_now_playing - - /** - * pubdate_now_playing - * this is the pub date we should use for the now playing information, - * this is a little specific as it uses the 'newest' expire we can find - */ - public static function pubdate_now_playing() { - - // Little redundent, should be fixed by an improvement in the get_now_playing stuff - $data = Stream::get_now_playing(); - - $element = array_shift($data); - - return $element['expire']; - - } // pubdate_now_playing - - /** - * load_recently_played - * This loads in the recently played information and formats it up real nice like - */ - public static function load_recently_played() { - - //FIXME: The time stuff should be centralized, it's currently in two places, lame - - $time_unit = array('', T_('seconds ago'), T_('minutes ago'), T_('hours ago'), T_('days ago'), T_('weeks ago'), T_('months ago'), T_('years ago')); - $data = Song::get_recently_played(); - - $results = array(); - - foreach ($data as $item) { - $client = new User($item['user']); - $song = new Song($item['object_id']); - $song->format(); - $amount = intval(time() - $item['date']+2); - $time_place = '0'; - while ($amount >= 1) { - $final = $amount; - $time_place++; - if ($time_place <= 2) { - $amount = floor($amount/60); - } - if ($time_place == '3') { - $amount = floor($amount/24); - } - if ($time_place == '4') { - $amount = floor($amount/7); - } - if ($time_place == '5') { - $amount = floor($amount/4); - } - if ($time_place == '6') { - $amount = floor ($amount/12); - } - if ($time_place > '6') { - $final = $amount . '+'; - break; - } - } // end while - - $time_string = $final . ' ' . $time_unit[$time_place]; - - $xml_array = array('title'=>$song->f_title . ' - ' . $song->f_artist . ' - ' . $song->f_album, - 'link'=>str_replace('&', '&', $song->link), - 'description'=>$song->title . ' - ' . $song->f_artist_full . ' - ' . $song->f_album_full . ' - ' . $time_string, - 'comments'=>$client->username, - 'pubDate'=>date("r",$item['date'])); - $results[] = $xml_array; - - } // end foreach - - return $results; - - } // load_recently_played - - /** - * pubdate_recently_played - * This just returns the 'newest' recently played entry - */ - public static function pubdate_recently_played() { - - $data = Song::get_recently_played(); - - $element = array_shift($data); - - return $element['date']; - - } // pubdate_recently_played + return $type; + + } // validate_type + + /** + * get_display + * This dumps out some html and an icon for the type of rss that we specify + */ + public static function get_display($type='now_playing') { + + // Default to now playing + $type = self::validate_type($type); + + $string = '' . UI::get_icon('feed', T_('RSS Feed')) . ''; + + return $string; + + } // get_display + + // type specific functions below, these are called semi-dynamically based on the current type // + + /** + * load_now_playing + * This loads in the now playing information. This is just the raw data with key=>value pairs that could be turned + * into an xml document if we so wished + */ + public static function load_now_playing() { + + $data = Stream::get_now_playing(); + + $results = array(); + $format = Config::get('rss_format') ?: '%t - %a - %A'; + $string_map = array( + '%t' => 'title', + '%a' => 'artist', + '%A' => 'album' + ); + foreach ($data as $element) { + $song = $element['media']; + $client = $element['user']; + $title = $format; + $description = $format; + foreach($string_map as $search => $replace) { + $trep = 'f_' . $replace; + $drep = 'f_' . $replace . '_full'; + $title = str_replace($search, $song->$trep, $title); + $description = str_replace($search, $song->$drep, $description); + } + $xml_array = array( + 'title' => $title, + 'link' => $song->link, + 'description' => $description, + 'comments' => $client->fullname . ' - ' . $element['agent'], + 'pubDate' => date('r', $element['expire']) + ); + $results[] = $xml_array; + } // end foreach + + return $results; + + } // load_now_playing + + /** + * pubdate_now_playing + * this is the pub date we should use for the now playing information, + * this is a little specific as it uses the 'newest' expire we can find + */ + public static function pubdate_now_playing() { + + // Little redundent, should be fixed by an improvement in the get_now_playing stuff + $data = Stream::get_now_playing(); + + $element = array_shift($data); + + return $element['expire']; + + } // pubdate_now_playing + + /** + * load_recently_played + * This loads in the recently played information and formats it up real nice like + */ + public static function load_recently_played() { + + //FIXME: The time stuff should be centralized, it's currently in two places, lame + + $time_unit = array('', T_('seconds ago'), T_('minutes ago'), T_('hours ago'), T_('days ago'), T_('weeks ago'), T_('months ago'), T_('years ago')); + $data = Song::get_recently_played(); + + $results = array(); + + foreach ($data as $item) { + $client = new User($item['user']); + $song = new Song($item['object_id']); + $song->format(); + $amount = intval(time() - $item['date']+2); + $time_place = '0'; + while ($amount >= 1) { + $final = $amount; + $time_place++; + if ($time_place <= 2) { + $amount = floor($amount/60); + } + if ($time_place == '3') { + $amount = floor($amount/24); + } + if ($time_place == '4') { + $amount = floor($amount/7); + } + if ($time_place == '5') { + $amount = floor($amount/4); + } + if ($time_place == '6') { + $amount = floor ($amount/12); + } + if ($time_place > '6') { + $final = $amount . '+'; + break; + } + } // end while + + $time_string = $final . ' ' . $time_unit[$time_place]; + + $xml_array = array('title'=>$song->f_title . ' - ' . $song->f_artist . ' - ' . $song->f_album, + 'link'=>str_replace('&', '&', $song->link), + 'description'=>$song->title . ' - ' . $song->f_artist_full . ' - ' . $song->f_album_full . ' - ' . $time_string, + 'comments'=>$client->username, + 'pubDate'=>date("r",$item['date'])); + $results[] = $xml_array; + + } // end foreach + + return $results; + + } // load_recently_played + + /** + * pubdate_recently_played + * This just returns the 'newest' recently played entry + */ + public static function pubdate_recently_played() { + + $data = Song::get_recently_played(); + + $element = array_shift($data); + + return $element['date']; + + } // pubdate_recently_played } // end Ampache_RSS class diff --git a/lib/class/api.class.php b/lib/class/api.class.php index 841d353404..f289e98ba3 100644 --- a/lib/class/api.class.php +++ b/lib/class/api.class.php @@ -1,5 +1,5 @@ set_filter('add_lt',strtotime($elements['1'])); - self::$browse->set_filter('add_gt',strtotime($elements['0'])); - } - else { - self::$browse->set_filter('add_gt',strtotime($value)); - } - break; - case 'update': - // Check for a range, if no range default to gt - if (strpos($value,'/')) { - $elements = explode('/',$value); - self::$browse->set_filter('update_lt',strtotime($elements['1'])); - self::$browse->set_filter('update_gt',strtotime($elements['0'])); - } - else { - self::$browse->set_filter('update_gt',strtotime($value)); - } - break; - case 'alpha_match': - self::$browse->set_filter('alpha_match',$value); - break; - case 'exact_match': - self::$browse->set_filter('exact_match',$value); - break; - default: - // Rien a faire - break; - } // end filter - - return true; - - } // set_filter - - /** - * handshake - * - * This is the function that handles verifying a new handshake - * Takes a timestamp, auth key, and username. - */ - public static function handshake($input) { - - $timestamp = preg_replace('/[^0-9]/', '', $input['timestamp']); - $passphrase = $input['auth']; - $ip = $_SERVER['REMOTE_ADDR']; - $username = $input['user']; - $version = $input['version']; - - // Log the attempt - debug_event('API', "Handshake Attempt, IP:$ip User:$username Version:$version", 5); - - if (intval($version) < self::$version) { - debug_event('API', 'Login Failed: version too old', 1); - Error::add('api', T_('Login Failed: version too old')); - return false; - } - - // If the timestamp isn't within 30 minutes sucks to be them - if (($timestamp < (time() - 1800)) || - ($timestamp > (time() + 1800))) { - debug_event('API', 'Login Failed: timestamp out of range', 1); - Error::add('api', T_('Login Failed: timestamp out of range')); - return false; - } - - // Grab the correct userid - // FIXME: Does this if/else make sense with the new ACLs? - if (!trim($username)) { - $user_id = '-1'; - } - else { - $client = User::get_from_username($username); - $user_id = $client->id; - } - $user_id = Dba::escape($user_id); - - // Log this attempt - debug_event('API', "Login Attempt, IP:$ip Time: $timestamp User:$username ($user_id) Auth:$passphrase", 1); - - if (Access::check_network('api', $user_id, 5, $ip)) { - // Now we're sure that there is an ACL line that matches - // this user or ALL USERS, pull the user's password and - // then see what we come out with - $sql = "SELECT * FROM `user` WHERE `id`='$user_id'"; - $db_results = Dba::read($sql); - - $row = Dba::fetch_assoc($db_results); - - if (!$row['password']) { - debug_event('API', 'Unable to find user with userid of ' . $user_id, 1); - Error::add('api', T_('Invalid Username/Password')); - return false; - } - - $sha1pass = hash('sha256', $timestamp . $row['password']); - - if ($sha1pass === $passphrase) { - // Create the session - // FIXME: needs to be moved to the correct class - $data['username'] = $client->username; - $data['type'] = 'api'; - $data['value'] = $timestamp; - $token = vauth::session_create($data); - - // Insert the token into the streamer - Stream::insert_session($token,$client->id); - debug_event('API', 'Login Success, passphrase matched', 1); - - // We need to also get the 'last update' of the - // catalog information in an RFC 2822 Format - $sql = "SELECT MAX(`last_update`) AS `update`,MAX(`last_add`) AS `add`, MAX(`last_clean`) AS `clean` FROM `catalog`"; - $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); - - // Now we need to quickly get the song totals - $sql = 'SELECT COUNT(`id`) AS `song`, ' . - 'COUNT(DISTINCT(`album`)) AS `album`, '. - 'COUNT(DISTINCT(`artist`)) AS `artist` ' . - 'FROM `song`'; - $db_results = Dba::read($sql); - $counts = Dba::fetch_assoc($db_results); - - // Next the video counts - $sql = "SELECT COUNT(`id`) AS `video` FROM `video`"; - $db_results = Dba::read($sql); - $vcounts = Dba::fetch_assoc($db_results); - - $sql = "SELECT COUNT(`id`) AS `playlist` FROM `playlist`"; - $db_results = Dba::read($sql); - $playlist = Dba::fetch_assoc($db_results); - - $sql = "SELECT COUNT(`id`) AS `catalog` FROM `catalog` WHERE `catalog_type`='local'"; - $db_results = Dba::read($sql); - $catalog = Dba::fetch_assoc($db_results); - - echo XML_Data::keyed_array(array('auth'=>$token, - 'api'=>self::$version, - 'session_expire'=>date("c",time()+Config::get('session_length')-60), - 'update'=>date("c",$row['update']), - 'add'=>date("c",$row['add']), - 'clean'=>date("c",$row['clean']), - 'songs'=>$counts['song'], - 'albums'=>$counts['album'], - 'artists'=>$counts['artist'], - 'playlists'=>$playlist['playlist'], - 'videos'=>$vcounts['video'], - 'catalogs'=>$catalog['catalog'])); - return true; - } // match - - } // end while - - debug_event('API','Login Failed, unable to match passphrase','1'); - XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password')); - - } // handshake - - /** - * ping - * This can be called without being authenticated, it is useful for determining if what the status - * of the server is, and what version it is running/compatible with - */ - public static function ping($input) { - - $xmldata = array('server'=>Config::get('version'),'version'=>Api::$version,'compatible'=>'350001'); - - // Check and see if we should extend the api sessions (done if valid sess is passed) - if (vauth::session_exists('api', $input['auth'])) { - vauth::session_extend($input['auth']); - $xmldata = array_merge(array('session_expire'=>date("c",time()+Config::get('session_length')-60)),$xmldata); - } - - debug_event('API','Ping Received from ' . $_SERVER['REMOTE_ADDR'] . ' :: ' . $input['auth'],'5'); - - ob_end_clean(); - echo XML_Data::keyed_array($xmldata); - - } // ping - - /** - * artists - * This takes a collection of inputs and returns - * artist objects. This function is deprecated! - * //DEPRECATED - */ - public static function artists($input) { - - self::$browse->reset_filters(); - self::$browse->set_type('artist'); - self::$browse->set_sort('name','ASC'); - - $method = $input['exact'] ? 'exact_match' : 'alpha_match'; - Api::set_filter($method,$input['filter']); - Api::set_filter('add',$input['add']); - Api::set_filter('update',$input['update']); - - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); - - $artists = self::$browse->get_objects(); - // echo out the resulting xml document - ob_end_clean(); - echo XML_Data::artists($artists); - - } // artists - - /** - * artist - * This returns a single artist based on the UID of said artist - * //DEPRECATED - */ - public static function artist($input) { - - $uid = scrub_in($input['filter']); - echo XML_Data::artists(array($uid)); - - } // artist - - /** - * artist_albums - * This returns the albums of an artist - */ - public static function artist_albums($input) { - - $artist = new Artist($input['filter']); - - $albums = $artist->get_albums(); - - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::albums($albums); - - } // artist_albums - - /** - * artist_songs - * This returns the songs of the specified artist - */ - public static function artist_songs($input) { + public static $version = '350001'; + + private static $browse = null; + + /** + * constructor + * This really isn't anything to do here, so it's private + */ + private function __construct() { + + // Rien a faire + + } // constructor + + /** + * _auto_init + * Automatically called when this class is loaded. + */ + public static function _auto_init() { + if (is_null(self::$browse)) { + self::$browse = new Browse(); + } + } + + /** + * set_filter + * This is a play on the browse function, it's different as we expose + * the filters in a slightly different and vastly simpler way to the + * end users--so we have to do a little extra work to make them work + * internally. + */ + public static function set_filter($filter,$value) { + + if (!strlen($value)) { return false; } + + switch ($filter) { + case 'add': + // Check for a range, if no range default to gt + if (strpos($value,'/')) { + $elements = explode('/',$value); + self::$browse->set_filter('add_lt',strtotime($elements['1'])); + self::$browse->set_filter('add_gt',strtotime($elements['0'])); + } + else { + self::$browse->set_filter('add_gt',strtotime($value)); + } + break; + case 'update': + // Check for a range, if no range default to gt + if (strpos($value,'/')) { + $elements = explode('/',$value); + self::$browse->set_filter('update_lt',strtotime($elements['1'])); + self::$browse->set_filter('update_gt',strtotime($elements['0'])); + } + else { + self::$browse->set_filter('update_gt',strtotime($value)); + } + break; + case 'alpha_match': + self::$browse->set_filter('alpha_match',$value); + break; + case 'exact_match': + self::$browse->set_filter('exact_match',$value); + break; + default: + // Rien a faire + break; + } // end filter + + return true; + + } // set_filter + + /** + * handshake + * + * This is the function that handles verifying a new handshake + * Takes a timestamp, auth key, and username. + */ + public static function handshake($input) { + + $timestamp = preg_replace('/[^0-9]/', '', $input['timestamp']); + $passphrase = $input['auth']; + $ip = $_SERVER['REMOTE_ADDR']; + $username = $input['user']; + $version = $input['version']; + + // Log the attempt + debug_event('API', "Handshake Attempt, IP:$ip User:$username Version:$version", 5); + + if (intval($version) < self::$version) { + debug_event('API', 'Login Failed: version too old', 1); + Error::add('api', T_('Login Failed: version too old')); + return false; + } + + // If the timestamp isn't within 30 minutes sucks to be them + if (($timestamp < (time() - 1800)) || + ($timestamp > (time() + 1800))) { + debug_event('API', 'Login Failed: timestamp out of range', 1); + Error::add('api', T_('Login Failed: timestamp out of range')); + return false; + } + + // Grab the correct userid + // FIXME: Does this if/else make sense with the new ACLs? + if (!trim($username)) { + $user_id = '-1'; + } + else { + $client = User::get_from_username($username); + $user_id = $client->id; + } + $user_id = Dba::escape($user_id); + + // Log this attempt + debug_event('API', "Login Attempt, IP:$ip Time: $timestamp User:$username ($user_id) Auth:$passphrase", 1); + + if (Access::check_network('api', $user_id, 5, $ip)) { + // Now we're sure that there is an ACL line that matches + // this user or ALL USERS, pull the user's password and + // then see what we come out with + $sql = "SELECT * FROM `user` WHERE `id`='$user_id'"; + $db_results = Dba::read($sql); + + $row = Dba::fetch_assoc($db_results); + + if (!$row['password']) { + debug_event('API', 'Unable to find user with userid of ' . $user_id, 1); + Error::add('api', T_('Invalid Username/Password')); + return false; + } + + $sha1pass = hash('sha256', $timestamp . $row['password']); + + if ($sha1pass === $passphrase) { + // Create the session + // FIXME: needs to be moved to the correct class + $data['username'] = $client->username; + $data['type'] = 'api'; + $data['value'] = $timestamp; + $token = vauth::session_create($data); + + // Insert the token into the streamer + Stream::insert_session($token,$client->id); + debug_event('API', 'Login Success, passphrase matched', 1); + + // We need to also get the 'last update' of the + // catalog information in an RFC 2822 Format + $sql = "SELECT MAX(`last_update`) AS `update`,MAX(`last_add`) AS `add`, MAX(`last_clean`) AS `clean` FROM `catalog`"; + $db_results = Dba::read($sql); + $row = Dba::fetch_assoc($db_results); + + // Now we need to quickly get the song totals + $sql = 'SELECT COUNT(`id`) AS `song`, ' . + 'COUNT(DISTINCT(`album`)) AS `album`, '. + 'COUNT(DISTINCT(`artist`)) AS `artist` ' . + 'FROM `song`'; + $db_results = Dba::read($sql); + $counts = Dba::fetch_assoc($db_results); + + // Next the video counts + $sql = "SELECT COUNT(`id`) AS `video` FROM `video`"; + $db_results = Dba::read($sql); + $vcounts = Dba::fetch_assoc($db_results); + + $sql = "SELECT COUNT(`id`) AS `playlist` FROM `playlist`"; + $db_results = Dba::read($sql); + $playlist = Dba::fetch_assoc($db_results); + + $sql = "SELECT COUNT(`id`) AS `catalog` FROM `catalog` WHERE `catalog_type`='local'"; + $db_results = Dba::read($sql); + $catalog = Dba::fetch_assoc($db_results); + + echo XML_Data::keyed_array(array('auth'=>$token, + 'api'=>self::$version, + 'session_expire'=>date("c",time()+Config::get('session_length')-60), + 'update'=>date("c",$row['update']), + 'add'=>date("c",$row['add']), + 'clean'=>date("c",$row['clean']), + 'songs'=>$counts['song'], + 'albums'=>$counts['album'], + 'artists'=>$counts['artist'], + 'playlists'=>$playlist['playlist'], + 'videos'=>$vcounts['video'], + 'catalogs'=>$catalog['catalog'])); + return true; + } // match + + } // end while + + debug_event('API','Login Failed, unable to match passphrase','1'); + XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password')); + + } // handshake + + /** + * ping + * This can be called without being authenticated, it is useful for determining if what the status + * of the server is, and what version it is running/compatible with + */ + public static function ping($input) { + + $xmldata = array('server'=>Config::get('version'),'version'=>Api::$version,'compatible'=>'350001'); + + // Check and see if we should extend the api sessions (done if valid sess is passed) + if (vauth::session_exists('api', $input['auth'])) { + vauth::session_extend($input['auth']); + $xmldata = array_merge(array('session_expire'=>date("c",time()+Config::get('session_length')-60)),$xmldata); + } + + debug_event('API','Ping Received from ' . $_SERVER['REMOTE_ADDR'] . ' :: ' . $input['auth'],'5'); + + ob_end_clean(); + echo XML_Data::keyed_array($xmldata); + + } // ping + + /** + * artists + * This takes a collection of inputs and returns + * artist objects. This function is deprecated! + * //DEPRECATED + */ + public static function artists($input) { + + self::$browse->reset_filters(); + self::$browse->set_type('artist'); + self::$browse->set_sort('name','ASC'); + + $method = $input['exact'] ? 'exact_match' : 'alpha_match'; + Api::set_filter($method,$input['filter']); + Api::set_filter('add',$input['add']); + Api::set_filter('update',$input['update']); + + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); + + $artists = self::$browse->get_objects(); + // echo out the resulting xml document + ob_end_clean(); + echo XML_Data::artists($artists); + + } // artists + + /** + * artist + * This returns a single artist based on the UID of said artist + * //DEPRECATED + */ + public static function artist($input) { + + $uid = scrub_in($input['filter']); + echo XML_Data::artists(array($uid)); + + } // artist + + /** + * artist_albums + * This returns the albums of an artist + */ + public static function artist_albums($input) { + + $artist = new Artist($input['filter']); + + $albums = $artist->get_albums(); + + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); + ob_end_clean(); + echo XML_Data::albums($albums); + + } // artist_albums + + /** + * artist_songs + * This returns the songs of the specified artist + */ + public static function artist_songs($input) { - $artist = new Artist($input['filter']); - $songs = $artist->get_songs(); + $artist = new Artist($input['filter']); + $songs = $artist->get_songs(); - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::songs($songs); + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); + ob_end_clean(); + echo XML_Data::songs($songs); - } // artist_songs + } // artist_songs - /** - * albums - * This returns albums based on the provided search filters - */ - public static function albums($input) { + /** + * albums + * This returns albums based on the provided search filters + */ + public static function albums($input) { - self::$browse->reset_filters(); - self::$browse->set_type('album'); - self::$browse->set_sort('name','ASC'); - $method = $input['exact'] ? 'exact_match' : 'alpha_match'; - Api::set_filter($method,$input['filter']); - Api::set_filter('add',$input['add']); - Api::set_filter('update',$input['update']); + self::$browse->reset_filters(); + self::$browse->set_type('album'); + self::$browse->set_sort('name','ASC'); + $method = $input['exact'] ? 'exact_match' : 'alpha_match'; + Api::set_filter($method,$input['filter']); + Api::set_filter('add',$input['add']); + Api::set_filter('update',$input['update']); - $albums = self::$browse->get_objects(); + $albums = self::$browse->get_objects(); - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::albums($albums); + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); + ob_end_clean(); + echo XML_Data::albums($albums); - } // albums + } // albums - /** - * album - * This returns a single album based on the UID provided - */ - public static function album($input) { + /** + * album + * This returns a single album based on the UID provided + */ + public static function album($input) { - $uid = scrub_in($input['filter']); - echo XML_Data::albums(array($uid)); + $uid = scrub_in($input['filter']); + echo XML_Data::albums(array($uid)); - } // album + } // album - /** - * album_songs - * This returns the songs of a specified album - */ - public static function album_songs($input) { + /** + * album_songs + * This returns the songs of a specified album + */ + public static function album_songs($input) { - $album = new Album($input['filter']); - $songs = $album->get_songs(); + $album = new Album($input['filter']); + $songs = $album->get_songs(); - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::songs($songs); + ob_end_clean(); + echo XML_Data::songs($songs); - } // album_songs + } // album_songs - /** - * tags - * This returns the tags based on the specified filter - */ - public static function tags($input) { + /** + * tags + * This returns the tags based on the specified filter + */ + public static function tags($input) { - self::$browse->reset_filters(); - self::$browse->set_type('tag'); - self::$browse->set_sort('name','ASC'); + self::$browse->reset_filters(); + self::$browse->set_type('tag'); + self::$browse->set_sort('name','ASC'); - $method = $input['exact'] ? 'exact_match' : 'alpha_match'; - Api::set_filter($method,$input['filter']); - $tags = self::$browse->get_objects(); + $method = $input['exact'] ? 'exact_match' : 'alpha_match'; + Api::set_filter($method,$input['filter']); + $tags = self::$browse->get_objects(); - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::tags($tags); + ob_end_clean(); + echo XML_Data::tags($tags); - } // tags + } // tags - /** - * tag - * This returns a single tag based on UID - */ - public static function tag($input) { + /** + * tag + * This returns a single tag based on UID + */ + public static function tag($input) { - $uid = scrub_in($input['filter']); - ob_end_clean(); - echo XML_Data::tags(array($uid)); + $uid = scrub_in($input['filter']); + ob_end_clean(); + echo XML_Data::tags(array($uid)); - } // tag + } // tag - /** - * tag_artists - * This returns the artists associated with the tag in question as defined by the UID - */ - public static function tag_artists($input) { + /** + * tag_artists + * This returns the artists associated with the tag in question as defined by the UID + */ + public static function tag_artists($input) { - $artists = Tag::get_tag_objects('artist',$input['filter']); + $artists = Tag::get_tag_objects('artist',$input['filter']); - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::artists($artists); + ob_end_clean(); + echo XML_Data::artists($artists); - } // tag_artists + } // tag_artists - /** - * tag_albums - * This returns the albums associated with the tag in question - */ - public static function tag_albums($input) { + /** + * tag_albums + * This returns the albums associated with the tag in question + */ + public static function tag_albums($input) { - $albums = Tag::get_tag_objects('album',$input['filter']); + $albums = Tag::get_tag_objects('album',$input['filter']); - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::albums($albums); + ob_end_clean(); + echo XML_Data::albums($albums); - } // tag_albums + } // tag_albums - /** - * tag_songs - * returns the songs for this tag - */ - public static function tag_songs($input) { + /** + * tag_songs + * returns the songs for this tag + */ + public static function tag_songs($input) { - $songs = Tag::get_tag_objects('song',$input['filter']); + $songs = Tag::get_tag_objects('song',$input['filter']); - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::songs($songs); + ob_end_clean(); + echo XML_Data::songs($songs); - } // tag_songs + } // tag_songs - /** - * songs - * Returns songs based on the specified filter - */ - public static function songs($input) { + /** + * songs + * Returns songs based on the specified filter + */ + public static function songs($input) { - self::$browse->reset_filters(); - self::$browse->set_type('song'); - self::$browse->set_sort('title','ASC'); + self::$browse->reset_filters(); + self::$browse->set_type('song'); + self::$browse->set_sort('title','ASC'); - $method = $input['exact'] ? 'exact_match' : 'alpha_match'; - Api::set_filter($method,$input['filter']); - Api::set_filter('add',$input['add']); - Api::set_filter('update',$input['update']); + $method = $input['exact'] ? 'exact_match' : 'alpha_match'; + Api::set_filter($method,$input['filter']); + Api::set_filter('add',$input['add']); + Api::set_filter('update',$input['update']); - $songs = self::$browse->get_objects(); + $songs = self::$browse->get_objects(); - // Set the offset - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + // Set the offset + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::songs($songs); + ob_end_clean(); + echo XML_Data::songs($songs); - } // songs + } // songs - /** - * song - * returns a single song - */ - public static function song($input) { + /** + * song + * returns a single song + */ + public static function song($input) { - $uid = scrub_in($input['filter']); + $uid = scrub_in($input['filter']); - ob_end_clean(); - echo XML_Data::songs(array($uid)); + ob_end_clean(); + echo XML_Data::songs(array($uid)); - } // song + } // song - /** - * url_to_song - * This takes a url and returns the song object in question - */ - public static function url_to_song($input) { + /** + * url_to_song + * This takes a url and returns the song object in question + */ + public static function url_to_song($input) { - // Don't scrub, the function needs her raw and juicy - $song_id = Song::parse_song_url($input['url']); + // Don't scrub, the function needs her raw and juicy + $song_id = Song::parse_song_url($input['url']); - ob_end_clean(); - echo XML_Data::songs(array($song_id)); + ob_end_clean(); + echo XML_Data::songs(array($song_id)); - } // url_to_song + } // url_to_song - /** - * playlists - * This returns playlists based on the specified filter - */ - public static function playlists($input) { + /** + * playlists + * This returns playlists based on the specified filter + */ + public static function playlists($input) { - self::$browse->reset_filters(); - self::$browse->set_type('playlist'); - self::$browse->set_sort('name','ASC'); + self::$browse->reset_filters(); + self::$browse->set_type('playlist'); + self::$browse->set_sort('name','ASC'); - $method = $input['exact'] ? 'exact_match' : 'alpha_match'; - Api::set_filter($method,$input['filter']); + $method = $input['exact'] ? 'exact_match' : 'alpha_match'; + Api::set_filter($method,$input['filter']); - $playlist_ids = self::$browse->get_objects(); + $playlist_ids = self::$browse->get_objects(); - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::playlists($playlist_ids); + ob_end_clean(); + echo XML_Data::playlists($playlist_ids); - } // playlists + } // playlists - /** - * playlist - * This returns a single playlist - */ - public static function playlist($input) { + /** + * playlist + * This returns a single playlist + */ + public static function playlist($input) { - $uid = scrub_in($input['filter']); + $uid = scrub_in($input['filter']); - ob_end_clean(); - echo XML_Data::playlists(array($uid)); + ob_end_clean(); + echo XML_Data::playlists(array($uid)); - } // playlist + } // playlist - /** - * playlist_songs - * This returns the songs for a playlist - */ - public static function playlist_songs($input) { + /** + * playlist_songs + * This returns the songs for a playlist + */ + public static function playlist_songs($input) { - $playlist = new Playlist($input['filter']); - $items = $playlist->get_items(); + $playlist = new Playlist($input['filter']); + $items = $playlist->get_items(); - foreach ($items as $object) { - if ($object['object_type'] == 'song') { - $songs[] = $object['object_id']; - } - } // end foreach + foreach ($items as $object) { + if ($object['object_type'] == 'song') { + $songs[] = $object['object_id']; + } + } // end foreach - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); - ob_end_clean(); - echo XML_Data::songs($songs); + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); + ob_end_clean(); + echo XML_Data::songs($songs); - } // playlist_songs + } // playlist_songs - /** - * search_songs - * This searches the songs and returns... songs - */ - public static function search_songs($input) { - $array['type'] = 'song'; - $array['rule_1'] = 'anywhere'; - $array['rule_1_input'] = $input['filter']; - $array['rule_1_operator'] = 0; + /** + * search_songs + * This searches the songs and returns... songs + */ + public static function search_songs($input) { + $array['type'] = 'song'; + $array['rule_1'] = 'anywhere'; + $array['rule_1_input'] = $input['filter']; + $array['rule_1_operator'] = 0; - ob_end_clean(); + ob_end_clean(); - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); - $results = Search::run($array); - - echo XML_Data::songs($results); + $results = Search::run($array); + + echo XML_Data::songs($results); - } // search_songs + } // search_songs - /** - * videos - * This returns video objects! - */ - public static function videos($input) { - - self::$browse->reset_filters(); - self::$browse->set_type('video'); - self::$browse->set_sort('title','ASC'); - - $method = $input['exact'] ? 'exact_match' : 'alpha_match'; - Api::set_filter($method,$input['filter']); - - $video_ids = self::$browse->get_objects(); - - XML_Data::set_offset($input['offset']); - XML_Data::set_limit($input['limit']); - - echo XML_Data::videos($video_ids); - - } // videos - - /** - * video - * This returns a single video - */ - public static function video($input) { - - $video_id = scrub_in($input['filter']); - - echo XML_Data::videos(array($video_id)); - - - } // video - - /** - * localplay - * This is for controling localplay - */ - public static function localplay($input) { - - // Load their localplay instance - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); - - switch ($input['command']) { - case 'next': - case 'prev': - case 'play': - case 'stop': - $result_status = $localplay->$input['command'](); - $xml_array = array('localplay'=>array('command'=>array($input['command']=>make_bool($result_status)))); - echo XML_Data::keyed_array($xml_array); - break; - default: - // They are doing it wrong - echo XML_Data::error('405', T_('Invalid Request')); - break; - } // end switch on command - - } // localplay - - /** - * democratic - * This is for controlling democratic play - */ - public static function democratic($input) { - - // Load up democratic information - $democratic = Democratic::get_current_playlist(); - $democratic->set_parent(); - - switch ($input['method']) { - case 'vote': - $type = 'song'; - $media = new $type($input['oid']); - if (!$media->id) { - echo XML_Data::error('400', T_('Media Object Invalid or Not Specified')); - break; - } - $democratic->add_vote(array( - array( - 'object_type' => 'song', - 'object_id' => $media->id - ) - )); - - // If everything was ok - $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true); - echo XML_Data::keyed_array($xml_array); - break; - case 'devote': - $type = 'song'; - $media = new $type($input['oid']); - if (!$media->id) { - echo XML_Data::error('400', T_('Media Object Invalid or Not Specified')); - } - - $uid = $democratic->get_uid_from_object_id($media->id,$type); - $democratic->remove_vote($uid); - - // Everything was ok - $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true); - echo XML_Data::keyed_array($xml_array); - break; - case 'playlist': - $objects = $democratic->get_items(); - Song::build_cache($democratic->object_ids); - Democratic::build_vote_cache($democratic->vote_ids); - XML_Data::democratic($objects); - break; - case 'play': - $url = $democratic->play_url(); - $xml_array = array('url'=>$url); - echo XML_Data::keyed_array($xml_array); - break; - default: - echo XML_Data::error('405', T_('Invalid Request')); - break; - } // switch on method - - } // democratic + /** + * videos + * This returns video objects! + */ + public static function videos($input) { + + self::$browse->reset_filters(); + self::$browse->set_type('video'); + self::$browse->set_sort('title','ASC'); + + $method = $input['exact'] ? 'exact_match' : 'alpha_match'; + Api::set_filter($method,$input['filter']); + + $video_ids = self::$browse->get_objects(); + + XML_Data::set_offset($input['offset']); + XML_Data::set_limit($input['limit']); + + echo XML_Data::videos($video_ids); + + } // videos + + /** + * video + * This returns a single video + */ + public static function video($input) { + + $video_id = scrub_in($input['filter']); + + echo XML_Data::videos(array($video_id)); + + + } // video + + /** + * localplay + * This is for controling localplay + */ + public static function localplay($input) { + + // Load their localplay instance + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); + + switch ($input['command']) { + case 'next': + case 'prev': + case 'play': + case 'stop': + $result_status = $localplay->$input['command'](); + $xml_array = array('localplay'=>array('command'=>array($input['command']=>make_bool($result_status)))); + echo XML_Data::keyed_array($xml_array); + break; + default: + // They are doing it wrong + echo XML_Data::error('405', T_('Invalid Request')); + break; + } // end switch on command + + } // localplay + + /** + * democratic + * This is for controlling democratic play + */ + public static function democratic($input) { + + // Load up democratic information + $democratic = Democratic::get_current_playlist(); + $democratic->set_parent(); + + switch ($input['method']) { + case 'vote': + $type = 'song'; + $media = new $type($input['oid']); + if (!$media->id) { + echo XML_Data::error('400', T_('Media Object Invalid or Not Specified')); + break; + } + $democratic->add_vote(array( + array( + 'object_type' => 'song', + 'object_id' => $media->id + ) + )); + + // If everything was ok + $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true); + echo XML_Data::keyed_array($xml_array); + break; + case 'devote': + $type = 'song'; + $media = new $type($input['oid']); + if (!$media->id) { + echo XML_Data::error('400', T_('Media Object Invalid or Not Specified')); + } + + $uid = $democratic->get_uid_from_object_id($media->id,$type); + $democratic->remove_vote($uid); + + // Everything was ok + $xml_array = array('action'=>$input['action'],'method'=>$input['method'],'result'=>true); + echo XML_Data::keyed_array($xml_array); + break; + case 'playlist': + $objects = $democratic->get_items(); + Song::build_cache($democratic->object_ids); + Democratic::build_vote_cache($democratic->vote_ids); + XML_Data::democratic($objects); + break; + case 'play': + $url = $democratic->play_url(); + $xml_array = array('url'=>$url); + echo XML_Data::keyed_array($xml_array); + break; + default: + echo XML_Data::error('405', T_('Invalid Request')); + break; + } // switch on method + + } // democratic } // API class ?> diff --git a/lib/class/art.class.php b/lib/class/art.class.php index 0e23463f58..4b896e7f82 100644 --- a/lib/class/art.class.php +++ b/lib/class/art.class.php @@ -1,5 +1,5 @@ type = Art::validate_type($type); - $this->uid = $uid; - - } // constructor - - /** - * build_cache - * This attempts to reduce # of queries by asking for everything in the - * browse all at once and storing it in the cache, this can help if the - * db connection is the slow point - */ - public static function build_cache($object_ids) { - - if (!is_array($object_ids) || !count($object_ids)) { return false; } - $uidlist = '(' . implode(',', $object_ids) . ')'; - $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_id` IN $uidlist"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('art', $row['object_type'] . - $row['object_id'] . $row['size'], $row); - } - - return true; - } // build_cache - - - /** - * _auto_init - * Called on creation of the class - */ - public static function _auto_init() { - if (!isset($_SESSION['art_enabled'])) { - $_SESSION['art_enabled'] = (Config::get('bandwidth') > 25); - } - self::$enabled = make_bool($_SESSION['art_enabled']); - } - - /** - * is_enabled - * Checks whether the user currently wants art - */ - public static function is_enabled() { - if (self::$enabled) { - return true; - } - - return false; - } - - /** - * set_enabled - * Changes the value of enabled - */ - public static function set_enabled($value = null) { - if (is_null($value)) { - self::$enabled = self::$enabled ? false : true; - } - else { - self::$enabled = make_bool($value); - } - - $_SESSION['art_enabled'] = self::$enabled; - } - - /** - * validate_type - * This validates the type - */ - public static function validate_type($type) { - - switch ($type) { - case 'album': - case 'artist': - case 'video': - return $type; - break; - default: - return 'album'; - break; - } - - } // validate_type - - /** - * extension - * This returns the file extension for the currently loaded art - */ - public static function extension($mime) { - - $data = explode("/", $mime); - $extension = $data['1']; - - if ($extension == 'jpeg') { $extension = 'jpg'; } - - return $extension; - - } // extension - - /** - * test_image - * Runs some sanity checks on the putative image - */ - public static function test_image($source) { - if (strlen($source) < 10) { - debug_event('Art', 'Invalid image passed', 1); - return false; - } - - // Check to make sure PHP:GD exists. If so, we can sanity check - // the image. - if (function_exists('ImageCreateFromString')) { - $image = ImageCreateFromString($source); - if (!$image || imagesx($image) < 5 || imagesy($image) < 5) { - debug_event('Art', 'Image failed PHP-GD test',1); - return false; - } - } - - return true; - } //test_image - - /** - * get - * This returns the art for our current object, this can - * look in the database and will return the thumb if it - * exists, if it doesn't depending on settings it will try - * to create it. - */ - public function get($raw=false) { - - // Get the data either way - if (!$this->get_db()) { - return false; - } - - if ($raw || !$this->thumb) { - return $this->raw; - } - else { - return $this->thumb; - } - - } // get - - - /** - * get_db - * This pulls the information out from the database, depending - * on if we want to resize and if there is not a thumbnail go - * ahead and try to resize - */ - public function get_db() { - - $type = Dba::escape($this->type); - $id = Dba::escape($this->uid); - - $sql = "SELECT `image`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$id'"; - $db_results = Dba::read($sql); - - while ($results = Dba::fetch_assoc($db_results)) { - if ($results['size'] == 'original') { - $this->raw = $results['image']; - $this->raw_mime = $results['mime']; - } - else if (Config::get('resize_images') && - $results['size'] == '275x275') { - $this->thumb = $results['image']; - $this->raw_mime = $results['mime']; - } - } - // If we get nothing return false - if (!$this->raw) { return false; } - - // If there is no thumb and we want thumbs - if (!$this->thumb && Config::get('resize_images')) { - $data = $this->generate_thumb($this->raw, array('width' => 275, 'height' => 275), $this->raw_mime); - // If it works save it! - if ($data) { - $this->save_thumb($data['thumb'], $data['thumb_mime'], '275x275'); - $this->thumb = $data['thumb']; - $this->thumb_mime = $data['thumb_mime']; - } - else { - debug_event('Art','Unable to retrieve or generate thumbnail for ' . $type . '::' . $id,1); - } - } // if no thumb, but art and we want to resize - - return true; - - } // get_db - - /** - * insert - * This takes the string representation of an image and inserts it into - * the database. You must also pass the mime type. - */ - public function insert($source, $mime) { - - // Disabled in demo mode cause people suck and upload porn - if (Config::get('demo_mode')) { return false; } - - // Check to make sure we like this image - if (!self::test_image($source)) { - debug_event('Art', 'Not inserting image, invalid data passed', 1); - return false; - } - - // Default to image/jpeg if they don't pass anything - $mime = $mime ? $mime : 'image/jpeg'; - - $image = Dba::escape($source); - $mime = Dba::escape($mime); - $uid = Dba::escape($this->uid); - $type = Dba::escape($this->type); - - // Blow it away! - $this->reset(); - - // Insert it! - $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$image', '$mime', 'original', '$type', '$uid')"; - $db_results = Dba::write($sql); - - return true; - - } // insert - - /** - * reset - * This resets the art in the database - */ - public function reset() { - - $type = Dba::escape($this->type); - $uid = Dba::escape($this->uid); - - $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type'"; - $db_results = Dba::write($sql); - - } // reset - - /** - * save_thumb - * This saves the thumbnail that we're passed - */ - public function save_thumb($source, $mime, $size) { - - // Quick sanity check - if (!self::test_image($source)) { - debug_event('Art', 'Not inserting thumbnail, invalid data passed', 1); - return false; - } - - $source = Dba::escape($source); - $mime = Dba::escape($mime); - $size = Dba::escape($size); - $uid = Dba::escape($this->uid); - $type = Dba::escape($this->type); - - $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type' AND `size`='$size'"; - $db_results = Dba::write($sql); - - $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$source', '$mime', '$size', '$type', '$uid')"; - $db_results = Dba::write($sql); - - } // save_thumb - - /** - * get_thumb - * Returns the specified resized image. If the requested size doesn't - * already exist, create and cache it. - */ - public function get_thumb($size) { - $sizetext = $size['width'] . 'x' . $size['height']; - $sizetext = Dba::escape($sizetext); - $type = Dba::escape($this->type); - $uid = Dba::escape($this->uid); - - $sql = "SELECT `image`, `mime` FROM `image` WHERE `size`='$sizetext' AND `object_type`='$type' AND `object_id`='$uid'"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - if (count($results)) { - return array('thumb' => $results['image'], - 'thumb_mime' => $results['mime']); - } - - // If we didn't get a result - $results = $this->generate_thumb($this->raw, $size, $this->raw_mime); - if ($results) { - $this->save_thumb($results['thumb'], $results['thumb_mime'], $sizetext); - } - - return $results; - } // get_thumb - - /** - * generate_thumb - * Automatically resizes the image for thumbnail viewing. - * Only works on gif/jpg/png/bmp. Fails if PHP-GD isn't available - * or lacks support for the requested image type. - */ - public function generate_thumb($image,$size,$mime) { - - $data = explode("/",$mime); - $type = strtolower($data['1']); - - if (!self::test_image($image)) { - debug_event('Art', 'Not trying to generate thumbnail, invalid data passed', 1); - return false; - } - - if (!function_exists('gd_info')) { - debug_event('Art','PHP-GD Not found - unable to resize art',1); - return false; - } - - // Check and make sure we can resize what you've asked us to - if (($type == 'jpg' OR $type == 'jpeg') AND !(imagetypes() & IMG_JPG)) { - debug_event('Art','PHP-GD Does not support JPGs - unable to resize',1); - return false; - } - if ($type == 'png' AND !imagetypes() & IMG_PNG) { - debug_event('Art','PHP-GD Does not support PNGs - unable to resize',1); - return false; - } - if ($type == 'gif' AND !imagetypes() & IMG_GIF) { - debug_event('Art','PHP-GD Does not support GIFs - unable to resize',1); - return false; - } - if ($type == 'bmp' AND !imagetypes() & IMG_WBMP) { - debug_event('Art','PHP-GD Does not support BMPs - unable to resize',1); - return false; - } - - $source = imagecreatefromstring($image); - - if (!$source) { - debug_event('Art','Failed to create Image from string - Source Image is damaged / malformed',1); - return false; - } - - $source_size = array('height' => imagesy($source), 'width' => imagesx($source)); - - // Create a new blank image of the correct size - $thumbnail = imagecreatetruecolor($size['width'], $size['height']); - - if (!imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $size['width'], $size['height'], $source_size['width'], $source_size['height'])) { - debug_event('Art','Unable to create resized image',1); - return false; - } - - // Start output buffer - ob_start(); - - // Generate the image to our OB - switch ($type) { - case 'jpg': - case 'jpeg': - imagejpeg($thumbnail, null, 75); - $mime_type = image_type_to_mime_type(IMAGETYPE_JPEG); - break; - case 'gif': - imagegif($thumbnail); - $mime_type = image_type_to_mime_type(IMAGETYPE_GIF); - break; - // Turn bmps into pngs - case 'bmp': - $type = 'png'; - case 'png': - imagepng($thumbnail); - $mime_type = image_type_to_mime_type(IMAGETYPE_PNG); - break; - } // resized - - $data = ob_get_contents(); - ob_end_clean(); - - if (!strlen($data)) { - debug_event('Art', 'Unknown Error resizing art', 1); - return false; - } - - return array('thumb' => $data, 'thumb_mime' => $mime_type); - - } // generate_thumb - - /** - * get_from_source - * This gets an image for the album art from a source as - * defined in the passed array. Because we don't know where - * it's coming from we are a passed an array that can look like - * ['url'] = URL *** OPTIONAL *** - * ['file'] = FILENAME *** OPTIONAL *** - * ['raw'] = Actual Image data, already captured - */ - public static function get_from_source($data, $type = 'album') { - - // Already have the data, this often comes from id3tags - if (isset($data['raw'])) { - return $data['raw']; - } - - // If it came from the database - if (isset($data['db'])) { - // Repull it - $uid = Dba::escape($data['db']); - $type = Dba::escape($type); - - $sql = "SELECT * FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid' AND `size`='original'"; - $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); - return $row['art']; - } // came from the db - - // Check to see if it's a URL - if (isset($data['url'])) { - $snoopy = new Snoopy(); - if(Config::get('proxy_host') AND Config::get('proxy_port')) { - $snoopy->proxy_user = Config::get('proxy_host'); - $snoopy->proxy_port = Config::get('proxy_port'); - $snoopy->proxy_user = Config::get('proxy_user'); - $snoopy->proxy_pass = Config::get('proxy_pass'); - } - $snoopy->fetch($data['url']); - return $snoopy->results; - } - - // Check to see if it's a FILE - if (isset($data['file'])) { - $handle = fopen($data['file'],'rb'); - $image_data = fread($handle,filesize($data['file'])); - fclose($handle); - return $image_data; - } - - // Check to see if it is embedded in id3 of a song - if (isset($data['song'])) { - // If we find a good one, stop looking - $getID3 = new getID3(); - $id3 = $getID3->analyze($data['song']); - - if ($id3['format_name'] == "WMA") { - return $id3['asf']['extended_content_description_object']['content_descriptors']['13']['data']; - } - elseif (isset($id3['id3v2']['APIC'])) { - // Foreach in case they have more then one - foreach ($id3['id3v2']['APIC'] as $image) { - return $image['data']; - } - } - } // if data song - - return false; - - } // get_from_source - - /** - * url - * This returns the constructed URL for the art in question - */ - public static function url($uid,$type,$sid=false) { - - $sid = $sid ? scrub_out($sid) : scrub_out(session_id()); - $type = self::validate_type($type); - - $key = $type . $uid; - if (parent::is_cached('art', $key . '275x275') && Config::get('resize_images')) { - $row = parent::get_from_cache('art', $key . '275x275'); - $mime = $row['mime']; - } - if (parent::is_cached('art', $key . 'original')) { - $row = parent::get_from_cache('art', $key . 'original'); - $thumb_mime = $row['mime']; - } - if (!$mime && !$thumb_mime) { - - $type = Dba::escape($type); - $uid = Dba::escape($uid); - - $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid'"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('art', $key . $row['size'], $row); - if ($row['size'] == 'original') { - $mime = $row['mime']; - } - else if ($row['size'] == '275x275' && Config::get('resize_images')) { - $thumb_mime = $row['mime']; - } - } - } - - $mime = $thumb_mime ? $thumb_mime : $mime; - $extension = self::extension($mime); - - $name = 'art.' . $extension; - $url = Config::get('web_path') . '/image.php?id=' . scrub_out($uid) . '&object_type=' . scrub_out($type) . '&auth=' . $sid . '&name=' . $name; - - return $url; - - } // url - - - /** - * gc - * This cleans up art that no longer has a corresponding object - */ - public static function gc() { - // iterate over our types and delete the images - foreach (array('album', 'artist') as $type) { - $sql = "DELETE FROM `image` USING `image` LEFT JOIN `" . - $type . "` ON `" . $type . "`.`id`=" . - "`image`.`object_id` WHERE `object_type`='" . - $type . "' AND `" . $type . "`.`id` IS NULL"; - $db_results = Dba::write($sql); - } // foreach - } - - /** - * gather - * This tries to get the art in question - */ - public function gather($options = array(), $limit = false) { - - // Define vars - $results = array(); - - switch ($this->type) { - case 'album': - $allowed_methods = array('db','lastfm','folder','amazon','google','musicbrainz','tags'); - break; - case 'artist': - $allowed_methods = array(); - break; - case 'video': - $allowed_methods = array(); - break; - } - - $config = Config::get('art_order'); - $methods = get_class_methods('Art'); - - /* If it's not set */ - if (empty($config)) { - // They don't want art! - debug_event('Art', 'art_order is empty, skipping art gathering', 3); - return array(); - } - elseif (!is_array($config)) { - $config = array($config); - } - - debug_event('Art','Searching using:' . json_encode($config), 3); - - foreach ($config as $method) { - - $data = array(); - - if (!in_array($method, $allowed_methods)) { - debug_event('Art', "$method not in allowed_methods, skipping", 3); - continue; - } - - $method_name = "gather_" . $method; - - if (in_array($method_name, $methods)) { - debug_event('Art', "Method used: $method_name", 3); - // Some of these take options! - switch ($method_name) { - case 'gather_amazon': - $data = $this->{$method_name}($limit, $options['keyword']); - break; - case 'gather_lastfm': - $data = $this->{$method_name}($limit, $options); - break; - default: - $data = $this->{$method_name}($limit); - break; - } - - // Add the results we got to the current set - $results = array_merge($results, (array)$data); - - if ($limit && count($results) >= $limit) { - return array_slice($results, 0, $limit); - } - - } // if the method exists - else { - debug_event("Art", "$method_name not defined", 1); - } - - } // end foreach - - return $results; - - } // gather - - - /////////////////////////////////////////////////////////////////////// - // Art Methods - /////////////////////////////////////////////////////////////////////// - - /** - * gather_db - * This function retrieves art that's already in the database - */ - public function gather_db($limit = null) { - if ($this->get_db()) { - return array('db' => true); - } - return array(); - } - - /** - * gather_musicbrainz - * This function retrieves art based on MusicBrainz' Advanced - * Relationships - */ - public function gather_musicbrainz($limit = 5) { - $images = array(); - $num_found = 0; - - if ($this->type == 'album') { - $album = new Album($this->uid); - } - else { - return $images; - } - - if ($album->mbid) { - debug_event('mbz-gatherart', "Album MBID: " . $album->mbid, '5'); - } - else { - return $images; - } - - $mbquery = new MusicBrainzQuery(); - $includes = new mbReleaseIncludes(); - try { - $release = $mbquery->getReleaseByID($album->mbid, $includes->urlRelations()); - } catch (Exception $e) { - return $images; - } - - $asin = $release->getAsin(); - - if ($asin) { - debug_event('mbz-gatherart', "Found ASIN: " . $asin, '5'); - $base_urls = array( - "01" => "ec1.images-amazon.com", - "02" => "ec1.images-amazon.com", - "03" => "ec2.images-amazon.com", - "08" => "ec1.images-amazon.com", - "09" => "ec1.images-amazon.com", - ); - foreach ($base_urls as $server_num => $base_url) { - // to avoid complicating things even further, we only look for large cover art - $url = 'http://' . $base_url . '/images/P/' . $asin . '.' . $server_num . '.LZZZZZZZ.jpg'; - debug_event('mbz-gatherart', "Evaluating Amazon URL: " . $url, '5'); - $snoopy = new Snoopy(); - if(Config::get('proxy_host') AND Config::get('proxy_port')) { - $snoopy->proxy_user = Config::get('proxy_host'); - $snoopy->proxy_port = Config::get('proxy_port'); - $snoopy->proxy_user = Config::get('proxy_user'); - $snoopy->proxy_pass = Config::get('proxy_pass'); - } - if ($snoopy->fetch($url)) { - $num_found++; - debug_event('mbz-gatherart', "Amazon URL added: " . $url, '5'); - $images[] = array( - 'url' => $url, - 'mime' => 'image/jpeg', - ); - if ($num_found >= $limit) { - return $images; - } - } - } - } - // The next bit is based directly on the MusicBrainz server code - // that displays cover art. - // I'm leaving in the releaseuri info for the moment, though - // it's not going to be used. - $coverartsites[] = array( - 'name' => "CD Baby", - 'domain' => "cdbaby.com", - 'regexp' => '@http://cdbaby\.com/cd/(\w)(\w)(\w*)@', - 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[1]$matches[2]$matches[3].jpg', - 'releaseuri' => 'http://cdbaby.com/cd/$matches[1]$matches[2]$matches[3]/from/musicbrainz', - ); - $coverartsites[] = array( - 'name' => "CD Baby", - 'domain' => "cdbaby.name", - 'regexp' => "@http://cdbaby\.name/([a-z0-9])/([a-z0-9])/([A-Za-z0-9]*).jpg@", - 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[3].jpg', - 'releaseuri' => 'http://cdbaby.com/cd/$matches[3]/from/musicbrainz', - ); - $coverartsites[] = array( - 'name' => 'archive.org', - 'domain' => 'archive.org', - 'regexp' => '/^(.*\.(jpg|jpeg|png|gif))$/', - 'imguri' => '$matches[1]', - 'releaseuri' => '', - ); - $coverartsites[] = array( - 'name' => "Jamendo", - 'domain' => "www.jamendo.com", - 'regexp' => '/http://www\.jamendo\.com/(\w\w/)?album/(\d+)/', - 'imguri' => 'http://img.jamendo.com/albums/$matches[2]/covers/1.200.jpg', - 'releaseuri' => 'http://www.jamendo.com/album/$matches[2]', - ); - $coverartsites[] = array( - 'name' => '8bitpeoples.com', - 'domain' => '8bitpeoples.com', - 'regexp' => '/^(.*)$/', - 'imguri' => '$matches[1]', - 'releaseuri' => '', - ); - $coverartsites[] = array( - 'name' => 'Encyclopédisque', - 'domain' => 'encyclopedisque.fr', - 'regexp' => '/http://www.encyclopedisque.fr/images/imgdb/(thumb250|main)/(\d+).jpg/', - 'imguri' => 'http://www.encyclopedisque.fr/images/imgdb/thumb250/$matches[2].jpg', - 'releaseuri' => 'http://www.encyclopedisque.fr/', - ); - $coverartsites[] = array( - 'name' => 'Thastrom', - 'domain' => 'www.thastrom.se', - 'regexp' => '/^(.*)$/', - 'imguri' => '$matches[1]', - 'releaseuri' => '', - ); - $coverartsites[] = array( - 'name' => 'Universal Poplab', - 'domain' => 'www.universalpoplab.com', - 'regexp' => '/^(.*)$/', - 'imguri' => '$matches[1]', - 'releaseuri' => '', - ); - foreach ($release->getRelations(mbRelation::TO_URL) as $ar) { - $arurl = $ar->getTargetId(); - debug_event('mbz-gatherart', "Found URL AR: " . $arurl , '5'); - foreach ($coverartsites as $casite) { - if (strpos($arurl, $casite['domain']) !== false) { - debug_event('mbz-gatherart', "Matched coverart site: " . $casite['name'], '5'); - if (preg_match($casite['regexp'], $arurl, $matches)) { - $num_found++; - eval("\$url = \"$casite[imguri]\";"); - debug_event('mbz-gatherart', "Generated URL added: " . $url, '5'); - $images[] = array( - 'url' => $url, - 'mime' => 'image/jpeg', - ); - if ($num_found >= $limit) { - return $images; - } - } - } - } // end foreach coverart sites - } // end foreach - - return $images; - - } // gather_musicbrainz - - /** - * gather_amazon - * This takes keywords and performs a search of the Amazon website - * for the art. It returns an array of found objects with mime/url keys - */ - public function gather_amazon($limit = 5, $keywords = '') { - - $images = array(); - $final_results = array(); - $possible_keys = array( - 'LargeImage', - 'MediumImage', - 'SmallImage' - ); - - // Prevent the script from timing out - set_time_limit(0); - - if (empty($keywords)) { - $keywords = $this->full_name; - /* If this isn't a various album combine with artist name */ - if ($this->artist_count == '1') { $keywords .= ' ' . $this->artist_name; } - } - - /* Attempt to retrieve the album art order */ - $amazon_base_urls = Config::get('amazon_base_urls'); - - /* If it's not set */ - if (!count($amazon_base_urls)) { - $amazon_base_urls = array('http://webservices.amazon.com'); - } - - /* Foreach through the base urls that we should check */ - foreach ($amazon_base_urls as $amazon_base) { - - // Create the Search Object - $amazon = new AmazonSearch(Config::get('amazon_developer_public_key'), Config::get('amazon_developer_private_key'), $amazon_base); - if(Config::get('proxy_host') AND Config::get('proxy_port')) { - $proxyhost = Config::get('proxy_host'); - $proxyport = Config::get('proxy_port'); - $proxyuser = Config::get('proxy_user'); - $proxypass = Config::get('proxy_pass'); - debug_event('amazon', 'setProxy', 5); - $amazon->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass); - } - - $search_results = array(); - - /* Set up the needed variables */ - $max_pages_to_search = max(Config::get('max_amazon_results_pages'),$amazon->_default_results_pages); - $pages_to_search = $max_pages_to_search; //init to max until we know better. - // while we have pages to search - do { - $raw_results = $amazon->search(array('artist'=>$artist,'album'=>$albumname,'keywords'=>$keywords)); - - $total = count($raw_results) + count($search_results); - - // If we've gotten more then we wanted - if ($limit && $total > $limit) { - $raw_results = array_slice($raw_results, 0, -($total - $limit), true); - - debug_event('amazon-xml', "Found $total, limit $limit; reducing and breaking from loop", 5); - // Merge the results and BREAK! - $search_results = array_merge($search_results,$raw_results); - break; - } // if limit defined - - $search_results = array_merge($search_results,$raw_results); - $pages_to_search = min($max_pages_to_search, $amazon->_maxPage); - debug_event('amazon-xml', "Searched results page " . ($amazon->_currentPage+1) . "/" . $pages_to_search,'5'); - $amazon->_currentPage++; - - } while ($amazon->_currentPage < $pages_to_search); - - - // Only do the second search if the first actually returns something - if (count($search_results)) { - $final_results = $amazon->lookup($search_results); - } - - /* Log this if we're doin debug */ - debug_event('amazon-xml',"Searched using $keywords with " . Config::get('amazon_developer_key') . " as key, results: " . count($final_results), 5); - - // If we've hit our limit - if (!empty($limit) && count($final_results) >= $limit) { - break; - } - - } // end foreach - - /* Foreach through what we've found */ - foreach ($final_results as $result) { - - /* Recurse through the images found */ - foreach ($possible_keys as $key) { - if (strlen($result[$key])) { - break; - } - } // foreach - - // Rudimentary image type detection, only JPG and GIF allowed. - if (substr($result[$key], -4 == '.jpg')) { - $mime = "image/jpeg"; - } - elseif (substr($result[$key], -4 == '.gif')) { - $mime = "image/gif"; - } - elseif (substr($result[$key], -4 == '.png')) { - $mime = "image/png"; - } - else { - /* Just go to the next result */ - continue; - } - - $data['url'] = $result[$key]; - $data['mime'] = $mime; - - $images[] = $data; - - if (!empty($limit)) { - if (count($images) >= $limit) { - return $images; - } - } - - } // if we've got something - - return $images; - - } // gather_amazon - - /** - * gather_folder - * This returns the art from the folder of the files - * If a limit is passed or the preferred filename is found the current - * results set is returned - */ - public function gather_folder($limit = 5) { - - $media = new Album($this->uid); - $songs = $media->get_songs(); - $results = array(); - $preferred = false; - // For storing which directories we've already done - $processed = array(); - - /* See if we are looking for a specific filename */ - $preferred_filename = Config::get('album_art_preferred_filename'); - - // Array of valid extensions - $image_extensions = array( - 'bmp', - 'gif', - 'jp2', - 'jpeg', - 'jpg', - 'png' - ); - - foreach ($songs as $song_id) { - $data = array(); - $song = new Song($song_id); - $dir = dirname($song->file); - - if (isset($processed[$dir])) { - continue; - } - - debug_event('folder_art', "Opening $dir and checking for Album Art", 3); - - /* Open up the directory */ - $handle = opendir($dir); - - if (!$handle) { - Error::add('general', T_('Error: Unable to open') . ' ' . $dir); - debug_event('folder_art', "Error: Unable to open $dir for album art read", 2); - continue; - } - - $processed[$dir] = true; - - // Recurse through this dir and create the files array - while ($file = readdir($handle)) { - $extension = pathinfo($file); - $extension = $extension['extension']; - - // Make sure it looks like an image file - if (!in_array($extension, $image_extensions)) { - continue; - } - - $full_filename = $dir . '/' . $file; - - // Make sure it's got something in it - if (!filesize($full_filename)) { - debug_event('folder_art', "Empty file, rejecting $file", 5); - continue; - } - - // Regularise for mime type - if ($extension == 'jpg') { - $extension = 'jpeg'; - } - - // Take an md5sum so we don't show duplicate - // files. - $index = md5($full_filename); - - if ($file == $preferred_filename) { - // We found the preferred filename and - // so we're done. - debug_event('folder_art', "Found preferred image file: $file", 5); - $preferred[$index] = array( - 'file' => $full_filename, - 'mime' => 'image/' . $extension - ); - break; - } - - debug_event('folder_art', "Found image file: $file", 5); - $results[$index] = array( - 'file' => $full_filename, - 'mime' => 'image/' . $extension - ); - - } // end while reading dir - closedir($handle); - - } // end foreach songs - - if (is_array($preferred)) { - // We found our favourite filename somewhere, so we need - // to dump the other, less sexy ones. - $results = $preferred; - } - - debug_event('folder_art', 'Results: ' . json_encode($results), 5); - if ($limit && count($results) > $limit) { - $results = array_slice($results, 0, $limit); - } - - return array_values($results); - - } // gather_folder - - /** - * gather_tags - * This looks for the art in the meta-tags of the file - * itself - */ - public function gather_tags($limit = 5) { - - // We need the filenames - $album = new Album($this->uid); - - // grab the songs and define our results - $songs = $album->get_songs(); - $data = array(); - - // Foreach songs in this album - foreach ($songs as $song_id) { - $song = new Song($song_id); - // If we find a good one, stop looking - $getID3 = new getID3(); - try { $id3 = $getID3->analyze($song->file); } - catch (Exception $error) { - debug_event('getid3', $error->message, 1); - } - - if (isset($id3['asf']['extended_content_description_object']['content_descriptors']['13'])) { - $image = $id3['asf']['extended_content_description_object']['content_descriptors']['13']; - $data[] = array( - 'song' => $song->file, - 'raw' => $image['data'], - 'mime' => $image['mime']); - } - - if (isset($id3['id3v2']['APIC'])) { - // Foreach in case they have more then one - foreach ($id3['id3v2']['APIC'] as $image) { - $data[] = array( - 'song' => $song->file, - 'raw' => $image['data'], - 'mime' => $image['mime']); - } - } - - if ($limit && count($data) >= $limit) { - return array_slice($data, 0, $limit); - } - - } // end foreach - - return $data; - - } // gather_tags - - /** - * gather_google - * Raw google search to retrieve the art, not very reliable - */ - public function gather_google($limit = 5) { - - $images = array(); - $media = new $this->type($this->uid); - $media->format(); - - $search = $media->full_name; - - if ($media->artist_count == '1') - $search = $media->artist_name . ', ' . $search; - - $search = rawurlencode($search); - - $size = '&imgsz=m'; // Medium - //$size = '&imgsz=l'; // Large - - $html = file_get_contents("http://images.google.com/images?source=hp&q=$search&oq=&um=1&ie=UTF-8&sa=N&tab=wi&start=0&tbo=1$size"); - - if(preg_match_all("|\ssrc\=\"(http.+?)\"|", $html, $matches, PREG_PATTERN_ORDER)) - foreach ($matches[1] as $match) { - $extension = "image/jpeg"; - - if (strrpos($extension, '.') !== false) $extension = substr($extension, strrpos($extension, '.') + 1); - - $images[] = array('url' => $match, 'mime' => $extension); - } - - return $images; - - } // gather_google - - /** - * gather_lastfm - * This returns the art from lastfm. It doesn't currently require an - * account but may in the future. - */ - public function gather_lastfm($limit, $options = false) { - - // Create the parser object - $lastfm = new LastFMSearch(); - - switch ($this->type) { - case 'album': - if (is_array($options)) { - $artist = $options['artist']; - $album = $options['album_name']; - } - else { - $media = new Album($this->uid); - $media->format(); - $artist = $media->artist_name; - $album = $media->full_name; - } - break; - } - - if(Config::get('proxy_host') AND Config::get('proxy_port')) { - $proxyhost = Config::get('proxy_host'); - $proxyport = Config::get('proxy_port'); - $proxyuser = Config::get('proxy_user'); - $proxypass = Config::get('proxy_pass'); - debug_event('LastFM', 'proxy set', 5); - $lastfm->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass); - } - - $raw_data = $lastfm->album_search($artist, $album); - - if (!count($raw_data)) { return array(); } - - $coverart = $raw_data['coverart']; - if (!is_array($coverart)) { return array(); } - - ksort($coverart); - foreach ($coverart as $url) { - // We need to check the URL for the /noimage/ stuff - if (strpos($url, '/noimage/') !== false) { - debug_event('LastFM', 'Detected as noimage, skipped ' . $url, 3); - continue; - } - - // HACK: we shouldn't rely on the extension to determine file type - $results = pathinfo($url); - $mime = 'image/' . $results['extension']; - $data[] = array('url' => $url, 'mime' => $mime); - if ($limit && count($data) >= $limit) { - return $data; - } - } // end foreach - - return $data; - - } // gather_lastfm + public $type; + public $uid; // UID of the object not ID because it's not the ART.ID + public $raw; // Raw art data + public $raw_mime; + + public $thumb; + public $thumb_mime; + + private static $enabled; + + /** + * Constructor + * Art constructor, takes the UID of the object and the + * object type. + */ + public function __construct($uid, $type = 'album') { + + $this->type = Art::validate_type($type); + $this->uid = $uid; + + } // constructor + + /** + * build_cache + * This attempts to reduce # of queries by asking for everything in the + * browse all at once and storing it in the cache, this can help if the + * db connection is the slow point + */ + public static function build_cache($object_ids) { + + if (!is_array($object_ids) || !count($object_ids)) { return false; } + $uidlist = '(' . implode(',', $object_ids) . ')'; + $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_id` IN $uidlist"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('art', $row['object_type'] . + $row['object_id'] . $row['size'], $row); + } + + return true; + } // build_cache + + + /** + * _auto_init + * Called on creation of the class + */ + public static function _auto_init() { + if (!isset($_SESSION['art_enabled'])) { + $_SESSION['art_enabled'] = (Config::get('bandwidth') > 25); + } + self::$enabled = make_bool($_SESSION['art_enabled']); + } + + /** + * is_enabled + * Checks whether the user currently wants art + */ + public static function is_enabled() { + if (self::$enabled) { + return true; + } + + return false; + } + + /** + * set_enabled + * Changes the value of enabled + */ + public static function set_enabled($value = null) { + if (is_null($value)) { + self::$enabled = self::$enabled ? false : true; + } + else { + self::$enabled = make_bool($value); + } + + $_SESSION['art_enabled'] = self::$enabled; + } + + /** + * validate_type + * This validates the type + */ + public static function validate_type($type) { + + switch ($type) { + case 'album': + case 'artist': + case 'video': + return $type; + break; + default: + return 'album'; + break; + } + + } // validate_type + + /** + * extension + * This returns the file extension for the currently loaded art + */ + public static function extension($mime) { + + $data = explode("/", $mime); + $extension = $data['1']; + + if ($extension == 'jpeg') { $extension = 'jpg'; } + + return $extension; + + } // extension + + /** + * test_image + * Runs some sanity checks on the putative image + */ + public static function test_image($source) { + if (strlen($source) < 10) { + debug_event('Art', 'Invalid image passed', 1); + return false; + } + + // Check to make sure PHP:GD exists. If so, we can sanity check + // the image. + if (function_exists('ImageCreateFromString')) { + $image = ImageCreateFromString($source); + if (!$image || imagesx($image) < 5 || imagesy($image) < 5) { + debug_event('Art', 'Image failed PHP-GD test',1); + return false; + } + } + + return true; + } //test_image + + /** + * get + * This returns the art for our current object, this can + * look in the database and will return the thumb if it + * exists, if it doesn't depending on settings it will try + * to create it. + */ + public function get($raw=false) { + + // Get the data either way + if (!$this->get_db()) { + return false; + } + + if ($raw || !$this->thumb) { + return $this->raw; + } + else { + return $this->thumb; + } + + } // get + + + /** + * get_db + * This pulls the information out from the database, depending + * on if we want to resize and if there is not a thumbnail go + * ahead and try to resize + */ + public function get_db() { + + $type = Dba::escape($this->type); + $id = Dba::escape($this->uid); + + $sql = "SELECT `image`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$id'"; + $db_results = Dba::read($sql); + + while ($results = Dba::fetch_assoc($db_results)) { + if ($results['size'] == 'original') { + $this->raw = $results['image']; + $this->raw_mime = $results['mime']; + } + else if (Config::get('resize_images') && + $results['size'] == '275x275') { + $this->thumb = $results['image']; + $this->raw_mime = $results['mime']; + } + } + // If we get nothing return false + if (!$this->raw) { return false; } + + // If there is no thumb and we want thumbs + if (!$this->thumb && Config::get('resize_images')) { + $data = $this->generate_thumb($this->raw, array('width' => 275, 'height' => 275), $this->raw_mime); + // If it works save it! + if ($data) { + $this->save_thumb($data['thumb'], $data['thumb_mime'], '275x275'); + $this->thumb = $data['thumb']; + $this->thumb_mime = $data['thumb_mime']; + } + else { + debug_event('Art','Unable to retrieve or generate thumbnail for ' . $type . '::' . $id,1); + } + } // if no thumb, but art and we want to resize + + return true; + + } // get_db + + /** + * insert + * This takes the string representation of an image and inserts it into + * the database. You must also pass the mime type. + */ + public function insert($source, $mime) { + + // Disabled in demo mode cause people suck and upload porn + if (Config::get('demo_mode')) { return false; } + + // Check to make sure we like this image + if (!self::test_image($source)) { + debug_event('Art', 'Not inserting image, invalid data passed', 1); + return false; + } + + // Default to image/jpeg if they don't pass anything + $mime = $mime ? $mime : 'image/jpeg'; + + $image = Dba::escape($source); + $mime = Dba::escape($mime); + $uid = Dba::escape($this->uid); + $type = Dba::escape($this->type); + + // Blow it away! + $this->reset(); + + // Insert it! + $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$image', '$mime', 'original', '$type', '$uid')"; + $db_results = Dba::write($sql); + + return true; + + } // insert + + /** + * reset + * This resets the art in the database + */ + public function reset() { + + $type = Dba::escape($this->type); + $uid = Dba::escape($this->uid); + + $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type'"; + $db_results = Dba::write($sql); + + } // reset + + /** + * save_thumb + * This saves the thumbnail that we're passed + */ + public function save_thumb($source, $mime, $size) { + + // Quick sanity check + if (!self::test_image($source)) { + debug_event('Art', 'Not inserting thumbnail, invalid data passed', 1); + return false; + } + + $source = Dba::escape($source); + $mime = Dba::escape($mime); + $size = Dba::escape($size); + $uid = Dba::escape($this->uid); + $type = Dba::escape($this->type); + + $sql = "DELETE FROM `image` WHERE `object_id`='$uid' AND `object_type`='$type' AND `size`='$size'"; + $db_results = Dba::write($sql); + + $sql = "INSERT INTO `image` (`image`, `mime`, `size`, `object_type`, `object_id`) VALUES('$source', '$mime', '$size', '$type', '$uid')"; + $db_results = Dba::write($sql); + + } // save_thumb + + /** + * get_thumb + * Returns the specified resized image. If the requested size doesn't + * already exist, create and cache it. + */ + public function get_thumb($size) { + $sizetext = $size['width'] . 'x' . $size['height']; + $sizetext = Dba::escape($sizetext); + $type = Dba::escape($this->type); + $uid = Dba::escape($this->uid); + + $sql = "SELECT `image`, `mime` FROM `image` WHERE `size`='$sizetext' AND `object_type`='$type' AND `object_id`='$uid'"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + if (count($results)) { + return array('thumb' => $results['image'], + 'thumb_mime' => $results['mime']); + } + + // If we didn't get a result + $results = $this->generate_thumb($this->raw, $size, $this->raw_mime); + if ($results) { + $this->save_thumb($results['thumb'], $results['thumb_mime'], $sizetext); + } + + return $results; + } // get_thumb + + /** + * generate_thumb + * Automatically resizes the image for thumbnail viewing. + * Only works on gif/jpg/png/bmp. Fails if PHP-GD isn't available + * or lacks support for the requested image type. + */ + public function generate_thumb($image,$size,$mime) { + + $data = explode("/",$mime); + $type = strtolower($data['1']); + + if (!self::test_image($image)) { + debug_event('Art', 'Not trying to generate thumbnail, invalid data passed', 1); + return false; + } + + if (!function_exists('gd_info')) { + debug_event('Art','PHP-GD Not found - unable to resize art',1); + return false; + } + + // Check and make sure we can resize what you've asked us to + if (($type == 'jpg' OR $type == 'jpeg') AND !(imagetypes() & IMG_JPG)) { + debug_event('Art','PHP-GD Does not support JPGs - unable to resize',1); + return false; + } + if ($type == 'png' AND !imagetypes() & IMG_PNG) { + debug_event('Art','PHP-GD Does not support PNGs - unable to resize',1); + return false; + } + if ($type == 'gif' AND !imagetypes() & IMG_GIF) { + debug_event('Art','PHP-GD Does not support GIFs - unable to resize',1); + return false; + } + if ($type == 'bmp' AND !imagetypes() & IMG_WBMP) { + debug_event('Art','PHP-GD Does not support BMPs - unable to resize',1); + return false; + } + + $source = imagecreatefromstring($image); + + if (!$source) { + debug_event('Art','Failed to create Image from string - Source Image is damaged / malformed',1); + return false; + } + + $source_size = array('height' => imagesy($source), 'width' => imagesx($source)); + + // Create a new blank image of the correct size + $thumbnail = imagecreatetruecolor($size['width'], $size['height']); + + if (!imagecopyresampled($thumbnail, $source, 0, 0, 0, 0, $size['width'], $size['height'], $source_size['width'], $source_size['height'])) { + debug_event('Art','Unable to create resized image',1); + return false; + } + + // Start output buffer + ob_start(); + + // Generate the image to our OB + switch ($type) { + case 'jpg': + case 'jpeg': + imagejpeg($thumbnail, null, 75); + $mime_type = image_type_to_mime_type(IMAGETYPE_JPEG); + break; + case 'gif': + imagegif($thumbnail); + $mime_type = image_type_to_mime_type(IMAGETYPE_GIF); + break; + // Turn bmps into pngs + case 'bmp': + $type = 'png'; + case 'png': + imagepng($thumbnail); + $mime_type = image_type_to_mime_type(IMAGETYPE_PNG); + break; + } // resized + + $data = ob_get_contents(); + ob_end_clean(); + + if (!strlen($data)) { + debug_event('Art', 'Unknown Error resizing art', 1); + return false; + } + + return array('thumb' => $data, 'thumb_mime' => $mime_type); + + } // generate_thumb + + /** + * get_from_source + * This gets an image for the album art from a source as + * defined in the passed array. Because we don't know where + * it's coming from we are a passed an array that can look like + * ['url'] = URL *** OPTIONAL *** + * ['file'] = FILENAME *** OPTIONAL *** + * ['raw'] = Actual Image data, already captured + */ + public static function get_from_source($data, $type = 'album') { + + // Already have the data, this often comes from id3tags + if (isset($data['raw'])) { + return $data['raw']; + } + + // If it came from the database + if (isset($data['db'])) { + // Repull it + $uid = Dba::escape($data['db']); + $type = Dba::escape($type); + + $sql = "SELECT * FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid' AND `size`='original'"; + $db_results = Dba::read($sql); + $row = Dba::fetch_assoc($db_results); + return $row['art']; + } // came from the db + + // Check to see if it's a URL + if (isset($data['url'])) { + $snoopy = new Snoopy(); + if(Config::get('proxy_host') AND Config::get('proxy_port')) { + $snoopy->proxy_user = Config::get('proxy_host'); + $snoopy->proxy_port = Config::get('proxy_port'); + $snoopy->proxy_user = Config::get('proxy_user'); + $snoopy->proxy_pass = Config::get('proxy_pass'); + } + $snoopy->fetch($data['url']); + return $snoopy->results; + } + + // Check to see if it's a FILE + if (isset($data['file'])) { + $handle = fopen($data['file'],'rb'); + $image_data = fread($handle,filesize($data['file'])); + fclose($handle); + return $image_data; + } + + // Check to see if it is embedded in id3 of a song + if (isset($data['song'])) { + // If we find a good one, stop looking + $getID3 = new getID3(); + $id3 = $getID3->analyze($data['song']); + + if ($id3['format_name'] == "WMA") { + return $id3['asf']['extended_content_description_object']['content_descriptors']['13']['data']; + } + elseif (isset($id3['id3v2']['APIC'])) { + // Foreach in case they have more then one + foreach ($id3['id3v2']['APIC'] as $image) { + return $image['data']; + } + } + } // if data song + + return false; + + } // get_from_source + + /** + * url + * This returns the constructed URL for the art in question + */ + public static function url($uid,$type,$sid=false) { + + $sid = $sid ? scrub_out($sid) : scrub_out(session_id()); + $type = self::validate_type($type); + + $key = $type . $uid; + if (parent::is_cached('art', $key . '275x275') && Config::get('resize_images')) { + $row = parent::get_from_cache('art', $key . '275x275'); + $mime = $row['mime']; + } + if (parent::is_cached('art', $key . 'original')) { + $row = parent::get_from_cache('art', $key . 'original'); + $thumb_mime = $row['mime']; + } + if (!$mime && !$thumb_mime) { + + $type = Dba::escape($type); + $uid = Dba::escape($uid); + + $sql = "SELECT `object_type`, `object_id`, `mime`, `size` FROM `image` WHERE `object_type`='$type' AND `object_id`='$uid'"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('art', $key . $row['size'], $row); + if ($row['size'] == 'original') { + $mime = $row['mime']; + } + else if ($row['size'] == '275x275' && Config::get('resize_images')) { + $thumb_mime = $row['mime']; + } + } + } + + $mime = $thumb_mime ? $thumb_mime : $mime; + $extension = self::extension($mime); + + $name = 'art.' . $extension; + $url = Config::get('web_path') . '/image.php?id=' . scrub_out($uid) . '&object_type=' . scrub_out($type) . '&auth=' . $sid . '&name=' . $name; + + return $url; + + } // url + + + /** + * gc + * This cleans up art that no longer has a corresponding object + */ + public static function gc() { + // iterate over our types and delete the images + foreach (array('album', 'artist') as $type) { + $sql = "DELETE FROM `image` USING `image` LEFT JOIN `" . + $type . "` ON `" . $type . "`.`id`=" . + "`image`.`object_id` WHERE `object_type`='" . + $type . "' AND `" . $type . "`.`id` IS NULL"; + $db_results = Dba::write($sql); + } // foreach + } + + /** + * gather + * This tries to get the art in question + */ + public function gather($options = array(), $limit = false) { + + // Define vars + $results = array(); + + switch ($this->type) { + case 'album': + $allowed_methods = array('db','lastfm','folder','amazon','google','musicbrainz','tags'); + break; + case 'artist': + $allowed_methods = array(); + break; + case 'video': + $allowed_methods = array(); + break; + } + + $config = Config::get('art_order'); + $methods = get_class_methods('Art'); + + /* If it's not set */ + if (empty($config)) { + // They don't want art! + debug_event('Art', 'art_order is empty, skipping art gathering', 3); + return array(); + } + elseif (!is_array($config)) { + $config = array($config); + } + + debug_event('Art','Searching using:' . json_encode($config), 3); + + foreach ($config as $method) { + + $data = array(); + + if (!in_array($method, $allowed_methods)) { + debug_event('Art', "$method not in allowed_methods, skipping", 3); + continue; + } + + $method_name = "gather_" . $method; + + if (in_array($method_name, $methods)) { + debug_event('Art', "Method used: $method_name", 3); + // Some of these take options! + switch ($method_name) { + case 'gather_amazon': + $data = $this->{$method_name}($limit, $options['keyword']); + break; + case 'gather_lastfm': + $data = $this->{$method_name}($limit, $options); + break; + default: + $data = $this->{$method_name}($limit); + break; + } + + // Add the results we got to the current set + $results = array_merge($results, (array)$data); + + if ($limit && count($results) >= $limit) { + return array_slice($results, 0, $limit); + } + + } // if the method exists + else { + debug_event("Art", "$method_name not defined", 1); + } + + } // end foreach + + return $results; + + } // gather + + + /////////////////////////////////////////////////////////////////////// + // Art Methods + /////////////////////////////////////////////////////////////////////// + + /** + * gather_db + * This function retrieves art that's already in the database + */ + public function gather_db($limit = null) { + if ($this->get_db()) { + return array('db' => true); + } + return array(); + } + + /** + * gather_musicbrainz + * This function retrieves art based on MusicBrainz' Advanced + * Relationships + */ + public function gather_musicbrainz($limit = 5) { + $images = array(); + $num_found = 0; + + if ($this->type == 'album') { + $album = new Album($this->uid); + } + else { + return $images; + } + + if ($album->mbid) { + debug_event('mbz-gatherart', "Album MBID: " . $album->mbid, '5'); + } + else { + return $images; + } + + $mbquery = new MusicBrainzQuery(); + $includes = new mbReleaseIncludes(); + try { + $release = $mbquery->getReleaseByID($album->mbid, $includes->urlRelations()); + } catch (Exception $e) { + return $images; + } + + $asin = $release->getAsin(); + + if ($asin) { + debug_event('mbz-gatherart', "Found ASIN: " . $asin, '5'); + $base_urls = array( + "01" => "ec1.images-amazon.com", + "02" => "ec1.images-amazon.com", + "03" => "ec2.images-amazon.com", + "08" => "ec1.images-amazon.com", + "09" => "ec1.images-amazon.com", + ); + foreach ($base_urls as $server_num => $base_url) { + // to avoid complicating things even further, we only look for large cover art + $url = 'http://' . $base_url . '/images/P/' . $asin . '.' . $server_num . '.LZZZZZZZ.jpg'; + debug_event('mbz-gatherart', "Evaluating Amazon URL: " . $url, '5'); + $snoopy = new Snoopy(); + if(Config::get('proxy_host') AND Config::get('proxy_port')) { + $snoopy->proxy_user = Config::get('proxy_host'); + $snoopy->proxy_port = Config::get('proxy_port'); + $snoopy->proxy_user = Config::get('proxy_user'); + $snoopy->proxy_pass = Config::get('proxy_pass'); + } + if ($snoopy->fetch($url)) { + $num_found++; + debug_event('mbz-gatherart', "Amazon URL added: " . $url, '5'); + $images[] = array( + 'url' => $url, + 'mime' => 'image/jpeg', + ); + if ($num_found >= $limit) { + return $images; + } + } + } + } + // The next bit is based directly on the MusicBrainz server code + // that displays cover art. + // I'm leaving in the releaseuri info for the moment, though + // it's not going to be used. + $coverartsites[] = array( + 'name' => "CD Baby", + 'domain' => "cdbaby.com", + 'regexp' => '@http://cdbaby\.com/cd/(\w)(\w)(\w*)@', + 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[1]$matches[2]$matches[3].jpg', + 'releaseuri' => 'http://cdbaby.com/cd/$matches[1]$matches[2]$matches[3]/from/musicbrainz', + ); + $coverartsites[] = array( + 'name' => "CD Baby", + 'domain' => "cdbaby.name", + 'regexp' => "@http://cdbaby\.name/([a-z0-9])/([a-z0-9])/([A-Za-z0-9]*).jpg@", + 'imguri' => 'http://cdbaby.name/$matches[1]/$matches[2]/$matches[3].jpg', + 'releaseuri' => 'http://cdbaby.com/cd/$matches[3]/from/musicbrainz', + ); + $coverartsites[] = array( + 'name' => 'archive.org', + 'domain' => 'archive.org', + 'regexp' => '/^(.*\.(jpg|jpeg|png|gif))$/', + 'imguri' => '$matches[1]', + 'releaseuri' => '', + ); + $coverartsites[] = array( + 'name' => "Jamendo", + 'domain' => "www.jamendo.com", + 'regexp' => '/http://www\.jamendo\.com/(\w\w/)?album/(\d+)/', + 'imguri' => 'http://img.jamendo.com/albums/$matches[2]/covers/1.200.jpg', + 'releaseuri' => 'http://www.jamendo.com/album/$matches[2]', + ); + $coverartsites[] = array( + 'name' => '8bitpeoples.com', + 'domain' => '8bitpeoples.com', + 'regexp' => '/^(.*)$/', + 'imguri' => '$matches[1]', + 'releaseuri' => '', + ); + $coverartsites[] = array( + 'name' => 'Encyclopédisque', + 'domain' => 'encyclopedisque.fr', + 'regexp' => '/http://www.encyclopedisque.fr/images/imgdb/(thumb250|main)/(\d+).jpg/', + 'imguri' => 'http://www.encyclopedisque.fr/images/imgdb/thumb250/$matches[2].jpg', + 'releaseuri' => 'http://www.encyclopedisque.fr/', + ); + $coverartsites[] = array( + 'name' => 'Thastrom', + 'domain' => 'www.thastrom.se', + 'regexp' => '/^(.*)$/', + 'imguri' => '$matches[1]', + 'releaseuri' => '', + ); + $coverartsites[] = array( + 'name' => 'Universal Poplab', + 'domain' => 'www.universalpoplab.com', + 'regexp' => '/^(.*)$/', + 'imguri' => '$matches[1]', + 'releaseuri' => '', + ); + foreach ($release->getRelations(mbRelation::TO_URL) as $ar) { + $arurl = $ar->getTargetId(); + debug_event('mbz-gatherart', "Found URL AR: " . $arurl , '5'); + foreach ($coverartsites as $casite) { + if (strpos($arurl, $casite['domain']) !== false) { + debug_event('mbz-gatherart', "Matched coverart site: " . $casite['name'], '5'); + if (preg_match($casite['regexp'], $arurl, $matches)) { + $num_found++; + eval("\$url = \"$casite[imguri]\";"); + debug_event('mbz-gatherart', "Generated URL added: " . $url, '5'); + $images[] = array( + 'url' => $url, + 'mime' => 'image/jpeg', + ); + if ($num_found >= $limit) { + return $images; + } + } + } + } // end foreach coverart sites + } // end foreach + + return $images; + + } // gather_musicbrainz + + /** + * gather_amazon + * This takes keywords and performs a search of the Amazon website + * for the art. It returns an array of found objects with mime/url keys + */ + public function gather_amazon($limit = 5, $keywords = '') { + + $images = array(); + $final_results = array(); + $possible_keys = array( + 'LargeImage', + 'MediumImage', + 'SmallImage' + ); + + // Prevent the script from timing out + set_time_limit(0); + + if (empty($keywords)) { + $keywords = $this->full_name; + /* If this isn't a various album combine with artist name */ + if ($this->artist_count == '1') { $keywords .= ' ' . $this->artist_name; } + } + + /* Attempt to retrieve the album art order */ + $amazon_base_urls = Config::get('amazon_base_urls'); + + /* If it's not set */ + if (!count($amazon_base_urls)) { + $amazon_base_urls = array('http://webservices.amazon.com'); + } + + /* Foreach through the base urls that we should check */ + foreach ($amazon_base_urls as $amazon_base) { + + // Create the Search Object + $amazon = new AmazonSearch(Config::get('amazon_developer_public_key'), Config::get('amazon_developer_private_key'), $amazon_base); + if(Config::get('proxy_host') AND Config::get('proxy_port')) { + $proxyhost = Config::get('proxy_host'); + $proxyport = Config::get('proxy_port'); + $proxyuser = Config::get('proxy_user'); + $proxypass = Config::get('proxy_pass'); + debug_event('amazon', 'setProxy', 5); + $amazon->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass); + } + + $search_results = array(); + + /* Set up the needed variables */ + $max_pages_to_search = max(Config::get('max_amazon_results_pages'),$amazon->_default_results_pages); + $pages_to_search = $max_pages_to_search; //init to max until we know better. + // while we have pages to search + do { + $raw_results = $amazon->search(array('artist'=>$artist,'album'=>$albumname,'keywords'=>$keywords)); + + $total = count($raw_results) + count($search_results); + + // If we've gotten more then we wanted + if ($limit && $total > $limit) { + $raw_results = array_slice($raw_results, 0, -($total - $limit), true); + + debug_event('amazon-xml', "Found $total, limit $limit; reducing and breaking from loop", 5); + // Merge the results and BREAK! + $search_results = array_merge($search_results,$raw_results); + break; + } // if limit defined + + $search_results = array_merge($search_results,$raw_results); + $pages_to_search = min($max_pages_to_search, $amazon->_maxPage); + debug_event('amazon-xml', "Searched results page " . ($amazon->_currentPage+1) . "/" . $pages_to_search,'5'); + $amazon->_currentPage++; + + } while ($amazon->_currentPage < $pages_to_search); + + + // Only do the second search if the first actually returns something + if (count($search_results)) { + $final_results = $amazon->lookup($search_results); + } + + /* Log this if we're doin debug */ + debug_event('amazon-xml',"Searched using $keywords with " . Config::get('amazon_developer_key') . " as key, results: " . count($final_results), 5); + + // If we've hit our limit + if (!empty($limit) && count($final_results) >= $limit) { + break; + } + + } // end foreach + + /* Foreach through what we've found */ + foreach ($final_results as $result) { + + /* Recurse through the images found */ + foreach ($possible_keys as $key) { + if (strlen($result[$key])) { + break; + } + } // foreach + + // Rudimentary image type detection, only JPG and GIF allowed. + if (substr($result[$key], -4 == '.jpg')) { + $mime = "image/jpeg"; + } + elseif (substr($result[$key], -4 == '.gif')) { + $mime = "image/gif"; + } + elseif (substr($result[$key], -4 == '.png')) { + $mime = "image/png"; + } + else { + /* Just go to the next result */ + continue; + } + + $data['url'] = $result[$key]; + $data['mime'] = $mime; + + $images[] = $data; + + if (!empty($limit)) { + if (count($images) >= $limit) { + return $images; + } + } + + } // if we've got something + + return $images; + + } // gather_amazon + + /** + * gather_folder + * This returns the art from the folder of the files + * If a limit is passed or the preferred filename is found the current + * results set is returned + */ + public function gather_folder($limit = 5) { + + $media = new Album($this->uid); + $songs = $media->get_songs(); + $results = array(); + $preferred = false; + // For storing which directories we've already done + $processed = array(); + + /* See if we are looking for a specific filename */ + $preferred_filename = Config::get('album_art_preferred_filename'); + + // Array of valid extensions + $image_extensions = array( + 'bmp', + 'gif', + 'jp2', + 'jpeg', + 'jpg', + 'png' + ); + + foreach ($songs as $song_id) { + $data = array(); + $song = new Song($song_id); + $dir = dirname($song->file); + + if (isset($processed[$dir])) { + continue; + } + + debug_event('folder_art', "Opening $dir and checking for Album Art", 3); + + /* Open up the directory */ + $handle = opendir($dir); + + if (!$handle) { + Error::add('general', T_('Error: Unable to open') . ' ' . $dir); + debug_event('folder_art', "Error: Unable to open $dir for album art read", 2); + continue; + } + + $processed[$dir] = true; + + // Recurse through this dir and create the files array + while ($file = readdir($handle)) { + $extension = pathinfo($file); + $extension = $extension['extension']; + + // Make sure it looks like an image file + if (!in_array($extension, $image_extensions)) { + continue; + } + + $full_filename = $dir . '/' . $file; + + // Make sure it's got something in it + if (!filesize($full_filename)) { + debug_event('folder_art', "Empty file, rejecting $file", 5); + continue; + } + + // Regularise for mime type + if ($extension == 'jpg') { + $extension = 'jpeg'; + } + + // Take an md5sum so we don't show duplicate + // files. + $index = md5($full_filename); + + if ($file == $preferred_filename) { + // We found the preferred filename and + // so we're done. + debug_event('folder_art', "Found preferred image file: $file", 5); + $preferred[$index] = array( + 'file' => $full_filename, + 'mime' => 'image/' . $extension + ); + break; + } + + debug_event('folder_art', "Found image file: $file", 5); + $results[$index] = array( + 'file' => $full_filename, + 'mime' => 'image/' . $extension + ); + + } // end while reading dir + closedir($handle); + + } // end foreach songs + + if (is_array($preferred)) { + // We found our favourite filename somewhere, so we need + // to dump the other, less sexy ones. + $results = $preferred; + } + + debug_event('folder_art', 'Results: ' . json_encode($results), 5); + if ($limit && count($results) > $limit) { + $results = array_slice($results, 0, $limit); + } + + return array_values($results); + + } // gather_folder + + /** + * gather_tags + * This looks for the art in the meta-tags of the file + * itself + */ + public function gather_tags($limit = 5) { + + // We need the filenames + $album = new Album($this->uid); + + // grab the songs and define our results + $songs = $album->get_songs(); + $data = array(); + + // Foreach songs in this album + foreach ($songs as $song_id) { + $song = new Song($song_id); + // If we find a good one, stop looking + $getID3 = new getID3(); + try { $id3 = $getID3->analyze($song->file); } + catch (Exception $error) { + debug_event('getid3', $error->message, 1); + } + + if (isset($id3['asf']['extended_content_description_object']['content_descriptors']['13'])) { + $image = $id3['asf']['extended_content_description_object']['content_descriptors']['13']; + $data[] = array( + 'song' => $song->file, + 'raw' => $image['data'], + 'mime' => $image['mime']); + } + + if (isset($id3['id3v2']['APIC'])) { + // Foreach in case they have more then one + foreach ($id3['id3v2']['APIC'] as $image) { + $data[] = array( + 'song' => $song->file, + 'raw' => $image['data'], + 'mime' => $image['mime']); + } + } + + if ($limit && count($data) >= $limit) { + return array_slice($data, 0, $limit); + } + + } // end foreach + + return $data; + + } // gather_tags + + /** + * gather_google + * Raw google search to retrieve the art, not very reliable + */ + public function gather_google($limit = 5) { + + $images = array(); + $media = new $this->type($this->uid); + $media->format(); + + $search = $media->full_name; + + if ($media->artist_count == '1') + $search = $media->artist_name . ', ' . $search; + + $search = rawurlencode($search); + + $size = '&imgsz=m'; // Medium + //$size = '&imgsz=l'; // Large + + $html = file_get_contents("http://images.google.com/images?source=hp&q=$search&oq=&um=1&ie=UTF-8&sa=N&tab=wi&start=0&tbo=1$size"); + + if(preg_match_all("|\ssrc\=\"(http.+?)\"|", $html, $matches, PREG_PATTERN_ORDER)) + foreach ($matches[1] as $match) { + $extension = "image/jpeg"; + + if (strrpos($extension, '.') !== false) $extension = substr($extension, strrpos($extension, '.') + 1); + + $images[] = array('url' => $match, 'mime' => $extension); + } + + return $images; + + } // gather_google + + /** + * gather_lastfm + * This returns the art from lastfm. It doesn't currently require an + * account but may in the future. + */ + public function gather_lastfm($limit, $options = false) { + + // Create the parser object + $lastfm = new LastFMSearch(); + + switch ($this->type) { + case 'album': + if (is_array($options)) { + $artist = $options['artist']; + $album = $options['album_name']; + } + else { + $media = new Album($this->uid); + $media->format(); + $artist = $media->artist_name; + $album = $media->full_name; + } + break; + } + + if(Config::get('proxy_host') AND Config::get('proxy_port')) { + $proxyhost = Config::get('proxy_host'); + $proxyport = Config::get('proxy_port'); + $proxyuser = Config::get('proxy_user'); + $proxypass = Config::get('proxy_pass'); + debug_event('LastFM', 'proxy set', 5); + $lastfm->setProxy($proxyhost, $proxyport, $proxyuser, $proxypass); + } + + $raw_data = $lastfm->album_search($artist, $album); + + if (!count($raw_data)) { return array(); } + + $coverart = $raw_data['coverart']; + if (!is_array($coverart)) { return array(); } + + ksort($coverart); + foreach ($coverart as $url) { + // We need to check the URL for the /noimage/ stuff + if (strpos($url, '/noimage/') !== false) { + debug_event('LastFM', 'Detected as noimage, skipped ' . $url, 3); + continue; + } + + // HACK: we shouldn't rely on the extension to determine file type + $results = pathinfo($url); + $mime = 'image/' . $results['extension']; + $data[] = array('url' => $url, 'mime' => $mime); + if ($limit && count($data) >= $limit) { + return $data; + } + } // end foreach + + return $data; + + } // gather_lastfm } // Art diff --git a/lib/class/artist.class.php b/lib/class/artist.class.php index d971e33a49..caf243357a 100644 --- a/lib/class/artist.class.php +++ b/lib/class/artist.class.php @@ -1,5 +1,5 @@ catalog_id = $catalog_init; - /* Get the information from the db */ - $info = $this->get_info($id); + $this->catalog_id = $catalog_init; + /* Get the information from the db */ + $info = $this->get_info($id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } // foreach info + foreach ($info as $key=>$value) { + $this->$key = $value; + } // foreach info - return true; + return true; - } //constructor + } //constructor - /** - * construct_from_array - * This is used by the metadata class specifically but fills out a Artist object - * based on a key'd array, it sets $_fake to true - */ - public static function construct_from_array($data) { + /** + * construct_from_array + * This is used by the metadata class specifically but fills out a Artist object + * based on a key'd array, it sets $_fake to true + */ + public static function construct_from_array($data) { - $artist = new Artist(0); - foreach ($data as $key=>$value) { - $artist->$key = $value; - } + $artist = new Artist(0); + foreach ($data as $key=>$value) { + $artist->$key = $value; + } - //Ack that this is not a real object from the DB - $artist->_fake = true; + //Ack that this is not a real object from the DB + $artist->_fake = true; - return $artist; + return $artist; - } // construct_from_array + } // construct_from_array - /** - * gc - * - * This cleans out unused artists - */ - public static function gc() { - Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` WHERE `song`.`id` IS NULL'); - } + /** + * gc + * + * This cleans out unused artists + */ + public static function gc() { + Dba::write('DELETE FROM `artist` USING `artist` LEFT JOIN `song` ON `song`.`artist` = `artist`.`id` WHERE `song`.`id` IS NULL'); + } - /** - * this attempts to build a cache of the data from the passed albums all in one query - */ - public static function build_cache($ids,$extra=false) { - if(!is_array($ids) OR !count($ids)) { return false; } + /** + * this attempts to build a cache of the data from the passed albums all in one query + */ + public static function build_cache($ids,$extra=false) { + if(!is_array($ids) OR !count($ids)) { return false; } - $idlist = '(' . implode(',', $ids) . ')'; + $idlist = '(' . implode(',', $ids) . ')'; - $sql = "SELECT * FROM `artist` WHERE `id` IN $idlist"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `artist` WHERE `id` IN $idlist"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('artist',$row['id'],$row); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('artist',$row['id'],$row); + } - // If we need to also pull the extra information, this is normally only used when we are doing the human display - if ($extra) { - $sql = "SELECT `song`.`artist`, COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist` IN $idlist GROUP BY `song`.`artist`"; - - debug_event("Artist", "build_cache sql: " . $sql, "6"); - $db_results = Dba::read($sql); + // If we need to also pull the extra information, this is normally only used when we are doing the human display + if ($extra) { + $sql = "SELECT `song`.`artist`, COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist` IN $idlist GROUP BY `song`.`artist`"; + + debug_event("Artist", "build_cache sql: " . $sql, "6"); + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('artist_extra',$row['artist'],$row); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('artist_extra',$row['artist'],$row); + } - } // end if extra + } // end if extra - return true; + return true; - } // build_cache + } // build_cache - /** - * get_from_name - * This gets an artist object based on the artist name - */ - public static function get_from_name($name) { + /** + * get_from_name + * This gets an artist object based on the artist name + */ + public static function get_from_name($name) { - $name = Dba::escape($name); - $sql = "SELECT `id` FROM `artist` WHERE `name`='$name'"; - $db_results = Dba::write($sql); + $name = Dba::escape($name); + $sql = "SELECT `id` FROM `artist` WHERE `name`='$name'"; + $db_results = Dba::write($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - $object = new Artist($row['id']); + $object = new Artist($row['id']); - return $object; + return $object; - } // get_from_name + } // get_from_name - /** - * get_albums - * gets the album ids that this artist is a part - * of - */ - public function get_albums($catalog = null) { + /** + * get_albums + * gets the album ids that this artist is a part + * of + */ + public function get_albums($catalog = null) { - if($catalog) { - $catalog_join = "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`"; - $catalog_where = "AND `catalog`.`id` = '$catalog'"; - } + if($catalog) { + $catalog_join = "LEFT JOIN `catalog` ON `catalog`.`id` = `song`.`catalog`"; + $catalog_where = "AND `catalog`.`id` = '$catalog'"; + } - $results = array(); + $results = array(); - $sql = "SELECT `album`.`id` FROM album LEFT JOIN `song` ON `song`.`album`=`album`.`id` $catalog_join " . - "WHERE `song`.`artist`='$this->id' $catalog_where GROUP BY `album`.`id` ORDER BY `album`.`name`,`album`.`disk`,`album`.`year`"; + $sql = "SELECT `album`.`id` FROM album LEFT JOIN `song` ON `song`.`album`=`album`.`id` $catalog_join " . + "WHERE `song`.`artist`='$this->id' $catalog_where GROUP BY `album`.`id` ORDER BY `album`.`name`,`album`.`disk`,`album`.`year`"; - debug_event("Artist", "$sql", "6"); - $db_results = Dba::read($sql); + debug_event("Artist", "$sql", "6"); + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['id']; - } + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['id']; + } - return $results; + return $results; - } // get_albums + } // get_albums - /** - * get_songs - * gets the songs for this artist - */ - public function get_songs() { + /** + * get_songs + * gets the songs for this artist + */ + public function get_songs() { - $sql = "SELECT `song`.`id` FROM `song` WHERE `song`.`artist`='" . Dba::escape($this->id) . "' ORDER BY album, track"; - $db_results = Dba::read($sql); + $sql = "SELECT `song`.`id` FROM `song` WHERE `song`.`artist`='" . Dba::escape($this->id) . "' ORDER BY album, track"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['id']; - } + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['id']; + } - return $results; + return $results; - } // get_songs + } // get_songs - /** - * get_random_songs - * Gets the songs from this artist in a random order - */ - public function get_random_songs() { + /** + * get_random_songs + * Gets the songs from this artist in a random order + */ + public function get_random_songs() { - $results = array(); + $results = array(); - $sql = "SELECT `id` FROM `song` WHERE `artist`='$this->id' ORDER BY RAND()"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `song` WHERE `artist`='$this->id' ORDER BY RAND()"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['id']; - } + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['id']; + } - return $results; + return $results; - } // get_random_songs + } // get_random_songs - /** - * _get_extra info - * This returns the extra information for the artist, this means totals etc - */ - private function _get_extra_info($catalog=FALSE) { + /** + * _get_extra info + * This returns the extra information for the artist, this means totals etc + */ + private function _get_extra_info($catalog=FALSE) { - // Try to find it in the cache and save ourselves the trouble - if (parent::is_cached('artist_extra',$this->id) ) { - $row = parent::get_from_cache('artist_extra',$this->id); - } - else { - $uid = Dba::escape($this->id); - $sql = "SELECT `song`.`artist`,COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist`='$uid' "; - if ($catalog) { - $sql .= "AND (`song`.`catalog` = '$catalog') "; - } + // Try to find it in the cache and save ourselves the trouble + if (parent::is_cached('artist_extra',$this->id) ) { + $row = parent::get_from_cache('artist_extra',$this->id); + } + else { + $uid = Dba::escape($this->id); + $sql = "SELECT `song`.`artist`,COUNT(`song`.`id`) AS `song_count`, COUNT(DISTINCT `song`.`album`) AS `album_count`, SUM(`song`.`time`) AS `time` FROM `song` WHERE `song`.`artist`='$uid' "; + if ($catalog) { + $sql .= "AND (`song`.`catalog` = '$catalog') "; + } - $sql .= "GROUP BY `song`.`artist`"; - - $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); - parent::add_to_cache('artist_extra',$row['artist'],$row); - } + $sql .= "GROUP BY `song`.`artist`"; + + $db_results = Dba::read($sql); + $row = Dba::fetch_assoc($db_results); + parent::add_to_cache('artist_extra',$row['artist'],$row); + } - /* Set Object Vars */ - $this->songs = $row['song_count']; - $this->albums = $row['album_count']; - $this->time = $row['time']; + /* Set Object Vars */ + $this->songs = $row['song_count']; + $this->albums = $row['album_count']; + $this->time = $row['time']; - return $row; + return $row; - } // _get_extra_info + } // _get_extra_info - /** - * format - * this function takes an array of artist - * information and reformats the relevent values - * so they can be displayed in a table for example - * it changes the title into a full link. - */ - public function format() { + /** + * format + * this function takes an array of artist + * information and reformats the relevent values + * so they can be displayed in a table for example + * it changes the title into a full link. + */ + public function format() { - /* Combine prefix and name, trim then add ... if needed */ - $name = UI::truncate(trim($this->prefix . " " . $this->name),Config::get('ellipse_threshold_artist')); - $this->f_name = $name; - $this->f_full_name = trim(trim($this->prefix) . ' ' . trim($this->name)); + /* Combine prefix and name, trim then add ... if needed */ + $name = UI::truncate(trim($this->prefix . " " . $this->name),Config::get('ellipse_threshold_artist')); + $this->f_name = $name; + $this->f_full_name = trim(trim($this->prefix) . ' ' . trim($this->name)); - // If this is a fake object, we're done here - if ($this->_fake) { return true; } + // If this is a fake object, we're done here + if ($this->_fake) { return true; } - if ($this->catalog_id) { - $this->f_name_link = "catalog_id . "&artist=" . $this->id . "\" title=\"" . $this->f_full_name . "\">" . $name . ""; - $this->f_link = Config::get('web_path') . '/artists.php?action=show&catalog=' . $this->catalog_id . '&artist=' . $this->id; - } else { - $this->f_name_link = "id . "\" title=\"" . $this->f_full_name . "\">" . $name . ""; - $this->f_link = Config::get('web_path') . '/artists.php?action=show&artist=' . $this->id; - } - // Get the counts - $extra_info = $this->_get_extra_info($this->catalog_id); - - //Format the new time thingy that we just got - $min = sprintf("%02d",(floor($extra_info['time']/60)%60)); - - $sec = sprintf("%02d",($extra_info['time']%60)); - $hours = floor($extra_info['time']/3600); - - $this->f_time = ltrim($hours . ':' . $min . ':' . $sec,'0:'); - - $this->tags = Tag::get_top_tags('artist',$this->id); - - $this->f_tags = Tag::get_display($this->tags,$this->id,'artist'); - - return true; - - } // format - - /** - * update - * This takes a key'd array of data and updates the current artist - * it will flag songs as neeed - */ - public function update($data) { - - // Save our current ID - $current_id = $this->id; - - $artist_id = Catalog::check_artist($data['name'], $this->mbid); - - // If it's changed we need to update - if ($artist_id != $this->id) { - $songs = $this->get_songs(); - foreach ($songs as $song_id) { - Song::update_artist($artist_id,$song_id); - } - $updated = 1; - $current_id = $artist_id; - self::gc(); - } // end if it changed - - if ($updated) { - foreach ($songs as $song_id) { - Flag::add($song_id,'song','retag','Interface Artist Update'); - Song::update_utime($song_id); - } - Stats::gc(); - Rating::gc(); - } // if updated - - return $current_id; - - } // update + if ($this->catalog_id) { + $this->f_name_link = "catalog_id . "&artist=" . $this->id . "\" title=\"" . $this->f_full_name . "\">" . $name . ""; + $this->f_link = Config::get('web_path') . '/artists.php?action=show&catalog=' . $this->catalog_id . '&artist=' . $this->id; + } else { + $this->f_name_link = "id . "\" title=\"" . $this->f_full_name . "\">" . $name . ""; + $this->f_link = Config::get('web_path') . '/artists.php?action=show&artist=' . $this->id; + } + // Get the counts + $extra_info = $this->_get_extra_info($this->catalog_id); + + //Format the new time thingy that we just got + $min = sprintf("%02d",(floor($extra_info['time']/60)%60)); + + $sec = sprintf("%02d",($extra_info['time']%60)); + $hours = floor($extra_info['time']/3600); + + $this->f_time = ltrim($hours . ':' . $min . ':' . $sec,'0:'); + + $this->tags = Tag::get_top_tags('artist',$this->id); + + $this->f_tags = Tag::get_display($this->tags,$this->id,'artist'); + + return true; + + } // format + + /** + * update + * This takes a key'd array of data and updates the current artist + * it will flag songs as neeed + */ + public function update($data) { + + // Save our current ID + $current_id = $this->id; + + $artist_id = Catalog::check_artist($data['name'], $this->mbid); + + // If it's changed we need to update + if ($artist_id != $this->id) { + $songs = $this->get_songs(); + foreach ($songs as $song_id) { + Song::update_artist($artist_id,$song_id); + } + $updated = 1; + $current_id = $artist_id; + self::gc(); + } // end if it changed + + if ($updated) { + foreach ($songs as $song_id) { + Flag::add($song_id,'song','retag','Interface Artist Update'); + Song::update_utime($song_id); + } + Stats::gc(); + Rating::gc(); + } // if updated + + return $current_id; + + } // update } // end of artist class ?> diff --git a/lib/class/browse.class.php b/lib/class/browse.class.php index ce22728efb..e747430a63 100644 --- a/lib/class/browse.class.php +++ b/lib/class/browse.class.php @@ -1,5 +1,5 @@ set_is_simple($value); - - } // set_simple_browse - - /** - * add_supplemental_object - * Legacy function, need to find a better way to do that - */ - public function add_supplemental_object($class, $uid) { - - $_SESSION['browse']['supplemental'][$this->id][$class] = intval($uid); - - return true; - - } // add_supplemental_object - - /** - * get_supplemental_objects - * This returns an array of 'class','id' for additional objects that - * need to be created before we start this whole browsing thing. - */ - public function get_supplemental_objects() { - - $objects = $_SESSION['browse']['supplemental'][$this->id]; - - if (!is_array($objects)) { $objects = array(); } - - return $objects; - - } // get_supplemental_objects - - /** - * show_objects - * This takes an array of objects - * and requires the correct template based on the - * type that we are currently browsing - */ - public function show_objects($object_ids = null) { - - if ($this->is_simple() || ! is_array($object_ids)) { - $object_ids = $this->get_saved(); - } - else { - $this->save_objects($object_ids); - } - - // Limit is based on the user's preferences if this is not a - // simple browse because we've got too much here - if ((count($object_ids) > $this->get_start()) && - ! $this->is_simple() && - ! $this->is_static_content()) { - $object_ids = array_slice( - $object_ids, - $this->get_start(), - $this->get_offset(), - true - ); - } - - // Load any additional object we need for this - $extra_objects = $this->get_supplemental_objects(); - $browse = $this; - - foreach ($extra_objects as $class_name => $id) { - ${$class_name} = new $class_name($id); - } - - $match = ''; - // Format any matches we have so we can show them to the masses - if ($filter_value = $this->get_filter('alpha_match')) { - $match = ' (' . $filter_value . ')'; - } - elseif ($filter_value = $this->get_filter('starts_with')) { - $match = ' (' . $filter_value . ')'; - } elseif ($filter_value = $this->get_filter('catalog')) { - // Get the catalog title - $catalog = new Catalog($filter_value); - $match = ' (' . $catalog->name . ')'; - } - - $type = $this->get_type(); - - // Set the correct classes based on type - $class = "box browse_" . $type; - - Ajax::start_container('browse_content'); - // Switch on the type of browsing we're doing - switch ($type) { - case 'song': - UI::show_box_top(T_('Songs') . $match, $class); - Song::build_cache($object_ids); - require_once Config::get('prefix') . '/templates/show_songs.inc.php'; - UI::show_box_bottom(); - break; - case 'album': - UI::show_box_top(T_('Albums') . $match, $class); - Album::build_cache($object_ids,'extra'); - require_once Config::get('prefix') . '/templates/show_albums.inc.php'; - UI::show_box_bottom(); - break; - case 'user': - UI::show_box_top(T_('Manage Users') . $match, $class); - require_once Config::get('prefix') . '/templates/show_users.inc.php'; - UI::show_box_bottom(); - break; - case 'artist': - UI::show_box_top(T_('Artists') . $match, $class); - Artist::build_cache($object_ids,'extra'); - require_once Config::get('prefix') . '/templates/show_artists.inc.php'; - UI::show_box_bottom(); - break; - case 'live_stream': - require_once Config::get('prefix') . '/templates/show_live_stream.inc.php'; - UI::show_box_top(T_('Radio Stations') . $match, $class); - require_once Config::get('prefix') . '/templates/show_live_streams.inc.php'; - UI::show_box_bottom(); - break; - case 'playlist': - Playlist::build_cache($object_ids); - UI::show_box_top(T_('Playlists') . $match, $class); - require_once Config::get('prefix') . '/templates/show_playlists.inc.php'; - UI::show_box_bottom(); - break; - case 'playlist_song': - UI::show_box_top(T_('Playlist Songs') . $match,$class); - require_once Config::get('prefix') . '/templates/show_playlist_songs.inc.php'; - UI::show_box_bottom(); - break; - case 'playlist_localplay': - UI::show_box_top(T_('Current Playlist')); - require_once Config::get('prefix') . '/templates/show_localplay_playlist.inc.php'; - UI::show_box_bottom(); - break; - case 'smartplaylist': - UI::show_box_top(T_('Smart Playlists') . $match, $class); - require_once Config::get('prefix') . '/templates/show_smartplaylists.inc.php'; - UI::show_box_bottom(); - break; - case 'catalog': - UI::show_box_top(T_('Catalogs'), $class); - require_once Config::get('prefix') . '/templates/show_catalogs.inc.php'; - UI::show_box_bottom(); - break; - case 'shoutbox': - UI::show_box_top(T_('Shoutbox Records'),$class); - require_once Config::get('prefix') . '/templates/show_manage_shoutbox.inc.php'; - UI::show_box_bottom(); - break; - case 'flagged': - UI::show_box_top(T_('Flagged Records'),$class); - require_once Config::get('prefix') . '/templates/show_flagged.inc.php'; - UI::show_box_bottom(); - break; - case 'tag': - Tag::build_cache($tags); - UI::show_box_top(T_('Tag Cloud'),$class); - require_once Config::get('prefix') . '/templates/show_tagcloud.inc.php'; - UI::show_box_bottom(); - break; - case 'video': - Video::build_cache($object_ids); - UI::show_box_top(T_('Videos'),$class); - require_once Config::get('prefix') . '/templates/show_videos.inc.php'; - UI::show_box_bottom(); - break; - case 'democratic': - UI::show_box_top(T_('Democratic Playlist'),$class); - require_once Config::get('prefix') . '/templates/show_democratic_playlist.inc.php'; - UI::show_box_bottom(); - default: - // Rien a faire - break; - } // end switch on type - echo ''; - - Ajax::end_container(); - - } // show_object - - /** - * set_filter_from_request - * //FIXME - */ - public function set_filter_from_request($request) { - foreach($request as $key => $value) { - //reinterpret v as a list of int - $list = explode(',', $value); - $ok = true; - foreach($list as $item) { - if (!is_numeric($item)) { - $ok = false; - break; - } - } - if ($ok) { - if (sizeof($list) == 1) { - $this->set_filter($key, $list[0]); - } - } - else { - $this->set_filter($key, $list); - } - } - } // set_filter_from_request + /** + * set_simple_browse + * This sets the current browse object to a 'simple' browse method + * which means use the base query provided and expand from there + */ + public function set_simple_browse($value) { + + $this->set_is_simple($value); + + } // set_simple_browse + + /** + * add_supplemental_object + * Legacy function, need to find a better way to do that + */ + public function add_supplemental_object($class, $uid) { + + $_SESSION['browse']['supplemental'][$this->id][$class] = intval($uid); + + return true; + + } // add_supplemental_object + + /** + * get_supplemental_objects + * This returns an array of 'class','id' for additional objects that + * need to be created before we start this whole browsing thing. + */ + public function get_supplemental_objects() { + + $objects = $_SESSION['browse']['supplemental'][$this->id]; + + if (!is_array($objects)) { $objects = array(); } + + return $objects; + + } // get_supplemental_objects + + /** + * show_objects + * This takes an array of objects + * and requires the correct template based on the + * type that we are currently browsing + */ + public function show_objects($object_ids = null) { + + if ($this->is_simple() || ! is_array($object_ids)) { + $object_ids = $this->get_saved(); + } + else { + $this->save_objects($object_ids); + } + + // Limit is based on the user's preferences if this is not a + // simple browse because we've got too much here + if ((count($object_ids) > $this->get_start()) && + ! $this->is_simple() && + ! $this->is_static_content()) { + $object_ids = array_slice( + $object_ids, + $this->get_start(), + $this->get_offset(), + true + ); + } + + // Load any additional object we need for this + $extra_objects = $this->get_supplemental_objects(); + $browse = $this; + + foreach ($extra_objects as $class_name => $id) { + ${$class_name} = new $class_name($id); + } + + $match = ''; + // Format any matches we have so we can show them to the masses + if ($filter_value = $this->get_filter('alpha_match')) { + $match = ' (' . $filter_value . ')'; + } + elseif ($filter_value = $this->get_filter('starts_with')) { + $match = ' (' . $filter_value . ')'; + } elseif ($filter_value = $this->get_filter('catalog')) { + // Get the catalog title + $catalog = new Catalog($filter_value); + $match = ' (' . $catalog->name . ')'; + } + + $type = $this->get_type(); + + // Set the correct classes based on type + $class = "box browse_" . $type; + + Ajax::start_container('browse_content'); + // Switch on the type of browsing we're doing + switch ($type) { + case 'song': + UI::show_box_top(T_('Songs') . $match, $class); + Song::build_cache($object_ids); + require_once Config::get('prefix') . '/templates/show_songs.inc.php'; + UI::show_box_bottom(); + break; + case 'album': + UI::show_box_top(T_('Albums') . $match, $class); + Album::build_cache($object_ids,'extra'); + require_once Config::get('prefix') . '/templates/show_albums.inc.php'; + UI::show_box_bottom(); + break; + case 'user': + UI::show_box_top(T_('Manage Users') . $match, $class); + require_once Config::get('prefix') . '/templates/show_users.inc.php'; + UI::show_box_bottom(); + break; + case 'artist': + UI::show_box_top(T_('Artists') . $match, $class); + Artist::build_cache($object_ids,'extra'); + require_once Config::get('prefix') . '/templates/show_artists.inc.php'; + UI::show_box_bottom(); + break; + case 'live_stream': + require_once Config::get('prefix') . '/templates/show_live_stream.inc.php'; + UI::show_box_top(T_('Radio Stations') . $match, $class); + require_once Config::get('prefix') . '/templates/show_live_streams.inc.php'; + UI::show_box_bottom(); + break; + case 'playlist': + Playlist::build_cache($object_ids); + UI::show_box_top(T_('Playlists') . $match, $class); + require_once Config::get('prefix') . '/templates/show_playlists.inc.php'; + UI::show_box_bottom(); + break; + case 'playlist_song': + UI::show_box_top(T_('Playlist Songs') . $match,$class); + require_once Config::get('prefix') . '/templates/show_playlist_songs.inc.php'; + UI::show_box_bottom(); + break; + case 'playlist_localplay': + UI::show_box_top(T_('Current Playlist')); + require_once Config::get('prefix') . '/templates/show_localplay_playlist.inc.php'; + UI::show_box_bottom(); + break; + case 'smartplaylist': + UI::show_box_top(T_('Smart Playlists') . $match, $class); + require_once Config::get('prefix') . '/templates/show_smartplaylists.inc.php'; + UI::show_box_bottom(); + break; + case 'catalog': + UI::show_box_top(T_('Catalogs'), $class); + require_once Config::get('prefix') . '/templates/show_catalogs.inc.php'; + UI::show_box_bottom(); + break; + case 'shoutbox': + UI::show_box_top(T_('Shoutbox Records'),$class); + require_once Config::get('prefix') . '/templates/show_manage_shoutbox.inc.php'; + UI::show_box_bottom(); + break; + case 'flagged': + UI::show_box_top(T_('Flagged Records'),$class); + require_once Config::get('prefix') . '/templates/show_flagged.inc.php'; + UI::show_box_bottom(); + break; + case 'tag': + Tag::build_cache($tags); + UI::show_box_top(T_('Tag Cloud'),$class); + require_once Config::get('prefix') . '/templates/show_tagcloud.inc.php'; + UI::show_box_bottom(); + break; + case 'video': + Video::build_cache($object_ids); + UI::show_box_top(T_('Videos'),$class); + require_once Config::get('prefix') . '/templates/show_videos.inc.php'; + UI::show_box_bottom(); + break; + case 'democratic': + UI::show_box_top(T_('Democratic Playlist'),$class); + require_once Config::get('prefix') . '/templates/show_democratic_playlist.inc.php'; + UI::show_box_bottom(); + default: + // Rien a faire + break; + } // end switch on type + echo ''; + + Ajax::end_container(); + + } // show_object + + /** + * set_filter_from_request + * //FIXME + */ + public function set_filter_from_request($request) { + foreach($request as $key => $value) { + //reinterpret v as a list of int + $list = explode(',', $value); + $ok = true; + foreach($list as $item) { + if (!is_numeric($item)) { + $ok = false; + break; + } + } + if ($ok) { + if (sizeof($list) == 1) { + $this->set_filter($key, $list[0]); + } + } + else { + $this->set_filter($key, $list); + } + } + } // set_filter_from_request } // browse diff --git a/lib/class/catalog.class.php b/lib/class/catalog.class.php index 3833d32927..df5229a4bd 100644 --- a/lib/class/catalog.class.php +++ b/lib/class/catalog.class.php @@ -1,5 +1,5 @@ id = intval($catalog_id); + /** + * Constructor + * Catalog class constructor, pulls catalog information + * $catalog_id The ID of the catalog you want to build information from + */ + public function __construct($catalog_id = '') { + + if (!$catalog_id) { return false; } + + /* Assign id for use in get_info() */ + $this->id = intval($catalog_id); - /* Get the information from the db */ - $info = $this->get_info($catalog_id); + /* Get the information from the db */ + $info = $this->get_info($catalog_id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } + foreach ($info as $key=>$value) { + $this->$key = $value; + } - } //constructor + } //constructor - /** - * _create_filecache - * This poplates an array (filecache) on this object from the database - * it is used to speed up the add process - */ - private function _create_filecache() { + /** + * _create_filecache + * This poplates an array (filecache) on this object from the database + * it is used to speed up the add process + */ + private function _create_filecache() { - if (count($this->_filecache) == 0) { - $catalog_id = Dba::escape($this->id); - // Get _EVERYTHING_ - $sql = "SELECT `id`,`file` FROM `song` WHERE `catalog`='$catalog_id'"; - $db_results = Dba::read($sql); - - // Populate the filecache - while ($results = Dba::fetch_assoc($db_results)) { - $this->_filecache[strtolower($results['file'])] = $results['id']; - } + if (count($this->_filecache) == 0) { + $catalog_id = Dba::escape($this->id); + // Get _EVERYTHING_ + $sql = "SELECT `id`,`file` FROM `song` WHERE `catalog`='$catalog_id'"; + $db_results = Dba::read($sql); + + // Populate the filecache + while ($results = Dba::fetch_assoc($db_results)) { + $this->_filecache[strtolower($results['file'])] = $results['id']; + } - $sql = "SELECT `id`,`file` FROM `video` WHERE `catalog`='$catalog_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id`,`file` FROM `video` WHERE `catalog`='$catalog_id'"; + $db_results = Dba::read($sql); - while ($results = Dba::fetch_assoc($db_results)) { - $this->_filecache[strtolower($results['file'])] = 'v_' . $results['id']; - } - } // end if empty filecache + while ($results = Dba::fetch_assoc($db_results)) { + $this->_filecache[strtolower($results['file'])] = 'v_' . $results['id']; + } + } // end if empty filecache - return true; + return true; - } // _create_filecache + } // _create_filecache - /** - * get_from_path - * Try to figure out which catalog path most closely resembles this one - * This is useful when creating a new catalog to make sure we're not - * doubling up here. - */ - public static function get_from_path($path) { + /** + * get_from_path + * Try to figure out which catalog path most closely resembles this one + * This is useful when creating a new catalog to make sure we're not + * doubling up here. + */ + public static function get_from_path($path) { - // First pull a list of all of the paths for the different catalogs - $sql = "SELECT `id`,`path` FROM `catalog` WHERE `catalog_type`='local'"; - $db_results = Dba::read($sql); + // First pull a list of all of the paths for the different catalogs + $sql = "SELECT `id`,`path` FROM `catalog` WHERE `catalog_type`='local'"; + $db_results = Dba::read($sql); - $catalog_paths = array(); - $component_path = $path; + $catalog_paths = array(); + $component_path = $path; - while ($row = Dba::fetch_assoc($db_results)) { - $catalog_paths[$row['path']] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $catalog_paths[$row['path']] = $row['id']; + } - // Break it down into its component parts and start looking for a catalog - do { - if ($catalog_paths[$component_path]) { - return $catalog_paths[$component_path]; - } + // Break it down into its component parts and start looking for a catalog + do { + if ($catalog_paths[$component_path]) { + return $catalog_paths[$component_path]; + } - // Keep going until the path stops changing - $old_path = $component_path; - $component_path = realpath($component_path . '/../'); + // Keep going until the path stops changing + $old_path = $component_path; + $component_path = realpath($component_path . '/../'); - } while (strcmp($component_path,$old_path) != 0); + } while (strcmp($component_path,$old_path) != 0); - return false; + return false; - } // get_from_path + } // get_from_path - /** - * format - * This makes the object human readable - */ - public function format() { + /** + * format + * This makes the object human readable + */ + public function format() { - $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title')); - $this->f_name_link = '' . scrub_out($this->f_name) . ''; - $this->f_path = UI::truncate($this->path,Config::get('ellipse_threshold_title')); - $this->f_update = $this->last_update ? date('d/m/Y h:i',$this->last_update) : T_('Never'); - $this->f_add = $this->last_add ? date('d/m/Y h:i',$this->last_add) : T_('Never'); - $this->f_clean = $this->last_clean ? date('d/m/Y h:i',$this->last_clean) : T_('Never'); + $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title')); + $this->f_name_link = '' . scrub_out($this->f_name) . ''; + $this->f_path = UI::truncate($this->path,Config::get('ellipse_threshold_title')); + $this->f_update = $this->last_update ? date('d/m/Y h:i',$this->last_update) : T_('Never'); + $this->f_add = $this->last_add ? date('d/m/Y h:i',$this->last_add) : T_('Never'); + $this->f_clean = $this->last_clean ? date('d/m/Y h:i',$this->last_clean) : T_('Never'); - } // format + } // format - /** - * get_catalogs - * Pull all the current catalogs and return an array of ids - * of what you find - */ - public static function get_catalogs() { + /** + * get_catalogs + * Pull all the current catalogs and return an array of ids + * of what you find + */ + public static function get_catalogs() { - $sql = "SELECT `id` FROM `catalog` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `catalog` ORDER BY `name`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_catalogs - - /** - * get_stats - * This returns an hash with the #'s for the different - * objects that are associated with this catalog. This is used - * to build the stats box, it also calculates time. - */ - public static function get_stats($catalog_id = null) { - - $results = self::count_songs($catalog_id); - $results = array_merge(self::count_users($catalog_id), $results); - $results['tags'] = self::count_tags(); - $results = array_merge(self::count_videos($catalog_id), $results); + } // get_catalogs + + /** + * get_stats + * This returns an hash with the #'s for the different + * objects that are associated with this catalog. This is used + * to build the stats box, it also calculates time. + */ + public static function get_stats($catalog_id = null) { + + $results = self::count_songs($catalog_id); + $results = array_merge(self::count_users($catalog_id), $results); + $results['tags'] = self::count_tags(); + $results = array_merge(self::count_videos($catalog_id), $results); - $hours = floor($results['time'] / 3600); + $hours = floor($results['time'] / 3600); - $results['formatted_size'] = UI::format_bytes($results['size']); + $results['formatted_size'] = UI::format_bytes($results['size']); - $days = floor($hours / 24); - $hours = $hours % 24; + $days = floor($hours / 24); + $hours = $hours % 24; - $time_text = "$days "; - $time_text .= T_ngettext('day','days',$days); - $time_text .= ", $hours "; - $time_text .= T_ngettext('hour','hours',$hours); + $time_text = "$days "; + $time_text .= T_ngettext('day','days',$days); + $time_text .= ", $hours "; + $time_text .= T_ngettext('hour','hours',$hours); - $results['time_text'] = $time_text; + $results['time_text'] = $time_text; - return $results; + return $results; - } // get_stats - - /** - * create - * This creates a new catalog entry and then returns the insert id - * it checks to make sure this path is not already used before creating - * the catalog - */ - public static function create($data) { + } // get_stats + + /** + * create + * This creates a new catalog entry and then returns the insert id + * it checks to make sure this path is not already used before creating + * the catalog + */ + public static function create($data) { - // Clean up the path just in case - $data['path'] = rtrim(rtrim(trim($data['path']),'/'),'\\'); + // Clean up the path just in case + $data['path'] = rtrim(rtrim(trim($data['path']),'/'),'\\'); - $path = Dba::escape($data['path']); + $path = Dba::escape($data['path']); - // Make sure the path is readable/exists - if ($data['type'] == 'local') { - $handle = opendir($path); - if ($handle === false) { - Error::add('general', sprintf(T_('Error: %s is not readable or does not exist'), scrub_out($data['path']))); - return false; - } - closedir($handle); - } + // Make sure the path is readable/exists + if ($data['type'] == 'local') { + $handle = opendir($path); + if ($handle === false) { + Error::add('general', sprintf(T_('Error: %s is not readable or does not exist'), scrub_out($data['path']))); + return false; + } + closedir($handle); + } - // Make sure this path isn't already in use by an existing catalog - $sql = "SELECT `id` FROM `catalog` WHERE `path`='$path'"; - $db_results = Dba::read($sql); + // Make sure this path isn't already in use by an existing catalog + $sql = "SELECT `id` FROM `catalog` WHERE `path`='$path'"; + $db_results = Dba::read($sql); - if (Dba::num_rows($db_results)) { - Error::add('general', sprintf(T_('Error: Catalog with %s already exists'), $path)); - return false; - } + if (Dba::num_rows($db_results)) { + Error::add('general', sprintf(T_('Error: Catalog with %s already exists'), $path)); + return false; + } - $name = Dba::escape($data['name']); - $catalog_type = Dba::escape($data['type']); - $rename_pattern = Dba::escape($data['rename_pattern']); - $sort_pattern = Dba::escape($data['sort_pattern']); - $gather_types = 'NULL'; - $remote_username = 'NULL'; - $remote_password = 'NULL'; + $name = Dba::escape($data['name']); + $catalog_type = Dba::escape($data['type']); + $rename_pattern = Dba::escape($data['rename_pattern']); + $sort_pattern = Dba::escape($data['sort_pattern']); + $gather_types = 'NULL'; + $remote_username = 'NULL'; + $remote_password = 'NULL'; - // Don't save these if it isn't a remote catalog - if ($catalog_type == 'remote') { - $remote_username = "'" . Dba::escape($data['remote_username']) . "'"; - $remote_password = "'" . Dba::escape($data['remote_password']) . "'"; - } + // Don't save these if it isn't a remote catalog + if ($catalog_type == 'remote') { + $remote_username = "'" . Dba::escape($data['remote_username']) . "'"; + $remote_password = "'" . Dba::escape($data['remote_password']) . "'"; + } - // Ok we're good to go ahead and insert this record - $sql = "INSERT INTO `catalog` (`name`,`path`,`catalog_type`,`remote_username`,`remote_password`,`rename_pattern`,`sort_pattern`,`gather_types`) " . - "VALUES ('$name','$path','$catalog_type',$remote_username,$remote_password,'$rename_pattern','$sort_pattern',$gather_types)"; - $db_results = Dba::write($sql); + // Ok we're good to go ahead and insert this record + $sql = "INSERT INTO `catalog` (`name`,`path`,`catalog_type`,`remote_username`,`remote_password`,`rename_pattern`,`sort_pattern`,`gather_types`) " . + "VALUES ('$name','$path','$catalog_type',$remote_username,$remote_password,'$rename_pattern','$sort_pattern',$gather_types)"; + $db_results = Dba::write($sql); - $insert_id = Dba::insert_id(); + $insert_id = Dba::insert_id(); - if (!$insert_id) { - Error::add('general', T_('Catalog Insert Failed check debug logs')); - debug_event('catalog','SQL Failed:' . $sql,'3'); - return false; - } + if (!$insert_id) { + Error::add('general', T_('Catalog Insert Failed check debug logs')); + debug_event('catalog','SQL Failed:' . $sql,'3'); + return false; + } - return $insert_id; + return $insert_id; - } // create + } // create - /** - * run_add - * This runs the add to catalog function - * it includes the javascript refresh stuff and then starts rolling - * throught the path for this catalog - */ - public function run_add($options) { - - if ($this->catalog_type == 'remote') { - UI::show_box_top(T_('Running Remote Sync') . '. . .'); - $this->get_remote_catalog($type=0); - UI::show_box_bottom(); - return true; - } + /** + * run_add + * This runs the add to catalog function + * it includes the javascript refresh stuff and then starts rolling + * throught the path for this catalog + */ + public function run_add($options) { + + if ($this->catalog_type == 'remote') { + UI::show_box_top(T_('Running Remote Sync') . '. . .'); + $this->get_remote_catalog($type=0); + UI::show_box_bottom(); + return true; + } - // Catalog Add start - $start_time = time(); + // Catalog Add start + $start_time = time(); - require Config::get('prefix') . '/templates/show_adds_catalog.inc.php'; - flush(); - - // Prevent the script from timing out and flush what we've got - set_time_limit(0); - - $this->add_files($this->path,$options); - - // If they have checked the box then go ahead and gather the art - if ($options['gather_art']) { - $catalog_id = $this->id; - require Config::get('prefix') . '/templates/show_gather_art.inc.php'; - flush(); - $this->get_art('',1); - } - - if ($options['parse_m3u'] AND count($this->_playlists)) { - foreach ($this->_playlists as $playlist_file) { - $result = $this->import_m3u($playlist_file); - } - } // if we need to do some m3u-age - - return true; - - } // run_add - - /** - * count_videos - * This returns the current # of video files we've got in the db - */ - public static function count_videos($catalog_id = null) { - - $catalog_search = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : ''; - - $sql = 'SELECT COUNT(`id`) AS `videos` FROM `video` '; - if ($catalog_id) { - $sql .= "WHERE `catalog`='" . Dba::escape($catalog_id) . "'"; - } - $db_results = Dba::read($sql); - - $row = Dba::fetch_assoc($db_results); - - return $row; - - } // count_videos - - /** - * count_tags - * This returns the current # of unique tags that exist in the database - */ - public static function count_tags($catalog_id = null) { - - // FIXME: Ignores catalog_id - $sql = "SELECT COUNT(`id`) FROM `tag`"; - $db_results = Dba::read($sql); - - $info = Dba::fetch_row($db_results); - - return $info['0']; - - } // count_tags - - /** - * count_songs - * This returns the current # of songs, albums, artists - * in this catalog - */ - public static function count_songs($catalog_id = null) { - - $where_sql = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : ''; - - $sql = "SELECT COUNT(`id`),SUM(`time`),SUM(`size`) FROM `song` $where_sql"; - $db_results = Dba::read($sql); - $data = Dba::fetch_row($db_results); - $songs = $data['0']; - $time = $data['1']; - $size = $data['2']; - - $sql = "SELECT COUNT(DISTINCT(`album`)) FROM `song` $where_sql"; - $db_results = Dba::read($sql); - $data = Dba::fetch_row($db_results); - $albums = $data['0']; - - $sql = "SELECT COUNT(DISTINCT(`artist`)) FROM `song` $where_sql"; - $db_results = Dba::read($sql); - $data = Dba::fetch_row($db_results); - $artists = $data['0']; - - $results['songs'] = $songs; - $results['albums'] = $albums; - $results['artists'] = $artists; - $results['size'] = $size; - $results['time'] = $time; - - return $results; - - } // count_songs - - /** - * count_users - * This returns the total number of users in the ampache instance - */ - public static function count_users($catalog_id = null) { - - // Count total users - $sql = "SELECT COUNT(`id`) FROM `user`"; - $db_results = Dba::read($sql); - $data = Dba::fetch_row($db_results); - $results['users'] = $data['0']; - - // Get the connected users - $time = time(); - $last_seen_time = $time - 1200; - $sql = 'SELECT COUNT(DISTINCT `session`.`username`) ' . - 'FROM `session` INNER JOIN `user` ' . - 'ON `session`.`username` = `user`.`username` ' . - "WHERE `session`.`expire` > '$time' " . - "AND `user`.`last_seen` > '$last_seen_time'"; - $db_results = Dba::read($sql); - $data = Dba::fetch_row($db_results); - - $results['connected'] = $data['0']; - - return $results; - - } // count_users - - /** - * add_files - * Recurses through $this->path and pulls out all mp3s and returns the - * full path in an array. Passes gather_type to determine if we need to - * check id3 information against the db. - */ - public function add_files($path, $options) { - - // Profile the memory a bit - debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5); - - // See if we want a non-root path for the add - if (isset($options['subdirectory'])) { - $path = $options['subdirectory']; - unset($options['subdirectory']); - } - - // Correctly detect the slash we need to use here - if (strpos($path, '/') !== false) { - $slash_type = '/'; - } - else { - $slash_type = '\\'; - } - - /* Open up the directory */ - $handle = opendir($path); - - if (!is_resource($handle)) { - debug_event('read', "Unable to open $path", 5,'ampache-catalog'); - Error::add('catalog_add', sprintf(T_('Error: Unable to open %s'), $path)); - return false; - } - - /* Change the dir so is_dir works correctly */ - if (!chdir($path)) { - debug_event('read', "Unable to chdir $path", 2,'ampache-catalog'); - Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path)); - return false; - } - - // Ensure that we've got our cache - $this->_create_filecache(); - - debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5); - - /* Recurse through this dir and create the files array */ - while ( false !== ( $file = readdir($handle) ) ) { - - /* Skip to next if we've got . or .. */ - if (substr($file,0,1) == '.') { continue; } - - debug_event('read',"Starting work on $file inside $path",'5','ampache-catalog'); - debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5); - - /* Create the new path */ - $full_file = $path.$slash_type.$file; - - /* First thing first, check if file is already in catalog. - * This check is very quick, so it should be performed before any other checks to save time - */ - if (isset($this->_filecache[strtolower($full_file)])) { - continue; - } - - // Incase this is the second time through clear this variable - // if it was set the day before - unset($failed_check); - - if (Config::get('no_symlinks')) { - if (is_link($full_file)) { - debug_event('read',"Skipping Symbolic Link $path",'5','ampache-catalog'); - continue; - } - } - - /* If it's a dir run this function again! */ - if (is_dir($full_file)) { - $this->add_files($full_file,$options); - - /* Change the dir so is_dir works correctly */ - if (!chdir($path)) { - debug_event('read',"Unable to chdir $path",'2','ampache-catalog'); - Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path)); - } - - /* Skip to the next file */ - continue; - } //it's a directory - - /* If it's not a dir let's roll with it - * next we need to build the pattern that we will use - * to detect if it's an audio file - */ - $pattern = "/\.(" . Config::get('catalog_file_pattern'); - if ($options['parse_m3u']) { - $pattern .= "|m3u)$/i"; - } - else { - $pattern .= ")$/i"; - } - - $is_audio_file = preg_match($pattern,$file); - - // Define the Video file pattern - if (!$is_audio_file AND Config::get('catalog_video_pattern')) { - $video_pattern = "/\.(" . Config::get('catalog_video_pattern') . ")$/i"; - $is_video_file = preg_match($video_pattern,$file); - } - - /* see if this is a valid audio file or playlist file */ - if ($is_audio_file OR $is_video_file) { - - /* Now that we're sure its a file get filesize */ - $file_size = filesize($full_file); - - if (!$file_size) { - debug_event('read',"Unable to get filesize for $full_file",'2','ampache-catalog'); - /* HINT: FullFile */ - Error::add('catalog_add', sprintf(T_('Error: Unable to get filesize for %s'), $full_file)); - } // file_size check - - if (!is_readable($full_file)) { - // not readable, warn user - debug_event('read',"$full_file is not readable by ampache",'2','ampache-catalog'); - /* HINT: FullFile */ - Error::add('catalog_add', sprintf(T_('%s is not readable by ampache'), $full_file)); - continue; - } - - // Check to make sure the filename is of the expected charset - if (function_exists('iconv')) { - if (strcmp($full_file,iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file)) != '0') { - debug_event('read',$full_file . ' has non-' . Config::get('site_charset') . ' characters and can not be indexed, converted filename:' . iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file),'1'); - /* HINT: FullFile */ - Error::add('catalog_add', sprintf(T_('%s does not match site charset'), $full_file)); - continue; - } - } // end if iconv - - if ($options['parse_m3u'] AND substr($file,-3,3) == 'm3u') { - $this->_playlists[] = $full_file; - } // if it's an m3u - - else { - if ($is_audio_file) { $this->insert_local_song($full_file,$file_size); } - else { $this->insert_local_video($full_file,$file_size); } - - $this->count++; - $file = str_replace(array('(',')','\''),'',$full_file); - if(UI::check_ticker()) { - UI::update_text('add_count_' . $this->id, $this->count); - UI::update_text('add_dir_' . $this->id, scrub_out($file)); - } // update our current state - - } // if it's not an m3u - - } //if it matches the pattern - else { - debug_event('read',"$full_file ignored, non audio file or 0 bytes",'5','ampache-catalog'); - } // else not an audio file - - } // end while reading directory - - debug_event('closedir',"Finished reading $path closing handle",'5','ampache-catalog'); - - // This should only happen on the last run - if ($path == $this->path) { - UI::update_text('add_count_' . $this->id, $this->count); - UI::update_text('add_dir_' . $this->id, scrub_out($file)); - } - - - /* Close the dir handle */ - @closedir($handle); - - } // add_files - - /** - * get_album_ids - * This returns an array of ids of albums that have songs in this - * catalog - */ - public function get_album_ids() { - - $id = Dba::escape($this->id); - $results = array(); - - $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$id'"; - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['album']; - } - - return $results; - - } // get_album_ids - - /** - * get_art - * This runs through all of the needs art albums and trys - * to find the art for them from the mp3s - */ - public function get_art($catalog_id = null, $all = false) { - - // Make sure they've actually got methods - $art_order = Config::get('art_order'); - if (!count($art_order)) { - debug_event('gather_art', 'art_order not set, Catalog::get_art aborting', 3); - return true; - } - - // Prevent the script from timing out - set_time_limit(0); - - // If not passed use $this - $catalog_id = $catalog_id ? $catalog_id : $this->id; - - if ($all) { - $albums = $this->get_album_ids(); - } - else { - $albums = array_keys(self::$_art_albums); - } - - // Run through them an get the art! - foreach ($albums as $album_id) { - - // Create the object - $art = new Art($album_id, 'album'); - $album = new Album($album_id); - // We're going to need the name here - $album->format(); - - debug_event('gather_art', 'Gathering art for ' . $album->name, 5); - - // Define the options we want to use for the find art function - $options = array( - 'album_name' => $album->full_name, - 'artist' => $album->artist_name, - 'keyword' => $album->artist_name . ' ' . $album->full_name - ); + require Config::get('prefix') . '/templates/show_adds_catalog.inc.php'; + flush(); + + // Prevent the script from timing out and flush what we've got + set_time_limit(0); + + $this->add_files($this->path,$options); + + // If they have checked the box then go ahead and gather the art + if ($options['gather_art']) { + $catalog_id = $this->id; + require Config::get('prefix') . '/templates/show_gather_art.inc.php'; + flush(); + $this->get_art('',1); + } + + if ($options['parse_m3u'] AND count($this->_playlists)) { + foreach ($this->_playlists as $playlist_file) { + $result = $this->import_m3u($playlist_file); + } + } // if we need to do some m3u-age + + return true; + + } // run_add + + /** + * count_videos + * This returns the current # of video files we've got in the db + */ + public static function count_videos($catalog_id = null) { + + $catalog_search = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : ''; + + $sql = 'SELECT COUNT(`id`) AS `videos` FROM `video` '; + if ($catalog_id) { + $sql .= "WHERE `catalog`='" . Dba::escape($catalog_id) . "'"; + } + $db_results = Dba::read($sql); + + $row = Dba::fetch_assoc($db_results); + + return $row; + + } // count_videos + + /** + * count_tags + * This returns the current # of unique tags that exist in the database + */ + public static function count_tags($catalog_id = null) { + + // FIXME: Ignores catalog_id + $sql = "SELECT COUNT(`id`) FROM `tag`"; + $db_results = Dba::read($sql); + + $info = Dba::fetch_row($db_results); + + return $info['0']; + + } // count_tags + + /** + * count_songs + * This returns the current # of songs, albums, artists + * in this catalog + */ + public static function count_songs($catalog_id = null) { + + $where_sql = $catalog_id ? "WHERE `catalog`='" . Dba::escape($catalog_id) . "'" : ''; + + $sql = "SELECT COUNT(`id`),SUM(`time`),SUM(`size`) FROM `song` $where_sql"; + $db_results = Dba::read($sql); + $data = Dba::fetch_row($db_results); + $songs = $data['0']; + $time = $data['1']; + $size = $data['2']; + + $sql = "SELECT COUNT(DISTINCT(`album`)) FROM `song` $where_sql"; + $db_results = Dba::read($sql); + $data = Dba::fetch_row($db_results); + $albums = $data['0']; + + $sql = "SELECT COUNT(DISTINCT(`artist`)) FROM `song` $where_sql"; + $db_results = Dba::read($sql); + $data = Dba::fetch_row($db_results); + $artists = $data['0']; + + $results['songs'] = $songs; + $results['albums'] = $albums; + $results['artists'] = $artists; + $results['size'] = $size; + $results['time'] = $time; + + return $results; + + } // count_songs + + /** + * count_users + * This returns the total number of users in the ampache instance + */ + public static function count_users($catalog_id = null) { + + // Count total users + $sql = "SELECT COUNT(`id`) FROM `user`"; + $db_results = Dba::read($sql); + $data = Dba::fetch_row($db_results); + $results['users'] = $data['0']; + + // Get the connected users + $time = time(); + $last_seen_time = $time - 1200; + $sql = 'SELECT COUNT(DISTINCT `session`.`username`) ' . + 'FROM `session` INNER JOIN `user` ' . + 'ON `session`.`username` = `user`.`username` ' . + "WHERE `session`.`expire` > '$time' " . + "AND `user`.`last_seen` > '$last_seen_time'"; + $db_results = Dba::read($sql); + $data = Dba::fetch_row($db_results); + + $results['connected'] = $data['0']; + + return $results; + + } // count_users + + /** + * add_files + * Recurses through $this->path and pulls out all mp3s and returns the + * full path in an array. Passes gather_type to determine if we need to + * check id3 information against the db. + */ + public function add_files($path, $options) { + + // Profile the memory a bit + debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5); + + // See if we want a non-root path for the add + if (isset($options['subdirectory'])) { + $path = $options['subdirectory']; + unset($options['subdirectory']); + } + + // Correctly detect the slash we need to use here + if (strpos($path, '/') !== false) { + $slash_type = '/'; + } + else { + $slash_type = '\\'; + } + + /* Open up the directory */ + $handle = opendir($path); + + if (!is_resource($handle)) { + debug_event('read', "Unable to open $path", 5,'ampache-catalog'); + Error::add('catalog_add', sprintf(T_('Error: Unable to open %s'), $path)); + return false; + } + + /* Change the dir so is_dir works correctly */ + if (!chdir($path)) { + debug_event('read', "Unable to chdir $path", 2,'ampache-catalog'); + Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path)); + return false; + } + + // Ensure that we've got our cache + $this->_create_filecache(); + + debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5); + + /* Recurse through this dir and create the files array */ + while ( false !== ( $file = readdir($handle) ) ) { + + /* Skip to next if we've got . or .. */ + if (substr($file,0,1) == '.') { continue; } + + debug_event('read',"Starting work on $file inside $path",'5','ampache-catalog'); + debug_event('Memory', UI::format_bytes(memory_get_usage(true)), 5); + + /* Create the new path */ + $full_file = $path.$slash_type.$file; + + /* First thing first, check if file is already in catalog. + * This check is very quick, so it should be performed before any other checks to save time + */ + if (isset($this->_filecache[strtolower($full_file)])) { + continue; + } + + // Incase this is the second time through clear this variable + // if it was set the day before + unset($failed_check); + + if (Config::get('no_symlinks')) { + if (is_link($full_file)) { + debug_event('read',"Skipping Symbolic Link $path",'5','ampache-catalog'); + continue; + } + } + + /* If it's a dir run this function again! */ + if (is_dir($full_file)) { + $this->add_files($full_file,$options); + + /* Change the dir so is_dir works correctly */ + if (!chdir($path)) { + debug_event('read',"Unable to chdir $path",'2','ampache-catalog'); + Error::add('catalog_add', sprintf(T_('Error: Unable to change to directory %s'), $path)); + } + + /* Skip to the next file */ + continue; + } //it's a directory + + /* If it's not a dir let's roll with it + * next we need to build the pattern that we will use + * to detect if it's an audio file + */ + $pattern = "/\.(" . Config::get('catalog_file_pattern'); + if ($options['parse_m3u']) { + $pattern .= "|m3u)$/i"; + } + else { + $pattern .= ")$/i"; + } + + $is_audio_file = preg_match($pattern,$file); + + // Define the Video file pattern + if (!$is_audio_file AND Config::get('catalog_video_pattern')) { + $video_pattern = "/\.(" . Config::get('catalog_video_pattern') . ")$/i"; + $is_video_file = preg_match($video_pattern,$file); + } + + /* see if this is a valid audio file or playlist file */ + if ($is_audio_file OR $is_video_file) { + + /* Now that we're sure its a file get filesize */ + $file_size = filesize($full_file); + + if (!$file_size) { + debug_event('read',"Unable to get filesize for $full_file",'2','ampache-catalog'); + /* HINT: FullFile */ + Error::add('catalog_add', sprintf(T_('Error: Unable to get filesize for %s'), $full_file)); + } // file_size check + + if (!is_readable($full_file)) { + // not readable, warn user + debug_event('read',"$full_file is not readable by ampache",'2','ampache-catalog'); + /* HINT: FullFile */ + Error::add('catalog_add', sprintf(T_('%s is not readable by ampache'), $full_file)); + continue; + } + + // Check to make sure the filename is of the expected charset + if (function_exists('iconv')) { + if (strcmp($full_file,iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file)) != '0') { + debug_event('read',$full_file . ' has non-' . Config::get('site_charset') . ' characters and can not be indexed, converted filename:' . iconv(Config::get('site_charset'),Config::get('site_charset'),$full_file),'1'); + /* HINT: FullFile */ + Error::add('catalog_add', sprintf(T_('%s does not match site charset'), $full_file)); + continue; + } + } // end if iconv + + if ($options['parse_m3u'] AND substr($file,-3,3) == 'm3u') { + $this->_playlists[] = $full_file; + } // if it's an m3u + + else { + if ($is_audio_file) { $this->insert_local_song($full_file,$file_size); } + else { $this->insert_local_video($full_file,$file_size); } + + $this->count++; + $file = str_replace(array('(',')','\''),'',$full_file); + if(UI::check_ticker()) { + UI::update_text('add_count_' . $this->id, $this->count); + UI::update_text('add_dir_' . $this->id, scrub_out($file)); + } // update our current state + + } // if it's not an m3u + + } //if it matches the pattern + else { + debug_event('read',"$full_file ignored, non audio file or 0 bytes",'5','ampache-catalog'); + } // else not an audio file + + } // end while reading directory + + debug_event('closedir',"Finished reading $path closing handle",'5','ampache-catalog'); + + // This should only happen on the last run + if ($path == $this->path) { + UI::update_text('add_count_' . $this->id, $this->count); + UI::update_text('add_dir_' . $this->id, scrub_out($file)); + } + + + /* Close the dir handle */ + @closedir($handle); + + } // add_files + + /** + * get_album_ids + * This returns an array of ids of albums that have songs in this + * catalog + */ + public function get_album_ids() { + + $id = Dba::escape($this->id); + $results = array(); + + $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$id'"; + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['album']; + } + + return $results; + + } // get_album_ids + + /** + * get_art + * This runs through all of the needs art albums and trys + * to find the art for them from the mp3s + */ + public function get_art($catalog_id = null, $all = false) { + + // Make sure they've actually got methods + $art_order = Config::get('art_order'); + if (!count($art_order)) { + debug_event('gather_art', 'art_order not set, Catalog::get_art aborting', 3); + return true; + } + + // Prevent the script from timing out + set_time_limit(0); + + // If not passed use $this + $catalog_id = $catalog_id ? $catalog_id : $this->id; + + if ($all) { + $albums = $this->get_album_ids(); + } + else { + $albums = array_keys(self::$_art_albums); + } + + // Run through them an get the art! + foreach ($albums as $album_id) { + + // Create the object + $art = new Art($album_id, 'album'); + $album = new Album($album_id); + // We're going to need the name here + $album->format(); + + debug_event('gather_art', 'Gathering art for ' . $album->name, 5); + + // Define the options we want to use for the find art function + $options = array( + 'album_name' => $album->full_name, + 'artist' => $album->artist_name, + 'keyword' => $album->artist_name . ' ' . $album->full_name + ); - // Return results - $results = $art->gather($options, 1); + // Return results + $results = $art->gather($options, 1); - if (count($results)) { - // Pull the string representation from the source - $image = Art::get_from_source($results['0'], 'album'); - if (strlen($image) > '5') { - $art->insert($image, $results['0']['mime']); - // If they've enabled resizing of images generate the thumbnail now - if (Config::get('resize_images')) { - $thumb = $art->generate_thumb($image,array('width'=>275,'height'=>275),$results['0']['mime']); - if (is_array($thumb)) { $art->save_thumb($thumb['thumb'], $thumb['thumb_mime'], '275x275'); } - } - - } - else { - debug_event('gather_art', 'Image less than 5 chars, not inserting', 3); - } - $art_found++; - } + if (count($results)) { + // Pull the string representation from the source + $image = Art::get_from_source($results['0'], 'album'); + if (strlen($image) > '5') { + $art->insert($image, $results['0']['mime']); + // If they've enabled resizing of images generate the thumbnail now + if (Config::get('resize_images')) { + $thumb = $art->generate_thumb($image,array('width'=>275,'height'=>275),$results['0']['mime']); + if (is_array($thumb)) { $art->save_thumb($thumb['thumb'], $thumb['thumb_mime'], '275x275'); } + } + + } + else { + debug_event('gather_art', 'Image less than 5 chars, not inserting', 3); + } + $art_found++; + } - /* Stupid little cutesie thing */ - $search_count++; - if (UI::check_ticker()) { - UI::update_text('count_art_' . $this->id, $search_count); - UI::update_text('read_art_' . $this->id, scrub_out($album->name)); - } //echos song count + /* Stupid little cutesie thing */ + $search_count++; + if (UI::check_ticker()) { + UI::update_text('count_art_' . $this->id, $search_count); + UI::update_text('read_art_' . $this->id, scrub_out($album->name)); + } //echos song count - unset($found); - } // foreach albums + unset($found); + } // foreach albums - // One last time for good measure - UI::update_text('count_art_' . $this->id, $search_count); - UI::update_text('read_art_' . $this->id, scrub_out($album->name)); - - self::$_art_albums = array(); - - } // get_art + // One last time for good measure + UI::update_text('count_art_' . $this->id, $search_count); + UI::update_text('read_art_' . $this->id, scrub_out($album->name)); + + self::$_art_albums = array(); + + } // get_art - /** - * generate_thumbnails - * This generates the thumbnails from the images for object - * of this catalog - */ - public function generate_thumbnails() { - - // Albums first - $albums = $this->get_album_ids(); - - $thumb_count = 0; - - foreach ($albums as $album) { - $art = new Art($album, 'album'); - $image = $art->get(); - - /* Stupid little cutesie thing */ - $thumb_count++; - if (UI::check_ticker()) { - UI::update_text('count_thumb_' . $this->id, $search_count); - } //echos thumb count - - } // end foreach albums - - UI::update_text('count_thumb_' . $this->id, $search_count); - - } // generate_thumbnails - - /** - * get_catalog_albums() - * Returns an array of the albums from a catalog - */ - public static function get_catalog_albums($catalog_id) { - - $results = array(); - - $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$catalog_id'"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['album']; - } - - return $results; - - } // get_catalog_albums - - - /** - * get_catalog_files - * Returns an array of song objects from a catalog, used by sort_files script - */ - public function get_catalog_files($catalog_id=0) { - - $results = array(); - - /* Use $this->id if nothing passed */ - $catalog_id = $catalog_id ? Dba::escape($catalog_id) : Dba::escape($this->id); - - $sql = "SELECT `id` FROM `song` WHERE `catalog`='$catalog_id' AND `enabled`='1'"; - $db_results = Dba::read($sql); - - $results = array(); // return an emty array instead of nothing if no objects - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = new Song($r['id']); - } //end while - - return $results; - - } //get_catalog_files - - /** - * dump_album_art - * This runs through all of the albums and tries to dump the - * art for them into the 'folder.jpg' file in the appropriate dir - */ - public static function dump_album_art($catalog_id, $methods=array()) { + /** + * generate_thumbnails + * This generates the thumbnails from the images for object + * of this catalog + */ + public function generate_thumbnails() { + + // Albums first + $albums = $this->get_album_ids(); + + $thumb_count = 0; + + foreach ($albums as $album) { + $art = new Art($album, 'album'); + $image = $art->get(); + + /* Stupid little cutesie thing */ + $thumb_count++; + if (UI::check_ticker()) { + UI::update_text('count_thumb_' . $this->id, $search_count); + } //echos thumb count + + } // end foreach albums + + UI::update_text('count_thumb_' . $this->id, $search_count); + + } // generate_thumbnails + + /** + * get_catalog_albums() + * Returns an array of the albums from a catalog + */ + public static function get_catalog_albums($catalog_id) { + + $results = array(); + + $sql = "SELECT DISTINCT(`song`.`album`) FROM `song` WHERE `song`.`catalog`='$catalog_id'"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['album']; + } + + return $results; + + } // get_catalog_albums + + + /** + * get_catalog_files + * Returns an array of song objects from a catalog, used by sort_files script + */ + public function get_catalog_files($catalog_id=0) { + + $results = array(); + + /* Use $this->id if nothing passed */ + $catalog_id = $catalog_id ? Dba::escape($catalog_id) : Dba::escape($this->id); + + $sql = "SELECT `id` FROM `song` WHERE `catalog`='$catalog_id' AND `enabled`='1'"; + $db_results = Dba::read($sql); + + $results = array(); // return an emty array instead of nothing if no objects + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = new Song($r['id']); + } //end while + + return $results; + + } //get_catalog_files + + /** + * dump_album_art + * This runs through all of the albums and tries to dump the + * art for them into the 'folder.jpg' file in the appropriate dir + */ + public static function dump_album_art($catalog_id, $methods=array()) { - // Get all of the albums in this catalog - $albums = self::get_catalog_albums($catalog_id); + // Get all of the albums in this catalog + $albums = self::get_catalog_albums($catalog_id); - echo "Starting Dump Album Art...\n"; + echo "Starting Dump Album Art...\n"; - // Run through them and get the art! - foreach ($albums as $album_id) { + // Run through them and get the art! + foreach ($albums as $album_id) { - $album = new Album($album_id); - $art = new Art($album_id, 'album'); - - // If no art, skip - if ( ! $art->get_db() ) { continue; } + $album = new Album($album_id); + $art = new Art($album_id, 'album'); + + // If no art, skip + if ( ! $art->get_db() ) { continue; } - // Get the first song in the album - $songs = $album->get_songs(1); - $song = new Song($songs[0]); - $dir = dirname($song->file); + // Get the first song in the album + $songs = $album->get_songs(1); + $song = new Song($songs[0]); + $dir = dirname($song->file); - $extension = Art::extension($art->raw_mime); - - // Try the preferred filename, if that fails use folder.??? - $preferred_filename = Config::get('album_art_preferred_filename'); - if (!$preferred_filename || - strpos($preferred_filename, '%') !== false) { - $preferred_filename = "folder.$extension"; - } + $extension = Art::extension($art->raw_mime); + + // Try the preferred filename, if that fails use folder.??? + $preferred_filename = Config::get('album_art_preferred_filename'); + if (!$preferred_filename || + strpos($preferred_filename, '%') !== false) { + $preferred_filename = "folder.$extension"; + } - $file = "$dir/$preferred_filename"; - if ($file_handle = fopen($file,"w")) { - if (fwrite($file_handle, $art->raw)) { + $file = "$dir/$preferred_filename"; + if ($file_handle = fopen($file,"w")) { + if (fwrite($file_handle, $art->raw)) { - // Also check and see if we should write - // out some metadata - if ($methods['metadata']) { - switch ($methods['metadata']) { - case 'windows': - $meta_file = $dir . '/desktop.ini'; - $string = "[.ShellClassInfo]\nIconFile=$file\nIconIndex=0\nInfoTip=$album->full_name"; - break; - default: - case 'linux': - $meta_file = $dir . '/.directory'; - $string = "Name=$album->full_name\nIcon=$file"; - break; - } // end switch + // Also check and see if we should write + // out some metadata + if ($methods['metadata']) { + switch ($methods['metadata']) { + case 'windows': + $meta_file = $dir . '/desktop.ini'; + $string = "[.ShellClassInfo]\nIconFile=$file\nIconIndex=0\nInfoTip=$album->full_name"; + break; + default: + case 'linux': + $meta_file = $dir . '/.directory'; + $string = "Name=$album->full_name\nIcon=$file"; + break; + } // end switch - $meta_handle = fopen($meta_file,"w"); - fwrite($meta_handle,$string); - fclose($meta_handle); - - } // end metadata - $i++; - if (!($i%100)) { - echo "Written: $i. . .\n"; - debug_event('art_write',"$album->name Art written to $file",'5'); - } - } // end if fopen - else { - debug_event('art_write',"Unable to open $file for writting",'5'); - echo "Error unable to open file for writting [$file]\n"; - } - } // end if fopen worked - - fclose($file_handle); - - - } // end foreach - - echo "Album Art Dump Complete\n"; - - } // dump_album_art - - /** - * update_last_update - * updates the last_update of the catalog - */ - private function update_last_update() { - - $date = time(); - $sql = "UPDATE `catalog` SET `last_update`='$date' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - } // update_last_update - - /** - * update_last_add - * updates the last_add of the catalog - */ - public function update_last_add() { - - $date = time(); - $sql = "UPDATE `catalog` SET `last_add`='$date' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - } // update_last_add - - /** - * update_last_clean - * This updates the last clean information - */ - public function update_last_clean() { - - $date = time(); - $sql = "UPDATE `catalog` SET `last_clean`='$date' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - } // update_last_clean - - /** - * update_settings - * This function updates the basic setting of the catalog - */ - public static function update_settings($data) { - - $id = Dba::escape($data['catalog_id']); - $name = Dba::escape($data['name']); - $rename = Dba::escape($data['rename_pattern']); - $sort = Dba::escape($data['sort_pattern']); - $remote_username = Dba::escape($data['remote_username']); - $remote_password = Dba::escape($data['remote_password']); - - $sql = "UPDATE `catalog` SET `name`='$name', `rename_pattern`='$rename', " . - "`sort_pattern`='$sort', `remote_username`='$remote_username', `remote_password`='$remote_password' WHERE `id` = '$id'"; - $db_results = Dba::write($sql); - - return true; - - } // update_settings - - /** - * update_single_item - * updates a single album,artist,song from the tag data - * this can be done by 75+ - */ - public static function update_single_item($type,$id) { - - // Because single items are large numbers of things too - set_time_limit(0); - - $songs = array(); - - switch ($type) { - case 'album': - $album = new Album($id); - $songs = $album->get_songs(); - break; - case 'artist': - $artist = new Artist($id); - $songs = $artist->get_songs(); - break; - case 'song': - $songs[] = $id; - break; - } // end switch type - - foreach($songs as $song_id) { - $song = new Song($song_id); - $info = self::update_media_from_tags($song,'',''); - - if ($info['change']) { - $file = scrub_out($song->file); - echo "
\n\t
"; - echo "$file " . T_('Updated') . "\n"; - echo $info['text']; - echo "\t
\n

"; - flush(); - } // if change - else { - echo"
\n\t
"; - echo "" . scrub_out($song->file) . "
" . T_('No Update Needed') . "\n"; - echo "\t
\n

"; - flush(); - } - } // foreach songs - - self::gc(); - - } // update_single_item - - /** - * update_media_from_tags - * This is a 'wrapper' function calls the update function for the media - * type in question - */ - public static function update_media_from_tags($media, $sort_pattern='', $rename_pattern='') { - - // Check for patterns - if (!$sort_pattern OR !$rename_pattern) { - $catalog = new Catalog($media->catalog); - $sort_pattern = $catalog->sort_pattern; - $rename_pattern = $catalog->rename_pattern; - } - - debug_event('tag-read','Reading tags from ' . $media->file,'5','ampache-catalog'); - - $vainfo = new vainfo($media->file,'','','',$sort_pattern,$rename_pattern); - $vainfo->get_info(); - - $key = vainfo::get_tag_type($vainfo->tags); - - $results = vainfo::clean_tag_info($vainfo->tags,$key,$media->file); - - // Figure out what type of object this is and call the right - // function, giving it the stuff we've figured out above - $name = (get_class($media) == 'Song') ? 'song' : 'video'; - - $function = 'update_' . $name . '_from_tags'; - - $return = call_user_func(array('Catalog',$function),$results,$media); - - return $return; - - } // update_media_from_tags - - /** - * update_video_from_tags - * Updates the video info based on tags - */ - public static function update_video_from_tags($results,$video) { - - // Pretty sweet function here - return $results; - - } // update_video_from_tags - - /** - * update_song_from_tags - * Updates the song info based on tags; this is called from a bunch of - * different places and passes in a full fledged song object, so it's a - * static function. - * FIXME: This is an ugly mess, this really needs to be consolidated and - * cleaned up. - */ - public static function update_song_from_tags($results,$song) { - - /* Setup the vars */ - $new_song = new Song(); - $new_song->file = $results['file']; - $new_song->title = $results['title']; - $new_song->year = $results['year']; - $new_song->comment = $results['comment']; - $new_song->language = $results['language']; - $new_song->lyrics = $results['lyrics']; - $new_song->bitrate = $results['bitrate']; - $new_song->rate = $results['rate']; - $new_song->mode = ($results['mode'] == 'cbr') ? 'cbr' : 'vbr'; - $new_song->size = $results['size']; - $new_song->time = $results['time']; - $new_song->mime = $results['mime']; - $new_song->track = intval($results['track']); - $new_song->mbid = $results['mb_trackid']; - $artist = $results['artist']; - $artist_mbid = $results['mb_artistid']; - $album = $results['album']; - $album_mbid = $results['mb_albumid']; - $disk = $results['disk']; - $tags = $results['genre']; // multiple genre support makes this an array - - /* - * We have the artist/genre/album name need to check it in the tables - * If found then add & return id, else return id - */ - $new_song->artist = self::check_artist($artist,$artist_mbid); - $new_song->f_artist = $artist; - $new_song->album = self::check_album($album,$new_song->year,$disk,$album_mbid); - $new_song->f_album = $album . " - " . $new_song->year; - $new_song->title = self::check_title($new_song->title,$new_song->file); - - // Nothing to assign here this is a multi-value doodly - // multiple genre support - foreach ($tags as $tag) { - $tag = trim($tag); - self::check_tag($tag,$song->id); - self::check_tag($tag,$new_song->album,'album'); - self::check_tag($tag,$new_song->artist,'artist'); - } - - /* Since we're doing a full compare make sure we fill the extended information */ - $song->fill_ext_info(); - - $info = Song::compare_song_information($song,$new_song); - - if ($info['change']) { - debug_event('update',"$song->file difference found, updating database",'5','ampache-catalog'); - $song->update_song($song->id,$new_song); - // Refine our reference - $song = $new_song; - } - else { - debug_event('update',"$song->file no difference found returning",'5','ampache-catalog'); - } - - return $info; - - } // update_song_from_tags - - /** - * add_to_catalog - * this function adds new files to an - * existing catalog - */ - public function add_to_catalog() { - - if ($this->catalog_type == 'remote') { - UI::show_box_top(T_('Running Remote Update') . '. . .'); - $this->get_remote_catalog($type=0); - UI::show_box_bottom(); - return true; - } - - require Config::get('prefix') . '/templates/show_adds_catalog.inc.php'; - flush(); - - /* Set the Start time */ - $start_time = time(); - - // Make sure the path doesn't end in a / or \ - $this->path = rtrim($this->path,'/'); - $this->path = rtrim($this->path,'\\'); - - // Prevent the script from timing out and flush what we've got - set_time_limit(0); - - /* Get the songs and then insert them into the db */ - $this->add_files($this->path,$type,0,$verbose); - - // Foreach Playlists we found - foreach ($this->_playlists as $full_file) { - $result = $this->import_m3u($full_file); - if ($result['success']) { - $file = basename($full_file); - if ($verbose) { - echo "   " . T_('Added Playlist From') . " $file . . . .
\n"; - flush(); - } - } // end if import worked - } // end foreach playlist files - - /* Do a little stats mojo here */ - $current_time = time(); - - $catalog_id = $this->id; - require Config::get('prefix') . '/templates/show_gather_art.inc.php'; - flush(); - $this->get_art(); - - /* Update the Catalog last_update */ - $this->update_last_add(); - - $time_diff = ($current_time - $start_time) ?: 0; - $rate = intval($this->count / $time_diff) ?: T_('N/A'); - - UI::show_box_top(); - echo "\n
" . - printf(T_('Catalog Update Finished. Total Time: [%s] Total Songs: [%s] Songs Per Second: [%s]'), - date('i:s', $time_diff), $this->count, $rate); - echo '

'; - UI::show_box_bottom(); - - } // add_to_catalog - - /** - * get_remote_catalog - * get a remote catalog and runs update if needed this requires - * this uses the AmpacheAPI library provided, replaces legacy XMLRPC - */ - public function get_remote_catalog($type=0) { - - try { - $remote_handle = new AmpacheApi(array('username'=>$this->remote_username,'password'=>$this->remote_password,'server'=>$this->path,'debug'=>true)); - } catch (Exception $e) { - Error::add('general',$e->getMessage()); - Error::display('general'); - flush(); - return false; - } - - if ($remote_handle->state() != 'CONNECTED') { - debug_event('APICLIENT','Error Unable to make API client ready','1'); - Error::add('general', T_('Error Connecting to Remote Server')); - Error::display('general'); - return false; - } - - // Figure out how many songs, more information etc - $remote_catalog_info = $remote_handle->info(); - - // Tell em what we've found johnny! - printf(T_('%u remote catalog(s) found (%u songs)'),$remote_catalog_info['catalogs'],$remote_catalog_info['songs']); - flush(); - - // Hardcoded for now - $step = '500'; - $current = '0'; - $total = $remote_catalog_info['songs']; - - while ($total > $current) { - $start = $current; - $current += $step; - // It uses exceptions so lets try this - try { - $remote_handle->parse_response($remote_handle->send_command('songs',array('offset'=>$start,'limit'=>$step))); - $songs = $remote_handle->get_response(); - } catch (Exception $e) { - Error::add('general',$e->getMessage()); - Error::display('general'); - flush(); - } - // itterate the songs we retrieved and insert them - foreach ($songs as $data) { - if (!$this->insert_remote_song($data['song'])) { - debug_event('REMOTE_INSERT','Remote Insert failed, see previous log messages -' . $data['song']['self']['id'],'1'); - Error::add('general', T_('Unable to Insert Song - %s'),$data['song']['title']); - Error::display('general'); - flush(); - } - } // end foreach - } // end while - - echo "

" . T_('Completed updating remote catalog(s)') . ".


\n"; - flush(); - - // Update the last update value - $this->update_last_update(); - - return true; - - } // get_remote_catalog - - /** - * update_remote_catalog - * actually updates from the remote data, takes an array of songs that are base64 encoded and parses them - */ - public function update_remote_catalog($data,$root_path) { - - // Going to leave this be for now - //FIXME: Implement - - return true; - - } // update_remote_catalog - - /** - * clean_catalog - * Cleans the catalog of files that no longer exist. - */ - public function clean_catalog() { - - // We don't want to run out of time - set_time_limit(0); - - debug_event('clean', 'Starting on ' . $this->name, 5, 'ampache-catalog'); - - require_once Config::get('prefix') . '/templates/show_clean_catalog.inc.php'; - ob_flush(); - flush(); - - // Do a quick check to make sure that the root of the catalog is - // readable. This will minimize the loss of catalog data if - // mount points fail - if ($this->catalog_type == 'local' && !is_readable($this->path)) { - debug_event('catalog', 'Catalog path:' . $this->path . ' unreadable, clean failed', 1); - Error::add('general', T_('Catalog Root unreadable, stopping clean')); - Error::display('general'); - return false; - } - - - $dead_total = 0; - $stats = self::get_stats($this->id); - foreach(array('video', 'song') as $media_type) { - $total = $stats[$media_type . 's']; // UGLY - if ($total == 0) { - continue; - } - $chunks = floor($total / 10000); - $dead = array(); - foreach(range(0, $chunks) as $chunk) { - $dead = array_merge($dead, $this->_clean_chunk($media_type, $chunk, 10000)); - } - - $dead_count = count($dead); - // The AlmightyOatmeal sanity check - // Never remove everything; it might be a dead mount - if ($dead_count >= $total) { - debug_event('catalog', 'All files would be removed. Doing nothing.', 1); - Error::add('general', T_('All files would be removed. Doing nothing')); - continue; - } - if ($dead_count) { - $dead_total += $dead_count; - $sql = "DELETE FROM `$media_type` WHERE `id` IN " . - '(' . implode(',',$dead) . ')'; - $db_results = Dba::write($sql); - } - debug_event('clean', "$media_type finished, $dead_count removed from " . - $this->name, 5, 'ampache-catalog'); - } - - // Remove any orphaned artists/albums/etc. - self::gc(); - - UI::show_box_top(); - echo ""; - printf (T_ngettext('Catalog Clean Done. %d file removed.', 'Catalog Clean Done. %d files removed.', $dead_total), $dead_total); - echo "
\n"; - UI::show_box_bottom(); - ob_flush(); - flush(); - - $this->update_last_clean(); - } // clean_catalog - - - /** - * _clean_chunk - * This is the clean function, its broken into - * said chunks to try to save a little memory - */ - private function _clean_chunk($media_type, $chunk, $chunk_size) { - debug_event('clean', "Starting chunk $chunk", 5, 'ampache-catalog'); - $dead = array(); - $count = $chunk * $chunk_size; - - $sql = "SELECT `id`, `file` FROM `$media_type` " . - "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size"; - $db_results = Dba::read($sql); - - while ($results = Dba::fetch_assoc($db_results)) { - debug_event('clean', 'Starting work on ' . $results['file'] . '(' . $results['id'] . ')', 5, 'ampache-catalog'); - $count++; - if (UI::check_ticker()) { - $file = str_replace(array('(',')', '\''), '', $results['file']); - UI::update_text('clean_count_' . $this->id, $count); - UI::update_text('clean_dir_' . $this->id, scrub_out($file)); - } - if($this->catalog_type == 'local') { - $file_info = filesize($results['file']); - if (!file_exists($results['file']) || $file_info < 1) { - debug_event('clean', 'File not found or empty: ' . $results['file'], 5, 'ampache-catalog'); - Error::add('general', sprintf(T_('Error File Not Found or 0 Bytes: %s'), $results['file'])); - - - // Store it in an array we'll delete it later... - $dead[] = $results['id']; - - } //if error - else if (!is_readable($results['file'])) { - debug_event('clean', $results['file'] . ' is not readable, but does exist', 1, 'ampache-catalog'); - } - } // if localtype - else { - //do remote url check - $file_info = $this->check_remote_song($results['file']); - - if ($file_info == false) { - /* Add Error */ - Error::add('general', sprintf(T_('Error Remote File Not Found or 0 Bytes: %s'), $results['file'])); - - - // Store it in an array we'll delete it later... - $dead[] = $results['id']; - - } //if error - } // remote catalog - - } //while gettings songs - return $dead; - - } //_clean_chunk - - /** - * verify_catalog - * This function compares the DB's information with the ID3 tags - */ - public function verify_catalog() { - - debug_event('verify', 'Starting on ' . $this->name, 5, 'ampache-catalog'); - set_time_limit(0); - - $stats = self::get_stats($this->id); - $number = $stats['videos'] + $stats['songs']; - $total_updated = 0; - - require_once Config::get('prefix') . '/templates/show_verify_catalog.inc.php'; - - foreach(array('video', 'song') as $media_type) { - $total = $stats[$media_type . 's']; // UGLY - if ($total == 0) { - continue; - } - $chunks = floor($total / 10000); - foreach(range(0, $chunks) as $chunk) { - // Try to be nice about memory usage - if ($chunk > 0) { - $media_type::clear_cache(); - } - $total_updated += $this->_verify_chunk($media_type, $chunk, 10000); - } - } - - debug_event('verify', "Finished, $total_updated updated in " . $this->name, 5, 'ampache-catalog'); - - self::gc(); - $this->update_last_update(); - - UI::show_box_top(); - echo ''; - printf(T_('Catalog Verify Done. %d of %d files updated.'), $total_updated, $number); - echo "
\n"; - UI::show_box_bottom(); - ob_flush(); - flush(); - - return true; - - } // verify_catalog - - /** - * _verify_chunk - * This verifies a chunk of the catalog, done to save - * memory - */ - private function _verify_chunk($media_type, $chunk, $chunk_size) { - debug_event('verify', "Starting chunk $chunk", 5, 'ampache-catalog'); - $count = $chunk * $chunk_size; - $changed = 0; - - $sql = "SELECT `id`, `file` FROM `$media_type` " . - "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size"; - $db_results = Dba::read($sql); - - if (Config::get('memory_cache')) { - while ($row = Dba::fetch_assoc($db_results, false)) { - $media_ids[] = $row['id']; - } - $media_type::build_cache($media_ids); - Dba::seek($db_results, 0); - } - - while ($row = Dba::fetch_assoc($db_results)) { - $count++; - if (UI::check_ticker()) { - $file = str_replace(array('(',')','\''), '', $row['file']); - UI::update_text('verify_count_' . $this->id, $count); - UI::update_text('verify_dir_' . $this->id, scrub_out($file)); - } - - if (!is_readable($row['file'])) { - Error::add('general', sprintf(T_('%s does not exist or is not readable'), $row['file'])); - debug_event('read', $row['file'] . ' does not exist or is not readable', 5,'ampache-catalog'); - continue; - } - - $media = new $media_type($row['id']); - - if (Flag::has_flag($media->id, $type)) { - debug_event('verify', "$media->file is flagged, skipping", 5, 'ampache-catalog'); - continue; - } - - $info = self::update_media_from_tags($media, $this->sort_pattern,$this->rename_pattern); - if ($info['change']) { - $changed++; - } - unset($info); - } - - UI::update_text('verify_count_' . $this->id, $count); - return $changed; - - } // _verfiy_chunk - - /** - * gc - * - * This is a wrapper function for all of the different cleaning - * functions, it runs them in an order that resembles correct - */ - public static function gc() { - - debug_event('catalog', 'Database cleanup started', 5, 'ampache-catalog'); - Song::gc(); - Album::gc(); - Artist::gc(); - Art::gc(); - Flag::gc(); - Stats::gc(); - Rating::gc(); - Playlist::gc(); - Tmp_Playlist::gc(); - Shoutbox::gc(); - Tag::gc(); - debug_event('catalog', 'Database cleanup ended', 5, 'ampache-catalog'); - - } - - /** - * trim_prefix - * Splits the prefix from the string - */ - public static function trim_prefix($string) { - $prefix_pattern = '/^(' . implode('\\s|',explode('|',Config::get('catalog_prefix_pattern'))) . '\\s)(.*)/i'; - preg_match($prefix_pattern, $string, $matches); - - if (count($matches)) { - $string = trim($matches[2]); - $prefix = trim($matches[1]); - } - else { - $prefix = null; - } - - return array('string' => $string, 'prefix' => $prefix); - } // trim_prefix - - /** - * check_artist - * $artist checks if there then return id else insert and return id - * If readonly is passed then don't create, return false on not found - */ - public static function check_artist($artist,$mbid='',$readonly='') { - - /* Clean up the artist */ - $artist = trim($artist); - $artist = Dba::escape($artist); - - /* Ohh no the artist has lost it's mojo! */ - if (!$artist) { - $artist = T_('Unknown (Orphaned)'); - } - - // Remove the prefix so we can sort it correctly - $trimmed = Catalog::trim_prefix($artist); - $artist = $trimmed['string']; - $prefix = $trimmed['prefix']; - - // Check to see if we've seen this artist before - if (isset(self::$artists[$artist][$mbid])) { - return self::$artists[$artist][$mbid]; - } // if we've seen this artist before - - $exists = false; - - $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'"; - $db_results = Dba::read($sql); - - // Check for results - if ($r = Dba::fetch_assoc($db_results)) { - $artist_id = $r['id']; - $exists = true; - } - - else { // No exact match based on MBID - $sql = "SELECT `id`, `mbid` FROM `artist` WHERE `name` LIKE '$artist'"; - $db_results = Dba::read($sql); - - - /* If we have results */ - while ($r = Dba::fetch_assoc($db_results)) { - $key = is_null($r['mbid']) ? 'null' : $r['mbid']; - $id_array[$key] = $r['id']; - } // while - - /* Choose one */ - if (isset($id_array)) { - if ($mbid == '') { // Prefer null entry, otherwise pick the first - if (isset($id_array['null'])) { - $key = 'null'; - } - else { - $keys = array_keys($id_array); - $key = array_shift($keys); - } - $artist_id = $id_array[$key]; - $exists = true; - } - elseif (isset($id_array['null'])) { - $artist_id = $id_array['null']; - $exists = true; - if (!$readonly) { - $sql = "UPDATE `artist` SET `mbid`='$mbid' WHERE `id`='$artist_id'"; - $db_results = Dba::write($sql); - if (!$db_results) { - Error::add('general', sprintf(T_('Updating Artist: %s'), $artist)); - } - } - } - unset($id_array); - } - } // fuzzy matching - - /* If not found create */ - if (!$readonly && !$exists) { - - $prefix_txt = $prefix ? "'$prefix'" : 'NULL'; - - $mbid = $mbid == '' ? 'NULL' : "'$mbid'"; - - $sql = "INSERT INTO `artist` (`name`, `prefix`, `mbid`) " . - "VALUES ('$artist',$prefix_txt,$mbid)"; - $db_results = Dba::write($sql); - $artist_id = Dba::insert_id(); - - if (!$db_results) { - Error::add('general', sprintf(T_('Inserting Artist: %s'), $artist)); - } - - } // not found - // If readonly, and not found return false - elseif (!$exists) { - return false; - } - - self::$artists[$artist][$mbid] = $artist_id; - - return $artist_id; - - } // check_artist - - /** - * check_album - * Searches for album; if found returns id else inserts and returns id - */ - public static function check_album($album, $album_year = 0, - $album_disk = 0, $mbid = '', $readonly = false) { - - /* Clean up the values */ - $album = trim($album); - $album = Dba::escape($album); - // Not even sure if these can be negative, but better safe than - // llama. - $album_year = abs(intval($album_year)); - $album_disk = abs(intval($album_disk)); - - /* Ohh no the album has lost its mojo */ - if (!$album) { - $album = T_('Unknown (Orphaned)'); - unset($album_year, $album_disk); - } - - // Remove the prefix so we can sort it correctly - $trimmed = Catalog::trim_prefix($album); - $album = $trimmed['string']; - $prefix = $trimmed['prefix']; - - // Check to see if we've seen this album before - if (isset(self::$albums[$album][$album_year][$album_disk][$mbid])) { - return self::$albums[$album][$album_year][$album_disk][$mbid]; - } - - /* Set up the Query */ - $sql = "SELECT `id` FROM `album` WHERE `name` = '$album'" . - " AND `disk`='$album_disk' AND `year`='$album_year'" . - " AND `mbid`" . ($mbid ? "='$mbid'" : ' IS NULL') . - " AND `prefix`" . ($prefix ? "='$prefix'" : ' IS NULL'); - - $db_results = Dba::read($sql); - - /* If it's found */ - if ($r = Dba::fetch_assoc($db_results)) { - $album_id = $r['id']; - - // If we don't have art put it in the 'needs me some - // art' array - $art = new Art($r['id'], 'album'); - $art->get_db(); - if (!$art->raw) { - $key = $r['id']; - self::$_art_albums[$key] = $key; - } - - } //if found - elseif (!$readonly) { // If not found, create - - $prefix = $prefix ? "'$prefix'" : 'NULL'; - $mbid = $mbid ? "'$mbid'" : 'NULL'; - - $sql = "INSERT INTO `album` (`name`, `prefix`,`year`,`disk`,`mbid`) " . - "VALUES ('$album',$prefix,'$album_year','$album_disk',$mbid)"; - $db_results = Dba::write($sql); - $album_id = Dba::insert_id(); - - if (!$db_results) { - debug_event('album',"Error Unable to insert Album:$album",'2'); - return false; - } - - // Add it to the I needs me some album art array - self::$_art_albums[$album_id] = $album_id; - - } //not found - else { - // readonly and not found - return false; - } - - // Save the cache - self::$albums[$album][$album_year][$album_disk][$mbid] = $album_id; - - return $album_id; - - } // check_album - - /** - * check_tag - * This checks the tag we've been passed (name) - * and sees if it exists, and if so if it's mapped - * to this object, this is only done for songs for now - */ - public static function check_tag($value,$object_id,$object_type='song') { - - $map_id = Tag::add($object_type,$object_id,$value,'0'); - - return $map_id; - - } // check_tag - - /** - * check_title - * this checks to make sure something is - * set on the title, if it isn't it looks at the - * filename and trys to set the title based on that - */ - public static function check_title($title,$file=0) { - - if (strlen(trim($title)) < 1) { - $title = Dba::escape($file); - } - - return $title; - - } // check_title - - /** - * insert_local_song - * Insert a song that isn't already in the database this - * function is in here so we don't have to create a song object - */ - public function insert_local_song($file,$file_info) { - - /* Create the vainfo object and get info */ - $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern); - $vainfo->get_info(); - - $key = vainfo::get_tag_type($vainfo->tags); - - /* Clean Up the tags */ - $results = vainfo::clean_tag_info($vainfo->tags,$key,$file); - - /* Set the vars here... so we don't have to do the '" . $blah['asd'] . "' */ - $title = Dba::escape($results['title']); - $artist = $results['artist']; - $album = $results['album']; - $bitrate = $results['bitrate']; - $rate = $results['rate']; - $mode = $results['mode']; - $size = $results['size']; - $song_time = $results['time']; - $track = $results['track']; - $track_mbid = $results['mb_trackid']; - $album_mbid = $results['mb_albumid']; - $artist_mbid= $results['mb_artistid']; - $disk = $results['disk']; - $year = $results['year']; - $comment = $results['comment']; - $tags = $results['genre']; // multiple genre support makes this an array - $current_time = time(); - $lyrics = ' '; - - /* - * We have the artist/genre/album name need to check it in the tables - * If found then add & return id, else return id - */ - $artist_id = self::check_artist($artist,$artist_mbid); - $album_id = self::check_album($album,$year,$disk,$album_mbid); - $title = self::check_title($title,$file); - $add_file = Dba::escape($file); - - $sql = "INSERT INTO `song` (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,addition_time,year,mbid)" . - " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$track_mbid')"; - $db_results = Dba::write($sql); - - if (!$db_results) { - debug_event('insert',"Unable to insert $file -- $sql" . Dba::error(),'5','ampache-catalog'); - Error::add('catalog_add', sprintf(T_('SQL Error Adding %s'), $file)); - } - - $song_id = Dba::insert_id(); - - // multiple genre support - foreach ($tags as $tag) { - $tag = trim($tag); - self::check_tag($tag,$song_id); - self::check_tag($tag,$album_id,'album'); - self::check_tag($tag,$artist_id,'artist'); - } - - - /* Add the EXT information */ - $sql = "INSERT INTO `song_data` (`song_id`,`comment`,`lyrics`) " . - " VALUES ('$song_id','$comment','$lyrics')"; - $db_results = Dba::write($sql); - - if (!$db_results) { - debug_event('insert',"Unable to insert EXT Info for $file -- $sql",'5','ampache-catalog'); - } - - } // insert_local_song - - /** - * insert_remote_song - * takes the information gotten from XML-RPC and - * inserts it into the local database. The filename - * ends up being the url. - */ - public function insert_remote_song($song) { - - /* Limitations: - * Missing Following Metadata - * Disk,Rate - */ - - // Strip the SSID off of the url, we will need to regenerate this every time - $url = preg_replace("/ssid=.*&/","",$song['url']); - $title = Dba::escape($song['title']); - $album = self::check_album($song['album'],$song['year'],null,$song['album_mbid']); - $artist = self::check_artist($song['artist'],$song['artist_mbid']); - $bitrate = Dba::escape($song['bitrate']); - $size = Dba::escape($song['size']); - $song_time = Dba::escape($song['time']); - $track = Dba::escape($song['track']); - $year = Dba::escape($song['year']); - $title = Dba::escape($song['title']); - $mbid = Dba::escape($song['mbid']); - $mode = Dba::escape($song['mode']); - $current_time = time(); - $catalog_id = Dba::escape($this->id); - - $sql = "INSERT INTO `song` (`file`,`catalog`,`album`,`artist`,`title`,`bitrate`,`rate`,`mode`,`size`,`time`,`track`,`addition_time`,`year`,`mbid`)" . - " VALUES ('$url','$catalog_id','$album','$artist','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$mbid')"; - $db_results = Dba::write($sql); - - if (!$db_results) { - debug_event('insert',"Unable to Add Remote $url -- $sql",'5','ampache-catalog'); - return false; - } - - // Weird to do this here, but we have the information - see if the album has art, if it doesn't then use the remote - // art url - $art = new Art($album, 'album'); - // If it doesn't have art... - if (!$art->get()) { - // Get the mime out - $get_vars = parse_url($song['art']); - $extension = substr($get_vars['query'],strlen($get_vars['query'])-3,3); - // Pull the image - $raw = Art::get_from_source( - array('url' => $song['art']), 'album'); - $inserted = $art->insert($raw,'image/' . $extension); - } - - return true; - - } // insert_remote_song - - /** - * insert_local_video - * This inserts a video file into the video file table the tag - * information we can get is super sketchy so it's kind of a crap shoot - * here - */ - public function insert_local_video($file,$filesize) { - - /* Create the vainfo object and get info */ - $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern); - $vainfo->get_info(); - - $tag_name = vainfo::get_tag_type($vainfo->tags); - $results = vainfo::clean_tag_info($vainfo->tags,$tag_name,$file); - - - $file = Dba::escape($file); - $catalog_id = Dba::escape($this->id); - $title = Dba::escape($results['title']); - $vcodec = $results['video_codec']; - $acodec = $results['audio_codec']; - $rezx = intval($results['resolution_x']); - $rezy = intval($results['resolution_y']); - $filesize = Dba::escape($filesize); - $time = Dba::escape($results['time']); - $mime = Dba::escape($results['mime']); - // UNUSED CURRENTLY - $comment = Dba::escape($results['comment']); - $year = Dba::escape($results['year']); - $disk = Dba::escape($results['disk']); - - $sql = "INSERT INTO `video` (`file`,`catalog`,`title`,`video_codec`,`audio_codec`,`resolution_x`,`resolution_y`,`size`,`time`,`mime`) " . - " VALUES ('$file','$catalog_id','$title','$vcodec','$acodec','$rezx','$rezy','$filesize','$time','$mime')"; - $db_results = Dba::write($sql); - - return true; - - } // insert_local_video - - /** - * check_remote_song - * checks to see if a remote song exists in the database or not - * if it find a song it returns the UID - */ - public function check_remote_song($url) { - - $url = Dba::escape($url); - - $sql = "SELECT `id` FROM `song` WHERE `file`='$url'"; - $db_results = Dba::read($sql); - - if ($results = Dba::fetch_assoc($db_results)) { - return $results['id']; - } - - return false; - - } // check_remote_song - - /** - * check_local_mp3 - * Checks the song to see if it's there already returns true if found, false if not - */ - public function check_local_mp3($full_file, $gather_type='') { - - $file_date = filemtime($full_file); - if ($file_date < $this->last_add) { - debug_event('Check','Skipping ' . $full_file . ' File modify time before last add run','3'); - return true; - } - - $full_file = Dba::escape($full_file); + $meta_handle = fopen($meta_file,"w"); + fwrite($meta_handle,$string); + fclose($meta_handle); + + } // end metadata + $i++; + if (!($i%100)) { + echo "Written: $i. . .\n"; + debug_event('art_write',"$album->name Art written to $file",'5'); + } + } // end if fopen + else { + debug_event('art_write',"Unable to open $file for writting",'5'); + echo "Error unable to open file for writting [$file]\n"; + } + } // end if fopen worked + + fclose($file_handle); + + + } // end foreach + + echo "Album Art Dump Complete\n"; + + } // dump_album_art + + /** + * update_last_update + * updates the last_update of the catalog + */ + private function update_last_update() { + + $date = time(); + $sql = "UPDATE `catalog` SET `last_update`='$date' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + } // update_last_update + + /** + * update_last_add + * updates the last_add of the catalog + */ + public function update_last_add() { + + $date = time(); + $sql = "UPDATE `catalog` SET `last_add`='$date' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + } // update_last_add + + /** + * update_last_clean + * This updates the last clean information + */ + public function update_last_clean() { + + $date = time(); + $sql = "UPDATE `catalog` SET `last_clean`='$date' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + } // update_last_clean + + /** + * update_settings + * This function updates the basic setting of the catalog + */ + public static function update_settings($data) { + + $id = Dba::escape($data['catalog_id']); + $name = Dba::escape($data['name']); + $rename = Dba::escape($data['rename_pattern']); + $sort = Dba::escape($data['sort_pattern']); + $remote_username = Dba::escape($data['remote_username']); + $remote_password = Dba::escape($data['remote_password']); + + $sql = "UPDATE `catalog` SET `name`='$name', `rename_pattern`='$rename', " . + "`sort_pattern`='$sort', `remote_username`='$remote_username', `remote_password`='$remote_password' WHERE `id` = '$id'"; + $db_results = Dba::write($sql); + + return true; + + } // update_settings + + /** + * update_single_item + * updates a single album,artist,song from the tag data + * this can be done by 75+ + */ + public static function update_single_item($type,$id) { + + // Because single items are large numbers of things too + set_time_limit(0); + + $songs = array(); + + switch ($type) { + case 'album': + $album = new Album($id); + $songs = $album->get_songs(); + break; + case 'artist': + $artist = new Artist($id); + $songs = $artist->get_songs(); + break; + case 'song': + $songs[] = $id; + break; + } // end switch type + + foreach($songs as $song_id) { + $song = new Song($song_id); + $info = self::update_media_from_tags($song,'',''); + + if ($info['change']) { + $file = scrub_out($song->file); + echo "
\n\t
"; + echo "$file " . T_('Updated') . "\n"; + echo $info['text']; + echo "\t
\n

"; + flush(); + } // if change + else { + echo"
\n\t
"; + echo "" . scrub_out($song->file) . "
" . T_('No Update Needed') . "\n"; + echo "\t
\n

"; + flush(); + } + } // foreach songs + + self::gc(); + + } // update_single_item + + /** + * update_media_from_tags + * This is a 'wrapper' function calls the update function for the media + * type in question + */ + public static function update_media_from_tags($media, $sort_pattern='', $rename_pattern='') { + + // Check for patterns + if (!$sort_pattern OR !$rename_pattern) { + $catalog = new Catalog($media->catalog); + $sort_pattern = $catalog->sort_pattern; + $rename_pattern = $catalog->rename_pattern; + } + + debug_event('tag-read','Reading tags from ' . $media->file,'5','ampache-catalog'); + + $vainfo = new vainfo($media->file,'','','',$sort_pattern,$rename_pattern); + $vainfo->get_info(); + + $key = vainfo::get_tag_type($vainfo->tags); + + $results = vainfo::clean_tag_info($vainfo->tags,$key,$media->file); + + // Figure out what type of object this is and call the right + // function, giving it the stuff we've figured out above + $name = (get_class($media) == 'Song') ? 'song' : 'video'; + + $function = 'update_' . $name . '_from_tags'; + + $return = call_user_func(array('Catalog',$function),$results,$media); + + return $return; + + } // update_media_from_tags + + /** + * update_video_from_tags + * Updates the video info based on tags + */ + public static function update_video_from_tags($results,$video) { + + // Pretty sweet function here + return $results; + + } // update_video_from_tags + + /** + * update_song_from_tags + * Updates the song info based on tags; this is called from a bunch of + * different places and passes in a full fledged song object, so it's a + * static function. + * FIXME: This is an ugly mess, this really needs to be consolidated and + * cleaned up. + */ + public static function update_song_from_tags($results,$song) { + + /* Setup the vars */ + $new_song = new Song(); + $new_song->file = $results['file']; + $new_song->title = $results['title']; + $new_song->year = $results['year']; + $new_song->comment = $results['comment']; + $new_song->language = $results['language']; + $new_song->lyrics = $results['lyrics']; + $new_song->bitrate = $results['bitrate']; + $new_song->rate = $results['rate']; + $new_song->mode = ($results['mode'] == 'cbr') ? 'cbr' : 'vbr'; + $new_song->size = $results['size']; + $new_song->time = $results['time']; + $new_song->mime = $results['mime']; + $new_song->track = intval($results['track']); + $new_song->mbid = $results['mb_trackid']; + $artist = $results['artist']; + $artist_mbid = $results['mb_artistid']; + $album = $results['album']; + $album_mbid = $results['mb_albumid']; + $disk = $results['disk']; + $tags = $results['genre']; // multiple genre support makes this an array + + /* + * We have the artist/genre/album name need to check it in the tables + * If found then add & return id, else return id + */ + $new_song->artist = self::check_artist($artist,$artist_mbid); + $new_song->f_artist = $artist; + $new_song->album = self::check_album($album,$new_song->year,$disk,$album_mbid); + $new_song->f_album = $album . " - " . $new_song->year; + $new_song->title = self::check_title($new_song->title,$new_song->file); + + // Nothing to assign here this is a multi-value doodly + // multiple genre support + foreach ($tags as $tag) { + $tag = trim($tag); + self::check_tag($tag,$song->id); + self::check_tag($tag,$new_song->album,'album'); + self::check_tag($tag,$new_song->artist,'artist'); + } + + /* Since we're doing a full compare make sure we fill the extended information */ + $song->fill_ext_info(); + + $info = Song::compare_song_information($song,$new_song); + + if ($info['change']) { + debug_event('update',"$song->file difference found, updating database",'5','ampache-catalog'); + $song->update_song($song->id,$new_song); + // Refine our reference + $song = $new_song; + } + else { + debug_event('update',"$song->file no difference found returning",'5','ampache-catalog'); + } + + return $info; + + } // update_song_from_tags + + /** + * add_to_catalog + * this function adds new files to an + * existing catalog + */ + public function add_to_catalog() { + + if ($this->catalog_type == 'remote') { + UI::show_box_top(T_('Running Remote Update') . '. . .'); + $this->get_remote_catalog($type=0); + UI::show_box_bottom(); + return true; + } + + require Config::get('prefix') . '/templates/show_adds_catalog.inc.php'; + flush(); + + /* Set the Start time */ + $start_time = time(); + + // Make sure the path doesn't end in a / or \ + $this->path = rtrim($this->path,'/'); + $this->path = rtrim($this->path,'\\'); + + // Prevent the script from timing out and flush what we've got + set_time_limit(0); + + /* Get the songs and then insert them into the db */ + $this->add_files($this->path,$type,0,$verbose); + + // Foreach Playlists we found + foreach ($this->_playlists as $full_file) { + $result = $this->import_m3u($full_file); + if ($result['success']) { + $file = basename($full_file); + if ($verbose) { + echo "   " . T_('Added Playlist From') . " $file . . . .
\n"; + flush(); + } + } // end if import worked + } // end foreach playlist files + + /* Do a little stats mojo here */ + $current_time = time(); + + $catalog_id = $this->id; + require Config::get('prefix') . '/templates/show_gather_art.inc.php'; + flush(); + $this->get_art(); + + /* Update the Catalog last_update */ + $this->update_last_add(); + + $time_diff = ($current_time - $start_time) ?: 0; + $rate = intval($this->count / $time_diff) ?: T_('N/A'); + + UI::show_box_top(); + echo "\n
" . + printf(T_('Catalog Update Finished. Total Time: [%s] Total Songs: [%s] Songs Per Second: [%s]'), + date('i:s', $time_diff), $this->count, $rate); + echo '

'; + UI::show_box_bottom(); + + } // add_to_catalog + + /** + * get_remote_catalog + * get a remote catalog and runs update if needed this requires + * this uses the AmpacheAPI library provided, replaces legacy XMLRPC + */ + public function get_remote_catalog($type=0) { + + try { + $remote_handle = new AmpacheApi(array('username'=>$this->remote_username,'password'=>$this->remote_password,'server'=>$this->path,'debug'=>true)); + } catch (Exception $e) { + Error::add('general',$e->getMessage()); + Error::display('general'); + flush(); + return false; + } + + if ($remote_handle->state() != 'CONNECTED') { + debug_event('APICLIENT','Error Unable to make API client ready','1'); + Error::add('general', T_('Error Connecting to Remote Server')); + Error::display('general'); + return false; + } + + // Figure out how many songs, more information etc + $remote_catalog_info = $remote_handle->info(); + + // Tell em what we've found johnny! + printf(T_('%u remote catalog(s) found (%u songs)'),$remote_catalog_info['catalogs'],$remote_catalog_info['songs']); + flush(); + + // Hardcoded for now + $step = '500'; + $current = '0'; + $total = $remote_catalog_info['songs']; + + while ($total > $current) { + $start = $current; + $current += $step; + // It uses exceptions so lets try this + try { + $remote_handle->parse_response($remote_handle->send_command('songs',array('offset'=>$start,'limit'=>$step))); + $songs = $remote_handle->get_response(); + } catch (Exception $e) { + Error::add('general',$e->getMessage()); + Error::display('general'); + flush(); + } + // itterate the songs we retrieved and insert them + foreach ($songs as $data) { + if (!$this->insert_remote_song($data['song'])) { + debug_event('REMOTE_INSERT','Remote Insert failed, see previous log messages -' . $data['song']['self']['id'],'1'); + Error::add('general', T_('Unable to Insert Song - %s'),$data['song']['title']); + Error::display('general'); + flush(); + } + } // end foreach + } // end while + + echo "

" . T_('Completed updating remote catalog(s)') . ".


\n"; + flush(); + + // Update the last update value + $this->update_last_update(); + + return true; + + } // get_remote_catalog + + /** + * update_remote_catalog + * actually updates from the remote data, takes an array of songs that are base64 encoded and parses them + */ + public function update_remote_catalog($data,$root_path) { + + // Going to leave this be for now + //FIXME: Implement + + return true; + + } // update_remote_catalog + + /** + * clean_catalog + * Cleans the catalog of files that no longer exist. + */ + public function clean_catalog() { + + // We don't want to run out of time + set_time_limit(0); + + debug_event('clean', 'Starting on ' . $this->name, 5, 'ampache-catalog'); + + require_once Config::get('prefix') . '/templates/show_clean_catalog.inc.php'; + ob_flush(); + flush(); + + // Do a quick check to make sure that the root of the catalog is + // readable. This will minimize the loss of catalog data if + // mount points fail + if ($this->catalog_type == 'local' && !is_readable($this->path)) { + debug_event('catalog', 'Catalog path:' . $this->path . ' unreadable, clean failed', 1); + Error::add('general', T_('Catalog Root unreadable, stopping clean')); + Error::display('general'); + return false; + } + + + $dead_total = 0; + $stats = self::get_stats($this->id); + foreach(array('video', 'song') as $media_type) { + $total = $stats[$media_type . 's']; // UGLY + if ($total == 0) { + continue; + } + $chunks = floor($total / 10000); + $dead = array(); + foreach(range(0, $chunks) as $chunk) { + $dead = array_merge($dead, $this->_clean_chunk($media_type, $chunk, 10000)); + } + + $dead_count = count($dead); + // The AlmightyOatmeal sanity check + // Never remove everything; it might be a dead mount + if ($dead_count >= $total) { + debug_event('catalog', 'All files would be removed. Doing nothing.', 1); + Error::add('general', T_('All files would be removed. Doing nothing')); + continue; + } + if ($dead_count) { + $dead_total += $dead_count; + $sql = "DELETE FROM `$media_type` WHERE `id` IN " . + '(' . implode(',',$dead) . ')'; + $db_results = Dba::write($sql); + } + debug_event('clean', "$media_type finished, $dead_count removed from " . + $this->name, 5, 'ampache-catalog'); + } + + // Remove any orphaned artists/albums/etc. + self::gc(); + + UI::show_box_top(); + echo ""; + printf (T_ngettext('Catalog Clean Done. %d file removed.', 'Catalog Clean Done. %d files removed.', $dead_total), $dead_total); + echo "
\n"; + UI::show_box_bottom(); + ob_flush(); + flush(); + + $this->update_last_clean(); + } // clean_catalog + + + /** + * _clean_chunk + * This is the clean function, its broken into + * said chunks to try to save a little memory + */ + private function _clean_chunk($media_type, $chunk, $chunk_size) { + debug_event('clean', "Starting chunk $chunk", 5, 'ampache-catalog'); + $dead = array(); + $count = $chunk * $chunk_size; + + $sql = "SELECT `id`, `file` FROM `$media_type` " . + "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size"; + $db_results = Dba::read($sql); + + while ($results = Dba::fetch_assoc($db_results)) { + debug_event('clean', 'Starting work on ' . $results['file'] . '(' . $results['id'] . ')', 5, 'ampache-catalog'); + $count++; + if (UI::check_ticker()) { + $file = str_replace(array('(',')', '\''), '', $results['file']); + UI::update_text('clean_count_' . $this->id, $count); + UI::update_text('clean_dir_' . $this->id, scrub_out($file)); + } + if($this->catalog_type == 'local') { + $file_info = filesize($results['file']); + if (!file_exists($results['file']) || $file_info < 1) { + debug_event('clean', 'File not found or empty: ' . $results['file'], 5, 'ampache-catalog'); + Error::add('general', sprintf(T_('Error File Not Found or 0 Bytes: %s'), $results['file'])); + + + // Store it in an array we'll delete it later... + $dead[] = $results['id']; + + } //if error + else if (!is_readable($results['file'])) { + debug_event('clean', $results['file'] . ' is not readable, but does exist', 1, 'ampache-catalog'); + } + } // if localtype + else { + //do remote url check + $file_info = $this->check_remote_song($results['file']); + + if ($file_info == false) { + /* Add Error */ + Error::add('general', sprintf(T_('Error Remote File Not Found or 0 Bytes: %s'), $results['file'])); + + + // Store it in an array we'll delete it later... + $dead[] = $results['id']; + + } //if error + } // remote catalog + + } //while gettings songs + return $dead; + + } //_clean_chunk + + /** + * verify_catalog + * This function compares the DB's information with the ID3 tags + */ + public function verify_catalog() { + + debug_event('verify', 'Starting on ' . $this->name, 5, 'ampache-catalog'); + set_time_limit(0); + + $stats = self::get_stats($this->id); + $number = $stats['videos'] + $stats['songs']; + $total_updated = 0; + + require_once Config::get('prefix') . '/templates/show_verify_catalog.inc.php'; + + foreach(array('video', 'song') as $media_type) { + $total = $stats[$media_type . 's']; // UGLY + if ($total == 0) { + continue; + } + $chunks = floor($total / 10000); + foreach(range(0, $chunks) as $chunk) { + // Try to be nice about memory usage + if ($chunk > 0) { + $media_type::clear_cache(); + } + $total_updated += $this->_verify_chunk($media_type, $chunk, 10000); + } + } + + debug_event('verify', "Finished, $total_updated updated in " . $this->name, 5, 'ampache-catalog'); + + self::gc(); + $this->update_last_update(); + + UI::show_box_top(); + echo ''; + printf(T_('Catalog Verify Done. %d of %d files updated.'), $total_updated, $number); + echo "
\n"; + UI::show_box_bottom(); + ob_flush(); + flush(); + + return true; + + } // verify_catalog + + /** + * _verify_chunk + * This verifies a chunk of the catalog, done to save + * memory + */ + private function _verify_chunk($media_type, $chunk, $chunk_size) { + debug_event('verify', "Starting chunk $chunk", 5, 'ampache-catalog'); + $count = $chunk * $chunk_size; + $changed = 0; + + $sql = "SELECT `id`, `file` FROM `$media_type` " . + "WHERE `catalog`='$this->id' LIMIT $count,$chunk_size"; + $db_results = Dba::read($sql); + + if (Config::get('memory_cache')) { + while ($row = Dba::fetch_assoc($db_results, false)) { + $media_ids[] = $row['id']; + } + $media_type::build_cache($media_ids); + Dba::seek($db_results, 0); + } + + while ($row = Dba::fetch_assoc($db_results)) { + $count++; + if (UI::check_ticker()) { + $file = str_replace(array('(',')','\''), '', $row['file']); + UI::update_text('verify_count_' . $this->id, $count); + UI::update_text('verify_dir_' . $this->id, scrub_out($file)); + } + + if (!is_readable($row['file'])) { + Error::add('general', sprintf(T_('%s does not exist or is not readable'), $row['file'])); + debug_event('read', $row['file'] . ' does not exist or is not readable', 5,'ampache-catalog'); + continue; + } + + $media = new $media_type($row['id']); + + if (Flag::has_flag($media->id, $type)) { + debug_event('verify', "$media->file is flagged, skipping", 5, 'ampache-catalog'); + continue; + } + + $info = self::update_media_from_tags($media, $this->sort_pattern,$this->rename_pattern); + if ($info['change']) { + $changed++; + } + unset($info); + } + + UI::update_text('verify_count_' . $this->id, $count); + return $changed; + + } // _verfiy_chunk + + /** + * gc + * + * This is a wrapper function for all of the different cleaning + * functions, it runs them in an order that resembles correct + */ + public static function gc() { + + debug_event('catalog', 'Database cleanup started', 5, 'ampache-catalog'); + Song::gc(); + Album::gc(); + Artist::gc(); + Art::gc(); + Flag::gc(); + Stats::gc(); + Rating::gc(); + Playlist::gc(); + Tmp_Playlist::gc(); + Shoutbox::gc(); + Tag::gc(); + debug_event('catalog', 'Database cleanup ended', 5, 'ampache-catalog'); + + } + + /** + * trim_prefix + * Splits the prefix from the string + */ + public static function trim_prefix($string) { + $prefix_pattern = '/^(' . implode('\\s|',explode('|',Config::get('catalog_prefix_pattern'))) . '\\s)(.*)/i'; + preg_match($prefix_pattern, $string, $matches); + + if (count($matches)) { + $string = trim($matches[2]); + $prefix = trim($matches[1]); + } + else { + $prefix = null; + } + + return array('string' => $string, 'prefix' => $prefix); + } // trim_prefix + + /** + * check_artist + * $artist checks if there then return id else insert and return id + * If readonly is passed then don't create, return false on not found + */ + public static function check_artist($artist,$mbid='',$readonly='') { + + /* Clean up the artist */ + $artist = trim($artist); + $artist = Dba::escape($artist); + + /* Ohh no the artist has lost it's mojo! */ + if (!$artist) { + $artist = T_('Unknown (Orphaned)'); + } + + // Remove the prefix so we can sort it correctly + $trimmed = Catalog::trim_prefix($artist); + $artist = $trimmed['string']; + $prefix = $trimmed['prefix']; + + // Check to see if we've seen this artist before + if (isset(self::$artists[$artist][$mbid])) { + return self::$artists[$artist][$mbid]; + } // if we've seen this artist before + + $exists = false; + + $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'"; + $db_results = Dba::read($sql); + + // Check for results + if ($r = Dba::fetch_assoc($db_results)) { + $artist_id = $r['id']; + $exists = true; + } + + else { // No exact match based on MBID + $sql = "SELECT `id`, `mbid` FROM `artist` WHERE `name` LIKE '$artist'"; + $db_results = Dba::read($sql); + + + /* If we have results */ + while ($r = Dba::fetch_assoc($db_results)) { + $key = is_null($r['mbid']) ? 'null' : $r['mbid']; + $id_array[$key] = $r['id']; + } // while + + /* Choose one */ + if (isset($id_array)) { + if ($mbid == '') { // Prefer null entry, otherwise pick the first + if (isset($id_array['null'])) { + $key = 'null'; + } + else { + $keys = array_keys($id_array); + $key = array_shift($keys); + } + $artist_id = $id_array[$key]; + $exists = true; + } + elseif (isset($id_array['null'])) { + $artist_id = $id_array['null']; + $exists = true; + if (!$readonly) { + $sql = "UPDATE `artist` SET `mbid`='$mbid' WHERE `id`='$artist_id'"; + $db_results = Dba::write($sql); + if (!$db_results) { + Error::add('general', sprintf(T_('Updating Artist: %s'), $artist)); + } + } + } + unset($id_array); + } + } // fuzzy matching + + /* If not found create */ + if (!$readonly && !$exists) { + + $prefix_txt = $prefix ? "'$prefix'" : 'NULL'; + + $mbid = $mbid == '' ? 'NULL' : "'$mbid'"; + + $sql = "INSERT INTO `artist` (`name`, `prefix`, `mbid`) " . + "VALUES ('$artist',$prefix_txt,$mbid)"; + $db_results = Dba::write($sql); + $artist_id = Dba::insert_id(); + + if (!$db_results) { + Error::add('general', sprintf(T_('Inserting Artist: %s'), $artist)); + } + + } // not found + // If readonly, and not found return false + elseif (!$exists) { + return false; + } + + self::$artists[$artist][$mbid] = $artist_id; + + return $artist_id; + + } // check_artist + + /** + * check_album + * Searches for album; if found returns id else inserts and returns id + */ + public static function check_album($album, $album_year = 0, + $album_disk = 0, $mbid = '', $readonly = false) { + + /* Clean up the values */ + $album = trim($album); + $album = Dba::escape($album); + // Not even sure if these can be negative, but better safe than + // llama. + $album_year = abs(intval($album_year)); + $album_disk = abs(intval($album_disk)); + + /* Ohh no the album has lost its mojo */ + if (!$album) { + $album = T_('Unknown (Orphaned)'); + unset($album_year, $album_disk); + } + + // Remove the prefix so we can sort it correctly + $trimmed = Catalog::trim_prefix($album); + $album = $trimmed['string']; + $prefix = $trimmed['prefix']; + + // Check to see if we've seen this album before + if (isset(self::$albums[$album][$album_year][$album_disk][$mbid])) { + return self::$albums[$album][$album_year][$album_disk][$mbid]; + } + + /* Set up the Query */ + $sql = "SELECT `id` FROM `album` WHERE `name` = '$album'" . + " AND `disk`='$album_disk' AND `year`='$album_year'" . + " AND `mbid`" . ($mbid ? "='$mbid'" : ' IS NULL') . + " AND `prefix`" . ($prefix ? "='$prefix'" : ' IS NULL'); + + $db_results = Dba::read($sql); + + /* If it's found */ + if ($r = Dba::fetch_assoc($db_results)) { + $album_id = $r['id']; + + // If we don't have art put it in the 'needs me some + // art' array + $art = new Art($r['id'], 'album'); + $art->get_db(); + if (!$art->raw) { + $key = $r['id']; + self::$_art_albums[$key] = $key; + } + + } //if found + elseif (!$readonly) { // If not found, create + + $prefix = $prefix ? "'$prefix'" : 'NULL'; + $mbid = $mbid ? "'$mbid'" : 'NULL'; + + $sql = "INSERT INTO `album` (`name`, `prefix`,`year`,`disk`,`mbid`) " . + "VALUES ('$album',$prefix,'$album_year','$album_disk',$mbid)"; + $db_results = Dba::write($sql); + $album_id = Dba::insert_id(); + + if (!$db_results) { + debug_event('album',"Error Unable to insert Album:$album",'2'); + return false; + } + + // Add it to the I needs me some album art array + self::$_art_albums[$album_id] = $album_id; + + } //not found + else { + // readonly and not found + return false; + } + + // Save the cache + self::$albums[$album][$album_year][$album_disk][$mbid] = $album_id; + + return $album_id; + + } // check_album + + /** + * check_tag + * This checks the tag we've been passed (name) + * and sees if it exists, and if so if it's mapped + * to this object, this is only done for songs for now + */ + public static function check_tag($value,$object_id,$object_type='song') { + + $map_id = Tag::add($object_type,$object_id,$value,'0'); + + return $map_id; + + } // check_tag + + /** + * check_title + * this checks to make sure something is + * set on the title, if it isn't it looks at the + * filename and trys to set the title based on that + */ + public static function check_title($title,$file=0) { + + if (strlen(trim($title)) < 1) { + $title = Dba::escape($file); + } + + return $title; + + } // check_title + + /** + * insert_local_song + * Insert a song that isn't already in the database this + * function is in here so we don't have to create a song object + */ + public function insert_local_song($file,$file_info) { + + /* Create the vainfo object and get info */ + $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern); + $vainfo->get_info(); + + $key = vainfo::get_tag_type($vainfo->tags); + + /* Clean Up the tags */ + $results = vainfo::clean_tag_info($vainfo->tags,$key,$file); + + /* Set the vars here... so we don't have to do the '" . $blah['asd'] . "' */ + $title = Dba::escape($results['title']); + $artist = $results['artist']; + $album = $results['album']; + $bitrate = $results['bitrate']; + $rate = $results['rate']; + $mode = $results['mode']; + $size = $results['size']; + $song_time = $results['time']; + $track = $results['track']; + $track_mbid = $results['mb_trackid']; + $album_mbid = $results['mb_albumid']; + $artist_mbid= $results['mb_artistid']; + $disk = $results['disk']; + $year = $results['year']; + $comment = $results['comment']; + $tags = $results['genre']; // multiple genre support makes this an array + $current_time = time(); + $lyrics = ' '; + + /* + * We have the artist/genre/album name need to check it in the tables + * If found then add & return id, else return id + */ + $artist_id = self::check_artist($artist,$artist_mbid); + $album_id = self::check_album($album,$year,$disk,$album_mbid); + $title = self::check_title($title,$file); + $add_file = Dba::escape($file); + + $sql = "INSERT INTO `song` (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,addition_time,year,mbid)" . + " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$track_mbid')"; + $db_results = Dba::write($sql); + + if (!$db_results) { + debug_event('insert',"Unable to insert $file -- $sql" . Dba::error(),'5','ampache-catalog'); + Error::add('catalog_add', sprintf(T_('SQL Error Adding %s'), $file)); + } + + $song_id = Dba::insert_id(); + + // multiple genre support + foreach ($tags as $tag) { + $tag = trim($tag); + self::check_tag($tag,$song_id); + self::check_tag($tag,$album_id,'album'); + self::check_tag($tag,$artist_id,'artist'); + } + + + /* Add the EXT information */ + $sql = "INSERT INTO `song_data` (`song_id`,`comment`,`lyrics`) " . + " VALUES ('$song_id','$comment','$lyrics')"; + $db_results = Dba::write($sql); + + if (!$db_results) { + debug_event('insert',"Unable to insert EXT Info for $file -- $sql",'5','ampache-catalog'); + } + + } // insert_local_song + + /** + * insert_remote_song + * takes the information gotten from XML-RPC and + * inserts it into the local database. The filename + * ends up being the url. + */ + public function insert_remote_song($song) { + + /* Limitations: + * Missing Following Metadata + * Disk,Rate + */ + + // Strip the SSID off of the url, we will need to regenerate this every time + $url = preg_replace("/ssid=.*&/","",$song['url']); + $title = Dba::escape($song['title']); + $album = self::check_album($song['album'],$song['year'],null,$song['album_mbid']); + $artist = self::check_artist($song['artist'],$song['artist_mbid']); + $bitrate = Dba::escape($song['bitrate']); + $size = Dba::escape($song['size']); + $song_time = Dba::escape($song['time']); + $track = Dba::escape($song['track']); + $year = Dba::escape($song['year']); + $title = Dba::escape($song['title']); + $mbid = Dba::escape($song['mbid']); + $mode = Dba::escape($song['mode']); + $current_time = time(); + $catalog_id = Dba::escape($this->id); + + $sql = "INSERT INTO `song` (`file`,`catalog`,`album`,`artist`,`title`,`bitrate`,`rate`,`mode`,`size`,`time`,`track`,`addition_time`,`year`,`mbid`)" . + " VALUES ('$url','$catalog_id','$album','$artist','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$current_time','$year','$mbid')"; + $db_results = Dba::write($sql); + + if (!$db_results) { + debug_event('insert',"Unable to Add Remote $url -- $sql",'5','ampache-catalog'); + return false; + } + + // Weird to do this here, but we have the information - see if the album has art, if it doesn't then use the remote + // art url + $art = new Art($album, 'album'); + // If it doesn't have art... + if (!$art->get()) { + // Get the mime out + $get_vars = parse_url($song['art']); + $extension = substr($get_vars['query'],strlen($get_vars['query'])-3,3); + // Pull the image + $raw = Art::get_from_source( + array('url' => $song['art']), 'album'); + $inserted = $art->insert($raw,'image/' . $extension); + } + + return true; + + } // insert_remote_song + + /** + * insert_local_video + * This inserts a video file into the video file table the tag + * information we can get is super sketchy so it's kind of a crap shoot + * here + */ + public function insert_local_video($file,$filesize) { + + /* Create the vainfo object and get info */ + $vainfo = new vainfo($file,'','','',$this->sort_pattern,$this->rename_pattern); + $vainfo->get_info(); + + $tag_name = vainfo::get_tag_type($vainfo->tags); + $results = vainfo::clean_tag_info($vainfo->tags,$tag_name,$file); + + + $file = Dba::escape($file); + $catalog_id = Dba::escape($this->id); + $title = Dba::escape($results['title']); + $vcodec = $results['video_codec']; + $acodec = $results['audio_codec']; + $rezx = intval($results['resolution_x']); + $rezy = intval($results['resolution_y']); + $filesize = Dba::escape($filesize); + $time = Dba::escape($results['time']); + $mime = Dba::escape($results['mime']); + // UNUSED CURRENTLY + $comment = Dba::escape($results['comment']); + $year = Dba::escape($results['year']); + $disk = Dba::escape($results['disk']); + + $sql = "INSERT INTO `video` (`file`,`catalog`,`title`,`video_codec`,`audio_codec`,`resolution_x`,`resolution_y`,`size`,`time`,`mime`) " . + " VALUES ('$file','$catalog_id','$title','$vcodec','$acodec','$rezx','$rezy','$filesize','$time','$mime')"; + $db_results = Dba::write($sql); + + return true; + + } // insert_local_video + + /** + * check_remote_song + * checks to see if a remote song exists in the database or not + * if it find a song it returns the UID + */ + public function check_remote_song($url) { + + $url = Dba::escape($url); + + $sql = "SELECT `id` FROM `song` WHERE `file`='$url'"; + $db_results = Dba::read($sql); + + if ($results = Dba::fetch_assoc($db_results)) { + return $results['id']; + } + + return false; + + } // check_remote_song + + /** + * check_local_mp3 + * Checks the song to see if it's there already returns true if found, false if not + */ + public function check_local_mp3($full_file, $gather_type='') { + + $file_date = filemtime($full_file); + if ($file_date < $this->last_add) { + debug_event('Check','Skipping ' . $full_file . ' File modify time before last add run','3'); + return true; + } + + $full_file = Dba::escape($full_file); - $sql = "SELECT `id` FROM `song` WHERE `file` = '$full_file'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `song` WHERE `file` = '$full_file'"; + $db_results = Dba::read($sql); - //If it's found then return true - if (Dba::fetch_row($db_results)) { - return true; - } + //If it's found then return true + if (Dba::fetch_row($db_results)) { + return true; + } - return false; + return false; - } //check_local_mp3 + } //check_local_mp3 - /** - * import_m3u - * this takes m3u filename and then attempts to create a Public Playlist based on the filenames - * listed in the m3u - */ - public function import_m3u($filename) { + /** + * import_m3u + * this takes m3u filename and then attempts to create a Public Playlist based on the filenames + * listed in the m3u + */ + public function import_m3u($filename) { - $m3u_handle = fopen($filename,'r'); + $m3u_handle = fopen($filename,'r'); - $data = fread($m3u_handle,filesize($filename)); + $data = fread($m3u_handle,filesize($filename)); - $results = explode("\n",$data); + $results = explode("\n",$data); - $pattern = '/\.(' . Config::get('catalog_file_pattern') . ')$/i'; + $pattern = '/\.(' . Config::get('catalog_file_pattern') . ')$/i'; - // Foreach what we're able to pull out from the file - foreach ($results as $value) { + // Foreach what we're able to pull out from the file + foreach ($results as $value) { - // Remove extra whitespace - $value = trim($value); - if (preg_match($pattern,$value)) { + // Remove extra whitespace + $value = trim($value); + if (preg_match($pattern,$value)) { - /* Translate from \ to / so basename works */ - $value = str_replace("\\","/",$value); - $file = basename($value); + /* Translate from \ to / so basename works */ + $value = str_replace("\\","/",$value); + $file = basename($value); - /* Search for this filename, cause it's a audio file */ - $sql = "SELECT `id` FROM `song` WHERE `file` LIKE '%" . Dba::escape($file) . "'"; - $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + /* Search for this filename, cause it's a audio file */ + $sql = "SELECT `id` FROM `song` WHERE `file` LIKE '%" . Dba::escape($file) . "'"; + $db_results = Dba::read($sql); + $results = Dba::fetch_assoc($db_results); - if (isset($results['id'])) { $songs[] = $results['id']; } + if (isset($results['id'])) { $songs[] = $results['id']; } - } // if it's a file - // Check to see if it's a url from this ampache instance - elseif (substr($value,0,strlen(Config::get('web_path'))) == Config::get('web_path')) { - $song_id = intval(Song::parse_song_url($value)); + } // if it's a file + // Check to see if it's a url from this ampache instance + elseif (substr($value,0,strlen(Config::get('web_path'))) == Config::get('web_path')) { + $song_id = intval(Song::parse_song_url($value)); - $sql = "SELECT COUNT(*) FROM `song` WHERE `id`='$song_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT COUNT(*) FROM `song` WHERE `id`='$song_id'"; + $db_results = Dba::read($sql); - if (Dba::num_rows($db_results)) { - $songs[] = $song_id; - } + if (Dba::num_rows($db_results)) { + $songs[] = $song_id; + } - } // end if it's an http url + } // end if it's an http url - } // end foreach line + } // end foreach line - debug_event('m3u_parse', "Parsed $filename, found " . count($songs) . " songs", 5); - - if (count($songs)) { - $name = "M3U - " . basename($filename,'.m3u'); - $playlist_id = Playlist::create($name,'public'); - - if (!$playlist_id) { - return array( - 'success' => false, - 'error' => 'Failed to create playlist.', - ); - } - - /* Recreate the Playlist */ - $playlist = new Playlist($playlist_id); - $playlist->add_songs($songs, true); - - return array( - 'success' => true, - 'id' => $playlist_id, - 'count' => count($songs) - ); - } - - return array( - 'success' => false, - 'error' => 'No valid songs found in M3U.' - ); - - } // import_m3u - - /** - * delete - * Deletes the catalog and everything associated with it - * it takes the catalog id - */ - public static function delete($catalog_id) { - - $catalog_id = Dba::escape($catalog_id); - - // First remove the songs in this catalog - $sql = "DELETE FROM `song` WHERE `catalog` = '$catalog_id'"; - $db_results = Dba::write($sql); - - // Only if the previous one works do we go on - if (!$db_results) { return false; } - - $sql = "DELETE FROM `video` WHERE `catalog` = '$catalog_id'"; - $db_results = Dba::write($sql); - - if (!$db_results) { return false; } - - // Next Remove the Catalog Entry it's self - $sql = "DELETE FROM `catalog` WHERE `id` = '$catalog_id'"; - $db_results = Dba::write($sql); - - // Run the cleaners... - self::gc(); - - } // delete - - /** - * exports the catalog - * it exports all songs in the database to the given export type. - */ - public function export($type) { - - // Select all songs in catalog - if($this->id) { - $sql = 'SELECT `id` FROM `song` ' . - "WHERE `catalog`='$this->id' " . - 'ORDER BY `album`, `track`'; - } - else { - $sql = 'SELECT `id` FROM `song` ORDER BY `album`, `track`'; - } - $db_results = Dba::read($sql); - - switch ($type) { - case 'itunes': - echo xml_get_header('itunes'); - while ($results = Dba::fetch_assoc($db_results)) { - $song = new Song($results['id']); - $song->format(); - - $xml = array(); - $xml['key']= $results['id']; - $xml['dict']['Track ID']= intval($results['id']); - $xml['dict']['Name'] = $song->title; - $xml['dict']['Artist'] = $song->f_artist_full; - $xml['dict']['Album'] = $song->f_album_full; - $xml['dict']['Total Time'] = intval($song->time) * 1000; // iTunes uses milliseconds - $xml['dict']['Track Number'] = intval($song->track); - $xml['dict']['Year'] = intval($song->year); - $xml['dict']['Date Added'] = date("Y-m-d\TH:i:s\Z",$song->addition_time); - $xml['dict']['Bit Rate'] = intval($song->bitrate/1000); - $xml['dict']['Sample Rate'] = intval($song->rate); - $xml['dict']['Play Count'] = intval($song->played); - $xml['dict']['Track Type'] = "URL"; - $xml['dict']['Location'] = Song::play_url($song->id); - echo xml_from_array($xml, 1, 'itunes'); - // flush output buffer - } // while result - echo xml_get_footer('itunes'); - - break; - case 'csv': - echo "ID,Title,Artist,Album,Length,Track,Year,Date Added,Bitrate,Played,File\n"; - while ($results = Dba::fetch_assoc($db_results)) { - $song = new Song($results['id']); - $song->format(); - echo '"' . $song->id . '","' . - $song->title . '","' . - $song->f_artist_full . '","' . - $song->f_album_full .'","' . - $song->f_time . '","' . - $song->f_track . '","' . - $song->year .'","' . - date("Y-m-d\TH:i:s\Z", $song->addition_time) . '","' . - $song->f_bitrate .'","' . - $song->played . '","' . - $song->file . "\n"; - } - break; - } // end switch - - } // export + debug_event('m3u_parse', "Parsed $filename, found " . count($songs) . " songs", 5); + + if (count($songs)) { + $name = "M3U - " . basename($filename,'.m3u'); + $playlist_id = Playlist::create($name,'public'); + + if (!$playlist_id) { + return array( + 'success' => false, + 'error' => 'Failed to create playlist.', + ); + } + + /* Recreate the Playlist */ + $playlist = new Playlist($playlist_id); + $playlist->add_songs($songs, true); + + return array( + 'success' => true, + 'id' => $playlist_id, + 'count' => count($songs) + ); + } + + return array( + 'success' => false, + 'error' => 'No valid songs found in M3U.' + ); + + } // import_m3u + + /** + * delete + * Deletes the catalog and everything associated with it + * it takes the catalog id + */ + public static function delete($catalog_id) { + + $catalog_id = Dba::escape($catalog_id); + + // First remove the songs in this catalog + $sql = "DELETE FROM `song` WHERE `catalog` = '$catalog_id'"; + $db_results = Dba::write($sql); + + // Only if the previous one works do we go on + if (!$db_results) { return false; } + + $sql = "DELETE FROM `video` WHERE `catalog` = '$catalog_id'"; + $db_results = Dba::write($sql); + + if (!$db_results) { return false; } + + // Next Remove the Catalog Entry it's self + $sql = "DELETE FROM `catalog` WHERE `id` = '$catalog_id'"; + $db_results = Dba::write($sql); + + // Run the cleaners... + self::gc(); + + } // delete + + /** + * exports the catalog + * it exports all songs in the database to the given export type. + */ + public function export($type) { + + // Select all songs in catalog + if($this->id) { + $sql = 'SELECT `id` FROM `song` ' . + "WHERE `catalog`='$this->id' " . + 'ORDER BY `album`, `track`'; + } + else { + $sql = 'SELECT `id` FROM `song` ORDER BY `album`, `track`'; + } + $db_results = Dba::read($sql); + + switch ($type) { + case 'itunes': + echo xml_get_header('itunes'); + while ($results = Dba::fetch_assoc($db_results)) { + $song = new Song($results['id']); + $song->format(); + + $xml = array(); + $xml['key']= $results['id']; + $xml['dict']['Track ID']= intval($results['id']); + $xml['dict']['Name'] = $song->title; + $xml['dict']['Artist'] = $song->f_artist_full; + $xml['dict']['Album'] = $song->f_album_full; + $xml['dict']['Total Time'] = intval($song->time) * 1000; // iTunes uses milliseconds + $xml['dict']['Track Number'] = intval($song->track); + $xml['dict']['Year'] = intval($song->year); + $xml['dict']['Date Added'] = date("Y-m-d\TH:i:s\Z",$song->addition_time); + $xml['dict']['Bit Rate'] = intval($song->bitrate/1000); + $xml['dict']['Sample Rate'] = intval($song->rate); + $xml['dict']['Play Count'] = intval($song->played); + $xml['dict']['Track Type'] = "URL"; + $xml['dict']['Location'] = Song::play_url($song->id); + echo xml_from_array($xml, 1, 'itunes'); + // flush output buffer + } // while result + echo xml_get_footer('itunes'); + + break; + case 'csv': + echo "ID,Title,Artist,Album,Length,Track,Year,Date Added,Bitrate,Played,File\n"; + while ($results = Dba::fetch_assoc($db_results)) { + $song = new Song($results['id']); + $song->format(); + echo '"' . $song->id . '","' . + $song->title . '","' . + $song->f_artist_full . '","' . + $song->f_album_full .'","' . + $song->f_time . '","' . + $song->f_track . '","' . + $song->year .'","' . + date("Y-m-d\TH:i:s\Z", $song->addition_time) . '","' . + $song->f_bitrate .'","' . + $song->played . '","' . + $song->file . "\n"; + } + break; + } // end switch + + } // export } // end of catalog class diff --git a/lib/class/config.class.php b/lib/class/config.class.php index 5b325ff430..8412976030 100644 --- a/lib/class/config.class.php +++ b/lib/class/config.class.php @@ -1,5 +1,5 @@ $value) { - self::set($name,$value,$clobber); - } - - } // set_by_array + /** + * These are the settings for this specific class + * + * @var array + */ + private $_local = array(); + + /** + * These are the global settings they go where it goes + * + * @var array + */ + private static $_global = array(); + + /** + * constructor + * This is what is called when the class is loaded + */ + public function __construct() { + + // Rien a faire + + } // constructor + + /** + * get + * This checks to see if this is an instance or procedure + * call, procedure == global, instance == local + * + * @param string $name + * @return mixed array or null + */ + public static function get($name) { + + if (isset(self::$_global[$name])) { return self::$_global[$name]; } + else { return null; } + + } // get + + /** + * get_all + * This returns all of the current config variables as an array + * + * @return array + */ + public static function get_all() { + + return self::$_global; + + } // get_all + + /** + * set + * + * This sets config values. + * + * @param string $name Key name + * @param string $value Value name + * @param boolean $clobber Clobber flag true or false + * @return void + */ + public static function set($name, $value, $clobber = false) { + + if (isset(self::$_global[$name]) && !$clobber) { + debug_event('Config', "Tried to overwrite existing key $name without setting clobber", 5); + Error::add('Config Global', sprintf(T_('Trying to clobber \'%s\' without setting clobber'), $name)); + return false; + } + + self::$_global[$name] = $value; + + } // set + + /** + * set_by_array + * + * This is the same as the set function except it takes an array as + * input. + * + * @param array $array Array + * @param boolean $clobber Clobber flag true or false + */ + public static function set_by_array($array, $clobber = false) { + + foreach ($array as $name => $value) { + self::set($name,$value,$clobber); + } + + } // set_by_array } // end Config class ?> diff --git a/lib/class/core.class.php b/lib/class/core.class.php index b60339755d..55e594d5f1 100644 --- a/lib/class/core.class.php +++ b/lib/class/core.class.php @@ -1,5 +1,5 @@ $name, 'expire' => $expire); - debug_event('Core', "Registered $type form $name with SID $sid and expiration $expire ($window seconds from now)", 5); - - switch ($type) { - default: - case 'post': - $string = ''; - break; - case 'get': - $string = $sid; - break; - } // end switch on type - - return $string; - - } // form_register - - /** - * form_verify - * - * This takes a form name and then compares it with the posted sid, if - * they don't match then it returns false and doesn't let the person - * continue - */ - public static function form_verify($name, $type = 'post') { - switch ($type) { - case 'post': - $sid = $_POST['form_validation']; - break; - case 'get': - $sid = $_GET['form_validation']; - break; - case 'cookie': - $sid = $_COOKIE['form_validation']; - break; - case 'request': - $sid = $_REQUEST['form_validation']; - break; - } - - if (!isset($_SESSION['forms'][$sid])) { - debug_event('Core', "Form $sid not found in session, rejecting request", 2); - return false; - } - - $form = $_SESSION['forms'][$sid]; - unset($_SESSION['forms'][$sid]); - - if ($form['name'] == $name) { - debug_event('Core', "Verified SID $sid for $type form $name", 5); - if ($form['expire'] < time()) { - debug_event('Core', "Form $sid is expired, rejecting request", 2); - return false; - } - - return true; - } - - // OMG HAX0RZ - debug_event('Core', "$type form $sid failed consistency check, rejecting request", 2); - return false; - - } // form_verify - - /** - * image_dimensions - * This returns the dimensions of the passed song of the passed type - * returns an empty array if PHP-GD is not currently installed, returns - * false on error - */ - public static function image_dimensions($image_data) { - - if (!function_exists('ImageCreateFromString')) { return false; } - - $image = ImageCreateFromString($image_data); - - if (!$image) { return false; } - - $width = imagesx($image); - $height = imagesy($image); - - if (!$width || !$height) { return false; } - - return array('width'=>$width,'height'=>$height); - - } // image_dimensions + /** + * constructor + * This doesn't do anything + */ + private function __construct() { + + return false; + + } // construction + + /** + * autoload + * This function automatically loads any missing classes as they are + * needed so that we don't use a million include statements which load + * more than we need. + */ + public static function autoload($class) { + // Lowercase the class + $class = strtolower($class); + + $file = Config::get('prefix') . "/lib/class/$class.class.php"; + + // See if it exists + if (is_readable($file)) { + require $file; + if (is_callable($class . '::_auto_init')) { + $class::_auto_init(); + } + } + // Else log this as a fatal error + else { + debug_event('autoload', "'$class' not found!", 1); + } + } // autoload + + /** + * form_register + * This registers a form with a SID, inserts it into the session + * variables and then returns a string for use in the HTML form + */ + public static function form_register($name, $type = 'post') { + + // Make ourselves a nice little sid + $sid = md5(uniqid(rand(), true)); + $window = Config::get('session_length'); + $expire = time() + $window; + + // Register it + $_SESSION['forms'][$sid] = array('name' => $name, 'expire' => $expire); + debug_event('Core', "Registered $type form $name with SID $sid and expiration $expire ($window seconds from now)", 5); + + switch ($type) { + default: + case 'post': + $string = ''; + break; + case 'get': + $string = $sid; + break; + } // end switch on type + + return $string; + + } // form_register + + /** + * form_verify + * + * This takes a form name and then compares it with the posted sid, if + * they don't match then it returns false and doesn't let the person + * continue + */ + public static function form_verify($name, $type = 'post') { + switch ($type) { + case 'post': + $sid = $_POST['form_validation']; + break; + case 'get': + $sid = $_GET['form_validation']; + break; + case 'cookie': + $sid = $_COOKIE['form_validation']; + break; + case 'request': + $sid = $_REQUEST['form_validation']; + break; + } + + if (!isset($_SESSION['forms'][$sid])) { + debug_event('Core', "Form $sid not found in session, rejecting request", 2); + return false; + } + + $form = $_SESSION['forms'][$sid]; + unset($_SESSION['forms'][$sid]); + + if ($form['name'] == $name) { + debug_event('Core', "Verified SID $sid for $type form $name", 5); + if ($form['expire'] < time()) { + debug_event('Core', "Form $sid is expired, rejecting request", 2); + return false; + } + + return true; + } + + // OMG HAX0RZ + debug_event('Core', "$type form $sid failed consistency check, rejecting request", 2); + return false; + + } // form_verify + + /** + * image_dimensions + * This returns the dimensions of the passed song of the passed type + * returns an empty array if PHP-GD is not currently installed, returns + * false on error + */ + public static function image_dimensions($image_data) { + + if (!function_exists('ImageCreateFromString')) { return false; } + + $image = ImageCreateFromString($image_data); + + if (!$image) { return false; } + + $width = imagesx($image); + $height = imagesy($image); + + if (!$width || !$height) { return false; } + + return array('width'=>$width,'height'=>$height); + + } // image_dimensions } // Core ?> diff --git a/lib/class/database_object.abstract.php b/lib/class/database_object.abstract.php index 535a83d1d6..dc9872cba8 100644 --- a/lib/class/database_object.abstract.php +++ b/lib/class/database_object.abstract.php @@ -1,5 +1,5 @@ 0); - - private static $_sql; - private static $config; - - /** - * constructor - * This does nothing with the DBA class - */ - private function __construct() { - - // Rien a faire - - } // construct - - /** - * query - * This is the meat of the class this does a query, it emulates - * The mysql_query function - */ - public static function query($sql) { - - // Run the query - $resource = mysql_query($sql,self::dbh()); - debug_event('Query',$sql,'6'); - - // Save the query, to make debug easier - self::$_sql = $sql; - self::$stats['query']++; + public static $stats = array('query'=>0); + + private static $_sql; + private static $config; + + /** + * constructor + * This does nothing with the DBA class + */ + private function __construct() { + + // Rien a faire + + } // construct + + /** + * query + * This is the meat of the class this does a query, it emulates + * The mysql_query function + */ + public static function query($sql) { + + // Run the query + $resource = mysql_query($sql,self::dbh()); + debug_event('Query',$sql,'6'); + + // Save the query, to make debug easier + self::$_sql = $sql; + self::$stats['query']++; - // Do a little error checking here and try to recover from some forms of failure - if (!$resource) { - switch (mysql_errno(self::dbh())) { - case '2006': - case '2013': - case '2055': - debug_event('DBH','Lost connection to database server, trying to re-connect and hope nobody noticed','1'); - self::disconnect(); - // Try again - $resource = mysql_query($sql,self::dbh()); - break; - default: - debug_event('DBH',mysql_error(self::dbh()) . ' ['. mysql_errno(self::dbh()) . ']','1'); - break; - } // end switch on error # - } // if failed query - - return $resource; - - } // query - - /** - * read - * This is a wrapper for query, it's so that in the future if we ever wanted - * to split reads and writes we could - */ - public static function read($sql) { - - return self::query($sql); - - } // read - - /** - * write - * This is a wrapper for a write query, it is so that we can split out reads and - * writes if we want to - */ - public static function write($sql) { - - return self::query($sql); - - } // write - - /** - * escape - * This runs a escape on a variable so that it can be safely inserted - * into the sql - */ - public static function escape($var) { - - $string = mysql_real_escape_string($var,self::dbh()); - - return $string; - - } // escape - - /** - * fetch_assoc - * This emulates the mysql_fetch_assoc and takes a resource result - * we force it to always return an array, albeit an empty one - * The optional finish parameter affects whether we automatically clean - * up the result set after the last row is read. - */ - public static function fetch_assoc($resource, $finish = true) { - - $result = mysql_fetch_assoc($resource); - - if (!$result) { - if ($finish) { - self::finish($resource); - } - return array(); - } - - return $result; - - } // fetch_assoc - - /** - * fetch_row - * This emulates the mysql_fetch_row and takes a resource result - * we force it to always return an array, albeit an empty one - * The optional finish parameter affects whether we automatically clean - * up the result set after the last row is read. - */ - public static function fetch_row($resource, $finish = true) { - - $result = mysql_fetch_row($resource); - - if (!$result) { - if ($finish) { - self::finish($resource); - } - return array(); - } - - return $result; - - } // fetch_row - - /** - * num_rows - * This emulates the mysql_num_rows function which is really - * just a count of rows returned by our select statement, this - * doesn't work for updates or inserts - */ - public static function num_rows($resource) { - if ($resource) { - $result = mysql_num_rows($resource); - if ($result) { - return $result; - } - } - - return 0; - } // num_rows - - /** - * seek - * This resets the row pointer to the specified position - */ - public static function seek($resource, $row) { - return mysql_data_seek($resource, $row); - } - - /** - * finish - * This closes a result handle and clears the memory associated with it - */ - public static function finish($resource) { - - // Clear the result memory - mysql_free_result($resource); - - } // finish - - /** - * affected_rows - * This emulates the mysql_affected_rows function - */ - public static function affected_rows($resource) { - - $result = mysql_affected_rows($resource); - - if (!$result) { - return '0'; - } - - return $result; - - } // affected_rows - - /** - * _connect - * This connects to the database, used by the DBH function - */ - private static function _connect() { - - $username = Config::get('database_username'); - $hostname = Config::get('database_hostname'); - $password = Config::get('database_password'); - - $dbh = mysql_connect($hostname, $username, $password); - if (!$dbh) { - debug_event('Database', 'Unable to connect to database: ' . mysql_error(), 1); - return null; - } - - return $dbh; - } // _connect - - private static function _setup_dbh($dbh, $database) { - $data = self::translate_to_mysqlcharset(Config::get('site_charset')); - - if (function_exists('mysql_set_charset')) { - if (!$charset = mysql_set_charset($data['charset'], $dbh)) { - debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ', this may cause issues...', 1); - } - } - else { - $sql = "SET NAMES " . mysql_real_escape_string($data['charset']); - $charset = mysql_query($sql,$dbh); - if ($error = mysql_error($dbh)) { - debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ' using SET NAMES, this may cause issues: ' . $error, 1); - } - - } - - $select_db = mysql_select_db($database, $dbh); - if (!$select_db) { - debug_event('Database', 'Unable to select database ' . $database . ': ' . mysql_error(), 1); - } - - if (Config::get('sql_profiling')) { - mysql_query('set profiling=1', $dbh); - mysql_query('set profiling_history_size=50', $dbh); - mysql_query('set query_cache_type=0', $dbh); - } - } // _select_db - - /** - * check_database - * - * Make sure that we can connect to the database - */ - public static function check_database() { - - $dbh = self::_connect(); - - if (!is_resource($dbh)) { - return false; - } - - mysql_close($dbh); - return true; - - } // check_database - - public static function check_database_exists() { - $dbh = self::_connect(); - $select = mysql_select_db(Config::get('database_name'), $dbh); - mysql_close($dbh); - return $select; - } - - /** - * check_database_inserted - * checks to make sure that you have inserted the database - * and that the user you are using has access to it - */ - public static function check_database_inserted() { - - $sql = "DESCRIBE session"; - $db_results = Dba::read($sql); - - if (!$db_results) { - return false; - } - - // Make sure the whole table is there - if (Dba::num_rows($db_results) != '7') { - return false; - } - - return true; - - } // check_database_inserted - - public static function get_client_info() { - return mysql_get_client_info(); - } - - /** - * show_profile - * This function is used for debug, helps with profiling - */ - public static function show_profile() { - - if (Config::get('sql_profiling')) { - print '
Profiling data:
'; - $res = Dba::read('show profiles'); - print ''; - while ($r = Dba::fetch_row($res)) { - print ''; - } - print '
' . implode('', $r) . '
'; - } - } // show_profile - - /** - * dbh - * This is called by the class to return the database handle - * for the specified database, if none is found it connects - */ - public static function dbh($database='') { - - if (!$database) { - $database = Config::get('database_name'); - } - - // Assign the Handle name that we are going to store - $handle = 'dbh_' . $database; - - if (!is_resource(Config::get($handle))) { - $dbh = self::_connect(); - self::_setup_dbh($dbh, $database); - Config::set($handle, $dbh, true); - return $dbh; - } - else { - return Config::get($handle); - } - - - } // dbh - - /** - * disconnect - * This nukes the dbh connection based, this isn't used very often... - */ - public static function disconnect($database='') { - - if (!$database) { - $database = Config::get('database_name'); - } - - $handle = 'dbh_' . $database; - - // Try to close it correctly - mysql_close(Config::get($handle)); - - // Nuke it - Config::set($handle, false, true); - - return true; - - } // disconnect - - /** - * insert_id - * This emulates the mysql_insert_id function, it takes - * an optional database target - */ - public static function insert_id() { - - $id = mysql_insert_id(self::dbh()); - return $id; - - } // insert_id - - /** - * error - * this returns the error of the db - */ - public static function error() { - - return mysql_error(); - - } // error - - /** - * translate_to_mysqlcharset - * This translates the specified charset to a mysqlcharset, stupid ass mysql - * demands that it's charset list is different! - */ - public static function translate_to_mysqlcharset($charset) { - - // MySQL translte real charset names into fancy smancy MySQL land names - switch (strtoupper($charset)) { - case 'CP1250': - case 'WINDOWS-1250': - $target_charset = 'cp1250'; - $target_collation = 'cp1250_general_ci'; - break; - case 'ISO-8859': - case 'ISO-8859-2': - $target_charset = 'latin2'; - $target_collation = 'latin2_general_ci'; - break; - case 'ISO-8859-1': - case 'CP1252': - case 'WINDOWS-1252': - $target_charset = 'latin1'; - $target_collation = 'latin1_general_ci'; - break; - case 'EUC-KR': - $target_charset = 'euckr'; - $target_collation = 'euckr_korean_ci'; - break; - case 'CP932': - $target_charset = 'sjis'; - $target_collation = 'sjis_japanese_ci'; - break; - case 'KOI8-U': - $target_charset = 'koi8u'; - $target_collation = 'koi8u_general_ci'; - break; - case 'KOI8-R': - $target_charset = 'koi8r'; - $target_collation = 'koi8r_general_ci'; - break; - default; - case 'UTF-8': - $target_charset = 'utf8'; - $target_collation = 'utf8_unicode_ci'; - break; - } // end mysql charset translation - - return array('charset'=>$target_charset,'collation'=>$target_collation); - - } // translate_to_mysqlcharset - - /** - * reset_db_charset - * This cruises through the database and trys to set the charset to the current - * site charset, this is an admin function that can be run by an administrator - * this can mess up data if you switch between charsets that are not overlapping - * a catalog verify must be re-run to correct them - */ - public static function reset_db_charset() { - - $translated_charset = self::translate_to_mysqlcharset(Config::get('site_charset')); - $target_charset = $translated_charset['charset']; - $target_collation = $translated_charset['collation']; - - // Alter the charset for the entire database - $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; - $db_results = Dba::write($sql); - - $sql = "SHOW TABLES"; - $db_results = Dba::read($sql); - - // Go through the tables! - while ($row = Dba::fetch_row($db_results)) { - $sql = "DESCRIBE `" . $row['0'] . "`"; - $describe_results = Dba::read($sql); - - // Change the tables default charset and colliation - $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; - $alter_table = Dba::write($sql); - - // Itterate through the columns of the table - while ($table = Dba::fetch_assoc($describe_results)) { - if ( - (strpos($table['Type'], 'varchar') !== false) || - (strpos($table['Type'], 'enum') !== false) || - (strpos($table['Table'],'text') !== false)) { - $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset; - $charset_results = Dba::write($sql); - if (!$charset_results) { - debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3'); - } // if it fails - } // if its a varchar - } // end columns - - } // end tables - - - } // reset_db_charset - - /** - * optimize_tables - * - * This runs an optimize on the tables and updates the stats to improve - * join speed. - * This can be slow, but is a good idea to do from time to time. We do - * it in case the dba isn't doing it... which we're going to assume they - * aren't. - */ - public static function optimize_tables() { - $sql = "SHOW TABLES"; - $db_results = Dba::read($sql); - - while($row = Dba::fetch_row($db_results)) { - $sql = "OPTIMIZE TABLE `" . $row[0] . "`"; - $db_results_inner = Dba::write($sql); - - $sql = "ANALYZE TABLE `" . $row[0] . "`"; - $db_results_inner = Dba::write($sql); - } - } + // Do a little error checking here and try to recover from some forms of failure + if (!$resource) { + switch (mysql_errno(self::dbh())) { + case '2006': + case '2013': + case '2055': + debug_event('DBH','Lost connection to database server, trying to re-connect and hope nobody noticed','1'); + self::disconnect(); + // Try again + $resource = mysql_query($sql,self::dbh()); + break; + default: + debug_event('DBH',mysql_error(self::dbh()) . ' ['. mysql_errno(self::dbh()) . ']','1'); + break; + } // end switch on error # + } // if failed query + + return $resource; + + } // query + + /** + * read + * This is a wrapper for query, it's so that in the future if we ever wanted + * to split reads and writes we could + */ + public static function read($sql) { + + return self::query($sql); + + } // read + + /** + * write + * This is a wrapper for a write query, it is so that we can split out reads and + * writes if we want to + */ + public static function write($sql) { + + return self::query($sql); + + } // write + + /** + * escape + * This runs a escape on a variable so that it can be safely inserted + * into the sql + */ + public static function escape($var) { + + $string = mysql_real_escape_string($var,self::dbh()); + + return $string; + + } // escape + + /** + * fetch_assoc + * This emulates the mysql_fetch_assoc and takes a resource result + * we force it to always return an array, albeit an empty one + * The optional finish parameter affects whether we automatically clean + * up the result set after the last row is read. + */ + public static function fetch_assoc($resource, $finish = true) { + + $result = mysql_fetch_assoc($resource); + + if (!$result) { + if ($finish) { + self::finish($resource); + } + return array(); + } + + return $result; + + } // fetch_assoc + + /** + * fetch_row + * This emulates the mysql_fetch_row and takes a resource result + * we force it to always return an array, albeit an empty one + * The optional finish parameter affects whether we automatically clean + * up the result set after the last row is read. + */ + public static function fetch_row($resource, $finish = true) { + + $result = mysql_fetch_row($resource); + + if (!$result) { + if ($finish) { + self::finish($resource); + } + return array(); + } + + return $result; + + } // fetch_row + + /** + * num_rows + * This emulates the mysql_num_rows function which is really + * just a count of rows returned by our select statement, this + * doesn't work for updates or inserts + */ + public static function num_rows($resource) { + if ($resource) { + $result = mysql_num_rows($resource); + if ($result) { + return $result; + } + } + + return 0; + } // num_rows + + /** + * seek + * This resets the row pointer to the specified position + */ + public static function seek($resource, $row) { + return mysql_data_seek($resource, $row); + } + + /** + * finish + * This closes a result handle and clears the memory associated with it + */ + public static function finish($resource) { + + // Clear the result memory + mysql_free_result($resource); + + } // finish + + /** + * affected_rows + * This emulates the mysql_affected_rows function + */ + public static function affected_rows($resource) { + + $result = mysql_affected_rows($resource); + + if (!$result) { + return '0'; + } + + return $result; + + } // affected_rows + + /** + * _connect + * This connects to the database, used by the DBH function + */ + private static function _connect() { + + $username = Config::get('database_username'); + $hostname = Config::get('database_hostname'); + $password = Config::get('database_password'); + + $dbh = mysql_connect($hostname, $username, $password); + if (!$dbh) { + debug_event('Database', 'Unable to connect to database: ' . mysql_error(), 1); + return null; + } + + return $dbh; + } // _connect + + private static function _setup_dbh($dbh, $database) { + $data = self::translate_to_mysqlcharset(Config::get('site_charset')); + + if (function_exists('mysql_set_charset')) { + if (!$charset = mysql_set_charset($data['charset'], $dbh)) { + debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ', this may cause issues...', 1); + } + } + else { + $sql = "SET NAMES " . mysql_real_escape_string($data['charset']); + $charset = mysql_query($sql,$dbh); + if ($error = mysql_error($dbh)) { + debug_event('Database', 'Unable to set MySQL connection charset to ' . $data['charset'] . ' using SET NAMES, this may cause issues: ' . $error, 1); + } + + } + + $select_db = mysql_select_db($database, $dbh); + if (!$select_db) { + debug_event('Database', 'Unable to select database ' . $database . ': ' . mysql_error(), 1); + } + + if (Config::get('sql_profiling')) { + mysql_query('set profiling=1', $dbh); + mysql_query('set profiling_history_size=50', $dbh); + mysql_query('set query_cache_type=0', $dbh); + } + } // _select_db + + /** + * check_database + * + * Make sure that we can connect to the database + */ + public static function check_database() { + + $dbh = self::_connect(); + + if (!is_resource($dbh)) { + return false; + } + + mysql_close($dbh); + return true; + + } // check_database + + public static function check_database_exists() { + $dbh = self::_connect(); + $select = mysql_select_db(Config::get('database_name'), $dbh); + mysql_close($dbh); + return $select; + } + + /** + * check_database_inserted + * checks to make sure that you have inserted the database + * and that the user you are using has access to it + */ + public static function check_database_inserted() { + + $sql = "DESCRIBE session"; + $db_results = Dba::read($sql); + + if (!$db_results) { + return false; + } + + // Make sure the whole table is there + if (Dba::num_rows($db_results) != '7') { + return false; + } + + return true; + + } // check_database_inserted + + public static function get_client_info() { + return mysql_get_client_info(); + } + + /** + * show_profile + * This function is used for debug, helps with profiling + */ + public static function show_profile() { + + if (Config::get('sql_profiling')) { + print '
Profiling data:
'; + $res = Dba::read('show profiles'); + print ''; + while ($r = Dba::fetch_row($res)) { + print ''; + } + print '
' . implode('', $r) . '
'; + } + } // show_profile + + /** + * dbh + * This is called by the class to return the database handle + * for the specified database, if none is found it connects + */ + public static function dbh($database='') { + + if (!$database) { + $database = Config::get('database_name'); + } + + // Assign the Handle name that we are going to store + $handle = 'dbh_' . $database; + + if (!is_resource(Config::get($handle))) { + $dbh = self::_connect(); + self::_setup_dbh($dbh, $database); + Config::set($handle, $dbh, true); + return $dbh; + } + else { + return Config::get($handle); + } + + + } // dbh + + /** + * disconnect + * This nukes the dbh connection based, this isn't used very often... + */ + public static function disconnect($database='') { + + if (!$database) { + $database = Config::get('database_name'); + } + + $handle = 'dbh_' . $database; + + // Try to close it correctly + mysql_close(Config::get($handle)); + + // Nuke it + Config::set($handle, false, true); + + return true; + + } // disconnect + + /** + * insert_id + * This emulates the mysql_insert_id function, it takes + * an optional database target + */ + public static function insert_id() { + + $id = mysql_insert_id(self::dbh()); + return $id; + + } // insert_id + + /** + * error + * this returns the error of the db + */ + public static function error() { + + return mysql_error(); + + } // error + + /** + * translate_to_mysqlcharset + * This translates the specified charset to a mysqlcharset, stupid ass mysql + * demands that it's charset list is different! + */ + public static function translate_to_mysqlcharset($charset) { + + // MySQL translte real charset names into fancy smancy MySQL land names + switch (strtoupper($charset)) { + case 'CP1250': + case 'WINDOWS-1250': + $target_charset = 'cp1250'; + $target_collation = 'cp1250_general_ci'; + break; + case 'ISO-8859': + case 'ISO-8859-2': + $target_charset = 'latin2'; + $target_collation = 'latin2_general_ci'; + break; + case 'ISO-8859-1': + case 'CP1252': + case 'WINDOWS-1252': + $target_charset = 'latin1'; + $target_collation = 'latin1_general_ci'; + break; + case 'EUC-KR': + $target_charset = 'euckr'; + $target_collation = 'euckr_korean_ci'; + break; + case 'CP932': + $target_charset = 'sjis'; + $target_collation = 'sjis_japanese_ci'; + break; + case 'KOI8-U': + $target_charset = 'koi8u'; + $target_collation = 'koi8u_general_ci'; + break; + case 'KOI8-R': + $target_charset = 'koi8r'; + $target_collation = 'koi8r_general_ci'; + break; + default; + case 'UTF-8': + $target_charset = 'utf8'; + $target_collation = 'utf8_unicode_ci'; + break; + } // end mysql charset translation + + return array('charset'=>$target_charset,'collation'=>$target_collation); + + } // translate_to_mysqlcharset + + /** + * reset_db_charset + * This cruises through the database and trys to set the charset to the current + * site charset, this is an admin function that can be run by an administrator + * this can mess up data if you switch between charsets that are not overlapping + * a catalog verify must be re-run to correct them + */ + public static function reset_db_charset() { + + $translated_charset = self::translate_to_mysqlcharset(Config::get('site_charset')); + $target_charset = $translated_charset['charset']; + $target_collation = $translated_charset['collation']; + + // Alter the charset for the entire database + $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; + $db_results = Dba::write($sql); + + $sql = "SHOW TABLES"; + $db_results = Dba::read($sql); + + // Go through the tables! + while ($row = Dba::fetch_row($db_results)) { + $sql = "DESCRIBE `" . $row['0'] . "`"; + $describe_results = Dba::read($sql); + + // Change the tables default charset and colliation + $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; + $alter_table = Dba::write($sql); + + // Itterate through the columns of the table + while ($table = Dba::fetch_assoc($describe_results)) { + if ( + (strpos($table['Type'], 'varchar') !== false) || + (strpos($table['Type'], 'enum') !== false) || + (strpos($table['Table'],'text') !== false)) { + $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset; + $charset_results = Dba::write($sql); + if (!$charset_results) { + debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3'); + } // if it fails + } // if its a varchar + } // end columns + + } // end tables + + + } // reset_db_charset + + /** + * optimize_tables + * + * This runs an optimize on the tables and updates the stats to improve + * join speed. + * This can be slow, but is a good idea to do from time to time. We do + * it in case the dba isn't doing it... which we're going to assume they + * aren't. + */ + public static function optimize_tables() { + $sql = "SHOW TABLES"; + $db_results = Dba::read($sql); + + while($row = Dba::fetch_row($db_results)) { + $sql = "OPTIMIZE TABLE `" . $row[0] . "`"; + $db_results_inner = Dba::write($sql); + + $sql = "ANALYZE TABLE `" . $row[0] . "`"; + $db_results_inner = Dba::write($sql); + } + } } // dba class diff --git a/lib/class/democratic.class.php b/lib/class/democratic.class.php index 0e4fadbb88..31913a0765 100644 --- a/lib/class/democratic.class.php +++ b/lib/class/democratic.class.php @@ -1,5 +1,5 @@ get_info($id); + $info = $this->get_info($id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } + foreach ($info as $key=>$value) { + $this->$key = $value; + } - } // constructor + } // constructor - /** - * build_vote_cache - * This builds a vote cache of the objects we've got in the playlist - */ - public static function build_vote_cache($ids) { + /** + * build_vote_cache + * This builds a vote cache of the objects we've got in the playlist + */ + public static function build_vote_cache($ids) { - if (!is_array($ids) || !count($ids)) { return false; } + if (!is_array($ids) || !count($ids)) { return false; } - $idlist = '(' . implode(',', $ids) . ')'; + $idlist = '(' . implode(',', $ids) . ')'; - $sql = 'SELECT `object_id`, COUNT(`user`) AS `count` ' . - 'FROM `user_vote` ' . - "WHERE `object_id` IN $idlist GROUP BY `object_id`"; + $sql = 'SELECT `object_id`, COUNT(`user`) AS `count` ' . + 'FROM `user_vote` ' . + "WHERE `object_id` IN $idlist GROUP BY `object_id`"; - $db_results = Dba::read($sql); + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('democratic_vote', $row['object_id'], $row['count']); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('democratic_vote', $row['object_id'], $row['count']); + } - return true; + return true; - } // build_vote_cache + } // build_vote_cache - /** - * is_enabled - * This function just returns true / false if the current democratic - * playlist is currently enabled / configured - */ - public function is_enabled() { + /** + * is_enabled + * This function just returns true / false if the current democratic + * playlist is currently enabled / configured + */ + public function is_enabled() { - if ($this->tmp_playlist) { return true; } + if ($this->tmp_playlist) { return true; } - return false; + return false; - } // is_enabled + } // is_enabled - /** - * set_parent - * This returns the Tmp_Playlist for this democratic play instance - */ - public function set_parent() { + /** + * set_parent + * This returns the Tmp_Playlist for this democratic play instance + */ + public function set_parent() { - $demo_id = Dba::escape($this->id); + $demo_id = Dba::escape($this->id); - $sql = "SELECT * FROM `tmp_playlist` WHERE `session`='$demo_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `tmp_playlist` WHERE `session`='$demo_id'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - $this->tmp_playlist = $row['id']; + $this->tmp_playlist = $row['id']; - } // set_parent + } // set_parent - /** - * set_user_preferences - * This sets up a (or all) user(s) to use democratic play. This sets - * their play method and playlist method (clear on send) If no user is - * passed it does it for everyone and also locks down the ability to - * change to admins only - */ - public static function set_user_preferences($user = null) { + /** + * set_user_preferences + * This sets up a (or all) user(s) to use democratic play. This sets + * their play method and playlist method (clear on send) If no user is + * passed it does it for everyone and also locks down the ability to + * change to admins only + */ + public static function set_user_preferences($user = null) { - //FIXME: Code in single user stuff + //FIXME: Code in single user stuff - $preference_id = Preference::id_from_name('play_type'); - Preference::update_level($preference_id,'75'); - Preference::update_all($preference_id,'democratic'); + $preference_id = Preference::id_from_name('play_type'); + Preference::update_level($preference_id,'75'); + Preference::update_all($preference_id,'democratic'); - $allow_demo = Preference::id_from_name('allow_democratic_playback'); - Preference::update_all($allow_demo,'1'); - - $play_method = Preference::id_from_name('playlist_method'); - Preference::update_all($play_method,'clear'); - - return true; + $allow_demo = Preference::id_from_name('allow_democratic_playback'); + Preference::update_all($allow_demo,'1'); + + $play_method = Preference::id_from_name('playlist_method'); + Preference::update_all($play_method,'clear'); + + return true; - } // set_user_preferences + } // set_user_preferences - /** - * format - * This makes the variables all purrty so that they can be displayed - */ - public function format() { + /** + * format + * This makes the variables all purrty so that they can be displayed + */ + public function format() { - $this->f_cooldown = $this->cooldown . ' ' . T_('minutes'); - $this->f_primary = $this->primary ? T_('Primary') : ''; + $this->f_cooldown = $this->cooldown . ' ' . T_('minutes'); + $this->f_primary = $this->primary ? T_('Primary') : ''; - switch ($this->level) { - case '5': - $this->f_level = T_('Guest'); - break; - case '25': - $this->f_level = T_('User'); - break; - case '50': - $this->f_level = T_('Content Manager'); - break; - case '75': - $this->f_level = T_('Catalog Manager'); - break; - case '100': - $this->f_level = T_('Admin'); - break; - } + switch ($this->level) { + case '5': + $this->f_level = T_('Guest'); + break; + case '25': + $this->f_level = T_('User'); + break; + case '50': + $this->f_level = T_('Content Manager'); + break; + case '75': + $this->f_level = T_('Catalog Manager'); + break; + case '100': + $this->f_level = T_('Admin'); + break; + } - } // format + } // format - /** - * get_playlists - * This returns all of the current valid 'Democratic' Playlists - * that have been created. - */ - public static function get_playlists() { + /** + * get_playlists + * This returns all of the current valid 'Democratic' Playlists + * that have been created. + */ + public static function get_playlists() { - $sql = "SELECT `id` FROM `democratic` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `democratic` ORDER BY `name`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_playlists + } // get_playlists - /** - * get_current_playlist - * This returns the curren users current playlist, or if specified - * this current playlist of the user - */ - public static function get_current_playlist() { - - $democratic_id = Config::get('democratic_id'); - - if (!$democratic_id) { - $level = Dba::escape($GLOBALS['user']->access); - $sql = "SELECT `id` FROM `democratic` WHERE `level` <= '$level' " . - " ORDER BY `level` DESC,`primary` DESC"; - $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); - $democratic_id = $row['id']; - } - - $object = new Democratic($democratic_id); - - return $object; - - } // get_current_playlist - - /** - * get_items - * This returns a sorted array of all object_ids in this Tmp_Playlist. - * The array is multidimensional; the inner array needs to contain the - * keys 'id', 'object_type' and 'object_id'. - * - * Sorting is highest to lowest vote count, then by oldest to newest - * vote activity. - */ - public function get_items($limit = null) { - - $sql = 'SELECT `tmp_playlist_data`.`object_type`, ' . - '`tmp_playlist_data`.`object_id`, ' . - '`tmp_playlist_data`.`id` ' . - 'FROM `tmp_playlist_data` INNER JOIN `user_vote` ' . - 'ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` ' . - "WHERE `tmp_playlist_data`.`tmp_playlist` = '" . - Dba::escape($this->tmp_playlist) . "' " . - 'GROUP BY 1, 2 ' . - 'ORDER BY COUNT(*) DESC, MAX(`user_vote`.`date`) '; - - if ($limit) { - $sql .= 'LIMIT ' . intval($limit); - } - - $db_results = Dba::read($sql); - - $results = array(); - - while ($results[] = Dba::fetch_assoc($db_results)) { - // Nada - } - - return $results; - - } // get_items - - /** - * play_url - * This returns the special play URL for democratic play, only open to ADMINs - */ - public function play_url() { - - $link = Stream::get_base_url() . 'uid=' . scrub_out($GLOBALS['user']->id) . '&demo_id=' . scrub_out($this->id); - - return $link; - - } // play_url - - /** - * get_next_object - * This returns the next object in the tmp_playlist. - * Most of the time this will just be the top entry, but if there is a - * base_playlist and no items in the playlist then it returns a random - * entry from the base_playlist - */ - public function get_next_object($offset = 0) { - - // FIXME: Shouldn't this return object_type? - - $offset = intval($offset); - - $items = $this->get_items($offset + 1); - - if (count($items) > $offset) { - return $items[$offset]['object_id']; - } - - - // If nothing was found and this is a voting playlist then get - // from base_playlist - if ($this->base_playlist) { - $base_playlist = new Playlist($this->base_playlist); - $data = $base_playlist->get_random_items(1); - return $data[0]['object_id']; - } - else { - $sql = "SELECT `id` FROM `song` WHERE `enabled`='1' ORDER BY RAND() LIMIT 1"; - $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); - return $results['id']; - } - - return null; - - } // get_next_object - - /** - * get_uid_from_object_id - * This takes an object_id and an object type and returns the ID for the row - */ - public function get_uid_from_object_id($object_id, $object_type = 'song') { - - $object_id = Dba::escape($object_id); - $object_type = Dba::escape($object_type); - $tmp_id = Dba::escape($this->tmp_playlist); - - $sql = 'SELECT `id` FROM `tmp_playlist_data` ' . - "WHERE `object_type`='$object_type' AND " . - "`tmp_playlist`='$tmp_id' AND `object_id`='$object_id'"; - $db_results = Dba::read($sql); - - $row = Dba::fetch_assoc($db_results); - - return $row['id']; - - } // get_uid_from_object_id - - /** - * get_cool_songs - * This returns all of the song_ids for songs that have happened within - * the last 'cooldown' for this user. - */ - public function get_cool_songs() { - - // Convert cooldown time to a timestamp in the past - $cool_time = time() - ($this->cooldown * 60); - - $song_ids = Stats::get_object_history($GLOBALS['user']->id, $cool_time); - - return $song_ids; - - } // get_cool_songs - - /** - * vote - * This function is called by users to vote on a system wide playlist - * This adds the specified objects to the tmp_playlist and adds a 'vote' - * by this user, naturally it checks to make sure that the user hasn't - * already voted on any of these objects - */ - public function add_vote($items) { - - /* Itterate through the objects if no vote, add to playlist and vote */ - foreach ($items as $element) { - $type = array_shift($element); - $object_id = array_shift($element); - if (!$this->has_vote($object_id, $type)) { - $this->_add_vote($object_id, $type); - } - } // end foreach - - } // vote - - /** - * has_vote - * This checks to see if the current user has already voted on this object - */ - public function has_vote($object_id, $type = 'song') { - - $tmp_id = Dba::escape($this->tmp_playlist); - $object_id = Dba::escape($object_id); - $type = Dba::escape($type); - $user_id = Dba::escape($GLOBALS['user']->id); - - /* Query vote table */ - $sql = 'SELECT `tmp_playlist_data`.`object_id` ' . - 'FROM `user_vote` INNER JOIN `tmp_playlist_data` ' . - 'ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` ' . - "WHERE `user_vote`.`user`='$user_id' " . - "AND `tmp_playlist_data`.`object_type`='$type' " . - "AND `tmp_playlist_data`.`object_id`='$object_id' " . - "AND `tmp_playlist_data`.`tmp_playlist`='$tmp_id'"; - $db_results = Dba::read($sql); - - /* If we find row, they've voted!! */ - if (Dba::num_rows($db_results)) { - return true; - } - - return false; - - } // has_vote - - /** - * _add_vote - * This takes a object id and user and actually inserts the row - */ - private function _add_vote($object_id, $object_type = 'song') { - - $object_id = Dba::escape($object_id); - $tmp_playlist = Dba::escape($this->tmp_playlist); - $object_type = Dba::escape($object_type); - $media = new $object_type($object_id); - $track = isset($media->track) ? "'" . intval($media->track) . "'" : "NULL"; + /** + * get_current_playlist + * This returns the curren users current playlist, or if specified + * this current playlist of the user + */ + public static function get_current_playlist() { + + $democratic_id = Config::get('democratic_id'); + + if (!$democratic_id) { + $level = Dba::escape($GLOBALS['user']->access); + $sql = "SELECT `id` FROM `democratic` WHERE `level` <= '$level' " . + " ORDER BY `level` DESC,`primary` DESC"; + $db_results = Dba::read($sql); + $row = Dba::fetch_assoc($db_results); + $democratic_id = $row['id']; + } + + $object = new Democratic($democratic_id); + + return $object; + + } // get_current_playlist + + /** + * get_items + * This returns a sorted array of all object_ids in this Tmp_Playlist. + * The array is multidimensional; the inner array needs to contain the + * keys 'id', 'object_type' and 'object_id'. + * + * Sorting is highest to lowest vote count, then by oldest to newest + * vote activity. + */ + public function get_items($limit = null) { + + $sql = 'SELECT `tmp_playlist_data`.`object_type`, ' . + '`tmp_playlist_data`.`object_id`, ' . + '`tmp_playlist_data`.`id` ' . + 'FROM `tmp_playlist_data` INNER JOIN `user_vote` ' . + 'ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` ' . + "WHERE `tmp_playlist_data`.`tmp_playlist` = '" . + Dba::escape($this->tmp_playlist) . "' " . + 'GROUP BY 1, 2 ' . + 'ORDER BY COUNT(*) DESC, MAX(`user_vote`.`date`) '; + + if ($limit) { + $sql .= 'LIMIT ' . intval($limit); + } + + $db_results = Dba::read($sql); + + $results = array(); + + while ($results[] = Dba::fetch_assoc($db_results)) { + // Nada + } + + return $results; + + } // get_items + + /** + * play_url + * This returns the special play URL for democratic play, only open to ADMINs + */ + public function play_url() { + + $link = Stream::get_base_url() . 'uid=' . scrub_out($GLOBALS['user']->id) . '&demo_id=' . scrub_out($this->id); + + return $link; + + } // play_url + + /** + * get_next_object + * This returns the next object in the tmp_playlist. + * Most of the time this will just be the top entry, but if there is a + * base_playlist and no items in the playlist then it returns a random + * entry from the base_playlist + */ + public function get_next_object($offset = 0) { + + // FIXME: Shouldn't this return object_type? + + $offset = intval($offset); + + $items = $this->get_items($offset + 1); + + if (count($items) > $offset) { + return $items[$offset]['object_id']; + } + + + // If nothing was found and this is a voting playlist then get + // from base_playlist + if ($this->base_playlist) { + $base_playlist = new Playlist($this->base_playlist); + $data = $base_playlist->get_random_items(1); + return $data[0]['object_id']; + } + else { + $sql = "SELECT `id` FROM `song` WHERE `enabled`='1' ORDER BY RAND() LIMIT 1"; + $db_results = Dba::read($sql); + $results = Dba::fetch_assoc($db_results); + return $results['id']; + } + + return null; + + } // get_next_object + + /** + * get_uid_from_object_id + * This takes an object_id and an object type and returns the ID for the row + */ + public function get_uid_from_object_id($object_id, $object_type = 'song') { + + $object_id = Dba::escape($object_id); + $object_type = Dba::escape($object_type); + $tmp_id = Dba::escape($this->tmp_playlist); + + $sql = 'SELECT `id` FROM `tmp_playlist_data` ' . + "WHERE `object_type`='$object_type' AND " . + "`tmp_playlist`='$tmp_id' AND `object_id`='$object_id'"; + $db_results = Dba::read($sql); + + $row = Dba::fetch_assoc($db_results); + + return $row['id']; + + } // get_uid_from_object_id + + /** + * get_cool_songs + * This returns all of the song_ids for songs that have happened within + * the last 'cooldown' for this user. + */ + public function get_cool_songs() { + + // Convert cooldown time to a timestamp in the past + $cool_time = time() - ($this->cooldown * 60); + + $song_ids = Stats::get_object_history($GLOBALS['user']->id, $cool_time); + + return $song_ids; + + } // get_cool_songs + + /** + * vote + * This function is called by users to vote on a system wide playlist + * This adds the specified objects to the tmp_playlist and adds a 'vote' + * by this user, naturally it checks to make sure that the user hasn't + * already voted on any of these objects + */ + public function add_vote($items) { + + /* Itterate through the objects if no vote, add to playlist and vote */ + foreach ($items as $element) { + $type = array_shift($element); + $object_id = array_shift($element); + if (!$this->has_vote($object_id, $type)) { + $this->_add_vote($object_id, $type); + } + } // end foreach + + } // vote + + /** + * has_vote + * This checks to see if the current user has already voted on this object + */ + public function has_vote($object_id, $type = 'song') { + + $tmp_id = Dba::escape($this->tmp_playlist); + $object_id = Dba::escape($object_id); + $type = Dba::escape($type); + $user_id = Dba::escape($GLOBALS['user']->id); + + /* Query vote table */ + $sql = 'SELECT `tmp_playlist_data`.`object_id` ' . + 'FROM `user_vote` INNER JOIN `tmp_playlist_data` ' . + 'ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` ' . + "WHERE `user_vote`.`user`='$user_id' " . + "AND `tmp_playlist_data`.`object_type`='$type' " . + "AND `tmp_playlist_data`.`object_id`='$object_id' " . + "AND `tmp_playlist_data`.`tmp_playlist`='$tmp_id'"; + $db_results = Dba::read($sql); + + /* If we find row, they've voted!! */ + if (Dba::num_rows($db_results)) { + return true; + } + + return false; + + } // has_vote + + /** + * _add_vote + * This takes a object id and user and actually inserts the row + */ + private function _add_vote($object_id, $object_type = 'song') { + + $object_id = Dba::escape($object_id); + $tmp_playlist = Dba::escape($this->tmp_playlist); + $object_type = Dba::escape($object_type); + $media = new $object_type($object_id); + $track = isset($media->track) ? "'" . intval($media->track) . "'" : "NULL"; - /* If it's on the playlist just vote */ - $sql = "SELECT `id` FROM `tmp_playlist_data` " . - "WHERE `tmp_playlist_data`.`object_id`='$object_id' AND `tmp_playlist_data`.`tmp_playlist`='$tmp_playlist'"; - $db_results = Dba::write($sql); + /* If it's on the playlist just vote */ + $sql = "SELECT `id` FROM `tmp_playlist_data` " . + "WHERE `tmp_playlist_data`.`object_id`='$object_id' AND `tmp_playlist_data`.`tmp_playlist`='$tmp_playlist'"; + $db_results = Dba::write($sql); - /* If it's not there, add it and pull ID */ - if (!$results = Dba::fetch_assoc($db_results)) { - $sql = "INSERT INTO `tmp_playlist_data` (`tmp_playlist`,`object_id`,`object_type`,`track`) " . - "VALUES ('$tmp_playlist','$object_id','$object_type',$track)"; - $db_results = Dba::write($sql); - $results['id'] = Dba::insert_id(); - } + /* If it's not there, add it and pull ID */ + if (!$results = Dba::fetch_assoc($db_results)) { + $sql = "INSERT INTO `tmp_playlist_data` (`tmp_playlist`,`object_id`,`object_type`,`track`) " . + "VALUES ('$tmp_playlist','$object_id','$object_type',$track)"; + $db_results = Dba::write($sql); + $results['id'] = Dba::insert_id(); + } - /* Vote! */ - $time = time(); - $sql = "INSERT INTO user_vote (`user`,`object_id`,`date`) " . - "VALUES ('" . Dba::escape($GLOBALS['user']->id) . "','" . $results['id'] . "','$time')"; - $db_results = Dba::write($sql); + /* Vote! */ + $time = time(); + $sql = "INSERT INTO user_vote (`user`,`object_id`,`date`) " . + "VALUES ('" . Dba::escape($GLOBALS['user']->id) . "','" . $results['id'] . "','$time')"; + $db_results = Dba::write($sql); - return true; - - } // add_vote - - /** - * remove_vote - * This is called to remove a vote by a user for an object, it uses the object_id - * As that's what we'll have most the time, no need to check if they've got an existing - * vote for this, just remove anything that is there - */ - public function remove_vote($row_id) { - - $object_id = Dba::escape($row_id); - $user_id = Dba::escape($GLOBALS['user']->id); - - $sql = "DELETE FROM `user_vote` WHERE `object_id`='$object_id' AND `user`='$user_id'"; - $db_results = Dba::write($sql); - - /* Clean up anything that has no votes */ - self::prune_tracks(); - - return true; - - } // remove_vote - - /** - * delete_votes - * This removes the votes for the specified object on the current playlist - */ - public function delete_votes($row_id) { - - $row_id = Dba::escape($row_id); - - $sql = "DELETE FROM `user_vote` WHERE `object_id`='$row_id'"; - $db_results = Dba::write($sql); - - $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$row_id'"; - $db_results = Dba::write($sql); - - return true; - - } // delete_votes - - /** - * delete_from_oid - * This takes an OID and type and removes the object from the democratic playlist - */ - public function delete_from_oid($oid,$object_type) { - - $row_id = $this->get_uid_from_object_id($oid,$object_type); - if ($row_id) { - debug_event('Democratic','Removing Votes for ' . $oid . ' of type ' . $object_type,'5'); - $this->delete_votes($row_id); - } - else { debug_event('Democratic','Unable to find Votes for ' . $oid . ' of type ' . $object_type,'3'); } + return true; + + } // add_vote + + /** + * remove_vote + * This is called to remove a vote by a user for an object, it uses the object_id + * As that's what we'll have most the time, no need to check if they've got an existing + * vote for this, just remove anything that is there + */ + public function remove_vote($row_id) { + + $object_id = Dba::escape($row_id); + $user_id = Dba::escape($GLOBALS['user']->id); + + $sql = "DELETE FROM `user_vote` WHERE `object_id`='$object_id' AND `user`='$user_id'"; + $db_results = Dba::write($sql); + + /* Clean up anything that has no votes */ + self::prune_tracks(); + + return true; + + } // remove_vote + + /** + * delete_votes + * This removes the votes for the specified object on the current playlist + */ + public function delete_votes($row_id) { + + $row_id = Dba::escape($row_id); + + $sql = "DELETE FROM `user_vote` WHERE `object_id`='$row_id'"; + $db_results = Dba::write($sql); + + $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$row_id'"; + $db_results = Dba::write($sql); + + return true; + + } // delete_votes + + /** + * delete_from_oid + * This takes an OID and type and removes the object from the democratic playlist + */ + public function delete_from_oid($oid,$object_type) { + + $row_id = $this->get_uid_from_object_id($oid,$object_type); + if ($row_id) { + debug_event('Democratic','Removing Votes for ' . $oid . ' of type ' . $object_type,'5'); + $this->delete_votes($row_id); + } + else { debug_event('Democratic','Unable to find Votes for ' . $oid . ' of type ' . $object_type,'3'); } - return true; + return true; - } // delete_from_oid + } // delete_from_oid - /** - * delete - * This deletes a democratic playlist - */ - public static function delete($democratic_id) { + /** + * delete + * This deletes a democratic playlist + */ + public static function delete($democratic_id) { - $democratic_id = Dba::escape($democratic_id); + $democratic_id = Dba::escape($democratic_id); - $sql = "DELETE FROM `democratic` WHERE `id`='$democratic_id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `democratic` WHERE `id`='$democratic_id'"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$democratic_id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$democratic_id'"; + $db_results = Dba::write($sql); - self::prune_tracks(); + self::prune_tracks(); - return true; + return true; - } // delete + } // delete - /** - * update - * This updates an existing democratic playlist item. It takes a key'd array just like the create - */ - public function update($data) { + /** + * update + * This updates an existing democratic playlist item. It takes a key'd array just like the create + */ + public function update($data) { - $name = Dba::escape($data['name']); - $base = Dba::escape($data['democratic']); - $cool = Dba::escape($data['cooldown']); - $id = Dba::escape($this->id); + $name = Dba::escape($data['name']); + $base = Dba::escape($data['democratic']); + $cool = Dba::escape($data['cooldown']); + $id = Dba::escape($this->id); - $sql = "UPDATE `democratic` SET `name`='$name', `base_playlist`='$base',`cooldown`='$cool' WHERE `id`='$id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `democratic` SET `name`='$name', `base_playlist`='$base',`cooldown`='$cool' WHERE `id`='$id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // update + } // update - /** - * create - * This is the democratic play create function it inserts this into the democratic table - */ - public static function create($data) { + /** + * create + * This is the democratic play create function it inserts this into the democratic table + */ + public static function create($data) { - // Clean up the input - $name = Dba::escape($data['name']); - $base = Dba::escape($data['democratic']); - $cool = Dba::escape($data['cooldown']); - $level = Dba::escape($data['level']); - $default = Dba::escape($data['make_default']); - $user = Dba::escape($GLOBALS['user']->id); + // Clean up the input + $name = Dba::escape($data['name']); + $base = Dba::escape($data['democratic']); + $cool = Dba::escape($data['cooldown']); + $level = Dba::escape($data['level']); + $default = Dba::escape($data['make_default']); + $user = Dba::escape($GLOBALS['user']->id); - $sql = "INSERT INTO `democratic` (`name`,`base_playlist`,`cooldown`,`level`,`user`,`primary`) " . - "VALUES ('$name','$base','$cool','$level','$user','$default')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `democratic` (`name`,`base_playlist`,`cooldown`,`level`,`user`,`primary`) " . + "VALUES ('$name','$base','$cool','$level','$user','$default')"; + $db_results = Dba::write($sql); - if ($db_results) { - $insert_id = Dba::insert_id(); - parent::create(array( - 'session_id' => $insert_id, - 'type' => 'vote', - 'object_type' => 'song' - )); - } + if ($db_results) { + $insert_id = Dba::insert_id(); + parent::create(array( + 'session_id' => $insert_id, + 'type' => 'vote', + 'object_type' => 'song' + )); + } - return $db_results; + return $db_results; - } // create + } // create - /** - * prune_tracks - * This replaces the normal prune tracks and correctly removes the votes - * as well - */ - public static function prune_tracks() { + /** + * prune_tracks + * This replaces the normal prune tracks and correctly removes the votes + * as well + */ + public static function prune_tracks() { - // This deletes data without votes, if it's a voting democratic playlist - $sql = "DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` " . - "LEFT JOIN `user_vote` ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` " . - "LEFT JOIN `tmp_playlist` ON `tmp_playlist`.`id`=`tmp_playlist_data`.`tmp_playlist` " . - "WHERE `user_vote`.`object_id` IS NULL AND `tmp_playlist`.`type` = 'vote'"; - $db_results = Dba::write($sql); + // This deletes data without votes, if it's a voting democratic playlist + $sql = "DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` " . + "LEFT JOIN `user_vote` ON `tmp_playlist_data`.`id`=`user_vote`.`object_id` " . + "LEFT JOIN `tmp_playlist` ON `tmp_playlist`.`id`=`tmp_playlist_data`.`tmp_playlist` " . + "WHERE `user_vote`.`object_id` IS NULL AND `tmp_playlist`.`type` = 'vote'"; + $db_results = Dba::write($sql); - return true; + return true; - } // prune_tracks + } // prune_tracks - /** - * clear - * This is really just a wrapper function, it clears the entire playlist - * including all votes etc. - */ - public function clear() { + /** + * clear + * This is really just a wrapper function, it clears the entire playlist + * including all votes etc. + */ + public function clear() { - $tmp_id = Dba::escape($this->tmp_playlist); + $tmp_id = Dba::escape($this->tmp_playlist); - /* Clear all votes then prune */ - $sql = "DELETE FROM `user_vote` USING `user_vote` " . - "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` " . - "WHERE `tmp_playlist_data`.`tmp_playlist`='$tmp_id'"; - $db_results = Dba::write($sql); + /* Clear all votes then prune */ + $sql = "DELETE FROM `user_vote` USING `user_vote` " . + "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id` = `tmp_playlist_data`.`id` " . + "WHERE `tmp_playlist_data`.`tmp_playlist`='$tmp_id'"; + $db_results = Dba::write($sql); - // Prune! - self::prune_tracks(); + // Prune! + self::prune_tracks(); - // Clean the votes - self::clear_votes(); + // Clean the votes + self::clear_votes(); - return true; + return true; - } // clear_playlist + } // clear_playlist - /** - * clean_votes - * This removes in left over garbage in the votes table - */ - public function clear_votes() { + /** + * clean_votes + * This removes in left over garbage in the votes table + */ + public function clear_votes() { - $sql = "DELETE FROM `user_vote` USING `user_vote` " . - "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id`=`tmp_playlist_data`.`id` " . - "WHERE `tmp_playlist_data`.`id` IS NULL"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `user_vote` USING `user_vote` " . + "LEFT JOIN `tmp_playlist_data` ON `user_vote`.`object_id`=`tmp_playlist_data`.`id` " . + "WHERE `tmp_playlist_data`.`id` IS NULL"; + $db_results = Dba::write($sql); - return true; + return true; - } // clear_votes + } // clear_votes - /** - * get_vote - * This returns the current count for a specific song - */ - public function get_vote($id) { + /** + * get_vote + * This returns the current count for a specific song + */ + public function get_vote($id) { - if (parent::is_cached('democratic_vote', $id)) { - return parent::get_from_cache('democratic_vote', $id); - } - - $sql = 'SELECT COUNT(`user`) AS `count` FROM `user_vote` ' . - "WHERE `object_id`='" . Dba::escape($id) . "'"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - parent::add_to_cache('democratic_vote', $id, $results['count']); - return $results['count']; - - } // get_vote + if (parent::is_cached('democratic_vote', $id)) { + return parent::get_from_cache('democratic_vote', $id); + } + + $sql = 'SELECT COUNT(`user`) AS `count` FROM `user_vote` ' . + "WHERE `object_id`='" . Dba::escape($id) . "'"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + parent::add_to_cache('democratic_vote', $id, $results['count']); + return $results['count']; + + } // get_vote - /** - * get_voters - * This returns the users that voted for the specified object - * This is an array of user ids - */ - public function get_voters($object_id) { + /** + * get_voters + * This returns the users that voted for the specified object + * This is an array of user ids + */ + public function get_voters($object_id) { - return parent::get_from_cache('democratic_voters',$object_id); + return parent::get_from_cache('democratic_voters',$object_id); - } // get_voters + } // get_voters } // Democratic class diff --git a/lib/class/error.class.php b/lib/class/error.class.php index 3cc52e742c..6d2189af6a 100644 --- a/lib/class/error.class.php +++ b/lib/class/error.class.php @@ -1,5 +1,5 @@ $error) { - $_SESSION['errors'][$key] = $error; - } + foreach (self::$errors as $key=>$error) { + $_SESSION['errors'][$key] = $error; + } - } // __destruct + } // __destruct - /** - * add - * This is a public static function it adds a new error message to the array - * It can optionally clobber rather then adding to the error message - */ - public static function add($name,$message,$clobber=0) { + /** + * add + * This is a public static function it adds a new error message to the array + * It can optionally clobber rather then adding to the error message + */ + public static function add($name,$message,$clobber=0) { - // Make sure its set first - if (!isset(Error::$errors[$name])) { - Error::$errors[$name] = $message; - Error::$state = 1; - $_SESSION['errors'][$name] = $message; - } - // They want us to clobber it - elseif ($clobber) { - Error::$state = 1; - Error::$errors[$name] = $message; - $_SESSION['errors'][$name] = $message; - } - // They want us to append the error, add a BR\n and then the message - else { - Error::$state = 1; - Error::$errors[$name] .= "
\n" . $message; - $_SESSION['errors'][$name] .= "
\n" . $message; - } + // Make sure its set first + if (!isset(Error::$errors[$name])) { + Error::$errors[$name] = $message; + Error::$state = 1; + $_SESSION['errors'][$name] = $message; + } + // They want us to clobber it + elseif ($clobber) { + Error::$state = 1; + Error::$errors[$name] = $message; + $_SESSION['errors'][$name] = $message; + } + // They want us to append the error, add a BR\n and then the message + else { + Error::$state = 1; + Error::$errors[$name] .= "
\n" . $message; + $_SESSION['errors'][$name] .= "
\n" . $message; + } - } // add + } // add - /** - * occurred - * This returns true / false if an error has occured anywhere - */ - public static function occurred() { + /** + * occurred + * This returns true / false if an error has occured anywhere + */ + public static function occurred() { - if (self::$state == '1') { return true; } + if (self::$state == '1') { return true; } - return false; + return false; - } // occurred + } // occurred - /** - * get - * This returns an error by name - */ - public static function get($name) { + /** + * get + * This returns an error by name + */ + public static function get($name) { - if (!isset(Error::$errors[$name])) { return ''; } + if (!isset(Error::$errors[$name])) { return ''; } - return Error::$errors[$name]; + return Error::$errors[$name]; - } // get + } // get - /** - * display - * This prints the error out with a standard Error class span - * Ben Goska: Renamed from print to display, print is reserved - */ - public static function display($name) { + /** + * display + * This prints the error out with a standard Error class span + * Ben Goska: Renamed from print to display, print is reserved + */ + public static function display($name) { - // Be smart about this, if no error don't print - if (!isset(Error::$errors[$name])) { return ''; } + // Be smart about this, if no error don't print + if (!isset(Error::$errors[$name])) { return ''; } - echo '' . Error::$errors[$name] . ''; + echo '' . Error::$errors[$name] . ''; - } // display + } // display - /** - * auto_init - * This loads the errors from the session back into Ampache - */ - public static function auto_init() { + /** + * auto_init + * This loads the errors from the session back into Ampache + */ + public static function auto_init() { - if (!is_array($_SESSION['errors'])) { return false; } + if (!is_array($_SESSION['errors'])) { return false; } - // Re-insert them - foreach ($_SESSION['errors'] as $key=>$error) { - self::add($key,$error); - } + // Re-insert them + foreach ($_SESSION['errors'] as $key=>$error) { + self::add($key,$error); + } - } // auto_init + } // auto_init } // Error diff --git a/lib/class/flag.class.php b/lib/class/flag.class.php index ed1fef0642..d7fdc81160 100644 --- a/lib/class/flag.class.php +++ b/lib/class/flag.class.php @@ -1,5 +1,5 @@ get_info($flag_id,'flagged'); + $info = $this->get_info($flag_id,'flagged'); - foreach ($info as $key=>$value) { - $this->$key = $value; - } + foreach ($info as $key=>$value) { + $this->$key = $value; + } - return true; + return true; - } // Constructor + } // Constructor - /** - * gc - * - * This cleans out unused flagged items - */ - public static function gc() { - Dba::write("DELETE FROM `flagged` USING `flagged` LEFT JOIN `song` ON `song`.`id` = `flagged`.`object_id` WHERE `song`.`id` IS NULL AND `object_type` = 'song'"); - } + /** + * gc + * + * This cleans out unused flagged items + */ + public static function gc() { + Dba::write("DELETE FROM `flagged` USING `flagged` LEFT JOIN `song` ON `song`.`id` = `flagged`.`object_id` WHERE `song`.`id` IS NULL AND `object_type` = 'song'"); + } - /** - * build_cache - * This takes an array of ids and builds up a nice little cache - * for us - */ - public static function build_cache($ids) { + /** + * build_cache + * This takes an array of ids and builds up a nice little cache + * for us + */ + public static function build_cache($ids) { - if (!is_array($ids) OR !count($ids)) { return false; } + if (!is_array($ids) OR !count($ids)) { return false; } - $idlist = '(' . implode(',',$ids) . ')'; + $idlist = '(' . implode(',',$ids) . ')'; - $sql = "SELECT * FROM `flagged` WHERE `id` IN $idlist"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `flagged` WHERE `id` IN $idlist"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('flagged',$row['id'],$row); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('flagged',$row['id'],$row); + } - } // build_cache + } // build_cache - /** - * build_map_cache - * This takes an array of ids and builds a map cache to avoid some of the object_type calls - * we would normally have to make - */ - public static function build_map_cache($ids,$type) { + /** + * build_map_cache + * This takes an array of ids and builds a map cache to avoid some of the object_type calls + * we would normally have to make + */ + public static function build_map_cache($ids,$type) { - if (!is_array($ids) OR !count($ids)) { return false; } + if (!is_array($ids) OR !count($ids)) { return false; } - $idlist = '(' . implode(',',$ids) . ')'; - $type = Dba::escape($type); + $idlist = '(' . implode(',',$ids) . ')'; + $type = Dba::escape($type); - $sql = "SELECT * FROM `flagged` " . - "WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id` IN $idlist"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `flagged` " . + "WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id` IN $idlist"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[$row['object_id']] = $row; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[$row['object_id']] = $row; + } - // Itterate through the passed ids as we need to cache 'nulls' - foreach ($ids as $id) { - parent::add_to_cache('flagged_' . $type,$id,$results[$id]); - } + // Itterate through the passed ids as we need to cache 'nulls' + foreach ($ids as $id) { + parent::add_to_cache('flagged_' . $type,$id,$results[$id]); + } - return true; + return true; - } // build_map_cache + } // build_map_cache - /** - * has_flag - * Static function, tries to check the cache, but falls back on a query - */ - public static function has_flag($id,$type) { + /** + * has_flag + * Static function, tries to check the cache, but falls back on a query + */ + public static function has_flag($id,$type) { - if (parent::is_cached('flagged_' . $type,$id)) { - $data = parent::get_from_cache('flagged_' . $type,$id); - return $data['date']; - } + if (parent::is_cached('flagged_' . $type,$id)) { + $data = parent::get_from_cache('flagged_' . $type,$id); + return $data['date']; + } - // Ok we have to query this - $type = Dba::escape($type); + // Ok we have to query this + $type = Dba::escape($type); - $sql = "SELECT * FROM `flagged` WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id`='$id'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `flagged` WHERE `flagged`.`object_type`='$type' AND `flagged`.`object_id`='$id'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); - parent::add_to_cache('flagged_' . $type,$row['object_id'],$row); + $row = Dba::fetch_assoc($db_results); + parent::add_to_cache('flagged_' . $type,$row['object_id'],$row); - return $row['date']; + return $row['date']; - } // has_flag + } // has_flag - /** - * get_recent - * This returns the id's of the most recently flagged songs, it takes an int - * as an argument which is the count of the object you want to return - */ - public static function get_recent($count=0) { + /** + * get_recent + * This returns the id's of the most recently flagged songs, it takes an int + * as an argument which is the count of the object you want to return + */ + public static function get_recent($count=0) { - if ($count) { $limit = " LIMIT " . intval($count); } + if ($count) { $limit = " LIMIT " . intval($count); } - $results = array(); + $results = array(); - $sql = "SELECT id FROM flagged ORDER BY date " . $limit; - $db_results = Dba::read($sql); + $sql = "SELECT id FROM flagged ORDER BY date " . $limit; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['id']; - } + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['id']; + } - return $results; + return $results; - } // get_recent + } // get_recent - /** - * get_disabled - * This returns all of the songs that have been disabled, this is - * a form of being flagged - */ - public static function get_disabled() { + /** + * get_disabled + * This returns all of the songs that have been disabled, this is + * a form of being flagged + */ + public static function get_disabled() { - $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_disabled + } // get_disabled - /** - * get_all - * This returns an array of ids of flagged songs if no limit is passed - * it gets everything - */ - public static function get_all($count=0) { + /** + * get_all + * This returns an array of ids of flagged songs if no limit is passed + * it gets everything + */ + public static function get_all($count=0) { - if ($count) { $limit_clause = "LIMIT " . intval($count); } + if ($count) { $limit_clause = "LIMIT " . intval($count); } - $sql = "SELECT `id` FROM `flagged` $limit_clause"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `flagged` $limit_clause"; + $db_results = Dba::read($sql); - /* Default it to an array */ - $results = array(); + /* Default it to an array */ + $results = array(); - /* While the query */ - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + /* While the query */ + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_all + } // get_all - /** - * get_approved - * This returns an array of approved flagged songs - */ - public static function get_approved() { + /** + * get_approved + * This returns an array of approved flagged songs + */ + public static function get_approved() { - $sql = "SELECT `id` FROM `flagged` WHERE `approved`='1'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `flagged` WHERE `approved`='1'"; + $db_results = Dba::read($sql); - /* Default the results array */ - $results = array(); + /* Default the results array */ + $results = array(); - /* While it */ - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['id']; - } + /* While it */ + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['id']; + } - return $results; + return $results; - } // get_approved + } // get_approved - /** - * add - * This adds a flag entry for an item, it takes an id, a type, the flag type - * and a comment and then inserts the mofo - */ - public static function add($id,$type,$flag,$comment) { + /** + * add + * This adds a flag entry for an item, it takes an id, a type, the flag type + * and a comment and then inserts the mofo + */ + public static function add($id,$type,$flag,$comment) { - $id = Dba::escape($id); - $type = Dba::escape($type); - $flag = self::validate_flag($flag); - $user = Dba::escape($GLOBALS['user']->id); - $comment = Dba::escape($comment); - $time = time(); - $approved = '0'; + $id = Dba::escape($id); + $type = Dba::escape($type); + $flag = self::validate_flag($flag); + $user = Dba::escape($GLOBALS['user']->id); + $comment = Dba::escape($comment); + $time = time(); + $approved = '0'; - /* If they are an content manager or higher, it's auto approved */ - if (Access::check('interface','75')) { $approved = '1'; } + /* If they are an content manager or higher, it's auto approved */ + if (Access::check('interface','75')) { $approved = '1'; } - $sql = "INSERT INTO `flagged` (`object_id`,`object_type`,`flag`,`comment`,`date`,`approved`,`user`) VALUES " . - " ('$id','$type','$flag','$comment','$time','$approved','$user')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `flagged` (`object_id`,`object_type`,`flag`,`comment`,`date`,`approved`,`user`) VALUES " . + " ('$id','$type','$flag','$comment','$time','$approved','$user')"; + $db_results = Dba::write($sql); - return true; + return true; - } // add + } // add - /** - * delete - * This deletes the flagged entry and rescans the file to revert to the origional - * state, in a perfect world, I could just roll the changes back... not until 3.4 - * or.. haha 3.5! - */ - public function delete() { + /** + * delete + * This deletes the flagged entry and rescans the file to revert to the origional + * state, in a perfect world, I could just roll the changes back... not until 3.4 + * or.. haha 3.5! + */ + public function delete() { - // Re-scan the file - $song = new Song($this->object_id); - $info = Catalog::update_media_from_tags($song); - - // Delete the row - $sql = "DELETE FROM `flagged` WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - // Reset the Last-Updated date so that it'll get re-scaned - $song->update_utime($song->id,1); - - return true; - - } // delete - - /** - * approve - * This approves the current flag object ($this->id) by setting approved to - * 1 - */ - public function approve() { - - $sql = "UPDATE `flagged` SET `approved`='1' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - $this->approved = 1; - - return true; - - } // approve - - /** - * format - * This function figures out what kind of object we've got and sets up all the - * vars all nice and fuzzy like - */ - public function format() { - - switch ($this->object_type) { - case 'song': - $song = new Song($this->object_id); - $song->format(); - $this->f_name = $song->f_link; - break; - } // end switch on type - - $client = new User($this->user); - $client->format(); - $this->f_user = $client->f_link; - - } // format - - /** - * print_status - * This prints out a userfriendly version of the current status for this flagged - * object - */ - public function print_status() { - - if ($this->approved) { echo T_('Approved'); } - else { echo T_('Pending'); } - - } // print_status - - /** - * print_flag - * This prints out a userfriendly version of the current flag type - */ - public function print_flag() { - - switch ($this->flag) { - case 'delete': - $name = T_('Delete'); - break; - case 'retag': - $name = T_('Re-Tag'); - break; - case 'reencode': - $name = T_('Re-encode'); - break; - case 'other': - $name = T_('Other'); - break; - default: - $name = T_('Unknown'); - break; - } // end switch - - echo $name; - - } // print_flag - - /** - * validate_flag - * This takes a flag input and makes sure it's one of the reigstered - * and valid 'flag' values - */ - public static function validate_flag($flag) { - - switch ($flag) { - case 'delete': - case 'retag': - case 'reencode': - case 'other': - return $flag; - break; - default: - return 'other'; - break; - } // end switch - - } // validate_flag - - /** - * fill_tags - * This is used by the write_tags script. - */ - public static function fill_tags( $tagWriter, $song, $type = 'comment' ) { - - // Set all of the attributes for the tag to be written(All pulled from the song object) - // Use a function since ID3v1, ID3v2, and vorbis/flac/ape are different - switch ($type) { - case 'comment': - $tagWriter->comments['title'] = $song->title; - $tagWriter->comments['date'] = $song->year; - $tagWriter->comments['year'] = $song->year; - $tagWriter->comments['comment'] = $song->comment; - $tagWriter->comments['size'] = $song->size; - $tagWriter->comments['time'] = $song->time; - $tagWriter->comments['album'] = $song->get_album_name(); - $tagWriter->comments['artist'] = $song->get_artist_name(); - $tagWriter->comments['genre'] = $song->get_genre_name(); - $tagWriter->comments['track'] = $song->track; - break; - case 'id3v1': - $tagWriter->title = $song->title; - $tagWriter->year = $song->year; - $tagWriter->comment = $song->comment; - $tagWriter->artist = $song->get_artist_name(); - $tagWriter->album = $song->get_album_name(); - $tagWriter->genre = $song->get_genre_name(); - $tagWriter->track = $song->track; - unset($tagWriter->genre_id); - break; - case 'id3v2': - $tagWriter->title = $song->title; - $tagWriter->year = $song->year; - $tagWriter->comment = $song->comment; - $tagWriter->artist = $song->get_artist_name(); - $tagWriter->album = $song->get_album_name(); - $tagWriter->genre = $song->get_genre_name(); - $tagWriter->track = $song->track; - unset($tagWriter->genre_id); - break; - } // end switch on type - - } // fill_tags + // Re-scan the file + $song = new Song($this->object_id); + $info = Catalog::update_media_from_tags($song); + + // Delete the row + $sql = "DELETE FROM `flagged` WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + // Reset the Last-Updated date so that it'll get re-scaned + $song->update_utime($song->id,1); + + return true; + + } // delete + + /** + * approve + * This approves the current flag object ($this->id) by setting approved to + * 1 + */ + public function approve() { + + $sql = "UPDATE `flagged` SET `approved`='1' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + $this->approved = 1; + + return true; + + } // approve + + /** + * format + * This function figures out what kind of object we've got and sets up all the + * vars all nice and fuzzy like + */ + public function format() { + + switch ($this->object_type) { + case 'song': + $song = new Song($this->object_id); + $song->format(); + $this->f_name = $song->f_link; + break; + } // end switch on type + + $client = new User($this->user); + $client->format(); + $this->f_user = $client->f_link; + + } // format + + /** + * print_status + * This prints out a userfriendly version of the current status for this flagged + * object + */ + public function print_status() { + + if ($this->approved) { echo T_('Approved'); } + else { echo T_('Pending'); } + + } // print_status + + /** + * print_flag + * This prints out a userfriendly version of the current flag type + */ + public function print_flag() { + + switch ($this->flag) { + case 'delete': + $name = T_('Delete'); + break; + case 'retag': + $name = T_('Re-Tag'); + break; + case 'reencode': + $name = T_('Re-encode'); + break; + case 'other': + $name = T_('Other'); + break; + default: + $name = T_('Unknown'); + break; + } // end switch + + echo $name; + + } // print_flag + + /** + * validate_flag + * This takes a flag input and makes sure it's one of the reigstered + * and valid 'flag' values + */ + public static function validate_flag($flag) { + + switch ($flag) { + case 'delete': + case 'retag': + case 'reencode': + case 'other': + return $flag; + break; + default: + return 'other'; + break; + } // end switch + + } // validate_flag + + /** + * fill_tags + * This is used by the write_tags script. + */ + public static function fill_tags( $tagWriter, $song, $type = 'comment' ) { + + // Set all of the attributes for the tag to be written(All pulled from the song object) + // Use a function since ID3v1, ID3v2, and vorbis/flac/ape are different + switch ($type) { + case 'comment': + $tagWriter->comments['title'] = $song->title; + $tagWriter->comments['date'] = $song->year; + $tagWriter->comments['year'] = $song->year; + $tagWriter->comments['comment'] = $song->comment; + $tagWriter->comments['size'] = $song->size; + $tagWriter->comments['time'] = $song->time; + $tagWriter->comments['album'] = $song->get_album_name(); + $tagWriter->comments['artist'] = $song->get_artist_name(); + $tagWriter->comments['genre'] = $song->get_genre_name(); + $tagWriter->comments['track'] = $song->track; + break; + case 'id3v1': + $tagWriter->title = $song->title; + $tagWriter->year = $song->year; + $tagWriter->comment = $song->comment; + $tagWriter->artist = $song->get_artist_name(); + $tagWriter->album = $song->get_album_name(); + $tagWriter->genre = $song->get_genre_name(); + $tagWriter->track = $song->track; + unset($tagWriter->genre_id); + break; + case 'id3v2': + $tagWriter->title = $song->title; + $tagWriter->year = $song->year; + $tagWriter->comment = $song->comment; + $tagWriter->artist = $song->get_artist_name(); + $tagWriter->album = $song->get_album_name(); + $tagWriter->genre = $song->get_genre_name(); + $tagWriter->track = $song->track; + unset($tagWriter->genre_id); + break; + } // end switch on type + + } // fill_tags } //end of flag class diff --git a/lib/class/localplay.class.php b/lib/class/localplay.class.php index 28c8bed9dc..187ae5484c 100644 --- a/lib/class/localplay.class.php +++ b/lib/class/localplay.class.php @@ -1,5 +1,5 @@ type = $type; - - $this->_get_info(); - - } // Localplay - - /** - * _get_info - * This functions takes the type and attempts to get all the - * information needed to load it. Will log errors if there are - * any failures, fatal errors will actually return something to the - * gui - */ - private function _get_info() { - - $this->_load_player(); - - } // _get_info - - /** - * player_loaded - * This returns true / false if the player load - * failed / worked - */ - public function player_loaded() { - - if (is_object($this->_player)) { - return true; - } - else { - return false; - } - - } // player_loaded - - /** - * format - * This makes the localplay/plugin information - * human readable - */ - public function format() { - - if (!is_object($this->_player)) { return false; } - - $this->f_name = ucfirst($this->type); - $this->f_description = $this->_player->get_description(); - $this->f_version = $this->_player->get_version(); - - - } // format - - /** - * _load_player - * This function attempts to load the player class that localplay - * Will interface with in order to make all this magical stuf work - * all LocalPlay modules should be located in /modules//.class.php - */ - private function _load_player() { - - if (!$this->type) { return false; } - - $filename = Config::get('prefix') . '/modules/localplay/' . $this->type . '.controller.php'; - $include = require_once $filename; - - if (!$include) { - /* Throw Error Here */ - debug_event('localplay','Unable to load ' . $this->type . ' controller','2'); - return false; - } // include - else { - $class_name = "Ampache" . $this->type; - $this->_player = new $class_name(); - if (!($this->_player instanceof localplay_controller)) { - debug_event('Localplay',$this->type . ' not an instance of controller abstract, unable to load','1'); - unset($this->_player); - return false; - } - } - - } // _load_player - - /** - * format_name - * This function takes the track name and checks to see if 'skip' - * is supported in the current player, if so it returns a 'skip to' - * link, otherwise it returns just the text - */ - public function format_name($name,$id) { - - $name = scrub_out($name); - $name = Ajax::text('?page=localplay&action=command&command=skip&id=' . $id,$name,'localplay_skip_' . $id); - return $name; - - } // format_name - - /** - * get_controllers - * This returns the controllers that are currently loaded into this instance - */ - public static function get_controllers() { - - /* First open the dir */ - $handle = opendir(Config::get('prefix') . '/modules/localplay'); - - if (!is_resource($handle)) { - debug_event('Localplay','Error: Unable to read localplay controller directory','1'); - return array(); - } - - $results = array(); - - while ($file = readdir($handle)) { - - if (substr($file,-14,14) != 'controller.php') { continue; } + /* Base Variables */ + public $type; + + /* Built Variables */ + private $_template; + private $_preferences = array(); + private $_player; + + /** + * Constructor + * This must be called with a localplay type, it then loads the config + * file for the specified type and attempts to load in the function + * map, the preferences and the template + */ + public function __construct($type) { + + $this->type = $type; + + $this->_get_info(); + + } // Localplay + + /** + * _get_info + * This functions takes the type and attempts to get all the + * information needed to load it. Will log errors if there are + * any failures, fatal errors will actually return something to the + * gui + */ + private function _get_info() { + + $this->_load_player(); + + } // _get_info + + /** + * player_loaded + * This returns true / false if the player load + * failed / worked + */ + public function player_loaded() { + + if (is_object($this->_player)) { + return true; + } + else { + return false; + } + + } // player_loaded + + /** + * format + * This makes the localplay/plugin information + * human readable + */ + public function format() { + + if (!is_object($this->_player)) { return false; } + + $this->f_name = ucfirst($this->type); + $this->f_description = $this->_player->get_description(); + $this->f_version = $this->_player->get_version(); + + + } // format + + /** + * _load_player + * This function attempts to load the player class that localplay + * Will interface with in order to make all this magical stuf work + * all LocalPlay modules should be located in /modules//.class.php + */ + private function _load_player() { + + if (!$this->type) { return false; } + + $filename = Config::get('prefix') . '/modules/localplay/' . $this->type . '.controller.php'; + $include = require_once $filename; + + if (!$include) { + /* Throw Error Here */ + debug_event('localplay','Unable to load ' . $this->type . ' controller','2'); + return false; + } // include + else { + $class_name = "Ampache" . $this->type; + $this->_player = new $class_name(); + if (!($this->_player instanceof localplay_controller)) { + debug_event('Localplay',$this->type . ' not an instance of controller abstract, unable to load','1'); + unset($this->_player); + return false; + } + } + + } // _load_player + + /** + * format_name + * This function takes the track name and checks to see if 'skip' + * is supported in the current player, if so it returns a 'skip to' + * link, otherwise it returns just the text + */ + public function format_name($name,$id) { + + $name = scrub_out($name); + $name = Ajax::text('?page=localplay&action=command&command=skip&id=' . $id,$name,'localplay_skip_' . $id); + return $name; + + } // format_name + + /** + * get_controllers + * This returns the controllers that are currently loaded into this instance + */ + public static function get_controllers() { + + /* First open the dir */ + $handle = opendir(Config::get('prefix') . '/modules/localplay'); + + if (!is_resource($handle)) { + debug_event('Localplay','Error: Unable to read localplay controller directory','1'); + return array(); + } + + $results = array(); + + while ($file = readdir($handle)) { + + if (substr($file,-14,14) != 'controller.php') { continue; } - /* Make sure it isn't a dir */ - if (!is_dir($file)) { - /* Get the basename and then everything before controller */ - $filename = basename($file,'.controller.php'); - $results[] = $filename; - } - } // end while - - return $results; + /* Make sure it isn't a dir */ + if (!is_dir($file)) { + /* Get the basename and then everything before controller */ + $filename = basename($file,'.controller.php'); + $results[] = $filename; + } + } // end while + + return $results; - } // get_controllers - - /** - * is_enabled - * This returns true or false depending on if the specified controller - * is currently enabled - */ - public static function is_enabled($controller) { + } // get_controllers + + /** + * is_enabled + * This returns true or false depending on if the specified controller + * is currently enabled + */ + public static function is_enabled($controller) { - // Load the controller and then check for its preferences - $localplay = new Localplay($controller); - // If we can't even load it no sense in going on - if (!isset($localplay->_player)) { return false; } + // Load the controller and then check for its preferences + $localplay = new Localplay($controller); + // If we can't even load it no sense in going on + if (!isset($localplay->_player)) { return false; } - return $localplay->_player->is_installed(); + return $localplay->_player->is_installed(); - } // is_enabled + } // is_enabled - /** - * install - * This runs the install for the localplay controller we've - * currently got pimped out - */ - public function install() { + /** + * install + * This runs the install for the localplay controller we've + * currently got pimped out + */ + public function install() { - // Run the player's installer - $installed = $this->_player->install(); - - return $installed; - - } // install + // Run the player's installer + $installed = $this->_player->install(); + + return $installed; + + } // install - /** - * uninstall - * This runs the uninstall for the localplay controller we've - * currently pimped out - */ - public function uninstall() { + /** + * uninstall + * This runs the uninstall for the localplay controller we've + * currently pimped out + */ + public function uninstall() { - // Run the players uninstaller - $this->_player->uninstall(); + // Run the players uninstaller + $this->_player->uninstall(); - // If its our current player, reset player to nothing - if (Config::get('localplay_controller') == $this->type) { - Preference::update('localplay_controller',$GLOBALS['user']->id,''); - } + // If its our current player, reset player to nothing + if (Config::get('localplay_controller') == $this->type) { + Preference::update('localplay_controller',$GLOBALS['user']->id,''); + } - return true; + return true; - } // uninstall + } // uninstall - /** - * connect - * This function attempts to connect to the localplay - * player that we are using - */ - public function connect() { + /** + * connect + * This function attempts to connect to the localplay + * player that we are using + */ + public function connect() { - if (!$this->_player->connect()) { - debug_event('localplay','Error Unable to connect, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->connect()) { + debug_event('localplay','Error Unable to connect, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // connect + } // connect - /** - * play - * This function passes NULL and calls the play function of the player - * object - */ - public function play() { + /** + * play + * This function passes NULL and calls the play function of the player + * object + */ + public function play() { - if (!$this->_player->play()) { - debug_event('localplay','Error Unable to start playback, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->play()) { + debug_event('localplay','Error Unable to start playback, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // play + } // play - /** - * stop - * This functions passes NULl and calls the stop function of the player - * object, it should recieve a true/false boolean value - */ - public function stop() { + /** + * stop + * This functions passes NULl and calls the stop function of the player + * object, it should recieve a true/false boolean value + */ + public function stop() { - if (!$this->_player->stop()) { - debug_event('localplay','Error Unable to stop playback, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->stop()) { + debug_event('localplay','Error Unable to stop playback, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // stop + } // stop - /** - * add - */ - public function add($object) { + /** + * add + */ + public function add($object) { - debug_event('localplay', 'Deprecated add method called: ' . json_encode($object), 5); - return false; + debug_event('localplay', 'Deprecated add method called: ' . json_encode($object), 5); + return false; - } // add + } // add - /** - * add_url - * This directly adds an URL to the localplay module. Is more betterer. - */ - public function add_url(Stream_URL $url) { + /** + * add_url + * This directly adds an URL to the localplay module. Is more betterer. + */ + public function add_url(Stream_URL $url) { - if (!$this->_player->add_url($url)) { - debug_event('localplay', 'Unable to add url ' . $url . ', check ' . $this->type . ' controller', 1); - return false; - } + if (!$this->_player->add_url($url)) { + debug_event('localplay', 'Unable to add url ' . $url . ', check ' . $this->type . ' controller', 1); + return false; + } - return true; + return true; - } // add_url + } // add_url - /** - * repeat - * This turns the repeat feature of a localplay method on or - * off, takes a 0/1 value - */ - public function repeat($state) { + /** + * repeat + * This turns the repeat feature of a localplay method on or + * off, takes a 0/1 value + */ + public function repeat($state) { - $data = $this->_player->repeat($state); + $data = $this->_player->repeat($state); - if (!$data) { - debug_event('localplay',"Error Unable to set Repeat to $state",'1'); - } + if (!$data) { + debug_event('localplay',"Error Unable to set Repeat to $state",'1'); + } - return $data; + return $data; - } // repeat + } // repeat - /** - * random - * This turns on the random feature of a localplay method - * It takes a 0/1 value - */ - public function random($state) { + /** + * random + * This turns on the random feature of a localplay method + * It takes a 0/1 value + */ + public function random($state) { - $data = $this->_player->random($state); + $data = $this->_player->random($state); - if (!$data) { - debug_event('localplay',"Error Unable to set Random to $state",'1'); - } + if (!$data) { + debug_event('localplay',"Error Unable to set Random to $state",'1'); + } - return $data; + return $data; - } // random + } // random - /** - * status - * This returns current information about the state of the player - * There is an expected array format - */ - public function status() { + /** + * status + * This returns current information about the state of the player + * There is an expected array format + */ + public function status() { - $data = $this->_player->status(); + $data = $this->_player->status(); - if (!count($data)) { - debug_event('localplay','Error Unable to get status, check ' . $this->type . ' controller','1'); - return false; - } + if (!count($data)) { + debug_event('localplay','Error Unable to get status, check ' . $this->type . ' controller','1'); + return false; + } - return $data; + return $data; - } // status + } // status - /** - * get - * This calls the get function of the player and then returns - * the array of current songs for display or whatever - * an empty array is passed on failure - */ - public function get() { + /** + * get + * This calls the get function of the player and then returns + * the array of current songs for display or whatever + * an empty array is passed on failure + */ + public function get() { - $data = $this->_player->get(); + $data = $this->_player->get(); - if (!count($data) OR !is_array($data)) { - debug_event('localplay','Error Unable to get song info, check ' . $this->type . ' controller','1'); - return array(); - } + if (!count($data) OR !is_array($data)) { + debug_event('localplay','Error Unable to get song info, check ' . $this->type . ' controller','1'); + return array(); + } - return $data; + return $data; - } // get + } // get - /** - * volume_set - * This isn't a required function, it sets the volume to a specified value - * as passed in the variable it is a 0 - 100 scale the controller is - * responsible for adjusting the scale if nessecary - */ - public function volume_set($value) { + /** + * volume_set + * This isn't a required function, it sets the volume to a specified value + * as passed in the variable it is a 0 - 100 scale the controller is + * responsible for adjusting the scale if nessecary + */ + public function volume_set($value) { - /* Make sure it's int and 0 - 100 */ - $value = int($value); + /* Make sure it's int and 0 - 100 */ + $value = int($value); - /* Make sure that it's between 0 and 100 */ - if ($value > 100 OR $value < 0) { return false; } + /* Make sure that it's between 0 and 100 */ + if ($value > 100 OR $value < 0) { return false; } - if (!$this->_player->volume($value)) { - debug_event('localplay','Error: Unable to set volume, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->volume($value)) { + debug_event('localplay','Error: Unable to set volume, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // volume_set + } // volume_set - /** - * volume_up - * This function isn't required. It tells the daemon to increase the volume - * by a pre-defined amount controlled by the controller - */ - public function volume_up() { + /** + * volume_up + * This function isn't required. It tells the daemon to increase the volume + * by a pre-defined amount controlled by the controller + */ + public function volume_up() { - if (!$this->_player->volume_up()) { - debug_event('localplay','Error: Unable to increase volume, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->volume_up()) { + debug_event('localplay','Error: Unable to increase volume, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // volume_up + } // volume_up - /** - * volume_down - * This function isn't required. It tells the daemon to decrese the volume - * by a pre-defined amount controlled by the controller. - */ - public function volume_down() { + /** + * volume_down + * This function isn't required. It tells the daemon to decrese the volume + * by a pre-defined amount controlled by the controller. + */ + public function volume_down() { - if (!$this->_player->volume_down()) { - debug_event('localplay','Error: Unable to decrese volume, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->volume_down()) { + debug_event('localplay','Error: Unable to decrese volume, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // volume_down + } // volume_down - /** - * volume_mute - * This function isn't required, It tells the daemon to mute all output - * It's up to the controller to decide what that actually entails - */ - public function volume_mute() { + /** + * volume_mute + * This function isn't required, It tells the daemon to mute all output + * It's up to the controller to decide what that actually entails + */ + public function volume_mute() { - if (!$this->_player->volume(0)){ - debug_event('localplay','Error: Unable to mute volume, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->volume(0)){ + debug_event('localplay','Error: Unable to mute volume, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // volume_mute + } // volume_mute - /** - * skip - * This isn't a required function, it tells the daemon to skip to the specified song - */ - public function skip($track_id) { + /** + * skip + * This isn't a required function, it tells the daemon to skip to the specified song + */ + public function skip($track_id) { - if (!$this->_player->skip($track_id)) { - debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->skip($track_id)) { + debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // skip + } // skip - /** - * next - * This isn't a required function, it tells the daemon to go to the next - * song - */ - public function next() { + /** + * next + * This isn't a required function, it tells the daemon to go to the next + * song + */ + public function next() { - if (!$this->_player->next()) { - debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->next()) { + debug_event('localplay','Error: Unable to skip to next song, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // next + } // next - /** - * prev - * This isn't a required function, it tells the daemon to go the the previous - * song - */ - public function prev() { + /** + * prev + * This isn't a required function, it tells the daemon to go the the previous + * song + */ + public function prev() { - if (!$this->_player->prev()) { - debug_event('localplay','Error: Unable to skip to previous song, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->prev()) { + debug_event('localplay','Error: Unable to skip to previous song, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // prev + } // prev - /** - * pause - * This isn't a required function, it tells the daemon to pause the - * song - */ - public function pause() { + /** + * pause + * This isn't a required function, it tells the daemon to pause the + * song + */ + public function pause() { - if (!$this->_player->pause()) { - debug_event('localplay','Error: Unable to pause song, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->pause()) { + debug_event('localplay','Error: Unable to pause song, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // pause + } // pause - /** - * get_instances - * This returns the instances of the current type - */ - public function get_instances() { + /** + * get_instances + * This returns the instances of the current type + */ + public function get_instances() { - $instances = $this->_player->get_instances(); + $instances = $this->_player->get_instances(); - return $instances; + return $instances; - } // get_instances + } // get_instances - /** - * current_instance - * This returns the UID of the current Instance - */ - public function current_instance() { + /** + * current_instance + * This returns the UID of the current Instance + */ + public function current_instance() { - $data = $this->_player->get_instance(); + $data = $this->_player->get_instance(); - return $data['id']; + return $data['id']; - } // current_instance + } // current_instance - /** - * get_instance - * This returns the specified instance - */ - public function get_instance($uid) { + /** + * get_instance + * This returns the specified instance + */ + public function get_instance($uid) { - $data = $this->_player->get_instance($uid); + $data = $this->_player->get_instance($uid); - return $data; + return $data; - } // get_instance + } // get_instance - /** - * update_instance - * This updates the specified instance with a named array of data (_POST most likely) - */ - public function update_instance($uid,$data) { + /** + * update_instance + * This updates the specified instance with a named array of data (_POST most likely) + */ + public function update_instance($uid,$data) { - $data = $this->_player->update_instance($uid,$data); + $data = $this->_player->update_instance($uid,$data); - return $data; + return $data; - } // update_instance + } // update_instance - /** - * add_instance - * This adds a new instance for the current controller type - */ - public function add_instance($data) { + /** + * add_instance + * This adds a new instance for the current controller type + */ + public function add_instance($data) { - $this->_player->add_instance($data); + $this->_player->add_instance($data); - } // add_instance + } // add_instance - /** - * delete_instance - * This removes an instance (it actually calls the players function) - */ - public function delete_instance($instance_uid) { + /** + * delete_instance + * This removes an instance (it actually calls the players function) + */ + public function delete_instance($instance_uid) { - $this->_player->delete_instance($instance_uid); + $this->_player->delete_instance($instance_uid); - } // delete_instance + } // delete_instance - /** - * set_active_instance - * This sets the active instance of the localplay controller - */ - public function set_active_instance($instance) { + /** + * set_active_instance + * This sets the active instance of the localplay controller + */ + public function set_active_instance($instance) { - $this->_player->set_active_instance($instance); + $this->_player->set_active_instance($instance); - } // set_active_instance + } // set_active_instance - /** - * delete_track - * This removes songs from the players playlist it takes a single ID as provided - * by the get command - */ - public function delete_track($object_id) { + /** + * delete_track + * This removes songs from the players playlist it takes a single ID as provided + * by the get command + */ + public function delete_track($object_id) { - if (!$this->_player->delete_track($object_id)) { - debug_event('localplay','Error: Unable to remove songs, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->delete_track($object_id)) { + debug_event('localplay','Error: Unable to remove songs, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // delete + } // delete - /** - * delete_all - * This removes every song from the players playlist as defined by the delete_all function - * map - */ - public function delete_all() { + /** + * delete_all + * This removes every song from the players playlist as defined by the delete_all function + * map + */ + public function delete_all() { - if (!$this->_player->clear_playlist()) { - debug_event('localplay','Error: Unable to delete entire playlist, check ' . $this->type . ' controller','1'); - return false; - } + if (!$this->_player->clear_playlist()) { + debug_event('localplay','Error: Unable to delete entire playlist, check ' . $this->type . ' controller','1'); + return false; + } - return true; + return true; - } // delete_all + } // delete_all - /** - * get_instance_fields - * This loads the fields from the localplay - * player and returns them - */ - public function get_instance_fields() { + /** + * get_instance_fields + * This loads the fields from the localplay + * player and returns them + */ + public function get_instance_fields() { - $fields = $this->_player->instance_fields(); + $fields = $this->_player->instance_fields(); - return $fields; + return $fields; - } // get_instance_fields + } // get_instance_fields - /** - * get_user_state - * This function returns a user friendly version - * of the current player state - */ - public function get_user_state($state) { + /** + * get_user_state + * This function returns a user friendly version + * of the current player state + */ + public function get_user_state($state) { - switch ($state) { - case 'play': - return T_('Now Playing'); - break; - case 'stop': - return T_('Stopped'); - break; - case 'pause': - return T_('Paused'); - break; - default: - return T_('Unknown'); - break; - } // switch on state + switch ($state) { + case 'play': + return T_('Now Playing'); + break; + case 'stop': + return T_('Stopped'); + break; + case 'pause': + return T_('Paused'); + break; + default: + return T_('Unknown'); + break; + } // switch on state - } // get_user_state + } // get_user_state - /** - * get_user_playing - * This attempts to return a nice user friendly - * currently playing string - */ - public function get_user_playing() { + /** + * get_user_playing + * This attempts to return a nice user friendly + * currently playing string + */ + public function get_user_playing() { - $status = $this->status(); + $status = $this->status(); - /* Format the track name */ - $track_name = $status['track_artist'] . ' - ' . $status['track_album'] . ' - ' . $status['track_title']; + /* Format the track name */ + $track_name = $status['track_artist'] . ' - ' . $status['track_album'] . ' - ' . $status['track_title']; - /* This is a cheezball fix for when we were unable to find a - * artist/album (or one wasn't provided) - */ - $track_name = ltrim(ltrim($track_name,' - '),' - '); + /* This is a cheezball fix for when we were unable to find a + * artist/album (or one wasn't provided) + */ + $track_name = ltrim(ltrim($track_name,' - '),' - '); - $track_name = "[" . $status['track'] . "] - " . $track_name; + $track_name = "[" . $status['track'] . "] - " . $track_name; - return $track_name; + return $track_name; - } // get_user_playing + } // get_user_playing } // end localplay class diff --git a/lib/class/localplay_controller.abstract.php b/lib/class/localplay_controller.abstract.php index 38e2bc7d03..e1b79db9be 100644 --- a/lib/class/localplay_controller.abstract.php +++ b/lib/class/localplay_controller.abstract.php @@ -1,5 +1,5 @@ id); - - return $url; - - } // get_url - - /** - * get_file - * This returns the Filename for the passed object, not - * always possible - */ - public function get_file($object) { - - - } // get_file - - /** - * parse_url - * This takes an Ampache URL and then returns the 'primary' part of it - * So that it's easier for localplay modules to return valid song information - */ - public function parse_url($url) { - - // Define possible 'primary' keys - $primary_array = array('oid','demo_id','random'); - $data = array(); - - $variables = parse_url($url,PHP_URL_QUERY); - parse_str($variables,$data); - - foreach ($primary_array as $pkey) { - if ($data[$pkey]) { - $data['primary_key'] = $pkey; - return $data; - } - - } // end foreach - - return $data; - - } // parse_url + // Required Functions + abstract public function add_url(Stream_URL $url); // Takes an array of song_ids + abstract public function delete_track($object_id); // Takes a single object_id and removes it from the playlist + abstract public function play(); + abstract public function stop(); + abstract public function get(); + abstract public function connect(); + abstract public function status(); + abstract public function get_version(); // Returns the version of this plugin + abstract public function get_description(); // Returns the description + abstract public function is_installed(); // Returns an boolean t/f + abstract public function install(); + abstract public function uninstall(); + + // For display we need the following 'instance' functions + abstract public function add_instance($data); + abstract public function delete_instance($id); + abstract public function update_instance($id,$post); + abstract public function get_instances(); + abstract public function instance_fields(); + abstract public function set_active_instance($uid); + abstract public function get_active_instance(); + + /** + * get_url + * This returns the URL for the passed object + */ + public function get_url($object) { + + // This might not be an object! + if (!is_object($object)) { + // Stupiidly we'll just blindly add it for now + return $object; + } + + $class = get_class($object); + + $url = call_user_func(array($class,'play_url'),$object->id); + + return $url; + + } // get_url + + /** + * get_file + * This returns the Filename for the passed object, not + * always possible + */ + public function get_file($object) { + + + } // get_file + + /** + * parse_url + * This takes an Ampache URL and then returns the 'primary' part of it + * So that it's easier for localplay modules to return valid song information + */ + public function parse_url($url) { + + // Define possible 'primary' keys + $primary_array = array('oid','demo_id','random'); + $data = array(); + + $variables = parse_url($url,PHP_URL_QUERY); + parse_str($variables,$data); + + foreach ($primary_array as $pkey) { + if ($data[$pkey]) { + $data['primary_key'] = $pkey; + return $data; + } + + } // end foreach + + return $data; + + } // parse_url } // end localplay_controller interface diff --git a/lib/class/media.interface.php b/lib/class/media.interface.php index 97e018d135..f1f794f81e 100644 --- a/lib/class/media.interface.php +++ b/lib/class/media.interface.php @@ -1,5 +1,5 @@ diff --git a/lib/class/memory_object.class.php b/lib/class/memory_object.class.php index 3ee4f18391..2a8fa13357 100644 --- a/lib/class/memory_object.class.php +++ b/lib/class/memory_object.class.php @@ -1,5 +1,5 @@ $value) { - if (in_array($key, $this->properties)) { - $this->_data[$key] = $value; - } - } + foreach ($data as $key => $value) { + if (in_array($key, $this->properties)) { + $this->_data[$key] = $value; + } + } - } + } - public function __set($name, $value) { - if (!in_array($name, $this->properties)) { - return false; - } - $this->_data[$name] = $value; - } + public function __set($name, $value) { + if (!in_array($name, $this->properties)) { + return false; + } + $this->_data[$name] = $value; + } - public function __get($name) { - if (!in_array($name, $this->properties)) { - return false; - } + public function __get($name) { + if (!in_array($name, $this->properties)) { + return false; + } - return isset($this->_data[$name]) ? $this->_data[$name] : null; - } + return isset($this->_data[$name]) ? $this->_data[$name] : null; + } } diff --git a/lib/class/playlist.class.php b/lib/class/playlist.class.php index 20035f2bc8..ae3ceb2e9c 100644 --- a/lib/class/playlist.class.php +++ b/lib/class/playlist.class.php @@ -1,5 +1,5 @@ get_info($id); + $info = $this->get_info($id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } + foreach ($info as $key=>$value) { + $this->$key = $value; + } - } // Playlist + } // Playlist - /** - * gc - * - * Clean dead items out of playlists - */ - public static function gc() { - Dba::write("DELETE FROM `playlist_data` USING `playlist_data` LEFT JOIN `song` ON `song`.`id` = `playlist_data`.`object_id` WHERE `song`.`file` IS NULL AND `playlist_data`.`object_type`='song'"); - } + /** + * gc + * + * Clean dead items out of playlists + */ + public static function gc() { + Dba::write("DELETE FROM `playlist_data` USING `playlist_data` LEFT JOIN `song` ON `song`.`id` = `playlist_data`.`object_id` WHERE `song`.`file` IS NULL AND `playlist_data`.`object_type`='song'"); + } - /** - * build_cache - * This is what builds the cache from the objects - */ - public static function build_cache($ids) { + /** + * build_cache + * This is what builds the cache from the objects + */ + public static function build_cache($ids) { - if (!count($ids)) { return false; } + if (!count($ids)) { return false; } - $idlist = '(' . implode(',',$ids) . ')'; + $idlist = '(' . implode(',',$ids) . ')'; - $sql = "SELECT * FROM `playlist` WHERE `id` IN $idlist"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `playlist` WHERE `id` IN $idlist"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('playlist',$row['id'],$row); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('playlist',$row['id'],$row); + } - } // build_cache + } // build_cache - /** - * get_playlists - * Returns a list of playlists accessible by the current user. - */ - public static function get_playlists() { - $sql = "SELECT `id` from `playlist` WHERE `type`='public' OR " . - "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`"; - $db_results = Dba::read($sql); + /** + * get_playlists + * Returns a list of playlists accessible by the current user. + */ + public static function get_playlists() { + $sql = "SELECT `id` from `playlist` WHERE `type`='public' OR " . + "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; - } // get_playlists + return $results; + } // get_playlists - /** - * format - * This takes the current playlist object and gussies it up a little - * bit so it is presentable to the users - */ - public function format() { - parent::format(); - $this->f_link = '' . $this->f_name . ''; + /** + * format + * This takes the current playlist object and gussies it up a little + * bit so it is presentable to the users + */ + public function format() { + parent::format(); + $this->f_link = '' . $this->f_name . ''; - } // format + } // format - /** - * get_track - * Returns the single item on the playlist and all of it's information, restrict - * it to this Playlist - */ - public function get_track($track_id) { + /** + * get_track + * Returns the single item on the playlist and all of it's information, restrict + * it to this Playlist + */ + public function get_track($track_id) { - $track_id = Dba::escape($track_id); - $playlist_id = Dba::escape($this->id); + $track_id = Dba::escape($track_id); + $playlist_id = Dba::escape($this->id); - $sql = "SELECT * FROM `playlist_data` WHERE `id`='$track_id' AND `playlist`='$playlist_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `playlist_data` WHERE `id`='$track_id' AND `playlist`='$playlist_id'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - return $row; + return $row; - } // get_track + } // get_track - /** - * get_items - * This returns an array of playlist songs that are in this playlist. - * Because the same song can be on the same playlist twice they are - * keyed by the uid from playlist_data - */ - public function get_items() { + /** + * get_items + * This returns an array of playlist songs that are in this playlist. + * Because the same song can be on the same playlist twice they are + * keyed by the uid from playlist_data + */ + public function get_items() { - $results = array(); + $results = array(); - $sql = "SELECT `id`,`object_id`,`object_type`,`track` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id`,`object_id`,`object_type`,`track` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = array( - 'object_type' => $row['object_type'], - 'object_id' => $row['object_id'], - 'track' => $row['track'], - 'track_id' => $row['id'] - ); - } // end while + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = array( + 'object_type' => $row['object_type'], + 'object_id' => $row['object_id'], + 'track' => $row['track'], + 'track_id' => $row['id'] + ); + } // end while - return $results; + return $results; - } // get_items + } // get_items - /** - * get_random_items - * This is the same as before but we randomize the buggers! - */ - public function get_random_items($limit='') { + /** + * get_random_items + * This is the same as before but we randomize the buggers! + */ + public function get_random_items($limit='') { - $results = array(); + $results = array(); - $limit_sql = $limit ? 'LIMIT ' . intval($limit) : ''; + $limit_sql = $limit ? 'LIMIT ' . intval($limit) : ''; - $sql = "SELECT `object_id`,`object_type` FROM `playlist_data` " . - "WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY RAND() $limit_sql"; - $db_results = Dba::read($sql); + $sql = "SELECT `object_id`,`object_type` FROM `playlist_data` " . + "WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY RAND() $limit_sql"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { + while ($row = Dba::fetch_assoc($db_results)) { - $results[] = array( - 'object_type' => $row['object_type'], - 'object_id' => $row['object_id'] - ); - } // end while + $results[] = array( + 'object_type' => $row['object_type'], + 'object_id' => $row['object_id'] + ); + } // end while - return $results; + return $results; - } // get_random_items + } // get_random_items - /** - * get_songs - * This is called by the batch script, because we can't pass in Dynamic objects they pulled once and then their - * target song.id is pushed into the array - */ - function get_songs() { + /** + * get_songs + * This is called by the batch script, because we can't pass in Dynamic objects they pulled once and then their + * target song.id is pushed into the array + */ + function get_songs() { - $results = array(); + $results = array(); - $sql = "SELECT * FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - if ($r['dyn_song']) { - $array = $this->get_dyn_songs($r['dyn_song']); - $results = array_merge($array,$results); - } - else { - $results[] = $r['object_id']; - } + while ($r = Dba::fetch_assoc($db_results)) { + if ($r['dyn_song']) { + $array = $this->get_dyn_songs($r['dyn_song']); + $results = array_merge($array,$results); + } + else { + $results[] = $r['object_id']; + } - } // end while + } // end while - return $results; + return $results; - } // get_songs + } // get_songs - /** - * get_song_count - * This simply returns a int of how many song elements exist in this playlist - * For now let's consider a dyn_song a single entry - */ - public function get_song_count() { + /** + * get_song_count + * This simply returns a int of how many song elements exist in this playlist + * For now let's consider a dyn_song a single entry + */ + public function get_song_count() { - $sql = "SELECT COUNT(`id`) FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::read($sql); + $sql = "SELECT COUNT(`id`) FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_row($db_results); + $results = Dba::fetch_row($db_results); - return $results['0']; + return $results['0']; - } // get_song_count + } // get_song_count - /** - * get_users - * This returns the specified users playlists as an array of - * playlist ids - */ - public static function get_users($user_id) { + /** + * get_users + * This returns the specified users playlists as an array of + * playlist ids + */ + public static function get_users($user_id) { - $user_id = Dba::escape($user_id); - $results = array(); + $user_id = Dba::escape($user_id); + $results = array(); - $sql = "SELECT `id` FROM `playlist` WHERE `user`='$user_id' ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `playlist` WHERE `user`='$user_id' ORDER BY `name`"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_users + } // get_users - /** - * update - * This function takes a key'd array of data and runs updates - */ - public function update($data) { + /** + * update + * This function takes a key'd array of data and runs updates + */ + public function update($data) { - if ($data['name'] != $this->name) { - $this->update_name($data['name']); - } - if ($data['pl_type'] != $this->type) { - $this->update_type($data['pl_type']); - } + if ($data['name'] != $this->name) { + $this->update_name($data['name']); + } + if ($data['pl_type'] != $this->type) { + $this->update_type($data['pl_type']); + } - } // update + } // update - /** - * update_type - * This updates the playlist type, it calls the generic update_item function - */ - private function update_type($new_type) { - - if ($this->_update_item('type',$new_type,'50')) { - $this->type = $new_type; - } - - } // update_type - - /** - * update_name - * This updates the playlist name, it calls the generic update_item function - */ - private function update_name($new_name) { - - if ($this->_update_item('name',$new_name,'50')) { - $this->name = $new_name; - } - - } // update_name + /** + * update_type + * This updates the playlist type, it calls the generic update_item function + */ + private function update_type($new_type) { + + if ($this->_update_item('type',$new_type,'50')) { + $this->type = $new_type; + } + + } // update_type + + /** + * update_name + * This updates the playlist name, it calls the generic update_item function + */ + private function update_name($new_name) { + + if ($this->_update_item('name',$new_name,'50')) { + $this->name = $new_name; + } + + } // update_name - /** - * _update_item - * This is the generic update function, it does the escaping and error checking - */ - private function _update_item($field,$value,$level) { + /** + * _update_item + * This is the generic update function, it does the escaping and error checking + */ + private function _update_item($field,$value,$level) { - if ($GLOBALS['user']->id != $this->user AND !Access::check('interface',$level)) { - return false; - } + if ($GLOBALS['user']->id != $this->user AND !Access::check('interface',$level)) { + return false; + } - $value = Dba::escape($value); + $value = Dba::escape($value); - $sql = "UPDATE `playlist` SET $field='$value' WHERE `id`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `playlist` SET $field='$value' WHERE `id`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::write($sql); - return $db_results; + return $db_results; - } // update_item + } // update_item - /** - * update_track_number - * This takes a playlist_data.id and a track (int) and updates the track value - */ - public function update_track_number($track_id,$track) { - - $playlist_id = Dba::escape($this->id); - $track_id = Dba::escape($track_id); - $track = Dba::escape($track); - - $sql = "UPDATE `playlist_data` SET `track`='$track' WHERE `id`='$track_id' AND `playlist`='$playlist_id'"; - $db_results = Dba::write($sql); - - } // update_track_number - - /** - * add_songs - * This takes an array of song_ids and then adds it to the playlist - * if you want to add a dyn_song you need to use the one shot function - * add_dyn_song - */ - public function add_songs($song_ids=array(),$ordered=false) { - - /* We need to pull the current 'end' track and then use that to - * append, rather then integrate take end track # and add it to - * $song->track add one to make sure it really is 'next' - */ - $sql = "SELECT `track` FROM `playlist_data` WHERE `playlist`='" . $this->id . "' ORDER BY `track` DESC LIMIT 1"; - $db_results = Dba::read($sql); - $data = Dba::fetch_assoc($db_results); - $base_track = $data['track']; - debug_event('add_songs', 'Track number: '.$base_track, '5'); - - foreach ($song_ids as $song_id) { - /* We need the songs track */ - $song = new Song($song_id); - - // Based on the ordered prop we use track + base or just $i++ - if (!$ordered) { - $track = Dba::escape($song->track+$base_track); - } - else { - $i++; - $track = Dba::escape($base_track+$i); - } - $id = Dba::escape($song->id); - $pl_id = Dba::escape($this->id); - - /* Don't insert dead songs */ - if ($id) { - $sql = "INSERT INTO `playlist_data` (`playlist`,`object_id`,`object_type`,`track`) " . - " VALUES ('$pl_id','$id','song','$track')"; - $db_results = Dba::write($sql); - } // if valid id + /** + * update_track_number + * This takes a playlist_data.id and a track (int) and updates the track value + */ + public function update_track_number($track_id,$track) { + + $playlist_id = Dba::escape($this->id); + $track_id = Dba::escape($track_id); + $track = Dba::escape($track); + + $sql = "UPDATE `playlist_data` SET `track`='$track' WHERE `id`='$track_id' AND `playlist`='$playlist_id'"; + $db_results = Dba::write($sql); + + } // update_track_number + + /** + * add_songs + * This takes an array of song_ids and then adds it to the playlist + * if you want to add a dyn_song you need to use the one shot function + * add_dyn_song + */ + public function add_songs($song_ids=array(),$ordered=false) { + + /* We need to pull the current 'end' track and then use that to + * append, rather then integrate take end track # and add it to + * $song->track add one to make sure it really is 'next' + */ + $sql = "SELECT `track` FROM `playlist_data` WHERE `playlist`='" . $this->id . "' ORDER BY `track` DESC LIMIT 1"; + $db_results = Dba::read($sql); + $data = Dba::fetch_assoc($db_results); + $base_track = $data['track']; + debug_event('add_songs', 'Track number: '.$base_track, '5'); + + foreach ($song_ids as $song_id) { + /* We need the songs track */ + $song = new Song($song_id); + + // Based on the ordered prop we use track + base or just $i++ + if (!$ordered) { + $track = Dba::escape($song->track+$base_track); + } + else { + $i++; + $track = Dba::escape($base_track+$i); + } + $id = Dba::escape($song->id); + $pl_id = Dba::escape($this->id); + + /* Don't insert dead songs */ + if ($id) { + $sql = "INSERT INTO `playlist_data` (`playlist`,`object_id`,`object_type`,`track`) " . + " VALUES ('$pl_id','$id','song','$track')"; + $db_results = Dba::write($sql); + } // if valid id - } // end foreach songs + } // end foreach songs - } // add_songs + } // add_songs - /** - * create - * This function creates an empty playlist, gives it a name and type - * Assumes $GLOBALS['user']->id as the user - */ - public static function create($name,$type) { + /** + * create + * This function creates an empty playlist, gives it a name and type + * Assumes $GLOBALS['user']->id as the user + */ + public static function create($name,$type) { - $name = Dba::escape($name); - $type = Dba::escape($type); - $user = Dba::escape($GLOBALS['user']->id); - $date = time(); + $name = Dba::escape($name); + $type = Dba::escape($type); + $user = Dba::escape($GLOBALS['user']->id); + $date = time(); - $sql = "INSERT INTO `playlist` (`name`,`user`,`type`,`date`) " . - " VALUES ('$name','$user','$type','$date')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `playlist` (`name`,`user`,`type`,`date`) " . + " VALUES ('$name','$user','$type','$date')"; + $db_results = Dba::write($sql); - $insert_id = Dba::insert_id(); + $insert_id = Dba::insert_id(); - return $insert_id; + return $insert_id; - } // create + } // create - /** - * set_items - * This calles the get_items function and sets it to $this->items which is an array in this object - */ - function set_items() { + /** + * set_items + * This calles the get_items function and sets it to $this->items which is an array in this object + */ + function set_items() { - $this->items = $this->get_items(); + $this->items = $this->get_items(); - } // set_items + } // set_items - /** - * normalize_tracks - * this takes the crazy out of order tracks - * and numbers them in a liner fashion, not allowing for - * the same track # twice, this is an optional funcition - */ - public function normalize_tracks() { - - /* First get all of the songs in order of their tracks */ - $sql = "SELECT `id` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track` ASC"; - $db_results = Dba::read($sql); - - $i = 1; - $results = array(); + /** + * normalize_tracks + * this takes the crazy out of order tracks + * and numbers them in a liner fashion, not allowing for + * the same track # twice, this is an optional funcition + */ + public function normalize_tracks() { + + /* First get all of the songs in order of their tracks */ + $sql = "SELECT `id` FROM `playlist_data` WHERE `playlist`='" . Dba::escape($this->id) . "' ORDER BY `track` ASC"; + $db_results = Dba::read($sql); + + $i = 1; + $results = array(); - while ($r = Dba::fetch_assoc($db_results)) { - $new_data = array(); - $new_data['id'] = $r['id']; - $new_data['track'] = $i; - $results[] = $new_data; - $i++; - } // end while results - - foreach($results as $data) { - $sql = "UPDATE `playlist_data` SET `track`='" . $data['track'] . "' WHERE" . - " `id`='" . $data['id'] . "'"; - $db_results = Dba::write($sql); - } // foreach re-ordered results - - return true; + while ($r = Dba::fetch_assoc($db_results)) { + $new_data = array(); + $new_data['id'] = $r['id']; + $new_data['track'] = $i; + $results[] = $new_data; + $i++; + } // end while results + + foreach($results as $data) { + $sql = "UPDATE `playlist_data` SET `track`='" . $data['track'] . "' WHERE" . + " `id`='" . $data['id'] . "'"; + $db_results = Dba::write($sql); + } // foreach re-ordered results + + return true; - } // normalize_tracks - - /** - * delete_track - * this deletes a single track, you specify the playlist_data.id here - */ - public function delete_track($id) { + } // normalize_tracks + + /** + * delete_track + * this deletes a single track, you specify the playlist_data.id here + */ + public function delete_track($id) { - $this_id = Dba::escape($this->id); - $id = Dba::escape($id); + $this_id = Dba::escape($this->id); + $id = Dba::escape($id); - $sql = "DELETE FROM `playlist_data` WHERE `playlist_data`.`playlist`='$this_id' AND `playlist_data`.`id`='$id' LIMIT 1"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `playlist_data` WHERE `playlist_data`.`playlist`='$this_id' AND `playlist_data`.`id`='$id' LIMIT 1"; + $db_results = Dba::write($sql); - return true; + return true; - } // delete_track + } // delete_track - /** - * delete - * This deletes the current playlist and all associated data - */ - public function delete() { + /** + * delete + * This deletes the current playlist and all associated data + */ + public function delete() { - $id = Dba::escape($this->id); + $id = Dba::escape($this->id); - $sql = "DELETE FROM `playlist_data` WHERE `playlist` = '$id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `playlist_data` WHERE `playlist` = '$id'"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `playlist` WHERE `id`='$id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `playlist` WHERE `id`='$id'"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `object_count` WHERE `object_type`='playlist' AND `object_id`='$id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `object_count` WHERE `object_type`='playlist' AND `object_id`='$id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // delete + } // delete } // class Playlist diff --git a/lib/class/playlist_object.abstract.php b/lib/class/playlist_object.abstract.php index d232d6d7f0..5cf0bdb764 100644 --- a/lib/class/playlist_object.abstract.php +++ b/lib/class/playlist_object.abstract.php @@ -1,5 +1,5 @@ f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title')); - $this->f_type = ($this->type == 'private') ? UI::get_icon('lock', T_('Private')) : ''; + $this->f_name = UI::truncate($this->name,Config::get('ellipse_threshold_title')); + $this->f_type = ($this->type == 'private') ? UI::get_icon('lock', T_('Private')) : ''; - $client = new User($this->user); + $client = new User($this->user); - $this->f_user = $client->fullname; + $this->f_user = $client->fullname; - } // format + } // format - /** - * has_access - * This function returns true or false if the current user - * has access to this playlist - */ - public function has_access() { + /** + * has_access + * This function returns true or false if the current user + * has access to this playlist + */ + public function has_access() { - if (!Access::check('interface','25')) { - return false; - } - if ($this->user == $GLOBALS['user']->id) { - return true; - } - else { - return Access::check('interface','100'); - } + if (!Access::check('interface','25')) { + return false; + } + if ($this->user == $GLOBALS['user']->id) { + return true; + } + else { + return Access::check('interface','100'); + } - return false; + return false; - } // has_access + } // has_access } // end playlist_object diff --git a/lib/class/plugin.class.php b/lib/class/plugin.class.php index 8878ba906c..a2ca4891e7 100644 --- a/lib/class/plugin.class.php +++ b/lib/class/plugin.class.php @@ -1,5 +1,5 @@ _get_info($name)) { - return false; - } - - return true; - - } // Constructor - - - /** - * _get_info - * This actually loads the config file for the plugin the name of the - * class contained within the config file must be Plugin[NAME OF FILE] - */ - public function _get_info($name) { - - /* Require the file we want */ - require_once Config::get('prefix') . '/modules/plugins/' . $name . '.plugin.php'; - - $plugin_name = "Ampache$name"; - - $this->_plugin = new $plugin_name(); - - if (!$this->is_valid()) { - return false; - } - - return true; - - } // _get_info - - /** - * get_plugins - * This returns an array of plugin names - */ - public static function get_plugins($type='') { - - $results = array(); - - // Open up the plugin dir - $handle = opendir(Config::get('prefix') . '/modules/plugins'); - - if (!is_resource($handle)) { - debug_event('Plugins','Unable to read plugins directory','1'); - } - - // Recurse the directory - while ($file = readdir($handle)) { - // Ignore non-plugin files - if (substr($file,-10,10) != 'plugin.php') { continue; } - if (is_dir($file)) { continue; } - $plugin_name = basename($file,'.plugin.php'); - if ($type != '') { - $plugin = new Plugin($plugin_name); - if (! Plugin::is_installed($plugin->_plugin->name)) { - debug_event('Plugins', 'Plugin ' . $plugin->_plugin->name . ' is not installed, skipping', 5); - continue; - } - if (! $plugin->is_valid()) { - debug_event('Plugins', 'Plugin ' . $plugin_name . ' is not valid, skipping', 5); - continue; - } - if (! method_exists($plugin->_plugin, $type)) { - debug_event('Plugins', 'Plugin ' . $plugin_name . ' does not support ' . $type . ', skipping', 5); - continue; - } - } - // It's a plugin record it - $results[$plugin_name] = $plugin_name; - } // end while - - // Little stupid but hey - ksort($results); - - return $results; - - } // get_plugins - - /** - * is_valid - * This checks to make sure the plugin has the required functions and - * settings. Ampache requires public variables name, description, and - * version (as an int), and methods install, uninstall, and load. We - * also check that Ampache's database version falls within the min/max - * version specified by the plugin. - */ - function is_valid() { - - /* Check the plugin to make sure it's got the needed vars */ - if (!strlen($this->_plugin->name)) { - return false; - } - if (!strlen($this->_plugin->description)) { - return false; - } - if (!strlen($this->_plugin->version)) { - return false; - } - - /* Make sure we've got the required methods */ - if (!method_exists($this->_plugin,'install')) { - return false; - } - - if (!method_exists($this->_plugin,'uninstall')) { - return false; - } - - if (!method_exists($this->_plugin,'load')) { - return false; - } - - /* Make sure it's within the version confines */ - $db_version = $this->get_ampache_db_version(); - - if ($db_version < $this->_plugin->min_ampache) { - return false; - } - - if ($db_version > $this->_plugin->max_ampache) { - return false; - } - - // We've passed all of the tests - return true; - - } // is_valid - - /** - * is_installed - * This checks to see if the specified plugin is currently installed in - * the database, it doesn't check the files for integrity - */ - public static function is_installed($plugin_name) { - - /* All we do is check the version */ - return self::get_plugin_version($plugin_name); - - } // is_installed - - /** - * install - * This runs the install function of the plugin and inserts a row into - * the update_info table to indicate that it's installed. - */ - public function install() { - if ($this->_plugin->install() && - $this->set_plugin_version($this->_plugin->version)) { - return true; - } - - return false; - } // install - - /** - * uninstall - * This runs the uninstall function of the plugin and removes the row - * from the update_info table to indicate that it isn't installed. - */ - public function uninstall() { - - $this->_plugin->uninstall(); - - $this->remove_plugin_version(); - - } // uninstall - - /** - * upgrade - * This runs the upgrade function of the plugin (if it exists) and - * updates the database to indicate our new version. - */ - public function upgrade() { - if (method_exists($this->_plugin, 'upgrade')) { - if($this->_plugin->upgrade()) { - $this->set_plugin_version($this->_plugin->version); - } - } - } // upgrade - - /** - * load - * This calls the plugin's load function - */ - public function load() { - $GLOBALS['user']->set_preferences(); - return $this->_plugin->load(); - } - - /** - * get_plugin_version - * This returns the version of the specified plugin - */ - public static function get_plugin_version($plugin_name) { + /* Base Variables */ + public $name; + + /* constructed objects */ + public $_plugin; + + /** + * Constructor + * This constructor loads the Plugin config file which defines how to + * install/uninstall the plugin from Ampache's database + */ + public function __construct($name) { + + /* Load the plugin */ + if (!$this->_get_info($name)) { + return false; + } + + return true; + + } // Constructor + + + /** + * _get_info + * This actually loads the config file for the plugin the name of the + * class contained within the config file must be Plugin[NAME OF FILE] + */ + public function _get_info($name) { + + /* Require the file we want */ + require_once Config::get('prefix') . '/modules/plugins/' . $name . '.plugin.php'; + + $plugin_name = "Ampache$name"; + + $this->_plugin = new $plugin_name(); + + if (!$this->is_valid()) { + return false; + } + + return true; + + } // _get_info + + /** + * get_plugins + * This returns an array of plugin names + */ + public static function get_plugins($type='') { + + $results = array(); + + // Open up the plugin dir + $handle = opendir(Config::get('prefix') . '/modules/plugins'); + + if (!is_resource($handle)) { + debug_event('Plugins','Unable to read plugins directory','1'); + } + + // Recurse the directory + while ($file = readdir($handle)) { + // Ignore non-plugin files + if (substr($file,-10,10) != 'plugin.php') { continue; } + if (is_dir($file)) { continue; } + $plugin_name = basename($file,'.plugin.php'); + if ($type != '') { + $plugin = new Plugin($plugin_name); + if (! Plugin::is_installed($plugin->_plugin->name)) { + debug_event('Plugins', 'Plugin ' . $plugin->_plugin->name . ' is not installed, skipping', 5); + continue; + } + if (! $plugin->is_valid()) { + debug_event('Plugins', 'Plugin ' . $plugin_name . ' is not valid, skipping', 5); + continue; + } + if (! method_exists($plugin->_plugin, $type)) { + debug_event('Plugins', 'Plugin ' . $plugin_name . ' does not support ' . $type . ', skipping', 5); + continue; + } + } + // It's a plugin record it + $results[$plugin_name] = $plugin_name; + } // end while + + // Little stupid but hey + ksort($results); + + return $results; + + } // get_plugins + + /** + * is_valid + * This checks to make sure the plugin has the required functions and + * settings. Ampache requires public variables name, description, and + * version (as an int), and methods install, uninstall, and load. We + * also check that Ampache's database version falls within the min/max + * version specified by the plugin. + */ + function is_valid() { + + /* Check the plugin to make sure it's got the needed vars */ + if (!strlen($this->_plugin->name)) { + return false; + } + if (!strlen($this->_plugin->description)) { + return false; + } + if (!strlen($this->_plugin->version)) { + return false; + } + + /* Make sure we've got the required methods */ + if (!method_exists($this->_plugin,'install')) { + return false; + } + + if (!method_exists($this->_plugin,'uninstall')) { + return false; + } + + if (!method_exists($this->_plugin,'load')) { + return false; + } + + /* Make sure it's within the version confines */ + $db_version = $this->get_ampache_db_version(); + + if ($db_version < $this->_plugin->min_ampache) { + return false; + } + + if ($db_version > $this->_plugin->max_ampache) { + return false; + } + + // We've passed all of the tests + return true; + + } // is_valid + + /** + * is_installed + * This checks to see if the specified plugin is currently installed in + * the database, it doesn't check the files for integrity + */ + public static function is_installed($plugin_name) { + + /* All we do is check the version */ + return self::get_plugin_version($plugin_name); + + } // is_installed + + /** + * install + * This runs the install function of the plugin and inserts a row into + * the update_info table to indicate that it's installed. + */ + public function install() { + if ($this->_plugin->install() && + $this->set_plugin_version($this->_plugin->version)) { + return true; + } + + return false; + } // install + + /** + * uninstall + * This runs the uninstall function of the plugin and removes the row + * from the update_info table to indicate that it isn't installed. + */ + public function uninstall() { + + $this->_plugin->uninstall(); + + $this->remove_plugin_version(); + + } // uninstall + + /** + * upgrade + * This runs the upgrade function of the plugin (if it exists) and + * updates the database to indicate our new version. + */ + public function upgrade() { + if (method_exists($this->_plugin, 'upgrade')) { + if($this->_plugin->upgrade()) { + $this->set_plugin_version($this->_plugin->version); + } + } + } // upgrade + + /** + * load + * This calls the plugin's load function + */ + public function load() { + $GLOBALS['user']->set_preferences(); + return $this->_plugin->load(); + } + + /** + * get_plugin_version + * This returns the version of the specified plugin + */ + public static function get_plugin_version($plugin_name) { - $name = Dba::escape('Plugin_' . $plugin_name); + $name = Dba::escape('Plugin_' . $plugin_name); - $sql = "SELECT * FROM `update_info` WHERE `key`='$name'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `update_info` WHERE `key`='$name'"; + $db_results = Dba::read($sql); - if ($results = Dba::fetch_assoc($db_results)) { - return $results['value']; - } + if ($results = Dba::fetch_assoc($db_results)) { + return $results['value']; + } - return false; + return false; - } // get_plugin_version + } // get_plugin_version - /** - * get_ampache_db_version - * This function returns the Ampache database version - */ - function get_ampache_db_version() { + /** + * get_ampache_db_version + * This function returns the Ampache database version + */ + function get_ampache_db_version() { - $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - return $results['value']; + return $results['value']; - } // get_ampache_db_version + } // get_ampache_db_version - /** - * set_plugin_version - * This sets the plugin version in the update_info table - */ - public function set_plugin_version($version) { + /** + * set_plugin_version + * This sets the plugin version in the update_info table + */ + public function set_plugin_version($version) { - $name = Dba::escape('Plugin_' . $this->_plugin->name); - $version = Dba::escape($version); + $name = Dba::escape('Plugin_' . $this->_plugin->name); + $version = Dba::escape($version); - $sql = "REPLACE INTO `update_info` SET `key`='$name', `value`='$version'"; - $db_results = Dba::read($sql); + $sql = "REPLACE INTO `update_info` SET `key`='$name', `value`='$version'"; + $db_results = Dba::read($sql); - return true; + return true; - } // set_plugin_version + } // set_plugin_version - /** - * remove_plugin_version - * This removes the version row from the db done on uninstall - */ - public function remove_plugin_version() { + /** + * remove_plugin_version + * This removes the version row from the db done on uninstall + */ + public function remove_plugin_version() { - $name = Dba::escape('Plugin_' . $this->_plugin->name); + $name = Dba::escape('Plugin_' . $this->_plugin->name); - $sql = "DELETE FROM `update_info` WHERE `key`='$name'"; - $db_results = Dba::read($sql); + $sql = "DELETE FROM `update_info` WHERE `key`='$name'"; + $db_results = Dba::read($sql); - return true; + return true; - } // remove_plugin_version + } // remove_plugin_version } //end plugin class ?> diff --git a/lib/class/preference.class.php b/lib/class/preference.class.php index e342e65a52..2515b750d3 100644 --- a/lib/class/preference.class.php +++ b/lib/class/preference.class.php @@ -1,5 +1,5 @@ username . ' attempted to update ' . $name . ' but does not have sufficient permissions','3'); - } + /** + * __constructor + * This does nothing... amazing isn't it! + */ + private function __construct() { + + // Rien a faire + + } // __construct + + /** + * update + * This updates a single preference from the given name or id + */ + public static function update($preference,$user_id,$value,$applytoall='') { + + // First prepare + if (!is_numeric($preference)) { + $id = self::id_from_name($preference); + $name = $preference; + } + else { + $name = self::name_from_id($preference); + $id = $preference; + } + if ($applytoall AND Access::check('interface','100')) { + $user_check = ""; + } + else { + $user_check = " AND `user`='$user_id'"; + } + + // Now do + if (self::has_access($name)) { + $value = Dba::escape($value); + $user_id = Dba::escape($user_id); + $sql = "UPDATE `user_preference` SET `value`='$value' " . + "WHERE `preference`='$id'$user_check"; + $db_results = Dba::write($sql); + Preference::clear_from_session(); + return true; + } + else { + debug_event('denied',$GLOBALS['user']->username . ' attempted to update ' . $name . ' but does not have sufficient permissions','3'); + } - return false; - } // update - - /** - * update_level - * This takes a preference ID and updates the level required to update it (performed by an admin) - */ - public static function update_level($preference,$level) { - - // First prepare - if (!is_numeric($preference)) { - $preference_id = self::id_from_name($preference); - } - else { - $preference_id = $preference; - } + return false; + } // update + + /** + * update_level + * This takes a preference ID and updates the level required to update it (performed by an admin) + */ + public static function update_level($preference,$level) { + + // First prepare + if (!is_numeric($preference)) { + $preference_id = self::id_from_name($preference); + } + else { + $preference_id = $preference; + } - $preference_id = Dba::escape($preference_id); - $level = Dba::escape($level); + $preference_id = Dba::escape($preference_id); + $level = Dba::escape($level); - $sql = "UPDATE `preference` SET `level`='$level' WHERE `id`='$preference_id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `level`='$level' WHERE `id`='$preference_id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // update_level + } // update_level - /** - * update_all - * This takes a preference id and a value and updates all users with the new info - */ - public static function update_all($preference_id,$value) { + /** + * update_all + * This takes a preference id and a value and updates all users with the new info + */ + public static function update_all($preference_id,$value) { - $preference_id = Dba::escape($preference_id); - $value = Dba::escape($value); + $preference_id = Dba::escape($preference_id); + $value = Dba::escape($value); - $sql = "UPDATE `user_preference` SET `value`='$value' WHERE `preference`='$preference_id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `user_preference` SET `value`='$value' WHERE `preference`='$preference_id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // update_all + } // update_all - /** - * exists - * This just checks to see if a preference currently exists - */ - public static function exists($preference) { + /** + * exists + * This just checks to see if a preference currently exists + */ + public static function exists($preference) { - // We assume it's the name - $name = Dba::escape($preference); - $sql = "SELECT * FROM `preference` WHERE `name`='$name'"; - $db_results = Dba::read($sql); + // We assume it's the name + $name = Dba::escape($preference); + $sql = "SELECT * FROM `preference` WHERE `name`='$name'"; + $db_results = Dba::read($sql); - return Dba::num_rows($db_results); + return Dba::num_rows($db_results); - } // exists + } // exists - /** - * has_access - * This checks to see if the current user has access to modify this preference - * as defined by the preference name - */ - public static function has_access($preference) { + /** + * has_access + * This checks to see if the current user has access to modify this preference + * as defined by the preference name + */ + public static function has_access($preference) { - // Nothing for those demo thugs - if (Config::get('demo_mode')) { return false; } + // Nothing for those demo thugs + if (Config::get('demo_mode')) { return false; } - $preference = Dba::escape($preference); + $preference = Dba::escape($preference); - $sql = "SELECT `level` FROM `preference` WHERE `name`='$preference'"; - $db_results = Dba::read($sql); - $data = Dba::fetch_assoc($db_results); + $sql = "SELECT `level` FROM `preference` WHERE `name`='$preference'"; + $db_results = Dba::read($sql); + $data = Dba::fetch_assoc($db_results); - if (Access::check('interface',$data['level'])) { - return true; - } + if (Access::check('interface',$data['level'])) { + return true; + } - return false; + return false; - } // has_access + } // has_access - /** - * id_from_name - * This takes a name and returns the id - */ - public static function id_from_name($name) { + /** + * id_from_name + * This takes a name and returns the id + */ + public static function id_from_name($name) { - $name = Dba::escape($name); + $name = Dba::escape($name); - $sql = "SELECT `id` FROM `preference` WHERE `name`='$name'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `preference` WHERE `name`='$name'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - return $row['id']; + return $row['id']; - } // id_from_name + } // id_from_name - /** - * name_from_id - * This returns the name from an id, it's the exact opposite - * of the function above it, amazing! - */ - public static function name_from_id($id) { + /** + * name_from_id + * This returns the name from an id, it's the exact opposite + * of the function above it, amazing! + */ + public static function name_from_id($id) { - $id = Dba::escape($id); + $id = Dba::escape($id); - $sql = "SELECT `name` FROM `preference` WHERE `id`='$id'"; - $db_results = Dba::read($sql); + $sql = "SELECT `name` FROM `preference` WHERE `id`='$id'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - return $row['name']; + return $row['name']; - } // name_from_id + } // name_from_id - /** - * get_catagories - * This returns an array of the names of the different possible sections - * it ignores the 'internal' catagory - */ - public static function get_catagories() { + /** + * get_catagories + * This returns an array of the names of the different possible sections + * it ignores the 'internal' catagory + */ + public static function get_catagories() { - $sql = "SELECT `preference`.`catagory` FROM `preference` GROUP BY `catagory` ORDER BY `catagory`"; - $db_results = Dba::read($sql); + $sql = "SELECT `preference`.`catagory` FROM `preference` GROUP BY `catagory` ORDER BY `catagory`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - if ($row['catagory'] != 'internal') { - $results[] = $row['catagory']; - } - } // end while + while ($row = Dba::fetch_assoc($db_results)) { + if ($row['catagory'] != 'internal') { + $results[] = $row['catagory']; + } + } // end while - return $results; + return $results; - } // get_catagories + } // get_catagories - /** - * get_all - * This returns a nice flat array of all of the possible preferences for the specified user - */ - public static function get_all($user_id) { + /** + * get_all + * This returns a nice flat array of all of the possible preferences for the specified user + */ + public static function get_all($user_id) { - $user_id = Dba::escape($user_id); + $user_id = Dba::escape($user_id); - if ($user_id != '-1') { - $user_limit = "AND `preference`.`catagory` != 'system'"; - } + if ($user_id != '-1') { + $user_limit = "AND `preference`.`catagory` != 'system'"; + } - $sql = "SELECT `preference`.`name`,`preference`.`description`,`user_preference`.`value` FROM `preference` " . - " INNER JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` " . - " WHERE `user_preference`.`user`='$user_id' AND `preference`.`catagory` != 'internal' $user_limit " . - " ORDER BY `preference`.`description`"; - $db_results = Dba::read($sql); + $sql = "SELECT `preference`.`name`,`preference`.`description`,`user_preference`.`value` FROM `preference` " . + " INNER JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` " . + " WHERE `user_preference`.`user`='$user_id' AND `preference`.`catagory` != 'internal' $user_limit " . + " ORDER BY `preference`.`description`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = array('name'=>$row['name'],'level'=>$row['level'],'description'=>$row['description'],'value'=>$row['value']); - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = array('name'=>$row['name'],'level'=>$row['level'],'description'=>$row['description'],'value'=>$row['value']); + } - return $results; + return $results; - } // get_all + } // get_all - /** - * insert - * This inserts a new preference into the preference table - * it does NOT sync up the users, that should be done independtly - */ - public static function insert($name,$description,$default,$level,$type,$catagory) { + /** + * insert + * This inserts a new preference into the preference table + * it does NOT sync up the users, that should be done independtly + */ + public static function insert($name,$description,$default,$level,$type,$catagory) { - // Clean em up - $name = Dba::escape($name); - $description = Dba::escape($description); - $default = Dba::escape($default); - $level = Dba::escape($level); - $type = Dba::escape($type); - $catagory = Dba::escape($catagory); + // Clean em up + $name = Dba::escape($name); + $description = Dba::escape($description); + $default = Dba::escape($default); + $level = Dba::escape($level); + $type = Dba::escape($type); + $catagory = Dba::escape($catagory); - $sql = "INSERT INTO `preference` (`name`,`description`,`value`,`level`,`type`,`catagory`) " . - "VALUES ('$name','$description','$default','$level','$type','$catagory')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `preference` (`name`,`description`,`value`,`level`,`type`,`catagory`) " . + "VALUES ('$name','$description','$default','$level','$type','$catagory')"; + $db_results = Dba::write($sql); - if (!$db_results) { return false; } + if (!$db_results) { return false; } - return true; + return true; - } // insert + } // insert - /** - * delete - * This deletes the specified preference, a name or a ID can be passed - */ - public static function delete($preference) { + /** + * delete + * This deletes the specified preference, a name or a ID can be passed + */ + public static function delete($preference) { - // First prepare - if (!is_numeric($preference)) { - $name = Dba::escape($preference); - $sql = "DELETE FROM `preference` WHERE `name`='$name'"; - } - else { - $id = Dba::escape($preference); - $sql = "DELETE FROM `preference` WHERE `id`='$id'"; - } - - $db_results = Dba::write($sql); - - self::rebuild_preferences(); - - } // delete - - /** - * rename - * This renames a preference in the database - */ - public static function rename($old, $new) { - $old = Dba::escape($old); - $new = Dba::escape($new); - - $sql = "UPDATE `preference` SET `name`='$new' WHERE `name`='$old'"; - $db_results = Dba::write($sql); - } - - /** - * rebuild_preferences - * This removes any garbage and then adds back in anything missing preferences wise - */ - public static function rebuild_preferences() { - - // First remove garbage - $sql = "DELETE FROM `user_preference` USING `user_preference` LEFT JOIN `preference` ON `preference`.`id`=`user_preference`.`preference` " . - "WHERE `preference`.`id` IS NULL"; - $db_results = Dba::write($sql); - - // Now add anything that we are missing back in, except System - $sql = "SELECT * FROM `preference` WHERE `type`!='system'"; - //FIXME: Uhh WTF shouldn't there be something here?? - - } // rebuild_preferences - - /** - * fix_preferences - * This takes the preferences, explodes what needs to - * become an array and boolean everythings - */ - public static function fix_preferences($results) { - $arrays = array('auth_methods', 'getid3_tag_order', - 'metadata_order', 'art_order', 'amazon_base_urls'); - - foreach ($arrays as $item) { - $results[$item] = trim($results[$item]) - ? explode(',', $results[$item]) - : array(); - } - - foreach ($results as $key=>$data) { - if (!is_array($data)) { - if (strcasecmp($data,"true") == "0") { $results[$key] = 1; } - if (strcasecmp($data,"false") == "0") { $results[$key] = 0; } - } - } - - return $results; - - } // fix_preferences - - /** - * load_from_session - * This loads the preferences from the session rather then creating a connection to the database - */ - public static function load_from_session($uid=-1) { - - if (is_array($_SESSION['userdata']['preferences']) AND $_SESSION['userdata']['uid'] == $uid) { - Config::set_by_array($_SESSION['userdata']['preferences'], true); - return true; - } - - return false; - - } // load_from_session - - /** - * clear_from_session - * This clears the users preferences, this is done whenever modifications are made to the preferences - * or the admin resets something - */ - public static function clear_from_session() { - - unset($_SESSION['userdata']['preferences']); - - } // clear_from_session - - /** - * is_boolean - * This returns true / false if the preference in question is a boolean preference - * This is currently only used by the debug view, could be used other places.. wouldn't be a half - * bad idea - */ - public static function is_boolean($key) { - - $boolean_array = array('session_cookiesecure','require_session', - 'access_control','require_localnet_session', - 'downsample_remote','track_user_ip', - 'xml_rpc','allow_zip_download', - 'file_zip_download','ratings', - 'shoutbox','resize_images', - 'show_album_art','allow_public_registration', - 'captcha_public_reg','admin_notify_reg', - 'use_rss','download','force_http_play','cookie_secure', - 'allow_stream_playback','allow_democratic_playback', - 'use_auth','allow_localplay_playback','debug','lock_songs', - 'transcode_m4a','transcode_mp3','transcode_ogg','transcode_flac', - 'shoutcast_active','httpq_active','show_lyrics'); - - if (in_array($key,$boolean_array)) { - return true; - } - - return false; - - } // is_boolean - - /** - * init - * This grabs the preferences and then loads them into conf it should be run on page load - * to initialize the needed variables - */ - public static function init() { - - $user_id = $GLOBALS['user']->id ? Dba::escape($GLOBALS['user']->id) : '-1'; - - // First go ahead and try to load it from the preferences - if (self::load_from_session($user_id)) { - return true; - } - - /* Get Global Preferences */ - $sql = "SELECT `preference`.`name`,`user_preference`.`value`,`syspref`.`value` AS `system_value` FROM `preference` " . - "LEFT JOIN `user_preference` `syspref` ON `syspref`.`preference`=`preference`.`id` AND `syspref`.`user`='-1' AND `preference`.`catagory`='system' " . - "LEFT JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` AND `user_preference`.`user`='$user_id' AND `preference`.`catagory`!='system'"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $value = $row['system_value'] ? $row['system_value'] : $row['value']; - $name = $row['name']; - $results[$name] = $value; - } // end while sys prefs - - /* Set the Theme mojo */ - if (strlen($results['theme_name']) > 0) { - $results['theme_path'] = '/themes/' . $results['theme_name']; - } - // Default to the classic theme if we don't get anything from their - // preferenecs because we're going to want at least something otherwise - // the page is going to be really ugly - else { - $results['theme_path'] = '/themes/classic'; - } - - Config::set_by_array($results, true); - $_SESSION['userdata']['preferences'] = $results; - $_SESSION['userdata']['uid'] = $user_id; - - } // init + // First prepare + if (!is_numeric($preference)) { + $name = Dba::escape($preference); + $sql = "DELETE FROM `preference` WHERE `name`='$name'"; + } + else { + $id = Dba::escape($preference); + $sql = "DELETE FROM `preference` WHERE `id`='$id'"; + } + + $db_results = Dba::write($sql); + + self::rebuild_preferences(); + + } // delete + + /** + * rename + * This renames a preference in the database + */ + public static function rename($old, $new) { + $old = Dba::escape($old); + $new = Dba::escape($new); + + $sql = "UPDATE `preference` SET `name`='$new' WHERE `name`='$old'"; + $db_results = Dba::write($sql); + } + + /** + * rebuild_preferences + * This removes any garbage and then adds back in anything missing preferences wise + */ + public static function rebuild_preferences() { + + // First remove garbage + $sql = "DELETE FROM `user_preference` USING `user_preference` LEFT JOIN `preference` ON `preference`.`id`=`user_preference`.`preference` " . + "WHERE `preference`.`id` IS NULL"; + $db_results = Dba::write($sql); + + // Now add anything that we are missing back in, except System + $sql = "SELECT * FROM `preference` WHERE `type`!='system'"; + //FIXME: Uhh WTF shouldn't there be something here?? + + } // rebuild_preferences + + /** + * fix_preferences + * This takes the preferences, explodes what needs to + * become an array and boolean everythings + */ + public static function fix_preferences($results) { + $arrays = array('auth_methods', 'getid3_tag_order', + 'metadata_order', 'art_order', 'amazon_base_urls'); + + foreach ($arrays as $item) { + $results[$item] = trim($results[$item]) + ? explode(',', $results[$item]) + : array(); + } + + foreach ($results as $key=>$data) { + if (!is_array($data)) { + if (strcasecmp($data,"true") == "0") { $results[$key] = 1; } + if (strcasecmp($data,"false") == "0") { $results[$key] = 0; } + } + } + + return $results; + + } // fix_preferences + + /** + * load_from_session + * This loads the preferences from the session rather then creating a connection to the database + */ + public static function load_from_session($uid=-1) { + + if (is_array($_SESSION['userdata']['preferences']) AND $_SESSION['userdata']['uid'] == $uid) { + Config::set_by_array($_SESSION['userdata']['preferences'], true); + return true; + } + + return false; + + } // load_from_session + + /** + * clear_from_session + * This clears the users preferences, this is done whenever modifications are made to the preferences + * or the admin resets something + */ + public static function clear_from_session() { + + unset($_SESSION['userdata']['preferences']); + + } // clear_from_session + + /** + * is_boolean + * This returns true / false if the preference in question is a boolean preference + * This is currently only used by the debug view, could be used other places.. wouldn't be a half + * bad idea + */ + public static function is_boolean($key) { + + $boolean_array = array('session_cookiesecure','require_session', + 'access_control','require_localnet_session', + 'downsample_remote','track_user_ip', + 'xml_rpc','allow_zip_download', + 'file_zip_download','ratings', + 'shoutbox','resize_images', + 'show_album_art','allow_public_registration', + 'captcha_public_reg','admin_notify_reg', + 'use_rss','download','force_http_play','cookie_secure', + 'allow_stream_playback','allow_democratic_playback', + 'use_auth','allow_localplay_playback','debug','lock_songs', + 'transcode_m4a','transcode_mp3','transcode_ogg','transcode_flac', + 'shoutcast_active','httpq_active','show_lyrics'); + + if (in_array($key,$boolean_array)) { + return true; + } + + return false; + + } // is_boolean + + /** + * init + * This grabs the preferences and then loads them into conf it should be run on page load + * to initialize the needed variables + */ + public static function init() { + + $user_id = $GLOBALS['user']->id ? Dba::escape($GLOBALS['user']->id) : '-1'; + + // First go ahead and try to load it from the preferences + if (self::load_from_session($user_id)) { + return true; + } + + /* Get Global Preferences */ + $sql = "SELECT `preference`.`name`,`user_preference`.`value`,`syspref`.`value` AS `system_value` FROM `preference` " . + "LEFT JOIN `user_preference` `syspref` ON `syspref`.`preference`=`preference`.`id` AND `syspref`.`user`='-1' AND `preference`.`catagory`='system' " . + "LEFT JOIN `user_preference` ON `user_preference`.`preference`=`preference`.`id` AND `user_preference`.`user`='$user_id' AND `preference`.`catagory`!='system'"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $value = $row['system_value'] ? $row['system_value'] : $row['value']; + $name = $row['name']; + $results[$name] = $value; + } // end while sys prefs + + /* Set the Theme mojo */ + if (strlen($results['theme_name']) > 0) { + $results['theme_path'] = '/themes/' . $results['theme_name']; + } + // Default to the classic theme if we don't get anything from their + // preferenecs because we're going to want at least something otherwise + // the page is going to be really ugly + else { + $results['theme_path'] = '/themes/classic'; + } + + Config::set_by_array($results, true); + $_SESSION['userdata']['preferences'] = $results; + $_SESSION['userdata']['uid'] = $user_id; + + } // init } // end Preference class diff --git a/lib/class/query.class.php b/lib/class/query.class.php index ea451a4551..84729b8fa6 100644 --- a/lib/class/query.class.php +++ b/lib/class/query.class.php @@ -1,5 +1,5 @@ reset(); - $data = Dba::escape(serialize($this->_state)); - - $sql = "INSERT INTO `tmp_browse` (`sid`, `data`) " . - "VALUES('$sid', '$data')"; - $db_results = Dba::write($sql); - $this->id = Dba::insert_id(); - - return true; - } - - $this->id = $id; - - $sql = "SELECT `data` FROM `tmp_browse` " . - "WHERE `id`='$id' AND `sid`='$sid'"; - - $db_results = Dba::read($sql); - - if ($results = Dba::fetch_assoc($db_results)) { - $this->_state = unserialize($results['data']); - return true; - } - - Error::add('browse', T_('Browse not found or expired, try reloading the page')); - return false; - } - - /** - * _auto_init - * Automatically called when the class is loaded. - * Populate static arrays if necessary - */ - public static function _auto_init() { - if (is_array(self::$allowed_filters)) { - return true; - } - - self::$allowed_filters = array( - 'album' => array( - 'add_lt', - 'add_gt', - 'update_lt', - 'update_gt', - 'show_art', - 'starts_with', - 'exact_match', - 'alpha_match', - 'catalog' - ), - 'artist' => array( - 'add_lt', - 'add_gt', - 'update_lt', - 'update_gt', - 'exact_match', - 'alpha_match', - 'starts_with', - 'tag', - 'catalog' - ), - 'song' => array( - 'add_lt', - 'add_gt', - 'update_lt', - 'update_gt', - 'exact_match', - 'alpha_match', - 'starts_with', - 'tag', - 'catalog' - ), - 'live_stream' => array( - 'alpha_match', - 'starts_with' - ), - 'playlist' => array( - 'alpha_match', - 'starts_with' - ), - 'smartplaylist' => array( - 'alpha_match', - 'starts_with' - ), - 'tag' => array( - 'tag', - 'object_type', - 'exact_match', - 'alpha_match' - ), - 'video' => array( - 'starts_with', - 'exact_match', - 'alpha_match' - ) - ); - - if (Access::check('interface','50')) { - array_push(self::$allowed_filters['playlist'], 'playlist_type'); - } - - self::$allowed_sorts = array( - 'playlist_song' => array( - 'title', - 'year', - 'track', - 'time', - 'album', - 'artist' - ), - 'song' => array( - 'title', - 'year', - 'track', - 'time', - 'album', - 'artist' - ), - 'artist' => array( - 'name', - 'album' - ), - 'tag' => array( - 'tag' - ), - 'album' => array( - 'name', - 'year', - 'artist' - ), - 'playlist' => array( - 'name', - 'user' - ), - 'smartplaylist' => array( - 'name', - 'user' - ), - 'shoutbox' => array( - 'date', - 'user', - 'sticky' - ), - 'live_stream' => array( - 'name', - 'call_sign', - 'frequency' - ), - 'video' => array( - 'title', - 'resolution', - 'length', - 'codec' - ), - 'user' => array( - 'fullname', - 'username', - 'last_seen', - 'create_date' - ) - ); - } - - /** - * gc - * This cleans old data out of the table - */ - public static function gc() { - $sql = "DELETE FROM `tmp_browse` USING `tmp_browse` LEFT JOIN ". - "`session` ON `session`.`id`=`tmp_browse`.`sid` " . - "WHERE `session`.`id` IS NULL"; - $db_results = Dba::write($sql); - } - - /** - * set_filter - * This saves the filter data we pass it. - */ - public function set_filter($key, $value) { - - switch ($key) { - case 'tag': - if (is_array($value)) { - $this->_state['filter'][$key] = $value; - } - elseif (is_numeric($value)) { - $this->_state['filter'][$key] = array($value); - } - else { - $this->_state['filter'][$key] = array(); - } - break; - case 'artist': - case 'catalog': - case 'album': - $this->_state['filter'][$key] = $value; - break; - case 'min_count': - case 'unplayed': - case 'rated': - - break; - case 'add_lt': - case 'add_gt': - case 'update_lt': - case 'update_gt': - $this->_state['filter'][$key] = intval($value); - break; - case 'exact_match': - case 'alpha_match': - case 'starts_with': - if ($this->is_static_content()) { return false; } - $this->_state['filter'][$key] = $value; - break; - case 'playlist_type': - // Must be a content manager to turn this off - if ($this->_state['filter'][$key] AND Access::check('interface','50')) { unset($this->_state['filter'][$key]); } - else { $this->_state['filter'][$key] = '1'; } - break; - default: - // Rien a faire - return false; - break; - } // end switch - - // If we've set a filter we need to reset the totals - $this->reset_total(); - $this->set_start(0); - - return true; - - } // set_filter - - /** - * reset - * Reset everything, this should only be called when we are starting - * fresh - */ - public function reset() { - - $this->reset_base(); - $this->reset_filters(); - $this->reset_total(); - $this->reset_join(); - $this->reset_select(); - $this->reset_having(); - $this->set_static_content(false); - $this->set_is_simple(false); - $this->set_start(0); - $this->set_offset(Config::get('offset_limit') ? Config::get('offset_limit') : '25'); - - } // reset - - /** - * reset_base - * this resets the base string - */ - public function reset_base() { - - $this->_state['base'] = NULL; - - } // reset_base - - /** - * reset_select - * This resets the select fields that we've added so far - */ - public function reset_select() { - - $this->_state['select'] = array(); - - } // reset_select - - /** - * reset_having - * Null out the having clause - */ - public function reset_having() { - - unset($this->_state['having']); - - } // reset_having - - /** - * reset_join - * clears the joins if there are any - */ - public function reset_join() { - - unset($this->_state['join']); - - } // reset_join - - /** - * reset_filter - * This is a wrapper function that resets the filters - */ - public function reset_filters() { - - $this->_state['filter'] = array(); - - } // reset_filters - - /** - * reset_total - * This resets the total for the browse type - */ - public function reset_total() { - - unset($this->_state['total']); - - } // reset_total - - /** - * get_filter - * returns the specified filter value - */ - public function get_filter($key) { - - // Simple enough, but if we ever move this crap - // If we ever move this crap what? - return isset($this->_state['filter'][$key]) - ? $this->_state['filter'][$key] - : false; - - } // get_filter - - /** - * get_start - * This returns the current value of the start - */ - public function get_start() { - - return $this->_state['start']; - - } // get_start - - /** - * get_offset - * This returns the current offset - */ - public function get_offset() { - if ($this->is_static_content()) { - return $this->get_total(); - } - - return $this->_state['offset']; - } // get_offset - - /** - * set_total - * This sets the total number of objects - */ - public function set_total($total) { - $this->_state['total'] = $total; - } - - /** - * get_total - * This returns the total number of objects for this current sort type. - * If it's already cached used it. if they pass us an array then use - * that. - */ - public function get_total($objects = null) { - - // If they pass something then just return that - if (is_array($objects) and !$this->is_simple()) { - return count($objects); - } - - // See if we can find it in the cache - if (isset($this->_state['total'])) { - return $this->_state['total']; - } - - $db_results = Dba::read($this->get_sql(false)); - $num_rows = Dba::num_rows($db_results); - - $this->_state['total'] = $num_rows; - - return $num_rows; - - } // get_total - - /** - * get_allowed_filters - * This returns an array of the allowed filters based on the type of - * object we are working with, this is used to display the 'filter' - * sidebar stuff. - */ - public static function get_allowed_filters($type) { - return isset(self::$allowed_filters[$type]) - ? self::$allowed_filters[$type] - : array(); - } // get_allowed_filters - - /** - * set_type - * This sets the type of object that we want to browse by - * we do this here so we only have to maintain a single whitelist - * and if I want to change the location I only have to do it here - */ - public function set_type($type) { - - switch($type) { - case 'user': - case 'video': - case 'playlist': - case 'playlist_song': - case 'smartplaylist': - case 'song': - case 'flagged': - case 'catalog': - case 'album': - case 'artist': - case 'tag': - case 'playlist_localplay': - case 'shoutbox': - case 'live_stream': - case 'democratic': - // Set it - $this->_state['type'] = $type; - $this->set_base_sql(true); - break; - default: - // Rien a faire - break; - } // end type whitelist - } // set_type - - /** - * get_type - * This returns the type of the browse we currently are using - */ - public function get_type() { - - return $this->_state['type']; - - } // get_type - - /** - * set_sort - * This sets the current sort(s) - */ - public function set_sort($sort,$order='') { - - // If it's not in our list, smeg off! - if (!in_array($sort, self::$allowed_sorts[$this->get_type()])) { - return false; - } - - if ($order) { - $order = ($order == 'DESC') ? 'DESC' : 'ASC'; - $this->_state['sort'] = array(); - $this->_state['sort'][$sort] = $order; - } - elseif ($this->_state['sort'][$sort] == 'DESC') { - // Reset it till I can figure out how to interface the hotness - $this->_state['sort'] = array(); - $this->_state['sort'][$sort] = 'ASC'; - } - else { - // Reset it till I can figure out how to interface the hotness - $this->_state['sort'] = array(); - $this->_state['sort'][$sort] = 'DESC'; - } - - $this->resort_objects(); - - } // set_sort - - /** - * set_offset - * This sets the current offset of this query - */ - public function set_offset($offset) { - - $this->_state['offset'] = abs($offset); - - } // set_offset + public $id; + public $catalog; + + protected $_state = array(); + protected $_cache; + + private static $allowed_filters; + private static $allowed_sorts; + + /** + * constructor + * This should be called + */ + public function __construct($id = null) { + $sid = Dba::escape(session_id()); + + if (is_null($id)) { + $this->reset(); + $data = Dba::escape(serialize($this->_state)); + + $sql = "INSERT INTO `tmp_browse` (`sid`, `data`) " . + "VALUES('$sid', '$data')"; + $db_results = Dba::write($sql); + $this->id = Dba::insert_id(); + + return true; + } + + $this->id = $id; + + $sql = "SELECT `data` FROM `tmp_browse` " . + "WHERE `id`='$id' AND `sid`='$sid'"; + + $db_results = Dba::read($sql); + + if ($results = Dba::fetch_assoc($db_results)) { + $this->_state = unserialize($results['data']); + return true; + } + + Error::add('browse', T_('Browse not found or expired, try reloading the page')); + return false; + } + + /** + * _auto_init + * Automatically called when the class is loaded. + * Populate static arrays if necessary + */ + public static function _auto_init() { + if (is_array(self::$allowed_filters)) { + return true; + } + + self::$allowed_filters = array( + 'album' => array( + 'add_lt', + 'add_gt', + 'update_lt', + 'update_gt', + 'show_art', + 'starts_with', + 'exact_match', + 'alpha_match', + 'catalog' + ), + 'artist' => array( + 'add_lt', + 'add_gt', + 'update_lt', + 'update_gt', + 'exact_match', + 'alpha_match', + 'starts_with', + 'tag', + 'catalog' + ), + 'song' => array( + 'add_lt', + 'add_gt', + 'update_lt', + 'update_gt', + 'exact_match', + 'alpha_match', + 'starts_with', + 'tag', + 'catalog' + ), + 'live_stream' => array( + 'alpha_match', + 'starts_with' + ), + 'playlist' => array( + 'alpha_match', + 'starts_with' + ), + 'smartplaylist' => array( + 'alpha_match', + 'starts_with' + ), + 'tag' => array( + 'tag', + 'object_type', + 'exact_match', + 'alpha_match' + ), + 'video' => array( + 'starts_with', + 'exact_match', + 'alpha_match' + ) + ); + + if (Access::check('interface','50')) { + array_push(self::$allowed_filters['playlist'], 'playlist_type'); + } + + self::$allowed_sorts = array( + 'playlist_song' => array( + 'title', + 'year', + 'track', + 'time', + 'album', + 'artist' + ), + 'song' => array( + 'title', + 'year', + 'track', + 'time', + 'album', + 'artist' + ), + 'artist' => array( + 'name', + 'album' + ), + 'tag' => array( + 'tag' + ), + 'album' => array( + 'name', + 'year', + 'artist' + ), + 'playlist' => array( + 'name', + 'user' + ), + 'smartplaylist' => array( + 'name', + 'user' + ), + 'shoutbox' => array( + 'date', + 'user', + 'sticky' + ), + 'live_stream' => array( + 'name', + 'call_sign', + 'frequency' + ), + 'video' => array( + 'title', + 'resolution', + 'length', + 'codec' + ), + 'user' => array( + 'fullname', + 'username', + 'last_seen', + 'create_date' + ) + ); + } + + /** + * gc + * This cleans old data out of the table + */ + public static function gc() { + $sql = "DELETE FROM `tmp_browse` USING `tmp_browse` LEFT JOIN ". + "`session` ON `session`.`id`=`tmp_browse`.`sid` " . + "WHERE `session`.`id` IS NULL"; + $db_results = Dba::write($sql); + } + + /** + * set_filter + * This saves the filter data we pass it. + */ + public function set_filter($key, $value) { + + switch ($key) { + case 'tag': + if (is_array($value)) { + $this->_state['filter'][$key] = $value; + } + elseif (is_numeric($value)) { + $this->_state['filter'][$key] = array($value); + } + else { + $this->_state['filter'][$key] = array(); + } + break; + case 'artist': + case 'catalog': + case 'album': + $this->_state['filter'][$key] = $value; + break; + case 'min_count': + case 'unplayed': + case 'rated': + + break; + case 'add_lt': + case 'add_gt': + case 'update_lt': + case 'update_gt': + $this->_state['filter'][$key] = intval($value); + break; + case 'exact_match': + case 'alpha_match': + case 'starts_with': + if ($this->is_static_content()) { return false; } + $this->_state['filter'][$key] = $value; + break; + case 'playlist_type': + // Must be a content manager to turn this off + if ($this->_state['filter'][$key] AND Access::check('interface','50')) { unset($this->_state['filter'][$key]); } + else { $this->_state['filter'][$key] = '1'; } + break; + default: + // Rien a faire + return false; + break; + } // end switch + + // If we've set a filter we need to reset the totals + $this->reset_total(); + $this->set_start(0); + + return true; + + } // set_filter + + /** + * reset + * Reset everything, this should only be called when we are starting + * fresh + */ + public function reset() { + + $this->reset_base(); + $this->reset_filters(); + $this->reset_total(); + $this->reset_join(); + $this->reset_select(); + $this->reset_having(); + $this->set_static_content(false); + $this->set_is_simple(false); + $this->set_start(0); + $this->set_offset(Config::get('offset_limit') ? Config::get('offset_limit') : '25'); + + } // reset + + /** + * reset_base + * this resets the base string + */ + public function reset_base() { + + $this->_state['base'] = NULL; + + } // reset_base + + /** + * reset_select + * This resets the select fields that we've added so far + */ + public function reset_select() { + + $this->_state['select'] = array(); + + } // reset_select + + /** + * reset_having + * Null out the having clause + */ + public function reset_having() { + + unset($this->_state['having']); + + } // reset_having + + /** + * reset_join + * clears the joins if there are any + */ + public function reset_join() { + + unset($this->_state['join']); + + } // reset_join + + /** + * reset_filter + * This is a wrapper function that resets the filters + */ + public function reset_filters() { + + $this->_state['filter'] = array(); + + } // reset_filters + + /** + * reset_total + * This resets the total for the browse type + */ + public function reset_total() { + + unset($this->_state['total']); + + } // reset_total + + /** + * get_filter + * returns the specified filter value + */ + public function get_filter($key) { + + // Simple enough, but if we ever move this crap + // If we ever move this crap what? + return isset($this->_state['filter'][$key]) + ? $this->_state['filter'][$key] + : false; + + } // get_filter + + /** + * get_start + * This returns the current value of the start + */ + public function get_start() { + + return $this->_state['start']; + + } // get_start + + /** + * get_offset + * This returns the current offset + */ + public function get_offset() { + if ($this->is_static_content()) { + return $this->get_total(); + } + + return $this->_state['offset']; + } // get_offset + + /** + * set_total + * This sets the total number of objects + */ + public function set_total($total) { + $this->_state['total'] = $total; + } + + /** + * get_total + * This returns the total number of objects for this current sort type. + * If it's already cached used it. if they pass us an array then use + * that. + */ + public function get_total($objects = null) { + + // If they pass something then just return that + if (is_array($objects) and !$this->is_simple()) { + return count($objects); + } + + // See if we can find it in the cache + if (isset($this->_state['total'])) { + return $this->_state['total']; + } + + $db_results = Dba::read($this->get_sql(false)); + $num_rows = Dba::num_rows($db_results); + + $this->_state['total'] = $num_rows; + + return $num_rows; + + } // get_total + + /** + * get_allowed_filters + * This returns an array of the allowed filters based on the type of + * object we are working with, this is used to display the 'filter' + * sidebar stuff. + */ + public static function get_allowed_filters($type) { + return isset(self::$allowed_filters[$type]) + ? self::$allowed_filters[$type] + : array(); + } // get_allowed_filters + + /** + * set_type + * This sets the type of object that we want to browse by + * we do this here so we only have to maintain a single whitelist + * and if I want to change the location I only have to do it here + */ + public function set_type($type) { + + switch($type) { + case 'user': + case 'video': + case 'playlist': + case 'playlist_song': + case 'smartplaylist': + case 'song': + case 'flagged': + case 'catalog': + case 'album': + case 'artist': + case 'tag': + case 'playlist_localplay': + case 'shoutbox': + case 'live_stream': + case 'democratic': + // Set it + $this->_state['type'] = $type; + $this->set_base_sql(true); + break; + default: + // Rien a faire + break; + } // end type whitelist + } // set_type + + /** + * get_type + * This returns the type of the browse we currently are using + */ + public function get_type() { + + return $this->_state['type']; + + } // get_type + + /** + * set_sort + * This sets the current sort(s) + */ + public function set_sort($sort,$order='') { + + // If it's not in our list, smeg off! + if (!in_array($sort, self::$allowed_sorts[$this->get_type()])) { + return false; + } + + if ($order) { + $order = ($order == 'DESC') ? 'DESC' : 'ASC'; + $this->_state['sort'] = array(); + $this->_state['sort'][$sort] = $order; + } + elseif ($this->_state['sort'][$sort] == 'DESC') { + // Reset it till I can figure out how to interface the hotness + $this->_state['sort'] = array(); + $this->_state['sort'][$sort] = 'ASC'; + } + else { + // Reset it till I can figure out how to interface the hotness + $this->_state['sort'] = array(); + $this->_state['sort'][$sort] = 'DESC'; + } + + $this->resort_objects(); + + } // set_sort + + /** + * set_offset + * This sets the current offset of this query + */ + public function set_offset($offset) { + + $this->_state['offset'] = abs($offset); + + } // set_offset public function set_catalog( $catalog_number ) { $this->catalog = $catalog_number; - debug_event("Catalog", "set catalog id: " . $this->catalog, "5"); + debug_event("Catalog", "set catalog id: " . $this->catalog, "5"); + } + + /** + * set_select + * This appends more information to the select part of the SQL + * statement, we're going to move to the %%SELECT%% style queries, as I + * think it's the only way to do this... + */ + public function set_select($field) { + + $this->_state['select'][] = $field; + + } // set_select + + /** + * set_join + * This sets the joins for the current browse object + */ + public function set_join($type, $table, $source, $dest, $priority) { + + $this->_state['join'][$priority][$table] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $source . '=' . $dest; + + } // set_join + + /** + * set_having + * This sets the "HAVING" part of the query, we can only have one.. + * god this is ugly + */ + public function set_having($condition) { + + $this->_state['having'] = $condition; + + } // set_having + + /** + * set_start + * This sets the start point for our show functions + * We need to store this in the session so that it can be pulled + * back, if they hit the back button + */ + public function set_start($start) { + + + $start = intval($start); + + if (!$this->is_static_content()) { + $this->_state['start'] = $start; + } + + } // set_start + + /** + * set_is_simple + * This sets the current browse object to a 'simple' browse method + * which means use the base query provided and expand from there + */ + public function set_is_simple($value) { + + $value = make_bool($value); + $this->_state['simple'] = $value; + + } // set_is_simple + + /** + * set_static_content + * This sets true/false if the content of this browse + * should be static, if they are then content filtering/altering + * methods will be skipped + */ + public function set_static_content($value) { + + $value = make_bool($value); + + // We want to start at 0 if it's static + if ($value) { + $this->set_start('0'); + } + + $this->_state['static'] = $value; + + } // set_static_content + + public function is_static_content() { + return $this->_state['static']; + } + + /** + * is_simple + * This returns whether or not the current browse type is set to static. + */ + public function is_simple() { + + return $this->_state['simple']; + + } // is_simple + + /** + * get_saved + * This looks in the session for the saved stuff and returns what it + * finds. + */ + public function get_saved() { + + // See if we have it in the local cache first + if (is_array($this->_cache)) { + return $this->_cache; } - /** - * set_select - * This appends more information to the select part of the SQL - * statement, we're going to move to the %%SELECT%% style queries, as I - * think it's the only way to do this... - */ - public function set_select($field) { + if (!$this->is_simple()) { + $sid = Dba::escape(session_id()); + $id = Dba::escape($this->id); + $sql = "SELECT `object_data` FROM `tmp_browse` WHERE `sid`='$sid' AND `id`='$id'"; + $db_results = Dba::read($sql); - $this->_state['select'][] = $field; + $row = Dba::fetch_assoc($db_results); + + $this->_cache = unserialize($row['object_data']); + return $this->_cache; + } + else { + $objects = $this->get_objects(); + } + + return $objects; + + } // get_saved + + /** + * get_objects + * This gets an array of the ids of the objects that we are + * currently browsing by it applies the sql and logic based + * filters + */ + public function get_objects() { + + // First we need to get the SQL statement we are going to run + // This has to run against any possible filters (dependent on type) + $sql = $this->get_sql(true); + $db_results = Dba::read($sql); + + $results = array(); + while ($data = Dba::fetch_assoc($db_results)) { + $results[] = $data; + } + + $results = $this->post_process($results); + $filtered = array(); + foreach ($results as $data) { + // Make sure that this object passes the logic filter + if ($this->logic_filter($data['id'])) { + $filtered[] = $data['id']; + } + } // end while + + // Save what we've found and then return it + $this->save_objects($filtered); + + return $filtered; + + } // get_objects + + /** + * set_base_sql + * This saves the base sql statement we are going to use. + */ + private function set_base_sql($force = false) { + + // Only allow it to be set once + if (strlen($this->_state['base']) && !$force) { return true; } + + switch ($this->get_type()) { + case 'album': + $this->set_select("DISTINCT(`album`.`id`)"); + $sql = "SELECT %%SELECT%% FROM `album` "; + break; + case 'artist': + $this->set_select("`artist`.`id`"); + $sql = "SELECT %%SELECT%% FROM `artist` "; + break; + case 'catalog': + $this->set_select("`artist`.`name`"); + $sql = "SELECT %%SELECT%% FROM `artist` "; + break; + case 'user': + $this->set_select("`user`.`id`"); + $sql = "SELECT %%SELECT%% FROM `user` "; + break; + case 'live_stream': + $this->set_select("`live_stream`.`id`"); + $sql = "SELECT %%SELECT%% FROM `live_stream` "; + break; + case 'playlist': + $this->set_select("`playlist`.`id`"); + $sql = "SELECT %%SELECT%% FROM `playlist` "; + break; + case 'smartplaylist': + self::set_select('`search`.`id`'); + $sql = "SELECT %%SELECT%% FROM `search` "; + break; + case 'flagged': + $this->set_select("`flagged`.`id`"); + $sql = "SELECT %%SELECT%% FROM `flagged` "; + break; + case 'shoutbox': + $this->set_select("`user_shout`.`id`"); + $sql = "SELECT %%SELECT%% FROM `user_shout` "; + break; + case 'video': + $this->set_select("`video`.`id`"); + $sql = "SELECT %%SELECT%% FROM `video` "; + break; + case 'tag': + $this->set_select("DISTINCT(`tag`.`id`)"); + $this->set_join('left', 'tag_map', '`tag_map`.`tag_id`', '`tag`.`id`', 1); + $sql = "SELECT %%SELECT%% FROM `tag` "; + break; + case 'playlist_song': + case 'song': + default: + $this->set_select("DISTINCT(`song`.`id`)"); + $sql = "SELECT %%SELECT%% FROM `song` "; + break; + } // end base sql + + $this->_state['base'] = $sql; + + } // set_base_sql + + /** + * get_select + * This returns the selects in a format that is friendly for a sql + * statement. + */ + private function get_select() { + + $select_string = implode($this->_state['select'], ", "); + return $select_string; + + } // get_select + + /** + * get_base_sql + * This returns the base sql statement all parsed up, this should be + * called after all set operations. + */ + private function get_base_sql() { + + $sql = str_replace("%%SELECT%%", $this->get_select(), $this->_state['base']); + return $sql; + + } // get_base_sql + + /** + * get_filter_sql + * This returns the filter part of the sql statement + */ + private function get_filter_sql() { + + if (!is_array($this->_state['filter'])) { + return ''; + } + + $sql = "WHERE 1=1 AND "; + + foreach ($this->_state['filter'] + as $key => $value) { + + $sql .= $this->sql_filter($key, $value); + } + + $sql = rtrim($sql,'AND ') . ' '; + + return $sql; + + } // get_filter_sql + + /** + * get_sort_sql + * Returns the sort sql part + */ + private function get_sort_sql() { + + if (!is_array($this->_state['sort'])) { + return ''; + } + + $sql = 'ORDER BY '; + + foreach ($this->_state['sort'] + as $key => $value) { + $sql .= $this->sql_sort($key, $value); + } - } // set_select + $sql = rtrim($sql,'ORDER BY '); + $sql = rtrim($sql,','); - /** - * set_join - * This sets the joins for the current browse object - */ - public function set_join($type, $table, $source, $dest, $priority) { + return $sql; - $this->_state['join'][$priority][$table] = strtoupper($type) . ' JOIN ' . $table . ' ON ' . $source . '=' . $dest; + } // get_sort_sql - } // set_join + /** + * get_limit_sql + * This returns the limit part of the sql statement + */ + private function get_limit_sql() { - /** - * set_having - * This sets the "HAVING" part of the query, we can only have one.. - * god this is ugly - */ - public function set_having($condition) { + if (!$this->is_simple()) { return ''; } - $this->_state['having'] = $condition; + $sql = ' LIMIT ' . intval($this->get_start()) . ',' . intval($this->get_offset()); - } // set_having + return $sql; - /** - * set_start - * This sets the start point for our show functions - * We need to store this in the session so that it can be pulled - * back, if they hit the back button - */ - public function set_start($start) { + } // get_limit_sql + /** + * get_join_sql + * This returns the joins that this browse may need to work correctly + */ + private function get_join_sql() { - $start = intval($start); + if (!is_array($this->_state['join'])) { + return ''; + } - if (!$this->is_static_content()) { - $this->_state['start'] = $start; - } + $sql = ''; - } // set_start + foreach ($this->_state['join'] as $joins) { + foreach ($joins as $join) { + $sql .= $join . ' '; + } // end foreach joins at this level + } // end foreach of this level of joins - /** - * set_is_simple - * This sets the current browse object to a 'simple' browse method - * which means use the base query provided and expand from there - */ - public function set_is_simple($value) { + return $sql; - $value = make_bool($value); - $this->_state['simple'] = $value; + } // get_join_sql - } // set_is_simple + /** + * get_having_sql + * this returns the having sql stuff, if we've got anything + */ + public function get_having_sql() { - /** - * set_static_content - * This sets true/false if the content of this browse - * should be static, if they are then content filtering/altering - * methods will be skipped - */ - public function set_static_content($value) { + $sql = $this->_state['having']; - $value = make_bool($value); - - // We want to start at 0 if it's static - if ($value) { - $this->set_start('0'); - } - - $this->_state['static'] = $value; - - } // set_static_content - - public function is_static_content() { - return $this->_state['static']; - } - - /** - * is_simple - * This returns whether or not the current browse type is set to static. - */ - public function is_simple() { - - return $this->_state['simple']; - - } // is_simple - - /** - * get_saved - * This looks in the session for the saved stuff and returns what it - * finds. - */ - public function get_saved() { - - // See if we have it in the local cache first - if (is_array($this->_cache)) { - return $this->_cache; - } - - if (!$this->is_simple()) { - $sid = Dba::escape(session_id()); - $id = Dba::escape($this->id); - $sql = "SELECT `object_data` FROM `tmp_browse` WHERE `sid`='$sid' AND `id`='$id'"; - $db_results = Dba::read($sql); - - $row = Dba::fetch_assoc($db_results); - - $this->_cache = unserialize($row['object_data']); - return $this->_cache; - } - else { - $objects = $this->get_objects(); - } - - return $objects; - - } // get_saved - - /** - * get_objects - * This gets an array of the ids of the objects that we are - * currently browsing by it applies the sql and logic based - * filters - */ - public function get_objects() { - - // First we need to get the SQL statement we are going to run - // This has to run against any possible filters (dependent on type) - $sql = $this->get_sql(true); - $db_results = Dba::read($sql); - - $results = array(); - while ($data = Dba::fetch_assoc($db_results)) { - $results[] = $data; - } - - $results = $this->post_process($results); - $filtered = array(); - foreach ($results as $data) { - // Make sure that this object passes the logic filter - if ($this->logic_filter($data['id'])) { - $filtered[] = $data['id']; - } - } // end while - - // Save what we've found and then return it - $this->save_objects($filtered); - - return $filtered; - - } // get_objects - - /** - * set_base_sql - * This saves the base sql statement we are going to use. - */ - private function set_base_sql($force = false) { - - // Only allow it to be set once - if (strlen($this->_state['base']) && !$force) { return true; } - - switch ($this->get_type()) { - case 'album': - $this->set_select("DISTINCT(`album`.`id`)"); - $sql = "SELECT %%SELECT%% FROM `album` "; - break; - case 'artist': - $this->set_select("`artist`.`id`"); - $sql = "SELECT %%SELECT%% FROM `artist` "; - break; - case 'catalog': - $this->set_select("`artist`.`name`"); - $sql = "SELECT %%SELECT%% FROM `artist` "; - break; - case 'user': - $this->set_select("`user`.`id`"); - $sql = "SELECT %%SELECT%% FROM `user` "; - break; - case 'live_stream': - $this->set_select("`live_stream`.`id`"); - $sql = "SELECT %%SELECT%% FROM `live_stream` "; - break; - case 'playlist': - $this->set_select("`playlist`.`id`"); - $sql = "SELECT %%SELECT%% FROM `playlist` "; - break; - case 'smartplaylist': - self::set_select('`search`.`id`'); - $sql = "SELECT %%SELECT%% FROM `search` "; - break; - case 'flagged': - $this->set_select("`flagged`.`id`"); - $sql = "SELECT %%SELECT%% FROM `flagged` "; - break; - case 'shoutbox': - $this->set_select("`user_shout`.`id`"); - $sql = "SELECT %%SELECT%% FROM `user_shout` "; - break; - case 'video': - $this->set_select("`video`.`id`"); - $sql = "SELECT %%SELECT%% FROM `video` "; - break; - case 'tag': - $this->set_select("DISTINCT(`tag`.`id`)"); - $this->set_join('left', 'tag_map', '`tag_map`.`tag_id`', '`tag`.`id`', 1); - $sql = "SELECT %%SELECT%% FROM `tag` "; - break; - case 'playlist_song': - case 'song': - default: - $this->set_select("DISTINCT(`song`.`id`)"); - $sql = "SELECT %%SELECT%% FROM `song` "; - break; - } // end base sql - - $this->_state['base'] = $sql; - - } // set_base_sql - - /** - * get_select - * This returns the selects in a format that is friendly for a sql - * statement. - */ - private function get_select() { - - $select_string = implode($this->_state['select'], ", "); - return $select_string; - - } // get_select - - /** - * get_base_sql - * This returns the base sql statement all parsed up, this should be - * called after all set operations. - */ - private function get_base_sql() { - - $sql = str_replace("%%SELECT%%", $this->get_select(), $this->_state['base']); - return $sql; - - } // get_base_sql - - /** - * get_filter_sql - * This returns the filter part of the sql statement - */ - private function get_filter_sql() { - - if (!is_array($this->_state['filter'])) { - return ''; - } - - $sql = "WHERE 1=1 AND "; - - foreach ($this->_state['filter'] - as $key => $value) { - - $sql .= $this->sql_filter($key, $value); - } - - $sql = rtrim($sql,'AND ') . ' '; - - return $sql; - - } // get_filter_sql - - /** - * get_sort_sql - * Returns the sort sql part - */ - private function get_sort_sql() { - - if (!is_array($this->_state['sort'])) { - return ''; - } - - $sql = 'ORDER BY '; - - foreach ($this->_state['sort'] - as $key => $value) { - $sql .= $this->sql_sort($key, $value); - } - - $sql = rtrim($sql,'ORDER BY '); - $sql = rtrim($sql,','); - - return $sql; - - } // get_sort_sql - - /** - * get_limit_sql - * This returns the limit part of the sql statement - */ - private function get_limit_sql() { + return $sql; - if (!$this->is_simple()) { return ''; } + } // get_having_sql - $sql = ' LIMIT ' . intval($this->get_start()) . ',' . intval($this->get_offset()); + /** + * get_sql + * This returns the sql statement we are going to use this has to be run + * every time we get the objects because it depends on the filters and + * the type of object we are currently browsing. + */ + public function get_sql($limit = true) { - return $sql; + $sql = $this->get_base_sql(); - } // get_limit_sql + $filter_sql = $this->get_filter_sql(); + $join_sql = $this->get_join_sql(); + $having_sql = $this->get_having_sql(); + $order_sql = $this->get_sort_sql(); + $limit_sql = $limit ? $this->get_limit_sql() : ''; + $final_sql = $sql . $join_sql . $filter_sql . $having_sql; + + if( $this->get_type() == 'artist' ) { + $final_sql .= " GROUP BY `" . $this->get_type() . "`.`name` "; + } + $final_sql .= $order_sql . $limit_sql; + debug_event("Catalog", "catalog sql: " . $final_sql, "6"); + return $final_sql; - /** - * get_join_sql - * This returns the joins that this browse may need to work correctly - */ - private function get_join_sql() { + } // get_sql - if (!is_array($this->_state['join'])) { - return ''; - } + /** + * post_process + * This does some additional work on the results that we've received + * before returning them. + */ + private function post_process($data) { - $sql = ''; + $tags = $this->_state['filter']['tag']; - foreach ($this->_state['join'] as $joins) { - foreach ($joins as $join) { - $sql .= $join . ' '; - } // end foreach joins at this level - } // end foreach of this level of joins + if (!is_array($tags) || sizeof($tags) < 2) { + return $data; + } - return $sql; + $tag_count = sizeof($tags); + $count = array(); - } // get_join_sql + foreach($data as $row) { + $count[$row['id']]++; + } - /** - * get_having_sql - * this returns the having sql stuff, if we've got anything - */ - public function get_having_sql() { - - $sql = $this->_state['having']; - - return $sql; - - } // get_having_sql - - /** - * get_sql - * This returns the sql statement we are going to use this has to be run - * every time we get the objects because it depends on the filters and - * the type of object we are currently browsing. - */ - public function get_sql($limit = true) { - - $sql = $this->get_base_sql(); - - $filter_sql = $this->get_filter_sql(); - $join_sql = $this->get_join_sql(); - $having_sql = $this->get_having_sql(); - $order_sql = $this->get_sort_sql(); - $limit_sql = $limit ? $this->get_limit_sql() : ''; - $final_sql = $sql . $join_sql . $filter_sql . $having_sql; - - if( $this->get_type() == 'artist' ) { - $final_sql .= " GROUP BY `" . $this->get_type() . "`.`name` "; - } - $final_sql .= $order_sql . $limit_sql; - debug_event("Catalog", "catalog sql: " . $final_sql, "6"); - return $final_sql; - - } // get_sql - - /** - * post_process - * This does some additional work on the results that we've received - * before returning them. - */ - private function post_process($data) { - - $tags = $this->_state['filter']['tag']; - - if (!is_array($tags) || sizeof($tags) < 2) { - return $data; - } - - $tag_count = sizeof($tags); - $count = array(); - - foreach($data as $row) { - $count[$row['id']]++; - } - - $results = array(); - - foreach($count as $key => $value) { - if ($value >= $tag_count) { - $results[] = array('id' => $key); - } - } // end foreach - - return $results; - - } // post_process - - /** - * sql_filter - * This takes a filter name and value and if it is possible - * to filter by this name on this type returns the appropriate sql - * if not returns nothing - */ - private function sql_filter($filter, $value) { - - $filter_sql = ''; - - switch ($this->get_type()) { - - case 'song': - switch($filter) { - case 'tag': - $this->set_join('left', '`tag_map`', '`tag_map`.`object_id`', '`song`.`id`', 100); - $filter_sql = " `tag_map`.`object_type`='song' AND ("; - - foreach ($value as $tag_id) { - $filter_sql .= " `tag_map`.`tag_id`='" . Dba::escape($tag_id) . "' AND"; - } - $filter_sql = rtrim($filter_sql,'AND') . ') AND '; - break; - case 'exact_match': - $filter_sql = " `song`.`title` = '" . Dba::escape($value) . "' AND "; - break; - case 'alpha_match': - $filter_sql = " `song`.`title` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $filter_sql = " `song`.`title` LIKE '" . Dba::escape($value) . "%' AND "; - if( $this->catalog != 0 ) { - $filter_sql .= " `song`.`catalog` = '" . $this->catalog . "' AND "; - } - break; - case 'unplayed': - $filter_sql = " `song`.`played`='0' AND "; - break; - case 'album': - $filter_sql = " `song`.`album` = '". Dba::escape($value) . "' AND "; - break; - case 'artist': - $filter_sql = " `song`.`artist` = '". Dba::escape($value) . "' AND "; - break; - case 'add_gt': - $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND "; - break; - case 'add_lt': - $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND "; - break; - case 'update_gt': - $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND "; - break; - case 'update_lt': - $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND "; - break; - case 'catalog': - if($value != 0) { - $filter_sql = " `song`.`catalog` = '$value' AND "; - } - break; - default: - // Rien a faire - break; - } // end list of sqlable filters - break; - case 'album': - switch($filter) { - case 'exact_match': - $filter_sql = " `album`.`name` = '" . Dba::escape($value) . "' AND "; - break; - case 'alpha_match': - $filter_sql = " `album`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $this->set_join('left', '`song`', '`album`.`id`', '`song`.`album`', 100); - $filter_sql = " `album`.`name` LIKE '" . Dba::escape($value) . "%' AND "; - if( $this->catalog != 0 ) { - $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND "; - } - break; - case 'artist': - $filter_sql = " `artist`.`id` = '". Dba::escape($value) . "' AND "; - break; - case 'add_lt': - $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); - $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND "; - break; - case 'add_gt': - $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); - $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND "; - break; - case 'catalog': - if($value != 0) { - $this->set_join('left','`song`','`album`.`id`','`song`.`album`', 100); - $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100); + $results = array(); + + foreach($count as $key => $value) { + if ($value >= $tag_count) { + $results[] = array('id' => $key); + } + } // end foreach + + return $results; + + } // post_process + + /** + * sql_filter + * This takes a filter name and value and if it is possible + * to filter by this name on this type returns the appropriate sql + * if not returns nothing + */ + private function sql_filter($filter, $value) { + + $filter_sql = ''; + + switch ($this->get_type()) { + + case 'song': + switch($filter) { + case 'tag': + $this->set_join('left', '`tag_map`', '`tag_map`.`object_id`', '`song`.`id`', 100); + $filter_sql = " `tag_map`.`object_type`='song' AND ("; + + foreach ($value as $tag_id) { + $filter_sql .= " `tag_map`.`tag_id`='" . Dba::escape($tag_id) . "' AND"; + } + $filter_sql = rtrim($filter_sql,'AND') . ') AND '; + break; + case 'exact_match': + $filter_sql = " `song`.`title` = '" . Dba::escape($value) . "' AND "; + break; + case 'alpha_match': + $filter_sql = " `song`.`title` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $filter_sql = " `song`.`title` LIKE '" . Dba::escape($value) . "%' AND "; + if( $this->catalog != 0 ) { + $filter_sql .= " `song`.`catalog` = '" . $this->catalog . "' AND "; + } + break; + case 'unplayed': + $filter_sql = " `song`.`played`='0' AND "; + break; + case 'album': + $filter_sql = " `song`.`album` = '". Dba::escape($value) . "' AND "; + break; + case 'artist': + $filter_sql = " `song`.`artist` = '". Dba::escape($value) . "' AND "; + break; + case 'add_gt': + $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND "; + break; + case 'add_lt': + $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND "; + break; + case 'update_gt': + $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND "; + break; + case 'update_lt': + $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND "; + break; + case 'catalog': + if($value != 0) { + $filter_sql = " `song`.`catalog` = '$value' AND "; + } + break; + default: + // Rien a faire + break; + } // end list of sqlable filters + break; + case 'album': + switch($filter) { + case 'exact_match': + $filter_sql = " `album`.`name` = '" . Dba::escape($value) . "' AND "; + break; + case 'alpha_match': + $filter_sql = " `album`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $this->set_join('left', '`song`', '`album`.`id`', '`song`.`album`', 100); + $filter_sql = " `album`.`name` LIKE '" . Dba::escape($value) . "%' AND "; + if( $this->catalog != 0 ) { + $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND "; + } + break; + case 'artist': + $filter_sql = " `artist`.`id` = '". Dba::escape($value) . "' AND "; + break; + case 'add_lt': + $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); + $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND "; + break; + case 'add_gt': + $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); + $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND "; + break; + case 'catalog': + if($value != 0) { + $this->set_join('left','`song`','`album`.`id`','`song`.`album`', 100); + $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100); $filter_sql = " (`song`.`catalog` = '$value') AND "; } - break; - case 'update_lt': - $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); - $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND "; - break; - case 'update_gt': - $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); - $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND "; - break; - default: - // Rien a faire - break; - } - break; - case 'artist': - switch($filter) { - case 'catalog': - if($value != 0) { - $this->set_join('left','`song`','`artist`.`id`','`song`.`artist`', 100); - $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100); - $filter_sql = " (`catalog`.`id` = '$value') AND "; - } - break; - case 'exact_match': - $filter_sql = " `artist`.`name` = '" . Dba::escape($value) . "' AND "; - break; - case 'alpha_match': - $filter_sql = " `artist`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $this->set_join('left', '`song`', '`artist`.`id`', '`song`.`artist`', 100); - $filter_sql = " `artist`.`name` LIKE '" . Dba::escape($value) . "%' AND "; - if( $this->catalog != 0 ) { - $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND "; - } - break; - case 'add_lt': - $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); - $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND "; - break; - case 'add_gt': - $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); - $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND "; - break; - case 'update_lt': - $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); - $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND "; - break; - case 'update_gt': - $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); - $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND "; - break; - default: - // Rien a faire - break; - } // end filter - break; - case 'live_stream': - switch ($filter) { - case 'alpha_match': - $filter_sql = " `live_stream`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $filter_sql = " `live_stream`.`name` LIKE '" . Dba::escape($value) . "%' AND "; - break; - default: - // Rien a faire - break; - } // end filter - break; - case 'playlist': - switch ($filter) { - case 'alpha_match': - $filter_sql = " `playlist`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $filter_sql = " `playlist`.`name` LIKE '" . Dba::escape($value) . "%' AND "; - break; - case 'playlist_type': - $user_id = intval($GLOBALS['user']->id); - $filter_sql = " (`playlist`.`type` = 'public' OR `playlist`.`user`='$user_id') AND "; - break; - default; - // Rien a faire - break; - } // end filter - break; - case 'smartplaylist': - switch ($filter) { - case 'alpha_match': - $filter_sql = " `search`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $filter_sql = " `search`.`name` LIKE '" . Dba::escape($value) . "%' AND "; - break; - case 'playlist_type': - $user_id = intval($GLOBALS['user']->id); - $filter_sql = " (`search`.`type` = 'public' OR `search`.`user`='$user_id') AND "; - break; - } // end switch on $filter - break; - case 'tag': - switch ($filter) { - case 'alpha_match': - $filter_sql = " `tag`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'exact_match': - $filter_sql = " `tag`.`name` = '" . Dba::escape($value) . "' AND "; - break; - case 'tag': - $filter_sql = " `tag`.`id` = '" . Dba::escape($value) . "' AND "; - break; - default: - // Rien a faire - break; - } // end filter - break; - case 'video': - switch ($filter) { - case 'alpha_match': - $filter_sql = " `video`.`title` LIKE '%" . Dba::escape($value) . "%' AND "; - break; - case 'starts_with': - $filter_sql = " `video`.`title` LIKE '" . Dba::escape($value) . "%' AND "; - break; - default: - // Rien a faire - break; - } // end filter - break; - } // end switch on type - - return $filter_sql; - - } // sql_filter - - /** - * logic_filter - * This runs the filters that we can't easily apply - * to the sql so they have to be done after the fact - * these should be limited as they are often intensive and - * require additional queries per object... :( - */ - private function logic_filter($object_id) { - - return true; - - } // logic_filter - - /** - * sql_sort - * This builds any order bys we need to do - * to sort the results as best we can, there is also - * a logic based sort that will come later as that's - * a lot more complicated - */ - private function sql_sort($field, $order) { - - if ($order != 'DESC') { $order == 'ASC'; } - - // Depending on the type of browsing we are doing we can apply - // different filters that apply to different fields - switch ($this->get_type()) { - case 'song': - switch($field) { - case 'title'; - $sql = "`song`.`title`"; - break; - case 'year': - $sql = "`song`.`year`"; - break; - case 'time': - $sql = "`song`.`time`"; - break; - case 'track': - $sql = "`song`.`track`"; - break; - case 'album': - $sql = '`album`.`name`'; - $this->set_join('left', '`album`', '`album`.`id`', '`song`.`album`', 100); - break; - case 'artist': - $sql = '`artist`.`name`'; - $this->set_join('left', '`artist`', '`artist`.`id`', '`song`.`artist`', 100); - break; - default: - // Rien a faire - break; - } // end switch - break; - case 'album': - switch($field) { - case 'name': - $sql = "`album`.`name` $order, `album`.`disk`"; - break; - case 'artist': - $sql = "`artist`.`name`"; - $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); - $this->set_join('left', '`artist`', '`song`.`artist`', '`artist`.`id`', 100); - break; - case 'year': - $sql = "`album`.`year`"; - break; - } // end switch - break; - case 'artist': - switch ($field) { - case 'name': - $sql = "`artist`.`name`"; - break; - } // end switch - break; - case 'playlist': - switch ($field) { - case 'type': - $sql = "`playlist`.`type`"; - break; - case 'name': - $sql = "`playlist`.`name`"; - break; - case 'user': - $sql = "`playlist`.`user`"; - break; - } // end switch - break; - case 'smartplaylist': - switch ($field) { - case 'type': - $sql = "`search`.`type`"; - break; - case 'name': - $sql = "`search`.`name`"; - break; - case 'user': - $sql = "`search`.`user`"; - break; - } // end switch on $field - break; - case 'live_stream': - switch ($field) { - case 'name': - $sql = "`live_stream`.`name`"; - break; - case 'call_sign': - $sql = "`live_stream`.`call_sign`"; - break; - case 'frequency': - $sql = "`live_stream`.`frequency`"; - break; - } // end switch - break; - case 'genre': - switch ($field) { - case 'name': - $sql = "`genre`.`name`"; - break; - } // end switch - break; - case 'user': - switch ($field) { - case 'username': - $sql = "`user`.`username`"; - break; - case 'fullname': - $sql = "`user`.`fullname`"; - break; - case 'last_seen': - $sql = "`user`.`last_seen`"; - break; - case 'create_date': - $sql = "`user`.`create_date`"; - break; - } // end switch - break; - case 'video': - switch ($field) { - case 'title': - $sql = "`video`.`title`"; - break; - case 'resolution': - $sql = "`video`.`resolution_x`"; - break; - case 'length': - $sql = "`video`.`time`"; - break; - case 'codec': - $sql = "`video`.`video_codec`"; - break; - } // end switch on field - break; - default: - // Rien a faire - break; - } // end switch - - if ($sql) { $sql_sort = "$sql $order,"; } - - return $sql_sort; - - } // sql_sort - - /** - * resort_objects - * This takes the existing objects, looks at the current - * sort method and then re-sorts them This is internally - * called by the set_sort() function - */ - private function resort_objects() { - - // There are two ways to do this.. the easy way... - // and the vollmer way, hopefully we don't have to - // do it the vollmer way - if ($this->is_simple()) { - $sql = $this->get_sql(true); - } - else { - // First pull the objects - $objects = $this->get_saved(); - - // If there's nothing there don't do anything - if (!count($objects) or !is_array($objects)) { - return false; - } - $type = $this->get_type(); - $where_sql = "WHERE `$type`.`id` IN ("; - - foreach ($objects as $object_id) { - $object_id = Dba::escape($object_id); - $where_sql .= "'$object_id',"; - } - $where_sql = rtrim($where_sql,','); - - $where_sql .= ")"; - - $sql = $this->get_base_sql(); - - $order_sql = " ORDER BY "; - - foreach ($this->_state['sort'] as $key => $value) { - $order_sql .= $this->sql_sort($key, $value); - } - // Clean her up - $order_sql = rtrim($order_sql,"ORDER BY "); - $order_sql = rtrim($order_sql,","); - - $sql = $sql . $this->get_join_sql() . $where_sql . $order_sql; - } // if not simple - - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } - - $this->save_objects($results); - - return true; - - } // resort_objects - - /** - * store - * This saves the current state to the database - */ - public function store() { - $sid = Dba::escape(session_id()); - $id = Dba::escape($this->id); - $data = Dba::escape(serialize($this->_state)); - - $sql = "UPDATE `tmp_browse` SET `data`='$data' " . - "WHERE `sid`='$sid' AND `id`='$id'"; - $db_results = Dba::write($sql); - } - - /** - * save_objects - * This takes the full array of object ids, often passed into show and - * if necessary it saves them - */ - public function save_objects($object_ids) { - - // Saving these objects has two operations, one holds it in - // a local variable and then second holds it in a row in the - // tmp_browse table - - // Only do this if it's a not a simple browse - if (!$this->is_simple()) { - $this->_cache = $object_ids; - $this->set_total(count($object_ids)); - $sid = Dba::escape(session_id()); - $id = Dba::escape($this->id); - $data = Dba::escape(serialize($this->_cache)); - - $sql = "UPDATE `tmp_browse` SET `object_data`='$data' " . - "WHERE `sid`='$sid' AND `id`='$id'"; - $db_results = Dba::write($sql); - } // save it - - return true; - - } // save_objects - - /** - * get_state - * This is a debug only function - */ - public function get_state() { - - return $this->_state; - - } // get_state + break; + case 'update_lt': + $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); + $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND "; + break; + case 'update_gt': + $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); + $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND "; + break; + default: + // Rien a faire + break; + } + break; + case 'artist': + switch($filter) { + case 'catalog': + if($value != 0) { + $this->set_join('left','`song`','`artist`.`id`','`song`.`artist`', 100); + $this->set_join('left','`catalog`','`song`.`catalog`','`catalog`.`id`', 100); + $filter_sql = " (`catalog`.`id` = '$value') AND "; + } + break; + case 'exact_match': + $filter_sql = " `artist`.`name` = '" . Dba::escape($value) . "' AND "; + break; + case 'alpha_match': + $filter_sql = " `artist`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $this->set_join('left', '`song`', '`artist`.`id`', '`song`.`artist`', 100); + $filter_sql = " `artist`.`name` LIKE '" . Dba::escape($value) . "%' AND "; + if( $this->catalog != 0 ) { + $filter_sql .= "`song`.`catalog` = '" . $this->catalog . "' AND "; + } + break; + case 'add_lt': + $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); + $filter_sql = " `song`.`addition_time` <= '" . Dba::escape($value) . "' AND "; + break; + case 'add_gt': + $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); + $filter_sql = " `song`.`addition_time` >= '" . Dba::escape($value) . "' AND "; + break; + case 'update_lt': + $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); + $filter_sql = " `song`.`update_time` <= '" . Dba::escape($value) . "' AND "; + break; + case 'update_gt': + $this->set_join('left', '`song`', '`song`.`artist`', '`artist`.`id`', 100); + $filter_sql = " `song`.`update_time` >= '" . Dba::escape($value) . "' AND "; + break; + default: + // Rien a faire + break; + } // end filter + break; + case 'live_stream': + switch ($filter) { + case 'alpha_match': + $filter_sql = " `live_stream`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $filter_sql = " `live_stream`.`name` LIKE '" . Dba::escape($value) . "%' AND "; + break; + default: + // Rien a faire + break; + } // end filter + break; + case 'playlist': + switch ($filter) { + case 'alpha_match': + $filter_sql = " `playlist`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $filter_sql = " `playlist`.`name` LIKE '" . Dba::escape($value) . "%' AND "; + break; + case 'playlist_type': + $user_id = intval($GLOBALS['user']->id); + $filter_sql = " (`playlist`.`type` = 'public' OR `playlist`.`user`='$user_id') AND "; + break; + default; + // Rien a faire + break; + } // end filter + break; + case 'smartplaylist': + switch ($filter) { + case 'alpha_match': + $filter_sql = " `search`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $filter_sql = " `search`.`name` LIKE '" . Dba::escape($value) . "%' AND "; + break; + case 'playlist_type': + $user_id = intval($GLOBALS['user']->id); + $filter_sql = " (`search`.`type` = 'public' OR `search`.`user`='$user_id') AND "; + break; + } // end switch on $filter + break; + case 'tag': + switch ($filter) { + case 'alpha_match': + $filter_sql = " `tag`.`name` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'exact_match': + $filter_sql = " `tag`.`name` = '" . Dba::escape($value) . "' AND "; + break; + case 'tag': + $filter_sql = " `tag`.`id` = '" . Dba::escape($value) . "' AND "; + break; + default: + // Rien a faire + break; + } // end filter + break; + case 'video': + switch ($filter) { + case 'alpha_match': + $filter_sql = " `video`.`title` LIKE '%" . Dba::escape($value) . "%' AND "; + break; + case 'starts_with': + $filter_sql = " `video`.`title` LIKE '" . Dba::escape($value) . "%' AND "; + break; + default: + // Rien a faire + break; + } // end filter + break; + } // end switch on type + + return $filter_sql; + + } // sql_filter + + /** + * logic_filter + * This runs the filters that we can't easily apply + * to the sql so they have to be done after the fact + * these should be limited as they are often intensive and + * require additional queries per object... :( + */ + private function logic_filter($object_id) { + + return true; + + } // logic_filter + + /** + * sql_sort + * This builds any order bys we need to do + * to sort the results as best we can, there is also + * a logic based sort that will come later as that's + * a lot more complicated + */ + private function sql_sort($field, $order) { + + if ($order != 'DESC') { $order == 'ASC'; } + + // Depending on the type of browsing we are doing we can apply + // different filters that apply to different fields + switch ($this->get_type()) { + case 'song': + switch($field) { + case 'title'; + $sql = "`song`.`title`"; + break; + case 'year': + $sql = "`song`.`year`"; + break; + case 'time': + $sql = "`song`.`time`"; + break; + case 'track': + $sql = "`song`.`track`"; + break; + case 'album': + $sql = '`album`.`name`'; + $this->set_join('left', '`album`', '`album`.`id`', '`song`.`album`', 100); + break; + case 'artist': + $sql = '`artist`.`name`'; + $this->set_join('left', '`artist`', '`artist`.`id`', '`song`.`artist`', 100); + break; + default: + // Rien a faire + break; + } // end switch + break; + case 'album': + switch($field) { + case 'name': + $sql = "`album`.`name` $order, `album`.`disk`"; + break; + case 'artist': + $sql = "`artist`.`name`"; + $this->set_join('left', '`song`', '`song`.`album`', '`album`.`id`', 100); + $this->set_join('left', '`artist`', '`song`.`artist`', '`artist`.`id`', 100); + break; + case 'year': + $sql = "`album`.`year`"; + break; + } // end switch + break; + case 'artist': + switch ($field) { + case 'name': + $sql = "`artist`.`name`"; + break; + } // end switch + break; + case 'playlist': + switch ($field) { + case 'type': + $sql = "`playlist`.`type`"; + break; + case 'name': + $sql = "`playlist`.`name`"; + break; + case 'user': + $sql = "`playlist`.`user`"; + break; + } // end switch + break; + case 'smartplaylist': + switch ($field) { + case 'type': + $sql = "`search`.`type`"; + break; + case 'name': + $sql = "`search`.`name`"; + break; + case 'user': + $sql = "`search`.`user`"; + break; + } // end switch on $field + break; + case 'live_stream': + switch ($field) { + case 'name': + $sql = "`live_stream`.`name`"; + break; + case 'call_sign': + $sql = "`live_stream`.`call_sign`"; + break; + case 'frequency': + $sql = "`live_stream`.`frequency`"; + break; + } // end switch + break; + case 'genre': + switch ($field) { + case 'name': + $sql = "`genre`.`name`"; + break; + } // end switch + break; + case 'user': + switch ($field) { + case 'username': + $sql = "`user`.`username`"; + break; + case 'fullname': + $sql = "`user`.`fullname`"; + break; + case 'last_seen': + $sql = "`user`.`last_seen`"; + break; + case 'create_date': + $sql = "`user`.`create_date`"; + break; + } // end switch + break; + case 'video': + switch ($field) { + case 'title': + $sql = "`video`.`title`"; + break; + case 'resolution': + $sql = "`video`.`resolution_x`"; + break; + case 'length': + $sql = "`video`.`time`"; + break; + case 'codec': + $sql = "`video`.`video_codec`"; + break; + } // end switch on field + break; + default: + // Rien a faire + break; + } // end switch + + if ($sql) { $sql_sort = "$sql $order,"; } + + return $sql_sort; + + } // sql_sort + + /** + * resort_objects + * This takes the existing objects, looks at the current + * sort method and then re-sorts them This is internally + * called by the set_sort() function + */ + private function resort_objects() { + + // There are two ways to do this.. the easy way... + // and the vollmer way, hopefully we don't have to + // do it the vollmer way + if ($this->is_simple()) { + $sql = $this->get_sql(true); + } + else { + // First pull the objects + $objects = $this->get_saved(); + + // If there's nothing there don't do anything + if (!count($objects) or !is_array($objects)) { + return false; + } + $type = $this->get_type(); + $where_sql = "WHERE `$type`.`id` IN ("; + + foreach ($objects as $object_id) { + $object_id = Dba::escape($object_id); + $where_sql .= "'$object_id',"; + } + $where_sql = rtrim($where_sql,','); + + $where_sql .= ")"; + + $sql = $this->get_base_sql(); + + $order_sql = " ORDER BY "; + + foreach ($this->_state['sort'] as $key => $value) { + $order_sql .= $this->sql_sort($key, $value); + } + // Clean her up + $order_sql = rtrim($order_sql,"ORDER BY "); + $order_sql = rtrim($order_sql,","); + + $sql = $sql . $this->get_join_sql() . $where_sql . $order_sql; + } // if not simple + + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } + + $this->save_objects($results); + + return true; + + } // resort_objects + + /** + * store + * This saves the current state to the database + */ + public function store() { + $sid = Dba::escape(session_id()); + $id = Dba::escape($this->id); + $data = Dba::escape(serialize($this->_state)); + + $sql = "UPDATE `tmp_browse` SET `data`='$data' " . + "WHERE `sid`='$sid' AND `id`='$id'"; + $db_results = Dba::write($sql); + } + + /** + * save_objects + * This takes the full array of object ids, often passed into show and + * if necessary it saves them + */ + public function save_objects($object_ids) { + + // Saving these objects has two operations, one holds it in + // a local variable and then second holds it in a row in the + // tmp_browse table + + // Only do this if it's a not a simple browse + if (!$this->is_simple()) { + $this->_cache = $object_ids; + $this->set_total(count($object_ids)); + $sid = Dba::escape(session_id()); + $id = Dba::escape($this->id); + $data = Dba::escape(serialize($this->_cache)); + + $sql = "UPDATE `tmp_browse` SET `object_data`='$data' " . + "WHERE `sid`='$sid' AND `id`='$id'"; + $db_results = Dba::write($sql); + } // save it + + return true; + + } // save_objects + + /** + * get_state + * This is a debug only function + */ + public function get_state() { + + return $this->_state; + + } // get_state } // query diff --git a/lib/class/radio.class.php b/lib/class/radio.class.php index 02ca3bc898..101f60f7d1 100644 --- a/lib/class/radio.class.php +++ b/lib/class/radio.class.php @@ -1,5 +1,5 @@ get_info($id,'live_stream'); + $info = $this->get_info($id,'live_stream'); - // Set the vars - foreach ($info as $key=>$value) { - $this->$key = $value; - } - - } // constructor - - /** - * format - * This takes the normal data from the database and makes it pretty - * for the users, the new variables are put in f_??? and f_???_link - */ - public function format() { - - // Default link used on the rightbar - $this->f_link = "url\">$this->name"; + // Set the vars + foreach ($info as $key=>$value) { + $this->$key = $value; + } + + } // constructor + + /** + * format + * This takes the normal data from the database and makes it pretty + * for the users, the new variables are put in f_??? and f_???_link + */ + public function format() { + + // Default link used on the rightbar + $this->f_link = "url\">$this->name"; - $this->f_name_link = "site_url\">$this->name"; - $this->f_callsign = scrub_out($this->call_sign); - $this->f_frequency = scrub_out($this->frequency); + $this->f_name_link = "site_url\">$this->name"; + $this->f_callsign = scrub_out($this->call_sign); + $this->f_frequency = scrub_out($this->frequency); - return true; + return true; - } // format + } // format - /** - * update - * This is a static function that takes a key'd array for input - * it depends on a ID element to determine which radio element it - * should be updating - */ - public static function update($data) { + /** + * update + * This is a static function that takes a key'd array for input + * it depends on a ID element to determine which radio element it + * should be updating + */ + public static function update($data) { - // Verify the incoming data - if (!$data['id']) { - Error::add('general', T_('Missing ID')); - } + // Verify the incoming data + if (!$data['id']) { + Error::add('general', T_('Missing ID')); + } - if (!$data['name']) { - Error::add('general', T_('Name Required')); - } - - $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp'); + if (!$data['name']) { + Error::add('general', T_('Name Required')); + } + + $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp'); - $elements = explode(":",$data['url']); + $elements = explode(":",$data['url']); - if (!in_array($elements['0'],$allowed_array)) { - Error::add('general', T_('Invalid URL must be mms:// , https:// or http://')); - } + if (!in_array($elements['0'],$allowed_array)) { + Error::add('general', T_('Invalid URL must be mms:// , https:// or http://')); + } - if (Error::occurred()) { - return false; - } + if (Error::occurred()) { + return false; + } - // Setup the data - $name = Dba::escape($data['name']); - $site_url = Dba::escape($data['site_url']); - $url = Dba::escape($data['url']); - $frequency = Dba::escape($data['frequency']); - $call_sign = Dba::escape($data['call_sign']); - $id = Dba::escape($data['id']); + // Setup the data + $name = Dba::escape($data['name']); + $site_url = Dba::escape($data['site_url']); + $url = Dba::escape($data['url']); + $frequency = Dba::escape($data['frequency']); + $call_sign = Dba::escape($data['call_sign']); + $id = Dba::escape($data['id']); - $sql = "UPDATE `live_stream` SET `name`='$name',`site_url`='$site_url',`url`='$url'" . - ",`frequency`='$frequency',`call_sign`='$call_sign' WHERE `id`='$id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `live_stream` SET `name`='$name',`site_url`='$site_url',`url`='$url'" . + ",`frequency`='$frequency',`call_sign`='$call_sign' WHERE `id`='$id'"; + $db_results = Dba::write($sql); - return $db_results; + return $db_results; - } // update + } // update - /** - * create - * This is a static function that takes a key'd array for input - * and if everything is good creates the object. - */ - public static function create($data) { + /** + * create + * This is a static function that takes a key'd array for input + * and if everything is good creates the object. + */ + public static function create($data) { - // Make sure we've got a name - if (!strlen($data['name'])) { - Error::add('name', T_('Name Required')); - } + // Make sure we've got a name + if (!strlen($data['name'])) { + Error::add('name', T_('Name Required')); + } - $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp'); + $allowed_array = array('https','http','mms','mmsh','mmsu','mmst','rtsp'); - $elements = explode(":",$data['url']); + $elements = explode(":",$data['url']); - if (!in_array($elements['0'],$allowed_array)) { - Error::add('url', T_('Invalid URL must be http:// or https://')); - } + if (!in_array($elements['0'],$allowed_array)) { + Error::add('url', T_('Invalid URL must be http:// or https://')); + } - // Make sure it's a real catalog - $catalog = new Catalog($data['catalog']); - if (!$catalog->name) { - Error::add('catalog', T_('Invalid Catalog')); - } + // Make sure it's a real catalog + $catalog = new Catalog($data['catalog']); + if (!$catalog->name) { + Error::add('catalog', T_('Invalid Catalog')); + } - if (Error::occurred()) { return false; } + if (Error::occurred()) { return false; } - // Clean up the input - $name = Dba::escape($data['name']); - $site_url = Dba::escape($data['site_url']); - $url = Dba::escape($data['url']); - $catalog = $catalog->id; - $frequency = Dba::escape($data['frequency']); - $call_sign = Dba::escape($data['call_sign']); + // Clean up the input + $name = Dba::escape($data['name']); + $site_url = Dba::escape($data['site_url']); + $url = Dba::escape($data['url']); + $catalog = $catalog->id; + $frequency = Dba::escape($data['frequency']); + $call_sign = Dba::escape($data['call_sign']); - // If we've made it this far everything must be ok... I hope - $sql = "INSERT INTO `live_stream` (`name`,`site_url`,`url`,`catalog`,`frequency`,`call_sign`) " . - "VALUES ('$name','$site_url','$url','$catalog','$frequency','$call_sign')"; - $db_results = Dba::write($sql); + // If we've made it this far everything must be ok... I hope + $sql = "INSERT INTO `live_stream` (`name`,`site_url`,`url`,`catalog`,`frequency`,`call_sign`) " . + "VALUES ('$name','$site_url','$url','$catalog','$frequency','$call_sign')"; + $db_results = Dba::write($sql); - return $db_results; + return $db_results; - } // create + } // create - /** - * delete - * This deletes the current object from the database - */ - public function delete() { + /** + * delete + * This deletes the current object from the database + */ + public function delete() { - $id = Dba::escape($this->id); + $id = Dba::escape($this->id); - $sql = "DELETE FROM `live_stream` WHERE `id`='$id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `live_stream` WHERE `id`='$id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // delete + } // delete - /** - * get_stream_types - * This is needed by the media interface - */ - public function get_stream_types() { - return array('foreign'); - } // native_stream + /** + * get_stream_types + * This is needed by the media interface + */ + public function get_stream_types() { + return array('foreign'); + } // native_stream - /** - * play_url - * This is needed by the media interface - */ - public static function play_url($oid,$sid='',$force_http='') { + /** + * play_url + * This is needed by the media interface + */ + public static function play_url($oid,$sid='',$force_http='') { - $radio = new Radio($oid); + $radio = new Radio($oid); - return $radio->url; + return $radio->url; - } // play_url + } // play_url - /** - * has_flag - * This is needed by the media interface - */ - public function has_flag() { + /** + * has_flag + * This is needed by the media interface + */ + public function has_flag() { - } // has_flag + } // has_flag - /** - * get_transcode_settings - * - * This will probably never be implemented - */ - public function get_transcode_settings() { - return false; - } + /** + * get_transcode_settings + * + * This will probably never be implemented + */ + public function get_transcode_settings() { + return false; + } } //end of radio class diff --git a/lib/class/random.class.php b/lib/class/random.class.php index 5f383c7c07..c7204392fd 100644 --- a/lib/class/random.class.php +++ b/lib/class/random.class.php @@ -1,5 +1,5 @@ type = Random::get_id_type($id); - $this->id = intval($id); + $this->type = Random::get_id_type($id); + $this->id = intval($id); - } // constructor + } // constructor - /** - * album - * This returns the ID of a random album, nothing special - */ - public static function album() { + /** + * album + * This returns the ID of a random album, nothing special + */ + public static function album() { - $sql = "SELECT `id` FROM `album` ORDER BY RAND() LIMIT 1"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `album` ORDER BY RAND() LIMIT 1"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - return $results['id']; + return $results['id']; - } // album + } // album - /** - * artist - * This returns the ID of a random artist, nothing special here for now - */ - public static function artist() { + /** + * artist + * This returns the ID of a random artist, nothing special here for now + */ + public static function artist() { - $sql = "SELECT `id` FROM `artist` ORDER BY RAND() LIMIT 1"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `artist` ORDER BY RAND() LIMIT 1"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - return $results['id']; + return $results['id']; - } // artist + } // artist - /** - * playlist - * This returns a random Playlist with songs little bit of extra - * logic require - */ - public static function playlist() { + /** + * playlist + * This returns a random Playlist with songs little bit of extra + * logic require + */ + public static function playlist() { - $sql = "SELECT `playlist`.`id` FROM `playlist` LEFT JOIN `playlist_data` " . - " ON `playlist`.`id`=`playlist_data`.`playlist` WHERE `playlist_data`.`object_id` IS NOT NULL " . - " ORDER BY RAND()"; - $db_results = Dba::read($sql); + $sql = "SELECT `playlist`.`id` FROM `playlist` LEFT JOIN `playlist_data` " . + " ON `playlist`.`id`=`playlist_data`.`playlist` WHERE `playlist_data`.`object_id` IS NOT NULL " . + " ORDER BY RAND()"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - return $results['id']; + return $results['id']; - } // playlist + } // playlist - /** - * play_url - * This generates a random play url based on the passed type - * and returns it - */ - public static function play_url($id,$sid='',$force_http='') { + /** + * play_url + * This generates a random play url based on the passed type + * and returns it + */ + public static function play_url($id,$sid='',$force_http='') { - if (!$type = self::get_id_type($id)) { - return false; - } + if (!$type = self::get_id_type($id)) { + return false; + } - $uid = $GLOBALS['user']->id; + $uid = $GLOBALS['user']->id; - $url = Stream::get_base_url() . "random=1&type=$type&uid=$uid"; + $url = Stream::get_base_url() . "random=1&type=$type&uid=$uid"; - return $url; + return $url; - } // play_url + } // play_url - /** - * get_single_song - * This returns a single song pulled based on the passed random method - */ - public static function get_single_song($type) { + /** + * get_single_song + * This returns a single song pulled based on the passed random method + */ + public static function get_single_song($type) { - if (!$type = self::validate_type($type)) { - return false; - } + if (!$type = self::validate_type($type)) { + return false; + } - $method_name = 'get_' . $type; + $method_name = 'get_' . $type; - if (method_exists('Random',$method_name)) { - $song_ids = self::$method_name(1); - $song_id = array_pop($song_ids); - } + if (method_exists('Random',$method_name)) { + $song_ids = self::$method_name(1); + $song_id = array_pop($song_ids); + } - return $song_id; + return $song_id; - } // get_single_song + } // get_single_song - /** - * get_default - * This just randomly picks a song at whim from all catalogs - * nothing special here... - */ - public static function get_default($limit) { + /** + * get_default + * This just randomly picks a song at whim from all catalogs + * nothing special here... + */ + public static function get_default($limit) { - $results = array(); + $results = array(); - $sql = "SELECT `id` FROM `song` ORDER BY RAND() LIMIT $limit"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `song` ORDER BY RAND() LIMIT $limit"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_default + } // get_default - /** - * get_album - * This looks at the last album played by the current user and - * picks something else in the same album - */ - public static function get_album($limit) { + /** + * get_album + * This looks at the last album played by the current user and + * picks something else in the same album + */ + public static function get_album($limit) { - $results = array(); - - // Get the last album playbed by us - $data = $GLOBALS['user']->get_recently_played('1','album'); - if ($data['0']) { - $where_sql = " WHERE `album`='" . $data['0'] . "' "; - } + $results = array(); + + // Get the last album playbed by us + $data = $GLOBALS['user']->get_recently_played('1','album'); + if ($data['0']) { + $where_sql = " WHERE `album`='" . $data['0'] . "' "; + } - $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } - - return $results; - - } // get_album - - /** - * get_artist - * This looks at the last artist played and then randomly picks a song from the - * same artist - */ - public static function get_artist($limit) { - - $results = array(); - - $data = $GLOBALS['user']->get_recently_played('1','artist'); - if ($data['0']) { - $where_sql = " WHERE `artist`='" . $data['0'] . "' "; - } - - $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } - - return $results; - - } // get_artist - - /** - * advanced - * This processes the results of a post from a form and returns an - * array of song items that were returned from said randomness - */ - public static function advanced($type, $data) { - - /* Figure out our object limit */ - $limit = intval($data['random']); - - // Generate our matchlist - - /* If they've passed -1 as limit then get everything */ - if ($data['random'] == "-1") { unset($data['random']); } - else { $limit_sql = "LIMIT " . Dba::escape($limit); } - - $search_data = Search::clean_request($data); - - $search_info = false; - - if (count($search_data) > 1) { - $search = new Search($type); - $search->parse_rules($search_data); - $search_info = $search->to_sql(); - } - - switch ($type) { - case 'song': - $sql = "SELECT `song`.`id`, `size`, `time` " . - "FROM `song` "; - if ($search_info) { - $sql .= $search_info['table_sql']; - $sql .= ' WHERE ' . $search_info['where_sql']; - } - break; - case 'album': - $sql = "SELECT `album`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `album` "; - if (! $search_info || ! $search_info['join']['song']) { - $sql .= "LEFT JOIN `song` ON `song`.`album`=`album`.`id` "; - } - if ($search_info) { - $sql .= $search_info['table_sql']; - $sql .= ' WHERE ' . $search_info['where_sql']; - } - $sql .= ' GROUP BY `album`.`id`'; - break; - case 'artist': - $sql = "SELECT `artist`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `artist` "; - if (! $search_info || ! $search_info['join']['song']) { - $sql .= "LEFT JOIN `song` ON `song`.`artist`=`artist`.`id` "; - } - if ($search_info) { - $sql .= $search_info['table_sql']; - $sql .= ' WHERE ' . $search_info['where_sql']; - } - $sql .= ' GROUP BY `artist`.`id`'; - break; - } - $sql .= " ORDER BY RAND() $limit_sql"; - - // Run the query generated above so we can while it - $db_results = Dba::read($sql); - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - - // If size limit is specified - if ($data['size_limit']) { - // Convert - $new_size = ($row['size'] / 1024) / 1024; - - // Only fuzzy 100 times - if ($fuzzy_size > 100) { - break; - } - - // Add and check, skip if over size - if (($size_total + $new_size) > $data['size_limit']) { - $fuzzy_size++; - continue; - } - - $size_total = $size_total + $new_size; - $results[] = $row['id']; - - // If we are within 4mb of target then jump ship - if (($data['size_limit'] - floor($size_total)) < 4) { - break; } - } // if size_limit - - // If length really does matter - if ($data['length']) { - // base on min, seconds are for chumps and chumpettes - $new_time = floor($row['time'] / 60); - - if ($fuzzy_time > 100) { - break;; - } - - // If the new one would go over skip! - if (($time_total + $new_time) > $data['length']) { - $fuzzy_time++; - continue; - } - - $time_total = $time_total + $new_time; - $results[] = $row['id']; - - // If there are less then 2 min of free space return - if (($data['length'] - $time_total) < 2) { - return $results; - } - } // if length does matter - - if (!$data['size_limit'] && !$data['length']) { - $results[] = $row['id']; - } - - } // end while results - - switch ($type) { - case 'song': - return $results; - break; - case 'album': - $songs = array(); - foreach ($results as $result) { - $album = new Album($result); - $songs = array_merge($songs, $album->get_songs()); - } - return $songs; - break; - case 'artist': - $songs = array(); - foreach ($results as $result) { - $artist = new Artist($result); - $songs = array_merge($songs, $artist->get_songs()); - } - return $songs; - break; - default: - return false; - break; - } - } // advanced - - /** - * get_type_name - * This returns a 'purrty' name for the different random types - */ - public static function get_type_name($type) { - - switch ($type) { - case 'album': - return T_('Related Album'); - break; - case 'genre': - return T_('Related Genre'); - break; - case 'artist': - return T_('Related Artist'); - break; - default: - return T_('Pure Random'); - break; - } // end switch - - } // get_type_name - - /** - * get_type_id - * This takes random type and returns the ID - * MOTHER OF PEARL THIS MAKES BABY JESUS CRY - * HACK HACK HACK HACK HACK HACK HACK HACK - */ - public static function get_type_id($type) { - - switch ($type) { - case 'album': - return '1'; - break; - case 'artist': - return '2'; - break; - case 'tag': - return '3'; - break; - default: - return '4'; - break; - } - - } // get_type_id - - /** - * get_id_name - * This takes an ID and returns the 'name' of the random dealie - * HACK HACK HACK HACK HACK HACK HACK - * Can you tell I don't like this code? - */ - public static function get_id_type($id) { - - switch ($id) { - case '1': - return 'album'; - break; - case '2': - return 'artist'; - break; - case '3': - return 'tag'; - break; - default: - return 'default'; - break; - } // end switch - - } // get_id_name - - /** - * validate_type - * this validates the random type - */ - public static function validate_type($type) { - - switch ($type) { - case 'default': - case 'genre': - case 'album': - case 'artist': - case 'rated': - return $type; - break; - } // end switch - - return 'default'; - - } // validate_type - - public function native_stream() { } - public function stream_cmd() { } - public function has_flag() { } - public function format() { } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } + + return $results; + + } // get_album + + /** + * get_artist + * This looks at the last artist played and then randomly picks a song from the + * same artist + */ + public static function get_artist($limit) { + + $results = array(); + + $data = $GLOBALS['user']->get_recently_played('1','artist'); + if ($data['0']) { + $where_sql = " WHERE `artist`='" . $data['0'] . "' "; + } + + $sql = "SELECT `id` FROM `song` $where_sql ORDER BY RAND() LIMIT $limit"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } + + return $results; + + } // get_artist + + /** + * advanced + * This processes the results of a post from a form and returns an + * array of song items that were returned from said randomness + */ + public static function advanced($type, $data) { + + /* Figure out our object limit */ + $limit = intval($data['random']); + + // Generate our matchlist + + /* If they've passed -1 as limit then get everything */ + if ($data['random'] == "-1") { unset($data['random']); } + else { $limit_sql = "LIMIT " . Dba::escape($limit); } + + $search_data = Search::clean_request($data); + + $search_info = false; + + if (count($search_data) > 1) { + $search = new Search($type); + $search->parse_rules($search_data); + $search_info = $search->to_sql(); + } + + switch ($type) { + case 'song': + $sql = "SELECT `song`.`id`, `size`, `time` " . + "FROM `song` "; + if ($search_info) { + $sql .= $search_info['table_sql']; + $sql .= ' WHERE ' . $search_info['where_sql']; + } + break; + case 'album': + $sql = "SELECT `album`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `album` "; + if (! $search_info || ! $search_info['join']['song']) { + $sql .= "LEFT JOIN `song` ON `song`.`album`=`album`.`id` "; + } + if ($search_info) { + $sql .= $search_info['table_sql']; + $sql .= ' WHERE ' . $search_info['where_sql']; + } + $sql .= ' GROUP BY `album`.`id`'; + break; + case 'artist': + $sql = "SELECT `artist`.`id`, SUM(`song`.`size`) AS `size`, SUM(`song`.`time`) AS `time` FROM `artist` "; + if (! $search_info || ! $search_info['join']['song']) { + $sql .= "LEFT JOIN `song` ON `song`.`artist`=`artist`.`id` "; + } + if ($search_info) { + $sql .= $search_info['table_sql']; + $sql .= ' WHERE ' . $search_info['where_sql']; + } + $sql .= ' GROUP BY `artist`.`id`'; + break; + } + $sql .= " ORDER BY RAND() $limit_sql"; + + // Run the query generated above so we can while it + $db_results = Dba::read($sql); + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + + // If size limit is specified + if ($data['size_limit']) { + // Convert + $new_size = ($row['size'] / 1024) / 1024; + + // Only fuzzy 100 times + if ($fuzzy_size > 100) { + break; + } + + // Add and check, skip if over size + if (($size_total + $new_size) > $data['size_limit']) { + $fuzzy_size++; + continue; + } + + $size_total = $size_total + $new_size; + $results[] = $row['id']; + + // If we are within 4mb of target then jump ship + if (($data['size_limit'] - floor($size_total)) < 4) { + break; } + } // if size_limit + + // If length really does matter + if ($data['length']) { + // base on min, seconds are for chumps and chumpettes + $new_time = floor($row['time'] / 60); + + if ($fuzzy_time > 100) { + break;; + } + + // If the new one would go over skip! + if (($time_total + $new_time) > $data['length']) { + $fuzzy_time++; + continue; + } + + $time_total = $time_total + $new_time; + $results[] = $row['id']; + + // If there are less then 2 min of free space return + if (($data['length'] - $time_total) < 2) { + return $results; + } + } // if length does matter + + if (!$data['size_limit'] && !$data['length']) { + $results[] = $row['id']; + } + + } // end while results + + switch ($type) { + case 'song': + return $results; + break; + case 'album': + $songs = array(); + foreach ($results as $result) { + $album = new Album($result); + $songs = array_merge($songs, $album->get_songs()); + } + return $songs; + break; + case 'artist': + $songs = array(); + foreach ($results as $result) { + $artist = new Artist($result); + $songs = array_merge($songs, $artist->get_songs()); + } + return $songs; + break; + default: + return false; + break; + } + } // advanced + + /** + * get_type_name + * This returns a 'purrty' name for the different random types + */ + public static function get_type_name($type) { + + switch ($type) { + case 'album': + return T_('Related Album'); + break; + case 'genre': + return T_('Related Genre'); + break; + case 'artist': + return T_('Related Artist'); + break; + default: + return T_('Pure Random'); + break; + } // end switch + + } // get_type_name + + /** + * get_type_id + * This takes random type and returns the ID + * MOTHER OF PEARL THIS MAKES BABY JESUS CRY + * HACK HACK HACK HACK HACK HACK HACK HACK + */ + public static function get_type_id($type) { + + switch ($type) { + case 'album': + return '1'; + break; + case 'artist': + return '2'; + break; + case 'tag': + return '3'; + break; + default: + return '4'; + break; + } + + } // get_type_id + + /** + * get_id_name + * This takes an ID and returns the 'name' of the random dealie + * HACK HACK HACK HACK HACK HACK HACK + * Can you tell I don't like this code? + */ + public static function get_id_type($id) { + + switch ($id) { + case '1': + return 'album'; + break; + case '2': + return 'artist'; + break; + case '3': + return 'tag'; + break; + default: + return 'default'; + break; + } // end switch + + } // get_id_name + + /** + * validate_type + * this validates the random type + */ + public static function validate_type($type) { + + switch ($type) { + case 'default': + case 'genre': + case 'album': + case 'artist': + case 'rated': + return $type; + break; + } // end switch + + return 'default'; + + } // validate_type + + public function native_stream() { } + public function stream_cmd() { } + public function has_flag() { } + public function format() { } } //end of random class diff --git a/lib/class/rating.class.php b/lib/class/rating.class.php index 0943de2f3b..76b8c85e38 100644 --- a/lib/class/rating.class.php +++ b/lib/class/rating.class.php @@ -1,5 +1,5 @@ id = $id; - $this->type = $type; - - return true; - - } // Constructor - - /** - * gc - * - * Remove ratings for items that no longer exist. - */ - public static function gc() { - foreach(array('song', 'album', 'artist', 'video') as $object_type) { - Dba::write("DELETE FROM `rating` USING `rating` LEFT JOIN `$object_type` ON `$object_type`.`id` = `rating`.`object_type` WHERE `object_type` = '$object_type` AND `$object_type`.`id` IS NULL"); - } - } - - /** - * build_cache - * This attempts to get everything we'll need for this page load in a - * single query, saving on connection overhead - */ - public static function build_cache($type, $ids) { - - if (!is_array($ids) OR !count($ids)) { return false; } - - $user_id = intval($GLOBALS['user']->id); - $ratings = array(); - $user_ratings = array(); - - $idlist = '(' . implode(',', $ids) . ')'; - $sql = "SELECT `rating`, `object_id` FROM `rating` " . - "WHERE `user`='$user_id' AND `object_id` IN $idlist " . - "AND `object_type`='$type'"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $user_ratings[$row['object_id']] = $row['rating']; - } - - $sql = "SELECT AVG(`rating`) as `rating`, `object_id` FROM " . - "`rating` WHERE `object_id` IN $idlist AND " . - "`object_type`='$type' GROUP BY `object_id`"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $ratings[$row['object_id']] = $row['rating']; - } - - foreach ($ids as $id) { - // First store the user-specific rating - if (!isset($user_ratings[$id])) { - $rating = 0; - } - else { - $rating = intval($user_ratings[$id]); - } - parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating); - - // Then store the average - if (!isset($ratings[$id])) { - $rating = 0; - } - else { - $rating = round($ratings[$id]['rating'], 1); - } - parent::add_to_cache('rating_' . $type . '_all', $id, $rating); - } - - return true; - - } // build_cache - - /** - * get_user_rating - * Get a user's rating. If no userid is passed in, we use the currently - * logged in user. - */ - public function get_user_rating($user_id = null) { - - $id = intval($this->id); - $type = Dba::escape($this->type); - if (is_null($user_id)) { - $user_id = $GLOBALS['user']->id; - } - $user_id = intval($user_id); - - $key = 'rating_' . $type . '_user' . $user_id; - if (parent::is_cached($key, $id)) { - return parent::get_from_cache($key, $id); - } - - $sql = "SELECT `rating` FROM `rating` WHERE `user`='$user_id' ". - "AND `object_id`='$id' AND `object_type`='$type'"; - $db_results = Dba::read($sql); - - $rating = 0; - - if ($results = Dba::fetch_assoc($db_results)) { - $rating = $results['rating']; - } - - parent::add_to_cache($key, $id, $rating); - return $rating; - - } // get_user_rating - - /** - * get_average_rating - * Get the floored average rating of what everyone has rated this object - * as. This is shown if there is no personal rating. - */ - public function get_average_rating() { - - $id = intval($this->id); - $type = Dba::escape($this->type); - - if (parent::is_cached('rating_' . $type . '_all', $id)) { - return parent::get_from_cache('rating_' . $type . '_user', $id); - } - - $sql = "SELECT AVG(`rating`) as `rating` FROM `rating` WHERE " . - "`object_id`='$id' AND `object_type`='$type'"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - - parent::add_to_cache('rating_' . $type . '_all', $id, $results['rating']); - return $results['rating']; - - } // get_average_rating - - /** - * set_rating - * This function sets the rating for the current object. - * If no userid is passed in, we use the currently logged in user. - */ - public function set_rating($rating, $user_id = null) { - $id = intval($this->id); - $type = Dba::escape($this->type); - $rating = intval($rating); - if (is_null($user_id)) { - $user_id = $GLOBALS['user']->id; - } - $user_id = intval($user_id); - - debug_event('Rating', "Setting rating for $type $id to $rating", 5); - - // If score is -1, then remove rating - if ($rating == '-1') { - $sql = "DELETE FROM `rating` WHERE " . - "`object_id`='$this->id' AND " . - "`object_type`='$this->type' AND " . - "`user`='$user_id'"; - } - else { - $sql = "REPLACE INTO `rating` " . - "(`object_id`, `object_type`, `rating`, `user`) " . - "VALUES ('$id', '$type', '$rating', '$user_id')"; - } - $db_results = Dba::write($sql); - - parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating); - - foreach (Plugin::get_plugins('save_rating') as $plugin_name) { - $plugin = new Plugin($plugin_name); - if ($plugin->load()) { - $plugin->_plugin->save_rating($this, $rating); - } - } - - return true; - - } // set_rating - - /** - * show - * This takes an id and a type and displays the rating if ratings are - * enabled. If $static is true, the rating won't be editable. - */ - public static function show($object_id, $type, $static=false) { - - // If ratings aren't enabled don't do anything - if (!Config::get('ratings')) { return false; } - - $rating = new Rating($object_id, $type); - - if ($static) { - require Config::get('prefix') . '/templates/show_static_object_rating.inc.php'; - } - else { - require Config::get('prefix') . '/templates/show_object_rating.inc.php'; - } - - } // show + // Public variables + public $id; // The ID of the object rated + public $type; // The type of object we want + + /** + * Constructor + * This is run every time a new object is created, and requires + * the id and type of object that we need to pull the rating for + */ + public function __construct($id, $type) { + $id = intval($id); + $type = Dba::escape($type); + + $this->id = $id; + $this->type = $type; + + return true; + + } // Constructor + + /** + * gc + * + * Remove ratings for items that no longer exist. + */ + public static function gc() { + foreach(array('song', 'album', 'artist', 'video') as $object_type) { + Dba::write("DELETE FROM `rating` USING `rating` LEFT JOIN `$object_type` ON `$object_type`.`id` = `rating`.`object_type` WHERE `object_type` = '$object_type` AND `$object_type`.`id` IS NULL"); + } + } + + /** + * build_cache + * This attempts to get everything we'll need for this page load in a + * single query, saving on connection overhead + */ + public static function build_cache($type, $ids) { + + if (!is_array($ids) OR !count($ids)) { return false; } + + $user_id = intval($GLOBALS['user']->id); + $ratings = array(); + $user_ratings = array(); + + $idlist = '(' . implode(',', $ids) . ')'; + $sql = "SELECT `rating`, `object_id` FROM `rating` " . + "WHERE `user`='$user_id' AND `object_id` IN $idlist " . + "AND `object_type`='$type'"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $user_ratings[$row['object_id']] = $row['rating']; + } + + $sql = "SELECT AVG(`rating`) as `rating`, `object_id` FROM " . + "`rating` WHERE `object_id` IN $idlist AND " . + "`object_type`='$type' GROUP BY `object_id`"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $ratings[$row['object_id']] = $row['rating']; + } + + foreach ($ids as $id) { + // First store the user-specific rating + if (!isset($user_ratings[$id])) { + $rating = 0; + } + else { + $rating = intval($user_ratings[$id]); + } + parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating); + + // Then store the average + if (!isset($ratings[$id])) { + $rating = 0; + } + else { + $rating = round($ratings[$id]['rating'], 1); + } + parent::add_to_cache('rating_' . $type . '_all', $id, $rating); + } + + return true; + + } // build_cache + + /** + * get_user_rating + * Get a user's rating. If no userid is passed in, we use the currently + * logged in user. + */ + public function get_user_rating($user_id = null) { + + $id = intval($this->id); + $type = Dba::escape($this->type); + if (is_null($user_id)) { + $user_id = $GLOBALS['user']->id; + } + $user_id = intval($user_id); + + $key = 'rating_' . $type . '_user' . $user_id; + if (parent::is_cached($key, $id)) { + return parent::get_from_cache($key, $id); + } + + $sql = "SELECT `rating` FROM `rating` WHERE `user`='$user_id' ". + "AND `object_id`='$id' AND `object_type`='$type'"; + $db_results = Dba::read($sql); + + $rating = 0; + + if ($results = Dba::fetch_assoc($db_results)) { + $rating = $results['rating']; + } + + parent::add_to_cache($key, $id, $rating); + return $rating; + + } // get_user_rating + + /** + * get_average_rating + * Get the floored average rating of what everyone has rated this object + * as. This is shown if there is no personal rating. + */ + public function get_average_rating() { + + $id = intval($this->id); + $type = Dba::escape($this->type); + + if (parent::is_cached('rating_' . $type . '_all', $id)) { + return parent::get_from_cache('rating_' . $type . '_user', $id); + } + + $sql = "SELECT AVG(`rating`) as `rating` FROM `rating` WHERE " . + "`object_id`='$id' AND `object_type`='$type'"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + + parent::add_to_cache('rating_' . $type . '_all', $id, $results['rating']); + return $results['rating']; + + } // get_average_rating + + /** + * set_rating + * This function sets the rating for the current object. + * If no userid is passed in, we use the currently logged in user. + */ + public function set_rating($rating, $user_id = null) { + $id = intval($this->id); + $type = Dba::escape($this->type); + $rating = intval($rating); + if (is_null($user_id)) { + $user_id = $GLOBALS['user']->id; + } + $user_id = intval($user_id); + + debug_event('Rating', "Setting rating for $type $id to $rating", 5); + + // If score is -1, then remove rating + if ($rating == '-1') { + $sql = "DELETE FROM `rating` WHERE " . + "`object_id`='$this->id' AND " . + "`object_type`='$this->type' AND " . + "`user`='$user_id'"; + } + else { + $sql = "REPLACE INTO `rating` " . + "(`object_id`, `object_type`, `rating`, `user`) " . + "VALUES ('$id', '$type', '$rating', '$user_id')"; + } + $db_results = Dba::write($sql); + + parent::add_to_cache('rating_' . $type . '_user' . $user_id, $id, $rating); + + foreach (Plugin::get_plugins('save_rating') as $plugin_name) { + $plugin = new Plugin($plugin_name); + if ($plugin->load()) { + $plugin->_plugin->save_rating($this, $rating); + } + } + + return true; + + } // set_rating + + /** + * show + * This takes an id and a type and displays the rating if ratings are + * enabled. If $static is true, the rating won't be editable. + */ + public static function show($object_id, $type, $static=false) { + + // If ratings aren't enabled don't do anything + if (!Config::get('ratings')) { return false; } + + $rating = new Rating($object_id, $type); + + if ($static) { + require Config::get('prefix') . '/templates/show_static_object_rating.inc.php'; + } + else { + require Config::get('prefix') . '/templates/show_object_rating.inc.php'; + } + + } // show } //end rating class ?> diff --git a/lib/class/recommendation.class.php b/lib/class/recommendation.class.php index 98cd07e70a..138d81b472 100644 --- a/lib/class/recommendation.class.php +++ b/lib/class/recommendation.class.php @@ -1,5 +1,5 @@ proxy_user = Config::get('proxy_host'); - $snoopy->proxy_port = Config::get('proxy_port'); - $snoopy->proxy_user = Config::get('proxy_user'); - $snoopy->proxy_pass = Config::get('proxy_pass'); - } - $snoopy->fetch($url); - $content = $snoopy->results; - - return simplexml_load_string($content); - } // get_lastfm_results - - /** - * get_songs_like - * Returns a list of similar songs - */ - public static function get_songs_like($song_id, $limit = 5, $local_only = true) { - $song = new Song($song_id); - - if (isset($song->mbid)) { - $query = 'mbid=' . rawurlencode($song->mbid); - } - else { - $query = 'track=' . rawurlencode($song->title); - } - - if ($limit && !$local_only) { - $query .= "&limit=$limit"; - } - - $xml = self::get_lastfm_results('track.getsimilar', $query); - - foreach ($xml->similartracks->children() as $child) { - $name = $child->name; - $local_id = null; - - $artist_name = $child->artist->name; - $s_artist_name = Catalog::trim_prefix($artist_name); - $s_artist_name = Dba::escape($s_artist_name['string']); - - $sql = "SELECT `song`.`id` FROM `song` " . - "LEFT JOIN `artist` ON " . - "`song`.`artist`=`artist`.`id` WHERE " . - "`song`.`title`='" . Dba::escape($name) . - "' AND `artist`.`name`='$s_artist_name'"; - - $db_result = Dba::read($sql); - - if ($result = Dba::fetch_assoc($db_result)) { - $local_id = $result['id']; - } - - if (is_null($local_id)) { - debug_event('Recommendation', "$name did not match any local song", 5); - if (! $local_only) { - $results[] = array( - 'id' => null, - 'title' => $name, - 'artist' => $artist_name - ); - } - } - else { - debug_event('Recommendation', "$name matched local song $local_id", 5); - $results[] = array( - 'id' => $local_id, - 'title' => $name - ); - } - - if ($limit && count($results) >= $limit) { - break; - } - } - - if (isset($results)) { - return $results; - } - - return false; - } - - /** - * get_artists_like - * Returns a list of similar artists - */ - public static function get_artists_like($artist_id, $limit = 5, $local_only = true) { - $artist = new Artist($artist_id); - - $query = 'artist=' . rawurlencode($artist->name); - if ($limit && !$local_only) { - $query .= "&limit=$limit"; - } - - $xml = self::get_lastfm_results('artist.getsimilar', $query); - - foreach ($xml->similarartists->children() as $child) { - $name = $child->name; - $local_id = null; - - // First we check by MBID - if ((string)$child->mbid) { - $mbid = Dba::escape($child->mbid); - $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'"; - $db_result = Dba::read($sql); - if ($result = Dba::fetch_assoc($db_result)) { - $local_id = $result['id']; - } - } - - // Then we fall back to the less likely to work exact - // name match - if (is_null($local_id)) { - $searchname = Catalog::trim_prefix($name); - $searchname = Dba::escape($searchname['string']); - $sql = "SELECT `id` FROM `artist` WHERE `name`='$searchname'"; - $db_result = Dba::read($sql); - if ($result = Dba::fetch_assoc($db_result)) { - $local_id = $result['id']; - } - } - - // Then we give up - if (is_null($local_id)) { - debug_event('Recommendation', "$name did not match any local artist", 5); - if (! $local_only) { - $results[] = array( - 'id' => null, - 'name' => $name - ); - } - } - else { - debug_event('Recommendation', "$name matched local artist " . $local_id, 5); - $results[] = array( - 'id' => $local_id, - 'name' => $name - ); - } - - // Don't do more work than we have to - if ($limit && count($results) >= $limit) { - break; - } - } - - if (isset($results)) { - return $results; - } - - return false; - } // get_artists_like + /** + * Constructor + * Not on my watch, boyo. + */ + private function __construct() { + return false; + } //constructor + + /** + * get_lastfm_results + * Runs a last.fm query and returns the parsed results + */ + private static function get_lastfm_results($method, $query) { + $api_key = Config::get('lastfm_api_key'); + $api_base = "http://ws.audioscrobbler.com/2.0/?method="; + $url = $api_base . $method . '&api_key=' . $api_key . '&' . $query; + debug_event('Recommendation', 'search url : ' . $url, 5); + + $snoopy = new Snoopy(); + if(Config::get('proxy_host') AND Config::get('proxy_port')) { + $snoopy->proxy_user = Config::get('proxy_host'); + $snoopy->proxy_port = Config::get('proxy_port'); + $snoopy->proxy_user = Config::get('proxy_user'); + $snoopy->proxy_pass = Config::get('proxy_pass'); + } + $snoopy->fetch($url); + $content = $snoopy->results; + + return simplexml_load_string($content); + } // get_lastfm_results + + /** + * get_songs_like + * Returns a list of similar songs + */ + public static function get_songs_like($song_id, $limit = 5, $local_only = true) { + $song = new Song($song_id); + + if (isset($song->mbid)) { + $query = 'mbid=' . rawurlencode($song->mbid); + } + else { + $query = 'track=' . rawurlencode($song->title); + } + + if ($limit && !$local_only) { + $query .= "&limit=$limit"; + } + + $xml = self::get_lastfm_results('track.getsimilar', $query); + + foreach ($xml->similartracks->children() as $child) { + $name = $child->name; + $local_id = null; + + $artist_name = $child->artist->name; + $s_artist_name = Catalog::trim_prefix($artist_name); + $s_artist_name = Dba::escape($s_artist_name['string']); + + $sql = "SELECT `song`.`id` FROM `song` " . + "LEFT JOIN `artist` ON " . + "`song`.`artist`=`artist`.`id` WHERE " . + "`song`.`title`='" . Dba::escape($name) . + "' AND `artist`.`name`='$s_artist_name'"; + + $db_result = Dba::read($sql); + + if ($result = Dba::fetch_assoc($db_result)) { + $local_id = $result['id']; + } + + if (is_null($local_id)) { + debug_event('Recommendation', "$name did not match any local song", 5); + if (! $local_only) { + $results[] = array( + 'id' => null, + 'title' => $name, + 'artist' => $artist_name + ); + } + } + else { + debug_event('Recommendation', "$name matched local song $local_id", 5); + $results[] = array( + 'id' => $local_id, + 'title' => $name + ); + } + + if ($limit && count($results) >= $limit) { + break; + } + } + + if (isset($results)) { + return $results; + } + + return false; + } + + /** + * get_artists_like + * Returns a list of similar artists + */ + public static function get_artists_like($artist_id, $limit = 5, $local_only = true) { + $artist = new Artist($artist_id); + + $query = 'artist=' . rawurlencode($artist->name); + if ($limit && !$local_only) { + $query .= "&limit=$limit"; + } + + $xml = self::get_lastfm_results('artist.getsimilar', $query); + + foreach ($xml->similarartists->children() as $child) { + $name = $child->name; + $local_id = null; + + // First we check by MBID + if ((string)$child->mbid) { + $mbid = Dba::escape($child->mbid); + $sql = "SELECT `id` FROM `artist` WHERE `mbid`='$mbid'"; + $db_result = Dba::read($sql); + if ($result = Dba::fetch_assoc($db_result)) { + $local_id = $result['id']; + } + } + + // Then we fall back to the less likely to work exact + // name match + if (is_null($local_id)) { + $searchname = Catalog::trim_prefix($name); + $searchname = Dba::escape($searchname['string']); + $sql = "SELECT `id` FROM `artist` WHERE `name`='$searchname'"; + $db_result = Dba::read($sql); + if ($result = Dba::fetch_assoc($db_result)) { + $local_id = $result['id']; + } + } + + // Then we give up + if (is_null($local_id)) { + debug_event('Recommendation', "$name did not match any local artist", 5); + if (! $local_only) { + $results[] = array( + 'id' => null, + 'name' => $name + ); + } + } + else { + debug_event('Recommendation', "$name matched local artist " . $local_id, 5); + $results[] = array( + 'id' => $local_id, + 'name' => $name + ); + } + + // Don't do more work than we have to + if ($limit && count($results) >= $limit) { + break; + } + } + + if (isset($results)) { + return $results; + } + + return false; + } // get_artists_like } // end of recommendation class ?> diff --git a/lib/class/registration.class.php b/lib/class/registration.class.php index d22a23aba2..5df8e563fe 100644 --- a/lib/class/registration.class.php +++ b/lib/class/registration.class.php @@ -1,5 +1,5 @@ set_default_sender(); + // We are the system + $mailer->set_default_sender(); - $mailer->subject = sprintf(T_("New User Registration at %s"), Config::get('site_title')); + $mailer->subject = sprintf(T_("New User Registration at %s"), Config::get('site_title')); - $mailer->message = sprintf(T_("Thank you for registering\n\n + $mailer->message = sprintf(T_("Thank you for registering\n\n Please keep this e-mail for your records. Your account information is as follows: ---------------------- Username: %s @@ -64,14 +64,14 @@ public static function send_confirmation($username, $fullname, $email, $password Thank you for registering "), $username, $password, Config::get('web_path') . "/register.php?action=validate&username=$username&auth=$validation"); - $mailer->recipient = $email; - $mailer->recipient_name = $fullname; + $mailer->recipient = $email; + $mailer->recipient_name = $fullname; - $mailer->send(); + $mailer->send(); - // Check to see if the admin should be notified - if (Config::get('admin_notify_reg')) { - $mailer->message = sprintf(T_("A new user has registered + // Check to see if the admin should be notified + if (Config::get('admin_notify_reg')) { + $mailer->message = sprintf(T_("A new user has registered The following values were entered. Username: %s @@ -80,34 +80,34 @@ public static function send_confirmation($username, $fullname, $email, $password "), $username, $fullname, $email); - $mailer->send_to_group('admins'); - } - - return true; + $mailer->send_to_group('admins'); + } + + return true; - } // send_confirmation + } // send_confirmation - /** - * show_agreement - * This shows the registration agreement, /config/registration_agreement.php - */ - public static function show_agreement() { + /** + * show_agreement + * This shows the registration agreement, /config/registration_agreement.php + */ + public static function show_agreement() { - $filename = Config::get('prefix') . '/config/registration_agreement.php'; + $filename = Config::get('prefix') . '/config/registration_agreement.php'; - if (!file_exists($filename)) { return false; } + if (!file_exists($filename)) { return false; } - /* Check for existance */ - $fp = fopen($filename,'r'); + /* Check for existance */ + $fp = fopen($filename,'r'); - if (!$fp) { return false; } + if (!$fp) { return false; } - $data = fread($fp,filesize($filename)); + $data = fread($fp,filesize($filename)); - /* Scrub and show */ - echo $data; + /* Scrub and show */ + echo $data; - } // show_agreement + } // show_agreement } // end registration class ?> diff --git a/lib/class/scrobbler.class.php b/lib/class/scrobbler.class.php index 96ca84c863..f7b4482a20 100644 --- a/lib/class/scrobbler.class.php +++ b/lib/class/scrobbler.class.php @@ -1,5 +1,5 @@ error_msg = ''; - $this->username = trim($username); - $this->password = trim($password); - $this->challenge = $challenge; - $this->submit_host = $host; - $this->submit_port = $port; - $this->submit_url = $url; - $this->queued_tracks = array(); - if ($scrobble_host) { $this->scrobble_host = $scrobble_host; } - - } // scrobbler - - /** - * get_error_msg - */ - public function get_error_msg() { - - return $this->error_msg; - - } // get_error_msg - - /** - * get_queue_count - */ - public function get_queue_count() { - - return count($this->queued_tracks); - - } // get_queue_count - - /** - * handshake - * This does a handshake with the audioscrobber server it doesn't pass the password, but - * it does pass the username and has a 10 second timeout - */ - public function handshake() { - - $as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2); - if(!$as_socket) { - $this->error_msg = $errstr; - return false; - } - - $username = rawurlencode($this->username); - $timestamp = time(); - $auth_token = rawurlencode(md5($this->password . $timestamp)); - - $get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n"; - - fwrite($as_socket, $get_string); - fwrite($as_socket, "Host: $this->scrobble_host\r\n"); - fwrite($as_socket, "Accept: */*\r\n\r\n"); - - $buffer = ''; - while(!feof($as_socket)) { - $buffer .= fread($as_socket, 4096); - } - fclose($as_socket); - $split_response = preg_split("/\r\n\r\n/", $buffer); - if(!isset($split_response[1])) { - $this->error_msg = 'Did not receive a valid response'; - return false; - } - $response = explode("\n", $split_response[1]); - - // Handle the fact Libre.FM has extranious values at the start of it's handshake response - if(is_numeric(trim($response['0']))) { - array_shift($response); - debug_event('SCROBBLER','Junk in handshake, removing first line',1); - } - if(substr($response[0], 0, 6) == 'FAILED') { - $this->error_msg = substr($response[0], 7); - return false; - } - if(substr($response[0], 0, 7) == 'BADUSER') { - $this->error_msg = 'Invalid Username'; - return false; - } - if(substr($response[0],0,7) == 'BADTIME') { - $this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect'; - return false; - } - if(substr($response[0], 0, 6) == 'UPDATE') { - $this->error_msg = 'You need to update your client: '.substr($response[0], 7); - return false; - } - - if(preg_match('/http:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) { - $host_parts = explode(":",$matches[1]); - $data['submit_host'] = $host_parts[0]; - $data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80'; - $data['submit_url'] = '/' . $matches[2]; - } else { - $this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer . - "\n---------\nExpected:" . print_r($response, true); - return false; - } - - // Remove any extra junk around the challenge - $data['challenge'] = trim($response[1]); - return $data; - - } // handshake - - /** - * queue_track - * This queues the LastFM track by storing it in this object, it doesn't actually - * submit the track or talk to LastFM in anyway, kind of useless for our uses but its - * here, and that's how it is. - */ - public function queue_track($artist, $album, $title, $timestamp, $length,$track) { - - if ($length < 30) { - debug_event('Scrobbler',"Not queuing track, too short",'5'); - return false; - } - - $newtrack = array(); - $newtrack['artist'] = $artist; - $newtrack['album'] = $album; - $newtrack['title'] = $title; - $newtrack['track'] = $track; - $newtrack['length'] = $length; - $newtrack['time'] = $timestamp; - - $this->queued_tracks[$timestamp] = $newtrack; - return true; - - } // queue_track - - /** - * submit_tracks - * This actually talks to LastFM submiting the tracks that are queued up. It - * passed the md5'd password combinted with the challenge, which is then md5'd - */ - public function submit_tracks() { - - // Check and make sure that we've got some queued tracks - if(!count($this->queued_tracks)) { - $this->error_msg = "No tracks to submit"; - return false; - } - - //sort array by timestamp - ksort($this->queued_tracks); - - // build the query string - $query_str = 's='.rawurlencode($this->challenge).'&'; - - $i = 0; - - foreach($this->queued_tracks as $track) { - $query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&"; - $query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&"; - $query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&"; - $i++; - } - - if (!trim($this->submit_host) || !$this->submit_port) { - $this->reset_handshake = true; - return false; - } - - $as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2); - - if(!$as_socket) { - $this->error_msg = $errstr; - $this->reset_handshake = true; - return false; - } - - $action = "POST ".$this->submit_url." HTTP/1.0\r\n"; - fwrite($as_socket, $action); - fwrite($as_socket, "Host: ".$this->submit_host."\r\n"); - fwrite($as_socket, "Accept: */*\r\n"); - fwrite($as_socket, "User-Agent: Ampache/3.6\r\n"); - fwrite($as_socket, "Content-type: application/x-www-form-urlencoded\r\n"); - fwrite($as_socket, "Content-length: ".strlen($query_str)."\r\n\r\n"); - - fwrite($as_socket, $query_str."\r\n\r\n"); - // Allow us to debug this - debug_event('SCROBBLER','Query String:' . $query_str,6); - - $buffer = ''; - while(!feof($as_socket)) { - $buffer .= fread($as_socket, 8192); - } - fclose($as_socket); - - $split_response = preg_split("/\r\n\r\n/", $buffer); - if(!isset($split_response[1])) { - $this->error_msg = 'Did not receive a valid response'; - $this->reset_handshake = true; - return false; - } - $response = explode("\n", $split_response[1]); - if(!isset($response[0])) { - $this->error_msg = 'Unknown error submitting tracks'. - "\nDebug output:\n".$buffer; - $this->reset_handshake = true; - return false; - } - if(substr($response[0], 0, 6) == 'FAILED') { - $this->error_msg = $response[0]; - $this->reset_handshake = true; - return false; - } - if(substr($response[0], 0, 7) == 'BADAUTH') { - $this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')'; - return false; - } - if (substr($response[0],0,10) == 'BADSESSION') { - $this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')'; - $this->reset_handshake = true; - return false; - } - if(substr($response[0], 0, 2) != 'OK') { - $this->error_msg = 'Response Not ok, unknown error'. - "\nDebug output:\n".$buffer; - $this->reset_handshake = true; - return false; - } - - return true; - - } // submit_tracks + public $error_msg; + public $username; + public $password; + public $challenge; + public $submit_host; + public $submit_port; + public $submit_url; + public $queued_tracks; + public $reset_handshake = false; + public $scrobble_host = 'post.audioscrobbler.com'; + + /** + * Constructor + * This is the constructer it takes a username and password + */ + public function __construct($username, $password,$host='',$port='',$url='',$challenge='',$scrobble_host='') { + + $this->error_msg = ''; + $this->username = trim($username); + $this->password = trim($password); + $this->challenge = $challenge; + $this->submit_host = $host; + $this->submit_port = $port; + $this->submit_url = $url; + $this->queued_tracks = array(); + if ($scrobble_host) { $this->scrobble_host = $scrobble_host; } + + } // scrobbler + + /** + * get_error_msg + */ + public function get_error_msg() { + + return $this->error_msg; + + } // get_error_msg + + /** + * get_queue_count + */ + public function get_queue_count() { + + return count($this->queued_tracks); + + } // get_queue_count + + /** + * handshake + * This does a handshake with the audioscrobber server it doesn't pass the password, but + * it does pass the username and has a 10 second timeout + */ + public function handshake() { + + $as_socket = fsockopen($this->scrobble_host, 80, $errno, $errstr, 2); + if(!$as_socket) { + $this->error_msg = $errstr; + return false; + } + + $username = rawurlencode($this->username); + $timestamp = time(); + $auth_token = rawurlencode(md5($this->password . $timestamp)); + + $get_string = "GET /?hs=true&p=1.2&c=apa&v=0.1&u=$username&t=$timestamp&a=$auth_token HTTP/1.1\r\n"; + + fwrite($as_socket, $get_string); + fwrite($as_socket, "Host: $this->scrobble_host\r\n"); + fwrite($as_socket, "Accept: */*\r\n\r\n"); + + $buffer = ''; + while(!feof($as_socket)) { + $buffer .= fread($as_socket, 4096); + } + fclose($as_socket); + $split_response = preg_split("/\r\n\r\n/", $buffer); + if(!isset($split_response[1])) { + $this->error_msg = 'Did not receive a valid response'; + return false; + } + $response = explode("\n", $split_response[1]); + + // Handle the fact Libre.FM has extranious values at the start of it's handshake response + if(is_numeric(trim($response['0']))) { + array_shift($response); + debug_event('SCROBBLER','Junk in handshake, removing first line',1); + } + if(substr($response[0], 0, 6) == 'FAILED') { + $this->error_msg = substr($response[0], 7); + return false; + } + if(substr($response[0], 0, 7) == 'BADUSER') { + $this->error_msg = 'Invalid Username'; + return false; + } + if(substr($response[0],0,7) == 'BADTIME') { + $this->error_msg = 'Your time is too far off from the server, or your PHP timezone is incorrect'; + return false; + } + if(substr($response[0], 0, 6) == 'UPDATE') { + $this->error_msg = 'You need to update your client: '.substr($response[0], 7); + return false; + } + + if(preg_match('/http:\/\/([^\/]+)\/(.*)$/', $response[3], $matches)) { + $host_parts = explode(":",$matches[1]); + $data['submit_host'] = $host_parts[0]; + $data['submit_port'] = $host_parts[1] ? $host_parts[1] : '80'; + $data['submit_url'] = '/' . $matches[2]; + } else { + $this->error_msg = "Invalid POST URL returned, unable to continue. Sent:\n$get_string\n----\nReceived:\n" . $buffer . + "\n---------\nExpected:" . print_r($response, true); + return false; + } + + // Remove any extra junk around the challenge + $data['challenge'] = trim($response[1]); + return $data; + + } // handshake + + /** + * queue_track + * This queues the LastFM track by storing it in this object, it doesn't actually + * submit the track or talk to LastFM in anyway, kind of useless for our uses but its + * here, and that's how it is. + */ + public function queue_track($artist, $album, $title, $timestamp, $length,$track) { + + if ($length < 30) { + debug_event('Scrobbler',"Not queuing track, too short",'5'); + return false; + } + + $newtrack = array(); + $newtrack['artist'] = $artist; + $newtrack['album'] = $album; + $newtrack['title'] = $title; + $newtrack['track'] = $track; + $newtrack['length'] = $length; + $newtrack['time'] = $timestamp; + + $this->queued_tracks[$timestamp] = $newtrack; + return true; + + } // queue_track + + /** + * submit_tracks + * This actually talks to LastFM submiting the tracks that are queued up. It + * passed the md5'd password combinted with the challenge, which is then md5'd + */ + public function submit_tracks() { + + // Check and make sure that we've got some queued tracks + if(!count($this->queued_tracks)) { + $this->error_msg = "No tracks to submit"; + return false; + } + + //sort array by timestamp + ksort($this->queued_tracks); + + // build the query string + $query_str = 's='.rawurlencode($this->challenge).'&'; + + $i = 0; + + foreach($this->queued_tracks as $track) { + $query_str .= "a[$i]=".rawurlencode($track['artist'])."&t[$i]=".rawurlencode($track['title'])."&b[$i]=".rawurlencode($track['album'])."&"; + $query_str .= "m[$i]=&l[$i]=".rawurlencode($track['length'])."&i[$i]=".rawurlencode($track['time'])."&"; + $query_str .= "n[$i]=" . rawurlencode($track['track']) . "&o[$i]=P&r[$i]=&"; + $i++; + } + + if (!trim($this->submit_host) || !$this->submit_port) { + $this->reset_handshake = true; + return false; + } + + $as_socket = fsockopen($this->submit_host, intval($this->submit_port), $errno, $errstr, 2); + + if(!$as_socket) { + $this->error_msg = $errstr; + $this->reset_handshake = true; + return false; + } + + $action = "POST ".$this->submit_url." HTTP/1.0\r\n"; + fwrite($as_socket, $action); + fwrite($as_socket, "Host: ".$this->submit_host."\r\n"); + fwrite($as_socket, "Accept: */*\r\n"); + fwrite($as_socket, "User-Agent: Ampache/3.6\r\n"); + fwrite($as_socket, "Content-type: application/x-www-form-urlencoded\r\n"); + fwrite($as_socket, "Content-length: ".strlen($query_str)."\r\n\r\n"); + + fwrite($as_socket, $query_str."\r\n\r\n"); + // Allow us to debug this + debug_event('SCROBBLER','Query String:' . $query_str,6); + + $buffer = ''; + while(!feof($as_socket)) { + $buffer .= fread($as_socket, 8192); + } + fclose($as_socket); + + $split_response = preg_split("/\r\n\r\n/", $buffer); + if(!isset($split_response[1])) { + $this->error_msg = 'Did not receive a valid response'; + $this->reset_handshake = true; + return false; + } + $response = explode("\n", $split_response[1]); + if(!isset($response[0])) { + $this->error_msg = 'Unknown error submitting tracks'. + "\nDebug output:\n".$buffer; + $this->reset_handshake = true; + return false; + } + if(substr($response[0], 0, 6) == 'FAILED') { + $this->error_msg = $response[0]; + $this->reset_handshake = true; + return false; + } + if(substr($response[0], 0, 7) == 'BADAUTH') { + $this->error_msg = 'Invalid username/password (' . trim($response[0]) . ')'; + return false; + } + if (substr($response[0],0,10) == 'BADSESSION') { + $this->error_msg = 'Invalid Session passed (' . trim($response[0]) . ')'; + $this->reset_handshake = true; + return false; + } + if(substr($response[0], 0, 2) != 'OK') { + $this->error_msg = 'Response Not ok, unknown error'. + "\nDebug output:\n".$buffer; + $this->reset_handshake = true; + return false; + } + + return true; + + } // submit_tracks } // end audioscrobbler class ?> diff --git a/lib/class/search.class.php b/lib/class/search.class.php index dea0b41d6f..6a1c2352ab 100644 --- a/lib/class/search.class.php +++ b/lib/class/search.class.php @@ -1,5 +1,5 @@ searchtype = $searchtype; - if ($id) { - $info = $this->get_info($id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } - - $this->rules = unserialize($this->rules); - } - - // Define our basetypes - - $this->basetypes['numeric'][] = array( - 'name' => 'gte', - 'description' => T_('is greater than or equal to'), - 'sql' => '>=' - ); - - $this->basetypes['numeric'][] = array( - 'name' => 'lte', - 'description' => T_('is less than or equal to'), - 'sql' => '<=' - ); - - $this->basetypes['numeric'][] = array( - 'name' => 'equal', - 'description' => T_('is'), - 'sql' => '<=>' - ); - - $this->basetypes['numeric'][] = array( - 'name' => 'ne', - 'description' => T_('is not'), - 'sql' => '<>' - ); - - $this->basetypes['numeric'][] = array( - 'name' => 'gt', - 'description' => T_('is greater than'), - 'sql' => '>' - ); - - $this->basetypes['numeric'][] = array( - 'name' => 'lt', - 'description' => T_('is less than'), - 'sql' => '<' - ); - - - $this->basetypes['boolean'][] = array( - 'name' => 'true', - 'description' => T_('is true') - ); - - $this->basetypes['boolean'][] = array( - 'name' => 'false', - 'description' => T_('is false') - ); - - - $this->basetypes['text'][] = array( - 'name' => 'contain', - 'description' => T_('contains'), - 'sql' => 'LIKE', - 'preg_match' => array('/^/','/$/'), - 'preg_replace' => array('%', '%') - ); - - $this->basetypes['text'][] = array( - 'name' => 'notcontain', - 'description' => T_('does not contain'), - 'sql' => 'NOT LIKE', - 'preg_match' => array('/^/','/$/'), - 'preg_replace' => array('%', '%') - ); - - $this->basetypes['text'][] = array( - 'name' => 'start', - 'description' => T_('starts with'), - 'sql' => 'LIKE', - 'preg_match' => '/$/', - 'preg_replace' => '%' - ); - - $this->basetypes['text'][] = array( - 'name' => 'end', - 'description' => T_('ends with'), - 'sql' => 'LIKE', - 'preg_match' => '/^/', - 'preg_replace' => '%' - ); - - $this->basetypes['text'][] = array( - 'name' => 'equal', - 'description' => T_('is'), - 'sql' => '=' - ); - - $this->basetypes['text'][] = array( - 'name' => 'sounds', - 'description' => T_('sounds like'), - 'sql' => 'SOUNDS LIKE' - ); - - $this->basetypes['text'][] = array( - 'name' => 'notsounds', - 'description' => T_('does not sound like'), - 'sql' => 'NOT SOUNDS LIKE' - ); - - - $this->basetypes['boolean_numeric'][] = array( - 'name' => 'equal', - 'description' => T_('is'), - 'sql' => '<=>' - ); - - $this->basetypes['boolean_numeric'][] = array( - 'name' => 'ne', - 'description' => T_('is not'), - 'sql' => '<>' - ); - - - $this->basetypes['boolean_subsearch'][] = array( - 'name' => 'equal', - 'description' => T_('is'), - 'sql' => '' - ); - - $this->basetypes['boolean_subsearch'][] = array( - 'name' => 'ne', - 'description' => T_('is not'), - 'sql' => 'NOT' - ); - - - $this->basetypes['date'][] = array( - 'name' => 'lt', - 'description' => T_('before'), - 'sql' => '>' - ); - - $this->basetypes['date'][] = array( - 'name' => 'gt', - 'description' => T_('after'), - 'sql' => '>' - ); - - switch ($searchtype) { - case 'song': - $this->types[] = array( - 'name' => 'anywhere', - 'label' => T_('Any searchable text'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'title', - 'label' => T_('Title'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'album', - 'label' => T_('Album'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'artist', - 'label' => T_('Artist'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'comment', - 'label' => T_('Comment'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - - $this->types[] = array( - 'name' => 'tag', - 'label' => T_('Tag'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'file', - 'label' => T_('Filename'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'year', - 'label' => T_('Year'), - 'type' => 'numeric', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'time', - 'label' => T_('Length (in minutes)'), - 'type' => 'numeric', - 'widget' => array('input', 'text') - ); - - if (Config::get('ratings')) { - $this->types[] = array( - 'name' => 'rating', - 'label' => T_('Rating'), - 'type' => 'numeric', - 'widget' => array( - 'select', - array( - '1 Star', - '2 Stars', - '3 Stars', - '4 Stars', - '5 Stars' - ) - ) - ); - } - - $this->types[] = array( - 'name' => 'bitrate', - 'label' => T_('Bitrate'), - 'type' => 'numeric', - 'widget' => array( - 'select', - array( - '32', - '40', - '48', - '56', - '64', - '80', - '96', - '112', - '128', - '160', - '192', - '224', - '256', - '320' - ) - ) - ); - - $this->types[] = array( - 'name' => 'played', - 'label' => T_('Played'), - 'type' => 'boolean', - 'widget' => array('input', 'hidden') - ); - - $this->types[] = array( - 'name' => 'added', - 'label' => T_('Added'), - 'type' => 'date', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'updated', - 'label' => T_('Updated'), - 'type' => 'date', - 'widget' => array('input', 'text') - ); - - $catalogs = array(); - foreach (Catalog::get_catalogs() as $catid) { - $catalog = new Catalog($catid); - $catalog->format(); - $catalogs[$catid] = $catalog->f_name; - } - $this->types[] = array( - 'name' => 'catalog', - 'label' => T_('Catalog'), - 'type' => 'boolean_numeric', - 'widget' => array('select', $catalogs) - ); - - $playlists = array(); - foreach (Playlist::get_playlists() as $playlistid) { - $playlist = new Playlist($playlistid); - $playlist->format(); - $playlists[$playlistid] = $playlist->f_name; - } - $this->types[] = array( - 'name' => 'playlist', - 'label' => T_('Playlist'), - 'type' => 'boolean_numeric', - 'widget' => array('select', $playlists) - ); - - $playlists = array(); - foreach (Search::get_searches() as $playlistid) { - // Slightly different from the above so we don't - // instigate a vicious loop. - $playlists[$playlistid] = Search::get_name_byid($playlistid); - } - $this->types[] = array( - 'name' => 'smartplaylist', - 'label' => T_('Smart Playlist'), - 'type' => 'boolean_subsearch', - 'widget' => array('select', $playlists) - ); - break; - case 'album': - $this->types[] = array( - 'name' => 'title', - 'label' => T_('Title'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - - $this->types[] = array( - 'name' => 'year', - 'label' => T_('Year'), - 'type' => 'numeric', - 'widget' => array('input', 'text') - ); - - if (Config::get('ratings')) { - $this->types[] = array( - 'name' => 'rating', - 'label' => T_('Rating'), - 'type' => 'numeric', - 'widget' => array( - 'select', - array( - '1 Star', - '2 Stars', - '3 Stars', - '4 Stars', - '5 Stars' - ) - ) - ); - } - - $catalogs = array(); - foreach (Catalog::get_catalogs() as $catid) { - $catalog = new Catalog($catid); - $catalog->format(); - $catalogs[$catid] = $catalog->f_name; - } - $this->types[] = array( - 'name' => 'catalog', - 'label' => T_('Catalog'), - 'type' => 'boolean_numeric', - 'widget' => array('select', $catalogs) - ); - - - $this->types[] = array( - 'name' => 'tag', - 'label' => T_('Tag'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - break; - case 'video': - $this->types[] = array( - 'name' => 'filename', - 'label' => T_('Filename'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - break; - case 'artist': - $this->types[] = array( - 'name' => 'name', - 'label' => T_('Name'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - $this->types[] = array( - 'name' => 'tag', - 'label' => T_('Tag'), - 'type' => 'text', - 'widget' => array('input', 'text') - ); - break; - } // end switch on searchtype - - } // end constructor - - /** - * clean_request - * Sanitizes raw search data - */ - public static function clean_request($data) { - foreach ($data as $key => $value) { - $prefix = substr($key, 0, 4); - $value = trim($value); - - if ($prefix == 'rule' && strlen($value)) { - $request[$key] = Dba::escape($value); - } - } // end foreach $data - - // Figure out if they want an AND based search or an OR based - // search - switch($data['operator']) { - case 'or': - $request['operator'] = 'OR'; - break; - default: - $request['operator'] = 'AND'; - break; - } // end switcn on operator - - // Verify the type - switch($data['type']) { - case 'album': - case 'artist': - case 'video': - case 'song': - $request['type'] = $data['type']; - break; - default: - $request['type'] = 'song'; - break; - } - - return $request; - } // end clean_request - - /** - * get_name_byid - * Returns the name of the saved search corresponding to the given ID - */ - public static function get_name_byid($id) { - $sql = "SELECT `name` FROM `search` WHERE `id`='$id'"; - $db_results = Dba::read($sql); - $r = Dba::fetch_assoc($db_results); - return $r['name']; - } // end get_name_byid - - /** - * get_searches - * Return the IDs of all saved searches accessible by the current user. - */ - public static function get_searches() { - $sql = "SELECT `id` from `search` WHERE `type`='public' OR " . - "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`"; - $db_results = Dba::read($sql); - - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } - - return $results; - } // end get_searches - - /** - * run - * This function actually runs the search, and returns an array of the - * results. - */ - public static function run($data) { - $limit = intval($data['limit']); - /* Create an array of the object we need to search on */ - $data = Search::clean_request($data); - - $search = new Search($data['type']); - $search->parse_rules($data); - - /* Generate BASE SQL */ - - if ($limit > 0) { - $limit_sql = " LIMIT " . $limit; - } - - $search_info = $search->to_sql(); - $sql = $search_info['base'] . ' ' . $search_info['table_sql'] . - ' WHERE ' . $search_info['where_sql'] . " $limit_sql"; - - $db_results = Dba::read($sql); - - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } - - return $results; - } // run - - /** - * delete - * Does what it says on the tin. - */ - public function delete() { - $id = Dba::escape($this->id); - $sql = "DELETE FROM `search` WHERE `id`='$id'"; - $db_results = Dba::write($sql); - - return true; - } // end delete - - /** - * format - * Gussy up the data - */ - public function format() { - parent::format(); - $this->f_link = '' . $this->f_name . ''; - } // end format - - /** - * get_items - * return an array of the items output by our search (part of the - * playlist interface). - */ - public function get_items() { - $results = array(); - - $sql = $this->to_sql(); - $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . - $sql['where_sql']; - - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = array( - 'object_id' => $row['id'], - 'object_type' => $this->searchtype - ); - } - - return $results; - } // end get_items - - /** - * get_random_items - * return a randomly sorted array (with an optional limit) of the items - * output by our search (part of the playlist interface) - */ - - public function get_random_items($limit = null) { - $results = array(); - - $sql = $this->to_sql(); - $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . - $sql['where_sql']; - - $sql .= ' ORDER BY RAND()'; - $sql .= $limit ? ' LIMIT ' . intval($limit) : ''; - - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = array( - 'object_id' => $row['id'], - 'object_type' => $this->searchtype - ); - } - - return $results; - } - - /** - * name_to_basetype - * Iterates over our array of types to find out the basetype for - * the passed string. - */ - public function name_to_basetype($name) { - foreach ($this->types as $type) { - if ($type['name'] == $name) { - return $type['type']; - } - } - return false; - } // end name_to_basetype - - /** - * parse_rules - * Takes an array of sanitized search data from the form and generates - * our real array from it. - */ - public function parse_rules($data) { - $this->rules = array(); - foreach ($data as $rule => $value) { - if (preg_match('/^rule_(\d+)$/', $rule, $ruleID)) { - $ruleID = $ruleID[1]; - foreach (explode('|', $data['rule_' . $ruleID . '_input']) as $input) { - $this->rules[] = array( - $value, - $this->basetypes[$this->name_to_basetype($value)][$data['rule_' . $ruleID . '_operator']]['name'], - $input - ); - } - } - } - $this->logic_operator = $data['operator']; - } // end parse_rules - - /** - * save - * Save this search to the database for use as a smart playlist - */ - public function save() { - // Make sure we have a unique name - if (! $this->name) { - $this->name = $GLOBALS['user']->username . ' - ' . date("Y-m-d H:i:s",time()); - } - $sql = "SELECT `id` FROM `search` WHERE `name`='$this->name'"; - $db_results = Dba::read($sql); - if (Dba::num_rows($db_results)) { - $this->name .= uniqid('', true); - } - - // clean up variables for insert - $name = Dba::escape($this->name); - $user = Dba::escape($GLOBALS['user']->id); - $type = Dba::escape($this->type); - $rules = serialize($this->rules); - $logic_operator = $this->logic_operator; - - $sql = "INSERT INTO `search` (`name`, `type`, `user`, `rules`, `logic_operator`) VALUES ('$name', '$type', '$user', '$rules', '$logic_operator')"; - $db_results = Dba::write($sql); - $insert_id = Dba::insert_id(); - $this->id = $insert_id; - return $insert_id; - } // end save - - - /** - * to_js - * Outputs the javascript necessary to re-show the current set of - * rules. - */ - public function to_js() { - foreach ($this->rules as $rule) { - $js .= ''; - } - return $js; - } // end to_js - - /** - * to_sql - * Call the appropriate real function - */ - public function to_sql() { - return call_user_func( - array($this, $this->searchtype . "_to_sql")); - } // end to_sql - - /** - * update - * This function updates the saved version with the current settings - */ - public function update() { - if (!$this->id) { - return false; - } - - $name = Dba::escape($this->name); - $user = Dba::escape($GLOBALS['user']->id); - $type = Dba::escape($this->type); - $rules = serialize($this->rules); - $logic_operator = $this->logic_operator; - - $sql = "UPDATE `search` SET `name`='$name', `type`='$type', `rules`='$rules', `logic_operator`='$logic_operator' WHERE `id`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::write($sql); - return $db_results; - } // end update - - /** - * mangle_data - * Private convenience function. Mangles the input according to a set - * of predefined rules so that we don't have to include this logic in - * foo_to_sql. - */ - private function mangle_data($data, $type, $operator) { - if ($operator['preg_match']) { - $data = preg_replace( - $operator['preg_match'], - $operator['preg_replace'], - $data - ); - } - - if ($type == 'numeric') { - return intval($data); - } - - if ($type == 'boolean') { - return make_bool($input); - } - - return $data; - } // end mangle_data - - /** - * album_to_sql - * Handles the generation of the SQL for album searches. - */ - private function album_to_sql() { - $sql_logic_operator = $this->logic_operator; - - $where = array(); - $table = array(); - $join = array(); - $join['tag'] = array(); - - foreach ($this->rules as $rule) { - $type = $this->name_to_basetype($rule[0]); - foreach ($this->basetypes[$type] as $operator) { - if ($operator['name'] == $rule[1]) { - break; - } - } - $input = $this->mangle_data($rule[2], $type, $operator); - $sql_match_operator = $operator['sql']; - - switch ($rule[0]) { - case 'title': - $where[] = "`album`.`name` $sql_match_operator '$input'"; - break; - case 'year': - $where[] = "`album`.`year` $sql_match_operator '$input'"; - break; - case 'rating': - $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'"; - $join['rating'] = true; - break; - case 'catalog': - $where[] = "`song`.`catalog` $sql_match_operator '$input'"; - $join['song'] = true; - break; - case 'tag': - $key = md5($input . $sql_match_operator); - $where[] = "`realtag_$key`.`match` > 0"; - $join['tag'][$key] = "$sql_match_operator '$input'"; - break; - default: - // Nae laird! - break; - } // switch on ruletype - } // foreach rule - - $where_sql = implode(" $sql_logic_operator ", $where); - - foreach ($join['tag'] as $key => $value) { - $table['tag_' . $key] = - "LEFT JOIN (" . - "SELECT `object_id`, COUNT(`name`) AS `match` ". - "FROM `tag` LEFT JOIN `tag_map` " . - "ON `tag`.`id`=`tag_map`.`tag_id` " . - "WHERE `tag_map`.`object_type`='album' " . - "AND `tag`.`name` $value GROUP BY `object_id`" . - ") AS realtag_$key " . - "ON `album`.`id`=`realtag_$key`.`object_id`"; - } - if ($join['song']) { - $table['song'] = "LEFT JOIN `song` ON `song`.`album`=`album`.`id`"; - } - if ($join['rating']) { - $userid = $GLOBALS['user']->id; - $table['rating'] = "LEFT JOIN `rating` ON " . - "`rating`.`object_type`='album' " . - "AND `rating`.`user`='$userid' " . - "AND `rating`.`object_id`=`album`.`id`"; - } - - $table_sql = implode(' ', $table); - - return array( - 'base' => 'SELECT DISTINCT(`album`.`id`) FROM `album`', - 'join' => $join, - 'where' => $where, - 'where_sql' => $where_sql, - 'table' => $table, - 'table_sql' => $table_sql - ); - } // album_to_sql - - /** - * artist_to_sql - * Handles the generation of the SQL for artist searches. - */ - private function artist_to_sql() { - $sql_logic_operator = $this->logic_operator; - $where = array(); - $table = array(); - $join = array(); - $join['tag'] = array(); - - foreach ($this->rules as $rule) { - $type = $this->name_to_basetype($rule[0]); - foreach ($this->basetypes[$type] as $operator) { - if ($operator['name'] == $rule[1]) { - break; - } - } - $input = $this->mangle_data($rule[2], $type, $operator); - $sql_match_operator = $operator['sql']; - - switch ($rule[0]) { - case 'name': - $where[] = "`artist`.`name` $sql_match_operator '$input'"; - break; - case 'tag': - $key = md5($input . $sql_match_operator); - $where[] = "`realtag_$key`.`match` > 0"; - $join['tag'][$key] = "$sql_match_operator '$input'"; - break; - default: - // Nihil - break; - } // switch on ruletype - } // foreach rule - - $where_sql = implode(" $sql_logic_operator ", $where); - - foreach ($join['tag'] as $key => $value) { - $table['tag_' . $key] = - "LEFT JOIN (" . - "SELECT `object_id`, COUNT(`name`) AS `match` ". - "FROM `tag` LEFT JOIN `tag_map` " . - "ON `tag`.`id`=`tag_map`.`tag_id` " . - "WHERE `tag_map`.`object_type`='artist' " . - "AND `tag`.`name` $value GROUP BY `object_id`". - ") AS realtag_$key " . - "ON `artist`.`id`=`realtag_$key`.`object_id`"; - } - - $table_sql = implode(' ', $table); - - return array( - 'base' => 'SELECT DISTINCT(`artist`.`id`) FROM `artist`', - 'join' => $join, - 'where' => $where, - 'where_sql' => $where_sql, - 'table' => $table, - 'table_sql' => $table_sql - ); - } // artist_to_sql - - /** - * song_to_sql - * Handles the generation of the SQL for song searches. - */ - private function song_to_sql() { - $sql_logic_operator = $this->logic_operator; - - $where = array(); - $table = array(); - $join = array(); - $join['tag'] = array(); - - foreach ($this->rules as $rule) { - $type = $this->name_to_basetype($rule[0]); - foreach ($this->basetypes[$type] as $operator) { - if ($operator['name'] == $rule[1]) { - break; - } - } - $input = $this->mangle_data($rule[2], $type, $operator); - $sql_match_operator = $operator['sql']; - - switch ($rule[0]) { - case 'anywhere': - $where[] = "(`artist`.`name` $sql_match_operator '$input' OR `album`.`name` $sql_match_operator '$input' OR `song_data`.`comment` $sql_match_operator '$input' OR `song`.`file` $sql_match_operator '$input' OR `song`.`title` $sql_match_operator '$input')"; - $join['album'] = true; - $join['artist'] = true; - $join['song_data'] = true; - break; - case 'tag': - $key = md5($input . $sql_match_operator); - $where[] = "`realtag_$key`.`match` > 0"; - $join['tag'][$key] = "$sql_match_operator '$input'"; - break; - case 'title': - $where[] = "`song`.`title` $sql_match_operator '$input'"; - break; - case 'album': - $where[] = "`album`.`name` $sql_match_operator '$input'"; - $join['album'] = true; - break; - case 'artist': - $where[] = "`artist`.`name` $sql_match_operator '$input'"; - $join['artist'] = true; - break; - case 'time': - $input = $input * 60; - $where[] = "`song`.`time` $sql_match_operator '$input'"; - break; - case 'file': - $where[] = "`song`.`file` $sql_match_operator '$input'"; - break; - case 'year': - $where[] = "`song`.`year` $sql_match_operator '$input'"; - break; - case 'comment': - $where[] = "`song_data`.`comment` $sql_match_operator '$input'"; - $join['song_data'] = true; - break; - case 'played': - $where[] = " `song`.`played` = '$input'"; - break; - case 'bitrate': - $input = $input * 1000; - $where[] = "`song`.`bitrate` $sql_match_operator '$input'"; - break; - case 'rating': - $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'"; - $join['rating'] = true; - break; - case 'catalog': - $where[] = "`song`.`catalog` $sql_match_operator '$input'"; - break; - case 'playlist': - $join['playlist_data'] = true; - $where[] = "`playlist_data`.`playlist` $sql_match_operator '$input'"; - break; - case 'smartplaylist': - $subsearch = new Search('song', $input); - $subsql = $subsearch->to_sql(); - $where[] = "$sql_match_operator (" . $subsql['where_sql'] . ")"; - // HACK: array_merge would potentially - // lose tags, since it overwrites. - // Save our merged tag joins in a temp - // variable, even though that's ugly. - $tagjoin = array_merge($subsql['join']['tag'], $join['tag']); - $join = array_merge($subsql['join'], $join); - $join['tag'] = $tagjoin; - break; - case 'added': - $input = strtotime($input); - $where[] = "`song`.`addition_time` $sql_match_operator $input"; - break; - case 'updated': - $input = strtotime($input); - $where[] = "`song`.`update_time` $sql_match_operator $input"; - default: - // NOSSINK! - break; - } // end switch on type - } // end foreach over rules - - $where_sql = implode(" $sql_logic_operator ", $where); - - // now that we know which things we want to JOIN... - if ($join['artist']) { - $table['artist'] = "LEFT JOIN `artist` ON `song`.`artist`=`artist`.`id`"; - } - if ($join['album']) { - $table['album'] = "LEFT JOIN `album` ON `song`.`album`=`album`.`id`"; - } - if ($join['song_data']) { - $table['song_data'] = "LEFT JOIN `song_data` ON `song`.`id`=`song_data`.`song_id`"; - } - foreach ($join['tag'] as $key => $value) { - $table['tag_' . $key] = - "LEFT JOIN (" . - "SELECT `object_id`, COUNT(`name`) AS `match` ". - "FROM `tag` LEFT JOIN `tag_map` " . - "ON `tag`.`id`=`tag_map`.`tag_id` " . - "WHERE `tag_map`.`object_type`='song' " . - "AND `tag`.`name` $value GROUP BY `object_id`" . - ") AS realtag_$key " . - "ON `song`.`id`=`realtag_$key`.`object_id`"; - } - if ($join['rating']) { - $userid = $GLOBALS['user']->id; - $table['rating'] = "LEFT JOIN `rating` ON " . - "`rating`.`object_type`='song' AND " . - "`rating`.`user`='$userid' AND " . - "`rating`.`object_id`=`song`.`id`"; - } - if ($join['playlist_data']) { - $table['playlist_data'] = "LEFT JOIN `playlist_data` ON `song`.`id`=`playlist_data`.`object_id` AND `playlist_data`.`object_type`='song'"; - } - - $table_sql = implode(' ', $table); - - return array( - 'base' => 'SELECT DISTINCT(`song`.`id`) FROM `song`', - 'join' => $join, - 'where' => $where, - 'where_sql' => $where_sql, - 'table' => $table, - 'table_sql' => $table_sql - ); - } // end song_to_sql - - /** - * video_to_sql - * Handles the generation of the SQL for video searches. - */ - private function video_to_sql() { - $sql_logic_operator = $this->logic_operator; - - $where = array(); - - - foreach ($this->rules as $rule) { - $type = $this->name_to_basetype($rule[0]); - foreach ($this->basetypes[$type] as $operator) { - if ($operator['name'] == $rule[1]) { - break; - } - } - $input = $this->mangle_data($rule[2], $type, $operator); - $sql_match_operator = $operator['sql']; - - switch ($rule[0]) { - case 'filename': - $where[] = "`video`.`file` $sql_match_operator '$input'"; - break; - default: - // WE WILLNA BE FOOLED AGAIN! - } // switch on ruletype - } // foreach rule - - $where_sql = implode(" $sql_logic_operator ", $where); - - return array( - 'base' => 'SELECT DISTINCT(`video`.`id`) FROM `video`', - 'where' => $where, - 'where_sql' => $where_sql - ); - } // end video_to_sql + public $searchtype; + public $rules; + public $logic_operator = 'AND'; + public $type = 'public'; + + public $basetypes; + public $types; + + /** + * constructor + */ + public function __construct($searchtype = 'song', $id = '') { + $this->searchtype = $searchtype; + if ($id) { + $info = $this->get_info($id); + foreach ($info as $key=>$value) { + $this->$key = $value; + } + + $this->rules = unserialize($this->rules); + } + + // Define our basetypes + + $this->basetypes['numeric'][] = array( + 'name' => 'gte', + 'description' => T_('is greater than or equal to'), + 'sql' => '>=' + ); + + $this->basetypes['numeric'][] = array( + 'name' => 'lte', + 'description' => T_('is less than or equal to'), + 'sql' => '<=' + ); + + $this->basetypes['numeric'][] = array( + 'name' => 'equal', + 'description' => T_('is'), + 'sql' => '<=>' + ); + + $this->basetypes['numeric'][] = array( + 'name' => 'ne', + 'description' => T_('is not'), + 'sql' => '<>' + ); + + $this->basetypes['numeric'][] = array( + 'name' => 'gt', + 'description' => T_('is greater than'), + 'sql' => '>' + ); + + $this->basetypes['numeric'][] = array( + 'name' => 'lt', + 'description' => T_('is less than'), + 'sql' => '<' + ); + + + $this->basetypes['boolean'][] = array( + 'name' => 'true', + 'description' => T_('is true') + ); + + $this->basetypes['boolean'][] = array( + 'name' => 'false', + 'description' => T_('is false') + ); + + + $this->basetypes['text'][] = array( + 'name' => 'contain', + 'description' => T_('contains'), + 'sql' => 'LIKE', + 'preg_match' => array('/^/','/$/'), + 'preg_replace' => array('%', '%') + ); + + $this->basetypes['text'][] = array( + 'name' => 'notcontain', + 'description' => T_('does not contain'), + 'sql' => 'NOT LIKE', + 'preg_match' => array('/^/','/$/'), + 'preg_replace' => array('%', '%') + ); + + $this->basetypes['text'][] = array( + 'name' => 'start', + 'description' => T_('starts with'), + 'sql' => 'LIKE', + 'preg_match' => '/$/', + 'preg_replace' => '%' + ); + + $this->basetypes['text'][] = array( + 'name' => 'end', + 'description' => T_('ends with'), + 'sql' => 'LIKE', + 'preg_match' => '/^/', + 'preg_replace' => '%' + ); + + $this->basetypes['text'][] = array( + 'name' => 'equal', + 'description' => T_('is'), + 'sql' => '=' + ); + + $this->basetypes['text'][] = array( + 'name' => 'sounds', + 'description' => T_('sounds like'), + 'sql' => 'SOUNDS LIKE' + ); + + $this->basetypes['text'][] = array( + 'name' => 'notsounds', + 'description' => T_('does not sound like'), + 'sql' => 'NOT SOUNDS LIKE' + ); + + + $this->basetypes['boolean_numeric'][] = array( + 'name' => 'equal', + 'description' => T_('is'), + 'sql' => '<=>' + ); + + $this->basetypes['boolean_numeric'][] = array( + 'name' => 'ne', + 'description' => T_('is not'), + 'sql' => '<>' + ); + + + $this->basetypes['boolean_subsearch'][] = array( + 'name' => 'equal', + 'description' => T_('is'), + 'sql' => '' + ); + + $this->basetypes['boolean_subsearch'][] = array( + 'name' => 'ne', + 'description' => T_('is not'), + 'sql' => 'NOT' + ); + + + $this->basetypes['date'][] = array( + 'name' => 'lt', + 'description' => T_('before'), + 'sql' => '>' + ); + + $this->basetypes['date'][] = array( + 'name' => 'gt', + 'description' => T_('after'), + 'sql' => '>' + ); + + switch ($searchtype) { + case 'song': + $this->types[] = array( + 'name' => 'anywhere', + 'label' => T_('Any searchable text'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'title', + 'label' => T_('Title'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'album', + 'label' => T_('Album'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'artist', + 'label' => T_('Artist'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'comment', + 'label' => T_('Comment'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + + $this->types[] = array( + 'name' => 'tag', + 'label' => T_('Tag'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'file', + 'label' => T_('Filename'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'year', + 'label' => T_('Year'), + 'type' => 'numeric', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'time', + 'label' => T_('Length (in minutes)'), + 'type' => 'numeric', + 'widget' => array('input', 'text') + ); + + if (Config::get('ratings')) { + $this->types[] = array( + 'name' => 'rating', + 'label' => T_('Rating'), + 'type' => 'numeric', + 'widget' => array( + 'select', + array( + '1 Star', + '2 Stars', + '3 Stars', + '4 Stars', + '5 Stars' + ) + ) + ); + } + + $this->types[] = array( + 'name' => 'bitrate', + 'label' => T_('Bitrate'), + 'type' => 'numeric', + 'widget' => array( + 'select', + array( + '32', + '40', + '48', + '56', + '64', + '80', + '96', + '112', + '128', + '160', + '192', + '224', + '256', + '320' + ) + ) + ); + + $this->types[] = array( + 'name' => 'played', + 'label' => T_('Played'), + 'type' => 'boolean', + 'widget' => array('input', 'hidden') + ); + + $this->types[] = array( + 'name' => 'added', + 'label' => T_('Added'), + 'type' => 'date', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'updated', + 'label' => T_('Updated'), + 'type' => 'date', + 'widget' => array('input', 'text') + ); + + $catalogs = array(); + foreach (Catalog::get_catalogs() as $catid) { + $catalog = new Catalog($catid); + $catalog->format(); + $catalogs[$catid] = $catalog->f_name; + } + $this->types[] = array( + 'name' => 'catalog', + 'label' => T_('Catalog'), + 'type' => 'boolean_numeric', + 'widget' => array('select', $catalogs) + ); + + $playlists = array(); + foreach (Playlist::get_playlists() as $playlistid) { + $playlist = new Playlist($playlistid); + $playlist->format(); + $playlists[$playlistid] = $playlist->f_name; + } + $this->types[] = array( + 'name' => 'playlist', + 'label' => T_('Playlist'), + 'type' => 'boolean_numeric', + 'widget' => array('select', $playlists) + ); + + $playlists = array(); + foreach (Search::get_searches() as $playlistid) { + // Slightly different from the above so we don't + // instigate a vicious loop. + $playlists[$playlistid] = Search::get_name_byid($playlistid); + } + $this->types[] = array( + 'name' => 'smartplaylist', + 'label' => T_('Smart Playlist'), + 'type' => 'boolean_subsearch', + 'widget' => array('select', $playlists) + ); + break; + case 'album': + $this->types[] = array( + 'name' => 'title', + 'label' => T_('Title'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + + $this->types[] = array( + 'name' => 'year', + 'label' => T_('Year'), + 'type' => 'numeric', + 'widget' => array('input', 'text') + ); + + if (Config::get('ratings')) { + $this->types[] = array( + 'name' => 'rating', + 'label' => T_('Rating'), + 'type' => 'numeric', + 'widget' => array( + 'select', + array( + '1 Star', + '2 Stars', + '3 Stars', + '4 Stars', + '5 Stars' + ) + ) + ); + } + + $catalogs = array(); + foreach (Catalog::get_catalogs() as $catid) { + $catalog = new Catalog($catid); + $catalog->format(); + $catalogs[$catid] = $catalog->f_name; + } + $this->types[] = array( + 'name' => 'catalog', + 'label' => T_('Catalog'), + 'type' => 'boolean_numeric', + 'widget' => array('select', $catalogs) + ); + + + $this->types[] = array( + 'name' => 'tag', + 'label' => T_('Tag'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + break; + case 'video': + $this->types[] = array( + 'name' => 'filename', + 'label' => T_('Filename'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + break; + case 'artist': + $this->types[] = array( + 'name' => 'name', + 'label' => T_('Name'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + $this->types[] = array( + 'name' => 'tag', + 'label' => T_('Tag'), + 'type' => 'text', + 'widget' => array('input', 'text') + ); + break; + } // end switch on searchtype + + } // end constructor + + /** + * clean_request + * Sanitizes raw search data + */ + public static function clean_request($data) { + foreach ($data as $key => $value) { + $prefix = substr($key, 0, 4); + $value = trim($value); + + if ($prefix == 'rule' && strlen($value)) { + $request[$key] = Dba::escape($value); + } + } // end foreach $data + + // Figure out if they want an AND based search or an OR based + // search + switch($data['operator']) { + case 'or': + $request['operator'] = 'OR'; + break; + default: + $request['operator'] = 'AND'; + break; + } // end switcn on operator + + // Verify the type + switch($data['type']) { + case 'album': + case 'artist': + case 'video': + case 'song': + $request['type'] = $data['type']; + break; + default: + $request['type'] = 'song'; + break; + } + + return $request; + } // end clean_request + + /** + * get_name_byid + * Returns the name of the saved search corresponding to the given ID + */ + public static function get_name_byid($id) { + $sql = "SELECT `name` FROM `search` WHERE `id`='$id'"; + $db_results = Dba::read($sql); + $r = Dba::fetch_assoc($db_results); + return $r['name']; + } // end get_name_byid + + /** + * get_searches + * Return the IDs of all saved searches accessible by the current user. + */ + public static function get_searches() { + $sql = "SELECT `id` from `search` WHERE `type`='public' OR " . + "`user`='" . $GLOBALS['user']->id . "' ORDER BY `name`"; + $db_results = Dba::read($sql); + + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } + + return $results; + } // end get_searches + + /** + * run + * This function actually runs the search, and returns an array of the + * results. + */ + public static function run($data) { + $limit = intval($data['limit']); + /* Create an array of the object we need to search on */ + $data = Search::clean_request($data); + + $search = new Search($data['type']); + $search->parse_rules($data); + + /* Generate BASE SQL */ + + if ($limit > 0) { + $limit_sql = " LIMIT " . $limit; + } + + $search_info = $search->to_sql(); + $sql = $search_info['base'] . ' ' . $search_info['table_sql'] . + ' WHERE ' . $search_info['where_sql'] . " $limit_sql"; + + $db_results = Dba::read($sql); + + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } + + return $results; + } // run + + /** + * delete + * Does what it says on the tin. + */ + public function delete() { + $id = Dba::escape($this->id); + $sql = "DELETE FROM `search` WHERE `id`='$id'"; + $db_results = Dba::write($sql); + + return true; + } // end delete + + /** + * format + * Gussy up the data + */ + public function format() { + parent::format(); + $this->f_link = '' . $this->f_name . ''; + } // end format + + /** + * get_items + * return an array of the items output by our search (part of the + * playlist interface). + */ + public function get_items() { + $results = array(); + + $sql = $this->to_sql(); + $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . + $sql['where_sql']; + + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = array( + 'object_id' => $row['id'], + 'object_type' => $this->searchtype + ); + } + + return $results; + } // end get_items + + /** + * get_random_items + * return a randomly sorted array (with an optional limit) of the items + * output by our search (part of the playlist interface) + */ + + public function get_random_items($limit = null) { + $results = array(); + + $sql = $this->to_sql(); + $sql = $sql['base'] . ' ' . $sql['table_sql'] . ' WHERE ' . + $sql['where_sql']; + + $sql .= ' ORDER BY RAND()'; + $sql .= $limit ? ' LIMIT ' . intval($limit) : ''; + + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = array( + 'object_id' => $row['id'], + 'object_type' => $this->searchtype + ); + } + + return $results; + } + + /** + * name_to_basetype + * Iterates over our array of types to find out the basetype for + * the passed string. + */ + public function name_to_basetype($name) { + foreach ($this->types as $type) { + if ($type['name'] == $name) { + return $type['type']; + } + } + return false; + } // end name_to_basetype + + /** + * parse_rules + * Takes an array of sanitized search data from the form and generates + * our real array from it. + */ + public function parse_rules($data) { + $this->rules = array(); + foreach ($data as $rule => $value) { + if (preg_match('/^rule_(\d+)$/', $rule, $ruleID)) { + $ruleID = $ruleID[1]; + foreach (explode('|', $data['rule_' . $ruleID . '_input']) as $input) { + $this->rules[] = array( + $value, + $this->basetypes[$this->name_to_basetype($value)][$data['rule_' . $ruleID . '_operator']]['name'], + $input + ); + } + } + } + $this->logic_operator = $data['operator']; + } // end parse_rules + + /** + * save + * Save this search to the database for use as a smart playlist + */ + public function save() { + // Make sure we have a unique name + if (! $this->name) { + $this->name = $GLOBALS['user']->username . ' - ' . date("Y-m-d H:i:s",time()); + } + $sql = "SELECT `id` FROM `search` WHERE `name`='$this->name'"; + $db_results = Dba::read($sql); + if (Dba::num_rows($db_results)) { + $this->name .= uniqid('', true); + } + + // clean up variables for insert + $name = Dba::escape($this->name); + $user = Dba::escape($GLOBALS['user']->id); + $type = Dba::escape($this->type); + $rules = serialize($this->rules); + $logic_operator = $this->logic_operator; + + $sql = "INSERT INTO `search` (`name`, `type`, `user`, `rules`, `logic_operator`) VALUES ('$name', '$type', '$user', '$rules', '$logic_operator')"; + $db_results = Dba::write($sql); + $insert_id = Dba::insert_id(); + $this->id = $insert_id; + return $insert_id; + } // end save + + + /** + * to_js + * Outputs the javascript necessary to re-show the current set of + * rules. + */ + public function to_js() { + foreach ($this->rules as $rule) { + $js .= ''; + } + return $js; + } // end to_js + + /** + * to_sql + * Call the appropriate real function + */ + public function to_sql() { + return call_user_func( + array($this, $this->searchtype . "_to_sql")); + } // end to_sql + + /** + * update + * This function updates the saved version with the current settings + */ + public function update() { + if (!$this->id) { + return false; + } + + $name = Dba::escape($this->name); + $user = Dba::escape($GLOBALS['user']->id); + $type = Dba::escape($this->type); + $rules = serialize($this->rules); + $logic_operator = $this->logic_operator; + + $sql = "UPDATE `search` SET `name`='$name', `type`='$type', `rules`='$rules', `logic_operator`='$logic_operator' WHERE `id`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::write($sql); + return $db_results; + } // end update + + /** + * mangle_data + * Private convenience function. Mangles the input according to a set + * of predefined rules so that we don't have to include this logic in + * foo_to_sql. + */ + private function mangle_data($data, $type, $operator) { + if ($operator['preg_match']) { + $data = preg_replace( + $operator['preg_match'], + $operator['preg_replace'], + $data + ); + } + + if ($type == 'numeric') { + return intval($data); + } + + if ($type == 'boolean') { + return make_bool($input); + } + + return $data; + } // end mangle_data + + /** + * album_to_sql + * Handles the generation of the SQL for album searches. + */ + private function album_to_sql() { + $sql_logic_operator = $this->logic_operator; + + $where = array(); + $table = array(); + $join = array(); + $join['tag'] = array(); + + foreach ($this->rules as $rule) { + $type = $this->name_to_basetype($rule[0]); + foreach ($this->basetypes[$type] as $operator) { + if ($operator['name'] == $rule[1]) { + break; + } + } + $input = $this->mangle_data($rule[2], $type, $operator); + $sql_match_operator = $operator['sql']; + + switch ($rule[0]) { + case 'title': + $where[] = "`album`.`name` $sql_match_operator '$input'"; + break; + case 'year': + $where[] = "`album`.`year` $sql_match_operator '$input'"; + break; + case 'rating': + $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'"; + $join['rating'] = true; + break; + case 'catalog': + $where[] = "`song`.`catalog` $sql_match_operator '$input'"; + $join['song'] = true; + break; + case 'tag': + $key = md5($input . $sql_match_operator); + $where[] = "`realtag_$key`.`match` > 0"; + $join['tag'][$key] = "$sql_match_operator '$input'"; + break; + default: + // Nae laird! + break; + } // switch on ruletype + } // foreach rule + + $where_sql = implode(" $sql_logic_operator ", $where); + + foreach ($join['tag'] as $key => $value) { + $table['tag_' . $key] = + "LEFT JOIN (" . + "SELECT `object_id`, COUNT(`name`) AS `match` ". + "FROM `tag` LEFT JOIN `tag_map` " . + "ON `tag`.`id`=`tag_map`.`tag_id` " . + "WHERE `tag_map`.`object_type`='album' " . + "AND `tag`.`name` $value GROUP BY `object_id`" . + ") AS realtag_$key " . + "ON `album`.`id`=`realtag_$key`.`object_id`"; + } + if ($join['song']) { + $table['song'] = "LEFT JOIN `song` ON `song`.`album`=`album`.`id`"; + } + if ($join['rating']) { + $userid = $GLOBALS['user']->id; + $table['rating'] = "LEFT JOIN `rating` ON " . + "`rating`.`object_type`='album' " . + "AND `rating`.`user`='$userid' " . + "AND `rating`.`object_id`=`album`.`id`"; + } + + $table_sql = implode(' ', $table); + + return array( + 'base' => 'SELECT DISTINCT(`album`.`id`) FROM `album`', + 'join' => $join, + 'where' => $where, + 'where_sql' => $where_sql, + 'table' => $table, + 'table_sql' => $table_sql + ); + } // album_to_sql + + /** + * artist_to_sql + * Handles the generation of the SQL for artist searches. + */ + private function artist_to_sql() { + $sql_logic_operator = $this->logic_operator; + $where = array(); + $table = array(); + $join = array(); + $join['tag'] = array(); + + foreach ($this->rules as $rule) { + $type = $this->name_to_basetype($rule[0]); + foreach ($this->basetypes[$type] as $operator) { + if ($operator['name'] == $rule[1]) { + break; + } + } + $input = $this->mangle_data($rule[2], $type, $operator); + $sql_match_operator = $operator['sql']; + + switch ($rule[0]) { + case 'name': + $where[] = "`artist`.`name` $sql_match_operator '$input'"; + break; + case 'tag': + $key = md5($input . $sql_match_operator); + $where[] = "`realtag_$key`.`match` > 0"; + $join['tag'][$key] = "$sql_match_operator '$input'"; + break; + default: + // Nihil + break; + } // switch on ruletype + } // foreach rule + + $where_sql = implode(" $sql_logic_operator ", $where); + + foreach ($join['tag'] as $key => $value) { + $table['tag_' . $key] = + "LEFT JOIN (" . + "SELECT `object_id`, COUNT(`name`) AS `match` ". + "FROM `tag` LEFT JOIN `tag_map` " . + "ON `tag`.`id`=`tag_map`.`tag_id` " . + "WHERE `tag_map`.`object_type`='artist' " . + "AND `tag`.`name` $value GROUP BY `object_id`". + ") AS realtag_$key " . + "ON `artist`.`id`=`realtag_$key`.`object_id`"; + } + + $table_sql = implode(' ', $table); + + return array( + 'base' => 'SELECT DISTINCT(`artist`.`id`) FROM `artist`', + 'join' => $join, + 'where' => $where, + 'where_sql' => $where_sql, + 'table' => $table, + 'table_sql' => $table_sql + ); + } // artist_to_sql + + /** + * song_to_sql + * Handles the generation of the SQL for song searches. + */ + private function song_to_sql() { + $sql_logic_operator = $this->logic_operator; + + $where = array(); + $table = array(); + $join = array(); + $join['tag'] = array(); + + foreach ($this->rules as $rule) { + $type = $this->name_to_basetype($rule[0]); + foreach ($this->basetypes[$type] as $operator) { + if ($operator['name'] == $rule[1]) { + break; + } + } + $input = $this->mangle_data($rule[2], $type, $operator); + $sql_match_operator = $operator['sql']; + + switch ($rule[0]) { + case 'anywhere': + $where[] = "(`artist`.`name` $sql_match_operator '$input' OR `album`.`name` $sql_match_operator '$input' OR `song_data`.`comment` $sql_match_operator '$input' OR `song`.`file` $sql_match_operator '$input' OR `song`.`title` $sql_match_operator '$input')"; + $join['album'] = true; + $join['artist'] = true; + $join['song_data'] = true; + break; + case 'tag': + $key = md5($input . $sql_match_operator); + $where[] = "`realtag_$key`.`match` > 0"; + $join['tag'][$key] = "$sql_match_operator '$input'"; + break; + case 'title': + $where[] = "`song`.`title` $sql_match_operator '$input'"; + break; + case 'album': + $where[] = "`album`.`name` $sql_match_operator '$input'"; + $join['album'] = true; + break; + case 'artist': + $where[] = "`artist`.`name` $sql_match_operator '$input'"; + $join['artist'] = true; + break; + case 'time': + $input = $input * 60; + $where[] = "`song`.`time` $sql_match_operator '$input'"; + break; + case 'file': + $where[] = "`song`.`file` $sql_match_operator '$input'"; + break; + case 'year': + $where[] = "`song`.`year` $sql_match_operator '$input'"; + break; + case 'comment': + $where[] = "`song_data`.`comment` $sql_match_operator '$input'"; + $join['song_data'] = true; + break; + case 'played': + $where[] = " `song`.`played` = '$input'"; + break; + case 'bitrate': + $input = $input * 1000; + $where[] = "`song`.`bitrate` $sql_match_operator '$input'"; + break; + case 'rating': + $where[] = "COALESCE(`rating`.`rating`,0) $sql_match_operator '$input'"; + $join['rating'] = true; + break; + case 'catalog': + $where[] = "`song`.`catalog` $sql_match_operator '$input'"; + break; + case 'playlist': + $join['playlist_data'] = true; + $where[] = "`playlist_data`.`playlist` $sql_match_operator '$input'"; + break; + case 'smartplaylist': + $subsearch = new Search('song', $input); + $subsql = $subsearch->to_sql(); + $where[] = "$sql_match_operator (" . $subsql['where_sql'] . ")"; + // HACK: array_merge would potentially + // lose tags, since it overwrites. + // Save our merged tag joins in a temp + // variable, even though that's ugly. + $tagjoin = array_merge($subsql['join']['tag'], $join['tag']); + $join = array_merge($subsql['join'], $join); + $join['tag'] = $tagjoin; + break; + case 'added': + $input = strtotime($input); + $where[] = "`song`.`addition_time` $sql_match_operator $input"; + break; + case 'updated': + $input = strtotime($input); + $where[] = "`song`.`update_time` $sql_match_operator $input"; + default: + // NOSSINK! + break; + } // end switch on type + } // end foreach over rules + + $where_sql = implode(" $sql_logic_operator ", $where); + + // now that we know which things we want to JOIN... + if ($join['artist']) { + $table['artist'] = "LEFT JOIN `artist` ON `song`.`artist`=`artist`.`id`"; + } + if ($join['album']) { + $table['album'] = "LEFT JOIN `album` ON `song`.`album`=`album`.`id`"; + } + if ($join['song_data']) { + $table['song_data'] = "LEFT JOIN `song_data` ON `song`.`id`=`song_data`.`song_id`"; + } + foreach ($join['tag'] as $key => $value) { + $table['tag_' . $key] = + "LEFT JOIN (" . + "SELECT `object_id`, COUNT(`name`) AS `match` ". + "FROM `tag` LEFT JOIN `tag_map` " . + "ON `tag`.`id`=`tag_map`.`tag_id` " . + "WHERE `tag_map`.`object_type`='song' " . + "AND `tag`.`name` $value GROUP BY `object_id`" . + ") AS realtag_$key " . + "ON `song`.`id`=`realtag_$key`.`object_id`"; + } + if ($join['rating']) { + $userid = $GLOBALS['user']->id; + $table['rating'] = "LEFT JOIN `rating` ON " . + "`rating`.`object_type`='song' AND " . + "`rating`.`user`='$userid' AND " . + "`rating`.`object_id`=`song`.`id`"; + } + if ($join['playlist_data']) { + $table['playlist_data'] = "LEFT JOIN `playlist_data` ON `song`.`id`=`playlist_data`.`object_id` AND `playlist_data`.`object_type`='song'"; + } + + $table_sql = implode(' ', $table); + + return array( + 'base' => 'SELECT DISTINCT(`song`.`id`) FROM `song`', + 'join' => $join, + 'where' => $where, + 'where_sql' => $where_sql, + 'table' => $table, + 'table_sql' => $table_sql + ); + } // end song_to_sql + + /** + * video_to_sql + * Handles the generation of the SQL for video searches. + */ + private function video_to_sql() { + $sql_logic_operator = $this->logic_operator; + + $where = array(); + + + foreach ($this->rules as $rule) { + $type = $this->name_to_basetype($rule[0]); + foreach ($this->basetypes[$type] as $operator) { + if ($operator['name'] == $rule[1]) { + break; + } + } + $input = $this->mangle_data($rule[2], $type, $operator); + $sql_match_operator = $operator['sql']; + + switch ($rule[0]) { + case 'filename': + $where[] = "`video`.`file` $sql_match_operator '$input'"; + break; + default: + // WE WILLNA BE FOOLED AGAIN! + } // switch on ruletype + } // foreach rule + + $where_sql = implode(" $sql_logic_operator ", $where); + + return array( + 'base' => 'SELECT DISTINCT(`video`.`id`) FROM `video`', + 'where' => $where, + 'where_sql' => $where_sql + ); + } // end video_to_sql } // end of Search class ?> diff --git a/lib/class/shoutbox.class.php b/lib/class/shoutbox.class.php index 42adec0846..0bd1207083 100644 --- a/lib/class/shoutbox.class.php +++ b/lib/class/shoutbox.class.php @@ -1,5 +1,5 @@ _get_info($shout_id); + // Load the data from the database + $this->_get_info($shout_id); - return true; + return true; - } // Constructor + } // Constructor - /** - * _get_info - * does the db call, reads from the user_shout table - */ - private function _get_info($shout_id) { + /** + * _get_info + * does the db call, reads from the user_shout table + */ + private function _get_info($shout_id) { - $sticky_id = Dba::escape($shout_id); + $sticky_id = Dba::escape($shout_id); - $sql = "SELECT * FROM `user_shout` WHERE `id`='$shout_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `user_shout` WHERE `id`='$shout_id'"; + $db_results = Dba::read($sql); - $data = Dba::fetch_assoc($db_results); + $data = Dba::fetch_assoc($db_results); - foreach ($data as $key=>$value) { - $this->$key = $value; - } + foreach ($data as $key=>$value) { + $this->$key = $value; + } - return true; + return true; - } // _get_info + } // _get_info - /** - * gc - * - * Cleans out orphaned shoutbox items - */ - public static function gc() { - foreach(array('song', 'album', 'artist') as $object_type) { - Dba::write("DELETE FROM `user_shout` USING `user_shout` LEFT JOIN `$object_type` ON `$object_type`.`id` = `user_shout`.`object_id` WHERE `$object_type`.`id` IS NULL AND `user_shout`.`object_type` = '$object_type'"); - } - } + /** + * gc + * + * Cleans out orphaned shoutbox items + */ + public static function gc() { + foreach(array('song', 'album', 'artist') as $object_type) { + Dba::write("DELETE FROM `user_shout` USING `user_shout` LEFT JOIN `$object_type` ON `$object_type`.`id` = `user_shout`.`object_id` WHERE `$object_type`.`id` IS NULL AND `user_shout`.`object_type` = '$object_type'"); + } + } - /** - * get_top - * This returns the top user_shouts, shoutbox objects are always shown regardless and count against the total - * number of objects shown - */ - public static function get_top($limit) { + /** + * get_top + * This returns the top user_shouts, shoutbox objects are always shown regardless and count against the total + * number of objects shown + */ + public static function get_top($limit) { - $shouts = self::get_sticky(); + $shouts = self::get_sticky(); - // If we've already got too many stop here - if (count($shouts) > $limit) { - $shouts = array_slice($shouts,0,$limit); - return $shouts; - } + // If we've already got too many stop here + if (count($shouts) > $limit) { + $shouts = array_slice($shouts,0,$limit); + return $shouts; + } - // Only get as many as we need - $limit = intval($limit) - count($shouts); - $sql = "SELECT * FROM `user_shout` WHERE `sticky`='0' ORDER BY `date` DESC LIMIT $limit"; - $db_results = Dba::read($sql); + // Only get as many as we need + $limit = intval($limit) - count($shouts); + $sql = "SELECT * FROM `user_shout` WHERE `sticky`='0' ORDER BY `date` DESC LIMIT $limit"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $shouts[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $shouts[] = $row['id']; + } - return $shouts; + return $shouts; - } // get_top + } // get_top - /** - * get_sticky - * This returns all current sticky shoutbox items - */ - public static function get_sticky() { + /** + * get_sticky + * This returns all current sticky shoutbox items + */ + public static function get_sticky() { - $sql = "SELECT * FROM `user_shout` WHERE `sticky`='1' ORDER BY `date` DESC"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `user_shout` WHERE `sticky`='1' ORDER BY `date` DESC"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['id']; + } - return $results; + return $results; - } // get_sticky + } // get_sticky - /** - * get_object - * This takes a type and an ID and returns a created object - */ - public static function get_object($type,$object_id) { + /** + * get_object + * This takes a type and an ID and returns a created object + */ + public static function get_object($type,$object_id) { - $allowed_objects = array('song','genre','album','artist','radio'); + $allowed_objects = array('song','genre','album','artist','radio'); - if (!in_array($type,$allowed_objects)) { - return false; - } + if (!in_array($type,$allowed_objects)) { + return false; + } - $object = new $type($object_id); + $object = new $type($object_id); - return $object; + return $object; - } // get_object + } // get_object - /** - * get_image - * This returns an image tag if the type of object we're currently rolling with - * has an image associated with it - */ - public function get_image() { + /** + * get_image + * This returns an image tag if the type of object we're currently rolling with + * has an image associated with it + */ + public function get_image() { - switch ($this->object_type) { - case 'album': - $image_string = ""; - break; - case 'artist': + switch ($this->object_type) { + case 'album': + $image_string = ""; + break; + case 'artist': - break; - case 'song': - $song = new Song($this->object_id); - $image_string = ""; - break; - default: - // Rien a faire - break; - } // end switch + break; + case 'song': + $song = new Song($this->object_id); + $image_string = ""; + break; + default: + // Rien a faire + break; + } // end switch - return $image_string; + return $image_string; - } // get_image + } // get_image - /** - * create - * This takes a key'd array of data as input and inserts a new shoutbox entry, it returns the auto_inc id - */ - public static function create($data) { + /** + * create + * This takes a key'd array of data as input and inserts a new shoutbox entry, it returns the auto_inc id + */ + public static function create($data) { - $user = Dba::escape($GLOBALS['user']->id); - $text = Dba::escape(strip_tags($data['comment'])); - $date = time(); - $sticky = isset($data['sticky']) ? 1 : 0; - $object_id = Dba::escape($data['object_id']); - $object_type = Dba::escape($data['object_type']); + $user = Dba::escape($GLOBALS['user']->id); + $text = Dba::escape(strip_tags($data['comment'])); + $date = time(); + $sticky = isset($data['sticky']) ? 1 : 0; + $object_id = Dba::escape($data['object_id']); + $object_type = Dba::escape($data['object_type']); - $sql = "INSERT INTO `user_shout` (`user`,`date`,`text`,`sticky`,`object_id`,`object_type`) " . - "VALUES ('$user','$date','$text','$sticky','$object_id','$object_type')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `user_shout` (`user`,`date`,`text`,`sticky`,`object_id`,`object_type`) " . + "VALUES ('$user','$date','$text','$sticky','$object_id','$object_type')"; + $db_results = Dba::write($sql); - $insert_id = Dba::insert_id(); + $insert_id = Dba::insert_id(); - return $insert_id; + return $insert_id; - } // create + } // create - /** - * update - * This takes a key'd array of data as input and updates a shoutbox entry - */ - public static function update($data) { + /** + * update + * This takes a key'd array of data as input and updates a shoutbox entry + */ + public static function update($data) { - $id = Dba::escape($data['shout_id']); - $text = Dba::escape(strip_tags($data['comment'])); - $sticky = make_bool($data['sticky']); + $id = Dba::escape($data['shout_id']); + $text = Dba::escape(strip_tags($data['comment'])); + $sticky = make_bool($data['sticky']); - $sql = "UPDATE `user_shout` SET `text`='$text', `sticky`='$sticky' WHERE `id`='$id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `user_shout` SET `text`='$text', `sticky`='$sticky' WHERE `id`='$id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // create + } // create - /** - * format - * this function takes the object and reformats some values - */ + /** + * format + * this function takes the object and reformats some values + */ - public function format() { - $this->sticky = ($this->sticky == "0") ? 'No' : 'Yes'; - $this->date = date("m\/d\/Y - H:i", $this->date); - return true; + public function format() { + $this->sticky = ($this->sticky == "0") ? 'No' : 'Yes'; + $this->date = date("m\/d\/Y - H:i", $this->date); + return true; - } //format + } //format - /** - * delete - * this function deletes a specific shoutbox entry - */ + /** + * delete + * this function deletes a specific shoutbox entry + */ - public function delete($shout_id) { + public function delete($shout_id) { - // Delete the shoutbox post - $shout_id = Dba::escape($shout_id); - $sql = "DELETE FROM `user_shout` WHERE `id`='$shout_id'"; - $db_results = Dba::write($sql); + // Delete the shoutbox post + $shout_id = Dba::escape($shout_id); + $sql = "DELETE FROM `user_shout` WHERE `id`='$shout_id'"; + $db_results = Dba::write($sql); - } // delete + } // delete } // Shoutbox class ?> diff --git a/lib/class/song.class.php b/lib/class/song.class.php index ac25b1a0f4..3d865b2506 100644 --- a/lib/class/song.class.php +++ b/lib/class/song.class.php @@ -1,5 +1,5 @@ id = intval($id); - - /* Get the information from the db */ - if ($info = $this->_get_info()) { - - foreach ($info as $key=>$value) { - $this->$key = $value; - } - $data = pathinfo($this->file); - $this->type = strtolower($data['extension']); - $this->mime = self::type_to_mime($this->type); - } - - return true; - - } // constructor - - /** - * gc - * - * Cleans up the song_data table - */ - public static function gc() { - Dba::write('DELETE FROM `song_data` USING `song_data` LEFT JOIN `song` ON `song`.`id` = `song_data`.`song_id` WHERE `song`.`id` IS NULL'); - } - - /** - * build_cache - * - * This attempts to reduce queries by asking for everything in the - * browse all at once and storing it in the cache, this can help if the - * db connection is the slow point. - */ - public static function build_cache($song_ids) { - - if (!is_array($song_ids) || !count($song_ids)) { return false; } - - $idlist = '(' . implode(',', $song_ids) . ')'; - - // Callers might have passed array(false) because they are dumb - if ($idlist == '()') { return false; } - - // Song data cache - $sql = 'SELECT `song`.`id`, `file`, `catalog`, `album`, ' . - '`year`, `artist`, `title`, `bitrate`, `rate`, ' . - '`mode`, `size`, `time`, `track`, `played`, ' . - '`song`.`enabled`, `update_time`, `tag_map`.`tag_id`, '. - '`mbid`, `addition_time` ' . - 'FROM `song` LEFT JOIN `tag_map` ' . - 'ON `tag_map`.`object_id`=`song`.`id` ' . - "AND `tag_map`.`object_type`='song' " . - "WHERE `song`.`id` IN $idlist"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('song', $row['id'], $row); - $artists[$row['artist']] = $row['artist']; - $albums[$row['album']] = $row['album']; - if ($row['tag_id']) { - $tags[$row['tag_id']] = $row['tag_id']; - } - } - - Artist::build_cache($artists); - Album::build_cache($albums); - Tag::build_cache($tags); - Tag::build_map_cache('song',$song_ids); - Art::build_cache($albums); - - // If we're rating this then cache them as well - if (Config::get('ratings')) { - Rating::build_cache('song', $song_ids); - } - - // Build a cache for the song's extended table - $sql = "SELECT * FROM `song_data` WHERE `song_id` IN $idlist"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('song_data', $row['song_id'], $row); - } - - return true; - - } // build_cache - - /** - * _get_info - * get's the vars for $this out of the database - * Taken from the object - */ - private function _get_info() { - - $id = intval($this->id); - - if (parent::is_cached('song',$id)) { - return parent::get_from_cache('song',$id); - } - - /* Grab the basic information from the catalog and return it */ - $sql = "SELECT song.id,file,catalog,album,year,artist,". - "title,bitrate,rate,mode,size,time,track,played,song.enabled,update_time,". - "mbid,". - "addition_time FROM `song` WHERE `song`.`id` = '$id'"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - - parent::add_to_cache('song',$id,$results); - - return $results; - - } // _get_info - - /** - * _get_ext_info - * This function gathers information from the song_ext_info table and adds it to the - * current object - */ - public function _get_ext_info() { - - $id = intval($this->id); - - if (parent::is_cached('song_data',$id)) { - return parent::get_from_cache('song_data',$id); - } - - $sql = "SELECT * FROM song_data WHERE `song_id`='$id'"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - - parent::add_to_cache('song_data',$id,$results); - - return $results; - - } // _get_ext_info - - /** - * fill_ext_info - * This calls the _get_ext_info and then sets the correct vars - */ - public function fill_ext_info() { - - $info = $this->_get_ext_info(); - - foreach ($info as $key=>$value) { - if ($key != 'song_id') { - $this->$key = $value; - } - } // end foreach - - } // fill_ext_info - - /** - * type_to_mime - * - * Returns the mime type for the specified file extension/type - */ - public static function type_to_mime($type) { - // FIXME: This should really be done the other way around. - // Store the mime type in the database, and provide a function - // to make it a human-friendly type. - switch ($type) { - case 'spx': - case 'ogg': - return 'application/ogg'; - break; - case 'wma': - case 'asf': - return 'audio/x-ms-wma'; - break; - case 'mp3': - case 'mpeg3': - return 'audio/mpeg'; - break; - case 'rm': - case 'ra': - return 'audio/x-realaudio'; - break; - case 'flac'; - return 'audio/x-flac'; - break; - case 'wv': - return 'audio/x-wavpack'; - break; - case 'aac': - case 'mp4': - case 'm4a': - return 'audio/mp4'; - break; - case 'mpc': - return 'audio/x-musepack'; - break; - default: - return 'audio/mpeg'; - break; - } - - return true; - - } - - /** - * get_disabled - * - * Gets a list of the disabled songs for and returns an array of Songs - */ - public static function get_disabled($count = 0) { - - $results = array(); - - $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'"; - if ($count) { $sql .= " LIMIT $count"; } - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = new Song($r['id']); - } - - return $results; - - } - - /** - * find_duplicates - * - * This function takes a search type and returns a list of probable - * duplicates - */ - public static function find_duplicates($search_type) { - $where_sql = $_REQUEST['search_disabled'] ? '' : "WHERE `enabled` != '0'"; - $sql = 'SELECT `id`, `artist`, `album`, `title`, ' . - 'COUNT(`title`) FROM `song` ' . $where_sql . - ' GROUP BY `title`'; - - if ($search_type == 'artist_title' || - $search_type == 'artist_album_title') { - $sql .= ',`artist`'; - } - if ($search_type == 'artist_album_title') { - $sql .= ',`album`'; - } - - $sql .= ' HAVING COUNT(`title`) > 1 ORDER BY `title`'; - - $db_results = Dba::read($sql); - - $results = array(); - - while ($item = Dba::fetch_assoc($db_results)) { - $results[] = $item; - } // end while - - return $results; - } - - public static function get_duplicate_info($dupe, $search_type) { - $sql = 'SELECT `id` FROM `song` ' . - "WHERE `title`='" . Dba::escape($item['title']) . "' "; - - if ($search_type == 'artist_title' || - $search_type == 'artist_album_title') { - $sql .= "AND `artist`='" . Dba::escape($item['artist']) . "' "; - } - if ($search_type == 'artist_album_title') { - $sql .= "AND `album` = '" . Dba::escape($item['album']) . "' "; - } - - $sql .= 'ORDER BY `time`,`bitrate`,`size`'; - $db_results = Dba::read($sql); - - $results = array(); - - while ($item = Dba::fetch_assoc($db_results)) { - $results[] = $item['id']; - } // end while - - return $results; - } - - /** - * get_album_name - * gets the name of $this->album, allows passing of id - */ - public function get_album_name($album_id=0) { - if (!$album_id) { $album_id = $this->album; } - $album = new Album($album_id); - if ($album->prefix) - return $album->prefix . " " . $album->name; - else - return $album->name; - } // get_album_name - - /** - * get_artist_name - * gets the name of $this->artist, allows passing of id - */ - public function get_artist_name($artist_id=0) { - - if (!$artist_id) { $artist_id = $this->artist; } - $artist = new Artist($artist_id); - if ($artist->prefix) - return $artist->prefix . " " . $artist->name; - else - return $artist->name; - - } // get_album_name - - /** - * has_flag - * This just returns true or false depending on if this song is flagged for something - * We don't care what so we limit the SELECT to 1 - */ - public function has_flag() { - - $sql = "SELECT `id` FROM `flagged` WHERE `object_type`='song' AND `object_id`='$this->id' LIMIT 1"; - $db_results = Dba::read($sql); - - if (Dba::fetch_assoc($db_results)) { - return true; - } - - return false; - - } // has_flag - - /** - * set_played - * this checks to see if the current object has been played - * if not then it sets it to played - */ - public function set_played() { - - if ($this->played) { - return true; - } - - /* If it hasn't been played, set it! */ - self::update_played('1',$this->id); - - return true; - - } // set_played - - /** - * compare_song_information - * this compares the new ID3 tags of a file against - * the ones in the database to see if they have changed - * it returns false if nothing has changes, or the true - * if they have. Static because it doesn't need this - */ - public static function compare_song_information($song,$new_song) { - - // Remove some stuff we don't care about - unset($song->catalog,$song->played,$song->enabled,$song->addition_time,$song->update_time,$song->type); - - $string_array = array('title','comment','lyrics'); - $skip_array = array('id','tag_id','mime','mb_artistid','mbid'); - - // Pull out all the currently set vars - $fields = get_object_vars($song); - - // Foreach them - foreach ($fields as $key=>$value) { - if (in_array($key,$skip_array)) { continue; } - // If it's a stringie thing - if (in_array($key,$string_array)) { - if (trim(stripslashes($song->$key)) != trim(stripslashes($new_song->$key))) { - $array['change'] = true; - $array['element'][$key] = 'OLD: ' . $song->$key . ' --> ' . $new_song->$key; - } - } // in array of stringies - else { - if ($song->$key != $new_song->$key) { - $array['change'] = true; - $array['element'][$key] = 'OLD:' . $song->$key . ' --> ' . $new_song->$key; - } - } // end else - - } // end foreach - - if ($array['change']) { - debug_event('song-diff', json_encode($array['element']), 5, 'ampache-catalog'); - } - - return $array; - - } // compare_song_information - - - /** - * update - * This takes a key'd array of data does any cleaning it needs to - * do and then calls the helper functions as needed. This will also - * cause the song to be flagged - */ - public function update($data) { - - foreach ($data as $key=>$value) { - switch ($key) { - case 'artist': - // Don't do anything if we've negative one'd this baby - if ($value == '-1') { - $value = Catalog::check_artist($data['artist_name'], $data['mb_artistid']); - } - case 'album': - if ($value == '-1') { - $value = Catalog::check_album($data['album_name'], $data['year'], $data['disk'], $data['mb_albumid']); - } - case 'title': - case 'track': - // Check to see if it needs to be updated - if ($value != $this->$key) { - $function = 'update_' . $key; - self::$function($value,$this->id); - $this->$key = $value; - $updated = 1; - } - break; - default: - // Rien a faire - break; - } // end whitelist - } // end foreach - - // If a field was changed then we need to flag this mofo - if ($updated) { - Flag::add($this->id,'song','retag','Interface Update'); - } - - return true; - - } // update - - /** - * update_song - * this is the main updater for a song it actually - * calls a whole bunch of mini functions to update - * each little part of the song... lastly it updates - * the "update_time" of the song - */ - public static function update_song($song_id, $new_song) { - - $title = Dba::escape($new_song->title); - $bitrate = Dba::escape($new_song->bitrate); - $rate = Dba::escape($new_song->rate); - $mode = Dba::escape($new_song->mode); - $size = Dba::escape($new_song->size); - $time = Dba::escape($new_song->time); - $track = Dba::escape($new_song->track); - $mbid = Dba::escape($new_song->mbid); - $artist = Dba::escape($new_song->artist); - $album = Dba::escape($new_song->album); - $year = Dba::escape($new_song->year); - $song_id = Dba::escape($song_id); - $update_time = time(); - - - $sql = "UPDATE `song` SET `album`='$album', `year`='$year', `artist`='$artist', " . - "`title`='$title', `bitrate`='$bitrate', `rate`='$rate', `mode`='$mode', " . - "`size`='$size', `time`='$time', `track`='$track', " . - "`mbid`='$mbid', " . - "`update_time`='$update_time' WHERE `id`='$song_id'"; - $db_results = Dba::write($sql); - - - $comment = Dba::escape($new_song->comment); - $language = Dba::escape($new_song->language); - $lyrics = Dba::escape($new_song->lyrics); - - $sql = "UPDATE `song_data` SET `lyrics`='$lyrics', `language`='$language', `comment`='$comment' " . - "WHERE `song_id`='$song_id'"; - $db_results = Dba::write($sql); - - } // update_song - - /** - * update_year - * update the year tag - */ - public static function update_year($new_year,$song_id) { - - self::_update_item('year',$new_year,$song_id,'50'); - - } // update_year - - /** - * update_language - * This updates the language tag of the song - */ - public static function update_language($new_lang,$song_id) { - - self::_update_ext_item('language',$new_lang,$song_id,'50'); - - } // update_language - - /** - * update_comment - * updates the comment field - */ - public static function update_comment($new_comment,$song_id) { + /* Variables from DB */ + public $id; + public $file; + public $album; // album.id (Int) + public $artist; // artist.id (Int) + public $title; + public $year; + public $bitrate; + public $rate; + public $mode; + public $size; + public $time; + public $track; + public $album_mbid; + public $artist_mbid; + public $type; + public $mime; + public $played; + public $enabled; + public $addition_time; + public $update_time; + public $mbid; // MusicBrainz ID + + /* Setting Variables */ + public $_fake = false; // If this is a 'construct_from_array' object + + /** + * Constructor + * Song class, for modifing a song. + */ + public function __construct($id='') { + + if (!$id) { return false; } + + /* Assign id for use in get_info() */ + $this->id = intval($id); + + /* Get the information from the db */ + if ($info = $this->_get_info()) { + + foreach ($info as $key=>$value) { + $this->$key = $value; + } + $data = pathinfo($this->file); + $this->type = strtolower($data['extension']); + $this->mime = self::type_to_mime($this->type); + } + + return true; + + } // constructor + + /** + * gc + * + * Cleans up the song_data table + */ + public static function gc() { + Dba::write('DELETE FROM `song_data` USING `song_data` LEFT JOIN `song` ON `song`.`id` = `song_data`.`song_id` WHERE `song`.`id` IS NULL'); + } + + /** + * build_cache + * + * This attempts to reduce queries by asking for everything in the + * browse all at once and storing it in the cache, this can help if the + * db connection is the slow point. + */ + public static function build_cache($song_ids) { + + if (!is_array($song_ids) || !count($song_ids)) { return false; } + + $idlist = '(' . implode(',', $song_ids) . ')'; + + // Callers might have passed array(false) because they are dumb + if ($idlist == '()') { return false; } + + // Song data cache + $sql = 'SELECT `song`.`id`, `file`, `catalog`, `album`, ' . + '`year`, `artist`, `title`, `bitrate`, `rate`, ' . + '`mode`, `size`, `time`, `track`, `played`, ' . + '`song`.`enabled`, `update_time`, `tag_map`.`tag_id`, '. + '`mbid`, `addition_time` ' . + 'FROM `song` LEFT JOIN `tag_map` ' . + 'ON `tag_map`.`object_id`=`song`.`id` ' . + "AND `tag_map`.`object_type`='song' " . + "WHERE `song`.`id` IN $idlist"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('song', $row['id'], $row); + $artists[$row['artist']] = $row['artist']; + $albums[$row['album']] = $row['album']; + if ($row['tag_id']) { + $tags[$row['tag_id']] = $row['tag_id']; + } + } + + Artist::build_cache($artists); + Album::build_cache($albums); + Tag::build_cache($tags); + Tag::build_map_cache('song',$song_ids); + Art::build_cache($albums); + + // If we're rating this then cache them as well + if (Config::get('ratings')) { + Rating::build_cache('song', $song_ids); + } + + // Build a cache for the song's extended table + $sql = "SELECT * FROM `song_data` WHERE `song_id` IN $idlist"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('song_data', $row['song_id'], $row); + } + + return true; + + } // build_cache + + /** + * _get_info + * get's the vars for $this out of the database + * Taken from the object + */ + private function _get_info() { + + $id = intval($this->id); + + if (parent::is_cached('song',$id)) { + return parent::get_from_cache('song',$id); + } + + /* Grab the basic information from the catalog and return it */ + $sql = "SELECT song.id,file,catalog,album,year,artist,". + "title,bitrate,rate,mode,size,time,track,played,song.enabled,update_time,". + "mbid,". + "addition_time FROM `song` WHERE `song`.`id` = '$id'"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + + parent::add_to_cache('song',$id,$results); + + return $results; + + } // _get_info + + /** + * _get_ext_info + * This function gathers information from the song_ext_info table and adds it to the + * current object + */ + public function _get_ext_info() { + + $id = intval($this->id); + + if (parent::is_cached('song_data',$id)) { + return parent::get_from_cache('song_data',$id); + } + + $sql = "SELECT * FROM song_data WHERE `song_id`='$id'"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + + parent::add_to_cache('song_data',$id,$results); + + return $results; + + } // _get_ext_info + + /** + * fill_ext_info + * This calls the _get_ext_info and then sets the correct vars + */ + public function fill_ext_info() { + + $info = $this->_get_ext_info(); + + foreach ($info as $key=>$value) { + if ($key != 'song_id') { + $this->$key = $value; + } + } // end foreach + + } // fill_ext_info + + /** + * type_to_mime + * + * Returns the mime type for the specified file extension/type + */ + public static function type_to_mime($type) { + // FIXME: This should really be done the other way around. + // Store the mime type in the database, and provide a function + // to make it a human-friendly type. + switch ($type) { + case 'spx': + case 'ogg': + return 'application/ogg'; + break; + case 'wma': + case 'asf': + return 'audio/x-ms-wma'; + break; + case 'mp3': + case 'mpeg3': + return 'audio/mpeg'; + break; + case 'rm': + case 'ra': + return 'audio/x-realaudio'; + break; + case 'flac'; + return 'audio/x-flac'; + break; + case 'wv': + return 'audio/x-wavpack'; + break; + case 'aac': + case 'mp4': + case 'm4a': + return 'audio/mp4'; + break; + case 'mpc': + return 'audio/x-musepack'; + break; + default: + return 'audio/mpeg'; + break; + } + + return true; + + } + + /** + * get_disabled + * + * Gets a list of the disabled songs for and returns an array of Songs + */ + public static function get_disabled($count = 0) { + + $results = array(); + + $sql = "SELECT `id` FROM `song` WHERE `enabled`='0'"; + if ($count) { $sql .= " LIMIT $count"; } + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = new Song($r['id']); + } + + return $results; + + } + + /** + * find_duplicates + * + * This function takes a search type and returns a list of probable + * duplicates + */ + public static function find_duplicates($search_type) { + $where_sql = $_REQUEST['search_disabled'] ? '' : "WHERE `enabled` != '0'"; + $sql = 'SELECT `id`, `artist`, `album`, `title`, ' . + 'COUNT(`title`) FROM `song` ' . $where_sql . + ' GROUP BY `title`'; + + if ($search_type == 'artist_title' || + $search_type == 'artist_album_title') { + $sql .= ',`artist`'; + } + if ($search_type == 'artist_album_title') { + $sql .= ',`album`'; + } + + $sql .= ' HAVING COUNT(`title`) > 1 ORDER BY `title`'; + + $db_results = Dba::read($sql); + + $results = array(); + + while ($item = Dba::fetch_assoc($db_results)) { + $results[] = $item; + } // end while + + return $results; + } + + public static function get_duplicate_info($dupe, $search_type) { + $sql = 'SELECT `id` FROM `song` ' . + "WHERE `title`='" . Dba::escape($item['title']) . "' "; + + if ($search_type == 'artist_title' || + $search_type == 'artist_album_title') { + $sql .= "AND `artist`='" . Dba::escape($item['artist']) . "' "; + } + if ($search_type == 'artist_album_title') { + $sql .= "AND `album` = '" . Dba::escape($item['album']) . "' "; + } + + $sql .= 'ORDER BY `time`,`bitrate`,`size`'; + $db_results = Dba::read($sql); + + $results = array(); + + while ($item = Dba::fetch_assoc($db_results)) { + $results[] = $item['id']; + } // end while + + return $results; + } + + /** + * get_album_name + * gets the name of $this->album, allows passing of id + */ + public function get_album_name($album_id=0) { + if (!$album_id) { $album_id = $this->album; } + $album = new Album($album_id); + if ($album->prefix) + return $album->prefix . " " . $album->name; + else + return $album->name; + } // get_album_name + + /** + * get_artist_name + * gets the name of $this->artist, allows passing of id + */ + public function get_artist_name($artist_id=0) { + + if (!$artist_id) { $artist_id = $this->artist; } + $artist = new Artist($artist_id); + if ($artist->prefix) + return $artist->prefix . " " . $artist->name; + else + return $artist->name; + + } // get_album_name + + /** + * has_flag + * This just returns true or false depending on if this song is flagged for something + * We don't care what so we limit the SELECT to 1 + */ + public function has_flag() { + + $sql = "SELECT `id` FROM `flagged` WHERE `object_type`='song' AND `object_id`='$this->id' LIMIT 1"; + $db_results = Dba::read($sql); + + if (Dba::fetch_assoc($db_results)) { + return true; + } + + return false; + + } // has_flag + + /** + * set_played + * this checks to see if the current object has been played + * if not then it sets it to played + */ + public function set_played() { + + if ($this->played) { + return true; + } + + /* If it hasn't been played, set it! */ + self::update_played('1',$this->id); + + return true; + + } // set_played + + /** + * compare_song_information + * this compares the new ID3 tags of a file against + * the ones in the database to see if they have changed + * it returns false if nothing has changes, or the true + * if they have. Static because it doesn't need this + */ + public static function compare_song_information($song,$new_song) { + + // Remove some stuff we don't care about + unset($song->catalog,$song->played,$song->enabled,$song->addition_time,$song->update_time,$song->type); + + $string_array = array('title','comment','lyrics'); + $skip_array = array('id','tag_id','mime','mb_artistid','mbid'); + + // Pull out all the currently set vars + $fields = get_object_vars($song); + + // Foreach them + foreach ($fields as $key=>$value) { + if (in_array($key,$skip_array)) { continue; } + // If it's a stringie thing + if (in_array($key,$string_array)) { + if (trim(stripslashes($song->$key)) != trim(stripslashes($new_song->$key))) { + $array['change'] = true; + $array['element'][$key] = 'OLD: ' . $song->$key . ' --> ' . $new_song->$key; + } + } // in array of stringies + else { + if ($song->$key != $new_song->$key) { + $array['change'] = true; + $array['element'][$key] = 'OLD:' . $song->$key . ' --> ' . $new_song->$key; + } + } // end else + + } // end foreach + + if ($array['change']) { + debug_event('song-diff', json_encode($array['element']), 5, 'ampache-catalog'); + } + + return $array; + + } // compare_song_information + + + /** + * update + * This takes a key'd array of data does any cleaning it needs to + * do and then calls the helper functions as needed. This will also + * cause the song to be flagged + */ + public function update($data) { + + foreach ($data as $key=>$value) { + switch ($key) { + case 'artist': + // Don't do anything if we've negative one'd this baby + if ($value == '-1') { + $value = Catalog::check_artist($data['artist_name'], $data['mb_artistid']); + } + case 'album': + if ($value == '-1') { + $value = Catalog::check_album($data['album_name'], $data['year'], $data['disk'], $data['mb_albumid']); + } + case 'title': + case 'track': + // Check to see if it needs to be updated + if ($value != $this->$key) { + $function = 'update_' . $key; + self::$function($value,$this->id); + $this->$key = $value; + $updated = 1; + } + break; + default: + // Rien a faire + break; + } // end whitelist + } // end foreach + + // If a field was changed then we need to flag this mofo + if ($updated) { + Flag::add($this->id,'song','retag','Interface Update'); + } + + return true; + + } // update + + /** + * update_song + * this is the main updater for a song it actually + * calls a whole bunch of mini functions to update + * each little part of the song... lastly it updates + * the "update_time" of the song + */ + public static function update_song($song_id, $new_song) { + + $title = Dba::escape($new_song->title); + $bitrate = Dba::escape($new_song->bitrate); + $rate = Dba::escape($new_song->rate); + $mode = Dba::escape($new_song->mode); + $size = Dba::escape($new_song->size); + $time = Dba::escape($new_song->time); + $track = Dba::escape($new_song->track); + $mbid = Dba::escape($new_song->mbid); + $artist = Dba::escape($new_song->artist); + $album = Dba::escape($new_song->album); + $year = Dba::escape($new_song->year); + $song_id = Dba::escape($song_id); + $update_time = time(); + + + $sql = "UPDATE `song` SET `album`='$album', `year`='$year', `artist`='$artist', " . + "`title`='$title', `bitrate`='$bitrate', `rate`='$rate', `mode`='$mode', " . + "`size`='$size', `time`='$time', `track`='$track', " . + "`mbid`='$mbid', " . + "`update_time`='$update_time' WHERE `id`='$song_id'"; + $db_results = Dba::write($sql); + + + $comment = Dba::escape($new_song->comment); + $language = Dba::escape($new_song->language); + $lyrics = Dba::escape($new_song->lyrics); + + $sql = "UPDATE `song_data` SET `lyrics`='$lyrics', `language`='$language', `comment`='$comment' " . + "WHERE `song_id`='$song_id'"; + $db_results = Dba::write($sql); + + } // update_song + + /** + * update_year + * update the year tag + */ + public static function update_year($new_year,$song_id) { + + self::_update_item('year',$new_year,$song_id,'50'); + + } // update_year + + /** + * update_language + * This updates the language tag of the song + */ + public static function update_language($new_lang,$song_id) { + + self::_update_ext_item('language',$new_lang,$song_id,'50'); + + } // update_language + + /** + * update_comment + * updates the comment field + */ + public static function update_comment($new_comment,$song_id) { - self::_update_ext_item('comment',$new_comment,$song_id,'50'); + self::_update_ext_item('comment',$new_comment,$song_id,'50'); - } // update_comment + } // update_comment - /** - * update_lyrics - * updates the lyrics field - */ - public static function update_lyrics($new_lyrics,$song_id) { + /** + * update_lyrics + * updates the lyrics field + */ + public static function update_lyrics($new_lyrics,$song_id) { - self::_update_ext_item('lyrics',$new_lyrics,$song_id,'50'); + self::_update_ext_item('lyrics',$new_lyrics,$song_id,'50'); - } // update_lyrics + } // update_lyrics - /** - * update_title - * updates the title field - */ - public static function update_title($new_title,$song_id) { + /** + * update_title + * updates the title field + */ + public static function update_title($new_title,$song_id) { - self::_update_item('title',$new_title,$song_id,'50'); + self::_update_item('title',$new_title,$song_id,'50'); - } // update_title + } // update_title - /** - * update_bitrate - * updates the bitrate field - */ - public static function update_bitrate($new_bitrate,$song_id) { + /** + * update_bitrate + * updates the bitrate field + */ + public static function update_bitrate($new_bitrate,$song_id) { - self::_update_item('bitrate',$new_bitrate,$song_id,'50'); + self::_update_item('bitrate',$new_bitrate,$song_id,'50'); - } // update_bitrate + } // update_bitrate - /** - * update_rate - * updates the rate field - */ - public static function update_rate($new_rate,$song_id) { + /** + * update_rate + * updates the rate field + */ + public static function update_rate($new_rate,$song_id) { - self::_update_item('rate',$new_rate,$song_id,'50'); + self::_update_item('rate',$new_rate,$song_id,'50'); - } // update_rate + } // update_rate - /** - * update_mode - * updates the mode field - */ - public static function update_mode($new_mode,$song_id) { + /** + * update_mode + * updates the mode field + */ + public static function update_mode($new_mode,$song_id) { - self::_update_item('mode',$new_mode,$song_id,'50'); + self::_update_item('mode',$new_mode,$song_id,'50'); - } // update_mode + } // update_mode - /** - * update_size - * updates the size field - */ - public static function update_size($new_size,$song_id) { + /** + * update_size + * updates the size field + */ + public static function update_size($new_size,$song_id) { - self::_update_item('size',$new_size,$song_id,'50'); + self::_update_item('size',$new_size,$song_id,'50'); - } // update_size + } // update_size - /** - * update_time - * updates the time field - */ - public static function update_time($new_time,$song_id) { + /** + * update_time + * updates the time field + */ + public static function update_time($new_time,$song_id) { - self::_update_item('time',$new_time,$song_id,'50'); + self::_update_item('time',$new_time,$song_id,'50'); - } // update_time + } // update_time - /** - * update_track - * this updates the track field - */ - public static function update_track($new_track,$song_id) { + /** + * update_track + * this updates the track field + */ + public static function update_track($new_track,$song_id) { - self::_update_item('track',$new_track,$song_id,'50'); + self::_update_item('track',$new_track,$song_id,'50'); - } // update_track + } // update_track - public static function update_mbid($new_mbid,$song_id) { + public static function update_mbid($new_mbid,$song_id) { - self::_update_item('mbid',$new_mbid,$song_id,'50'); + self::_update_item('mbid',$new_mbid,$song_id,'50'); - } // update_mbid + } // update_mbid - /** - * update_artist - * updates the artist field - */ - public static function update_artist($new_artist,$song_id) { + /** + * update_artist + * updates the artist field + */ + public static function update_artist($new_artist,$song_id) { - self::_update_item('artist',$new_artist,$song_id,'50'); + self::_update_item('artist',$new_artist,$song_id,'50'); - } // update_artist + } // update_artist - /** - * update_album - * updates the album field - */ - public static function update_album($new_album,$song_id) { + /** + * update_album + * updates the album field + */ + public static function update_album($new_album,$song_id) { - self::_update_item('album',$new_album,$song_id,'50'); + self::_update_item('album',$new_album,$song_id,'50'); - } // update_album + } // update_album - /** - * update_utime - * sets a new update time - */ - public static function update_utime($song_id,$time=0) { + /** + * update_utime + * sets a new update time + */ + public static function update_utime($song_id,$time=0) { - if (!$time) { $time = time(); } + if (!$time) { $time = time(); } - self::_update_item('update_time',$time,$song_id,'75'); + self::_update_item('update_time',$time,$song_id,'75'); - } // update_utime + } // update_utime - /** - * update_played - * sets the played flag - */ - public static function update_played($new_played,$song_id) { + /** + * update_played + * sets the played flag + */ + public static function update_played($new_played,$song_id) { - self::_update_item('played',$new_played,$song_id,'25'); + self::_update_item('played',$new_played,$song_id,'25'); - } // update_played + } // update_played - /** - * update_enabled - * sets the enabled flag - */ - public static function update_enabled($new_enabled,$song_id) { + /** + * update_enabled + * sets the enabled flag + */ + public static function update_enabled($new_enabled,$song_id) { - self::_update_item('enabled',$new_enabled,$song_id,'75'); + self::_update_item('enabled',$new_enabled,$song_id,'75'); - } // update_enabled + } // update_enabled - /** - * _update_item - * This is a private function that should only be called from within the song class. - * It takes a field, value song id and level. first and foremost it checks the level - * against $GLOBALS['user'] to make sure they are allowed to update this record - * it then updates it and sets $this->{$field} to the new value - */ - private static function _update_item($field,$value,$song_id,$level) { + /** + * _update_item + * This is a private function that should only be called from within the song class. + * It takes a field, value song id and level. first and foremost it checks the level + * against $GLOBALS['user'] to make sure they are allowed to update this record + * it then updates it and sets $this->{$field} to the new value + */ + private static function _update_item($field,$value,$song_id,$level) { - /* Check them Rights! */ - if (!Access::check('interface',$level)) { return false; } + /* Check them Rights! */ + if (!Access::check('interface',$level)) { return false; } - /* Can't update to blank */ - if (!strlen(trim($value)) && $field != 'comment') { return false; } + /* Can't update to blank */ + if (!strlen(trim($value)) && $field != 'comment') { return false; } - $value = Dba::escape($value); + $value = Dba::escape($value); - $sql = "UPDATE `song` SET `$field`='$value' WHERE `id`='$song_id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `song` SET `$field`='$value' WHERE `id`='$song_id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // _update_item + } // _update_item - /** - * _update_ext_item - * This updates a song record that is housed in the song_ext_info table - * These are items that aren't used normally, and often large/informational only - */ - private static function _update_ext_item($field,$value,$song_id,$level) { + /** + * _update_ext_item + * This updates a song record that is housed in the song_ext_info table + * These are items that aren't used normally, and often large/informational only + */ + private static function _update_ext_item($field,$value,$song_id,$level) { - /* Check them rights boy! */ - if (!Access::check('interface',$level)) { return false; } + /* Check them rights boy! */ + if (!Access::check('interface',$level)) { return false; } - $value = Dba::escape($value); + $value = Dba::escape($value); - $sql = "UPDATE `song_data` SET `$field`='$value' WHERE `song_id`='$song_id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `song_data` SET `$field`='$value' WHERE `song_id`='$song_id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // _update_ext_item + } // _update_ext_item - /** - * format - * This takes the current song object - * and does a ton of formating on it creating f_??? variables on the current - * object - */ - public function format() { + /** + * format + * This takes the current song object + * and does a ton of formating on it creating f_??? variables on the current + * object + */ + public function format() { - $this->fill_ext_info(); + $this->fill_ext_info(); - // Format the filename - preg_match("/^.*\/(.*?)$/",$this->file, $short); - $this->f_file = htmlspecialchars($short[1]); + // Format the filename + preg_match("/^.*\/(.*?)$/",$this->file, $short); + $this->f_file = htmlspecialchars($short[1]); - // Format the album name - $this->f_album_full = $this->get_album_name(); - $this->f_album = UI::truncate($this->f_album_full,Config::get('ellipse_threshold_album')); + // Format the album name + $this->f_album_full = $this->get_album_name(); + $this->f_album = UI::truncate($this->f_album_full,Config::get('ellipse_threshold_album')); - // Format the artist name - $this->f_artist_full = $this->get_artist_name(); - $this->f_artist = UI::truncate($this->f_artist_full,Config::get('ellipse_threshold_artist')); + // Format the artist name + $this->f_artist_full = $this->get_artist_name(); + $this->f_artist = UI::truncate($this->f_artist_full,Config::get('ellipse_threshold_artist')); - // Format the title - $this->f_title_full = $this->title; - $this->f_title = UI::truncate($this->title,Config::get('ellipse_threshold_title')); + // Format the title + $this->f_title_full = $this->title; + $this->f_title = UI::truncate($this->title,Config::get('ellipse_threshold_title')); - // Create Links for the different objects - $this->link = Config::get('web_path') . "/song.php?action=show_song&song_id=" . $this->id; - $this->f_link = "link) . "\" title=\"" . scrub_out($this->title) . "\"> " . scrub_out($this->f_title) . ""; - $this->f_album_link = "album . "\" title=\"" . scrub_out($this->f_album_full) . "\"> " . scrub_out($this->f_album) . ""; - $this->f_artist_link = "artist . "\" title=\"" . scrub_out($this->f_artist_full) . "\"> " . scrub_out($this->f_artist) . ""; + // Create Links for the different objects + $this->link = Config::get('web_path') . "/song.php?action=show_song&song_id=" . $this->id; + $this->f_link = "link) . "\" title=\"" . scrub_out($this->title) . "\"> " . scrub_out($this->f_title) . ""; + $this->f_album_link = "album . "\" title=\"" . scrub_out($this->f_album_full) . "\"> " . scrub_out($this->f_album) . ""; + $this->f_artist_link = "artist . "\" title=\"" . scrub_out($this->f_artist_full) . "\"> " . scrub_out($this->f_artist) . ""; - // Format the Bitrate - $this->f_bitrate = intval($this->bitrate/1000) . "-" . strtoupper($this->mode); + // Format the Bitrate + $this->f_bitrate = intval($this->bitrate/1000) . "-" . strtoupper($this->mode); - // Format the Time - $min = floor($this->time/60); - $sec = sprintf("%02d", ($this->time%60) ); - $this->f_time = $min . ":" . $sec; + // Format the Time + $min = floor($this->time/60); + $sec = sprintf("%02d", ($this->time%60) ); + $this->f_time = $min . ":" . $sec; - // Format the track (there isn't really anything to do here) - $this->f_track = $this->track; + // Format the track (there isn't really anything to do here) + $this->f_track = $this->track; - // Get the top tags - $tags = Tag::get_top_tags('song',$this->id); - $this->tags = $tags; + // Get the top tags + $tags = Tag::get_top_tags('song',$this->id); + $this->tags = $tags; - $this->f_tags = Tag::get_display($tags,$this->id,'song'); + $this->f_tags = Tag::get_display($tags,$this->id,'song'); - // Format the size - $this->f_size = UI::format_bytes($this->size); + // Format the size + $this->f_size = UI::format_bytes($this->size); - return true; + return true; - } // format + } // format - /** - * format_pattern - * This reformats the song information based on the catalog - * rename patterns - */ - public function format_pattern() { + /** + * format_pattern + * This reformats the song information based on the catalog + * rename patterns + */ + public function format_pattern() { - $extension = ltrim(substr($this->file,strlen($this->file)-4,4),"."); + $extension = ltrim(substr($this->file,strlen($this->file)-4,4),"."); - $catalog = new Catalog($this->catalog); + $catalog = new Catalog($this->catalog); - // If we don't have a rename pattern then just return it - if (!trim($catalog->rename_pattern)) { - $this->f_pattern = $this->title; - $this->f_file = $this->title . '.' . $extension; - return; - } + // If we don't have a rename pattern then just return it + if (!trim($catalog->rename_pattern)) { + $this->f_pattern = $this->title; + $this->f_file = $this->title . '.' . $extension; + return; + } - /* Create the filename that this file should have */ - $album = $this->f_album_full; - $artist = $this->f_artist_full; - $track = sprintf('%02d', $this->track); - $title = $this->title; - $year = $this->year; + /* Create the filename that this file should have */ + $album = $this->f_album_full; + $artist = $this->f_artist_full; + $track = sprintf('%02d', $this->track); + $title = $this->title; + $year = $this->year; - /* Start replacing stuff */ - $replace_array = array('%a','%A','%t','%T','%y','/','\\'); - $content_array = array($artist,$album,$title,$track,$year,'-','-'); + /* Start replacing stuff */ + $replace_array = array('%a','%A','%t','%T','%y','/','\\'); + $content_array = array($artist,$album,$title,$track,$year,'-','-'); - $rename_pattern = str_replace($replace_array,$content_array,$catalog->rename_pattern); + $rename_pattern = str_replace($replace_array,$content_array,$catalog->rename_pattern); - $rename_pattern = preg_replace("[\-\:\!]","_",$rename_pattern); + $rename_pattern = preg_replace("[\-\:\!]","_",$rename_pattern); - $this->f_pattern = $rename_pattern; - $this->f_file = $rename_pattern . "." . $extension; + $this->f_pattern = $rename_pattern; + $this->f_file = $rename_pattern . "." . $extension; - } // format_pattern + } // format_pattern - /** - * get_fields - * This returns all of the 'data' fields for this object, we need to filter out some that we don't - * want to present to a user, and add some that don't exist directly on the object but are related - */ - public static function get_fields() { + /** + * get_fields + * This returns all of the 'data' fields for this object, we need to filter out some that we don't + * want to present to a user, and add some that don't exist directly on the object but are related + */ + public static function get_fields() { - $fields = get_class_vars('Song'); + $fields = get_class_vars('Song'); - unset($fields['id'],$fields['_transcoded'],$fields['_fake'],$fields['cache_hit'],$fields['mime'],$fields['type']); + unset($fields['id'],$fields['_transcoded'],$fields['_fake'],$fields['cache_hit'],$fields['mime'],$fields['type']); - // Some additional fields - $fields['tag'] = true; - $fields['catalog'] = true; + // Some additional fields + $fields['tag'] = true; + $fields['catalog'] = true; //FIXME: These are here to keep the ideas, don't want to have to worry about them for now -// $fields['rating'] = true; -// $fields['recently Played'] = true; +// $fields['rating'] = true; +// $fields['recently Played'] = true; - return $fields; + return $fields; - } // get_fields + } // get_fields - /** - * get_from_path - * This returns all of the songs that exist under the specified path - */ - public static function get_from_path($path) { + /** + * get_from_path + * This returns all of the songs that exist under the specified path + */ + public static function get_from_path($path) { - $path = Dba::escape($path); + $path = Dba::escape($path); - $sql = "SELECT * FROM `song` WHERE `file` LIKE '$path%'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `song` WHERE `file` LIKE '$path%'"; + $db_results = Dba::read($sql); - $songs = array(); + $songs = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $songs[] = $row['id']; - } - - return $songs; + while ($row = Dba::fetch_assoc($db_results)) { + $songs[] = $row['id']; + } + + return $songs; - } // get_from_path + } // get_from_path - /** - * @function get_rel_path - * @discussion returns the path of the song file stripped of the catalog path - * used for mpd playback - */ - public function get_rel_path($file_path=0,$catalog_id=0) { + /** + * @function get_rel_path + * @discussion returns the path of the song file stripped of the catalog path + * used for mpd playback + */ + public function get_rel_path($file_path=0,$catalog_id=0) { - if (!$file_path) { - $info = $this->_get_info(); - $file_path = $info->file; - } - if (!$catalog_id) { - $catalog_id = $info->catalog; - } - $catalog = new Catalog( $catalog_id ); - $info = $catalog->_get_info(); - $catalog_path = $info->path; - $catalog_path = rtrim($catalog_path, "/"); - return( str_replace( $catalog_path . "/", "", $file_path ) ); + if (!$file_path) { + $info = $this->_get_info(); + $file_path = $info->file; + } + if (!$catalog_id) { + $catalog_id = $info->catalog; + } + $catalog = new Catalog( $catalog_id ); + $info = $catalog->_get_info(); + $catalog_path = $info->path; + $catalog_path = rtrim($catalog_path, "/"); + return( str_replace( $catalog_path . "/", "", $file_path ) ); - } // get_rel_path + } // get_rel_path - /** - * play_url - * This function takes all the song information and correctly formats a - * a stream URL taking into account the downsmapling mojo and everything - * else, this is the true function - */ - public static function play_url($oid) { - - $song = new Song($oid); - $user_id = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1'; - $type = $song->type; - - // Required for some versions of winamp that won't work if the - // stream doesn't end in .ogg This will not break any properly - // working player, don't report this as a bug! - if ($song->type == 'flac') { $type = 'ogg'; } - - $song_name = rawurlencode($song->get_artist_name() . " - " . $song->title . "." . $type); - - $url = Stream::get_base_url() . "oid=$song->id&uid=$user_id&name=/$song_name"; - - return $url; - - } // play_url - - /** - * parse_song_url - * Takes a URL from this ampache install and returns the song that the url represents - * used by the API, and used to parse out stream urls for localplay - * right now just gets song id might do more later, hence the complexity - */ - public static function parse_song_url($url) { - - // We only care about the question mark stuff - $query = parse_url($url,PHP_URL_QUERY); - - $elements = explode("&",$query); - - foreach ($elements as $items) { - list($key,$value) = explode("=",$items); - if ($key == 'oid') { - return $value; - } - } // end foreach - - return false; - - } // parse_song_url - - /** - * get_recently_played - * This function returns the last X songs that have been played - * it uses the popular threshold to figure out how many to pull - * it will only return unique object - */ - public static function get_recently_played($user_id='') { - - $user_id = Dba::escape($user_id); - - $sql = "SELECT `object_id`, `user`, `object_type`, `date` " . - "FROM `object_count` WHERE `object_type`='song' "; - if ($user_id) { - $sql .= "AND `user`='$user_id' "; - } - $sql .= "ORDER BY `date` DESC "; - $db_results = Dba::read($sql); - - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - if (isset($results[$row['object_id']])) { continue; } - $results[$row['object_id']] = $row; - if (count($results) >= Config::get('popular_threshold')) { break; } - } - - return $results; - - } // get_recently_played - - public function get_stream_types() { - $types = array(); - $transcode = Config::get('transcode_' . $this->type); - - if ($transcode != 'required') { - $types[] = 'native'; - } - if (make_bool($transcode)) { - $types[] = 'transcode'; - } - - return $types; - } // end stream_types - - public function get_transcode_settings($target = null) { - $source = $this->type; - - if ($target) { - debug_event('transcode', 'Explicit format request', 5); - } - else if ($target = Config::get('encode_target_' . $source)) { - debug_event('transcode', 'Defaulting to configured target format for ' . $source, 5); - } - else if ($target = Config::get('encode_target')) { - debug_event('transcode', 'Using default target format', 5); - } - else { - $target = $source; - debug_event('transcode', 'No default target for ' . $source . ', choosing to resample', 5); - } - - debug_event('transcode', 'Transcoding from ' . $source . ' to ' . $target, 5); - - $cmd = Config::get('transcode_cmd_' . $source) ?: Config::get('transcode_cmd'); - $args = Config::get('encode_args_' . $target); - - if (!$args) { - debug_event('transcode', 'Target format ' . $target . ' is not properly configured', 2); - return false; - } - - debug_event('transcode', 'Command: ' . $cmd . ' Arguments: ' . $args, 5); - return array('format' => $target, - 'command' => $cmd . ' ' . $args); - } + /** + * play_url + * This function takes all the song information and correctly formats a + * a stream URL taking into account the downsmapling mojo and everything + * else, this is the true function + */ + public static function play_url($oid) { + + $song = new Song($oid); + $user_id = $GLOBALS['user']->id ? scrub_out($GLOBALS['user']->id) : '-1'; + $type = $song->type; + + // Required for some versions of winamp that won't work if the + // stream doesn't end in .ogg This will not break any properly + // working player, don't report this as a bug! + if ($song->type == 'flac') { $type = 'ogg'; } + + $song_name = rawurlencode($song->get_artist_name() . " - " . $song->title . "." . $type); + + $url = Stream::get_base_url() . "oid=$song->id&uid=$user_id&name=/$song_name"; + + return $url; + + } // play_url + + /** + * parse_song_url + * Takes a URL from this ampache install and returns the song that the url represents + * used by the API, and used to parse out stream urls for localplay + * right now just gets song id might do more later, hence the complexity + */ + public static function parse_song_url($url) { + + // We only care about the question mark stuff + $query = parse_url($url,PHP_URL_QUERY); + + $elements = explode("&",$query); + + foreach ($elements as $items) { + list($key,$value) = explode("=",$items); + if ($key == 'oid') { + return $value; + } + } // end foreach + + return false; + + } // parse_song_url + + /** + * get_recently_played + * This function returns the last X songs that have been played + * it uses the popular threshold to figure out how many to pull + * it will only return unique object + */ + public static function get_recently_played($user_id='') { + + $user_id = Dba::escape($user_id); + + $sql = "SELECT `object_id`, `user`, `object_type`, `date` " . + "FROM `object_count` WHERE `object_type`='song' "; + if ($user_id) { + $sql .= "AND `user`='$user_id' "; + } + $sql .= "ORDER BY `date` DESC "; + $db_results = Dba::read($sql); + + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + if (isset($results[$row['object_id']])) { continue; } + $results[$row['object_id']] = $row; + if (count($results) >= Config::get('popular_threshold')) { break; } + } + + return $results; + + } // get_recently_played + + public function get_stream_types() { + $types = array(); + $transcode = Config::get('transcode_' . $this->type); + + if ($transcode != 'required') { + $types[] = 'native'; + } + if (make_bool($transcode)) { + $types[] = 'transcode'; + } + + return $types; + } // end stream_types + + public function get_transcode_settings($target = null) { + $source = $this->type; + + if ($target) { + debug_event('transcode', 'Explicit format request', 5); + } + else if ($target = Config::get('encode_target_' . $source)) { + debug_event('transcode', 'Defaulting to configured target format for ' . $source, 5); + } + else if ($target = Config::get('encode_target')) { + debug_event('transcode', 'Using default target format', 5); + } + else { + $target = $source; + debug_event('transcode', 'No default target for ' . $source . ', choosing to resample', 5); + } + + debug_event('transcode', 'Transcoding from ' . $source . ' to ' . $target, 5); + + $cmd = Config::get('transcode_cmd_' . $source) ?: Config::get('transcode_cmd'); + $args = Config::get('encode_args_' . $target); + + if (!$args) { + debug_event('transcode', 'Target format ' . $target . ' is not properly configured', 2); + return false; + } + + debug_event('transcode', 'Command: ' . $cmd . ' Arguments: ' . $args, 5); + return array('format' => $target, + 'command' => $cmd . ' ' . $args); + } } // end of song class ?> diff --git a/lib/class/stats.class.php b/lib/class/stats.class.php index 4ff676e9af..23b17b2044 100644 --- a/lib/class/stats.class.php +++ b/lib/class/stats.class.php @@ -1,5 +1,5 @@ id; - - $user_id = Dba::escape($user_id); + /** + * get_last_song + * This returns the full data for the last song that was played, including when it + * was played, this is used by, among other things, the LastFM plugin to figure out + * if we should re-submit or if this is a duplicate / if it's too soon. This takes an + * optional user_id because when streaming we don't have $GLOBALS() + */ + public static function get_last_song($user_id='') { + + $user_id = $user_id ? $user_id : $GLOBALS['user']->id; + + $user_id = Dba::escape($user_id); - $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' ORDER BY `date` DESC LIMIT 1"; - $db_results = Dba::read($sql); - - $results = Dba::fetch_assoc($db_results); - - return $results; + $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' ORDER BY `date` DESC LIMIT 1"; + $db_results = Dba::read($sql); + + $results = Dba::fetch_assoc($db_results); + + return $results; - } // get_last_song + } // get_last_song - /** - * get_object_history - * This returns the objects that have happened for $user_id sometime after $time - * used primarly by the democratic cooldown code - */ - public static function get_object_history($user_id='',$time) { + /** + * get_object_history + * This returns the objects that have happened for $user_id sometime after $time + * used primarly by the democratic cooldown code + */ + public static function get_object_history($user_id='',$time) { - $user_id = $user_id ? $user_id : $GLOBALS['user']->id; - - $user_id = Dba::escape($user_id); - - $time = Dba::escape($time); - - $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' AND `date`>='$time' " . - "ORDER BY `date` DESC"; - $db_results = Dba::read($sql); - - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['object_id']; - } - - return $results; - - } // get_object_history - - /** - * get_top - * This returns the top X for type Y from the - * last stats_threshold days - */ - public static function get_top($type,$count='',$threshold = '') { - - /* If they don't pass one, then use the preference */ - if (!$threshold) { - $threshold = Config::get('stats_threshold'); - } - - if (!$count) { - $count = Config::get('popular_threshold'); - } - - $count = intval($count); - $type = self::validate_type($type); - $date = time() - (86400*$threshold); + $user_id = $user_id ? $user_id : $GLOBALS['user']->id; + + $user_id = Dba::escape($user_id); + + $time = Dba::escape($time); + + $sql = "SELECT * FROM `object_count` WHERE `user`='$user_id' AND `object_type`='song' AND `date`>='$time' " . + "ORDER BY `date` DESC"; + $db_results = Dba::read($sql); + + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['object_id']; + } + + return $results; + + } // get_object_history + + /** + * get_top + * This returns the top X for type Y from the + * last stats_threshold days + */ + public static function get_top($type,$count='',$threshold = '') { + + /* If they don't pass one, then use the preference */ + if (!$threshold) { + $threshold = Config::get('stats_threshold'); + } + + if (!$count) { + $count = Config::get('popular_threshold'); + } + + $count = intval($count); + $type = self::validate_type($type); + $date = time() - (86400*$threshold); - /* Select Top objects counting by # of rows */ - $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" . - " WHERE object_type='$type' AND date >= '$date'" . - " GROUP BY object_id ORDER BY `count` DESC LIMIT $count"; - $db_results = Dba::read($sql); + /* Select Top objects counting by # of rows */ + $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" . + " WHERE object_type='$type' AND date >= '$date'" . + " GROUP BY object_id ORDER BY `count` DESC LIMIT $count"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['object_id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['object_id']; + } - return $results; + return $results; - } // get_top + } // get_top - /** - * get_user - * This gets all stats for atype based on user with thresholds and all - * If full is passed, doesn't limit based on date - */ - public static function get_user($count,$type,$user,$full='') { + /** + * get_user + * This gets all stats for atype based on user with thresholds and all + * If full is passed, doesn't limit based on date + */ + public static function get_user($count,$type,$user,$full='') { - $count = intval($count); - $type = self::validate_type($type); - $user = Dba::escape($user); + $count = intval($count); + $type = self::validate_type($type); + $user = Dba::escape($user); - /* If full then don't limit on date */ - if ($full) { - $date = '0'; - } - else { - $date = time() - (86400*Config::get('stats_threshold')); - } + /* If full then don't limit on date */ + if ($full) { + $date = '0'; + } + else { + $date = time() - (86400*Config::get('stats_threshold')); + } - /* Select Objects based on user */ - //FIXME:: Requires table scan, look at improving - $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" . - " WHERE object_type='$type' AND date >= '$date' AND user = '$user'" . - " GROUP BY object_id ORDER BY `count` DESC LIMIT $count"; - $db_results = Dba::read($sql); + /* Select Objects based on user */ + //FIXME:: Requires table scan, look at improving + $sql = "SELECT object_id,COUNT(id) AS `count` FROM object_count" . + " WHERE object_type='$type' AND date >= '$date' AND user = '$user'" . + " GROUP BY object_id ORDER BY `count` DESC LIMIT $count"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r; - } + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r; + } - return $results; + return $results; - } // get_user + } // get_user - /** - * validate_type - * This function takes a type and returns only those - * which are allowed, ensures good data gets put into the db - */ - public static function validate_type($type) { + /** + * validate_type + * This function takes a type and returns only those + * which are allowed, ensures good data gets put into the db + */ + public static function validate_type($type) { - switch ($type) { - case 'artist': - case 'album': - case 'genre': - case 'song': - case 'video': - return $type; - default: - return 'song'; - break; - } // end switch - - } // validate_type - - /** - * get_newest - * This returns an array of the newest artists/albums/whatever - * in this ampache instance - */ - public static function get_newest($type,$limit='') { - - if (!$limit) { $limit = Config::get('popular_threshold'); } - - $type = self::validate_type($type); - $object_name = ucfirst($type); - - $sql = "SELECT DISTINCT(`$type`), MIN(`addition_time`) AS `real_atime` FROM `song` GROUP BY `$type` ORDER BY `real_atime` DESC " . - "LIMIT $limit"; - $db_results = Dba::read($sql); - - $items = array(); - - while ($row = Dba::fetch_row($db_results)) { - $items[] = $row['0']; - } // end while results - - return $items; - - } // get_newest + switch ($type) { + case 'artist': + case 'album': + case 'genre': + case 'song': + case 'video': + return $type; + default: + return 'song'; + break; + } // end switch + + } // validate_type + + /** + * get_newest + * This returns an array of the newest artists/albums/whatever + * in this ampache instance + */ + public static function get_newest($type,$limit='') { + + if (!$limit) { $limit = Config::get('popular_threshold'); } + + $type = self::validate_type($type); + $object_name = ucfirst($type); + + $sql = "SELECT DISTINCT(`$type`), MIN(`addition_time`) AS `real_atime` FROM `song` GROUP BY `$type` ORDER BY `real_atime` DESC " . + "LIMIT $limit"; + $db_results = Dba::read($sql); + + $items = array(); + + while ($row = Dba::fetch_row($db_results)) { + $items[] = $row['0']; + } // end while results + + return $items; + + } // get_newest } // Stats class ?> diff --git a/lib/class/stream.class.php b/lib/class/stream.class.php index 428f5a4a7a..338898a267 100644 --- a/lib/class/stream.class.php +++ b/lib/class/stream.class.php @@ -1,5 +1,5 @@ id); + $sid = $sid ? Dba::escape($sid) : Dba::escape(self::$session); + $uid = $uid ? Dba::escape($uid) : Dba::escape($GLOBALS['user']->id); - $expire = time() + Config::get('stream_length'); + $expire = time() + Config::get('stream_length'); - $sql = "INSERT INTO `session_stream` (`id`,`expire`,`user`) " . - "VALUES('$sid','$expire','$uid')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `session_stream` (`id`,`expire`,`user`) " . + "VALUES('$sid','$expire','$uid')"; + $db_results = Dba::write($sql); - if (!$db_results) { return false; } + if (!$db_results) { return false; } - self::$session_inserted = true; + self::$session_inserted = true; - return true; + return true; - } // insert_session + } // insert_session - /** - * session_exists - * This checks to see if the passed stream session exists and is valid - */ - public static function session_exists($sid) { + /** + * session_exists + * This checks to see if the passed stream session exists and is valid + */ + public static function session_exists($sid) { - $sid = Dba::escape($sid); - $time = time(); + $sid = Dba::escape($sid); + $time = time(); - $sql = "SELECT * FROM `session_stream` WHERE `id`='$sid' AND `expire` > '$time'"; - $db_results = Dba::write($sql); + $sql = "SELECT * FROM `session_stream` WHERE `id`='$sid' AND `expire` > '$time'"; + $db_results = Dba::write($sql); - if ($row = Dba::fetch_assoc($db_results)) { - return true; - } + if ($row = Dba::fetch_assoc($db_results)) { + return true; + } - return false; - - } // session_exists - - /** - * gc - * This function performes the garbage collection stuff, run on extend - * and on now playing refresh. - */ - public static function gc() { + return false; + + } // session_exists + + /** + * gc + * This function performes the garbage collection stuff, run on extend + * and on now playing refresh. + */ + public static function gc() { - $time = time(); - $sql = "DELETE FROM `session_stream` WHERE `expire` < '$time'"; - $db_results = Dba::write($sql); - - Stream_Playlist::gc(); + $time = time(); + $sql = "DELETE FROM `session_stream` WHERE `expire` < '$time'"; + $db_results = Dba::write($sql); + + Stream_Playlist::gc(); - } + } - /** - * extend_session - * This takes the passed sid and does a replace into also setting the user - * agent and IP also do a little GC in this function - */ - public static function extend_session($sid,$uid) { + /** + * extend_session + * This takes the passed sid and does a replace into also setting the user + * agent and IP also do a little GC in this function + */ + public static function extend_session($sid,$uid) { - $expire = time() + Config::get('stream_length'); - $sid = Dba::escape($sid); - $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']); - $ip = Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])); - $uid = Dba::escape($uid); - - $sql = "UPDATE `session_stream` SET `expire`='$expire', `agent`='$agent', `ip`='$ip' " . - "WHERE `id`='$sid'"; - $db_results = Dba::write($sql); - - self::gc(); + $expire = time() + Config::get('stream_length'); + $sid = Dba::escape($sid); + $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']); + $ip = Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])); + $uid = Dba::escape($uid); + + $sql = "UPDATE `session_stream` SET `expire`='$expire', `agent`='$agent', `ip`='$ip' " . + "WHERE `id`='$sid'"; + $db_results = Dba::write($sql); + + self::gc(); - return true; + return true; - } // extend_session + } // extend_session - /** - * start_transcode - * - * This is a rather complex function that starts the transcoding or - * resampling of a song and returns the opened file handle. - */ - public static function start_transcode($song) { - $transcode_settings = $song->get_transcode_settings(); - // Bail out early if we're unutterably broken - if ($transcode_settings == false) { - debug_event('stream', 'Transcode requested, but get_transcode_settings failed', 2); - return false; - } + /** + * start_transcode + * + * This is a rather complex function that starts the transcoding or + * resampling of a song and returns the opened file handle. + */ + public static function start_transcode($song) { + $transcode_settings = $song->get_transcode_settings(); + // Bail out early if we're unutterably broken + if ($transcode_settings == false) { + debug_event('stream', 'Transcode requested, but get_transcode_settings failed', 2); + return false; + } - $max_bitrate = Config::get('max_bit_rate'); - $min_bitrate = Config::get('min_bit_rate'); - // FIXME: This should be configurable for each output type - $user_sample_rate = Config::get('sample_rate'); + $max_bitrate = Config::get('max_bit_rate'); + $min_bitrate = Config::get('min_bit_rate'); + // FIXME: This should be configurable for each output type + $user_sample_rate = Config::get('sample_rate'); - // If the user's crazy, that's no skin off our back - if ($user_sample_rate < $min_bitrate) { - $min_bitrate = $user_sample_rate; - } + // If the user's crazy, that's no skin off our back + if ($user_sample_rate < $min_bitrate) { + $min_bitrate = $user_sample_rate; + } - // Are there site-wide constraints? (Dynamic downsampling.) - if ($max_bitrate > 1 ) { - $sql = 'SELECT COUNT(*) FROM `now_playing` ' . - 'WHERE `user` IN ' . - '(SELECT DISTINCT `user_preference`.`user` ' . - 'FROM `preference` JOIN `user_preference` ' . - 'ON `preference`.`id` = ' . - '`user_preferece`.`preference` ' . - "WHERE `preference`.`name` = 'play_type' " . - "AND `user_preference`.`value` = 'downsample')"; - - $db_results = Dba::read($sql); - $results = Dba::fetch_row($db_results); - - $active_streams = intval($results[0]) ?: 0; - debug_event('stream', 'Active transcoding streams: ' . $active_streams, 5); - - // We count as one for the algorithm - // FIXME: Should this reflect the actual bit rates? - $active_streams++; - $sample_rate = floor($max_bitrate / $active_streams); - - // Exit if this would be insane - if ($sample_rate < ($min_bitrate ?: 8)) { - debug_event('stream', 'Max transcode bandwidth already allocated. Active streams: ' . $active_streams, 2); - header('HTTP/1.1 503 Service Temporarily Unavailable'); - exit(); - } - - // Never go over the user's sample rate - if ($sample_rate > $user_sample_rate) { - $sample_rate = $user_sample_rate; - } - - } // end if we've got bitrates - else { - $sample_rate = $user_sample_rate; - } - - debug_event('stream', 'Configured bitrate is ' . $sample_rate, 5); - - // Validate the bitrate - $sample_rate = self::validate_bitrate($sample_rate); - - // Never upsample a song - if ($song->type == $transcode_settings['format'] && ($sample_rate * 1000) > $song->bitrate) { - debug_event('stream', 'Clamping bitrate to avoid upsampling to ' . $sample_rate, 5); - $sample_rate = self::validate_bitrate($song->bitrate / 1000); - } - - debug_event('stream', 'Final transcode bitrate is ' . $sample_rate, 5); - - $song_file = scrub_arg($song->file); - - // Finalise the command line - $command = $transcode_settings['command']; - - $string_map = array( - '%FILE%' => $song_file, - '%SAMPLE%' => $sample_rate - ); - - foreach ($string_map as $search => $replace) { - $command = str_replace($search, $replace, $command, $ret); - if (!$ret) { - debug_event('downsample', "$search not in downsample command", 5); - } - } - - debug_event('downsample', "Downsample command: $command", 3); - - return array( - 'handle' => popen($command, 'rb'), - 'format' => $transcode_settings['format'] - ); - - } - - /** - * validate_bitrate - * this function takes a bitrate and returns a valid one - */ - public static function validate_bitrate($bitrate) { - - /* Round to standard bitrates */ - $sample_rate = 16*(floor($bitrate/16)); - - return $sample_rate; - - } // validate_bitrate - - - /** - * gc_now_playing - * This will garbage collect the now playing data, - * this is done on every play start - */ - public static function gc_now_playing() { + // Are there site-wide constraints? (Dynamic downsampling.) + if ($max_bitrate > 1 ) { + $sql = 'SELECT COUNT(*) FROM `now_playing` ' . + 'WHERE `user` IN ' . + '(SELECT DISTINCT `user_preference`.`user` ' . + 'FROM `preference` JOIN `user_preference` ' . + 'ON `preference`.`id` = ' . + '`user_preferece`.`preference` ' . + "WHERE `preference`.`name` = 'play_type' " . + "AND `user_preference`.`value` = 'downsample')"; + + $db_results = Dba::read($sql); + $results = Dba::fetch_row($db_results); + + $active_streams = intval($results[0]) ?: 0; + debug_event('stream', 'Active transcoding streams: ' . $active_streams, 5); + + // We count as one for the algorithm + // FIXME: Should this reflect the actual bit rates? + $active_streams++; + $sample_rate = floor($max_bitrate / $active_streams); + + // Exit if this would be insane + if ($sample_rate < ($min_bitrate ?: 8)) { + debug_event('stream', 'Max transcode bandwidth already allocated. Active streams: ' . $active_streams, 2); + header('HTTP/1.1 503 Service Temporarily Unavailable'); + exit(); + } + + // Never go over the user's sample rate + if ($sample_rate > $user_sample_rate) { + $sample_rate = $user_sample_rate; + } + + } // end if we've got bitrates + else { + $sample_rate = $user_sample_rate; + } + + debug_event('stream', 'Configured bitrate is ' . $sample_rate, 5); + + // Validate the bitrate + $sample_rate = self::validate_bitrate($sample_rate); + + // Never upsample a song + if ($song->type == $transcode_settings['format'] && ($sample_rate * 1000) > $song->bitrate) { + debug_event('stream', 'Clamping bitrate to avoid upsampling to ' . $sample_rate, 5); + $sample_rate = self::validate_bitrate($song->bitrate / 1000); + } + + debug_event('stream', 'Final transcode bitrate is ' . $sample_rate, 5); + + $song_file = scrub_arg($song->file); + + // Finalise the command line + $command = $transcode_settings['command']; + + $string_map = array( + '%FILE%' => $song_file, + '%SAMPLE%' => $sample_rate + ); + + foreach ($string_map as $search => $replace) { + $command = str_replace($search, $replace, $command, $ret); + if (!$ret) { + debug_event('downsample', "$search not in downsample command", 5); + } + } + + debug_event('downsample', "Downsample command: $command", 3); + + return array( + 'handle' => popen($command, 'rb'), + 'format' => $transcode_settings['format'] + ); + + } + + /** + * validate_bitrate + * this function takes a bitrate and returns a valid one + */ + public static function validate_bitrate($bitrate) { + + /* Round to standard bitrates */ + $sample_rate = 16*(floor($bitrate/16)); + + return $sample_rate; + + } // validate_bitrate + + + /** + * gc_now_playing + * This will garbage collect the now playing data, + * this is done on every play start + */ + public static function gc_now_playing() { - // Remove any now playing entries for session_streams that have been GC'd - $sql = "DELETE FROM `now_playing` USING `now_playing` " . - "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " . - "WHERE `session_stream`.`id` IS NULL OR `now_playing`.`expire` < '" . time() . "'"; - $db_results = Dba::write($sql); - - } // gc_now_playing - - /** - * insert_now_playing - * This will insert the now playing data - * This fucntion is used by the /play/index.php song - * primarily, but could be used by other people - */ - public static function insert_now_playing($oid,$uid,$length,$sid,$type) { + // Remove any now playing entries for session_streams that have been GC'd + $sql = "DELETE FROM `now_playing` USING `now_playing` " . + "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " . + "WHERE `session_stream`.`id` IS NULL OR `now_playing`.`expire` < '" . time() . "'"; + $db_results = Dba::write($sql); + + } // gc_now_playing + + /** + * insert_now_playing + * This will insert the now playing data + * This fucntion is used by the /play/index.php song + * primarily, but could be used by other people + */ + public static function insert_now_playing($oid,$uid,$length,$sid,$type) { - $time = intval(time()+$length); - $session_id = Dba::escape($sid); - $object_type = Dba::escape(strtolower($type)); - - // Do a replace into ensuring that this client always only has a single row - $sql = "REPLACE INTO `now_playing` (`id`,`object_id`,`object_type`, `user`, `expire`)" . - " VALUES ('$session_id','$oid','$object_type', '$uid', '$time')"; - $db_result = Dba::write($sql); - - } // insert_now_playing - - /** - * clear_now_playing - * There really isn't anywhere else for this function, shouldn't have deleted it in the first - * place - */ - public static function clear_now_playing() { - - $sql = "TRUNCATE `now_playing`"; - $db_results = Dba::write($sql); - - return true; - - } // clear_now_playing - - /** - * get_now_playing - * This returns the now playing information - */ - public static function get_now_playing($filter=NULL) { - - $sql = "SELECT `session_stream`.`agent`,`now_playing`.* " . - "FROM `now_playing` " . - "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " . - "ORDER BY `now_playing`.`expire` DESC"; - $db_results = Dba::read($sql); - - $results = array(); - - while ($row = Dba::fetch_assoc($db_results)) { - $type = $row['object_type']; - $media = new $type($row['object_id']); - $media->format(); - $client = new User($row['user']); - $results[] = array('media'=>$media,'client'=>$client,'agent'=>$row['agent'],'expire'=>$row['expire']); - } // end while - - return $results; - - } // get_now_playing - - /** - * check_lock_media - * This checks to see if the media is already being played, if it is then it returns false - * else return true - */ - public static function check_lock_media($media_id,$type) { - - $media_id = Dba::escape($media_id); - $type = Dba::escape($type); - - $sql = "SELECT `object_id` FROM `now_playing` WHERE `object_id`='$media_id' AND `object_type`='$type'"; - $db_results = Dba::read($sql); - - if (Dba::num_rows($db_results)) { - debug_event('Stream','Unable to play media currently locked by another user','3'); - return false; - } - - return true; - - } // check_lock_media - - /** - * auto_init - * This is called on class load it sets the session - */ - public static function _auto_init() { - - // Generate the session ID - self::$session = md5(uniqid(rand(), true)); - - } // auto_init - - /** - * run_playlist_method - * This takes care of the different types of 'playlist methods'. The - * reason this is here is because it deals with streaming rather than - * playlist mojo. If something needs to happen this will echo the - * javascript required to cause a reload of the iframe. - */ - public static function run_playlist_method() { - - // If this wasn't ajax included run away - if (!defined('AJAX_INCLUDE')) { return false; } - - // If we're doin the flash magic then run away as well - if (Config::get('play_type') == 'xspf_player') { return false; } - - switch (Config::get('playlist_method')) { - default: - case 'clear': - case 'default': - return true; - break; - case 'send': - $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket'; - break; - case 'send_clear': - $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket&playlist_method=clear'; - break; - } // end switch on method - - // Load our javascript - echo ""; - - } // run_playlist_method - - /** - * get_base_url - * This returns the base requirements for a stream URL this does not include anything after the index.php?sid=???? - */ - public static function get_base_url() { - - if (Config::get('require_session')) { - $session_string = 'ssid=' . Stream::get_session() . '&'; - } - - $web_path = Config::get('web_path'); - - if (Config::get('force_http_play') OR !empty(self::$force_http)) { - $web_path = str_replace("https://", "http://",$web_path); - } - if (Config::get('http_port') != '80') { - if (preg_match("/:(\d+)/",$web_path,$matches)) { - $web_path = str_replace(':' . $matches['1'],':' . Config::get('http_port'),$web_path); - } - else { - $web_path = str_replace($_SERVER['HTTP_HOST'],$_SERVER['HTTP_HOST'] . ':' . Config::get('http_port'),$web_path); - } - } - - $url = $web_path . "/play/index.php?$session_string"; - - return $url; - - } // get_base_url + $time = intval(time()+$length); + $session_id = Dba::escape($sid); + $object_type = Dba::escape(strtolower($type)); + + // Do a replace into ensuring that this client always only has a single row + $sql = "REPLACE INTO `now_playing` (`id`,`object_id`,`object_type`, `user`, `expire`)" . + " VALUES ('$session_id','$oid','$object_type', '$uid', '$time')"; + $db_result = Dba::write($sql); + + } // insert_now_playing + + /** + * clear_now_playing + * There really isn't anywhere else for this function, shouldn't have deleted it in the first + * place + */ + public static function clear_now_playing() { + + $sql = "TRUNCATE `now_playing`"; + $db_results = Dba::write($sql); + + return true; + + } // clear_now_playing + + /** + * get_now_playing + * This returns the now playing information + */ + public static function get_now_playing($filter=NULL) { + + $sql = "SELECT `session_stream`.`agent`,`now_playing`.* " . + "FROM `now_playing` " . + "LEFT JOIN `session_stream` ON `session_stream`.`id`=`now_playing`.`id` " . + "ORDER BY `now_playing`.`expire` DESC"; + $db_results = Dba::read($sql); + + $results = array(); + + while ($row = Dba::fetch_assoc($db_results)) { + $type = $row['object_type']; + $media = new $type($row['object_id']); + $media->format(); + $client = new User($row['user']); + $results[] = array('media'=>$media,'client'=>$client,'agent'=>$row['agent'],'expire'=>$row['expire']); + } // end while + + return $results; + + } // get_now_playing + + /** + * check_lock_media + * This checks to see if the media is already being played, if it is then it returns false + * else return true + */ + public static function check_lock_media($media_id,$type) { + + $media_id = Dba::escape($media_id); + $type = Dba::escape($type); + + $sql = "SELECT `object_id` FROM `now_playing` WHERE `object_id`='$media_id' AND `object_type`='$type'"; + $db_results = Dba::read($sql); + + if (Dba::num_rows($db_results)) { + debug_event('Stream','Unable to play media currently locked by another user','3'); + return false; + } + + return true; + + } // check_lock_media + + /** + * auto_init + * This is called on class load it sets the session + */ + public static function _auto_init() { + + // Generate the session ID + self::$session = md5(uniqid(rand(), true)); + + } // auto_init + + /** + * run_playlist_method + * This takes care of the different types of 'playlist methods'. The + * reason this is here is because it deals with streaming rather than + * playlist mojo. If something needs to happen this will echo the + * javascript required to cause a reload of the iframe. + */ + public static function run_playlist_method() { + + // If this wasn't ajax included run away + if (!defined('AJAX_INCLUDE')) { return false; } + + // If we're doin the flash magic then run away as well + if (Config::get('play_type') == 'xspf_player') { return false; } + + switch (Config::get('playlist_method')) { + default: + case 'clear': + case 'default': + return true; + break; + case 'send': + $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket'; + break; + case 'send_clear': + $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket&playlist_method=clear'; + break; + } // end switch on method + + // Load our javascript + echo ""; + + } // run_playlist_method + + /** + * get_base_url + * This returns the base requirements for a stream URL this does not include anything after the index.php?sid=???? + */ + public static function get_base_url() { + + if (Config::get('require_session')) { + $session_string = 'ssid=' . Stream::get_session() . '&'; + } + + $web_path = Config::get('web_path'); + + if (Config::get('force_http_play') OR !empty(self::$force_http)) { + $web_path = str_replace("https://", "http://",$web_path); + } + if (Config::get('http_port') != '80') { + if (preg_match("/:(\d+)/",$web_path,$matches)) { + $web_path = str_replace(':' . $matches['1'],':' . Config::get('http_port'),$web_path); + } + else { + $web_path = str_replace($_SERVER['HTTP_HOST'],$_SERVER['HTTP_HOST'] . ':' . Config::get('http_port'),$web_path); + } + } + + $url = $web_path . "/play/index.php?$session_string"; + + return $url; + + } // get_base_url } //end of stream class diff --git a/lib/class/stream_playlist.class.php b/lib/class/stream_playlist.class.php index 917b543cc0..6d85f8f06b 100644 --- a/lib/class/stream_playlist.class.php +++ b/lib/class/stream_playlist.class.php @@ -1,5 +1,5 @@ id = Dba::escape(Stream::get_session()); - - if (!Stream::session_exists($this->id)) { - debug_event('stream_playlist', 'Stream::session_exists failed', 2); - return false; - } - - $this->user = intval($GLOBALS['user']->id); - - $sql = "SELECT * FROM `stream_playlist` WHERE `sid`='" . - $this->id . "' ORDER BY `id`"; - - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - $this->urls[] = new Stream_URL($row); - } - - return true; - } - - private function _add_url($url) { - $this->urls[] = $url; - - $sql = 'INSERT INTO `stream_playlist` '; - - $fields[] = '`sid`'; - $values[] = Dba::escape($this->id); - - foreach ($url->properties as $field) { - if ($url->$field) { - $fields[] = '`' . $field . '`'; - $values[] = Dba::escape($url->$field); - } - } - $sql .= '(' . implode(', ', $fields) . ') '; - $sql .= "VALUES('" . implode("', '", $values) . "')"; - - return Dba::write($sql); - } - - public static function gc() { - $sql = 'DELETE FROM `stream_playlist` ' . - 'USING `stream_playlist` LEFT JOIN `session_stream` ' . - 'ON `session_stream`.`id`=`stream_playlist`.`sid` ' . - 'WHERE `session_stream`.`id` IS NULL'; - return Dba::write($sql); - } - - /** - * _media_to_urlarray - * Formats the URL and media information and adds it to the object - */ - private static function _media_to_urlarray($media) { - $urls = array(); - foreach($media as $medium) { - debug_event('stream_playlist', 'Adding ' . json_encode($media), 5); - $url = array(); - - $type = $medium['object_type']; - $array['type'] = $type; - - $object = new $type($medium['object_id']); - $object->format(); - //FIXME: play_url shouldn't be static - $url['url'] = $type::play_url($object->id); - - // Set a default which can be overridden - $url['author'] = 'Ampache'; - $url['time'] = $object->time; - switch($type) { - case 'song': - $url['title'] = $object->title; - $url['author'] = $object->f_artist_full; - $url['info_url'] = $object->f_link; - $url['image_url'] = Art::url($object->album, 'album'); - $url['album'] = $object->f_album_full; - break; - case 'video': - $url['title'] = 'Video - ' . $object->title; - $url['author'] = $object->f_artist_full; - break; - case 'radio': - $url['title'] = 'Radio - ' . $object->name . - ' [' . $object->frequency . - '] (' . $object->site_url . ')'; - break; - case 'random': - $url['title'] = 'Random URL'; - break; - default: - $url['title'] = 'URL-Add'; - $url['time'] = -1; - break; - } - - $urls[] = new Stream_URL($url); - } - - return $urls; - } - - public function generate_playlist($type, $redirect = false) { - - if (!count($this->urls)) { - debug_event('stream_playlist', 'Error: Empty URL array for ' . $this->id, 2); - return false; - } - - debug_event('stream_playlist', 'generating a ' . $type, 5); - - $ext = $type; - switch($type) { - case 'democratic': - case 'localplay': - case 'xspf_player': - // These are valid, but witchy - $redirect = false; - unset($ext); - break; - case 'asx': - $ct = 'video/x-ms-wmv'; - break; - case 'pls': - $ct = 'audio/x-scpls'; - break; - case 'ram': - $ct = 'audio/x-pn-realaudio ram'; - break; - case 'simple_m3u': - $ext = 'm3u'; - $ct = 'audio/x-mpegurl'; - break; - case 'xspf': - $ct = 'application/xspf+xml'; - break; - case 'm3u': - default: - // Assume M3U if the pooch is screwed - $ext = $type = 'm3u'; - $ct = 'audio/x-mpegurl'; - break; - } - - if ($redirect) { - // Our ID is the SID, so we always want to include it - Config::set('require_session', true, true); - header('Location: ' . Stream::get_base_url() . 'uid=' . scrub_out($this->user) . '&type=playlist&playlist_type=' . scrub_out($type)); - exit; - } - - if (isset($ext)) { - header('Cache-control: public'); - header('Content-Disposition: filename=ampache_playlist.' . $ext); - header('Content-Type: ' . $ct . ';'); - } - - $this->{'create_' . $type}(); - } - - /** - * add - * Adds an array of media - */ - public function add($media = array()) { - $urls = $this->_media_to_urlarray($media); - foreach ($urls as $url) { - $this->_add_url($url); - } - } - - /** - * add_urls - * Add an array of urls. This is used for things that aren't coming - * from media objects - */ - public function add_urls($urls = array()) { - - if (!is_array($urls)) { return false; } - - foreach ($urls as $url) { - $this->_add_url(new Stream_URL(array( - 'url' => $url, - 'title' => 'URL-Add', - 'author' => 'Ampache', - 'time' => '-1' - ))); - } - } - - /** - * create_simplem3u - * this creates a simple m3u without any of the extended information - */ - public function create_simple_m3u() { - - foreach ($this->urls as $url) { - echo $url->url . "\n"; - } - - } // simple_m3u - - /** - * create_m3u - * creates an m3u file, this includes the EXTINFO and as such can be - * large with very long playlsits - */ - public function create_m3u() { - - echo "#EXTM3U\n"; - - foreach ($this->urls as $url) { - echo '#EXTINF:' . $url->time, ',' . $url->author . - ' - ' . $url->title . "\n"; - echo $url->url . "\n"; - } - - } // create_m3u - - /** - * create_pls - */ - public function create_pls() { - - echo "[playlist]\n"; - echo 'NumberOfEntries=' . count($this->urls) . "\n"; - foreach ($this->urls as $url) { - $i++; - echo 'File' . $i . '='. $url->url . "\n"; - echo 'Title' . $i . '=' . $url->author . ' - ' . - $url->title . "\n"; - echo 'Length' . $i . '=' . $url->time . "\n"; - } - - echo "Version=2\n"; - } // create_pls - - /** - * create_asx - * This should really only be used if all of the content is ASF files. - */ - public function create_asx() { - - echo '' . "\n"; - echo "Ampache ASX Playlist"; - - foreach ($this->urls as $url) { - echo "\n"; - echo '' . $url->title . "\n"; - echo '' . $url->author . "\n"; - echo "\t\t" . '' . "\n"; - echo "\t\t" . '' . "\n"; - echo "\t\t" . '' . "\n"; - echo "\t\t" . '' . "\n"; - echo '' . "\n"; - echo "\n"; - } - - echo "\n"; - - } // create_asx - - /** - * create_xspf - */ - public function create_xspf() { - - foreach ($this->urls as $url) { - $xml = array(); - - $xml['track'] = array( - 'title' => $url->title, - 'creator' => $url->author, - 'duration' => $url->time * 1000, - 'location' => $url->url, - 'identifier' => $url->url - ); - if ($url->type == 'video') { - $xml['track']['meta'] = - array( - 'attribute' => 'rel="provider"', - 'value' => 'video' - ); - } - if ($url->info_url) { - $xml['track']['info'] = $url->info_url; - } - if ($url->image_url) { - $xml['track']['image'] = $url->image_url; - } - if ($url->album) { - $xml['track']['album'] = $url->album; - } - - $result .= XML_Data::keyed_array($xml, true); - - } // end foreach - - XML_Data::set_type('xspf'); - echo XML_Data::header(); - echo $result; - echo XML_Data::footer(); - - } // create_xspf - - /** - * create_xspf_player - * Due to the fact that this is an integrated player (flash) we actually - * have to do a little 'cheating' to make this work. - * We are going to take advantage of tmp_playlists to do all of this - * hotness - */ - public function create_xspf_player() { - debug_event('stream_playlist', 'Creating XSPF player', 5); - /* Build the extra info we need to have it pass */ - $play_info = "?action=show&tmpplaylist_id=" . $GLOBALS['user']->playlist->id; - - // start ugly evil javascript code - //FIXME: This needs to go in a template, here for now though - //FIXME: This preference doesn't even exists, we'll eventually - //FIXME: just make it the default - if (Config::get('embed_xspf') == 1 ){ - header("Location: ".Config::get('web_path')."/index.php?xspf&play_info=".$GLOBALS['user']->playlist->id); - } - else { - echo "\n"; - echo "" . Config::get('site_title') . "\n"; - echo "\n"; - echo "\n"; - - echo "\n"; - echo "\n"; - echo "\n"; - } - } // create_xspf_player - - /** - * create_localplay - * This calls the Localplay API to add the URLs and then start playback - */ - public function create_localplay() { - - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); - foreach ($this->urls as $url) { - $localplay->add_url($url); - } - - $localplay->play(); - - } // create_localplay - - /** - * create_democratic - * This 'votes' on the songs it inserts them into - * a tmp_playlist with user of -1 (System) - */ - public function create_democratic() { - - $democratic = Democratic::get_current_playlist(); - $democratic->set_parent(); - $democratic->add_vote($this->media); - - } // create_democratic - - /** - * create_download - * This prompts for a download of the song - */ - private function create_download() { - - // There should only be one here... - if (count($this->urls) != 1) { - debug_event('stream_playlist', 'Download called, but $urls contains ' . json_encode($this->urls), 2); - } - - // Header redirect baby! - $url = current($this->urls); - header('Location: ' . $url->url . '&action=download'); - exit; - } //create_download - - /** - * create_ram - *this functions creates a RAM file for use by Real Player - */ - public function create_ram() { - foreach ($this->urls as $url) { - echo $url->url . "\n"; - } - } // create_ram + public $id; + public $urls = array(); + public $user; + + /** + * Stream_Playlist constructor + * If an ID is passed, it should be a stream session ID. + */ + public function __construct($id = null) { + + if($id) { + Stream::set_session($id); + } + + $this->id = Dba::escape(Stream::get_session()); + + if (!Stream::session_exists($this->id)) { + debug_event('stream_playlist', 'Stream::session_exists failed', 2); + return false; + } + + $this->user = intval($GLOBALS['user']->id); + + $sql = "SELECT * FROM `stream_playlist` WHERE `sid`='" . + $this->id . "' ORDER BY `id`"; + + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + $this->urls[] = new Stream_URL($row); + } + + return true; + } + + private function _add_url($url) { + $this->urls[] = $url; + + $sql = 'INSERT INTO `stream_playlist` '; + + $fields[] = '`sid`'; + $values[] = Dba::escape($this->id); + + foreach ($url->properties as $field) { + if ($url->$field) { + $fields[] = '`' . $field . '`'; + $values[] = Dba::escape($url->$field); + } + } + $sql .= '(' . implode(', ', $fields) . ') '; + $sql .= "VALUES('" . implode("', '", $values) . "')"; + + return Dba::write($sql); + } + + public static function gc() { + $sql = 'DELETE FROM `stream_playlist` ' . + 'USING `stream_playlist` LEFT JOIN `session_stream` ' . + 'ON `session_stream`.`id`=`stream_playlist`.`sid` ' . + 'WHERE `session_stream`.`id` IS NULL'; + return Dba::write($sql); + } + + /** + * _media_to_urlarray + * Formats the URL and media information and adds it to the object + */ + private static function _media_to_urlarray($media) { + $urls = array(); + foreach($media as $medium) { + debug_event('stream_playlist', 'Adding ' . json_encode($media), 5); + $url = array(); + + $type = $medium['object_type']; + $array['type'] = $type; + + $object = new $type($medium['object_id']); + $object->format(); + //FIXME: play_url shouldn't be static + $url['url'] = $type::play_url($object->id); + + // Set a default which can be overridden + $url['author'] = 'Ampache'; + $url['time'] = $object->time; + switch($type) { + case 'song': + $url['title'] = $object->title; + $url['author'] = $object->f_artist_full; + $url['info_url'] = $object->f_link; + $url['image_url'] = Art::url($object->album, 'album'); + $url['album'] = $object->f_album_full; + break; + case 'video': + $url['title'] = 'Video - ' . $object->title; + $url['author'] = $object->f_artist_full; + break; + case 'radio': + $url['title'] = 'Radio - ' . $object->name . + ' [' . $object->frequency . + '] (' . $object->site_url . ')'; + break; + case 'random': + $url['title'] = 'Random URL'; + break; + default: + $url['title'] = 'URL-Add'; + $url['time'] = -1; + break; + } + + $urls[] = new Stream_URL($url); + } + + return $urls; + } + + public function generate_playlist($type, $redirect = false) { + + if (!count($this->urls)) { + debug_event('stream_playlist', 'Error: Empty URL array for ' . $this->id, 2); + return false; + } + + debug_event('stream_playlist', 'generating a ' . $type, 5); + + $ext = $type; + switch($type) { + case 'democratic': + case 'localplay': + case 'xspf_player': + // These are valid, but witchy + $redirect = false; + unset($ext); + break; + case 'asx': + $ct = 'video/x-ms-wmv'; + break; + case 'pls': + $ct = 'audio/x-scpls'; + break; + case 'ram': + $ct = 'audio/x-pn-realaudio ram'; + break; + case 'simple_m3u': + $ext = 'm3u'; + $ct = 'audio/x-mpegurl'; + break; + case 'xspf': + $ct = 'application/xspf+xml'; + break; + case 'm3u': + default: + // Assume M3U if the pooch is screwed + $ext = $type = 'm3u'; + $ct = 'audio/x-mpegurl'; + break; + } + + if ($redirect) { + // Our ID is the SID, so we always want to include it + Config::set('require_session', true, true); + header('Location: ' . Stream::get_base_url() . 'uid=' . scrub_out($this->user) . '&type=playlist&playlist_type=' . scrub_out($type)); + exit; + } + + if (isset($ext)) { + header('Cache-control: public'); + header('Content-Disposition: filename=ampache_playlist.' . $ext); + header('Content-Type: ' . $ct . ';'); + } + + $this->{'create_' . $type}(); + } + + /** + * add + * Adds an array of media + */ + public function add($media = array()) { + $urls = $this->_media_to_urlarray($media); + foreach ($urls as $url) { + $this->_add_url($url); + } + } + + /** + * add_urls + * Add an array of urls. This is used for things that aren't coming + * from media objects + */ + public function add_urls($urls = array()) { + + if (!is_array($urls)) { return false; } + + foreach ($urls as $url) { + $this->_add_url(new Stream_URL(array( + 'url' => $url, + 'title' => 'URL-Add', + 'author' => 'Ampache', + 'time' => '-1' + ))); + } + } + + /** + * create_simplem3u + * this creates a simple m3u without any of the extended information + */ + public function create_simple_m3u() { + + foreach ($this->urls as $url) { + echo $url->url . "\n"; + } + + } // simple_m3u + + /** + * create_m3u + * creates an m3u file, this includes the EXTINFO and as such can be + * large with very long playlsits + */ + public function create_m3u() { + + echo "#EXTM3U\n"; + + foreach ($this->urls as $url) { + echo '#EXTINF:' . $url->time, ',' . $url->author . + ' - ' . $url->title . "\n"; + echo $url->url . "\n"; + } + + } // create_m3u + + /** + * create_pls + */ + public function create_pls() { + + echo "[playlist]\n"; + echo 'NumberOfEntries=' . count($this->urls) . "\n"; + foreach ($this->urls as $url) { + $i++; + echo 'File' . $i . '='. $url->url . "\n"; + echo 'Title' . $i . '=' . $url->author . ' - ' . + $url->title . "\n"; + echo 'Length' . $i . '=' . $url->time . "\n"; + } + + echo "Version=2\n"; + } // create_pls + + /** + * create_asx + * This should really only be used if all of the content is ASF files. + */ + public function create_asx() { + + echo '' . "\n"; + echo "Ampache ASX Playlist"; + + foreach ($this->urls as $url) { + echo "\n"; + echo '' . $url->title . "\n"; + echo '' . $url->author . "\n"; + echo "\t\t" . '' . "\n"; + echo "\t\t" . '' . "\n"; + echo "\t\t" . '' . "\n"; + echo "\t\t" . '' . "\n"; + echo '' . "\n"; + echo "\n"; + } + + echo "\n"; + + } // create_asx + + /** + * create_xspf + */ + public function create_xspf() { + + foreach ($this->urls as $url) { + $xml = array(); + + $xml['track'] = array( + 'title' => $url->title, + 'creator' => $url->author, + 'duration' => $url->time * 1000, + 'location' => $url->url, + 'identifier' => $url->url + ); + if ($url->type == 'video') { + $xml['track']['meta'] = + array( + 'attribute' => 'rel="provider"', + 'value' => 'video' + ); + } + if ($url->info_url) { + $xml['track']['info'] = $url->info_url; + } + if ($url->image_url) { + $xml['track']['image'] = $url->image_url; + } + if ($url->album) { + $xml['track']['album'] = $url->album; + } + + $result .= XML_Data::keyed_array($xml, true); + + } // end foreach + + XML_Data::set_type('xspf'); + echo XML_Data::header(); + echo $result; + echo XML_Data::footer(); + + } // create_xspf + + /** + * create_xspf_player + * Due to the fact that this is an integrated player (flash) we actually + * have to do a little 'cheating' to make this work. + * We are going to take advantage of tmp_playlists to do all of this + * hotness + */ + public function create_xspf_player() { + debug_event('stream_playlist', 'Creating XSPF player', 5); + /* Build the extra info we need to have it pass */ + $play_info = "?action=show&tmpplaylist_id=" . $GLOBALS['user']->playlist->id; + + // start ugly evil javascript code + //FIXME: This needs to go in a template, here for now though + //FIXME: This preference doesn't even exists, we'll eventually + //FIXME: just make it the default + if (Config::get('embed_xspf') == 1 ){ + header("Location: ".Config::get('web_path')."/index.php?xspf&play_info=".$GLOBALS['user']->playlist->id); + } + else { + echo "\n"; + echo "" . Config::get('site_title') . "\n"; + echo "\n"; + echo "\n"; + + echo "\n"; + echo "\n"; + echo "\n"; + } + } // create_xspf_player + + /** + * create_localplay + * This calls the Localplay API to add the URLs and then start playback + */ + public function create_localplay() { + + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); + foreach ($this->urls as $url) { + $localplay->add_url($url); + } + + $localplay->play(); + + } // create_localplay + + /** + * create_democratic + * This 'votes' on the songs it inserts them into + * a tmp_playlist with user of -1 (System) + */ + public function create_democratic() { + + $democratic = Democratic::get_current_playlist(); + $democratic->set_parent(); + $democratic->add_vote($this->media); + + } // create_democratic + + /** + * create_download + * This prompts for a download of the song + */ + private function create_download() { + + // There should only be one here... + if (count($this->urls) != 1) { + debug_event('stream_playlist', 'Download called, but $urls contains ' . json_encode($this->urls), 2); + } + + // Header redirect baby! + $url = current($this->urls); + header('Location: ' . $url->url . '&action=download'); + exit; + } //create_download + + /** + * create_ram + *this functions creates a RAM file for use by Real Player + */ + public function create_ram() { + foreach ($this->urls as $url) { + echo $url->url . "\n"; + } + } // create_ram } diff --git a/lib/class/stream_url.class.php b/lib/class/stream_url.class.php index e590dd49ba..d651ca5929 100644 --- a/lib/class/stream_url.class.php +++ b/lib/class/stream_url.class.php @@ -1,5 +1,5 @@ get_info($id); + $info = $this->get_info($id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } // end foreach + foreach ($info as $key=>$value) { + $this->$key = $value; + } // end foreach - } // constructor + } // constructor - /** - * construct_from_name - * This attempts to construct the tag from a name, rather then the ID - */ - public static function construct_from_name($name) { + /** + * construct_from_name + * This attempts to construct the tag from a name, rather then the ID + */ + public static function construct_from_name($name) { - $tag_id = self::tag_exists($name); + $tag_id = self::tag_exists($name); - $tag = new Tag($tag_id); + $tag = new Tag($tag_id); - return $tag; + return $tag; - } // construct_from_name + } // construct_from_name - /** - * format - * This makes the tag presentable to the great humans that use this program, other life forms - * will just have to fend for themselves - */ - public function format($type=0,$object_id=0) { + /** + * format + * This makes the tag presentable to the great humans that use this program, other life forms + * will just have to fend for themselves + */ + public function format($type=0,$object_id=0) { - if ($type AND !self::validate_type($type)) { return false; } + if ($type AND !self::validate_type($type)) { return false; } - if ($type) { - $this->set_object($type,$object_id); - } + if ($type) { + $this->set_object($type,$object_id); + } - $size = 3 + ($this->weight-1) - ($this->count-1); - if (abs($size) > 4) { $size = 4; } - if (abs($size) < 1) { $size = 1; } + $size = 3 + ($this->weight-1) - ($this->count-1); + if (abs($size) > 4) { $size = 4; } + if (abs($size) < 1) { $size = 1; } - if ($this->owner == $GLOBALS['user']->id) { - $action = '?page=tag&action=remove_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id); - $class = "hover-remove "; - } - else { - $action = '?page=tag&action=add_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id); - $class = "hover-add "; - } + if ($this->owner == $GLOBALS['user']->id) { + $action = '?page=tag&action=remove_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id); + $class = "hover-remove "; + } + else { + $action = '?page=tag&action=add_tag&type=' . scrub_out($type) . '&tag_id=' . intval($this->id) . '&object_id=' . intval($object_id); + $class = "hover-add "; + } - $class .= 'tag_size' . $size; - $this->f_class = $class; + $class .= 'tag_size' . $size; + $this->f_class = $class; - $this->f_name = Ajax::text($action,$this->name,'modify_tag_' . $this->id . '_' . $object_id,'',$class); + $this->f_name = Ajax::text($action,$this->name,'modify_tag_' . $this->id . '_' . $object_id,'',$class); - } // format + } // format - /** - * set_object - * This associates the tag with a specified object, we try to get the - * data from the map cache, otherwise I guess we'll just have to look it - * up. - */ - public function set_object($type,$object_id) { + /** + * set_object + * This associates the tag with a specified object, we try to get the + * data from the map cache, otherwise I guess we'll just have to look it + * up. + */ + public function set_object($type,$object_id) { - if (parent::is_cached('tag_top_' . $type,$object_id)) { - $data = parent::get_from_cache('tag_top_' . $type,$object_id); - } - else { - $data = self::get_top_tags($type,$object_id); - } + if (parent::is_cached('tag_top_' . $type,$object_id)) { + $data = parent::get_from_cache('tag_top_' . $type,$object_id); + } + else { + $data = self::get_top_tags($type,$object_id); + } - // If nothing is found, then go ahead and return false - if (!is_array($data) OR !count($data)) { return false; } + // If nothing is found, then go ahead and return false + if (!is_array($data) OR !count($data)) { return false; } - $this->weight = count($data[$this->id]['users']); + $this->weight = count($data[$this->id]['users']); - if (in_array($GLOBALS['user']->id,$data[$this->id]['users'])) { - $this->owner = $GLOBALS['user']->id; - } + if (in_array($GLOBALS['user']->id,$data[$this->id]['users'])) { + $this->owner = $GLOBALS['user']->id; + } - $this->count = count($data); + $this->count = count($data); - } // set_object + } // set_object - /** - * build_cache - * This takes an array of object ids and caches all of their information - * in a single query, cuts down on the connections - */ - public static function build_cache($ids) { + /** + * build_cache + * This takes an array of object ids and caches all of their information + * in a single query, cuts down on the connections + */ + public static function build_cache($ids) { - if (!is_array($ids) OR !count($ids)) { return false; } + if (!is_array($ids) OR !count($ids)) { return false; } - $idlist = '(' . implode(',',$ids) . ')'; + $idlist = '(' . implode(',',$ids) . ')'; - $sql = "SELECT * FROM `tag` WHERE `id` IN $idlist"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `tag` WHERE `id` IN $idlist"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('tag',$row['id'],$row); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('tag',$row['id'],$row); + } - return true; - } // build_cache + return true; + } // build_cache - /** - * build_map_cache - * This builds a cache of the mappings for the specified object, no limit is given - */ - public static function build_map_cache($type,$ids) { + /** + * build_map_cache + * This builds a cache of the mappings for the specified object, no limit is given + */ + public static function build_map_cache($type,$ids) { - if (!is_array($ids) OR !count($ids)) { return false; } + if (!is_array($ids) OR !count($ids)) { return false; } - $type = self::validate_type($type); - $idlist = '(' . implode(',',$ids) . ')'; + $type = self::validate_type($type); + $idlist = '(' . implode(',',$ids) . ')'; - $sql = "SELECT `tag_map`.`id`,`tag_map`.`tag_id`,`tag_map`.`object_id`,`tag_map`.`user` FROM `tag_map` " . - "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id` IN $idlist "; - $db_results = Dba::read($sql); + $sql = "SELECT `tag_map`.`id`,`tag_map`.`tag_id`,`tag_map`.`object_id`,`tag_map`.`user` FROM `tag_map` " . + "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id` IN $idlist "; + $db_results = Dba::read($sql); - $tags = array(); + $tags = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $tags[$row['object_id']][$row['tag_id']]['users'][] = $row['user']; - $tag_map[$row['object_id']] = array('id'=>$row['id'],'tag_id'=>$row['tag_id'],'user'=>$row['user'],'object_type'=>$type,'object_id'=>$row['object_id']); - } + while ($row = Dba::fetch_assoc($db_results)) { + $tags[$row['object_id']][$row['tag_id']]['users'][] = $row['user']; + $tag_map[$row['object_id']] = array('id'=>$row['id'],'tag_id'=>$row['tag_id'],'user'=>$row['user'],'object_type'=>$type,'object_id'=>$row['object_id']); + } - // Run through our original ids as we also want to cache NULL - // results - foreach ($ids as $id) { - if (!isset($tags[$id])) { - $tags[$id] = null; - $tag_map[$id] = null; - } - parent::add_to_cache('tag_top_' . $type, $id, $tags[$id]); - parent::add_to_cache('tag_map_' . $type, $id, $tag_map[$id]); - } + // Run through our original ids as we also want to cache NULL + // results + foreach ($ids as $id) { + if (!isset($tags[$id])) { + $tags[$id] = null; + $tag_map[$id] = null; + } + parent::add_to_cache('tag_top_' . $type, $id, $tags[$id]); + parent::add_to_cache('tag_map_' . $type, $id, $tag_map[$id]); + } - return true; + return true; - } // build_map_cache + } // build_map_cache - /** - * add - * This is a wrapper function, it figures out what we need to add, be it a tag - * and map, or just the mapping - */ - public static function add($type,$id,$value,$user=false) { + /** + * add + * This is a wrapper function, it figures out what we need to add, be it a tag + * and map, or just the mapping + */ + public static function add($type,$id,$value,$user=false) { - // Validate the tag type - if (!self::validate_type($type)) { return false; } + // Validate the tag type + if (!self::validate_type($type)) { return false; } - if (!is_numeric($id)) { return false; } + if (!is_numeric($id)) { return false; } - $cleaned_value = self::clean_tag($value); + $cleaned_value = self::clean_tag($value); - if (!strlen($cleaned_value)) { return false; } + if (!strlen($cleaned_value)) { return false; } - $uid = ($user === false) ? intval($user) : intval($GLOBALS['user']->id); + $uid = ($user === false) ? intval($user) : intval($GLOBALS['user']->id); - // Check and see if the tag exists, if not create it, we need the tag id from this - if (!$tag_id = self::tag_exists($cleaned_value)) { - $tag_id = self::add_tag($cleaned_value); - } + // Check and see if the tag exists, if not create it, we need the tag id from this + if (!$tag_id = self::tag_exists($cleaned_value)) { + $tag_id = self::add_tag($cleaned_value); + } - if (!$tag_id) { - debug_event('Error','Error unable to create tag value:' . $cleaned_value . ' unknown error','1'); - return false; - } + if (!$tag_id) { + debug_event('Error','Error unable to create tag value:' . $cleaned_value . ' unknown error','1'); + return false; + } - // We've got the tag id, let's see if it's already got a map, if not then create the map and return the value - if (!$map_id = self::tag_map_exists($type,$id,$tag_id,$user)) { - $map_id = self::add_tag_map($type,$id,$tag_id,$user); - } + // We've got the tag id, let's see if it's already got a map, if not then create the map and return the value + if (!$map_id = self::tag_map_exists($type,$id,$tag_id,$user)) { + $map_id = self::add_tag_map($type,$id,$tag_id,$user); + } - return $map_id; + return $map_id; - } // add + } // add - /** - * add_tag - * This function adds a new tag, for now we're going to limit the tagging a bit - */ - public static function add_tag($value) { + /** + * add_tag + * This function adds a new tag, for now we're going to limit the tagging a bit + */ + public static function add_tag($value) { - // Clean it up and make it tagish - $value = self::clean_tag($value); + // Clean it up and make it tagish + $value = self::clean_tag($value); - if (!strlen($value)) { return false; } + if (!strlen($value)) { return false; } - $value = Dba::escape($value); + $value = Dba::escape($value); - $sql = "REPLACE INTO `tag` SET `name`='$value'"; - $db_results = Dba::write($sql); - $insert_id = Dba::insert_id(); + $sql = "REPLACE INTO `tag` SET `name`='$value'"; + $db_results = Dba::write($sql); + $insert_id = Dba::insert_id(); - parent::add_to_cache('tag_name',$value,$insert_id); + parent::add_to_cache('tag_name',$value,$insert_id); - return $insert_id; + return $insert_id; - } // add_tag + } // add_tag - /** - * add_tag_map - * This adds a specific tag to the map for specified object - */ - public static function add_tag_map($type,$object_id,$tag_id,$user='') { + /** + * add_tag_map + * This adds a specific tag to the map for specified object + */ + public static function add_tag_map($type,$object_id,$tag_id,$user='') { - $uid = ($user == '') ? intval($GLOBALS['user']->id) : intval($user); - $tag_id = intval($tag_id); - if (!self::validate_type($type)) { return false; } - $id = intval($object_id); + $uid = ($user == '') ? intval($GLOBALS['user']->id) : intval($user); + $tag_id = intval($tag_id); + if (!self::validate_type($type)) { return false; } + $id = intval($object_id); - if (!$tag_id || !$id) { return false; } + if (!$tag_id || !$id) { return false; } - $sql = "INSERT INTO `tag_map` (`tag_id`,`user`,`object_type`,`object_id`) " . - "VALUES ('$tag_id','$uid','$type','$id')"; - $db_results = Dba::write($sql); - $insert_id = Dba::insert_id(); + $sql = "INSERT INTO `tag_map` (`tag_id`,`user`,`object_type`,`object_id`) " . + "VALUES ('$tag_id','$uid','$type','$id')"; + $db_results = Dba::write($sql); + $insert_id = Dba::insert_id(); - parent::add_to_cache('tag_map_' . $type,$insert_id,array('tag_id'=>$tag_id,'user'=>$uid,'object_type'=>$type,'object_id'=>$id)); + parent::add_to_cache('tag_map_' . $type,$insert_id,array('tag_id'=>$tag_id,'user'=>$uid,'object_type'=>$type,'object_id'=>$id)); - return $insert_id; + return $insert_id; - } // add_tag_map + } // add_tag_map - /** - * gc - * - * This cleans out tag_maps that are obsolete and then removes tags that - * have no maps. - */ - public static function gc() { - $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `song` ON `song`.`id`=`tag_map`.`object_id` " . - "WHERE `tag_map`.`object_type`='song' AND `song`.`id` IS NULL"; - $db_results = Dba::write($sql); + /** + * gc + * + * This cleans out tag_maps that are obsolete and then removes tags that + * have no maps. + */ + public static function gc() { + $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `song` ON `song`.`id`=`tag_map`.`object_id` " . + "WHERE `tag_map`.`object_type`='song' AND `song`.`id` IS NULL"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `album` ON `album`.`id`=`tag_map`.`object_id` " . - "WHERE `tag_map`.`object_type`='album' AND `album`.`id` IS NULL"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `album` ON `album`.`id`=`tag_map`.`object_id` " . + "WHERE `tag_map`.`object_type`='album' AND `album`.`id` IS NULL"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `artist` ON `artist`.`id`=`tag_map`.`object_id` " . - "WHERE `tag_map`.`object_type`='artist' AND `artist`.`id` IS NULL"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `artist` ON `artist`.`id`=`tag_map`.`object_id` " . + "WHERE `tag_map`.`object_type`='artist' AND `artist`.`id` IS NULL"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `video` ON `video`.`id`=`tag_map`.`object_id` " . - "WHERE `tag_map`.`object_type`='video' AND `video`.`id` IS NULL"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tag_map` USING `tag_map` LEFT JOIN `video` ON `video`.`id`=`tag_map`.`object_id` " . + "WHERE `tag_map`.`object_type`='video' AND `video`.`id` IS NULL"; + $db_results = Dba::write($sql); - // Now nuke the tags themselves - $sql = "DELETE FROM `tag` USING `tag` LEFT JOIN `tag_map` ON `tag`.`id`=`tag_map`.`tag_id` " . - "WHERE `tag_map`.`id` IS NULL"; - $db_results = Dba::write($sql); - } + // Now nuke the tags themselves + $sql = "DELETE FROM `tag` USING `tag` LEFT JOIN `tag_map` ON `tag`.`id`=`tag_map`.`tag_id` " . + "WHERE `tag_map`.`id` IS NULL"; + $db_results = Dba::write($sql); + } - /** - * tag_exists - * This checks to see if a tag exists, this has nothing to do with objects or maps - */ - public static function tag_exists($value) { + /** + * tag_exists + * This checks to see if a tag exists, this has nothing to do with objects or maps + */ + public static function tag_exists($value) { - if (parent::is_cached('tag_name',$value)) { - return parent::get_from_cache('tag_name',$value); - } + if (parent::is_cached('tag_name',$value)) { + return parent::get_from_cache('tag_name',$value); + } - $value = Dba::escape($value); - $sql = "SELECT * FROM `tag` WHERE `name`='$value'"; - $db_results = Dba::read($sql); + $value = Dba::escape($value); + $sql = "SELECT * FROM `tag` WHERE `name`='$value'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - parent::add_to_cache('tag_name',$results['name'],$results['id']); + parent::add_to_cache('tag_name',$results['name'],$results['id']); - return $results['id']; + return $results['id']; - } // tag_exists + } // tag_exists - /** - * tag_map_exists - * This looks to see if the current mapping of the current object of the current tag of the current - * user exists, lots of currents... taste good in scones. - */ - public static function tag_map_exists($type,$object_id,$tag_id,$user) { + /** + * tag_map_exists + * This looks to see if the current mapping of the current object of the current tag of the current + * user exists, lots of currents... taste good in scones. + */ + public static function tag_map_exists($type,$object_id,$tag_id,$user) { - if (!self::validate_type($type)) { return false; } + if (!self::validate_type($type)) { return false; } - if (parent::is_cached('tag_map_' . $type,$object_id)) { - $data = parent::get_from_cache('tag_map_' . $type,$object_id); - return $data['id']; - } + if (parent::is_cached('tag_map_' . $type,$object_id)) { + $data = parent::get_from_cache('tag_map_' . $type,$object_id); + return $data['id']; + } - $object_id = Dba::escape($object_id); - $tag_id = Dba::escape($tag_id); - $user = Dba::escape($user); - $type = Dba::escape($type); + $object_id = Dba::escape($object_id); + $tag_id = Dba::escape($tag_id); + $user = Dba::escape($user); + $type = Dba::escape($type); - $sql = "SELECT * FROM `tag_map` WHERE `tag_id`='$tag_id' AND `user`='$user' AND `object_id`='$object_id' AND `object_type`='$type'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `tag_map` WHERE `tag_id`='$tag_id' AND `user`='$user' AND `object_id`='$object_id' AND `object_type`='$type'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - parent::add_to_cache('tag_map_' . $type,$results['id'],$results); + parent::add_to_cache('tag_map_' . $type,$results['id'],$results); - return $results['id']; + return $results['id']; - } // tag_map_exists + } // tag_map_exists - /** - * get_top_tags - * This gets the top tags for the specified object using limit - */ - public static function get_top_tags($type, $object_id, $limit = 10) { + /** + * get_top_tags + * This gets the top tags for the specified object using limit + */ + public static function get_top_tags($type, $object_id, $limit = 10) { - if (!self::validate_type($type)) { return false; } + if (!self::validate_type($type)) { return false; } - if (parent::is_cached('tag_top_' . $type,$object_id)) { - return parent::get_from_cache('tag_top_' . $type,$object_id); - } + if (parent::is_cached('tag_top_' . $type,$object_id)) { + return parent::get_from_cache('tag_top_' . $type,$object_id); + } - $object_id = intval($object_id); - $limit = intval($limit); + $object_id = intval($object_id); + $limit = intval($limit); - $sql = "SELECT `tag_id`, `user` FROM `tag_map` " . - "WHERE `object_type`='$type' AND `object_id`='$object_id' " . - "LIMIT $limit"; - $db_results = Dba::read($sql); + $sql = "SELECT `tag_id`, `user` FROM `tag_map` " . + "WHERE `object_type`='$type' AND `object_id`='$object_id' " . + "LIMIT $limit"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[$row['tag_id']]['users'][] = $row['user']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[$row['tag_id']]['users'][] = $row['user']; + } - parent::add_to_cache('tag_top_' . $type,$object_id,$results); + parent::add_to_cache('tag_top_' . $type,$object_id,$results); - return $results; + return $results; - } // get_top_tags + } // get_top_tags - /** - * get_object_tags - * Display all tags that apply to maching target type of the specified id - * UNUSED - */ - public static function get_object_tags($type, $id) { + /** + * get_object_tags + * Display all tags that apply to maching target type of the specified id + * UNUSED + */ + public static function get_object_tags($type, $id) { - if (!self::validate_type($type)) { return array(); } + if (!self::validate_type($type)) { return array(); } - $id = Dba::escape($id); + $id = Dba::escape($id); - $sql = "SELECT `tag_map`.`id`, `tag`.`name`, `tag_map`.`user` FROM `tag` " . - "LEFT JOIN `tag_map` ON `tag_map`.`tag_id`=`tag`.`id` " . - "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id`='$id'"; + $sql = "SELECT `tag_map`.`id`, `tag`.`name`, `tag_map`.`user` FROM `tag` " . + "LEFT JOIN `tag_map` ON `tag_map`.`tag_id`=`tag`.`id` " . + "WHERE `tag_map`.`object_type`='$type' AND `tag_map`.`object_id`='$id'"; - $results = array(); - $db_results = Dba::read($sql); + $results = array(); + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row; + } - return $results; + return $results; - } // get_object_tags + } // get_object_tags - /** - * get_tag_objects - * This gets the objects from a specified tag and returns an array of object ids, nothing more - */ - public static function get_tag_objects($type,$tag_id) { + /** + * get_tag_objects + * This gets the objects from a specified tag and returns an array of object ids, nothing more + */ + public static function get_tag_objects($type,$tag_id) { - if (!self::validate_type($type)) { return array(); } + if (!self::validate_type($type)) { return array(); } - $tag_id = Dba::escape($tag_id); + $tag_id = Dba::escape($tag_id); - $sql = "SELECT DISTINCT `tag_map`.`object_id` FROM `tag_map` " . - "WHERE `tag_map`.`tag_id`='$tag_id' AND `tag_map`.`object_type`='$type'"; - $db_results = Dba::read($sql); + $sql = "SELECT DISTINCT `tag_map`.`object_id` FROM `tag_map` " . + "WHERE `tag_map`.`tag_id`='$tag_id' AND `tag_map`.`object_type`='$type'"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['object_id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['object_id']; + } - return $results; + return $results; - } // get_tag_objects + } // get_tag_objects - /** - * get_tags - * This is a non-object non type depedent function that just returns tags - * we've got, it can take filters (this is used by the tag cloud) - */ - public static function get_tags($limit,$filters=array()) { + /** + * get_tags + * This is a non-object non type depedent function that just returns tags + * we've got, it can take filters (this is used by the tag cloud) + */ + public static function get_tags($limit,$filters=array()) { - $sql = "SELECT `tag_map`.`tag_id`,COUNT(`tag_map`.`object_id`) AS `count` " . - "FROM `tag_map` " . - "LEFT JOIN `tag` ON `tag`.`id`=`tag_map`.`tag_id` " . - "GROUP BY `tag`.`name` ORDER BY `count` DESC " . - "LIMIT $limit"; - $db_results = Dba::read($sql); + $sql = "SELECT `tag_map`.`tag_id`,COUNT(`tag_map`.`object_id`) AS `count` " . + "FROM `tag_map` " . + "LEFT JOIN `tag` ON `tag`.`id`=`tag_map`.`tag_id` " . + "GROUP BY `tag`.`name` ORDER BY `count` DESC " . + "LIMIT $limit"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - if ($row['count'] > $top) { $top = $row['count']; } - $results[$row['tag_id']] = array('id'=>$row['tag_id'],'count'=>$row['count']); - $count+= $row['count']; - } + while ($row = Dba::fetch_assoc($db_results)) { + if ($row['count'] > $top) { $top = $row['count']; } + $results[$row['tag_id']] = array('id'=>$row['tag_id'],'count'=>$row['count']); + $count+= $row['count']; + } - // Do something with this - $min = $row['count']; + // Do something with this + $min = $row['count']; - return $results; + return $results; - } // get_tags + } // get_tags - /** - * get_display - * This returns a human formated version of the tags that we are given - * it also takes a type so that it knows how to return it, this is used - * by the formating functions of the different objects - */ - public static function get_display($tags,$element_id,$type='song') { + /** + * get_display + * This returns a human formated version of the tags that we are given + * it also takes a type so that it knows how to return it, this is used + * by the formating functions of the different objects + */ + public static function get_display($tags,$element_id,$type='song') { - if (!is_array($tags)) { return ''; } + if (!is_array($tags)) { return ''; } - $results = ''; + $results = ''; - // Itterate through the tags, format them according to type and element id - foreach ($tags as $tag_id=>$value) { - $tag = new Tag($tag_id); - $tag->format($type,$element_id); - $results .= $tag->f_name . ', '; - } + // Itterate through the tags, format them according to type and element id + foreach ($tags as $tag_id=>$value) { + $tag = new Tag($tag_id); + $tag->format($type,$element_id); + $results .= $tag->f_name . ', '; + } - $results = rtrim($results,', '); + $results = rtrim($results,', '); - return $results; + return $results; - } // get_display + } // get_display - /** - * count - * This returns the count for the all objects associated with this tag - * If a type is specific only counts for said type are returned - */ - public function count($type='') { + /** + * count + * This returns the count for the all objects associated with this tag + * If a type is specific only counts for said type are returned + */ + public function count($type='') { - if ($type) { - $filter_sql = " AND `object_type`='" . Dba::escape($type) . "'"; - } + if ($type) { + $filter_sql = " AND `object_type`='" . Dba::escape($type) . "'"; + } - $results = array(); + $results = array(); - $sql = "SELECT COUNT(`id`) AS `count`,`object_type` FROM `tag_map` WHERE `tag_id`='" . Dba::escape($this->id) . "'" . $filter_sql . " GROUP BY `object_type`"; - $db_results = Dba::read($sql); + $sql = "SELECT COUNT(`id`) AS `count`,`object_type` FROM `tag_map` WHERE `tag_id`='" . Dba::escape($this->id) . "'" . $filter_sql . " GROUP BY `object_type`"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[$row['object_type']] = $row['count']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[$row['object_type']] = $row['count']; + } - return $results; + return $results; - } // count + } // count - /** - * filter_with_prefs - * This filters the tags based on the users preference - */ - public static function filter_with_prefs($l) { + /** + * filter_with_prefs + * This filters the tags based on the users preference + */ + public static function filter_with_prefs($l) { - $colors = array('#0000FF', - '#00FF00', '#FFFF00', '#00FFFF','#FF00FF','#FF0000'); - $prefs = 'tag company'; -// $prefs = Config::get('tags_userlist'); + $colors = array('#0000FF', + '#00FF00', '#FFFF00', '#00FFFF','#FF00FF','#FF0000'); + $prefs = 'tag company'; +// $prefs = Config::get('tags_userlist'); - $ulist = explode(' ', $prefs); - $req = ''; + $ulist = explode(' ', $prefs); + $req = ''; - foreach($ulist as $i) { - $req .= "'" . Dba::escape($i) . "',"; - } - $req = rtrim($req, ','); + foreach($ulist as $i) { + $req .= "'" . Dba::escape($i) . "',"; + } + $req = rtrim($req, ','); - $sql = 'SELECT `id`,`username` FROM `user` WHERE '; + $sql = 'SELECT `id`,`username` FROM `user` WHERE '; - if ($prefs=='all') { - $sql .= '1'; - } - else { - $sql .= 'username in ('.$req.')'; - } + if ($prefs=='all') { + $sql .= '1'; + } + else { + $sql .= 'username in ('.$req.')'; + } - $db_results = Dba::read($sql); + $db_results = Dba::read($sql); - $uids=array(); - $usernames = array(); - $p = 0; - while ($r = Dba::fetch_assoc($db_results)) { - $usernames[$r['id']] = $r['username']; - $uids[$r['id']] = $colors[$p]; - $p++; - if ($p == sizeof($colors)) { - $p = 0; - } - } + $uids=array(); + $usernames = array(); + $p = 0; + while ($r = Dba::fetch_assoc($db_results)) { + $usernames[$r['id']] = $r['username']; + $uids[$r['id']] = $colors[$p]; + $p++; + if ($p == sizeof($colors)) { + $p = 0; + } + } - $res = array(); + $res = array(); - foreach ($l as $i) { - if ($GLOBALS['user']->id == $i['user']) { - $res[] = $i; - } - elseif (isset($uids[$i['user']])) { - $i['color'] = $uids[$i['user']]; - $i['username'] = $usernames[$i['user']]; - $res[] = $i; - } - } + foreach ($l as $i) { + if ($GLOBALS['user']->id == $i['user']) { + $res[] = $i; + } + elseif (isset($uids[$i['user']])) { + $i['color'] = $uids[$i['user']]; + $i['username'] = $usernames[$i['user']]; + $res[] = $i; + } + } - return $res; + return $res; - } // filter_with_prefs + } // filter_with_prefs - /** - * remove_map - * This will only remove tag maps for the current user - */ - public function remove_map($type,$object_id) { + /** + * remove_map + * This will only remove tag maps for the current user + */ + public function remove_map($type,$object_id) { - if (!self::validate_type($type)) { return false; } + if (!self::validate_type($type)) { return false; } - $type = Dba::escape($type); - $tag_id = Dba::escape($this->id); - $object_id = Dba::escape($object_id); - $user_id = Dba::escape($GLOBALS['user']->id); + $type = Dba::escape($type); + $tag_id = Dba::escape($this->id); + $object_id = Dba::escape($object_id); + $user_id = Dba::escape($GLOBALS['user']->id); - $sql = "DELETE FROM `tag_map` WHERE `tag_id`='$tag_id' AND `object_type`='$type' AND `object_id`='$object_id' AND `user`='$user_id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tag_map` WHERE `tag_id`='$tag_id' AND `object_type`='$type' AND `object_id`='$object_id' AND `user`='$user_id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // remove_map + } // remove_map - /** - * validate_type - * This validates the type of the object the user wants to tag, we limit this to types - * we currently support - */ - public static function validate_type($type) { + /** + * validate_type + * This validates the type of the object the user wants to tag, we limit this to types + * we currently support + */ + public static function validate_type($type) { - $valid_array = array('song','artist','album','video','playlist','live_stream'); + $valid_array = array('song','artist','album','video','playlist','live_stream'); - if (in_array($type,$valid_array)) { return $type; } + if (in_array($type,$valid_array)) { return $type; } - return false; + return false; - } // validate_type + } // validate_type - /** - * clean_tag - * This takes a string and makes it Tagish - */ - public static function clean_tag($value) { + /** + * clean_tag + * This takes a string and makes it Tagish + */ + public static function clean_tag($value) { - $tag = preg_replace("/[^\w\_\-\s\&]/","",$value); + $tag = preg_replace("/[^\w\_\-\s\&]/","",$value); - return $tag; + return $tag; - } // clean_tag + } // clean_tag } // end of Tag class ?> diff --git a/lib/class/tmp_playlist.class.php b/lib/class/tmp_playlist.class.php index 129a8d1abc..9022c15e47 100644 --- a/lib/class/tmp_playlist.class.php +++ b/lib/class/tmp_playlist.class.php @@ -1,5 +1,5 @@ id = intval($playlist_id); - $info = $this->_get_info(); + $this->id = intval($playlist_id); + $info = $this->_get_info(); - foreach ($info as $key=>$value) { - $this->$key = $value; - } + foreach ($info as $key=>$value) { + $this->$key = $value; + } - return true; + return true; - } // __construct + } // __construct - /** - * _get_info - * This is an internal (private) function that gathers the information - * for this object from the playlist_id that was passed in. - */ - private function _get_info() { + /** + * _get_info + * This is an internal (private) function that gathers the information + * for this object from the playlist_id that was passed in. + */ + private function _get_info() { - $sql = "SELECT * FROM `tmp_playlist` WHERE `id`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `tmp_playlist` WHERE `id`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - return $results; + return $results; - } // _get_info + } // _get_info - /** - * get_from_session - * This returns a playlist object based on the session that is passed to - * us. This is used by the load_playlist on user for the most part. - */ - public static function get_from_session($session_id) { + /** + * get_from_session + * This returns a playlist object based on the session that is passed to + * us. This is used by the load_playlist on user for the most part. + */ + public static function get_from_session($session_id) { - $session_id = Dba::escape($session_id); + $session_id = Dba::escape($session_id); - $sql = "SELECT `id` FROM `tmp_playlist` WHERE `session`='$session_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `tmp_playlist` WHERE `session`='$session_id'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_row($db_results); + $results = Dba::fetch_row($db_results); - if (!$results['0']) { - $results['0'] = Tmp_Playlist::create(array( - 'session_id' => $session_id, - 'type' => 'user', - 'object_type' => 'song' - )); - } + if (!$results['0']) { + $results['0'] = Tmp_Playlist::create(array( + 'session_id' => $session_id, + 'type' => 'user', + 'object_type' => 'song' + )); + } - $playlist = new Tmp_Playlist($results['0']); + $playlist = new Tmp_Playlist($results['0']); - return $playlist; + return $playlist; - } // get_from_session + } // get_from_session - /** - * get_from_userid - * This returns a tmp playlist object based on a userid passed - * this is used for the user profiles page - */ - public static function get_from_userid($user_id) { + /** + * get_from_userid + * This returns a tmp playlist object based on a userid passed + * this is used for the user profiles page + */ + public static function get_from_userid($user_id) { - // This is a little stupid, but because we don't have the - // user_id in the session or in the tmp_playlist table we have - // to do it this way. - $client = new User($user_id); - $username = Dba::escape($client->username); + // This is a little stupid, but because we don't have the + // user_id in the session or in the tmp_playlist table we have + // to do it this way. + $client = new User($user_id); + $username = Dba::escape($client->username); - $sql = "SELECT `tmp_playlist`.`id` FROM `tmp_playlist` " . - "LEFT JOIN `session` ON " . - "`session`.`id`=`tmp_playlist`.`session` " . - "WHERE `session`.`username`='$username' " . - "ORDER BY `session`.`expire` DESC"; - $db_results = Dba::read($sql); + $sql = "SELECT `tmp_playlist`.`id` FROM `tmp_playlist` " . + "LEFT JOIN `session` ON " . + "`session`.`id`=`tmp_playlist`.`session` " . + "WHERE `session`.`username`='$username' " . + "ORDER BY `session`.`expire` DESC"; + $db_results = Dba::read($sql); - $data = Dba::fetch_assoc($db_results); + $data = Dba::fetch_assoc($db_results); - return $data['id']; + return $data['id']; - } // get_from_userid + } // get_from_userid - /** - * get_items - * Returns an array of all object_ids currently in this Tmp_Playlist. - */ - public function get_items() { + /** + * get_items + * Returns an array of all object_ids currently in this Tmp_Playlist. + */ + public function get_items() { - $id = Dba::escape($this->id); + $id = Dba::escape($this->id); - /* Select all objects from this playlist */ - $sql = "SELECT `object_type`, `id`, `object_id` " . - "FROM `tmp_playlist_data` " . - "WHERE `tmp_playlist`='$id' ORDER BY `id` ASC"; - $db_results = Dba::read($sql); + /* Select all objects from this playlist */ + $sql = "SELECT `object_type`, `id`, `object_id` " . + "FROM `tmp_playlist_data` " . + "WHERE `tmp_playlist`='$id' ORDER BY `id` ASC"; + $db_results = Dba::read($sql); - /* Define the array */ - $items = array(); + /* Define the array */ + $items = array(); - while ($results = Dba::fetch_assoc($db_results)) { - $key = $results['id']; - $items[$key] = array( - 'object_type' => $results['object_type'], - 'object_id' => $results['object_id'] - ); - } + while ($results = Dba::fetch_assoc($db_results)) { + $key = $results['id']; + $items[$key] = array( + 'object_type' => $results['object_type'], + 'object_id' => $results['object_id'] + ); + } - return $items; + return $items; - } // get_items + } // get_items - /** - * get_next_object - * This returns the next object in the tmp_playlist. - */ - public function get_next_object() { + /** + * get_next_object + * This returns the next object in the tmp_playlist. + */ + public function get_next_object() { - $id = Dba::escape($this->id); + $id = Dba::escape($this->id); - $sql = "SELECT `object_id` FROM `tmp_playlist_data` " . - "WHERE `tmp_playlist`='$id' ORDER BY `id` LIMIT 1"; - $db_results = Dba::read($sql); + $sql = "SELECT `object_id` FROM `tmp_playlist_data` " . + "WHERE `tmp_playlist`='$id' ORDER BY `id` LIMIT 1"; + $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $results = Dba::fetch_assoc($db_results); - return $results['object_id']; + return $results['object_id']; - } // get_next_object + } // get_next_object - /** - * count_items - * This returns a count of the total number of tracks that are in this - * tmp playlist - */ - public function count_items() { + /** + * count_items + * This returns a count of the total number of tracks that are in this + * tmp playlist + */ + public function count_items() { - $id = Dba::escape($this->id); + $id = Dba::escape($this->id); - $sql = "SELECT COUNT(`id`) FROM `tmp_playlist_data` WHERE " . - "`tmp_playlist`='$id'"; - $db_results = Dba::read($sql); + $sql = "SELECT COUNT(`id`) FROM `tmp_playlist_data` WHERE " . + "`tmp_playlist`='$id'"; + $db_results = Dba::read($sql); - $results = Dba::fetch_row($db_results); + $results = Dba::fetch_row($db_results); - return $results['0']; + return $results['0']; - } // count_items + } // count_items - /** - * clear - * This clears all the objects out of a single playlist - */ - public function clear() { + /** + * clear + * This clears all the objects out of a single playlist + */ + public function clear() { - $id = Dba::escape($this->id); + $id = Dba::escape($this->id); - $sql = "DELETE FROM `tmp_playlist_data` WHERE " . - "`tmp_playlist`='$id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tmp_playlist_data` WHERE " . + "`tmp_playlist`='$id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // clear + } // clear - /** - * create - * This function initializes a new Tmp_Playlist. It is associated with - * the current session rather than a user, as you could have the same - * user logged in from multiple locations. - */ - public static function create($data) { + /** + * create + * This function initializes a new Tmp_Playlist. It is associated with + * the current session rather than a user, as you could have the same + * user logged in from multiple locations. + */ + public static function create($data) { - $sessid = Dba::escape($data['session_id']); - $type = Dba::escape($data['type']); - $object_type = Dba::escape($data['object_type']); + $sessid = Dba::escape($data['session_id']); + $type = Dba::escape($data['type']); + $object_type = Dba::escape($data['object_type']); - $sql = "INSERT INTO `tmp_playlist` " . - "(`session`,`type`,`object_type`) " . - " VALUES ('$sessid','$type','$object_type')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `tmp_playlist` " . + "(`session`,`type`,`object_type`) " . + " VALUES ('$sessid','$type','$object_type')"; + $db_results = Dba::write($sql); - $id = Dba::insert_id(); + $id = Dba::insert_id(); - /* Clean any other playlists associated with this session */ - self::session_clean($sessid, $id); + /* Clean any other playlists associated with this session */ + self::session_clean($sessid, $id); - return $id; + return $id; - } // create + } // create - /** - * update_playlist - * This updates the base_playlist on this tmp_playlist - */ - public function update_playlist($playlist_id) { + /** + * update_playlist + * This updates the base_playlist on this tmp_playlist + */ + public function update_playlist($playlist_id) { - $playlist_id = Dba::escape($playlist_id); - $id = Dba::escape($this->id); + $playlist_id = Dba::escape($playlist_id); + $id = Dba::escape($this->id); - $sql = "UPDATE `tmp_playlist` SET " . - "`base_playlist`='$playlist_id' WHERE `id`='$id'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `tmp_playlist` SET " . + "`base_playlist`='$playlist_id' WHERE `id`='$id'"; + $db_results = Dba::write($sql); - return true; + return true; - } // update_playlist + } // update_playlist - /** - * session_clean - * This deletes any other tmp_playlists associated with this - * session - */ - public static function session_clean($sessid, $id) { + /** + * session_clean + * This deletes any other tmp_playlists associated with this + * session + */ + public static function session_clean($sessid, $id) { - $sessid = Dba::escape($sessid); - $id = Dba::escape($id); + $sessid = Dba::escape($sessid); + $id = Dba::escape($id); - $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$sessid' " . - "AND `id` != '$id'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `tmp_playlist` WHERE `session`='$sessid' " . + "AND `id` != '$id'"; + $db_results = Dba::write($sql); - /* Remove associated tracks */ - self::prune_tracks(); + /* Remove associated tracks */ + self::prune_tracks(); - return true; + return true; - } // session_clean + } // session_clean - /** - * gc - * This cleans up old data - */ - public static function gc() { - self::prune_playlists(); - self::prune_tracks(); - Dba::write("DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` LEFT JOIN `song` ON `tmp_playlist_data`.`object_id` = `song`.`id` WHERE `song`.`id` IS NULL"); - } + /** + * gc + * This cleans up old data + */ + public static function gc() { + self::prune_playlists(); + self::prune_tracks(); + Dba::write("DELETE FROM `tmp_playlist_data` USING `tmp_playlist_data` LEFT JOIN `song` ON `tmp_playlist_data`.`object_id` = `song`.`id` WHERE `song`.`id` IS NULL"); + } - /** - * prune_playlists - * This deletes any playlists that don't have an associated session - */ - public static function prune_playlists() { + /** + * prune_playlists + * This deletes any playlists that don't have an associated session + */ + public static function prune_playlists() { - /* Just delete if no matching session row */ - $sql = "DELETE FROM `tmp_playlist` USING `tmp_playlist` " . - "LEFT JOIN `session` " . - "ON `session`.`id`=`tmp_playlist`.`session` " . - "WHERE `session`.`id` IS NULL " . - "AND `tmp_playlist`.`type` != 'vote'"; - $db_results = Dba::write($sql); + /* Just delete if no matching session row */ + $sql = "DELETE FROM `tmp_playlist` USING `tmp_playlist` " . + "LEFT JOIN `session` " . + "ON `session`.`id`=`tmp_playlist`.`session` " . + "WHERE `session`.`id` IS NULL " . + "AND `tmp_playlist`.`type` != 'vote'"; + $db_results = Dba::write($sql); - return true; + return true; - } // prune_playlists + } // prune_playlists - /** - * prune_tracks - * This prunes tracks that don't have playlists or don't have votes - */ - public static function prune_tracks() { + /** + * prune_tracks + * This prunes tracks that don't have playlists or don't have votes + */ + public static function prune_tracks() { - // This prune is always run and clears data for playlists that - // don't exist anymore - $sql = "DELETE FROM `tmp_playlist_data` USING " . - "`tmp_playlist_data` LEFT JOIN `tmp_playlist` ON " . - "`tmp_playlist_data`.`tmp_playlist`=`tmp_playlist`.`id` " . - "WHERE `tmp_playlist`.`id` IS NULL"; - $db_results = Dba::write($sql); + // This prune is always run and clears data for playlists that + // don't exist anymore + $sql = "DELETE FROM `tmp_playlist_data` USING " . + "`tmp_playlist_data` LEFT JOIN `tmp_playlist` ON " . + "`tmp_playlist_data`.`tmp_playlist`=`tmp_playlist`.`id` " . + "WHERE `tmp_playlist`.`id` IS NULL"; + $db_results = Dba::write($sql); - } // prune_tracks + } // prune_tracks - /** - * add_object - * This adds the object of $this->object_type to this tmp playlist - * it takes an optional type, default is song - */ - public function add_object($object_id,$object_type) { + /** + * add_object + * This adds the object of $this->object_type to this tmp playlist + * it takes an optional type, default is song + */ + public function add_object($object_id,$object_type) { - $object_id = Dba::escape($object_id); - $playlist_id = Dba::escape($this->id); - $object_type = $object_type ? Dba::escape($object_type) : 'song'; + $object_id = Dba::escape($object_id); + $playlist_id = Dba::escape($this->id); + $object_type = $object_type ? Dba::escape($object_type) : 'song'; - $sql = "INSERT INTO `tmp_playlist_data` " . - "(`object_id`,`tmp_playlist`,`object_type`) " . - " VALUES ('$object_id','$playlist_id','$object_type')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `tmp_playlist_data` " . + "(`object_id`,`tmp_playlist`,`object_type`) " . + " VALUES ('$object_id','$playlist_id','$object_type')"; + $db_results = Dba::write($sql); - return true; + return true; - } // add_object + } // add_object - /** - * vote_active - * This checks to see if this playlist is a voting playlist - * and if it is active - */ - public function vote_active() { + /** + * vote_active + * This checks to see if this playlist is a voting playlist + * and if it is active + */ + public function vote_active() { - /* Going to do a little more here later */ - if ($this->type == 'vote') { return true; } + /* Going to do a little more here later */ + if ($this->type == 'vote') { return true; } - return false; + return false; - } // vote_active - - /** - * delete_track - * This deletes a track from the tmpplaylist - */ - public function delete_track($id) { + } // vote_active + + /** + * delete_track + * This deletes a track from the tmpplaylist + */ + public function delete_track($id) { - $id = Dba::escape($id); + $id = Dba::escape($id); - /* delete the track its self */ - $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$id'"; - $db_results = Dba::write($sql); - - return true; + /* delete the track its self */ + $sql = "DELETE FROM `tmp_playlist_data` WHERE `id`='$id'"; + $db_results = Dba::write($sql); + + return true; - } // delete_track + } // delete_track } // class Tmp_Playlist diff --git a/lib/class/ui.class.php b/lib/class/ui.class.php index ae4ec091c4..ff9ef0cd7d 100644 --- a/lib/class/ui.class.php +++ b/lib/class/ui.class.php @@ -1,5 +1,5 @@ self::$_ticker + 1)) { - self::$_ticker = time(); - return true; - } - - return false; - } - - /** - * flip_class - * - * First initialised with an array of two class names. Subsequent calls - * reverse the array then return the first element. - */ - public static function flip_class($classes = null) { - if (is_array($classes)) { - self::$_classes = $array; - } - else { - self::$_classes = array_reverse(self::$_classes); - } - return self::$_classes[0]; - } - - /** - * format_bytes - * - * Turns a size in bytes into the best human-readable value - */ - public static function format_bytes($value, $precision = 2) { - $pass = 0; - while (strlen(floor($value)) > 3) { - $value /= 1024; - $pass++; - } - - switch ($pass) { - case 1: $unit = 'kB'; break; - case 2: $unit = 'MB'; break; - case 3: $unit = 'GB'; break; - case 4: $unit = 'TB'; break; - case 5: $unit = 'PB'; break; - default: $unit = 'B'; break; - } - - return round($value, $precision) . ' ' . $unit; - } - - /** - * unformat_bytes - * - * Parses a human-readable size - */ - public static function unformat_bytes($value) { - if (preg_match('/^([0-9]+) *([[:alpha:]]+)$/', $value, $matches)) { - $value = $matches[1]; - $unit = strtolower(substr($matches[2], 0, 1)); - } - else { - return $value; - } - - switch($unit) { - case 'p': - $value *= 1024; - case 't': - $value *= 1024; - case 'g': - $value *= 1024; - case 'm': - $value *= 1024; - case 'k': - $value *= 1024; - } - - return $value; - } - - /** - * get_icon - * - * Returns an tag for the specified icon - */ - public static function get_icon($name, $title = null, $id = null) { - if (is_array($name)) { - $hover_name = $name[1]; - $name = $name[0]; - } - - $title = $title ?: T_(ucfirst($name)); - - $icon_url = self::_find_icon($name); - if ($hover_name) { - $hover_url = self::_find_icon($hover_text); - } - - $tag = ' $max) { - $text = iconv_substr($text, 0, $max - 3, $charset); - $text .= iconv('ISO-8859-1', $charset, '...'); - } - } - else { - if (strlen($text) > $max) { - $text = substr($text, 0, $max - 3) . '...'; - } - } - - return $text; - } - - /** - * update_text - * - * Convenience function that, if the output is going to a browser, - * blarfs JS to do a fancy update. Otherwise it just outputs the text. - */ - public static function update_text($field, $value) { - if (defined('CLI')) { - echo $value . "\n"; - return; - } - - echo '\n"; - ob_flush(); - flush(); - } + private static $_classes; + private static $_ticker; + private static $_icon_cache; + + public function __construct($data) { + return false; + } + + /** + * access_denied + * + * Throw an error when they try to do something naughty. + */ + public static function access_denied($error = 'Access Denied') { + // Clear any buffered crap + ob_end_clean(); + header("HTTP/1.1 403 $error"); + require_once Config::get('prefix') . '/templates/show_denied.inc.php'; + exit; + } + + /** + * ajax_include + * + * Does some trickery with the output buffer to return the output of a + * template. + */ + public static function ajax_include($template) { + ob_start(); + require Config::get('prefix') . '/templates/' . $template; + $output = ob_get_contents(); + ob_end_clean(); + + return $output; + } + + /** + * check_iconv + * + * Checks to see whether iconv is available; + */ + public static function check_iconv() { + if (function_exists('iconv') && function_exists('iconv_substr')) { + return true; + } + return false; + } + + /** + * check_ticker + * + * Stupid little cutesie thing to ratelimit output of long-running + * operations. + */ + public static function check_ticker() { + if (!isset(self::$_ticker) || (time() > self::$_ticker + 1)) { + self::$_ticker = time(); + return true; + } + + return false; + } + + /** + * flip_class + * + * First initialised with an array of two class names. Subsequent calls + * reverse the array then return the first element. + */ + public static function flip_class($classes = null) { + if (is_array($classes)) { + self::$_classes = $array; + } + else { + self::$_classes = array_reverse(self::$_classes); + } + return self::$_classes[0]; + } + + /** + * format_bytes + * + * Turns a size in bytes into the best human-readable value + */ + public static function format_bytes($value, $precision = 2) { + $pass = 0; + while (strlen(floor($value)) > 3) { + $value /= 1024; + $pass++; + } + + switch ($pass) { + case 1: $unit = 'kB'; break; + case 2: $unit = 'MB'; break; + case 3: $unit = 'GB'; break; + case 4: $unit = 'TB'; break; + case 5: $unit = 'PB'; break; + default: $unit = 'B'; break; + } + + return round($value, $precision) . ' ' . $unit; + } + + /** + * unformat_bytes + * + * Parses a human-readable size + */ + public static function unformat_bytes($value) { + if (preg_match('/^([0-9]+) *([[:alpha:]]+)$/', $value, $matches)) { + $value = $matches[1]; + $unit = strtolower(substr($matches[2], 0, 1)); + } + else { + return $value; + } + + switch($unit) { + case 'p': + $value *= 1024; + case 't': + $value *= 1024; + case 'g': + $value *= 1024; + case 'm': + $value *= 1024; + case 'k': + $value *= 1024; + } + + return $value; + } + + /** + * get_icon + * + * Returns an tag for the specified icon + */ + public static function get_icon($name, $title = null, $id = null) { + if (is_array($name)) { + $hover_name = $name[1]; + $name = $name[0]; + } + + $title = $title ?: T_(ucfirst($name)); + + $icon_url = self::_find_icon($name); + if ($hover_name) { + $hover_url = self::_find_icon($hover_text); + } + + $tag = ' $max) { + $text = iconv_substr($text, 0, $max - 3, $charset); + $text .= iconv('ISO-8859-1', $charset, '...'); + } + } + else { + if (strlen($text) > $max) { + $text = substr($text, 0, $max - 3) . '...'; + } + } + + return $text; + } + + /** + * update_text + * + * Convenience function that, if the output is going to a browser, + * blarfs JS to do a fancy update. Otherwise it just outputs the text. + */ + public static function update_text($field, $value) { + if (defined('CLI')) { + echo $value . "\n"; + return; + } + + echo '\n"; + ob_flush(); + flush(); + } } diff --git a/lib/class/update.class.php b/lib/class/update.class.php index 0e7ce44c52..bfaefc6583 100644 --- a/lib/class/update.class.php +++ b/lib/class/update.class.php @@ -1,5 +1,5 @@ key = intval($key); - $info = $this->_get_info(); - $this->value = $info['value']; - $this->versions = $this->populate_version(); + $this->key = intval($key); + $info = $this->_get_info(); + $this->value = $info['value']; + $this->versions = $this->populate_version(); - } // constructor + } // constructor - /** - * _get_info - * gets the information for the zone - */ - private function _get_info() { + /** + * _get_info + * gets the information for the zone + */ + private function _get_info() { - $sql = "SELECT * FROM `update_info` WHERE `key`='$this->key'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `update_info` WHERE `key`='$this->key'"; + $db_results = Dba::read($sql); - return Dba::fetch_assoc($db_results); + return Dba::fetch_assoc($db_results); - } // _get_info + } // _get_info - /** - * get_version - * this checks to see what version you are currently running - * because we may not have the update_info table we have to check - * for it's existance first. - */ - public static function get_version() { + /** + * get_version + * this checks to see what version you are currently running + * because we may not have the update_info table we have to check + * for it's existance first. + */ + public static function get_version() { - /* Make sure that update_info exits */ - $sql = "SHOW TABLES LIKE 'update_info'"; - $db_results = Dba::read($sql); - if (!is_resource(Dba::dbh())) { header("Location: test.php"); } + /* Make sure that update_info exits */ + $sql = "SHOW TABLES LIKE 'update_info'"; + $db_results = Dba::read($sql); + if (!is_resource(Dba::dbh())) { header("Location: test.php"); } - // If no table - if (!Dba::num_rows($db_results)) { - // They can't upgrade, they are too old - header("Location: test.php"); + // If no table + if (!Dba::num_rows($db_results)) { + // They can't upgrade, they are too old + header("Location: test.php"); - } // if table isn't found + } // if table isn't found - else { - // If we've found the update_info table, let's get the version from it - $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'"; - $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); - $version = $results['value']; - } + else { + // If we've found the update_info table, let's get the version from it + $sql = "SELECT * FROM `update_info` WHERE `key`='db_version'"; + $db_results = Dba::read($sql); + $results = Dba::fetch_assoc($db_results); + $version = $results['value']; + } - return $version; + return $version; - } // get_version + } // get_version - /** - * format_version - * make the version number pretty - */ - public static function format_version($data) { + /** + * format_version + * make the version number pretty + */ + public static function format_version($data) { - $new_version = substr($data,0,strlen($data) - 5) . "." . substr($data,strlen($data)-5,1) . " Build:" . - substr($data,strlen($data)-4,strlen($data)); + $new_version = substr($data,0,strlen($data) - 5) . "." . substr($data,strlen($data)-5,1) . " Build:" . + substr($data,strlen($data)-4,strlen($data)); - return $new_version; + return $new_version; - } // format_version + } // format_version - /** - * need_update - * checks to see if we need to update - * ampache at all - */ - public static function need_update() { + /** + * need_update + * checks to see if we need to update + * ampache at all + */ + public static function need_update() { - $current_version = self::get_version(); + $current_version = self::get_version(); - if (!is_array(self::$versions)) { - self::$versions = self::populate_version(); - } + if (!is_array(self::$versions)) { + self::$versions = self::populate_version(); + } - /* - Go through the versions we have and see if - we need to apply any updates - */ - foreach (self::$versions as $update) { - if ($update['version'] > $current_version) { - return true; - } + /* + Go through the versions we have and see if + we need to apply any updates + */ + foreach (self::$versions as $update) { + if ($update['version'] > $current_version) { + return true; + } - } // end foreach version + } // end foreach version - return false; + return false; - } // need_update + } // need_update - /** - * plugins_installed - * This function checks to make sure that there are no plugins - * installed before allowing you to run the update. this is - * to protect the integrity of the database - */ - public static function plugins_installed() { + /** + * plugins_installed + * This function checks to make sure that there are no plugins + * installed before allowing you to run the update. this is + * to protect the integrity of the database + */ + public static function plugins_installed() { - /* Pull all version info */ - $sql = "SELECT * FROM `update_info`"; - $db_results = Dba::read($sql); + /* Pull all version info */ + $sql = "SELECT * FROM `update_info`"; + $db_results = Dba::read($sql); - while ($results = Dba::fetch_assoc($db_results)) { + while ($results = Dba::fetch_assoc($db_results)) { - /* We have only one allowed string */ - if ($results['key'] != 'db_version') { - return false; - } + /* We have only one allowed string */ + if ($results['key'] != 'db_version') { + return false; + } - } // while update_info results + } // while update_info results - return true; + return true; - } // plugins_installed + } // plugins_installed - /** - * populate_version - * just sets an array the current differences - * that require an update - */ - public static function populate_version() { + /** + * populate_version + * just sets an array the current differences + * that require an update + */ + public static function populate_version() { - /* Define the array */ - $version = array(); + /* Define the array */ + $version = array(); - $update_string = '- Moved back to ID for user tracking internally.
' . - '- Added date to user_vote to allow sorting by vote time.
' . - '- Added Random Method and Object Count Preferences.
' . - '- Removed some unused tables/fields.
' . - '- Added Label, Catalog # and Language to Extended Song Data Table.'; + $update_string = '- Moved back to ID for user tracking internally.
' . + '- Added date to user_vote to allow sorting by vote time.
' . + '- Added Random Method and Object Count Preferences.
' . + '- Removed some unused tables/fields.
' . + '- Added Label, Catalog # and Language to Extended Song Data Table.'; - $version[] = array('version' => '340001','description' => $update_string); + $version[] = array('version' => '340001','description' => $update_string); - $update_string = '- Added Offset Limit to Preferences and removed from user table.'; + $update_string = '- Added Offset Limit to Preferences and removed from user table.'; - $version[] = array('version' => '340002','description' => $update_string); + $version[] = array('version' => '340002','description' => $update_string); - $update_string = '- Moved Art from the Album table into album_data to improve performance.
' . - '- Made some minor changes to song table to reduce size of each row.
' . - '- Moved song_ext_data to song_data to match album_data pattern.
' . - '- Added Playlist Method and Rate Limit Preferences.
' . - '- Renamed preferences and ratings to preference and rating to fit table pattern.
' . - '- Fixed rating table, renamed user_rating to rating and switched 00 for -1.
'; + $update_string = '- Moved Art from the Album table into album_data to improve performance.
' . + '- Made some minor changes to song table to reduce size of each row.
' . + '- Moved song_ext_data to song_data to match album_data pattern.
' . + '- Added Playlist Method and Rate Limit Preferences.
' . + '- Renamed preferences and ratings to preference and rating to fit table pattern.
' . + '- Fixed rating table, renamed user_rating to rating and switched 00 for -1.
'; - $version[] = array('version' => '340003','description' => $update_string); + $version[] = array('version' => '340003','description' => $update_string); - $update_string = '- Alter the Session.id to be VARCHAR(64) to account for all potential configs.
' . - '- Added new user_shout table for Sticky objects / shoutbox.
' . - '- Added new playlist preferences, and new preference catagory of playlist.
' . - '- Tweaked Now Playing Table.
'; + $update_string = '- Alter the Session.id to be VARCHAR(64) to account for all potential configs.
' . + '- Added new user_shout table for Sticky objects / shoutbox.
' . + '- Added new playlist preferences, and new preference catagory of playlist.
' . + '- Tweaked Now Playing Table.
'; - $version[] = array('version' => '340004','description' => $update_string); + $version[] = array('version' => '340004','description' => $update_string); - $update_string = '- Altered Ratings table so the fields make more sense.
' . - '- Moved Random Method to Playlist catagory.
' . - '- Added Transcode Method to Streaming.
'; + $update_string = '- Altered Ratings table so the fields make more sense.
' . + '- Moved Random Method to Playlist catagory.
' . + '- Added Transcode Method to Streaming.
'; - $version[] = array('version' => '340005','description' => $update_string); + $version[] = array('version' => '340005','description' => $update_string); - $update_string = '- Remove Random Method config option, ended up being useless.
' . - '- Check and change album_data.art to a MEDIUMBLOB if needed.
'; + $update_string = '- Remove Random Method config option, ended up being useless.
' . + '- Check and change album_data.art to a MEDIUMBLOB if needed.
'; - $version[] = array('version' => '340006','description' => $update_string); + $version[] = array('version' => '340006','description' => $update_string); - $update_string = '- Added new session_stream table for sessions tied directly to stream instances.
' . - '- Altered the session table, making value a LONGTEXT.
'; + $update_string = '- Added new session_stream table for sessions tied directly to stream instances.
' . + '- Altered the session table, making value a LONGTEXT.
'; - $version[] = array('version' => '340007','description' => $update_string); + $version[] = array('version' => '340007','description' => $update_string); - $update_string = '- Modified Playlist_Data table to account for multiple object types.
' . - '- Verified previous updates, adjusting as needed.
' . - '- Dropped Allow Downsampling pref, configured in cfg file.
' . - '- Renamed Downsample Rate --> Transcode Rate to reflect new terminiology.
'; + $update_string = '- Modified Playlist_Data table to account for multiple object types.
' . + '- Verified previous updates, adjusting as needed.
' . + '- Dropped Allow Downsampling pref, configured in cfg file.
' . + '- Renamed Downsample Rate --> Transcode Rate to reflect new terminiology.
'; - $version[] = array('version' => '340008','description' => $update_string); + $version[] = array('version' => '340008','description' => $update_string); - $update_string = '- Added disk to Album table.
' . - '- Added artist_data for artist images and bios.
' . - '- Added DNS to access list to allow for dns based ACLs.
'; + $update_string = '- Added disk to Album table.
' . + '- Added artist_data for artist images and bios.
' . + '- Added DNS to access list to allow for dns based ACLs.
'; - $version[] = array('version' => '340009','description' => $update_string); + $version[] = array('version' => '340009','description' => $update_string); - $update_string = '- Removed Playlist Add preference.
' . - '- Moved Localplay* preferences to options.
' . - '- Tweaked Default Playlist Method.
' . - '- Change wording on Localplay preferences.
'; - $version[] = array('version' => '340010','description'=>$update_string); + $update_string = '- Removed Playlist Add preference.
' . + '- Moved Localplay* preferences to options.
' . + '- Tweaked Default Playlist Method.
' . + '- Change wording on Localplay preferences.
'; + $version[] = array('version' => '340010','description'=>$update_string); - $update_string = '- Added api session table, will eventually recombine with others.
'; + $update_string = '- Added api session table, will eventually recombine with others.
'; - $version[] = array('version' => '340011','description'=>$update_string); + $version[] = array('version' => '340011','description'=>$update_string); - $update_string = '- Added Democratic Table for new democratic play features.
' . - '- Added Add Path to Catalog to improve add speeds on large catalogs.
'; + $update_string = '- Added Democratic Table for new democratic play features.
' . + '- Added Add Path to Catalog to improve add speeds on large catalogs.
'; - $version[] = array('version' => '340012','description'=>$update_string); + $version[] = array('version' => '340012','description'=>$update_string); - $update_string = '- Removed Unused Preferences.
' . - '- Changed Localplay Config to Localplay Access.
' . - '- Changed all XML-RPC acls to RPC to reflect inclusion of new API.
'; + $update_string = '- Removed Unused Preferences.
' . + '- Changed Localplay Config to Localplay Access.
' . + '- Changed all XML-RPC acls to RPC to reflect inclusion of new API.
'; - $version[] = array('version' => '340013','description'=>$update_string); + $version[] = array('version' => '340013','description'=>$update_string); - $update_string = '- Removed API Session table, been a nice run....
' . - '- Alterted Session table to handle API sessions correctly.
'; + $update_string = '- Removed API Session table, been a nice run....
' . + '- Alterted Session table to handle API sessions correctly.
'; - $version[] = array('version' => '340014','description'=>$update_string); + $version[] = array('version' => '340014','description'=>$update_string); - $update_string = '- Alter Playlist Date Field to fix issues with some MySQL configurations.
' . - '- Alter Rating type to correct AVG issue on searching.
'; + $update_string = '- Alter Playlist Date Field to fix issues with some MySQL configurations.
' . + '- Alter Rating type to correct AVG issue on searching.
'; - $version[] = array('version' => '340015','description'=>$update_string); + $version[] = array('version' => '340015','description'=>$update_string); - $update_string = '- Alter the Democratic Playlist table, adding base_playlist.
' . - '- Alter tmp_playlist to account for Democratic changes.
' . - '- Cleared Existing Democratic playlists due to changes.
'; + $update_string = '- Alter the Democratic Playlist table, adding base_playlist.
' . + '- Alter tmp_playlist to account for Democratic changes.
' . + '- Cleared Existing Democratic playlists due to changes.
'; - $version[] = array('version' => '340016','description'=>$update_string); + $version[] = array('version' => '340016','description'=>$update_string); - $update_string = '- Fix Tables for new Democratic Play methodology.
'; + $update_string = '- Fix Tables for new Democratic Play methodology.
'; - $version[] = array('version' => '340017','description'=>$update_string); + $version[] = array('version' => '340017','description'=>$update_string); - $update_string = '- Attempt to detect and correct charset issues between filesystem and database.
'; + $update_string = '- Attempt to detect and correct charset issues between filesystem and database.
'; - $version[] = array('version' => '340018','description'=>$update_string); + $version[] = array('version' => '340018','description'=>$update_string); - $update_string = '- Modify the Tag tables so that they actually work.
' . - '- Alter the Prefix fields to allow for more prefixs.
'; + $update_string = '- Modify the Tag tables so that they actually work.
' . + '- Alter the Prefix fields to allow for more prefixs.
'; - $version[] = array('version' => '350001','description'=>$update_string); + $version[] = array('version' => '350001','description'=>$update_string); - $update_string = '- Remove Genre Field from song table.
' . - '- Add user_catalog table for tracking user<-->catalog mappings.
' . - '- Add tmp_browse to handle caching rather then session table.
'; + $update_string = '- Remove Genre Field from song table.
' . + '- Add user_catalog table for tracking user<-->catalog mappings.
' . + '- Add tmp_browse to handle caching rather then session table.
'; - $version[] = array('version' => '350002','description'=>$update_string); + $version[] = array('version' => '350002','description'=>$update_string); - $update_string = '- Modify Tag tables.
' . - '- Remove useless config preferences.
'; + $update_string = '- Modify Tag tables.
' . + '- Remove useless config preferences.
'; - $version[] = array('version'=> '350003','description'=>$update_string); + $version[] = array('version'=> '350003','description'=>$update_string); - $update_string = '- Modify ACL table to enable IPv6 ACL support
' . - '- Modify Session Tables to store IPv6 addresses if provided
' . - '- Modify IP History table to store IPv6 addresses and User Agent
'; + $update_string = '- Modify ACL table to enable IPv6 ACL support
' . + '- Modify Session Tables to store IPv6 addresses if provided
' . + '- Modify IP History table to store IPv6 addresses and User Agent
'; - $version[] = array('version'=>'350004','description'=>$update_string); + $version[] = array('version'=>'350004','description'=>$update_string); - $update_string = "- Add table for Video files
"; + $update_string = "- Add table for Video files
"; - $version[] = array('version'=>'350005','description'=>$update_string); + $version[] = array('version'=>'350005','description'=>$update_string); - $update_string = "- Add data for Lyrics
"; + $update_string = "- Add data for Lyrics
"; - $version[] = array('version'=>'350006','description'=>$update_string); + $version[] = array('version'=>'350006','description'=>$update_string); - $update_string = '- Remove unused fields from catalog, playlist, playlist_data
' . - '- Add tables for dynamic playlists
' . - '- Add last_clean to catalog table
' . - '- Add track to tmp_playlist_data
' . - '- Increase Thumbnail blob size
'; + $update_string = '- Remove unused fields from catalog, playlist, playlist_data
' . + '- Add tables for dynamic playlists
' . + '- Add last_clean to catalog table
' . + '- Add track to tmp_playlist_data
' . + '- Increase Thumbnail blob size
'; - $version[] = array('version'=>'350007','description'=>$update_string); + $version[] = array('version'=>'350007','description'=>$update_string); - $update_string = '- Modify Now Playing table to handle Videos
' . - '- Modify tmp_browse to make it easier to prune
' . - '- Add missing indexes to the _data tables
' . - '- Drop unused song.hash
' . - '- Add addition_time and update_time to video table
'; + $update_string = '- Modify Now Playing table to handle Videos
' . + '- Modify tmp_browse to make it easier to prune
' . + '- Add missing indexes to the _data tables
' . + '- Drop unused song.hash
' . + '- Add addition_time and update_time to video table
'; - $version[] = array('version'=>'350008','description'=>$update_string); + $version[] = array('version'=>'350008','description'=>$update_string); - $update_string = '- Add MBID (MusicBrainz ID) fields
' . - '- Remove useless preferences
'; + $update_string = '- Add MBID (MusicBrainz ID) fields
' . + '- Remove useless preferences
'; - $version[] = array('version'=>'360001','description'=>$update_string); + $version[] = array('version'=>'360001','description'=>$update_string); - $update_string = '- Add Bandwidth and Feature preferences to simplify how interface is presented
' . - '- Change Tables to FULLTEXT() for improved searching
' . - '- Increase Filename lengths to 4096
' . - '- Remove useless "KEY" reference from ACL and Catalog tables
' . - '- Add new Remote User / Remote Password fields to Catalog
'; + $update_string = '- Add Bandwidth and Feature preferences to simplify how interface is presented
' . + '- Change Tables to FULLTEXT() for improved searching
' . + '- Increase Filename lengths to 4096
' . + '- Remove useless "KEY" reference from ACL and Catalog tables
' . + '- Add new Remote User / Remote Password fields to Catalog
'; - $version[] = array('version'=>'360002','description'=>$update_string); + $version[] = array('version'=>'360002','description'=>$update_string); - $update_string = '- Add image table to store images.
' . - '- Drop album_data and artist_data.
'; - $version[] = array('version'=>'360003','description'=>$update_string); + $update_string = '- Add image table to store images.
' . + '- Drop album_data and artist_data.
'; + $version[] = array('version'=>'360003','description'=>$update_string); - $update_string = '- Add uniqueness constraint to ratings.
'; - $version[] = array('version' => '360004','description' => $update_string); + $update_string = '- Add uniqueness constraint to ratings.
'; + $version[] = array('version' => '360004','description' => $update_string); - $update_string = '- Modify tmp_browse to allow caching of multiple browses per session.
'; - $version[] = array('version' => '360005','description' => $update_string); + $update_string = '- Modify tmp_browse to allow caching of multiple browses per session.
'; + $version[] = array('version' => '360005','description' => $update_string); - $update_string = '- Add table for dynamic playlists.
'; - $version[] = array('version' => '360006','description' => $update_string); + $update_string = '- Add table for dynamic playlists.
'; + $version[] = array('version' => '360006','description' => $update_string); - $update_string = '- Add local auth method to session.type.
'; - $version[] = array('version' => '360007','description' => $update_string); + $update_string = '- Add local auth method to session.type.
'; + $version[] = array('version' => '360007','description' => $update_string); - $update_string = '- Verify remote_username and remote_password were added correctly to catalog table.
'; - $version[] = array('version' => '360008','description' => $update_string); + $update_string = '- Verify remote_username and remote_password were added correctly to catalog table.
'; + $version[] = array('version' => '360008','description' => $update_string); - $update_string = '- Allow long sessionids in tmp_playlist table.
'; - $version[] = array('version' => '360009', 'description' => $update_string); + $update_string = '- Allow long sessionids in tmp_playlist table.
'; + $version[] = array('version' => '360009', 'description' => $update_string); - $update_string = '- Allow compound MBIDs in the artist table.
'; - $version[] = array('version' => '360010', 'description' => $update_string); + $update_string = '- Allow compound MBIDs in the artist table.
'; + $version[] = array('version' => '360010', 'description' => $update_string); - $update_string = '- Add table to store stream session playlist.
'; - $version[] = array('version' => '360011', 'description' => $update_string); + $update_string = '- Add table to store stream session playlist.
'; + $version[] = array('version' => '360011', 'description' => $update_string); - return $version; + return $version; - } // populate_version + } // populate_version - /** - * display_update - * This displays a list of the needed - * updates to the database. This will actually - * echo out the list... - */ - public static function display_update() { + /** + * display_update + * This displays a list of the needed + * updates to the database. This will actually + * echo out the list... + */ + public static function display_update() { - $current_version = self::get_version(); - if (!is_array(self::$versions)) { - self::$versions = self::populate_version(); - } - $update_needed = false; + $current_version = self::get_version(); + if (!is_array(self::$versions)) { + self::$versions = self::populate_version(); + } + $update_needed = false; - if (!defined('CLI')) { echo "
    \n"; } + if (!defined('CLI')) { echo "
      \n"; } - foreach (self::$versions as $update) { + foreach (self::$versions as $update) { - if ($update['version'] > $current_version) { - $update_needed = true; - if (!defined('CLI')) { echo '
    • '; } - echo 'Version: ', self::format_version($update['version']); - if (defined('CLI')) { - echo "\n", str_replace('
      ', "\n", $update['description']), "\n"; - } - else { - echo '

      ', $update['description'], "
    • \n"; - } - } // if newer + if ($update['version'] > $current_version) { + $update_needed = true; + if (!defined('CLI')) { echo '
    • '; } + echo 'Version: ', self::format_version($update['version']); + if (defined('CLI')) { + echo "\n", str_replace('
      ', "\n", $update['description']), "\n"; + } + else { + echo '

      ', $update['description'], "
    • \n"; + } + } // if newer - } // foreach versions + } // foreach versions - if (!defined('CLI')) { echo "
    \n"; } + if (!defined('CLI')) { echo "
\n"; } - if (!$update_needed) { - if (!defined('CLI')) { echo '

'; } - echo T_('No updates needed.'); - if (!defined('CLI')) { - echo '[Return]

'; - } - else { - echo "\n"; - } - } - } // display_update + if (!$update_needed) { + if (!defined('CLI')) { echo '

'; } + echo T_('No updates needed.'); + if (!defined('CLI')) { + echo '[Return]

'; + } + else { + echo "\n"; + } + } + } // display_update - /** - * run_update - * This function actually updates the db. - * it goes through versions and finds the ones - * that need to be run. Checking to make sure - * the function exists first. - */ - public static function run_update() { + /** + * run_update + * This function actually updates the db. + * it goes through versions and finds the ones + * that need to be run. Checking to make sure + * the function exists first. + */ + public static function run_update() { - /* Nuke All Active session before we start the mojo */ - $sql = "TRUNCATE session"; - $db_results = Dba::write($sql); - - // Prevent the script from timing out, which could be bad - set_time_limit(0); - - /* Verify that there are no plugins installed - //FIXME: provide a link to remove all plugins, otherwise this could turn into a catch 22 - if (!$self::plugins_installed()) { - $GLOBALS['error']->add_error('general', T_('Plugins detected, please remove all Plugins and try again')); - return false; - } */ - - $methods = array(); + /* Nuke All Active session before we start the mojo */ + $sql = "TRUNCATE session"; + $db_results = Dba::write($sql); + + // Prevent the script from timing out, which could be bad + set_time_limit(0); + + /* Verify that there are no plugins installed + //FIXME: provide a link to remove all plugins, otherwise this could turn into a catch 22 + if (!$self::plugins_installed()) { + $GLOBALS['error']->add_error('general', T_('Plugins detected, please remove all Plugins and try again')); + return false; + } */ + + $methods = array(); - $current_version = self::get_version(); - - // Run a check to make sure that they don't try to upgrade from a version that - // won't work. - if ($current_version < '340001') { - echo "

Database version too old, please upgrade to Ampache-3.3.3.5 first

"; - return false; - } - - - $methods = get_class_methods('Update'); - - if (!is_array((self::$versions))) { - self::$versions = self::populate_version(); - } - - foreach (self::$versions as $version) { + $current_version = self::get_version(); + + // Run a check to make sure that they don't try to upgrade from a version that + // won't work. + if ($current_version < '340001') { + echo "

Database version too old, please upgrade to Ampache-3.3.3.5 first

"; + return false; + } + + + $methods = get_class_methods('Update'); + + if (!is_array((self::$versions))) { + self::$versions = self::populate_version(); + } + + foreach (self::$versions as $version) { - // If it's newer than our current version - // let's see if a function exists and run the - // bugger - if ($version['version'] > $current_version) { - $update_function = "update_" . $version['version']; - if (in_array($update_function,$methods)) { - $success = call_user_func(array('Update',$update_function)); - - // If the update fails drop out - if (!$success) { - Error::display('update'); - return false; - } - } - - } - - } // end foreach version + // If it's newer than our current version + // let's see if a function exists and run the + // bugger + if ($version['version'] > $current_version) { + $update_function = "update_" . $version['version']; + if (in_array($update_function,$methods)) { + $success = call_user_func(array('Update',$update_function)); + + // If the update fails drop out + if (!$success) { + Error::display('update'); + return false; + } + } + + } + + } // end foreach version - // Once we've run all of the updates let's re-sync the character set as the user - // can change this between updates and cause mis-matches on any new tables - Dba::reset_db_charset(); + // Once we've run all of the updates let's re-sync the character set as the user + // can change this between updates and cause mis-matches on any new tables + Dba::reset_db_charset(); - } // run_update + } // run_update - /** - * set_version - * This updates the 'update_info' which is used by the updater - * and plugins - */ - private static function set_version($key,$value) { + /** + * set_version + * This updates the 'update_info' which is used by the updater + * and plugins + */ + private static function set_version($key,$value) { - $sql = "UPDATE update_info SET value='$value' WHERE `key`='$key'"; - $db_results = Dba::write($sql); + $sql = "UPDATE update_info SET value='$value' WHERE `key`='$key'"; + $db_results = Dba::write($sql); - } //set_version + } //set_version - /** - * update_340001 - * This update moves back to the ID for user UID and - * adds date to the user_vote so that it can be sorted - * correctly - */ - private function update_340001() { + /** + * update_340001 + * This update moves back to the ID for user UID and + * adds date to the user_vote so that it can be sorted + * correctly + */ + private function update_340001() { - // Build the User -> ID map using the username as the key - $sql = "SELECT `id`,`username` FROM `user`"; - $db_results = Dba::read($sql); + // Build the User -> ID map using the username as the key + $sql = "SELECT `id`,`username` FROM `user`"; + $db_results = Dba::read($sql); - $user_array = array(); + $user_array = array(); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['username']; - $user_array[$username] = Dba::escape($r['id']); - } // end while + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['username']; + $user_array[$username] = Dba::escape($r['id']); + } // end while - // Alter the user table so that you can't have an ID beyond the - // range of the other tables which have to allow for -1 - $sql = "ALTER TABLE `user` CHANGE `id` `id` INT ( 11 ) NOT NULL AUTO_INCREMENT"; - $db_results = Dba::write($sql); + // Alter the user table so that you can't have an ID beyond the + // range of the other tables which have to allow for -1 + $sql = "ALTER TABLE `user` CHANGE `id` `id` INT ( 11 ) NOT NULL AUTO_INCREMENT"; + $db_results = Dba::write($sql); - // Now pull the access list users, alter table and then re-insert - $sql = "SELECT DISTINCT(`user`) FROM `access_list`"; - $db_results = Dba::read($sql); + // Now pull the access list users, alter table and then re-insert + $sql = "SELECT DISTINCT(`user`) FROM `access_list`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - // Build the new SQL - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + // Build the new SQL + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `access_list` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `access_list` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while access_list + } // end while access_list - // Alter the table - $sql = "ALTER TABLE `access_list` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `access_list` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Now pull flagged users, update and alter - $sql = "SELECT DISTINCT(`user`) FROM `flagged`"; - $db_results = Dba::read($sql); + // Now pull flagged users, update and alter + $sql = "SELECT DISTINCT(`user`) FROM `flagged`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `flagged` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `flagged` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while + } // end while - // Alter the table - $sql = "ALTER TABLE `flagged` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `flagged` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Now fix up the ip history - $sql = "SELECT DISTINCT(`user`) FROM `ip_history`"; - $db_results = Dba::read($sql); + // Now fix up the ip history + $sql = "SELECT DISTINCT(`user`) FROM `ip_history`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `ip_history` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `ip_history` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while + } // end while - // Alter the table - $sql = "ALTER TABLE `ip_history` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `ip_history` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Now fix now playing - $sql = "SELECT DISTINCT(`user`) FROM `now_playing`"; - $db_results = Dba::read($sql); + // Now fix now playing + $sql = "SELECT DISTINCT(`user`) FROM `now_playing`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `now_playing` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `now_playing` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while + } // end while - // Alter the table - $sql = "ALTER TABLE `now_playing` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `now_playing` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Now fix the playlist table - $sql = "SELECT DISTINCT(`user`) FROM `playlist`"; - $db_results = Dba::read($sql); + // Now fix the playlist table + $sql = "SELECT DISTINCT(`user`) FROM `playlist`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `playlist` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `playlist` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while + } // end while - // Alter the table - $sql = "ALTER TABLE `playlist` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `playlist` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Drop unused table - $sql = "DROP TABLE `playlist_permission`"; - $db_results = Dba::write($sql); + // Drop unused table + $sql = "DROP TABLE `playlist_permission`"; + $db_results = Dba::write($sql); - // Now fix the ratings table - $sql = "SELECT DISTINCT(`user`) FROM `ratings`"; - $db_results = Dba::read($sql); + // Now fix the ratings table + $sql = "SELECT DISTINCT(`user`) FROM `ratings`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `ratings` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `ratings` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while + } // end while - $sql = "ALTER TABLE `ratings` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `ratings` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Now work on the tag_map - $sql = "ALTER TABLE `tag_map` CHANGE `user_id` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Now work on the tag_map + $sql = "ALTER TABLE `tag_map` CHANGE `user_id` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Now fix user preferences - $sql = "SELECT DISTINCT(`user`) FROM `user_preference`"; - $db_results = Dba::read($sql); + // Now fix user preferences + $sql = "SELECT DISTINCT(`user`) FROM `user_preference`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $username = $r['user']; - $user_id = $user_array[$username]; - $username = Dba::escape($username); + while ($r = Dba::fetch_assoc($db_results)) { + $username = $r['user']; + $user_id = $user_array[$username]; + $username = Dba::escape($username); - $sql = "UPDATE `user_preference` SET `user`='$user_id' WHERE `user`='$username'"; - $update_results = Dba::write($sql); + $sql = "UPDATE `user_preference` SET `user`='$user_id' WHERE `user`='$username'"; + $update_results = Dba::write($sql); - } // end while + } // end while - // Alter the table - $sql = "ALTER TABLE `user_preference` CHANGE `user` `user` INT ( 11 ) NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `user_preference` CHANGE `user` `user` INT ( 11 ) NOT NULL"; + $db_results = Dba::write($sql); - // Add a date to the user_vote - $sql = "ALTER TABLE `user_vote` ADD `date` INT( 11 ) UNSIGNED NOT NULL"; - $db_results = Dba::write($sql); + // Add a date to the user_vote + $sql = "ALTER TABLE `user_vote` ADD `date` INT( 11 ) UNSIGNED NOT NULL"; + $db_results = Dba::write($sql); - // Add the index for said field - $sql = "ALTER TABLE `user_vote` ADD INDEX(`date`)"; - $db_results = Dba::write($sql); + // Add the index for said field + $sql = "ALTER TABLE `user_vote` ADD INDEX(`date`)"; + $db_results = Dba::write($sql); - // Add the thumb fields to album - $sql = "ALTER TABLE `album` ADD `thumb` TINYBLOB NULL ,ADD `thumb_mime` VARCHAR( 128 ) NULL"; - $db_results = Dba::write($sql); + // Add the thumb fields to album + $sql = "ALTER TABLE `album` ADD `thumb` TINYBLOB NULL ,ADD `thumb_mime` VARCHAR( 128 ) NULL"; + $db_results = Dba::write($sql); - // Now add in the min_object_count preference and the random_method - $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES('min_object_count','1','Min Element Count','5','integer','interface')"; - $db_results = Dba::write($sql); + // Now add in the min_object_count preference and the random_method + $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES('min_object_count','1','Min Element Count','5','integer','interface')"; + $db_results = Dba::write($sql); - $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES('random_method','default','Random Method','5','string','interface')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES('random_method','default','Random Method','5','string','interface')"; + $db_results = Dba::write($sql); - // Delete old preference - $sql = "DELETE FROM `preferences` WHERE `name`='min_album_size'"; - $db_results = Dba::write($sql); + // Delete old preference + $sql = "DELETE FROM `preferences` WHERE `name`='min_album_size'"; + $db_results = Dba::write($sql); - // Make Hash a non-required field and smaller - $sql = "ALTER TABLE `song` CHANGE `hash` `hash` VARCHAR ( 64 ) NULL"; - $db_results = Dba::write($sql); + // Make Hash a non-required field and smaller + $sql = "ALTER TABLE `song` CHANGE `hash` `hash` VARCHAR ( 64 ) NULL"; + $db_results = Dba::write($sql); - // Make user access an int, nothing else - $sql = "UPDATE `user` SET `access`='100' WHERE `access`='admin'"; - $db_results = Dba::write($sql); + // Make user access an int, nothing else + $sql = "UPDATE `user` SET `access`='100' WHERE `access`='admin'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `user` SET `access`='25' WHERE `access`='user'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `user` SET `access`='25' WHERE `access`='user'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `user` SET `access`='5' WHERE `access`='guest'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `user` SET `access`='5' WHERE `access`='guest'"; + $db_results = Dba::write($sql); - // Alter the table - $sql = "ALTER TABLE `user` CHANGE `access` `access` TINYINT ( 4 ) UNSIGNED NOT NULL"; - $db_results = Dba::write($sql); + // Alter the table + $sql = "ALTER TABLE `user` CHANGE `access` `access` TINYINT ( 4 ) UNSIGNED NOT NULL"; + $db_results = Dba::write($sql); - // Add in Label and Catalog # and language - $sql = "ALTER TABLE `song_ext_data` ADD `label` VARCHAR ( 128 ) NULL, ADD `catalog_number` VARCHAR ( 128 ) NULL, ADD `language` VARCHAR ( 128 ) NULL"; - $db_results = Dba::write($sql); + // Add in Label and Catalog # and language + $sql = "ALTER TABLE `song_ext_data` ADD `label` VARCHAR ( 128 ) NULL, ADD `catalog_number` VARCHAR ( 128 ) NULL, ADD `language` VARCHAR ( 128 ) NULL"; + $db_results = Dba::write($sql); - /* Fix every users preferences */ - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + /* Fix every users preferences */ + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } // while results + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } // while results - self::set_version('db_version','340001'); + self::set_version('db_version','340001'); - return true; + return true; - } //update_340001 + } //update_340001 - /** - * update_340002 - * This update tweaks the preferences a little more and make sure that the - * min_object_count has a rational value - */ - private function update_340002() { + /** + * update_340002 + * This update tweaks the preferences a little more and make sure that the + * min_object_count has a rational value + */ + private function update_340002() { - /* Add the offset_limit preference and remove it from the user table */ - $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('offset_limit','50','Offset Limit','5','integer','interface')"; - $db_results = Dba::write($sql); + /* Add the offset_limit preference and remove it from the user table */ + $sql = "INSERT INTO `preferences` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('offset_limit','50','Offset Limit','5','integer','interface')"; + $db_results = Dba::write($sql); - self::set_version('db_version','340002'); + self::set_version('db_version','340002'); - return true; + return true; - } // update_340002 + } // update_340002 - /** - * update_340003 - * This update moves the album art out of the album table - * and puts it in an album_data table. It also makes some - * minor changes to the song table in an attempt to reduce - * the size of each row - */ - public static function update_340003() { + /** + * update_340003 + * This update moves the album art out of the album table + * and puts it in an album_data table. It also makes some + * minor changes to the song table in an attempt to reduce + * the size of each row + */ + public static function update_340003() { - $sql = "ALTER TABLE `song` CHANGE `mode` `mode` ENUM( 'abr', 'vbr', 'cbr' ) NULL DEFAULT 'cbr'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` CHANGE `mode` `mode` ENUM( 'abr', 'vbr', 'cbr' ) NULL DEFAULT 'cbr'"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` CHANGE `time` `time` SMALLINT( 5 ) UNSIGNED NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` CHANGE `time` `time` SMALLINT( 5 ) UNSIGNED NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` CHANGE `rate` `rate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` CHANGE `rate` `rate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` CHANGE `bitrate` `bitrate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` CHANGE `bitrate` `bitrate` MEDIUMINT( 8 ) UNSIGNED NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` CHANGE `track` `track` SMALLINT( 5 ) UNSIGNED NULL DEFAULT NULL "; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` CHANGE `track` `track` SMALLINT( 5 ) UNSIGNED NULL DEFAULT NULL "; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `user` CHANGE `disabled` `disabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `user` CHANGE `disabled` `disabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - $sql = "CREATE TABLE `album_data` (" . - "`album_id` INT( 11 ) UNSIGNED NOT NULL , " . - "`art` MEDIUMBLOB NULL , " . - "`art_mime` VARCHAR( 64 ) NULL , " . - "`thumb` BLOB NULL , " . - "`thumb_mime` VARCHAR( 64 ) NULL , " . - "UNIQUE ( `album_id` )" . - ") ENGINE = MYISAM"; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `album_data` (" . + "`album_id` INT( 11 ) UNSIGNED NOT NULL , " . + "`art` MEDIUMBLOB NULL , " . + "`art_mime` VARCHAR( 64 ) NULL , " . + "`thumb` BLOB NULL , " . + "`thumb_mime` VARCHAR( 64 ) NULL , " . + "UNIQUE ( `album_id` )" . + ") ENGINE = MYISAM"; + $db_results = Dba::write($sql); - /* Foreach the Albums and move the data into the new album_data table */ - $sql = "SELECT * FROM album"; - $db_results = Dba::write($sql); + /* Foreach the Albums and move the data into the new album_data table */ + $sql = "SELECT * FROM album"; + $db_results = Dba::write($sql); - while ($data = Dba::fetch_assoc($db_results)) { - $id = $data['id']; - $art = Dba::escape($data['art']); - $art_mime = Dba::escape($data['art_mime']); - $thumb = Dba::escape($data['thumb']); - $thumb_mime = Dba::escape($data['thumb_mime']); - $sql = "INSERT INTO `album_data` (`album_id`,`art`,`art_mime`,`thumb`,`thumb_mime`)" . - " VALUES ('$id','$art','$art_mime','$thumb','$thumb_mime')"; - $insert_results = Dba::write($sql); - } // end while + while ($data = Dba::fetch_assoc($db_results)) { + $id = $data['id']; + $art = Dba::escape($data['art']); + $art_mime = Dba::escape($data['art_mime']); + $thumb = Dba::escape($data['thumb']); + $thumb_mime = Dba::escape($data['thumb_mime']); + $sql = "INSERT INTO `album_data` (`album_id`,`art`,`art_mime`,`thumb`,`thumb_mime`)" . + " VALUES ('$id','$art','$art_mime','$thumb','$thumb_mime')"; + $insert_results = Dba::write($sql); + } // end while - $sql = "RENAME TABLE `song_ext_data` TO `song_data`"; - $db_results = Dba::write($sql); + $sql = "RENAME TABLE `song_ext_data` TO `song_data`"; + $db_results = Dba::write($sql); - $sql = "RENAME TABLE `preferences` TO `preference`"; - $db_results = Dba::write($sql); + $sql = "RENAME TABLE `preferences` TO `preference`"; + $db_results = Dba::write($sql); - $sql = "RENAME TABLE `ratings` TO `rating`"; - $db_results = Dba::write($sql); + $sql = "RENAME TABLE `ratings` TO `rating`"; + $db_results = Dba::write($sql); - // Go ahead and drop the art/thumb stuff - $sql = "ALTER TABLE `album` DROP `art`, DROP `art_mime`, DROP `thumb`, DROP `thumb_mime`"; - $db_results = Dba::write($sql); + // Go ahead and drop the art/thumb stuff + $sql = "ALTER TABLE `album` DROP `art`, DROP `art_mime`, DROP `thumb`, DROP `thumb_mime`"; + $db_results = Dba::write($sql); - // We need to fix the user_vote table - $sql = "ALTER TABLE `user_vote` CHANGE `user` `user` INT( 11 ) UNSIGNED NOT NULL"; - $db_results = Dba::write($sql); + // We need to fix the user_vote table + $sql = "ALTER TABLE `user_vote` CHANGE `user` `user` INT( 11 ) UNSIGNED NOT NULL"; + $db_results = Dba::write($sql); - // Remove offset limit from the user - $sql = "ALTER TABLE `user` DROP `offset_limit`"; - $db_results = Dba::write($sql); + // Remove offset limit from the user + $sql = "ALTER TABLE `user` DROP `offset_limit`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `rating` CHANGE `user_rating` `rating` ENUM( '-1', '0', '1', '2', '3', '4', '5' ) NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `rating` CHANGE `user_rating` `rating` ENUM( '-1', '0', '1', '2', '3', '4', '5' ) NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - /* Add the rate_limit preference */ - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('rate_limit','8192','Rate Limit','100','integer','streaming')"; - $db_results = Dba::write($sql); + /* Add the rate_limit preference */ + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('rate_limit','8192','Rate Limit','100','integer','streaming')"; + $db_results = Dba::write($sql); - /* Add the playlist_method preference and remove it from the user table */ - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('playlist_method','normal','Playlist Method','5','string','streaming')"; - $db_results = Dba::write($sql); + /* Add the playlist_method preference and remove it from the user table */ + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('playlist_method','normal','Playlist Method','5','string','streaming')"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `update_info` ADD UNIQUE (`key`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `update_info` ADD UNIQUE (`key`)"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } - self::set_version('db_version','340003'); - - return true; - - } // update_340003 - - /** - * update_340004 - * Update the session.id to varchar(64) to handle - * newer configs - */ - public static function update_340004() { + self::set_version('db_version','340003'); + + return true; + + } // update_340003 + + /** + * update_340004 + * Update the session.id to varchar(64) to handle + * newer configs + */ + public static function update_340004() { - /* Alter the session.id so that it's 64 */ - $sql = "ALTER TABLE `session` CHANGE `id` `id` VARCHAR( 64 ) NOT NULL"; - $db_results = Dba::write($sql); + /* Alter the session.id so that it's 64 */ + $sql = "ALTER TABLE `session` CHANGE `id` `id` VARCHAR( 64 ) NOT NULL"; + $db_results = Dba::write($sql); - /* Add Playlist Related Preferences */ - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('playlist_add','append','Add Behavior','5','string','playlist')"; - $db_results = Dba::write($sql); + /* Add Playlist Related Preferences */ + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('playlist_add','append','Add Behavior','5','string','playlist')"; + $db_results = Dba::write($sql); - // Switch the existing preferences over to this new catagory - $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='playlist_method' " . - " OR `name`='playlist_type'"; - $db_results = Dba::write($sql); + // Switch the existing preferences over to this new catagory + $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='playlist_method' " . + " OR `name`='playlist_type'"; + $db_results = Dba::write($sql); - // Change the default value for playlist_method - $sql = "UPDATE `preference` SET `value`='normal' WHERE `name`='playlist_method'"; - $db_results = Dba::write($sql); + // Change the default value for playlist_method + $sql = "UPDATE `preference` SET `value`='normal' WHERE `name`='playlist_method'"; + $db_results = Dba::write($sql); - // Add in the shoutbox - $sql = "CREATE TABLE `user_shout` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , " . - "`user` INT( 11 ) NOT NULL , " . - "`text` TEXT NOT NULL , " . - "`date` INT( 11 ) UNSIGNED NOT NULL , " . - "`sticky` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0', " . - "`object_id` INT( 11 ) UNSIGNED NOT NULL , " . - "`object_type` VARCHAR( 32 ) NOT NULL " . - ") ENGINE = MYISAM"; - $db_results = Dba::write($sql); + // Add in the shoutbox + $sql = "CREATE TABLE `user_shout` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , " . + "`user` INT( 11 ) NOT NULL , " . + "`text` TEXT NOT NULL , " . + "`date` INT( 11 ) UNSIGNED NOT NULL , " . + "`sticky` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0', " . + "`object_id` INT( 11 ) UNSIGNED NOT NULL , " . + "`object_type` VARCHAR( 32 ) NOT NULL " . + ") ENGINE = MYISAM"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `user_shout` ADD INDEX ( `sticky` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `user_shout` ADD INDEX ( `sticky` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `user_shout` ADD INDEX ( `date` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `user_shout` ADD INDEX ( `date` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `user_shout` ADD INDEX ( `user` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `user_shout` ADD INDEX ( `user` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `now_playing` CHANGE `start_time` `expire` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `now_playing` CHANGE `start_time` `expire` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - $sql = "OPTIMIZE TABLE `album`"; - $db_results = Dba::write($sql); + $sql = "OPTIMIZE TABLE `album`"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } - // Update our database version now that we are all done - self::set_version('db_version','340004'); + // Update our database version now that we are all done + self::set_version('db_version','340004'); - return true; + return true; - } // update_340004 + } // update_340004 - /** - * update_340005 - * This update fixes the preferences types - */ - public static function update_340005() { + /** + * update_340005 + * This update fixes the preferences types + */ + public static function update_340005() { - // Turn user_rating into a tinyint and call it score - $sql = "ALTER TABLE `rating` CHANGE `user_rating` `score` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '0'"; - $db_results = Dba::write($sql); + // Turn user_rating into a tinyint and call it score + $sql = "ALTER TABLE `rating` CHANGE `user_rating` `score` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '0'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='random_method'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `catagory`='playlist' WHERE `name`='random_method'"; + $db_results = Dba::write($sql); - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('transcode','default','Transcoding','25','string','streaming')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('transcode','default','Transcoding','25','string','streaming')"; + $db_results = Dba::write($sql); - /* We need to check for playlist_method here because I fubar'd an earlier update */ - $sql = "SELECT * FROM `preference` WHERE `name`='playlist_method'"; - $db_results = Dba::read($sql); - if (!Dba::num_rows($db_results)) { - /* Add the playlist_method preference and remove it from the user table */ - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('playlist_method','default','Playlist Method','5','string','playlist')"; - $db_results = Dba::write($sql); - } + /* We need to check for playlist_method here because I fubar'd an earlier update */ + $sql = "SELECT * FROM `preference` WHERE `name`='playlist_method'"; + $db_results = Dba::read($sql); + if (!Dba::num_rows($db_results)) { + /* Add the playlist_method preference and remove it from the user table */ + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('playlist_method','default','Playlist Method','5','string','playlist')"; + $db_results = Dba::write($sql); + } - // Add in the object_type to the tmpplaylist data table so that we can have non-songs in there - $sql = "ALTER TABLE `tmp_playlist_data` ADD `object_type` VARCHAR( 32 ) NULL AFTER `tmp_playlist`"; - $db_results = Dba::write($sql); + // Add in the object_type to the tmpplaylist data table so that we can have non-songs in there + $sql = "ALTER TABLE `tmp_playlist_data` ADD `object_type` VARCHAR( 32 ) NULL AFTER `tmp_playlist`"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } - self::set_version('db_version','340005'); + self::set_version('db_version','340005'); - return true; + return true; - } // update_340005 + } // update_340005 - /** - * update_340006 - * This just updates the size of the album_data table - * and removes the random_method config option - */ - public static function update_340006() { + /** + * update_340006 + * This just updates the size of the album_data table + * and removes the random_method config option + */ + public static function update_340006() { - $sql = "DESCRIBE `album_data`"; - $db_results = Dba::read($sql); + $sql = "DESCRIBE `album_data`"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - if ($row['Field'] == 'art' AND $row['Type'] == 'blob') { - $blob_needed = true; - } - } // end while - if ($blob_needed) { - $sql = "ALTER TABLE `album_data` CHANGE `art` `art` MEDIUMBLOB NULL DEFAULT NULL"; - $db_results = Dba::write($sql); - } + while ($row = Dba::fetch_assoc($db_results)) { + if ($row['Field'] == 'art' AND $row['Type'] == 'blob') { + $blob_needed = true; + } + } // end while + if ($blob_needed) { + $sql = "ALTER TABLE `album_data` CHANGE `art` `art` MEDIUMBLOB NULL DEFAULT NULL"; + $db_results = Dba::write($sql); + } - // No matter what remove that random method preference - $sql = "DELETE FROM `preference` WHERE `name`='random_method'"; - $db_results = Dba::write($sql); + // No matter what remove that random method preference + $sql = "DELETE FROM `preference` WHERE `name`='random_method'"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } - self::set_version('db_version','340006'); + self::set_version('db_version','340006'); - return true; + return true; - } // update_340006 + } // update_340006 - /** - * update_340007 - * This update converts the session.value to a longtext - * and adds a session_stream table - */ - public static function update_340007() { + /** + * update_340007 + * This update converts the session.value to a longtext + * and adds a session_stream table + */ + public static function update_340007() { - // Tweak the session table to handle larger session vars for my page-a-nation hotness - $sql = "ALTER TABLE `session` CHANGE `value` `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL"; - $db_results = Dba::write($sql); + // Tweak the session table to handle larger session vars for my page-a-nation hotness + $sql = "ALTER TABLE `session` CHANGE `value` `value` LONGTEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL"; + $db_results = Dba::write($sql); - // Create the new stream table where we will store stream SIDs - $sql = "CREATE TABLE `session_stream` ( " . - "`id` VARCHAR( 64 ) NOT NULL , " . - "`user` INT( 11 ) UNSIGNED NOT NULL , " . - "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " . - "`expire` INT( 11 ) UNSIGNED NOT NULL , " . - "`ip` INT( 11 ) UNSIGNED NULL , " . - "PRIMARY KEY ( `id` ) " . - ") ENGINE = MYISAM"; - $db_results = Dba::write($sql); + // Create the new stream table where we will store stream SIDs + $sql = "CREATE TABLE `session_stream` ( " . + "`id` VARCHAR( 64 ) NOT NULL , " . + "`user` INT( 11 ) UNSIGNED NOT NULL , " . + "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " . + "`expire` INT( 11 ) UNSIGNED NOT NULL , " . + "`ip` INT( 11 ) UNSIGNED NULL , " . + "PRIMARY KEY ( `id` ) " . + ") ENGINE = MYISAM"; + $db_results = Dba::write($sql); - // Change the now playing to use stream session ids for its ID - $sql = "ALTER TABLE `now_playing` CHANGE `id` `id` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL"; - $db_results = Dba::write($sql); + // Change the now playing to use stream session ids for its ID + $sql = "ALTER TABLE `now_playing` CHANGE `id` `id` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL"; + $db_results = Dba::write($sql); - // Now longer needed because of the new hotness - $sql = "ALTER TABLE `now_playing` DROP `session`"; - $db_results = Dba::write($sql); + // Now longer needed because of the new hotness + $sql = "ALTER TABLE `now_playing` DROP `session`"; + $db_results = Dba::write($sql); - self::set_version('db_version','340007'); + self::set_version('db_version','340007'); - return true; + return true; - } // update_340007 + } // update_340007 - /** - * update_340008 - * This modifies the playlist table to handle the different types of objects that it needs to be able to - * store, and tweaks how dynamic playlist stuff works - */ - public static function update_340008() { + /** + * update_340008 + * This modifies the playlist table to handle the different types of objects that it needs to be able to + * store, and tweaks how dynamic playlist stuff works + */ + public static function update_340008() { - $sql = "ALTER TABLE `playlist_data` CHANGE `song` `object_id` INT( 11 ) UNSIGNED NULL DEFAULT NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist_data` CHANGE `song` `object_id` INT( 11 ) UNSIGNED NULL DEFAULT NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `playlist_data` CHANGE `dyn_song` `dynamic_song` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist_data` CHANGE `dyn_song` `dynamic_song` TEXT CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `playlist_data` ADD `object_type` VARCHAR( 32 ) NOT NULL DEFAULT 'song' AFTER `object_id`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist_data` ADD `object_type` VARCHAR( 32 ) NOT NULL DEFAULT 'song' AFTER `object_id`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `playlist` ADD `genre` INT( 11 ) UNSIGNED NOT NULL AFTER `type`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist` ADD `genre` INT( 11 ) UNSIGNED NOT NULL AFTER `type`"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `preference` WHERE `name`='allow_downsample_playback'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `preference` WHERE `name`='allow_downsample_playback'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `preference` SET `description`='Transcode Bitrate' WHERE `name`='sample_rate'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `description`='Transcode Bitrate' WHERE `name`='sample_rate'"; + $db_results = Dba::write($sql); - // Check for old tables and drop if found, seems like there was a glitch that caused them - // not to get droped.. *shrug* - $sql = "DROP TABLE IF EXISTS `preferences`"; - $db_results = Dba::write($sql); + // Check for old tables and drop if found, seems like there was a glitch that caused them + // not to get droped.. *shrug* + $sql = "DROP TABLE IF EXISTS `preferences`"; + $db_results = Dba::write($sql); - $sql = "DROP TABLE IF EXISTS `song_ext_data`"; - $db_results = Dba::write($sql); + $sql = "DROP TABLE IF EXISTS `song_ext_data`"; + $db_results = Dba::write($sql); - $sql = "DROP TABLE IF EXISTS `ratings`"; - $db_results = Dba::write($sql); + $sql = "DROP TABLE IF EXISTS `ratings`"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } - self::set_version('db_version','340008'); + self::set_version('db_version','340008'); - return true; + return true; - } // update_340008 + } // update_340008 - /** - * update_340009 - * This modifies the song table to handle pos fields - */ - public static function update_340009() { + /** + * update_340009 + * This modifies the song table to handle pos fields + */ + public static function update_340009() { - $sql = "ALTER TABLE `album` ADD `disk` smallint(5) UNSIGNED DEFAULT NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `album` ADD `disk` smallint(5) UNSIGNED DEFAULT NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `album` ADD INDEX (`disk`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `album` ADD INDEX (`disk`)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `access_list` ADD `dns` VARCHAR( 255 ) NOT NULL AFTER `end`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `access_list` ADD `dns` VARCHAR( 255 ) NOT NULL AFTER `end`"; + $db_results = Dba::write($sql); - $sql = "CREATE TABLE `artist_data` (" . - "`artist_id` INT( 11 ) UNSIGNED NOT NULL ," . - "`art` MEDIUMBLOB NOT NULL ," . - "`art_mime` VARCHAR( 32 ) NOT NULL ," . - "`thumb` BLOB NOT NULL ," . - "`thumb_mime` VARCHAR( 32 ) NOT NULL ," . - "`bio` TEXT NOT NULL , " . - "UNIQUE (`artist_id`) ) ENGINE = MYISAM"; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `artist_data` (" . + "`artist_id` INT( 11 ) UNSIGNED NOT NULL ," . + "`art` MEDIUMBLOB NOT NULL ," . + "`art_mime` VARCHAR( 32 ) NOT NULL ," . + "`thumb` BLOB NOT NULL ," . + "`thumb_mime` VARCHAR( 32 ) NOT NULL ," . + "`bio` TEXT NOT NULL , " . + "UNIQUE (`artist_id`) ) ENGINE = MYISAM"; + $db_results = Dba::write($sql); - self::set_version('db_version','340009'); + self::set_version('db_version','340009'); - return true; + return true; - } // update_340009 + } // update_340009 - /** - * update_340010 - * Bunch of minor tweaks to the preference table - */ - public static function update_340010() { + /** + * update_340010 + * Bunch of minor tweaks to the preference table + */ + public static function update_340010() { - $sql = "UPDATE `preference` SET `catagory`='options' WHERE `name` LIKE 'localplay_%'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `catagory`='options' WHERE `name` LIKE 'localplay_%'"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `preference` WHERE `name`='playlist_add'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `preference` WHERE `name`='playlist_add'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `preference` SET `catagory`='plugins' WHERE (`name` LIKE 'mystrands_%' OR `name` LIKE 'lastfm_%') AND `catagory`='options'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `catagory`='plugins' WHERE (`name` LIKE 'mystrands_%' OR `name` LIKE 'lastfm_%') AND `catagory`='options'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `preference` SET `value`='default' WHERE `name`='playlist_method'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `value`='default' WHERE `name`='playlist_method'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `preference` SET `description`='Localplay Config' WHERE `name`='localplay_level'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `description`='Localplay Config' WHERE `name`='localplay_level'"; + $db_results = Dba::write($sql); - /* Fix every users preferences */ - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + /* Fix every users preferences */ + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } // while results + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } // while results - self::set_version('db_version','340010'); + self::set_version('db_version','340010'); - return true; + return true; - } // update_340010 + } // update_340010 - /** - * update_340011 - * This updates the democratic play stuff so that can handle a little more complext mojo - * It also adds yet another table to the db to handle the sessions for API access. Eventually - * should combine all of the session tables, but I'll do that later - */ - public static function update_340011() { + /** + * update_340011 + * This updates the democratic play stuff so that can handle a little more complext mojo + * It also adds yet another table to the db to handle the sessions for API access. Eventually + * should combine all of the session tables, but I'll do that later + */ + public static function update_340011() { - // First add the new table for the new session stuff - $sql = "CREATE TABLE `session_api` ( " . - "`id` VARCHAR( 64 ) NOT NULL , " . - "`user` INT( 11 ) UNSIGNED NOT NULL , " . - "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " . - "`level` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', " . - "`expire` INT( 11 ) UNSIGNED NOT NULL , " . - "`ip` INT( 11 ) UNSIGNED NULL , " . - "PRIMARY KEY ( `id` ) " . - ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; - $db_results = Dba::write($sql); + // First add the new table for the new session stuff + $sql = "CREATE TABLE `session_api` ( " . + "`id` VARCHAR( 64 ) NOT NULL , " . + "`user` INT( 11 ) UNSIGNED NOT NULL , " . + "`agent` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL , " . + "`level` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0', " . + "`expire` INT( 11 ) UNSIGNED NOT NULL , " . + "`ip` INT( 11 ) UNSIGNED NULL , " . + "PRIMARY KEY ( `id` ) " . + ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; + $db_results = Dba::write($sql); - self::set_version('db_version','340011'); + self::set_version('db_version','340011'); - return true; + return true; - } // 340011 + } // 340011 - /** - * update_340012 - * This update adds in the democratic stuff, checks for some potentially screwed up indexes - * and removes the timestamp from the playlist, and adds the field to the catalog for the upload dir - */ - public static function update_340012() { + /** + * update_340012 + * This update adds in the democratic stuff, checks for some potentially screwed up indexes + * and removes the timestamp from the playlist, and adds the field to the catalog for the upload dir + */ + public static function update_340012() { - $sql = "ALTER TABLE `catalog` ADD `add_path` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER `path`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `catalog` ADD `add_path` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL AFTER `path`"; + $db_results = Dba::write($sql); - $sql = "CREATE TABLE `democratic` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . - "`name` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ," . - "`cooldown` TINYINT( 4 ) UNSIGNED NULL ," . - "`level` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '25'," . - "`user` INT( 11 ) NOT NULL ," . - "`primary` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'" . - ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `democratic` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . + "`name` VARCHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ," . + "`cooldown` TINYINT( 4 ) UNSIGNED NULL ," . + "`level` TINYINT( 4 ) UNSIGNED NOT NULL DEFAULT '25'," . + "`user` INT( 11 ) NOT NULL ," . + "`primary` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0'" . + ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `democratic` ADD INDEX (`primary`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `democratic` ADD INDEX (`primary`)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `democratic` ADD INDEX (`level`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `democratic` ADD INDEX (`level`)"; + $db_results = Dba::write($sql); - self::set_version('db_version','340012'); + self::set_version('db_version','340012'); - return true; + return true; - } // update_340012 + } // update_340012 - /** - * update_340013 - * This update removes a whole bunch of preferences that are no longer - * being used in any way, and changes the ACL XML-RPC to just RPC - */ - public static function update_340013() { + /** + * update_340013 + * This update removes a whole bunch of preferences that are no longer + * being used in any way, and changes the ACL XML-RPC to just RPC + */ + public static function update_340013() { - $sql = "DELETE FROM `preference` WHERE `name`='localplay_mpd_hostname' OR `name`='localplay_mpd_port' " . - "OR `name`='direct_link' OR `name`='localplay_mpd_password' OR `name`='catalog_echo_count'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `preference` WHERE `name`='localplay_mpd_hostname' OR `name`='localplay_mpd_port' " . + "OR `name`='direct_link' OR `name`='localplay_mpd_password' OR `name`='catalog_echo_count'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `preference` SET `description`='Localplay Access' WHERE `name`='localplay_level'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `preference` SET `description`='Localplay Access' WHERE `name`='localplay_level'"; + $db_results = Dba::write($sql); - $sql = "UPDATE `access_list` SET `type`='rpc' WHERE `type`='xml-rpc'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `access_list` SET `type`='rpc' WHERE `type`='xml-rpc'"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } // while we're fixing the useres stuff + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } // while we're fixing the useres stuff - self::set_version('db_version','340013'); + self::set_version('db_version','340013'); - return true; + return true; - } // update_340013 + } // update_340013 - /** - * update_340014 - * This update drops the session_api table that I added just two updates ago - * it's been nice while it lasted but it's time to pack your stuff and GTFO - * at the same time it updates the core session table to handle the additional - * stuff we're going to ask it to do. - */ - public static function update_340014() { + /** + * update_340014 + * This update drops the session_api table that I added just two updates ago + * it's been nice while it lasted but it's time to pack your stuff and GTFO + * at the same time it updates the core session table to handle the additional + * stuff we're going to ask it to do. + */ + public static function update_340014() { - $sql = "DROP TABLE `session_api`"; - $db_results = Dba::write($sql); + $sql = "DROP TABLE `session_api`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `session` CHANGE `type` `type` ENUM ('mysql','ldap','http','api','xml-rpc') NOT NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `session` CHANGE `type` `type` ENUM ('mysql','ldap','http','api','xml-rpc') NOT NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `session` ADD `agent` VARCHAR ( 255 ) NOT NULL AFTER `type`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `session` ADD `agent` VARCHAR ( 255 ) NOT NULL AFTER `type`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `session` ADD INDEX (`type`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `session` ADD INDEX (`type`)"; + $db_results = Dba::write($sql); - self::set_version('db_version','340014'); + self::set_version('db_version','340014'); - return true; + return true; - } // update_340014 + } // update_340014 - /** - * update_340015 - * This update tweaks the playlist table responding to complaints from usres - * who say it doesn't work, unreproduceable. This also adds an index to the - * album art table to try to make the random album art faster - */ - public static function update_340015() { + /** + * update_340015 + * This update tweaks the playlist table responding to complaints from usres + * who say it doesn't work, unreproduceable. This also adds an index to the + * album art table to try to make the random album art faster + */ + public static function update_340015() { - $sql = "ALTER TABLE `playlist` DROP `date`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist` DROP `date`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `playlist` ADD `date` INT ( 11 ) UNSIGNED NOT NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist` ADD `date` INT ( 11 ) UNSIGNED NOT NULL"; + $db_results = Dba::write($sql); - // Pull all of the rating information - $sql = "SELECT `id`,`rating` FROM `rating`"; - $db_results = Dba::read($sql); + // Pull all of the rating information + $sql = "SELECT `id`,`rating` FROM `rating`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row; + } - $sql = "ALTER TABLE `rating` DROP `rating`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `rating` DROP `rating`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `rating` ADD `rating` TINYINT ( 4 ) NOT NULL"; - $db_results = Dba::write($sql); - - foreach ($results as $row) { - $rating = Dba::escape($row['rating']); - $id = Dba::escape($row['id']); - $sql = "UPDATE `rating` SET `rating`='$rating' WHERE `id`='$id'"; - $db_results = Dba::write($sql); - } - - self::set_version('db_version','340015'); - - return true; - - } // update_340015 - - /** - * update_340016 - * This adds in the base_playlist to the democratic table... should have - * done this in the previous one but I screwed up... sigh - */ - public static function update_340016() { - - $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT ( 11 ) UNSIGNED NOT NULL"; - $db_results = Dba::write($sql); - - self::set_version('db_version','340016'); - - return true; - - } // update_340016 - - /** - * update_340017 - * This finalizes the democratic table. - * and fixes the charset crap - */ - public static function update_340017() { - - $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT( 11 ) UNSIGNED NOT NULL AFTER `name`"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `tmp_playlist` DROP `base_playlist`"; - $db_results = Dba::write($sql); - - $sql = "DELETE FROM `tmp_playlist` WHERE `session`='-1'"; - $db_results = Dba::write($sql); - - $sql = "TRUNCATE `democratic`"; - $db_results = Dba::write($sql); - - self::set_version('db_version','340017'); - - return true; - - } // update_340017 - - /** - * update_340018 - * This attempts to correct the charset on your database, it does some checking - * to make sure that if we do this it will actually will work. We will fail this update - * if it would cause problems - */ - public static function update_340018() { - - // MySQL translate real charset names into fancy smancy MySQL land names - switch (strtoupper(Config::get('site_charset'))) { - case 'CP1250': - case 'WINDOWS-1250': - case 'WINDOWS-1252': - $target_charset = 'cp1250'; - $target_collation = 'cp1250_general_ci'; - break; - case 'ISO-8859': - case 'ISO-8859-2': - $target_charset = 'latin2'; - $target_collation = 'latin2_general_ci'; - break; - case 'ISO-8859-1': - $target_charset = 'latin1'; - $target_charset = 'latin1_general_ci'; - break; - case 'EUC-KR': - $target_charset = 'euckr'; - $target_collation = 'euckr_korean_ci'; - break; - case 'CP932': - $target_charset = 'sjis'; - $target_collation = 'sjis_japanese_ci'; - break; - case 'KOI8-U': - $target_charset = 'koi8u'; - $target_collation = 'koi8u_general_ci'; - break; - case 'KOI8-R': - $target_charset = 'koi8r'; - $target_collation = 'koi8r_general_ci'; - break; - case 'ISO-8859': - $target_charset = 'latin2'; - $target_collation = 'latin2_general_ci'; - break; - default; - case 'UTF-8': - $target_charset = 'utf8'; - $target_collation = 'utf8_unicode_ci'; - break; - } // end mysql charset translation - - // Alter the charset for the entire database - $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; - $db_results = Dba::write($sql); - - $sql = "SHOW TABLES"; - $db_results = Dba::read($sql); - - // Go through the tables! - while ($row = Dba::fetch_row($db_results)) { - $sql = "DESCRIBE `" . $row['0'] . "`"; - $describe_results = Dba::read($sql); - - // Change the tables default charset and colliation - $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; - $alter_table = Dba::write($sql); - - // Itterate through the columns of the table - while ($table = Dba::fetch_assoc($describe_results)) { - if ( - (strpos($table['Type'], 'varchar') !== false) || - (strpos($table['Type'], 'enum') !== false) || - strpos($table['Table'],'text') !== false) { - $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset; - $charset_results = Dba::write($sql); - if (!$charset_results) { - debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3'); - } // if it fails - } // if its a varchar - } // end columns - - } // end tables - - self::set_version('db_version','340018'); - - return true; - - } // update_340018 - - /** - * update_350001 - * This updates modifies the tag tables per codeunde1load's specs from his tag patch - * it also adjusts the prefix fields so that we can use more prefixes - */ - public static function update_350001() { - - $sql = "ALTER TABLE `tag_map` ADD `tag_id` INT ( 11 ) UNSIGNED NOT NULL AFTER `id`"; - $db_results = Dba::write($sql); - - $sql = "RENAME TABLE `tags` TO `tag`"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `tag` CHANGE `map_id` `id` INT ( 11 ) UNSIGNED NOT NULL auto_increment"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `album` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `artist` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL"; - $db_results = Dba::write($sql); - - self::set_version('db_version','350001'); - - return true; - - } // update_350001 - - /** - * update_350002 - * This update adds in the browse_cache table that we use to hold peoples cached browse results - * rather then try to store everything in the session we split them out into one serilized array per - * row, per person. A little slow this way when browsing, but faster when now browsing and more flexible - */ - public static function update_350002() { - - $sql = "CREATE TABLE `tmp_browse` (`sid` varchar(128) NOT NULL,`data` longtext NOT NULL," . - " UNIQUE KEY `sid` (`sid`)) ENGINE=MyISAM"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `tmp_browse` ADD INDEX ( `type` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `rating` ADD `rating` TINYINT ( 4 ) NOT NULL"; + $db_results = Dba::write($sql); + + foreach ($results as $row) { + $rating = Dba::escape($row['rating']); + $id = Dba::escape($row['id']); + $sql = "UPDATE `rating` SET `rating`='$rating' WHERE `id`='$id'"; + $db_results = Dba::write($sql); + } + + self::set_version('db_version','340015'); + + return true; + + } // update_340015 + + /** + * update_340016 + * This adds in the base_playlist to the democratic table... should have + * done this in the previous one but I screwed up... sigh + */ + public static function update_340016() { + + $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT ( 11 ) UNSIGNED NOT NULL"; + $db_results = Dba::write($sql); + + self::set_version('db_version','340016'); + + return true; + + } // update_340016 + + /** + * update_340017 + * This finalizes the democratic table. + * and fixes the charset crap + */ + public static function update_340017() { + + $sql = "ALTER TABLE `democratic` ADD `base_playlist` INT( 11 ) UNSIGNED NOT NULL AFTER `name`"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `tmp_playlist` DROP `base_playlist`"; + $db_results = Dba::write($sql); + + $sql = "DELETE FROM `tmp_playlist` WHERE `session`='-1'"; + $db_results = Dba::write($sql); + + $sql = "TRUNCATE `democratic`"; + $db_results = Dba::write($sql); + + self::set_version('db_version','340017'); + + return true; + + } // update_340017 + + /** + * update_340018 + * This attempts to correct the charset on your database, it does some checking + * to make sure that if we do this it will actually will work. We will fail this update + * if it would cause problems + */ + public static function update_340018() { + + // MySQL translate real charset names into fancy smancy MySQL land names + switch (strtoupper(Config::get('site_charset'))) { + case 'CP1250': + case 'WINDOWS-1250': + case 'WINDOWS-1252': + $target_charset = 'cp1250'; + $target_collation = 'cp1250_general_ci'; + break; + case 'ISO-8859': + case 'ISO-8859-2': + $target_charset = 'latin2'; + $target_collation = 'latin2_general_ci'; + break; + case 'ISO-8859-1': + $target_charset = 'latin1'; + $target_charset = 'latin1_general_ci'; + break; + case 'EUC-KR': + $target_charset = 'euckr'; + $target_collation = 'euckr_korean_ci'; + break; + case 'CP932': + $target_charset = 'sjis'; + $target_collation = 'sjis_japanese_ci'; + break; + case 'KOI8-U': + $target_charset = 'koi8u'; + $target_collation = 'koi8u_general_ci'; + break; + case 'KOI8-R': + $target_charset = 'koi8r'; + $target_collation = 'koi8r_general_ci'; + break; + case 'ISO-8859': + $target_charset = 'latin2'; + $target_collation = 'latin2_general_ci'; + break; + default; + case 'UTF-8': + $target_charset = 'utf8'; + $target_collation = 'utf8_unicode_ci'; + break; + } // end mysql charset translation + + // Alter the charset for the entire database + $sql = "ALTER DATABASE `" . Config::get('database_name') . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; + $db_results = Dba::write($sql); + + $sql = "SHOW TABLES"; + $db_results = Dba::read($sql); + + // Go through the tables! + while ($row = Dba::fetch_row($db_results)) { + $sql = "DESCRIBE `" . $row['0'] . "`"; + $describe_results = Dba::read($sql); + + // Change the tables default charset and colliation + $sql = "ALTER TABLE `" . $row['0'] . "` DEFAULT CHARACTER SET $target_charset COLLATE $target_collation"; + $alter_table = Dba::write($sql); + + // Itterate through the columns of the table + while ($table = Dba::fetch_assoc($describe_results)) { + if ( + (strpos($table['Type'], 'varchar') !== false) || + (strpos($table['Type'], 'enum') !== false) || + strpos($table['Table'],'text') !== false) { + $sql = "ALTER TABLE `" . $row['0'] . "` MODIFY `" . $table['Field'] . "` " . $table['Type'] . " CHARACTER SET " . $target_charset; + $charset_results = Dba::write($sql); + if (!$charset_results) { + debug_event('CHARSET','Unable to update the charset of ' . $table['Field'] . '.' . $table['Type'] . ' to ' . $target_charset,'3'); + } // if it fails + } // if its a varchar + } // end columns + + } // end tables + + self::set_version('db_version','340018'); + + return true; + + } // update_340018 + + /** + * update_350001 + * This updates modifies the tag tables per codeunde1load's specs from his tag patch + * it also adjusts the prefix fields so that we can use more prefixes + */ + public static function update_350001() { + + $sql = "ALTER TABLE `tag_map` ADD `tag_id` INT ( 11 ) UNSIGNED NOT NULL AFTER `id`"; + $db_results = Dba::write($sql); + + $sql = "RENAME TABLE `tags` TO `tag`"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `tag` CHANGE `map_id` `id` INT ( 11 ) UNSIGNED NOT NULL auto_increment"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `album` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `artist` CHANGE `prefix` `prefix` VARCHAR ( 32 ) NULL"; + $db_results = Dba::write($sql); + + self::set_version('db_version','350001'); + + return true; + + } // update_350001 + + /** + * update_350002 + * This update adds in the browse_cache table that we use to hold peoples cached browse results + * rather then try to store everything in the session we split them out into one serilized array per + * row, per person. A little slow this way when browsing, but faster when now browsing and more flexible + */ + public static function update_350002() { + + $sql = "CREATE TABLE `tmp_browse` (`sid` varchar(128) NOT NULL,`data` longtext NOT NULL," . + " UNIQUE KEY `sid` (`sid`)) ENGINE=MyISAM"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `tmp_browse` ADD INDEX ( `type` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` DROP `genre`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` DROP `genre`"; + $db_results = Dba::write($sql); - $sql = "CREATE TABLE `user_catalog` (`user` INT( 11 ) UNSIGNED NOT NULL ,`catalog` INT( 11 ) UNSIGNED NOT NULL ,`level` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '5', " . - "INDEX ( `user` )) ENGINE = MYISAM"; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `user_catalog` (`user` INT( 11 ) UNSIGNED NOT NULL ,`catalog` INT( 11 ) UNSIGNED NOT NULL ,`level` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '5', " . + "INDEX ( `user` )) ENGINE = MYISAM"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `user_catalog` ADD INDEX ( `catalog` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `user_catalog` ADD INDEX ( `catalog` )"; + $db_results = Dba::write($sql); - self::set_version('db_version','350002'); + self::set_version('db_version','350002'); - return true; + return true; - } // update_350002 + } // update_350002 - /** - * update_350003 - * This update tweakes the tag tables a little bit more, we're going to simplify things for the first little bit and then - * then if it all works out we will worry about making it complex again. One thing at a time people... - */ - public static function update_350003() { + /** + * update_350003 + * This update tweakes the tag tables a little bit more, we're going to simplify things for the first little bit and then + * then if it all works out we will worry about making it complex again. One thing at a time people... + */ + public static function update_350003() { - $sql = "ALTER TABLE `tag` DROP `order`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `tag` DROP `order`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `tag` DROP INDEX `order`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `tag` DROP INDEX `order`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `tag` ADD UNIQUE ( `name` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `tag` ADD UNIQUE ( `name` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `tag` CHANGE `name` `name` VARCHAR( 255 )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `tag` CHANGE `name` `name` VARCHAR( 255 )"; + $db_results = Dba::write($sql); - // Make sure that they don't have any of the mystrands crap left - $sql = "DELETE FROM `preference` WHERE `name`='mystrands_user' OR `name`='mystrands_pass'"; - $db_results = Dba::write($sql); + // Make sure that they don't have any of the mystrands crap left + $sql = "DELETE FROM `preference` WHERE `name`='mystrands_user' OR `name`='mystrands_pass'"; + $db_results = Dba::write($sql); - self::set_version('db_version','350003'); + self::set_version('db_version','350003'); - return true; + return true; - } // update_350003 + } // update_350003 - /** - * update_350004 - * This update makes some changes to the ACL table so that it can support IPv6 entries as well as some other feature - * enhancements - */ - public static function update_350004() { + /** + * update_350004 + * This update makes some changes to the ACL table so that it can support IPv6 entries as well as some other feature + * enhancements + */ + public static function update_350004() { - $sql = "ALTER TABLE `session` CHANGE `ip` `ip` VARBINARY( 255 ) NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `session` CHANGE `ip` `ip` VARBINARY( 255 ) NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `session_stream` CHANGE `ip` `ip` VARBINARY( 255 ) NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `session_stream` CHANGE `ip` `ip` VARBINARY( 255 ) NULL"; + $db_results = Dba::write($sql); - // Pull all of the IP history, this could take a while - $sql = "SELECT * FROM `ip_history`"; - $db_results = Dba::read($sql); + // Pull all of the IP history, this could take a while + $sql = "SELECT * FROM `ip_history`"; + $db_results = Dba::read($sql); - $ip_history = array(); + $ip_history = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $row['ip'] = long2ip($row['ip']); - $ip_history[] = $row; - } - - // Clear the table before we make the changes - $sql = "TRUNCATE `ip_history`"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `ip_history` CHANGE `ip` `ip` VARBINARY( 255 ) NULL"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `ip_history` ADD `agent` VARCHAR ( 255 ) NULL AFTER `date`"; - $db_results = Dba::write($sql); - - // Reinsert the old rows - foreach ($ip_history as $row) { - $ip = Dba::escape(inet_pton($row['ip'])); - $sql = "INSERT INTO `ip_history` (`user`,`ip`,`date`,`agent`) " . - "VALUES ('" . $row['user'] . "','" . $ip . "','" . $row['date'] . "',NULL)"; - $db_results = Dba::write($sql); - } - - // First pull all of their current ACL's - $sql = "SELECT * FROM `access_list`"; - $db_results = Dba::read($sql); - - $acl_information = array(); + while ($row = Dba::fetch_assoc($db_results)) { + $row['ip'] = long2ip($row['ip']); + $ip_history[] = $row; + } + + // Clear the table before we make the changes + $sql = "TRUNCATE `ip_history`"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `ip_history` CHANGE `ip` `ip` VARBINARY( 255 ) NULL"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `ip_history` ADD `agent` VARCHAR ( 255 ) NULL AFTER `date`"; + $db_results = Dba::write($sql); + + // Reinsert the old rows + foreach ($ip_history as $row) { + $ip = Dba::escape(inet_pton($row['ip'])); + $sql = "INSERT INTO `ip_history` (`user`,`ip`,`date`,`agent`) " . + "VALUES ('" . $row['user'] . "','" . $ip . "','" . $row['date'] . "',NULL)"; + $db_results = Dba::write($sql); + } + + // First pull all of their current ACL's + $sql = "SELECT * FROM `access_list`"; + $db_results = Dba::read($sql); + + $acl_information = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $row['start'] = long2ip($row['start']); - $row['end'] = long2ip($row['end']); - $acl_information[] = $row; - } - - $sql = "TRUNCATE `access_list`"; - $db_results = Dba::write($sql); - - // Make the changes to the database - $sql = "ALTER TABLE `access_list` CHANGE `start` `start` VARBINARY( 255 ) NOT NULL"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `access_list` CHANGE `end` `end` VARBINARY( 255 ) NOT NULL"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `access_list` DROP `dns`"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `access_list` ADD `enabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1' AFTER `key`"; - $db_results = Dba::write($sql); - - // If we had nothing in there before add some base ALLOW ALL stuff as we're going - // to start defaulting Access Control to On. - if (!count($acl_information)) { - $v6_start = Dba::escape(inet_pton('::')); - $v6_end = Dba::escape(inet_pton('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')); - $v4_start = Dba::escape(inet_pton('0.0.0.0')); - $v4_end = Dba::escape(inet_pton('255.255.255.255')); - $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . - "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','interface','1')"; - $db_results = Dba::write($sql); - $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . - "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','stream','1')"; - $db_results = Dba::write($sql); - $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . - "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','interface','1')"; - $db_results = Dba::write($sql); - $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . - "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','stream','1')"; - $db_results = Dba::write($sql); - } // Adding default information - - foreach ($acl_information as $row) { - $row['start'] = Dba::escape(inet_pton($row['start'])); - $row['end'] = Dba::escape(inet_pton($row['end'])); - $row['key'] = Dba::escape($row['key']); - $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . - "VALUES ('" . Dba::escape($row['name']) . "','" . intval($row['level']) . - "','" . $row['start'] . "','" . $row['end'] . "','" . $row['key'] . "','" . intval($row['user']) . "','" . - $row['type'] . "','1')"; - $db_results = Dba::write($sql); - } // end foreach of existing rows - - self::set_version('db_version','350004'); - - return true; - - } // update_350004 - - /** - * update_350005 - * This update adds the video table... *gasp* no you didn't - */ - public static function update_350005() { - - $sql = " CREATE TABLE `video` (" . - "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . - "`file` VARCHAR( 255 ) NOT NULL , " . - "`catalog` INT( 11 ) UNSIGNED NOT NULL ," . - "`title` VARCHAR( 255 ) NOT NULL ," . - "`video_codec` VARCHAR( 255 ) NOT NULL ," . - "`audio_codec` VARCHAR( 255 ) NOT NULL ," . - "`resolution_x` MEDIUMINT UNSIGNED NOT NULL ," . - "`resolution_y` MEDIUMINT UNSIGNED NOT NULL ," . - "`time` INT( 11 ) UNSIGNED NOT NULL ," . - "`size` BIGINT UNSIGNED NOT NULL," . - "`mime` VARCHAR( 255 ) NOT NULL," . - "`enabled` TINYINT( 1) NOT NULL DEFAULT '1'" . - ") ENGINE = MYISAM "; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `access_list` ADD INDEX ( `enabled` )"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `video` ADD INDEX ( `file` )"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `video` ADD INDEX ( `enabled` )"; - $db_results = Dba::write($sql); - - $sql = "ALTER TABLE `video` ADD INDEX ( `title` )"; - $db_results = Dba::write($sql); - - self::set_version('db_version','350005'); - - return true; - - } // update_350005 - - /** - * update_350006 - * This update inserts the Lyrics pref table... - */ - public static function update_350006() { - - $sql = "INSERT INTO `preference` VALUES (69,'show_lyrics','0','Show Lyrics',0,'boolean','interface')"; - $db_results = Dba::write($sql); - - $sql = "INSERT INTO `user_preference` VALUES (1,69,'0')"; - $db_results = Dba::write($sql); - - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); - - User::fix_preferences('-1'); - - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } // while we're fixing the useres stuff - - self::set_version('db_version','350006'); - - return true; - - } // update_350006 - - /** - * update_350007 - * This update adds in the random rules tables, and also increases the size of the blobs - * on the album and artist data. Also add track to tmp_playlist_data - */ - public static function update_350007() { + while ($row = Dba::fetch_assoc($db_results)) { + $row['start'] = long2ip($row['start']); + $row['end'] = long2ip($row['end']); + $acl_information[] = $row; + } + + $sql = "TRUNCATE `access_list`"; + $db_results = Dba::write($sql); + + // Make the changes to the database + $sql = "ALTER TABLE `access_list` CHANGE `start` `start` VARBINARY( 255 ) NOT NULL"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `access_list` CHANGE `end` `end` VARBINARY( 255 ) NOT NULL"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `access_list` DROP `dns`"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `access_list` ADD `enabled` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1' AFTER `key`"; + $db_results = Dba::write($sql); + + // If we had nothing in there before add some base ALLOW ALL stuff as we're going + // to start defaulting Access Control to On. + if (!count($acl_information)) { + $v6_start = Dba::escape(inet_pton('::')); + $v6_end = Dba::escape(inet_pton('ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff')); + $v4_start = Dba::escape(inet_pton('0.0.0.0')); + $v4_end = Dba::escape(inet_pton('255.255.255.255')); + $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . + "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','interface','1')"; + $db_results = Dba::write($sql); + $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . + "VALUES ('DEFAULTv4','75','$v4_start','$v4_end',NULL,'-1','stream','1')"; + $db_results = Dba::write($sql); + $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . + "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','interface','1')"; + $db_results = Dba::write($sql); + $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . + "VALUES ('DEFAULTv6','75','$v6_start','$v6_end',NULL,'-1','stream','1')"; + $db_results = Dba::write($sql); + } // Adding default information + + foreach ($acl_information as $row) { + $row['start'] = Dba::escape(inet_pton($row['start'])); + $row['end'] = Dba::escape(inet_pton($row['end'])); + $row['key'] = Dba::escape($row['key']); + $sql = "INSERT INTO `access_list` (`name`,`level`,`start`,`end`,`key`,`user`,`type`,`enabled`) " . + "VALUES ('" . Dba::escape($row['name']) . "','" . intval($row['level']) . + "','" . $row['start'] . "','" . $row['end'] . "','" . $row['key'] . "','" . intval($row['user']) . "','" . + $row['type'] . "','1')"; + $db_results = Dba::write($sql); + } // end foreach of existing rows + + self::set_version('db_version','350004'); + + return true; + + } // update_350004 + + /** + * update_350005 + * This update adds the video table... *gasp* no you didn't + */ + public static function update_350005() { + + $sql = " CREATE TABLE `video` (" . + "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . + "`file` VARCHAR( 255 ) NOT NULL , " . + "`catalog` INT( 11 ) UNSIGNED NOT NULL ," . + "`title` VARCHAR( 255 ) NOT NULL ," . + "`video_codec` VARCHAR( 255 ) NOT NULL ," . + "`audio_codec` VARCHAR( 255 ) NOT NULL ," . + "`resolution_x` MEDIUMINT UNSIGNED NOT NULL ," . + "`resolution_y` MEDIUMINT UNSIGNED NOT NULL ," . + "`time` INT( 11 ) UNSIGNED NOT NULL ," . + "`size` BIGINT UNSIGNED NOT NULL," . + "`mime` VARCHAR( 255 ) NOT NULL," . + "`enabled` TINYINT( 1) NOT NULL DEFAULT '1'" . + ") ENGINE = MYISAM "; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `access_list` ADD INDEX ( `enabled` )"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `video` ADD INDEX ( `file` )"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `video` ADD INDEX ( `enabled` )"; + $db_results = Dba::write($sql); + + $sql = "ALTER TABLE `video` ADD INDEX ( `title` )"; + $db_results = Dba::write($sql); + + self::set_version('db_version','350005'); + + return true; + + } // update_350005 + + /** + * update_350006 + * This update inserts the Lyrics pref table... + */ + public static function update_350006() { + + $sql = "INSERT INTO `preference` VALUES (69,'show_lyrics','0','Show Lyrics',0,'boolean','interface')"; + $db_results = Dba::write($sql); + + $sql = "INSERT INTO `user_preference` VALUES (1,69,'0')"; + $db_results = Dba::write($sql); + + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); + + User::fix_preferences('-1'); + + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } // while we're fixing the useres stuff + + self::set_version('db_version','350006'); + + return true; + + } // update_350006 + + /** + * update_350007 + * This update adds in the random rules tables, and also increases the size of the blobs + * on the album and artist data. Also add track to tmp_playlist_data + */ + public static function update_350007() { - // We need to clear the thumbs as they will need to be re-generated - $sql = "UPDATE `album_data` SET `thumb`=NULL,`thumb_mime`=NULL"; - $db_results = Dba::write($sql); + // We need to clear the thumbs as they will need to be re-generated + $sql = "UPDATE `album_data` SET `thumb`=NULL,`thumb_mime`=NULL"; + $db_results = Dba::write($sql); - $sql = "UPDATE `artist_data` SET `thumb`=NULL,`thumb_mime`=NULL"; - $db_results = Dba::write($sql); + $sql = "UPDATE `artist_data` SET `thumb`=NULL,`thumb_mime`=NULL"; + $db_results = Dba::write($sql); - // Change the db thumb sizes - $sql = "ALTER TABLE `album_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL"; - $db_results = Dba::write($sql); + // Change the db thumb sizes + $sql = "ALTER TABLE `album_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `artist_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `artist_data` CHANGE `thumb` `thumb` MEDIUMBLOB NULL"; + $db_results = Dba::write($sql); - // Remove dead column - $sql = "ALTER TABLE `playlist_data` DROP `dynamic_song`"; - $db_results = Dba::write($sql); + // Remove dead column + $sql = "ALTER TABLE `playlist_data` DROP `dynamic_song`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `playlist` DROP `genre`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `playlist` DROP `genre`"; + $db_results = Dba::write($sql); - // Add track item to tmp_playlist_data so we can order this stuff manually - $sql = "ALTER TABLE `tmp_playlist_data` ADD `track` INT ( 11 ) UNSIGNED NULL"; - $db_results = Dba::write($sql); + // Add track item to tmp_playlist_data so we can order this stuff manually + $sql = "ALTER TABLE `tmp_playlist_data` ADD `track` INT ( 11 ) UNSIGNED NULL"; + $db_results = Dba::write($sql); - $sql = "DROP TABLE `genre`"; - $db_results = Dba::write($sql); + $sql = "DROP TABLE `genre`"; + $db_results = Dba::write($sql); - // Clean up the catalog and add last_clean to it - $sql = "ALTER TABLE `catalog` ADD `last_clean` INT ( 11 ) UNSIGNED NULL AFTER `last_update`"; - $db_results = Dba::write($sql); + // Clean up the catalog and add last_clean to it + $sql = "ALTER TABLE `catalog` ADD `last_clean` INT ( 11 ) UNSIGNED NULL AFTER `last_update`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `catalog` DROP `add_path`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `catalog` DROP `add_path`"; + $db_results = Dba::write($sql); - $sql = "CREATE TABLE `dynamic_playlist` (" . - "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . - "`name` VARCHAR( 255 ) NOT NULL ," . - "`user` INT( 11 ) NOT NULL ," . - "`date` INT( 11 ) UNSIGNED NOT NULL ," . - "`type` VARCHAR( 128 ) NOT NULL" . - ") ENGINE = MYISAM "; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `dynamic_playlist` (" . + "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . + "`name` VARCHAR( 255 ) NOT NULL ," . + "`user` INT( 11 ) NOT NULL ," . + "`date` INT( 11 ) UNSIGNED NOT NULL ," . + "`type` VARCHAR( 128 ) NOT NULL" . + ") ENGINE = MYISAM "; + $db_results = Dba::write($sql); - $sql = "CREATE TABLE `dynamic_playlist_data` (" . - "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . - "`dynamic_id` INT( 11 ) UNSIGNED NOT NULL ," . - "`field` VARCHAR( 255 ) NOT NULL ," . - "`internal_operator` VARCHAR( 64 ) NOT NULL ," . - "`external_operator` VARCHAR( 64 ) NOT NULL ," . - "`value` VARCHAR( 255 ) NOT NULL" . - ") ENGINE = MYISAM"; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `dynamic_playlist_data` (" . + "`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ," . + "`dynamic_id` INT( 11 ) UNSIGNED NOT NULL ," . + "`field` VARCHAR( 255 ) NOT NULL ," . + "`internal_operator` VARCHAR( 64 ) NOT NULL ," . + "`external_operator` VARCHAR( 64 ) NOT NULL ," . + "`value` VARCHAR( 255 ) NOT NULL" . + ") ENGINE = MYISAM"; + $db_results = Dba::write($sql); - self::set_version('db_version','350007'); + self::set_version('db_version','350007'); - return true; + return true; - } // update_350007 + } // update_350007 - /** - * update_350008 - * Change song_id references to be object so they are a little more general - * add a type to now playing table so that we can handle different playing information - */ - public static function update_350008() { + /** + * update_350008 + * Change song_id references to be object so they are a little more general + * add a type to now playing table so that we can handle different playing information + */ + public static function update_350008() { - $sql = "ALTER TABLE `now_playing` CHANGE `song_id` `object_id` INT( 11 ) UNSIGNED NOT NULL"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `now_playing` CHANGE `song_id` `object_id` INT( 11 ) UNSIGNED NOT NULL"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `now_playing` ADD `object_type` VARCHAR ( 255 ) NOT NULL AFTER `object_id`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `now_playing` ADD `object_type` VARCHAR ( 255 ) NOT NULL AFTER `object_id`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `now_playing` ADD INDEX ( `expire` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `now_playing` ADD INDEX ( `expire` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `video` ADD `addition_time` INT( 11 ) UNSIGNED NOT NULL AFTER `mime`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `video` ADD `addition_time` INT( 11 ) UNSIGNED NOT NULL AFTER `mime`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `video` ADD `update_time` INT( 11 ) UNSIGNED NULL AFTER `addition_time`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `video` ADD `update_time` INT( 11 ) UNSIGNED NULL AFTER `addition_time`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `video` ADD INDEX (`addition_time`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `video` ADD INDEX (`addition_time`)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `video` ADD INDEX (`update_time`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `video` ADD INDEX (`update_time`)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `artist_data` ADD INDEX ( `art_mime` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `artist_data` ADD INDEX ( `art_mime` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `album_data` ADD INDEX ( `art_mime` )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `album_data` ADD INDEX ( `art_mime` )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `tmp_browse` ADD `type` VARCHAR ( 255 ) NOT NULL AFTER `sid`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `tmp_browse` ADD `type` VARCHAR ( 255 ) NOT NULL AFTER `sid`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `tmp_browse` ADD INDEX (`type)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `tmp_browse` ADD INDEX (`type)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` DROP `hash`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` DROP `hash`"; + $db_results = Dba::write($sql); - self::set_version('db_version','350008'); + self::set_version('db_version','350008'); - } // update_350008 + } // update_350008 - /** - * update_360001 - * This adds the MB UUIDs to the different tables as well as some additional cleanup - */ - public static function update_360001() { + /** + * update_360001 + * This adds the MB UUIDs to the different tables as well as some additional cleanup + */ + public static function update_360001() { - $sql = "ALTER TABLE `album` ADD `mbid` CHAR ( 36 ) AFTER `prefix`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `album` ADD `mbid` CHAR ( 36 ) AFTER `prefix`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `artist` ADD `mbid` CHAR ( 36 ) AFTER `prefix`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `artist` ADD `mbid` CHAR ( 36 ) AFTER `prefix`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` ADD `mbid` CHAR ( 36 ) AFTER `track`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` ADD `mbid` CHAR ( 36 ) AFTER `track`"; + $db_results = Dba::write($sql); - // Remove any RIO related information from the database as the plugin has been removed - $sql = "DELETE FROM `update_info` WHERE `key` LIKE 'Plugin_Ri%'"; - $db_results = Dba::write($sql); + // Remove any RIO related information from the database as the plugin has been removed + $sql = "DELETE FROM `update_info` WHERE `key` LIKE 'Plugin_Ri%'"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `preference` WHERE `name` LIKE 'rio_%'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `preference` WHERE `name` LIKE 'rio_%'"; + $db_results = Dba::write($sql); - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } // while we're fixing the useres stuff + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } // while we're fixing the useres stuff - self::set_version('db_version','360001'); + self::set_version('db_version','360001'); - } // update_360001 + } // update_360001 - /** - * update_360002 - * This update makes changes to the cataloging to accomodate the new method for syncing between - * Ampache instances, could be adapted to sync with whatever for "full" catalog - */ - public static function update_360002() { + /** + * update_360002 + * This update makes changes to the cataloging to accomodate the new method for syncing between + * Ampache instances, could be adapted to sync with whatever for "full" catalog + */ + public static function update_360002() { - // Drop the key from catalog and ACL - $sql = "ALTER TABLE `catalog` DROP `key`"; - $db_results = Dba::write($sql); + // Drop the key from catalog and ACL + $sql = "ALTER TABLE `catalog` DROP `key`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `access_list` DROP `key`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `access_list` DROP `key`"; + $db_results = Dba::write($sql); - // Add in Username / Password for catalog - to be used for remote catalogs - $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`"; - $db_results = Dba::write($sql); + // Add in Username / Password for catalog - to be used for remote catalogs + $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`"; + $db_results = Dba::write($sql); - // Adjust the Filename field in song, make it gi-normous. If someone has anything close to - // this file length, they seriously need to reconsider what they are doing. - $sql = "ALTER TABLE `song` CHANGE `file` `file` VARCHAR ( 4096 )"; - $db_results = Dba::write($sql); + // Adjust the Filename field in song, make it gi-normous. If someone has anything close to + // this file length, they seriously need to reconsider what they are doing. + $sql = "ALTER TABLE `song` CHANGE `file` `file` VARCHAR ( 4096 )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `video` CHANGE `file` `file` VARCHAR ( 4096 )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `video` CHANGE `file` `file` VARCHAR ( 4096 )"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `live_stream` CHANGE `url` `url` VARCHAR ( 4096 )"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `live_stream` CHANGE `url` `url` VARCHAR ( 4096 )"; + $db_results = Dba::write($sql); - // Index the Artist, Album, and Song tables to prepare for Fulltext searches. - $sql = "ALTER TABLE `artist` ADD FULLTEXT(`name`)"; - $db_results = Dba::write($sql); + // Index the Artist, Album, and Song tables to prepare for Fulltext searches. + $sql = "ALTER TABLE `artist` ADD FULLTEXT(`name`)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `album` ADD FULLTEXT(`name`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `album` ADD FULLTEXT(`name`)"; + $db_results = Dba::write($sql); - $sql = "ALTER TABLE `song` ADD FULLTEXT(`title`)"; - $db_results = Dba::write($sql); + $sql = "ALTER TABLE `song` ADD FULLTEXT(`title`)"; + $db_results = Dba::write($sql); - // Now add in the min_object_count preference and the random_method - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('bandwidth','50','Bandwidth','5','integer','interface')"; - $db_results = Dba::write($sql); + // Now add in the min_object_count preference and the random_method + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('bandwidth','50','Bandwidth','5','integer','interface')"; + $db_results = Dba::write($sql); - $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . - "VALUES ('features','50','Features','5','integer','interface')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `preference` (`name`,`value`,`description`,`level`,`type`,`catagory`) " . + "VALUES ('features','50','Features','5','integer','interface')"; + $db_results = Dba::write($sql); - /* Fix every users preferences */ - $sql = "SELECT `id` FROM `user`"; - $db_results = Dba::read($sql); + /* Fix every users preferences */ + $sql = "SELECT `id` FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($r = Dba::fetch_assoc($db_results)) { - User::fix_preferences($r['id']); - } // while results + while ($r = Dba::fetch_assoc($db_results)) { + User::fix_preferences($r['id']); + } // while results - self::set_version('db_version','360002'); - - } // update_360002 - - /** - * update_360003 - * This update moves the image data to its own table. - */ - public static function update_360003() { - $sql = "CREATE TABLE `image` (" . - "`id` int(11) unsigned NOT NULL auto_increment," . - "`image` mediumblob NOT NULL," . - "`mime` varchar(64) NOT NULL," . - "`size` varchar(64) NOT NULL," . - "`object_type` varchar(64) NOT NULL," . - "`object_id` int(11) unsigned NOT NULL," . - "PRIMARY KEY (`id`)," . - "KEY `object_type` (`object_type`)," . - "KEY `object_id` (`object_id`)" . - ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; - $db_results = Dba::write($sql); - - foreach (array('album', 'artist') as $type) { - $sql = "SELECT `" . $type . "_id` AS `object_id`, " . - "`art`, `art_mime` FROM `" . $type . - "_data` WHERE `art` IS NOT NULL"; - $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $sql = "INSERT INTO `image` " . - "(`image`, `mime`, `size`, " . - "`object_type`, `object_id`) " . - "VALUES('" . Dba::escape($row['art']) . - "', '" . $row['art_mime'] . - "', 'original', '" . $type . "', '" . - $row['object_id'] . "')"; - $db_other_results = Dba::write($sql); - } - $sql = "DROP TABLE `" . $type . "_data`"; - $db_results = Dba::write($sql); - } - - self::set_version('db_version','360003'); - - } // update_360003 + self::set_version('db_version','360002'); + + } // update_360002 + + /** + * update_360003 + * This update moves the image data to its own table. + */ + public static function update_360003() { + $sql = "CREATE TABLE `image` (" . + "`id` int(11) unsigned NOT NULL auto_increment," . + "`image` mediumblob NOT NULL," . + "`mime` varchar(64) NOT NULL," . + "`size` varchar(64) NOT NULL," . + "`object_type` varchar(64) NOT NULL," . + "`object_id` int(11) unsigned NOT NULL," . + "PRIMARY KEY (`id`)," . + "KEY `object_type` (`object_type`)," . + "KEY `object_id` (`object_id`)" . + ") ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; + $db_results = Dba::write($sql); + + foreach (array('album', 'artist') as $type) { + $sql = "SELECT `" . $type . "_id` AS `object_id`, " . + "`art`, `art_mime` FROM `" . $type . + "_data` WHERE `art` IS NOT NULL"; + $db_results = Dba::read($sql); + while ($row = Dba::fetch_assoc($db_results)) { + $sql = "INSERT INTO `image` " . + "(`image`, `mime`, `size`, " . + "`object_type`, `object_id`) " . + "VALUES('" . Dba::escape($row['art']) . + "', '" . $row['art_mime'] . + "', 'original', '" . $type . "', '" . + $row['object_id'] . "')"; + $db_other_results = Dba::write($sql); + } + $sql = "DROP TABLE `" . $type . "_data`"; + $db_results = Dba::write($sql); + } + + self::set_version('db_version','360003'); + + } // update_360003 /** - * update_360004 - * This update creates an index on the rating table. - */ - public static function update_360004() { - $sql = "CREATE UNIQUE INDEX `unique_rating` ON `rating` (`user`, `object_type`, `object_id`)"; - $db_results = Dba::write($sql); - - self::set_version('db_version','360004'); - } // update_360004 - - /** - * update_360005 - * This changes the tmp_browse table around. - */ - public static function update_360005() { - $sql = "DROP TABLE `tmp_browse`"; - $db_results = Dba::write($sql); - - $sql = "CREATE TABLE `tmp_browse` (" . - "`id` int(13) NOT NULL auto_increment," . - "`sid` varchar(128) character set utf8 NOT NULL default ''," . - "`data` longtext NOT NULL," . - "`object_data` longtext," . - "PRIMARY KEY (`sid`,`id`)" . - ") ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $db_results = Dba::write($sql); - - self::set_version('db_version','360005'); - } // update_360005 - - /** - * update_360006 - * This adds the table for newsearch/dynamic playlists - */ - public static function update_360006() { - $sql = "CREATE TABLE `search` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, - `user` int(11) NOT NULL, - `type` enum('private','public') CHARACTER SET utf8 DEFAULT NULL, - `rules` mediumtext NOT NULL, - `name` varchar(255) CHARACTER SET utf8 DEFAULT NULL, - `logic_operator` varchar(3) CHARACTER SET utf8 DEFAULT NULL, - PRIMARY KEY (`id`) - ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8"; - $db_results = Dba::write($sql); - - self::set_version('db_version','360006'); - } - - /** - * update_360007 - * This fixes the session table - */ - public static function update_360007() { - $sql = "ALTER TABLE `session` MODIFY `type` ENUM ('mysql','ldap','http','api','xml-rpc','local') NOT NULL"; - $db_results = Dba::write($sql); - self::set_version('db_version','360007'); - } - - /** - * update_360008 - * Fix bug that caused the remote_username/password fields to not be created - */ - public static function update_360008() { - - $remote_username = false; - $remote_password = false; - - $sql = "DESCRIBE `catalog`"; - $db_results = Dba::read($sql); - - while ($row = Dba::fetch_assoc($db_results)) { - if ($row['Field'] == 'remote_username') { - $remote_username = true; - } - if ($row['Field'] == 'remote_password') { - $remote_password = true; - } - } // end while - - if (!$remote_username) { - // Add in Username / Password for catalog - to be used for remote catalogs - $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`"; - $db_results = Dba::write($sql); - } - if (!$remote_password) { - $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`"; - $db_results = Dba::write($sql); - } - - self::set_version('db_version','360008'); - - } // update_360008 - - - /** - * update_360009 - * The main session table was already updated to use varchar(64) for the ID, - * tmp_playlist needs the same change - */ - public static function update_360009() { - $sql = "ALTER TABLE `tmp_playlist` CHANGE `session` `session` VARCHAR(64)"; - $db_results = Dba::write($sql); - - self::set_version('db_version','360009'); - } - - /** - * update_360010 - * MBz NGS means collaborations have more than one MBID (the ones - * belonging to the underlying artists). We need a bigger column. - */ - public static function update_360010() { - $sql = 'ALTER TABLE `artist` CHANGE `mbid` `mbid` VARCHAR(1369)'; - $db_results = Dba::write($sql); - - self::set_version('db_version', '360010'); - } - - /** - * update_380011 - * We need a place to store actual playlist data for downloadable - * playlist files. - */ - public static function update_360011() { - $sql = 'CREATE TABLE `stream_playlist` (' . - '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,' . - '`sid` varchar(64) NOT NULL,' . - '`url` text NOT NULL,' . - '`info_url` text DEFAULT NULL,' . - '`image_url` text DEFAULT NULL,' . - '`title` varchar(255) DEFAULT NULL,' . - '`author` varchar(255) DEFAULT NULL,' . - '`album` varchar(255) DEFAULT NULL,' . - '`type` varchar(255) DEFAULT NULL,' . - '`time` smallint(5) DEFAULT NULL,' . - 'PRIMARY KEY (`id`), KEY `sid` (`sid`))'; - $db_results = Dba::write($sql); - self::set_version('db_version', '360011'); - } + * update_360004 + * This update creates an index on the rating table. + */ + public static function update_360004() { + $sql = "CREATE UNIQUE INDEX `unique_rating` ON `rating` (`user`, `object_type`, `object_id`)"; + $db_results = Dba::write($sql); + + self::set_version('db_version','360004'); + } // update_360004 + + /** + * update_360005 + * This changes the tmp_browse table around. + */ + public static function update_360005() { + $sql = "DROP TABLE `tmp_browse`"; + $db_results = Dba::write($sql); + + $sql = "CREATE TABLE `tmp_browse` (" . + "`id` int(13) NOT NULL auto_increment," . + "`sid` varchar(128) character set utf8 NOT NULL default ''," . + "`data` longtext NOT NULL," . + "`object_data` longtext," . + "PRIMARY KEY (`sid`,`id`)" . + ") ENGINE=MyISAM DEFAULT CHARSET=utf8"; + $db_results = Dba::write($sql); + + self::set_version('db_version','360005'); + } // update_360005 + + /** + * update_360006 + * This adds the table for newsearch/dynamic playlists + */ + public static function update_360006() { + $sql = "CREATE TABLE `search` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `user` int(11) NOT NULL, + `type` enum('private','public') CHARACTER SET utf8 DEFAULT NULL, + `rules` mediumtext NOT NULL, + `name` varchar(255) CHARACTER SET utf8 DEFAULT NULL, + `logic_operator` varchar(3) CHARACTER SET utf8 DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8"; + $db_results = Dba::write($sql); + + self::set_version('db_version','360006'); + } + + /** + * update_360007 + * This fixes the session table + */ + public static function update_360007() { + $sql = "ALTER TABLE `session` MODIFY `type` ENUM ('mysql','ldap','http','api','xml-rpc','local') NOT NULL"; + $db_results = Dba::write($sql); + self::set_version('db_version','360007'); + } + + /** + * update_360008 + * Fix bug that caused the remote_username/password fields to not be created + */ + public static function update_360008() { + + $remote_username = false; + $remote_password = false; + + $sql = "DESCRIBE `catalog`"; + $db_results = Dba::read($sql); + + while ($row = Dba::fetch_assoc($db_results)) { + if ($row['Field'] == 'remote_username') { + $remote_username = true; + } + if ($row['Field'] == 'remote_password') { + $remote_password = true; + } + } // end while + + if (!$remote_username) { + // Add in Username / Password for catalog - to be used for remote catalogs + $sql = "ALTER TABLE `catalog` ADD `remote_username` VARCHAR ( 255 ) AFTER `catalog_type`"; + $db_results = Dba::write($sql); + } + if (!$remote_password) { + $sql = "ALTER TABLE `catalog` ADD `remote_password` VARCHAR ( 255 ) AFTER `remote_username`"; + $db_results = Dba::write($sql); + } + + self::set_version('db_version','360008'); + + } // update_360008 + + + /** + * update_360009 + * The main session table was already updated to use varchar(64) for the ID, + * tmp_playlist needs the same change + */ + public static function update_360009() { + $sql = "ALTER TABLE `tmp_playlist` CHANGE `session` `session` VARCHAR(64)"; + $db_results = Dba::write($sql); + + self::set_version('db_version','360009'); + } + + /** + * update_360010 + * MBz NGS means collaborations have more than one MBID (the ones + * belonging to the underlying artists). We need a bigger column. + */ + public static function update_360010() { + $sql = 'ALTER TABLE `artist` CHANGE `mbid` `mbid` VARCHAR(1369)'; + $db_results = Dba::write($sql); + + self::set_version('db_version', '360010'); + } + + /** + * update_380011 + * We need a place to store actual playlist data for downloadable + * playlist files. + */ + public static function update_360011() { + $sql = 'CREATE TABLE `stream_playlist` (' . + '`id` int(11) unsigned NOT NULL AUTO_INCREMENT,' . + '`sid` varchar(64) NOT NULL,' . + '`url` text NOT NULL,' . + '`info_url` text DEFAULT NULL,' . + '`image_url` text DEFAULT NULL,' . + '`title` varchar(255) DEFAULT NULL,' . + '`author` varchar(255) DEFAULT NULL,' . + '`album` varchar(255) DEFAULT NULL,' . + '`type` varchar(255) DEFAULT NULL,' . + '`time` smallint(5) DEFAULT NULL,' . + 'PRIMARY KEY (`id`), KEY `sid` (`sid`))'; + $db_results = Dba::write($sql); + self::set_version('db_version', '360011'); + } } // end update class ?> diff --git a/lib/class/user.class.php b/lib/class/user.class.php index 01f709f276..edc711e9fc 100644 --- a/lib/class/user.class.php +++ b/lib/class/user.class.php @@ -1,5 +1,5 @@ id = intval($user_id); + $this->id = intval($user_id); - $info = $this->_get_info(); + $info = $this->_get_info(); - foreach ($info as $key=>$value) { - // Let's not save the password in this object :S - if ($key == 'password') { continue; } - $this->$key = $value; - } + foreach ($info as $key=>$value) { + // Let's not save the password in this object :S + if ($key == 'password') { continue; } + $this->$key = $value; + } - // Make sure the Full name is always filled - if (strlen($this->fullname) < 1) { $this->fullname = $this->username; } + // Make sure the Full name is always filled + if (strlen($this->fullname) < 1) { $this->fullname = $this->username; } - } // Constructor + } // Constructor - /** - * _get_info - * This function returns the information for this object - */ - private function _get_info() { + /** + * _get_info + * This function returns the information for this object + */ + private function _get_info() { - $id = intval($this->id); + $id = intval($this->id); - if (parent::is_cached('user',$id)) { - return parent::get_from_cache('user',$id); - } + if (parent::is_cached('user',$id)) { + return parent::get_from_cache('user',$id); + } - // If the ID is -1 then - if ($id == '-1') { - $data['username'] = 'System'; - $data['fullname'] = 'Ampache User'; - $data['access'] = '25'; - return $data; - } + // If the ID is -1 then + if ($id == '-1') { + $data['username'] = 'System'; + $data['fullname'] = 'Ampache User'; + $data['access'] = '25'; + return $data; + } - $sql = "SELECT * FROM `user` WHERE `id`='$id'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `user` WHERE `id`='$id'"; + $db_results = Dba::read($sql); - $data = Dba::fetch_assoc($db_results); + $data = Dba::fetch_assoc($db_results); - parent::add_to_cache('user',$id,$data); + parent::add_to_cache('user',$id,$data); - return $data; + return $data; - } // _get_info + } // _get_info - /** - * load_playlist - * This is called once per page load it makes sure that this session - * has a tmp_playlist, creating it if it doesn't, then sets $this->playlist - * as a tmp_playlist object that can be fiddled with later on - */ - public function load_playlist() { + /** + * load_playlist + * This is called once per page load it makes sure that this session + * has a tmp_playlist, creating it if it doesn't, then sets $this->playlist + * as a tmp_playlist object that can be fiddled with later on + */ + public function load_playlist() { - $session_id = session_id(); + $session_id = session_id(); - $this->playlist = Tmp_Playlist::get_from_session($session_id); + $this->playlist = Tmp_Playlist::get_from_session($session_id); - } // load_playlist + } // load_playlist - /** - * get_from_username - * This returns a built user from a username. This is a - * static function so it doesn't require an instance - */ - public static function get_from_username($username) { + /** + * get_from_username + * This returns a built user from a username. This is a + * static function so it doesn't require an instance + */ + public static function get_from_username($username) { - $username = Dba::escape($username); + $username = Dba::escape($username); - $sql = "SELECT `id` FROM `user` WHERE `username`='$username'"; - $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $sql = "SELECT `id` FROM `user` WHERE `username`='$username'"; + $db_results = Dba::read($sql); + $results = Dba::fetch_assoc($db_results); - $user = new User($results['id']); + $user = new User($results['id']); - return $user; + return $user; - } // get_from_username + } // get_from_username - /** - * get_from_email - * This returns a built user from a email. This is a - * static function so it doesn't require an instance - */ - public static function get_from_email($email) { + /** + * get_from_email + * This returns a built user from a email. This is a + * static function so it doesn't require an instance + */ + public static function get_from_email($email) { - $email = Dba::escape($email); + $email = Dba::escape($email); - $sql = "SELECT `id` FROM `user` WHERE `email`='$email'"; - $db_results = Dba::read($sql); - $results = Dba::fetch_assoc($db_results); + $sql = "SELECT `id` FROM `user` WHERE `email`='$email'"; + $db_results = Dba::read($sql); + $results = Dba::fetch_assoc($db_results); - $user = new User($results['id']); + $user = new User($results['id']); - return $user; + return $user; - } // get_from_username + } // get_from_username - /** - * get_catalogs - * This returns the catalogs as an array of ids that this user is allowed to access - */ - public function get_catalogs() { + /** + * get_catalogs + * This returns the catalogs as an array of ids that this user is allowed to access + */ + public function get_catalogs() { - if (parent::is_cached('user_catalog',$this->id)) { - return parent::get_from_cache('user_catalog',$this->id); - } + if (parent::is_cached('user_catalog',$this->id)) { + return parent::get_from_cache('user_catalog',$this->id); + } - $sql = "SELECT * FROM `user_catalog` WHERE `user`='$user_id'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `user_catalog` WHERE `user`='$user_id'"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $catalogs[] = $row['catalog']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $catalogs[] = $row['catalog']; + } - parent::add_to_cache('user_catalog',$this->id,$catalogs); + parent::add_to_cache('user_catalog',$this->id,$catalogs); - return $catalogs; + return $catalogs; - } // get_catalogs + } // get_catalogs - /** - * get_preferences - * This is a little more complicate now that we've got many types of preferences - * This funtions pulls all of them an arranges them into a spiffy little array - * You can specify a type to limit it to a single type of preference - * []['title'] = ucased type name - * []['prefs'] = array(array('name','display','value')); - * []['admin'] = t/f value if this is an admin only section - */ - function get_preferences($type = 0, $system = false) { + /** + * get_preferences + * This is a little more complicate now that we've got many types of preferences + * This funtions pulls all of them an arranges them into a spiffy little array + * You can specify a type to limit it to a single type of preference + * []['title'] = ucased type name + * []['prefs'] = array(array('name','display','value')); + * []['admin'] = t/f value if this is an admin only section + */ + function get_preferences($type = 0, $system = false) { - // Fill out the user id - $user_id = $system ? Dba::escape(-1) : Dba::escape($this->id); + // Fill out the user id + $user_id = $system ? Dba::escape(-1) : Dba::escape($this->id); - if (!$system) { - $user_limit = "AND preference.catagory != 'system'"; - } - - if ($type != '0') { - $user_limit = "AND preference.catagory = '" . Dba::escape($type) . "'"; - } - - - $sql = "SELECT preference.name, preference.description, preference.catagory, preference.level, user_preference.value " . - "FROM preference INNER JOIN user_preference ON user_preference.preference=preference.id " . - "WHERE user_preference.user='$user_id' " . $user_limit . - " ORDER BY preference.catagory, preference.description"; - - $db_results = Dba::read($sql); - - /* Ok this is crapy, need to clean this up or improve the code FIXME */ - while ($r = Dba::fetch_assoc($db_results)) { - $type = $r['catagory']; - $admin = false; - if ($type == 'system') { $admin = true; } - $type_array[$type][$r['name']] = array('name'=>$r['name'],'level'=>$r['level'],'description'=>$r['description'],'value'=>$r['value']); - $results[$type] = array ('title'=>ucwords($type),'admin'=>$admin,'prefs'=>$type_array[$type]); - } // end while - - return $results; - - } // get_preferences - - /** - * set_preferences - * sets the prefs for this specific user - */ - public function set_preferences() { - - $user_id = Dba::escape($this->id); - - $sql = "SELECT preference.name,user_preference.value FROM preference,user_preference WHERE user_preference.user='$user_id' " . - "AND user_preference.preference=preference.id AND preference.type != 'system'"; - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - $key = $r['name']; - $this->prefs[$key] = $r['value']; - } - } // set_preferences - - /** - * get_favorites - * returns an array of your $type favorites - */ - function get_favorites($type) { - - $web_path = Config::get('web_path'); - - $results = Stats::get_user(Config::get('popular_threshold'),$type,$this->id,1); - - $items = array(); - - foreach ($results as $r) { - /* If its a song */ - if ($type == 'song') { - $data = new Song($r['object_id']); - $data->count = $r['count']; - $data->format(); - $data->f_name = $data->f_link; - $items[] = $data; - } - /* If its an album */ - elseif ($type == 'album') { - $data = new Album($r['object_id']); - $data->count = $r['count']; - $data->format(); - $items[] = $data; - } - /* If its an artist */ - elseif ($type == 'artist') { - $data = new Artist($r['object_id']); - $data->count = $r['count']; - $data->format(); - $data->f_name = $data->f_link; - $items[] = $data; - } - /* If it's a genre */ - elseif ($type == 'genre') { - $data = new Genre($r['object_id']); - $data->count = $r['count']; - $data->format(); - $data->f_name = $data->f_link; - $items[] = $data; - } - - } // end foreach - - return $items; - - } // get_favorites - - /** - * get_recommendations - * This returns recommended objects of $type. The recommendations - * are based on voodoo economics,the phase of the moon and my current BAL. - */ - function get_recommendations($type) { - - /* First pull all of your ratings of this type */ - $sql = "SELECT object_id,user_rating FROM ratings " . - "WHERE object_type='" . Dba::escape($type) . "' AND user='" . Dba::escape($this->id) . "'"; - $db_results = Dba::read($sql); - - // Incase they only have one user - $users = array(); - - while ($r = Dba::fetch_assoc($db_results)) { - /* Store the fact that you rated this */ - $key = $r['object_id']; - $ratings[$key] = true; - - /* Build a key'd array of users with this same rating */ - $sql = "SELECT user FROM ratings WHERE object_type='" . Dba::escape($type) . "' " . - "AND user !='" . Dba::escape($this->id) . "' AND object_id='" . Dba::escape($r['object_id']) . "' " . - "AND user_rating ='" . Dba::escape($r['user_rating']) . "'"; - $user_results = Dba::read($sql); - - while ($user_info = Dba::fetch_assoc($user_results)) { - $key = $user_info['user']; - $users[$key]++; - } - - } // end while - - /* now we've got your ratings, and all users and the # of ratings that match your ratings - * sort the users[$key] array by value and then find things they've rated high (4+) that you - * haven't rated - */ - $recommendations = array(); - asort($users); - - foreach ($users as $user_id=>$score) { - - /* Find everything they've rated at 4+ */ - $sql = "SELECT object_id,user_rating FROM ratings " . - "WHERE user='" . Dba::escape($user_id) . "' AND user_rating >='4' AND " . - "object_type = '" . Dba::escape($type) . "' ORDER BY user_rating DESC"; - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - $key = $r['object_id']; - if (isset($ratings[$key])) { continue; } - - /* Let's only get 5 total for now */ - if (count($recommendations) > 5) { return $recommendations; } - - $recommendations[$key] = $r['user_rating']; - - } // end while - - - } // end foreach users - - return $recommendations; - - } // get_recommendations - - /** - * is_logged_in - * checks to see if $this user is logged in returns their current IP if they - * are logged in - */ - public function is_logged_in() { - - $username = Dba::escape($this->username); - - $sql = "SELECT `id`,`ip` FROM `session` WHERE `username`='$username'" . - " AND `expire` > ". time(); - $db_results = Dba::read($sql); - - if ($row = Dba::fetch_assoc($db_results)) { - $ip = $row['ip'] ? $row['ip'] : NULL; - return $ip; - } - - return false; - - } // is_logged_in + if (!$system) { + $user_limit = "AND preference.catagory != 'system'"; + } + + if ($type != '0') { + $user_limit = "AND preference.catagory = '" . Dba::escape($type) . "'"; + } + + + $sql = "SELECT preference.name, preference.description, preference.catagory, preference.level, user_preference.value " . + "FROM preference INNER JOIN user_preference ON user_preference.preference=preference.id " . + "WHERE user_preference.user='$user_id' " . $user_limit . + " ORDER BY preference.catagory, preference.description"; + + $db_results = Dba::read($sql); + + /* Ok this is crapy, need to clean this up or improve the code FIXME */ + while ($r = Dba::fetch_assoc($db_results)) { + $type = $r['catagory']; + $admin = false; + if ($type == 'system') { $admin = true; } + $type_array[$type][$r['name']] = array('name'=>$r['name'],'level'=>$r['level'],'description'=>$r['description'],'value'=>$r['value']); + $results[$type] = array ('title'=>ucwords($type),'admin'=>$admin,'prefs'=>$type_array[$type]); + } // end while + + return $results; + + } // get_preferences + + /** + * set_preferences + * sets the prefs for this specific user + */ + public function set_preferences() { + + $user_id = Dba::escape($this->id); + + $sql = "SELECT preference.name,user_preference.value FROM preference,user_preference WHERE user_preference.user='$user_id' " . + "AND user_preference.preference=preference.id AND preference.type != 'system'"; + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + $key = $r['name']; + $this->prefs[$key] = $r['value']; + } + } // set_preferences + + /** + * get_favorites + * returns an array of your $type favorites + */ + function get_favorites($type) { + + $web_path = Config::get('web_path'); + + $results = Stats::get_user(Config::get('popular_threshold'),$type,$this->id,1); + + $items = array(); + + foreach ($results as $r) { + /* If its a song */ + if ($type == 'song') { + $data = new Song($r['object_id']); + $data->count = $r['count']; + $data->format(); + $data->f_name = $data->f_link; + $items[] = $data; + } + /* If its an album */ + elseif ($type == 'album') { + $data = new Album($r['object_id']); + $data->count = $r['count']; + $data->format(); + $items[] = $data; + } + /* If its an artist */ + elseif ($type == 'artist') { + $data = new Artist($r['object_id']); + $data->count = $r['count']; + $data->format(); + $data->f_name = $data->f_link; + $items[] = $data; + } + /* If it's a genre */ + elseif ($type == 'genre') { + $data = new Genre($r['object_id']); + $data->count = $r['count']; + $data->format(); + $data->f_name = $data->f_link; + $items[] = $data; + } + + } // end foreach + + return $items; + + } // get_favorites + + /** + * get_recommendations + * This returns recommended objects of $type. The recommendations + * are based on voodoo economics,the phase of the moon and my current BAL. + */ + function get_recommendations($type) { + + /* First pull all of your ratings of this type */ + $sql = "SELECT object_id,user_rating FROM ratings " . + "WHERE object_type='" . Dba::escape($type) . "' AND user='" . Dba::escape($this->id) . "'"; + $db_results = Dba::read($sql); + + // Incase they only have one user + $users = array(); + + while ($r = Dba::fetch_assoc($db_results)) { + /* Store the fact that you rated this */ + $key = $r['object_id']; + $ratings[$key] = true; + + /* Build a key'd array of users with this same rating */ + $sql = "SELECT user FROM ratings WHERE object_type='" . Dba::escape($type) . "' " . + "AND user !='" . Dba::escape($this->id) . "' AND object_id='" . Dba::escape($r['object_id']) . "' " . + "AND user_rating ='" . Dba::escape($r['user_rating']) . "'"; + $user_results = Dba::read($sql); + + while ($user_info = Dba::fetch_assoc($user_results)) { + $key = $user_info['user']; + $users[$key]++; + } + + } // end while + + /* now we've got your ratings, and all users and the # of ratings that match your ratings + * sort the users[$key] array by value and then find things they've rated high (4+) that you + * haven't rated + */ + $recommendations = array(); + asort($users); + + foreach ($users as $user_id=>$score) { + + /* Find everything they've rated at 4+ */ + $sql = "SELECT object_id,user_rating FROM ratings " . + "WHERE user='" . Dba::escape($user_id) . "' AND user_rating >='4' AND " . + "object_type = '" . Dba::escape($type) . "' ORDER BY user_rating DESC"; + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + $key = $r['object_id']; + if (isset($ratings[$key])) { continue; } + + /* Let's only get 5 total for now */ + if (count($recommendations) > 5) { return $recommendations; } + + $recommendations[$key] = $r['user_rating']; + + } // end while + + + } // end foreach users + + return $recommendations; + + } // get_recommendations + + /** + * is_logged_in + * checks to see if $this user is logged in returns their current IP if they + * are logged in + */ + public function is_logged_in() { + + $username = Dba::escape($this->username); + + $sql = "SELECT `id`,`ip` FROM `session` WHERE `username`='$username'" . + " AND `expire` > ". time(); + $db_results = Dba::read($sql); + + if ($row = Dba::fetch_assoc($db_results)) { + $ip = $row['ip'] ? $row['ip'] : NULL; + return $ip; + } + + return false; + + } // is_logged_in - /** - * has_access - * this function checkes to see if this user has access - * to the passed action (pass a level requirement) - */ - function has_access($needed_level) { + /** + * has_access + * this function checkes to see if this user has access + * to the passed action (pass a level requirement) + */ + function has_access($needed_level) { - if (!Config::get('use_auth') || Config::get('demo_mode')) { return true; } + if (!Config::get('use_auth') || Config::get('demo_mode')) { return true; } - if ($this->access >= $needed_level) { return true; } + if ($this->access >= $needed_level) { return true; } - return false; + return false; - } // has_access + } // has_access - /** - * update - * This function is an all encompasing update function that - * calls the mini ones does all the error checking and all that - * good stuff - */ - public function update($data) { + /** + * update + * This function is an all encompasing update function that + * calls the mini ones does all the error checking and all that + * good stuff + */ + public function update($data) { - if (empty($data['username'])) { - Error::add('username', T_('Error Username Required')); - } + if (empty($data['username'])) { + Error::add('username', T_('Error Username Required')); + } - if ($data['password1'] != $data['password2'] AND !empty($data['password1'])) { - Error::add('password', T_("Error Passwords don't match")); - } + if ($data['password1'] != $data['password2'] AND !empty($data['password1'])) { + Error::add('password', T_("Error Passwords don't match")); + } - if (Error::occurred()) { - return false; - } + if (Error::occurred()) { + return false; + } - foreach ($data as $name=>$value) { - switch ($name) { - case 'password1'; - $name = 'password'; - case 'access': - case 'email': - case 'username': - case 'fullname'; - if ($this->$name != $value) { - $function = 'update_' . $name; - $this->$function($value); - } - break; - default: - // Rien a faire - break; - } // end switch on field + foreach ($data as $name=>$value) { + switch ($name) { + case 'password1'; + $name = 'password'; + case 'access': + case 'email': + case 'username': + case 'fullname'; + if ($this->$name != $value) { + $function = 'update_' . $name; + $this->$function($value); + } + break; + default: + // Rien a faire + break; + } // end switch on field - } // end foreach + } // end foreach - return true; + return true; - } // update + } // update - /** - * update_username - * updates their username - */ - public function update_username($new_username) { + /** + * update_username + * updates their username + */ + public function update_username($new_username) { - $new_username = Dba::escape($new_username); - $sql = "UPDATE `user` SET `username`='$new_username' WHERE `id`='$this->id'"; - $this->username = $new_username; - $db_results = Dba::write($sql); + $new_username = Dba::escape($new_username); + $sql = "UPDATE `user` SET `username`='$new_username' WHERE `id`='$this->id'"; + $this->username = $new_username; + $db_results = Dba::write($sql); - } // update_username + } // update_username - /** - * update_validation - * This is used by the registration mumbojumbo - * Use this function to update the validation key - * NOTE: crap this doesn't have update_item the humanity of it all - */ - public function update_validation($new_validation) { + /** + * update_validation + * This is used by the registration mumbojumbo + * Use this function to update the validation key + * NOTE: crap this doesn't have update_item the humanity of it all + */ + public function update_validation($new_validation) { - $new_validation = Dba::escape($new_validation); - $sql = "UPDATE `user` SET `validation`='$new_validation', `disabled`='1' WHERE `id`='" . Dba::escape($this->id) . "'"; - $db_results = Dba::write($sql); - $this->validation = $new_validation; + $new_validation = Dba::escape($new_validation); + $sql = "UPDATE `user` SET `validation`='$new_validation', `disabled`='1' WHERE `id`='" . Dba::escape($this->id) . "'"; + $db_results = Dba::write($sql); + $this->validation = $new_validation; - return $db_results; + return $db_results; - } // update_validation + } // update_validation - /** - * update_fullname - * updates their fullname - */ - public function update_fullname($new_fullname) { + /** + * update_fullname + * updates their fullname + */ + public function update_fullname($new_fullname) { - $new_fullname = Dba::escape($new_fullname); - $sql = "UPDATE `user` SET `fullname`='$new_fullname' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - } // update_fullname - - /** - * update_email - * updates their email address - */ - public function update_email($new_email) { + $new_fullname = Dba::escape($new_fullname); + $sql = "UPDATE `user` SET `fullname`='$new_fullname' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + } // update_fullname + + /** + * update_email + * updates their email address + */ + public function update_email($new_email) { - $new_email = Dba::escape($new_email); - $sql = "UPDATE `user` SET `email`='$new_email' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); + $new_email = Dba::escape($new_email); + $sql = "UPDATE `user` SET `email`='$new_email' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); - } // update_email - - /** - * disable - * This disables the current user - */ - public function disable() { - - // Make sure we aren't disabling the last admin - $sql = "SELECT `id` FROM `user` WHERE `disabled` = '0' AND `id` != '" . $this->id . "' AND `access`='100'"; - $db_results = Dba::read($sql); - - if (!Dba::num_rows($db_results)) { return false; } - - $sql = "UPDATE `user` SET `disabled`='1' WHERE id='" . $this->id . "'"; - $db_results = Dba::write($sql); - - // Delete any sessions they may have - $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'"; - $db_results = Dba::write($sql); - - return true; - - } // disable - - /** - * enable - * this enables the current user - */ - public function enable() { - - $sql = "UPDATE `user` SET `disabled`='0' WHERE id='" . $this->id . "'"; - $db_results = Dba::write($sql); + } // update_email + + /** + * disable + * This disables the current user + */ + public function disable() { + + // Make sure we aren't disabling the last admin + $sql = "SELECT `id` FROM `user` WHERE `disabled` = '0' AND `id` != '" . $this->id . "' AND `access`='100'"; + $db_results = Dba::read($sql); + + if (!Dba::num_rows($db_results)) { return false; } + + $sql = "UPDATE `user` SET `disabled`='1' WHERE id='" . $this->id . "'"; + $db_results = Dba::write($sql); + + // Delete any sessions they may have + $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'"; + $db_results = Dba::write($sql); + + return true; + + } // disable + + /** + * enable + * this enables the current user + */ + public function enable() { + + $sql = "UPDATE `user` SET `disabled`='0' WHERE id='" . $this->id . "'"; + $db_results = Dba::write($sql); - return true; + return true; - } // enable + } // enable - /** - * update_access - * updates their access level - */ - public function update_access($new_access) { + /** + * update_access + * updates their access level + */ + public function update_access($new_access) { - /* Prevent Only User accounts */ - if ($new_access < '100') { - $sql = "SELECT `id` FROM user WHERE `access`='100' AND `id` != '$this->id'"; - $db_results = Dba::read($sql); - if (!Dba::num_rows($db_results)) { return false; } - } - - $new_access = Dba::escape($new_access); - $sql = "UPDATE `user` SET `access`='$new_access' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - } // update_access - - /*! - @function update_last_seen - @discussion updates the last seen data for this user - */ - function update_last_seen() { - - $sql = "UPDATE user SET last_seen='" . time() . "' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); + /* Prevent Only User accounts */ + if ($new_access < '100') { + $sql = "SELECT `id` FROM user WHERE `access`='100' AND `id` != '$this->id'"; + $db_results = Dba::read($sql); + if (!Dba::num_rows($db_results)) { return false; } + } + + $new_access = Dba::escape($new_access); + $sql = "UPDATE `user` SET `access`='$new_access' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + } // update_access + + /*! + @function update_last_seen + @discussion updates the last seen data for this user + */ + function update_last_seen() { + + $sql = "UPDATE user SET last_seen='" . time() . "' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); - } // update_last_seen + } // update_last_seen - /** - * update_user_stats - * updates the playcount mojo for this specific user - */ - public function update_stats($song_id) { + /** + * update_user_stats + * updates the playcount mojo for this specific user + */ + public function update_stats($song_id) { - $song_info = new Song($song_id); - $song_info->format(); - $user = $this->id; + $song_info = new Song($song_id); + $song_info->format(); + $user = $this->id; - if (!strlen($song_info->file)) { return false; } + if (!strlen($song_info->file)) { return false; } - $this->set_preferences(); + $this->set_preferences(); - foreach (Plugin::get_plugins('save_songplay') as $plugin_name) { - $plugin = new Plugin($plugin_name); - if ($plugin->load()) { - $plugin->_plugin->save_songplay($song_info); - } - } + foreach (Plugin::get_plugins('save_songplay') as $plugin_name) { + $plugin = new Plugin($plugin_name); + if ($plugin->load()) { + $plugin->_plugin->save_songplay($song_info); + } + } - // Do this last so the 'last played checks are correct' - Stats::insert('song',$song_id,$user); - Stats::insert('album',$song_info->album,$user); - Stats::insert('artist',$song_info->artist,$user); + // Do this last so the 'last played checks are correct' + Stats::insert('song',$song_id,$user); + Stats::insert('album',$song_info->album,$user); + Stats::insert('artist',$song_info->artist,$user); - return true; + return true; - } // update_stats + } // update_stats - /** - * insert_ip_history - * This inserts a row into the IP History recording this user at this - * address at this time in this place, doing this thing.. you get the point - */ - public function insert_ip_history() { + /** + * insert_ip_history + * This inserts a row into the IP History recording this user at this + * address at this time in this place, doing this thing.. you get the point + */ + public function insert_ip_history() { - if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ - $sip = $_SERVER['HTTP_X_FORWARDED_FOR']; - debug_event('User Ip', 'Login from ip adress: ' . $sip,'3'); - } - else { - $sip = $_SERVER['REMOTE_ADDR']; - debug_event('User Ip', 'Login from ip adress: ' . $sip,'3'); - } + if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ + $sip = $_SERVER['HTTP_X_FORWARDED_FOR']; + debug_event('User Ip', 'Login from ip adress: ' . $sip,'3'); + } + else { + $sip = $_SERVER['REMOTE_ADDR']; + debug_event('User Ip', 'Login from ip adress: ' . $sip,'3'); + } - $ip = Dba::escape(inet_pton($sip)); - $date = time(); - $user = $this->id; - $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']); - - $sql = "INSERT INTO `ip_history` (`ip`,`user`,`date`,`agent`) VALUES ('$ip','$user','$date','$agent')"; - $db_results = Dba::write($sql); - - /* Clean up old records... sometimes */ - if (rand(1,100) > 60) { - $date = time() - (86400*Config::get('user_ip_cardinality')); - $sql = "DELETE FROM `ip_history` WHERE `date` < $date"; - $db_results = Dba::write($sql); - } - - return true; - - } // insert_ip_history - - /** - * create - * inserts a new user into ampache - */ - public static function create($username, $fullname, $email, $password, $access, $disabled = false) { - - /* Lets clean up the fields... */ - $username = Dba::escape($username); - $fullname = Dba::escape($fullname); - $email = Dba::escape($email); - $access = Dba::escape($access); - $password = hash('sha256', $password); - $disabled = $disabled ? 1 : 0; - - /* Now Insert this new user */ - $sql = "INSERT INTO `user` (`username`, `disabled`, " . - "`fullname`, `email`, `password`, `access`, " . - "`create_date`)" . - "VALUES('$username', '$disabled', '$fullname', " . - "'$email', '$password', '$access', '" . time() ."')"; - $db_results = Dba::write($sql); - - if (!$db_results) { return false; } - - // Get the insert_id - $insert_id = Dba::insert_id(); - - /* Populates any missing preferences, in this case all of them */ - self::fix_preferences($insert_id); - - return $insert_id; - - } // create - - /** - * update_password - * updates a users password - */ - public function update_password($new_password) { - - $new_password = hash('sha256',$new_password); - - $new_password = Dba::escape($new_password); - $sql = "UPDATE `user` SET `password`='$new_password' WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); - - // Clear this (temp fix) - if ($db_results) { unset($_SESSION['userdata']['password']); } - - } // update_password - - /** - * format - * This function sets up the extra variables we need when we are displaying a - * user for an admin, these should not be normally called when creating a - * user object - */ - public function format() { - - /* If they have a last seen date */ - if (!$this->last_seen) { $this->f_last_seen = T_('Never'); } - else { $this->f_last_seen = date("m\/d\/Y - H:i",$this->last_seen); } - - /* If they have a create date */ - if (!$this->create_date) { $this->f_create_date = T_('Unknown'); } - else { $this->f_create_date = date("m\/d\/Y - H:i",$this->create_date); } - - // Base link - $this->f_link = '' . $this->fullname . ''; - - /* Calculate their total Bandwidth Useage */ - $sql = "SELECT `song`.`size` FROM `song` LEFT JOIN `object_count` ON `song`.`id`=`object_count`.`object_id` " . - "WHERE `object_count`.`user`='$this->id' AND `object_count`.`object_type`='song'"; - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - $total = $total + $r['size']; - } - - $this->f_useage = UI::format_bytes($total); - - /* Get Users Last ip */ - if (count($data = $this->get_ip_history(1))) { - $this->ip_history = inet_ntop($data['0']['ip']); - } - else { - $this->ip_history = T_('Not Enough Data'); - } - - } // format_user - - /** - * format_favorites - * takes an array of objects and formats them corrrectly - * and returns a simply array with just count); - - // Go through the favs - foreach ($items as $data) { - - // Make all number lengths equal - $len = strlen($data->count); - while ($len < $maxlen) { - $data->count = "0" . $data->count; - $len++; - } - - $item = "[$data->count] - $data->f_name"; - $results[]->f_name_link = $item; - } // end foreach items - - return $results; - - } // format_favorites - - /** - * format_recommendations - * This takes an array of [object_id] = ratings - * and displays them in a semi-pretty format - */ - function format_recommendations($items,$type) { - - foreach ($items as $object_id=>$rating) { - - switch ($type) { - case 'artist': - $object = new Artist($object_id); - $object->format_artist(); - $name = $object->link; - break; - case 'album': - $object = new Album($object_id); - $object->format_album(); - $name = $object->f_link; - break; - case 'song': - $object = new Song($object_id); - $object->format_song(); - $name = $object->f_link; - break; - } // end switch on type - $results[] = "
  • $name -- " . get_rating_name($rating) . "
    \n
  • "; - - } // end foreach items - - - return $results; - - } // format_recommendations - - /** - * access_name_to_level - * This takes the access name for the user and returns the level - */ - public static function access_name_to_level($level) { - - switch ($level) { - case 'admin': - return '100'; - break; - case 'user': - return '25'; - break; - case 'manager': - return '75'; - break; - case 'guest': - return '5'; - break; - default: - return '0'; - break; - } - - return false; - - } // access_name_to_level - - /** - * fix_preferences - * This is the new fix_preferences function, it does the following - * Remove Duplicates from user, add in missing - * If -1 is passed it also removes duplicates from the `preferences` - * table. - */ - public static function fix_preferences($user_id) { - - $user_id = Dba::escape($user_id); - - /* Get All Preferences for the current user */ - $sql = "SELECT * FROM `user_preference` WHERE `user`='$user_id'"; - $db_results = Dba::read($sql); - - $results = array(); - - while ($r = Dba::fetch_assoc($db_results)) { - $pref_id = $r['preference']; - /* Check for duplicates */ - if (isset($results[$pref_id])) { - $r['value'] = Dba::escape($r['value']); - $sql = "DELETE FROM `user_preference` WHERE `user`='$user_id' AND `preference`='" . $r['preference'] . "' AND" . - " `value`='" . Dba::escape($r['value']) . "'"; - $delete_results = Dba::write($sql); - } // if its set - else { - $results[$pref_id] = 1; - } - } // end while - - /* If we aren't the -1 user before we continue grab the -1 users values */ - if ($user_id != '-1') { - $sql = "SELECT `user_preference`.`preference`,`user_preference`.`value` FROM `user_preference`,`preference` " . - "WHERE `user_preference`.`preference` = `preference`.`id` AND `user_preference`.`user`='-1' AND `preference`.`catagory` !='system'"; - $db_results = Dba::read($sql); - /* While through our base stuff */ - while ($r = Dba::fetch_assoc($db_results)) { - $key = $r['preference']; - $zero_results[$key] = $r['value']; - } - } // if not user -1 - - // get me _EVERYTHING_ - $sql = "SELECT * FROM `preference`"; - - // If not system, exclude system... *gasp* - if ($user_id != '-1') { - $sql .= " WHERE catagory !='system'"; - } - $db_results = Dba::read($sql); - - while ($r = Dba::fetch_assoc($db_results)) { - - $key = $r['id']; - - /* Check if this preference is set */ - if (!isset($results[$key])) { - if (isset($zero_results[$key])) { - $r['value'] = $zero_results[$key]; - } - $value = Dba::escape($r['value']); - $sql = "INSERT INTO user_preference (`user`,`preference`,`value`) VALUES ('$user_id','$key','$value')"; - $insert_db = Dba::write($sql); - } - } // while preferences - - /* Let's also clean out any preferences garbage left over */ - $sql = "SELECT DISTINCT(user_preference.user) FROM user_preference " . - "LEFT JOIN user ON user_preference.user = user.id " . - "WHERE user_preference.user!='-1' AND user.id IS NULL"; - $db_results = Dba::read($sql); - - $results = array(); - - while ($r = Dba::fetch_assoc($db_results)) { - $results[] = $r['user']; - } - - foreach ($results as $data) { - $sql = "DELETE FROM user_preference WHERE user='$data'"; - $db_results = Dba::write($sql); - } - - } // fix_preferences - - /** - * delete - * deletes this user and everything associated with it. This will affect - * ratings and tottal stats - */ - public function delete() { - - /* - Before we do anything make sure that they aren't the last - admin - */ - if ($this->has_access(100)) { - $sql = "SELECT `id` FROM `user` WHERE `access`='100' AND id !='" . Dba::escape($this->id) . "'"; - $db_results = Dba::read($sql); - if (!Dba::num_rows($db_results)) { - return false; - } - } // if this is an admin check for others - - // Delete their playlists - $sql = "DELETE FROM `playlist` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); - - // Clean up the playlist data table - $sql = "DELETE FROM `playlist_data` USING `playlist_data` " . - "LEFT JOIN `playlist` ON `playlist`.`id`=`playlist_data`.`playlist` " . - "WHERE `playlist`.`id` IS NULL"; - $db_results = Dba::write($sql); - - // Delete any stats they have - $sql = "DELETE FROM `object_count` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); - - // Clear the IP history for this user - $sql = "DELETE FROM `ip_history` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); - - // Nuke any access lists that are specific to this user - $sql = "DELETE FROM `access_list` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); - - // Delete their ratings - $sql = "DELETE FROM `rating` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); - - // Delete their tags - $sql = "DELETE FROM `tag_map` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); - - // Clean out the tags - $sql = "DELETE FROM `tags` USING `tag_map` LEFT JOIN `tag_map` ON tag_map.id=tags.map_id AND tag_map.id IS NULL"; - $db_results = Dba::write($sql); - - // Delete their preferences - $sql = "DELETE FROM `user_preference` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); + $ip = Dba::escape(inet_pton($sip)); + $date = time(); + $user = $this->id; + $agent = Dba::escape($_SERVER['HTTP_USER_AGENT']); + + $sql = "INSERT INTO `ip_history` (`ip`,`user`,`date`,`agent`) VALUES ('$ip','$user','$date','$agent')"; + $db_results = Dba::write($sql); + + /* Clean up old records... sometimes */ + if (rand(1,100) > 60) { + $date = time() - (86400*Config::get('user_ip_cardinality')); + $sql = "DELETE FROM `ip_history` WHERE `date` < $date"; + $db_results = Dba::write($sql); + } + + return true; + + } // insert_ip_history + + /** + * create + * inserts a new user into ampache + */ + public static function create($username, $fullname, $email, $password, $access, $disabled = false) { + + /* Lets clean up the fields... */ + $username = Dba::escape($username); + $fullname = Dba::escape($fullname); + $email = Dba::escape($email); + $access = Dba::escape($access); + $password = hash('sha256', $password); + $disabled = $disabled ? 1 : 0; + + /* Now Insert this new user */ + $sql = "INSERT INTO `user` (`username`, `disabled`, " . + "`fullname`, `email`, `password`, `access`, " . + "`create_date`)" . + "VALUES('$username', '$disabled', '$fullname', " . + "'$email', '$password', '$access', '" . time() ."')"; + $db_results = Dba::write($sql); + + if (!$db_results) { return false; } + + // Get the insert_id + $insert_id = Dba::insert_id(); + + /* Populates any missing preferences, in this case all of them */ + self::fix_preferences($insert_id); + + return $insert_id; + + } // create + + /** + * update_password + * updates a users password + */ + public function update_password($new_password) { + + $new_password = hash('sha256',$new_password); + + $new_password = Dba::escape($new_password); + $sql = "UPDATE `user` SET `password`='$new_password' WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); + + // Clear this (temp fix) + if ($db_results) { unset($_SESSION['userdata']['password']); } + + } // update_password + + /** + * format + * This function sets up the extra variables we need when we are displaying a + * user for an admin, these should not be normally called when creating a + * user object + */ + public function format() { + + /* If they have a last seen date */ + if (!$this->last_seen) { $this->f_last_seen = T_('Never'); } + else { $this->f_last_seen = date("m\/d\/Y - H:i",$this->last_seen); } + + /* If they have a create date */ + if (!$this->create_date) { $this->f_create_date = T_('Unknown'); } + else { $this->f_create_date = date("m\/d\/Y - H:i",$this->create_date); } + + // Base link + $this->f_link = '
    ' . $this->fullname . ''; + + /* Calculate their total Bandwidth Useage */ + $sql = "SELECT `song`.`size` FROM `song` LEFT JOIN `object_count` ON `song`.`id`=`object_count`.`object_id` " . + "WHERE `object_count`.`user`='$this->id' AND `object_count`.`object_type`='song'"; + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + $total = $total + $r['size']; + } + + $this->f_useage = UI::format_bytes($total); + + /* Get Users Last ip */ + if (count($data = $this->get_ip_history(1))) { + $this->ip_history = inet_ntop($data['0']['ip']); + } + else { + $this->ip_history = T_('Not Enough Data'); + } + + } // format_user + + /** + * format_favorites + * takes an array of objects and formats them corrrectly + * and returns a simply array with just count); + + // Go through the favs + foreach ($items as $data) { + + // Make all number lengths equal + $len = strlen($data->count); + while ($len < $maxlen) { + $data->count = "0" . $data->count; + $len++; + } + + $item = "[$data->count] - $data->f_name"; + $results[]->f_name_link = $item; + } // end foreach items + + return $results; + + } // format_favorites + + /** + * format_recommendations + * This takes an array of [object_id] = ratings + * and displays them in a semi-pretty format + */ + function format_recommendations($items,$type) { + + foreach ($items as $object_id=>$rating) { + + switch ($type) { + case 'artist': + $object = new Artist($object_id); + $object->format_artist(); + $name = $object->link; + break; + case 'album': + $object = new Album($object_id); + $object->format_album(); + $name = $object->f_link; + break; + case 'song': + $object = new Song($object_id); + $object->format_song(); + $name = $object->f_link; + break; + } // end switch on type + $results[] = "
  • $name -- " . get_rating_name($rating) . "
    \n
  • "; + + } // end foreach items + + + return $results; + + } // format_recommendations + + /** + * access_name_to_level + * This takes the access name for the user and returns the level + */ + public static function access_name_to_level($level) { + + switch ($level) { + case 'admin': + return '100'; + break; + case 'user': + return '25'; + break; + case 'manager': + return '75'; + break; + case 'guest': + return '5'; + break; + default: + return '0'; + break; + } + + return false; + + } // access_name_to_level + + /** + * fix_preferences + * This is the new fix_preferences function, it does the following + * Remove Duplicates from user, add in missing + * If -1 is passed it also removes duplicates from the `preferences` + * table. + */ + public static function fix_preferences($user_id) { + + $user_id = Dba::escape($user_id); + + /* Get All Preferences for the current user */ + $sql = "SELECT * FROM `user_preference` WHERE `user`='$user_id'"; + $db_results = Dba::read($sql); + + $results = array(); + + while ($r = Dba::fetch_assoc($db_results)) { + $pref_id = $r['preference']; + /* Check for duplicates */ + if (isset($results[$pref_id])) { + $r['value'] = Dba::escape($r['value']); + $sql = "DELETE FROM `user_preference` WHERE `user`='$user_id' AND `preference`='" . $r['preference'] . "' AND" . + " `value`='" . Dba::escape($r['value']) . "'"; + $delete_results = Dba::write($sql); + } // if its set + else { + $results[$pref_id] = 1; + } + } // end while + + /* If we aren't the -1 user before we continue grab the -1 users values */ + if ($user_id != '-1') { + $sql = "SELECT `user_preference`.`preference`,`user_preference`.`value` FROM `user_preference`,`preference` " . + "WHERE `user_preference`.`preference` = `preference`.`id` AND `user_preference`.`user`='-1' AND `preference`.`catagory` !='system'"; + $db_results = Dba::read($sql); + /* While through our base stuff */ + while ($r = Dba::fetch_assoc($db_results)) { + $key = $r['preference']; + $zero_results[$key] = $r['value']; + } + } // if not user -1 + + // get me _EVERYTHING_ + $sql = "SELECT * FROM `preference`"; + + // If not system, exclude system... *gasp* + if ($user_id != '-1') { + $sql .= " WHERE catagory !='system'"; + } + $db_results = Dba::read($sql); + + while ($r = Dba::fetch_assoc($db_results)) { + + $key = $r['id']; + + /* Check if this preference is set */ + if (!isset($results[$key])) { + if (isset($zero_results[$key])) { + $r['value'] = $zero_results[$key]; + } + $value = Dba::escape($r['value']); + $sql = "INSERT INTO user_preference (`user`,`preference`,`value`) VALUES ('$user_id','$key','$value')"; + $insert_db = Dba::write($sql); + } + } // while preferences + + /* Let's also clean out any preferences garbage left over */ + $sql = "SELECT DISTINCT(user_preference.user) FROM user_preference " . + "LEFT JOIN user ON user_preference.user = user.id " . + "WHERE user_preference.user!='-1' AND user.id IS NULL"; + $db_results = Dba::read($sql); + + $results = array(); + + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = $r['user']; + } + + foreach ($results as $data) { + $sql = "DELETE FROM user_preference WHERE user='$data'"; + $db_results = Dba::write($sql); + } + + } // fix_preferences + + /** + * delete + * deletes this user and everything associated with it. This will affect + * ratings and tottal stats + */ + public function delete() { + + /* + Before we do anything make sure that they aren't the last + admin + */ + if ($this->has_access(100)) { + $sql = "SELECT `id` FROM `user` WHERE `access`='100' AND id !='" . Dba::escape($this->id) . "'"; + $db_results = Dba::read($sql); + if (!Dba::num_rows($db_results)) { + return false; + } + } // if this is an admin check for others + + // Delete their playlists + $sql = "DELETE FROM `playlist` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); + + // Clean up the playlist data table + $sql = "DELETE FROM `playlist_data` USING `playlist_data` " . + "LEFT JOIN `playlist` ON `playlist`.`id`=`playlist_data`.`playlist` " . + "WHERE `playlist`.`id` IS NULL"; + $db_results = Dba::write($sql); + + // Delete any stats they have + $sql = "DELETE FROM `object_count` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); + + // Clear the IP history for this user + $sql = "DELETE FROM `ip_history` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); + + // Nuke any access lists that are specific to this user + $sql = "DELETE FROM `access_list` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); + + // Delete their ratings + $sql = "DELETE FROM `rating` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); + + // Delete their tags + $sql = "DELETE FROM `tag_map` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); + + // Clean out the tags + $sql = "DELETE FROM `tags` USING `tag_map` LEFT JOIN `tag_map` ON tag_map.id=tags.map_id AND tag_map.id IS NULL"; + $db_results = Dba::write($sql); + + // Delete their preferences + $sql = "DELETE FROM `user_preference` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); - // Delete their voted stuff in democratic play - $sql = "DELETE FROM `user_vote` WHERE `user`='$this->id'"; - $db_results = Dba::write($sql); + // Delete their voted stuff in democratic play + $sql = "DELETE FROM `user_vote` WHERE `user`='$this->id'"; + $db_results = Dba::write($sql); - // Delete their shoutbox posts - $sql = "DELETE FROM `user_shout` WHERE `user='$this->id'"; - $db_results = Dba::write($sql); + // Delete their shoutbox posts + $sql = "DELETE FROM `user_shout` WHERE `user='$this->id'"; + $db_results = Dba::write($sql); - // Delete the user itself - $sql = "DELETE FROM `user` WHERE `id`='$this->id'"; - $db_results = Dba::write($sql); + // Delete the user itself + $sql = "DELETE FROM `user` WHERE `id`='$this->id'"; + $db_results = Dba::write($sql); - $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `session` WHERE `username`='" . Dba::escape($this->username) . "'"; + $db_results = Dba::write($sql); - return true; + return true; - } // delete + } // delete - /** - * is_online - * delay how long since last_seen in seconds default of 20 min - * calcs difference between now and last_seen - * if less than delay, we consider them still online - */ - public function is_online( $delay = 1200 ) { + /** + * is_online + * delay how long since last_seen in seconds default of 20 min + * calcs difference between now and last_seen + * if less than delay, we consider them still online + */ + public function is_online( $delay = 1200 ) { - return time() - $this->last_seen <= $delay; + return time() - $this->last_seen <= $delay; - } // is_online + } // is_online - /** - * get_user_validation - *if user exists before activation can be done. - */ - public static function get_validation($username) { + /** + * get_user_validation + *if user exists before activation can be done. + */ + public static function get_validation($username) { - $usename = Dba::escape($username); + $usename = Dba::escape($username); - $sql = "SELECT `validation` FROM `user` WHERE `username`='$username'"; - $db_results = Dba::read($sql); + $sql = "SELECT `validation` FROM `user` WHERE `username`='$username'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - return $row['validation']; + return $row['validation']; - } // get_validation + } // get_validation - /** - * get_recently_played - * This gets the recently played items for this user respecting - * the limit passed - */ - public function get_recently_played($limit,$type='') { + /** + * get_recently_played + * This gets the recently played items for this user respecting + * the limit passed + */ + public function get_recently_played($limit,$type='') { - if (!$type) { $type = 'song'; } + if (!$type) { $type = 'song'; } - $sql = "SELECT * FROM `object_count` WHERE `object_type`='$type' AND `user`='$this->id' " . - "ORDER BY `date` DESC LIMIT $limit"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `object_count` WHERE `object_type`='$type' AND `user`='$this->id' " . + "ORDER BY `date` DESC LIMIT $limit"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row['object_id']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row['object_id']; + } - return $results; + return $results; - } // get_recently_played + } // get_recently_played - /** - * get_ip_history - * This returns the ip_history from the - * last Config::get('user_ip_cardinality') days - */ - public function get_ip_history($count='',$distinct='') { + /** + * get_ip_history + * This returns the ip_history from the + * last Config::get('user_ip_cardinality') days + */ + public function get_ip_history($count='',$distinct='') { - $username = Dba::escape($this->id); - $count = $count ? intval($count) : intval(Config::get('user_ip_cardinality')); + $username = Dba::escape($this->id); + $count = $count ? intval($count) : intval(Config::get('user_ip_cardinality')); - // Make sure it's something - if ($count < 1) { $count = '1'; } - $limit_sql = "LIMIT " . intval($count); + // Make sure it's something + if ($count < 1) { $count = '1'; } + $limit_sql = "LIMIT " . intval($count); - if ($distinct) { $group_sql = "GROUP BY `ip`"; } + if ($distinct) { $group_sql = "GROUP BY `ip`"; } - /* Select ip history */ - $sql = "SELECT `ip`,`date` FROM `ip_history`" . - " WHERE `user`='$username'" . - " $group_sql ORDER BY `date` DESC $limit_sql"; - $db_results = Dba::read($sql); + /* Select ip history */ + $sql = "SELECT `ip`,`date` FROM `ip_history`" . + " WHERE `user`='$username'" . + " $group_sql ORDER BY `date` DESC $limit_sql"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[] = $row; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[] = $row; + } - return $results; + return $results; - } // get_ip_history + } // get_ip_history - /** - * activate_user - * the user from public_registration - */ - public function activate_user($username) { + /** + * activate_user + * the user from public_registration + */ + public function activate_user($username) { - $username = Dba::escape($username); + $username = Dba::escape($username); - $sql = "UPDATE `user` SET `disabled`='0' WHERE `username`='$username'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `user` SET `disabled`='0' WHERE `username`='$username'"; + $db_results = Dba::write($sql); - } // activate_user + } // activate_user - /** - * is_xmlrpc - * checks to see if this is a valid xmlrpc user - */ - public function is_xmlrpc() { + /** + * is_xmlrpc + * checks to see if this is a valid xmlrpc user + */ + public function is_xmlrpc() { - /* If we aren't using XML-RPC return true */ - if (!Config::get('xml_rpc')) { - return false; - } + /* If we aren't using XML-RPC return true */ + if (!Config::get('xml_rpc')) { + return false; + } - //FIXME: Ok really what we will do is check the MD5 of the HTTP_REFERER - //FIXME: combined with the song title to make sure that the REFERER - //FIXME: is in the access list with full rights - return true; + //FIXME: Ok really what we will do is check the MD5 of the HTTP_REFERER + //FIXME: combined with the song title to make sure that the REFERER + //FIXME: is in the access list with full rights + return true; - } // is_xmlrpc + } // is_xmlrpc - /** - * check_username - * This checks to make sure the username passed doesn't already - * exist in this instance of ampache - */ - public static function check_username($username) { + /** + * check_username + * This checks to make sure the username passed doesn't already + * exist in this instance of ampache + */ + public static function check_username($username) { - $username = Dba::escape($username); + $username = Dba::escape($username); - $sql = "SELECT `id` FROM `user` WHERE `username`='$username'"; - $db_results = Dba::read($sql); + $sql = "SELECT `id` FROM `user` WHERE `username`='$username'"; + $db_results = Dba::read($sql); - if (Dba::num_rows($db_results)) { - return false; - } + if (Dba::num_rows($db_results)) { + return false; + } - return true; + return true; - } // check_username + } // check_username - /** - * rebuild_all_preferences - * This rebuilds the user preferences for all installed users, called by the plugin functions - */ - public static function rebuild_all_preferences() { + /** + * rebuild_all_preferences + * This rebuilds the user preferences for all installed users, called by the plugin functions + */ + public static function rebuild_all_preferences() { - $sql = "SELECT * FROM `user`"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `user`"; + $db_results = Dba::read($sql); - User::fix_preferences('-1'); + User::fix_preferences('-1'); - while ($row = Dba::fetch_assoc($db_results)) { - User::fix_preferences($row['id']); - } + while ($row = Dba::fetch_assoc($db_results)) { + User::fix_preferences($row['id']); + } - return true; + return true; - } // rebuild_all_preferences + } // rebuild_all_preferences } //end user class ?> diff --git a/lib/class/vainfo.class.php b/lib/class/vainfo.class.php index 2df7e74338..b1d825bb84 100644 --- a/lib/class/vainfo.class.php +++ b/lib/class/vainfo.class.php @@ -1,5 +1,5 @@ _iconv = true; - } - else { - $this->_iconv = false; - } - - $this->filename = $file; - if ($encoding) { - $this->encoding = $encoding; - } - else { - $this->encoding = Config::get('site_charset'); - } - - /* These are needed for the filename mojo */ - $this->_file_pattern = $file_pattern; - $this->_dir_pattern = $dir_pattern; - - if(strtoupper(substr(PHP_OS,0,3)) == 'WIN') { - $this->_pathinfo = str_replace('%3A', ':', urlencode($this->filename)); - $this->_pathinfo = pathinfo(str_replace('%5C', '\\', $this->_pathinfo)); - } - else { - $this->_pathinfo = pathinfo(str_replace('%2F', '/', urlencode($this->filename))); - } - $this->_pathinfo['extension'] = strtolower($this->_pathinfo['extension']); - - // Initialize getID3 engine - $this->_getID3 = new getID3(); - - $this->_getID3->option_md5_data = false; - $this->_getID3->option_md5_data_source = false; - $this->_getID3->option_tags_html = false; - $this->_getID3->option_extra_info = true; - $this->_getID3->option_tag_lyrics3 = true; - $this->_getID3->option_tags_process = true; - $this->_getID3->encoding = $this->encoding; - - // get id3tag encoding (try to work around off-spec id3v1 tags) - try { - $this->_raw = $this->_getID3->analyze($file); - } - catch (Exception $error) { - debug_event('Getid3()',"Broken file detected $file - " . $error->message,'1'); - $this->_broken = true; - return false; - } - - /* Use default mb_detect_order in php.ini or not */ - if (Config::get('mb_detect_order')) { - $mb_order = Config::get('mb_detect_order'); - } - elseif (function_exists('mb_detect_order')) { - $mb_order = implode(", ", mb_detect_order()); - } - else { - $mb_order = "auto"; - } - - $test_tags = array('artist', 'album', 'genre', 'title'); - - if ($encoding_id3v1) { - $this->encoding_id3v1 = $encoding_id3v1; - } - else { - foreach ($test_tags as $tag) { - if ($value = $this->_raw['id3v1'][$tag]) { - $tags[$tag] = $value; - } - } - - $this->encoding_id3v1 = self::_detect_encoding($tags, $mb_order); - } - - if (Config::get('getid3_detect_id3v2_encoding')) { - foreach ($test_tags as $tag) { - if ($value = $this->_raw['id3v2']['comments'][$tag]) { - $tags[$tag] = $value; - } - } - - $this->encoding_id3v2 = self::_detect_encoding($tags, $mb_order); - $this->_getID3->encoding_id3v2 = $this->encoding_id3v2; - } - - $this->_getID3->encoding_id3v1 = $this->encoding_id3v1; - - } // vainfo - - /** - * _detect_encoding - * Takes an array of tags and attempts to automatically detect their - * encoding. - */ - private static function _detect_encoding($tags, $mb_order) { - if (function_exists('mb_detect_encoding')) { - $encodings = array(); - $tags = array('artist', 'album', 'genre', 'title'); - foreach ($tags as $tag) { - $encodings[mb_detect_encoding($tag, $mb_order, true)]++; - } - - debug_event('vainfo', 'encoding detection: ' . json_encode($encodings), 5); - $high = 0; - foreach ($encodings as $key => $value) { - if ($value > $high) { - $encoding = $key; - $high = $value; - } - } - - if ($encoding != 'ASCII' && $encoding != '0') { - return $encoding; - } - else { - return 'ISO-8859-1'; - } - } - return 'ISO-8859-1'; - } - - - /** - * get_info - * This function runs the various steps to gathering the metadata - */ - public function get_info() { - - // If this is broken, don't waste time figuring it out a second - // time, just return their rotting carcass of a media file. - if ($this->_broken) { - $this->tags = $this->set_broken(); - return true; - } - - /* Get the Raw file information */ - try { - $this->_raw = $this->_getID3->analyze($this->filename); - } - catch (Exception $error) { - debug_event('Getid3()',"Unable to catalog file:" . $error->message,'1'); - } - - /* Figure out what type of file we are dealing with */ - $this->type = $this->_get_type(); - - $enabled_sources = (array)Config::get('metadata_order'); - - if (in_array('filename', $enabled_sources)) { - $this->tags['filename'] = $this->_parse_filename($this->filename); - } - - if (in_array('getID3', $enabled_sources)) { - $this->tags['getID3'] = $this->_get_tags(); - } - - $this->_get_plugin_tags(); - - } // get_info - - /** - * get_tag_type - * This takes the result set and the tag_order defined in your config - * file and tries to figure out which tag type(s) it should use. If your - * tag_order doesn't match anything then it throws up its hands and uses - * everything. - */ - public static function get_tag_type($results, $config_key = 'metadata_order') { - - $order = (array)Config::get($config_key); - - /* Iterate through the defined key order adding them to an - * ordered array as we go. - */ - - foreach($order as $key) { - if ($results[$key]) { - $returned_keys[] = $key; - } - } - - /* If we didn't find anything then default to everything. - */ - if (!isset($returned_keys)) { - $returned_keys = array_keys($results); - $returned_keys = sort($returned_keys); - } - - return $returned_keys; - - } // get_tag_type - - /** - * clean_tag_info - * This function takes the array from vainfo along with the - * key we've decided on and the filename and returns it in a - * sanitized format that ampache can actually use - */ - public static function clean_tag_info($results, $keys, $filename = null) { - - $info = array(); - - if ($filename) { - $info['file'] = $filename; - } - - // Iteration! - foreach ($keys as $key) { - $tags = $results[$key]; - - $info['file'] = $info['file'] ?: $tags['file']; - $info['bitrate'] = $info['bitrate'] ?: intval($tags['bitrate']); - $info['rate'] = $info['rate'] ?: intval($tags['rate']); - $info['mode'] = $info['mode'] ?: $tags['mode']; - $info['size'] = $info['size'] ?: $tags['size']; - $info['mime'] = $info['mime'] ?: $tags['mime']; - $info['encoding'] = $info['encoding'] ?: $tags['encoding']; - $info['rating'] = $info['rating'] ?: $tags['rating']; - $info['time'] = $info['time'] ?: intval($tags['time']); - $info['channels'] = $info['channels'] ?: $tags['channels']; - - /* These are used to generate the correct IDs later */ - $info['title'] = $info['title'] ?: stripslashes(trim($tags['title'])); - - $info['year'] = $info['year'] ?: intval($tags['year']); - - $info['disk'] = $info['disk'] ?: intval($tags['disk']); - - $info['totaldiscs'] = $info['totaldiscs'] ?: intval($tags['totaldiscs']); - - $info['artist'] = $info['artist'] ?: trim($tags['artist']); - - $info['album'] = $info['album'] ?: trim($tags['album']); - - // multiple genre support - if ((!$info['genre']) && $tags['genre']) { - if (!is_array($tags['genre'])) { - // not all tag formats will return an array, but we need one - $info['genre'][] = trim($tags['genre']); - } - else { - // if we trim the array we lose everything after 1st entry - foreach ($tags['genre'] as $genre) { - $info['genre'][] = trim($genre); - } - } - } - - $info['mb_trackid'] = $info['mb_trackid'] ?: trim($tags['mb_trackid']); - $info['mb_albumid'] = $info['mb_albumid'] ?: trim($tags['mb_albumid']); - $info['mb_artistid'] = $info['mb_artistid'] ?: trim($tags['mb_artistid']); - - /* @TODO language doesn't import from id3tag. @momo-i */ - $info['language'] = $info['language'] ?: Dba::escape($tags['language']); - - $info['lyrics'] = $info['lyrics'] - ?: str_replace( - array("\r\n","\r","\n"), - '
    ', - strip_tags($tags['lyrics'])); - - $info['track'] = $info['track'] ?: intval($tags['track']); - $info['resolution_x'] = $info['resolution_x'] ?: intval($tags['resolution_x']); - $info['resolution_y'] = $info['resolution_y'] ?: intval($tags['resolution_y']); - $info['audio_codec'] = $info['audio_codec'] ?: Dba::escape($tags['audio_codec']); - $info['video_codec'] = $info['video_codec'] ?: Dba::escape($tags['video_codec']); - } - - if ($info['totaldiscs'] == 1 && $info['disk'] == 1) { - unset($info['disk']); - unset($info['totaldiscs']); - } - - return $info; - - } // clean_tag_info - - /** - * _get_type - * This function takes the raw information and figures out - * what type of file we are dealing with for use by the tag - * function - */ - public function _get_type() { - - /* There are a few places that the file type can - * come from, in the end we trust the encoding - * type - */ - if ($type = $this->_raw['video']['dataformat']) { - $type = $this->_clean_type($type); - return $type; - } - if ($type = $this->_raw['audio']['streams']['0']['dataformat']) { - $type = $this->_clean_type($type); - return $type; - } - if ($type = $this->_raw['audio']['dataformat']) { - $type = $this->_clean_type($type); - return $type; - } - if ($type = $this->_raw['fileformat']) { - $type = $this->_clean_type($type); - return $type; - } - - return false; - - } // _get_type - - - /** - * _get_tags - * This function takes the raw information and the type and - * attempts to gather the tags and then normalize them into - * ['tag_name']['var'] = value - */ - public function _get_tags() { - - $results = array(); - - /* The tags can come in many different shapes and colors - * depending on the encoding time of day and phase of the moon. - */ - foreach ($this->_raw['tags'] as $key => $tag_array) { - switch ($key) { - case 'vorbiscomment': - debug_event('_get_tags', 'Parsing vorbis', '5'); - $results[$key] = $this->_parse_vorbiscomment($tag_array); - break; - case 'id3v1': - debug_event('_get_tags', 'Parsing id3v1', '5'); - $results[$key] = $this->_parse_id3v1($tag_array); - break; - case 'id3v2': - debug_event('_get_tags', 'Parsing id3v2', '5'); - $results[$key] = $this->_parse_id3v2($tag_array); - break; - case 'ape': - debug_event('_get_tags', 'Parsing ape', '5'); - $results[$key] = $this->_parse_ape($tag_array); - break; - case 'quicktime': - debug_event('_get_tags', 'Parsing quicktime', '5'); - $results[$key] = $this->_parse_quicktime($tag_array); - break; - case 'riff': - debug_event('_get_tags', 'Parsing riff', '5'); - $results[$key] = $this->_parse_riff($tag_array); - break; - case 'flv': - debug_event('_get_tags', 'Parsing flv', '5'); - $results[$key] = $this->_parse_flv($this->_raw); - break; - case 'mpg': - case 'mpeg': - debug_event('_get_tags', 'Parsing MPEG', '5'); - $results['mpeg'] = $this->_parse_mpg($this->_raw); - break; - case 'asf': - case 'wmv': - debug_event('_get_tags', 'Parsing WMV/WMA/ASF', '5'); - $results['asf'] = $this->_parse_wmv($this->_raw); - break; - case 'avi': - debug_event('_get_tags', 'Parsing avi', '5'); - $results[$key] = $this->_parse_avi($this->_raw); - break; - case 'lyrics3': - debug_event('_get_tags', 'Parsing lyrics3', '5'); - $results[$key] = $this->_parse_lyrics($tag_array); - break; - default: - debug_event('vainfo','Error: Unable to determine tag type of ' . $key . ' for file ' . $this->filename . ' Assuming id3v2','5'); - $results[$key] = $this->_parse_id3v2($this->_raw['id3v2']['comments']); - break; - } // end switch - } // end foreach - - - $cleaned = self::clean_tag_info($results, self::get_tag_type($results, 'getid3_tag_order'), $this->filename); - $cleaned = array_merge($cleaned, $this->_get_info()); - $cleaned['raw'] = $results; - - return $cleaned; - - } // _get_tags - - /** - * _get_plugin_tags - * Get additional metadata from plugins - */ - private function _get_plugin_tags() { - $tag_order = Config::get('metadata_order'); - if (!is_array($tag_order)) { - $tag_order = array($tag_order); - } - - $plugin_names = Plugin::get_plugins('get_metadata'); - foreach ($tag_order as $key => $tag_source) { - if (in_array($tag_source, $plugin_names)) { - $plugin = new Plugin($tag_source); - if ($plugin->load()) { - $this->tags[$tag_source] = $plugin->_plugin->get_metadata(self::clean_tag_info($this->tags, self::get_tag_type($this->tags), $this->filename)); - } - } - } - } // _get_plugin_tags - - /** - * _get_info - * Gather and return the general information about a song (vbr/cbr, - * sample rate, channels, etc.) - */ - private function _get_info() { - - $array = array(); - - /* Try to pull the information directly from - * the audio array - */ - if ($this->_raw['audio']['bitrate_mode']) { - $array['mode'] = $this->_raw['audio']['bitrate_mode']; - if ($array['mode'] == 'con') { - $array['mode'] = 'cbr'; - } - } - if ($this->_raw['audio']['bitrate']) { - $array['bitrate'] = $this->_raw['audio']['bitrate']; - } - if ($this->_raw['audio']['channels']) { - $array['channels'] = intval($this->_raw['audio']['channels']); - } - if ($this->_raw['audio']['sample_rate']) { - $array['rate'] = intval($this->_raw['audio']['sample_rate']); - } - if ($this->_raw['filesize']) { - $array['size'] = intval($this->_raw['filesize']); - } - if ($this->_raw['encoding']) { - $array['encoding'] = $this->_raw['encoding']; - } - if ($this->_raw['mime_type']) { - $array['mime'] = $this->_raw['mime_type']; - } - if ($this->_raw['playtime_seconds']) { - $array['time'] = $this->_raw['playtime_seconds']; - } - - return $array; - - } // _get_info - - /** - * _clean_type - * This standardizes the type that we are given into a recognized type. - */ - private function _clean_type($type) { - - switch ($type) { - case 'mp3': - case 'mp2': - case 'mpeg3': - return 'mp3'; - break; - case 'vorbis': - return 'ogg'; - break; - case 'flac': - case 'flv': - case 'mpg': - case 'mpeg': - case 'asf': - case 'wmv': - case 'avi': - case 'quicktime': - return $type; - default: - /* Log the fact that we couldn't figure it out */ - debug_event('vainfo','Unable to determine file type from ' . $type . ' on file ' . $this->filename,'5'); - return $type; - break; - } // end switch on type - - } // _clean_type - - /** - * _parse_lyrics - * This function takes a lyrics3 from getid3() - * nothing to do? - */ - private function _parse_lyrics($tags) { - - /* Results array */ - $array = array(); - - /* go through them all! */ - foreach ($tags as $tag => $data) { - if ($tag == 'unsynchedlyrics' || $tag == 'unsynchronised lyric') { - $tag = 'lyrics'; - } - $array[$tag] = $this->_clean_tag($data['0']); - - } // end foreach - - return $array; - - } // _parse_lyrics - - /** - * _parse_vorbiscomment - * This function takes a vorbiscomment from getid3() and then - * returns the elements translated using iconv if needed in a - * pretty little format - */ - private function _parse_vorbiscomment($tags) { - - /* Results array */ - $array = array(); - - /* go through them all! */ - foreach ($tags as $tag=>$data) { - - /* We need to translate a few of these tags */ - switch ($tag) { - - case 'genre': - // multiple genre support - foreach($data as $foo) { - $array['genre'][] = $this->_clean_tag($foo,''); - } - break; - case 'tracknumber': - $array['track'] = $this->_clean_tag($data['0']); - break; - case 'discnumber': - $el = explode('/', $data['0']); - $array['disk'] = $el[0]; - break; - case 'date': - $array['year'] = $this->_clean_tag($data['0']); - break; - default: - $array[$tag] = $this->_clean_tag($data['0']); - break; - } // end switch - - } // end foreach - - return $array; - - } // _parse_vorbiscomment - - /** - * _parse_id3v1 - * This function takes an id3v1 tag set from getid3() and then - * returns the elements (translated using iconv if needed) in a - * pretty little format. - */ - private function _parse_id3v1($tags) { - - $array = array(); - - /* Go through all the tags */ - foreach ($tags as $tag=>$data) { - - /* This is our baseline for naming - * so no translation needed - */ - $array[$tag] = $this->_clean_tag($data['0']); - - } // end foreach - - return $array; - - } // _parse_id3v1 - - /** - * _parse_id3v2 - * This function takes an id3v2 tag set from getid3() and then - * returns the elements (translated using iconv if needed) in a - * pretty little format. - */ - private function _parse_id3v2($tags) { - - $array = array(); - - /* Go through the tags */ - foreach ($tags as $tag=>$data) { - - /** - * the new getid3 handles this differently - * so we now need to account for it :( - */ - switch ($tag) { - case 'genre': - // multiple genre support - foreach($data as $genre) { - $array['genre'][] = $this->_clean_tag($genre); - } - break; - case 'part_of_a_set': - $el = explode('/', $data['0']); - $array['disk'] = $el[0]; - $array['totaldiscs'] = $el[1]; - break; - case 'track_number': - $array['track'] = $this->_clean_tag($data['0']); - break; - case 'comments': - $array['comment'] = $this->_clean_tag($data['0']); - break; - default: - $array[$tag] = $this->_clean_tag($data['0']); - break; - } // end switch on tag - - } // end foreach - - $id3v2 = $this->_raw['id3v2']; - - if(!empty($id3v2['UFID'])) { - // Find the MBID for the track - foreach ($id3v2['UFID'] as $ufid) { - if ($ufid['ownerid'] == 'http://musicbrainz.org') { - $array['mb_trackid'] = $this->_clean_tag($ufid['data']); - } - } - - // Find the MBIDs for the album and artist - foreach ($id3v2['TXXX'] as $txxx) { - switch ($txxx['description']) { - case 'MusicBrainz Album Id': - $array['mb_albumid'] = $this->_clean_tag($txxx['data']); - break; - case 'MusicBrainz Artist Id': - $array['mb_artistid'] = $this->_clean_tag($txxx['data']); - break; - } - } - } - - // Find the rating - if (is_array($id3v2['POPM'])) { - foreach ($id3v2['POPM'] as $popm) { - if (array_key_exists('email', $popm) && - $user = User::get_from_email($popm['email'])) { - // Ratings are out of 255; scale it - $array['rating'][$user->id] = $popm['rating'] / 255 * 5; - } - } - } - - return $array; - - } // _parse_id3v2 - - /** - * _parse_ape - * This function takes ape tags set by getid3() and then - * returns the elements translated using iconv if needed in a - * pretty little format - */ - private function _parse_ape($tags) { - - foreach ($tags as $tag=>$data) { - switch ($tag) { - - case 'genre': - // multiple genre support - foreach($data as $genre) { - $array['genre'][] = $this->_clean_tag($genre); - } - break; - - default: - $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding); - break; - } // end switch on tag - - } // end foreach tags - - return $array; - - } // _parse_ape - - /** - * _parse_riff - * this function takes the riff take information passed by getid3() and - * then reformats it so that it matches the other formats. May require iconv - */ - private function _parse_riff($tags) { - - foreach ($tags as $tag=>$data) { - - switch ($tag) { - case 'product': - $array['album'] = $this->_clean_tag($data['0'], $this->_file_encoding); - break; - default: - $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding); - break; - } // end switch on tag - - } // foreach tags - - return $array; - - } // _parse_riff - - /** - * _parse_quicktime - * this function takes the quicktime tags set by getid3() and then - * returns the elements translated using iconv if needed in a - * pretty little format - */ - private function _parse_quicktime($tags) { - - /* Results array */ - $array = array(); - - /* go through them all! */ - foreach ($tags as $tag=>$data) { - - /* We need to translate a few of these tags */ - switch ($tag) { - case 'creation_date': - if (strlen($data['0']) > 4) { - /* Weird Date format, attempt to normalize */ - $data['0'] = date("Y",strtotime($data['0'])); - } - $array['year'] = $this->_clean_tag($data['0']); - break; - case 'MusicBrainz Track Id': - $array['mb_trackid'] = $this->_clean_tag($data['0']); - break; - case 'MusicBrainz Album Id': - $array['mb_albumid'] = $this->_clean_tag($data['0']); - break; - case 'MusicBrainz Artist Id': - $array['mb_artistid'] = $this->_clean_tag($data['0']); - break; - } // end switch - - $array[$tag] = $this->_clean_tag($data['0']); - - } // end foreach - - // Also add in any video related stuff we might find - if (strpos($this->_raw['mime_type'], 'video') !== false) { - $info = $this->_parse_avi($this->_raw); - $info['video_codec'] = $this->_raw['quicktime']['ftyp']['fourcc']; - $array = array_merge($info, $array); - } - - return $array; - - } // _parse_quicktime - - /** - * _parse_avi - * This attempts to parse our the information on an avi file and present it in some - * kind of sane format, this is a little hard as these files don't have tags - */ - private function _parse_avi($tags) { - - $array = array(); - - $array['title'] = urldecode($this->_pathinfo['filename']); - $array['video_codec'] = $tags['video']['fourcc']; - $array['audio_codec'] = $tags['audio']['dataformat']; - $array['resolution_x'] = $tags['video']['resolution_x']; - $array['resolution_y'] = $tags['video']['resolution_y']; - $array['mime'] = $tags['mime_type']; - $array['comment'] = $tags['video']['codec']; - - return $array; - - } // _parse_avi - - /** - * _parse_mpg - * This attempts to parse our the information on a mpg file and present it in some - * kind of sane format, this is a little hard as these files don't have tags - */ - private function _parse_mpg($tags) { - - $array = array(); - - $array['title'] = urldecode($this->_pathinfo['filename']); - $array['video_codec'] = $tags['video']['codec']; - $array['audio_codec'] = $tags['audio']['dataformat']; - $array['resolution_x'] = $tags['video']['resolution_x']; - $array['resolution_y'] = $tags['video']['resolution_y']; - $array['mime'] = $tags['mime_type']; - $array['comment'] = $tags['video']['codec']; - - return $array; - - } // _parse_mpg - - /** - * _parse_wmv - * This attempts to parse our the information on a asf/wmv file and present it in some - * kind of sane format, this is a little hard as these files don't have tags - */ - private function _parse_wmv($tags) { - - $array = array(); - - $array['mime'] = $tags['mime_type']; - - switch($array['mime']) { - default: - case 'video/x-ms-wmv': - if(isset($tags['tags']['asf']['title']['0'])) { - $array['title'] = $tags['tags']['asf']['title']['0']; - } - else { - $array['title'] = urldecode($this->_pathinfo['filename']); - } - $array['video_codec'] = $tags['video']['streams']['2']['codec']; - $array['audio_codec'] = $tags['audio']['streams']['1']['codec']; - $array['resolution_x'] = $tags['video']['streams']['2']['resolution_x']; - $array['resolution_y'] = $tags['video']['streams']['2']['resolution_y']; - $array['comment'] = $tags['tags']['asf']['title']['1']; - break; - } - - foreach($tags['tags']['asf'] as $tag => $data) { - $array[$tag] = $this->_clean_tag($data['0']); - } - - return $array; - - } // _parse_wmv - - /** - * _parse_flv - * This attempts to parse our the information on an flv file and present it in some - * kind of sane format, this is a little hard as these files don't have tags - */ - private function _parse_flv($tags) { - - $array = array(); - - $array['title'] = urldecode($this->_pathinfo['filename']); - $array['video_codec'] = $tags['video']['codec']; - $array['audio_codec'] = $tags['audio']['dataformat']; - $array['resolution_x'] = $tags['video']['resolution_x']; - $array['resolution_y'] = $tags['video']['resolution_y']; - $array['mime'] = $tags['mime_type']; - $array['comment'] = $tags['video']['codec']; - - return $array; - - } // _parse_flv - - /** - * _parse_filename - * - * This function uses the passed file and dir patterns - * To pull out extra tag information and populate it into - * its own array - * - * @param string $filename Filename that want to parse - * @return array Parsed results - */ - private function _parse_filename($filename) { - - $results = array(); - - // Correctly detect the slash we need to use here - if (strpos($filename, '/') !== false) { - $slash_type = '/'; - } - else { - $slash_type = '\\'; - } - - // Combine the patterns - $pattern = preg_quote($this->_dir_pattern) . $slash_type . preg_quote($this->_file_pattern); - - // Pull out the pattern codes into an array - preg_match_all('/\%\w/', $pattern, $elements); - - // Mangle the pattern by turning the codes into regex captures - $pattern = preg_replace('/\%[Ty]/', '([0-9]+?)', $pattern); - $pattern = preg_replace('/\%\w/', '(.+?)', $pattern); - $pattern = str_replace('/', '\/', $pattern); - $pattern = str_replace(' ', '\s', $pattern); - $pattern = '/' . $pattern . '\..+$/'; - - // Pull out our actual matches - preg_match($pattern, $filename, $matches); - - // The first element is the full match text - $matched = array_shift($matches); - debug_event('vainfo', $pattern . ' matched ' . $matched . ' on ' . $filename, 5); - - // Iterate over what we found - foreach ($matches as $key => $value) { - $new_key = translate_pattern_code($elements['0'][$key]); - if ($new_key) { - $results[$new_key] = $value; - } - } - - $results['size'] = filesize($filename); - - return $results; - - } // _parse_filename - - /** - * _id3v2_tag_to_frame - * - * This translates the tag name to a frame, if there a many it returns the first - * one if finds that exists in the raw - * - * @param string $tag_name Tag name - * @return mixed If found id3v2 frame, return frame. If not found, return false. - */ - private function _id3v2_tag_to_frame($tag_name) { - - static $map = array( - 'comment'=>array('COM','COMM'), - 'cd_ident'=>array('MCDI','MCI'), - 'album'=>array('TAL','TALB'), - 'language'=>array('TLA','TLAN'), - 'mood'=>array('TMOO'), - 'artist'=>array('TPE1'), - 'year'=>array('TDRC')); - - foreach ($map[$tag_name] as $frame) { - if (isset($this->_raw['id3v2'][$frame])) { - return $frame; - } - } - - return false; - - } // _id3v2_tag_to_frame - - /** - * _clean_tag - * - * This function cleans up the tag that it's passed using Iconv - * if we've got it. It also takes an optional encoding param - * for the cases where we know what the tags source encoding - * is, and or if it's different then the encoding recorded - * in the file - * - * @param string $tag Encoding string - * @param string $encoding Encode charset - * @return string Return encoded string - */ - private function _clean_tag($tag, $encoding = null) { - - // Default to getID3's native encoding - if (!$encoding) { - $encoding = $this->_getID3->encoding; - } - // If we've got iconv then go ahead and clear her up - if ($encoding == $this->encoding) { - debug_event('vainfo', "\$encoding -> ${encoding}, \$this->encoding -> {$this->encoding}", 5); - return $tag; - } - if ($this->_iconv) { - debug_event('vainfo', 'Use iconv()',5); - - // Try GNU iconv //TRANSLIT extension first - $new_encoding = $this->encoding . '//TRANSLIT'; - $clean = iconv($encoding, $new_encoding, $tag); - - // If that fails, do a plain conversion - if(strcmp($clean, '') == 0) { - $clean = iconv($encoding, $this->encoding, $tag); - } - } - elseif (function_exists('mb_convert_encoding')) { - debug_event('vainfo', 'Use mbstring',5); - debug_event('vainfo', "Try to convert from {$this->encoding} to $encoding", 5); - $clean = mb_convert_encoding($tag, $encoding, $this->encoding); - } - else { - $clean = $tag; - } - - return $clean; - - } // _clean_tag - - /** - * set_broken - * - * This fills all tag types with Unknown (Broken) - * - * @return array Return broken title, album, artist - */ - public function set_broken() { - - /* Pull In the config option */ - $order = Config::get('tag_order'); - - if (!is_array($order)) { - $order = array($order); - } - - $key = array_shift($order); - - $broken[$key]['title'] = '**BROKEN** ' . $this->filename; - $broken[$key]['album'] = 'Unknown (Broken)'; - $broken[$key]['artist'] = 'Unknown (Broken)'; - - return $broken; - - } // set_broken + public $encoding = ''; + public $encoding_id3v1 = ''; + public $encoding_id3v2 = ''; + + public $filename = ''; + public $type = ''; + public $tags = array(); + + protected $_raw = array(); + protected $_getID3 = ''; + protected $_iconv = false; + + protected $_file_encoding = ''; + protected $_file_pattern = ''; + protected $_dir_pattern = ''; + + private $_pathinfo; + private $_broken = false; + + /** + * Constructor + * + * This function just sets up the class, it doesn't + * actually pull the information + * + * @param string $file filename + * @param string $encoding Target encode character set + * @param string $encoding_id3v1 Default id3v1 encode character set + * @param string $encoding_iv3v2 Default id3v2 encode character set + * @param string $dir_pattern Directory pattern + * @param string $file_pattern File pattern + * @return mixed If can't analyze file, return false. default return: void + */ + public function __construct($file, $encoding = null, $encoding_id3v1 = null, $encoding_id3v2 = null, $dir_pattern, $file_pattern) { + + /* Check for ICONV */ + if (function_exists('iconv') && Config::get('use_iconv') == "1") { + $this->_iconv = true; + } + else { + $this->_iconv = false; + } + + $this->filename = $file; + if ($encoding) { + $this->encoding = $encoding; + } + else { + $this->encoding = Config::get('site_charset'); + } + + /* These are needed for the filename mojo */ + $this->_file_pattern = $file_pattern; + $this->_dir_pattern = $dir_pattern; + + if(strtoupper(substr(PHP_OS,0,3)) == 'WIN') { + $this->_pathinfo = str_replace('%3A', ':', urlencode($this->filename)); + $this->_pathinfo = pathinfo(str_replace('%5C', '\\', $this->_pathinfo)); + } + else { + $this->_pathinfo = pathinfo(str_replace('%2F', '/', urlencode($this->filename))); + } + $this->_pathinfo['extension'] = strtolower($this->_pathinfo['extension']); + + // Initialize getID3 engine + $this->_getID3 = new getID3(); + + $this->_getID3->option_md5_data = false; + $this->_getID3->option_md5_data_source = false; + $this->_getID3->option_tags_html = false; + $this->_getID3->option_extra_info = true; + $this->_getID3->option_tag_lyrics3 = true; + $this->_getID3->option_tags_process = true; + $this->_getID3->encoding = $this->encoding; + + // get id3tag encoding (try to work around off-spec id3v1 tags) + try { + $this->_raw = $this->_getID3->analyze($file); + } + catch (Exception $error) { + debug_event('Getid3()',"Broken file detected $file - " . $error->message,'1'); + $this->_broken = true; + return false; + } + + /* Use default mb_detect_order in php.ini or not */ + if (Config::get('mb_detect_order')) { + $mb_order = Config::get('mb_detect_order'); + } + elseif (function_exists('mb_detect_order')) { + $mb_order = implode(", ", mb_detect_order()); + } + else { + $mb_order = "auto"; + } + + $test_tags = array('artist', 'album', 'genre', 'title'); + + if ($encoding_id3v1) { + $this->encoding_id3v1 = $encoding_id3v1; + } + else { + foreach ($test_tags as $tag) { + if ($value = $this->_raw['id3v1'][$tag]) { + $tags[$tag] = $value; + } + } + + $this->encoding_id3v1 = self::_detect_encoding($tags, $mb_order); + } + + if (Config::get('getid3_detect_id3v2_encoding')) { + foreach ($test_tags as $tag) { + if ($value = $this->_raw['id3v2']['comments'][$tag]) { + $tags[$tag] = $value; + } + } + + $this->encoding_id3v2 = self::_detect_encoding($tags, $mb_order); + $this->_getID3->encoding_id3v2 = $this->encoding_id3v2; + } + + $this->_getID3->encoding_id3v1 = $this->encoding_id3v1; + + } // vainfo + + /** + * _detect_encoding + * Takes an array of tags and attempts to automatically detect their + * encoding. + */ + private static function _detect_encoding($tags, $mb_order) { + if (function_exists('mb_detect_encoding')) { + $encodings = array(); + $tags = array('artist', 'album', 'genre', 'title'); + foreach ($tags as $tag) { + $encodings[mb_detect_encoding($tag, $mb_order, true)]++; + } + + debug_event('vainfo', 'encoding detection: ' . json_encode($encodings), 5); + $high = 0; + foreach ($encodings as $key => $value) { + if ($value > $high) { + $encoding = $key; + $high = $value; + } + } + + if ($encoding != 'ASCII' && $encoding != '0') { + return $encoding; + } + else { + return 'ISO-8859-1'; + } + } + return 'ISO-8859-1'; + } + + + /** + * get_info + * This function runs the various steps to gathering the metadata + */ + public function get_info() { + + // If this is broken, don't waste time figuring it out a second + // time, just return their rotting carcass of a media file. + if ($this->_broken) { + $this->tags = $this->set_broken(); + return true; + } + + /* Get the Raw file information */ + try { + $this->_raw = $this->_getID3->analyze($this->filename); + } + catch (Exception $error) { + debug_event('Getid3()',"Unable to catalog file:" . $error->message,'1'); + } + + /* Figure out what type of file we are dealing with */ + $this->type = $this->_get_type(); + + $enabled_sources = (array)Config::get('metadata_order'); + + if (in_array('filename', $enabled_sources)) { + $this->tags['filename'] = $this->_parse_filename($this->filename); + } + + if (in_array('getID3', $enabled_sources)) { + $this->tags['getID3'] = $this->_get_tags(); + } + + $this->_get_plugin_tags(); + + } // get_info + + /** + * get_tag_type + * This takes the result set and the tag_order defined in your config + * file and tries to figure out which tag type(s) it should use. If your + * tag_order doesn't match anything then it throws up its hands and uses + * everything. + */ + public static function get_tag_type($results, $config_key = 'metadata_order') { + + $order = (array)Config::get($config_key); + + /* Iterate through the defined key order adding them to an + * ordered array as we go. + */ + + foreach($order as $key) { + if ($results[$key]) { + $returned_keys[] = $key; + } + } + + /* If we didn't find anything then default to everything. + */ + if (!isset($returned_keys)) { + $returned_keys = array_keys($results); + $returned_keys = sort($returned_keys); + } + + return $returned_keys; + + } // get_tag_type + + /** + * clean_tag_info + * This function takes the array from vainfo along with the + * key we've decided on and the filename and returns it in a + * sanitized format that ampache can actually use + */ + public static function clean_tag_info($results, $keys, $filename = null) { + + $info = array(); + + if ($filename) { + $info['file'] = $filename; + } + + // Iteration! + foreach ($keys as $key) { + $tags = $results[$key]; + + $info['file'] = $info['file'] ?: $tags['file']; + $info['bitrate'] = $info['bitrate'] ?: intval($tags['bitrate']); + $info['rate'] = $info['rate'] ?: intval($tags['rate']); + $info['mode'] = $info['mode'] ?: $tags['mode']; + $info['size'] = $info['size'] ?: $tags['size']; + $info['mime'] = $info['mime'] ?: $tags['mime']; + $info['encoding'] = $info['encoding'] ?: $tags['encoding']; + $info['rating'] = $info['rating'] ?: $tags['rating']; + $info['time'] = $info['time'] ?: intval($tags['time']); + $info['channels'] = $info['channels'] ?: $tags['channels']; + + /* These are used to generate the correct IDs later */ + $info['title'] = $info['title'] ?: stripslashes(trim($tags['title'])); + + $info['year'] = $info['year'] ?: intval($tags['year']); + + $info['disk'] = $info['disk'] ?: intval($tags['disk']); + + $info['totaldiscs'] = $info['totaldiscs'] ?: intval($tags['totaldiscs']); + + $info['artist'] = $info['artist'] ?: trim($tags['artist']); + + $info['album'] = $info['album'] ?: trim($tags['album']); + + // multiple genre support + if ((!$info['genre']) && $tags['genre']) { + if (!is_array($tags['genre'])) { + // not all tag formats will return an array, but we need one + $info['genre'][] = trim($tags['genre']); + } + else { + // if we trim the array we lose everything after 1st entry + foreach ($tags['genre'] as $genre) { + $info['genre'][] = trim($genre); + } + } + } + + $info['mb_trackid'] = $info['mb_trackid'] ?: trim($tags['mb_trackid']); + $info['mb_albumid'] = $info['mb_albumid'] ?: trim($tags['mb_albumid']); + $info['mb_artistid'] = $info['mb_artistid'] ?: trim($tags['mb_artistid']); + + /* @TODO language doesn't import from id3tag. @momo-i */ + $info['language'] = $info['language'] ?: Dba::escape($tags['language']); + + $info['lyrics'] = $info['lyrics'] + ?: str_replace( + array("\r\n","\r","\n"), + '
    ', + strip_tags($tags['lyrics'])); + + $info['track'] = $info['track'] ?: intval($tags['track']); + $info['resolution_x'] = $info['resolution_x'] ?: intval($tags['resolution_x']); + $info['resolution_y'] = $info['resolution_y'] ?: intval($tags['resolution_y']); + $info['audio_codec'] = $info['audio_codec'] ?: Dba::escape($tags['audio_codec']); + $info['video_codec'] = $info['video_codec'] ?: Dba::escape($tags['video_codec']); + } + + if ($info['totaldiscs'] == 1 && $info['disk'] == 1) { + unset($info['disk']); + unset($info['totaldiscs']); + } + + return $info; + + } // clean_tag_info + + /** + * _get_type + * This function takes the raw information and figures out + * what type of file we are dealing with for use by the tag + * function + */ + public function _get_type() { + + /* There are a few places that the file type can + * come from, in the end we trust the encoding + * type + */ + if ($type = $this->_raw['video']['dataformat']) { + $type = $this->_clean_type($type); + return $type; + } + if ($type = $this->_raw['audio']['streams']['0']['dataformat']) { + $type = $this->_clean_type($type); + return $type; + } + if ($type = $this->_raw['audio']['dataformat']) { + $type = $this->_clean_type($type); + return $type; + } + if ($type = $this->_raw['fileformat']) { + $type = $this->_clean_type($type); + return $type; + } + + return false; + + } // _get_type + + + /** + * _get_tags + * This function takes the raw information and the type and + * attempts to gather the tags and then normalize them into + * ['tag_name']['var'] = value + */ + public function _get_tags() { + + $results = array(); + + /* The tags can come in many different shapes and colors + * depending on the encoding time of day and phase of the moon. + */ + foreach ($this->_raw['tags'] as $key => $tag_array) { + switch ($key) { + case 'vorbiscomment': + debug_event('_get_tags', 'Parsing vorbis', '5'); + $results[$key] = $this->_parse_vorbiscomment($tag_array); + break; + case 'id3v1': + debug_event('_get_tags', 'Parsing id3v1', '5'); + $results[$key] = $this->_parse_id3v1($tag_array); + break; + case 'id3v2': + debug_event('_get_tags', 'Parsing id3v2', '5'); + $results[$key] = $this->_parse_id3v2($tag_array); + break; + case 'ape': + debug_event('_get_tags', 'Parsing ape', '5'); + $results[$key] = $this->_parse_ape($tag_array); + break; + case 'quicktime': + debug_event('_get_tags', 'Parsing quicktime', '5'); + $results[$key] = $this->_parse_quicktime($tag_array); + break; + case 'riff': + debug_event('_get_tags', 'Parsing riff', '5'); + $results[$key] = $this->_parse_riff($tag_array); + break; + case 'flv': + debug_event('_get_tags', 'Parsing flv', '5'); + $results[$key] = $this->_parse_flv($this->_raw); + break; + case 'mpg': + case 'mpeg': + debug_event('_get_tags', 'Parsing MPEG', '5'); + $results['mpeg'] = $this->_parse_mpg($this->_raw); + break; + case 'asf': + case 'wmv': + debug_event('_get_tags', 'Parsing WMV/WMA/ASF', '5'); + $results['asf'] = $this->_parse_wmv($this->_raw); + break; + case 'avi': + debug_event('_get_tags', 'Parsing avi', '5'); + $results[$key] = $this->_parse_avi($this->_raw); + break; + case 'lyrics3': + debug_event('_get_tags', 'Parsing lyrics3', '5'); + $results[$key] = $this->_parse_lyrics($tag_array); + break; + default: + debug_event('vainfo','Error: Unable to determine tag type of ' . $key . ' for file ' . $this->filename . ' Assuming id3v2','5'); + $results[$key] = $this->_parse_id3v2($this->_raw['id3v2']['comments']); + break; + } // end switch + } // end foreach + + + $cleaned = self::clean_tag_info($results, self::get_tag_type($results, 'getid3_tag_order'), $this->filename); + $cleaned = array_merge($cleaned, $this->_get_info()); + $cleaned['raw'] = $results; + + return $cleaned; + + } // _get_tags + + /** + * _get_plugin_tags + * Get additional metadata from plugins + */ + private function _get_plugin_tags() { + $tag_order = Config::get('metadata_order'); + if (!is_array($tag_order)) { + $tag_order = array($tag_order); + } + + $plugin_names = Plugin::get_plugins('get_metadata'); + foreach ($tag_order as $key => $tag_source) { + if (in_array($tag_source, $plugin_names)) { + $plugin = new Plugin($tag_source); + if ($plugin->load()) { + $this->tags[$tag_source] = $plugin->_plugin->get_metadata(self::clean_tag_info($this->tags, self::get_tag_type($this->tags), $this->filename)); + } + } + } + } // _get_plugin_tags + + /** + * _get_info + * Gather and return the general information about a song (vbr/cbr, + * sample rate, channels, etc.) + */ + private function _get_info() { + + $array = array(); + + /* Try to pull the information directly from + * the audio array + */ + if ($this->_raw['audio']['bitrate_mode']) { + $array['mode'] = $this->_raw['audio']['bitrate_mode']; + if ($array['mode'] == 'con') { + $array['mode'] = 'cbr'; + } + } + if ($this->_raw['audio']['bitrate']) { + $array['bitrate'] = $this->_raw['audio']['bitrate']; + } + if ($this->_raw['audio']['channels']) { + $array['channels'] = intval($this->_raw['audio']['channels']); + } + if ($this->_raw['audio']['sample_rate']) { + $array['rate'] = intval($this->_raw['audio']['sample_rate']); + } + if ($this->_raw['filesize']) { + $array['size'] = intval($this->_raw['filesize']); + } + if ($this->_raw['encoding']) { + $array['encoding'] = $this->_raw['encoding']; + } + if ($this->_raw['mime_type']) { + $array['mime'] = $this->_raw['mime_type']; + } + if ($this->_raw['playtime_seconds']) { + $array['time'] = $this->_raw['playtime_seconds']; + } + + return $array; + + } // _get_info + + /** + * _clean_type + * This standardizes the type that we are given into a recognized type. + */ + private function _clean_type($type) { + + switch ($type) { + case 'mp3': + case 'mp2': + case 'mpeg3': + return 'mp3'; + break; + case 'vorbis': + return 'ogg'; + break; + case 'flac': + case 'flv': + case 'mpg': + case 'mpeg': + case 'asf': + case 'wmv': + case 'avi': + case 'quicktime': + return $type; + default: + /* Log the fact that we couldn't figure it out */ + debug_event('vainfo','Unable to determine file type from ' . $type . ' on file ' . $this->filename,'5'); + return $type; + break; + } // end switch on type + + } // _clean_type + + /** + * _parse_lyrics + * This function takes a lyrics3 from getid3() + * nothing to do? + */ + private function _parse_lyrics($tags) { + + /* Results array */ + $array = array(); + + /* go through them all! */ + foreach ($tags as $tag => $data) { + if ($tag == 'unsynchedlyrics' || $tag == 'unsynchronised lyric') { + $tag = 'lyrics'; + } + $array[$tag] = $this->_clean_tag($data['0']); + + } // end foreach + + return $array; + + } // _parse_lyrics + + /** + * _parse_vorbiscomment + * This function takes a vorbiscomment from getid3() and then + * returns the elements translated using iconv if needed in a + * pretty little format + */ + private function _parse_vorbiscomment($tags) { + + /* Results array */ + $array = array(); + + /* go through them all! */ + foreach ($tags as $tag=>$data) { + + /* We need to translate a few of these tags */ + switch ($tag) { + + case 'genre': + // multiple genre support + foreach($data as $foo) { + $array['genre'][] = $this->_clean_tag($foo,''); + } + break; + case 'tracknumber': + $array['track'] = $this->_clean_tag($data['0']); + break; + case 'discnumber': + $el = explode('/', $data['0']); + $array['disk'] = $el[0]; + break; + case 'date': + $array['year'] = $this->_clean_tag($data['0']); + break; + default: + $array[$tag] = $this->_clean_tag($data['0']); + break; + } // end switch + + } // end foreach + + return $array; + + } // _parse_vorbiscomment + + /** + * _parse_id3v1 + * This function takes an id3v1 tag set from getid3() and then + * returns the elements (translated using iconv if needed) in a + * pretty little format. + */ + private function _parse_id3v1($tags) { + + $array = array(); + + /* Go through all the tags */ + foreach ($tags as $tag=>$data) { + + /* This is our baseline for naming + * so no translation needed + */ + $array[$tag] = $this->_clean_tag($data['0']); + + } // end foreach + + return $array; + + } // _parse_id3v1 + + /** + * _parse_id3v2 + * This function takes an id3v2 tag set from getid3() and then + * returns the elements (translated using iconv if needed) in a + * pretty little format. + */ + private function _parse_id3v2($tags) { + + $array = array(); + + /* Go through the tags */ + foreach ($tags as $tag=>$data) { + + /** + * the new getid3 handles this differently + * so we now need to account for it :( + */ + switch ($tag) { + case 'genre': + // multiple genre support + foreach($data as $genre) { + $array['genre'][] = $this->_clean_tag($genre); + } + break; + case 'part_of_a_set': + $el = explode('/', $data['0']); + $array['disk'] = $el[0]; + $array['totaldiscs'] = $el[1]; + break; + case 'track_number': + $array['track'] = $this->_clean_tag($data['0']); + break; + case 'comments': + $array['comment'] = $this->_clean_tag($data['0']); + break; + default: + $array[$tag] = $this->_clean_tag($data['0']); + break; + } // end switch on tag + + } // end foreach + + $id3v2 = $this->_raw['id3v2']; + + if(!empty($id3v2['UFID'])) { + // Find the MBID for the track + foreach ($id3v2['UFID'] as $ufid) { + if ($ufid['ownerid'] == 'http://musicbrainz.org') { + $array['mb_trackid'] = $this->_clean_tag($ufid['data']); + } + } + + // Find the MBIDs for the album and artist + foreach ($id3v2['TXXX'] as $txxx) { + switch ($txxx['description']) { + case 'MusicBrainz Album Id': + $array['mb_albumid'] = $this->_clean_tag($txxx['data']); + break; + case 'MusicBrainz Artist Id': + $array['mb_artistid'] = $this->_clean_tag($txxx['data']); + break; + } + } + } + + // Find the rating + if (is_array($id3v2['POPM'])) { + foreach ($id3v2['POPM'] as $popm) { + if (array_key_exists('email', $popm) && + $user = User::get_from_email($popm['email'])) { + // Ratings are out of 255; scale it + $array['rating'][$user->id] = $popm['rating'] / 255 * 5; + } + } + } + + return $array; + + } // _parse_id3v2 + + /** + * _parse_ape + * This function takes ape tags set by getid3() and then + * returns the elements translated using iconv if needed in a + * pretty little format + */ + private function _parse_ape($tags) { + + foreach ($tags as $tag=>$data) { + switch ($tag) { + + case 'genre': + // multiple genre support + foreach($data as $genre) { + $array['genre'][] = $this->_clean_tag($genre); + } + break; + + default: + $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding); + break; + } // end switch on tag + + } // end foreach tags + + return $array; + + } // _parse_ape + + /** + * _parse_riff + * this function takes the riff take information passed by getid3() and + * then reformats it so that it matches the other formats. May require iconv + */ + private function _parse_riff($tags) { + + foreach ($tags as $tag=>$data) { + + switch ($tag) { + case 'product': + $array['album'] = $this->_clean_tag($data['0'], $this->_file_encoding); + break; + default: + $array[$tag] = $this->_clean_tag($data['0'], $this->_file_encoding); + break; + } // end switch on tag + + } // foreach tags + + return $array; + + } // _parse_riff + + /** + * _parse_quicktime + * this function takes the quicktime tags set by getid3() and then + * returns the elements translated using iconv if needed in a + * pretty little format + */ + private function _parse_quicktime($tags) { + + /* Results array */ + $array = array(); + + /* go through them all! */ + foreach ($tags as $tag=>$data) { + + /* We need to translate a few of these tags */ + switch ($tag) { + case 'creation_date': + if (strlen($data['0']) > 4) { + /* Weird Date format, attempt to normalize */ + $data['0'] = date("Y",strtotime($data['0'])); + } + $array['year'] = $this->_clean_tag($data['0']); + break; + case 'MusicBrainz Track Id': + $array['mb_trackid'] = $this->_clean_tag($data['0']); + break; + case 'MusicBrainz Album Id': + $array['mb_albumid'] = $this->_clean_tag($data['0']); + break; + case 'MusicBrainz Artist Id': + $array['mb_artistid'] = $this->_clean_tag($data['0']); + break; + } // end switch + + $array[$tag] = $this->_clean_tag($data['0']); + + } // end foreach + + // Also add in any video related stuff we might find + if (strpos($this->_raw['mime_type'], 'video') !== false) { + $info = $this->_parse_avi($this->_raw); + $info['video_codec'] = $this->_raw['quicktime']['ftyp']['fourcc']; + $array = array_merge($info, $array); + } + + return $array; + + } // _parse_quicktime + + /** + * _parse_avi + * This attempts to parse our the information on an avi file and present it in some + * kind of sane format, this is a little hard as these files don't have tags + */ + private function _parse_avi($tags) { + + $array = array(); + + $array['title'] = urldecode($this->_pathinfo['filename']); + $array['video_codec'] = $tags['video']['fourcc']; + $array['audio_codec'] = $tags['audio']['dataformat']; + $array['resolution_x'] = $tags['video']['resolution_x']; + $array['resolution_y'] = $tags['video']['resolution_y']; + $array['mime'] = $tags['mime_type']; + $array['comment'] = $tags['video']['codec']; + + return $array; + + } // _parse_avi + + /** + * _parse_mpg + * This attempts to parse our the information on a mpg file and present it in some + * kind of sane format, this is a little hard as these files don't have tags + */ + private function _parse_mpg($tags) { + + $array = array(); + + $array['title'] = urldecode($this->_pathinfo['filename']); + $array['video_codec'] = $tags['video']['codec']; + $array['audio_codec'] = $tags['audio']['dataformat']; + $array['resolution_x'] = $tags['video']['resolution_x']; + $array['resolution_y'] = $tags['video']['resolution_y']; + $array['mime'] = $tags['mime_type']; + $array['comment'] = $tags['video']['codec']; + + return $array; + + } // _parse_mpg + + /** + * _parse_wmv + * This attempts to parse our the information on a asf/wmv file and present it in some + * kind of sane format, this is a little hard as these files don't have tags + */ + private function _parse_wmv($tags) { + + $array = array(); + + $array['mime'] = $tags['mime_type']; + + switch($array['mime']) { + default: + case 'video/x-ms-wmv': + if(isset($tags['tags']['asf']['title']['0'])) { + $array['title'] = $tags['tags']['asf']['title']['0']; + } + else { + $array['title'] = urldecode($this->_pathinfo['filename']); + } + $array['video_codec'] = $tags['video']['streams']['2']['codec']; + $array['audio_codec'] = $tags['audio']['streams']['1']['codec']; + $array['resolution_x'] = $tags['video']['streams']['2']['resolution_x']; + $array['resolution_y'] = $tags['video']['streams']['2']['resolution_y']; + $array['comment'] = $tags['tags']['asf']['title']['1']; + break; + } + + foreach($tags['tags']['asf'] as $tag => $data) { + $array[$tag] = $this->_clean_tag($data['0']); + } + + return $array; + + } // _parse_wmv + + /** + * _parse_flv + * This attempts to parse our the information on an flv file and present it in some + * kind of sane format, this is a little hard as these files don't have tags + */ + private function _parse_flv($tags) { + + $array = array(); + + $array['title'] = urldecode($this->_pathinfo['filename']); + $array['video_codec'] = $tags['video']['codec']; + $array['audio_codec'] = $tags['audio']['dataformat']; + $array['resolution_x'] = $tags['video']['resolution_x']; + $array['resolution_y'] = $tags['video']['resolution_y']; + $array['mime'] = $tags['mime_type']; + $array['comment'] = $tags['video']['codec']; + + return $array; + + } // _parse_flv + + /** + * _parse_filename + * + * This function uses the passed file and dir patterns + * To pull out extra tag information and populate it into + * its own array + * + * @param string $filename Filename that want to parse + * @return array Parsed results + */ + private function _parse_filename($filename) { + + $results = array(); + + // Correctly detect the slash we need to use here + if (strpos($filename, '/') !== false) { + $slash_type = '/'; + } + else { + $slash_type = '\\'; + } + + // Combine the patterns + $pattern = preg_quote($this->_dir_pattern) . $slash_type . preg_quote($this->_file_pattern); + + // Pull out the pattern codes into an array + preg_match_all('/\%\w/', $pattern, $elements); + + // Mangle the pattern by turning the codes into regex captures + $pattern = preg_replace('/\%[Ty]/', '([0-9]+?)', $pattern); + $pattern = preg_replace('/\%\w/', '(.+?)', $pattern); + $pattern = str_replace('/', '\/', $pattern); + $pattern = str_replace(' ', '\s', $pattern); + $pattern = '/' . $pattern . '\..+$/'; + + // Pull out our actual matches + preg_match($pattern, $filename, $matches); + + // The first element is the full match text + $matched = array_shift($matches); + debug_event('vainfo', $pattern . ' matched ' . $matched . ' on ' . $filename, 5); + + // Iterate over what we found + foreach ($matches as $key => $value) { + $new_key = translate_pattern_code($elements['0'][$key]); + if ($new_key) { + $results[$new_key] = $value; + } + } + + $results['size'] = filesize($filename); + + return $results; + + } // _parse_filename + + /** + * _id3v2_tag_to_frame + * + * This translates the tag name to a frame, if there a many it returns the first + * one if finds that exists in the raw + * + * @param string $tag_name Tag name + * @return mixed If found id3v2 frame, return frame. If not found, return false. + */ + private function _id3v2_tag_to_frame($tag_name) { + + static $map = array( + 'comment'=>array('COM','COMM'), + 'cd_ident'=>array('MCDI','MCI'), + 'album'=>array('TAL','TALB'), + 'language'=>array('TLA','TLAN'), + 'mood'=>array('TMOO'), + 'artist'=>array('TPE1'), + 'year'=>array('TDRC')); + + foreach ($map[$tag_name] as $frame) { + if (isset($this->_raw['id3v2'][$frame])) { + return $frame; + } + } + + return false; + + } // _id3v2_tag_to_frame + + /** + * _clean_tag + * + * This function cleans up the tag that it's passed using Iconv + * if we've got it. It also takes an optional encoding param + * for the cases where we know what the tags source encoding + * is, and or if it's different then the encoding recorded + * in the file + * + * @param string $tag Encoding string + * @param string $encoding Encode charset + * @return string Return encoded string + */ + private function _clean_tag($tag, $encoding = null) { + + // Default to getID3's native encoding + if (!$encoding) { + $encoding = $this->_getID3->encoding; + } + // If we've got iconv then go ahead and clear her up + if ($encoding == $this->encoding) { + debug_event('vainfo', "\$encoding -> ${encoding}, \$this->encoding -> {$this->encoding}", 5); + return $tag; + } + if ($this->_iconv) { + debug_event('vainfo', 'Use iconv()',5); + + // Try GNU iconv //TRANSLIT extension first + $new_encoding = $this->encoding . '//TRANSLIT'; + $clean = iconv($encoding, $new_encoding, $tag); + + // If that fails, do a plain conversion + if(strcmp($clean, '') == 0) { + $clean = iconv($encoding, $this->encoding, $tag); + } + } + elseif (function_exists('mb_convert_encoding')) { + debug_event('vainfo', 'Use mbstring',5); + debug_event('vainfo', "Try to convert from {$this->encoding} to $encoding", 5); + $clean = mb_convert_encoding($tag, $encoding, $this->encoding); + } + else { + $clean = $tag; + } + + return $clean; + + } // _clean_tag + + /** + * set_broken + * + * This fills all tag types with Unknown (Broken) + * + * @return array Return broken title, album, artist + */ + public function set_broken() { + + /* Pull In the config option */ + $order = Config::get('tag_order'); + + if (!is_array($order)) { + $order = array($order); + } + + $key = array_shift($order); + + $broken[$key]['title'] = '**BROKEN** ' . $this->filename; + $broken[$key]['album'] = 'Unknown (Broken)'; + $broken[$key]['artist'] = 'Unknown (Broken)'; + + return $broken; + + } // set_broken } // end class vainfo ?> diff --git a/lib/class/vauth.class.php b/lib/class/vauth.class.php index b978c35c67..e6dcab43f7 100644 --- a/lib/class/vauth.class.php +++ b/lib/class/vauth.class.php @@ -1,5 +1,5 @@ reloadRedirect("' . $target . '")'; - echo xml_from_array($results); - } - else { - /* Redirect them to the login page */ - header('Location: ' . $target); - } - - exit; - - } // logout - - /** - * get_session_data - * This takes a key and returns the raw data from the database, nothing - * to see here move along people - */ - public static function get_session_data($key) { - - $key = Dba::escape($key); - - $sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '" . time() . "'"; - $db_results = Dba::read($sql); - - if ($results = Dba::fetch_assoc($db_results)) { - return $results; - } - - return false; - - } // get_session_data - - /** - * create_cookie - * This is separated into its own function because of some flaws in - * specific webservers *cough* IIS *cough* which prevent us from setting - * a cookie at the same time as a header redirect. As such on view of a - * login a cookie is set with the proper name - */ - public static function create_cookie() { - - /* Setup the cookie prefs before we throw down, this is very important */ - $cookie_life = Config::get('cookie_life'); - $cookie_path = Config::get('cookie_path'); - $cookie_domain = false; - $cookie_secure = Config::get('cookie_secure'); - - session_set_cookie_params($cookie_life,$cookie_path,$cookie_domain,$cookie_secure); - - session_name(Config::get('session_name')); - - /* Start the session */ - self::ungimp_ie(); - session_start(); - - } // create_cookie, just watch out for the cookie monster - - /** - * create_remember_cookie - * This function just creates the remember me cookie, nothing special - */ - public static function create_remember_cookie() { - - $remember_length = Config::get('remember_length'); - $session_name = Config::get('session_name'); - - Config::set('cookie_life', $remember_length, true); - setcookie($session_name . '_remember',"Rappelez-vous, rappelez-vous le 27 mars", time() + $remember_length, '/'); - - } // create_remember_cookie - - /** - * session_create - * This is called when you want to create a new session - * it takes care of setting the initial cookie, and inserting the first - * chunk of data, nifty ain't it! - */ - public static function session_create($data) { - - // Regenerate the session ID to prevent fixation - switch ($data['type']) { - case 'xml-rpc': - case 'api': - $key = md5(uniqid(rand(), true)); - break; - case 'mysql': - default: - session_regenerate_id(); - - // Before refresh we don't have the cookie so we - // have to use session ID - $key = session_id(); - break; - } // end switch on data type - - $username = Dba::escape($data['username']); - $ip = $_SERVER['REMOTE_ADDR'] - ? Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])) - : '0'; - $type = Dba::escape($data['type']); - $value = Dba::escape($data['value']); - $agent = Dba::escape(substr($_SERVER['HTTP_USER_AGENT'], 0, 254)); - $expire = Dba::escape(time() + Config::get('session_length')); - - /* We can't have null things here people */ - if (!strlen($value)) { $value = ' '; } - - /* Insert the row */ - $sql = "INSERT INTO `session` (`id`,`username`,`ip`,`type`,`agent`,`value`,`expire`) " . - " VALUES ('$key','$username','$ip','$type','$agent','$value','$expire')"; - $db_results = Dba::write($sql); - - if (!$db_results) { - debug_event('SESSION', "Session Creation Failed with Query: $sql and " . Dba::error(), '1'); - return false; - } - - debug_event('SESSION', 'Session Created:' . $key, '6'); - - return $key; - - } // session_create - - /** - * check_session - * This checks for an existing session. If it's still valid we go ahead - * and start it and return true. - */ - public static function check_session() { - - $session_name = Config::get('session_name'); - - // No cookie no go! - if (!isset($_COOKIE[$session_name])) { return false; } - - // Check for a remember me - if (isset($_COOKIE[$session_name . '_remember'])) { - self::create_remember_cookie(); - } - - // Set up the cookie params before we start the session. - // This is vital - session_set_cookie_params( - Config::get('cookie_life'), - Config::get('cookie_path'), - Config::get('cookie_domain'), - Config::get('cookie_secure')); - - // Set name - session_name($session_name); - - // Ungimp IE and go - self::ungimp_ie(); - session_start(); - - return true; - - } // check_session - - /** - * session_exists - * This checks to see if the specified session of the specified type - * exists, it also provides an array of key'd data that may be required - * based on the type - */ - public static function session_exists($type, $key, $data=array()) { - - // Switch on the type they pass - switch ($type) { - case 'xml-rpc': - case 'api': - $key = Dba::escape($key); - $time = time(); - $sql = "SELECT * FROM `session` WHERE " . - "`id`='$key' AND `expire` > '$time' " . - "AND `type`='$type'"; - $db_results = Dba::read($sql); - - if (Dba::num_rows($db_results)) { - return true; - } - break; - case 'interface': - $key = Dba::escape($key); - $time = time(); - // Build a list of enabled authentication types - $types = Config::get('auth_methods'); - if (!Config::get('use_auth')) { - $types[] = ''; - } - $enabled_types = implode("','", $types); - $sql = "SELECT * FROM `session` WHERE " . - "`id`='$key' AND `expire` > '$time' " . - "AND `type` IN('$enabled_types')"; - $db_results = Dba::read($sql); - - if (Dba::num_rows($db_results)) { - return true; - } - break; - case 'stream': - $key = Dba::escape($key); - $ip = Dba::escape(inet_pton($data['ip'])); - $agent = Dba::escape($data['agent']); - $sql = "SELECT * FROM `session_stream` WHERE " . - "`id`='$key' AND `expire` > '$time' " . - "AND `ip`='$ip' AND `agent`='$agent'"; - $db_results = Dba::read($sql); - - if (Dba::num_rows($db_results)) { - return true; - } - - break; - default: - return false; - break; - } // type - - // Default to false - return false; - - } // session_exists - - /** - * session_extend - * This should really be extend_session but hey you gotta go with the - * flow. - * This takes a SID and extends its expiration. - */ - public static function session_extend($sid) { - $time = time(); - $sid = Dba::escape($sid); - $expire = isset($_COOKIE[Config::get('session_name') . '_remember']) - ? $time + Config::get('remember_length') - : $time + Config::get('session_length'); - - $sql = "UPDATE `session` SET `expire`='$expire' WHERE `id`='$sid'"; - $db_results = Dba::write($sql); - - debug_event('SESSION', $sid . ' has been extended to ' . date('r', $expire) . ' extension length ' . ($expire - $time), 5); - - return $db_results; - } // session_extend - - /** - * _auto_init - * This function is called when the object is included, this sets up the - * session_save_handler - */ - public static function _auto_init() { - - if (!function_exists('session_start')) { - header("Location:" . Config::get('web_path') . "/test.php"); - exit; - } - - session_set_save_handler( - array('vauth', 'open'), - array('vauth', 'close'), - array('vauth', 'read'), - array('vauth', 'write'), - array('vauth', 'destroy'), - array('vauth', 'gc')); - - } // auto init - - /** - * ungimp_ie - * This function sets the cache limiting to public if you are running - * some flavor of IE. The detection used here is very conservative so - * feel free to fix it. This only has to be done if we're rolling HTTPS. - */ - public static function ungimp_ie() { - - // If no https, no ungimpage required - if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'on') { - return true; - } - - // Try to detect IE - $agent = trim($_SERVER['HTTP_USER_AGENT']); - - if ((strpos($agent, 'MSIE') !== false) || - (strpos($agent,'Internet Explorer/') !== false)) { - session_cache_limiter('public'); - } - - return true; - - } // ungimp_ie - - /** - * authenticate - * This takes a username and password and then returns the results - * based on what happens when we try to do the auth. - */ - public static function authenticate($username, $password) { - - // Foreach the auth methods - foreach (Config::get('auth_methods') as $method) { - - // Build the function name and call it - $function_name = $method . '_auth'; - - if (!method_exists('vauth', $function_name)) { - continue; - } - - $results = self::$function_name($username, $password); - - // If we achieve victory return - if ($results['success']) { break; } - - } // end foreach - - return $results; - - } // authenticate - - /** - * mysql_auth - * - * This is the core function of our built-in authentication. - */ - private static function mysql_auth($username, $password) { - - $username = Dba::escape($username); - - if (strlen($password) && strlen($username)) { - $sql = "SELECT `password` FROM `user` WHERE " . - "`username`='$username'"; - $db_results = Dba::read($sql); - if ($row = Dba::fetch_assoc($db_results)) { - - // Use SHA2 now... cooking with fire. - // For backwards compatibility, we hash a couple - // of different variations of the password. - // Increases collision chances, but doesn't - // break things. - $hashed_password[] = hash('sha256', $password); - $hashed_password[] = hash('sha256', - Dba::escape(scrub_in($password))); - - // Automagically update the password if it's - // old and busted. - if($row['password'] == $hashed_password[1] && - $hashed_password[0] != $hashed_password[1]) { - $user = User::get_from_username($username); - $user->update_password($password); - } - - if(in_array($row['password'], $hashed_password)) { - $results['success'] = true; - $results['type'] = 'mysql'; - $results['username'] = $username; - return $results; - } - } - } - - // Default to failure - $results['success'] = false; - $results['error'] = 'MySQL login attempt failed'; - return $results; - - } // mysql_auth - - /** - * local_auth - * Check to make sure the pam_auth function is implemented (module is - * installed), then check the credentials. - */ - private static function local_auth($username, $password) { - if (!function_exists('pam_auth')) { - $results['success'] = false; - $results['error'] = 'The PAM PHP module is not installed'; - return $results; - } - - $password = scrub_in($password); - - if (pam_auth($username, $password)) { - $results['success'] = true; - $results['type'] = 'local'; - $results['username'] = $username; - } - else { - $results['success'] = false; - $results['error'] = 'PAM login attempt failed'; - } - - return $results; - } // local_auth - - /** - * ldap_auth - * Step one, connect to the LDAP server and perform a search for the - * username provided. - * Step two, attempt to bind using that username and the password - * provided. - * Step three, figure out if they are authorized to use ampache: - * TODO: in config but unimplemented: - * * require-dn "Grant access if the DN in the directive matches - * the DN fetched from the LDAP directory" - * * require-attribute "an attribute fetched from the LDAP - * directory matches the given value" - */ - private static function ldap_auth($username, $password) { - - $ldap_username = Config::get('ldap_username'); - $ldap_password = Config::get('ldap_password'); - - $require_group = Config::get('ldap_require_group'); - - // This is the DN for the users (required) - $ldap_dn = Config::get('ldap_search_dn'); - - // This is the server url (required) - $ldap_url = Config::get('ldap_url'); - - // This is the ldap filter string (required) - $ldap_filter = Config::get('ldap_filter'); - - //This is the ldap objectclass (required) - $ldap_class = Config::get('ldap_objectclass'); - - if (!($ldap_dn && $ldap_url && $ldap_filter && $ldap_class)) { - debug_event('ldap_auth', 'Required config value missing', 1); - $results['success'] = false; - $results['error'] = 'Incomplete LDAP config'; - return $results; - } - - $ldap_name_field = Config::get('ldap_name_field'); - $ldap_email_field = Config::get('ldap_email_field'); - - if ($ldap_link = ldap_connect($ldap_url) ) { - - /* Set to Protocol 3 */ - ldap_set_option($ldap_link, LDAP_OPT_PROTOCOL_VERSION, 3); - - // bind using our auth if we need to for initial search - if (!ldap_bind($ldap_link, $ldap_username, $ldap_password)) { - $results['success'] = false; - $results['error'] = 'Could not bind to LDAP server.'; - return $results; - } // If bind fails - - $sr = ldap_search($ldap_link, $ldap_dn, "(&(objectclass=$ldap_class)($ldap_filter=$username))"); - $info = ldap_get_entries($ldap_link, $sr); - - if ($info["count"] == 1) { - $user_entry = ldap_first_entry($ldap_link, $sr); - $user_dn = ldap_get_dn($ldap_link, $user_entry); - $password = scrub_in($password); - // bind using the user.. - $retval = ldap_bind($ldap_link, $user_dn, $password); - - if ($retval) { - // When the current user needs to be in - // a specific group to access Ampache, - // check whether the 'member' list of - // the group contains the DN - if ($require_group) { - $group_result = ldap_read($ldap_link, $require_group, 'objectclass=*', array('member')); - if (!$group_result) { - debug_event('ldap_auth', "Failure reading $require_group", 1); - $results['success'] = false; - $results['error'] = 'The LDAP group could not be read'; - return $results; - } - - $group_info = ldap_get_entries($ldap_link, $group_result); - - if ($group_info['count'] < 1) { - debug_event('ldap_auth', "No members found in $require_group", 1); - $results['success'] = false; - $results['error'] = 'Empty LDAP group'; - return $results; - } - - $group_match = preg_grep("/^$user_dn\$/i", $group_info[0]['member']); - if (!$group_match) { - debug_event('ldap_auth', "$user_dn is not a member of $require_group",1); - $results['success'] = false; - $results['error'] = 'LDAP login attempt failed'; - return $results; - } - } - ldap_close($ldap_link); - $results['success'] = true; - $results['type'] = "ldap"; - $results['username'] = $username; - $results['name'] = $info[0][$ldap_name_field][0]; - $results['email'] = $info[0][$ldap_email_field][0]; - - return $results; - - } // if we get something good back - - } // if something was sent back - - } // if failed connect - - /* Default to bad news */ - $results['success'] = false; - $results['error'] = 'LDAP login attempt failed'; - - return $results; - - } // ldap_auth - - /** - * http_auth - * This auth method relies on HTTP auth from the webserver - */ - private static function http_auth($username, $password) { - if (($_SERVER['REMOTE_USER'] == $username) || - ($_SERVER['HTTP_REMOTE_USER'] == $username)) { - $results['success'] = true; - $results['type'] = 'http'; - $results['username'] = $username; - $results['name'] = $username; - $results['email'] = ''; - } - else { - $results['success'] = false; - $results['error'] = 'HTTP auth login attempt failed'; - } - return $results; - } // http_auth + // Do a quick check to see if this is an AJAXed logout request + // if so use the iframe to redirect + if (defined('AJAX_INCLUDE')) { + ob_end_clean(); + ob_start(); + + /* Set the correct headers */ + header("Content-type: text/xml; charset=" . Config::get('site_charset')); + header("Content-Disposition: attachment; filename=ajax.xml"); + header("Expires: Tuesday, 27 Mar 1984 05:00:00 GMT"); + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Pragma: no-cache"); + + $results['rfc3514'] = ''; + echo xml_from_array($results); + } + else { + /* Redirect them to the login page */ + header('Location: ' . $target); + } + + exit; + + } // logout + + /** + * get_session_data + * This takes a key and returns the raw data from the database, nothing + * to see here move along people + */ + public static function get_session_data($key) { + + $key = Dba::escape($key); + + $sql = "SELECT * FROM `session` WHERE `id`='$key' AND `expire` > '" . time() . "'"; + $db_results = Dba::read($sql); + + if ($results = Dba::fetch_assoc($db_results)) { + return $results; + } + + return false; + + } // get_session_data + + /** + * create_cookie + * This is separated into its own function because of some flaws in + * specific webservers *cough* IIS *cough* which prevent us from setting + * a cookie at the same time as a header redirect. As such on view of a + * login a cookie is set with the proper name + */ + public static function create_cookie() { + + /* Setup the cookie prefs before we throw down, this is very important */ + $cookie_life = Config::get('cookie_life'); + $cookie_path = Config::get('cookie_path'); + $cookie_domain = false; + $cookie_secure = Config::get('cookie_secure'); + + session_set_cookie_params($cookie_life,$cookie_path,$cookie_domain,$cookie_secure); + + session_name(Config::get('session_name')); + + /* Start the session */ + self::ungimp_ie(); + session_start(); + + } // create_cookie, just watch out for the cookie monster + + /** + * create_remember_cookie + * This function just creates the remember me cookie, nothing special + */ + public static function create_remember_cookie() { + + $remember_length = Config::get('remember_length'); + $session_name = Config::get('session_name'); + + Config::set('cookie_life', $remember_length, true); + setcookie($session_name . '_remember',"Rappelez-vous, rappelez-vous le 27 mars", time() + $remember_length, '/'); + + } // create_remember_cookie + + /** + * session_create + * This is called when you want to create a new session + * it takes care of setting the initial cookie, and inserting the first + * chunk of data, nifty ain't it! + */ + public static function session_create($data) { + + // Regenerate the session ID to prevent fixation + switch ($data['type']) { + case 'xml-rpc': + case 'api': + $key = md5(uniqid(rand(), true)); + break; + case 'mysql': + default: + session_regenerate_id(); + + // Before refresh we don't have the cookie so we + // have to use session ID + $key = session_id(); + break; + } // end switch on data type + + $username = Dba::escape($data['username']); + $ip = $_SERVER['REMOTE_ADDR'] + ? Dba::escape(inet_pton($_SERVER['REMOTE_ADDR'])) + : '0'; + $type = Dba::escape($data['type']); + $value = Dba::escape($data['value']); + $agent = Dba::escape(substr($_SERVER['HTTP_USER_AGENT'], 0, 254)); + $expire = Dba::escape(time() + Config::get('session_length')); + + /* We can't have null things here people */ + if (!strlen($value)) { $value = ' '; } + + /* Insert the row */ + $sql = "INSERT INTO `session` (`id`,`username`,`ip`,`type`,`agent`,`value`,`expire`) " . + " VALUES ('$key','$username','$ip','$type','$agent','$value','$expire')"; + $db_results = Dba::write($sql); + + if (!$db_results) { + debug_event('SESSION', "Session Creation Failed with Query: $sql and " . Dba::error(), '1'); + return false; + } + + debug_event('SESSION', 'Session Created:' . $key, '6'); + + return $key; + + } // session_create + + /** + * check_session + * This checks for an existing session. If it's still valid we go ahead + * and start it and return true. + */ + public static function check_session() { + + $session_name = Config::get('session_name'); + + // No cookie no go! + if (!isset($_COOKIE[$session_name])) { return false; } + + // Check for a remember me + if (isset($_COOKIE[$session_name . '_remember'])) { + self::create_remember_cookie(); + } + + // Set up the cookie params before we start the session. + // This is vital + session_set_cookie_params( + Config::get('cookie_life'), + Config::get('cookie_path'), + Config::get('cookie_domain'), + Config::get('cookie_secure')); + + // Set name + session_name($session_name); + + // Ungimp IE and go + self::ungimp_ie(); + session_start(); + + return true; + + } // check_session + + /** + * session_exists + * This checks to see if the specified session of the specified type + * exists, it also provides an array of key'd data that may be required + * based on the type + */ + public static function session_exists($type, $key, $data=array()) { + + // Switch on the type they pass + switch ($type) { + case 'xml-rpc': + case 'api': + $key = Dba::escape($key); + $time = time(); + $sql = "SELECT * FROM `session` WHERE " . + "`id`='$key' AND `expire` > '$time' " . + "AND `type`='$type'"; + $db_results = Dba::read($sql); + + if (Dba::num_rows($db_results)) { + return true; + } + break; + case 'interface': + $key = Dba::escape($key); + $time = time(); + // Build a list of enabled authentication types + $types = Config::get('auth_methods'); + if (!Config::get('use_auth')) { + $types[] = ''; + } + $enabled_types = implode("','", $types); + $sql = "SELECT * FROM `session` WHERE " . + "`id`='$key' AND `expire` > '$time' " . + "AND `type` IN('$enabled_types')"; + $db_results = Dba::read($sql); + + if (Dba::num_rows($db_results)) { + return true; + } + break; + case 'stream': + $key = Dba::escape($key); + $ip = Dba::escape(inet_pton($data['ip'])); + $agent = Dba::escape($data['agent']); + $sql = "SELECT * FROM `session_stream` WHERE " . + "`id`='$key' AND `expire` > '$time' " . + "AND `ip`='$ip' AND `agent`='$agent'"; + $db_results = Dba::read($sql); + + if (Dba::num_rows($db_results)) { + return true; + } + + break; + default: + return false; + break; + } // type + + // Default to false + return false; + + } // session_exists + + /** + * session_extend + * This should really be extend_session but hey you gotta go with the + * flow. + * This takes a SID and extends its expiration. + */ + public static function session_extend($sid) { + $time = time(); + $sid = Dba::escape($sid); + $expire = isset($_COOKIE[Config::get('session_name') . '_remember']) + ? $time + Config::get('remember_length') + : $time + Config::get('session_length'); + + $sql = "UPDATE `session` SET `expire`='$expire' WHERE `id`='$sid'"; + $db_results = Dba::write($sql); + + debug_event('SESSION', $sid . ' has been extended to ' . date('r', $expire) . ' extension length ' . ($expire - $time), 5); + + return $db_results; + } // session_extend + + /** + * _auto_init + * This function is called when the object is included, this sets up the + * session_save_handler + */ + public static function _auto_init() { + + if (!function_exists('session_start')) { + header("Location:" . Config::get('web_path') . "/test.php"); + exit; + } + + session_set_save_handler( + array('vauth', 'open'), + array('vauth', 'close'), + array('vauth', 'read'), + array('vauth', 'write'), + array('vauth', 'destroy'), + array('vauth', 'gc')); + + } // auto init + + /** + * ungimp_ie + * This function sets the cache limiting to public if you are running + * some flavor of IE. The detection used here is very conservative so + * feel free to fix it. This only has to be done if we're rolling HTTPS. + */ + public static function ungimp_ie() { + + // If no https, no ungimpage required + if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'on') { + return true; + } + + // Try to detect IE + $agent = trim($_SERVER['HTTP_USER_AGENT']); + + if ((strpos($agent, 'MSIE') !== false) || + (strpos($agent,'Internet Explorer/') !== false)) { + session_cache_limiter('public'); + } + + return true; + + } // ungimp_ie + + /** + * authenticate + * This takes a username and password and then returns the results + * based on what happens when we try to do the auth. + */ + public static function authenticate($username, $password) { + + // Foreach the auth methods + foreach (Config::get('auth_methods') as $method) { + + // Build the function name and call it + $function_name = $method . '_auth'; + + if (!method_exists('vauth', $function_name)) { + continue; + } + + $results = self::$function_name($username, $password); + + // If we achieve victory return + if ($results['success']) { break; } + + } // end foreach + + return $results; + + } // authenticate + + /** + * mysql_auth + * + * This is the core function of our built-in authentication. + */ + private static function mysql_auth($username, $password) { + + $username = Dba::escape($username); + + if (strlen($password) && strlen($username)) { + $sql = "SELECT `password` FROM `user` WHERE " . + "`username`='$username'"; + $db_results = Dba::read($sql); + if ($row = Dba::fetch_assoc($db_results)) { + + // Use SHA2 now... cooking with fire. + // For backwards compatibility, we hash a couple + // of different variations of the password. + // Increases collision chances, but doesn't + // break things. + $hashed_password[] = hash('sha256', $password); + $hashed_password[] = hash('sha256', + Dba::escape(scrub_in($password))); + + // Automagically update the password if it's + // old and busted. + if($row['password'] == $hashed_password[1] && + $hashed_password[0] != $hashed_password[1]) { + $user = User::get_from_username($username); + $user->update_password($password); + } + + if(in_array($row['password'], $hashed_password)) { + $results['success'] = true; + $results['type'] = 'mysql'; + $results['username'] = $username; + return $results; + } + } + } + + // Default to failure + $results['success'] = false; + $results['error'] = 'MySQL login attempt failed'; + return $results; + + } // mysql_auth + + /** + * local_auth + * Check to make sure the pam_auth function is implemented (module is + * installed), then check the credentials. + */ + private static function local_auth($username, $password) { + if (!function_exists('pam_auth')) { + $results['success'] = false; + $results['error'] = 'The PAM PHP module is not installed'; + return $results; + } + + $password = scrub_in($password); + + if (pam_auth($username, $password)) { + $results['success'] = true; + $results['type'] = 'local'; + $results['username'] = $username; + } + else { + $results['success'] = false; + $results['error'] = 'PAM login attempt failed'; + } + + return $results; + } // local_auth + + /** + * ldap_auth + * Step one, connect to the LDAP server and perform a search for the + * username provided. + * Step two, attempt to bind using that username and the password + * provided. + * Step three, figure out if they are authorized to use ampache: + * TODO: in config but unimplemented: + * * require-dn "Grant access if the DN in the directive matches + * the DN fetched from the LDAP directory" + * * require-attribute "an attribute fetched from the LDAP + * directory matches the given value" + */ + private static function ldap_auth($username, $password) { + + $ldap_username = Config::get('ldap_username'); + $ldap_password = Config::get('ldap_password'); + + $require_group = Config::get('ldap_require_group'); + + // This is the DN for the users (required) + $ldap_dn = Config::get('ldap_search_dn'); + + // This is the server url (required) + $ldap_url = Config::get('ldap_url'); + + // This is the ldap filter string (required) + $ldap_filter = Config::get('ldap_filter'); + + //This is the ldap objectclass (required) + $ldap_class = Config::get('ldap_objectclass'); + + if (!($ldap_dn && $ldap_url && $ldap_filter && $ldap_class)) { + debug_event('ldap_auth', 'Required config value missing', 1); + $results['success'] = false; + $results['error'] = 'Incomplete LDAP config'; + return $results; + } + + $ldap_name_field = Config::get('ldap_name_field'); + $ldap_email_field = Config::get('ldap_email_field'); + + if ($ldap_link = ldap_connect($ldap_url) ) { + + /* Set to Protocol 3 */ + ldap_set_option($ldap_link, LDAP_OPT_PROTOCOL_VERSION, 3); + + // bind using our auth if we need to for initial search + if (!ldap_bind($ldap_link, $ldap_username, $ldap_password)) { + $results['success'] = false; + $results['error'] = 'Could not bind to LDAP server.'; + return $results; + } // If bind fails + + $sr = ldap_search($ldap_link, $ldap_dn, "(&(objectclass=$ldap_class)($ldap_filter=$username))"); + $info = ldap_get_entries($ldap_link, $sr); + + if ($info["count"] == 1) { + $user_entry = ldap_first_entry($ldap_link, $sr); + $user_dn = ldap_get_dn($ldap_link, $user_entry); + $password = scrub_in($password); + // bind using the user.. + $retval = ldap_bind($ldap_link, $user_dn, $password); + + if ($retval) { + // When the current user needs to be in + // a specific group to access Ampache, + // check whether the 'member' list of + // the group contains the DN + if ($require_group) { + $group_result = ldap_read($ldap_link, $require_group, 'objectclass=*', array('member')); + if (!$group_result) { + debug_event('ldap_auth', "Failure reading $require_group", 1); + $results['success'] = false; + $results['error'] = 'The LDAP group could not be read'; + return $results; + } + + $group_info = ldap_get_entries($ldap_link, $group_result); + + if ($group_info['count'] < 1) { + debug_event('ldap_auth', "No members found in $require_group", 1); + $results['success'] = false; + $results['error'] = 'Empty LDAP group'; + return $results; + } + + $group_match = preg_grep("/^$user_dn\$/i", $group_info[0]['member']); + if (!$group_match) { + debug_event('ldap_auth', "$user_dn is not a member of $require_group",1); + $results['success'] = false; + $results['error'] = 'LDAP login attempt failed'; + return $results; + } + } + ldap_close($ldap_link); + $results['success'] = true; + $results['type'] = "ldap"; + $results['username'] = $username; + $results['name'] = $info[0][$ldap_name_field][0]; + $results['email'] = $info[0][$ldap_email_field][0]; + + return $results; + + } // if we get something good back + + } // if something was sent back + + } // if failed connect + + /* Default to bad news */ + $results['success'] = false; + $results['error'] = 'LDAP login attempt failed'; + + return $results; + + } // ldap_auth + + /** + * http_auth + * This auth method relies on HTTP auth from the webserver + */ + private static function http_auth($username, $password) { + if (($_SERVER['REMOTE_USER'] == $username) || + ($_SERVER['HTTP_REMOTE_USER'] == $username)) { + $results['success'] = true; + $results['type'] = 'http'; + $results['username'] = $username; + $results['name'] = $username; + $results['email'] = ''; + } + else { + $results['success'] = false; + $results['error'] = 'HTTP auth login attempt failed'; + } + return $results; + } // http_auth } // end of vauth class diff --git a/lib/class/video.class.php b/lib/class/video.class.php index 5a758aae24..8299cf8dbf 100644 --- a/lib/class/video.class.php +++ b/lib/class/video.class.php @@ -1,5 +1,5 @@ get_info($id); - foreach ($info as $key=>$value) { - $this->$key = $value; - } + // Load the data from the database + $info = $this->get_info($id); + foreach ($info as $key=>$value) { + $this->$key = $value; + } - return true; + return true; - } // Constructor + } // Constructor - /** - * build_cache - * Build a cache based on the array of ids passed, saves lots of little queries - */ - public static function build_cache($ids=array()) { + /** + * build_cache + * Build a cache based on the array of ids passed, saves lots of little queries + */ + public static function build_cache($ids=array()) { - if (!is_array($ids) OR !count($ids)) { return false; } + if (!is_array($ids) OR !count($ids)) { return false; } - $idlist = '(' . implode(',',$ids) . ')'; + $idlist = '(' . implode(',',$ids) . ')'; - $sql = "SELECT * FROM `video` WHERE `video`.`id` IN $idlist"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `video` WHERE `video`.`id` IN $idlist"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - parent::add_to_cache('video',$row['id'],$row); - } + while ($row = Dba::fetch_assoc($db_results)) { + parent::add_to_cache('video',$row['id'],$row); + } - } // build_cache + } // build_cache - /** - * format - * This formats a video object so that it is human readable - */ - public function format() { + /** + * format + * This formats a video object so that it is human readable + */ + public function format() { - $this->f_title = scrub_out($this->title); - $this->f_link = scrub_out($this->title); - $this->f_codec = $this->video_codec . ' / ' . $this->audio_codec; - $this->f_resolution = $this->resolution_x . 'x' . $this->resolution_y; - $this->f_tags = ''; - $this->f_length = floor($this->time/60) . ' ' . T_('minutes'); + $this->f_title = scrub_out($this->title); + $this->f_link = scrub_out($this->title); + $this->f_codec = $this->video_codec . ' / ' . $this->audio_codec; + $this->f_resolution = $this->resolution_x . 'x' . $this->resolution_y; + $this->f_tags = ''; + $this->f_length = floor($this->time/60) . ' ' . T_('minutes'); - } // format + } // format - public function get_stream_types() { + public function get_stream_types() { - return array('native'); + return array('native'); - } // native_stream + } // native_stream - /** - * play_url - * This returns a "PLAY" url for the video in question here, this currently feels a little - * like a hack, might need to adjust it in the future - */ - public static function play_url($oid,$sid='',$force_http='') { + /** + * play_url + * This returns a "PLAY" url for the video in question here, this currently feels a little + * like a hack, might need to adjust it in the future + */ + public static function play_url($oid,$sid='',$force_http='') { - $video = new Video($oid); + $video = new Video($oid); - if (!$video->id) { return false; } + if (!$video->id) { return false; } - $uid = intval($GLOBALS['user']->id); - $oid = intval($video->id); + $uid = intval($GLOBALS['user']->id); + $oid = intval($video->id); - $url = Stream::get_base_url() . "video=true&uid=$uid&oid=$oid"; + $url = Stream::get_base_url() . "video=true&uid=$uid&oid=$oid"; - return $url; + return $url; - } // play_url + } // play_url - /** - * get_transcode_settings - * - * FIXME: Video transcoding is not implemented - */ - public function get_transcode_settings($target = null) { - return false; - } + /** + * get_transcode_settings + * + * FIXME: Video transcoding is not implemented + */ + public function get_transcode_settings($target = null) { + return false; + } - /** - * has_flag - * returns true if the video has been flagged and we shouldn't try to re-read - * the meta data - */ - public function has_flag() { + /** + * has_flag + * returns true if the video has been flagged and we shouldn't try to re-read + * the meta data + */ + public function has_flag() { - } // has_flag + } // has_flag } // end Video class diff --git a/lib/class/xml_data.class.php b/lib/class/xml_data.class.php index da3c98c2d2..8c7884c9c1 100644 --- a/lib/class/xml_data.class.php +++ b/lib/class/xml_data.class.php @@ -1,5 +1,5 @@ " . self::_footer(); - return $string; - - } // error - - /** - * single_string - * - * This takes two values, first the key second the string - * - * @param string $key (description here...) - * @param string $string xml data - * @return string return xml - */ - public static function single_string($key,$string) { - - $final = self::_header() . "\t<$key>" . self::_footer(); - - return $final; - - } // single_string - - /** - * header - * - * This returns the header - * - * @see _header() - * @return string return xml - */ - public static function header() { - - return self::_header(); - - } // header - - /** - * footer - * - * This returns the footer - * - * @see _footer() - * @return string return xml - */ - public static function footer() { - - return self::_footer(); - - } // footer - - /** - * tags_string - * - * This returns the formatted 'tags' string for an xml document - * - */ - private static function tags_string($tags) { - - $string = ''; - - if (is_array($tags)) { - - foreach ($tags as $tag_id => $data) { - $tag = new Tag($tag_id); - $string .= "\tid . - '" count="' . count($data['users']) . - '">name . "]]>\n"; - } - } - - return $string; - - } // tags_string - - /** - * keyed_array - * - * This will build an xml document from a key'd array, - * - * @param array $array (description here...) - * @param boolean $callback (description here...) - * @return string return xml - */ - public static function keyed_array($array,$callback='') { - - $string = ''; - - // Foreach it - foreach ($array as $key=>$value) { - $attribute = ''; - // See if the key has attributes - if (is_array($value) AND isset($value[''])) { - $attribute = ' ' . $value['']; - $key = $value['value']; - } - - // If it's an array, run again - if (is_array($value)) { - $value = self::keyed_array($value,1); - $string .= "<$key$attribute>\n$value\n\n"; - } - else { - $string .= "\t<$key$attribute>\n"; - } - - } // end foreach - - if (!$callback) { - $string = self::_header() . $string . self::_footer(); - } - - return $string; - - } // keyed_array - - /** - * tags - * - * This returns tags to the user, in a pretty xml document with the information - * - * @param array $tags (description here...) - * @return string return xml - */ - public static function tags($tags) { - - if (count($tags) > self::$limit OR self::$offset > 0) { - $tags = array_splice($tags,self::$offset,self::$limit); - } - - $string = ''; - - foreach ($tags as $tag_id) { - $tag = new Tag($tag_id); - $counts = $tag->count(); - $string .= "\n" . - "\tname]]>\n" . - "\t" . intval($counts['album']) . "\n" . - "\t" . intval($counts['artist']) . "\n" . - "\t" . intval($counts['song']) . "\n" . - "\t" . intval($counts['video']) . "\n" . - "\t" . intval($count['playlist']) . "\n" . - "\t" . intval($count['live_stream']) . "\n" . - "\n"; - } // end foreach - - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // tags - - /** - * artists - * - * This takes an array of artists and then returns a pretty xml document with the information - * we want - * - * @param array $artists (description here...) - * @return string return xml - */ - public static function artists($artists) { - - if (count($artists) > self::$limit OR self::$offset > 0) { - $artists = array_splice($artists,self::$offset,self::$limit); - } - - $string = ''; - - Rating::build_cache('artist',$artists); - - foreach ($artists as $artist_id) { - $artist = new Artist($artist_id); - $artist->format(); - - $rating = new Rating($artist_id,'artist'); - $tag_string = self::tags_string($artist->tags); - - $string .= "id\">\n" . - "\tf_full_name]]>\n" . - $tag_string . - "\t$artist->albums\n" . - "\t$artist->songs\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_average_rating() . "\n" . - "\n"; - } // end foreach artists - - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // artists - - /** - * albums - * - * This echos out a standard albums XML document, it pays attention to the limit - * - * @param array $albums (description here...) - * @return string return xml - */ - public static function albums($albums) { - - if (count($albums) > self::$limit OR self::$offset > 0) { - $albums = array_splice($albums,self::$offset,self::$limit); - } - - Rating::build_cache('album',$albums); - - foreach ($albums as $album_id) { - $album = new Album($album_id); - $album->format(); - - $rating = new Rating($album_id,'album'); - - // Build the Art URL, include session - $art_url = Config::get('web_path') . '/image.php?id=' . $album->id . '&auth=' . scrub_out($_REQUEST['auth']); - - $string .= "id\">\n" . - "\tname]]>\n"; - - // Do a little check for artist stuff - if ($album->artist_count != 1) { - $string .= "\t\n"; - } - else { - $string .= "\tartist_id\">artist_name]]>\n"; - } - - $string .= "\t$album->year\n" . - "\t$album->song_count\n" . - "\t$album->disk\n" . - self::tags_string($album->tags) . - "\t\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_average_rating() . "\n" . - "\n"; - } // end foreach - - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // albums - - /** - * playlists - * - * This takes an array of playlist ids and then returns a nice pretty XML document - * - * @param array $playlists (description here...) - * @return string return xml - */ - public static function playlists($playlists) { - - if (count($playlists) > self::$limit OR self::$offset > 0) { - $playlists = array_slice($playlists,self::$offset,self::$limit); - } - - $string = ''; - - // Foreach the playlist ids - foreach ($playlists as $playlist_id) { - $playlist = new Playlist($playlist_id); - $playlist->format(); - $item_total = $playlist->get_song_count(); - - // Build this element - $string .= "id\">\n" . - "\tname]]>\n" . - "\tf_user]]>\n" . - "\t$item_total\n" . - "\t$playlist->type\n" . - "\n"; - - - } // end foreach - - // Build the final and then send her off - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // playlists - - /** - * songs - * - * This returns an xml document from an array of song ids. - * (Spiffy isn't it!) - */ - public static function songs($songs) { - - if (count($songs) > self::$limit OR self::$offset > 0) { - $songs = array_slice($songs, self::$offset, self::$limit); - } - - Song::build_cache($songs); - Stream::set_session($_REQUEST['auth']); - - // Foreach the ids! - foreach ($songs as $song_id) { - $song = new Song($song_id); - - // If the song id is invalid/null - if (!$song->id) { continue; } - - $tag_string = self::tags_string(Tag::get_top_tags('song', $song_id)); - $rating = new Rating($song_id, 'song'); - $art_url = Art::url($song->album, 'album', $_REQUEST['auth']); - - $string .= "id\">\n" . - "\t<![CDATA[$song->title]]>\n" . - "\tartist . - '">get_artist_name() . - "]]>\n" . - "\talbum . - '">get_album_name(). - "]]>\n" . - $tag_string . - "\t$song->track\n" . - "\t\n" . - "\t$song->year\n" . - "\t$song->bitrate\n". - "\t$song->mode\n". - "\t$song->mime\n" . - "\tid) . "]]>\n" . - "\t$song->size\n". - "\t$song->mbid\n". - "\t$song->album_mbid\n". - "\t$song->artist_mbid\n". - "\t\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_average_rating() . "\n" . - "\n"; - - } // end foreach - - return self::_header() . $string . self::_footer(); - - } // songs - - /** - * videos - * - * This builds the xml document for displaying video objects - * - * @param array $videos (description here...) - * @return string return xml - */ - public static function videos($videos) { - - if (count($videos) > self::$limit OR self::$offset > 0) { - $videos = array_slice($videos,self::$offset,self::$limit); - } - - $string = ''; - - foreach ($videos as $video_id) { - $video = new Video($video_id); - $video->format(); - - $string .= "\n"; - - } // end foreach - - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // videos - - /** - * democratic - * - * This handles creating an xml document for democratic items, this can be a little complicated - * due to the votes and all of that - * - * @param array $object_ids Object IDs - * @return string return xml - */ - public static function democratic($object_ids=array()) { - - if (!is_array($object_ids)) { $object_ids = array(); } - - $democratic = Democratic::get_current_playlist(); - - $string = ''; - - foreach ($object_ids as $row_id=>$data) { - $song = new $data['object_type']($data['object_id']); - $song->format(); - - //FIXME: This is duplicate code and so wrong, functions need to be improved - $tag_string = ''; - - $tag = new Tag($song->tags['0']); - $song->genre = $tag->id; - $song->f_genre = $tag->name; - - $tag_string = self::tags_string($song->tags); - - $rating = new Rating($song_id,'song'); - - $art_url = Art::url($song->album, 'album', $_REQUEST['auth']); - - $string .= "id\">\n" . - "\t<![CDATA[$song->title]]>\n" . - "\tartist\">f_artist_full]]>\n" . - "\talbum\">f_album_full]]>\n" . - "\tgenre\">f_genre]]>\n" . - $tag_string . - "\t$song->track\n" . - "\t\n" . - "\t$song->mime\n" . - "\tid) . "]]>\n" . - "\t$song->size\n" . - "\t\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_user_rating() . "\n" . - "\t" . $rating->get_average_rating() . "\n" . - "\t" . $democratic->get_vote($row_id) . "\n" . - "\n"; - - } // end foreach - - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // democratic - - /** - * rss_feed - * - * (description here...) - * - * @param array $data (descriptiong here...) - * @param string $title RSS feed title - * @param string $description (not use yet?) - * @param string $date publish date - * @return string RSS feed xml - */ - public static function rss_feed($data,$title,$description,$date) { - - $string = "\t$title\n\t" . Config::get('web_path') . "\n\t" . - "" . date("r",$date) . "\n"; - - // Pass it to the keyed array xml function - foreach ($data as $item) { - // We need to enclose it in an item tag - $string .= self::keyed_array(array('item'=>$item),1); - } - - $final = self::_header() . $string . self::_footer(); - - return $final; - - } // rss_feed - - /** - * _header - * - * this returns a standard header, there are a few types - * so we allow them to pass a type if they want to - * - * @return string Header xml tag. - */ - private static function _header() { - - switch (self::$type) { - case 'xspf': - $header = "\n" . - "\n " . - "Ampache XSPF Playlist\n" . - "" . scrub_out(Config::get('site_title')) . "\n" . - "" . scrub_out(Config::get('site_title')) . "\n" . - "". Config::get('web_path') ."\n" . - "\n"; - break; - case 'itunes': - $header = "\n" . - "\n"; - "\n" . - "\n" . - "\n" . - " Major Version1\n" . - " Minor Version1\n" . - " Application Version7.0.2\n" . - " Features1\n" . - " Show Content Ratings\n" . - " Tracks\n" . - " \n"; - break; - case 'rss': - $header = "\n " . - "\n" . - "\n\n"; - break; - default: - $header = "\n\n"; - break; - } // end switch - - return $header; - - } // _header - - /** - * _footer - * - * this returns the footer for this document, these are pretty boring - * - * @return string Footer xml tag. - */ - private static function _footer() { - - switch (self::$type) { - case 'itunes': - $footer = "\t\t\t\n\n\n"; - break; - case 'xspf': - $footer = "\n\n"; - break; - case 'rss': - $footer = "\n\n\n"; - break; - default: - $footer = "\n\n"; - break; - } // end switch on type - - - return $footer; - - } // _footer + // This is added so that we don't pop any webservers + private static $limit = '5000'; + private static $offset = '0'; + private static $type = ''; + + /** + * constructor + * + * We don't use this, as its really a static class + */ + private function __construct() { + + // Rien a faire + + } // constructor + + /** + * set_offset + * + * This takes an int and changes the offset + * + * @param integer $offset (description here...) + * @return void + */ + public static function set_offset($offset) { + + $offset = intval($offset); + self::$offset = $offset; + + } // set_offset + + /** + * set_limit + * + * This sets the limit for any ampache transactions + * + * @param integer $limit (description here...) + * @return void + */ + public static function set_limit($limit) { + + if (!$limit) { return false; } + + $limit = intval($limit); + self::$limit = $limit; + + } // set_limit + + /** + * set_type + * + * This sets the type of XML_Data we are working on + * + * @param string $type XML_Data type + * @return void + */ + public static function set_type($type) { + + if (!in_array($type,array('rss','xspf','itunes'))) { return false; } + + self::$type = $type; + + } // set_type + + /** + * error + * + * This generates a standard XML Error message + * nothing fancy here... + * + * @param integer $code Error code + * @param string $string Error message + * @return string return error message xml + */ + public static function error($code,$string) { + + $string = self::_header() . "\t" . self::_footer(); + return $string; + + } // error + + /** + * single_string + * + * This takes two values, first the key second the string + * + * @param string $key (description here...) + * @param string $string xml data + * @return string return xml + */ + public static function single_string($key,$string) { + + $final = self::_header() . "\t<$key>" . self::_footer(); + + return $final; + + } // single_string + + /** + * header + * + * This returns the header + * + * @see _header() + * @return string return xml + */ + public static function header() { + + return self::_header(); + + } // header + + /** + * footer + * + * This returns the footer + * + * @see _footer() + * @return string return xml + */ + public static function footer() { + + return self::_footer(); + + } // footer + + /** + * tags_string + * + * This returns the formatted 'tags' string for an xml document + * + */ + private static function tags_string($tags) { + + $string = ''; + + if (is_array($tags)) { + + foreach ($tags as $tag_id => $data) { + $tag = new Tag($tag_id); + $string .= "\tid . + '" count="' . count($data['users']) . + '">name . "]]>\n"; + } + } + + return $string; + + } // tags_string + + /** + * keyed_array + * + * This will build an xml document from a key'd array, + * + * @param array $array (description here...) + * @param boolean $callback (description here...) + * @return string return xml + */ + public static function keyed_array($array,$callback='') { + + $string = ''; + + // Foreach it + foreach ($array as $key=>$value) { + $attribute = ''; + // See if the key has attributes + if (is_array($value) AND isset($value[''])) { + $attribute = ' ' . $value['']; + $key = $value['value']; + } + + // If it's an array, run again + if (is_array($value)) { + $value = self::keyed_array($value,1); + $string .= "<$key$attribute>\n$value\n\n"; + } + else { + $string .= "\t<$key$attribute>\n"; + } + + } // end foreach + + if (!$callback) { + $string = self::_header() . $string . self::_footer(); + } + + return $string; + + } // keyed_array + + /** + * tags + * + * This returns tags to the user, in a pretty xml document with the information + * + * @param array $tags (description here...) + * @return string return xml + */ + public static function tags($tags) { + + if (count($tags) > self::$limit OR self::$offset > 0) { + $tags = array_splice($tags,self::$offset,self::$limit); + } + + $string = ''; + + foreach ($tags as $tag_id) { + $tag = new Tag($tag_id); + $counts = $tag->count(); + $string .= "\n" . + "\tname]]>\n" . + "\t" . intval($counts['album']) . "\n" . + "\t" . intval($counts['artist']) . "\n" . + "\t" . intval($counts['song']) . "\n" . + "\t" . intval($counts['video']) . "\n" . + "\t" . intval($count['playlist']) . "\n" . + "\t" . intval($count['live_stream']) . "\n" . + "\n"; + } // end foreach + + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // tags + + /** + * artists + * + * This takes an array of artists and then returns a pretty xml document with the information + * we want + * + * @param array $artists (description here...) + * @return string return xml + */ + public static function artists($artists) { + + if (count($artists) > self::$limit OR self::$offset > 0) { + $artists = array_splice($artists,self::$offset,self::$limit); + } + + $string = ''; + + Rating::build_cache('artist',$artists); + + foreach ($artists as $artist_id) { + $artist = new Artist($artist_id); + $artist->format(); + + $rating = new Rating($artist_id,'artist'); + $tag_string = self::tags_string($artist->tags); + + $string .= "id\">\n" . + "\tf_full_name]]>\n" . + $tag_string . + "\t$artist->albums\n" . + "\t$artist->songs\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_average_rating() . "\n" . + "\n"; + } // end foreach artists + + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // artists + + /** + * albums + * + * This echos out a standard albums XML document, it pays attention to the limit + * + * @param array $albums (description here...) + * @return string return xml + */ + public static function albums($albums) { + + if (count($albums) > self::$limit OR self::$offset > 0) { + $albums = array_splice($albums,self::$offset,self::$limit); + } + + Rating::build_cache('album',$albums); + + foreach ($albums as $album_id) { + $album = new Album($album_id); + $album->format(); + + $rating = new Rating($album_id,'album'); + + // Build the Art URL, include session + $art_url = Config::get('web_path') . '/image.php?id=' . $album->id . '&auth=' . scrub_out($_REQUEST['auth']); + + $string .= "id\">\n" . + "\tname]]>\n"; + + // Do a little check for artist stuff + if ($album->artist_count != 1) { + $string .= "\t\n"; + } + else { + $string .= "\tartist_id\">artist_name]]>\n"; + } + + $string .= "\t$album->year\n" . + "\t$album->song_count\n" . + "\t$album->disk\n" . + self::tags_string($album->tags) . + "\t\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_average_rating() . "\n" . + "\n"; + } // end foreach + + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // albums + + /** + * playlists + * + * This takes an array of playlist ids and then returns a nice pretty XML document + * + * @param array $playlists (description here...) + * @return string return xml + */ + public static function playlists($playlists) { + + if (count($playlists) > self::$limit OR self::$offset > 0) { + $playlists = array_slice($playlists,self::$offset,self::$limit); + } + + $string = ''; + + // Foreach the playlist ids + foreach ($playlists as $playlist_id) { + $playlist = new Playlist($playlist_id); + $playlist->format(); + $item_total = $playlist->get_song_count(); + + // Build this element + $string .= "id\">\n" . + "\tname]]>\n" . + "\tf_user]]>\n" . + "\t$item_total\n" . + "\t$playlist->type\n" . + "\n"; + + + } // end foreach + + // Build the final and then send her off + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // playlists + + /** + * songs + * + * This returns an xml document from an array of song ids. + * (Spiffy isn't it!) + */ + public static function songs($songs) { + + if (count($songs) > self::$limit OR self::$offset > 0) { + $songs = array_slice($songs, self::$offset, self::$limit); + } + + Song::build_cache($songs); + Stream::set_session($_REQUEST['auth']); + + // Foreach the ids! + foreach ($songs as $song_id) { + $song = new Song($song_id); + + // If the song id is invalid/null + if (!$song->id) { continue; } + + $tag_string = self::tags_string(Tag::get_top_tags('song', $song_id)); + $rating = new Rating($song_id, 'song'); + $art_url = Art::url($song->album, 'album', $_REQUEST['auth']); + + $string .= "id\">\n" . + "\t<![CDATA[$song->title]]>\n" . + "\tartist . + '">get_artist_name() . + "]]>\n" . + "\talbum . + '">get_album_name(). + "]]>\n" . + $tag_string . + "\t$song->track\n" . + "\t\n" . + "\t$song->year\n" . + "\t$song->bitrate\n". + "\t$song->mode\n". + "\t$song->mime\n" . + "\tid) . "]]>\n" . + "\t$song->size\n". + "\t$song->mbid\n". + "\t$song->album_mbid\n". + "\t$song->artist_mbid\n". + "\t\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_average_rating() . "\n" . + "\n"; + + } // end foreach + + return self::_header() . $string . self::_footer(); + + } // songs + + /** + * videos + * + * This builds the xml document for displaying video objects + * + * @param array $videos (description here...) + * @return string return xml + */ + public static function videos($videos) { + + if (count($videos) > self::$limit OR self::$offset > 0) { + $videos = array_slice($videos,self::$offset,self::$limit); + } + + $string = ''; + + foreach ($videos as $video_id) { + $video = new Video($video_id); + $video->format(); + + $string .= "\n"; + + } // end foreach + + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // videos + + /** + * democratic + * + * This handles creating an xml document for democratic items, this can be a little complicated + * due to the votes and all of that + * + * @param array $object_ids Object IDs + * @return string return xml + */ + public static function democratic($object_ids=array()) { + + if (!is_array($object_ids)) { $object_ids = array(); } + + $democratic = Democratic::get_current_playlist(); + + $string = ''; + + foreach ($object_ids as $row_id=>$data) { + $song = new $data['object_type']($data['object_id']); + $song->format(); + + //FIXME: This is duplicate code and so wrong, functions need to be improved + $tag_string = ''; + + $tag = new Tag($song->tags['0']); + $song->genre = $tag->id; + $song->f_genre = $tag->name; + + $tag_string = self::tags_string($song->tags); + + $rating = new Rating($song_id,'song'); + + $art_url = Art::url($song->album, 'album', $_REQUEST['auth']); + + $string .= "id\">\n" . + "\t<![CDATA[$song->title]]>\n" . + "\tartist\">f_artist_full]]>\n" . + "\talbum\">f_album_full]]>\n" . + "\tgenre\">f_genre]]>\n" . + $tag_string . + "\t$song->track\n" . + "\t\n" . + "\t$song->mime\n" . + "\tid) . "]]>\n" . + "\t$song->size\n" . + "\t\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_user_rating() . "\n" . + "\t" . $rating->get_average_rating() . "\n" . + "\t" . $democratic->get_vote($row_id) . "\n" . + "\n"; + + } // end foreach + + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // democratic + + /** + * rss_feed + * + * (description here...) + * + * @param array $data (descriptiong here...) + * @param string $title RSS feed title + * @param string $description (not use yet?) + * @param string $date publish date + * @return string RSS feed xml + */ + public static function rss_feed($data,$title,$description,$date) { + + $string = "\t$title\n\t" . Config::get('web_path') . "\n\t" . + "" . date("r",$date) . "\n"; + + // Pass it to the keyed array xml function + foreach ($data as $item) { + // We need to enclose it in an item tag + $string .= self::keyed_array(array('item'=>$item),1); + } + + $final = self::_header() . $string . self::_footer(); + + return $final; + + } // rss_feed + + /** + * _header + * + * this returns a standard header, there are a few types + * so we allow them to pass a type if they want to + * + * @return string Header xml tag. + */ + private static function _header() { + + switch (self::$type) { + case 'xspf': + $header = "\n" . + "\n " . + "Ampache XSPF Playlist\n" . + "" . scrub_out(Config::get('site_title')) . "\n" . + "" . scrub_out(Config::get('site_title')) . "\n" . + "". Config::get('web_path') ."\n" . + "\n"; + break; + case 'itunes': + $header = "\n" . + "\n"; + "\n" . + "\n" . + "\n" . + " Major Version1\n" . + " Minor Version1\n" . + " Application Version7.0.2\n" . + " Features1\n" . + " Show Content Ratings\n" . + " Tracks\n" . + " \n"; + break; + case 'rss': + $header = "\n " . + "\n" . + "\n\n"; + break; + default: + $header = "\n\n"; + break; + } // end switch + + return $header; + + } // _header + + /** + * _footer + * + * this returns the footer for this document, these are pretty boring + * + * @return string Footer xml tag. + */ + private static function _footer() { + + switch (self::$type) { + case 'itunes': + $footer = "\t\t\t\n\n\n"; + break; + case 'xspf': + $footer = "\n\n"; + break; + case 'rss': + $footer = "\n\n\n"; + break; + default: + $footer = "\n\n"; + break; + } // end switch on type + + + return $footer; + + } // _footer } // XML_Data diff --git a/lib/debug.lib.php b/lib/debug.lib.php index 8087bf4d1f..aca6c27a65 100644 --- a/lib/debug.lib.php +++ b/lib/debug.lib.php @@ -1,5 +1,5 @@ = 60 || $current == 0); + $current = intval(ini_get('max_execution_time')); + return ($current >= 60 || $current == 0); } // check_php_timelimit @@ -163,10 +163,10 @@ function check_php_timelimit() { * Checks to make sure we aren't in safe mode */ function check_safemode() { - if (ini_get('safe_mode')) { - return false; - } - return true; + if (ini_get('safe_mode')) { + return false; + } + return true; } /** @@ -174,24 +174,24 @@ function check_safemode() { * This checks to see if we can manually override the memory limit */ function check_override_memory() { - /* Check memory */ - $current_memory = ini_get('memory_limit'); - $current_memory = substr($current_memory,0,strlen($current_memory)-1); - $new_limit = ($current_memory+16) . "M"; + /* Check memory */ + $current_memory = ini_get('memory_limit'); + $current_memory = substr($current_memory,0,strlen($current_memory)-1); + $new_limit = ($current_memory+16) . "M"; - /* Bump it by 16 megs (for getid3)*/ - if (!ini_set('memory_limit',$new_limit)) { - return false; - } + /* Bump it by 16 megs (for getid3)*/ + if (!ini_set('memory_limit',$new_limit)) { + return false; + } - // Make sure it actually worked - $new_memory = ini_get('memory_limit'); + // Make sure it actually worked + $new_memory = ini_get('memory_limit'); - if ($new_limit != $new_memory) { - return false; - } + if ($new_limit != $new_memory) { + return false; + } - return true; + return true; } /** @@ -199,14 +199,14 @@ function check_override_memory() { * This checks to see if we can manually override the max execution time */ function check_override_exec_time() { - $current = ini_get('max_execution_time'); - set_time_limit($current+60); + $current = ini_get('max_execution_time'); + set_time_limit($current+60); - if ($current == ini_get('max_execution_time')) { - return false; - } + if ($current == ini_get('max_execution_time')) { + return false; + } - return true; + return true; } /** @@ -215,11 +215,11 @@ function check_override_exec_time() { */ function check_gettext() { - if (!function_exists('gettext')) { - return false; - } + if (!function_exists('gettext')) { + return false; + } - return true; + return true; } // check_gettext @@ -229,11 +229,11 @@ function check_gettext() { */ function check_mbstring() { - if (!function_exists('mb_check_encoding')) { - return false; - } + if (!function_exists('mb_check_encoding')) { + return false; + } - return true; + return true; } // check_mbstring @@ -243,9 +243,9 @@ function check_mbstring() { */ function check_config_writable() { - // file eixsts && is writable, or dir is writable - return ((file_exists(Config::get('prefix') . '/config/ampache.cfg.php') && is_writable(Config::get('prefix') . '/config/ampache.cfg.php')) - || (!file_exists(Config::get('prefix') . '/config/ampache.cfg.php') && is_writeable(Config::get('prefix') . '/config/'))); + // file eixsts && is writable, or dir is writable + return ((file_exists(Config::get('prefix') . '/config/ampache.cfg.php') && is_writable(Config::get('prefix') . '/config/ampache.cfg.php')) + || (!file_exists(Config::get('prefix') . '/config/ampache.cfg.php') && is_writeable(Config::get('prefix') . '/config/'))); } /** @@ -255,41 +255,41 @@ function check_config_writable() { */ function generate_config($current) { - /* Start building the new config file */ - $distfile = Config::get('prefix') . '/config/ampache.cfg.php.dist'; - $handle = fopen($distfile,'r'); - $dist = fread($handle,filesize($distfile)); - fclose($handle); + /* Start building the new config file */ + $distfile = Config::get('prefix') . '/config/ampache.cfg.php.dist'; + $handle = fopen($distfile,'r'); + $dist = fread($handle,filesize($distfile)); + fclose($handle); - $data = explode("\n",$dist); + $data = explode("\n",$dist); - /* Run throught the lines and set our settings */ - foreach ($data as $line) { + /* Run throught the lines and set our settings */ + foreach ($data as $line) { - /* Attempt to pull out Key */ - if (preg_match("/^;?([\w\d]+)\s+=\s+[\"]{1}(.*?)[\"]{1}$/",$line,$matches) - || preg_match("/^;?([\w\d]+)\s+=\s+[\']{1}(.*?)[\']{1}$/", $line, $matches) - || preg_match("/^;?([\w\d]+)\s+=\s+[\'\"]{0}(.*)[\'\"]{0}$/",$line,$matches)) { + /* Attempt to pull out Key */ + if (preg_match("/^;?([\w\d]+)\s+=\s+[\"]{1}(.*?)[\"]{1}$/",$line,$matches) + || preg_match("/^;?([\w\d]+)\s+=\s+[\']{1}(.*?)[\']{1}$/", $line, $matches) + || preg_match("/^;?([\w\d]+)\s+=\s+[\'\"]{0}(.*)[\'\"]{0}$/",$line,$matches)) { - $key = $matches[1]; - $value = $matches[2]; + $key = $matches[1]; + $value = $matches[2]; - /* Put in the current value */ - if ($key == 'config_version') { - $line = $key . ' = ' . escape_ini($value); - } - elseif (isset($current[$key])) { - $line = $key . ' = "' . escape_ini($current[$key]) . '"'; - unset($current[$key]); - } // if set + /* Put in the current value */ + if ($key == 'config_version') { + $line = $key . ' = ' . escape_ini($value); + } + elseif (isset($current[$key])) { + $line = $key . ' = "' . escape_ini($current[$key]) . '"'; + unset($current[$key]); + } // if set - } // if key + } // if key - $final .= $line . "\n"; + $final .= $line . "\n"; - } // end foreach line + } // end foreach line - return $final; + return $final; } // generate_config @@ -300,7 +300,7 @@ function generate_config($current) { */ function escape_ini($str) { - return str_replace('"', '\"', $str); + return str_replace('"', '\"', $str); } @@ -311,14 +311,14 @@ function escape_ini($str) { */ function debug_result($comment,$status=false,$value=false) { - $class = $status ? 'ok' : 'notok'; - if (!$value) { - $value = $status ? 'OK' : 'ERROR'; - } + $class = $status ? 'ok' : 'notok'; + if (!$value) { + $value = $status ? 'OK' : 'ERROR'; + } - $final = '' . scrub_out($value) . ' ' . $comment . ''; + $final = '' . scrub_out($value) . ' ' . $comment . ''; - return $final; + return $final; } // debug_ok ?> diff --git a/lib/general.lib.php b/lib/general.lib.php index 6833b8bf0b..9ba241b2f5 100644 --- a/lib/general.lib.php +++ b/lib/general.lib.php @@ -1,5 +1,5 @@ 'album', - '%a'=>'artist', - '%c'=>'comment', - '%g'=>'genre', - '%T'=>'track', - '%t'=>'title', - '%y'=>'year', - '%o'=>'zz_other'); + $code_array = array('%A'=>'album', + '%a'=>'artist', + '%c'=>'comment', + '%g'=>'genre', + '%T'=>'track', + '%t'=>'title', + '%y'=>'year', + '%o'=>'zz_other'); - if (isset($code_array[$code])) { - return $code_array[$code]; - } + if (isset($code_array[$code])) { + return $code_array[$code]; + } - return false; + return false; } // translate_pattern_code diff --git a/lib/i18n.php b/lib/i18n.php index 09984624bd..e222f7e047 100644 --- a/lib/i18n.php +++ b/lib/i18n.php @@ -1,5 +1,5 @@ diff --git a/lib/init-tiny.php b/lib/init-tiny.php index a54281ed68..9461fb2e88 100644 --- a/lib/init-tiny.php +++ b/lib/init-tiny.php @@ -1,5 +1,5 @@ id AND !Config::get('demo_mode')) { vauth::logout(session_id()); exit; } + /* If the user ID doesn't exist deny them */ + if (!$GLOBALS['user']->id AND !Config::get('demo_mode')) { vauth::logout(session_id()); exit; } - /* Load preferences and theme */ - $GLOBALS['user']->update_last_seen(); + /* Load preferences and theme */ + $GLOBALS['user']->update_last_seen(); } elseif (!Config::get('use_auth')) { - $auth['success'] = 1; - $auth['username'] = '-1'; - $auth['fullname'] = "Ampache User"; - $auth['id'] = -1; - $auth['offset_limit'] = 50; - $auth['access'] = Config::get('default_auth_level') ? User::access_name_to_level(Config::get('default_auth_level')) : '100'; - if (!vauth::session_exists('interface',$_COOKIE[Config::get('session_name')])) { - vauth::create_cookie(); - vauth::session_create($auth); - vauth::check_session(); - $GLOBALS['user'] = new User($auth['username']); - $GLOBALS['user']->username = $auth['username']; - $GLOBALS['user']->fullname = $auth['fullname']; - $GLOBALS['user']->access = $auth['access']; - } - else { - vauth::check_session(); - if ($_SESSION['userdata']['username']) { - $GLOBALS['user'] = User::get_from_username($_SESSION['userdata']['username']); - } - else { - $GLOBALS['user'] = new User($auth['username']); - $GLOBALS['user']->id = '-1'; - $GLOBALS['user']->username = $auth['username']; - $GLOBALS['user']->fullname = $auth['fullname']; - $GLOBALS['user']->access = $auth['access']; - } - if (!$GLOBALS['user']->id AND !Config::get('demo_mode')) { vauth::logout(session_id()); exit; } - $GLOBALS['user']->update_last_seen(); - } + $auth['success'] = 1; + $auth['username'] = '-1'; + $auth['fullname'] = "Ampache User"; + $auth['id'] = -1; + $auth['offset_limit'] = 50; + $auth['access'] = Config::get('default_auth_level') ? User::access_name_to_level(Config::get('default_auth_level')) : '100'; + if (!vauth::session_exists('interface',$_COOKIE[Config::get('session_name')])) { + vauth::create_cookie(); + vauth::session_create($auth); + vauth::check_session(); + $GLOBALS['user'] = new User($auth['username']); + $GLOBALS['user']->username = $auth['username']; + $GLOBALS['user']->fullname = $auth['fullname']; + $GLOBALS['user']->access = $auth['access']; + } + else { + vauth::check_session(); + if ($_SESSION['userdata']['username']) { + $GLOBALS['user'] = User::get_from_username($_SESSION['userdata']['username']); + } + else { + $GLOBALS['user'] = new User($auth['username']); + $GLOBALS['user']->id = '-1'; + $GLOBALS['user']->username = $auth['username']; + $GLOBALS['user']->fullname = $auth['fullname']; + $GLOBALS['user']->access = $auth['access']; + } + if (!$GLOBALS['user']->id AND !Config::get('demo_mode')) { vauth::logout(session_id()); exit; } + $GLOBALS['user']->update_last_seen(); + } } // If Auth, but no session is set else { - if (isset($_REQUEST['sid'])) { - session_name(Config::get('session_name')); - session_id(scrub_in($_REQUEST['sid'])); - session_start(); - $GLOBALS['user'] = new User($_SESSION['userdata']['uid']); - } - else { - $GLOBALS['user'] = new User(); - } + if (isset($_REQUEST['sid'])) { + session_name(Config::get('session_name')); + session_id(scrub_in($_REQUEST['sid'])); + session_start(); + $GLOBALS['user'] = new User($_SESSION['userdata']['uid']); + } + else { + $GLOBALS['user'] = new User(); + } } // If NO_SESSION passed @@ -196,9 +196,9 @@ Preference::init(); if (session_id()) { - vauth::session_extend(session_id()); - // We only need to create the tmp playlist if we have a session - $GLOBALS['user']->load_playlist(); + vauth::session_extend(session_id()); + // We only need to create the tmp playlist if we have a session + $GLOBALS['user']->load_playlist(); } /* Add in some variables for ajax done here because we need the user */ @@ -216,16 +216,16 @@ /* Check to see if we need to perform an update */ if (!defined('OUTDATED_DATABASE_OK')) { - if (Update::need_update()) { - header("Location: " . Config::get('web_path') . "/update.php"); - exit(); - } + if (Update::need_update()) { + header("Location: " . Config::get('web_path') . "/update.php"); + exit(); + } } // For the XMLRPC stuff $GLOBALS['xmlrpc_internalencoding'] = Config::get('site_charset'); // If debug is on GIMMIE DA ERRORS if (Config::get('debug')) { - error_reporting(E_ALL); + error_reporting(E_ALL); } ?> diff --git a/lib/install.lib.php b/lib/install.lib.php index f7372a8948..882c065b87 100644 --- a/lib/install.lib.php +++ b/lib/install.lib.php @@ -1,5 +1,5 @@ 0, we can ignore lazy comparison problems - if (!file_put_contents($config_file,$final)) { - Error::add('general', T_("Error Writing config file")); - return false; - } - } - } - else { - $browser = new Horde_Browser(); - $browser->downloadHeaders('ampache.cfg.php', 'text/plain', false, strlen($final)); - echo $final; - exit(); - } - - return true; + /* + First Test The Variables they've given us to make + sure that they actually work! + */ + // Connect to the DB + if(!Dba::check_database()) { + Error::add('general', T_("Database Connection Failed Check Hostname, Username and Password")); + return false; + } + if (!Dba::check_database_exists()) { + Error::add('general', sprintf(T_('Database selection failed. Check existence of %s'), $database)); + return false; + } + + $final = generate_config($data); + + // Make sure the directory is writable OR the empty config file is + if (!$download) { + if (!check_config_writable()) { + Error::add('general', T_("Config file is not writable")); + return false; + } + else { + // Given that $final is > 0, we can ignore lazy comparison problems + if (!file_put_contents($config_file,$final)) { + Error::add('general', T_("Error Writing config file")); + return false; + } + } + } + else { + $browser = new Horde_Browser(); + $browser->downloadHeaders('ampache.cfg.php', 'text/plain', false, strlen($final)); + echo $final; + exit(); + } + + return true; } // install_create_config @@ -278,40 +278,40 @@ function install_create_config($web_path,$username,$password,$hostname,$database */ function install_create_account($username,$password,$password2) { - if (!strlen($username) OR !strlen($password)) { - Error::add('general', T_('No Username/Password specified')); - return false; - } + if (!strlen($username) OR !strlen($password)) { + Error::add('general', T_('No Username/Password specified')); + return false; + } - if ($password !== $password2) { - Error::add('general', T_('Passwords do not match')); - return false; - } + if ($password !== $password2) { + Error::add('general', T_('Passwords do not match')); + return false; + } - if (!Dba::check_database()) { - Error::add('general', sprintf(T_('Database Connection Failed: %s'), Dba::error())); - return false; - } + if (!Dba::check_database()) { + Error::add('general', sprintf(T_('Database Connection Failed: %s'), Dba::error())); + return false; + } - if (!Dba::check_database_inserted()) { - Error::add('general', sprintf(T_('Database Select Failed: %s'), Dba::error())); - return false; - } + if (!Dba::check_database_inserted()) { + Error::add('general', sprintf(T_('Database Select Failed: %s'), Dba::error())); + return false; + } - $username = Dba::escape($username); - $password = Dba::escape($password); + $username = Dba::escape($username); + $password = Dba::escape($password); - $insert_id = User::create($username,'Administrator','',$password,'100'); + $insert_id = User::create($username,'Administrator','',$password,'100'); - if (!$insert_id) { - Error::add('general', sprintf(T_('Insert of Base User Failed %s'), Dba::error())); - return false; - } + if (!$insert_id) { + Error::add('general', sprintf(T_('Insert of Base User Failed %s'), Dba::error())); + return false; + } - // Fix the system users preferences - User::fix_preferences('-1'); + // Fix the system users preferences + User::fix_preferences('-1'); - return true; + return true; } // install_create_account diff --git a/lib/javascript/ajax.js b/lib/javascript/ajax.js index 3f45590a28..8b4d29d8c3 100644 --- a/lib/javascript/ajax.js +++ b/lib/javascript/ajax.js @@ -1,4 +1,4 @@ -// vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: +// vim:set softtabstop=4 shiftwidth=4 expandtab: // // Copyright 2001 - 2013 Ampache.org // @@ -17,64 +17,64 @@ // Some cutesy flashing thing while we run Ajax.Responders.register({ - onCreate: function(){ - $('ajax-loading').style.display = 'block'; - }, - onComplete: function() { - $('ajax-loading').style.display = 'none'; - } + onCreate: function(){ + $('ajax-loading').style.display = 'block'; + }, + onComplete: function() { + $('ajax-loading').style.display = 'none'; + } }); // ajaxPost // Post the contents of a form. function ajaxPost(url, input, source) { - if ($(source)) { - Event.stopObserving(source, 'click', function() { ajaxPost(url, input, source); }); - } + if ($(source)) { + Event.stopObserving(source, 'click', function() { ajaxPost(url, input, source); }); + } - new Ajax.Request(url, { - method: 'post', - parameters: $(input).serialize(true), - onSuccess: processContents - }); + new Ajax.Request(url, { + method: 'post', + parameters: $(input).serialize(true), + onSuccess: processContents + }); } // ajaxPost // ajaxPut // Get response from the specified URL. function ajaxPut(url, source) { - if ($(source)) { - Event.stopObserving(source, 'click', function(){ ajaxPut(url, source); }); - } + if ($(source)) { + Event.stopObserving(source, 'click', function(){ ajaxPut(url, source); }); + } - new Ajax.Request(url, { - method: 'put', - onSuccess: processContents - }); + new Ajax.Request(url, { + method: 'put', + onSuccess: processContents + }); } // ajaxPut // ajaxState // Post the contents of a form without doing any observe() things. function ajaxState(url, input) { - new Ajax.Request(url, { - method: 'post', - parameters: $(input).serialize(true), - onSuccess: processContents - }); + new Ajax.Request(url, { + method: 'post', + parameters: $(input).serialize(true), + onSuccess: processContents + }); } // ajaxState // processContents // Iterate over a response and do any updates we received. function processContents(transport) { - $A(transport.responseXML.getElementsByTagName('content')).each(updateElement); + $A(transport.responseXML.getElementsByTagName('content')).each(updateElement); } // processContents // updateElement // This isn't an anonymous function because I'm ornery. Does the actual // updates for processContents. function updateElement(contentXML) { - var newID = contentXML.getAttribute('div'); - if($(newID)) { - $(newID).update(contentXML.firstChild.nodeValue); - } + var newID = contentXML.getAttribute('div'); + if($(newID)) { + $(newID).update(contentXML.firstChild.nodeValue); + } } // updateElement diff --git a/lib/javascript/base.js b/lib/javascript/base.js index 3e6e7e6d17..9d56f4f494 100644 --- a/lib/javascript/base.js +++ b/lib/javascript/base.js @@ -1,4 +1,4 @@ -// vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: +// vim:set softtabstop=4 shiftwidth=4 expandtab: // // Copyright 2001 - 2013 Ampache.org // All rights reserved. @@ -32,34 +32,34 @@ function flipField(field) { // updateText // Changes the specified elements innards. Used for the catalog mojo fluff. function updateText(field, value) { - $(field).innerHTML = value; + $(field).innerHTML = value; } // updateText // toggleVisible // Toggles display type between block and none. Used for ajax loading div. function toggleVisible(element) { - if ($(element).style.display == 'block') { - $(element).style.display = 'none'; - } - else { - $(element).style.display = 'block'; - } + if ($(element).style.display == 'block') { + $(element).style.display = 'none'; + } + else { + $(element).style.display = 'block'; + } } // toggleVisible // delayRun // This function delays the run of another function by X milliseconds function delayRun(element, time, method, page, source) { - var function_string = method + '(\'' + page + '\',\'' + source + '\')'; + var function_string = method + '(\'' + page + '\',\'' + source + '\')'; - var action = function () { eval(function_string); }; + var action = function () { eval(function_string); }; - if (element.zid) { - clearTimeout(element.zid); - } + if (element.zid) { + clearTimeout(element.zid); + } - element.zid = setTimeout(action, time); + element.zid = setTimeout(action, time); } // delayRun @@ -69,21 +69,21 @@ function delayRun(element, time, method, page, source) { // Localplay, which don't actually prompt for a new file function reloadUtil(target) { - if (navigator.appName == 'Opera') { - $('util_iframe').contentWindow.location.reload(true); - } - else if (navigator.appName == 'Konqueror') { - $('util_iframe').contentDocument.location.reload(true); - } - else { - $('util_iframe').src = $('util_iframe').src; - } + if (navigator.appName == 'Opera') { + $('util_iframe').contentWindow.location.reload(true); + } + else if (navigator.appName == 'Konqueror') { + $('util_iframe').contentDocument.location.reload(true); + } + else { + $('util_iframe').src = $('util_iframe').src; + } } // reloadUtil // reloadRedirect // Send them elsewhere function reloadRedirect(target) { - window.location = target; + window.location = target; } // reloadRedirect // popupWindow @@ -96,10 +96,10 @@ function popupWindow(url) { // This is kind of ugly. Let's not mess with it too much. function check_inline_song_edit(type, song) { var target = type + '_select_' + song; - if ($(target).options[$(target).selectedIndex].value == -1) { - $(target).innerHTML = ''; - } else { - $(target).innerHTML = ''; - } + if ($(target).options[$(target).selectedIndex].value == -1) { + $(target).innerHTML = ''; + } else { + $(target).innerHTML = ''; + } } diff --git a/lib/javascript/search-data.php b/lib/javascript/search-data.php index dd3e302e2e..2f52106039 100644 --- a/lib/javascript/search-data.php +++ b/lib/javascript/search-data.php @@ -1,5 +1,5 @@ $value) { - $json .= '"' . $key . '" : '; - if (is_array($value)) { - $json .= arrayToJSON($value); - } - else { - // Make sure to strip backslashes and convert things to - // entities in our output - $json .= '"' . scrub_out(str_replace('\\', '', $value)) . '"'; - } - $json .= ' , '; - } - $json = rtrim($json, ', '); - return $json . ' }'; + $json = '{ '; + foreach ($array as $key => $value) { + $json .= '"' . $key . '" : '; + if (is_array($value)) { + $json .= arrayToJSON($value); + } + else { + // Make sure to strip backslashes and convert things to + // entities in our output + $json .= '"' . scrub_out(str_replace('\\', '', $value)) . '"'; + } + $json .= ' , '; + } + $json = rtrim($json, ', '); + return $json . ' }'; } Header('content-type: application/x-javascript'); diff --git a/lib/javascript/search.js b/lib/javascript/search.js index 52267ad10a..b6307a7239 100644 --- a/lib/javascript/search.js +++ b/lib/javascript/search.js @@ -1,4 +1,4 @@ -// vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: +// vim:set softtabstop=4 shiftwidth=4 expandtab: // // Copyright 2010 - 2013 Ampache.org // All rights reserved. @@ -21,148 +21,148 @@ var rowIter = 1; var rowCount = 0; var SearchRow = { - add: function(ruleType, operator, input) { - if (typeof(ruleType) != 'string') { - ruleType = 0; - } - else { - types.each(function(i) { - if (i.value.name == ruleType) { - ruleType = i.key; - throw $break; - } - }); - } - - if (typeof(operator) != 'string') { - operator = 0; - } - else { - $H(basetypes.get(types.get(ruleType).type)).each(function(i) { - if (i.value.name == operator) { - operator = i.key; - throw $break; - } - }); - } - - var row = document.createElement('tr'); - var cells = new Array(); - for (var i = 0 ; i < 5 ; i++) { - cells[i] = document.createElement('td'); - } - - cells[0].appendChild(SearchRow.constructOptions(ruleType, rowIter)); - cells[1].appendChild(SearchRow.constructOperators(ruleType, rowIter, operator)); - cells[2].appendChild(SearchRow.constructInput(ruleType, rowIter, input)); - cells[3].innerHTML = removeIcon; - - cells.each(function(i) { - row.appendChild(i); - }); - - $('searchtable').appendChild(row); - rowCount++; - - Event.observe(cells[3], 'click', function(e){if(rowCount > 1) { Element.remove(this.parentNode); rowCount--; }}); - - rowIter++; - }, - constructInput: function(ruleType, ruleNumber, input) { - if (input === null || input === undefined) { - input = ''; - } - - widget = $H(types.get(ruleType).widget); - - var inputNode = document.createElement(widget.get('0')); - inputNode.id = 'rule_' + ruleNumber + '_input'; - inputNode.name = 'rule_' + ruleNumber + '_input'; - - switch(widget.get('0')) { - case 'input': - inputNode.setAttribute('type', widget.get('1')); - inputNode.setAttribute('value', input); - break; - case 'select': - $H(widget.get('1')).each(function(i) { - var option = document.createElement('option'); - if ( isNaN(parseInt(i.value)) ) { - realvalue = i.key; - } - else { - realvalue = parseInt(i.value); - } - if ( input == realvalue ) { - option.selected = true; - } - option.value = realvalue; - option.innerHTML = i.value; - inputNode.appendChild(option); - }); - break; - } - - return inputNode; - }, - constructOptions: function(ruleType, ruleNumber) { - var optionsNode = document.createElement('select'); - optionsNode.id = 'rule_' + ruleNumber; - optionsNode.name = 'rule_' + ruleNumber; - - types.each(function(i) { - var option = document.createElement('option'); - option.innerHTML = i.value.label; - option.value = i.value.name; - if ( i.key == ruleType ) { - option.selected = true; - } - optionsNode.appendChild(option); - }); - - Event.observe(optionsNode, 'change', SearchRow.update); - - return optionsNode; - }, - constructOperators: function(ruleType, ruleNumber, operator) { - var operatorNode = document.createElement('select'); - operatorNode.id = 'rule_' + ruleNumber + '_operator'; - operatorNode.name = 'rule_' + ruleNumber + '_operator'; - - basetype = types.get(ruleType).type; - operatorNode.className = 'operator' + basetype; - - $H(basetypes.get(basetype)).each(function(i) { - var option = document.createElement('option'); - option.innerHTML = i.value.description; - option.value = i.key; - if (i.key == operator) { - option.selected = true; - } - operatorNode.appendChild(option); - }); - - return operatorNode; - }, - update: function() { - var r_findID = /rule_(\d+)/; - var targetID = r_findID.exec(this.id)[1]; - - var operator = $('rule_' + targetID + '_operator'); - if (operator.className != 'operator' + types.get(this.selectedIndex).type) { - var operator_cell = operator.parentNode; - Element.remove(operator); - operator_cell.appendChild(SearchRow.constructOperators(this.selectedIndex, targetID)); - } - - var input = $('rule_' + targetID + '_input'); - - if (input.type == 'text') { - var oldinput = input.value; - } - - var input_cell = input.parentNode; - Element.remove(input); - input_cell.appendChild(SearchRow.constructInput(this.selectedIndex, targetID, oldinput)); - } + add: function(ruleType, operator, input) { + if (typeof(ruleType) != 'string') { + ruleType = 0; + } + else { + types.each(function(i) { + if (i.value.name == ruleType) { + ruleType = i.key; + throw $break; + } + }); + } + + if (typeof(operator) != 'string') { + operator = 0; + } + else { + $H(basetypes.get(types.get(ruleType).type)).each(function(i) { + if (i.value.name == operator) { + operator = i.key; + throw $break; + } + }); + } + + var row = document.createElement('tr'); + var cells = new Array(); + for (var i = 0 ; i < 5 ; i++) { + cells[i] = document.createElement('td'); + } + + cells[0].appendChild(SearchRow.constructOptions(ruleType, rowIter)); + cells[1].appendChild(SearchRow.constructOperators(ruleType, rowIter, operator)); + cells[2].appendChild(SearchRow.constructInput(ruleType, rowIter, input)); + cells[3].innerHTML = removeIcon; + + cells.each(function(i) { + row.appendChild(i); + }); + + $('searchtable').appendChild(row); + rowCount++; + + Event.observe(cells[3], 'click', function(e){if(rowCount > 1) { Element.remove(this.parentNode); rowCount--; }}); + + rowIter++; + }, + constructInput: function(ruleType, ruleNumber, input) { + if (input === null || input === undefined) { + input = ''; + } + + widget = $H(types.get(ruleType).widget); + + var inputNode = document.createElement(widget.get('0')); + inputNode.id = 'rule_' + ruleNumber + '_input'; + inputNode.name = 'rule_' + ruleNumber + '_input'; + + switch(widget.get('0')) { + case 'input': + inputNode.setAttribute('type', widget.get('1')); + inputNode.setAttribute('value', input); + break; + case 'select': + $H(widget.get('1')).each(function(i) { + var option = document.createElement('option'); + if ( isNaN(parseInt(i.value)) ) { + realvalue = i.key; + } + else { + realvalue = parseInt(i.value); + } + if ( input == realvalue ) { + option.selected = true; + } + option.value = realvalue; + option.innerHTML = i.value; + inputNode.appendChild(option); + }); + break; + } + + return inputNode; + }, + constructOptions: function(ruleType, ruleNumber) { + var optionsNode = document.createElement('select'); + optionsNode.id = 'rule_' + ruleNumber; + optionsNode.name = 'rule_' + ruleNumber; + + types.each(function(i) { + var option = document.createElement('option'); + option.innerHTML = i.value.label; + option.value = i.value.name; + if ( i.key == ruleType ) { + option.selected = true; + } + optionsNode.appendChild(option); + }); + + Event.observe(optionsNode, 'change', SearchRow.update); + + return optionsNode; + }, + constructOperators: function(ruleType, ruleNumber, operator) { + var operatorNode = document.createElement('select'); + operatorNode.id = 'rule_' + ruleNumber + '_operator'; + operatorNode.name = 'rule_' + ruleNumber + '_operator'; + + basetype = types.get(ruleType).type; + operatorNode.className = 'operator' + basetype; + + $H(basetypes.get(basetype)).each(function(i) { + var option = document.createElement('option'); + option.innerHTML = i.value.description; + option.value = i.key; + if (i.key == operator) { + option.selected = true; + } + operatorNode.appendChild(option); + }); + + return operatorNode; + }, + update: function() { + var r_findID = /rule_(\d+)/; + var targetID = r_findID.exec(this.id)[1]; + + var operator = $('rule_' + targetID + '_operator'); + if (operator.className != 'operator' + types.get(this.selectedIndex).type) { + var operator_cell = operator.parentNode; + Element.remove(operator); + operator_cell.appendChild(SearchRow.constructOperators(this.selectedIndex, targetID)); + } + + var input = $('rule_' + targetID + '_input'); + + if (input.type == 'text') { + var oldinput = input.value; + } + + var input_cell = input.parentNode; + Element.remove(input); + input_cell.appendChild(SearchRow.constructInput(this.selectedIndex, targetID, oldinput)); + } }; diff --git a/lib/log.lib.php b/lib/log.lib.php index 37a1c790be..19aad9645d 100644 --- a/lib/log.lib.php +++ b/lib/log.lib.php @@ -1,5 +1,5 @@ $event_description \n"; + $log_filename = Config::get('log_path') . "/$log_name.$log_day.log"; + $log_line = "$log_time [$username] ($event_name) -> $event_description \n"; - // Do the deed - $log_write = error_log($log_line, 3, $log_filename); + // Do the deed + $log_write = error_log($log_line, 3, $log_filename); - if (!$log_write) { - echo "Warning: Unable to write to log ($log_filename) Please check your log_path variable in ampache.cfg.php"; - } + if (!$log_write) { + echo "Warning: Unable to write to log ($log_filename) Please check your log_path variable in ampache.cfg.php"; + } } // log_event @@ -54,67 +54,67 @@ function log_event($username, $event_name, $event_description, $log_name) { */ function ampache_error_handler($errno, $errstr, $errfile, $errline) { - /* Default level of 1 */ - $level = 1; - - switch ($errno) { - case E_WARNING: - $error_name = 'Runtime Error'; - break; - case E_COMPILE_WARNING: - case E_NOTICE: - case E_CORE_WARNING: - $error_name = 'Warning'; - $level = 6; - break; - case E_ERROR: - $error_name = 'Fatal run-time Error'; - break; - case E_PARSE: - $error_name = 'Parse Error'; - break; - case E_CORE_ERROR: - $error_name = 'Fatal Core Error'; - break; - case E_COMPILE_ERROR: - $error_name = 'Zend run-time Error'; - break; - case E_STRICT: - $error_name = "Strict Error"; - break; - default: - $error_name = "Error"; - $level = 2; - break; - } // end switch - - // List of things that should only be displayed if they told us to turn - // on the firehose - $ignores = array( - // We know var is deprecated, shut up - 'var: Deprecated. Please use the public/private/protected modifiers', - // getid3 spews errors, yay! - 'getimagesize() [', - 'Non-static method getid3', - 'Assigning the return value of new by reference is deprecated', - // The XML-RPC lib is broken (kinda) - 'used as offset, casting to integer' - ); - - foreach($ignores as $ignore) { - if (strpos($errstr, $ignore) !== false) { - $error_name = 'Ignored ' . $error_name; - $level = 7; - } - } - - if (strpos($errstr,"date.timezone") !== false) { - $error_name = 'Warning'; - $errstr = 'You have not set a valid timezone (date.timezone) in your php.ini file. This may cause display issues with dates. This warning is non-critical and not caused by Ampache.'; - } - - $log_line = "[$error_name] $errstr in file $errfile($errline)"; - debug_event('PHP', $log_line, $level, '', 'ampache'); + /* Default level of 1 */ + $level = 1; + + switch ($errno) { + case E_WARNING: + $error_name = 'Runtime Error'; + break; + case E_COMPILE_WARNING: + case E_NOTICE: + case E_CORE_WARNING: + $error_name = 'Warning'; + $level = 6; + break; + case E_ERROR: + $error_name = 'Fatal run-time Error'; + break; + case E_PARSE: + $error_name = 'Parse Error'; + break; + case E_CORE_ERROR: + $error_name = 'Fatal Core Error'; + break; + case E_COMPILE_ERROR: + $error_name = 'Zend run-time Error'; + break; + case E_STRICT: + $error_name = "Strict Error"; + break; + default: + $error_name = "Error"; + $level = 2; + break; + } // end switch + + // List of things that should only be displayed if they told us to turn + // on the firehose + $ignores = array( + // We know var is deprecated, shut up + 'var: Deprecated. Please use the public/private/protected modifiers', + // getid3 spews errors, yay! + 'getimagesize() [', + 'Non-static method getid3', + 'Assigning the return value of new by reference is deprecated', + // The XML-RPC lib is broken (kinda) + 'used as offset, casting to integer' + ); + + foreach($ignores as $ignore) { + if (strpos($errstr, $ignore) !== false) { + $error_name = 'Ignored ' . $error_name; + $level = 7; + } + } + + if (strpos($errstr,"date.timezone") !== false) { + $error_name = 'Warning'; + $errstr = 'You have not set a valid timezone (date.timezone) in your php.ini file. This may cause display issues with dates. This warning is non-critical and not caused by Ampache.'; + } + + $log_line = "[$error_name] $errstr in file $errfile($errline)"; + debug_event('PHP', $log_line, $level, '', 'ampache'); } // ampache_error_handler @@ -126,15 +126,15 @@ function ampache_error_handler($errno, $errstr, $errfile, $errline) { */ function debug_event($type, $message, $level, $file = '', $username = '') { - if (!Config::get('debug') || $level > Config::get('debug_level')) { - return false; - } + if (!Config::get('debug') || $level > Config::get('debug_level')) { + return false; + } - if (!$username && isset($GLOBALS['user'])) { - $username = $GLOBALS['user']->username; - } + if (!$username && isset($GLOBALS['user'])) { + $username = $GLOBALS['user']->username; + } - log_event($username, $type, $message, $file); + log_event($username, $type, $message, $file); } // debug_event diff --git a/lib/preferences.php b/lib/preferences.php index 46543a0f7f..6fe5c178a2 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -1,5 +1,5 @@ $r['id'], 'name' => $r['name'],'type' => $r['type']); - } // end collecting keys + // Collect the current possible keys + while ($r = Dba::fetch_assoc($db_results)) { + $results[] = array('id' => $r['id'], 'name' => $r['name'],'type' => $r['type']); + } // end collecting keys - /* Foreach through possible keys and assign them */ - foreach ($results as $data) { - /* Get the Value from POST/GET var called $data */ - $type = $data['type']; - $name = $data['name']; - $apply_to_all = 'check_' . $data['name']; - $new_level = 'level_' . $data['name']; - $id = $data['id']; - $value = scrub_in($_REQUEST[$name]); + /* Foreach through possible keys and assign them */ + foreach ($results as $data) { + /* Get the Value from POST/GET var called $data */ + $type = $data['type']; + $name = $data['name']; + $apply_to_all = 'check_' . $data['name']; + $new_level = 'level_' . $data['name']; + $id = $data['id']; + $value = scrub_in($_REQUEST[$name]); - /* Some preferences require some extra checks to be performed */ - switch ($name) { - case 'sample_rate': - $value = Stream::validate_bitrate($value); - break; - default: - break; - } + /* Some preferences require some extra checks to be performed */ + switch ($name) { + case 'sample_rate': + $value = Stream::validate_bitrate($value); + break; + default: + break; + } - if (preg_match('/_pass$/', $name)) { - if ($value == '******') { unset($_REQUEST[$name]); } - else if (preg_match('/md5_pass$/', $name)) { - $value = md5($value); - } - } + if (preg_match('/_pass$/', $name)) { + if ($value == '******') { unset($_REQUEST[$name]); } + else if (preg_match('/md5_pass$/', $name)) { + $value = md5($value); + } + } - /* Run the update for this preference only if it's set */ - if (isset($_REQUEST[$name])) { - Preference::update($id,$pref_id,$value,$_REQUEST[$apply_to_all]); - } + /* Run the update for this preference only if it's set */ + if (isset($_REQUEST[$name])) { + Preference::update($id,$pref_id,$value,$_REQUEST[$apply_to_all]); + } - if (Access::check('interface','100') AND $_REQUEST[$new_level]) { - Preference::update_level($id,$_REQUEST[$new_level]); - } + if (Access::check('interface','100') AND $_REQUEST[$new_level]) { + Preference::update_level($id,$_REQUEST[$new_level]); + } - } // end foreach preferences + } // end foreach preferences - // Now that we've done that we need to invalidate the cached preverences - Preference::clear_from_session(); + // Now that we've done that we need to invalidate the cached preverences + Preference::clear_from_session(); } // update_preferences @@ -91,28 +91,28 @@ function update_preferences($pref_id=0) { */ function update_preference($user_id,$name,$pref_id,$value) { - $apply_check = "check_" . $name; - $level_check = "level_" . $name; + $apply_check = "check_" . $name; + $level_check = "level_" . $name; - /* First see if they are an administrator and we are applying this to everything */ - if ($GLOBALS['user']->has_access(100) AND make_bool($_REQUEST[$apply_check])) { - Preference::update_all($pref_id,$value); - return true; - } + /* First see if they are an administrator and we are applying this to everything */ + if ($GLOBALS['user']->has_access(100) AND make_bool($_REQUEST[$apply_check])) { + Preference::update_all($pref_id,$value); + return true; + } - /* Check and see if they are an admin and the level def is set */ - if ($GLOBALS['user']->has_access(100) AND make_bool($_REQUEST[$level_check])) { - Preference::update_level($pref_id,$_REQUEST[$level_check]); - } + /* Check and see if they are an admin and the level def is set */ + if ($GLOBALS['user']->has_access(100) AND make_bool($_REQUEST[$level_check])) { + Preference::update_level($pref_id,$_REQUEST[$level_check]); + } - /* Else make sure that the current users has the right to do this */ - if (Preference::has_access($name)) { - $sql = "UPDATE `user_preference` SET `value`='$value' WHERE `preference`='$pref_id' AND `user`='$user_id'"; - $db_results = Dba::write($sql); - return true; - } + /* Else make sure that the current users has the right to do this */ + if (Preference::has_access($name)) { + $sql = "UPDATE `user_preference` SET `value`='$value' WHERE `preference`='$pref_id' AND `user`='$user_id'"; + $db_results = Dba::write($sql); + return true; + } - return false; + return false; } // update_preference @@ -122,183 +122,183 @@ function update_preference($user_id,$name,$pref_id,$value) { */ function create_preference_input($name,$value) { - // Escape it for output - $value = scrub_out($value); + // Escape it for output + $value = scrub_out($value); - $len = strlen($value); - if ($len <= 1) { $len = 8; } + $len = strlen($value); + if ($len <= 1) { $len = 8; } - if (!Preference::has_access($name)) { - if ($value == '1') { - echo "Enabled"; - } - elseif ($value == '0') { - echo "Disabled"; - } - else { - if (preg_match('/_pass$/', $name)) { - echo "******"; - } - else { - echo $value; - } - } - return; - } // if we don't have access to it + if (!Preference::has_access($name)) { + if ($value == '1') { + echo "Enabled"; + } + elseif ($value == '0') { + echo "Disabled"; + } + else { + if (preg_match('/_pass$/', $name)) { + echo "******"; + } + else { + echo $value; + } + } + return; + } // if we don't have access to it - switch($name) { - case 'display_menu': - case 'download': - case 'quarantine': - case 'upload': - case 'access_list': - case 'lock_songs': - case 'xml_rpc': - case 'force_http_play': - case 'no_symlinks': - case 'use_auth': - case 'access_control': - case 'allow_stream_playback': - case 'allow_democratic_playback': - case 'allow_localplay_playback': - case 'demo_mode': - case 'condPL': - case 'rio_track_stats': - case 'rio_global_stats': - case 'embed_xspf': - case 'direct_link': - if ($value == '1') { $is_true = "selected=\"selected\""; } - else { $is_false = "selected=\"selected\""; } - echo "\n"; - break; - case 'play_type': - if ($value == 'localplay') { $is_local = 'selected="selected"'; } - elseif ($value == 'democratic') { $is_vote = 'selected="selected"'; } - elseif ($value == 'xspf_player') { $is_xspf_player = 'selected="selected"'; } - else { $is_stream = "selected=\"selected\""; } - echo "\n"; - break; - case 'playlist_type': - $var_name = $value . "_type"; - ${$var_name} = "selected=\"selected\""; - echo "\n"; - break; - case 'lang': - $languages = get_languages(); - echo '\n"; + echo "\t\n"; + echo "\t\n"; + echo "\n"; + break; + case 'play_type': + if ($value == 'localplay') { $is_local = 'selected="selected"'; } + elseif ($value == 'democratic') { $is_vote = 'selected="selected"'; } + elseif ($value == 'xspf_player') { $is_xspf_player = 'selected="selected"'; } + else { $is_stream = "selected=\"selected\""; } + echo "\n"; + break; + case 'playlist_type': + $var_name = $value . "_type"; + ${$var_name} = "selected=\"selected\""; + echo "\n"; + break; + case 'lang': + $languages = get_languages(); + echo '\n"; - break; - case 'localplay_controller': - $controllers = Localplay::get_controllers(); - echo "\n"; - break; - case 'localplay_level': - if ($value == '25') { $is_user = 'selected="selected"'; } - elseif ($value == '100') { $is_admin = 'selected="selected"'; } - elseif ($value == '50') { $is_manager = 'selected="selected"'; } - echo "\n"; - break; - case 'theme_name': - $themes = get_themes(); - echo "\n"; - break; - case 'playlist_method': - ${$value} = ' selected="selected"'; - echo "\n"; - break; - case 'bandwidth': - ${"bandwidth_$value"} = ' selected="selected"'; - echo "\n"; - break; - case 'features': - ${"features_$value"} = ' selected="selected"'; - echo "\n"; + break; + case 'localplay_controller': + $controllers = Localplay::get_controllers(); + echo "\n"; + break; + case 'localplay_level': + if ($value == '25') { $is_user = 'selected="selected"'; } + elseif ($value == '100') { $is_admin = 'selected="selected"'; } + elseif ($value == '50') { $is_manager = 'selected="selected"'; } + echo "\n"; + break; + case 'theme_name': + $themes = get_themes(); + echo "\n"; + break; + case 'playlist_method': + ${$value} = ' selected="selected"'; + echo "\n"; + break; + case 'bandwidth': + ${"bandwidth_$value"} = ' selected="selected"'; + echo "\n"; + break; + case 'features': + ${"features_$value"} = ' selected="selected"'; + echo "\n"; - break; - case 'transcode': - ${$value} = ' selected="selected"'; - echo "\n"; - break; - case 'show_lyrics': - if ($value == '1') { $is_true = "selected=\"selected\""; } - else { $is_false = "selected=\"selected\""; } - echo "\n"; - break; - default: - if (preg_match('/_pass$/', $name)) { - echo ''; - } - else { - echo ''; - } - break; + break; + case 'transcode': + ${$value} = ' selected="selected"'; + echo "\n"; + break; + case 'show_lyrics': + if ($value == '1') { $is_true = "selected=\"selected\""; } + else { $is_false = "selected=\"selected\""; } + echo "\n"; + break; + default: + if (preg_match('/_pass$/', $name)) { + echo ''; + } + else { + echo ''; + } + break; - } + } } // create_preference_input diff --git a/lib/rating.lib.php b/lib/rating.lib.php index 461762f8bc..ca6d72093c 100644 --- a/lib/rating.lib.php +++ b/lib/rating.lib.php @@ -1,5 +1,5 @@ \n"; + // Added ID field so we can easily observe this element + echo "\n"; + echo "\n"; } // show_album_select @@ -230,36 +230,36 @@ function show_album_select($name='album',$album_id=0,$allow_add=0,$song_id=0) { * inventive! */ function show_artist_select($name='artist', $artist_id=0, $allow_add=0, $song_id=0) { - // Generate key to use for HTML element ID - static $id_cnt; - if ($song_id) { - $key = "artist_select_$song_id"; - } else { - $key = "artist_select_c" . ++$id_cnt; - } + // Generate key to use for HTML element ID + static $id_cnt; + if ($song_id) { + $key = "artist_select_$song_id"; + } else { + $key = "artist_select_c" . ++$id_cnt; + } - echo "\n"; - $sql = "SELECT `id`, `name`, `prefix` FROM `artist` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id`, `name`, `prefix` FROM `artist` ORDER BY `name`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $selected = ''; - $artist_name = trim($r['prefix'] . " " . $r['name']); - if ($r['id'] == $artist_id) { - $selected = "selected=\"selected\""; - } + while ($r = Dba::fetch_assoc($db_results)) { + $selected = ''; + $artist_name = trim($r['prefix'] . " " . $r['name']); + if ($r['id'] == $artist_id) { + $selected = "selected=\"selected\""; + } - echo "\t\n"; + echo "\t\n"; - } // end while + } // end while - if ($allow_add) { - // Append additional option to the end with value=-1 - echo "\t\n"; - } + if ($allow_add) { + // Append additional option to the end with value=-1 + echo "\t\n"; + } - echo "\n"; + echo "\n"; } // show_artist_select @@ -270,22 +270,22 @@ function show_artist_select($name='artist', $artist_id=0, $allow_add=0, $song_id */ function show_catalog_select($name='catalog',$catalog_id=0,$style='') { - echo "\n"; - $sql = "SELECT `id`, `name` FROM `catalog` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id`, `name` FROM `catalog` ORDER BY `name`"; + $db_results = Dba::read($sql); - while ($r = Dba::fetch_assoc($db_results)) { - $selected = ''; - if ($r['id'] == $catalog_id) { - $selected = "selected=\"selected\""; - } + while ($r = Dba::fetch_assoc($db_results)) { + $selected = ''; + if ($r['id'] == $catalog_id) { + $selected = "selected=\"selected\""; + } - echo "\t\n"; + echo "\t\n"; - } // end while + } // end while - echo "\n"; + echo "\n"; } // show_catalog_select @@ -296,24 +296,24 @@ function show_catalog_select($name='catalog',$catalog_id=0,$style='') { */ function show_user_select($name,$selected='',$style='') { - echo "\n"; + echo "\t\n"; - $sql = "SELECT `id`,`username`,`fullname` FROM `user` ORDER BY `fullname`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id`,`username`,`fullname` FROM `user` ORDER BY `fullname`"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $select_txt = ''; - if ($row['id'] == $selected) { - $select_txt = 'selected="selected"'; - } - // If they don't have a full name, revert to the username - $row['fullname'] = $row['fullname'] ? $row['fullname'] : $row['username']; + while ($row = Dba::fetch_assoc($db_results)) { + $select_txt = ''; + if ($row['id'] == $selected) { + $select_txt = 'selected="selected"'; + } + // If they don't have a full name, revert to the username + $row['fullname'] = $row['fullname'] ? $row['fullname'] : $row['username']; - echo "\t\n"; - } // end while users + echo "\t\n"; + } // end while users - echo "\n"; + echo "\n"; } // show_user_select @@ -323,22 +323,22 @@ function show_user_select($name,$selected='',$style='') { */ function show_playlist_select($name,$selected='',$style='') { - echo "\n"; + echo "\t\n"; - $sql = "SELECT `id`,`name` FROM `playlist` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT `id`,`name` FROM `playlist` ORDER BY `name`"; + $db_results = Dba::read($sql); - while ($row = Dba::fetch_assoc($db_results)) { - $select_txt = ''; - if ($row['id'] == $selected) { - $select_txt = 'selected="selected"'; - } - // If they don't have a full name, revert to the username - echo "\t\n"; - } // end while users + while ($row = Dba::fetch_assoc($db_results)) { + $select_txt = ''; + if ($row['id'] == $selected) { + $select_txt = 'selected="selected"'; + } + // If they don't have a full name, revert to the username + echo "\t\n"; + } // end while users - echo "\n"; + echo "\n"; } // show_playlist_select @@ -350,93 +350,93 @@ function show_playlist_select($name,$selected='',$style='') { */ function xml_from_array($array, $callback = false, $type = '') { - $string = ''; - - // If we weren't passed an array then return - if (!is_array($array)) { return $string; } - - // The type is used for the different XML docs we pass - switch ($type) { - case 'itunes': - foreach ($array as $key=>$value) { - if (is_array($value)) { - $value = xml_from_array($value,1,$type); - $string .= "\t\t<$key>\n$value\t\t\n"; - } - else { - if ($key == "key"){ - $string .= "\t\t<$key>$value\n"; - } elseif (is_int($value)) { - $string .= "\t\t\t$key$value\n"; - } elseif ($key == "Date Added") { - $string .= "\t\t\t$key$value\n"; - } elseif (is_string($value)) { - /* We need to escape the value */ - $string .= "\t\t\t$key\n"; - } - } - - } // end foreach - - return $string; - break; - case 'xspf': - foreach ($array as $key=>$value) { - if (is_array($value)) { - $value = xml_from_array($value,1,$type); - $string .= "\t\t<$key>\n$value\t\t\n"; - } - else { - if ($key == "key"){ - $string .= "\t\t<$key>$value\n"; - } elseif (is_numeric($value)) { - $string .= "\t\t\t<$key>$value\n"; - } elseif (is_string($value)) { - /* We need to escape the value */ - $string .= "\t\t\t<$key>\n"; - } - } - - } // end foreach - - return $string; - break; - default: - foreach ($array as $key => $value) { - // No numeric keys - if (is_numeric($key)) { - $key = 'item'; - } - - if (is_array($value)) { - // Call ourself - $value = xml_from_array($value, true); - $string .= "\t$value\n"; - } - else { - /* We need to escape the value */ - $string .= "\t\n"; - } - // end foreach elements - } - if (!$callback) { - $string = '' . - "\n\n" . $string . "\n"; - } - - // Remove invalid XML characters. - // See http://www.w3.org/TR/2006/REC-xml-20060816/#charsets - $clean = preg_replace('/[^\x{9}\x{a}\x{d}\x{20}-\x{d7ff}\x{e000}-\x{fffd}\x{10000}-\x{10ffff}]|[\x{7f}-\x{84}\x{86}-\x{9f}\x{fdd0}-\x{fddf}\x{1fffe}-\x{1ffff}\x{2fffe}-\x{2ffff}\x{3fffe}-\x{3ffff}\x{4fffe}-\x{4ffff}\x{5fffe}-\x{5ffff}\x{6fffe}-\x{6ffff}\x{7fffe}-\x{7ffff}\x{8fffe}-\x{8ffff}\x{9fffe}-\x{9ffff}\x{afffe}-\x{affff}\x{bfffe}-\x{bffff}\x{cfffe}-\x{cffff}\x{dfffe}-\x{dffff}\x{efffe}-\x{effff}\x{ffffe}-\x{fffff}\x{10fffe}-\x{10ffff}]/u', '', $string); - - if ($clean) { - return $clean; - } - else { - debug_event('xml_from_array', 'Charset cleanup failed, generated XML may be invalid', 1); - return $string; - } - break; - } + $string = ''; + + // If we weren't passed an array then return + if (!is_array($array)) { return $string; } + + // The type is used for the different XML docs we pass + switch ($type) { + case 'itunes': + foreach ($array as $key=>$value) { + if (is_array($value)) { + $value = xml_from_array($value,1,$type); + $string .= "\t\t<$key>\n$value\t\t\n"; + } + else { + if ($key == "key"){ + $string .= "\t\t<$key>$value\n"; + } elseif (is_int($value)) { + $string .= "\t\t\t$key$value\n"; + } elseif ($key == "Date Added") { + $string .= "\t\t\t$key$value\n"; + } elseif (is_string($value)) { + /* We need to escape the value */ + $string .= "\t\t\t$key\n"; + } + } + + } // end foreach + + return $string; + break; + case 'xspf': + foreach ($array as $key=>$value) { + if (is_array($value)) { + $value = xml_from_array($value,1,$type); + $string .= "\t\t<$key>\n$value\t\t\n"; + } + else { + if ($key == "key"){ + $string .= "\t\t<$key>$value\n"; + } elseif (is_numeric($value)) { + $string .= "\t\t\t<$key>$value\n"; + } elseif (is_string($value)) { + /* We need to escape the value */ + $string .= "\t\t\t<$key>\n"; + } + } + + } // end foreach + + return $string; + break; + default: + foreach ($array as $key => $value) { + // No numeric keys + if (is_numeric($key)) { + $key = 'item'; + } + + if (is_array($value)) { + // Call ourself + $value = xml_from_array($value, true); + $string .= "\t$value\n"; + } + else { + /* We need to escape the value */ + $string .= "\t\n"; + } + // end foreach elements + } + if (!$callback) { + $string = '' . + "\n\n" . $string . "\n"; + } + + // Remove invalid XML characters. + // See http://www.w3.org/TR/2006/REC-xml-20060816/#charsets + $clean = preg_replace('/[^\x{9}\x{a}\x{d}\x{20}-\x{d7ff}\x{e000}-\x{fffd}\x{10000}-\x{10ffff}]|[\x{7f}-\x{84}\x{86}-\x{9f}\x{fdd0}-\x{fddf}\x{1fffe}-\x{1ffff}\x{2fffe}-\x{2ffff}\x{3fffe}-\x{3ffff}\x{4fffe}-\x{4ffff}\x{5fffe}-\x{5ffff}\x{6fffe}-\x{6ffff}\x{7fffe}-\x{7ffff}\x{8fffe}-\x{8ffff}\x{9fffe}-\x{9ffff}\x{afffe}-\x{affff}\x{bfffe}-\x{bffff}\x{cfffe}-\x{cffff}\x{dfffe}-\x{dffff}\x{efffe}-\x{effff}\x{ffffe}-\x{fffff}\x{10fffe}-\x{10ffff}]/u', '', $string); + + if ($clean) { + return $clean; + } + else { + debug_event('xml_from_array', 'Charset cleanup failed, generated XML may be invalid', 1); + return $string; + } + break; + } } // xml_from_array /** @@ -444,38 +444,38 @@ function xml_from_array($array, $callback = false, $type = '') { * This takes the type and returns the correct xml header */ function xml_get_header($type){ - switch ($type){ - case 'itunes': - $header = "\n" . - "\n" . - "\n" . - "\n" . - " Major Version1\n" . - " Minor Version1\n" . - " Application Version7.0.2\n" . - " Features1\n" . - " Show Content Ratings\n" . - " Tracks\n" . - " \n"; - return $header; - break; - case 'xspf': - $header = "\n" . - ""; - "\n ". - "Ampache XSPF Playlist\n" . - "" . Config::get('site_title') . "\n" . - "" . Config::get('site_title') . "\n" . - "". Config::get('web_path') ."\n" . - "\n\n\n\n"; - return $header; - break; - default: - $header = "\n"; - return $header; - break; - } + switch ($type){ + case 'itunes': + $header = "\n" . + "\n" . + "\n" . + "\n" . + " Major Version1\n" . + " Minor Version1\n" . + " Application Version7.0.2\n" . + " Features1\n" . + " Show Content Ratings\n" . + " Tracks\n" . + " \n"; + return $header; + break; + case 'xspf': + $header = "\n" . + ""; + "\n ". + "Ampache XSPF Playlist\n" . + "" . Config::get('site_title') . "\n" . + "" . Config::get('site_title') . "\n" . + "". Config::get('web_path') ."\n" . + "\n\n\n\n"; + return $header; + break; + default: + $header = "\n"; + return $header; + break; + } } //xml_get_header /** @@ -483,22 +483,22 @@ function xml_get_header($type){ * This takes the type and returns the correct xml footer */ function xml_get_footer($type){ - switch ($type){ - case 'itunes': - $footer = " \n" . - "\n" . - "\n"; - return $footer; - break; - case 'xspf': - $footer = " \n" . - "\n"; - return $footer; - break; - default: - - break; - } + switch ($type){ + case 'itunes': + $footer = " \n" . + "\n" . + "\n"; + return $footer; + break; + case 'xspf': + $footer = " \n" . + "\n"; + return $footer; + break; + default: + + break; + } } // xml_get_footer /** @@ -507,9 +507,9 @@ function xml_get_footer($type){ */ function toggle_visible($element) { - echo '\n"; + echo '\n"; } // toggle_visible @@ -520,14 +520,14 @@ function toggle_visible($element) { */ function print_bool($value) { - if ($value) { - $string = '' . T_('On') . ''; - } - else { - $string = '' . T_('Off') . ''; - } + if ($value) { + $string = '' . T_('On') . ''; + } + else { + $string = '' . T_('Off') . ''; + } - return $string; + return $string; } // print_bool @@ -538,12 +538,12 @@ function print_bool($value) { */ function show_now_playing() { - Stream::gc(); - Stream::gc_now_playing(); + Stream::gc(); + Stream::gc_now_playing(); - $web_path = Config::get('web_path'); - $results = Stream::get_now_playing(); - require_once Config::get('prefix') . '/templates/show_now_playing.inc.php'; + $web_path = Config::get('web_path'); + $results = Stream::get_now_playing(); + require_once Config::get('prefix') . '/templates/show_now_playing.inc.php'; } // show_now_playing diff --git a/locale/base/gather-messages.sh b/locale/base/gather-messages.sh index bf7fa7c997..4fc671afd9 100755 --- a/locale/base/gather-messages.sh +++ b/locale/base/gather-messages.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: +# vim:set softtabstop=4 shiftwidth=4 expandtab: # # Copyright 2001 - 2013 Ampache.org # diff --git a/localplay.php b/localplay.php index 3e04a87a60..5aaa48680a 100644 --- a/localplay.php +++ b/localplay.php @@ -1,5 +1,5 @@ get_instance_fields(); - require_once Config::get('prefix') . '/templates/show_localplay_add_instance.inc.php'; - break; - case 'add_instance': - // This requires 50 or better! - if (!Access::check('localplay','75')) { UI::access_denied(); break; } + // Get the current localplay fields + $localplay = new Localplay(Config::get('localplay_controller')); + $fields = $localplay->get_instance_fields(); + require_once Config::get('prefix') . '/templates/show_localplay_add_instance.inc.php'; + break; + case 'add_instance': + // This requires 50 or better! + if (!Access::check('localplay','75')) { UI::access_denied(); break; } - // Setup the object - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->add_instance($_POST); - break; - case 'update_instance': - // Make sure they gots them rights - if (!Access::check('localplay','75')) { UI::access_denied(); break; } - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->update_instance($_REQUEST['instance'],$_POST); - header("Location:" . Config::get('web_path') . "/localplay.php?action=show_instances"); - break; - case 'edit_instance': - // Check to make sure they've got the access - if (!Access::check('localplay','75')) { UI::access_denied(); break; } - $localplay = new Localplay(Config::get('localplay_controller')); - $instance = $localplay->get_instance($_REQUEST['instance']); - $fields = $localplay->get_instance_fields(); - require_once Config::get('prefix') . '/templates/show_localplay_edit_instance.inc.php'; - break; - case 'show_instances': - // First build the localplay object and then get the instances - if (!Access::check('localplay','5')) { UI::access_denied(); break; } - $localplay = new Localplay(Config::get('localplay_controller')); - $instances = $localplay->get_instances(); - $fields = $localplay->get_instance_fields(); - require_once Config::get('prefix') . '/templates/show_localplay_instances.inc.php'; - break; - default: - case 'show_playlist': - if (!Access::check('localplay','5')) { UI::access_denied(); break; } - // Init and then connect to our localplay instance - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); + // Setup the object + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->add_instance($_POST); + break; + case 'update_instance': + // Make sure they gots them rights + if (!Access::check('localplay','75')) { UI::access_denied(); break; } + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->update_instance($_REQUEST['instance'],$_POST); + header("Location:" . Config::get('web_path') . "/localplay.php?action=show_instances"); + break; + case 'edit_instance': + // Check to make sure they've got the access + if (!Access::check('localplay','75')) { UI::access_denied(); break; } + $localplay = new Localplay(Config::get('localplay_controller')); + $instance = $localplay->get_instance($_REQUEST['instance']); + $fields = $localplay->get_instance_fields(); + require_once Config::get('prefix') . '/templates/show_localplay_edit_instance.inc.php'; + break; + case 'show_instances': + // First build the localplay object and then get the instances + if (!Access::check('localplay','5')) { UI::access_denied(); break; } + $localplay = new Localplay(Config::get('localplay_controller')); + $instances = $localplay->get_instances(); + $fields = $localplay->get_instance_fields(); + require_once Config::get('prefix') . '/templates/show_localplay_instances.inc.php'; + break; + default: + case 'show_playlist': + if (!Access::check('localplay','5')) { UI::access_denied(); break; } + // Init and then connect to our localplay instance + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); - // Pull the current playlist and require the template - $objects = $localplay->get(); - require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; - $browse = new Browse(); - $browse->set_type('playlist_localplay'); - $browse->set_static_content(true); - $browse->show_objects($objects); - $browse->store(); - break; + // Pull the current playlist and require the template + $objects = $localplay->get(); + require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; + $browse = new Browse(); + $browse->set_type('playlist_localplay'); + $browse->set_static_content(true); + $browse->show_objects($objects); + $browse->store(); + break; } // end switch action UI::show_footer(); diff --git a/login.php b/login.php index fab31b3284..30ef9d33fb 100644 --- a/login.php +++ b/login.php @@ -1,5 +1,5 @@ disabled) { - $auth['success'] = false; - Error::add('general', T_('User Disabled please contact Admin')); - debug_event('Login', scrub_out($username) . ' is disabled and attempted to login', '1'); - } // if user disabled - elseif (Config::get('prevent_multiple_logins')) { - $session_ip = $user->is_logged_in(); - $current_ip = inet_pton($_SERVER['REMOTE_ADDR']); - if ($current_ip && ($current_ip != $session_ip)) { - $auth['success'] = false; - Error::add('general', T_('User Already Logged in')); - debug_event('Login', scrub_out($username) . ' is already logged in from ' . $session_ip . ' and attempted to login from ' . $current_ip, '1'); - } // if logged in multiple times - } // if prevent multiple logins - elseif (Config::get('auto_create') && $auth['success'] && - ! $user->username) { - /* This is run if we want to autocreate users who don't - exist (useful for non-mysql auth) */ - $access = Config::get('auto_user') - ? User::access_name_to_level(Config::get('auto_user')) - : '5'; - $name = $auth['name']; - $email = $auth['email']; - - /* Attempt to create the user */ - if (User::create($username, $name, $email, - hash('sha256', mt_rand()), $access)) { - $user = User::get_from_username($username); - } - else { - $auth['success'] = false; - Error::add('general', T_('Unable to create local account')); - } - } // End if auto_create - - // This allows stealing passwords validated by external means - // such as LDAP - if (Config::get('auth_password_save') && $auth['success'] && $password) { - $user->update_password($password); - } - } // if we aren't in demo mode + (in_array('http', Config::get('auth_methods')) && + ($_SERVER['REMOTE_USER'] || $_SERVER['HTTP_REMOTE_USER']))) { + + if ($_POST['rememberme']) { + vauth::create_remember_cookie(); + } + + /* If we are in demo mode let's force auth success */ + if (Config::get('demo_mode')) { + $auth['success'] = true; + $auth['info']['username'] = 'Admin - DEMO'; + $auth['info']['fullname'] = 'Administrative User'; + $auth['info']['offset_limit'] = 25; + } + else { + if ($_POST['username'] && $_POST['password']) { + $username = scrub_in($_POST['username']); + $password = $_POST['password']; + } + else { + if ($_SERVER['REMOTE_USER']) { + $username = $_SERVER['REMOTE_USER']; + } + elseif ($_SERVER['HTTP_REMOTE_USER']) { + $username = $_SERVER['HTTP_REMOTE_USER']; + } + $password = ''; + } + + $auth = vauth::authenticate($username, $password); + + if ($auth['success']) { + $username = $auth['username']; + } + else { + debug_event('Login', scrub_out($username) . ' attempted to login and failed', '1'); + Error::add('general', T_('Error Username or Password incorrect, please try again')); + } + + $user = User::get_from_username($username); + + if ($user->disabled) { + $auth['success'] = false; + Error::add('general', T_('User Disabled please contact Admin')); + debug_event('Login', scrub_out($username) . ' is disabled and attempted to login', '1'); + } // if user disabled + elseif (Config::get('prevent_multiple_logins')) { + $session_ip = $user->is_logged_in(); + $current_ip = inet_pton($_SERVER['REMOTE_ADDR']); + if ($current_ip && ($current_ip != $session_ip)) { + $auth['success'] = false; + Error::add('general', T_('User Already Logged in')); + debug_event('Login', scrub_out($username) . ' is already logged in from ' . $session_ip . ' and attempted to login from ' . $current_ip, '1'); + } // if logged in multiple times + } // if prevent multiple logins + elseif (Config::get('auto_create') && $auth['success'] && + ! $user->username) { + /* This is run if we want to autocreate users who don't + exist (useful for non-mysql auth) */ + $access = Config::get('auto_user') + ? User::access_name_to_level(Config::get('auto_user')) + : '5'; + $name = $auth['name']; + $email = $auth['email']; + + /* Attempt to create the user */ + if (User::create($username, $name, $email, + hash('sha256', mt_rand()), $access)) { + $user = User::get_from_username($username); + } + else { + $auth['success'] = false; + Error::add('general', T_('Unable to create local account')); + } + } // End if auto_create + + // This allows stealing passwords validated by external means + // such as LDAP + if (Config::get('auth_password_save') && $auth['success'] && $password) { + $user->update_password($password); + } + } // if we aren't in demo mode } // if they passed a username/password /* If the authentication was a success */ if ($auth['success']) { - // $auth->info are the fields specified in the config file - // to retrieve for each user - vauth::session_create($auth); - - // Not sure if it was me or php tripping out, - // but naming this 'user' didn't work at all - $_SESSION['userdata'] = $auth; - - // Record the IP of this person! - if (Config::get('track_user_ip')) { - $user->insert_ip_history(); - } - - /* Make sure they are actually trying to get to this site and don't try - * to redirect them back into an admin section - */ - $web_path = Config::get('web_path'); - if ((substr($_POST['referrer'], 0, strlen($web_path)) == $web_path) && - strpos($_POST['referrer'], 'install.php') === false && - strpos($_POST['referrer'], 'login.php') === false && - strpos($_POST['referrer'], 'logout.php') === false && - strpos($_POST['referrer'], 'update.php') === false && - strpos($_POST['referrer'], 'activate.php') === false && - strpos($_POST['referrer'], 'admin') === false ) { - - header('Location: ' . $_POST['referrer']); - exit(); - } // if we've got a referrer - header('Location: ' . Config::get('web_path') . '/index.php'); - exit(); + // $auth->info are the fields specified in the config file + // to retrieve for each user + vauth::session_create($auth); + + // Not sure if it was me or php tripping out, + // but naming this 'user' didn't work at all + $_SESSION['userdata'] = $auth; + + // Record the IP of this person! + if (Config::get('track_user_ip')) { + $user->insert_ip_history(); + } + + /* Make sure they are actually trying to get to this site and don't try + * to redirect them back into an admin section + */ + $web_path = Config::get('web_path'); + if ((substr($_POST['referrer'], 0, strlen($web_path)) == $web_path) && + strpos($_POST['referrer'], 'install.php') === false && + strpos($_POST['referrer'], 'login.php') === false && + strpos($_POST['referrer'], 'logout.php') === false && + strpos($_POST['referrer'], 'update.php') === false && + strpos($_POST['referrer'], 'activate.php') === false && + strpos($_POST['referrer'], 'admin') === false ) { + + header('Location: ' . $_POST['referrer']); + exit(); + } // if we've got a referrer + header('Location: ' . Config::get('web_path') . '/index.php'); + exit(); } // auth success require Config::get('prefix') . '/templates/show_login_form.inc.php'; diff --git a/logout.php b/logout.php index 64e4929e03..0599537cf0 100644 --- a/logout.php +++ b/logout.php @@ -1,5 +1,5 @@ email == $email) { - $newpassword = generate_password(6); - $client->update_password($newpassword); + /* get the Client and set the new password */ + $client = User::get_from_email($email); + if ($client->email == $email) { + $newpassword = generate_password(6); + $client->update_password($newpassword); - $mailer = new Ampache_Mail(); - $mailer->set_default_sender(); - $mailer->subject = T_("Lost Password"); - $mailer->recipient_name = $client->fullname; - $mailer->recipient = $client->email; + $mailer = new Ampache_Mail(); + $mailer->set_default_sender(); + $mailer->subject = T_("Lost Password"); + $mailer->recipient_name = $client->fullname; + $mailer->recipient = $client->email; - $message = sprintf(T_("A user from %s has requested a password reset for '%s'."), $current_ip, $client->username); - $message .= "\n"; - $message .= sprintf(T_("The password has been set to: %s"), $newpassword); - $mailer->message = $message; + $message = sprintf(T_("A user from %s has requested a password reset for '%s'."), $current_ip, $client->username); + $message .= "\n"; + $message .= sprintf(T_("The password has been set to: %s"), $newpassword); + $mailer->message = $message; - return $mailer->send(); - } - return false; + return $mailer->send(); + } + return false; } ?> diff --git a/modules/ampacheapi/AmpacheApi.lib.php b/modules/ampacheapi/AmpacheApi.lib.php index a8cb029d66..97fe86d557 100644 --- a/modules/ampacheapi/AmpacheApi.lib.php +++ b/modules/ampacheapi/AmpacheApi.lib.php @@ -1,5 +1,5 @@ debug($config['debug']); - } - - // If we got something, then configure! - if (is_array($config) AND count($config)) { - $this->configure($config); - } - - // If we've been READY'd then go ahead and attempt to connect - if ($this->state() == 'READY') { - $this->connect(); - } - - } // constructor - - /** - * connect - * This attempts to connect to the ampache instance, for now we assume the newer version - */ - public function connect() { - - if ($this->debug) { echo "CONNECT:: Using $this->username / $this->password\n"; } - - // Setup the handshake - $results = array(); - $timestamp = time(); - $key = hash('sha256',$this->password); - $passphrase = hash('sha256',$timestamp . $key); - - $options = array('timestamp'=>$timestamp,'auth'=>$passphrase,'version'=>$this->LIB_version,'user'=>$this->username); - - $response = $this->send_command('handshake',$options); - - $this->parse_response($response); - - // We want the first response - $data = $this->get_response(); - foreach ($data as $value) { - $results = array_merge($results,$value); - } - - if (!$results['auth']) { - $this->set_state('error'); - return false; - } - $this->api_auth = $results['auth']; - $this->set_state('connected'); - // Define when we pulled this, it is not wine, it does - // not get better with age - $this->handshake_time = time(); - $this->handshake = $results; - - } // connect - - /** - * configure - * This function takes an array of elements and configures the AmpaceApi object - * it doesn't really do much more, it is it's own function so we can call it - * from the constructor or directly, if we so desire. - */ - public function configure($config=array()) { - - if ($this->debug) { echo "CONFIGURE :: Checking Passed config options\n"; } - - if (!is_array($config)) { - trigger_error('AmpacheApi::configure received a non-array value'); - return false; - } - - if (isset($config['username'])) { - $this->username = htmlentities($config['username'],ENT_QUOTES,'UTF-8'); - } - if (isset($config['password'])) { - $this->password = htmlentities($config['password'],ENT_QUOTES,'UTF-8'); - } - if (isset($config['server'])) { - // Replace any http:// in the URL with '' - $config['server'] = str_replace('http://','',$config['server']); - $this->server = htmlentities($config['server'],ENT_QUOTES,'UTF-8'); - } - if (isset($config['api_secure'])) { - // This should be a boolean response - $this->api_secure = $config['api_secure'] ? true : false; - } - - // Once we've loaded the config variables we can build some of the final values - $this->api_url = ($this->api_secure ? 'https://' : 'http://') . $this->server . '/server/xml.server.php'; - - // See if we have enough to authenticate, if so change the state - if ($this->username AND $this->password AND $this->server) { - $this->set_state('ready'); - } - - return true; - - } // configure - - /** - * set_state - * This sets the current state of the API, it is used mostly internally but - * the state can be accessed externally so it could be used to check and see - * where the API is at, at this moment - */ - public function set_state($state) { - - // Very simple for now, maybe we'll do something more with this later - $this->api_state = strtoupper($state); - - } // set_state - - /** - * state - * This returns the state of the API - */ - public function state() { - - return $this->api_state; - - } // state - - /** - * info - * Returns the information gathered by the handshake - * not raw so we can formated it if we wanted? - */ - public function info() { - - if ($this->state() != 'CONNECTED') { - throw new Exception('AmpacheApi::info API in non-ready state, unable to return info'); - } - - return $this->handshake; - - } // info - - /** - * send_command - * This sends an API command, with options to the currently connected - * host, and returns a nice clean keyed array - */ - public function send_command($command,$options=array()) { - - if ($this->debug) { echo "SEND COMMAND:: $command"; print_r($options,1); echo "\n"; } - - if ($this->state() != 'READY' AND $this->state() != 'CONNECTED') { - throw new Exception('AmpacheApi::send_command API in non-ready state, unable to send'); - } - if (!trim($command)) { - throw new Exception('AmpacheApi::send_command no command specified'); - } - if (!$this->validate_command($command)) { - throw new Exception('AmpacheApi::send_command Invalid/Unknown command ' . $command . ' issued'); - } - - $url = $this->api_url . '?action=' . urlencode($command); - - foreach ($options as $key=>$value) { - if (!trim($key)) { - // Non fatal don't need to except it - trigger_error('AmpacheApi::send_command unable to append empty variable to command'); - continue; - } - $url .= '&' . urlencode($key) . '=' . urlencode($value); - } - - // IF Auth is set then we append it so you don't have to think about it, also do username - if ($this->api_auth) { - $url .= '&auth=' . urlencode($this->api_auth) . '&username=' . urlencode($this->username); - } - - $data = file_get_contents($url); - return $data; - - } // send_command - - /** - * validate_command - * This takes the specified command, and checks it against the known - * commands for the current version of Ampache. If no version is known yet - * This it will return FALSE for everything except ping and handshake. - */ - public function validate_command($command) { - - return true; - - } // validate_command - - /** - * parse_response - * This takes an XML document and dumps it into $this->results but before - * it does that it will clean up anything that was there before, so I hope - * you've saved! - */ - public function parse_response($response) { - - // Reset the results - $this->XML_results = array(); - $this->XML_position = 0; - - $this->XML_create_parser(); - - if (!xml_parse($this->XML_parser,$response)) { - throw new Exception('AmpacheApi::parse_response was unable to parse XML document'); - } - - xml_parser_free($this->XML_parser); - return true; - - } // parse_response - - /** - * get_response - * This returns the raw response from the last parsed response - */ - public function get_response() { - - return $this->XML_results; - - } // get_response - - /** - * debug - * set debug to true? - */ - private function debug($value) { - - $this->debug = intval($value); - - } // debug - - /////////////////////////// XML PARSER FUNCTIONS ///////////////////////////// - - /** - * XML_create_parser - * This creates the xml parser and sets the options - */ - public function XML_create_parser() { - - $this->XML_parser = xml_parser_create(); - xml_parser_set_option($this->XML_parser,XML_OPTION_CASE_FOLDING,false); - xml_set_object($this->XML_parser,$this); - xml_set_element_handler($this->XML_parser,'XML_start_element','XML_end_element'); - xml_set_character_data_handler($this->XML_parser,'XML_cdata'); - - } // XML_create_parser - - /** - * XML_cdata - * This is called for the content of the XML tag - */ - public function XML_cdata($parser,$cdata) { + // General Settings + private $server; + private $username; + private $password; + private $api_secure; + + // Handshake variables + private $handshake; + private $handshake_time; // Used to figure out how stale our data is + + // Response variables + private $api_session; + + // Constructed variables + private $api_url; + private $api_state='UNCONFIGURED'; + private $api_auth; + + // XML Parser variables + private $XML_currentTag; + private $XML_subTag; + private $XML_parser; + private $XML_results; + private $XML_position=0; + protected $XML_grabtags = array(); + protected $XML_skiptags = array('root'); + protected $XML_parenttags = array('artist','album','song','tag','video','playlist','result', + 'auth','version','update','add','clean','songs', + 'artists','albums','tags','videos','api','playlists','catalogs'); + + // Library static version information + protected $LIB_version = '350001'; + private $API_version = ''; + + private $DEBUG=false; + + /** + * Constructor + * This takes an array of input, if enough information is provided then it will + * attempt to connect to the API right away, otherwise it will simply return an + * object that can be later configured and then connected + */ + public function __construct($config=array()) { + + // See if we are setting debug first + if ($config['debug']) { + $this->debug($config['debug']); + } + + // If we got something, then configure! + if (is_array($config) AND count($config)) { + $this->configure($config); + } + + // If we've been READY'd then go ahead and attempt to connect + if ($this->state() == 'READY') { + $this->connect(); + } + + } // constructor + + /** + * connect + * This attempts to connect to the ampache instance, for now we assume the newer version + */ + public function connect() { + + if ($this->debug) { echo "CONNECT:: Using $this->username / $this->password\n"; } + + // Setup the handshake + $results = array(); + $timestamp = time(); + $key = hash('sha256',$this->password); + $passphrase = hash('sha256',$timestamp . $key); + + $options = array('timestamp'=>$timestamp,'auth'=>$passphrase,'version'=>$this->LIB_version,'user'=>$this->username); + + $response = $this->send_command('handshake',$options); + + $this->parse_response($response); + + // We want the first response + $data = $this->get_response(); + foreach ($data as $value) { + $results = array_merge($results,$value); + } + + if (!$results['auth']) { + $this->set_state('error'); + return false; + } + $this->api_auth = $results['auth']; + $this->set_state('connected'); + // Define when we pulled this, it is not wine, it does + // not get better with age + $this->handshake_time = time(); + $this->handshake = $results; + + } // connect + + /** + * configure + * This function takes an array of elements and configures the AmpaceApi object + * it doesn't really do much more, it is it's own function so we can call it + * from the constructor or directly, if we so desire. + */ + public function configure($config=array()) { + + if ($this->debug) { echo "CONFIGURE :: Checking Passed config options\n"; } + + if (!is_array($config)) { + trigger_error('AmpacheApi::configure received a non-array value'); + return false; + } + + if (isset($config['username'])) { + $this->username = htmlentities($config['username'],ENT_QUOTES,'UTF-8'); + } + if (isset($config['password'])) { + $this->password = htmlentities($config['password'],ENT_QUOTES,'UTF-8'); + } + if (isset($config['server'])) { + // Replace any http:// in the URL with '' + $config['server'] = str_replace('http://','',$config['server']); + $this->server = htmlentities($config['server'],ENT_QUOTES,'UTF-8'); + } + if (isset($config['api_secure'])) { + // This should be a boolean response + $this->api_secure = $config['api_secure'] ? true : false; + } + + // Once we've loaded the config variables we can build some of the final values + $this->api_url = ($this->api_secure ? 'https://' : 'http://') . $this->server . '/server/xml.server.php'; + + // See if we have enough to authenticate, if so change the state + if ($this->username AND $this->password AND $this->server) { + $this->set_state('ready'); + } + + return true; + + } // configure + + /** + * set_state + * This sets the current state of the API, it is used mostly internally but + * the state can be accessed externally so it could be used to check and see + * where the API is at, at this moment + */ + public function set_state($state) { + + // Very simple for now, maybe we'll do something more with this later + $this->api_state = strtoupper($state); + + } // set_state + + /** + * state + * This returns the state of the API + */ + public function state() { + + return $this->api_state; + + } // state + + /** + * info + * Returns the information gathered by the handshake + * not raw so we can formated it if we wanted? + */ + public function info() { + + if ($this->state() != 'CONNECTED') { + throw new Exception('AmpacheApi::info API in non-ready state, unable to return info'); + } + + return $this->handshake; + + } // info + + /** + * send_command + * This sends an API command, with options to the currently connected + * host, and returns a nice clean keyed array + */ + public function send_command($command,$options=array()) { + + if ($this->debug) { echo "SEND COMMAND:: $command"; print_r($options,1); echo "\n"; } + + if ($this->state() != 'READY' AND $this->state() != 'CONNECTED') { + throw new Exception('AmpacheApi::send_command API in non-ready state, unable to send'); + } + if (!trim($command)) { + throw new Exception('AmpacheApi::send_command no command specified'); + } + if (!$this->validate_command($command)) { + throw new Exception('AmpacheApi::send_command Invalid/Unknown command ' . $command . ' issued'); + } + + $url = $this->api_url . '?action=' . urlencode($command); + + foreach ($options as $key=>$value) { + if (!trim($key)) { + // Non fatal don't need to except it + trigger_error('AmpacheApi::send_command unable to append empty variable to command'); + continue; + } + $url .= '&' . urlencode($key) . '=' . urlencode($value); + } + + // IF Auth is set then we append it so you don't have to think about it, also do username + if ($this->api_auth) { + $url .= '&auth=' . urlencode($this->api_auth) . '&username=' . urlencode($this->username); + } + + $data = file_get_contents($url); + return $data; + + } // send_command + + /** + * validate_command + * This takes the specified command, and checks it against the known + * commands for the current version of Ampache. If no version is known yet + * This it will return FALSE for everything except ping and handshake. + */ + public function validate_command($command) { + + return true; + + } // validate_command + + /** + * parse_response + * This takes an XML document and dumps it into $this->results but before + * it does that it will clean up anything that was there before, so I hope + * you've saved! + */ + public function parse_response($response) { + + // Reset the results + $this->XML_results = array(); + $this->XML_position = 0; + + $this->XML_create_parser(); + + if (!xml_parse($this->XML_parser,$response)) { + throw new Exception('AmpacheApi::parse_response was unable to parse XML document'); + } + + xml_parser_free($this->XML_parser); + return true; + + } // parse_response + + /** + * get_response + * This returns the raw response from the last parsed response + */ + public function get_response() { + + return $this->XML_results; + + } // get_response + + /** + * debug + * set debug to true? + */ + private function debug($value) { + + $this->debug = intval($value); + + } // debug + + /////////////////////////// XML PARSER FUNCTIONS ///////////////////////////// + + /** + * XML_create_parser + * This creates the xml parser and sets the options + */ + public function XML_create_parser() { + + $this->XML_parser = xml_parser_create(); + xml_parser_set_option($this->XML_parser,XML_OPTION_CASE_FOLDING,false); + xml_set_object($this->XML_parser,$this); + xml_set_element_handler($this->XML_parser,'XML_start_element','XML_end_element'); + xml_set_character_data_handler($this->XML_parser,'XML_cdata'); + + } // XML_create_parser + + /** + * XML_cdata + * This is called for the content of the XML tag + */ + public function XML_cdata($parser,$cdata) { - $cdata = trim($cdata); + $cdata = trim($cdata); - if (!$this->XML_currentTag || !$cdata) { return false; } + if (!$this->XML_currentTag || !$cdata) { return false; } - if ($this->XML_subTag) { - $this->XML_results[$this->XML_position][$this->XML_currentTag][$this->XML_subTag] = $cdata; - } - else { - $this->XML_results[$this->XML_position][$this->XML_currentTag] = $cdata; - } + if ($this->XML_subTag) { + $this->XML_results[$this->XML_position][$this->XML_currentTag][$this->XML_subTag] = $cdata; + } + else { + $this->XML_results[$this->XML_position][$this->XML_currentTag] = $cdata; + } - } // XML_cdata + } // XML_cdata - public function XML_start_element($parser,$tag,$attributes) { + public function XML_start_element($parser,$tag,$attributes) { - // Skip it! - if (in_array($tag,$this->XML_skiptags)) { return false; } - - if (!in_array($tag,$this->XML_parenttags) OR $this->XML_currentTag) { - $this->XML_subTag = $tag; - } - else { - $this->XML_currentTag = $tag; - } + // Skip it! + if (in_array($tag,$this->XML_skiptags)) { return false; } + + if (!in_array($tag,$this->XML_parenttags) OR $this->XML_currentTag) { + $this->XML_subTag = $tag; + } + else { + $this->XML_currentTag = $tag; + } - if (count($attributes)) { - if (!$this->XML_subTag) { - $this->XML_results[$this->XML_position][$this->XML_currentTag]['self'] = $attributes; - } - else { - $this->XML_results[$this->XML_position][$this->XML_currentTag][$this->XML_subTag]['self'] = $attributes; - } - } + if (count($attributes)) { + if (!$this->XML_subTag) { + $this->XML_results[$this->XML_position][$this->XML_currentTag]['self'] = $attributes; + } + else { + $this->XML_results[$this->XML_position][$this->XML_currentTag][$this->XML_subTag]['self'] = $attributes; + } + } - } // start_element + } // start_element - public function XML_end_element($parser,$tag) { + public function XML_end_element($parser,$tag) { - if ($tag != $this->XML_currentTag) { - $this->XML_subTag = false; - } - else { - $this->XML_currentTag = false; - $this->XML_position++; - } + if ($tag != $this->XML_currentTag) { + $this->XML_subTag = false; + } + else { + $this->XML_currentTag = false; + $this->XML_position++; + } - } // end_element + } // end_element } // end AmpacheApi class ?> diff --git a/modules/httpq/httpqplayer.class.php b/modules/httpq/httpqplayer.class.php index 0251ee76b3..1f061f4220 100644 --- a/modules/httpq/httpqplayer.class.php +++ b/modules/httpq/httpqplayer.class.php @@ -1,5 +1,5 @@ host = $h; - $this->port = $p; - $this->password = $pw; + public $host; + public $port; + public $password; + + /** + * HttpQPlayer + * This is the constructor, it defaults to localhost + * with port 4800 + */ + public function HttpQPlayer($h = "localhost", $pw = "", $p = 4800) { + + $this->host = $h; + $this->port = $p; + $this->password = $pw; - } // HttpQPlayer - - /** - * add - * append a song to the playlist - * $name Name to be shown in the playlist - * $url URL of the song - */ - public function add($name, $url) { - - $args['name'] = urlencode($name); - $args['url'] = urlencode($url); - - $results = $this->sendCommand('playurl', $args); - - if ($results == '0') { $results = null; } + } // HttpQPlayer + + /** + * add + * append a song to the playlist + * $name Name to be shown in the playlist + * $url URL of the song + */ + public function add($name, $url) { + + $args['name'] = urlencode($name); + $args['url'] = urlencode($url); + + $results = $this->sendCommand('playurl', $args); + + if ($results == '0') { $results = null; } - return $results; + return $results; - } // add - - /** - * version - * This gets the version of winamp currently - * running, use this to test for a valid connection - */ - public function version() { + } // add + + /** + * version + * This gets the version of winamp currently + * running, use this to test for a valid connection + */ + public function version() { - $args = array(); - $results = $this->sendCommand('getversion',$args); - - // a return of 0 is a bad value - if ($results == '0') { $results = null; } + $args = array(); + $results = $this->sendCommand('getversion',$args); + + // a return of 0 is a bad value + if ($results == '0') { $results = null; } - return $results; - - } // version + return $results; + + } // version - /** - * clear - * clear the playlist - */ - public function clear() { - $args = array(); - $results = $this->sendCommand("delete", $args); + /** + * clear + * clear the playlist + */ + public function clear() { + $args = array(); + $results = $this->sendCommand("delete", $args); - if ($results == '0') { $results = null; } + if ($results == '0') { $results = null; } - return $results; - - } // clear - - /** - * next - * go to next song - */ - public function next() { + return $results; + + } // clear + + /** + * next + * go to next song + */ + public function next() { - $args = array(); - $results = $this->sendCommand("next", $args); + $args = array(); + $results = $this->sendCommand("next", $args); - if ($results == '0') { return null; } + if ($results == '0') { return null; } - return true; + return true; - } // next + } // next - /** - * prev - * go to previous song - */ - public function prev() { + /** + * prev + * go to previous song + */ + public function prev() { - $args = array(); - $results = $this->sendCommand("prev", $args); + $args = array(); + $results = $this->sendCommand("prev", $args); - if ($results == '0') { return null; } - - return true; + if ($results == '0') { return null; } + + return true; - } // prev + } // prev - /** - * skip - * This skips to POS in the playlist - */ - public function skip($pos) { + /** + * skip + * This skips to POS in the playlist + */ + public function skip($pos) { - $args = array('index'=>$pos); - $results = $this->sendCommand('setplaylistpos',$args); + $args = array('index'=>$pos); + $results = $this->sendCommand('setplaylistpos',$args); - if ($results == '0') { return null; } + if ($results == '0') { return null; } - // Now stop start - $this->stop(); - $this->play(); + // Now stop start + $this->stop(); + $this->play(); - return true; + return true; - } // skip - - /** - * play - * play the current song - */ - public function play() { + } // skip + + /** + * play + * play the current song + */ + public function play() { - $args = array(); - $results = $this->sendCommand("play", $args); + $args = array(); + $results = $this->sendCommand("play", $args); - if ($results == '0') { $results = null; } + if ($results == '0') { $results = null; } - return $results; + return $results; - } // play - - /** - * pause - * toggle pause mode on current song - */ - public function pause() { + } // play + + /** + * pause + * toggle pause mode on current song + */ + public function pause() { - $args = array(); - $results = $this->sendCommand("pause", $args); + $args = array(); + $results = $this->sendCommand("pause", $args); - if ($results == '0') { $results = null; } + if ($results == '0') { $results = null; } - return $results; + return $results; - } // pause - - /** - * stop - * stops the current song amazing! - */ - public function stop() { + } // pause + + /** + * stop + * stops the current song amazing! + */ + public function stop() { - $args = array(); - $results = $this->sendCommand('stop', $args); + $args = array(); + $results = $this->sendCommand('stop', $args); - if ($results == '0') { $results = null; } + if ($results == '0') { $results = null; } - return $results; + return $results; - } // stop + } // stop - /** - * repeat - * This toggles the repeat state of HttpQ - */ - public function repeat($value) { - - $args = array('enable'=>$value); - $results = $this->sendCommand('repeat',$args); - - if ($results == '0') { $results = null; } + /** + * repeat + * This toggles the repeat state of HttpQ + */ + public function repeat($value) { + + $args = array('enable'=>$value); + $results = $this->sendCommand('repeat',$args); + + if ($results == '0') { $results = null; } - return $results; + return $results; - } // repeat + } // repeat - /** - * random - * this toggles the random state of HttpQ - */ - public function random($value) { + /** + * random + * this toggles the random state of HttpQ + */ + public function random($value) { - $args = array('enable'=>$value); - $results = $this->sendCommand('shuffle',$args); + $args = array('enable'=>$value); + $results = $this->sendCommand('shuffle',$args); - if ($results == '0') { $results = null; } + if ($results == '0') { $results = null; } - return $results; + return $results; - } // random + } // random - /** - * delete_pos - * This deletes a specific track - */ - public function delete_pos($track) { - - $args = array('index'=>$track); - $results = $this->sendCommand('deletepos',$args); - - if ($results == '0') { $results = null; } + /** + * delete_pos + * This deletes a specific track + */ + public function delete_pos($track) { + + $args = array('index'=>$track); + $results = $this->sendCommand('deletepos',$args); + + if ($results == '0') { $results = null; } - return $results; + return $results; - } // delete_pos + } // delete_pos - /** - * state - * This returns the current state of the httpQ player - */ - public function state() { + /** + * state + * This returns the current state of the httpQ player + */ + public function state() { - $args = array(); - $results = $this->sendCommand('isplaying',$args); + $args = array(); + $results = $this->sendCommand('isplaying',$args); - if ($results == '1') { $state = 'play'; } - if ($results == '0') { $state = 'stop'; } - if ($results == '3') { $state = 'pause'; } - - return $state; + if ($results == '1') { $state = 'play'; } + if ($results == '0') { $state = 'stop'; } + if ($results == '3') { $state = 'pause'; } + + return $state; - } // state + } // state - /** - * get_volume - * This returns the current volume - */ - public function get_volume() { + /** + * get_volume + * This returns the current volume + */ + public function get_volume() { - $args = array(); - $results = $this->sendCommand('getvolume',$args); + $args = array(); + $results = $this->sendCommand('getvolume',$args); - if ($results == '0') { $results = null; } - else { - /* Need to make this out of 100 */ - $results = round((($results / 255) * 100),2); - } + if ($results == '0') { $results = null; } + else { + /* Need to make this out of 100 */ + $results = round((($results / 255) * 100),2); + } - return $results; + return $results; - } // get_volume + } // get_volume - /** - * volume_up - * This increases the volume by Wimamp's defined amount - */ - public function volume_up() { + /** + * volume_up + * This increases the volume by Wimamp's defined amount + */ + public function volume_up() { - $args = array(); - $results = $this->sendCommand('volumeup',$args); - - if ($results == '0') { return null; } + $args = array(); + $results = $this->sendCommand('volumeup',$args); + + if ($results == '0') { return null; } - return true; + return true; - } // volume_up + } // volume_up - /** - * volume_down - * This decreases the volume by Winamp's defined amount - */ - public function volume_down() { + /** + * volume_down + * This decreases the volume by Winamp's defined amount + */ + public function volume_down() { - $args = array(); - $results = $this->sendCommand('volumedown',$args); - - if ($results == '0') { return null; } + $args = array(); + $results = $this->sendCommand('volumedown',$args); + + if ($results == '0') { return null; } - return true; + return true; - } // volume_down + } // volume_down - /** - * set_volume - * This sets the volume as best it can, we go from a resolution - * of 100 --> 255 so it's a little fuzzy - */ - public function set_volume($value) { + /** + * set_volume + * This sets the volume as best it can, we go from a resolution + * of 100 --> 255 so it's a little fuzzy + */ + public function set_volume($value) { - // Convert it to base 255 - $value = $value*2.55; - $args = array('level'=>$value); - $results = $this->sendCommand('setvolume',$args); + // Convert it to base 255 + $value = $value*2.55; + $args = array('level'=>$value); + $results = $this->sendCommand('setvolume',$args); - if ($results == '0') { return null; } + if ($results == '0') { return null; } - return true; + return true; - } // set_volume + } // set_volume - /** - * clear_playlist - * this flushes the playlist cache (I hope this means clear) - */ - public function clear_playlist() { + /** + * clear_playlist + * this flushes the playlist cache (I hope this means clear) + */ + public function clear_playlist() { - $args = array(); - $results = $this->sendcommand('flushplaylist',$args); - - if ($results == '0') { return null; } + $args = array(); + $results = $this->sendcommand('flushplaylist',$args); + + if ($results == '0') { return null; } - return true; + return true; - } // clear_playlist + } // clear_playlist - /** - * get_repeat - * This returns the current state of the repeat - */ - public function get_repeat() { + /** + * get_repeat + * This returns the current state of the repeat + */ + public function get_repeat() { - $args = array(); - $results = $this->sendCommand('repeat_status',$args); + $args = array(); + $results = $this->sendCommand('repeat_status',$args); - return $results; - - } // get_repeat + return $results; + + } // get_repeat - /** - * get_random - * This returns the current state of shuffle - */ - public function get_random() { - - $args = array(); - $results = $this->sendCommand('shuffle_status',$args); - - return $results; + /** + * get_random + * This returns the current state of shuffle + */ + public function get_random() { + + $args = array(); + $results = $this->sendCommand('shuffle_status',$args); + + return $results; - } // get_random + } // get_random - /** - * get_now_playing - * This returns the file information for the currently - * playing song - */ - public function get_now_playing() { + /** + * get_now_playing + * This returns the file information for the currently + * playing song + */ + public function get_now_playing() { - // First get the current POS - $pos = $this->sendCommand('getlistpos',array()); - - // Now get the filename - $file = $this->sendCommand('getplaylistfile',array('index'=>$pos)); - - return $file; + // First get the current POS + $pos = $this->sendCommand('getlistpos',array()); + + // Now get the filename + $file = $this->sendCommand('getplaylistfile',array('index'=>$pos)); + + return $file; - } // get_now_playing + } // get_now_playing - /** - * get_tracks - * This returns a delimiated string of all of the filenames - * current in your playlist - */ - public function get_tracks() { + /** + * get_tracks + * This returns a delimiated string of all of the filenames + * current in your playlist + */ + public function get_tracks() { - // Pull a delimited list of all tracks - $results = $this->sendCommand('getplaylistfile',array('delim'=>'::')); - - if ($results == '0') { $results = null; } - - return $results; + // Pull a delimited list of all tracks + $results = $this->sendCommand('getplaylistfile',array('delim'=>'::')); + + if ($results == '0') { $results = null; } + + return $results; - } // get_tracks - - /** - * sendCommand - * This is the core of this library it takes care of sending the HTTP - * request to the HttpQ server and getting the response - */ - private function sendCommand($cmd, $args) { - - $fp = fsockopen($this->host, $this->port, $errno, $errstr); - - if(!$fp) { - debug_event('httpq',"HttpQPlayer: $errstr ($errno)",'1'); - return null; - } + } // get_tracks + + /** + * sendCommand + * This is the core of this library it takes care of sending the HTTP + * request to the HttpQ server and getting the response + */ + private function sendCommand($cmd, $args) { + + $fp = fsockopen($this->host, $this->port, $errno, $errstr); + + if(!$fp) { + debug_event('httpq',"HttpQPlayer: $errstr ($errno)",'1'); + return null; + } - // Define the base message - $msg = "GET /$cmd?p=$this->password"; + // Define the base message + $msg = "GET /$cmd?p=$this->password"; - // Foreach our arguments - foreach ($args AS $key => $val) { - $msg = $msg . "&$key=$val"; - } + // Foreach our arguments + foreach ($args AS $key => $val) { + $msg = $msg . "&$key=$val"; + } - $msg = $msg . " HTTP/1.0\r\n\r\n"; - fputs($fp, $msg); - $data = ''; - - while(!feof($fp)) { - $data .= fgets($fp); - } - fclose($fp); - - // Explode the results by line break and take 4th line (results) - $data = explode("\n",$data); - - $result = $data['4']; - - return $result; - - } // sendCommand + $msg = $msg . " HTTP/1.0\r\n\r\n"; + fputs($fp, $msg); + $data = ''; + + while(!feof($fp)) { + $data .= fgets($fp); + } + fclose($fp); + + // Explode the results by line break and take 4th line (results) + $data = explode("\n",$data); + + $result = $data['4']; + + return $result; + + } // sendCommand } // End HttpQPlayer Class ?> diff --git a/modules/localplay/httpq.controller.php b/modules/localplay/httpq.controller.php index 6cad04c4e0..63d4e6deb3 100644 --- a/modules/localplay/httpq.controller.php +++ b/modules/localplay/httpq.controller.php @@ -1,5 +1,5 @@ description; + return $this->description; - } // get_description + } // get_description - /** - * get_version - * This returns the current version - */ - public function get_version() { + /** + * get_version + * This returns the current version + */ + public function get_version() { - return $this->version; + return $this->version; - } // get_version + } // get_version /** * is_installed @@ -75,10 +75,10 @@ public function get_version() { */ public function is_installed() { - $sql = "DESCRIBE `localplay_httpq`"; - $db_results = Dba::read($sql); + $sql = "DESCRIBE `localplay_httpq`"; + $db_results = Dba::read($sql); - return Dba::num_rows($db_results); + return Dba::num_rows($db_results); } // is_installed @@ -89,21 +89,21 @@ public function is_installed() { */ public function install() { - $sql = "CREATE TABLE `localplay_httpq` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , ". - "`name` VARCHAR( 128 ) COLLATE utf8_unicode_ci NOT NULL , " . - "`owner` INT( 11 ) NOT NULL, " . - "`host` VARCHAR( 255 ) COLLATE utf8_unicode_ci NOT NULL , " . - "`port` INT( 11 ) UNSIGNED NOT NULL , " . - "`password` VARCHAR( 255 ) COLLATE utf8_unicode_ci NOT NULL , " . - "`access` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '0'" . - ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; - $db_results = Dba::write($sql); + $sql = "CREATE TABLE `localplay_httpq` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , ". + "`name` VARCHAR( 128 ) COLLATE utf8_unicode_ci NOT NULL , " . + "`owner` INT( 11 ) NOT NULL, " . + "`host` VARCHAR( 255 ) COLLATE utf8_unicode_ci NOT NULL , " . + "`port` INT( 11 ) UNSIGNED NOT NULL , " . + "`password` VARCHAR( 255 ) COLLATE utf8_unicode_ci NOT NULL , " . + "`access` SMALLINT( 4 ) UNSIGNED NOT NULL DEFAULT '0'" . + ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; + $db_results = Dba::write($sql); - // Add an internal preference for the users current active instance - Preference::insert('httpq_active','HTTPQ Active Instance','0','25','integer','internal'); - User::rebuild_all_preferences(); + // Add an internal preference for the users current active instance + Preference::insert('httpq_active','HTTPQ Active Instance','0','25','integer','internal'); + User::rebuild_all_preferences(); - return true; + return true; } // install @@ -113,13 +113,13 @@ public function install() { */ public function uninstall() { - $sql = "DROP TABLE `localplay_httpq`"; - $db_results = Dba::write($sql); + $sql = "DROP TABLE `localplay_httpq`"; + $db_results = Dba::write($sql); - // Remove the pref we added for this - Preference::delete('httpq_active'); + // Remove the pref we added for this + Preference::delete('httpq_active'); - return true; + return true; } // uninstall @@ -129,18 +129,18 @@ public function uninstall() { */ public function add_instance($data) { - $name = Dba::escape($data['name']); - $host = Dba::escape($data['host']); - $port = Dba::escape($data['port']); - $password = Dba::escape($data['password']); - $user_id = Dba::escape($GLOBALS['user']->id); + $name = Dba::escape($data['name']); + $host = Dba::escape($data['host']); + $port = Dba::escape($data['port']); + $password = Dba::escape($data['password']); + $user_id = Dba::escape($GLOBALS['user']->id); - $sql = "INSERT INTO `localplay_httpq` (`name`,`host`,`port`,`password`,`owner`) " . - "VALUES ('$name','$host','$port','$password','$user_id')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `localplay_httpq` (`name`,`host`,`port`,`password`,`owner`) " . + "VALUES ('$name','$host','$port','$password','$user_id')"; + $db_results = Dba::write($sql); - return $db_results; + return $db_results; } // add_instance @@ -150,12 +150,12 @@ public function add_instance($data) { */ public function delete_instance($uid) { - $uid = Dba::escape($uid); + $uid = Dba::escape($uid); - $sql = "DELETE FROM `localplay_httpq` WHERE `id`='$uid'"; - $db_results = Dba::write($sql); + $sql = "DELETE FROM `localplay_httpq` WHERE `id`='$uid'"; + $db_results = Dba::write($sql); - return true; + return true; } // delete_instance @@ -166,16 +166,16 @@ public function delete_instance($uid) { */ public function get_instances() { - $sql = "SELECT * FROM `localplay_httpq` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `localplay_httpq` ORDER BY `name`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[$row['id']] = $row['name']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[$row['id']] = $row['name']; + } - return $results; + return $results; } // get_instances @@ -185,16 +185,16 @@ public function get_instances() { */ public function update_instance($uid, $data) { - $uid = Dba::escape($uid); - $port = Dba::escape($data['port']); - $host = Dba::escape($data['host']); - $name = Dba::escape($data['name']); - $pass = Dba::escape($data['password']); + $uid = Dba::escape($uid); + $port = Dba::escape($data['port']); + $host = Dba::escape($data['host']); + $name = Dba::escape($data['name']); + $pass = Dba::escape($data['password']); - $sql = "UPDATE `localplay_httpq` SET `host`='$host', `port`='$port', `name`='$name', `password`='$pass' WHERE `id`='$uid'"; - $db_results = Dba::write($sql); + $sql = "UPDATE `localplay_httpq` SET `host`='$host', `port`='$port', `name`='$name', `password`='$pass' WHERE `id`='$uid'"; + $db_results = Dba::write($sql); - return true; + return true; } // update_instance @@ -210,25 +210,25 @@ public function instance_fields() { $fields['port'] = array('description' => T_('Port'),'type'=>'textbox'); $fields['password'] = array('description' => T_('Password'),'type'=>'textbox'); - return $fields; + return $fields; - } // instance_fields + } // instance_fields - /** - * get_instance - * This returns a single instance and all its variables - */ - public function get_instance($instance='') { + /** + * get_instance + * This returns a single instance and all its variables + */ + public function get_instance($instance='') { - $instance = $instance ? $instance : Config::get('httpq_active'); - $instance = Dba::escape($instance); + $instance = $instance ? $instance : Config::get('httpq_active'); + $instance = Dba::escape($instance); - $sql = "SELECT * FROM `localplay_httpq` WHERE `id`='$instance'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `localplay_httpq` WHERE `id`='$instance'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - return $row; + return $row; } // get_instance @@ -238,17 +238,17 @@ public function get_instance($instance='') { */ public function set_active_instance($uid,$user_id='') { - // Not an admin? bubkiss! - if (!$GLOBALS['user']->has_access('100')) { - $user_id = $GLOBALS['user']->id; - } + // Not an admin? bubkiss! + if (!$GLOBALS['user']->has_access('100')) { + $user_id = $GLOBALS['user']->id; + } - $user_id = $user_id ? $user_id : $GLOBALS['user']->id; + $user_id = $user_id ? $user_id : $GLOBALS['user']->id; - Preference::update('httpq_active',$user_id,intval($uid)); - Config::set('httpq_active', intval($uid), true); + Preference::update('httpq_active',$user_id,intval($uid)); + Config::set('httpq_active', intval($uid), true); - return true; + return true; } // set_active_instance @@ -262,147 +262,147 @@ public function get_active_instance() { } // get_active_instance - /** - * add_url - * This is the new hotness - */ - public function add_url(Stream_URL $url) { - if (is_null($this->_httpq->add($url->title, $url->url))) { - debug_event('httpq', 'add_url failed to add ' . $url, 1); - return false; - } - - return true; - } + /** + * add_url + * This is the new hotness + */ + public function add_url(Stream_URL $url) { + if (is_null($this->_httpq->add($url->title, $url->url))) { + debug_event('httpq', 'add_url failed to add ' . $url, 1); + return false; + } + + return true; + } - /** - * delete_track - * This must take an ID (as returned by our get function) - * and delete it from httpQ - */ - public function delete_track($object_id) { + /** + * delete_track + * This must take an ID (as returned by our get function) + * and delete it from httpQ + */ + public function delete_track($object_id) { - if (is_null($this->_httpq->delete_pos($object_id))) { - debug_event('httpq', 'Unable to delete ' . $object_id . ' from httpQ', 1); - return false; - } + if (is_null($this->_httpq->delete_pos($object_id))) { + debug_event('httpq', 'Unable to delete ' . $object_id . ' from httpQ', 1); + return false; + } - return true; + return true; - } // delete_track + } // delete_track - /** - * clear_playlist - */ - public function clear_playlist() { + /** + * clear_playlist + */ + public function clear_playlist() { - if (is_null($this->_httpq->clear())) { return false; } + if (is_null($this->_httpq->clear())) { return false; } - // If the clear worked we should stop it! - $this->stop(); + // If the clear worked we should stop it! + $this->stop(); - return true; + return true; - } // clear_playlist + } // clear_playlist - /** - * play - * This just tells httpQ to start playing, it does not - * take any arguments - */ - public function play() { - // A play when it's already playing causes a track restart, - // so doublecheck its state - if ($this->_httpq->state() == 'play') { - return true; - } + /** + * play + * This just tells httpQ to start playing, it does not + * take any arguments + */ + public function play() { + // A play when it's already playing causes a track restart, + // so doublecheck its state + if ($this->_httpq->state() == 'play') { + return true; + } - if (is_null($this->_httpq->play())) { return false; } - return true; - } // play + if (is_null($this->_httpq->play())) { return false; } + return true; + } // play - /** - * stop - * This just tells httpQ to stop playing, it does not take - * any arguments - */ - public function stop() { + /** + * stop + * This just tells httpQ to stop playing, it does not take + * any arguments + */ + public function stop() { - if (is_null($this->_httpq->stop())) { return false; } - return true; + if (is_null($this->_httpq->stop())) { return false; } + return true; - } // stop + } // stop - /** - * skip - * This tells httpQ to skip to the specified song - */ - public function skip($song) { + /** + * skip + * This tells httpQ to skip to the specified song + */ + public function skip($song) { - if (is_null($this->_httpq->skip($song))) { return false; } - return true; + if (is_null($this->_httpq->skip($song))) { return false; } + return true; - } // skip + } // skip - /** - * This tells Httpq to increase the volume by WinAmps default amount - */ - public function volume_up() { + /** + * This tells Httpq to increase the volume by WinAmps default amount + */ + public function volume_up() { - if (is_null($this->_httpq->volume_up())) { return false; } - return true; + if (is_null($this->_httpq->volume_up())) { return false; } + return true; - } // volume_up + } // volume_up - /** - * This tells httpQ to decrease the volume by Winamp's default amount - */ - public function volume_down() { + /** + * This tells httpQ to decrease the volume by Winamp's default amount + */ + public function volume_down() { - if (is_null($this->_httpq->volume_down())) { return false; } - return true; + if (is_null($this->_httpq->volume_down())) { return false; } + return true; - } // volume_down + } // volume_down - /** - * next - * This just tells httpQ to skip to the next song - */ - public function next() { + /** + * next + * This just tells httpQ to skip to the next song + */ + public function next() { - if (is_null($this->_httpq->next())) { return false; } + if (is_null($this->_httpq->next())) { return false; } - return true; + return true; - } // next + } // next - /** - * prev - * This just tells httpQ to skip to the prev song - */ - public function prev() { + /** + * prev + * This just tells httpQ to skip to the prev song + */ + public function prev() { - if (is_null($this->_httpq->prev())) { return false; } + if (is_null($this->_httpq->prev())) { return false; } - return true; + return true; - } // prev + } // prev - /** - * pause - * This tells httpQ to pause the current song - */ - public function pause() { + /** + * pause + * This tells httpQ to pause the current song + */ + public function pause() { - if (is_null($this->_httpq->pause())) { return false; } - return true; + if (is_null($this->_httpq->pause())) { return false; } + return true; - } // pause + } // pause /** * volume * This tells httpQ to set the volume to the specified amount this - * is 0-100 + * is 0-100 */ public function volume($volume) { @@ -414,19 +414,19 @@ public function volume($volume) { /** * repeat * This tells httpQ to set the repeating the playlist (i.e. loop) to - * either on or off + * either on or off */ public function repeat($state) { - if (is_null($this->_httpq->repeat($state))) { return false; } - return true; + if (is_null($this->_httpq->repeat($state))) { return false; } + return true; } // repeat /** * random * This tells httpQ to turn on or off the playing of songs from the - * playlist in random order + * playlist in random order */ public function random($onoff) { @@ -435,29 +435,29 @@ public function random($onoff) { } // random - /** - * get - * This functions returns an array containing information about - * The songs that httpQ currently has in its playlist. This must be - * done in a standardized fashion - */ - public function get() { + /** + * get + * This functions returns an array containing information about + * The songs that httpQ currently has in its playlist. This must be + * done in a standardized fashion + */ + public function get() { - /* Get the Current Playlist */ - $list = $this->_httpq->get_tracks(); + /* Get the Current Playlist */ + $list = $this->_httpq->get_tracks(); - if (!$list) { return array(); } + if (!$list) { return array(); } - $songs = explode("::",$list); + $songs = explode("::",$list); - foreach ($songs as $key=>$entry) { - $data = array(); + foreach ($songs as $key=>$entry) { + $data = array(); - /* Required Elements */ - $data['id'] = $key; - $data['raw'] = $entry; + /* Required Elements */ + $data['id'] = $key; + $data['raw'] = $entry; - $url_data = $this->parse_url($entry); + $url_data = $this->parse_url($entry); switch ($url_data['primary_key']) { case 'oid': $song = new Song($url_data['oid']); @@ -470,10 +470,10 @@ public function get() { $data['name'] = T_('Democratic') . ' - ' . $democratic->name; $data['link'] = ''; break; - case 'random': - $data['name'] = T_('Random') . ' - ' . scrub_out(ucfirst($url_data['type'])); - $data['link'] = ''; - break; + case 'random': + $data['name'] = T_('Random') . ' - ' . scrub_out(ucfirst($url_data['type'])); + $data['link'] = ''; + break; default: /* If we don't know it, look up by filename */ $filename = Dba::escape($entry['file']); @@ -498,70 +498,70 @@ public function get() { break; } // end switch on type } // end if results - else { - $data['name'] = basename($data['raw']); - $data['link'] = basename($data['raw']); - } + else { + $data['name'] = basename($data['raw']); + $data['link'] = basename($data['raw']); + } break; } // end switch on primary key type - $data['track'] = $key+1; + $data['track'] = $key+1; - $results[] = $data; + $results[] = $data; - } // foreach playlist items + } // foreach playlist items - return $results; + return $results; - } // get + } // get - /** - * status - * This returns bool/int values for features, loop, repeat and any other features - * That this localplay method supports. required function - */ - public function status() { + /** + * status + * This returns bool/int values for features, loop, repeat and any other features + * That this localplay method supports. required function + */ + public function status() { - /* Construct the Array */ - $array['state'] = $this->_httpq->state(); - $array['volume'] = $this->_httpq->get_volume(); - $array['repeat'] = $this->_httpq->get_repeat(); - $array['random'] = $this->_httpq->get_random(); - $array['track'] = $this->_httpq->get_now_playing(); - $url_data = $this->parse_url($array['track']); + /* Construct the Array */ + $array['state'] = $this->_httpq->state(); + $array['volume'] = $this->_httpq->get_volume(); + $array['repeat'] = $this->_httpq->get_repeat(); + $array['random'] = $this->_httpq->get_random(); + $array['track'] = $this->_httpq->get_now_playing(); + $url_data = $this->parse_url($array['track']); - if (isset($url_data['oid'])) { - $song = new Song($url_data['oid']); - $array['track_title'] = $song->title; - $array['track_artist'] = $song->get_artist_name(); - $array['track_album'] = $song->get_album_name(); - } - else { - $array['track_title'] = basename($array['track']); - } + if (isset($url_data['oid'])) { + $song = new Song($url_data['oid']); + $array['track_title'] = $song->title; + $array['track_artist'] = $song->get_artist_name(); + $array['track_album'] = $song->get_album_name(); + } + else { + $array['track_title'] = basename($array['track']); + } - return $array; + return $array; - } // status + } // status - /** - * connect - * This functions creates the connection to httpQ and returns - * a boolean value for the status, to save time this handle - * is stored in this class - */ - public function connect() { + /** + * connect + * This functions creates the connection to httpQ and returns + * a boolean value for the status, to save time this handle + * is stored in this class + */ + public function connect() { - $options = self::get_instance(); - $this->_httpq = new HttpQPlayer($options['host'],$options['password'],$options['port']); + $options = self::get_instance(); + $this->_httpq = new HttpQPlayer($options['host'],$options['password'],$options['port']); - // Test our connection by retriving the version - if (!is_null($this->_httpq->version())) { return true; } + // Test our connection by retriving the version + if (!is_null($this->_httpq->version())) { return true; } - return false; + return false; - } // connect + } // connect } //end of AmpacheHttpq diff --git a/modules/localplay/mpd.controller.php b/modules/localplay/mpd.controller.php index 0fcacc6057..3949697dc2 100644 --- a/modules/localplay/mpd.controller.php +++ b/modules/localplay/mpd.controller.php @@ -1,5 +1,5 @@ description; + return $this->description; - } // get_description + } // get_description - /** - * get_version - * This returns the version information - */ - public function get_version() { + /** + * get_version + * This returns the version information + */ + public function get_version() { - return $this->version; + return $this->version; - } // get_version + } // get_version - /** - * is_installed - * This returns true or false if MPD controller is installed - */ - public function is_installed() { + /** + * is_installed + * This returns true or false if MPD controller is installed + */ + public function is_installed() { $sql = "DESCRIBE `localplay_mpd`"; $db_results = Dba::read($sql); return Dba::num_rows($db_results); - } // is_installed + } // is_installed - /** - * install - * This function installs the MPD localplay controller - */ - public function install() { + /** + * install + * This function installs the MPD localplay controller + */ + public function install() { /* We need to create the MPD table */ $sql = "CREATE TABLE `localplay_mpd` ( `id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , " . @@ -100,312 +100,312 @@ public function install() { ") ENGINE = MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci"; $db_results = Dba::write($sql); - // Add an internal preference for the users current active instance - Preference::insert('mpd_active','MPD Active Instance','0','25','integer','internal'); - User::rebuild_all_preferences(); + // Add an internal preference for the users current active instance + Preference::insert('mpd_active','MPD Active Instance','0','25','integer','internal'); + User::rebuild_all_preferences(); return true; - } // install + } // install - /** - * uninstall - * This removes the localplay controller - */ - public function uninstall() { + /** + * uninstall + * This removes the localplay controller + */ + public function uninstall() { $sql = "DROP TABLE `localplay_mpd`"; $db_results = Dba::write($sql); - Preference::delete('mpd_active'); + Preference::delete('mpd_active'); return true; - } // uninstall + } // uninstall - /** - * add_instance - * This takes key'd data and inserts a new MPD instance - */ - public function add_instance($data) { + /** + * add_instance + * This takes key'd data and inserts a new MPD instance + */ + public function add_instance($data) { - foreach ($data as $key=>$value) { - switch ($key) { - case 'name': - case 'host': - case 'port': - case 'password': - ${$key} = Dba::escape($value); - break; - default: + foreach ($data as $key=>$value) { + switch ($key) { + case 'name': + case 'host': + case 'port': + case 'password': + ${$key} = Dba::escape($value); + break; + default: - break; - } // end switch - } // end foreach + break; + } // end switch + } // end foreach - $user_id = Dba::escape($GLOBALS['user']->id); + $user_id = Dba::escape($GLOBALS['user']->id); - $sql = "INSERT INTO `localplay_mpd` (`name`,`host`,`port`,`password`,`owner`) " . - "VALUES ('$name','$host','$port','$password','$user_id')"; - $db_results = Dba::write($sql); + $sql = "INSERT INTO `localplay_mpd` (`name`,`host`,`port`,`password`,`owner`) " . + "VALUES ('$name','$host','$port','$password','$user_id')"; + $db_results = Dba::write($sql); - return $db_results; + return $db_results; - } // add_instance + } // add_instance - /** - * delete_instance - * This takes a UID and deletes the instance in question - */ - public function delete_instance($uid) { + /** + * delete_instance + * This takes a UID and deletes the instance in question + */ + public function delete_instance($uid) { - $uid = Dba::escape($uid); + $uid = Dba::escape($uid); - // Go ahead and delete this mofo! - $sql = "DELETE FROM `localplay_mpd` WHERE `id`='$uid'"; - $db_results = Dba::write($sql); + // Go ahead and delete this mofo! + $sql = "DELETE FROM `localplay_mpd` WHERE `id`='$uid'"; + $db_results = Dba::write($sql); - return true; + return true; - } // delete_instance + } // delete_instance - /** - * get_instances - * This returns a key'd array of the instance information with - * [UID]=>[NAME] - */ - public function get_instances() { + /** + * get_instances + * This returns a key'd array of the instance information with + * [UID]=>[NAME] + */ + public function get_instances() { - $sql = "SELECT * FROM `localplay_mpd` ORDER BY `name`"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `localplay_mpd` ORDER BY `name`"; + $db_results = Dba::read($sql); - $results = array(); + $results = array(); - while ($row = Dba::fetch_assoc($db_results)) { - $results[$row['id']] = $row['name']; - } + while ($row = Dba::fetch_assoc($db_results)) { + $results[$row['id']] = $row['name']; + } - return $results; + return $results; - } // get_instances + } // get_instances - /** - * get_instance - * This returns the specified instance and all it's pretty variables - * If no instance is passed current is used - */ - public function get_instance($instance='') { + /** + * get_instance + * This returns the specified instance and all it's pretty variables + * If no instance is passed current is used + */ + public function get_instance($instance='') { - $instance = $instance ? $instance : Config::get('mpd_active'); - $instance = Dba::escape($instance); + $instance = $instance ? $instance : Config::get('mpd_active'); + $instance = Dba::escape($instance); - $sql = "SELECT * FROM `localplay_mpd` WHERE `id`='$instance'"; - $db_results = Dba::read($sql); + $sql = "SELECT * FROM `localplay_mpd` WHERE `id`='$instance'"; + $db_results = Dba::read($sql); - $row = Dba::fetch_assoc($db_results); + $row = Dba::fetch_assoc($db_results); - return $row; + return $row; - } // get_instance + } // get_instance - /** - * update_instance - * This takes an ID and an array of data and updates the instance specified - */ - public function update_instance($uid,$data) { + /** + * update_instance + * This takes an ID and an array of data and updates the instance specified + */ + public function update_instance($uid,$data) { - $uid = Dba::escape($uid); - $host = $data['host'] ? Dba::escape($data['host']) : '127.0.0.1'; - $port = $data['port'] ? Dba::escape($data['port']) : '6600'; - $name = Dba::escape($data['name']); - $pass = Dba::escape($data['password']); - - $sql = "UPDATE `localplay_mpd` SET `host`='$host', `port`='$port', `name`='$name', `password`='$pass' WHERE `id`='$uid'"; - $db_results = Dba::write($sql); - - return true; - - } // update_instance - - /** - * instance_fields - * This returns a key'd array of [NAME]=>array([DESCRIPTION]=>VALUE,[TYPE]=>VALUE) for the - * fields so that we can on-the-fly generate a form - */ - public function instance_fields() { - - $fields['name'] = array('description' => T_('Instance Name'),'type'=>'textbox'); - $fields['host'] = array('description' => T_('Hostname'),'type'=>'textbox'); - $fields['port'] = array('description' => T_('Port'),'type'=>'textbox'); - $fields['password'] = array('description' => T_('Password'),'type'=>'textbox'); - - return $fields; - - } // instance_fields - - /** - * set_active_instance - * This sets the specified instance as the 'active' one - */ - public function set_active_instance($uid,$user_id='') { - - // Not an admin? bubkiss! - if (!$GLOBALS['user']->has_access('100')) { - $user_id = $GLOBALS['user']->id; - } - - $user_id = $user_id ? $user_id : $GLOBALS['user']->id; - - Preference::update('mpd_active',$user_id,intval($uid)); - Config::set('mpd_active', intval($uid), true); - - return true; - - } // set_active_instance - - /** - * get_active_instance - * This returns the UID of the current active instance - * false if none are active - */ - public function get_active_instance() { - - - } // get_active_instance - - /** - * add_url - * This is the new hotness - */ - public function add_url(Stream_URL $url) { - // If we haven't added anything then maybe we should clear the - // playlist. - if ($this->_add_count < 1) { - $this->_mpd->RefreshInfo(); - if ($this->_mpd->status['state'] == mpd::STATE_STOPPED) { - $this->clear_playlist(); - } - } - - if (!$this->_mpd->PlAdd($url->url)) { - debug_event('mpd', 'add_url failed to add: ' . json_encode($url), 1); - return false; - } - - $this->_add_count++; - return true; - } - - /** - * delete_track - * This must take a single ID (as returned by the get function) - * and delete it from the current playlist - */ - public function delete_track($object_id) { - return $this->_mpd->PLRemove($object_id); - } // delete_track - - /** - * clear_playlist - * This deletes the entire MPD playlist... nuff said - */ - public function clear_playlist() { - return $this->_mpd->PLClear(); - } // clear_playlist - - /** - * play - * This just tells MPD to start playing, it does not - * take any arguments - */ - public function play() { - return $this->_mpd->Play(); - } // play - - /** - * stop - * This just tells MPD to stop playing, it does not take - * any arguments - */ - public function stop() { - return $this->_mpd->Stop(); - } // stop - - /** - * skip - * This tells MPD to skip to the specified song - */ - public function skip($song) { - - if (!$this->_mpd->SkipTo($song)) { return false; } - sleep(2); - $this->stop(); - sleep(2); - $this->play(); - return true; - - } // skip - - /** - * This tells MPD to increase the volume by 5 - */ - public function volume_up() { - return $this->_mpd->AdjustVolume('5'); - } // volume_up - - /** - * This tells MPD to decrease the volume by 5 - */ - public function volume_down() { - return $this->_mpd->AdjustVolume('-5'); - } // volume_down - - /** - * next - * This just tells MPD to skip to the next song - */ - public function next() { - return $this->_mpd->Next(); - } // next - - /** - * prev - * This just tells MPD to skip to the prev song - */ - public function prev() { - return $this->_mpd->Previous(); - } // prev - - /** - * pause - * This tells MPD to pause the current song - */ - public function pause() { - return $this->_mpd->Pause(); - } // pause + $uid = Dba::escape($uid); + $host = $data['host'] ? Dba::escape($data['host']) : '127.0.0.1'; + $port = $data['port'] ? Dba::escape($data['port']) : '6600'; + $name = Dba::escape($data['name']); + $pass = Dba::escape($data['password']); + + $sql = "UPDATE `localplay_mpd` SET `host`='$host', `port`='$port', `name`='$name', `password`='$pass' WHERE `id`='$uid'"; + $db_results = Dba::write($sql); + + return true; + + } // update_instance + + /** + * instance_fields + * This returns a key'd array of [NAME]=>array([DESCRIPTION]=>VALUE,[TYPE]=>VALUE) for the + * fields so that we can on-the-fly generate a form + */ + public function instance_fields() { + + $fields['name'] = array('description' => T_('Instance Name'),'type'=>'textbox'); + $fields['host'] = array('description' => T_('Hostname'),'type'=>'textbox'); + $fields['port'] = array('description' => T_('Port'),'type'=>'textbox'); + $fields['password'] = array('description' => T_('Password'),'type'=>'textbox'); + + return $fields; + + } // instance_fields + + /** + * set_active_instance + * This sets the specified instance as the 'active' one + */ + public function set_active_instance($uid,$user_id='') { + + // Not an admin? bubkiss! + if (!$GLOBALS['user']->has_access('100')) { + $user_id = $GLOBALS['user']->id; + } + + $user_id = $user_id ? $user_id : $GLOBALS['user']->id; + + Preference::update('mpd_active',$user_id,intval($uid)); + Config::set('mpd_active', intval($uid), true); + + return true; + + } // set_active_instance + + /** + * get_active_instance + * This returns the UID of the current active instance + * false if none are active + */ + public function get_active_instance() { + + + } // get_active_instance + + /** + * add_url + * This is the new hotness + */ + public function add_url(Stream_URL $url) { + // If we haven't added anything then maybe we should clear the + // playlist. + if ($this->_add_count < 1) { + $this->_mpd->RefreshInfo(); + if ($this->_mpd->status['state'] == mpd::STATE_STOPPED) { + $this->clear_playlist(); + } + } + + if (!$this->_mpd->PlAdd($url->url)) { + debug_event('mpd', 'add_url failed to add: ' . json_encode($url), 1); + return false; + } + + $this->_add_count++; + return true; + } + + /** + * delete_track + * This must take a single ID (as returned by the get function) + * and delete it from the current playlist + */ + public function delete_track($object_id) { + return $this->_mpd->PLRemove($object_id); + } // delete_track + + /** + * clear_playlist + * This deletes the entire MPD playlist... nuff said + */ + public function clear_playlist() { + return $this->_mpd->PLClear(); + } // clear_playlist + + /** + * play + * This just tells MPD to start playing, it does not + * take any arguments + */ + public function play() { + return $this->_mpd->Play(); + } // play + + /** + * stop + * This just tells MPD to stop playing, it does not take + * any arguments + */ + public function stop() { + return $this->_mpd->Stop(); + } // stop + + /** + * skip + * This tells MPD to skip to the specified song + */ + public function skip($song) { + + if (!$this->_mpd->SkipTo($song)) { return false; } + sleep(2); + $this->stop(); + sleep(2); + $this->play(); + return true; + + } // skip + + /** + * This tells MPD to increase the volume by 5 + */ + public function volume_up() { + return $this->_mpd->AdjustVolume('5'); + } // volume_up + + /** + * This tells MPD to decrease the volume by 5 + */ + public function volume_down() { + return $this->_mpd->AdjustVolume('-5'); + } // volume_down + + /** + * next + * This just tells MPD to skip to the next song + */ + public function next() { + return $this->_mpd->Next(); + } // next + + /** + * prev + * This just tells MPD to skip to the prev song + */ + public function prev() { + return $this->_mpd->Previous(); + } // prev + + /** + * pause + * This tells MPD to pause the current song + */ + public function pause() { + return $this->_mpd->Pause(); + } // pause /** * volume * This tells MPD to set the volume to the parameter */ - public function volume($volume) { + public function volume($volume) { return $this->_mpd->SetVolume($volume); } // volume /** * repeat * This tells MPD to set the repeating the playlist (i.e. loop) to either - * on or off. + * on or off. */ - public function repeat($state) { - return $this->_mpd->SetRepeat($state); + public function repeat($state) { + return $this->_mpd->SetRepeat($state); } // repeat /** * random * This tells MPD to turn on or off the playing of songs from the - * playlist in random order. + * playlist in random order. */ public function random($onoff) { return $this->_mpd->SetRandom($onoff); @@ -416,137 +416,137 @@ public function random($onoff) { * This tells MPD to move a song */ public function move($source, $destination) { - return $this->_mpd->PLMoveTrack($source, $destination); - } // move - - /** - * get_songs - * This functions returns an array containing information about - * the songs that MPD currently has in its playlist. This must be - * done in a standardized fashion - */ - public function get() { - // If we don't have the playlist yet, pull it - if (!isset($this->_mpd->playlist)) { - $this->_mpd->RefreshInfo(); - } - - /* Get the Current Playlist */ - $playlist = $this->_mpd->playlist; - - foreach ($playlist as $entry) { - $data = array(); - - /* Required Elements */ - $data['id'] = $entry['Pos']; - $data['raw'] = $entry['file']; - - $url_data = $this->parse_url($entry['file']); - - switch ($url_data['primary_key']) { - case 'oid': - $song = new Song($url_data['oid']); - $song->format(); - $data['name'] = $song->f_title . ' - ' . $song->f_album . ' - ' . $song->f_artist; - $data['link'] = $song->f_link; - break; - case 'demo_id': - $democratic = new Democratic($url_data['demo_id']); - $data['name'] = T_('Democratic') . ' - ' . $democratic->name; - $data['link'] = ''; - break; - case 'random': - $data['name'] = T_('Random') . ' - ' . scrub_out(ucfirst($url_data['type'])); - $data['link'] = ''; - break; - default: - - /* If we don't know it, look up by filename */ - $filename = Dba::escape($entry['file']); - $sql = "SELECT `id`,'song' AS `type` FROM `song` WHERE `file` LIKE '%$filename' " . - "UNION ALL " . - "SELECT `id`,'radio' AS `type` FROM `live_stream` WHERE `url`='$filename' "; - - $db_results = Dba::read($sql); - if ($row = Dba::fetch_assoc($db_results)) { - $media = new $row['type']($row['id']); - $media->format(); - switch ($row['type']) { - case 'song': - $data['name'] = $media->f_title . ' - ' . $media->f_album . ' - ' . $media->f_artist; - $data['link'] = $media->f_link; - break; - case 'radio': - $frequency = $media->frequency ? '[' . $media->frequency . ']' : ''; - $site_url = $media->site_url ? '(' . $media->site_url . ')' : ''; - $data['name'] = "$media->name $frequency $site_url"; - $data['link'] = $media->site_url; - break; - } // end switch on type - } // end if results - - else { - $data['name'] = T_('Unknown'); - $data['link'] = ''; - } - - break; - } // end switch on primary key type - - /* Optional Elements */ - $data['track'] = $entry['Pos']+1; - - $results[] = $data; - - } // foreach playlist items - - return $results; - - } // get - - /** - * get_status - * This returns bool/int values for features, loop, repeat and any other - * features that this localplay method supports. - */ - public function status() { - - $track = $this->_mpd->status['song']; - - /* Construct the Array */ - $array['state'] = $this->_mpd->status['state']; - $array['volume'] = $this->_mpd->status['volume']; - $array['repeat'] = $this->_mpd->status['repeat']; - $array['random'] = $this->_mpd->status['random']; - $array['track'] = $track+1; - - $url_data = $this->parse_url($this->_mpd->playlist[$track]['file']); - $song = new Song($url_data['oid']); - $array['track_title'] = $song->title; - $array['track_artist'] = $song->get_artist_name(); - $array['track_album'] = $song->get_album_name(); - - return $array; - - } // get_status - - /** - * connect - * This functions creates the connection to MPD and returns - * a boolean value for the status, to save time this handle - * is stored in this class - */ - public function connect() { - - // Look at the current instance and pull the options for said instance - $options = self::get_instance(); - $this->_mpd = new mpd($options['host'], $options['port'], $options['password'], 'debug_event'); - - if ($this->_mpd->connected) { return true; } - - return false; - - } // connect + return $this->_mpd->PLMoveTrack($source, $destination); + } // move + + /** + * get_songs + * This functions returns an array containing information about + * the songs that MPD currently has in its playlist. This must be + * done in a standardized fashion + */ + public function get() { + // If we don't have the playlist yet, pull it + if (!isset($this->_mpd->playlist)) { + $this->_mpd->RefreshInfo(); + } + + /* Get the Current Playlist */ + $playlist = $this->_mpd->playlist; + + foreach ($playlist as $entry) { + $data = array(); + + /* Required Elements */ + $data['id'] = $entry['Pos']; + $data['raw'] = $entry['file']; + + $url_data = $this->parse_url($entry['file']); + + switch ($url_data['primary_key']) { + case 'oid': + $song = new Song($url_data['oid']); + $song->format(); + $data['name'] = $song->f_title . ' - ' . $song->f_album . ' - ' . $song->f_artist; + $data['link'] = $song->f_link; + break; + case 'demo_id': + $democratic = new Democratic($url_data['demo_id']); + $data['name'] = T_('Democratic') . ' - ' . $democratic->name; + $data['link'] = ''; + break; + case 'random': + $data['name'] = T_('Random') . ' - ' . scrub_out(ucfirst($url_data['type'])); + $data['link'] = ''; + break; + default: + + /* If we don't know it, look up by filename */ + $filename = Dba::escape($entry['file']); + $sql = "SELECT `id`,'song' AS `type` FROM `song` WHERE `file` LIKE '%$filename' " . + "UNION ALL " . + "SELECT `id`,'radio' AS `type` FROM `live_stream` WHERE `url`='$filename' "; + + $db_results = Dba::read($sql); + if ($row = Dba::fetch_assoc($db_results)) { + $media = new $row['type']($row['id']); + $media->format(); + switch ($row['type']) { + case 'song': + $data['name'] = $media->f_title . ' - ' . $media->f_album . ' - ' . $media->f_artist; + $data['link'] = $media->f_link; + break; + case 'radio': + $frequency = $media->frequency ? '[' . $media->frequency . ']' : ''; + $site_url = $media->site_url ? '(' . $media->site_url . ')' : ''; + $data['name'] = "$media->name $frequency $site_url"; + $data['link'] = $media->site_url; + break; + } // end switch on type + } // end if results + + else { + $data['name'] = T_('Unknown'); + $data['link'] = ''; + } + + break; + } // end switch on primary key type + + /* Optional Elements */ + $data['track'] = $entry['Pos']+1; + + $results[] = $data; + + } // foreach playlist items + + return $results; + + } // get + + /** + * get_status + * This returns bool/int values for features, loop, repeat and any other + * features that this localplay method supports. + */ + public function status() { + + $track = $this->_mpd->status['song']; + + /* Construct the Array */ + $array['state'] = $this->_mpd->status['state']; + $array['volume'] = $this->_mpd->status['volume']; + $array['repeat'] = $this->_mpd->status['repeat']; + $array['random'] = $this->_mpd->status['random']; + $array['track'] = $track+1; + + $url_data = $this->parse_url($this->_mpd->playlist[$track]['file']); + $song = new Song($url_data['oid']); + $array['track_title'] = $song->title; + $array['track_artist'] = $song->get_artist_name(); + $array['track_album'] = $song->get_album_name(); + + return $array; + + } // get_status + + /** + * connect + * This functions creates the connection to MPD and returns + * a boolean value for the status, to save time this handle + * is stored in this class + */ + public function connect() { + + // Look at the current instance and pull the options for said instance + $options = self::get_instance(); + $this->_mpd = new mpd($options['host'], $options['port'], $options['password'], 'debug_event'); + + if ($this->_mpd->connected) { return true; } + + return false; + + } // connect } //end of AmpacheMpd diff --git a/modules/localplay/vlc.controller.php b/modules/localplay/vlc.controller.php index 0765a194d2..60ef68d07b 100644 --- a/modules/localplay/vlc.controller.php +++ b/modules/localplay/vlc.controller.php @@ -1,5 +1,5 @@ _vlc->add($url->title, $url->url))) { - debug_event('vlc', 'add_url failed to add: ' . json_encode($url), 1); - return false; - } + if (is_null($this->_vlc->add($url->title, $url->url))) { + debug_event('vlc', 'add_url failed to add: ' . json_encode($url), 1); + return false; + } - return true; + return true; } /** diff --git a/modules/mpd/mpd.class.php b/modules/mpd/mpd.class.php index 5dacca64eb..ca9ca52c6a 100644 --- a/modules/mpd/mpd.class.php +++ b/modules/mpd/mpd.class.php @@ -1,5 +1,5 @@ load to - // fill them out - private $username; - private $password; - private $hostname; - private $port; - private $path; - private $challenge; - private $user_id; - - /** - * Constructor - * This function does nothing... - */ - public function __construct() { - - return true; - - } // constructor - - /** - * install - * This is a required plugin function. It inserts our preferences - * into Ampache - */ - public function install() { - - // Check and see if it's already installed (they've just hit refresh, those dorks) - if (Preference::exists('lastfm_user')) { return false; } - - Preference::insert('lastfm_user','Last.FM Username','','25','string','plugins'); - Preference::insert('lastfm_md5_pass','Last.FM Password','','25','string','plugins'); - Preference::insert('lastfm_port','Last.FM Submit Port','','25','string','internal'); - Preference::insert('lastfm_host','Last.FM Submit Host','','25','string','internal'); - Preference::insert('lastfm_url','Last.FM Submit URL','','25','string','internal'); - Preference::insert('lastfm_challenge','Last.FM Submit Challenge','','25','string','internal'); - - return true; - - } // install - - /** - * uninstall - * This is a required plugin function. It removes our preferences from - * the database returning it to its original form - */ - public function uninstall() { - - Preference::delete('lastfm_md5_pass'); - Preference::delete('lastfm_user'); - Preference::delete('lastfm_url'); - Preference::delete('lastfm_host'); - Preference::delete('lastfm_port'); - Preference::delete('lastfm_challenge'); - - } // uninstall - - /** - * upgrade - * This is a recommended plugin function - */ - public function upgrade() { - $from_version = Plugin::get_plugin_version($this->name); - if ($from_version < 4) { - Preference::rename('lastfm_pass', 'lastfm_md5_pass'); - } - return true; - } // upgrade - - /** - * save_songplay - * This takes care of queueing and then submitting the tracks. - */ - public function save_songplay($song) { - - // Let's pull the last song submitted by this user - $previous = Stats::get_last_song($this->user_id); - - $diff = time() - $previous['date']; - - // Make sure it wasn't within the last min - if ($diff < 60) { - debug_event($this->name,'Last song played within ' . $diff . ' seconds, not recording stats','3'); - return false; - } - - if ($song->time < 30) { - debug_event($this->name,'Song less then 30 seconds not queueing','3'); - return false; - } - - // Make sure there's actually a username and password before we keep going - if (!$this->username || !$this->password) { - debug_event($this->name,'Username or password missing','3'); - return false; - } - - // Create our scrobbler with everything this time and then queue it - $scrobbler = new scrobbler($this->username,$this->password,$this->hostname,$this->port,$this->path,$this->challenge); - - // Check to see if the scrobbling works - if (!$scrobbler->queue_track($song->f_artist_full,$song->f_album_full,$song->title,time(),$song->time,$song->track)) { - // Depending on the error we might need to do soemthing here - return false; - } - - // Go ahead and submit it now - if (!$scrobbler->submit_tracks()) { - debug_event($this->name,'Error Submit Failed: ' . $scrobbler->error_msg,'3'); - if ($scrobbler->reset_handshake) { - debug_event($this->name,'Re-running Handshake due to error','3'); - $this->set_handshake($this->user_id); - // Try try again - if ($scrobbler->submit_tracks()) { - debug_event($this->name,'Submission Successful','5'); - return true; - } - } - return false; - } - - debug_event($this->name,'Submission Successful','5'); - - return true; - - } // submit - - /** - * set_handshake - * This runs a handshake and properly updates the preferences as needed. - * It returns the data as an array so we don't have to requery the db. - * This requires a userid so it knows whose crap to update. - */ - public function set_handshake($user_id) { - - $scrobbler = new scrobbler($this->username,$this->password); - $data = $scrobbler->handshake(); - - if (!$data) { - debug_event($this->name,'Handshake Failed: ' . $scrobbler->error_msg,'3'); - return false; - } - - $this->hostname = $data['submit_host']; - $this->port = $data['submit_port']; - $this->path = $data['submit_url']; - $this->challenge = $data['challenge']; - - // Update the preferences - Preference::update('lastfm_port',$user_id,$data['submit_port']); - Preference::update('lastfm_host',$user_id,$data['submit_host']); - Preference::update('lastfm_url',$user_id,$data['submit_url']); - Preference::update('lastfm_challenge',$user_id,$data['challenge']); - - return true; - - } // set_handshake - - /** - * load - * This loads up the data we need into this object, this stuff comes - * from the preferences. - */ - public function load() { - - $GLOBALS['user']->set_preferences(); - $data = $GLOBALS['user']->prefs; - - if (strlen(trim($data['lastfm_user']))) { - $this->username = trim($data['lastfm_user']); - } - else { - debug_event($this->name,'No Username, not scrobbling','3'); - return false; - } - if (strlen(trim($data['lastfm_md5_pass']))) { - $this->password = trim($data['lastfm_md5_pass']); - } - else { - debug_event($this->name,'No Password, not scrobbling','3'); - return false; - } - - $this->user_id = $GLOBALS['user']->id; - - // If we don't have the other stuff try to get it before giving up - if (!$data['lastfm_host'] || !$data['lastfm_port'] || !$data['lastfm_url'] || !$data['lastfm_challenge']) { - debug_event($this->name,'Running Handshake, missing information','3'); - if (!$this->set_handshake($this->user_id)) { - debug_event($this->name,'Handshake failed, you lose','3'); - return false; - } - } - else { - $this->hostname = $data['lastfm_host']; - $this->port = $data['lastfm_port']; - $this->path = $data['lastfm_url']; - $this->challenge = $data['lastfm_challenge']; - } - - return true; - - } // load + public $name ='Last.FM'; + public $description ='Records your played songs to your Last.FM Account'; + public $url =''; + public $version ='000004'; + public $min_ampache ='360003'; + public $max_ampache ='999999'; + + // These are internal settings used by this class, run this->load to + // fill them out + private $username; + private $password; + private $hostname; + private $port; + private $path; + private $challenge; + private $user_id; + + /** + * Constructor + * This function does nothing... + */ + public function __construct() { + + return true; + + } // constructor + + /** + * install + * This is a required plugin function. It inserts our preferences + * into Ampache + */ + public function install() { + + // Check and see if it's already installed (they've just hit refresh, those dorks) + if (Preference::exists('lastfm_user')) { return false; } + + Preference::insert('lastfm_user','Last.FM Username','','25','string','plugins'); + Preference::insert('lastfm_md5_pass','Last.FM Password','','25','string','plugins'); + Preference::insert('lastfm_port','Last.FM Submit Port','','25','string','internal'); + Preference::insert('lastfm_host','Last.FM Submit Host','','25','string','internal'); + Preference::insert('lastfm_url','Last.FM Submit URL','','25','string','internal'); + Preference::insert('lastfm_challenge','Last.FM Submit Challenge','','25','string','internal'); + + return true; + + } // install + + /** + * uninstall + * This is a required plugin function. It removes our preferences from + * the database returning it to its original form + */ + public function uninstall() { + + Preference::delete('lastfm_md5_pass'); + Preference::delete('lastfm_user'); + Preference::delete('lastfm_url'); + Preference::delete('lastfm_host'); + Preference::delete('lastfm_port'); + Preference::delete('lastfm_challenge'); + + } // uninstall + + /** + * upgrade + * This is a recommended plugin function + */ + public function upgrade() { + $from_version = Plugin::get_plugin_version($this->name); + if ($from_version < 4) { + Preference::rename('lastfm_pass', 'lastfm_md5_pass'); + } + return true; + } // upgrade + + /** + * save_songplay + * This takes care of queueing and then submitting the tracks. + */ + public function save_songplay($song) { + + // Let's pull the last song submitted by this user + $previous = Stats::get_last_song($this->user_id); + + $diff = time() - $previous['date']; + + // Make sure it wasn't within the last min + if ($diff < 60) { + debug_event($this->name,'Last song played within ' . $diff . ' seconds, not recording stats','3'); + return false; + } + + if ($song->time < 30) { + debug_event($this->name,'Song less then 30 seconds not queueing','3'); + return false; + } + + // Make sure there's actually a username and password before we keep going + if (!$this->username || !$this->password) { + debug_event($this->name,'Username or password missing','3'); + return false; + } + + // Create our scrobbler with everything this time and then queue it + $scrobbler = new scrobbler($this->username,$this->password,$this->hostname,$this->port,$this->path,$this->challenge); + + // Check to see if the scrobbling works + if (!$scrobbler->queue_track($song->f_artist_full,$song->f_album_full,$song->title,time(),$song->time,$song->track)) { + // Depending on the error we might need to do soemthing here + return false; + } + + // Go ahead and submit it now + if (!$scrobbler->submit_tracks()) { + debug_event($this->name,'Error Submit Failed: ' . $scrobbler->error_msg,'3'); + if ($scrobbler->reset_handshake) { + debug_event($this->name,'Re-running Handshake due to error','3'); + $this->set_handshake($this->user_id); + // Try try again + if ($scrobbler->submit_tracks()) { + debug_event($this->name,'Submission Successful','5'); + return true; + } + } + return false; + } + + debug_event($this->name,'Submission Successful','5'); + + return true; + + } // submit + + /** + * set_handshake + * This runs a handshake and properly updates the preferences as needed. + * It returns the data as an array so we don't have to requery the db. + * This requires a userid so it knows whose crap to update. + */ + public function set_handshake($user_id) { + + $scrobbler = new scrobbler($this->username,$this->password); + $data = $scrobbler->handshake(); + + if (!$data) { + debug_event($this->name,'Handshake Failed: ' . $scrobbler->error_msg,'3'); + return false; + } + + $this->hostname = $data['submit_host']; + $this->port = $data['submit_port']; + $this->path = $data['submit_url']; + $this->challenge = $data['challenge']; + + // Update the preferences + Preference::update('lastfm_port',$user_id,$data['submit_port']); + Preference::update('lastfm_host',$user_id,$data['submit_host']); + Preference::update('lastfm_url',$user_id,$data['submit_url']); + Preference::update('lastfm_challenge',$user_id,$data['challenge']); + + return true; + + } // set_handshake + + /** + * load + * This loads up the data we need into this object, this stuff comes + * from the preferences. + */ + public function load() { + + $GLOBALS['user']->set_preferences(); + $data = $GLOBALS['user']->prefs; + + if (strlen(trim($data['lastfm_user']))) { + $this->username = trim($data['lastfm_user']); + } + else { + debug_event($this->name,'No Username, not scrobbling','3'); + return false; + } + if (strlen(trim($data['lastfm_md5_pass']))) { + $this->password = trim($data['lastfm_md5_pass']); + } + else { + debug_event($this->name,'No Password, not scrobbling','3'); + return false; + } + + $this->user_id = $GLOBALS['user']->id; + + // If we don't have the other stuff try to get it before giving up + if (!$data['lastfm_host'] || !$data['lastfm_port'] || !$data['lastfm_url'] || !$data['lastfm_challenge']) { + debug_event($this->name,'Running Handshake, missing information','3'); + if (!$this->set_handshake($this->user_id)) { + debug_event($this->name,'Handshake failed, you lose','3'); + return false; + } + } + else { + $this->hostname = $data['lastfm_host']; + $this->port = $data['lastfm_port']; + $this->path = $data['lastfm_url']; + $this->challenge = $data['lastfm_challenge']; + } + + return true; + + } // load } // end AmpacheLastfm ?> diff --git a/modules/plugins/Librefm.plugin.php b/modules/plugins/Librefm.plugin.php index 8489e7b654..fd2b89517f 100644 --- a/modules/plugins/Librefm.plugin.php +++ b/modules/plugins/Librefm.plugin.php @@ -1,5 +1,5 @@ load to - // fill them out - private $username; - private $password; - private $hostname; - private $port; - private $path; - private $challenge; - private $user_id; - - /** - * Constructor - * This function does nothing... - */ - public function __construct() { - - return true; - - } // constructor - - /** - * install - * This is a required plugin function. It inserts our preferences - * into Ampache - */ - public function install() { - - // Check and see if it's already installed (they've just hit refresh, those dorks) - if (Preference::exists('librefm_user')) { return false; } - - Preference::insert('librefm_user','Libre.FM Username','','25','string','plugins'); - Preference::insert('librefm_md5_pass','Libre.FM Password','','25','string','plugins'); - Preference::insert('librefm_port','Libre.FM Submit Port','','25','string','internal'); - Preference::insert('librefm_host','Libre.FM Submit Host','','25','string','internal'); - Preference::insert('librefm_url','Libre.FM Submit URL','','25','string','internal'); - Preference::insert('librefm_challenge','Libre.FM Submit Challenge','','25','string','internal'); - - return true; - - } // install - - /** - * uninstall - * This is a required plugin function. It removes our preferences from - * the database returning it to its original form - */ - public function uninstall() { - - Preference::delete('librefm_md5_pass'); - Preference::delete('librefm_user'); - Preference::delete('librefm_url'); - Preference::delete('librefm_host'); - Preference::delete('librefm_port'); - Preference::delete('librefm_challenge'); - - } // uninstall - - /** - * upgrade - * This is a recommended plugin function - */ - public function upgrade() { - $from_version = Plugin::get_plugin_version($this->name); - if ($from_version < 2) { - Preference::rename('librefm_pass', 'librefm_md5_pass'); - } - return true; - } // upgrade - - /** - * save_songplay - * This takes care of queueing and then submitting the tracks. - */ - public function save_songplay($song) { - - // Before we start let's pull the last song submitted by this user - $previous = Stats::get_last_song($this->user_id); - - $diff = time() - $previous['date']; - - // Make sure it wasn't within the last min - if ($diff < 60) { - debug_event($this->name,'Last song played within ' . $diff . ' seconds, not recording stats','3'); - return false; - } - - if ($song->time < 30) { - debug_event($this->name,'Song less then 30 seconds not queueing','3'); - return false; - } - - // Make sure there's actually a username and password before we keep going - if (!$this->username || !$this->password) { - debug_event($this->name,'Username or password missing','3'); - return false; - } - - // Create our scrobbler with everything this time and then queue it - $scrobbler = new scrobbler($this->username,$this->password,$this->hostname,$this->port,$this->path,$this->challenge,'turtle.libre.fm'); - - // Check to see if the scrobbling works - if (!$scrobbler->queue_track($song->f_artist_full,$song->f_album_full,$song->title,time(),$song->time,$song->track)) { - // Depending on the error we might need to do soemthing here - return false; - } - - // Go ahead and submit it now - if (!$scrobbler->submit_tracks()) { - debug_event($this->name,'Error Submit Failed: ' . $scrobbler->error_msg,'3'); - if ($scrobbler->reset_handshake) { - debug_event($this->name,'Re-running Handshake due to error','3'); - $this->set_handshake($this->user_id); - // Try try again - if ($scrobbler->submit_tracks()) { - return true; - } - } - return false; - } - - debug_event($this->name,'Submission Successful','5'); - - return true; - - } // submit - - /** - * set_handshake - * This runs a handshake and properly updates the preferences as needed. - * It returns the data as an array so we don't have to requery the db. - * This requires a userid so it knows whose crap to update. - */ - public function set_handshake($user_id) { - - $scrobbler = new scrobbler($this->username,$this->password,'','','','','turtle.libre.fm'); - $data = $scrobbler->handshake(); - - if (!$data) { - debug_event($this->name,'Handshake Failed: ' . $scrobbler->error_msg,'3'); - return false; - } - - $this->hostname = $data['submit_host']; - $this->port = $data['submit_port']; - $this->path = $data['submit_url']; - $this->challenge = $data['challenge']; - - // Update the preferences - Preference::update('librefm_port',$user_id,$data['submit_port']); - Preference::update('librefm_host',$user_id,$data['submit_host']); - Preference::update('librefm_url',$user_id,$data['submit_url']); - Preference::update('librefm_challenge',$user_id,$data['challenge']); - - return true; - - } // set_handshake - - /** - * load - * This loads up the data we need into this object, this stuff comes - * from the preferences. - */ - public function load() { - - $GLOBALS['user']->set_preferences(); - $data = $GLOBALS['user']->prefs; - - if (strlen(trim($data['librefm_user']))) { - $this->username = trim($data['librefm_user']); - } - else { - debug_event($this->name,'No Username, not scrobbling','3'); - return false; - } - if (strlen(trim($data['librefm_md5_pass']))) { - $this->password = trim($data['librefm_md5_pass']); - } - else { - debug_event($this->name,'No Password, not scrobbling','3'); - return false; - } - - $this->user_id = $GLOBALS['user']->id; - - // If we don't have the other stuff try to get it before giving up - if (!$data['librefm_host'] || !$data['librefm_port'] || !$data['librefm_url'] || !$data['librefm_challenge']) { - debug_event($this->name,'Running Handshake, missing information','3'); - if (!$this->set_handshake($this->user_id)) { - debug_event($this->name,'Handshake failed, you lose','3'); - return false; - } - } - else { - $this->hostname = $data['librefm_host']; - $this->port = $data['librefm_port']; - $this->path = $data['librefm_url']; - $this->challenge = $data['librefm_challenge']; - } - - return true; - - } // load + public $name ='Libre.FM'; + public $description ='Records your played songs to your Libre.FM Account'; + public $url =''; + public $version ='000002'; + public $min_ampache ='360003'; + public $max_ampache ='999999'; + + // These are internal settings used by this class, run this->load to + // fill them out + private $username; + private $password; + private $hostname; + private $port; + private $path; + private $challenge; + private $user_id; + + /** + * Constructor + * This function does nothing... + */ + public function __construct() { + + return true; + + } // constructor + + /** + * install + * This is a required plugin function. It inserts our preferences + * into Ampache + */ + public function install() { + + // Check and see if it's already installed (they've just hit refresh, those dorks) + if (Preference::exists('librefm_user')) { return false; } + + Preference::insert('librefm_user','Libre.FM Username','','25','string','plugins'); + Preference::insert('librefm_md5_pass','Libre.FM Password','','25','string','plugins'); + Preference::insert('librefm_port','Libre.FM Submit Port','','25','string','internal'); + Preference::insert('librefm_host','Libre.FM Submit Host','','25','string','internal'); + Preference::insert('librefm_url','Libre.FM Submit URL','','25','string','internal'); + Preference::insert('librefm_challenge','Libre.FM Submit Challenge','','25','string','internal'); + + return true; + + } // install + + /** + * uninstall + * This is a required plugin function. It removes our preferences from + * the database returning it to its original form + */ + public function uninstall() { + + Preference::delete('librefm_md5_pass'); + Preference::delete('librefm_user'); + Preference::delete('librefm_url'); + Preference::delete('librefm_host'); + Preference::delete('librefm_port'); + Preference::delete('librefm_challenge'); + + } // uninstall + + /** + * upgrade + * This is a recommended plugin function + */ + public function upgrade() { + $from_version = Plugin::get_plugin_version($this->name); + if ($from_version < 2) { + Preference::rename('librefm_pass', 'librefm_md5_pass'); + } + return true; + } // upgrade + + /** + * save_songplay + * This takes care of queueing and then submitting the tracks. + */ + public function save_songplay($song) { + + // Before we start let's pull the last song submitted by this user + $previous = Stats::get_last_song($this->user_id); + + $diff = time() - $previous['date']; + + // Make sure it wasn't within the last min + if ($diff < 60) { + debug_event($this->name,'Last song played within ' . $diff . ' seconds, not recording stats','3'); + return false; + } + + if ($song->time < 30) { + debug_event($this->name,'Song less then 30 seconds not queueing','3'); + return false; + } + + // Make sure there's actually a username and password before we keep going + if (!$this->username || !$this->password) { + debug_event($this->name,'Username or password missing','3'); + return false; + } + + // Create our scrobbler with everything this time and then queue it + $scrobbler = new scrobbler($this->username,$this->password,$this->hostname,$this->port,$this->path,$this->challenge,'turtle.libre.fm'); + + // Check to see if the scrobbling works + if (!$scrobbler->queue_track($song->f_artist_full,$song->f_album_full,$song->title,time(),$song->time,$song->track)) { + // Depending on the error we might need to do soemthing here + return false; + } + + // Go ahead and submit it now + if (!$scrobbler->submit_tracks()) { + debug_event($this->name,'Error Submit Failed: ' . $scrobbler->error_msg,'3'); + if ($scrobbler->reset_handshake) { + debug_event($this->name,'Re-running Handshake due to error','3'); + $this->set_handshake($this->user_id); + // Try try again + if ($scrobbler->submit_tracks()) { + return true; + } + } + return false; + } + + debug_event($this->name,'Submission Successful','5'); + + return true; + + } // submit + + /** + * set_handshake + * This runs a handshake and properly updates the preferences as needed. + * It returns the data as an array so we don't have to requery the db. + * This requires a userid so it knows whose crap to update. + */ + public function set_handshake($user_id) { + + $scrobbler = new scrobbler($this->username,$this->password,'','','','','turtle.libre.fm'); + $data = $scrobbler->handshake(); + + if (!$data) { + debug_event($this->name,'Handshake Failed: ' . $scrobbler->error_msg,'3'); + return false; + } + + $this->hostname = $data['submit_host']; + $this->port = $data['submit_port']; + $this->path = $data['submit_url']; + $this->challenge = $data['challenge']; + + // Update the preferences + Preference::update('librefm_port',$user_id,$data['submit_port']); + Preference::update('librefm_host',$user_id,$data['submit_host']); + Preference::update('librefm_url',$user_id,$data['submit_url']); + Preference::update('librefm_challenge',$user_id,$data['challenge']); + + return true; + + } // set_handshake + + /** + * load + * This loads up the data we need into this object, this stuff comes + * from the preferences. + */ + public function load() { + + $GLOBALS['user']->set_preferences(); + $data = $GLOBALS['user']->prefs; + + if (strlen(trim($data['librefm_user']))) { + $this->username = trim($data['librefm_user']); + } + else { + debug_event($this->name,'No Username, not scrobbling','3'); + return false; + } + if (strlen(trim($data['librefm_md5_pass']))) { + $this->password = trim($data['librefm_md5_pass']); + } + else { + debug_event($this->name,'No Password, not scrobbling','3'); + return false; + } + + $this->user_id = $GLOBALS['user']->id; + + // If we don't have the other stuff try to get it before giving up + if (!$data['librefm_host'] || !$data['librefm_port'] || !$data['librefm_url'] || !$data['librefm_challenge']) { + debug_event($this->name,'Running Handshake, missing information','3'); + if (!$this->set_handshake($this->user_id)) { + debug_event($this->name,'Handshake failed, you lose','3'); + return false; + } + } + else { + $this->hostname = $data['librefm_host']; + $this->port = $data['librefm_port']; + $this->path = $data['librefm_url']; + $this->challenge = $data['librefm_challenge']; + } + + return true; + + } // load } // end Ampachelibrefm ?> diff --git a/modules/plugins/MusicBrainz.plugin.php b/modules/plugins/MusicBrainz.plugin.php index 86f3e7f47f..672df7b50e 100644 --- a/modules/plugins/MusicBrainz.plugin.php +++ b/modules/plugins/MusicBrainz.plugin.php @@ -1,5 +1,5 @@ artist()->releases(); - try { - $track = $mbquery->getTrackById($mbid, $includes); - } - catch (Exception $e) { - return null; - } + $mbquery = new MusicBrainzQuery(); + $includes = new mbTrackIncludes(); + $includes = $includes->artist()->releases(); + try { + $track = $mbquery->getTrackById($mbid, $includes); + } + catch (Exception $e) { + return null; + } - $results = array(); + $results = array(); - $results['mb_artistid'] = $track->getArtist()->getId(); - $results['artist'] = $track->getArtist()->getName(); - $results['title'] = $track->getTitle(); - if ($track->getNumReleases() == 1) { - $release = $track->getReleases(); - $release = $release[0]; - $results['album'] = $release->getTitle(); - } + $results['mb_artistid'] = $track->getArtist()->getId(); + $results['artist'] = $track->getArtist()->getName(); + $results['title'] = $track->getTitle(); + if ($track->getNumReleases() == 1) { + $release = $track->getReleases(); + $release = $release[0]; + $results['album'] = $release->getTitle(); + } - return $results; - } // get_metadata + return $results; + } // get_metadata } // end AmpacheMusicBrainz ?> diff --git a/modules/twitter/twitter_login.php b/modules/twitter/twitter_login.php index 7e1b29e344..d929d1de77 100644 --- a/modules/twitter/twitter_login.php +++ b/modules/twitter/twitter_login.php @@ -1,7 +1,8 @@ getRequestToken( Config::get('web_path') . '/modules/twitter/twitter_works.php'); + // Requesting authentication tokens, the parameter is the URL we will be redirected to + $request_token = $twitteroauth->getRequestToken( Config::get('web_path') . '/modules/twitter/twitter_works.php'); - // Saving them into the session - $_SESSION['oauth_token'] = $request_token['oauth_token']; - $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; + // Saving them into the session + $_SESSION['oauth_token'] = $request_token['oauth_token']; + $_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; - // If everything goes well.. - if( $twitteroauth->http_code == 200 ) { - // Let's generate the URL and redirect - $url = $twitteroauth->getAuthorizeURL($request_token['oauth_token']); - header('Location: '. $url); - } else { - debug_event("Twitter", "Could not generate the URL to continue. Going back.", "5"); - header('Location: ' . Config::get('web_path') ); - } - } + // If everything goes well.. + if( $twitteroauth->http_code == 200 ) { + // Let's generate the URL and redirect + $url = $twitteroauth->getAuthorizeURL($request_token['oauth_token']); + header('Location: '. $url); + } else { + debug_event("Twitter", "Could not generate the URL to continue. Going back.", "5"); + header('Location: ' . Config::get('web_path') ); + } +} ?> diff --git a/modules/twitter/twitter_update.php b/modules/twitter/twitter_update.php index 9fe779d65c..04dbd878e4 100644 --- a/modules/twitter/twitter_update.php +++ b/modules/twitter/twitter_update.php @@ -1,4 +1,5 @@ get('account/verify'); - if( $user_info->error == 'Not found' ) { - debug_event("Twitter", "Auth Successful! Posting Status", "5"); - $twitteroauth->post('statuses/update', array('status' => 'is rocking out to ' . $return)); - header('Location: ' . Config::get('web_path') ); - } - - } else { - debug_event("Twitter", "Auth Error going back to home.", "5"); - header('Location: ' . Config::get('web_path') ); - } +require_once '../../lib/init.php'; +require_once( Config::get('prefix') . "/modules/twitter/twitteroauth/twitteroauth.php"); + session_start(); + + +if(!empty($_SESSION['twitterusername'])) { + + $nowplayingQuery = "SELECT song.title,artist.name FROM song,now_playing,artist WHERE song.id = now_playing.object_id AND artist.id = song.artist"; + debug_event("Twitter", "Now Playing query: " . $nowplayingQuery, "6"); + + $nowplayingRun = Dba::read($nowplayingQuery); + $nowplayingResults = Dba::fetch_assoc($nowplayingRun); + + $return = $nowplayingResults['title'] . " by " . $nowplayingResults['name']; + debug_event("Twitter", "Song from DB is: " . $return, "5"); + + $selectquery = "SELECT * FROM twitter_users WHERE username = '" . $_SESSION['twitterusername'] . "' AND ampache_id = " . $_SESSION['userdata']['uid']; + debug_event("Twitter", "Select query: " . $selectquery, "6"); + + $selectrun = Dba::read($selectquery); + $result = Dba::fetch_assoc($selectrun); + + $twitteroauth = new TwitterOAuth( Config::get('twitter_consumer_key'), Config::get('twitter_consumer_secret'), $result['oauth_token'], $result['oauth_secret']); + $user_info = $twitteroauth->get('account/verify'); + if( $user_info->error == 'Not found' ) { + debug_event("Twitter", "Auth Successful! Posting Status", "5"); + $twitteroauth->post('statuses/update', array('status' => 'is rocking out to ' . $return)); + header('Location: ' . Config::get('web_path') ); + } + +} else { + debug_event("Twitter", "Auth Error going back to home.", "5"); + header('Location: ' . Config::get('web_path') ); +} ?> diff --git a/modules/twitter/twitter_works.php b/modules/twitter/twitter_works.php index 9d031f5226..5bd0fca1c2 100644 --- a/modules/twitter/twitter_works.php +++ b/modules/twitter/twitter_works.php @@ -1,4 +1,5 @@ getAccessToken($_GET['oauth_verifier']); - if( !isset($access_token) ) { - debug_event("Twitter", "Couldn't get access token", "5"); - header('Location: ' . Config::get('web_path')); - } - // Save it in a session var - $_SESSION['access_token'] = $access_token; - - - // Let's get the user's info - $user_info = $twitteroauth->get('account/verify_credentials'); - - debug_event("Twttier", "User ID:{$user_info->id}. ScreenName:{$user_info->screen_name}.", "5"); - debug_event("Twitter", "access token:" . $access_token['oauth_token'], "5"); - debug_event("Twitter", "access token secret:" . $access_token['oauth_token_secret'], "5"); - - if( isset($user_info->error)) { - debug_event("Twitter", "Error verifying credentials", "5"); - session_destroy(); - header('Location: ' . Config::get('web_path')); - } else { - - // Let's find the user by its twitterid and ampacheid - $idselectquery = "SELECT * FROM twitter_users WHERE oauth_provider = 'twitter' AND oauth_uid = ". $user_info->id . " AND ampache_id = " . $_SESSION['userdata']['uid']; - debug_event("Twitter", "Id query: " . $idselectquery, "6"); - - $idselectrun = Dba::read($idselectquery); - $result = Dba::fetch_assoc($idselectrun); - - debug_event("Twitter", "ampache_id: {$_SESSION['userdata']['uid']}", "5"); - debug_event("Twitter", "oauth_uid: {$user_info->id}", "5"); - debug_event("Twitter", "oauth_token: {$access_token['oauth_token']}", "5"); - debug_event("Twitter", "oauth_secret: {$access_token['oauth_token_secret']}", "5"); - debug_event("Twitter", "username: {$user_info->screen_name}", "5"); - - // If not, let's add it to the database - if(empty($result)){ - debug_event("Twitter", "First time user. Add them to the DB.", "5"); - $insert_query ="INSERT INTO twitter_users (ampache_id, oauth_provider, oauth_uid, oauth_token, oauth_secret, username) VALUES ( '{$_SESSION['userdata']['uid']}', 'twitter', '{$user_info->id}', '{$access_token['oauth_token']}', '{$access_token['oauth_token_secret']}', '{$user_info->screen_name}')"; - - debug_event("Twitter", "Insert query: " . $insert_query, "6"); - $insert_run = Dba::write($insert_query); - - $select_query = "SELECT * FROM twitter_users WHERE username = '" . $user_info->screen_name . "' AND ampache_id = " . $_SESSION['userdata']['uid']; - debug_event("Twitter", "Select query: {$query}", "6"); - $select_run = Dba::read( $select_query ); - $result = Dba::fetch_assoc($select_run); - } else { - debug_event("Twitter", "Update the DB to hold current tokens", "5"); - - $update_query = "UPDATE twitter_users SET oauth_token = '{$access_token['oauth_token']}', oauth_secret = '{$access_token['oauth_token_secret']}' WHERE oauth_provider = 'twitter' AND oauth_uid = {$user_info->id} AND ampache_id = {$_SESSION['userdata']['uid']}"; - debug_event("Twitter", "update query: " . $update_query, "6"); - - $update_run = Dba::write($update_query); - - $select_query = "SELECT * FROM twitter_users WHERE username = '" . $user_info->screen_name . "'"; - debug_event("Twitter", "select query: " . $select_query, "6"); - - $select_run = Dba::read($select_query); - $result = Dba::fetch_assoc($select_run); - } - - $_SESSION['id'] = $result['id']; - $_SESSION['twitterusername'] = $result['username']; - $_SESSION['oauth_uid'] = $result['oauth_uid']; - $_SESSION['oauth_provider'] = $result['oauth_provider']; - $_SESSION['oauth_token'] = $result['oauth_token']; - $_SESSION['oauth_secret'] = $result['oauth_secret']; - - header('Location: ' . Config::get('web_path') . '/modules/twitter/twitter_update.php'); - } +require_once '../../lib/init.php'; + require_once( Config::get('prefix') . "/modules/twitter/twitteroauth/twitteroauth.php"); + +session_start(); + +if(!empty($_SESSION['twitterusername'])) { + header('Location: ' . Config::Get('web_path') . '/modules/twitter/twitter_update.php'); + debug_event("Twitter", "Twitter user has logged in this session.", "5"); +} + +if(!empty($_GET['oauth_verifier']) && !empty($_SESSION['oauth_token']) && !empty($_SESSION['oauth_token_secret'])){ + debug_event("Twitter", "Got all 3 pieces for auth", "5"); +} else { + if( $_SESSION['twitterCount'] < 4 ) { + debug_event("Twitter", "Didn't get all 3 auth pieces, going to try again. Try #" . $_SESSION['twitterCount'], "5"); + $_SESSION['twitterCount']++; + header('Location: ' . Config::Get('web_path') . '/modules/twitter/twitter_login.php'); + } else { + debug_event("Twitter", "Failed to auth too many times. Giving up.", "5"); + header('Location: ' . Config::Get('web_path') ); + } +} + +// TwitterOAuth instance, with two new parameters we got in twitter_login.php +$twitteroauth = new TwitterOAuth( Config::get('twitter_consumer_key'), Config::get('twitter_consumer_secret'), $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); +if( !isset($twitteroauth) ) { + debug_event("Twitter", "Couldn't create OAuth object.", "5"); + header('Location: ' . Config::get('web_path')); +} +// Let's request the access token +$access_token = $twitteroauth->getAccessToken($_GET['oauth_verifier']); +if( !isset($access_token) ) { + debug_event("Twitter", "Couldn't get access token", "5"); + header('Location: ' . Config::get('web_path')); +} +// Save it in a session var +$_SESSION['access_token'] = $access_token; + + +// Let's get the user's info +$user_info = $twitteroauth->get('account/verify_credentials'); + +debug_event("Twttier", "User ID:{$user_info->id}. ScreenName:{$user_info->screen_name}.", "5"); +debug_event("Twitter", "access token:" . $access_token['oauth_token'], "5"); +debug_event("Twitter", "access token secret:" . $access_token['oauth_token_secret'], "5"); + +if( isset($user_info->error)) { + debug_event("Twitter", "Error verifying credentials", "5"); + session_destroy(); + header('Location: ' . Config::get('web_path')); +} +else { + + // Let's find the user by its twitterid and ampacheid + $idselectquery = "SELECT * FROM twitter_users WHERE oauth_provider = 'twitter' AND oauth_uid = ". $user_info->id . " AND ampache_id = " . $_SESSION['userdata']['uid']; + debug_event("Twitter", "Id query: " . $idselectquery, "6"); + + $idselectrun = Dba::read($idselectquery); + $result = Dba::fetch_assoc($idselectrun); + + debug_event("Twitter", "ampache_id: {$_SESSION['userdata']['uid']}", "5"); + debug_event("Twitter", "oauth_uid: {$user_info->id}", "5"); + debug_event("Twitter", "oauth_token: {$access_token['oauth_token']}", "5"); + debug_event("Twitter", "oauth_secret: {$access_token['oauth_token_secret']}", "5"); + debug_event("Twitter", "username: {$user_info->screen_name}", "5"); + + // If not, let's add it to the database + if(empty($result)){ + debug_event("Twitter", "First time user. Add them to the DB.", "5"); + $insert_query ="INSERT INTO twitter_users (ampache_id, oauth_provider, oauth_uid, oauth_token, oauth_secret, username) VALUES ( '{$_SESSION['userdata']['uid']}', 'twitter', '{$user_info->id}', '{$access_token['oauth_token']}', '{$access_token['oauth_token_secret']}', '{$user_info->screen_name}')"; + + debug_event("Twitter", "Insert query: " . $insert_query, "6"); + $insert_run = Dba::write($insert_query); + + $select_query = "SELECT * FROM twitter_users WHERE username = '" . $user_info->screen_name . "' AND ampache_id = " . $_SESSION['userdata']['uid']; + debug_event("Twitter", "Select query: {$query}", "6"); + $select_run = Dba::read( $select_query ); + $result = Dba::fetch_assoc($select_run); + } + else { + debug_event("Twitter", "Update the DB to hold current tokens", "5"); + + $update_query = "UPDATE twitter_users SET oauth_token = '{$access_token['oauth_token']}', oauth_secret = '{$access_token['oauth_token_secret']}' WHERE oauth_provider = 'twitter' AND oauth_uid = {$user_info->id} AND ampache_id = {$_SESSION['userdata']['uid']}"; + debug_event("Twitter", "update query: " . $update_query, "6"); + + $update_run = Dba::write($update_query); + + $select_query = "SELECT * FROM twitter_users WHERE username = '" . $user_info->screen_name . "'"; + debug_event("Twitter", "select query: " . $select_query, "6"); + + $select_run = Dba::read($select_query); + $result = Dba::fetch_assoc($select_run); + } + + $_SESSION['id'] = $result['id']; + $_SESSION['twitterusername'] = $result['username']; + $_SESSION['oauth_uid'] = $result['oauth_uid']; + $_SESSION['oauth_provider'] = $result['oauth_provider']; + $_SESSION['oauth_token'] = $result['oauth_token']; + $_SESSION['oauth_secret'] = $result['oauth_secret']; + + header('Location: ' . Config::get('web_path') . '/modules/twitter/twitter_update.php'); + } ?> diff --git a/modules/vlc/vlcplayer.class.php b/modules/vlc/vlcplayer.class.php index d124b1a418..04e7a0a632 100644 --- a/modules/vlc/vlcplayer.class.php +++ b/modules/vlc/vlcplayer.class.php @@ -1,5 +1,5 @@ 'in_enqueue','&input'=>$aurl); $results = $this->sendCommand('status.xml?', $args); if (is_null($results)) { return null; } return true; - } // add /** diff --git a/phpinfo.php b/phpinfo.php index de6521f99a..460dc55bd7 100644 --- a/phpinfo.php +++ b/phpinfo.php @@ -1,5 +1,5 @@ disabled)) { - debug_event('UI::access_denied', "$user->username is currently disabled, stream access denied",'3'); - header('HTTP/1.1 403 User Disabled'); - exit; + debug_event('UI::access_denied', "$user->username is currently disabled, stream access denied",'3'); + header('HTTP/1.1 403 User Disabled'); + exit; } // If require session is set then we need to make sure we're legit if (Config::get('require_session')) { - if (!Config::get('require_localnet_session') AND Access::check_network('network',$GLOBALS['user']->id,'5')) { - debug_event('play', 'Streaming access allowed for local network IP ' . $_SERVER['REMOTE_ADDR'],'5'); - } - elseif(!Stream::session_exists($sid)) { - debug_event('UI::access_denied', 'Streaming access denied: ' . $GLOBALS['user']->username . "'s session has expired", 3); - header('HTTP/1.1 403 Session Expired'); - exit; - } + if (!Config::get('require_localnet_session') AND Access::check_network('network',$GLOBALS['user']->id,'5')) { + debug_event('play', 'Streaming access allowed for local network IP ' . $_SERVER['REMOTE_ADDR'],'5'); + } + elseif(!Stream::session_exists($sid)) { + debug_event('UI::access_denied', 'Streaming access denied: ' . $GLOBALS['user']->username . "'s session has expired", 3); + header('HTTP/1.1 403 Session Expired'); + exit; + } - // Now that we've confirmed the session is valid - // extend it - Stream::extend_session($sid,$uid); + // Now that we've confirmed the session is valid + // extend it + Stream::extend_session($sid,$uid); } @@ -102,9 +102,9 @@ /* If we are in demo mode.. die here */ if (Config::get('demo_mode') || (!Access::check('interface','25') )) { - debug_event('UI::access_denied', "Streaming Access Denied:" .Config::get('demo_mode') . "is the value of demo_mode. Current user level is " . $GLOBALS['user']->access,'3'); - UI::access_denied(); - exit; + debug_event('UI::access_denied', "Streaming Access Denied:" .Config::get('demo_mode') . "is the value of demo_mode. Current user level is " . $GLOBALS['user']->access,'3'); + UI::access_denied(); + exit; } /* @@ -112,24 +112,24 @@ that they have enough access to play this mojo */ if (Config::get('access_control')) { - if (!Access::check_network('stream',$GLOBALS['user']->id,'25') AND - !Access::check_network('network',$GLOBALS['user']->id,'25')) { - debug_event('UI::access_denied', "Streaming Access Denied: " . $_SERVER['REMOTE_ADDR'] . " does not have stream level access",'3'); - UI::access_denied(); - exit; - } + if (!Access::check_network('stream',$GLOBALS['user']->id,'25') AND + !Access::check_network('network',$GLOBALS['user']->id,'25')) { + debug_event('UI::access_denied', "Streaming Access Denied: " . $_SERVER['REMOTE_ADDR'] . " does not have stream level access",'3'); + UI::access_denied(); + exit; + } } // access_control is enabled // Handle playlist downloads if ($type == 'playlist') { - $playlist = new Stream_Playlist($oid); - // Some rudimentary security - if ($uid != $playlist->user) { - UI::access_denied(); - exit; - } - $playlist->generate_playlist($playlist_type, false); - exit; + $playlist = new Stream_Playlist($oid); + // Some rudimentary security + if ($uid != $playlist->user) { + UI::access_denied(); + exit; + } + $playlist->generate_playlist($playlist_type, false); + exit; } /** @@ -138,49 +138,49 @@ * we need to */ if ($demo_id) { - $democratic = new Democratic($demo_id); - $democratic->set_parent(); - - // If there is a cooldown we need to make sure this song isn't a repeat - if (!$democratic->cooldown) { - /* This takes into account votes etc and removes the */ - $oid = $democratic->get_next_object(); - } - else { - // Pull history - $oid = $democratic->get_next_object($song_cool_check); - $oids = $democratic->get_cool_songs(); - while (in_array($oid,$oids)) { - $song_cool_check++; - $oid = $democratic->get_next_object($song_cool_check); - if ($song_cool_check >= '5') { break; } - } // while we've got the 'new' song in old the array - - } // end if we've got a cooldown + $democratic = new Democratic($demo_id); + $democratic->set_parent(); + + // If there is a cooldown we need to make sure this song isn't a repeat + if (!$democratic->cooldown) { + /* This takes into account votes etc and removes the */ + $oid = $democratic->get_next_object(); + } + else { + // Pull history + $oid = $democratic->get_next_object($song_cool_check); + $oids = $democratic->get_cool_songs(); + while (in_array($oid,$oids)) { + $song_cool_check++; + $oid = $democratic->get_next_object($song_cool_check); + if ($song_cool_check >= '5') { break; } + } // while we've got the 'new' song in old the array + + } // end if we've got a cooldown } // if democratic ID passed /** * if we are doing random let's pull the random object */ if ($random) { - if ($start < 1) { - $oid = Random::get_single_song($_REQUEST['type']); - // Save this one in case we do a seek - $_SESSION['random']['last'] = $oid; - } - else { - $oid = $_SESSION['random']['last']; - } + if ($start < 1) { + $oid = Random::get_single_song($_REQUEST['type']); + // Save this one in case we do a seek + $_SESSION['random']['last'] = $oid; + } + else { + $oid = $_SESSION['random']['last']; + } } // if random if (!$video) { - /* Base Checks passed create the song object */ - $media = new Song($oid); - $media->format(); + /* Base Checks passed create the song object */ + $media = new Song($oid); + $media->format(); } else { - $media = new Video($oid); - $media->format(); + $media = new Video($oid); + $media->format(); } // Build up the catalog for our current object @@ -188,59 +188,59 @@ /* If the song is disabled */ if (!make_bool($media->enabled)) { - debug_event('Play',"Error: $media->file is currently disabled, song skipped",'5'); - // Check to see if this is a democratic playlist, if so remove it completely - if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } - exit; + debug_event('Play',"Error: $media->file is currently disabled, song skipped",'5'); + // Check to see if this is a democratic playlist, if so remove it completely + if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } + exit; } // If we are running in Legalize mode, don't play songs already playing if (Config::get('lock_songs')) { - if (!Stream::check_lock_media($media->id,get_class($media))) { - exit; - } + if (!Stream::check_lock_media($media->id,get_class($media))) { + exit; + } } /* Check to see if this is a 'remote' catalog */ if ($catalog->catalog_type == 'remote') { - preg_match("/(.+)\/play\/index.+/",$media->file,$match); + preg_match("/(.+)\/play\/index.+/",$media->file,$match); - $token = xmlRpcClient::ampache_handshake($match['1'],$catalog->key); + $token = xmlRpcClient::ampache_handshake($match['1'],$catalog->key); - // If we don't get anything back we failed and should bail now - if (!$token) { - debug_event('xmlrpc-stream','Error Unable to get Token from ' . $match['1'] . ' check target servers logs','1'); - exit; - } + // If we don't get anything back we failed and should bail now + if (!$token) { + debug_event('xmlrpc-stream','Error Unable to get Token from ' . $match['1'] . ' check target servers logs','1'); + exit; + } - $sid = xmlRpcClient::ampache_create_stream_session($match['1'],$token); + $sid = xmlRpcClient::ampache_create_stream_session($match['1'],$token); - $extra_info = "&xml_rpc=1&sid=$sid"; - header('Location: ' . $media->file . $extra_info); - debug_event('xmlrpc-stream',"Start XML-RPC Stream - " . $media->file . $extra_info,'5'); + $extra_info = "&xml_rpc=1&sid=$sid"; + header('Location: ' . $media->file . $extra_info); + debug_event('xmlrpc-stream',"Start XML-RPC Stream - " . $media->file . $extra_info,'5'); - /* If this is a voting tmp playlist remove the entry, we do this regardless of play amount */ - if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } // if democratic + /* If this is a voting tmp playlist remove the entry, we do this regardless of play amount */ + if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } // if democratic - exit; + exit; } // end if remote catalog /* If we don't have a file, or the file is not readable */ if (!$media->file OR !is_readable($media->file)) { - // We need to make sure this isn't democratic play, if it is then remove the song - // from the vote list - if (is_object($tmp_playlist)) { - $tmp_playlist->delete_track($oid); - } - // FIXME: why are these separate? - // Remove the song votes if this is a democratic song - if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } + // We need to make sure this isn't democratic play, if it is then remove the song + // from the vote list + if (is_object($tmp_playlist)) { + $tmp_playlist->delete_track($oid); + } + // FIXME: why are these separate? + // Remove the song votes if this is a democratic song + if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } - debug_event('play', "Song $media->file ($media->title) does not have a valid filename specified", 2); - header('HTTP/1.1 404 Invalid song, file not found or file unreadable'); - exit; + debug_event('play', "Song $media->file ($media->title) does not have a valid filename specified", 2); + header('HTTP/1.1 404 Invalid song, file not found or file unreadable'); + exit; } // don't abort the script if user skips this song because we need to update now_playing @@ -258,40 +258,40 @@ */ if ($_GET['action'] == 'download' AND Config::get('download')) { - // STUPID IE - $media->format_pattern(); - $media_name = str_replace(array('?','/','\\'),"_",$media->f_file); + // STUPID IE + $media->format_pattern(); + $media_name = str_replace(array('?','/','\\'),"_",$media->f_file); - $browser->downloadHeaders($media_name,$media->mime,false,$media->size); - $fp = fopen($media->file,'rb'); - $bytesStreamed = 0; + $browser->downloadHeaders($media_name,$media->mime,false,$media->size); + $fp = fopen($media->file,'rb'); + $bytesStreamed = 0; - if (!is_resource($fp)) { + if (!is_resource($fp)) { debug_event('Play',"Error: Unable to open $media->file for downloading",'2'); - exit(); + exit(); } - // Check to see if we should be throttling because we can get away with it - if (Config::get('rate_limit') > 0) { - while (!feof($fp)) { - echo fread($fp,round(Config::get('rate_limit')*1024)); - $bytesStreamed += round(Config::get('rate_limit')*1024); - flush(); - sleep(1); - } - } - else { - fpassthru($fp); - } - - // Make sure that a good chunk of the song has been played - if ($bytesStreamed >= $media->size) { - debug_event('Play','Downloaded, Registering stats for ' . $media->title,'5'); - $GLOBALS['user']->update_stats($media->id); - } // if enough bytes are streamed - - fclose($fp); - exit(); + // Check to see if we should be throttling because we can get away with it + if (Config::get('rate_limit') > 0) { + while (!feof($fp)) { + echo fread($fp,round(Config::get('rate_limit')*1024)); + $bytesStreamed += round(Config::get('rate_limit')*1024); + flush(); + sleep(1); + } + } + else { + fpassthru($fp); + } + + // Make sure that a good chunk of the song has been played + if ($bytesStreamed >= $media->size) { + debug_event('Play','Downloaded, Registering stats for ' . $media->title,'5'); + $GLOBALS['user']->update_stats($media->id); + } // if enough bytes are streamed + + fclose($fp); + exit(); } // if they are trying to download and they can @@ -300,15 +300,15 @@ // We're about to start. Record this user's IP. if (Config::get('track_user_ip')) { - $GLOBALS['user']->insert_ip_history(); + $GLOBALS['user']->insert_ip_history(); } $force_downsample = false; if (Config::get('downsample_remote')) { - if (!Access::check_network('network', $GLOBALS['user']->id,'0')) { - debug_event('play', 'Downsampling enabled for non-local address ' . $_SERVER['REMOTE_ADDR'], 5); - $force_downsample = true; - } + if (!Access::check_network('network', $GLOBALS['user']->id,'0')) { + debug_event('play', 'Downsampling enabled for non-local address ' . $_SERVER['REMOTE_ADDR'], 5); + $force_downsample = true; + } } // Determine whether to transcode @@ -316,53 +316,53 @@ $transcode_cfg = Config::get('transcode'); $valid_types = $media->get_stream_types(); if ($transcode_cfg != 'never' && in_array('transcode', $valid_types)) { - if ($transcode_cfg == 'always') { - $transcode = true; - debug_event('play', 'Transcoding due to always', 5); - } - else if ($force_downsample) { - $transcode = true; - debug_event('play', 'Transcoding due to downsample_remote', 5); - } - else if (!in_array('native', $valid_types)) { - $transcode = true; - debug_event('play', 'Transcoding because native streaming is unavailable', 5); - } - else { - debug_event('play', 'Decided not to transcode', 5); - } + if ($transcode_cfg == 'always') { + $transcode = true; + debug_event('play', 'Transcoding due to always', 5); + } + else if ($force_downsample) { + $transcode = true; + debug_event('play', 'Transcoding due to downsample_remote', 5); + } + else if (!in_array('native', $valid_types)) { + $transcode = true; + debug_event('play', 'Transcoding because native streaming is unavailable', 5); + } + else { + debug_event('play', 'Decided not to transcode', 5); + } } if ($transcode) { - header('Accept-Ranges: none'); - $transcoder = Stream::start_transcode($media); - $fp = $transcoder['handle']; - $media_name = $media->f_artist_full . " - " . $media->title . "." . $transcoder['format']; + header('Accept-Ranges: none'); + $transcoder = Stream::start_transcode($media); + $fp = $transcoder['handle']; + $media_name = $media->f_artist_full . " - " . $media->title . "." . $transcoder['format']; } else if (!in_array('native', $valid_types)) { - debug_event('play', 'Not transcoding and native streaming is not supported, aborting', 2); - exit(); + debug_event('play', 'Not transcoding and native streaming is not supported, aborting', 2); + exit(); } else { - header('Accept-Ranges: bytes'); - $fp = fopen($media->file, 'rb'); + header('Accept-Ranges: bytes'); + $fp = fopen($media->file, 'rb'); } if (!is_resource($fp)) { - debug_event('play', "Failed to open $media->file for streaming", 2); - exit(); + debug_event('play', "Failed to open $media->file for streaming", 2); + exit(); } // Put this song in the now_playing table only if it's a song for now... if (get_class($media) == 'Song') { - Stream::insert_now_playing($media->id,$uid,$media->time,$sid,get_class($media)); + Stream::insert_now_playing($media->id,$uid,$media->time,$sid,get_class($media)); } if ($transcode) { - $stream_size = null; + $stream_size = null; } else { - $stream_size = $media->size; + $stream_size = $media->size; } // Handle Content-Range @@ -370,35 +370,35 @@ sscanf($_SERVER['HTTP_RANGE'], "bytes=%d-%d", $start, $end); if ($start > 0 || $end > 0 ) { - // Calculate stream size from byte range - if (isset($end)) { - $end = min($end, $media->size - 1); - $stream_size = ($end - $start) + 1; - } - else { - $stream_size = $media->size - $start; - } - - if ($transcode) { - debug_event('play', 'Bad client behaviour. Content-Range header received, which we cannot fulfill due to transcoding', 2); - $stream_size = null; - } - else { - debug_event('play', 'Content-Range header received, skipping ' . $start . ' bytes out of ' . $media->size, 5); - fseek($fp, $start); - - $range = $start . '-' . $end . '/' . $media->size; - header('HTTP/1.1 206 Partial Content'); - header('Content-Range: bytes ' . $range); - } + // Calculate stream size from byte range + if (isset($end)) { + $end = min($end, $media->size - 1); + $stream_size = ($end - $start) + 1; + } + else { + $stream_size = $media->size - $start; + } + + if ($transcode) { + debug_event('play', 'Bad client behaviour. Content-Range header received, which we cannot fulfill due to transcoding', 2); + $stream_size = null; + } + else { + debug_event('play', 'Content-Range header received, skipping ' . $start . ' bytes out of ' . $media->size, 5); + fseek($fp, $start); + + $range = $start . '-' . $end . '/' . $media->size; + header('HTTP/1.1 206 Partial Content'); + header('Content-Range: bytes ' . $range); + } } else { - debug_event('play','Starting stream of ' . $media->file . ' with size ' . $media->size, 5); + debug_event('play','Starting stream of ' . $media->file . ' with size ' . $media->size, 5); } $mime = $transcode - ? $media->type_to_mime($transcoder['format']) - : $media->mime; + ? $media->type_to_mime($transcoder['format']) + : $media->mime; $browser->downloadHeaders($media_name, $mime, false, $stream_size); @@ -406,48 +406,48 @@ // Actually do the streaming do { - $read_size = $transcode - ? 2048 - : min(2048, $stream_size - $bytes_streamed); - $buf = fread($fp, $read_size); - print($buf); - $bytes_streamed += strlen($buf); + $read_size = $transcode + ? 2048 + : min(2048, $stream_size - $bytes_streamed); + $buf = fread($fp, $read_size); + print($buf); + $bytes_streamed += strlen($buf); } while (!feof($fp) && (connection_status() == 0) && ($transcode || $bytes_streamed < $stream_size)); $real_bytes_streamed = $bytes_streamed; // Need to make sure enough bytes were sent. if($bytes_streamed < $stream_size && (connection_status() == 0)) { - print(str_repeat(' ', $stream_size - $bytes_streamed)); - $bytes_streamed = $stream_size; + print(str_repeat(' ', $stream_size - $bytes_streamed)); + $bytes_streamed = $stream_size; } // Make sure that a good chunk of the song has been played $target = 131072; if ($stream_size) { - if ($stream_size > 1048576) { - $target = 262144; - } - else if ($stream_size < 360448) { - $target = $stream_size / 1.1; - } - else { - $target = $stream_size / 4; - } + if ($stream_size > 1048576) { + $target = 262144; + } + else if ($stream_size < 360448) { + $target = $stream_size / 1.1; + } + else { + $target = $stream_size / 4; + } } if ($start > $target) { - debug_event('play', 'Content-Range was more than ' . $target . ' into the file, not collecting stats', 5); + debug_event('play', 'Content-Range was more than ' . $target . ' into the file, not collecting stats', 5); } else if ($bytes_streamed > $target) { - // FIXME: This check looks suspicious - if (get_class($media) == 'Song') { - debug_event('play', 'Registering stats for ' . $media->title, 5); - $GLOBALS['user']->update_stats($media->id); - $media->set_played(); - } + // FIXME: This check looks suspicious + if (get_class($media) == 'Song') { + debug_event('play', 'Registering stats for ' . $media->title, 5); + $GLOBALS['user']->update_stats($media->id); + $media->set_played(); + } } else { - debug_event('play', $bytes_streamed .' of ' . $stream_size . ' streamed; not collecting stats', 5); + debug_event('play', $bytes_streamed .' of ' . $stream_size . ' streamed; not collecting stats', 5); } // If this is a democratic playlist remove the entry. @@ -455,10 +455,10 @@ if ($demo_id) { $democratic->delete_from_oid($oid,'song'); } if ($transcode) { - pclose($fp); + pclose($fp); } else { - fclose($fp); + fclose($fp); } debug_event('play', 'Stream ended at ' . $bytes_streamed . ' (' . $real_bytes_streamed . ') bytes out of ' . $stream_size, 5); diff --git a/playlist.php b/playlist.php index b91f013604..480b194fdf 100644 --- a/playlist.php +++ b/playlist.php @@ -1,5 +1,5 @@ has_access()) { - $playlist->delete(); - // Go elsewhere - header('Location: ' . Config::get('web_path') . '/browse.php?action=playlist'); - } + // Check rights + $playlist = new Playlist($_REQUEST['playlist_id']); + if ($playlist->has_access()) { + $playlist->delete(); + // Go elsewhere + header('Location: ' . Config::get('web_path') . '/browse.php?action=playlist'); + } } UI::show_header(); @@ -40,88 +40,88 @@ /* Switch on the action passed in */ switch ($_REQUEST['action']) { - case 'add_dyn_song': - /* Check Rights */ - if (!$playlist->has_access()) { - UI::access_denied(); - break; - } - - $playlist->add_dyn_song(); - $_SESSION['data']['playlist_id'] = $playlist->id; - show_playlist($playlist); - break; - case 'create_playlist': - /* Check rights */ - if (!Access::check('interface','25')) { - UI::access_denied(); - break; - } - - $playlist_name = scrub_in($_REQUEST['playlist_name']); - $playlist_type = scrub_in($_REQUEST['type']); - - $playlist->create($playlist_name,$playlist_type); - $_SESSION['data']['playlist_id'] = $playlist->id; - show_confirmation(T_('Playlist Created'), sprintf(T_('%1$s (%2$s) has been created'), $playlist_name, $playlist_type),'playlist.php'); - break; - case 'delete_playlist': - // If we made it here, we didn't have sufficient rights. - UI::access_denied(); - break; - case 'remove_song': - /* Check em for rights */ - if (!$playlist->has_access()) { - UI::access_denied(); - break; - } - $playlist->remove_songs($_REQUEST['song']); - show_playlist($playlist); - break; - case 'show_playlist': - $playlist = new Playlist($_REQUEST['playlist_id']); - $playlist->format(); - $object_ids = $playlist->get_items(); - require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; - break; - case 'show_import_playlist': - require_once Config::get('prefix') . '/templates/show_import_playlist.inc.php'; - break; - case 'import_playlist': - /* first we rename the file to it's original name before importing. - Otherwise the playlist name will have the $_FILES['filename']['tmp_name'] which doesn't look right... */ - $dir = dirname($_FILES['filename']['tmp_name']) . "/"; - $filename = $dir . basename($_FILES['filename']['name']); - move_uploaded_file($_FILES['filename']['tmp_name'], $filename ); - - $catalog = new Catalog(); - $result = $catalog->import_m3u($filename); - - if($result['success']) { - $url = 'show_playlist&playlist_id=' . $result['id']; - $title = T_('Playlist Imported'); - $body = basename($_FILES['filename']['name']); - $body .= '
    ' . - sprintf( - T_ngettext( - 'Successfully imported playlist with %d song.', - 'Successfully imported playlist with %d songs.', - $result['count']), - $result['count']); - } - else { - $url = 'show_import_playlist'; - $title = T_('Playlist Not Imported'); - $body = T_($result['error']); - } - show_confirmation($title, $body, Config::get('web_path') . '/playlist.php?action=' . $url); - break; - case 'set_track_numbers': - /* Make sure they have permission */ - if (!$playlist->has_access()) { - UI::access_denied(); - break; - } + case 'add_dyn_song': + /* Check Rights */ + if (!$playlist->has_access()) { + UI::access_denied(); + break; + } + + $playlist->add_dyn_song(); + $_SESSION['data']['playlist_id'] = $playlist->id; + show_playlist($playlist); + break; + case 'create_playlist': + /* Check rights */ + if (!Access::check('interface','25')) { + UI::access_denied(); + break; + } + + $playlist_name = scrub_in($_REQUEST['playlist_name']); + $playlist_type = scrub_in($_REQUEST['type']); + + $playlist->create($playlist_name,$playlist_type); + $_SESSION['data']['playlist_id'] = $playlist->id; + show_confirmation(T_('Playlist Created'), sprintf(T_('%1$s (%2$s) has been created'), $playlist_name, $playlist_type),'playlist.php'); + break; + case 'delete_playlist': + // If we made it here, we didn't have sufficient rights. + UI::access_denied(); + break; + case 'remove_song': + /* Check em for rights */ + if (!$playlist->has_access()) { + UI::access_denied(); + break; + } + $playlist->remove_songs($_REQUEST['song']); + show_playlist($playlist); + break; + case 'show_playlist': + $playlist = new Playlist($_REQUEST['playlist_id']); + $playlist->format(); + $object_ids = $playlist->get_items(); + require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; + break; + case 'show_import_playlist': + require_once Config::get('prefix') . '/templates/show_import_playlist.inc.php'; + break; + case 'import_playlist': + /* first we rename the file to it's original name before importing. + Otherwise the playlist name will have the $_FILES['filename']['tmp_name'] which doesn't look right... */ + $dir = dirname($_FILES['filename']['tmp_name']) . "/"; + $filename = $dir . basename($_FILES['filename']['name']); + move_uploaded_file($_FILES['filename']['tmp_name'], $filename ); + + $catalog = new Catalog(); + $result = $catalog->import_m3u($filename); + + if($result['success']) { + $url = 'show_playlist&playlist_id=' . $result['id']; + $title = T_('Playlist Imported'); + $body = basename($_FILES['filename']['name']); + $body .= '
    ' . + sprintf( + T_ngettext( + 'Successfully imported playlist with %d song.', + 'Successfully imported playlist with %d songs.', + $result['count']), + $result['count']); + } + else { + $url = 'show_import_playlist'; + $title = T_('Playlist Not Imported'); + $body = T_($result['error']); + } + show_confirmation($title, $body, Config::get('web_path') . '/playlist.php?action=' . $url); + break; + case 'set_track_numbers': + /* Make sure they have permission */ + if (!$playlist->has_access()) { + UI::access_denied(); + break; + } $song_ids = scrub_in($_REQUEST['song']); foreach ($song_ids as $song_id) { $track = scrub_in($_REQUEST['tr_' . $song_id]); @@ -132,34 +132,34 @@ show_playlist($playlist); break; - case 'prune_empty': - /* Make sure they have permission */ - if (!$GLOBALS['user']->has_access(100)) { - UI::access_denied(); - break; - } - - prune_empty_playlists(); - $url = Config::get('web_path') . '/playlist.php'; - $title = T_('Empty Playlists Deleted'); - $body = ''; - show_confirmation($title,$body,$url); - break; - case 'normalize_tracks': - $playlist = new Playlist($_REQUEST['playlist_id']); - - /* Make sure they have permission */ - if (!$playlist->has_access()) { - UI::access_denied(); - break; - } - - /* Normalize the tracks */ - $playlist->normalize_tracks(); - $object_ids = $playlist->get_items(); - default: - require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; - break; + case 'prune_empty': + /* Make sure they have permission */ + if (!$GLOBALS['user']->has_access(100)) { + UI::access_denied(); + break; + } + + prune_empty_playlists(); + $url = Config::get('web_path') . '/playlist.php'; + $title = T_('Empty Playlists Deleted'); + $body = ''; + show_confirmation($title,$body,$url); + break; + case 'normalize_tracks': + $playlist = new Playlist($_REQUEST['playlist_id']); + + /* Make sure they have permission */ + if (!$playlist->has_access()) { + UI::access_denied(); + break; + } + + /* Normalize the tracks */ + $playlist->normalize_tracks(); + $object_ids = $playlist->get_items(); + default: + require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; + break; } // switch on the action UI::show_footer(); diff --git a/preferences.php b/preferences.php index 1b7e0f676c..39fde752bd 100644 --- a/preferences.php +++ b/preferences.php @@ -1,5 +1,5 @@ id; - $fullname = $GLOBALS['user']->fullname; - } - - /* Update and reset preferences */ - update_preferences($user_id); - Preference::init(); - - // Reset gettext so that it's clear whether the preference took - // FIXME: do we need to do any header fiddling? - load_gettext(); - - $preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab'], $system); - break; - case 'admin_update_preferences': - // Make sure only admins here - if (!Access::check('interface','100')) { - UI::access_denied(); - exit; - } - - if (!Core::form_verify('update_preference','post')) { - UI::access_denied(); - exit; - } - - update_preferences($_POST['user_id']); - header("Location: " . Config::get('web_path') . "/admin/users.php?action=show_preferences&user_id=" . scrub_out($_POST['user_id'])); - break; - case 'admin': - // Make sure only admins here - if (!Access::check('interface','100')) { - UI::access_denied(); - exit; - } - $fullname= T_('Server'); - $preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab'], true); - break; - case 'user': - if (!Access::check('interface','100')) { - UI::access_denied(); - exit; - } - $client = new User($_REQUEST['user_id']); - $fullname = $client->fullname; - $preferences = $client->get_preferences($_REQUEST['tab']); - break; - case 'update_user': - // Make sure we're a user and they came from the form - if (!Access::check('interface','25') OR !Config::get('use_auth')) { - UI::access_denied(); - exit; - } - - if (!Core::form_verify('update_user','post')) { - UI::access_denied(); - exit; - } - - // Remove the value - unset($_SESSION['forms']['account']); - - // Don't let them change access, or username here - unset($_POST['access']); - $_POST['username'] = $GLOBALS['user']->username; - - if (!$GLOBALS['user']->update($_POST)) { - Error::add('general', T_('Error Update Failed')); - } - else { - $_REQUEST['action'] = 'confirm'; - $title = T_('Updated'); - $text = T_('Your Account has been updated'); - $next_url = Config::get('web_path') . '/preferences.php?tab=account'; - } - break; - default: - $fullname = $GLOBALS['user']->fullname; - $preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab']); - break; + case 'update_preferences': + if ($_POST['method'] == 'admin' && !Access::check('interface','100')) { + UI::access_denied(); + exit; + } + + if (!Core::form_verify('update_preference','post')) { + UI::access_denied(); + exit; + } + + /* Reset the Theme */ + if ($_POST['method'] == 'admin') { + $user_id = '-1'; + $system = true; + $fullname = T_('Server'); + $_REQUEST['action'] = 'admin'; + } + else { + $user_id = $GLOBALS['user']->id; + $fullname = $GLOBALS['user']->fullname; + } + + /* Update and reset preferences */ + update_preferences($user_id); + Preference::init(); + + // Reset gettext so that it's clear whether the preference took + // FIXME: do we need to do any header fiddling? + load_gettext(); + + $preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab'], $system); + break; + case 'admin_update_preferences': + // Make sure only admins here + if (!Access::check('interface','100')) { + UI::access_denied(); + exit; + } + + if (!Core::form_verify('update_preference','post')) { + UI::access_denied(); + exit; + } + + update_preferences($_POST['user_id']); + header("Location: " . Config::get('web_path') . "/admin/users.php?action=show_preferences&user_id=" . scrub_out($_POST['user_id'])); + break; + case 'admin': + // Make sure only admins here + if (!Access::check('interface','100')) { + UI::access_denied(); + exit; + } + $fullname= T_('Server'); + $preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab'], true); + break; + case 'user': + if (!Access::check('interface','100')) { + UI::access_denied(); + exit; + } + $client = new User($_REQUEST['user_id']); + $fullname = $client->fullname; + $preferences = $client->get_preferences($_REQUEST['tab']); + break; + case 'update_user': + // Make sure we're a user and they came from the form + if (!Access::check('interface','25') OR !Config::get('use_auth')) { + UI::access_denied(); + exit; + } + + if (!Core::form_verify('update_user','post')) { + UI::access_denied(); + exit; + } + + // Remove the value + unset($_SESSION['forms']['account']); + + // Don't let them change access, or username here + unset($_POST['access']); + $_POST['username'] = $GLOBALS['user']->username; + + if (!$GLOBALS['user']->update($_POST)) { + Error::add('general', T_('Error Update Failed')); + } + else { + $_REQUEST['action'] = 'confirm'; + $title = T_('Updated'); + $text = T_('Your Account has been updated'); + $next_url = Config::get('web_path') . '/preferences.php?tab=account'; + } + break; + default: + $fullname = $GLOBALS['user']->fullname; + $preferences = $GLOBALS['user']->get_preferences($_REQUEST['tab']); + break; } // End Switch Action UI::show_header(); @@ -131,13 +131,13 @@ * switch on the view */ switch ($_REQUEST['action']) { - case 'confirm': - show_confirmation($title,$text,$next_url,$cancel); - break; - default: - // Show the default preferences page - require Config::get('prefix') . '/templates/show_preferences.inc.php'; - break; + case 'confirm': + show_confirmation($title,$text,$next_url,$cancel); + break; + default: + // Show the default preferences page + require Config::get('prefix') . '/templates/show_preferences.inc.php'; + break; } // end switch on action UI::show_footer(); diff --git a/radio.php b/radio.php index 360c1ff7d5..e158b1bee4 100644 --- a/radio.php +++ b/radio.php @@ -1,5 +1,5 @@ playlist->add_object($object_id, 'song'); - } - case 'advanced': - default: - require_once Config::get('prefix') . '/templates/show_random.inc.php'; - break; + // We need to add them to the active playlist + foreach ($object_ids as $object_id) { + $GLOBALS['user']->playlist->add_object($object_id, 'song'); + } + case 'advanced': + default: + require_once Config::get('prefix') . '/templates/show_random.inc.php'; + break; } // end switch UI::show_footer(); diff --git a/register.php b/register.php index f96affed0b..68f0c06566 100644 --- a/register.php +++ b/register.php @@ -1,5 +1,5 @@ must accept the user agreement")); - } - } // if they have to agree to something - - if (!$_POST['username']) { - Error::add('username', T_("You did not enter a username")); - } - - if(!$fullname) { - Error::add('fullname', T_("Please fill in your full name (Firstname Lastname)")); - } - - /* Check the mail for correct address formation. */ - $attempt = 0; - $max_attempts = 3; - $response_code = ""; - - while ( $response_code == "" || strstr( $response_code, "fsockopen error" )) { - $validate_results = validateEmail( $email ); - $response_code = $validate_results[1]; - if($attempt == $max_attempts) { - break; - } - $attempt++; - } - - if ($validate_results[0] OR strstr($validate_results[1],"greylist")) { - $mmsg = "MAILOK"; - } - else { - Error::add('email', T_("Error Email address not confirmed") - . "
    $validate_results[1]"); - } - /* End of mailcheck */ - - if (!$pass1) { - Error::add('password', T_("You must enter a password")); - } - - if ( $pass1 != $pass2 ) { - Error::add('password', T_("Your passwords do not match")); - } - - if (!User::check_username($username)) { - Error::add('duplicate_user', T_("Error Username already exists")); - } - - // If we've hit an error anywhere up there break! - if (Error::occurred()) { - require_once Config::get('prefix') . '/templates/show_user_registration.inc.php'; - break; - } - - /* Attempt to create the new user */ - $access = '5'; - switch (Config::get('auto_user')) { - case 'admin': - $access = '100'; - break; - case 'user': - $access = '25'; - break; - default: - case 'guest': - $access = '5'; - break; - } // auto-user level - - - $new_user = User::create($username, $fullname, $email, $pass1, - $access, Config::get('admin_enable_required')); - - if (!$new_user) { - Error::add('duplicate_user', T_("Error: Insert Failed")); - require_once Config::get('prefix') . '/templates/show_user_registration.inc.php'; - break; - } - - $client = new User($new_user); - $validation = md5(uniqid(rand(), true)); - $client->update_validation($validation); - - Registration::send_confirmation($username, $fullname, $email, $pass1, $validation); - require_once Config::get('prefix') . '/templates/show_registration_confirmation.inc.php'; - break; - case 'show_add_user': - default: - require_once Config::get('prefix') . '/templates/show_user_registration.inc.php'; - break; + case 'validate': + $username = scrub_in($_GET['username']); + $validation = scrub_in($_GET['auth']); + require_once Config::get('prefix') . '/templates/show_user_activate.inc.php'; + break; + case 'add_user': + /** + * User information has been entered + * we need to check the database for possible existing username first + * if username exists, error and say "Please choose a different name." + * if username does not exist, insert user information into database + * then allow the user to 'click here to login' + * possibly by logging them in right then and there with their current info + * and 'click here to login' would just be a link back to index.php + */ + $fullname = scrub_in($_POST['fullname']); + $username = scrub_in($_POST['username']); + $email = scrub_in($_POST['email']); + $pass1 = scrub_in($_POST['password_1']); + $pass2 = scrub_in($_POST['password_2']); + + /* If we're using the captcha stuff */ + if (Config::get('captcha_public_reg')) { + $captcha = captcha::solved(); + if(!isset ($captcha)) { + Error::add('captcha', T_('Error Captcha Required')); + } + if (isset ($captcha)) { + if ($captcha) { + $msg="SUCCESS"; + } + else { + Error::add('captcha', T_('Error Captcha Failed')); + } + } // end if we've got captcha + } // end if it's enabled + + if (Config::get('user_agreement')) { + if (!$_POST['accept_agreement']) { + Error::add('user_agreement', T_("You must accept the user agreement")); + } + } // if they have to agree to something + + if (!$_POST['username']) { + Error::add('username', T_("You did not enter a username")); + } + + if(!$fullname) { + Error::add('fullname', T_("Please fill in your full name (Firstname Lastname)")); + } + + /* Check the mail for correct address formation. */ + $attempt = 0; + $max_attempts = 3; + $response_code = ""; + + while ( $response_code == "" || strstr( $response_code, "fsockopen error" )) { + $validate_results = validateEmail( $email ); + $response_code = $validate_results[1]; + if($attempt == $max_attempts) { + break; + } + $attempt++; + } + + if ($validate_results[0] OR strstr($validate_results[1],"greylist")) { + $mmsg = "MAILOK"; + } + else { + Error::add('email', T_("Error Email address not confirmed") + . "
    $validate_results[1]"); + } + /* End of mailcheck */ + + if (!$pass1) { + Error::add('password', T_("You must enter a password")); + } + + if ( $pass1 != $pass2 ) { + Error::add('password', T_("Your passwords do not match")); + } + + if (!User::check_username($username)) { + Error::add('duplicate_user', T_("Error Username already exists")); + } + + // If we've hit an error anywhere up there break! + if (Error::occurred()) { + require_once Config::get('prefix') . '/templates/show_user_registration.inc.php'; + break; + } + + /* Attempt to create the new user */ + $access = '5'; + switch (Config::get('auto_user')) { + case 'admin': + $access = '100'; + break; + case 'user': + $access = '25'; + break; + default: + case 'guest': + $access = '5'; + break; + } // auto-user level + + + $new_user = User::create($username, $fullname, $email, $pass1, + $access, Config::get('admin_enable_required')); + + if (!$new_user) { + Error::add('duplicate_user', T_("Error: Insert Failed")); + require_once Config::get('prefix') . '/templates/show_user_registration.inc.php'; + break; + } + + $client = new User($new_user); + $validation = md5(uniqid(rand(), true)); + $client->update_validation($validation); + + Registration::send_confirmation($username, $fullname, $email, $pass1, $validation); + require_once Config::get('prefix') . '/templates/show_registration_confirmation.inc.php'; + break; + case 'show_add_user': + default: + require_once Config::get('prefix') . '/templates/show_user_registration.inc.php'; + break; } // end switch on action ?> diff --git a/rss.php b/rss.php index 5f694cc180..091d64a574 100644 --- a/rss.php +++ b/rss.php @@ -1,5 +1,5 @@ set_type($_REQUEST['type']); - $browse->show_objects($results); - $browse->store(); - break; - case 'save_as_track': - $playlist_id = save_search($_REQUEST); - $playlist = new Playlist($playlist_id); - show_confirmation(T_('Search Saved'),sprintf(T_('Your Search has been saved as a track in %s'), $playlist->name), Config::get('web_path') . "/search.php"); - break; - case 'save_as_smartplaylist': - $playlist = new Search(); - $playlist->parse_rules(Search::clean_request($_REQUEST)); - $playlist->save(); - default: - require_once Config::get('prefix') . '/templates/show_search.inc.php'; - break; - case 'descriptor': - // This is a little special we don't want header/footers so trash what we've got in the OB - ob_clean(); - require_once Config::get('prefix') . '/templates/show_search_descriptor.inc.php'; - exit; - break; + case 'search': + $browse = new Browse(); + require_once Config::get('prefix') . '/templates/show_search.inc.php'; + require_once Config::get('prefix') . '/templates/show_search_options.inc.php'; + $results = Search::run($_REQUEST); + $browse->set_type($_REQUEST['type']); + $browse->show_objects($results); + $browse->store(); + break; + case 'save_as_track': + $playlist_id = save_search($_REQUEST); + $playlist = new Playlist($playlist_id); + show_confirmation(T_('Search Saved'),sprintf(T_('Your Search has been saved as a track in %s'), $playlist->name), Config::get('web_path') . "/search.php"); + break; + case 'save_as_smartplaylist': + $playlist = new Search(); + $playlist->parse_rules(Search::clean_request($_REQUEST)); + $playlist->save(); + default: + require_once Config::get('prefix') . '/templates/show_search.inc.php'; + break; + case 'descriptor': + // This is a little special we don't want header/footers so trash what we've got in the OB + ob_clean(); + require_once Config::get('prefix') . '/templates/show_search_descriptor.inc.php'; + exit; + break; } /* Show the Footer */ diff --git a/server/ajax.server.php b/server/ajax.server.php index 55739b8d2f..52175876e9 100644 --- a/server/ajax.server.php +++ b/server/ajax.server.php @@ -1,5 +1,5 @@ format(); - break; - case 'artist_row': - $key = 'artist_' . $_GET['id']; - $artist = new Artist($_GET['id']); - $artist->format(); - break; - case 'song_row': - $key = 'song_' . $_GET['id']; - $song = new Song($_GET['id']); - $song->format(); - break; - case 'live_stream_row': - $key = 'live_stream_' . $_GET['id']; - $radio = new Radio($_GET['id']); - $radio->format(); - break; - case 'playlist_row': - case 'playlist_title': - $key = 'playlist_row_' . $_GET['id']; - $playlist = new Playlist($_GET['id']); - $playlist->format(); - // If the current user is the owner, only user is required - if ($playlist->user == $GLOBALS['user']->id) { - $level = '25'; - } - break; - case 'smartplaylist_row': - case 'smartplaylist_title': - $key = 'playlist_row_' . $_GET['id']; - $playlist = new Search('song', $_GET['id']); - $playlist->format(); - if ($playlist->user == $GLOBALS['user']->id) { - $level = '25'; - } - break; - default: - $key = 'rfc3514'; - echo xml_from_array(array($key=>'0x1')); - exit; - break; - } // end switch on type + switch ($_GET['type']) { + case 'album_row': + $key = 'album_' . $_GET['id']; + $album = new Album($_GET['id']); + $album->format(); + break; + case 'artist_row': + $key = 'artist_' . $_GET['id']; + $artist = new Artist($_GET['id']); + $artist->format(); + break; + case 'song_row': + $key = 'song_' . $_GET['id']; + $song = new Song($_GET['id']); + $song->format(); + break; + case 'live_stream_row': + $key = 'live_stream_' . $_GET['id']; + $radio = new Radio($_GET['id']); + $radio->format(); + break; + case 'playlist_row': + case 'playlist_title': + $key = 'playlist_row_' . $_GET['id']; + $playlist = new Playlist($_GET['id']); + $playlist->format(); + // If the current user is the owner, only user is required + if ($playlist->user == $GLOBALS['user']->id) { + $level = '25'; + } + break; + case 'smartplaylist_row': + case 'smartplaylist_title': + $key = 'playlist_row_' . $_GET['id']; + $playlist = new Search('song', $_GET['id']); + $playlist->format(); + if ($playlist->user == $GLOBALS['user']->id) { + $level = '25'; + } + break; + default: + $key = 'rfc3514'; + echo xml_from_array(array($key=>'0x1')); + exit; + break; + } // end switch on type - // Make sure they got them rights - if (!Access::check('interface',$level)) { - $results['rfc3514'] = '0x1'; - break; - } + // Make sure they got them rights + if (!Access::check('interface',$level)) { + $results['rfc3514'] = '0x1'; + break; + } - ob_start(); - require Config::get('prefix') . '/templates/show_edit_' . $_GET['type'] . '.inc.php'; - $results[$key] = ob_get_contents(); - ob_end_clean(); - break; - case 'edit_object': + ob_start(); + require Config::get('prefix') . '/templates/show_edit_' . $_GET['type'] . '.inc.php'; + $results[$key] = ob_get_contents(); + ob_end_clean(); + break; + case 'edit_object': - $level = '50'; + $level = '50'; - if ($_POST['type'] == 'playlist_row' || $_POST['type'] == 'playlist_title') { - $playlist = new Playlist($_POST['id']); - if ($GLOBALS['user']->id == $playlist->user) { - $level = '25'; - } - } - if ($_POST['type'] == 'smartplaylist_row' || - $_POST['type'] == 'smartplaylist_title') { - $playlist = new Search('song', $_POST['id']); - if ($GLOBALS['user']->id == $playlist->user) { - $level = '25'; - } - } + if ($_POST['type'] == 'playlist_row' || $_POST['type'] == 'playlist_title') { + $playlist = new Playlist($_POST['id']); + if ($GLOBALS['user']->id == $playlist->user) { + $level = '25'; + } + } + if ($_POST['type'] == 'smartplaylist_row' || + $_POST['type'] == 'smartplaylist_title') { + $playlist = new Search('song', $_POST['id']); + if ($GLOBALS['user']->id == $playlist->user) { + $level = '25'; + } + } - // Make sure we've got them rights - if (!Access::check('interface',$level) || Config::get('demo_mode')) { - $results['rfc3514'] = '0x1'; - break; - } + // Make sure we've got them rights + if (!Access::check('interface',$level) || Config::get('demo_mode')) { + $results['rfc3514'] = '0x1'; + break; + } - switch ($_POST['type']) { - case 'album_row': - $key = 'album_' . $_POST['id']; - $album = new Album($_POST['id']); - $songs = $album->get_songs(); - $new_id = $album->update($_POST); - if ($new_id != $_POST['id']) { - $album = new Album($new_id); - foreach ($songs as $song_id) { - Flag::add($song_id,'song','retag','Inline Album Update'); - } - } - $album->format(); - break; - case 'artist_row': - $key = 'artist_' . $_POST['id']; - $artist = new Artist($_POST['id']); - $songs = $artist->get_songs(); - $new_id = $artist->update($_POST); - if ($new_id != $_POST['id']) { - $artist = new Artist($new_id); - foreach ($songs as $song_id) { - Flag::add($song_id,'song','retag','Inline Artist Update'); - } - } - $artist->format(); - break; - case 'song_row': - $key = 'song_' . $_POST['id']; - $song = new Song($_POST['id']); - Flag::add($song->id,'song','retag','Inline Single Song Update'); - $song->update($_POST); - $song->format(); - break; - case 'playlist_row': - case 'playlist_title': - $key = 'playlist_row_' . $_POST['id']; - $playlist->update($_POST); - $playlist->format(); - $count = $playlist->get_song_count(); - break; - case 'smartplaylist_row': - case 'smartplaylist_title': - $key = 'playlist_row_' . $_POST['id']; - $playlist->name = $_POST['name']; - $playlist->type = $_POST['pl_type']; - $playlist->update(); - $playlist->format(); - break; - case 'live_stream_row': - $key = 'live_stream_' . $_POST['id']; - Radio::update($_POST); - $radio = new Radio($_POST['id']); - $radio->format(); - break; - default: - $key = 'rfc3514'; - echo xml_from_array(array($key=>'0x1')); - exit; - break; - } // end switch on type + switch ($_POST['type']) { + case 'album_row': + $key = 'album_' . $_POST['id']; + $album = new Album($_POST['id']); + $songs = $album->get_songs(); + $new_id = $album->update($_POST); + if ($new_id != $_POST['id']) { + $album = new Album($new_id); + foreach ($songs as $song_id) { + Flag::add($song_id,'song','retag','Inline Album Update'); + } + } + $album->format(); + break; + case 'artist_row': + $key = 'artist_' . $_POST['id']; + $artist = new Artist($_POST['id']); + $songs = $artist->get_songs(); + $new_id = $artist->update($_POST); + if ($new_id != $_POST['id']) { + $artist = new Artist($new_id); + foreach ($songs as $song_id) { + Flag::add($song_id,'song','retag','Inline Artist Update'); + } + } + $artist->format(); + break; + case 'song_row': + $key = 'song_' . $_POST['id']; + $song = new Song($_POST['id']); + Flag::add($song->id,'song','retag','Inline Single Song Update'); + $song->update($_POST); + $song->format(); + break; + case 'playlist_row': + case 'playlist_title': + $key = 'playlist_row_' . $_POST['id']; + $playlist->update($_POST); + $playlist->format(); + $count = $playlist->get_song_count(); + break; + case 'smartplaylist_row': + case 'smartplaylist_title': + $key = 'playlist_row_' . $_POST['id']; + $playlist->name = $_POST['name']; + $playlist->type = $_POST['pl_type']; + $playlist->update(); + $playlist->format(); + break; + case 'live_stream_row': + $key = 'live_stream_' . $_POST['id']; + Radio::update($_POST); + $radio = new Radio($_POST['id']); + $radio->format(); + break; + default: + $key = 'rfc3514'; + echo xml_from_array(array($key=>'0x1')); + exit; + break; + } // end switch on type - ob_start(); - require Config::get('prefix') . '/templates/show_' . $_POST['type'] . '.inc.php'; - $results[$key] = ob_get_contents(); - ob_end_clean(); - break; - case 'current_playlist': - switch ($_REQUEST['type']) { - case 'delete': - $GLOBALS['user']->playlist->delete_track($_REQUEST['id']); - break; - } // end switch + ob_start(); + require Config::get('prefix') . '/templates/show_' . $_POST['type'] . '.inc.php'; + $results[$key] = ob_get_contents(); + ob_end_clean(); + break; + case 'current_playlist': + switch ($_REQUEST['type']) { + case 'delete': + $GLOBALS['user']->playlist->delete_track($_REQUEST['id']); + break; + } // end switch - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); - break; - // Handle the users basketcases... - case 'basket': - switch ($_REQUEST['type']) { - case 'album': - case 'artist': - case 'tag': - $object = new $_REQUEST['type']($_REQUEST['id']); - $songs = $object->get_songs(); - foreach ($songs as $song_id) { - $GLOBALS['user']->playlist->add_object($song_id,'song'); - } // end foreach - break; - case 'browse_set': - $browse = new Browse($_REQUEST['browse_id']); - $objects = $browse->get_saved(); - foreach ($objects as $object_id) { - $GLOBALS['user']->playlist->add_object($object_id,'song'); - } - break; - case 'album_random': - case 'artist_random': - case 'tag_random': - $data = explode('_',$_REQUEST['type']); - $type = $data['0']; - $object = new $type($_REQUEST['id']); - $songs = $object->get_random_songs(); - foreach ($songs as $song_id) { - $GLOBALS['user']->playlist->add_object($song_id,'song'); - } - break; - case 'playlist': - $playlist = new Playlist($_REQUEST['id']); - $items = $playlist->get_items(); - foreach ($items as $item) { - $GLOBALS['user']->playlist->add_object($item['object_id'], $item['object_type']); - } - break; - case 'playlist_random': - $playlist = new Playlist($_REQUEST['id']); - $items = $playlist->get_random_items(); - foreach ($items as $item) { - $GLOBALS['user']->playlist->add_object($item['object_id'], $item['object_type']); - } - break; - case 'smartplaylist': - $playlist = new Search('song', $_REQUEST['id']); - $items = $playlist->get_items(); - foreach ($items as $item) { - $GLOBALS['user']->playlist->add_object($item['object_id'],$item['object_type']); - } - break; - case 'clear_all': - $GLOBALS['user']->playlist->clear(); - break; - case 'live_stream': - $object = new Radio($_REQUEST['id']); - // Confirm its a valid ID - if ($object->name) { - $GLOBALS['user']->playlist->add_object($object->id,'radio'); - } - break; - case 'dynamic': - $random_id = Random::get_type_id($_REQUEST['random_type']); - $GLOBALS['user']->playlist->add_object($random_id,'random'); - break; - case 'video': - $GLOBALS['user']->playlist->add_object($_REQUEST['id'],'video'); - break; - default: - case 'song': - $GLOBALS['user']->playlist->add_object($_REQUEST['id'],'song'); - break; - } // end switch + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + break; + // Handle the users basketcases... + case 'basket': + switch ($_REQUEST['type']) { + case 'album': + case 'artist': + case 'tag': + $object = new $_REQUEST['type']($_REQUEST['id']); + $songs = $object->get_songs(); + foreach ($songs as $song_id) { + $GLOBALS['user']->playlist->add_object($song_id,'song'); + } // end foreach + break; + case 'browse_set': + $browse = new Browse($_REQUEST['browse_id']); + $objects = $browse->get_saved(); + foreach ($objects as $object_id) { + $GLOBALS['user']->playlist->add_object($object_id,'song'); + } + break; + case 'album_random': + case 'artist_random': + case 'tag_random': + $data = explode('_',$_REQUEST['type']); + $type = $data['0']; + $object = new $type($_REQUEST['id']); + $songs = $object->get_random_songs(); + foreach ($songs as $song_id) { + $GLOBALS['user']->playlist->add_object($song_id,'song'); + } + break; + case 'playlist': + $playlist = new Playlist($_REQUEST['id']); + $items = $playlist->get_items(); + foreach ($items as $item) { + $GLOBALS['user']->playlist->add_object($item['object_id'], $item['object_type']); + } + break; + case 'playlist_random': + $playlist = new Playlist($_REQUEST['id']); + $items = $playlist->get_random_items(); + foreach ($items as $item) { + $GLOBALS['user']->playlist->add_object($item['object_id'], $item['object_type']); + } + break; + case 'smartplaylist': + $playlist = new Search('song', $_REQUEST['id']); + $items = $playlist->get_items(); + foreach ($items as $item) { + $GLOBALS['user']->playlist->add_object($item['object_id'],$item['object_type']); + } + break; + case 'clear_all': + $GLOBALS['user']->playlist->clear(); + break; + case 'live_stream': + $object = new Radio($_REQUEST['id']); + // Confirm its a valid ID + if ($object->name) { + $GLOBALS['user']->playlist->add_object($object->id,'radio'); + } + break; + case 'dynamic': + $random_id = Random::get_type_id($_REQUEST['random_type']); + $GLOBALS['user']->playlist->add_object($random_id,'random'); + break; + case 'video': + $GLOBALS['user']->playlist->add_object($_REQUEST['id'],'video'); + break; + default: + case 'song': + $GLOBALS['user']->playlist->add_object($_REQUEST['id'],'song'); + break; + } // end switch - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); - break; - /* Setting ratings */ - case 'set_rating': - ob_start(); - $rating = new Rating($_GET['object_id'], $_GET['rating_type']); - $rating->set_rating($_GET['rating']); - Rating::show($_GET['object_id'], $_GET['rating_type']); - $key = "rating_" . $_GET['object_id'] . "_" . $_GET['rating_type']; - $results[$key] = ob_get_contents(); - ob_end_clean(); - break; - default: - $results['rfc3514'] = '0x1'; - break; + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + break; + /* Setting ratings */ + case 'set_rating': + ob_start(); + $rating = new Rating($_GET['object_id'], $_GET['rating_type']); + $rating->set_rating($_GET['rating']); + Rating::show($_GET['object_id'], $_GET['rating_type']); + $key = "rating_" . $_GET['object_id'] . "_" . $_GET['rating_type']; + $results[$key] = ob_get_contents(); + ob_end_clean(); + break; + default: + $results['rfc3514'] = '0x1'; + break; } // end switch action // Go ahead and do the echo diff --git a/server/browse.ajax.php b/server/browse.ajax.php index b6f3e15489..f9e4d39a1f 100644 --- a/server/browse.ajax.php +++ b/server/browse.ajax.php @@ -1,5 +1,5 @@ set_filter($_REQUEST['key'],$_REQUEST['multi_alpha_filter']); - $browse->set_catalog($_SESSION['catalog']); - } - - if ($_REQUEST['sort']) { - // Set the new sort value - $browse->set_sort($_REQUEST['sort']); - } - - - if ($_REQUEST['catalog_key'] || $SESSION['catalog'] != 0) { - $browse->set_filter('catalog',$_REQUEST['catalog_key']); - $_SESSION['catalog'] = $_REQUEST['catalog_key']; - } elseif ($_REQUEST['catalog_key'] == 0) { - $browse->set_filter('catalog', null); - unset($_SESSION['catalog']); - } - - ob_start(); + case 'browse': + $object_ids = array(); + + // Check 'value' with isset because it can null + //(user type a "start with" word and deletes it) + if ($_REQUEST['key'] && (isset($_REQUEST['multi_alpha_filter']) OR isset($_REQUEST['value']))) { + // Set any new filters we've just added + $browse->set_filter($_REQUEST['key'],$_REQUEST['multi_alpha_filter']); + $browse->set_catalog($_SESSION['catalog']); + } + + if ($_REQUEST['sort']) { + // Set the new sort value + $browse->set_sort($_REQUEST['sort']); + } + + + if ($_REQUEST['catalog_key'] || $SESSION['catalog'] != 0) { + $browse->set_filter('catalog',$_REQUEST['catalog_key']); + $_SESSION['catalog'] = $_REQUEST['catalog_key']; + } elseif ($_REQUEST['catalog_key'] == 0) { + $browse->set_filter('catalog', null); + unset($_SESSION['catalog']); + } + + ob_start(); $browse->show_objects(); $results['browse_content'] = ob_get_clean(); - break; - - case 'set_sort': - - if ($_REQUEST['sort']) { - $browse->set_sort($_REQUEST['sort']); - } - - ob_start(); - $browse->show_objects(); - $results['browse_content'] = ob_get_clean(); - break; - case 'toggle_tag': - $type = $_SESSION['tagcloud_type'] ? $_SESSION['tagcloud_type'] : 'song'; - $browse->set_type($type); - break; - case 'delete_object': - switch ($_REQUEST['type']) { - case 'playlist': - // Check the perms we need to on this - $playlist = new Playlist($_REQUEST['id']); - if (!$playlist->has_access()) { exit; } - - // Delete it! - $playlist->delete(); - $key = 'playlist_row_' . $playlist->id; - break; - case 'smartplaylist': - $playlist = new Search('song', $_REQUEST['id']); - if (!$playlist->has_access()) { exit; } - $playlist->delete(); - $key = 'playlist_row_' . $playlist->id; - break; - case 'live_stream': - if (!$GLOBALS['user']->has_access('75')) { exit; } - $radio = new Radio($_REQUEST['id']); - $radio->delete(); - $key = 'live_stream_' . $radio->id; - break; - default: - - break; - } // end switch on type - - $results[$key] = ''; - - break; - case 'page': - $browse->set_start($_REQUEST['start']); - - ob_start(); - $browse->show_objects(); - $results['browse_content'] = ob_get_clean(); - break; - case 'show_art': - Art::set_enabled(); - - ob_start(); - $browse->show_objects(); - $results['browse_content'] = ob_get_clean(); - break; - case 'get_filters': - ob_start(); - require_once Config::get('prefix') . '/templates/browse_filters.inc.php'; - $results['browse_filters'] = ob_get_clean(); - default: - $results['rfc3514'] = '0x1'; - break; + break; + + case 'set_sort': + + if ($_REQUEST['sort']) { + $browse->set_sort($_REQUEST['sort']); + } + + ob_start(); + $browse->show_objects(); + $results['browse_content'] = ob_get_clean(); + break; + case 'toggle_tag': + $type = $_SESSION['tagcloud_type'] ? $_SESSION['tagcloud_type'] : 'song'; + $browse->set_type($type); + break; + case 'delete_object': + switch ($_REQUEST['type']) { + case 'playlist': + // Check the perms we need to on this + $playlist = new Playlist($_REQUEST['id']); + if (!$playlist->has_access()) { exit; } + + // Delete it! + $playlist->delete(); + $key = 'playlist_row_' . $playlist->id; + break; + case 'smartplaylist': + $playlist = new Search('song', $_REQUEST['id']); + if (!$playlist->has_access()) { exit; } + $playlist->delete(); + $key = 'playlist_row_' . $playlist->id; + break; + case 'live_stream': + if (!$GLOBALS['user']->has_access('75')) { exit; } + $radio = new Radio($_REQUEST['id']); + $radio->delete(); + $key = 'live_stream_' . $radio->id; + break; + default: + + break; + } // end switch on type + + $results[$key] = ''; + + break; + case 'page': + $browse->set_start($_REQUEST['start']); + + ob_start(); + $browse->show_objects(); + $results['browse_content'] = ob_get_clean(); + break; + case 'show_art': + Art::set_enabled(); + + ob_start(); + $browse->show_objects(); + $results['browse_content'] = ob_get_clean(); + break; + case 'get_filters': + ob_start(); + require_once Config::get('prefix') . '/templates/browse_filters.inc.php'; + $results['browse_filters'] = ob_get_clean(); + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; $browse->store(); diff --git a/server/democratic.ajax.php b/server/democratic.ajax.php index 42ac3260a5..a3ebc9989a 100644 --- a/server/democratic.ajax.php +++ b/server/democratic.ajax.php @@ -1,5 +1,5 @@ set_parent(); switch ($_REQUEST['action']) { - case 'delete_vote': - $democratic->remove_vote($_REQUEST['row_id']); - $show_browse = true; - break; - case 'add_vote': - $democratic->add_vote(array( - array( - 'object_type' => $_REQUEST['type'], - 'object_id' => $_REQUEST['object_id'] - ) - )); - $show_browse = true; - break; - case 'delete': - if (!$GLOBALS['user']->has_access('75')) { - echo xml_from_array(array('rfc3514' => '0x1')); - exit; - } + case 'delete_vote': + $democratic->remove_vote($_REQUEST['row_id']); + $show_browse = true; + break; + case 'add_vote': + $democratic->add_vote(array( + array( + 'object_type' => $_REQUEST['type'], + 'object_id' => $_REQUEST['object_id'] + ) + )); + $show_browse = true; + break; + case 'delete': + if (!$GLOBALS['user']->has_access('75')) { + echo xml_from_array(array('rfc3514' => '0x1')); + exit; + } - $democratic->delete_votes($_REQUEST['row_id']); - $show_browse = true; - break; - case 'send_playlist': - if (!Access::check('interface','75')) { - echo xml_from_array(array('rfc3514' => '0x1')); - exit; - } + $democratic->delete_votes($_REQUEST['row_id']); + $show_browse = true; + break; + case 'send_playlist': + if (!Access::check('interface','75')) { + echo xml_from_array(array('rfc3514' => '0x1')); + exit; + } - $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=democratic&democratic_id=' . scrub_out($_REQUEST['democratic_id']); - $results['rfc3514'] = ''; - break; - case 'clear_playlist': - if (!Access::check('interface','100')) { - echo xml_from_array(array('rfc3514' => '0x1')); - exit; - } + $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=democratic&democratic_id=' . scrub_out($_REQUEST['democratic_id']); + $results['rfc3514'] = ''; + break; + case 'clear_playlist': + if (!Access::check('interface','100')) { + echo xml_from_array(array('rfc3514' => '0x1')); + exit; + } - $democratic = new Democratic($_REQUEST['democratic_id']); - $democratic->set_parent(); - $democratic->clear(); + $democratic = new Democratic($_REQUEST['democratic_id']); + $democratic->set_parent(); + $democratic->clear(); - $show_browse = true; - break; - default: - $results['rfc3514'] = '0x1'; - break; + $show_browse = true; + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; if ($show_browse) { - ob_start(); - $object_ids = $democratic->get_items(); - $browse = new Browse(); - $browse->set_type('democratic'); - $browse->set_static_content(true); - $browse->show_objects($object_ids); - $browse->store(); - $results['browse_content'] = ob_get_contents(); - ob_end_clean(); + ob_start(); + $object_ids = $democratic->get_items(); + $browse = new Browse(); + $browse->set_type('democratic'); + $browse->set_static_content(true); + $browse->show_objects($object_ids); + $browse->store(); + $results['browse_content'] = ob_get_contents(); + ob_end_clean(); } // We always do this diff --git a/server/flag.ajax.php b/server/flag.ajax.php index a375278933..0445217713 100644 --- a/server/flag.ajax.php +++ b/server/flag.ajax.php @@ -1,5 +1,5 @@ delete(); + // Remove the flag from the table + $flag = new Flag($_REQUEST['flag_id']); + $flag->delete(); - $flagged = Flag::get_all(); - ob_start(); - $browse = new Browse(); - $browse->set_type('flagged'); - $browse->set_static_content(true); - $browse->save_objects($flagged); - $browse->show_objects($flagged); - $browse->store(); - $results['browse_content'] = ob_get_contents(); - ob_end_clean(); + $flagged = Flag::get_all(); + ob_start(); + $browse = new Browse(); + $browse->set_type('flagged'); + $browse->set_static_content(true); + $browse->save_objects($flagged); + $browse->show_objects($flagged); + $browse->store(); + $results['browse_content'] = ob_get_contents(); + ob_end_clean(); - break; - case 'accept': - if (!Access::check('interface','75')) { - $results['rfc3514'] = '0x1'; - break; - } + break; + case 'accept': + if (!Access::check('interface','75')) { + $results['rfc3514'] = '0x1'; + break; + } - $flag = new Flag($_REQUEST['flag_id']); - $flag->approve(); - $flag->format(); - ob_start(); - require_once Config::get('prefix') . '/templates/show_flag_row.inc.php'; - $results['flagged_' . $flag->id] = ob_get_contents(); - ob_end_clean(); + $flag = new Flag($_REQUEST['flag_id']); + $flag->approve(); + $flag->format(); + ob_start(); + require_once Config::get('prefix') . '/templates/show_flag_row.inc.php'; + $results['flagged_' . $flag->id] = ob_get_contents(); + ob_end_clean(); - break; - default: - $results['rfc3514'] = '0x1'; - break; + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/index.ajax.php b/server/index.ajax.php index b46674d59c..2dc4b399c2 100644 --- a/server/index.ajax.php +++ b/server/index.ajax.php @@ -1,5 +1,5 @@ '; - } - break; - case 'reloadnp': - ob_start(); - show_now_playing(); - $results['now_playing'] = ob_get_clean(); - ob_start(); - $data = Song::get_recently_played(); - Song::build_cache(array_keys($data)); - if (count($data)) { + case 'random_albums': + $albums = Album::get_random_albums('6'); + if (count($albums) AND is_array($albums)) { + ob_start(); + require_once Config::get('prefix') . '/templates/show_random_albums.inc.php'; + $results['random_selection'] = ob_get_clean(); + } + else { + $results['random_selection'] = ''; + } + break; + case 'reloadnp': + ob_start(); + show_now_playing(); + $results['now_playing'] = ob_get_clean(); + ob_start(); + $data = Song::get_recently_played(); + Song::build_cache(array_keys($data)); + if (count($data)) { require_once Config::get('prefix') . '/templates/show_recently_played.inc.php'; - } - $results['recently_played'] = ob_get_clean(); - break; - case 'sidebar': + } + $results['recently_played'] = ob_get_clean(); + break; + case 'sidebar': switch ($_REQUEST['button']) { case 'home': case 'modules': @@ -72,9 +72,9 @@ require_once Config::get('prefix') . '/templates/sidebar.inc.php'; $results['sidebar'] = ob_get_contents(); ob_end_clean(); - default: - $results['rfc3514'] = '0x1'; - break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/localplay.ajax.php b/server/localplay.ajax.php index 66368870a9..f37cac7ecc 100644 --- a/server/localplay.ajax.php +++ b/server/localplay.ajax.php @@ -1,5 +1,5 @@ set_active_instance($_REQUEST['instance']); - Preference::update('play_type',$GLOBALS['user']->id,$type); - - // We should also refesh the sidebar - ob_start(); - require_once Config::get('prefix') . '/templates/sidebar.inc.php'; - $results['sidebar'] = ob_get_contents(); - ob_end_clean(); - break; - case 'command': - // Make sure they are allowed to do this - if (!Access::check('localplay','50')) { - debug_event('DENIED','Attempted to control Localplay without sufficient access','1'); - exit; - } - - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); - - // Switch on valid commands - switch ($_REQUEST['command']) { - case 'prev': - case 'next': - case 'stop': - case 'play': - case 'pause': - $command = scrub_in($_REQUEST['command']); - $localplay->$command(); - break; - case 'volume_up': - case 'volume_down': - case 'volume_mute': - $command = scrub_in($_REQUEST['command']); - $localplay->$command(); - - // We actually want to refresh something here - ob_start(); - require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; - $results['localplay_status'] = ob_get_contents(); - ob_end_clean(); - break; - case 'delete_all': - $localplay->delete_all(); - ob_start(); - $browse = new Browse(); - $browse->set_type('playlist_localplay'); - $browse->set_static_content(true); - $browse->save_objects(array()); - $browse->show_objects(array()); - $browse->store(); - $results['browse_content'] = ob_get_contents(); - ob_end_clean(); - break; - case 'skip': - $localplay->skip(intval($_REQUEST['id'])); - $objects = $localplay->get(); - ob_start(); - $browse = new Browse(); - $browse->set_type('playlist_localplay'); - $browse->set_static_content(true); - $browse->save_objects($objects); - $browse->show_objects($objects); - $browse->store(); - $results['browse_content'] = ob_get_contents(); - ob_end_clean(); - break; - default: - // Nothing - break; - } // end whitelist - - break; - case 'delete_track': - // Load Connect... yada yada - if (!Access::check('localplay','50')) { - debug_event('DENIED','Attempted to delete track without access','1'); - exit; - } - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); - - // Scrub in the delete request - $id = intval($_REQUEST['id']); - - $localplay->delete_track($id); - - // Wait in case we just deleted what we were playing - sleep(3); - $objects = $localplay->get(); - $status = $localplay->status(); - - ob_start(); - $browse = new Browse(); - $browse->set_type('playlist_localplay'); - $browse->set_static_content(true); - $browse->save_objects($objects); - $browse->show_objects($objects); - $browse->store(); - $results['browse_content'] = ob_get_contents(); - ob_end_clean(); - - break; - case 'delete_instance': - // Make sure that you have access to do this... - if (!Access::check('localplay','75')) { - debug_event('DENIED','Attempted to delete instance without access','1'); - exit; - } - - // Scrub it in - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->delete_instance($_REQUEST['instance']); - - $key = 'localplay_instance_' . $_REQUEST['instance']; - $results[$key] = ''; - break; - case 'repeat': - // Make sure that they have access to do this again no clue - if (!Access::check('localplay','50')) { - debug_event('DENIED','Attempted to set repeat without access','1'); - exit; - } - - // Scrub her in - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); - $localplay->repeat(make_bool($_REQUEST['value'])); - - ob_start(); - require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; - $results['localplay_status'] = ob_get_contents(); - ob_end_clean(); - - break; - case 'random': - // Make sure that they have access to do this - if (!Access::check('localplay','50')) { - debug_event('DENIED','Attempted to set random without access','1'); - exit; - } - - // Scrub her in - $localplay = new Localplay(Config::get('localplay_controller')); - $localplay->connect(); - $localplay->random(make_bool($_REQUEST['value'])); - - ob_start(); - require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; - $results['localplay_status'] = ob_get_contents(); - ob_end_clean(); - - break; - default: - $results['rfc3514'] = '0x1'; - break; + case 'set_instance': + // Make sure they they are allowed to do this + if (!Access::check('localplay','5')) { + debug_event('DENIED','Error attempted to set instance without required level','1'); + exit; + } + + $type = $_REQUEST['instance'] ? 'localplay' : 'stream'; + + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->set_active_instance($_REQUEST['instance']); + Preference::update('play_type',$GLOBALS['user']->id,$type); + + // We should also refesh the sidebar + ob_start(); + require_once Config::get('prefix') . '/templates/sidebar.inc.php'; + $results['sidebar'] = ob_get_contents(); + ob_end_clean(); + break; + case 'command': + // Make sure they are allowed to do this + if (!Access::check('localplay','50')) { + debug_event('DENIED','Attempted to control Localplay without sufficient access','1'); + exit; + } + + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); + + // Switch on valid commands + switch ($_REQUEST['command']) { + case 'prev': + case 'next': + case 'stop': + case 'play': + case 'pause': + $command = scrub_in($_REQUEST['command']); + $localplay->$command(); + break; + case 'volume_up': + case 'volume_down': + case 'volume_mute': + $command = scrub_in($_REQUEST['command']); + $localplay->$command(); + + // We actually want to refresh something here + ob_start(); + require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; + $results['localplay_status'] = ob_get_contents(); + ob_end_clean(); + break; + case 'delete_all': + $localplay->delete_all(); + ob_start(); + $browse = new Browse(); + $browse->set_type('playlist_localplay'); + $browse->set_static_content(true); + $browse->save_objects(array()); + $browse->show_objects(array()); + $browse->store(); + $results['browse_content'] = ob_get_contents(); + ob_end_clean(); + break; + case 'skip': + $localplay->skip(intval($_REQUEST['id'])); + $objects = $localplay->get(); + ob_start(); + $browse = new Browse(); + $browse->set_type('playlist_localplay'); + $browse->set_static_content(true); + $browse->save_objects($objects); + $browse->show_objects($objects); + $browse->store(); + $results['browse_content'] = ob_get_contents(); + ob_end_clean(); + break; + default: + // Nothing + break; + } // end whitelist + + break; + case 'delete_track': + // Load Connect... yada yada + if (!Access::check('localplay','50')) { + debug_event('DENIED','Attempted to delete track without access','1'); + exit; + } + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); + + // Scrub in the delete request + $id = intval($_REQUEST['id']); + + $localplay->delete_track($id); + + // Wait in case we just deleted what we were playing + sleep(3); + $objects = $localplay->get(); + $status = $localplay->status(); + + ob_start(); + $browse = new Browse(); + $browse->set_type('playlist_localplay'); + $browse->set_static_content(true); + $browse->save_objects($objects); + $browse->show_objects($objects); + $browse->store(); + $results['browse_content'] = ob_get_contents(); + ob_end_clean(); + + break; + case 'delete_instance': + // Make sure that you have access to do this... + if (!Access::check('localplay','75')) { + debug_event('DENIED','Attempted to delete instance without access','1'); + exit; + } + + // Scrub it in + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->delete_instance($_REQUEST['instance']); + + $key = 'localplay_instance_' . $_REQUEST['instance']; + $results[$key] = ''; + break; + case 'repeat': + // Make sure that they have access to do this again no clue + if (!Access::check('localplay','50')) { + debug_event('DENIED','Attempted to set repeat without access','1'); + exit; + } + + // Scrub her in + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); + $localplay->repeat(make_bool($_REQUEST['value'])); + + ob_start(); + require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; + $results['localplay_status'] = ob_get_contents(); + ob_end_clean(); + + break; + case 'random': + // Make sure that they have access to do this + if (!Access::check('localplay','50')) { + debug_event('DENIED','Attempted to set random without access','1'); + exit; + } + + // Scrub her in + $localplay = new Localplay(Config::get('localplay_controller')); + $localplay->connect(); + $localplay->random(make_bool($_REQUEST['value'])); + + ob_start(); + require_once Config::get('prefix') . '/templates/show_localplay_status.inc.php'; + $results['localplay_status'] = ob_get_contents(); + ob_end_clean(); + + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/playlist.ajax.php b/server/playlist.ajax.php index 333690631f..5bfe1a991d 100644 --- a/server/playlist.ajax.php +++ b/server/playlist.ajax.php @@ -1,5 +1,5 @@ format(); - if ($playlist->has_access()) { - $playlist->delete_track($_REQUEST['track_id']); - } - - $object_ids = $playlist->get_items(); - ob_start(); - $browse = new Browse(); - $browse->set_type('playlist_song'); - $browse->add_supplemental_object('playlist',$playlist->id); - $browse->save_objects($object_ids); - $browse->show_objects($object_ids); - $browse->store(); - $results['browse_content'] = ob_get_clean(); - break; - case 'edit_track': - $playlist = new Playlist($_REQUEST['playlist_id']); - if (!$playlist->has_access()) { - $results['rfc3514'] = '0x1'; - break; - } - - // They've got access, show the edit page - $track = $playlist->get_track($_REQUEST['track_id']); - $song = new Song($track['object_id']); - $song->format(); - require_once Config::get('prefix') . '/templates/show_edit_playlist_song_row.inc.php'; - $results['track_' . $track['id']] = ob_get_clean(); - break; - case 'save_track': - $playlist = new Playlist($_REQUEST['playlist_id']); - if (!$playlist->has_access()) { - $results['rfc3514'] = '0x1'; - break; - } - $playlist->format(); - - // They've got access, save this guy and re-display row - $playlist->update_track_number($_GET['track_id'],$_POST['track']); - $track = $playlist->get_track($_GET['track_id']); - $song = new Song($track['object_id']); - $song->format(); - $playlist_track = $track['track']; - require Config::get('prefix') . '/templates/show_playlist_song_row.inc.php'; - $results['track_' . $track['id']] = ob_get_clean(); - break; - case 'create': - if (!Access::check('interface','25')) { - debug_event('DENIED','Error:' . $GLOBALS['user']->username . ' does not have user access, unable to create playlist','1'); - break; - } - - // Pull the current active playlist items - $objects = $GLOBALS['user']->playlist->get_items(); - - $name = $GLOBALS['user']->username . ' - ' . date("Y-m-d H:i:s",time()); - - // generate the new playlist - $playlist_id = Playlist::create($name,'public'); - if (!$playlist_id) { break; } - $playlist = new Playlist($playlist_id); - - // Itterate through and add them to our new playlist - foreach ($objects as $object_data) { - // For now only allow songs on here, we'll change this later - $type = array_shift($object_data); - if ($type == 'song') { - $songs[] = array_shift($object_data); - } - } // object_data - - // Add our new songs - $playlist->add_songs($songs,'ORDERED'); - $playlist->format(); - $object_ids = $playlist->get_items(); - ob_start(); - require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; - $results['content'] = ob_get_clean(); - break; - case 'append': - // Pull the current active playlist items - $objects = $GLOBALS['user']->playlist->get_items(); - - // Create the playlist object - $playlist = new Playlist($_REQUEST['playlist_id']); - - // We need to make sure that they have access - if (!$playlist->has_access()) { - break; - } - - $songs = array(); - - // Itterate through and add them to our new playlist - foreach ($objects as $element) { - $type = array_shift($element); - switch ($type) { - case 'song': - $songs[] = array_shift($element); - break; - } // end switch - } // foreach - - // Override normal include procedure - Ajax::set_include_override(true); - - // Add our new songs - $playlist->add_songs($songs,'ORDERED'); - $playlist->format(); - $object_ids = $playlist->get_items(); - ob_start(); - require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; - $results['content'] = ob_get_contents(); - ob_end_clean(); - break; - default: - $results['rfc3514'] = '0x1'; - break; + case 'delete_track': + // Create the object and remove the track + $playlist = new Playlist($_REQUEST['playlist_id']); + $playlist->format(); + if ($playlist->has_access()) { + $playlist->delete_track($_REQUEST['track_id']); + } + + $object_ids = $playlist->get_items(); + ob_start(); + $browse = new Browse(); + $browse->set_type('playlist_song'); + $browse->add_supplemental_object('playlist',$playlist->id); + $browse->save_objects($object_ids); + $browse->show_objects($object_ids); + $browse->store(); + $results['browse_content'] = ob_get_clean(); + break; + case 'edit_track': + $playlist = new Playlist($_REQUEST['playlist_id']); + if (!$playlist->has_access()) { + $results['rfc3514'] = '0x1'; + break; + } + + // They've got access, show the edit page + $track = $playlist->get_track($_REQUEST['track_id']); + $song = new Song($track['object_id']); + $song->format(); + require_once Config::get('prefix') . '/templates/show_edit_playlist_song_row.inc.php'; + $results['track_' . $track['id']] = ob_get_clean(); + break; + case 'save_track': + $playlist = new Playlist($_REQUEST['playlist_id']); + if (!$playlist->has_access()) { + $results['rfc3514'] = '0x1'; + break; + } + $playlist->format(); + + // They've got access, save this guy and re-display row + $playlist->update_track_number($_GET['track_id'],$_POST['track']); + $track = $playlist->get_track($_GET['track_id']); + $song = new Song($track['object_id']); + $song->format(); + $playlist_track = $track['track']; + require Config::get('prefix') . '/templates/show_playlist_song_row.inc.php'; + $results['track_' . $track['id']] = ob_get_clean(); + break; + case 'create': + if (!Access::check('interface','25')) { + debug_event('DENIED','Error:' . $GLOBALS['user']->username . ' does not have user access, unable to create playlist','1'); + break; + } + + // Pull the current active playlist items + $objects = $GLOBALS['user']->playlist->get_items(); + + $name = $GLOBALS['user']->username . ' - ' . date("Y-m-d H:i:s",time()); + + // generate the new playlist + $playlist_id = Playlist::create($name,'public'); + if (!$playlist_id) { break; } + $playlist = new Playlist($playlist_id); + + // Itterate through and add them to our new playlist + foreach ($objects as $object_data) { + // For now only allow songs on here, we'll change this later + $type = array_shift($object_data); + if ($type == 'song') { + $songs[] = array_shift($object_data); + } + } // object_data + + // Add our new songs + $playlist->add_songs($songs,'ORDERED'); + $playlist->format(); + $object_ids = $playlist->get_items(); + ob_start(); + require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; + $results['content'] = ob_get_clean(); + break; + case 'append': + // Pull the current active playlist items + $objects = $GLOBALS['user']->playlist->get_items(); + + // Create the playlist object + $playlist = new Playlist($_REQUEST['playlist_id']); + + // We need to make sure that they have access + if (!$playlist->has_access()) { + break; + } + + $songs = array(); + + // Itterate through and add them to our new playlist + foreach ($objects as $element) { + $type = array_shift($element); + switch ($type) { + case 'song': + $songs[] = array_shift($element); + break; + } // end switch + } // foreach + + // Override normal include procedure + Ajax::set_include_override(true); + + // Add our new songs + $playlist->add_songs($songs,'ORDERED'); + $playlist->format(); + $object_ids = $playlist->get_items(); + ob_start(); + require_once Config::get('prefix') . '/templates/show_playlist.inc.php'; + $results['content'] = ob_get_contents(); + ob_end_clean(); + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/random.ajax.php b/server/random.ajax.php index ff1494765f..dbcd43b5e2 100644 --- a/server/random.ajax.php +++ b/server/random.ajax.php @@ -1,5 +1,5 @@ get_songs(); foreach ($songs as $song_id) { $GLOBALS['user']->playlist->add_object($song_id,'song'); } - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); break; case 'artist': $artist_id = Random::artist(); - // If we don't get anything stop - if (!$artist_id) { $results['rfc3514'] = '0x1'; break; } + // If we don't get anything stop + if (!$artist_id) { $results['rfc3514'] = '0x1'; break; } $artist = new Artist($artist_id); $songs = $artist->get_songs(); foreach ($songs as $song_id) { $GLOBALS['user']->playlist->add_object($song_id,'song'); } - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); break; case 'playlist': $playlist_id = Random::playlist(); - // If we don't get any results stop right here! - if (!$playlist_id) { $results['rfc3514'] = '0x1'; break; } + // If we don't get any results stop right here! + if (!$playlist_id) { $results['rfc3514'] = '0x1'; break; } $playlist = new Playlist($playlist_id); $items = $playlist->get_items(); foreach ($items as $item) { $GLOBALS['user']->playlist->add_object($item['object_id'],$item['type']); } - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); break; - case 'advanced_random': - $object_ids = Random::advanced($_POST); + case 'advanced_random': + $object_ids = Random::advanced($_POST); - // First add them to the active playlist - foreach ($object_ids as $object_id) { - $GLOBALS['user']->playlist->add_object($object_id,'song'); - } - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + // First add them to the active playlist + foreach ($object_ids as $object_id) { + $GLOBALS['user']->playlist->add_object($object_id,'song'); + } + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); - // Now setup the browse and show them below! - $browse = new Browse(); - $browse->set_type('song'); - $browse->save_objects($object_ids); - ob_start(); - $browse->show_objects(); - $results['browse'] = ob_get_contents(); - ob_end_clean(); + // Now setup the browse and show them below! + $browse = new Browse(); + $browse->set_type('song'); + $browse->save_objects($object_ids); + ob_start(); + $browse->show_objects(); + $results['browse'] = ob_get_contents(); + ob_end_clean(); - break; - default: - $results['rfc3514'] = '0x1'; - break; + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/song.ajax.php b/server/song.ajax.php index 2fccae37f7..1c83211ef9 100644 --- a/server/song.ajax.php +++ b/server/song.ajax.php @@ -1,5 +1,5 @@ username . ' attempted to change the state of a song','1'); - exit; - } + case 'flip_state': + if (!Access::check('interface','75')) { + debug_event('DENIED',$GLOBALS['user']->username . ' attempted to change the state of a song','1'); + exit; + } - $song = new Song($_REQUEST['song_id']); - $new_enabled = $song->enabled ? '0' : '1'; - $song->update_enabled($new_enabled,$song->id); - $song->enabled = $new_enabled; - $song->format(); + $song = new Song($_REQUEST['song_id']); + $new_enabled = $song->enabled ? '0' : '1'; + $song->update_enabled($new_enabled,$song->id); + $song->enabled = $new_enabled; + $song->format(); - //Return the new Ajax::button - $id = 'button_flip_state_' . $song->id; - $button = $song->enabled ? 'disable' : 'enable'; - $results[$id] = Ajax::button('?page=song&action=flip_state&song_id=' . $song->id,$button, T_(ucfirst($button)),'flip_state_' . $song->id); + //Return the new Ajax::button + $id = 'button_flip_state_' . $song->id; + $button = $song->enabled ? 'disable' : 'enable'; + $results[$id] = Ajax::button('?page=song&action=flip_state&song_id=' . $song->id,$button, T_(ucfirst($button)),'flip_state_' . $song->id); - break; - default: - $results['rfc3514'] = '0x1'; - break; + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/stats.ajax.php b/server/stats.ajax.php index 7e6d99f1d4..b4811ab305 100644 --- a/server/stats.ajax.php +++ b/server/stats.ajax.php @@ -1,5 +1,5 @@ id,$new)) { - Config::set('play_type', $new, true); - } + // Go ahead and update their preference + if (Preference::update('play_type',$GLOBALS['user']->id,$new)) { + Config::set('play_type', $new, true); + } - if (($new == 'localplay' AND $current != 'localplay') OR ($current == 'localplay' AND $new != 'localplay')) { - $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); - } + if (($new == 'localplay' AND $current != 'localplay') OR ($current == 'localplay' AND $new != 'localplay')) { + $results['rightbar'] = UI::ajax_include('rightbar.inc.php'); + } - $results['rfc3514'] = '0x0'; + $results['rfc3514'] = '0x0'; - break; - case 'basket': + break; + case 'basket': - // Go ahead and see if we should clear the playlist here or not, we might not actually clear it in the session - // we'll just have to feed it bad data. - // FIXME: This is sad, will be fixed when I switch how streaming works. + // Go ahead and see if we should clear the playlist here or not, we might not actually clear it in the session + // we'll just have to feed it bad data. + // FIXME: This is sad, will be fixed when I switch how streaming works. // Check to see if 'clear' was passed if it was then we need to reset the basket if ( ($_REQUEST['playlist_method'] == 'clear' || Config::get('playlist_method') == 'clear') AND Config::get('play_type') != 'xspf_player') { - define('NO_SONGS','1'); - ob_start(); - require_once Config::get('prefix') . '/templates/rightbar.inc.php'; - $results['rightbar'] = ob_get_clean(); + define('NO_SONGS','1'); + ob_start(); + require_once Config::get('prefix') . '/templates/rightbar.inc.php'; + $results['rightbar'] = ob_get_clean(); } - // We need to set the basket up! - $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket&playlist_method=' . scrub_out($_REQUEST['playlist_method']); - $results['rfc3514'] = ''; - break; - default: - $results['rfc3514'] = '0x1'; - break; + // We need to set the basket up! + $_SESSION['iframe']['target'] = Config::get('web_path') . '/stream.php?action=basket&playlist_method=' . scrub_out($_REQUEST['playlist_method']); + $results['rfc3514'] = ''; + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; // We always do this diff --git a/server/tag.ajax.php b/server/tag.ajax.php index 995318619d..d83c8ce748 100644 --- a/server/tag.ajax.php +++ b/server/tag.ajax.php @@ -1,5 +1,5 @@ remove_map($_GET['type'],$_GET['object_id']); - break; - case 'browse_type': - $browse = new Browse($_GET['browse_id']); - $browse->set_filter('object_type', $_GET['type']); - $browse->store(); - break; - case 'add_filter': - $browse = new Browse($_GET['browse_id']); - $browse->set_filter('tag', $_GET['tag_id']); - $object_ids = $browse->get_objects(); - ob_start(); - $browse->show_objects($object_ids); - $results['browse_content'] = ob_get_clean(); - $browse->store(); - // Retrieve current objects of type based on combined filters - break; - default: - $results['rfc3514'] = '0x1'; - break; + break; + case 'add_tag': + Tag::add_tag_map($_GET['type'],$_GET['object_id'],$_GET['tag_id']); + break; + case 'remove_tag': + $tag = new Tag($_GET['tag_id']); + $tag->remove_map($_GET['type'],$_GET['object_id']); + break; + case 'browse_type': + $browse = new Browse($_GET['browse_id']); + $browse->set_filter('object_type', $_GET['type']); + $browse->store(); + break; + case 'add_filter': + $browse = new Browse($_GET['browse_id']); + $browse->set_filter('tag', $_GET['tag_id']); + $object_ids = $browse->get_objects(); + ob_start(); + $browse->show_objects($object_ids); + $results['browse_content'] = ob_get_clean(); + $browse->store(); + // Retrieve current objects of type based on combined filters + break; + default: + $results['rfc3514'] = '0x1'; + break; } // switch on action; diff --git a/server/xml.server.php b/server/xml.server.php index 4dfc124dc2..ea7b9df611 100644 --- a/server/xml.server.php +++ b/server/xml.server.php @@ -1,5 +1,5 @@ id) { - Error::add('general', T_('Invalid Object Selected')); - Error::display('general'); - break; - } - - // Now go ahead and display the page where we let them add a comment etc - require_once Config::get('prefix') . '/templates/show_add_shout.inc.php'; - break; - default: - header("Location:" . Config::get('web_path')); - break; + case 'add_shout': + // Must be at least a user to do this + if (!Access::check('interface','25')) { + UI::access_denied(); + exit; + } + + if (!Core::form_verify('add_shout','post')) { + UI::access_denied(); + exit; + } + + $shout_id = Shoutbox::create($_POST); + header("Location:" . Config::get('web_path')); + break; + case 'show_add_shout': + // Get our object first + $object = Shoutbox::get_object($_REQUEST['type'],$_REQUEST['id']); + + if (!$object->id) { + Error::add('general', T_('Invalid Object Selected')); + Error::display('general'); + break; + } + + // Now go ahead and display the page where we let them add a comment etc + require_once Config::get('prefix') . '/templates/show_add_shout.inc.php'; + break; + default: + header("Location:" . Config::get('web_path')); + break; } // end switch on action UI::show_footer(); diff --git a/smartplaylist.php b/smartplaylist.php index ac4d5d4631..1a78fd6fb2 100644 --- a/smartplaylist.php +++ b/smartplaylist.php @@ -1,5 +1,5 @@ has_access()) { - $playlist->delete(); - // Go elsewhere - header('Location: ' . Config::get('web_path') . '/browse.php?action=smartplaylist'); - } + // Check rights + $playlist = new Search('song', $_REQUEST['playlist_id']); + if ($playlist->has_access()) { + $playlist->delete(); + // Go elsewhere + header('Location: ' . Config::get('web_path') . '/browse.php?action=smartplaylist'); + } } UI::show_header(); /* Switch on the action passed in */ switch ($_REQUEST['action']) { - case 'create_playlist': - /* Check rights */ - if (!Access::check('interface','25')) { - UI::access_denied(); - break; - } + case 'create_playlist': + /* Check rights */ + if (!Access::check('interface','25')) { + UI::access_denied(); + break; + } - foreach ($_REQUEST as $key => $value) { - $prefix = substr($key, 0, 4); - $value = trim($value); + foreach ($_REQUEST as $key => $value) { + $prefix = substr($key, 0, 4); + $value = trim($value); - if ($prefix == 'rule' && strlen($value)) { - $rules[$key] = Dba::escape($value); - } - } + if ($prefix == 'rule' && strlen($value)) { + $rules[$key] = Dba::escape($value); + } + } - switch($_REQUEST['operator']) { - case 'or': - $operator = 'OR'; - break; - default: - $operator = 'AND'; - break; - } // end switch on operator + switch($_REQUEST['operator']) { + case 'or': + $operator = 'OR'; + break; + default: + $operator = 'AND'; + break; + } // end switch on operator - $playlist_name = scrub_in($_REQUEST['playlist_name']); + $playlist_name = scrub_in($_REQUEST['playlist_name']); - $playlist = new Search('song'); - $playlist->parse_rules($data); - $playlist->logic_operator = $operator; - $playlist->name = $playlist_name; - $playlist->save(); - - break; - case 'delete_playlist': - // If we made it here, we didn't have sufficient rights. - UI::access_denied(); - break; - case 'show_playlist': - $playlist = new Search('song', $_REQUEST['playlist_id']); - $playlist->format(); - require_once Config::get('prefix') . '/templates/show_smartplaylist.inc.php'; - break; - case 'update_playlist': - $playlist = new Search('song', $_REQUEST['playlist_id']); - if ($playlist->has_access()) { - $playlist->parse_rules(Search::clean_request($_REQUEST)); - $playlist->update(); - $playlist->format(); - } - else { - UI::access_denied(); - break; - } - require_once Config::get('prefix') . '/templates/show_smartplaylist.inc.php'; - break; - default: - require_once Config::get('prefix') . '/templates/show_smartplaylist.inc.php'; - break; + $playlist = new Search('song'); + $playlist->parse_rules($data); + $playlist->logic_operator = $operator; + $playlist->name = $playlist_name; + $playlist->save(); + + break; + case 'delete_playlist': + // If we made it here, we didn't have sufficient rights. + UI::access_denied(); + break; + case 'show_playlist': + $playlist = new Search('song', $_REQUEST['playlist_id']); + $playlist->format(); + require_once Config::get('prefix') . '/templates/show_smartplaylist.inc.php'; + break; + case 'update_playlist': + $playlist = new Search('song', $_REQUEST['playlist_id']); + if ($playlist->has_access()) { + $playlist->parse_rules(Search::clean_request($_REQUEST)); + $playlist->update(); + $playlist->format(); + } + else { + UI::access_denied(); + break; + } + require_once Config::get('prefix') . '/templates/show_smartplaylist.inc.php'; + break; + default: + require_once Config::get('prefix') . '/templates/show_smartplaylist.inc.php'; + break; } // switch on the action UI::show_footer(); diff --git a/song.php b/song.php index 2170616d2a..9646712826 100644 --- a/song.php +++ b/song.php @@ -1,5 +1,5 @@ format(); - $song->fill_ext_info(); - require_once Config::get('prefix') . '/templates/show_song.inc.php'; - break; + default: + case 'show_song': + $song = new Song($_REQUEST['song_id']); + $song->format(); + $song->fill_ext_info(); + require_once Config::get('prefix') . '/templates/show_song.inc.php'; + break; } // end data collection UI::show_footer(); diff --git a/stats.php b/stats.php index fd2569ec59..ba96ed4fd4 100644 --- a/stats.php +++ b/stats.php @@ -1,5 +1,5 @@ get_favorites('artist'); - $favorite_albums = $working_user->get_favorites('album'); - $favorite_songs = $working_user->get_favorites('song'); - - require_once Config::get('prefix') . '/templates/show_user_stats.inc.php'; - - break; - // Show stats - case 'newest': - require_once Config::get('prefix') . '/templates/show_newest.inc.php'; - break; - case 'popular': - require_once Config::get('prefix') . '/templates/show_popular.inc.php'; - break; - case 'show': - default: - require_once Config::get('prefix') . '/templates/show_stats.inc.php'; - break; + // Show a Users "Profile" page + case 'show_user': + $client = new User($_REQUEST['user_id']); + require_once Config::get('prefix') . '/templates/show_user.inc.php'; + break; + case 'user_stats': + /* Get em! */ + $working_user = new User($_REQUEST['user_id']); + + /* Pull favs */ + $favorite_artists = $working_user->get_favorites('artist'); + $favorite_albums = $working_user->get_favorites('album'); + $favorite_songs = $working_user->get_favorites('song'); + + require_once Config::get('prefix') . '/templates/show_user_stats.inc.php'; + + break; + // Show stats + case 'newest': + require_once Config::get('prefix') . '/templates/show_newest.inc.php'; + break; + case 'popular': + require_once Config::get('prefix') . '/templates/show_popular.inc.php'; + break; + case 'show': + default: + require_once Config::get('prefix') . '/templates/show_stats.inc.php'; + break; } // end switch on action UI::show_footer(); diff --git a/stream.php b/stream.php index 22f9b85c1b..0b418509a1 100644 --- a/stream.php +++ b/stream.php @@ -1,5 +1,5 @@ playlist->get_items(); + case 'basket': + // Pull in our items (multiple types) + $media_ids = $GLOBALS['user']->playlist->get_items(); - // Check to see if 'clear' was passed if it was then we need to reset the basket - if ( ($_REQUEST['playlist_method'] == 'clear' || Config::get('playlist_method') == 'clear') AND Config::get('play_type') != 'xspf_player') { - $GLOBALS['user']->playlist->clear(); - } + // Check to see if 'clear' was passed if it was then we need to reset the basket + if ( ($_REQUEST['playlist_method'] == 'clear' || Config::get('playlist_method') == 'clear') AND Config::get('play_type') != 'xspf_player') { + $GLOBALS['user']->playlist->clear(); + } - break; - /* This is run if we need to gather info based on a tmp playlist */ - case 'tmp_playlist': - $tmp_playlist = new Tmp_Playlist($_REQUEST['tmpplaylist_id']); - $media_ids = $tmp_playlist->get_items(); - break; - case 'play_favorite': - $data = $GLOBALS['user']->get_favorites($_REQUEST['type']); - $media_ids = array(); - switch ($_REQUEST['type']) { - case 'artist': - case 'album': - foreach ($data as $value) { - $songs = $value->get_songs(); - $media_ids = array_merge($media_ids,$songs); - } - break; - case 'song': - foreach ($data as $value) { - $media_ids[] = $value->id; - } - break; - } // end switch on type - break; - case 'single_song': - $media_ids[] = array( - 'object_type' => 'song', - 'object_id' => scrub_in($_REQUEST['song_id']) - ); - break; - case 'artist': - $artist = new Artist($_REQUEST['artist_id']); - $media_ids = $artist->get_songs(); - break; - case 'artist_random': - $artist = new Artist($_REQUEST['artist_id']); - $artist->get_count(); - $media_ids = $artist->get_random_songs(); - break; - case 'album_random': - $album = new Album($_REQUEST['album_id']); - $media_ids = $album->get_random_songs(); - break; - case 'album': - $album = new Album($_REQUEST['album_id']); - $media_ids = $album->get_songs(); - break; - case 'playlist': - $playlist = new Playlist($_REQUEST['playlist_id']); - $media_ids = $playlist->get_songs($_REQUEST['song']); - break; - case 'playlist_random': - $playlist = new Playlist($_REQUEST['playlist_id']); - $media_ids = $playlist->get_random_songs(); - break; - case 'random': - if($_REQUEST['genre'][0] != '-1') { - $matchlist['genre'] = $_REQUEST['genre']; - } - if($_REQUEST['catalog'] != '-1') { - $matchlist['catalog'] = $_REQUEST['catalog']; - } - /* Setup the options array */ - $options = array('limit' => $_REQUEST['random'], 'random_type' => $_REQUEST['random_type'],'size_limit'=>$_REQUEST['size_limit']); - $media_ids = get_random_songs($options, $matchlist); - break; - case 'democratic': - $democratic = new Democratic($_REQUEST['democratic_id']); - $urls = array($democratic->play_url()); - break; - case 'download': - $media_ids[] = array( - 'object_type' => 'song', - 'object_id' => scrub_in($_REQUEST['song_id']) - ); - default: - break; + break; + /* This is run if we need to gather info based on a tmp playlist */ + case 'tmp_playlist': + $tmp_playlist = new Tmp_Playlist($_REQUEST['tmpplaylist_id']); + $media_ids = $tmp_playlist->get_items(); + break; + case 'play_favorite': + $data = $GLOBALS['user']->get_favorites($_REQUEST['type']); + $media_ids = array(); + switch ($_REQUEST['type']) { + case 'artist': + case 'album': + foreach ($data as $value) { + $songs = $value->get_songs(); + $media_ids = array_merge($media_ids,$songs); + } + break; + case 'song': + foreach ($data as $value) { + $media_ids[] = $value->id; + } + break; + } // end switch on type + break; + case 'single_song': + $media_ids[] = array( + 'object_type' => 'song', + 'object_id' => scrub_in($_REQUEST['song_id']) + ); + break; + case 'artist': + $artist = new Artist($_REQUEST['artist_id']); + $media_ids = $artist->get_songs(); + break; + case 'artist_random': + $artist = new Artist($_REQUEST['artist_id']); + $artist->get_count(); + $media_ids = $artist->get_random_songs(); + break; + case 'album_random': + $album = new Album($_REQUEST['album_id']); + $media_ids = $album->get_random_songs(); + break; + case 'album': + $album = new Album($_REQUEST['album_id']); + $media_ids = $album->get_songs(); + break; + case 'playlist': + $playlist = new Playlist($_REQUEST['playlist_id']); + $media_ids = $playlist->get_songs($_REQUEST['song']); + break; + case 'playlist_random': + $playlist = new Playlist($_REQUEST['playlist_id']); + $media_ids = $playlist->get_random_songs(); + break; + case 'random': + if($_REQUEST['genre'][0] != '-1') { + $matchlist['genre'] = $_REQUEST['genre']; + } + if($_REQUEST['catalog'] != '-1') { + $matchlist['catalog'] = $_REQUEST['catalog']; + } + /* Setup the options array */ + $options = array('limit' => $_REQUEST['random'], 'random_type' => $_REQUEST['random_type'],'size_limit'=>$_REQUEST['size_limit']); + $media_ids = get_random_songs($options, $matchlist); + break; + case 'democratic': + $democratic = new Democratic($_REQUEST['democratic_id']); + $urls = array($democratic->play_url()); + break; + case 'download': + $media_ids[] = array( + 'object_type' => 'song', + 'object_id' => scrub_in($_REQUEST['song_id']) + ); + default: + break; } // end action switch // See if we need a special streamtype switch ($_REQUEST['action']) { - case 'download': - $stream_type = 'download'; - break; - case 'democratic': - // Don't let them loop it - // FIXME: This looks hacky - if (Config::get('play_type') == 'democratic') { - Config::set('play_type', 'stream', true); - } - default: - $stream_type = Config::get('play_type'); - if ($stream_type == 'stream') { - $stream_type = Config::get('playlist_type'); - } - break; + case 'download': + $stream_type = 'download'; + break; + case 'democratic': + // Don't let them loop it + // FIXME: This looks hacky + if (Config::get('play_type') == 'democratic') { + Config::set('play_type', 'stream', true); + } + default: + $stream_type = Config::get('play_type'); + if ($stream_type == 'stream') { + $stream_type = Config::get('playlist_type'); + } + break; } debug_event('stream.php' , 'Stream Type: ' . $stream_type . ' Media IDs: '. json_encode($media_ids), 5); $playlist = new Stream_Playlist(); $playlist->add($media_ids); if (isset($urls)) { - $playlist->add_urls($urls); + $playlist->add_urls($urls); } // Depending on the stream type, will either generate a redirect or actually do // the streaming. diff --git a/templates/base.css b/templates/base.css index 89f207c7f5..cecf6c9f22 100644 --- a/templates/base.css +++ b/templates/base.css @@ -1,4 +1,4 @@ -/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */ +/* vim:set softtabstop=4 shiftwidth=4 expandtab: */ /** * * LICENSE: GNU General Public License, version 2 (GPLv2) @@ -27,16 +27,16 @@ *****************/ .tag_size1 { - font-size:.6em; + font-size:.6em; } .tag_size2 { - font-size:.8em; + font-size:.8em; } .tag_size3 { - font-size:1em; + font-size:1em; } .tag_size4 { - font-size:1.2em; + font-size:1.2em; } a.tag_size1, a.tag_size2, a.tag_size3, a.tag_size4 { text-decoration: none; } @@ -48,8 +48,8 @@ a.tag_size1, a.tag_size2, a.tag_size3, a.tag_size4 { text-decoration: none; } * Generic / Misc *****************/ .item_on { - color: #347C17; + color: #347C17; } .item_off { - color: #FF0000; + color: #FF0000; } diff --git a/templates/browse_content.inc.php b/templates/browse_content.inc.php index 2b5fb94ac7..f1f5ea5df6 100644 --- a/templates/browse_content.inc.php +++ b/templates/browse_content.inc.php @@ -1,5 +1,5 @@

    -
    - - + + +
    - -
    - id . '&key=min_count&value=1', '')); ?> + +
    + id . '&key=min_count&value=1', '')); ?> - -
    - id . '&key=rated&value=1', '')); ?> + +
    + id . '&key=rated&value=1', '')); ?> - get_filter('unplayed') ? 'checked="checked"' : ''; ?>/> -
    + get_filter('unplayed') ? 'checked="checked"' : ''; ?>/> +
    - get_filter('playlist_type') ? 'checked="checked"' : ''; ?>/> -
    - id . '&key=playlist_type&value=1','')); ?> + get_filter('playlist_type') ? 'checked="checked"' : ''; ?>/> +
    + id . '&key=playlist_type&value=1','')); ?> - get_filter('object_type'); ${$string} = 'selected="selected"'; ?> - /> -
    - id . '&type=song','')); ?> - -
    - id . '&type=album','')); ?> - -
    - id . '&type=artist','')); ?> + get_filter('object_type'); ${$string} = 'selected="selected"'; ?> + /> +
    + id . '&type=song','')); ?> + +
    + id . '&type=album','')); ?> + +
    + id . '&type=artist','')); ?>
    -
    - +
    + id,'catalog_select', 'catalog_choice'), true); ?>
    -  /> - id, '')); ?> +  /> + id, '')); ?>
    diff --git a/templates/error_page.inc.php b/templates/error_page.inc.php index 62cd63f50f..cc4734bb26 100644 --- a/templates/error_page.inc.php +++ b/templates/error_page.inc.php @@ -1,5 +1,5 @@ + xml:lang="" lang="" + dir=""> @@ -36,20 +36,20 @@
    - -
     
    -
    - -

    - :
    - -
    + +
     
    +
    + +

    + :
    + +
    diff --git a/templates/footer.inc.php b/templates/footer.inc.php index 846fca7820..4176884fac 100644 --- a/templates/footer.inc.php +++ b/templates/footer.inc.php @@ -1,5 +1,5 @@
    diff --git a/templates/header.inc.php b/templates/header.inc.php index a1deb4028d..803147c930 100644 --- a/templates/header.inc.php +++ b/templates/header.inc.php @@ -1,5 +1,5 @@ /default.css" type="text/css" media="screen" />
    - - -
    - -
    + + +
    + +
    Loading . . .
    has_access(100)) { ?>
    - - + +
    diff --git a/templates/install.css b/templates/install.css index 359dd0bf8e..ddc4e0e72b 100644 --- a/templates/install.css +++ b/templates/install.css @@ -1,4 +1,4 @@ -/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */ +/* vim:set softtabstop=4 shiftwidth=4 expandtab: */ /** * * LICENSE: GNU General Public License, version 2 (GPLv2) @@ -20,123 +20,123 @@ */ body { - font-family:Arial, Helvetica, sans-serif; - font-size: 1em; - margin: 0; - padding: 0; - text-align: center; - background: #FFFFFF url(../images/top_bg.jpg) repeat-x top left; + font-family:Arial, Helvetica, sans-serif; + font-size: 1em; + margin: 0; + padding: 0; + text-align: center; + background: #FFFFFF url(../images/top_bg.jpg) repeat-x top left; } h3 { - text-align:left; - border-bottom: 1px dotted #cccccc; - padding-left: 10px; + text-align:left; + border-bottom: 1px dotted #cccccc; + padding-left: 10px; } /* Header */ #header { - width: 90%; - min-height: 85px; - height: 85px; - margin: 0 auto; - padding: 0; - text-align: left; - font-size: smaller; - display: block; + width: 90%; + min-height: 85px; + height: 85px; + margin: 0 auto; + padding: 0; + text-align: left; + font-size: smaller; + display: block; } #header h1 { - margin: 0; - padding-top: 16px; - color: #000; - font-weight: bold; - font-size: large; + margin: 0; + padding-top: 16px; + color: #000; + font-weight: bold; + font-size: large; } #header p { - font-size: smaller; - color: #000; - margin: 0px; + font-size: smaller; + color: #000; + margin: 0px; } /* Content */ #text-box { - width: 90%; - min-height: 85px; - height: 85px; - display: block; - margin: 0 auto; - padding: 0; - text-align: left; - font-size: smaller; + width: 90%; + min-height: 85px; + height: 85px; + display: block; + margin: 0 auto; + padding: 0; + text-align: left; + font-size: smaller; } .error { - color: #ff0033; - font-weight: bold; + color: #ff0033; + font-weight: bold; } .notify { - border: 1px solid #cccccc; - background-color: #f4f4f4; - padding: 5px; - margin-top: 3px; + border: 1px solid #cccccc; + background-color: #f4f4f4; + padding: 5px; + margin-top: 3px; } .content { - border: 1px solid #cccccc; - padding: 5px; - margin-top: 3px; + border: 1px solid #cccccc; + padding: 5px; + margin-top: 3px; } /* Table style */ td{ - padding:5px; - /*background-color: #D9E0E8;*/ - font-size: smaller; + padding:5px; + /*background-color: #D9E0E8;*/ + font-size: smaller; } .align{ - text-align:right; + text-align:right; } /* Estilos para formas */ input, radio, select, textarea { - border: 1px solid #ddd; - background: #f2f2f2; - font: 11px verdana, sans-serif; - color: #443; - padding: 2px; - outline: none; + border: 1px solid #ddd; + background: #f2f2f2; + font: 11px verdana, sans-serif; + color: #443; + padding: 2px; + outline: none; } input:hover, textarea:hover, input:focus, textarea:focus{ - border: 1px solid #aaa; + border: 1px solid #aaa; } /* Extras */ .ok { - font-weight:bold; - color:#009900; - margin:10px 10px 10px 10px; + font-weight:bold; + color:#009900; + margin:10px 10px 10px 10px; } .notok { - font-weight:bold; - color:#FF3300; - margin:3px 3px 3px 3px; + font-weight:bold; + color:#FF3300; + margin:3px 3px 3px 3px; } /* Bottom */ #bottom { - border-top: 1px dotted #cccccc; - margin-top: 10px; - margin-bottom: 10px; - padding:5px; + border-top: 1px dotted #cccccc; + margin-top: 10px; + margin-bottom: 10px; + padding:5px; } #bottom p { - font-size:10px; + font-size:10px; } diff --git a/templates/install_header.inc.php b/templates/install_header.inc.php index c30417a797..8b5c643418 100644 --- a/templates/install_header.inc.php +++ b/templates/install_header.inc.php @@ -1,5 +1,5 @@ For the love of Music

    -
    -

    -

    - -

    -
      -
    • +
      +

      +

      + +

      +
        +
      • -
      -

      +

    +

    -

    +

    diff --git a/templates/javascript_refresh.inc.php b/templates/javascript_refresh.inc.php index eacab77650..aa28b3dcc5 100644 --- a/templates/javascript_refresh.inc.php +++ b/templates/javascript_refresh.inc.php @@ -1,5 +1,5 @@ get_offset(); -$start = $browse->get_start(); -$total = $browse->get_total(); -$uid = Config::get('list_header_uid'); +$limit = $browse->get_offset(); +$start = $browse->get_start(); +$total = $browse->get_total(); +$uid = Config::get('list_header_uid'); $sides = 5; // ++ the uid @@ -47,86 +47,86 @@ /* Calculate how many pages total exist */ if ($limit > 0 && $total > $limit) { - $pages = ceil($total / $limit); + $pages = ceil($total / $limit); } else { - $pages = 0; + $pages = 0; } // are there enough items to even need this view? if ($pages > 1) { - /* Calculate current page and how many we have on each side */ - $page_data = array('up' => array(), 'down' => array()); + /* Calculate current page and how many we have on each side */ + $page_data = array('up' => array(), 'down' => array()); - // Can't divide by 0 - if ($start > 0) { - $current_page = floor($start / $limit); - } - else { - $current_page = 0; - } + // Can't divide by 0 + if ($start > 0) { + $current_page = floor($start / $limit); + } + else { + $current_page = 0; + } - // Create 10 pages in either direction - // Down first - $page = $current_page; - $i = 0; - while ($page > 0) { - if ($i == $sides) { $page_data['down'][1] = '...'; $page_data['down'][0] = '0'; break; } - $i++; - $page = $page - 1; - $page_data['down'][$page] = $page * $limit; - } // while page > 0 + // Create 10 pages in either direction + // Down first + $page = $current_page; + $i = 0; + while ($page > 0) { + if ($i == $sides) { $page_data['down'][1] = '...'; $page_data['down'][0] = '0'; break; } + $i++; + $page = $page - 1; + $page_data['down'][$page] = $page * $limit; + } // while page > 0 - // Then up - $page = $current_page + 1; - $i = 0; - while ($page <= $pages) { - if ($page * $limit > $total) { break; } - if ($i == $sides) { - $key = $pages - 1; - if (!$page_data['up'][$key]) { $page_data['up'][$key] = '...'; } - $page_data['up'][$pages] = ($pages - 1) * $limit; - break; - } - $i++; - $page = $page + 1; - $page_data['up'][$page] = ($page - 1) * $limit; - } // end while + // Then up + $page = $current_page + 1; + $i = 0; + while ($page <= $pages) { + if ($page * $limit > $total) { break; } + if ($i == $sides) { + $key = $pages - 1; + if (!$page_data['up'][$key]) { $page_data['up'][$key] = '...'; } + $page_data['up'][$pages] = ($pages - 1) * $limit; + break; + } + $i++; + $page = $page + 1; + $page_data['up'][$page] = ($page - 1) * $limit; + } // end while - // Sort these arrays of hotness - ksort($page_data['up']); - ksort($page_data['down']); + // Sort these arrays of hotness + ksort($page_data['up']); + ksort($page_data['down']); ?>
    id . '&start=' . $prev_offset, T_('Prev'),'browse_' . $uid . 'prev','','prev'); ?> - id . '&start=' . $next_offset, T_('Next'),'browse_' . $uid . 'next','','next'); ?> - $offset) { - if ($offset === '...') { echo '... '; } - else { - // Hack Alert - $page++; - echo Ajax::text('?page=browse&action=page&browse_id=' . $browse->id . '&start=' . $offset,$page,'browse_' . $uid . 'page_' . $page,'','page-nb'); - } - } // end foreach down + id . '&start=' . $next_offset, T_('Next'),'browse_' . $uid . 'next','','next'); ?> + $offset) { + if ($offset === '...') { echo '... '; } + else { + // Hack Alert + $page++; + echo Ajax::text('?page=browse&action=page&browse_id=' . $browse->id . '&start=' . $offset,$page,'browse_' . $uid . 'page_' . $page,'','page-nb'); + } + } // end foreach down - /* Echo current page */ - $current_page++; - ?> - - + + $offset) { - if ($offset === '...') { echo '... '; } - else { - echo Ajax::text('?page=browse&action=page&browse_id=' . $browse->id . '&start=' . $offset,$page,'browse_' . $uid . 'page_' . $page,'','page-nb'); - } // end else - } // end foreach up - ?> + /* Echo everything above us */ + foreach ($page_data['up'] as $page=>$offset) { + if ($offset === '...') { echo '... '; } + else { + echo Ajax::text('?page=browse&action=page&browse_id=' . $browse->id . '&start=' . $offset,$page,'browse_' . $uid . 'page_' . $page,'','page-nb'); + } // end else + } // end foreach up + ?>
      -
    • - -
    • -
    • - - -
    • +
    • + +
    • +
    • + + +
    • -
    • - - +
    • + + -
    • + -
    • - -
    • -
    • - - -
    • +
    • + +
    • +
    • + + +
      playlist->get_items(); - } + //FIXME :: this is kludgy + if (!defined('NO_SONGS')) { + $objects = $GLOBALS['user']->playlist->get_items(); + } - // Limit the number of objects we show here - if (count($objects) > 100) { - $truncated = (count($objects) - 100); - $objects = array_slice($objects, 0, 100, true); - } + // Limit the number of objects we show here + if (count($objects) > 100) { + $truncated = (count($objects) - 100); + $objects = array_slice($objects, 0, 100, true); + } - $normal_array = array('radio','song','video','random'); + $normal_array = array('radio','song','video','random'); - foreach ($objects as $uid=>$object_data) { - $type = array_shift($object_data); - if (in_array($type,$normal_array)) { - $object = new $type(array_shift($object_data)); - $object->format(); - } - if ($type == 'random') { - $object->f_link = Random::get_type_name($type); - } + foreach ($objects as $uid=>$object_data) { + $type = array_shift($object_data); + if (in_array($type,$normal_array)) { + $object = new $type(array_shift($object_data)); + $object->format(); + } + if ($type == 'random') { + $object->f_link = Random::get_type_name($type); + } ?>
    • f_link; ?> - +
    • -
    • +
    • -
    • - ... -
    • +
    • + ... +
    @@ -121,6 +121,6 @@ // We do this last because we want it to load, and we want to know if there is anything // to even pass if (count($objects)) { - Stream::run_playlist_method(); + Stream::run_playlist_method(); } ?> diff --git a/templates/show_access_list.inc.php b/templates/show_access_list.inc.php index 2973e01cc6..c724779b9c 100644 --- a/templates/show_access_list.inc.php +++ b/templates/show_access_list.inc.php @@ -1,5 +1,5 @@
      -
    • - - -
    • -
    • - - -
    • -
    • - - -
    • - - -
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • + + +
    @@ -47,33 +47,33 @@ - - - - - - - + + + + + + + format(); + /* Start foreach List Item */ + foreach ($list as $access_id) { + $access = new Access($access_id); + $access->format(); ?> - - - - - - - + + + + + + + - +
    name); ?>f_start; ?>f_end; ?>f_level; ?>f_user; ?>f_type; ?> - - - name); ?>f_start; ?>f_end; ?>f_level; ?>f_user; ?>f_type; ?> + + +
    diff --git a/templates/show_account.inc.php b/templates/show_account.inc.php index 84b8ecf41f..0cf951f8d8 100644 --- a/templates/show_account.inc.php +++ b/templates/show_account.inc.php @@ -1,5 +1,5 @@ /preferences.php?action=update_user" enctype="multipart/form-data"> - - + + - - + + - - + + - - + + - - + +
    : - - : + +
    : - - : + +
    : - - - : + + +
    : - - : + +
    : - - : + +
    - - - - + + + +
    diff --git a/templates/show_add_access.inc.php b/templates/show_add_access.inc.php index 9e030ccc91..b2d0353105 100644 --- a/templates/show_add_access.inc.php +++ b/templates/show_add_access.inc.php @@ -1,5 +1,5 @@ /admin/access.php?action=add_host"> - - + + - - + + - - + + + + - + - - - - + + + +
    : - - : + +
    : - - - - - : + + + + +
    : - - : + +
    : - - + - + - - - - + -

    - (255.255.255.255) / (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff) -

    + (255.255.255.255) / (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff) +
    : - - - : - - - : + + + : + + +
    - - + +
    diff --git a/templates/show_add_catalog.inc.php b/templates/show_add_catalog.inc.php index 7a3049f736..28f01414cc 100644 --- a/templates/show_add_catalog.inc.php +++ b/templates/show_add_catalog.inc.php @@ -1,5 +1,5 @@ /admin/catalog.php" enctype="multipart/form-data"> - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    : - :
    - %A =
    - %a =
    - %c =
    - %T =
    - %t =
    - %y =
    - %o =
    -
    : + :
    + %A =
    + %a =
    + %c =
    + %T =
    + %t =
    + %y =
    + %o =
    +
    : :
    : - - : + +
    : *: *
    : *: *
    : :
    :
    :
    ::
    ::
    diff --git a/templates/show_add_live_stream.inc.php b/templates/show_add_live_stream.inc.php index ef7402ed65..37a0b8a3bb 100644 --- a/templates/show_add_live_stream.inc.php +++ b/templates/show_add_live_stream.inc.php @@ -1,5 +1,5 @@ /radio.php?action=create"> - - + + - - + + - - + + - - + + - - + + - - + +
    - - - + + +
    - - - + + +
    - - - + + +
    - - + +
    - - + +
    - - + +
    - - + +
    diff --git a/templates/show_add_playlist.inc.php b/templates/show_add_playlist.inc.php index 2a1239b46f..9ad0f4295c 100644 --- a/templates/show_add_playlist.inc.php +++ b/templates/show_add_playlist.inc.php @@ -1,5 +1,5 @@ /playlist.php"> - - + + - - + +
    ::
    : - - : + +
    - - + +
    diff --git a/templates/show_add_shout.inc.php b/templates/show_add_shout.inc.php index 739b1571c5..653140848f 100644 --- a/templates/show_add_shout.inc.php +++ b/templates/show_add_shout.inc.php @@ -1,5 +1,5 @@ /shout.php?action=add_shout"> - - + - + - +
    +
    - - - - - + + + + +
    diff --git a/templates/show_add_user.inc.php b/templates/show_add_user.inc.php index d42988cdbc..56d6461fd7 100644 --- a/templates/show_add_user.inc.php +++ b/templates/show_add_user.inc.php @@ -1,5 +1,5 @@ "> - - + + - - + + - - + + - - + + - - + + - +
    - : - - - - + : + + + +
    : - - : + +
    - : - - - + : + + +
    - : - - - - + : + + + +
    - : - - - + : + + +
    - : - + : + access; ${$var_name} = 'selected="selected"'; ?>
    - - + +
    diff --git a/templates/show_adds_catalog.inc.php b/templates/show_adds_catalog.inc.php index a1ddf4d97d..7fb04e3232 100644 --- a/templates/show_adds_catalog.inc.php +++ b/templates/show_adds_catalog.inc.php @@ -1,5 +1,5 @@ - + -   - -
    - ... -
    +   + +
    + ... +
    diff --git a/templates/show_admin_tools.inc.php b/templates/show_admin_tools.inc.php index 0df0be23f8..6bff287860 100644 --- a/templates/show_admin_tools.inc.php +++ b/templates/show_admin_tools.inc.php @@ -1,5 +1,5 @@ @@ -31,48 +31,48 @@ - - + + - - - name); ?> -   (path); ?>) - - - -  |  - -  |  - -  |  - -  |  - - - + + + name); ?> +   (path); ?>) + + + +  |  + +  |  + +  |  + +  |  + + + - - - + + + - - + +
    @@ -88,12 +88,12 @@
    - - - - - - - + + + + + + +
    diff --git a/templates/show_album.inc.php b/templates/show_album.inc.php index 449203baed..b987bf5be4 100644 --- a/templates/show_album.inc.php +++ b/templates/show_album.inc.php @@ -1,5 +1,5 @@ name) . ' (' . $album->year . ')'; if ($album->disk) { - $title .= "disk . "\">, " . T_('Disk') . " " . $album->disk . ""; + $title .= "disk . "\">, " . T_('Disk') . " " . $album->disk . ""; } $title .= ' - ' . $album->f_artist_link; ?>
    - name != T_('Unknown (Orphaned)')) { + name != T_('Unknown (Orphaned)')) { $name = '[' . $album->f_artist . '] ' . scrub_out($album->full_name); - $aa_url = $web_path . "/image.php?id=" . $album->id . "&type=popup&sid=" . session_id(); - echo ""; - echo "\"".$name."\""; - echo "\n"; - } - ?> + $aa_url = $web_path . "/image.php?id=" . $album->id . "&type=popup&sid=" . session_id(); + echo ""; + echo "\"".$name."\""; + echo "\n"; + } + ?>
    - id,'album'); ?> + id,'album'); ?>

    :

      -
    • - id,'add', T_('Add'),'play_full_' . $album->id); ?> - id, T_('Add Album'), 'play_full_text_' . $album->id); ?> -
    • -
    • - id,'random', T_('Random'),'play_random_' . $album->id); ?> - id, T_('Add Random from Album'), 'play_random_text_' . $album->id); ?> -
    • - -
    • - - -
    • - -
    • - - -
    • - -
    • - - -
    • - - -
    • - - -
    • - +
    • + id,'add', T_('Add'),'play_full_' . $album->id); ?> + id, T_('Add Album'), 'play_full_text_' . $album->id); ?> +
    • +
    • + id,'random', T_('Random'),'play_random_' . $album->id); ?> + id, T_('Add Random from Album'), 'play_random_text_' . $album->id); ?> +
    • + +
    • + + +
    • + +
    • + + +
    • + +
    • + + +
    • + + +
    • + + +
    • +
    @@ -85,12 +85,12 @@  
    set_type('song'); - $browse->set_simple_browse(true); - $browse->set_filter('album', $album->id); - $browse->set_sort('track', 'ASC'); - $browse->get_objects(); - $browse->show_objects(); - $browse->store(); + $browse = new Browse(); + $browse->set_type('song'); + $browse->set_simple_browse(true); + $browse->set_filter('album', $album->id); + $browse->set_sort('track', 'ASC'); + $browse->get_objects(); + $browse->show_objects(); + $browse->store(); ?> diff --git a/templates/show_album_art.inc.php b/templates/show_album_art.inc.php index 838bf5fba4..1ff7fefcbe 100644 --- a/templates/show_album_art.inc.php +++ b/templates/show_album_art.inc.php @@ -1,5 +1,5 @@  \n"; } - else { + $j=0; + while ($j < 4) { + $key = $i*4+$j; + $image_url = Config::get('web_path') . '/image.php?type=session&image_index=' . $key; + $dimensions = Core::image_dimensions(Art::get_from_source($_SESSION['form']['images'][$key], 'album')); + if (!isset($images[$key])) { echo " \n"; } + else { ?> - - <?php echo T_('Album Art'); ?> -
    -

    - - [x] - - - - [] -

    - + + <?php echo T_('Album Art'); ?> +
    +

    + + [x] + + + + [] +

    + \n"; } + } // end else + $j++; + } // end while cells + if($i < $rows) { echo "\n"; } else { echo ""; } - $i++; + $i++; } // end while ?> diff --git a/templates/show_album_row.inc.php b/templates/show_album_row.inc.php index db6ce30bc5..1d3782de51 100644 --- a/templates/show_album_row.inc.php +++ b/templates/show_album_row.inc.php @@ -1,5 +1,5 @@ - id,'add', T_('Add'),'add_album_' . $album->id); ?> - id,'random', T_('Random'),'random_album_' . $album->id); ?> + id,'add', T_('Add'),'add_album_' . $album->id); ?> + id,'random', T_('Random'),'random_album_' . $album->id); ?> f_artist . '] ' . scrub_out($album->full_name); + $name = '[' . $album->f_artist . '] ' . scrub_out($album->full_name); ?> - <?php echo($name) ?> + <?php echo($name) ?> @@ -41,17 +41,17 @@ f_tags; ?> id,'album'); ?> - - - - - - - - - - - - id,'edit', T_('Edit'),'edit_album_' . $album->id); ?> - + + + + + + + + + + + + id,'edit', T_('Edit'),'edit_album_' . $album->id); ?> + diff --git a/templates/show_albums.inc.php b/templates/show_albums.inc.php index a97276348b..41d5ccb0c9 100644 --- a/templates/show_albums.inc.php +++ b/templates/show_albums.inc.php @@ -1,5 +1,5 @@ - - - - - id . '&sort=name', T_('Album'),'album_sort_name'); ?> - id . '&sort=artist', T_('Artist'),'album_sort_artist'); ?> - - id . '&sort=year', T_('Year'),'album_sort_year'); ?> - - - + + + + + id . '&sort=name', T_('Album'),'album_sort_name'); ?> + id . '&sort=artist', T_('Artist'),'album_sort_artist'); ?> + + id . '&sort=year', T_('Year'),'album_sort_year'); ?> + + + format(); + if (Config::get('ratings')) { + Rating::build_cache('album',$object_ids); + } + /* Foreach through the albums */ + foreach ($object_ids as $album_id) { + $album = new Album($album_id); + $album->format(); ?> - + - + - - - - - id . '&sort=name', T_('Album'),'album_sort_name_bottom'); ?> - - - id . '&sort=year', T_('Year'),'album_sort_year_bottom'); ?> - - - + + + + + id . '&sort=name', T_('Album'),'album_sort_name_bottom'); ?> + + + id . '&sort=year', T_('Year'),'album_sort_year_bottom'); ?> + + + diff --git a/templates/show_all_popular.inc.php b/templates/show_all_popular.inc.php index 8f1b411988..ea05b14b9b 100644 --- a/templates/show_all_popular.inc.php +++ b/templates/show_all_popular.inc.php @@ -1,5 +1,5 @@ - - - + + + - - - + + +
    - - - - - - + + + + + +
     
    - - - - - - + + + + + +
     
    diff --git a/templates/show_alphabet_form.inc.php b/templates/show_alphabet_form.inc.php index 0efcdc9b07..e1d0865801 100644 --- a/templates/show_alphabet_form.inc.php +++ b/templates/show_alphabet_form.inc.php @@ -1,5 +1,5 @@
    " enctype="multipart/form-data"> - - - + + +
    diff --git a/templates/show_artist.inc.php b/templates/show_artist.inc.php index aa26d52db4..7bf95c5660 100644 --- a/templates/show_artist.inc.php +++ b/templates/show_artist.inc.php @@ -1,5 +1,5 @@
    - id, 'artist'); ?> + id, 'artist'); ?>

    :

    • - - - - f_name); ?> - - - - f_name); ?> - + + + + f_name); ?> + + + + f_name); ?> +
    • - - id,'add', T_('Add'),'add_' . $artist->id); ?> - id,sprintf(T_('Add All Songs By %s'), $artist->f_name),'add_text_' . $artist->id); ?> + + id,'add', T_('Add'),'add_' . $artist->id); ?> + id,sprintf(T_('Add All Songs By %s'), $artist->f_name),'add_text_' . $artist->id); ?>
    • - - id,'random', T_('Random'),'random_' . $artist->id); ?> - id, sprintf(T_('Add Random Songs By %s'), $artist->f_name),'random_text_' . $artist->id); ?> + + id,'random', T_('Random'),'random_' . $artist->id); ?> + id, sprintf(T_('Add Random Songs By %s'), $artist->f_name),'random_text_' . $artist->id); ?>
    • - - + +
    • - - + +
    • @@ -75,6 +75,6 @@
    show_objects($object_ids); - $browse->store(); + $browse->show_objects($object_ids); + $browse->store(); ?> diff --git a/templates/show_artist_row.inc.php b/templates/show_artist_row.inc.php index f7612c1e4e..295d2e8599 100644 --- a/templates/show_artist_row.inc.php +++ b/templates/show_artist_row.inc.php @@ -1,5 +1,5 @@ - id,'add', T_('Add'),'add_artist_' . $artist->id); ?> - id,'random', T_('Random'),'random_artist_' . $artist->id); ?> + id,'add', T_('Add'),'add_artist_' . $artist->id); ?> + id,'random', T_('Random'),'random_artist_' . $artist->id); ?> f_name_link; ?> songs; ?> @@ -32,11 +32,11 @@ id,'artist'); ?> - - + + - id,'edit', T_('Edit'),'edit_artist_' . $artist->id); ?> + id,'edit', T_('Edit'),'edit_artist_' . $artist->id); ?> diff --git a/templates/show_artists.inc.php b/templates/show_artists.inc.php index 36d9b01e30..0a3b664b57 100644 --- a/templates/show_artists.inc.php +++ b/templates/show_artists.inc.php @@ -1,5 +1,5 @@ - - - - - - - - + + + + + + + + format(); + $artist = new Artist($artist_id, $_SESSION['catalog']); + $artist->format(); ?> - + - + - - - - - - - - + + + + + + + + diff --git a/templates/show_big_art.inc.php b/templates/show_big_art.inc.php index 08fdb72fb3..c969ff6cbe 100644 --- a/templates/show_big_art.inc.php +++ b/templates/show_big_art.inc.php @@ -1,5 +1,5 @@
    -

    - +

    +
    diff --git a/templates/show_catalog_row.inc.php b/templates/show_catalog_row.inc.php index 7aef9d2721..189e99340d 100644 --- a/templates/show_catalog_row.inc.php +++ b/templates/show_catalog_row.inc.php @@ -1,5 +1,5 @@ f_add); ?> f_clean); ?> - - | + + | | - | - | - | + | + | + | diff --git a/templates/show_catalogs.inc.php b/templates/show_catalogs.inc.php index c9f8cedd29..86ab877ee6 100644 --- a/templates/show_catalogs.inc.php +++ b/templates/show_catalogs.inc.php @@ -1,5 +1,5 @@ - - - - - - + + + + + + format(); + foreach ($object_ids as $catalog_id) { + $catalog = new Catalog($catalog_id); + $catalog->format(); ?> - + - + - - - - - - + + + + + + diff --git a/templates/show_clean_catalog.inc.php b/templates/show_clean_catalog.inc.php index f3f264643c..07fdf1453a 100644 --- a/templates/show_clean_catalog.inc.php +++ b/templates/show_clean_catalog.inc.php @@ -1,5 +1,5 @@
    -
    - - -
    +
    + + +
    -
    - - -
    +
    + + +
    diff --git a/templates/show_create_democratic.inc.php b/templates/show_create_democratic.inc.php index ec82941627..8ec5396ae2 100644 --- a/templates/show_create_democratic.inc.php +++ b/templates/show_create_democratic.inc.php @@ -1,5 +1,5 @@ /democratic.php?action=create" enctype="multipart/form-data"> - - + + - - + + - - + + - - + +
    base_playlist); ?>base_playlist); ?>
    - - + +
    diff --git a/templates/show_debug.inc.php b/templates/show_debug.inc.php index 369774eb7b..3669fb2abc 100644 --- a/templates/show_debug.inc.php +++ b/templates/show_debug.inc.php @@ -1,5 +1,5 @@
    • - - + +
    • - - + +
    @@ -37,48 +37,48 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    Open BasedirOpen Basedir
    @@ -90,25 +90,25 @@ - - + + $value) { - if ($key == 'database_password' || $key == 'mysql_password') { $value = '*********'; } - if (is_array($value)) { - $string = ''; - foreach ($value as $setting) { - $string .= $setting . '
    '; - } - $value = $string; - } - if (Preference::is_boolean($key)) { - $value = print_bool($value); - } + if ($key == 'database_password' || $key == 'mysql_password') { $value = '*********'; } + if (is_array($value)) { + $string = ''; + foreach ($value as $setting) { + $string .= $setting . '
    '; + } + $value = $string; + } + if (Preference::is_boolean($key)) { + $value = print_bool($value); + } ?> - - + + diff --git a/templates/show_democratic.inc.php b/templates/show_democratic.inc.php index ed951c06ac..c3c8be1893 100644 --- a/templates/show_democratic.inc.php +++ b/templates/show_democratic.inc.php @@ -1,5 +1,5 @@ is_enabled()) { ?>
  • - :f_cooldown; ?> + :f_cooldown; ?>
  • - - + +
  • is_enabled()) { ?>
  • - id),'all', T_('Play'),'play_democratic'); ?> - + id),'all', T_('Play'),'play_democratic'); ?> +
  • - id),'delete', T_('Clear Playlist'),'clear_democratic'); ?> - + id),'delete', T_('Clear Playlist'),'clear_democratic'); ?> +
  • diff --git a/templates/show_democratic_playlist.inc.php b/templates/show_democratic_playlist.inc.php index 49dd889e46..1ce5bda647 100644 --- a/templates/show_democratic_playlist.inc.php +++ b/templates/show_democratic_playlist.inc.php @@ -1,5 +1,5 @@ base_playlist); + $playlist = new Playlist($democratic->base_playlist); ?> - : - - name); ?> - + : + + name); ?> + - - - - - - - - - + + + + + + + + + set_parent(); foreach($object_ids as $item) { - $media = new $item['object_type']($item['object_id']); - $media->format(); + $media = new $item['object_type']($item['object_id']); + $media->format(); ?> - - has_vote($item['object_id'], $item['object_type'])) { ?> - - - id . '&type=' . scrub_out($item['object_type']),'tick', T_('Add Vote'),'remove_vote_' . $item['id']); ?> - - - get_vote($item['id'])); ?> - f_link; ?> - f_album_link; ?> - f_artist_link; ?> - f_time; ?> - - - - - + + has_vote($item['object_id'], $item['object_type'])) { ?> + + + id . '&type=' . scrub_out($item['object_type']),'tick', T_('Add Vote'),'remove_vote_' . $item['id']); ?> + + + get_vote($item['id'])); ?> + f_link; ?> + f_album_link; ?> + f_artist_link; ?> + f_time; ?> + + + + + - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + - - - title; ?> - get_album_name($song->album); ?> - get_artist_name($song->album); ?> - file; ?> - addition_time); ?> + + + title; ?> + get_album_name($song->album); ?> + get_artist_name($song->album); ?> + file; ?> + addition_time); ?> - + - - - + + + - - - - - - + + + + + +
    -    - +    +
    diff --git a/templates/show_duplicate.inc.php b/templates/show_duplicate.inc.php index bc5435f2a1..85cd33795c 100644 --- a/templates/show_duplicate.inc.php +++ b/templates/show_duplicate.inc.php @@ -1,5 +1,5 @@ /admin/duplicates.php?action=find_duplicates" method="post" enctype="multipart/form-data" > - + +
    :: - - />
    + + />
    />
    />
    />
    -
    diff --git a/templates/show_duplicates.inc.php b/templates/show_duplicates.inc.php index 6a62e19ca3..8bd9cbda44 100644 --- a/templates/show_duplicates.inc.php +++ b/templates/show_duplicates.inc.php @@ -1,5 +1,5 @@ - - - - - - - - + + + + + + + + $song_id) { - $song = new Song($song_id); - $song->format(); - $row_key = 'duplicate_' . $song_id; - $button_flip_state_id = 'button_flip_state_' . $song_id; - $current_class = ($key == '0') ? 'row-highlight' : UI::flip_class(); - $button = $song->enabled ? 'disable' : 'enable'; - ?> + foreach ($songs as $key => $song_id) { + $song = new Song($song_id); + $song->format(); + $row_key = 'duplicate_' . $song_id; + $button_flip_state_id = 'button_flip_state_' . $song_id; + $current_class = ($key == '0') ? 'row-highlight' : UI::flip_class(); + $button = $song->enabled ? 'disable' : 'enable'; + ?> - - - - f_link; ?> - f_artist_link; ?> - f_album_link; ?> - f_time; ?> - f_bitrate; ?> - f_size; ?> - file); ?> + + + + f_link; ?> + f_artist_link; ?> + f_album_link; ?> + f_time; ?> + f_bitrate; ?> + f_size; ?> + file); ?> - - - - - - - - + + + + + + + + diff --git a/templates/show_dynamic.inc.php b/templates/show_dynamic.inc.php index 67173b97e4..65e411e766 100644 --- a/templates/show_dynamic.inc.php +++ b/templates/show_dynamic.inc.php @@ -1,5 +1,5 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - +
    - - - - - - - - + + + + + + + +
    - - - - - - + + + + + +
    -
    -
    +
    +
    diff --git a/templates/show_edit_access.inc.php b/templates/show_edit_access.inc.php index 88cdae60d4..b9a2e6f33c 100644 --- a/templates/show_edit_access.inc.php +++ b/templates/show_edit_access.inc.php @@ -1,5 +1,5 @@ /admin/access.php?action=update_record&access_id=id); ?>"> - - + + - + - - - - + + + + - - + + - - + +
    : :
    : :
    : - - - : - - - : + + + : + + +
    : - user); ?> - : + user); ?> +
    : - level; ${$name} = 'checked="checked"'; ?> - > - > - > - > - : + level; ${$name} = 'checked="checked"'; ?> + > + > + > + > +
    - - + +
    diff --git a/templates/show_edit_album.inc.php b/templates/show_edit_album.inc.php index 6895bd1fcc..e1a403343c 100644 --- a/templates/show_edit_album.inc.php +++ b/templates/show_edit_album.inc.php @@ -1,5 +1,5 @@ /admin/flag.php?action=edit_album"> - - + + - - + + - - + +
    - - + +
    - - + +
      - -   + +
    - - + +
    diff --git a/templates/show_edit_album_row.inc.php b/templates/show_edit_album_row.inc.php index e0330e220a..3ea037d8b9 100644 --- a/templates/show_edit_album_row.inc.php +++ b/templates/show_edit_album_row.inc.php @@ -1,5 +1,5 @@ - + - artist_count == '1') { - show_artist_select('artist',$album->artist_id); - } - else { - echo T_('Various'); - } - ?> + artist_count == '1') { + show_artist_select('artist',$album->artist_id); + } + else { + echo T_('Various'); + } + ?> - + - + - - - id . '&type=album_row','download', T_('Save Changes'),'save_album_' . $album->id,'edit_album_' . $album->id); ?> + + + id . '&type=album_row','download', T_('Save Changes'),'save_album_' . $album->id,'edit_album_' . $album->id); ?> diff --git a/templates/show_edit_artist.inc.php b/templates/show_edit_artist.inc.php index 14bb89fe5d..5fc2f383e1 100644 --- a/templates/show_edit_artist.inc.php +++ b/templates/show_edit_artist.inc.php @@ -1,5 +1,5 @@ /admin/flag.php?action=edit_artist"> - - + + - - + +
    - - + +
      - -   + +
    - - + +
    diff --git a/templates/show_edit_artist_row.inc.php b/templates/show_edit_artist_row.inc.php index 97424f912c..2c52d59f14 100644 --- a/templates/show_edit_artist_row.inc.php +++ b/templates/show_edit_artist_row.inc.php @@ -1,5 +1,5 @@ - + - - - id . '&type=artist_row','download', T_('Save Changes'),'save_artist_' . $artist->id,'edit_artist_' . $artist->id); ?> + + + id . '&type=artist_row','download', T_('Save Changes'),'save_artist_' . $artist->id,'edit_artist_' . $artist->id); ?> diff --git a/templates/show_edit_catalog.inc.php b/templates/show_edit_catalog.inc.php index c7d5752eab..7a6e6b8507 100644 --- a/templates/show_edit_catalog.inc.php +++ b/templates/show_edit_catalog.inc.php @@ -1,5 +1,5 @@ /admin/catalog.php" enctype="multipart/form-data"> - - - + + + - - + + @@ -51,24 +51,24 @@ - - + + - - + +
    : - :
    - %A=
    - %a=
    - %c=
    - %T=
    - %t=
    - %y=
    - %o=
    -
    : + :
    + %A=
    + %a=
    + %c=
    + %T=
    + %t=
    + %y=
    + %o=
    +
    catalog_type)); ?>catalog_type)); ?>
    : *
    : - - : + +
    - :
    -
    - - + :
    +
    + +
    - - - + + +
    diff --git a/templates/show_edit_live_stream_row.inc.php b/templates/show_edit_live_stream_row.inc.php index 51e076c964..d44e560561 100644 --- a/templates/show_edit_live_stream_row.inc.php +++ b/templates/show_edit_live_stream_row.inc.php @@ -1,5 +1,5 @@ id; ?>"> - - - - - - + + + + + +
      
    - + - + - + - + - + - - - id . '&type=live_stream_row','download', T_('Save Changes'),'save_live_stream_' . $radio->id,'edit_live_stream_' . $radio->id); ?> + + + id . '&type=live_stream_row','download', T_('Save Changes'),'save_live_stream_' . $radio->id,'edit_live_stream_' . $radio->id); ?>
    diff --git a/templates/show_edit_playlist_row.inc.php b/templates/show_edit_playlist_row.inc.php index 9728f05ae1..0c587efed0 100644 --- a/templates/show_edit_playlist_row.inc.php +++ b/templates/show_edit_playlist_row.inc.php @@ -1,5 +1,5 @@ id; ?>" action="javascript:void(0);"> - - + +
    - - - type; ${$name} = ' selected="selected"'; ?> - - - - - id . '&type=playlist_row','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> - + + + type; ${$name} = ' selected="selected"'; ?> + + + + + id . '&type=playlist_row','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> +
    diff --git a/templates/show_edit_playlist_song_row.inc.php b/templates/show_edit_playlist_song_row.inc.php index f5efe59377..edaba2a073 100644 --- a/templates/show_edit_playlist_song_row.inc.php +++ b/templates/show_edit_playlist_song_row.inc.php @@ -1,5 +1,5 @@ - + f_link; ?> f_artist_link; ?> @@ -34,9 +34,9 @@ f_track; ?> f_time; ?> - - - id . '&track_id=' . $track['id'],'download', T_('Save Changes'),'save_track_' . $track['id'],'edit_track_' . $track['id']); ?> + + + id . '&track_id=' . $track['id'],'download', T_('Save Changes'),'save_track_' . $track['id'],'edit_track_' . $track['id']); ?> diff --git a/templates/show_edit_playlist_title.inc.php b/templates/show_edit_playlist_title.inc.php index 475a882e9f..07707c11db 100644 --- a/templates/show_edit_playlist_title.inc.php +++ b/templates/show_edit_playlist_title.inc.php @@ -1,5 +1,5 @@ id; ?>" action="javascript:void(0);"> - - + +
    - - - type; ${$name} = ' selected="selected"'; ?> - - - - - id . '&type=playlist_title','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> - + + + type; ${$name} = ' selected="selected"'; ?> + + + + + id . '&type=playlist_title','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> +
    diff --git a/templates/show_edit_shout.inc.php b/templates/show_edit_shout.inc.php index c20fee9bbb..eb4b376d86 100644 --- a/templates/show_edit_shout.inc.php +++ b/templates/show_edit_shout.inc.php @@ -1,5 +1,5 @@ id; ?>" /> - - - + - + - +
    f_link, $object->f_link); ?> + f_link, $object->f_link); ?>
    +
    sticky == "1") { echo "checked"; } ?>/> sticky == "1") { echo "checked"; } ?>/>
    - - + +
    diff --git a/templates/show_edit_smartplaylist_row.inc.php b/templates/show_edit_smartplaylist_row.inc.php index 08feb91201..d366182a76 100644 --- a/templates/show_edit_smartplaylist_row.inc.php +++ b/templates/show_edit_smartplaylist_row.inc.php @@ -1,5 +1,5 @@ id; ?>" action="javascript:void(0);"> - - + +
    - - - type; ${$name} = ' selected="selected"'; ?> - - - - - id . '&type=smartplaylist_row','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> - + + + type; ${$name} = ' selected="selected"'; ?> + + + + + id . '&type=smartplaylist_row','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> +
    diff --git a/templates/show_edit_smartplaylist_title.inc.php b/templates/show_edit_smartplaylist_title.inc.php index f036235d5e..b7432eb0d8 100644 --- a/templates/show_edit_smartplaylist_title.inc.php +++ b/templates/show_edit_smartplaylist_title.inc.php @@ -1,5 +1,5 @@ id; ?>" action="javascript:void(0);"> - - + +
    - - - type; ${$name} = ' selected="selected"'; ?> - - - - - id . '&type=smartplaylist_title','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> - + + + type; ${$name} = ' selected="selected"'; ?> + + + + + id . '&type=smartplaylist_title','download', T_('Save Changes'),'save_playlist_' . $playlist->id,'edit_playlist_' . $playlist->id); ?> +
    diff --git a/templates/show_edit_song.inc.php b/templates/show_edit_song.inc.php index 95c427cc16..d679396336 100644 --- a/templates/show_edit_song.inc.php +++ b/templates/show_edit_song.inc.php @@ -1,5 +1,5 @@ /admin/flag.php"> - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    :file); ?>:file); ?>
    - - + +
    - album); ?> -

    - -
    + album); ?> +

    + +
    - artist); ?> -

    - -
    + artist); ?> +

    + +
    - - + +
    - - + +
    - - + +
      - -   + +
    - - - + + +
    diff --git a/templates/show_edit_song_row.inc.php b/templates/show_edit_song_row.inc.php index 90535c3117..d3a87ab121 100644 --- a/templates/show_edit_song_row.inc.php +++ b/templates/show_edit_song_row.inc.php @@ -1,5 +1,5 @@ - + - artist,true,$song->id); ?> -
    + artist,true,$song->id); ?> +
    id,'change','check_inline_song_edit("artist", '.$song->id.')'); ?> - album,true,$song->id); ?> -
    + album,true,$song->id); ?> +
    id,'change','check_inline_song_edit("album", '.$song->id.')'); ?> - + - - - id . '&type=song_row','download', T_('Save Changes'),'save_song_' . $song->id,'edit_song_' . $song->id); ?> + + + id . '&type=song_row','download', T_('Save Changes'),'save_song_' . $song->id,'edit_song_' . $song->id); ?> diff --git a/templates/show_edit_user.inc.php b/templates/show_edit_user.inc.php index 76dfb198e0..d6cb99424f 100644 --- a/templates/show_edit_user.inc.php +++ b/templates/show_edit_user.inc.php @@ -1,5 +1,5 @@ "> - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + +
    - : - - - - + : + + + +
    : - - : + +
    - : - - - + : + + +
    - : - - - - + : + + + +
    - : - - - + : + + +
    - : - + + : + access; ${$var_name} = 'selected="selected"'; ?> -
    - - + +
    - - + +
    - - + +
    - - - - + + + +
    diff --git a/templates/show_export.inc.php b/templates/show_export.inc.php index 9615149284..e7cd949e44 100644 --- a/templates/show_export.inc.php +++ b/templates/show_export.inc.php @@ -1,5 +1,5 @@ /admin/export.php?action=export" method="post" enctype="multipart/form-data" > - - + + + - - + +
    : - : + -
    : - - : + +
    diff --git a/templates/show_flag_row.inc.php b/templates/show_flag_row.inc.php index cbeef4f857..36eff61255 100644 --- a/templates/show_flag_row.inc.php +++ b/templates/show_flag_row.inc.php @@ -1,5 +1,5 @@ - f_name; ?> - f_user; ?> - print_flag(); ?> - comment); ?> - print_status(); ?> - - approved) { ?> - id,'disable', T_('Reject'),'reject_flag_' . $flag->id); ?> - - id,'enable', T_('Enable'),'enable_flag_' . $flag->id); ?> - - + f_name; ?> + f_user; ?> + print_flag(); ?> + comment); ?> + print_status(); ?> + + approved) { ?> + id,'disable', T_('Reject'),'reject_flag_' . $flag->id); ?> + + id,'enable', T_('Enable'),'enable_flag_' . $flag->id); ?> + + diff --git a/templates/show_flagged.inc.php b/templates/show_flagged.inc.php index ed51f277da..db239205fa 100644 --- a/templates/show_flagged.inc.php +++ b/templates/show_flagged.inc.php @@ -1,5 +1,5 @@ - - - - - - + + + + + + format(); - require Config::get('prefix') . '/templates/show_flag_row.inc.php'; + $flag = new Flag($flag_id); + $flag->format(); + require Config::get('prefix') . '/templates/show_flag_row.inc.php'; ?> - + - - - - - - + + + + + + diff --git a/templates/show_gather_art.inc.php b/templates/show_gather_art.inc.php index 9f17c90e78..56598316d8 100644 --- a/templates/show_gather_art.inc.php +++ b/templates/show_gather_art.inc.php @@ -1,5 +1,5 @@ /albums.php?action=find_art&album_id=id; ?>&artist_name=&album_name=&cover=" style="Display:inline;"> - - + + - - + + - - + + - - + +
    -   - - - +   + + +
    -   - - - +   + + +
    - - - - + + + +
    - - - - + + + +
    - - + + - +
    diff --git a/templates/show_import_playlist.inc.php b/templates/show_import_playlist.inc.php index a767d41aca..436f71c1bd 100644 --- a/templates/show_import_playlist.inc.php +++ b/templates/show_import_playlist.inc.php @@ -1,5 +1,5 @@ - : - - + : + + - - - - - - + + + + + +
    - - + +
    diff --git a/templates/show_index.inc.php b/templates/show_index.inc.php index 7c12cbf494..7c4db26e57 100644 --- a/templates/show_index.inc.php +++ b/templates/show_index.inc.php @@ -1,5 +1,5 @@
    - +
    - +
    diff --git a/templates/show_install.inc.php b/templates/show_install.inc.php index ea2f86a9d8..7350f43190 100644 --- a/templates/show_install.inc.php +++ b/templates/show_install.inc.php @@ -1,5 +1,5 @@ -
    -
    -
    -
    -
    -
    -
    -
    - -
    - -
    " enctype="multipart/form-data" > +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + " enctype="multipart/form-data" > - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + +
    ? ?
     " /> " />
    -
    -
    -

    Ampache Installation.
    - Pour l'Amour de la Musique

    +
    +
    +

    Ampache Installation.
    + Pour l'Amour de la Musique

    diff --git a/templates/show_install_account.inc.php b/templates/show_install_account.inc.php index 86c5b770b5..e3a0a0d1fe 100644 --- a/templates/show_install_account.inc.php +++ b/templates/show_install_account.inc.php @@ -1,5 +1,5 @@ -
    -
    -
    -
    -
    -
    -
    - -
    - -
    " enctype="multipart/form-data" > +
    +
    +
    +
    +
    +
    +
    + +
    + + " enctype="multipart/form-data" > - - + + - - + + - - + + - - + + -
      
    - -
    -
    -

    Ampache Installation.
    - For the love of Music.

    + + +
    +
    +

    Ampache Installation.
    + For the love of Music.

    diff --git a/templates/show_install_check.inc.php b/templates/show_install_check.inc.php index 9cd719a8a7..88ce8c6294 100644 --- a/templates/show_install_check.inc.php +++ b/templates/show_install_check.inc.php @@ -1,5 +1,5 @@ @@ -41,13 +41,13 @@ @@ -55,73 +55,73 @@ : : : : : @@ -130,48 +130,48 @@ : : : : @@ -179,24 +179,24 @@ : diff --git a/templates/show_install_config.inc.php b/templates/show_install_config.inc.php index 703ef89001..bae4d3ba95 100644 --- a/templates/show_install_config.inc.php +++ b/templates/show_install_config.inc.php @@ -1,5 +1,5 @@ -
    -
    -
    -
    -
    -
    -
    - -
    +
    +
    +
    +
    +
    +
    +
    + +
    " enctype="multipart/form-data" > - - + + - - + + - - + + - - + + - - + + - - + + -
      - - /> - - -   + + /> + + +
    -
    -
    - +
    + +
    + - - - -
    [ ] @@ -92,32 +92,32 @@ ]
      - - [] -
    -
    -
    " enctype="multipart/form-data"> - -
    -
    -
    -

    Ampache Installation.
    - For the love of Music.

    -
    +   + + + [] + + + +
    +
    " enctype="multipart/form-data"> + +
    +
    +
    +

    Ampache Installation.
    + For the love of Music.

    +
    diff --git a/templates/show_install_lang.inc.php b/templates/show_install_lang.inc.php index b90b671258..63e3290edd 100644 --- a/templates/show_install_lang.inc.php +++ b/templates/show_install_lang.inc.php @@ -1,5 +1,5 @@ -
    - -
    +
    + +
    - -

    - -

    + +

    + +

    " enctype="multipart/form-data" > \n"; foreach ($languages as $lang=>$name) { - $var_name = $lang . "_lang"; + $var_name = $lang . "_lang"; - echo "\t\n"; + echo "\t\n"; } // end foreach echo "\n"; ?> -
    -
    -
    -

    Ampache Installation.
    - For the love of Music.

    + +
    +
    +

    Ampache Installation.
    + For the love of Music.

    diff --git a/templates/show_ip_history.inc.php b/templates/show_ip_history.inc.php index da4fb60798..f1adbe6d89 100644 --- a/templates/show_ip_history.inc.php +++ b/templates/show_ip_history.inc.php @@ -1,5 +1,5 @@
  • - - + + - - + +
  • @@ -43,21 +43,21 @@ - + - - - - - - + + + + + + - + diff --git a/templates/show_live_stream.inc.php b/templates/show_live_stream.inc.php index 4cf52c2743..47d2bcde57 100644 --- a/templates/show_live_stream.inc.php +++ b/templates/show_live_stream.inc.php @@ -1,5 +1,5 @@
    • - +
    diff --git a/templates/show_live_stream_row.inc.php b/templates/show_live_stream_row.inc.php index 620d736682..033f05a65d 100644 --- a/templates/show_live_stream_row.inc.php +++ b/templates/show_live_stream_row.inc.php @@ -1,5 +1,5 @@ - id,'add', T_('Add'),'add_radio_' . $radio->id); ?> + id,'add', T_('Add'),'add_radio_' . $radio->id); ?> f_name_link; ?> f_callsign; ?> f_frequency; ?> f_tag; ?> - - id,'edit', T_('Edit'),'edit_radio_' . $radio->id); ?> - - - id,'delete', T_('Delete'),'delete_radio_' . $radio->id); ?> - + + id,'edit', T_('Edit'),'edit_radio_' . $radio->id); ?> + + + id,'delete', T_('Delete'),'delete_radio_' . $radio->id); ?> + diff --git a/templates/show_live_streams.inc.php b/templates/show_live_streams.inc.php index e03b4d1323..1cc782f0b0 100644 --- a/templates/show_live_streams.inc.php +++ b/templates/show_live_streams.inc.php @@ -1,5 +1,5 @@ - - - - - - + + + + + + format(); + $radio = new Radio($radio_id); + $radio->format(); ?> - + - + - - - - - - + + + + + + diff --git a/templates/show_localplay_add_instance.inc.php b/templates/show_localplay_add_instance.inc.php index ec92c41f27..d980c8e8cc 100644 --- a/templates/show_localplay_add_instance.inc.php +++ b/templates/show_localplay_add_instance.inc.php @@ -1,5 +1,5 @@ $field) { ?> - - + + -
    - +
    +
    diff --git a/templates/show_localplay_control.inc.php b/templates/show_localplay_control.inc.php index 5c3b099e09..5ca4a43fb5 100644 --- a/templates/show_localplay_control.inc.php +++ b/templates/show_localplay_control.inc.php @@ -1,5 +1,5 @@ - - - - + + + + player_loaded()) { continue; } - $localplay->format(); - if (Localplay::is_enabled($controller)) { - $action = 'confirm_uninstall_localplay'; - $action_txt = T_('Disable'); - } - else { - $action = 'install_localplay'; - $action_txt = T_('Activate'); - } + $localplay = new Localplay($controller); + if (!$localplay->player_loaded()) { continue; } + $localplay->format(); + if (Localplay::is_enabled($controller)) { + $action = 'confirm_uninstall_localplay'; + $action_txt = T_('Disable'); + } + else { + $action = 'install_localplay'; + $action_txt = T_('Activate'); + } ?> - f_name); ?> - f_description); ?> - f_version); ?> - + f_name); ?> + f_description); ?> + f_version); ?> + - + - - - - + + + +
    diff --git a/templates/show_localplay_edit_instance.inc.php b/templates/show_localplay_edit_instance.inc.php index 9d9484ce51..1bd1436475 100644 --- a/templates/show_localplay_edit_instance.inc.php +++ b/templates/show_localplay_edit_instance.inc.php @@ -1,5 +1,5 @@ $field) { ?> - - + + -
    - +
    +
    diff --git a/templates/show_localplay_instances.inc.php b/templates/show_localplay_instances.inc.php index 755744b7f2..6972479f66 100644 --- a/templates/show_localplay_instances.inc.php +++ b/templates/show_localplay_instances.inc.php @@ -1,5 +1,5 @@ - $field) { ?> - - - + $field) { ?> + + + $name) { - $instance = $localplay->get_instance($uid); + $instance = $localplay->get_instance($uid); ?> - $field) { ?> - - - + $field) { ?> + + +
    - - - + + +
    diff --git a/templates/show_localplay_playlist.inc.php b/templates/show_localplay_playlist.inc.php index 0f5b263352..8a1781b0de 100644 --- a/templates/show_localplay_playlist.inc.php +++ b/templates/show_localplay_playlist.inc.php @@ -1,5 +1,5 @@ - - - + + + - - - - > - format_name($object['name'],$object['id']); ?> - - - - + + + + > + format_name($object['name'],$object['id']); ?> + + + + - + - - - + + + diff --git a/templates/show_localplay_status.inc.php b/templates/show_localplay_status.inc.php index 87f2528312..00fa065feb 100644 --- a/templates/show_localplay_status.inc.php +++ b/templates/show_localplay_status.inc.php @@ -1,5 +1,5 @@ :%
  • - | - - + | + +
  • - | - - + | + +
  • - +
  • diff --git a/templates/show_login_form.inc.php b/templates/show_login_form.inc.php index a972fc3486..c2e73677c4 100644 --- a/templates/show_login_form.inc.php +++ b/templates/show_login_form.inc.php @@ -1,5 +1,5 @@ = Config::get('remember_length')) { - $remember_disabled = 'disabled="disabled"'; + $remember_disabled = 'disabled="disabled"'; } $htmllang = str_replace("_","-",Config::get('lang')); is_rtl(Config::get('lang')) ? $dir = 'rtl' : $dir = 'ltr'; @@ -45,54 +45,54 @@ function focus(){ document.login.username.focus(); }
    -

    - - + +
    - + - +
    - - + +
    - - - + + +
    - - + +
    @@ -100,13 +100,13 @@
    - - + +
    - - ' /> + + ' />
    - - - fullname; ?> (username; ?>) - - + + + fullname; ?> (username; ?>) + + f_useage; ?> - - - - ip_history; ?> - - - - - - - disabled == '1') { - echo "id\">" . UI::get_icon('enable', T_('Enable')) . ""; - } - else { - echo "id\">" . UI::get_icon('disable', T_('Disable')) .""; - } - ?> - - + + + + ip_history; ?> + + + + + + + disabled == '1') { + echo "id\">" . UI::get_icon('enable', T_('Enable')) . ""; + } + else { + echo "id\">" . UI::get_icon('disable', T_('Disable')) .""; + } + ?> + + is_logged_in()) AND ($client->is_online())) { - echo "   "; - } elseif ($client->disabled == 1) { - echo "   "; - } else { - echo "   "; - } + if (($client->is_logged_in()) AND ($client->is_online())) { + echo "   "; + } elseif ($client->disabled == 1) { + echo "   "; + } else { + echo "   "; + } ?> diff --git a/templates/show_user_stats.inc.php b/templates/show_user_stats.inc.php index 5bfdadafc1..bac817c5fc 100644 --- a/templates/show_user_stats.inc.php +++ b/templates/show_user_stats.inc.php @@ -1,5 +1,5 @@ fullname); ?> - - + - + + show_info_box($title,'your_song',$items); + } + else { + echo "" . T_('Not Enough Data') . ""; + } + ?> +
    - format_favorites($favorite_artists); - $title = '' . - UI::get_icon('all', T_('Favorite Artists')) . ' ' . T_('Favorite Artists'); - show_info_box($title,'artist',$items); - } - else { - echo "" . T_('Not Enough Data') . ""; - } - ?> - - format_favorites($favorite_albums); + + format_favorites($favorite_artists); + $title = '' . + UI::get_icon('all', T_('Favorite Artists')) . ' ' . T_('Favorite Artists'); + show_info_box($title,'artist',$items); + } + else { + echo "" . T_('Not Enough Data') . ""; + } + ?> + + format_favorites($favorite_albums); $title = '' . UI::get_icon('all', T_('Favorite Albums')) . ' ' . T_('Favorite Albums'); - show_info_box($title,'album',$items); - } - else { - echo "" . T_('Not Enough Data') . ""; - } - ?> - - format_favorites($favorite_songs); + show_info_box($title,'album',$items); + } + else { + echo "" . T_('Not Enough Data') . ""; + } + ?> + + format_favorites($favorite_songs); $title = '' . UI::get_icon('all', T_('Favorite Songs')) . ' ' . T_('Favorite Songs'); - show_info_box($title,'your_song',$items); - } - else { - echo "" . T_('Not Enough Data') . ""; - } - ?> -
    diff --git a/templates/show_users.inc.php b/templates/show_users.inc.php index ba3d7b849d..55ede6fdb1 100644 --- a/templates/show_users.inc.php +++ b/templates/show_users.inc.php @@ -1,5 +1,5 @@ - + - + @@ -41,32 +41,32 @@ - + - - + + format(); - $last_seen = $client->last_seen ? date("m\/d\/Y - H:i",$client->last_seen) : T_('Never'); - $create_date = $client->create_date ? date("m\/d\/Y - H:i",$client->create_date) : T_('Unknown'); + $client = new User($user_id); + $client->format(); + $last_seen = $client->last_seen ? date("m\/d\/Y - H:i",$client->last_seen) : T_('Never'); + $create_date = $client->create_date ? date("m\/d\/Y - H:i",$client->create_date) : T_('Unknown'); ?> - + - ( ) + ( ) - + - - + + diff --git a/templates/show_verify_catalog.inc.php b/templates/show_verify_catalog.inc.php index b913a4cf1f..fc41e534f9 100644 --- a/templates/show_verify_catalog.inc.php +++ b/templates/show_verify_catalog.inc.php @@ -1,5 +1,5 @@ - id,'add', T_('Add'),'add_video_' . $video->id); ?> + id,'add', T_('Add'),'add_video_' . $video->id); ?> f_title; ?> f_codec; ?> @@ -30,6 +30,6 @@ f_tags; ?> - + diff --git a/templates/show_videos.inc.php b/templates/show_videos.inc.php index 256fe6821f..7b4f6c756f 100644 --- a/templates/show_videos.inc.php +++ b/templates/show_videos.inc.php @@ -1,5 +1,5 @@ - - - - - - - + + + + + + + format(); + $video = new Video($video_id); + $video->format(); ?> - + - + - + - - - - - + + + + + diff --git a/templates/show_xspf_player.inc.php b/templates/show_xspf_player.inc.php index b668dbcbf0..5cfb52d170 100644 --- a/templates/show_xspf_player.inc.php +++ b/templates/show_xspf_player.inc.php @@ -1,5 +1,5 @@ - - - - - - - - - - - + + + + + + + + + + +

    Debian Policy requires the removal of the XSPF Flash Player, please see /usr/share/doc/ampache/README.Debian.gz for details and a work around.

    diff --git a/templates/sidebar.inc.php b/templates/sidebar.inc.php index 664ec3edf3..ba2670ab3a 100644 --- a/templates/sidebar.inc.php +++ b/templates/sidebar.inc.php @@ -1,5 +1,5 @@ diff --git a/templates/sidebar_admin.inc.php b/templates/sidebar_admin.inc.php index 86ae75c3bd..4363c37c07 100644 --- a/templates/sidebar_admin.inc.php +++ b/templates/sidebar_admin.inc.php @@ -1,5 +1,5 @@

      diff --git a/templates/sidebar_home.inc.php b/templates/sidebar_home.inc.php index 136374166e..9639813417 100644 --- a/templates/sidebar_home.inc.php +++ b/templates/sidebar_home.inc.php @@ -1,5 +1,5 @@
      • diff --git a/templates/sidebar_localplay.inc.php b/templates/sidebar_localplay.inc.php index 287528f13d..46e2675e6f 100644 --- a/templates/sidebar_localplay.inc.php +++ b/templates/sidebar_localplay.inc.php @@ -1,5 +1,5 @@ current_instance(); - $class = $current_instance ? '' : ' class="active_instance"'; + // Little bit of work to be done here + $localplay = new Localplay(Config::get('localplay_controller')); + $current_instance = $localplay->current_instance(); + $class = $current_instance ? '' : ' class="active_instance"'; ?>
        • -
        • -
        • +
        • +
        • -
        • +
        • -
        • >
        • - get_instances(); - foreach ($instances as $uid=>$name) { - $name = scrub_out($name); - $class = ''; - if ($uid == $current_instance) { - $class = ' class="active_instance"'; - } - ?> -
        • >
        • - +
        • >
        • + get_instances(); + foreach ($instances as $uid=>$name) { + $name = scrub_out($name); + $class = ''; + if ($uid == $current_instance) { + $class = ' class="active_instance"'; + } + ?> +
        • >
        • +
      • -
      • +
      • -
      • +
      • -
      • +
      diff --git a/templates/sidebar_modules.inc.php b/templates/sidebar_modules.inc.php index 36697794e4..675871cd3d 100644 --- a/templates/sidebar_modules.inc.php +++ b/templates/sidebar_modules.inc.php @@ -1,5 +1,5 @@

      • diff --git a/templates/subnavbar.inc.php b/templates/subnavbar.inc.php index 83ac34a480..f52d99c964 100644 --- a/templates/subnavbar.inc.php +++ b/templates/subnavbar.inc.php @@ -1,5 +1,5 @@ diff --git a/test.php b/test.php index 66309614de..4fd31f7bf8 100644 --- a/test.php +++ b/test.php @@ -1,5 +1,5 @@ diff --git a/update.php b/update.php index c9d00bde7f..948700ac78 100644 --- a/update.php +++ b/update.php @@ -1,5 +1,5 @@ Pour l'Amour de la Musique.

    -
    +
    3.3.3.5. According to your database your current version is: %s.'), Update::format_version($version)); ?>

    -
    -
    +
    +
    -
    -
    -


    - Pour l'Amour de la Musique.

    +
    +
    +


    + Pour l'Amour de la Musique.

    diff --git a/util.php b/util.php index 5679437aed..7d9d0a5185 100644 --- a/util.php +++ b/util.php @@ -1,5 +1,5 @@