/** * constructor * This should be called * @param int|null $id * @param boolean $cached */ public function __construct($id = null, $cached = true) { $sid = session_id(); if (!$cached) { $this->id = 'nocache'; return true; } if (is_null($id)) { $this->reset(); $data = self::_serialize($this->_state); $sql = 'INSERT INTO `tmp_browse` (`sid`, `data`) VALUES(?, ?)'; Dba::write($sql, array($sid, $data)); $this->id = Dba::insert_id(); return true; } else { $sql = 'SELECT `data` FROM `tmp_browse` WHERE `id` = ? AND `sid` = ?'; $db_results = Dba::read($sql, array($id, $sid)); if ($results = Dba::fetch_assoc($db_results)) { $this->id = $id; $this->_state = (array) self::_unserialize($results['data']); return true; } } AmpError::add('browse', T_('Browse not found or expired, try reloading the page')); return false; }
/** * set * * This sets config values. * @param string $name * @param boolean $clobber */ 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); AmpError::add('Config Global', sprintf(T_('Trying to clobber \'%s\' without setting clobber'), $name)); return false; } self::$_global[$name] = $value; }
/** * update_remote_catalog * * Pulls the data from a remote catalog and adds any missing songs to the * database. */ public function update_remote_catalog() { debug_event('subsonic_catalog', 'Updating remote catalog...', 5); $subsonic = $this->createClient(); $songsadded = 0; // Get all artists $artists = $subsonic->getIndexes(); if ($artists['success']) { foreach ($artists['data']['indexes']['index'] as $index) { foreach ($index['artist'] as $artist) { // Get albums for artist $albums = $subsonic->getMusicDirectory(array('id' => $artist['id'])); if ($albums['success']) { foreach ($albums['data']['directory']['child'] as $album) { if (is_array($album)) { $songs = $subsonic->getMusicDirectory(array('id' => $album['id'])); if ($songs['success']) { foreach ($songs['data']['directory']['child'] as $song) { if (is_array($song)) { $data = array(); $data['artist'] = html_entity_decode($song['artist']); $data['album'] = html_entity_decode($song['album']); $data['title'] = html_entity_decode($song['title']); $data['bitrate'] = $song['bitRate'] * 1000; $data['size'] = $song['size']; $data['time'] = $song['duration']; $data['track'] = $song['track']; $data['disk'] = $song['discNumber']; $data['mode'] = 'vbr'; $data['genre'] = explode(' ', html_entity_decode($song['genre'])); $data['file'] = $this->uri . '/rest/stream.view?id=' . $song['id'] . '&filename=' . urlencode($song['path']); if ($this->check_remote_song($data)) { debug_event('subsonic_catalog', 'Skipping existing song ' . $data['path'], 5); } else { $data['catalog'] = $this->id; debug_event('subsonic_catalog', 'Adding song ' . $song['path'], 5, 'ampache-catalog'); if (!Song::insert($data)) { debug_event('subsonic_catalog', 'Insert failed for ' . $song['path'], 1); AmpError::add('general', T_('Unable to Insert Song - %s'), $song['path']); } else { $songsadded++; } } } } } else { debug_event('subsonic_catalog', 'Song error:' . $songs['error'], 3); AmpError::add('general', T_('Song Error.') . ": " . $songs['error']); } } } } else { debug_event('subsonic_catalog', 'Album error:' . $albums['error'], 3); AmpError::add('general', T_('Album Error.') . ": " . $albums['error']); } } } UI::update_text('', T_('Completed updating Subsonic catalog(s).') . " " . $songsadded . " " . T_('Songs added.')); // Update the last update value $this->update_last_update(); } else { debug_event('subsonic_catalog', 'Artist error:' . $artists['error'], 3); AmpError::add('general', T_('Artist Error.') . ": " . $artists['error']); } debug_event('subsonic_catalog', 'Catalog updated.', 5); return true; }
break; } catalog_worker('update_from', null, $_POST); show_confirmation(T_('Subdirectory update started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false); break; case 'add_catalog': /* Wah Demo! */ if (AmpConfig::get('demo_mode')) { break; } ob_end_flush(); if (!strlen($_POST['type']) || $_POST['type'] == 'none') { AmpError::add('general', T_('Error: Please select a catalog type')); } if (!strlen($_POST['name'])) { AmpError::add('general', T_('Error: Name not specified')); } if (!Core::form_verify('add_catalog', 'post')) { UI::access_denied(); exit; } // If an error hasn't occured if (!AmpError::occurred()) { $catalog_id = Catalog::create($_POST); if (!$catalog_id) { require AmpConfig::get('prefix') . UI::find_template('show_add_catalog.inc.php'); break; } $catalogs[] = $catalog_id; catalog_worker('add_to_catalog', $catalogs, $_POST); show_confirmation(T_('Catalog Creation started...'), '', AmpConfig::get('web_path') . '/admin/catalog.php', 0, 'confirmation', false);
/** * update_360051 * * Copy default .htaccess configurations */ public static function update_360051() { require_once AmpConfig::get('prefix') . '/lib/install.lib.php'; if (!install_check_server_apache()) { debug_event('update', 'Not using Apache, update 360051 skipped.', '5'); return true; } $htaccess_play_file = AmpConfig::get('prefix') . '/play/.htaccess'; $htaccess_rest_file = AmpConfig::get('prefix') . '/rest/.htaccess'; $htaccess_channel_file = AmpConfig::get('prefix') . '/channel/.htaccess'; $ret = true; if (!is_readable($htaccess_play_file)) { $created = false; if (check_htaccess_play_writable()) { if (!install_rewrite_rules($htaccess_play_file, AmpConfig::get('raw_web_path'), false)) { AmpError::add('general', T_('File copy error.')); } else { $created = true; } } if (!$created) { AmpError::add('general', T_('Cannot copy default .htaccess file.') . ' Please copy <b>' . $htaccess_play_file . '.dist</b> to <b>' . $htaccess_play_file . '</b>.'); $ret = false; } } if (!is_readable($htaccess_rest_file)) { $created = false; if (check_htaccess_rest_writable()) { if (!install_rewrite_rules($htaccess_rest_file, AmpConfig::get('raw_web_path'), false)) { AmpError::add('general', T_('File copy error.')); } else { $created = true; } } if (!$created) { AmpError::add('general', T_('Cannot copy default .htaccess file.') . ' Please copy <b>' . $htaccess_rest_file . '.dist</b> to <b>' . $htaccess_rest_file . '</b>.'); $ret = false; } } if (!is_readable($htaccess_channel_file)) { $created = false; if (check_htaccess_channel_writable()) { if (!install_rewrite_rules($htaccess_channel_file, AmpConfig::get('raw_web_path'), false)) { AmpError::add('general', T_('File copy error.')); } else { $created = true; } } if (!$created) { AmpError::add('general', T_('Cannot copy default .htaccess file.') . ' Please copy <b>' . $htaccess_channel_file . '.dist</b> to <b>' . $htaccess_channel_file . '</b>.'); $ret = false; } } return $ret; }
/** * _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); $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); $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)); } $file_info = Core::get_filesize(Core::conv_lc_file($results['file'])); if (!file_exists(Core::conv_lc_file($results['file'])) || $file_info < 1) { debug_event('clean', 'File not found or empty: ' . $results['file'], 5); AmpError::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']; } else { if (!Core::is_readable(Core::conv_lc_file($results['file']))) { debug_event('clean', $results['file'] . ' is not readable, but does exist', 1); } } } return $dead; }
$_POST['username'] = $GLOBALS['user']->username; $mandatory_fields = (array) AmpConfig::get('registration_mandatory_fields'); if (in_array('fullname', $mandatory_fields) && !$_POST['fullname']) { AmpError::add('fullname', T_("Please fill in your full name (Firstname Lastname)")); } if (in_array('website', $mandatory_fields) && !$_POST['website']) { AmpError::add('website', T_("Please fill in your website")); } if (in_array('state', $mandatory_fields) && !$_POST['state']) { AmpError::add('state', T_("Please fill in your state")); } if (in_array('city', $mandatory_fields) && !$_POST['city']) { AmpError::add('city', T_("Please fill in your city")); } if (!$GLOBALS['user']->update($_POST)) { AmpError::add('general', T_('Error Update Failed')); } else { $GLOBALS['user']->upload_avatar(); //$_REQUEST['action'] = 'confirm'; $title = T_('Updated'); $text = T_('Your Account has been updated'); $next_url = AmpConfig::get('web_path') . '/preferences.php?tab=account'; } $notification_text = T_('User updated successfully'); break; case 'grant': // Make sure we're a user and they came from the form if (!Access::check('interface', '25') && $GLOBALS['user']->id > 0) { UI::access_denied(); exit; }
public static function create(array $data) { $subject = trim(strip_tags($data['subject'])); $message = trim(strip_tags($data['message'])); if (empty($subject)) { AmpError::add('subject', T_('Error: Subject Required')); } $to_user = User::get_from_username($data['to_user']); if (!$to_user->id) { AmpError::add('to_user', T_('Error: Unknown user')); } if (!AmpError::occurred()) { $from_user = $data['from_user'] ?: $GLOBALS['user']->id; $creation_date = $data['creation_date'] ?: time(); $is_read = $data['is_read'] ?: 0; $sql = "INSERT INTO `user_pvmsg` (`subject`, `message`, `from_user`, `to_user`, `creation_date`, `is_read`) " . "VALUES (?, ?, ?, ?, ?, ?)"; if (Dba::write($sql, array($subject, $message, $from_user, $to_user->id, $creation_date, $is_read))) { $insert_id = Dba::insert_id(); // Never send email in case of user impersonation if (!isset($data['from_user']) && $insert_id) { if (Preference::get_by_user($to_user->id, 'notify_email')) { if (!empty($to_user->email)) { $mailer = new Mailer(); $mailer->set_default_sender(); $mailer->recipient = $to_user->email; $mailer->recipient_name = $to_user->fullname; $mailer->subject = "[" . T_('Private Message') . "] " . $subject; $mailer->message = sprintf(T_("You just received a new private message from %s.\n\n\n ----------------------\n %s\n ----------------------\n\n %s\n "), $GLOBALS['user']->fullname, $message, AmpConfig::get('web_path') . "/pvmsg.php?action=show&pvmsg_id=" . $insert_id); $mailer->send(); } } } return $insert_id; } } return false; }
require_once 'lib/init.php'; $action = isset($_POST['action']) ? $_POST['action'] : ""; switch ($action) { case 'send': /* Check for posted email */ $result = false; if (isset($_POST['email']) && $_POST['email']) { /* Get the email address and the current ip*/ $email = scrub_in($_POST['email']); $current_ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; $result = send_newpassword($email, $current_ip); } if ($result) { AmpError::add('general', T_('Password has been sent')); } else { AmpError::add('general', T_('Password has not been sent')); } require AmpConfig::get('prefix') . UI::find_template('show_login_form.inc.php'); break; default: require AmpConfig::get('prefix') . UI::find_template('show_lostpassword_form.inc.php'); } function send_newpassword($email, $current_ip) { /* get the Client and set the new password */ $client = User::get_from_email($email); if ($client && $client->email == $email) { $newpassword = generate_password(6); $client->update_password($newpassword); $mailer = new Mailer(); $mailer->set_default_sender();
switch (AmpConfig::get('auto_user')) { case 'admin': $access = '100'; break; case 'user': $access = '25'; break; case 'guest': default: $access = '5'; break; } // auto-user level $new_user = User::create($username, $fullname, $email, $website, $pass1, $access, $state, $city, AmpConfig::get('admin_enable_required')); if (!$new_user) { AmpError::add('duplicate_user', T_("Error: Insert Failed")); require_once AmpConfig::get('prefix') . UI::find_template('show_user_registration.inc.php'); break; } if (!AmpConfig::get('user_no_email_confirm')) { $client = new User($new_user); $validation = md5(uniqid(rand(), true)); $client->update_validation($validation); // Notify user and/or admins Registration::send_confirmation($username, $fullname, $email, $website, $pass1, $validation); } require_once AmpConfig::get('prefix') . UI::find_template('show_registration_confirmation.inc.php'); break; case 'show_add_user': default: require_once AmpConfig::get('prefix') . UI::find_template('show_user_registration.inc.php');
/** * handshake * * This is the function that handles verifying a new handshake * Takes a timestamp, auth key, and username. * @param array * @return boolean */ public static function handshake($input) { $timestamp = preg_replace('/[^0-9]/', '', $input['timestamp']); $passphrase = $input['auth']; if (empty($passphrase)) { $passphrase = $_POST['auth']; } $username = trim($input['user']); $ip = $_SERVER['REMOTE_ADDR']; $version = $input['version']; // Log the attempt debug_event('API', "Handshake Attempt, IP:{$ip} User:{$username} Version:{$version}", 5); // Version check shouldn't be soo restrictive... only check with initial version to not break clients compatibility if (intval($version) < self::$auth_version) { debug_event('API', 'Login Failed: version too old', 1); AmpError::add('api', T_('Login Failed: version too old')); return false; } $user_id = -1; // Grab the correct userid if (!$username) { $client = User::get_from_apikey($passphrase); if ($client) { $user_id = $client->id; } } else { $client = User::get_from_username($username); $user_id = $client->id; } // Log this attempt debug_event('API', "Login Attempt, IP:{$ip} Time: {$timestamp} User:{$username} ({$user_id}) Auth:{$passphrase}", 1); if ($user_id > 0 && Access::check_network('api', $user_id, 5, $ip)) { // Authentication with user/password, we still need to check the password if ($username) { // 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 ' . $timestamp . '/' . time(), 1); AmpError::add('api', T_('Login Failed: timestamp out of range')); echo XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Login Failed: timestamp out of range')); return false; } // 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 $realpwd = $client->get_password(); if (!$realpwd) { debug_event('API', 'Unable to find user with userid of ' . $user_id, 1); AmpError::add('api', T_('Invalid Username/Password')); echo XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password')); return false; } $sha1pass = hash('sha256', $timestamp . $realpwd); if ($sha1pass !== $passphrase) { $client = null; } } else { $timestamp = time(); } if ($client) { // Create the session $data = array(); $data['username'] = $client->username; $data['type'] = 'api'; $data['value'] = $timestamp; if (isset($input['client'])) { $data['agent'] = $input['client']; } if (isset($input['geo_latitude'])) { $data['geo_latitude'] = $input['geo_latitude']; } if (isset($input['geo_longitude'])) { $data['geo_longitude'] = $input['geo_longitude']; } if (isset($input['geo_name'])) { $data['geo_name'] = $input['geo_name']; } $token = Session::create($data); 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() + AmpConfig::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'); echo XML_Data::error('401', T_('Error Invalid Handshake - ') . T_('Invalid Username/Password')); return false; }
} if ($write_htaccess_play || $download_htaccess_play || $all) { $created_config = $created_config && install_rewrite_rules($htaccess_play_file, $_POST['web_path'], $download_htaccess_play); } if ($write || $download || $all) { $created_config = $created_config && install_create_config($download); } } case 'show_create_account': $results = parse_ini_file($configfile); if (!isset($created_config)) { $created_config = true; } /* Make sure we've got a valid config file */ if (!check_config_values($results) || !$created_config) { AmpError::add('general', T_('Error: Config files not found or unreadable')); require_once AmpConfig::get('prefix') . UI::find_template('show_install_config.inc.php'); break; } // Don't try to add administrator user on existing database if (install_check_status($configfile)) { require_once AmpConfig::get('prefix') . UI::find_template('show_install_account.inc.php'); } else { header("Location: " . $web_path . '/login.php'); } break; case 'create_account': $results = parse_ini_file($configfile); AmpConfig::set_by_array($results, true); $password2 = $_REQUEST['local_pass2']; if (!install_create_account($username, $password, $password2)) {
break; case 'uninstall_localplay': $type = (string) scrub_in($_REQUEST['type']); $localplay = new Localplay($type); $localplay->uninstall(); /* Show Confirmation */ $url = AmpConfig::get('web_path') . '/admin/modules.php?action=show_localplay'; $title = T_('Plugin Deactivated'); $body = ''; show_confirmation($title, $body, $url); break; case 'uninstall_catalog_type': $type = (string) scrub_in($_REQUEST['type']); $catalog = Catalog::create_catalog_type($type); if ($catalog == null) { AmpError::add('general', T_('Uninstall Failed, Catalog Error')); AmpError::display('general'); break; } $catalog->uninstall(); /* Show Confirmation */ $url = AmpConfig::get('web_path') . '/admin/modules.php?action=show_catalog_types'; $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');
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 } elseif (AmpConfig::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 = AmpConfig::get('auto_user') ? User::access_name_to_level(AmpConfig::get('auto_user')) : '5'; $name = $auth['name']; $email = $auth['email']; $website = $auth['website']; /* Attempt to create the user */ if (User::create($username, $name, $email, $website, hash('sha256', mt_rand()), $access)) { $user = User::get_from_username($username); } else { $auth['success'] = false; AmpError::add('general', T_('Unable to create local account')); } } // End if auto_create // This allows stealing passwords validated by external means // such as LDAP if (AmpConfig::get('auth_password_save') && $auth['success'] && isset($password)) { $user->update_password($password); } } /* If the authentication was a success */ if (isset($auth) && $auth['success'] && isset($user)) { // $auth->info are the fields specified in the config file // to retrieve for each user Session::create($auth); // Not sure if it was me or php tripping out,
if (isset($_POST['date'])) { unset($_POST['date']); } if (!Core::is_library_item($_POST['object_type'])) { UI::access_denied(); exit; } $shout_id = Shoutbox::create($_POST); header("Location:" . AmpConfig::get('web_path') . '/shout.php?action=show_add_shout&type=' . $_POST['object_type'] . '&id=' . intval($_POST['object_id'])); exit; break; case 'show_add_shout': // Get our object first $object = Shoutbox::get_object($_REQUEST['type'], $_REQUEST['id']); if (!$object || !$object->id) { AmpError::add('general', T_('Invalid Object Selected')); AmpError::display('general'); break; } $object->format(); if (strtolower(get_class($object)) == 'song') { $data = $_REQUEST['offset']; } // Now go ahead and display the page where we let them add a comment etc require_once AmpConfig::get('prefix') . UI::find_template('show_add_shout.inc.php'); break; default: header("Location:" . AmpConfig::get('web_path')); break; } // end switch on action
/** * Add the song to the DB * @param array $song * @return integer */ protected function insertSong($song) { $inserted = Song::insert($song); if ($inserted) { debug_event('beets_catalog', 'Adding song ' . $song['file'], 5, 'ampache-catalog'); } else { debug_event('beets_catalog', 'Insert failed for ' . $song['file'], 1); AmpError::add('general', T_('Unable to Insert Song - %s'), $song['file']); AmpError::display('general'); } flush(); return $inserted; }
if (!User::check_username($username)) { AmpError::add('username', T_('Error Username already exists')); } // Check the mail for correct address formation. if (!Mailer::validate_address($email)) { AmpError::add('email', T_('Invalid email address')); } /* If we've got an error then show add form! */ if (AmpError::occurred()) { require_once AmpConfig::get('prefix') . UI::find_template('show_add_user.inc.php'); break; } /* Attempt to create the user */ $user_id = User::create($username, $fullname, $email, $website, $pass1, $access, $state, $city); if (!$user_id) { AmpError::add('general', T_("Error: Insert Failed")); } $user = new User($user_id); $user->upload_avatar(); 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), AmpConfig::get('web_path') . '/admin/users.php'); break; case 'enable': $client = new User($_REQUEST['user_id']);
public static function create(array $data) { $feed = $data['feed']; // Feed must be http/https if (strpos($feed, "http://") !== 0 && strpos($feed, "https://") !== 0) { AmpError::add('feed', T_('Wrong feed url')); } $catalog_id = intval($data['catalog']); if ($catalog_id <= 0) { AmpError::add('catalog', T_('Target catalog required')); } else { $catalog = Catalog::create_from_id($catalog_id); if ($catalog->gather_types !== "podcast") { AmpError::add('catalog', T_('Wrong target catalog type')); } } if (AmpError::occurred()) { return false; } $title = T_('Unknown'); $website = null; $description = null; $language = null; $copyright = null; $generator = null; $lastbuilddate = 0; $episodes = array(); $arturl = ''; $xmlstr = file_get_contents($feed); if ($xmlstr === false) { AmpError::add('feed', T_('Cannot access the feed.')); } else { $xml = simplexml_load_string($xmlstr); if ($xml === false) { AmpError::add('feed', T_('Cannot read the feed.')); } else { $title = html_entity_decode($xml->channel->title); $website = $xml->channel->link; $description = html_entity_decode($xml->channel->description); $language = $xml->channel->language; $copyright = html_entity_decode($xml->channel->copyright); $generator = html_entity_decode($xml->channel->generator); $lastbuilddatestr = $xml->channel->lastBuildDate; if ($lastbuilddatestr) { $lastbuilddate = strtotime($lastbuilddatestr); } if ($xml->channel->image) { $arturl = $xml->channel->image->url; } $episodes = $xml->channel->item; } } if (AmpError::occurred()) { return false; } $sql = "INSERT INTO `podcast` (`feed`, `catalog`, `title`, `website`, `description`, `language`, `copyright`, `generator`, `lastbuilddate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; $db_results = Dba::write($sql, array($feed, $catalog_id, $title, $website, $description, $language, $copyright, $generator, $lastbuilddate)); if ($db_results) { $id = Dba::insert_id(); $podcast = new Podcast($id); $dirpath = $podcast->get_root_path(); if (!is_dir($dirpath)) { if (mkdir($dirpath) === false) { debug_event('podcast', 'Cannot create directory ' . $dirpath, 1); } } if (!empty($arturl)) { $art = new Art($id, 'podcast'); $art->insert_url($arturl); } if (count($episodes) > 0) { $podcast->add_episodes($episodes); } } return $db_results; }
/** * update_remote_catalog * * Pulls the data from a remote catalog and adds any missing songs to the * database. */ public function update_remote_catalog() { $songsadded = 0; try { $api = $this->createClient(); if ($api != null) { // Get all liked songs $songs = json_decode($api->get('me/favorites')); if ($songs) { foreach ($songs as $song) { if ($song->streamable == true && $song->kind == 'track') { $data = array(); $data['artist'] = $song->user->username; $data['album'] = $data['artist']; $data['title'] = $song->title; $data['year'] = $song->release_year; $data['mode'] = 'vbr'; $data['genre'] = explode(' ', $song->genre); $data['comment'] = $song->description; $data['file'] = $song->stream_url . '.mp3'; // Always stream as mp3, if evolve => $song->original_format; $data['size'] = $song->original_content_size; $data['time'] = intval($song->duration / 1000); if ($this->check_remote_song($data)) { debug_event('soundcloud_catalog', 'Skipping existing song ' . $data['file'], 5); } else { $data['catalog'] = $this->id; debug_event('soundcloud_catalog', 'Adding song ' . $data['file'], 5, 'ampache-catalog'); if (!Song::insert($data)) { debug_event('soundcloud_catalog', 'Insert failed for ' . $data['file'], 1); AmpError::add('general', T_('Unable to Insert Song - %s'), $data['file']); } else { $songsadded++; } } } } UI::update_text('', T_('Completed updating SoundCloud catalog(s).') . " " . $songsadded . " " . T_('Songs added.')); // Update the last update value $this->update_last_update(); } else { AmpError::add('general', T_('API Error: cannot get song list.')); } } else { AmpError::add('general', T_('API Error: cannot connect to SoundCloud.')); } } catch (Exception $ex) { AmpError::add('general', T_('SoundCloud exception: ') . $ex->getMessage()); } return true; }
/** * create * * This takes a keyed array of data and trys to insert it as a * new ACL entry * @param array $data * @return boolean */ public static function create(array $data) { if (!self::_verify_range($data['start'], $data['end'])) { return false; } // Check existing ACLs 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 already exists. Not adding another one: ' . $data['start'] . ' - ' . $data['end'], 1); AmpError::add('general', T_('Duplicate ACL defined')); return false; } $start = @inet_pton($data['start']); $end = @inet_pton($data['end']); $name = $data['name']; $user = $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 (?, ?, ?, ?, ?, ?, ?)'; Dba::write($sql, array($name, $level, $start, $end, $user, $type, $enabled)); return true; }
public static function process_action($action, $catalogs, $options = null) { if (!$options || !is_array($options)) { $options = array(); } switch ($action) { case 'add_to_all_catalogs': $catalogs = Catalog::get_catalogs(); case 'add_to_catalog': if ($catalogs) { foreach ($catalogs as $catalog_id) { $catalog = Catalog::create_from_id($catalog_id); if ($catalog !== null) { $catalog->add_to_catalog($options); } } if (!defined('SSE_OUTPUT')) { AmpError::display('catalog_add'); } } break; case 'update_all_catalogs': $catalogs = Catalog::get_catalogs(); case 'update_catalog': if ($catalogs) { foreach ($catalogs as $catalog_id) { $catalog = Catalog::create_from_id($catalog_id); if ($catalog !== null) { $catalog->verify_catalog(); } } } break; case 'full_service': if (!$catalogs) { $catalogs = Catalog::get_catalogs(); } /* This runs the clean/verify/add in that order */ foreach ($catalogs as $catalog_id) { $catalog = Catalog::create_from_id($catalog_id); if ($catalog !== null) { $catalog->clean_catalog(); $catalog->verify_catalog(); $catalog->add_to_catalog(); } } Dba::optimize_tables(); break; case 'clean_all_catalogs': $catalogs = Catalog::get_catalogs(); case 'clean_catalog': if ($catalogs) { foreach ($catalogs as $catalog_id) { $catalog = Catalog::create_from_id($catalog_id); if ($catalog !== null) { $catalog->clean_catalog(); } } // end foreach catalogs Dba::optimize_tables(); } break; case 'update_from': $catalog_id = 0; // First see if we need to do an add if ($options['add_path'] != '/' && strlen($options['add_path'])) { if ($catalog_id = Catalog_local::get_from_path($options['add_path'])) { $catalog = Catalog::create_from_id($catalog_id); if ($catalog !== null) { $catalog->add_to_catalog(array('subdirectory' => $options['add_path'])); } } } // end if add // Now check for an update if ($options['update_path'] != '/' && strlen($options['update_path'])) { if ($catalog_id = Catalog_local::get_from_path($options['update_path'])) { $songs = Song::get_from_path($options['update_path']); foreach ($songs as $song_id) { Catalog::update_single_item('song', $song_id); } } } // end if update if ($catalog_id <= 0) { AmpError::add('general', T_("This subdirectory is not part of an existing catalog. Update cannot be processed.")); } break; case 'gather_media_art': if (!$catalogs) { $catalogs = Catalog::get_catalogs(); } // Iterate throught the catalogs and gather as needed foreach ($catalogs as $catalog_id) { $catalog = Catalog::create_from_id($catalog_id); if ($catalog !== null) { require AmpConfig::get('prefix') . UI::find_template('show_gather_art.inc.php'); flush(); $catalog->gather_art(); } } break; } }
/** * create_type * * This creates a new catalog type entry for a catalog * It checks to make sure its parameters is not already used before creating * the catalog. */ public static function create_type($catalog_id, $data) { // TODO: This Method should be required / provided by parent $uri = $data['uri']; if (substr($uri, 0, 7) != 'http://' && substr($uri, 0, 8) != 'https://') { AmpError::add('general', T_('Error: Beets selected, but path is not a URL')); return false; } // Make sure this uri isn't already in use by an existing catalog $selectSql = 'SELECT `id` FROM `catalog_beets` WHERE `uri` = ?'; $db_results = Dba::read($selectSql, array($uri)); if (Dba::num_rows($db_results)) { debug_event('catalog', 'Cannot add catalog with duplicate uri ' . $uri, 1); AmpError::add('general', sprintf(T_('Error: Catalog with %s already exists'), $uri)); return false; } $insertSql = 'INSERT INTO `catalog_beetsremote` (`uri`, `catalog_id`) VALUES (?, ?)'; Dba::write($insertSql, array($uri, $catalog_id)); return true; }
/** * 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(array $data) { if (empty($data['username'])) { AmpError::add('username', T_('Error Username Required')); } if ($data['password1'] != $data['password2'] and !empty($data['password1'])) { AmpError::add('password', T_("Error Passwords don't match")); } if (AmpError::occurred()) { return false; } if (!isset($data['fullname_public'])) { $data['fullname_public'] = false; } foreach ($data as $name => $value) { if ($name == 'password1') { $name = 'password'; } else { $value = scrub_in($value); } switch ($name) { case 'password': case 'access': case 'email': case 'username': case 'fullname': case 'fullname_public': case 'website': case 'state': case 'city': if ($this->{$name} != $value) { $function = 'update_' . $name; $this->{$function}($value); } break; case 'clear_stats': Stats::clear($this->id); break; default: // Rien a faire break; } } return $this->id; }
/** * install_create_account * this creates your initial account and sets up the preferences for the -1 user and you */ function install_create_account($username, $password, $password2) { if (!strlen($username) or !strlen($password)) { AmpError::add('general', T_('No Username/Password specified')); return false; } if ($password !== $password2) { AmpError::add('general', T_('Passwords do not match')); return false; } if (!Dba::check_database()) { AmpError::add('general', sprintf(T_('Database connection failed: %s'), Dba::error())); return false; } if (!Dba::check_database_inserted()) { AmpError::add('general', sprintf(T_('Database select failed: %s'), Dba::error())); return false; } $username = Dba::escape($username); $password = Dba::escape($password); $insert_id = User::create($username, 'Administrator', '', '', $password, '100'); if (!$insert_id) { AmpError::add('general', sprintf(T_('Administrative user creation failed: %s'), Dba::error())); return false; } // Fix the system users preferences User::fix_preferences('-1'); return true; }
/** * 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(array $data) { // Make sure we've got a name if (!strlen($data['name'])) { AmpError::add('name', T_('Name Required')); } $allowed_array = array('https', 'http', 'mms', 'mmsh', 'mmsu', 'mmst', 'rtsp', 'rtmp'); $elements = explode(":", $data['url']); if (!in_array($elements['0'], $allowed_array)) { AmpError::add('url', T_('Invalid URL must be http:// or https://')); } if (!empty($data['site_url'])) { $elements = explode(":", $data['site_url']); if (!in_array($elements['0'], $allowed_array)) { AmpError::add('site_url', T_('Invalid URL must be http:// or https://')); } } // Make sure it's a real catalog $catalog = Catalog::create_from_id($data['catalog']); if (!$catalog->name) { AmpError::add('catalog', T_('Invalid Catalog')); } if (AmpError::occurred()) { return false; } // If we've made it this far everything must be ok... I hope $sql = "INSERT INTO `live_stream` (`name`,`site_url`,`url`,`catalog`,`codec`) " . "VALUES (?, ?, ?, ?, ?)"; $db_results = Dba::write($sql, array($data['name'], $data['site_url'], $data['url'], $catalog->id, $data['codec'])); return $db_results; }
/** * update_remote_catalog * * Pulls the data from a remote catalog and adds any missing songs to the * database. */ public function update_remote_catalog($type = 0) { set_time_limit(0); $remote_handle = $this->connect(); if (!$remote_handle) { return false; } // Get the song count, etc. $remote_catalog_info = $remote_handle->info(); // Tell 'em what we've found, Johnny! UI::update_text('', sprintf(T_('%u remote catalog(s) found (%u songs)'), $remote_catalog_info['catalogs'], $remote_catalog_info['songs'])); // Hardcoded for now $step = 500; $current = 0; $total = $remote_catalog_info['songs']; while ($total > $current) { $start = $current; $current += $step; try { $songs = $remote_handle->send_command('songs', array('offset' => $start, 'limit' => $step)); } catch (Exception $e) { AmpError::add('general', $e->getMessage()); AmpError::display('general'); flush(); } // Iterate over the songs we retrieved and insert them foreach ($songs as $data) { if ($this->check_remote_song($data['song'])) { debug_event('remote_catalog', 'Skipping existing song ' . $data['song']['url'], 5); } else { $data['song']['catalog'] = $this->id; $data['song']['file'] = preg_replace('/ssid=.*?&/', '', $data['song']['url']); if (!Song::insert($data['song'])) { debug_event('remote_catalog', 'Insert failed for ' . $data['song']['self']['id'], 1); AmpError::add('general', T_('Unable to Insert Song - %s'), $data['song']['title']); AmpError::display('general'); flush(); } } } } // end while UI::update_text('', T_('Completed updating remote catalog(s).')); // Update the last update value $this->update_last_update(); return true; }
/** * 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 * @param int $limit * @return array */ public function gather_folder($limit = 5) { if (!$limit) { $limit = 5; } $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 = AmpConfig::get('album_art_preferred_filename'); // Array of valid extensions $image_extensions = array('bmp', 'gif', 'jp2', 'jpeg', 'jpg', 'png'); $dirs = array(); if ($this->type == 'album') { $media = new Album($this->uid); $songs = $media->get_songs(); foreach ($songs as $song_id) { $song = new Song($song_id); $dirs[] = Core::conv_lc_file(dirname($song->file)); } } else { if ($this->type == 'video') { $media = new Video($this->uid); $dirs[] = Core::conv_lc_file(dirname($media->file)); } } foreach ($dirs as $dir) { 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) { AmpError::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 (false !== ($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 (!Core::get_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, 'title' => 'Folder'); break; } debug_event('folder_art', "Found image file: {$file}", 5); $results[$index] = array('file' => $full_filename, 'mime' => 'image/' . $extension, 'title' => 'Folder'); } // end while reading dir closedir($handle); } // end foreach dirs 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); }
/** * clean_catalog_proc * * Removes songs that no longer exist. */ public function clean_catalog_proc() { $dead = 0; $client = $this->createClient(); if ($client != null) { $sql = 'SELECT `id`, `file` FROM `song` WHERE `catalog` = ?'; $db_results = Dba::read($sql, array($this->id)); while ($row = Dba::fetch_assoc($db_results)) { debug_event('dropbox-clean', 'Starting work on ' . $row['file'] . '(' . $row['id'] . ')', 5, 'ampache-catalog'); $file = $this->get_rel_path($row['file']); $metadata = $client->getMetadata($file); if ($metadata) { debug_event('dropbox-clean', 'keeping song', 5, 'ampache-catalog'); } else { debug_event('dropbox-clean', 'removing song', 5, 'ampache-catalog'); $dead++; Dba::write('DELETE FROM `song` WHERE `id` = ?', array($row['id'])); } } } else { AmpError::add('general', T_('API Error: cannot connect to Dropbox.')); } return $dead; }