summaryrefslogtreecommitdiffstats
path: root/modules/class
diff options
context:
space:
mode:
Diffstat (limited to 'modules/class')
-rw-r--r--modules/class/access.php189
-rw-r--r--modules/class/album.php463
-rw-r--r--modules/class/artist.php207
-rw-r--r--modules/class/catalog.php1934
-rw-r--r--modules/class/error.php94
-rw-r--r--modules/class/playlist.php366
-rw-r--r--modules/class/song.php657
-rw-r--r--modules/class/stream.php291
-rw-r--r--modules/class/update.php880
-rw-r--r--modules/class/user.php604
-rw-r--r--modules/class/view.php229
11 files changed, 5914 insertions, 0 deletions
diff --git a/modules/class/access.php b/modules/class/access.php
new file mode 100644
index 00000000..6e6afbf2
--- /dev/null
+++ b/modules/class/access.php
@@ -0,0 +1,189 @@
+<?
+/*
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header Access Class
+*/
+
+class Access {
+
+ /* Variables from DB */
+ var $id;
+ var $name;
+ var $start;
+ var $end;
+ var $level;
+
+ /*!
+ @function Access
+ @discussion Access class, for modifing access rights
+ @param $access_id The ID of access entry
+ */
+ function Access($access_id = 0) {
+
+ /* If we have passed an id then do something */
+ if ($access_id) {
+
+ /* Assign id for use in get_info() */
+ $this->id = $access_id;
+
+ /* Get the information from the db */
+ if ($info = $this->get_info()) {
+
+ /* Assign Vars */
+ $this->name = $info->name;
+ $this->start = $info->start;
+ $this->end = $info->end;
+ $this->level = $info->level;
+ } // if info
+
+ } // if access_id
+
+ } //constructor
+
+ /*!
+ @function get_info
+ @discussion get's the vars for $this out of the database
+ @param $this->id Taken from the object
+ */
+ function get_info() {
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT * FROM access_list WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results;
+
+ } //get_info
+
+ /*!
+ @function create
+ @discussion creates a new entry
+ */
+ function create($name,$start,$end,$level) {
+
+ $start = ip2int($start);
+ $end = ip2int($end);
+ $name = sql_escape($name);
+ $level = intval($level);
+
+ $sql = "INSERT INTO access_list (`name`,`level`,`start`,`end`) VALUES ".
+ "('$name','$level','$start','$end')";
+ $db_results = mysql_query($sql, dbh());
+
+ } // create
+
+ /*!
+ @function delete
+ @discussion deletes $this access_list entry
+ */
+ function delete($access_id=0) {
+
+ if (!$access_id) {
+ $access_id = $this->id;
+ }
+
+ $sql = "DELETE FROM access_list WHERE id='$access_id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // delete
+
+ /*!
+ @function check
+ @discussion check to see if they have rights
+ */
+ function check($needed, $ip) {
+
+ // They aren't using access control
+ // lets just keep on trucking
+ if (!conf('access_control')) {
+ return true;
+ }
+
+ $ip = ip2int($ip);
+
+ $sql = "SELECT id FROM access_list WHERE start<='$ip' AND end>='$ip' AND level>='$needed'";
+ $db_results = mysql_query($sql, dbh());
+
+ // Yah they have access they can use the mojo
+ if (mysql_fetch_row($db_results)) {
+ return true;
+ }
+
+ // No Access Sucks to be them.
+ else {
+ return false;
+ }
+
+ } // check
+
+ /*!
+ @function get_access_list
+ @discussion returns a full listing of all access
+ rules on this server
+ */
+ function get_access_list() {
+
+ $sql = "SELECT * FROM access_list";
+ $db_results = mysql_query($sql, dbh());
+
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $obj = new Access();
+ $obj->id = $r->id;
+ $obj->start = $r->start;
+ $obj->end = $r->end;
+ $obj->name = $r->name;
+ $obj->level = $r->level;
+ $results[] = $obj;
+ } // end while access list mojo
+
+ return $results;
+
+ } // get_access_list
+
+
+ /*!
+ @function get_level_name
+ @discussion take the int level and return a
+ named level
+ */
+ function get_level_name() {
+
+ if ($this->level == '75') {
+ return "Full Access";
+ }
+ if ($this->level == '5') {
+ return "Demo";
+ }
+ if ($this->level == '25') {
+ return "Stream";
+ }
+ if ($this->level == '50') {
+ return "Stream/Download";
+ }
+
+
+ } // get_level_name
+
+} //end of access class
+
+?>
diff --git a/modules/class/album.php b/modules/class/album.php
new file mode 100644
index 00000000..c95a8ff6
--- /dev/null
+++ b/modules/class/album.php
@@ -0,0 +1,463 @@
+<?php
+/*
+ Copyright (c) 2004
+ Ampache.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header Album Class
+*/
+
+class Album {
+
+ /* Variables from DB */
+ var $id;
+ var $name;
+ var $year;
+ var $prefix;
+
+ /*!
+ @function Album
+ @discussion Album class, for modifing a song.
+ @param $album_id The ID of the song
+ */
+ function Album($album_id = 0) {
+
+ /* If we have passed an id then do something */
+ if ($album_id) {
+
+ /* Assign id for use in get_info() */
+ $this->id = $album_id;
+
+ /* Get the information from the db */
+ if ($info = $this->get_info()) {
+
+ /* Assign Vars */
+ $this->name = trim($info->prefix . " " . $info->album_name);
+ $this->songs = $info->song_count;
+ $this->artist_count = $info->artist_count;
+ $this->year = $info->year;
+ $this->artist = trim($info->artist_prefix . " " . $info->artist_name);
+ $this->artist_id = $info->art_id;
+ $this->album = $info->album_name;
+
+ $this->prefix = $info->prefix;
+ } // if info
+
+ } // if album_id
+
+ } //constructor
+
+
+ /*!
+ @function get_info
+ @discussion get's the vars for $this out of the database
+ @param $this->id Taken from the object
+ */
+ function get_info() {
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT COUNT(DISTINCT(song.artist)) as artist_count,album.prefix,album.year,album.name AS album_name,COUNT(song.id) AS song_count," .
+ "artist.name AS artist_name,artist.id AS art_id,artist.prefix AS artist_prefix ".
+ "FROM song,artist,album WHERE album.id='$this->id' AND song.album=album.id AND song.artist=artist.id GROUP BY song.album";
+
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results;
+
+ } //get_info
+
+ /*!
+ @function get_songs
+ @discussion gets the songs for this album
+ */
+ function get_songs($limit = 0) {
+
+ $results = array();
+
+ $sql = "SELECT id FROM song WHERE album='$this->id' ORDER BY track, title";
+ if ($limit) { $sql .= " LIMIT $limit"; }
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Song($r->id);
+ }
+
+ return $results;
+
+ } // get_songs
+
+
+ /*!
+ @function format_album
+ @dicussion reformats this object with f_name, f_songs and f_artist
+ that contain links etc...
+ */
+ function format_album() {
+
+ $web_path = conf('web_path');
+
+ /* Truncate the string if it's to long */
+ $name = truncate_with_ellipse($this->name,conf('ellipse_threshold_album'));
+
+ $this->f_name = "<a href=\"$web_path/albums.php?action=show&amp;album=" . $this->id . "\" title=\"" . $this->name . "\">" . $name . "</a>";
+ $this->f_songs = "<div align=\"center\">" . $this->songs . "</div>";
+ if ($this->artist_count == '1') {
+ $this->f_artist = "<a href=\"$web_path/artists.php?action=show&amp;artist=" . $this->artist_id . "\">" . $this->artist . "</a>";
+ }
+ else {
+ $this->f_artist = _("Various");
+ }
+
+ if ($this->year == '0') {
+ $this->year = "N/A";
+ }
+
+ } // format_album
+
+ /*!
+ @function get_art
+ @discussion get art wrapper function
+ */
+ function get_art($fast = 0) {
+
+ /* Check DB first */
+ if ($image = $this->get_db_art()) {
+ return $image;
+ }
+
+ /* Stop here if we are doing the fast art */
+ if ($fast) { return false; }
+
+ /* Create Base Vars */
+ $album_art_order = array();
+
+ /* Attempt to retrive the album art order */
+ $config_value = conf('album_art_order');
+ $class_methods = get_class_methods('Album');
+
+ /* If it's not set */
+ if (empty($config_value)) {
+ $album_art_order = array('id3','folder','amazon');
+ }
+ elseif (!is_array($config_value)) {
+ $album_art_order = array_push($album_art_order,$config_value);
+ }
+ else {
+ $album_art_order = array_merge($album_art_order, conf('album_art_order'));
+ }
+
+ foreach ($album_art_order AS $method) {
+
+ $method_name = "get_" . $method . "_art";
+
+ if (in_array($method_name,$class_methods)) {
+ if ($this->{$method_name}()) {
+ return $this->get_db_art();
+ } // if method finds the art
+ } // if the method exists
+
+ } // end foreach
+
+ return false;
+
+ } // get_art
+
+ /*!
+ @function get_id3_art
+ @discussion looks for art from the id3 tags
+ */
+ function get_id3_art() {
+
+ $songs = $this->get_songs();
+
+ // Foreach songs in this album
+ foreach ($songs as $song) {
+ // If we find a good one, stop looking
+ $getID3 = new getID3();
+ $id3 = $getID3->analyze($song->file);
+
+ if ($id3['format_name'] == "WMA") {
+ $image = $id3['asf']['extended_content_description_object']['content_descriptors']['13'];
+ }
+ else {
+ $image = $id3['id3v2']['APIC']['0'];
+ }
+ if ($image) {
+ $art = $image['data'];
+ $mime = $image['mime'];
+
+ // Stick it in the db for next time
+ $sql = "UPDATE album SET art = '" . sql_escape($art) . "'," .
+ " art_mime = '" . sql_escape($mime) . "'" .
+ " WHERE id = '" . $this->id . "'";
+ $db_result = mysql_query($sql, dbh());
+
+ return true;
+ } // end if image
+ } // end foreach
+
+ return false;
+
+ } // get_id3_art
+
+ /*!
+ @function get_folder_art()
+ @discussion returns the album art from the folder of the mp3s
+ */
+ function get_folder_art() {
+
+ $songs = $this->get_songs();
+
+ /* See if we are looking for a specific filename */
+ $preferred_filename = conf('album_art_preferred_filename');
+
+ /* Thanks to dromio for origional code */
+ /* Added search for any .jpg, png or .gif - Vollmer */
+ foreach($songs as $song) {
+ $dir = dirname($song->file);
+
+ /* Open up the directory */
+ $handle = @opendir($dir);
+
+ if (!is_resource($handle)) {
+ echo "<font class=\"error\">" . _("Error: Unable to open") . " $dir</font><br />\n";
+ if (conf('debug')) { log_event($GLOBALS['user']->username,' read ',"Error: Unable to open $dir for album art read"); }
+ }
+
+ /* Recurse through this dir and create the files array */
+ while ( FALSE !== ($file = @readdir($handle)) ) {
+ $extension = substr($file,strlen($file)-3,4);
+
+ /* If it's an image file */
+ if ($extension == "jpg" || $extension == "gif" || $extension == "png" || $extension == "jp2") {
+
+ if ($file == $preferred_filename) {
+ $found = 1;
+ $album_art_filename = array('file' => $file, 'ext' => $extension);
+ break;
+ }
+ elseif (!$preferred_filename) {
+ $found = 1;
+ $album_art_filename = array('file' => $file, 'ext' => $extension);
+ break;
+ }
+ else {
+ $found = 1;
+ $album_art_filename = array('file' => $file, 'ext' => $extension);
+ }
+
+ } // end if it's an image
+
+ } // end while reading dir
+ @closedir($handle);
+
+ if ($found) {
+ $handle = fopen($dir."/".$album_art_filename['file'], "rb");
+ $mime = "image/" . $album_art_filename['ext'];
+ $art = '';
+ while(!feof($handle)) {
+ $art .= fread($handle, 1024);
+ }
+ fclose($handle);
+ $sql = "UPDATE album SET art = '" . sql_escape($art) . "'," .
+ " art_mime = '" . sql_escape($mime) . "'" .
+ " WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+ return true;
+ } // if found
+ } // end foreach songs
+
+ return false;
+
+ } // get_folder_art()
+
+ /*!
+ @function get_db_art()
+ @discussion returns the album art from the db
+ */
+ function get_db_art() {
+
+ $sql = "SELECT art,art_mime FROM album WHERE id='$this->id' AND art_mime IS NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results;
+
+ } // get_db_art
+
+
+ /*!
+ @function get_amazon_art
+ @discussion searches amazon for the
+ album art
+ */
+ function get_amazon_art() {
+
+ return $this->find_art();
+
+ } // get_amazon_art
+
+ /*!
+ @function get_random_songs
+ @discussion gets a random number, and
+ a random assortment of songs from this
+ album
+ */
+ function get_random_songs() {
+
+ $results = array();
+
+ $sql = "SELECT id FROM song WHERE album='$this->id' ORDER BY RAND() LIMIT " . rand(1,$this->songs);
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_array($db_results)) {
+ $results[] = $r[0];
+ }
+
+ return $results;
+
+ } // get_random_songs
+
+ /*!
+ @function clear_art
+ @discussion clears the album art from the DB
+ */
+ function clear_art() {
+
+ $sql = "UPDATE album SET art=NULL, art_mime=NULL WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // clear_art
+
+ /*!
+ @function find_art
+ @discussion searches amazon or a url
+ for the album art
+ //FIXME: Rename this POS
+ */
+ function find_art($coverurl = '') {
+
+ // No coverurl specified search amazon
+ if (empty($coverurl)) {
+ $amazon = new AmazonSearch(conf('amazon_developer_key'));
+ // Prevent the script from timing out
+ set_time_limit(0);
+ $search_term = $this->artist . " " . $this->name;
+ $amazon->search(array('artist' => $this->artist, 'album' => $this->name, 'keywords' => $serch_term));
+ // Only do the second search if the first actually returns something
+ if (count($amazon->results)) {
+ $amazon->lookup($amazon->results);
+ }
+
+ /* Log this if we're doin debug */
+ if (conf('debug')) {
+ log_event($_SESSION['userdata']['username'],' amazon-xml ',"Searched using $search_term with " . conf('amazon_developer_key') . " as key " . count($amazon->results) . " results found");
+ }
+
+ //FIXME: For now just pull the first one we find
+ foreach ($amazon->results as $key=>$value) {
+ $results = $value;
+ break;
+ } //FIXME:
+
+ } // if no cover
+ // If we've specified a coverurl, create a fake Amazon array with it
+ else {
+ $results = array('LargeImage' => $coverurl);
+ }
+
+ // If we have results of some kind
+ if (is_array($results)) {
+
+ /* Recurse through the images found */
+ $possible_keys = array("LargeImage","MediumImage","SmallImage");
+
+ foreach ($possible_keys as $key) {
+ if (strlen($results[$key])) {
+ break;
+ }
+
+
+ } // foreach
+
+ // Rudimentary image type detection, only JPG and GIF allowed.
+ if (substr($results[$key], -4 == ".jpg")) {
+ $mime = "image/jpg";
+ }
+ elseif (substr($results[$key], -4 == ".gif")) {
+ $mime = "image/gif";
+ }
+ else {
+ return false;
+ }
+
+ /* Create Snoopy Object and pull info */
+ $snoopy = new Snoopy;
+ $snoopy->fetch($results[$key]);
+ $art = $snoopy->results;
+
+ // Skip 1x1 size images
+ if (function_exists('ImageCreateFromString')) {
+ $im = @ImageCreateFromString($art);
+ if (@imagesx($im) == 1 || @imagesy($im) == 1 && $im) {
+ return false;
+ }
+ }
+
+ // Push the image into the database
+ $sql = "UPDATE album SET art = '" . sql_escape($art) . "'," .
+ " art_mime = '" . sql_escape($mime) . "'" .
+ " WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ return true;
+
+ } // if we've got something
+
+ /* Default to false */
+ return false;
+
+ } // find_art
+
+ /*!
+ @function get_song_ids
+ @discussion returns a list of song_ids on the album
+ get_songs returns a list of song objects
+ */
+
+ // it seems get_songs really should call this,
+ // but I don't feel comfortable imposing that - RCR
+ function get_song_ids( $limit = 0 ) {
+ $results = array();
+ $sql = "SELECT id FROM song WHERE album='$this->id' ORDER BY track, title";
+ if ($limit) { $sql .= " LIMIT $limit"; }
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = $r->id;
+ }
+ return( $results );
+ } // get_song_ids
+
+} //end of album class
+
+?>
diff --git a/modules/class/artist.php b/modules/class/artist.php
new file mode 100644
index 00000000..a0b4caa7
--- /dev/null
+++ b/modules/class/artist.php
@@ -0,0 +1,207 @@
+<?php
+/*
+
+ Copyright (c) 2004 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header Artist Class
+*/
+
+class Artist {
+
+ /* Variables from DB */
+ var $id;
+ var $name;
+ var $songs;
+ var $albums;
+ var $prefix;
+
+ /*!
+ @function Artist
+ @discussion Song class, for modifing a song.
+ @param $song_id The ID of the song
+ */
+ function Artist($song_id = 0) {
+
+ /* If we have passed an id then do something */
+ if ($song_id) {
+
+ /* Assign id for use in get_info() */
+ $this->id = $song_id;
+
+ /* Get the information from the db */
+ if ($info = $this->get_info()) {
+
+ /* Assign Vars */
+ $this->name = $info->name;
+ $this->prefix = $info->prefix;
+ } // if info
+
+ } // if song_id
+
+ } //constructor
+
+
+ /*!
+ @function get_info
+ @discussion get's the vars for $this out of the database
+ @param $this->id Taken from the object
+ */
+ function get_info() {
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT * FROM artist WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results;
+
+ } //get_info
+
+ /*!
+ @function get_albums
+ @discussion gets the albums for this artist
+ */
+ function get_albums() {
+
+ $results = array();
+
+ $sql = "SELECT DISTINCT(album.id) FROM song,album WHERE song.album=album.id AND song.artist='$this->id' ORDER BY album.name";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Album($r->id);
+ }
+
+ return $results;
+
+ } // get_albums
+
+ /*!
+ @function get_songs
+ @discussion gets the songs for this artist
+ */
+ function get_songs() {
+
+ $sql = "SELECT song.id FROM song WHERE song.artist='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Song($r->id);
+ }
+
+ return $results;
+
+ } // get_songs
+
+ /*!
+ @function get_random_songs
+ @discussion gets a random number, and
+ a random assortment of songs from this
+ album
+ */
+ function get_random_songs() {
+
+ $results = array();
+
+ $sql = "SELECT id FROM song WHERE artist='$this->id' ORDER BY RAND() LIMIT " . rand(1,$this->songs);
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_array($db_results)) {
+ $results[] = $r[0];
+ }
+
+ return $results;
+
+ } // get_random_songs
+
+ /*!
+ @function get_count
+ @discussion gets the album and song count of
+ this artist
+ */
+ function get_count() {
+
+ /* Define vars */
+ $songs = 0;
+ $albums = 0;
+
+ $sql = "SELECT COUNT(song.id) FROM song WHERE song.artist='$this->id' GROUP BY song.album";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_array($db_results)) {
+ $songs += $r[0];
+ $albums++;
+ }
+
+ /* Set Object Vars */
+ $this->songs = $songs;
+ $this->albums = $albums;
+
+ return true;
+
+ } // get_count
+
+ /*!
+ @function format_artist
+ @discussion 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.
+ */
+ function format_artist() {
+
+ /* Combine prefix and name, trim then add ... if needed */
+ $name = truncate_with_ellipse(trim($this->prefix . " " . $this->name));
+
+ $this->f_name = $this->name;
+ $this->full_name = trim($this->prefix . " " . $this->name);
+ //FIXME: This shouldn't be set like this, f_name should be like this
+ $this->link = "<a href=\"" . conf('web_path') . "/artists.php?action=show&amp;artist=" . $this->id . "\" title=\"" . $this->full_name . "\">" .
+ $name . "</a>";
+ $this->name = $this->link;
+ return $artist;
+
+ } // format_artist
+
+
+ /*!
+ @function show_albums
+ @discussion displays the show albums by artist page
+ */
+ function show_albums() {
+
+ /* Set Vars */
+ $web_path = conf('web_path');
+
+
+ $albums = $this->get_albums();
+ $this->format_artist();
+ $artist = $this;
+
+ require (conf('prefix') . "/templates/show_artist.inc");
+
+ } // show_albums
+
+
+} //end of artist class
+
+?>
diff --git a/modules/class/catalog.php b/modules/class/catalog.php
new file mode 100644
index 00000000..9affc95a
--- /dev/null
+++ b/modules/class/catalog.php
@@ -0,0 +1,1934 @@
+<?
+/*
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+/*!
+ @header Catalog Class
+ This class handles all actual work in regards to the catalog, it contains functions for creating/listing/updated the catalogs.
+*/
+
+class Catalog {
+
+ var $name;
+ var $last_update;
+ var $last_add;
+ var $id3_set_command;
+ var $rename_pattern;
+ var $sort_pattern;
+ var $catalog_type;
+
+ // Used in functions
+ var $albums = array();
+ var $artists = array();
+ var $genres = array();
+
+ /*!
+ @function Catalog
+ @discussion Catalog class constructor, pulls catalog information
+ @param $catalog_id The ID of the catalog you want to build information from
+ */
+ function Catalog($catalog_id = 0) {
+
+ /* If we have passed an id then do something */
+ if ($catalog_id) {
+ /* Assign id for use in get_info() */
+ $this->id = $catalog_id;
+
+ /* Get the information from the db */
+ $info = $this->get_info();
+
+ /* Assign Vars */
+ $this->path = $info->path;
+ $this->name = $info->name;
+ $this->last_update = $info->last_update;
+ $this->last_add = $info->last_add;
+ $this->id3_set_command = $info->id3_set_command;
+ $this->rename_pattern = $info->rename_pattern;
+ $this->sort_pattern = $info->sort_pattern;
+ $this->catalog_type = $info->catalog_type;
+ } //catalog_id
+
+ } //constructor
+
+
+ /*!
+ @function get_info
+ @discussion get's the vars for $this out of the database
+ @param $this->id Taken from the object
+ */
+ function get_info() {
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT * FROM catalog WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results;
+
+ } //get_info
+
+
+ /*!
+ @function get_catalogs
+ @discussion Pull all the current catalogs
+ */
+ function get_catalogs() {
+
+ $sql = "SELECT id FROM catalog";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Catalog($r->id);
+ }
+
+ return $results;
+
+ } // get_catalogs
+
+
+ /*!
+ @function get_catalog_stats
+ @discussion Pulls information about number of songs etc for a specifc catalog, or all catalogs
+ calls many other internal functions, returns an object containing results
+ @param $catalog_id If set tells us to pull from a single catalog, rather than all catalogs
+ */
+ function get_catalog_stats($catalog_id=0) {
+
+ $results->songs = $this->count_songs($catalog_id);
+ $results->albums = $this->count_albums($catalog_id);
+ $results->artists = $this->count_artists($catalog_id);
+ $results->size = $this->get_song_size($catalog_id);
+ $results->time = $this->get_song_time($catalog_id);
+
+ } // get_catalog_stats
+
+
+ /*!
+ @function get_song_time
+ @discussion Get the total amount of time (song wise) in all or specific catalog
+ @param $catalog_id If set tells ut to pick a specific catalog
+ */
+ function get_song_time($catalog_id=0) {
+
+ $sql = "SELECT SUM(song.time) FROM song";
+ if ($catalog_id) {
+ $sql .= " WHERE catalog='$catalog_id'";
+ }
+
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_field($db_results);
+
+ /* Do some conversion to get Hours Min Sec */
+
+
+ return $results;
+
+ } // get_song_time
+
+
+ /*!
+ @function get_song_size
+ @discussion Get the total size of songs in all or a specific catalog
+ @param $catalog_id If set tells us to pick a specific catalog
+ */
+ function get_song_size($catalog_id=0) {
+
+ $sql = "SELECT SUM(song.size) FROM song";
+ if ($catalog_id) {
+ $sql .= " WHERE catalog='$catalog_id'";
+ }
+
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_field($db_results);
+
+ /* Convert it into MB */
+ $results = ($results / 1048576);
+
+ return $results;
+
+ } // get_song_size
+
+
+ /*!
+ @function count_artists
+ @discussion Count the number of artists in all catalogs or in a specific one
+ @param $catalog_id If set tells us to pick a specific catalog
+ */
+ function count_artists($catalog_id=0) {
+
+ $sql = "SELECT DISTINCT(song.artist) FROM song";
+ if ($catalog_id) {
+ $sql .= " WHERE catalog='$catalog_id'";
+ }
+
+ $db_results = mysql_query($sql,dbh());
+
+ $results = mysql_num_rows($db_results);
+
+ return $results;
+
+ } // count_artists
+
+
+ /*!
+ @function count_albums
+ @discussion Count the number of albums in all catalogs or in a specific one
+ @param $catalog_id If set tells us to pick a specific catalog
+ */
+ function count_albums($catalog_id=0) {
+
+ $sql = "SELECT DISTINCT(song.album) FROM song";
+ if ($catalog_id) {
+ $sql .=" WHERE catalog='$catalog_id'";
+ }
+
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_num_rows($db_results);
+
+ return $results;
+
+ } // count_albums
+
+
+ /*!
+ @function count_songs
+ @discussion Count the number of songs in all catalogs, or a specific one
+ @param $catalog_id If set tells us to pick a specific catalog
+ */
+ function count_songs($catalog_id=0) {
+
+ $sql = "SELECT count(*) FROM song";
+ if ($catalog_id) {
+ $sql .= " WHERE catalog='$catalog_id'";
+ }
+
+ $db_results = mysql_query($sql, dbh());
+ $results = mysql_fetch_field($db_results);
+
+ return $results;
+
+ } // count_songs
+
+ /*!
+ @function add_file
+ @discussion adds a single file
+ */
+ function add_file($filename) {
+
+ $file_size = @filesize($filename);
+ $pattern = "/\.[" . conf('catalog_file_pattern') . "]$/i";
+
+ if ( preg_match($pattern ,$filename) && ($file_size > 0) && (!preg_match('/\.AppleDouble/', $filename)) ) {
+ if(!$this->check_local_mp3($filename,$gather_type)) {
+ $this->insert_local_song($filename,$file_size);
+ }
+ } // if valid file
+
+
+ } // add_file
+
+
+ /*!
+ @function add_files
+ @discussion Recurses throught $this->path and pulls out all mp3s and returns the full
+ path in an array. Passes gather_type to determin if we need to check id3
+ information against the db.
+ @param $path The root path you want to start grabing files from
+ @param $gather_type=0 Determins if we need to check the id3 tags of the file or not
+ */
+ function add_files($path,$gather_type=0,$parse_m3u=0) {
+ /* Strip existing escape slashes and then add them again
+ This is done because we keep adding to the dir (slashed) + (non slashed)
+ and a double addslashes would pooch things
+ */
+
+ /* Open up the directory */
+ $handle = opendir(stripslashes($path));
+
+ if (!is_resource($handle)) {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'read',"Unable to Open $path",'ampache-catalog'); }
+ echo "<font class=\"error\">" . _("Error: Unable to open") . " $path</font><br />\n";
+ }
+
+ /* Recurse through this dir and create the files array */
+ while ( false !== ( $file = readdir($handle) ) ) {
+
+ // Fix Found by Naund
+ // Needed to protect from ' in filenames
+ $file = sql_escape($file);
+
+ // Prevent the script from timing out
+ set_time_limit(0);
+
+ /* if not .. or . */
+ if ($file != "." AND $file != "..") {
+
+ if (conf('debug')) {
+ log_event($_SESSION['userdata']['username'],'read',"Starting work on $file inside $path",'ampache-catalog');
+ }
+
+ /* Change the dir so is_dir works correctly */
+ if (!@chdir(stripslashes($path))) {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'read',"Unable to chdir $path",'ampache-catalog'); }
+ echo "<font class=\"error\">" . _("Error: Unable to change to directory") . " $path</font><br />\n";
+ }
+
+ /* Create the new path */
+ $full_file = stripslashes($path."/".$file);
+ $full_file = str_replace("//","/",$full_file);
+
+ if (conf('no_symlinks')) {
+ if (is_link($full_file)) { $failed_check = 1; }
+ }
+
+ /* If it's a dir run this function again! */
+ if (is_dir($full_file) AND !$failed_check) {
+ $this->add_files($full_file,$gather_type,$parse_m3u);
+ unset($failed_check);
+ } //it's a directory
+
+ /* If it's not a dir let's roll with it */
+ else {
+ /* Get the file information */
+ $file_size = @filesize($full_file);
+
+ if (!$file_size && $file_size != '0') {
+ echo "<font class=\"error\">" . _("Error: Unable to get filesize for") . " $full_file <br />";
+ if (conf('debug')) { log_event($GLOBALS['user']->username,' read ',"Error: Unable to get filesize for $full_file",'ampache-catalog'); }
+ } // if no filesize
+
+ $pattern = "/\.(" . conf('catalog_file_pattern');
+ if ($parse_m3u) {
+ $pattern .= "|m3u)$/i";
+ }
+ else {
+ $pattern .= ")$/i";
+ }
+
+ /* see if this is an mp3 file and if it is greater than 0 bytes */
+ if ( preg_match($pattern ,$file) && ($file_size > 0) && (!preg_match('/\.AppleDouble/', $file)) ) {
+
+ if (is_readable($full_file)) {
+
+ if (substr($file,-3,3) == 'm3u') {
+ if ($this->import_m3u($full_file)) {
+ echo "&nbsp;&nbsp;&nbsp;" . _("Added Playlist From") . " $file . . . .<br />\n";
+ flush();
+ }
+ } // if it's an m3u
+
+ else {
+
+ /* see if the current song is in the catalog */
+ $found = $this->check_local_mp3($full_file,$gather_type);
+
+ /* If not found then insert, gets id3 information
+ * and then inserts it into the database
+ */
+ if (!$found) {
+ $this->insert_local_song($full_file,$file_size);
+
+ /* Stupid little cutesie thing */
+ $this->count++;
+ if ( !($this->count%conf('catalog_echo_count')) ) {
+ echo _("Added") . " $this->count. . . . <br />\n";
+ flush();
+ } //echos song count
+
+ } // not found
+
+ } // if it's not an m3u
+
+ } // is readable
+ else {
+ // not readable, warn user
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'read',"$full_file is not readable by ampache",'ampache-catalog'); }
+ echo "$full_file " . _("is not readable by ampache") . ".<br />\n";
+
+ }
+
+ } //if it's a mp3 and is greater than 0 bytes
+
+ else {
+ if (conf('debug')) {
+ log_event($_SESSION['userdata']['username'],'read',"$full_file ignored, non audio file or 0 bytes",'ampache-catalog');
+ }
+ } // else not an audio file or 0 size
+
+ } //else it's not a directory
+
+ } //end if not . or ..
+
+ } //end while
+
+ if (conf('debug')) {
+ log_event($_SESSION['userdata']['username'],' closedir ',"Finished reading $path closing handle",'ampache-catalog');
+ }
+
+ /* Close the dir handle */
+ @closedir($handle);
+
+ } //add_files
+
+ /*!
+ @function get_albums
+ @discussion This gets albums for all songs passed in an array
+ */
+ function get_albums($songs=array()) {
+
+ foreach ($songs as $song_id) {
+ $sql = "SELECT album FROM song WHERE id='$song_id'";
+ $db_results = mysql_query($sql, dbh());
+ $results = mysql_fetch_array($db_results);
+ $albums[] = new Album($results[0]);
+ } // files
+
+ return $albums;
+
+ } // get_albums
+
+ /*!
+ @function get_album_art
+ @discussion This runs through all of the albums and trys to find the
+ art for them from the mp3s
+ //FIXME: Make the display a table so it all lines up
+ */
+ function get_album_art($catalog_id=0,$methods=array()) {
+
+ if (!$catalog_id) { $catalog_id = $this->id; }
+
+ // Get all of the albums in this catalog
+ $albums = $this->get_catalog_albums($catalog_id);
+
+ // Run through them an get the art!
+ foreach ($albums as $album) {
+ flush();
+ if ($debug) { echo "&nbsp;&nbsp;&nbsp;&nbsp;" . $album->name . " -- "; }
+
+ if ($methods['id3']) {
+ $found = $album->get_id3_art();
+ if ($found && $debug) { echo _("Found in ID3") . "<br />\n"; }
+ }
+ if ($methods['amazon'] && !$found) {
+ $found = $album->get_amazon_art();
+ if ($found && $debug) { echo _("Found on Amazon") . "<br />\n"; }
+ }
+ if ($methods['folder'] && !$found) {
+ $found = $album->get_folder_art();
+ if ($found && $debug) { echo _("Found in Folder") . "<br />\n"; }
+ }
+ if (count($methods) == '0' && !$found) {
+ $found = $album->get_art();
+ if ($found && $debug) { echo _("Found") . "<br />\n"; }
+ }
+
+ if (!$found && $debug) { echo "<font class=\"error\">" . _("Not Found") . "</font><br />\n"; }
+
+ if ($found) { $art_found++; }
+
+
+ /* Stupid little cutesie thing */
+ $search_count++;
+ if ( !($search_count%conf('catalog_echo_count')) ) {
+ echo _("Searched") . " $search_count. . . . <br />\n";
+ flush();
+ } //echos song count
+
+
+ // Prevent the script from timing out
+ set_time_limit(0);
+
+ unset($found);
+
+ } // foreach albums
+
+ echo "$art_found album's with art. . .<br />\n";
+ flush();
+
+ } // get_album_art
+
+ /*!
+ @function get_catalog_albums()
+ @discussion Returns an array of the albums from a catalog
+ */
+ function get_catalog_albums($catalog_id=0) {
+
+ $results = array();
+
+ /* Use $this->id if nothing is passed */
+ if (!$catalog_id) { $catalog_id = $this->id; }
+
+ $sql = "SELECT DISTINCT(album.id) FROM album,song WHERE song.catalog='$catalog_id' AND song.album=album.id";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Album($r->id);
+ }
+
+ return $results;
+
+ } // get_catalog_albums
+
+
+ /*!
+ @function get_catalog_files
+ @discussion Returns an array of song objects from a catalog
+ @param $catalog_id=0 Specify the catalog ID you want to get the files of
+ */
+ function get_catalog_files($catalog_id=0) {
+
+ $results = array();
+
+ /* Use $this->id if nothing passed */
+ if (!$catalog_id) { $catalog_id = $this->id; }
+
+ $sql = "SELECT id FROM song WHERE catalog='$catalog_id' AND status='enabled'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array(); // return an emty array instead of nothing if no objects
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Song($r->id);
+ } //end while
+
+ return $results;
+
+ } //get_catalog_files
+
+
+ /*!
+ @function get_disabled
+ @discussion Gets an array of the disabled songs for all catalogs
+ and returns full song objects with them
+ */
+ function get_disabled() {
+ global $conf;
+
+ $results = array();
+
+ $sql = "SELECT id FROM song WHERE status='disabled'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_array($db_results)) {
+ $results[] = new Song($r['id']);
+ }
+
+ return $results;
+
+ } // get_disabled
+
+
+ /*!
+ @function get_files
+ @discussion Get's an array of .mp3s and returns the filenames
+ @param $path Get files starting at root $path
+ */
+ function get_files($path) {
+
+ /* Set it as an empty array */
+ $files = array();
+
+ $path = stripslashes($path);
+
+ /* Open up the directory */
+ $handle = @opendir($path);
+
+ if (!is_resource($handle)) { echo "<font class=\"error\">" . _("Error: Unable to open") . " $path</font><br />\n"; }
+
+ /* Change dir so we can tell if it's a directory */
+ if (!@chdir($path)) {
+ echo "<font class=\"error\">Error: Unable to change to $path directory</font><br />\n";
+ }
+
+ /* Recurse through this dir and create the files array */
+ while ( FALSE !== ($file = @readdir($handle)) ) {
+
+ $full_file = stripslashes($path . "/" . $file);
+ $full_file = str_replace("//","/",$full_file);
+
+ if (conf('no_symlinks')) {
+ if (is_link($full_file)) { $failed_check = true; }
+ }
+
+ /* It's a dir */
+ if (is_dir($full_file) AND $file != "." AND $file != ".." AND !$failed_check) {
+ /* Merge the results of the get_files with the current results */
+ $files = array_merge($files,$this->get_files($full_file));
+ } //isdir
+
+ /* Get the file information */
+ $file_info = filesize($full_file);
+
+ $pattern = "/\.[" . conf('catalog_file_pattern') . "]$/i";
+
+ if ( preg_match($pattern ,$file) && ($file_info > 0) && (!preg_match("/\.AppleDouble/", $file)) ) {
+ $files[] = $full_file;
+ } //is mp3 of at least some size
+
+ } //end while
+
+ /* Close the dir handle */
+ @closedir($handle);
+
+ /* Return the files array */
+ return $files;
+
+ } //get_files
+
+ /*!
+ @function dump_album_art (Added by Cucumber 20050216)
+ @discussion This runs through all of the albums and trys to dump the
+ art for them into the 'folder.jpg' file in the appropriate dir
+ */
+ function dump_album_art($catalog_id=0,$methods=array()) {
+ if (!$catalog_id) { $catalog_id = $this->id; }
+
+ // Get all of the albums in this catalog
+ $albums = $this->get_catalog_albums($catalog_id);
+
+ echo "<br /><b>" . _("Starting Dump Album Art") . ". . .</b><br><br />\n";
+
+ // Run through them an get the art!
+ foreach ($albums as $album) {
+ flush();
+ if ($image = $album->get_db_art()) {
+ /* Get the first song in the album */
+ $songs = $album->get_songs(1);
+ $song = $songs[0];
+ $dir = dirname($song->file);
+ $extension = substr($image->art_mime,strlen($image->art_mime)-3,3);
+
+ $preferred_filename = conf('album_art_preferred_filename');
+ if (!$preferred_filename) { $preferred_filename = "folder.$extension"; }
+
+ $file = "$dir/$preferred_filename";
+ if ($file_handle = @fopen($file,"w")) {
+ if (fwrite($file_handle, $image->art)) {
+ $i++;
+ if ( !($i%conf('catalog_echo_count')) ) {
+ echo _("Written") . " $i. . . <br />\n";
+ flush();
+ } //echos song count
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'art_write',"$album->name Art written to $file"); }
+ }
+ fclose($file_handle);
+ } // end if fopen
+ else {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'art_write',"Unable to open $file for writting"); }
+ echo "<font class=\"error\">" . _("Error unable to open file for writting") . " [$file] </font><br />\n";
+ }
+
+ } // end if image
+
+ } // end foreach
+
+ echo "<br /><b>" . _("Album Art Dump Complete") . "</b> &nbsp;&nbsp;";
+ echo "<a href=\"" . conf('web_path') . "/admin/catalog.php" . "\">[" . _("Return") . "]</a>";
+
+ flush();
+
+ } // dump_album_art
+
+ /*!
+ @function update_last_update
+ @discussion updates the last_update of the catalog
+ */
+ function update_last_update() {
+
+ $date = time();
+ $sql = "UPDATE catalog SET last_update='$date' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // update_last_update
+
+
+ /*!
+ @function update_last_add
+ @discussion updates the last_add of the catalog
+ */
+ function update_last_add() {
+
+ $date = time();
+ $sql = "UPDATE catalog SET last_add='$date' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // update_last_add
+
+
+ /*!
+ @function new_catalog
+ @discussion The Main array for making a new catalog calls many other child functions within this class
+ @param $path Root path to start from for catalog
+ @param $name Name of the new catalog
+ */
+ function new_catalog($path,$name, $id3cmd=0, $ren=0, $sort=0, $type=0,$gather_art=0,$parse_m3u=0,$art=array()) {
+
+ /* Record the time.. time the catalog gen */
+ $start_time = time();
+
+ /* Flush anything that has happened so they don't think it's locked */
+ flush();
+
+ /*
+ * Step one Add this to the catalog table if it's not
+ * already there returns the new catalog_id
+ */
+ $catalog_id = $this->check_catalog($path);
+
+ if (!$catalog_id) {
+ $catalog_id = $this->create_catalog_entry($path,$name,$id3cmd, $ren, $sort, $type);
+ }
+
+ /* Setup the $this with the new information */
+ $this->id = $catalog_id;
+ $this->path = $path;
+ $this->name = $name;
+ $this->id3_set_command = ($id3cmd)?$id3cmd:'';
+ $this->rename_pattern = ($ren)?$ren:'';
+ $this->sort_pattern = ($sort)?$sort:'';
+ $this->catalog_type = $type;
+
+ /* Fluf */
+ echo _("Starting Catalog Build") . " [$name]<br />\n";
+ flush();
+
+
+ if ($this->catalog_type == 'remote') {
+ echo _("Running Remote Sync") . ". . .<br /><br />";
+ flush();
+ $this->get_remote_catalog($type=0);
+ return true;
+ }
+ /* Get the songs and then insert them into the db */
+ $this->add_files($this->path,$type,$parse_m3u);
+
+ /* Now Adding Album Art? */
+ if ($gather_art) {
+ echo "<br />\n<b>" . _("Starting Album Art Search") . ". . .</b><br />\n";
+ flush();
+ $this->get_album_art(0,$art);
+ } // if we want to gather album art
+
+ /* Do a little stats mojo here */
+ $current_time = time();
+
+ $time_diff = $current_time - $start_time;
+ if ($time_diff) { $song_per_sec = intval($this->count/$time_diff); }
+ echo _("Catalog Finished") . ". . . " . _("Total Time") . " [" . date("i:s",$time_diff) . "] " . _("Total Songs") . " [" . $this->count . "] " .
+ _("Songs Per Seconds") . " [" . $song_per_sec . "]<br />\n";
+
+ return $catalog_id;
+
+ } //new_catalog
+
+ /*!
+ @function update_single_item
+ @discussion updates a single album,artist,song
+ */
+ function update_single_item($type,$id) {
+
+ $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[0] = new Song($id);
+ break;
+ } // end switch type
+
+ foreach($songs as $song) {
+
+ $info = $this->update_song_from_tags($song);
+
+ if ($info['change']) {
+ echo "<dl>\n\t<li>";
+ echo "<b>$song->file " . _("Updated") . "</b>\n";
+ echo $info['text'];
+ echo "\t</li>\n</dl><hr align=\"left\" width=\"50%\" />";
+ flush();
+ } // if change
+ else {
+ echo"<dl>\n\t<li>";
+ echo "<b>$song->file</b><br />" . _("No Update Needed") . "\n";
+ echo "\t</li>\n</dl><hr align=\"left\" width=\"50%\" />";
+ flush();
+ }
+ } // foreach songs
+
+ } // update_single_item
+
+ /*!
+ @function update_song_from_tags
+ @discussion updates the song info based on tags
+ */
+ function update_song_from_tags($song) {
+
+ $info = new Audioinfo();
+ $results = $info->Info($song->file);
+
+ /* Find the correct key */
+ $key = get_tag_type($results);
+
+ /* Fill Missing Information */
+ $results = $song->fill_info($results,$this->sort_pattern . "/" . $this->rename_pattern, $this->id, $key);
+
+ /* Clean up the tags */
+ $results = clean_tag_info($results,$key,$song->file);
+
+ /* 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->bitrate = $results['bitrate'];
+ $new_song->rate = $results['rate'];
+ $new_song->mode = $results['mode'];
+ $new_song->size = $results['size'];
+ $new_song->time = $results['time'];
+ $new_song->track = $results['track'];
+ $artist = $results['artist'];
+ $album = $results['album'];
+ $genre = $results['genre'];
+
+ /* Clean up Old Vars */
+ unset($results,$key,$info);
+
+ /*
+ * 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 = $this->check_artist($artist);
+ $new_song->f_artist = $artist;
+ $new_song->genre = $this->check_genre($genre);
+ $new_song->f_genre = $genre;
+ $new_song->album = $this->check_album($album,$new_song->year);
+ $new_song->f_album = $album . " - " . $new_song->year;
+ $new_song->title = $this->check_title($new_song->title,$new_song->file);
+
+ $info = $song->compare_song_information($song,$new_song);
+
+ if ($info['change']) {
+ $song->update_song($song->id,$new_song);
+ }
+
+ return $info;
+
+ } // update_song_from_tags
+
+ /*!
+ @function add_to_catalog
+ @discussion this function adds new files to an
+ existing catalog
+ */
+ function add_to_catalog($type=0) {
+
+ echo _("Starting New Song Search on") . " <b>[$this->name]</b> " . _("catalog") . "<br /><br />\n";
+ flush();
+
+ if ($this->catalog_type == 'remote') {
+ echo _("Running Remote Update") . ". . .<br /><br />";
+ flush();
+ $this->get_remote_catalog($type=0);
+ return true;
+ }
+
+ /* Set the Start time */
+ $start_time = time();
+
+ /* Get the songs and then insert them into the db */
+ $this->add_files($this->path,$type);
+
+ /* Do a little stats mojo here */
+ $current_time = time();
+
+ if ($type != "fast_add") {
+ echo "<b>" . _("Starting Album Art Search") . ". . .</b><br />\n";
+ flush();
+ $this->get_album_art();
+ }
+
+ /* Update the Catalog last_update */
+ $this->update_last_add();
+
+ $time_diff = $current_time - $start_time;
+ if ($time_diff) {
+ $song_per_sec = intval($this->count/$time_diff);
+ }
+ if (!$song_per_sec) {
+ $song_per_sec = "N/A";
+ }
+ if (!$this->count) {
+ $this->count = 0;
+ }
+
+ echo "\n<br />" . _("Catalog Update Finished") . "... " . _("Total Time") . " [" . date("i:s",$time_diff) . "] " .
+ _("Total Songs") . " [" . $this->count . "] " . _("Songs Per Seconds") . " [" . $song_per_sec . "]<br /><br />";
+
+ } // add_to_catalog
+
+
+ /*!
+ @function get_remote_catalog
+ @discussion get a remote catalog and runs update if needed
+ */
+ function get_remote_catalog($type=0) {
+
+ if (!class_exists('xmlrpc_client')) {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'xmlrpc',"Unable to load XMLRPC library"); }
+ echo "<font class=\"error\"><b>" . _("Error") . "</b>: " . _("Unable to load XMLRPC library, make sure XML-RPC is enabled") . "<br />\n";
+ return false;
+ }
+
+ // first, glean out the information from the path about the server and remote path
+ preg_match("/http:\/\/([^\/]+)\/*(.*)/", $this->path, $match);
+ $server = $match[1];
+ $path = $match[2];
+
+ if ( ! $path ) {
+ $client = new xmlrpc_client("/server.php", $server, 80);
+ }
+ else {
+ $client = new xmlrpc_client("/$path/server.php", $server, 80);
+ }
+
+ $f = new xmlrpcmsg('remote_server_query', array(new xmlrpcval( conf('web_path'), "string")) );
+ //if (conf('debug')) { $client->setDebug(1); }
+ $response = $client->send($f);
+ $value = $response->value();
+
+ if ( !$response->faultCode() ) {
+ $data = old_xmlrpc_decode($value);
+
+ // Print out the catalogs we are going to sync
+ //FIXME: We should add catalog level access control
+ foreach ($data as $vars) {
+ $catalog_name = $vars[0];
+ print("<b>Reading Remote Catalog: $catalog_name</b> [$this->path]<br />\n");
+ }
+ }
+ else {
+ $error_msg = _("Error connecting to") . " " . $server . " " . _("Code") . ": " . $response->faultCode() . " " . _("Reason") . ": " . $response->faultString();
+ log_event($_SESSION['userdata']['username'],'xmlrpc',$error_msg);
+ echo "<p class=\"error\">$error_msg</p>";
+ return;
+ }
+
+ $f = new xmlrpcmsg('remote_song_query', array(new xmlrpcval( 'song', "string")) );
+ $response = $client->send($f);
+ $value = $response->value();
+
+ if ( !$response->faultCode() ) {
+ $data = old_xmlrpc_decode($value);
+ $this->update_remote_catalog($data,$this->path);
+ }
+ else {
+ $error_msg = _("Error connecting to") . " " . $server . " " . _("Code") . ": " . $response->faultCode() . " " . _("Reason") . ": " . $response->faultString();
+ log_event($_SESSION['userdata']['username'],'xmlrpc',$error_msg);
+ echo "<p class=\"error\">$error_msg</p>";
+ }
+
+ echo "<p>" . _("Completed updating remote catalog(s)") . ".</p><hr>\n";
+
+
+ } // get_remote_catalog
+
+ /*!
+ @function update_remote_catalog
+ @discussion actually updates from the remote data
+ */
+ function update_remote_catalog($songs,$root_path) {
+ global $settings, $dbh, $artists;
+
+
+ /*
+ We need to check the incomming songs
+ to see which ones need to be added
+ */
+ foreach ($songs as $song) {
+
+ // Prevent a timeout
+ set_time_limit(0);
+
+ $song = base64_decode($song);
+
+ $data = explode("::", $song);
+
+ $new_song->artist = $this->check_artist($data[0]);
+ $new_song->album = $this->check_album($data[1],$data[4]);
+ $new_song->title = $data[2];
+ $new_song->comment = $data[3];
+ $new_song->year = $data[4];
+ $new_song->bitrate = $data[5];
+ $new_song->rate = $data[6];
+ $new_song->mode = $data[7];
+ $new_song->size = $data[8];
+ $new_song->time = $data[9];
+ $new_song->track = $data[10];
+ $new_song->genre = $this->check_genre($data[11]);
+ $new_song->file = $root_path . "/play/index.php?song=" . $data[12] . "uid=$md5_ip";
+ $new_song->catalog = $this->id;
+
+ if (!$song_id = $this->check_remote_song($new_song->file)) {
+ $this->insert_remote_song($new_song);
+ }
+
+ } // foreach new Songs
+
+ //FIXME: Delete Songs that were not updated (gone)
+
+ // now delete invalid entries
+ $this->clean_albums();
+ $this->clean_stats();
+ $this->clean_artists();
+ $this->clean_flagged();
+
+ } // update_remote_catalog
+
+
+ /*!
+ @function clean_catalog
+ @discussion Cleans the Catalog of files that no longer exist grabs from $this->id or $id passed
+ Doesn't actually delete anything, disables errored files, and returns them in an array
+ @param $catalog_id=0 Take the ID of the catalog you want to clean
+ @param $action=0 Delete/Disable, default is disable
+ */
+ function clean_catalog($catalog_id=0,$action=0) {
+
+ /* Define the Arrays we will need */
+ $dead_files = array();
+
+ if (!$catalog_id) { $catalog_id = $this->id; }
+
+ echo "Cleaning the <b>[" . $this->name . "]</b> Catalog...<br /><br />";
+ flush();
+
+ /* Get all songs in this catalog */
+ $sql = "SELECT id,file FROM song WHERE catalog='$catalog_id' AND status='enabled'";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Recurse through files, put @ to prevent errors poping up */
+ while ($results = mysql_fetch_object($db_results)) {
+
+ /* Remove slashes while we are checking for its existance */
+ $results->file = stripslashes($results->file);
+
+ /* Stupid little cutesie thing */
+ $this->count++;
+ if ( !($this->count%conf('catalog_echo_count')) ) {
+ echo _("Checking") . " $this->count. . . . <br />\n";
+ flush();
+ } //echos song count
+
+ /* Also check the file information */
+ $file_info = @filesize($results->file);
+
+ /* If it errors somethings splated, or the files empty */
+ if (!file_exists($results->file) OR $file_info < 1) {
+
+ /* Add Error */
+ echo "<font class=\"error\">Error File Not Found or 0 Bytes: " . $results->file . "</font><br />";
+ flush();
+
+ /* Add this file to the list for removal from the db */
+ $dead_files[] = $results;
+ } //if error
+
+ } //while gettings songs
+
+ /* Incase there's been a snafo with a mount point on something
+ * don't actually delete from DB here, simply disable and list
+ */
+ if (count($dead_files)) {
+ foreach ($dead_files as $data) {
+
+ //FIXME: Until I fix the form, assume delete
+ //if ($action === 'delete_dead') {
+ $sql = "DELETE FROM song WHERE id='$data->id'";
+ //}
+ //
+ //else {
+ // $sql = "UPDATE song SET status='disabled' WHERE id='$data->id'";
+ //}
+
+ $db_results = mysql_query($sql, dbh());
+
+ /* DB Error occured */
+ if (!$db_results) {
+ /* Add Error */
+ } //if error
+
+ } //end foreach
+
+ } // end if dead files
+
+ /* Step two find orphaned Arists/Albums
+ * This finds artists and albums that no
+ * longer have any songs associated with them
+ */
+ $this->clean_albums();
+ $this->clean_artists();
+ $this->clean_stats();
+ $this->clean_playlists();
+ $this->clean_flagged();
+
+ /* Return dead files, so they can be listed */
+ echo "<b>" . _("Catalog Clean Done") . " [" . count($dead_files) . "] " . _("files removed") . "</b><br />\n";
+ flush();
+ return $dead_files;
+
+ } //clean_catalog
+
+
+ /*!
+ @function clean_albums
+ @discussion This function cleans out unused albums
+ @param $this->id Depends on the current object
+ */
+ function clean_albums() {
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",mysql_get_server_info())) {
+ $sql = "SELECT album.id FROM album LEFT JOIN song ON song.album = album.id WHERE song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+
+ $sql = "DELETE FROM album WHERE id='$dead[0]'";
+ $db_results = mysql_query($sql,dbh());
+ }
+ return true;
+ }
+
+ /* Do a complex delete to get albums where there are no songs */
+ $sql = "DELETE FROM album USING album LEFT JOIN song ON song.album = album.id WHERE song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ } //clean_albums
+
+ /*!
+ @function clean_flagged
+ @discussion This functions cleans ou unused flagged items
+ */
+ function clean_flagged() {
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",mysql_get_server_info())) {
+ $sql = "SELECT flagged.id FROM flagged LEFT JOIN song ON song.id=flagged.song WHERE song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+ $sql = "DELETE FROM flagged WHERE id='$dead[0]'";
+ $db_results = mysql_query($sql, dbh());
+ }
+ return true;
+ }
+
+ /* Do a complex delete to get flagged items where the songs are now gone */
+ $sql = "DELETE FROM flagged USING flagged LEFT JOIN song ON song.id = flagged.song WHERE song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ } // clean_flagged
+
+
+ /*!
+ @function clean_artists
+ @discussion This function cleans out unused artists
+ @param $this->id Depends on the current object
+ */
+ function clean_artists() {
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",mysql_get_server_info())) {
+ $sql = "SELECT artist.id FROM artist LEFT JOIN song ON song.artist = artist.id WHERE song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+
+ $sql = "DELETE FROM artist WHERE id='$dead[0]'";
+ $db_results = mysql_query($sql,dbh());
+ }
+ return true;
+ }
+
+
+ /* Do a complex delete to get artists where there are no songs */
+ $sql = "DELETE FROM artist USING artist LEFT JOIN song ON song.artist = artist.id WHERE song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ } //clean_artists
+
+ /*
+ @function clean_playlists
+ @discussion cleans out dead files from playlists
+ @param $this->id depends on the current object
+ */
+ function clean_playlists() {
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",mysql_get_server_infO())) {
+ $sql = "SELECT playlist_data.song FROM playlist_data LEFT JOIN song ON song.id = playlist_data.song WHERE song.file IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+ $sql = "DELETE FROM playlist_data WHERE song='$dead[0]'";
+ $db_results = mysql_query($sql, dbh());
+ }
+ return true;
+ }
+
+ /* Do a complex delete to get playlist songs where there are no songs */
+ $sql = "DELETE FROM playlist_data USING playlist_data LEFT JOIN song ON song.id = playlist_data.song WHERE song.file IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ } // clean_playlists
+
+ /*!
+ @function clean_stats
+ @discussion This functions removes stats for songs/albums that no longer exist
+ @param $catalog_id The ID of the catalog to clean
+ */
+ function clean_stats() {
+
+ $version = mysql_get_server_info();
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",$version)) {
+ $sql = "SELECT object_count.id FROM object_count LEFT JOIN song ON song.id = object_count.object_id WHERE object_type='song' AND song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+
+ $sql = "DELETE FROM object_count WHERE id='$dead[0]'";
+ $db_results = mysql_query($sql,dbh());
+ }
+
+ }
+ // We assume this will be 4.0+
+ else {
+ /* Crazy SQL Mojo to remove stats where there are no songs */
+ $sql = "DELETE FROM object_count USING object_count LEFT JOIN song ON song.id=object_count.object_id WHERE object_type='song' AND song.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",$version)) {
+ $sql = "SELECT object_count.id FROM object_count LEFT JOIN album ON album.id = object_count.object_id WHERE object_type='album' AND album.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+
+ $sql = "DELETE FROM object_count WHERE id='$dead[0]'";
+ $db_results = mysql_query($sql,dbh());
+ }
+ }
+ // We assume 4.0+ Here
+ else {
+ /* Crazy SQL Mojo to remove stats where there are no albums */
+ $sql = "DELETE FROM object_count USING object_count LEFT JOIN album ON album.id=object_count.object_id WHERE object_type='album' AND album.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+ /* Mysql 3.23 doesn't support our cool query so we have to do it a different way */
+ if (preg_match("/^3\./",$version)) {
+ $sql = "SELECT object_count.id FROM object_count LEFT JOIN artist ON artist.id = object_count.object_id WHERE object_type='artist' AND artist.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_row($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $dead) {
+
+ $sql = "DELETE FROM object_count WHERE id='$dead[0]'";
+ $db_results = mysql_query($sql,dbh());
+ }
+ }
+ // We assume 4.0+ here
+ else {
+ /* Crazy SQL Mojo to remove stats where ther are no artists */
+ $sql = "DELETE FROM object_count USING object_count LEFT JOIN artist ON artist.id=object_count.object_id WHERE object_type='artist' AND artist.id IS NULL";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+
+ } // clean_stats
+
+
+ /*!
+ @function verify_catalog
+ @discussion This function compares the DB's information with the ID3 tags
+ @param $catalog_id The ID of the catalog to compare
+ */
+ function verify_catalog($catalog_id=0,$gather_type=0) {
+
+ /* Create and empty song for us to use */
+ $total_updated = 0;
+
+ /* Set it to this if they don't pass anything */
+ if (!$catalog_id) {
+ $catalog_id = $this->id;
+ }
+
+ /* First get the filenames for the catalog */
+ $sql = "SELECT id FROM song WHERE catalog='$catalog_id' ORDER BY id";
+ $db_results = mysql_query($sql, dbh());
+ $number = mysql_num_rows($db_results);
+
+ echo _("Updating the") . " <b>[ $this->name ]</b> " . _("Catalog") . "<br />\n";
+ echo $number . " " . _("songs found checking tag information.") . "<br /><br />\n\n";
+ flush();
+
+ /* Magical Fix so we don't run out of time */
+ set_time_limit(0);
+
+ /* Recurse through this catalogs files
+ * and get the id3 tage information,
+ * if it's not blank, and different in
+ * in the file then update!
+ */
+ while ($results = mysql_fetch_object($db_results)) {
+
+ $song = new Song($results->id);
+
+ if (is_readable($song->file)) {
+ unset($skip);
+
+ /* If they have specified fast_update check the file
+ filemtime to make sure the file has actually
+ changed
+ */
+ if ($gather_type === "fast_update") {
+ $file_date = filemtime($song->file);
+ if ($file_date < $this->last_update) { $skip = true; }
+ } // if gather_type
+
+ if ($song->update_time >= $this->last_update) {
+ $skip = true;
+ $song->update_utime($song->id,time()+86400);
+ }
+
+ // if the file hasn't been modified since the last_update
+ if (!$skip) {
+
+ $info = $this->update_song_from_tags($song);
+ $album_id = $song->album;
+ if ($info['change']) {
+ echo "<dl>\n\t<li>";
+ echo "<b>$song->file " . _("Updated") . "</b>\n";
+ echo $info['text'];
+ /* If we aren't doing a fast update re-gather album art */
+ if ($gather_type !== "fast_update" AND !isset($searched_albums[$album_id])) {
+ $album = new Album($song->album);
+ $searched_albums[$album_id] = 1;
+ $found = $album->get_art();
+ unset($album);
+ if ($found) { $is_found = _(" FOUND"); }
+ echo "<br /><b>" . _("Searching for new Album Art") . ". . .$is_found</b><br />\n";
+ unset($found,$is_found);
+ }
+ elseif (isset($searched_albums[$album_id])) {
+ echo "<br /><b>" . _("Album Art Already Found") . ". . .</b><br />\n";
+ }
+ echo "\t</li>\n</dl>\n<hr align=\"left\" width=\"50%\" />\n";
+ flush();
+ $total_updated++;
+ }
+
+ unset($info);
+
+ } // end skip
+
+ /* Stupid little cutesie thing */
+ $this->count++;
+ if ( !($this->count%conf('catalog_echo_count')) ) {
+ echo "Checked $this->count. . . . <br />\n";
+ flush();
+ } //echos song count
+
+ } // end if file exists
+
+ else {
+ echo "<dl>\n <li>";
+ echo "<b>$song->file does not exist or is not readable</b>\n";
+ echo " </li>\n</dl>\n<hr align=\"left\" width=\"50%\" />\n";
+ // Should we remove it from catalog?
+ }
+
+
+ } //end foreach
+
+
+ /* After we have updated all the songs with the new information clear any empty albums/artists */
+ $this->clean_albums();
+ $this->clean_artists();
+ $this->clean_stats();
+ $this->clean_flagged();
+
+ // Update the last_update
+ $this->update_last_update();
+
+ echo "Update Finished. Checked $this->count. $total_updated songs updated.<br /><br />";
+
+ } //verify_catalog
+
+
+ /*!
+ @function create_catalog_entry
+ @discussion Creates a new catalog from path and type
+ @param $path The root path for this catalog
+ @param $name The name of the new catalog
+ */
+ function create_catalog_entry($path,$name,$id3cmd=0,$ren=0,$sort=0, $type='local') {
+
+ // Current time
+ $date = time();
+
+ $path = sql_escape($path);
+ $name = sql_escape($name);
+
+ if($id3cmd && $ren && $sort) {
+ $sql = "INSERT INTO catalog (path,name,last_update,id3_set_command,rename_pattern,sort_pattern,catalog_type) " .
+ " VALUES ('$path','$name','$date', '$id3cmd', '$ren', '$sort','$type')";
+ }
+ else {
+ $sql = "INSERT INTO catalog (path,name,last_update) VALUES ('$path','$name','$date')";
+ }
+
+ $db_results = mysql_query($sql, dbh());
+ $catalog_id = mysql_insert_id(dbh());
+
+ return $catalog_id;
+
+ } //create_catalog_entry
+
+
+ /*!
+ @function check_catalog
+ @discussion Checks for the $path already in the catalog table
+ @param $path The root path for the catalog we are checking
+ */
+ function check_catalog($path) {
+
+ $path = sql_escape($path);
+
+ $sql = "SELECT id FROM catalog WHERE path='$path'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results->id;
+
+ } //check_catalog
+
+
+ /*!
+ @function check_artist
+ @discussion Takes $artist checks if there then return id else insert and return id
+ @param $artist The name of the artist
+ */
+ function check_artist($artist) {
+
+ // Only get the var ones.. less func calls
+ $cache_limit = conf('artist_cache_limit');
+
+ /* Clean up the artist */
+ $artist = trim($artist);
+ $artist = sql_escape($artist);
+
+
+ /* Ohh no the artist has lost it's mojo! */
+ if (!$artist) {
+ $artist = "Unknown (Orphaned)";
+ }
+
+ // Remove the prefix so we can sort it correctly
+ preg_match("/^(The\s|An\s|A\s)(.*)/i",$artist,$matches);
+
+ if (count($matches)) {
+ $artist = $matches[2];
+ $prefix = $matches[1];
+ }
+
+ // Check to see if we've seen this artist before
+ if (isset($this->artists[$artist])) {
+ return $this->artists[$artist];
+ } // if we've seen this artist before
+
+ /* Setup the checking sql statement */
+ $sql = "SELECT id FROM artist WHERE name LIKE '$artist' ";
+ $db_results = mysql_query($sql, dbh());
+
+ /* If it's found */
+ if ($r = mysql_fetch_object($db_results)) {
+ $artist_id = $r->id;
+ } //if found
+
+ /* If not found create */
+ else {
+
+ $sql = "INSERT INTO artist (name, prefix) VALUES ('$artist', '$prefix')";
+ $db_results = mysql_query($sql, dbh());
+ $artist_id = mysql_insert_id(dbh());
+
+
+ if (!$db_results) {
+ echo "Error Inserting Artist:$artist <br />";
+ flush();
+ }
+
+ } //not found
+
+ if ($cache_limit) {
+
+ $artist_count = count($this->artists);
+ if ($artist_count == $cache_limit) {
+ $this->artists = array_slice($this->artists,1);
+ }
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'cache',"Adding $artist with $artist_id to Cache",'ampache-catalog'); }
+ $array = array($artist => $artist_id);
+ $this->artists = array_merge($this->artists, $array);
+ unset($array);
+
+ } // if cache limit is on..
+
+ return $artist_id;
+
+ } //check_artist
+
+
+ /*!
+ @function check_album
+ @disucssion Takes $album and checks if there then return id else insert and return id
+ @param $album The name of the album
+ */
+ function check_album($album,$album_year=0) {
+
+ /* Clean up the album name */
+ $album = trim($album);
+ $album = sql_escape($album);
+ $album_year = intval($album_year);
+
+ // Set it once to reduce function calls
+ $cache_limit = conf('album_cache_limit');
+
+ /* Ohh no the album has lost it's mojo */
+ if (!$album) {
+ $album = "Unknown (Orphaned)";
+ }
+
+ // Remove the prefix so we can sort it correctly
+ preg_match("/^(The\s|An\s|A\s)(.*)/i",$album,$matches);
+
+ if (count($matches)) {
+ $album = $matches[2];
+ $prefix = $matches[1];
+ }
+
+ // Check to see if we've seen this album before
+ if (isset($this->albums[$album])) {
+ return $this->albums[$album];
+ }
+
+ /* Setup the Query */
+ $sql = "SELECT id FROM album WHERE name LIKE '$album'";
+ if ($album_year) { $sql .= " AND year='$album_year'"; }
+ $db_results = mysql_query($sql, dbh());
+
+ /* If it's found */
+ if ($r = mysql_fetch_object($db_results)) {
+ $album_id = $r->id;
+
+ } //if found
+
+ /* If not found create */
+ else {
+
+ $sql = "INSERT INTO album (name, prefix,year) VALUES ('$album', '$prefix','$album_year')";
+ $db_results = mysql_query($sql, dbh());
+ $album_id = mysql_insert_id(dbh());
+
+ if (!$db_results) {
+ echo "Error Inserting Album:$album <br />";
+ flush();
+ }
+
+ } //not found
+
+ if ($cache_limit > 0) {
+
+ $albums_count = count($this->albums);
+
+ if ($albums_count == $cache_limit) {
+ $this->albums = array_slice($this->albums,1);
+ }
+ $array = array($album => $album_id);
+ $this->albums = array_merge($this->albums,$array);
+ unset($array);
+
+ } // if cache limit is on..
+
+ return $album_id;
+
+ } //check_album
+
+
+ /*!
+ @function check_genre
+ @discussion Finds the Genre_id from the text name
+ @param $genre The name of the genre
+ */
+ function check_genre($genre) {
+
+ if (!$genre) {
+ return false;
+ }
+
+ if ($this->genres[$genre]) {
+ return $this->genres[$genre];
+ }
+
+ /* Look in the genre table */
+ $genre = sql_escape($genre);
+ $sql = "SELECT id FROM genre WHERE name LIKE '$genre'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ if (!$results->id) {
+ $sql = "INSERT INTO genre (name) VALUES ('$genre')";
+ $db_results = mysql_query($sql, dbh());
+ $results->id = mysql_insert_id(dbh());
+ }
+
+ $this->genres[$genre] = $results->id;
+
+ return $results->id;
+
+ } //check_genre
+
+
+ /*!
+ @function check_title
+ @discussion 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
+ */
+ function check_title($title,$file=0) {
+
+ if (strlen(trim($title)) < 1) {
+ preg_match("/.+\/(.*)\.....?$/",$file,$matches);
+ $title = sql_escape($matches[1]);
+ }
+
+ return $title;
+
+
+ } //check_title
+
+
+ /*!
+ @function insert_local_song
+ @discussion 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
+ @param $file The file name we are adding (full path)
+ @param $file_info The information of the file, size etc taken from stat()
+ */
+ function insert_local_song($file,$file_info) {
+
+ /* Create the Audioinfo object and get info */
+ $audio_info = new Audioinfo();
+ $song_obj = new Song();
+ $results = $audio_info->Info($file);
+ $results['file'] = $file;
+
+ $key = get_tag_type($results);
+
+ /* Fill Empty info from filename/path */
+ $results = $song_obj->fill_info($results,$this->sort_pattern . "/" . $this->rename_pattern,$this->id,$key);
+
+ /* Clean Up the tags */
+ $results = clean_tag_info($results,$key,$file);
+
+ /* Set the vars here... so we don't have to do the '" . $blah['asd'] . "' */
+ $title = sql_escape($results['title']);
+ $artist = $results['artist'];
+ $album = $results['album'];
+ $genre = $results['genre'];
+ $bitrate = $results['bitrate'];
+ $rate = $results['rate'];
+ $mode = $results['mode'];
+ $size = $results['size'];
+ $song_time = $results['time'];
+ $track = $results['track'];
+ $year = $results['year'];
+ $comment = $results['comment'];
+ $current_time = time();
+
+ /*
+ * 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 = $this->check_artist($artist);
+ $genre_id = $this->check_genre($genre);
+ $album_id = $this->check_album($album,$year);
+ $title = $this->check_title($title,$file);
+ $add_file = sql_escape($results['file']);
+
+ $sql = "INSERT INTO song (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,genre,addition_time,year,comment)" .
+ " VALUES ('$add_file','$this->id','$album_id','$artist_id','$title','$bitrate','$rate','$mode','$size','$song_time','$track','$genre_id','$current_time','$year','$comment')";
+
+ $db_results = mysql_query($sql, dbh());
+
+ if (!$db_results) {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'insert',"Unable to insert $file -- $sql",'ampache-catalog'); }
+ echo "<span style=\"color: #F00;\">Error Adding $file </span><br />$sql<br />";
+ flush();
+ }
+
+ /* Clear Variables */
+ unset($results,$audio_info,$song_obj);
+
+ } // insert_local_song
+
+ /*!
+ @function insert_remote_song
+ @discussion takes the information gotten from XML-RPC and
+ inserts it into the local database. The filename
+ ends up being the url.
+ */
+ function insert_remote_song($song) {
+
+ $url = sql_escape($song->file);
+ $title = $this->check_title($song->title);
+ $title = sql_escape($title);
+ $comment = sql_escape($song->comment);
+ $current_time = time();
+
+ $sql = "INSERT INTO song (file,catalog,album,artist,title,bitrate,rate,mode,size,time,track,genre,addition_time,year,comment)" .
+ " VALUES ('$url','$song->catalog','$song->album','$song->artist','$title','$song->bitrate','$song->rate','$song->mode','$song->size','$song->time','$song->track','$song->genre','$current_time','$song->year','$comment')";
+ $db_results = mysql_query($sql, dbh());
+
+ if (!$db_results) {
+ if (conf('debug')) { log_event($_SESSION['userdata']['username'],'insert',"Unable to Add Remote $url -- $sql",'ampache-catalog'); }
+ echo "<span style=\"color: #FOO;\">Error Adding Remote $url </span><br />$sql<br />\n";
+ flush();
+ }
+
+ } // insert_remote_song
+
+
+ /*!
+ @function check_remote_song
+ @discussion checks to see if a remote song exists in the database or not
+ if it find a song it returns the UID
+ */
+ function check_remote_song($url) {
+
+ $url = sql_escape($url);
+
+ $sql = "SELECT id FROM song WHERE file='$url'";
+ $db_results = mysql_query($sql, dbh());
+
+ if ($r = mysql_fetch_object($db_results)) {
+ return $r->id;
+ }
+
+ return false;
+
+ } // check_remote_song
+
+
+ /*!
+ @function check_local_mp3
+ @discussion Checks the song to see if it's there already returns true if found, false if not
+ @param $full_file The full file name that we are checking
+ @param $gather_type=0 If we need to check id3 tags or not
+ */
+ function check_local_mp3($full_file, $gather_type=0) {
+
+ if ($gather_type == 'fast_add') {
+ $file_date = filemtime($full_file);
+ if ($file_date < $this->last_add) {
+ return true;
+ }
+ }
+
+ $full_file = sql_escape($full_file);
+
+ $sql = "SELECT id FROM song WHERE file = '$full_file'";
+ $db_results = mysql_query($sql, dbh());
+
+ //If it's found then return true
+ if (@mysql_fetch_row($db_results)) {
+ return true;
+ }
+
+ return false;
+
+ } //check_local_mp3
+
+ /*!
+ @function import_m3u
+ @discussion this takes m3u filename and then attempts
+ to create a Public Playlist based on the filenames
+ listed in the m3u
+ */
+ function import_m3u($filename) {
+
+ $m3u_handle = @fopen($filename,'r');
+
+ $data = @fread($m3u_handle,filesize($filename));
+
+ $results = explode("\n",$data);
+
+ foreach ($results as $value) {
+ // Remove extra whitespace
+ $value = trim($value);
+ if (preg_match("/\.[A-Za-z0-9]{3}$/",$value)) {
+ $file[0] = str_replace("/","\\",$value);
+ $file[1] = str_replace("\\","/",$value);
+ /* Search for this filename, cause it's a audio file */
+ $sql = "SELECT id FROM song WHERE file LIKE '%" . sql_escape($file[0]) . "' OR file LIKE '%" . sql_escape($file[1]) . "'";
+ $db_results = mysql_query($sql, dbh());
+ $song_id = mysql_result($db_results,'id');
+ if ($song_id) { $songs[] = $song_id; }
+ } // if it's a file
+
+ } // end foreach line
+
+ if (conf('debug')) { log_event($GLOBALS['user']->username,' m3u_parse ',"Parsing $filename - Found: " . count($songs) . " Songs"); }
+
+ if (count($songs)) {
+ $playlist = new Playlist();
+ $playlist_name = "M3U - " . basename($filename);
+ $playlist->create_playlist($playlist_name,$GLOBALS['user']->id,'public');
+ $playlist->add_songs($songs);
+ return true;
+ }
+
+ return false;
+
+ } // import_m3u
+
+ /*!
+ @function delete_catalog
+ @discussion Deletes the catalog and everything assoicated with it
+ assumes $this
+ */
+ function delete_catalog() {
+
+ // Do some crazyness to delete all the songs in this catalog
+ // from playlists...
+ $sql = "SELECT playlist_data.song FROM song,playlist_data,catalog WHERE catalog.id=song.catalog AND playlist_data.song=song.id AND catalog.id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = $r;
+ }
+
+ foreach ($results as $r) {
+ // Clear Playlist Data
+ $sql = "DELETE FROM playlist_data WHERE song='$r->song'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // End Foreach
+
+ // First remove the songs in this catalog
+ $sql = "DELETE FROM song WHERE catalog = '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ // Next Remove the Catalog Entry it's self
+ $sql = "DELETE FROM catalog WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ // Run the Aritst/Album Cleaners...
+ $this->clean_albums();
+ $this->clean_artists();
+ $this->clean_stats();
+ $this->clean_playlists();
+ $this->clean_flagged();
+
+ } // delete_catalog
+
+
+ /*!
+ @function remove_songs
+ @discussion removes all songs sent in $songs array from the
+ database, it doesn't actually delete them...
+ */
+ function remove_songs($songs) {
+
+ foreach($songs as $song) {
+ $sql = "DELETE FROM song WHERE id = '$song'";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+ } // remove_songs
+
+} //end of catalog class
+
+?>
diff --git a/modules/class/error.php b/modules/class/error.php
new file mode 100644
index 00000000..9283e29d
--- /dev/null
+++ b/modules/class/error.php
@@ -0,0 +1,94 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2005 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header Error handler requires error_results() function
+
+*/
+
+
+class Error {
+
+ //Basic Componets
+ var $error_state=0;
+
+ /* Generated values */
+ var $errors = array();
+
+ /*!
+ @function error
+ @discussion this is the constructor for the error class
+ */
+ function Error() {
+
+ return true;
+
+ } //constructor
+
+ /*!
+ @function add_error
+ @discussion adds an error to the static array stored in
+ error_results()
+ */
+ function add_error($name,$description) {
+
+ $array = array($name=>$description);
+
+ error_results($array);
+ $this->error_state = 1;
+
+ return true;
+
+ } // add_error
+
+
+ /*!
+ @function has_error
+ @discussion returns true if the name given has an error,
+ false if it doesn't
+ */
+ function has_error($name) {
+
+ $results = error_results($name);
+
+ if (!empty($results)) {
+ return true;
+ }
+
+ return false;
+
+ } // has_error
+
+ /*!
+ @function print_error
+ @discussion prints out the error for a name if it exists
+ */
+ function print_error($name) {
+
+ if ($this->has_error($name)) {
+ echo "<div class=\"fatalerror\">" . error_results($name) . "</div>\n";
+ }
+
+ } // print_error
+
+} //end error class
+?>
diff --git a/modules/class/playlist.php b/modules/class/playlist.php
new file mode 100644
index 00000000..130537af
--- /dev/null
+++ b/modules/class/playlist.php
@@ -0,0 +1,366 @@
+<?
+/*
+
+ Copyright (c) 2001 - 2005 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+*/
+/*!
+ @header Playlist Class
+ This class handles all actual work in regards to playlists.
+*/
+
+class Playlist {
+
+ // Variables from DB
+ var $id;
+ var $name;
+ var $owner;
+ var $type;
+ var $time;
+ var $items;
+
+ /*!
+ @function Playlist
+ @discussion Playlist class
+ @param $playlist_id The ID of the playlist
+ */
+ function Playlist($playlist_id = 0) {
+
+ /* If we have an id then do something */
+ if ($playlist_id) {
+ // Assign id
+ $this->id = $playlist_id;
+
+ // Get the information from the db
+ $this->refresh_object();
+ }
+
+ }
+
+
+
+ /*!
+ @function refresh_object
+ @discussion Reads playlist information from the db and updates the Playlist object with it
+ */
+ function refresh_object() {
+
+ $dbh = dbh();
+
+ if ($this->id) {
+ $sql = "SELECT name, owner, type, date FROM playlist" .
+ " WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, $dbh);
+
+ if ($r = mysql_fetch_object($db_results)) {
+ $this->name = $r->name;
+ $this->owner = $r->owner;
+ $this->type = $r->type;
+ $this->time = $r->date;
+ $this->items = array();
+
+ // Fetch playlist items
+ $sql = "SELECT song, track FROM playlist_data" .
+ " WHERE playlist = '$this->id'" .
+ " ORDER BY track";
+ $db_results = mysql_query($sql, $dbh);
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $this->items[] = array("song_id" => $r->song, "track" => $r->track);
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function create_playlist
+ @discussion Creates an empty playlist, given a name, owner_id, and type.
+ */
+ function create_playlist($name, $owner_id, $type) {
+
+ $dbh = dbh();
+
+ if (isset($name) && isset($owner_id) && isset($type) && $this->check_type($type)) {
+ $name = sql_escape($name);
+ $sql = "INSERT INTO playlist" .
+ " (name, owner, type)" .
+ " VALUES ('$name', '$owner_id', '$type')";
+ $db_results = mysql_query($sql, $dbh);
+ if ($this->id = mysql_insert_id($dbh)) {
+ $this->refresh_object();
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function delete
+ @discussion Deletes the playlist.
+ */
+ function delete() {
+
+ $dbh = dbh();
+
+ if ($this->id) {
+ $sql = "DELETE FROM playlist_data" .
+ " WHERE playlist = '$this->id'";
+ $db_results = mysql_query($sql, $dbh);
+
+ $sql = "DELETE FROM playlist" .
+ " WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, $dbh);
+
+ // Clean up this object
+ foreach (get_object_vars($this) as $var) {
+ unset($var);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function update_track_numbers
+ @discussion Reads an array of song_ids and track numbers to update
+ */
+ function update_track_numbers($changes) {
+
+ $dbh = dbh();
+
+ if ($this->id && isset($changes) && is_array($changes)) {
+ foreach ($changes as $change) {
+ // Check for valid song_id
+ $sql = "SELECT count(*) FROM song WHERE id = '" . $change['song_id'] . "'";
+ $db_results = mysql_query($sql, $dbh);
+ $r = mysql_fetch_row($db_results);
+ if ($r[0] == 1) {
+ $sql = "UPDATE playlist_data SET" .
+ " track = '" . $change['track'] . "'" .
+ " WHERE playlist = '$this->id'".
+ " AND song = '" . $change['song_id'] . "'";
+ $db_results = mysql_query($sql, $dbh);
+ }
+ }
+
+ // Refresh the playlist object
+ $this->refresh_object();
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function add_songs
+ @discussion Reads an array of song_ids to add to the playlist
+ */
+ function add_songs($song_ids) {
+
+ $dbh = dbh();
+
+ if ($this->id && isset($song_ids) && is_array($song_ids)) {
+ foreach ($song_ids as $song_id) {
+ $song = new Song($song_id);
+ if (isset($song->id)) {
+ $sql = "INSERT INTO playlist_data" .
+ " (playlist, song, track)" .
+ " VALUES ('$this->id', '$song->id', '$song->track')";
+ $db_results = mysql_query($sql, $dbh);
+ }
+ }
+
+ // Refresh the playlist object
+ $this->refresh_object();
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function remove_songs
+ @discussion Reads an array of song_ids to remove from the playlist
+ */
+ function remove_songs($song_ids) {
+
+ $dbh = dbh();
+
+ if ($this->id && isset($song_ids) && is_array($song_ids)) {
+ foreach ($song_ids as $song_id) {
+ $sql = "DELETE FROM playlist_data" .
+ " WHERE song = '$song_id'" .
+ " AND playlist = '$this->id'";
+ $db_results = mysql_query($sql, $dbh);
+ }
+
+ // Refresh the playlist object
+ $this->refresh_object();
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function check_type
+ @discussion Checks for a valid playlist type
+ */
+ function check_type($type) {
+
+ if (isset($type)) {
+ if ($type === 'public' || $type === 'private') {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function update_type
+ @discussion Updates the playlist type
+ */
+ function update_type($type) {
+
+ $dbh = dbh();
+
+ if ($this->id && isset($type) && $this->check_type($type)) {
+ $sql = "UPDATE playlist SET type = '$type'" .
+ " WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, $dbh);
+
+ // Refresh the playlist object
+ $this->refresh_object();
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function update_name
+ @discussion Updates the playlist name
+ */
+ function update_name($name) {
+
+ $dbh = dbh();
+
+ if ($this->id && isset($name)) {
+ $name = sql_escape($name);
+ $sql = "UPDATE playlist SET name = '$name'" .
+ " WHERE id = '$this->id'";
+ $db_results = mysql_query($sql, $dbh);
+
+ // Refresh the playlist object
+ $this->refresh_object();
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+ }
+
+
+ /*!
+ @function get_songs
+ @discussion Returns an array of song_ids for the playlist
+ */
+ function get_songs() {
+
+ $song_ids = array();
+
+ if ($this->id && is_array($this->items)) {
+ foreach ($this->items as $item) {
+ $song_ids[] = $item['song_id'];
+ }
+ }
+
+ return $song_ids;
+
+ } // get_songs
+
+ /*!
+ @function get_random_songs
+ @discussion gets a random set of the songs in this
+ playlist
+ */
+ function get_random_songs() {
+
+ $sql = "SELECT COUNT(song) FROM playlist_data WHERE playlist = '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $total_songs = mysql_fetch_row($db_results);
+
+ $limit = rand(1,$total_songs[0]);
+
+ // Fetch playlist items
+ $sql = "SELECT song, track FROM playlist_data" .
+ " WHERE playlist = '$this->id'" .
+ " ORDER BY RAND() LIMIT $limit";
+ $db_results = mysql_query($sql, dbh());
+ while ($r = mysql_fetch_object($db_results)) {
+ $song_ids[] = $r->song;
+ }
+
+ return $song_ids;
+ } // get_random_songs
+
+ /*!
+ @function show_import
+ @discussion shows the import from file template
+ */
+ function show_import() {
+
+ require (conf('prefix') . "/templates/show_import_playlist.inc.php");
+
+ } // show_import
+
+
+} //end of playlist class
+
+?>
diff --git a/modules/class/song.php b/modules/class/song.php
new file mode 100644
index 00000000..f42f55a8
--- /dev/null
+++ b/modules/class/song.php
@@ -0,0 +1,657 @@
+<?
+/*
+
+ Copyright (c) 2004 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header Song Class
+*/
+
+class Song {
+
+ /* Variables from DB */
+ var $id;
+ var $file;
+ var $album;
+ var $artist;
+ var $title;
+ var $year;
+ var $comment;
+ var $bitrate;
+ var $rate;
+ var $mode;
+ var $size;
+ var $time;
+ var $track;
+ var $genre;
+ var $type;
+ var $mime;
+ var $played;
+ var $addition_time;
+ var $update_time;
+
+ /*!
+ @function Song
+ @discussion Song class, for modifing a song.
+ @param $song_id The ID of the song
+ */
+ function Song($song_id = 0) {
+
+ /* If we have passed an id then do something */
+ if ($song_id) {
+
+ /* Assign id for use in get_info() */
+ $this->id = $song_id;
+
+ /* Get the information from the db */
+ if ($info = $this->get_info()) {
+
+ /* Assign Vars */
+ $this->file = $info->file;
+ $this->album = $info->album;
+ $this->artist = $info->artist;
+ $this->title = $info->title;
+ $this->comment = $info->comment;
+ $this->year = $info->year;
+ $this->bitrate = $info->bitrate;
+ $this->rate = $info->rate;
+ $this->mode = $info->mode;
+ $this->size = $info->size;
+ $this->time = $info->time;
+ $this->track = $info->track;
+ $this->genre = $info->genre;
+ $this->addition_time = $info->addition_time;
+ $this->catalog = $info->catalog;
+ $this->played = $info->played;
+ $this->update_time = $info->update_time;
+ $this->flagid = $info->flagid;
+ $this->flaguser = $info->flaguser;
+ $this->flagtype = $info->flagtype;
+ $this->flagcomment = $info->flagcomment;
+ $this->status = $info->status;
+
+ // Format the Type of the song
+ $this->format_type();
+ }
+
+ }
+
+ } //constructor
+
+
+ /*!
+ @function get_info
+ @discussion get's the vars for $this out of the database
+ @param $this->id Taken from the object
+ */
+ function get_info() {
+
+ /* Grab the basic information from the catalog and return it */
+ $sql = "SELECT song.id,file,catalog,album,song.comment,year,artist,".
+ "title,bitrate,rate,mode,size,time,track,genre,played,status,update_time,".
+ "addition_time,flagged.id as flagid,flagged.user as flaguser,flagged.type ".
+ "as flagtype,flagged.date as flagdate,flagged.comment as flagcomment FROM ".
+ "song LEFT JOIN flagged ON song.id = flagged.song WHERE song.id = '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_object($db_results);
+
+ return $results;
+
+ } //get_info
+
+ /*!
+ @function format_type
+ @discussion gets the type of song we are trying to
+ play, used to set mime headers and to trick
+ players into playing them correctly
+ */
+ function format_type() {
+
+ preg_match('/\.([A-Za-z0-9]+)$/', $this->file,$results);
+
+ $this->type = $results[1];
+
+ switch ($this->type) {
+ case "spx":
+ case "ogg":
+ $this->mime = "application/x-ogg";
+ break;
+ case "wma":
+ case "WMA":
+ case "asf":
+ $this->mime = "audio/x-ms-wma";
+ break;
+ case "mp3":
+ case "mpeg3":
+ $this->mime = "audio/mpeg";
+ break;
+ case "rm":
+ $this->mime = "audio/x-realaudio";
+ break;
+ case "flac";
+ $this->mime = "audio/x-flac";
+ break;
+ case 'aac':
+ case 'mp4':
+ case 'm4a':
+ $this->mime = "audio/mp4";
+ break;
+ case 'mpc':
+ $this->mime = "audio/x-musepack";
+ break;
+ default:
+ $this->mime = "audio/mpeg";
+ break;
+ }
+
+ } // get_type
+ /*!
+ @function get_album_songs
+ @discussion gets an array of song objects based on album
+ */
+ function get_album_songs($album_id) {
+
+ $sql = "SELECT id FROM song WHERE album='$album_id'";
+ $db_results = mysql_query($sql, libglue_param(libglue_param('dbh_name')));
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = new Song($r->id);
+ }
+
+ return $results;
+
+ } // get_album_songs
+
+ /*!
+ @function get_album_name
+ @discussion gets the name of $this->album
+ */
+ function get_album_name() {
+
+ $sql = "SELECT name,prefix FROM album WHERE id='$this->album'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_array($db_results);
+
+ if ($results['prefix']) {
+ return $results['prefix'] . " " .$results['name'];
+ }
+ else {
+ return $results['name'];
+ }
+
+ } // get_album_name
+
+ /*!
+ @function get_artist_name
+ @discussion gets the name of $this->artist
+ */
+ function get_artist_name() {
+
+ $sql = "SELECT name,prefix FROM artist WHERE id='$this->artist'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_array($db_results);
+
+ if ($results['prefix']) {
+ return $results['prefix'] . " " . $results['name'];
+ }
+ else {
+ return $results['name'];
+ }
+
+ } // get_album_name
+
+ /*!
+ @function get_genre_name
+ @discussion gets the name of the genre
+ */
+ function get_genre_name() {
+
+ $sql = "SELECT name FROM genre WHERE id='$this->genre'";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = mysql_fetch_array($db_results);
+
+ return $results['name'];
+
+ } // get_genre_name
+ /*!
+ @function compare_song_information
+ @discussion 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.
+ @param $song The origional song object
+ @param $new_song The new version of the song
+ */
+ function compare_song_information($song,$new_song) {
+
+ if ($song->title == "No Title Found") { $song->title = false; }
+
+
+ if (trim($song->title) != trim($new_song->title) && strlen($new_song->title) > 0) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Title") . " [$song->title] " . _("updated to") . " [$new_song->title]\n";
+ } // if title
+ if ($song->bitrate != $new_song->bitrate) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Bitrate") . " [$song->bitrate] " . _("updated to") . " [$new_song->bitrate]\n";
+ } // if bitrate
+ if ($song->rate != $new_song->rate) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Rate") . " [$song->rate] " . _("updated to") . " [$new_song->rate]\n";
+ } // if rate
+ if ($song->mode != $new_song->mode) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Mode") . " [$song->mode] " . _("updated to") . " [$new_song->mode]\n";
+ } // if mode
+ if ($song->time != $new_song->time) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Time") . " [$song->time] " . _("updated to") . " [$new_song->time]\n";
+ } // if time
+ if ($song->track != $new_song->track) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Track") . " [$song->track] " . _("updated to") . " [$new_song->track]\n";
+ } // if track
+ if ($song->size != $new_song->size) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Filesize") . " [$song->size] " . _("updated to") . " [$new_song->size]\n";
+ } // if artist
+ if ($song->artist != $new_song->artist) {
+ $array['change'] = true;
+ $name = $song->get_artist_name();
+ $array['text'] .= "<br />" . _("Artist") . " [$name] " . _("updated to") . " [$new_song->f_artist]\n";
+ } // if artist
+ if ($song->album != $new_song->album) {
+ $array['change'] = true;
+ $name = $song->get_album_name() . " - " . $song->year;
+ $array['text'] .= "<br />" . _("Album") . " [$name] " . _("updated to") . " [$new_song->f_album]\n";
+ } // if album
+ if ($song->year != $new_song->year) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Year") . " [$song->year] " . _("updated to") . " [$new_song->year]\n";
+ } // if year
+ if (trim($song->comment) != trim($new_song->comment)) {
+ $array['change'] = true;
+ $array['text'] .= "<br />" . _("Comment") . " [$song->comment] " . _("updated to") . " [$new_song->comment]\n";
+ } // if comment
+ if ($song->genre != $new_song->genre) {
+ $array['change'] = true;
+ $name = $song->get_genre_name();
+ $array['text'] .= "<br />" . _("Genre") . " [$name] " . _("updated to") . " [$new_song->f_genre]\n";
+ } // if genre
+
+ return $array;
+
+ } // compare_song_information
+
+ /*!
+ @function update_song
+ @discussion 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
+ @param $song_id The id of the song we are updating
+ @param $new_song A object with the new song params
+ */
+ function update_song($song_id, $new_song) {
+
+ $this->update_title($new_song->title,$song_id);
+ $this->update_bitrate($new_song->bitrate,$song_id);
+ $this->update_rate($new_song->rate,$song_id);
+ $this->update_mode($new_song->mode,$song_id);
+ $this->update_size($new_song->size,$song_id);
+ $this->update_time($new_song->time,$song_id);
+ $this->update_track($new_song->track,$song_id);
+ $this->update_artist($new_song->artist,$song_id);
+ $this->update_genre($new_song->genre,$song_id);
+ $this->update_album($new_song->album,$song_id);
+ $this->update_year($new_song->year,$song_id);
+ $this->update_comment($new_song->comment,$song_id);
+ $this->update_played('false',$song_id);
+ $this->update_utime($song_id);
+
+ } // update_song
+
+ /*!
+ @function update_year
+ @discussion update the year tag
+ */
+ function update_year($new_year,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('year',$new_year,$song_id);
+ }
+ } // update_year
+
+ /*!
+ @function update_comment
+ @discussion updates the comment field
+ */
+ function update_comment($new_comment,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('comment',$new_comment,$song_id);
+ }
+ } // update_comment
+
+ /*!
+ @function update_title
+ @discussion updates the title field
+ */
+ function update_title($new_title,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('title',$new_title,$song_id);
+ }
+ } // update_title
+
+ /*!
+ @function update_bitrate
+ @discussion updates the bitrate field
+ */
+ function update_bitrate($new_bitrate,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('bitrate',$new_bitrate,$song_id);
+ }
+
+ } // update_bitrate
+
+ /*!
+ @function update_rate
+ @discussion updates the rate field
+ */
+ function update_rate($new_rate,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('rate',$new_rate,$song_id);
+ }
+
+ } // update_rate
+
+ /*!
+ @function update_mode
+ @discussion updates the mode field
+ */
+ function update_mode($new_mode,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('mode',$new_mode,$song_id);
+ }
+
+ } // update_mode
+
+ /*!
+ @function update_size
+ @discussion updates the size field
+ */
+ function update_size($new_size,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('size',$new_size,$song_id);
+ }
+
+ } // update_size
+
+ /*!
+ @function update_time
+ @discussion updates the time field
+ */
+ function update_time($new_time,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('time',$new_time,$song_id);
+ }
+
+ } // update_time
+
+ /*!
+ @function update_track
+ @discussion this updates the track field
+ */
+ function update_track($new_track,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('track',$new_track,$song_id);
+ }
+
+ } // update_track
+
+ /*!
+ @function update_artist
+ @discussion updates the artist field
+ */
+ function update_artist($new_artist,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('artist',$new_artist,$song_id);
+ }
+
+ } // update_artist
+
+ /*!
+ @function update_genre
+ @discussion updates the genre field
+ */
+ function update_genre($new_genre,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('genre',$new_genre,$song_id);
+ }
+
+ } // update_genre
+
+ /*!
+ @function update_album
+ @discussion updates the album field
+ */
+ function update_album($new_album,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('album',$new_album,$song_id);
+ }
+
+ } // update_album
+
+ /*!
+ @function update_utime
+ @discussion sets a new update time
+ */
+ function update_utime($song_id=0,$time=0) {
+
+ if (!$time) { $time = time(); }
+
+ if ($_SESSION['userdata']['access'] === 'admin') {
+ $this->update_item('update_time',$time,$song_id);
+ }
+
+ } // update_utime
+
+ /*!
+ @function update_played
+ @discussion sets the played flag
+ */
+ function update_played($new_played,$song_id=0) {
+
+ $this->update_item('played',$new_played,$song_id);
+
+ } // update_played
+
+
+ /*!
+ @function update_enabled
+ @discussion sets the enabled flag
+ */
+ function update_enabled($new_enabled,$song_id=0) {
+
+ if ($_SESSION['userdata']['access'] === 'admin' || $_SESSION['userdata']['access'] === '100') {
+ $this->update_item('status',$new_enabled,$song_id);
+ }
+
+ } // update_enabled
+
+ /*!
+ @function update_item
+ @discussion this is a generic function that is called
+ by all the other update functions...
+ @param $field The field we are updating
+ @param $value The new value for said field
+ @param $song_id ID of the song, uses $this->id by default
+ */
+ function update_item($field,$value,$song_id=0) {
+
+ if (!$song_id) { $song_id = $this->id; }
+
+ $value = sql_escape($value);
+
+ $sql = "UPDATE song SET $field='$value' WHERE id='$song_id'";
+ $db_results = mysql_query($sql, dbh());
+
+ $this->{$field} = $value;
+
+ } //update_item
+
+
+ /*!
+ @function format_song
+ @discussion this takes a song object
+ and formats it for display
+ and returns the object cleaned up
+ */
+ function format_song() {
+
+ // 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 = truncate_with_ellipse($this->f_album_full,conf('ellipse_threshold_album'));
+
+ // Format the artist name
+ $this->f_artist_full = $this->get_artist_name();
+ $this->f_artist = truncate_with_ellipse($this->f_artist_full,conf('ellipse_threshold_artist'));
+
+ // Format the title
+ $this->f_title = truncate_with_ellipse($this->title,conf('ellipse_threshold_title'));
+
+ // Create A link inclduing the title
+ $this->f_link = "<a href=\"" . conf('web_path') . "/song.php?action=m3u&song=" . $this->id . "\">$this->f_title</a>";
+
+ // Format the Bitrate
+ $this->f_bitrate = intval($this->bitrate/1000) . "-" . strtoupper($this->mode);
+
+ // Format Genre
+ $this->f_genre = $this->get_genre_name();
+
+ // Format the Time
+ $min = floor($this->time/60);
+ $sec = sprintf("%02d", ($this->time%60) );
+ $this->f_time = $min . ":" . $sec;
+
+ // Format the size
+ $this->f_size = sprintf("%.2f",($this->size/1048576));
+
+ // Set style
+ if (preg_match("/id3/", $this->flagtype)) { $this->f_style = "style=\"color: #33c;\""; }
+ elseif (preg_match("/(mp3|del|sort|ren)/", $this->flagtype)) { $this->f_style = "style=\"color: #C00;\""; }
+ if ($this->status === 'disabled') { $this->f_style = "style=\"text-decoration: line-through;\""; }
+
+ return true;
+
+ } // format_song
+
+ /*!
+ * @function get_rel_path
+ * @discussion returns the path of the song file stripped of the catalog path
+ * used for mpd playback
+ */
+ 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;
+ return( str_replace( $catalog_path . "/", "", $file_path ) );
+
+ } // get_rel_path
+
+
+ /*!
+ @function fill_info
+ @discussion this takes the $results from getid3 and attempts to fill
+ as much information as possible from the file name using the
+ pattern set in the current catalog
+ */
+ function fill_info($results,$pattern,$catalog_id,$key) {
+
+ $filename = $this->get_rel_path($results['file'],$catalog_id);
+
+ if (!strlen($results[$key]['title'])) {
+ $results[$key]['title'] = $this->get_info_from_filename($filename,$pattern,"%t");
+ }
+ if (!strlen($results[$key]['track'])) {
+ $results[$key]['track'] = $this->get_info_from_filename($filename,$pattern,"%T");
+ }
+ if (!strlen($results[$key]['year'])) {
+ $results[$key]['year'] = $this->get_info_from_filename($filename,$pattern,"%y");
+ }
+ if (!strlen($results[$key]['album'])) {
+ $results[$key]['album'] = $this->get_info_from_filename($filename,$pattern,"%A");
+ }
+ if (!strlen($results[$key]['artist'])) {
+ $results[$key]['artist'] = $this->get_info_from_filename($filename,$pattern,"%a");
+ }
+ if (!strlen($results[$key]['genre'])) {
+ $results[$key]['genre'] = $this->get_info_from_filename($filename,$pattern,"%g");
+ }
+
+ return $results;
+
+ } // fill_info
+
+ /*!
+ @function get_info_from_filename
+ @discussion get information from a filename based on pattern
+ */
+ function get_info_from_filename($file,$pattern,$tag) {
+
+ $preg_pattern = preg_replace("/$tag/","(.+)",$pattern);
+ $preg_pattern = preg_replace("/\%\w/",".+",$preg_pattern);
+ $preg_pattern = "/" . str_replace("/","\/",$preg_pattern) . "\..+/";
+
+ preg_match($preg_pattern,$file,$matches);
+
+ return stripslashes($matches[1]);
+
+ } // get_info_from_filename
+
+} //end of song class
+
+?>
diff --git a/modules/class/stream.php b/modules/class/stream.php
new file mode 100644
index 00000000..3472127a
--- /dev/null
+++ b/modules/class/stream.php
@@ -0,0 +1,291 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2005 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header Stream Class
+*/
+
+class Stream {
+
+ /* Variables from DB */
+ var $type;
+ var $web_path;
+ var $songs = array();
+ var $sess;
+
+ /*!
+ @function stream
+ @discussion constructor for the stream class
+ */
+ function Stream($type='m3u', $song_ids=0) {
+
+ $this->type = $type;
+ $this->songs = $song_ids;
+ $this->web_path = conf('web_path');
+
+ if (conf('force_http_play')) {
+ $port = conf('http_port');
+ $this->web_path = preg_replace("/https/", "http",$this->web_path);
+ $this->web_path = preg_replace("/:\d+/",":$port",$this->web_path);
+ }
+
+ $this->sess = session_id();
+ $this->user_id = $_SESSION['userdata']['id'];
+
+ } //constructor
+
+ /*!
+ @function start
+ @discussion runs this and depending on the type passed it will
+ call the correct function
+ */
+ function start() {
+
+ $methods = get_class_methods('Stream');
+ $create_function = "create_" . $this->type;
+ if (in_array($create_function,$methods)) {
+ $this->{$create_function}();
+ }
+ // Assume M3u incase they've pooched the type
+ else {
+ $this->create_m3u();
+ }
+
+ } // start
+
+ /*!
+ @function create_simplem3u
+ @discussion this creates a simple m3u
+ without any of the extended information
+ */
+ function create_simple_m3u() {
+
+ header("Cache-control: public");
+ header("Content-Disposition: filename=playlist.m3u");
+ header("Content-Type: audio/x-mpegurl;");
+ foreach ($this->songs as $song_id) {
+ $song = new Song($song_id);
+ if ($song->type == ".flac") { $song->type = ".ogg"; }
+ if($GLOBALS['user']->prefs['play_type'] == 'downsample') {
+ $ds = $GLOBALS['user']->prefs['sample_rate'];
+ }
+ echo "$this->web_path/play/index.php?song=$song_id&uid=$this->user_id&sid=$this->sess&ds=$ds&stupidwinamp=." . $song->type . "\n";
+ } // end foreach
+
+ } // simple_m3u
+
+ /*!
+ @function create_m3u
+ @discussion creates an m3u file
+ */
+ function create_m3u() {
+
+ // Send the client an m3u playlist
+ header("Cache-control: public");
+ header("Content-Disposition: filename=playlist.m3u");
+ header("Content-Type: audio/x-mpegurl;");
+ echo "#EXTM3U\n";
+ foreach($this->songs as $song_id) {
+ $song = new Song($song_id);
+ $song->format_song();
+ if ($song->type == ".flac") { $song->type = ".ogg"; }
+ $song_name = $song->f_artist_full . " - " . $song->title . "." . $song->type;
+ echo "#EXTINF:$song->time,$song_name\n";
+ $sess = $_COOKIE[libglue_param('sess_name')];
+ if($GLOBALS['user']->prefs['play_type'] == 'downsample') {
+ $ds = $GLOBALS['user']->prefs['sample_rate'];
+ }
+ echo "$this->web_path/play/index.php?song=$song_id&uid=$this->user_id&sid=$this->sess&ds=$ds&name=/" . rawurlencode($song_name) . "\n";
+ } // end foreach
+
+ } // create_m3u
+
+ /*!
+ @function create_pls
+ @discussion creates a pls file
+ */
+ function create_pls() {
+
+ // Send the client a pls playlist
+ header("Cache-control: public");
+ header("Content-Disposition: filename=playlist.pls");
+ header("Content-Type: audio/x-scpls;");
+ echo "[Playlist]\n";
+ echo "NumberOfEntries=" . count($this->songs) . "\n";
+ foreach ($this->songs as $song_id) {
+ $i++;
+ $song = new Song($song_id);
+ $song->format_song();
+ if ($song->type == ".flac") { $song->type = ".ogg"; }
+ $song_name = $song->f_artist_full . " - " . $song->title . "." . $song->type;
+ if($GLOBALS['user']->prefs['play_type'] == 'downsample') {
+ $ds = $GLOBALS['user']->prefs['sample_rate'];
+ }
+ $song_url = $this->web_path . "/play/index.php?song=$song_id&uid=$this->user_id&sid=$this->sess&ds=$ds&stupidwinamp=." . $song->type;
+ echo "File" . $i . "=$song_url\n";
+ echo "Title" . $i . "=$song_name\n";
+ echo "Length" . $i . "=-1\n";
+ } // end foreach songs
+ echo "Version=2\n";
+
+ } // create_pls
+
+ /*!
+ @function create_asx
+ @discussion creates an ASZ playlist (Thx Samir Kuthiala)
+ */
+ function create_asx() {
+
+ header("Cache-control: public");
+ header("Content-Disposition: filename=playlist.asx");
+ header("Content-Type: video/x-ms-asf;");
+
+ echo "<ASX version = \"3.0\" BANNERBAR=\"AUTO\">\n";
+ echo "<TITLE>Ampache ASX Playlist</TITLE>";
+
+ foreach ($this->songs as $song_id) {
+ $song = new Song($song_id);
+ $song->format_song();
+ $song_name = $song->f_artist_full . " - " . $song->title . "." . $song->type;
+ echo "<ENTRY>\n";
+ echo "<TITLE>".$song->f_album_full ." - ". $song->f_artist_full ." - ". $song->title ."</TITLE>\n";
+ echo "<AUTHOR>".$song->f_artist_full."</AUTHOR>\n";
+ $sess = $_COOKIE[libglue_param('sess_name')];
+ if ($GLOBALS['user']->prefs['play_type'] == 'downsample') {
+ $ds = $GLOBALS['user']->prefs['sample_rate'];
+ }
+ echo "<REF HREF = \"". conf('web_path') . "/play/index.php?song=$song_id&uid=$this->user_id&sid=$sess&ds=$ds&name=/" . rawurlencode($song_name) . "\" />\n";
+ echo "</ENTRY>\n";
+
+ } // end foreach
+
+ echo "</ASX>\n";
+
+ } // create_asx
+
+ /*!
+ @function create_icecast2
+ @discussion pushes an icecast stream
+ */
+ function create_icecast2() {
+
+ echo "ICECAST2<br>\n";
+
+ // Play the song locally using local play configuration
+ if (count($this->songs) > 0) {
+ echo "ICECAST2<br>\n";
+ exec("killall ices");
+ $filename = conf('icecast_tracklist');
+ echo "$filename " . _("Opened for writting") . "<br>\n";
+
+ /* Open the file for writting */
+ if (!$handle = @fopen($filename, "w")) {
+ log_event($_SESSION['userdata']['username'],"icecast","Fopen: $filename Failed");
+ echo _("Error, cannot write") . " $filename<br>\n";
+ exit;
+ }
+
+ /* Foreach through songs */
+ foreach($this->songs as $song_id) {
+ $song = new Song($song_id);
+ echo "$song->file<br>\n";
+ $line = "$song->file\n";
+ if (!fwrite($handle, $line)) {
+ log_event($_SESSION['userdata']['username'],"icecast","Fwrite: Unabled to write $line into $filename");
+ echo _("Error, cannot write song in file") . " $song->file --&gt; $filename";
+ exit;
+ } // if write fails
+
+ } // foreach songs
+
+ echo $filename . " " . _("Closed after write") . "<br>\n";
+ fclose($handle);
+ $cmd = conf('icecast_command');
+ $cmd = str_replace("%FILE%", $filename, $cmd);
+ if (conf('debug')) {
+ log_event($_SESSION['userdata']['username'],"icecast","Exec: $cmd");
+ }
+ exec($cmd);
+ exit;
+
+ } // if songs
+
+
+ } // create_icecast2
+
+ /*!
+ @function create_local_play
+ @discussion pushes out localplay mojo
+ */
+ function create_local_play() {
+
+ foreach($this->songs as $song_id) {
+ $song = new Song($song_id);
+ $song->format_song();
+ $song_name = $song->f_artist_full . " - " . $song->title . "." . $song->type;
+ $url = escapeshellarg("$this->web_path/play/?song=$song_id&uid=$this->user_id&sid=$this->sess&name=" . rawurlencode($song_name));
+ $localplay_add = conf('localplay_add');
+ $localplay_add = str_replace("%URL%", $url, $localplay_add);
+ if (conf('debug')) {
+ log_event($_SESSION['userdata']['username'],"localplay","Exec: $localplay_add");
+ }
+ exec($localplay_add);
+ header("Location: " . conf('web_path') . "/index.php");
+ }
+
+ } // create_localplay
+
+ /*!
+ @function create_mpd
+ @discussion function that passes information to
+ MPD
+ */
+ function create_mpd() {
+
+ /* Create the MPD object */
+ $myMpd = @new mpd(conf('mpd_host'),conf('mpd_port'),conf('mpd_pass'));
+
+ /* Add the files to the MPD playlist */
+ addToPlaylist($myMpd,$this->songs);
+
+ header ("Location: " . return_referer());
+
+ } // create_mpd
+
+
+ /*!
+ @function create_slim
+ @discussion this function passes the correct mojo to the slim
+ class which is in turn passed to the slimserver
+ */
+ function create_slim() {
+
+
+
+
+
+ } // create_slim
+
+
+} //end of stream class
+
+?>
diff --git a/modules/class/update.php b/modules/class/update.php
new file mode 100644
index 00000000..bd776e70
--- /dev/null
+++ b/modules/class/update.php
@@ -0,0 +1,880 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2005 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*!
+ @header Update Class
+ @discussion this class handles updating from one version of
+ maintain to the next. Versions are a 6 digit number
+ 220000
+ ^
+ Major Revision
+
+ 220000
+ ^
+ Minor Revision
+
+ The last 4 digits are a build number...
+ If Minor can't go over 9 Major can go as high as we want
+*/
+
+class Update {
+
+ var $key;
+ var $value;
+ var $versions; // array containing version information
+
+ /*!
+ @function Update
+ @discussion Constructor, pulls out information about
+ the desired key
+ */
+ function Update ( $key=0 ) {
+
+ if ($key) {
+ $info = $this->get_info();
+ $this->key = $key;
+ $this->value = $info->value;
+ $this->versions = $this->populate_version();
+ }
+
+ } // constructor
+
+ /*!
+ @function get_info
+ @discussion gets the information for the zone
+ */
+ function get_info() {
+ global $conf;
+
+ $sql = "SELECT * FROM update_info WHERE key='$this->key'";
+ $db_results = mysql_query($sql, dbh());
+
+ return mysql_fetch_object($db_results);
+
+ } //get_info
+
+ /*!
+ @function get_version
+ @discussion 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.
+ */
+ function get_version() {
+
+
+ /* Make sure that update_info exits */
+ $sql = "SHOW TABLES LIKE 'update_info'";
+ $db_results = mysql_query($sql, dbh());
+ // If no table
+ if (!mysql_num_rows($db_results)) {
+
+ $version = '310000';
+
+ } // 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 = mysql_query($sql, dbh());
+ $results = mysql_fetch_object($db_results);
+ $version = $results->value;
+ }
+
+ return $version;
+
+ } // get_version
+
+ /*!
+ @function format_version
+ @discussion make the version number pretty
+ */
+ 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));
+
+ return $new_version;
+
+ } // format_version
+
+ /*!
+ @function need_update
+ @discussion checks to see if we need to update
+ maintain at all
+ */
+ function need_update() {
+
+ $current_version = $this->get_version();
+
+ if (!is_array($this->versions)) {
+ $this->versions = $this->populate_version();
+ }
+
+ /*
+ Go through the versions we have and see if
+ we need to apply any updates
+ */
+ foreach ($this->versions as $update) {
+ if ($update['version'] > $current_version) {
+ return true;
+ }
+
+ } // end foreach version
+
+ return false;
+
+ } // need_update
+
+
+ /*!
+ @function populate_version
+ @discussion just sets an array the current differences
+ that require an update
+ */
+ function populate_version() {
+
+ /* Define the array */
+ $version = array();
+
+ /* Version 3.2 Build 0001 */
+ $update_string = "- Add update_info table to the database<br />" .
+ "- Add Now Playing Table<br />" .
+ "- Add album art columns to album table<br />" .
+ "- Compleatly Changed Preferences table<br />" .
+ "- Added Upload table<br />";
+ $version[] = array('version' => '320001', 'description' => $update_string);
+
+ $update_string = "- Add back in catalog_type for XML-RPC Mojo<br />" .
+ "- Add level to access list to allow for play/download/xml-rpc share permissions<br />" .
+ "- Changed access_list table to allow start-end (so we can set full ip ranges)<br />" .
+ "- Add default_play to preferences to allow quicktime/localplay/stream<br />" .
+ "- Switched Artist ID from 10 --> 11 to match other tables<br />";
+ $version[] = array('version' => '320002', 'description' => $update_string);
+
+ $update_string = "- Added a last_seen field user table to track users<br />" .
+ "- Made preferences table key/value based<br />";
+
+ $version[] = array('version' => '320003', 'description' => $update_string);
+
+ $update_string = "- Added play_type to preferences table<br />" .
+ "- Removed multicast,downsample,localplay from preferences table<br />" .
+ "- Dropped old config table which was no longer needed<br />";
+
+ $version[] = array('version' => '320004', 'description' => $update_string);
+
+ $update_string = "- Added type to preferences to allow for site/user preferences<br />";
+
+ $version[] = array('version' => '330000', 'description' => $update_string);
+
+ $update_string = "- Added Year to album table<br />" .
+ "- Increased length of password field in User table<br />";
+
+ $version[] = array('version' => '330001', 'description' => $update_string);
+
+ $update_string = "- Changed user.access to varchar from enum for more flexibility<br />" .
+ "- Added catalog.private for future catalog access control<br />" .
+ "- Added user_catalog table for future catalog access control<br />";
+
+
+ $version[] = array('version' => '330002', 'description' => $update_string);
+
+ $update_string = "- Added user_preferences table to once and for all fix preferences.<br />" .
+ "- Moved Contents of preferences into new table, and modifies old preferences table.<br />";
+
+ $version[] = array('version' => '330003', 'description' => $update_string);
+
+ $update_string = "- Changed song comment from varchar255 in order to handle comments longer than 255 chr.<br />" .
+ "- Added Language and Playlist Type as a per user preference.<br />" .
+ "- Added Level to Catalog_User table for future use.<br />" .
+ "- Added gather_types to Catalog table for future use.<br />";
+
+
+ $version[] = array('version' => '330004', 'description' => $update_string);
+
+ $update_string = "- Added Theme config option.<br />";
+
+ $version[] = array('version' => '331000', 'description' => $update_string);
+
+ $update_string = "- Added Elipse Threshold Preferences.<br />";
+
+ $version[] = array('version' => '331001', 'description' => $update_string);
+
+
+ return $version;
+
+ } // populate_version
+
+ /*!
+ @function display_update
+ @discussion This displays a list of the needed
+ updates to the database. This will actually
+ echo out the list...
+ */
+ function display_update() {
+
+ $current_version = $this->get_version();
+ if (!is_array($this->versions)) {
+ $this->versions = $this->populate_version();
+ }
+
+ echo "<ul>\n";
+
+ foreach ($this->versions as $version) {
+
+ if ($version['version'] > $current_version) {
+ $updated = true;
+ echo "<b>Version: " . $this->format_version($version['version']) . "</b><br />";
+ echo $version['description'] . "<br />\n";
+ } // if newer
+
+ } // foreach versions
+
+ echo "</ul>\n";
+
+ if (!$updated) { echo "<p align=\"center\">No Updates Needed [<a href=\"" . conf('web_path') . "\">Return]</a></p>"; }
+ } // display_update
+
+ /*!
+ @function run_update
+ @discussion 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.
+ */
+ function run_update() {
+
+ /* Nuke All Active session before we start the mojo */
+ $sql = "DELETE * FROM session";
+ $db_results = mysql_query($sql, dbh());
+
+
+ $methods = array();
+
+ $current_version = $this->get_version();
+
+ $methods = get_class_methods('Update');
+
+ if (!is_array($this->versions)) {
+ $this->versions = $this->populate_version();
+ }
+
+ foreach ($this->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)) {
+ $this->{$update_function}();
+ }
+
+ }
+
+ } // end foreach version
+
+ } // run_update
+
+ /*!
+ @function set_version
+ @discussion sets a new version takes
+ a key and value
+ */
+ function set_version($key,$value) {
+
+ $sql = "UPDATE update_info SET value='$value' WHERE `key`='$key'";
+ $db_results = mysql_query($sql, dbh());
+
+ } //set_version
+
+ /*!
+ @function update_320001
+ @discussion Migration function for 3.2 Build 0001
+ */
+ function update_320001() {
+
+ // Add the update_info table to the database
+ $sql = "CREATE TABLE `update_info` (`key` VARCHAR( 128 ) NOT NULL ,`value` VARCHAR( 255 ) NOT NULL ,INDEX ( `key` ) )";
+ $db_results = mysql_query($sql, dbh());
+
+ // Insert the first version info
+ $sql = "INSERT INTO update_info (`key`,`value`) VALUES ('db_version','320001')";
+ $db_results = mysql_query($sql, dbh());
+
+ // Add now_playing table to database
+ $sql = "CREATE TABLE now_playing (" .
+ "id int(11) unsigned NOT NULL auto_increment, " .
+ "song_id int(11) unsigned NOT NULL default '0', " .
+ "user_id int(11) unsigned default NULL, " .
+ "start_time int(11) unsigned NOT NULL default '0', " .
+ "PRIMARY KEY (id) " .
+ ") TYPE=MyISAM";
+ $db_results = mysql_query($sql, dbh());
+
+ // Add the upload table to the database
+ $sql = "CREATE TABLE upload ( id int(11) unsigned NOT NULL auto_increment, `user` int(11) unsigned NOT NULL," .
+ "`file` varchar(255) NOT NULL , `comment` varchar(255) NOT NULL , action enum('add','quarantine','delete') NOT NULL default 'quarantine', " .
+ "addition_time int(11) unsigned default '0', PRIMARY KEY (id), KEY action (`action`), KEY user (`user`) )";
+ $db_results = mysql_query($sql, dbh());
+
+ /*
+ Ok we need to compleatly tweak the preferences table
+ first things first, nuke the damn thing so we can
+ setup our new mojo
+ */
+ $sql = "DROP TABLE `preferences`";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "CREATE TABLE `preferences` (`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT , `user` INT( 11 ) UNSIGNED NOT NULL ," .
+ "`download` ENUM( 'true', 'false' ) DEFAULT 'false' NOT NULL , `upload` ENUM( 'disabled', 'html', 'gui' ) DEFAULT 'disabled' NOT NULL ," .
+ "`downsample` ENUM( 'true', 'false' ) DEFAULT 'false' NOT NULL , `local_play` ENUM( 'true', 'false' ) DEFAULT 'false' NOT NULL ," .
+ "`multicast` ENUM( 'true', 'false' ) DEFAULT 'false' NOT NULL , `quarantine` ENUM( 'true', 'false' ) DEFAULT 'true' NOT NULL ," .
+ "`popular_threshold` INT( 11 ) UNSIGNED DEFAULT '10' NOT NULL , `font` VARCHAR( 255 ) DEFAULT 'Verdana, Helvetica, sans-serif' NOT NULL ," .
+ "`bg_color1` VARCHAR( 32 ) DEFAULT '#ffffff' NOT NULL , `bg_color2` VARCHAR( 32 ) DEFAULT '#000000' NOT NULL , `base_color1` VARCHAR( 32 ) DEFAULT '#bbbbbb' NOT NULL , " .
+ "`base_color2` VARCHAR( 32 ) DEFAULT '#dddddd' NOT NULL , `font_color1` VARCHAR( 32 ) DEFAULT '#222222' NOT NULL , " .
+ "`font_color2` VARCHAR( 32 ) DEFAULT '#000000' NOT NULL , `font_color3` VARCHAR( 32 ) DEFAULT '#ffffff' NOT NULL , " .
+ "`row_color1` VARCHAR( 32 ) DEFAULT '#cccccc' NOT NULL , `row_color2` VARCHAR( 32 ) DEFAULT '#bbbbbb' NOT NULL , " .
+ "`row_color3` VARCHAR( 32 ) DEFAULT '#dddddd' NOT NULL , `error_color` VARCHAR( 32 ) DEFAULT '#990033' NOT NULL , " .
+ "`font_size` INT( 11 ) UNSIGNED DEFAULT '10' NOT NULL , `upload_dir` VARCHAR( 255 ) NOT NULL , " .
+ "`sample_rate` INT( 11 ) UNSIGNED DEFAULT '32' NOT NULL , PRIMARY KEY ( `id` ), KEY user (`user`) )";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "INSERT INTO preferences (`user`,`font_size`) VALUES ('0','12')";
+ $db_results = mysql_query($sql, dbh());
+
+ // Now we need to give everyone some preferences
+ $sql = "SELECT * FROM user";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $users[] = $r;
+ }
+
+ foreach ($users as $user) {
+ $sql = "INSERT INTO preferences (`user`) VALUES ('$user->id')";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+ // Add album art columns to album table
+ $sql = "ALTER TABLE album ADD art MEDIUMBLOB, ADD art_mime VARCHAR(128)";
+ $db_result = mysql_query($sql, dbh());
+
+ } // update_320001
+
+ /*!
+ @function update_320002
+ @discussion update to alpha 2
+ */
+ function update_320002() {
+
+ /* Add catalog_type back in for XML-RPC */
+ $sql = "ALTER TABLE `catalog` ADD `catalog_type` ENUM( 'local', 'remote' ) DEFAULT 'local' NOT NULL AFTER `path`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add default_play to pick between stream/localplay/quicktime */
+ $sql = "ALTER TABLE `preferences` ADD `default_play` VARCHAR( 128 ) DEFAULT 'stream' NOT NULL AFTER `popular_threshold`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Should be INT(11) Why not eah? */
+ $sql = "ALTER TABLE `artist` CHANGE `id` `id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add level to access_list so we can limit playback/download/xml-rpc share */
+ $sql = "ALTER TABLE `access_list` ADD `level` SMALLINT( 3 ) UNSIGNED DEFAULT '5' NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Shouldn't be zero fill... not needed */
+ $sql = "ALTER TABLE `user` CHANGE `offset_limit` `offset_limit` INT( 5 ) UNSIGNED DEFAULT '00050' NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Let's knock it up a notch 11.. BAM */
+ $sql = "ALTER TABLE `user` CHANGE `id` `id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Change IP --> Start */
+ $sql = "ALTER TABLE `access_list` CHANGE `ip` `start` INT( 11 ) UNSIGNED NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add End */
+ $sql = "ALTER TABLE `access_list` ADD `end` INT( 11 ) UNSIGNED NOT NULL AFTER `start`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Update Version */
+ $this->set_version('db_version', '320002');
+
+ } // update_320002
+
+
+ /*!
+ @function update_320003
+ @discussion updates to the alpha 3 of 3.2
+ */
+ function update_320003() {
+
+ /* Add last_seen to user table */
+ $sql = "ALTER TABLE `user` ADD `last_seen` INT( 11 ) UNSIGNED NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /*
+ Load the preferences table into an array
+ so we can migrate it to the new format
+ */
+ $sql = "SELECT * FROM preferences";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[$r->user]['download'] = $r->download;
+ $results[$r->user]['upload'] = $r->upload;
+ $results[$r->user]['downsample'] = $r->downsample;
+ $results[$r->user]['local_play'] = $r->local_play;
+ $results[$r->user]['multicast'] = $r->multicast;
+ $results[$r->user]['quarantine'] = $r->quarantine;
+ $results[$r->user]['popular_threshold'] = $r->popular_threshold;
+ $results[$r->user]['default_play'] = $r->default_play;
+ $results[$r->user]['font'] = $r->font;
+ $results[$r->user]['bg_color1'] = $r->bg_color1;
+ $results[$r->user]['bg_color2'] = $r->bg_color2;
+ $results[$r->user]['base_color1'] = $r->base_color1;
+ $results[$r->user]['base_color2'] = $r->base_color2;
+ $results[$r->user]['font_color1'] = $r->font_color1;
+ $results[$r->user]['font_color2'] = $r->font_color2;
+ $results[$r->user]['font_color3'] = $r->font_color3;
+ $results[$r->user]['row_color1'] = $r->row_color1;
+ $results[$r->user]['row_color2'] = $r->row_color2;
+ $results[$r->user]['row_color3'] = $r->row_color3;
+ $results[$r->user]['error_color'] = $r->error_color;
+ $results[$r->user]['font_size'] = $r->font_size;
+ $results[$r->user]['upload_dir'] = $r->upload_dir;
+ $results[$r->user]['sample_rate'] = $r->sample_rate;
+
+ } // while preferences
+
+ /* Drop the preferences table so we can start over */
+ $sql = "DROP TABLE `preferences`";
+ $db_results = mysql_query($sql, dbh()) or die('Query failed: ' . mysql_error());
+
+ /* Create the new preferences table */
+ $sql = "CREATE TABLE `preferences` (`key` VARCHAR( 255 ) NOT NULL , `value` VARCHAR( 255 ) NOT NULL , `user` INT( 11 ) UNSIGNED NOT NULL)";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "ALTER TABLE `preferences` ADD INDEX ( `key` )";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "ALTER TABLE `preferences` ADD INDEX ( `user` )";
+ $db_results = mysql_query($sql, dbh());
+
+
+ $user = new User();
+
+ /* Populate the mofo! */
+ foreach ($results as $key => $data) {
+
+ $user->add_preference('download',$results[$key]['download'],$key);
+ $user->add_preference('upload',$results[$key]['upload'], $key);
+ $user->add_preference('downsample',$results[$key]['downsample'], $key);
+ $user->add_preference('local_play', $results[$key]['local_play'], $key);
+ $user->add_preference('multicast', $results[$key]['multicast'], $key);
+ $user->add_preference('quarantine', $results[$key]['quarantine'], $key);
+ $user->add_preference('popular_threshold',$results[$key]['popular_threshold'], $key);
+ $user->add_preference('font', $results[$key]['font'], $key);
+ $user->add_preference('bg_color1',$results[$key]['bg_color1'], $key);
+ $user->add_preference('bg_color2',$results[$key]['bg_color2'], $key);
+ $user->add_preference('base_color1',$results[$key]['base_color1'], $key);
+ $user->add_preference('base_color2',$results[$key]['base_color2'], $key);
+ $user->add_preference('font_color1',$results[$key]['font_color1'], $key);
+ $user->add_preference('font_color2',$results[$key]['font_color2'], $key);
+ $user->add_preference('font_color3',$results[$key]['font_color3'], $key);
+ $user->add_preference('row_color1',$results[$key]['row_color1'], $key);
+ $user->add_preference('row_color2',$results[$key]['row_color2'], $key);
+ $user->add_preference('row_color3',$results[$key]['row_color3'], $key);
+ $user->add_preference('error_color', $results[$key]['error_color'], $key);
+ $user->add_preference('font_size', $results[$key]['font_size'], $key);
+ $user->add_preference('upload_dir', $results[$key]['upload_dir'], $key);
+ $user->add_preference('sample_rate', $results[$key]['sample_rate'], $key);
+
+ } // foreach preferences
+
+ /* Update Version */
+ $this->set_version('db_version', '320003');
+
+ } // update_320003
+
+ /*!
+ @function update_320004
+ @discussion updates to the 320004
+ version of the db
+ */
+ function update_320004() {
+
+ $results = array();
+
+ $sql = "SELECT * FROM preferences WHERE `key`='local_play' AND `value`='true'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[$r->user] = 'local_play';
+ }
+
+ $sql = "SELECT * FROM preferences WHERE `key`='downsample' AND `value`='true'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[$r->user] = 'downsample';
+ }
+
+ $sql = "SELECT * FROM preferences WHERE `key`='multicast' AND `value`='true'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[$r->user] = 'multicast';
+ }
+
+ $sql = "SELECT DISTINCT(user) FROM preferences";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ if (!isset($results[$r->user])) {
+ $results[$r->user] = 'normal';
+ }
+ }
+
+ foreach ($results as $key => $value) {
+ $sql = "INSERT INTO preferences (`key`,`value`,`user`) VALUES ('play_type','$value','$key')";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+ $sql = "DELETE FROM preferences WHERE `key`='downsample'";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "DELETE FROM preferences WHERE `key`='local_play'";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "DELETE FROM preferences WHERE `key`='multicast'";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "DROP TABLE `config`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Update Version */
+ $this->set_version('db_version', '320004');
+
+ } // update_320004
+
+ /*!
+ @function update_330000
+ @discussion updates to 3.3 Build 0
+ */
+ function update_330000() {
+
+ /* Add Type to preferences */
+ $sql = "ALTER TABLE `preferences` ADD `type` VARCHAR( 128 ) NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Set Type on current preferences */
+ $sql = "UPDATE `preferences` SET type='user'";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add New Preferences */
+ $new_prefs[] = array('key' => 'local_length', 'value' => libglue_param('local_length'));
+ $new_prefs[] = array('key' => 'site_title', 'value' => conf('site_title'));
+ $new_prefs[] = array('key' => 'access_control', 'value' => conf('access_control'));
+ $new_prefs[] = array('key' => 'xml_rpc', 'value' => conf('xml_rpc'));
+ $new_prefs[] = array('key' => 'lock_songs', 'value' => conf('lock_songs'));
+ $new_prefs[] = array('key' => 'force_http_play', 'value' => conf('force_http_play'));
+ $new_prefs[] = array('key' => 'http_port', 'value' => conf('http_port'));
+ $new_prefs[] = array('key' => 'do_mp3_md5', 'value' => conf('do_mp3_md5'));
+ $new_prefs[] = array('key' => 'catalog_echo_count', 'value' => conf('catalog_echo_count'));
+ $new_prefs[] = array('key' => 'no_symlinks', 'value' => conf('no_symlinks'));
+ $new_prefs[] = array('key' => 'album_cache_limit', 'value' => conf('album_cache_limit'));
+ $new_prefs[] = array('key' => 'artist_cache_limit', 'value' => conf('artist_cache_limit'));
+ $new_prefs[] = array('key' => 'memory_limit', 'value' => conf('memory_limit'));
+ $new_prefs[] = array('key' => 'refresh_limit', 'value' => conf('refresh_interval'));
+
+ foreach ($new_prefs as $pref) {
+ $sql = "INSERT INTO `preferences` (`key`,`value`,`type`) VALUES ('".$pref['key']."','".$pref['value']."','system')";
+ $db_results = mysql_query($sql, dbh());
+ }
+
+
+ /* Update Version */
+ $this->set_version('db_version','330000');
+
+
+ } // update_330000
+
+
+ /*!
+ @function update_330001
+ @discussion adds year to album and tweaks
+ the password field in session
+ */
+ function update_330001() {
+
+ /* Add Year to Album Table */
+ $sql = "ALTER TABLE `album` ADD `year` INT( 4 ) UNSIGNED NOT NULL AFTER `prefix`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Alter Password Field */
+ $sql = "ALTER TABLE `user` CHANGE `password` `password` VARCHAR( 64 ) NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Update Version */
+ $this->set_version('db_version', '330001');
+
+ } // update_330001
+
+ /*!
+ @function update_330002
+ @discussion changes user.access from enum to a
+ varchr field
+ */
+ function update_330002() {
+
+ /* Alter user table */
+ $sql = "ALTER TABLE `user` CHANGE `access` `access` VARCHAR( 64 ) NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add private option to catalog */
+ $sql = "ALTER TABLE `catalog` ADD `private` INT( 1 ) UNSIGNED DEFAULT '0' NOT NULL AFTER `enabled`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add new user_catalog table */
+ $sql = "CREATE TABLE `user_catalog` ( `user` INT( 11 ) UNSIGNED NOT NULL , `catalog` INT( 11 ) UNSIGNED NOT NULL )";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Update Version */
+ $this->set_version('db_version', '330002');
+
+ } // update_330002
+
+ /*!
+ @function update_330003
+ @discussion adds user_preference and modifies the
+ existing preferences table
+ */
+ function update_330003() {
+
+ /* Add new user_preference table */
+ $sql = "CREATE TABLE `user_preference` ( `user` INT( 11 ) UNSIGNED NOT NULL , `preference` INT( 11 ) UNSIGNED NOT NULL, `value` VARCHAR( 255 ) NOT NULL )";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add indexes */
+ $sql = "ALTER TABLE `user_preference` ADD INDEX ( `user` )";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "ALTER TABLE `user_preference` ADD INDEX ( `preference` )";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Pull and store all preference information */
+ $sql = "SELECT * FROM preferences";
+ $db_results = mysql_query($sql, dbh());
+
+ $results = array();
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = $r;
+ }
+
+
+ /* Re-combobulate preferences table */
+
+ /* Drop the preferences table so we can start over */
+ $sql = "DROP TABLE `preferences`";
+ $db_results = mysql_query($sql, dbh()) or die('Query failed: ' . mysql_error());
+
+ /* Insert new preference table */
+ $sql = "CREATE TABLE `preferences` ( `id` INT ( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT, `name` VARCHAR ( 128 ) NOT NULL, `value` VARCHAR ( 255 ) NOT NULL," .
+ " `description` VARCHAR ( 255 ) NOT NULL, `level` INT ( 11 ) UNSIGNED NOT NULL DEFAULT '100', `type` VARCHAR ( 128 ) NOT NULL, `locked` SMALLINT ( 1 ) NOT NULL Default '1'" .
+ ", PRIMARY KEY ( `id` ) )";
+ $db_results = mysql_query($sql, dbh()) or die("Query failed: " . mysql_error());
+
+ /* Create Array of Preferences */
+ $new_prefs = array();
+
+ $new_prefs[] = array('name' => 'download', 'value' => '0', 'description' => 'Allow Downloads', 'level' => '100', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'upload', 'value' => '0', 'description' => 'Allow Uploads', 'level' => '100', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'quarantine', 'value' => '1', 'description' => 'Quarantine All Uploads', 'level' => '100', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'popular_threshold', 'value' => '10', 'description' => 'Popular Threshold', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'font', 'value' => 'Verdana, Helvetica, sans-serif', 'description' => 'Interface Font', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'bg_color1', 'value' => '#ffffff', 'description' => 'Background Color 1', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'bg_color2', 'value' => '#000000', 'description' => 'Background Color 2', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'base_color1', 'value' => '#bbbbbb', 'description' => 'Base Color 1', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'base_color2', 'value' => '#dddddd', 'description' => 'Base Color 2', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'font_color1', 'value' => '#222222', 'description' => 'Font Color 1', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'font_color2', 'value' => '#000000', 'description' => 'Font Color 2', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'font_color3', 'value' => '#ffffff', 'description' => 'Font Color 3', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'row_color1', 'value' => '#cccccc', 'description' => 'Row Color 1', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'row_color2', 'value' => '#bbbbbb', 'description' => 'Row Color 2', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'row_color3', 'value' => '#dddddd', 'description' => 'Row Color 3', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'error_color', 'value' => '#990033', 'description' => 'Error Color', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'font_size', 'value' => '10', 'description' => 'Font Size', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'upload_dir', 'value' => '/tmp', 'description' => 'Upload Directory', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'sample_rate', 'value' => '32', 'description' => 'Downsample Bitrate', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'refresh_limit', 'value' => '0', 'description' => 'Refresh Rate for Homepage', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'local_length', 'value' => '900', 'description' => 'Session Expire in Seconds', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'site_title', 'value' => 'For The Love of Music', 'description' => 'Website Title', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'lock_songs', 'value' => '0', 'description' => 'Lock Songs', 'level' => '100', 'locked' => '1', 'type' => 'system');
+ $new_prefs[] = array('name' => 'force_http_play', 'value' => '1', 'description' => 'Forces Http play regardless of port', 'level' => '100', 'locked' => '1', 'type' => 'system');
+ $new_prefs[] = array('name' => 'http_port', 'value' => '80', 'description' => 'Non-Standard Http Port', 'level' => '100', 'locked' => '1', 'type' => 'system');
+ $new_prefs[] = array('name' => 'catalog_echo_count', 'value' => '100', 'description' => 'Catalog Echo Interval', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'no_symlinks', 'value' => '0', 'description' => 'Don\'t Follow Symlinks', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'album_cache_limit', 'value' => '25', 'description' => 'Album Cache Limit', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'artist_cache_limit', 'value' => '50', 'description' => 'Artist Cache Limit', 'level' => '100', 'locked' => '0', 'type' => 'system');
+ $new_prefs[] = array('name' => 'play_type', 'value' => 'stream', 'description' => 'Type of Playback', 'level' => '25', 'locked' => '0', 'type' => 'user');
+ $new_prefs[] = array('name' => 'direct_link', 'value' => '1', 'description' => 'Allow Direct Links', 'level' => '100', 'locked' => '0', 'type' => 'user');
+
+ foreach ($new_prefs as $prefs) {
+
+ $sql = "INSERT INTO preferences (`name`,`value`,`description`,`level`,`locked`,`type`) VALUES ('" . $prefs['name'] . "','" . $prefs['value'] ."','". $prefs['description'] ."','" . $prefs['level'] ."','". $prefs['locked'] ."','" . $prefs['type'] . "')";
+ $db_results = mysql_query($sql, dbh());
+
+ } // foreach prefs
+
+
+ /* Re-insert Data into preferences table */
+
+ $user = new User();
+ $users = array();
+
+ foreach ($results as $old_pref) {
+ // This makes sure that true/false yes no get turned into 0/1
+ $temp_array = fix_preferences(array('old' => $old_pref->value));
+ $old_pref->value = $temp_array['old'];
+ $user->add_preference($old_pref->key,$old_pref->value,$old_pref->user);
+ $users[$old_pref->user] = 1;
+ } // end foreach old preferences
+
+ /* Fix missing preferences */
+ foreach ($users as $userid => $data) {
+ $user->fix_preferences($userid);
+ } // end foreach user
+
+ /* Update Version */
+ $this->set_version('db_version', '330003');
+
+ } // update_330003
+
+ /*!
+ @function update_330004
+ @discussion changes comment from varchar to text
+ and also adds a few preferences options and
+ adds the per db art functions
+ */
+ function update_330004() {
+
+ /* Change comment field in song */
+ $sql = "ALTER TABLE `song` CHANGE `comment` `comment` TEXT NOT NULL";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add Extra Preferences */
+ $sql = "INSERT INTO `preferences` ( `id` , `name` , `value` , `description` , `level` , `type` , `locked` ) VALUES ('', 'lang', 'en_US', 'Language', '100', 'user', '0')";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "INSERT INTO `preferences` ( `id` , `name` , `value` , `description` , `level` , `type` , `locked` ) VALUES ('', 'playlist_type','m3u','Playlist Type','100','user','0')";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add Gathertype to Catalog for future use */
+ $sql = "ALTER TABLE `catalog` ADD `gather_types` VARCHAR( 255 ) NOT NULL AFTER `sort_pattern`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Add level to user_catalog for future use */
+ $sql = "ALTER TABLE `user_catalog` ADD `level` SMALLINT( 3 ) DEFAULT '25' NOT NULL AFTER `catalog`";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Fix existing preferences */
+ $sql = "SELECT id FROM user";
+ $db_results = mysql_query($sql, dbh());
+
+ $user = new User(0);
+
+ while ($results = mysql_fetch_array($db_results)) {
+ $user->fix_preferences($results[0]);
+ }
+
+ /* Update Version */
+ $this->set_version('db_version', '330004');
+
+ } // update_330004
+
+ /*!
+ @function update_331000
+ @discussion this updates is for 3.3.1 it adds
+ the theme preference.
+ */
+ function update_331000() {
+
+
+ /* Add new preference */
+ $sql = "INSERT INTO `preferences` (`id`,`name`,`value`,`description`,`level`,`type`,`locked`) VALUES ('','theme_name','classic','Theme','0','user','0')";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Fix existing preferecnes */
+ $sql = "SELECT DISTINCT(user) FROM user_preference";
+ $db_results = mysql_query($sql, dbh());
+
+ $user = new User(0);
+
+ while ($results = mysql_fetch_array($db_results)) {
+ $user->fix_preferences($results[0]);
+ }
+
+ /* Update Version */
+ $this->set_version('db_version','331000');
+
+ } // update_331000
+
+ /*!
+ @function update_331001
+ @discussion this adds a few more user preferences
+ */
+ function update_331001() {
+
+ /* Add new preference */
+ $sql = "INSERT INTO `preferences` (`id`,`name`,`value`,`description`,`level`,`type`,`locked`) VALUES ('','ellipse_threshold_album','27','Album Ellipse Threshold','0','user','0')";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "INSERT INTO `preferences` (`id`,`name`,`value`,`description`,`level`,`type`,`locked`) VALUES ('','ellipse_threshold_artist','27','Artist Ellipse Threshold','0','user','0')";
+ $db_results = mysql_query($sql, dbh());
+
+ $sql = "INSERT INTO `preferences` (`id`,`name`,`value`,`description`,`level`,`type`,`locked`) VALUES ('','ellipse_threshold_title','27','Title Ellipse Threshold','0','user','0')";
+ $db_results = mysql_query($sql, dbh());
+
+ /* Fix existing preferecnes */
+ $sql = "SELECT DISTINCT(user) FROM user_preference";
+ $db_results = mysql_query($sql, dbh());
+
+ $user = new User(0);
+
+ while ($results = mysql_fetch_array($db_results)) {
+ $user->fix_preferences($results[0]);
+ }
+
+ /* Update Version */
+ $this->set_version('db_version','331001');
+
+ } // update_331001
+
+} // end update class
+
+?>
diff --git a/modules/class/user.php b/modules/class/user.php
new file mode 100644
index 00000000..e5c2771b
--- /dev/null
+++ b/modules/class/user.php
@@ -0,0 +1,604 @@
+<?php
+/*
+
+ Copyright (c) 2001 - 2005 Ampache.org
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*!
+ @header User Object
+ View object that is thrown into their session
+
+*/
+
+
+class User {
+
+ //Basic Componets
+ var $username;
+ var $id=0;
+ var $fullname;
+ var $access;
+ var $offset_limit=25;
+ var $email;
+ var $last_seen;
+
+ function User($username=0,$uid=0) {
+
+ if (!$username && !$uid) {
+ return true;
+ }
+
+ $this->username = $username;
+ $this->id = $uid;
+ $info = $this->get_info();
+ $this->username = $info->username;
+ $this->id = $info->id;
+ $this->id = $info->id;
+ $this->fullname = $info->fullname;
+ $this->access = $info->access;
+ $this->offset_limit = $info->offset_limit;
+ $this->email = $info->email;
+ $this->last_seen = $info->last_seen;
+ $this->set_preferences();
+
+ // Make sure the Full name is always filled
+ if (strlen($this->fullname) < 1) { $this->fullname = $this->username; }
+
+ } // User
+
+
+ /*!
+ @function get_info
+ @dicussion gets the info!
+ */
+ function get_info() {
+
+ if ($this->username) {
+ $sql = "SELECT * FROM user WHERE username='$this->username'";
+ }
+ else {
+ $sql = "SELECT * FROM user WHERE id='$this->id'";
+ }
+ $db_results = mysql_query($sql, dbh());
+
+ return mysql_fetch_object($db_results);
+
+ } // get_info
+
+ /*!
+ @function get_preferences
+ @discussion gets the prefs for this specific
+ user and returns them as an array
+ */
+ function get_preferences() {
+
+ $sql = "SELECT preferences.name, preferences.description, preferences.type, user_preference.value FROM preferences,user_preference WHERE user_preference.user='$this->id' AND user_preference.preference=preferences.id AND preferences.type='user'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $results[] = $r;
+ }
+
+ return $results;
+
+ } // get_preferences
+
+ /*!
+ @function set_preferences
+ @discussion sets the prefs for this specific
+ user
+ */
+ function set_preferences() {
+
+ $sql = "SELECT preferences.name,user_preference.value FROM preferences,user_preference WHERE user_preference.user='$this->id' " .
+ "AND user_preference.preference=preferences.id AND preferences.type='user'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ $this->prefs[$r->name] = $r->value;
+ }
+ } // get_preferences
+
+ /*!
+ @function get_favorites
+ @discussion returns an array of your $type
+ favorites
+ */
+ function get_favorites($type) {
+
+ $sql = "SELECT * FROM object_count" .
+ " WHERE count > 0" .
+ " AND object_type = '$type'" .
+ " AND userid = '" . $this->id . "'" .
+ " ORDER BY count DESC LIMIT " . conf('popular_threshold');
+ $db_result = mysql_query($sql, dbh());
+
+ $items = array();
+ $web_path = conf('web_path');
+
+ while ($r = @mysql_fetch_object($db_result) ) {
+ /* If its a song */
+ if ($type == 'song') {
+ $data = new Song($r->object_id);
+ $data->count = $r->count;
+ $data->format_song();
+ $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_album();
+ $items[] = $data;
+ }
+ /* If its an artist */
+ elseif ($type == 'artist') {
+ $data = new Artist($r->object_id);
+ $data->count = $r->count;
+ $data->format_artist();
+ $data->f_name = $data->link;
+ $items[] = $data;
+ }
+
+ } // end while
+
+ return $items;
+
+ } // get_favorites
+
+ /*!
+ @function is_xmlrpc
+ @discussion checks to see if this is a valid
+ xmlrpc user
+ */
+ function is_xmlrpc() {
+
+ /* If we aren't using XML-RPC return true */
+ if (!conf('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;
+
+ } // is_xmlrpc
+
+ /*!
+ @function is_logged_in
+ @discussion checks to see if $this user is logged in
+ */
+ function is_logged_in() {
+
+ $sql = "SELECT id FROM session WHERE username='$this->id'" .
+ " AND expire > ". time();
+ $db_results = mysql_query($sql,dbh());
+
+ if (mysql_num_rows($db_results)) {
+ return true;
+ }
+
+ return false;
+
+ } // is_logged_in
+
+ /*!
+ @function has_access
+ @discussion this function checkes to see if this user has access
+ to the passed action (pass a level requirement)
+ */
+ function has_access($needed_level) {
+
+ if ($this->access == "admin") { $level = 100; }
+ elseif ($this->access == "user") { $level = 25; }
+ else { $level = $this->access; }
+
+ if (!conf('use_auth') || conf('demo_mode')) { return true; }
+
+ if ($level >= $needed_level) { return true; }
+
+ return false;
+
+ } // has_access
+
+ /*!
+ @function update_preference
+ @discussion updates a single preference if the query fails
+ it attempts to insert the preference instead
+ */
+ function update_preference($preference_id, $value, $id=0) {
+
+ if (!$id) {
+ $id = $this->id;
+ }
+
+ $value = sql_escape($value);
+ //FIXME:
+ // Do a has_access check here...
+
+ $sql = "UPDATE user_preference SET value='$value' WHERE user='$id' AND preference='$preference_id'";
+ $db_results = @mysql_query($sql, dbh());
+
+ } // update_preference
+
+ /*!
+ @function add_preference
+ @discussion adds a new preference
+ @param $key preference name
+ @param $value preference value
+ @param $id user is
+ */
+ function add_preference($preference_id, $value, $id=0) {
+
+ if (!$id) {
+ $id = $this->id;
+ }
+
+ $value = sql_escape($value);
+
+ if (!is_numeric($preference_id)) {
+ $sql = "SELECT id FROM preferences WHERE `name`='$preference_id'";
+ $db_results = mysql_query($sql, dbh());
+ $r = mysql_fetch_array($db_results);
+ $preference_id = $r[0];
+ } // end if it's not numeric
+
+ $sql = "INSERT user_preference SET `user`='$id' , `value`='$value' , `preference`='$preference_id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // add_preference
+
+ /*!
+ @function update_username
+ @discussion updates their username
+ */
+ function update_username($new_username) {
+
+ $new_username = sql_escape($new_username);
+ $sql = "UPDATE user SET username='$new_username' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // update_username
+
+ /*!
+ @function update_fullname
+ @discussion updates their fullname
+ */
+ function update_fullname($new_fullname) {
+
+ $new_fullname = sql_escape($new_fullname);
+ $sql = "UPDATE user SET fullname='$new_fullname' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // update_username
+
+ /*!
+ @function update_email
+ @discussion updates their email address
+ */
+ function update_email($new_email) {
+
+ $new_email = sql_escape($new_email);
+ $sql = "UPDATE user SET email='$new_email' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // update_email
+
+ /*!
+ @function update_offset
+ @discussion this updates the users offset_limit
+ */
+ function update_offset($new_offset) {
+
+ $new_offset = sql_escape($new_offset);
+ $sql = "UPDATE user SET offset_limit='$new_offset' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // update_offset
+
+ /*!
+ @function update_access
+ @discussion updates their access level
+ */
+ function update_access($new_access) {
+
+ /* Check for all disable */
+ if ($new_access == 'disabled') {
+ $sql = "SELECT id FROM user WHERE access != 'disabled' AND id != '$this->id'";
+ $db_results = mysql_query($sql,dbh());
+ if (!mysql_num_rows($db_results)) { return false; }
+ }
+
+ /* Prevent Only User accounts */
+ if ($new_access == 'user') {
+ $sql = "SELECT id FROM user WHERE (access='admin' OR access='100') AND id != '$this->id'";
+ $db_results = mysql_query($sql, dbh());
+ if (!mysql_num_rows($db_results)) { return false; }
+ }
+
+ $new_access = sql_escape($new_access);
+ $sql = "UPDATE user SET access='$new_access' WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // 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 = mysql_query($sql, dbh());
+
+ } // update_last_seen
+
+ /*!
+ @function update_user_stats
+ @discussion updates the playcount mojo for this
+ specific user
+ */
+ function update_stats($song_id) {
+
+ $song_info = new Song($song_id);
+ $user = $this->id;
+ $dbh = dbh();
+
+ if (!$song_info->file) { return false; }
+
+ $time = time();
+
+ // Play count for this song
+ $sql = "UPDATE object_count" .
+ " SET date = '$time', count=count+1" .
+ " WHERE object_type = 'song'" .
+ " AND object_id = '$song_id' AND userid = '$user'";
+ $db_result = mysql_query($sql, $dbh);
+
+ $rows = mysql_affected_rows();
+ if (!$rows) {
+ $sql = "INSERT INTO object_count (object_type,object_id,date,count,userid)" .
+ " VALUES ('song','$song_id','$time','1','$user')";
+ $db_result = mysql_query($sql, $dbh);
+ }
+
+ // Play count for this artist
+ $sql = "UPDATE object_count" .
+ " SET date = '$time', count=count+1" .
+ " WHERE object_type = 'artist'" .
+ " AND object_id = '" . $song_info->artist . "' AND userid = '$user'";
+ $db_result = mysql_query($sql, $dbh);
+
+ $rows = mysql_affected_rows();
+ if (!$rows) {
+ $sql = "INSERT INTO object_count (object_type,object_id,date,count,userid)" .
+ " VALUES ('artist','".$song_info->artist."','$time','1','$user')";
+ $db_result = mysql_query($sql, $dbh);
+ }
+
+ // Play count for this album
+ $sql = "UPDATE object_count" .
+ " SET date = '$time', count=count+1" .
+ " WHERE object_type = 'album'" .
+ " AND object_id = '".$song_info->album."' AND userid = '$user'";
+ $db_result = mysql_query($sql, $dbh);
+
+ $rows = mysql_affected_rows();
+ if (!$rows) {
+ $sql = "INSERT INTO object_count (object_type,object_id,date,count,userid)" .
+ "VALUES ('album','".$song_info->album."','$time','1','$user')";
+ $db_result = mysql_query($sql, $dbh);
+ }
+
+
+ } // update_stats
+
+ /*!
+ @function create
+ @discussion inserts a new user into ampache
+ */
+ function create($username, $fullname, $email, $password, $access) {
+
+ /* Lets clean up the fields... */
+ $username = sql_escape($username);
+ $fullname = sql_escape($fullname);
+ $email = sql_escape($email);
+
+ /* Now Insert this new user */
+ $sql = "INSERT INTO user (username, fullname, email, password, access) VALUES" .
+ " ('$username','$fullname','$email',PASSWORD('$password'),'$access')";
+ $db_results = mysql_query($sql, dbh());
+ if (!$db_results) { return false; }
+ $user_id = mysql_insert_id(dbh());
+
+ /* Populates any missing preferences, in this case all of them */
+ $this->fix_preferences($user_id);
+
+ return $user_id;
+
+ } // new
+
+ /*!
+ @function update_password
+ @discussion updates a users password
+ */
+ function update_password($new_password) {
+
+ $sql = "UPDATE user SET password=PASSWORD('$new_password') WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ return true;
+ } // update_password
+
+
+ /*!
+ @function format_favorites
+ @discussion takes an array of objects and formats them corrrectly
+ and returns a simply array with just <a href values
+ */
+ function format_favorites($items) {
+
+ // The length of the longest item
+ $maxlen = strlen($items[0]->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++;
+ }
+
+ $results[] = "<li>[$data->count] - $data->f_name</li>\n";
+
+ } // end foreach items
+
+ return $results;
+
+ } // format_favorites
+
+ /*!
+ @function fix_preferences
+ @discussion this makes sure that the specified user
+ has all the correct preferences. This function
+ should be run whenever a system preference is run
+ it's a cop out... FIXME!
+ */
+ function fix_preferences($user_id = 0) {
+
+ if (!$user_id) {
+ $user_id = $this->id;
+ }
+
+ /* Get All Preferences */
+ $sql = "SELECT * FROM user_preference WHERE user='$user_id'";
+ $db_results = mysql_query($sql, dbh());
+
+ while ($r = mysql_fetch_object($db_results)) {
+ /* Check for duplicates */
+ if (isset($results[$r->preference])) {
+ $r->value = sql_escape($r->value);
+ $sql = "DELETE FROM user_preference WHERE user='$user_id' AND preference='$r->preference' AND value='$r->value'";
+ $delete_results = mysql_query($sql, dbh());
+ } // duplicate
+ else {
+ $results[$r->preference] = $r;
+ }
+ } // while results
+
+ /*
+ If we aren't the 0 user before we continue then grab the
+ 0 user's values
+ */
+ if ($user_id != '0') {
+ $sql = "SELECT user_preference.preference,user_preference.value FROM user_preference,preferences " .
+ "WHERE user_preference.preference = preferences.id AND user_preference.user='0' AND preferences.type='user'";
+ $db_results = mysql_query($sql, dbh());
+ while ($r = mysql_fetch_object($db_results)) {
+ $zero_results[$r->preference] = $r->value;
+ }
+ } // if not user 0
+
+
+ $sql = "SELECT * FROM preferences";
+ if ($user_id != '0') {
+ $sql .= " WHERE type='user'";
+ }
+ $db_results = mysql_query($sql, dbh());
+
+
+ while ($r = mysql_fetch_object($db_results)) {
+
+ /* Check if this preference is set */
+ if (!isset($results[$r->id])) {
+ if (isset($zero_results[$r->id])) {
+ $r->value = $zero_results[$r->id];
+ }
+ $sql = "INSERT INTO user_preference (`user`,`preference`,`value`) VALUES ('$user_id','$r->id','$r->value')";
+ $insert_db = mysql_query($sql, dbh());
+ }
+ } // while preferences
+
+ } // fix_preferences
+
+
+ /*!
+ @function delete_stats
+ @discussion deletes the stats for this user
+ */
+ function delete_stats() {
+
+ $sql = "DELETE FROM object_count WHERE userid='" . $this->id . "'";
+ $db_results = mysql_query($sql, dbh());
+
+ } // delete_stats
+
+ /*!
+ @function delete
+ @discussion deletes this user and everything assoicated with it
+ */
+ function delete() {
+
+ /*
+ Before we do anything make sure that they aren't the last
+ admin
+ */
+ if ($this->has_access(100)) {
+ $sql = "SELECT * FROM user WHERE (level='admin' OR level='100') AND id!='" . $this->id . "'";
+ $db_results = mysql_query($sql, dbh());
+ if (!mysql_num_rows($db_results)) {
+ return false;
+ }
+ } // if this is an admin check for others
+
+ // Delete their playlists
+ $sql = "DELETE FROM playlist WHERE owner='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ // Delete any stats they have
+ $sql = "DELETE FROM object_count WHERE userid='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ // Delete their preferences
+ $sql = "DELETE FROM preferences WHERE user='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ // Delete the user itself
+ $sql = "DELETE FROM user WHERE id='$this->id'";
+ $db_results = mysql_query($sql, dbh());
+
+ return true;
+
+ } // delete
+
+ /*!
+ @function is_online
+ @parameter delay how long since last_seen in seconds default of 20 min
+ @description calcs difference between now and last_seen
+ if less than delay, we consider them still online
+ */
+ function is_online( $delay = 1200 ) {
+ return time() - $this->last_seen <= $delay;
+ }
+
+} //end class
+?>
diff --git a/modules/class/view.php b/modules/class/view.php
new file mode 100644
index 00000000..f9de4ee6
--- /dev/null
+++ b/modules/class/view.php
@@ -0,0 +1,229 @@
+<?
+/*
+
+ Copyright (c) 2004 Ampache.org
+ All rights reserved.
+
+ $CVSHeader: ampache/modules/class/artist.php,v 1.1 2004/03/25 09:12:57 vollmerk Exp $
+ $Source: /data/cvsroot/ampache/modules/class/artist.php,v $
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*!
+ @header View Object of crappyness
+ View object that is thrown into their session
+
+*/
+
+
+class View {
+
+ //Basic Componets
+ var $base_sql;
+ var $offset;
+ var $offset_limit;
+ var $sort_order; //asc or desc
+ var $sort_type;
+ var $action;
+ var $total_items;
+
+ //generate a new view
+ function View($base_sql=0,$script=0,$sort_type=0,$total_items=0,$offset_limit=0) {
+ global $conf;
+
+ // If we don't have a base sql, stop here
+ if (!is_string($base_sql)) {
+ return true;
+ }
+
+ //Convert all 's into "s
+ $base_sql = str_replace("'",'"',$base_sql);
+
+ $this->base_sql = $base_sql;
+ if ($offset_limit) { $this->offset_limit = $offset_limit; }
+ else { $this->offset_limit = $_SESSION['offset_limit']; }
+ if ($this->offset_limit < '1') { $this->offset_limit = '50'; }
+ $this->script = $script;
+ $this->sort_type = $sort_type;
+ $this->sort_order = "ASC";
+ $this->offset = 0;
+ $this->total_items = $total_items;
+
+ // Set the session
+ $_SESSION['view_offset_limit'] = $this->offset_limit;
+ $_SESSION['view_sort_type'] = $this->sort_type;
+ $_SESSION['view_offset'] = $this->offset;
+ $_SESSION['view_base_sql'] = $this->base_sql;
+ $_SESSION['view_sort_order'] = $this->sort_order;
+ $_SESSION['view_script'] = $this->script;
+ $_SESSION['view_total_items'] = $this->total_items;
+ $this->sql = $this->generate_sql();
+
+ } //constructor
+
+ //takes all the parts and makes a full blown sql statement
+ function generate_sql() {
+ global $conf;
+
+ $sql = $this->base_sql . " ORDER BY " . $this->sort_type ." ". $this->sort_order ." LIMIT " . $this->offset . "," . $this->offset_limit;
+
+ return $sql;
+
+ } //generate_sql
+
+ //change the sort order from asc to desc or vise versa
+ function change_sort($new_sort=0) {
+ global $conf;
+
+ if ($new_sort) {
+ $this->sort_order = $new_sort;
+ }
+ elseif ($this->sort_order == "DESC") {
+ $this->sort_order = "ASC";
+ }
+ else {
+ $this->sort_order = "DESC";
+ }
+
+ $_SESSION['view_sort_order'] = $this->sort_order;
+
+ $this->sql = $this->generate_sql();
+
+ return;
+
+ } //change_sort
+
+ //change the base sql
+ function change_sql($base_sql) {
+ global $conf;
+
+ //Convert all 's into "s
+ $base_sql = str_replace("'",'"',$base_sql);
+
+ $this->base_sql = $base_sql;
+
+ $_SESSION['view_base_sql'] = $this->base_sql;
+
+ $this->sql = $this->generate_sql();
+
+ } //change_sql
+
+ //change offset
+ function change_offset($offset=0) {
+ global $conf;
+
+ if (isset($offset)) {
+ $this->offset = $offset;
+ }
+ else {
+ $this->offset = $this->offset + $this->offset_limit;
+ }
+
+ $_SESSION['view_offset'] = $this->offset;
+
+ $this->sql = $this->generate_sql();
+
+ } //change_offset
+
+ //change sort_type
+ function change_sort_type($sort_type) {
+
+ $this->sort_type = $sort_type;
+
+ $_SESSION['view_sort_type'] = $this->sort_type;
+
+ $this->sql = $this->generate_sql();
+
+ } //change_sort_type
+
+ /*!
+ @function change_offset_limit
+ @discussion changes the offset limit, sets the session
+ var and generates the sql statement
+ */
+ function change_offset_limit($offset_limit) {
+
+ $this->offset_limit = $offset_limit;
+
+ $_SESSION['view_offset_limit'] = $this->offset_limit;
+
+ $this->sql = $this->generate_sql();
+
+ } // change_offset_limit
+
+ /*!
+ @function initialize
+ @discussion initializes the view object, checks $_REQUEST
+ for changes to the view object
+ */
+ function initialize() {
+
+ if ($_REQUEST['sort_type']) {
+ $this->change_sort_type($_REQUEST['sort_type']);
+ }
+
+ if (isset($_REQUEST['offset'])) {
+ $this->change_offset($_REQUEST['offset']);
+ }
+
+ if ($_REQUEST['base_sql']) {
+ $this->change_sql($_REQUEST['base_sql']);
+ }
+
+ if (isset($_REQUEST['sort_order'])) {
+ $this->change_sort($_REQUEST['sort_order']);
+ }
+
+ if ($_REQUEST['offset_limit']) {
+ $this->change_offset_limit($_REQUEST['offset_limit']);
+ }
+
+ } // initialize
+
+
+ /*!
+ @function import_session_view
+ @discussion this imports the view from the session for use..
+ this keeps us from having to globalize anything
+ wohoo!
+ */
+ function import_session_view() {
+
+ $this->sort_type = $_SESSION['view_sort_type'];
+ $this->offset = $_SESSION['view_offset'];
+ $this->base_sql = $_SESSION['view_base_sql'];
+ $this->sort_order = $_SESSION['view_sort_order'];
+ $this->script = $_SESSION['view_script'];
+ $this->total_items = $_SESSION['view_total_items'];
+
+
+ if ($_SESSION['view_offset_limit']) {
+ $this->offset_limit = $_SESSION['view_offset_limit'];
+ }
+ else {
+ $this->offset_limit = $_SESSION['offset_limit'];
+ }
+
+
+ $this->sql = $this->generate_sql();
+
+ } // import_session_view
+
+
+
+} //end class
+?>